249. Búfer de lectura de PPUDATA
Implementa el comportamiento de lectura con búfer de PPUDATA ($2007).
Lección 249 de 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_249_ppudata_read_buffer.py
Referencia
https://www.nesdev.org/wiki/PPU_registers#PPUDATAArchivo a actualizar
emulator/ppu/ppu.pyEstado a añadir
ppu_data_buffer: int = 0Por qué existe este paso
PPUDATA no es un registro simple normal. Es un puerto visible para la CPU hacia la memoria de la PPU. En la mayoría de las lecturas de memoria de la PPU, la NES devuelve el búfer de lectura interno antiguo y después recarga ese búfer desde la dirección actual de memoria de la PPU.
Comportamiento normal de lectura con búfer
read $2007:
value = ppu_data_buffer
ppu_data_buffer = ppu_bus.read(vram_addr)
vram_addr += increment
return valueEsto significa que la primera lectura suele devolver datos antiguos/obsoletos del búfer, y la segunda lectura devuelve el byte que se cargó con la primera lectura.
Ejemplo
ppu_bus[$2000] = $AA
ppu_bus[$2001] = $BB
ppu_data_buffer = $00
vram_addr = $2000
read $2007 -> returns $00, buffer becomes $AA, vram_addr becomes $2001
read $2007 -> returns $AA, buffer becomes $BB, vram_addr becomes $2002Campo de compatibilidad/depuración
El modelo anterior del tutorial tenía data como un valor simple de PPUDATA. Conserva self.data como campo de compatibilidad/depuración que contiene el valor devuelto por la última
lectura de PPUDATA, pero el comportamiento real debería usar
ppu_data_buffer
ppu_bus.read(vram_addr)Pseudocódigo de implementación sugerido
@dataclass
class PPU:
...
data: int = 0 # Compatibility/debug: last PPUDATA value
ppu_data_buffer: int = 0
def read_register(self, addr: int) -> int:
match addr:
...
case 0x2007:
value = self.ppu_data_buffer
self.ppu_data_buffer = self.ppu_bus.read(self.vram_addr)
increment = 32 if self.ctrl & CTRL_VRAM_INCREMENT_BY_32 else 1
self.vram_addr = (self.vram_addr + increment) & 0x3FFF
# Preserve old compatibility/debug field.
self.data = value
return self.dataNota importante para el futuro
Las lecturas de paleta de $3F00-$3FFF son una excepción en el hardware real. Devuelven el byte de paleta inmediatamente en lugar de devolver el valor retardado del búfer. Esa excepción no se implementa de forma intencionada en este test.
Fuera del alcance
- excepción de lectura de paleta
- precisión de la RAM de paleta
- escrituras de PPUDATA, ya probadas anteriormente
Ejecutar esta lección
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_249_ppudata_read_buffer.py -v