254. Mapper chr write routing

Implement CHR write routing through the mapper.

Lesson 254 of 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_254_mapper_chr_write_routing.py

Reference

https://www.nesdev.org/wiki/PPU_memory_map
https://www.nesdev.org/wiki/NROM

Files to update

emulator/cartridge/mapper_interface.py
emulator/cartridge/mapper000.py
emulator/bus/ppu_bus.py

What is CHR memory? CHR memory is where the PPU reads tile pattern bytes from. The PPU address range $0000-$1FFF is the CHR area.

Simple example

PPU reads $0000
mapper returns the first byte of CHR ROM

For official Mapper000/NROM in this tutorial, CHR is ROM, so writes are rejected.

Why this step exists

PpuBus should only route addresses. It should not decide whether CHR writes are legal. The mapper owns that policy.

Correct responsibility split

PpuBus.write($0000-$1FFF, value)
    -> mapper.write_chr(addr, value)

Mapper000.write_chr(addr, value)
    -> rejects writes because official Mapper000 CHR ROM is read-only

Suggested implementation example

class MapperInterface(Protocol):
    def read_prg(self, addr: int) -> int:
        ...

    def read_chr(self, addr: int) -> int:
        ...

    def write_chr(self, addr: int, value: int) -> None:
        ...

class Mapper000:
    def write_chr(self, addr: int, value: int) -> None:
        if not (CHR_ROM_START <= addr <= CHR_ROM_END):
            raise ValueError(f"Address out of CHR ROM range: {addr:04X}")

        raise ValueError("CHR ROM is read-only for official Mapper000")

class PpuBus:
    def write(self, addr: int, value: int) -> None:
        addr = addr & PPU_ADDRESS_MASK

        if CHR_START <= addr <= CHR_END:
            if self.mapper is not None:
                self.mapper.write_chr(addr, value)
                return

            self.vram.write(addr, value)
            return

Out of scope

  • CHR RAM support
  • unlicensed/homebrew Mapper000 variants with writable CHR RAM
  • mapper bank switching
  • rendering CHR tiles

Run this lesson

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