221. CPU 总线 cartridge 集成 第 1 部分
为 CpuBus 添加可选的 Cartridge 支持,第 1 部分。
第 221 / 356 · tests/chapter_02_rom_loading/test_221_cpu_bus_cartridge_integration_part1.py
前置条件
- 第 217 课提供了
Cartridge。 - 第 218-219 课提供了
Mapper000。 - 第 220 课提供了
create_mapper。
待更新文件
emulator/bus/cpu_bus.py待更新符号
emulator.bus.cpu_bus.CpuBus.cartridge
emulator.bus.cpu_bus.CpuBus.__post_init__该文件所需的导入
from emulator.cartridge.cartridge import Cartridge
from emulator.cartridge.mapper_factory import create_mapper本部分实现的内容
- CpuBus 接受一个可选的 cartridge
- CpuBus 在 __post_init__ 中根据该 cartridge 创建一个 mapper
- CpuBus 拒绝同时挂载 program_rom 和 cartridge
本部分尚未实现的内容
- CPU 从 cartridge PRG ROM 中读取
该读取行为将在第 2 部分中测试。
该步骤存在的原因
添加 cartridge 支持有两个独立的职责
1. construction-time wiring
2. read-time routing将它们分开可以让教程更容易理解。学生首先学习总线如何接收 cartridge 并将其转换为 mapper。之后才修改 $8000-$FFFF 的读取路径。
架构模型
Cartridge
stores PRG ROM, CHR ROM, and mapper number
create_mapper(cartridge)
chooses the correct mapper implementation
Mapper000
translates CPU PRG addresses into PRG ROM offsets
CpuBus
owns routing decisions重要边界
CpuBus 不应直接实现 Mapper000 的镜像规则,而应创建或持有一个 mapper,然后在之后将 PRG 读取委托给 mapper.read_prg(addr)。
预期的实现形态
@dataclass
class CpuBus:
program_rom: Optional[MemoryDevice] = None
cartridge: Optional[Cartridge] = None
ram: RAM = field(default_factory=RAM)
def __post_init__(self):
if self.program_rom is not None and self.cartridge is not None:
raise ValueError("Cannot attach both program_rom and cartridge")
self.mapper = None
if self.cartridge is not None:
self.mapper = create_mapper(self.cartridge)不变量
- program_rom remains the writable MemoryDevice seam used by CPU tests
- cartridge and program_rom are mutually exclusive PRG sources
- mapper is always initialized, to None without a cartridge and to the
factory result with one
- Cartridge PRG and CHR bytes reach the mapper unchanged through
create_mapper; CpuBus neither parses nor remaps those bytes常见误解
cartridge 本身并不是 program_rom 的 MemoryDevice 替代品。它是元数据加上 ROM 数据载荷;create_mapper(cartridge) 提供了总线将使用的、具有地址感知能力的对象。
本步骤的范围之外
1. Lesson 222 changes the $8000-$FFFF read path.
2. PPU register routing and PPU construction belong to Chapter 3.
3. Mapper writes, CHR/PPU bus routing, and later behavior are not added here.运行本课
uv run pytest tests/chapter_02_rom_loading/test_221_cpu_bus_cartridge_integration_part1.py -v