326. Mapper 保留镜像信息
将名称表镜像元数据从 Cartridge 传递到 Mapper000。
第 326 / 356 · tests/chapter_12_mirroring/test_326_mapper_preserves_mirroring.py
需要更新的文件
emulator/cartridge/mapper000.py
emulator/cartridge/mapper_factory.py
emulator/cartridge/mapper_interface.py该步骤存在的原因
PpuBus 已经获得了卡带 mapper。通过 mapper 暴露镜像信息,可以保持单一的卡带硬件所有权路径:
INesHeader
-> Cartridge
-> Mapper000
-> PpuBus (next step)这比让 Cartridge 单独直接连接到 PpuBus 更可取。未来的 mapper 可能会通过 mapper 寄存器来控制镜像,因此 mapper 是更有价值的长期边界。
建议的实现改动
# emulator/cartridge/mapper000.py
@dataclass
class Mapper000:
prg_rom: bytes
chr_rom: bytes
# --- NEW LINE ---
is_vertical_mirroring: bool = False
# --- END NEW LINE ---
...
# emulator/cartridge/mapper_factory.py
def create_mapper(cartridge: Cartridge):
if cartridge.mapper_number == 0:
return Mapper000(
prg_rom=cartridge.prg_rom,
chr_rom=cartridge.chr_rom,
# --- NEW LINE ---
is_vertical_mirroring=cartridge.is_vertical_mirroring,
# --- END NEW LINE ---
)
...
# emulator/cartridge/mapper_interface.py
class MapperInterface(Protocol):
# --- NEW LINE ---
is_vertical_mirroring: bool
# --- END NEW LINE ---
def read_prg(self, addr: int) -> int:
...注解兼容性
协议既可以使用即时注解,也可以使用 from __future__ import annotations。可执行测试会先解析类型提示,再检查镜像值是否为布尔类型,因此该契约不依赖于 Python 是将注解存储为 bool 还是字符串 "bool"。
为什么要为 Mapper000 追加一个带默认值的字段?历史上的测试和教程代码在构造 Mapper000 时只传入 PRG 和 CHR ROM。追加一个默认为 False 的字段可以保留该构造方式,并意味着在未提供元数据时使用水平镜像。
含义
False -> horizontal mirroring
True -> vertical mirroring不在本步骤范围内
- 修改 PpuBus 的地址映射
- 修改 CpuBus 的所有权
- 四屏镜像
- 卷动
- 商业 ROM 测试夹具
运行本课
uv run pytest tests/chapter_12_mirroring/test_326_mapper_preserves_mirroring.py -v