324. Ines vertical mirroring flag

Decode horizontal/vertical nametable mirroring from iNES flags 6 bit 0.

Lesson 324 of 356 · tests/chapter_12_mirroring/test_324_ines_vertical_mirroring_flag.py

File to update

emulator/cartridge/ines.py

Reference

https://www.nesdev.org/wiki/Mirroring#Nametable_Mirroring

Why this step exists

Before implementing a scrolling viewport, the emulator must know how the cartridge wires logical PPU nametables onto physical nametable RAM.

Mirroring does not visually flip an image. It controls memory mapping between the four logical nametable regions:

$2000
$2400
$2800
$2C00

iNES flags 6 bit 0 selects the basic mirroring mode:

bit 0 clear -> horizontal mirroring
bit 0 set   -> vertical mirroring

For the current incremental scope, expose this as one boolean property

is_vertical_mirroring is False -> horizontal
is_vertical_mirroring is True  -> vertical

Suggested implementation example

FLAGS6_VERTICAL_MIRRORING = 1 << 0


@dataclass(frozen=True)
class INesHeader:
    prg_rom_banks: int
    chr_rom_banks: int
    mapper_number: int
    has_trainer: bool
    flags_6: int
    flags_7: int

    @property
    def is_vertical_mirroring(self) -> bool:
        return (self.flags_6 & FLAGS6_VERTICAL_MIRRORING) != 0

Why a computed property? flags_6 remains the single source of truth, and the existing INesHeader constructor does not need to change. That preserves older tutorial callers and tests.

Future extension

Four-screen mirroring can later add an is_four_screen property checked before is_vertical_mirroring. Four-screen storage and routing are not implemented here.

Out of scope

  • changing Cartridge
  • changing Mapper000
  • changing PpuBus nametable mapping
  • four-screen nametable RAM
  • scrolling
  • commercial ROM fixtures

Run this lesson

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