248. Memoria OAM y OAMDATA
Implementa la memoria OAM y el comportamiento de OAMADDR/OAMDATA.
Lección 248 de 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_248_oam_memory_and_oamdata.py
Referencias
https://www.nesdev.org/wiki/PPU_registers#OAMADDR
https://www.nesdev.org/wiki/PPU_registers#OAMDATA
https://www.nesdev.org/wiki/PPU_OAMArchivo a actualizar
emulator/ppu/ppu.pyEstado a añadir
OAM_SIZE = 256
oam: bytearray = field(default_factory=lambda: bytearray(OAM_SIZE))Por qué existe este paso
OAM significa Object Attribute Memory. Es la memoria interna de sprites de 256 bytes de la PPU. La PPU renderiza los sprites desde la OAM, no directamente desde la RAM de la CPU.
Disposición de los sprites
NES OAM stores 64 sprites.
Each sprite uses 4 bytes.
64 sprites * 4 bytes = 256 bytesDisposición básica de los bytes de sprite
byte 0: Y position
byte 1: tile index
byte 2: attributes
byte 3: X positionRegistros visibles para la CPU
$2003 OAMADDR
selects which OAM byte is currently addressed
$2004 OAMDATA
reads/writes OAM at the current OAMADDRComportamiento importante para este paso
- escribir $2003 establece oam_addr
- escribir $2004 guarda en oam[oam_addr]
- escribir $2004 incrementa oam_addr con & 0xFF
- leer $2004 devuelve oam[oam_addr]
Por qué la OAM no es VRAM de PpuBus
PpuBus gestiona el espacio de direcciones de la PPU que usan PPUADDR/PPUDATA
$0000-$3FFFLa OAM es una memoria interna de sprites aparte, a la que se accede mediante OAMADDR/OAMDATA
$2003/$2004Pseudocódigo de implementación sugerido
OAM_SIZE = 256
@dataclass
class PPU:
...
oam_addr: int = 0
oam_data: int = 0
oam: bytearray = field(default_factory=lambda: bytearray(OAM_SIZE))
def write_register(self, addr: int, value: int) -> None:
value = value & 0xFF
match addr:
...
case 0x2003:
self.oam_addr = value
case 0x2004:
# Preserve old compatibility/debug field.
self.oam_data = value
# Write to current OAM byte.
self.oam[self.oam_addr] = value
# OAMADDR increments after OAMDATA write.
self.oam_addr = (self.oam_addr + 1) & 0xFF
...
def read_register(self, addr: int) -> int:
match addr:
...
case 0x2004:
self.oam_data = self.oam[self.oam_addr]
return self.oam_dataFuera del alcance
- OAMDMA en $4014
- evaluación de sprites
- renderizado de sprites
- comportamiento de desbordamiento de sprites
- comportamiento de sprite 0 hit
Ejecutar esta lección
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_248_oam_memory_and_oamdata.py -v