325. Cartridge preserves mirroring

Preserve decoded nametable mirroring metadata in Cartridge.

Lesson 325 of 356 · tests/chapter_12_mirroring/test_325_cartridge_preserves_mirroring.py

File to update

emulator/cartridge/cartridge.py

Why this step exists

Step 324 decodes iNES flags 6 bit 0 through

INesHeader.is_vertical_mirroring

That information must survive after parsing so later mapper and PpuBus steps can choose the correct nametable address mapping.

Metadata path for this step

iNES flags 6
    -> INesHeader.is_vertical_mirroring
    -> Cartridge.is_vertical_mirroring

Suggested implementation changes

@dataclass
class Cartridge:
    prg_rom: bytes
    chr_rom: bytes
    mapper_number: int
    chr_ram: bytearray | None = None

    # --- NEW LINE ---
    is_vertical_mirroring: bool = False
    # --- END NEW LINE ---


@classmethod
def from_ines_bytes(cls, data: bytes) -> "Cartridge":
    ines_rom = parse_ines_rom(data)

    return cls(
        prg_rom=ines_rom.prg_rom,
        chr_rom=ines_rom.chr_rom,
        mapper_number=ines_rom.header.mapper_number,

        # --- NEW LINE ---
        is_vertical_mirroring=ines_rom.header.is_vertical_mirroring,
        # --- END NEW LINE ---
    )

Why append a defaulted field? Historical tutorial code directly constructs Cartridge using three or four positional arguments. Appending a defaulted field preserves those constructor shapes while allowing parsed ROMs to provide real metadata.

Meaning

False -> horizontal mirroring
True  -> vertical mirroring

Out of scope

  • changing Mapper000
  • changing MapperInterface
  • changing mapper_factory
  • changing PpuBus nametable mapping
  • four-screen mirroring
  • scrolling
  • commercial ROM fixtures

Run this lesson

uv run pytest tests/chapter_12_mirroring/test_325_cartridge_preserves_mirroring.py -v