224. Ppu dataclass register attributes

Create the PPU dataclass with explicit register attributes.

Lesson 224 of 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_224_ppu_dataclass_register_attributes.py

File to create

emulator/ppu/ppu.py

Class to implement

PPU

Why this step exists

The CPU communicates with the NES Picture Processing Unit through CPU-visible hardware registers at addresses $2000-$2007. These are not normal RAM bytes; they are named hardware registers with specific meanings.

For this first PPU step, we only create the register state. We do not implement reads, writes, rendering, VBlank, scrolling, VRAM, or DMA yet.

This test verifies that the original CPU-visible PPU register fields exist. It does not require these to be the only fields forever. Later steps may add internal PPU state such as ppu_bus, vram_addr, or addr_latch.

CPU-visible PPU register window

$2000 PPUCTRL   -> ctrl
$2001 PPUMASK   -> mask
$2002 PPUSTATUS -> status
$2003 OAMADDR   -> oam_addr
$2004 OAMDATA   -> oam_data
$2005 PPUSCROLL -> scroll
$2006 PPUADDR   -> addr
$2007 PPUDATA   -> data

Important design choice

Use explicit integer fields, similar to the CPU registers. This keeps debugging simple and makes the hardware model visible:

assert ppu.ctrl == 0x80

Do not add OAMDMA here. OAMDMA is accessed at CPU address $4014 and triggers a 256-byte DMA copy into sprite memory. It is related to the PPU, but it is not part of the normal $2000-$2007 PPU register window.

Suggested implementation pseudocode

from dataclasses import dataclass


@dataclass
class PPU:
    ctrl: int = 0
    mask: int = 0
    status: int = 0
    oam_addr: int = 0
    oam_data: int = 0
    scroll: int = 0
    addr: int = 0
    data: int = 0

Run this lesson

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