241. Ppustatus read resets second write toggle
Reading PPUSTATUS ($2002) resets the PPU second-write toggle.
Lesson 241 of 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_241_ppustatus_read_resets_second_write_toggle.py
File to update
emulator/ppu/ppu.pyMethod to update
PPU.read_register(addr)Why this step exists
The NES PPU has two-write registers, especially
$2005 PPUSCROLL
$2006 PPUADDRThose registers use an internal first-write / second-write toggle. In this tutorial, that state is named:
second_write_toggleMeaning
False -> the next two-write register access is the first write
True -> the next two-write register access is the second writeImportant PPUSTATUS behavior
Reading $2002 resets this toggle back to False.
Why
Games commonly read PPUSTATUS before writing PPUSCROLL or PPUADDR so the PPU is known to be waiting for the first write again.
Example
write $23 to $2006
second_write_toggle = True
read $2002
second_write_toggle = False
write $20 to $2006
treated as first write / high byte, not as low byteSuggested implementation pseudocode
def read_register(self, addr: int) -> int:
match addr:
case 0x2002:
value = self.status
self.status &= ~VBLANK_STARTED
self.second_write_toggle = False
return value
case 0x2004:
return self.oam_data
case 0x2007:
return self.data
case _:
raise ValueError(...)Important invariant
Reading $2002 should return the old status value, then apply side effects.
Side effects currently modeled
- clear VBLANK_STARTED
- reset second_write_toggle
Side effects not modeled yet
- full scroll latch behavior
- timing/VBlank generation
- NMI behavior
Run this lesson
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_241_ppustatus_read_resets_second_write_toggle.py -v