220. Mapper factory

Create a mapper factory.

Lesson 220 of 356 · tests/chapter_02_rom_loading/test_220_mapper_factory.py

File to create

emulator/cartridge/mapper_factory.py

Function to implement

create_mapper(cartridge: Cartridge)

Why this step exists

The Cartridge object stores facts loaded from the ROM

Cartridge(prg_rom, chr_rom, mapper_number)

But the CPU/PPU do not talk directly to raw PRG/CHR bytes. They talk through a mapper, because the mapper is the cartridge hardware that translates emulator addresses into ROM offsets.

Current flow

raw .nes bytes
    -> Cartridge.from_ines_bytes(data)
    -> create_mapper(cartridge)
    -> Mapper000(prg_rom, chr_rom)

Responsibilities of the factory

  • inspect cartridge.mapper_number
  • create the correct mapper object
  • fail loudly for unsupported mappers

What the factory should NOT do

  • parse iNES bytes
  • perform CPU address translation
  • know about CpuBus routing
  • mutate the Cartridge

Expected implementation shape

from emulator.cartridge.cartridge import Cartridge
from emulator.cartridge.mapper000 import Mapper000


def create_mapper(cartridge: Cartridge):
    if cartridge.mapper_number == 0:
        return Mapper000(
            prg_rom=cartridge.prg_rom,
            chr_rom=cartridge.chr_rom,
        )

    raise ValueError(f"Unsupported mapper: {cartridge.mapper_number}")

Why this is separate from CpuBus

CpuBus should route reads and writes. It should not become responsible for every cartridge mapper selection rule. Keeping mapper creation here reduces coupling before we integrate cartridge-backed PRG ROM reads into the bus.

Run this lesson

uv run pytest tests/chapter_02_rom_loading/test_220_mapper_factory.py -v