253. Ppu bus nametable vram mapping
Implement PpuBus nametable VRAM address mapping.
Lesson 253 of 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_253_ppu_bus_nametable_vram_mapping.py
Reference
https://www.nesdev.org/wiki/PPU_memory_map
https://www.nesdev.org/wiki/PPU_nametablesFile to update
emulator/bus/ppu_bus.pyConstants to add
NAMETABLE_START = 0x2000
NAMETABLE_END = 0x3EFF
NAMETABLE_SIZE = 0x0800What is a nametable? A nametable is background layout memory. It does not store pixels. It stores tile numbers that tell the PPU which CHR tile to draw at each background position.
Simple example
PPU memory $2000 contains $24Meaning
the top-left background cell uses CHR tile index $24The PPU exposes four logical 1KB nametable areas
$2000-$23FF
$2400-$27FF
$2800-$2BFF
$2C00-$2FFFThe range $3000-$3EFF mirrors $2000-$2EFF.
Tutorial simplification
For now, use the existing large VRAM backing and normalize nametable addresses into a simple 2KB window. Do not create a separate nametable RAM object yet.
Suggested implementation example
NAMETABLE_START = 0x2000
NAMETABLE_END = 0x3EFF
NAMETABLE_SIZE = 0x0800
def normalize_nametable_addr(self, addr: int) -> int:
if 0x3000 <= addr <= 0x3EFF:
addr -= 0x1000
index = (addr - NAMETABLE_START) % NAMETABLE_SIZE
return NAMETABLE_START + index
def read(self, addr: int) -> int:
addr = addr & PPU_ADDRESS_MASK
if CHR_START <= addr <= CHR_END:
...
if NAMETABLE_START <= addr <= NAMETABLE_END:
return self.vram.read(self.normalize_nametable_addr(addr))
if PALETTE_START <= addr <= PALETTE_END:
...
return self.vram.read(addr)Out of scope
- horizontal/vertical cartridge mirroring
- four-screen mirroring
- attribute table interpretation
- rendering
- moving nametable storage out of the large VRAM backing
Run this lesson
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_253_ppu_bus_nametable_vram_mapping.py -v