217. Cartridge from ines

create

Lesson 217 of 356 · tests/chapter_02_rom_loading/test_217_cartridge_from_ines.py

create emulator/cartridge/cartridge.py::Cartridge.

Why this step exists

The iNES parser owns file-layout concerns; this class exposes the PRG bytes, CHR bytes, mapper identity, and optional CHR-RAM storage needed by the emulator. from_ines_bytes is the boundary between those representations and depends on the parser completed in lesson 216.

Suggested implementation for this lesson

from dataclasses import dataclass
from typing import Optional
from emulator.cartridge.ines import parse_ines_rom


@dataclass(frozen=True)
class Cartridge:
    prg_rom: bytes
    chr_rom: bytes
    mapper_number: int
    chr_ram: Optional[bytearray] = None

    @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,
        )

Invariants: the lesson's class is frozen; required field order is PRG, CHR, mapper number, then CHR RAM; and construction copies parsed values without translating addresses. The chr_ram field is required in the dataclass shape, but its value is optional and defaults to None.

Out of scope for this step

1. Lessons 218-219 put PRG and CHR address translation on `Mapper000`.
2. Lesson 220 selects a mapper from the cartridge metadata.
3. Lessons 221-222 route CPU-bus reads through that mapper.
4. Mirroring metadata and writable graphics behavior come later.

Run this lesson

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