214. Разбор заголовка iNES

добавьте

Урок 214 из 356 · tests/chapter_02_rom_loading/test_214_parse_ines_header.py

добавьте emulator/cartridge/ines.py::parse_ines_header.

Зачем нужен этот шаг

Парсер проверяет фиксированную оболочку перед преобразованием байтов 4-7 в неизменяемый INesHeader, введённый в уроке 213. Он зависит от констант из урока 212 и датакласса из урока 213.

Предлагаемая реализация

def parse_ines_header(data: bytes) -> INesHeader:
    if len(data) < INES_HEADER_SIZE:
        raise ValueError("iNES data is too short")
    if data[0:4] != INES_MAGIC:
        raise ValueError("Invalid iNES header")

    prg_rom_banks = data[4]
    chr_rom_banks = data[5]
    flags_6 = data[6]
    flags_7 = data[7]
    has_trainer = (flags_6 & 0b0000_0100) != 0
    mapper_number = (flags_6 >> 4) | (flags_7 & 0xF0)
    return INesHeader(
        prg_rom_banks,
        chr_rom_banks,
        mapper_number,
        has_trainer,
        flags_6,
        flags_7,
    )

Инварианты: отклоняйте короткие входные данные до индексирования; требуйте b"NES"; используйте старший ниббл flags 6 как биты 0-3 номера mapper, а старший ниббл flags 7 — как биты 4-7; сохраняйте оба исходных флага. Частая ошибка — умножать здесь байты 4 и 5: они остаются количествами банков.

Вне рамок этого шага

1. Lesson 215 groups a parsed header with ROM sections.
2. Lesson 216 extracts and validates declared PRG/CHR payload bytes.

Запустить этот урок

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