239. Ppu internal scroll address registers

Introduce the PPU internal scroll/address registers.

Lesson 239 of 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_239_ppu_internal_scroll_address_registers.py

Reference

https://www.nesdev.org/wiki/PPU_registers#Internal_registers

File to update

emulator/ppu/ppu.py

Fields to add

vram_addr: int = 0
temp_vram_addr: int = 0
fine_x: int = 0
second_write_toggle: bool = False

Why this step exists

PPUADDR ($2006), PPUSCROLL ($2005), PPUDATA ($2007), and rendering do not use only simple one-byte register fields. The PPU has internal address/scroll state.

Common nesdev names

v = current VRAM address
t = temporary VRAM address
x = fine X scroll
w = first/second write toggle

Tutorial names

vram_addr           -> v
temp_vram_addr      -> t
fine_x              -> x
second_write_toggle -> w

Short meaning

  • vram_addr is the current PPU memory address used by PPUDATA and rendering.
  • temp_vram_addr is built by PPUADDR/PPUSCROLL writes before being copied.
  • fine_x stores the fine horizontal scroll offset, 0-7. (pixel-level horizontal scroll offset inside a tile)
  • second_write_toggle tracks first vs second write for $2005/$2006.

Suggested implementation pseudocode

@dataclass
class PPU:
    ...
    vram_addr: int = 0
    temp_vram_addr: int = 0
    fine_x: int = 0
    second_write_toggle: bool = False

Out of scope

  • PPUSCROLL behavior
  • accurate rendering scroll reload timing
  • nametable rendering

Run this lesson

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