232. La lectura de ppu status limpia vblank

Leer PPUSTATUS limpia el flag de VBlank.

Lección 232 de 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_232_ppu_status_read_clears_vblank.py

Archivo a actualizar

emulator/ppu/ppu.py

Método a actualizar

PPU.read_register(addr)

Por qué existe este paso

PPUSTATUS en $2002 no es un valor pasivo. En el hardware real de la NES, leer PPUSTATUS devuelve el byte de estado actual y limpia el flag de inicio de VBlank dentro de la PPU.

Comportamiento importante

read_register($2002):
    1. save the old status value
    2. clear only VBLANK_STARTED, bit 7
    3. return the old status value

El orden importa.

Correcto

value = self.status
self.status &= ~VBLANK_STARTED
return value

Incorrecto

self.status &= ~VBLANK_STARTED
return self.status

Por qué es incorrecto

La CPU debe poder observar que se activó VBlank. Si el emulador limpia el bit 7 antes de devolver el valor, los bucles de sondeo de la CPU no detectarán VBlank.

Ejemplo a nivel de bits

status before read:      0b1110_0000
~VBLANK_STARTED:         0b0111_1111
status after AND:        0b0110_0000

Solo se limpia el bit 7. Sprite 0 hit y sprite overflow permanecen activados.

Pseudocódigo de implementación sugerido

def read_register(self, addr: int) -> int:
    match addr:
        case 0x2002:
            value = self.status
            self.status &= ~VBLANK_STARTED
            return value
        case 0x2004:
            return self.oam_data
        case 0x2007:
            return self.data
        case _:
            raise ValueError(...)

Fuera de alcance

  • activar VBlank automáticamente a partir de la temporización de la PPU
  • generación de NMI
  • scanlines/ciclos
  • comportamiento de sprite 0 hit
  • comportamiento de sprite overflow

Ejecutar esta lección

uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_232_ppu_status_read_clears_vblank.py -v