Cómo la SNES calcula la dirección y el valor de color de un Sprite en Memoria

A continuación dejo todos los componentes necesarios para entender como hacer reversing a esta parte.

OAM (Object Attribute Memory) – Selección de Paleta

La OAM tiene 544 bytes y define las propiedades de los sprites. Cada sprite en pantalla consume 4 bytes consecutivos:

  • Byte 0: Posición X.
  • Byte 1: Posición Y.
  • Byte 2: Índice del Tile (Puntero a los gráficos en VRAM).
  • Byte 3: Atributos del Sprite.

El Byte 3 se estructura a nivel de bits como vhoopppc. Los bits p p p (bits 1, 2 y 3) definen el número de paleta (0 a 7) asignada a ese sprite.

  • 000 = Paleta 0
  • 001 = Paleta 1
  • (…)
  • 111 = Paleta 7

VRAM (Video RAM) – El Índice del Píxel

En VRAM residen los gráficos puros (Tiles). Los sprites estándar usan un formato de 4bpp (4 bits por píxel).
Al leer un Tile, cada píxel se forma apilando 4 bits, lo que permite un valor numérico local del 0 al 15 (0000 a 1111 en binario).

  • Valor 0 (0000): El hardware lo procesa como fondo (transparencia).
  • Valores 1 a 15 (0001 a 1111): Tinta sólida (colores usables).

CGRAM (Color Generator RAM) y el límite de 15 bits

Es la memoria física (512 bytes) que contiene los colores.

  • Base de Fondos: Direcciones $000 a $0FF.
  • Base de Sprites: Direcciones $100 a $1FF.

Las paletas se dividen en bloques de 32 bytes ($20 en hexadecimal). Cada paleta tiene 16 colores (16 * 2 = 32). El programador tiene total libertad para adaptar y sobreescribir esta paleta a su gusto, definiendo qué valores hexadecimales ocupan esos bytes.

El formato RGB555 y el almacenamiento en Memoria (Por qué es FF 7F y no FFFF):
Aunque la memoria dedica 16 bits (2 bytes) a cada color, el sistema solo utiliza 15 bits (5 Azul, 5 Verde, 5 Rojo). El bit 16 es ignorado por hardware y es fijado a 0.

  • El valor máximo con los tres canales encendidos (Blanco puro) en binario es: 0111 1111 1111 1111.
  • En valor hexadecimal absoluto, eso es $7FFF.
  • La SNES guarda los datos usando Little Endian (el byte de menor peso se escribe primero). Por lo tanto, el $7FFF se divide e invierte en memoria guardándose como FF 7F. Si intentas escribir FFFF, un emulador preciso corregirá el bit 16 automáticamente, devolviéndolo a FF 7F.

Ejemplo de una sub-paleta en Memoria (32 bytes a partir de $100):

100: 00 00 FF 7F 1F 00 E0 03 FF 7F 00 00 00 00 00 00
110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

En este bloque adaptado por el programador, el Color 0 es 00 00 (transparente), el Color 1 es FF 7F (Blanco Puro), el Color 2 es 1F 00 (Rojo puro) y el Color 3 es E0 03 (Verde puro).

La Fórmula del Hardware (Direccionamiento Físico)

Cuando la PPU va a dibujar un píxel específico de un sprite en pantalla, ejecuta el siguiente cálculo matemático para saber qué bytes exactos leer en la CGRAM:

Dirección CGRAM = Memoria Base + (Paleta OAM * Tamaño Paleta) + (Píxel VRAM * Tamaño Color)

  • Memoria Base: $100 (Inicio del bloque de sprites).
  • Tamaño Paleta: $20 (32 bytes).
  • Tamaño Color: 2 (2 bytes por color).

La fórmula matemática final es:
Dirección = $100 + (Valor ppp * $20) + (Valor Píxel * 2)

Caso Práctico: El cálculo del color en $102

Si tenemos un sprite dibujando texto blanco y queremos saber por qué el emulador altera los valores ubicados específicamente en la dirección $102 y no en la $100, aplicamos el rastro de memoria:

A. Lectura de OAM:
El sprite del texto tiene los bits ppp del Byte 3 configurados en 000.

  • Offset de paleta: 0 * $20 = $000.

B. Lectura de VRAM:
La PPU escanea la cuadrícula del Tile y llega al píxel que forma la “tinta” de la letra blanca. El programador dibujó esa letra usando el valor 1 (0001).

  • Offset del píxel: 1 * 2 = $002.

C. Cálculo Final (PPU):

  • Base: $100
  • Offset OAM: + $000
  • Offset VRAM: + $002
  • Dirección Resultante: $102

La PPU lee los bytes $102 y $103, extrae los valores almacenados (FF 7F) y pinta el píxel blanco en pantalla respetando el límite de 15 bits.

¿Qué pasa con el fondo transparente del texto?
Cuando la PPU lee el píxel que actúa como fondo vacío de la letra en la VRAM, obtiene el valor 0 (0000).

  • Base: $100
  • Offset OAM: + $000
  • Offset VRAM: 0 * 2 = + $000
  • Dirección Resultante: $100

El hardware identifica que el valor del píxel en VRAM es 0. Por arquitectura de la SNES, se aborta la lectura de color para la dirección $100 y renderiza el píxel actual como transparente, dejando ver los gráficos de fondo (Backgrounds) que existan debajo del sprite.

Leave a Reply

Your email address will not be published. Required fields are marked *

Are you human? Please solve:Captcha