324. iNES 垂直镜像标志

从 iNES flags 6 第 0 位解码水平/垂直名称表镜像方式。

324 / 356 · tests/chapter_12_mirroring/test_324_ines_vertical_mirroring_flag.py

需要更新的文件

emulator/cartridge/ines.py

参考资料

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

该步骤存在的原因

在实现卷动视口之前,模拟器必须知道卡带如何将逻辑 PPU 名称表接线到物理名称表 RAM 上。

镜像不会在视觉上翻转图像,它控制的是四个逻辑名称表区域之间的内存映射:

$2000
$2400
$2800
$2C00

iNES flags 6 第 0 位选择基本的镜像模式:

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

在当前的增量范围内,将其暴露为一个布尔属性

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

建议的实现示例

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

为什么使用计算属性?flags_6 仍是唯一的信息来源,现有的 INesHeader 构造函数无需改动。这样可以保持旧版教程调用方和测试的兼容性。

未来的扩展

以后可以为四屏镜像新增一个 is_four_screen 属性,在检查 is_vertical_mirroring 之前先检查它。四屏存储和路由在此处未实现。

不在本步骤范围内

  • 修改 Cartridge
  • 修改 Mapper000
  • 修改 PpuBus 的名称表映射
  • 四屏名称表 RAM
  • 卷动
  • 商业 ROM 测试夹具

运行本课

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