214. 解析 iNES 文件头

添加

214 / 356 · tests/chapter_02_rom_loading/test_214_parse_ines_header.py

添加 emulator/cartridge/ines.py::parse_ines_header

此步骤存在的原因

该解析器先校验固定的信封结构,然后再把第 4-7 字节转换为第 213 课引入的不可变 INesHeader。它依赖于第 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 位,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