254. 映射器的 CHR 写入路由
实现通过映射器进行的 CHR 写入路由。
第 254 / 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_254_mapper_chr_write_routing.py
参考资料
https://www.nesdev.org/wiki/PPU_memory_map
https://www.nesdev.org/wiki/NROM需要更新的文件
emulator/cartridge/mapper_interface.py
emulator/cartridge/mapper000.py
emulator/bus/ppu_bus.py什么是 CHR 内存?CHR 内存是 PPU 读取图块图案字节的地方。PPU 地址范围 $0000-$1FFF 就是 CHR 区域。
简单示例
PPU reads $0000
mapper returns the first byte of CHR ROM对于本教程中官方的 Mapper000/NROM,CHR 是 ROM,因此写入会被拒绝。
为什么需要这一步
PpuBus 应该只负责路由地址,不应该决定 CHR 写入是否合法,这个策略应由映射器来负责。
正确的职责划分
PpuBus.write($0000-$1FFF, value)
-> mapper.write_chr(addr, value)
Mapper000.write_chr(addr, value)
-> rejects writes because official Mapper000 CHR ROM is read-only建议的实现示例
class MapperInterface(Protocol):
def read_prg(self, addr: int) -> int:
...
def read_chr(self, addr: int) -> int:
...
def write_chr(self, addr: int, value: int) -> None:
...
class Mapper000:
def write_chr(self, addr: int, value: int) -> None:
if not (CHR_ROM_START <= addr <= CHR_ROM_END):
raise ValueError(f"Address out of CHR ROM range: {addr:04X}")
raise ValueError("CHR ROM is read-only for official Mapper000")
class PpuBus:
def write(self, addr: int, value: int) -> None:
addr = addr & PPU_ADDRESS_MASK
if CHR_START <= addr <= CHR_END:
if self.mapper is not None:
self.mapper.write_chr(addr, value)
return
self.vram.write(addr, value)
return不在本步骤范围内
- CHR RAM 支持
- 带有可写 CHR RAM 的非官方/自制 Mapper000 变体
- 映射器的存储体切换
- 渲染 CHR 图块
运行本课
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_254_mapper_chr_write_routing.py -v