216. Analizar la ROM iNES

añade

Lección 216 de 356 · tests/chapter_02_rom_loading/test_216_parse_ines_rom.py

añade emulator/cartridge/ines.py::parse_ines_rom.

Por qué existe este paso

Esta función convierte las afirmaciones de la cabecera en fragmentos limpios de PRG/CHR, de modo que el código posterior de Cartridge y del mapper nunca necesite entender las cabeceras iNES ni los desplazamientos del trainer. Utiliza todas las constantes de formato y los modelos del analizador de las lecciones 212-215.

Implementación sugerida

def parse_ines_rom(data: bytes) -> INesRom:
    header = parse_ines_header(data)
    prg_size = header.prg_rom_banks * PRG_ROM_BANK_SIZE
    chr_size = header.chr_rom_banks * CHR_ROM_BANK_SIZE
    prg_start = INES_HEADER_SIZE + (
        TRAINER_SIZE if header.has_trainer else 0
    )
    prg_end = prg_start + prg_size
    chr_start = prg_end
    chr_end = chr_start + chr_size
    if len(data) < chr_end:
        raise ValueError(
            "iNES data is too short for declared PRG/CHR ROM"
        )
    return INesRom(
        header=header,
        prg_rom=data[prg_start:prg_end],
        chr_rom=data[chr_start:chr_end],
    )

Invariantes: los tamaños proceden de los recuentos de bancos; la PRG comienza después de la cabecera y del trainer opcional de 512 bytes; la CHR sigue inmediatamente a la PRG; y todos los bytes declarados deben existir antes de recortarlos (slicing). No confíes en el comportamiento tolerante de los slices cortos de Python, que aceptarían en silencio una imagen truncada.

Fuera de alcance para este paso

1. Extra trailing-byte policy and CHR RAM allocation are not introduced here.
2. Lesson 217 constructs a `Cartridge` from this parser result.
3. Lessons 218-220 add mapper behavior and mapper selection.

Ejecutar esta lección

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