221. Integración de cartridge en CpuBus, parte 1
Añadir soporte opcional de Cartridge a CpuBus, parte 1.
Lección 221 de 356 · tests/chapter_02_rom_loading/test_221_cpu_bus_cartridge_integration_part1.py
Requisitos previos
- La lección 217 proporciona
Cartridge. - Las lecciones 218-219 proporcionan
Mapper000. - La lección 220 proporciona
create_mapper.
Archivo a actualizar
emulator/bus/cpu_bus.pySímbolos a actualizar
emulator.bus.cpu_bus.CpuBus.cartridge
emulator.bus.cpu_bus.CpuBus.__post_init__Importaciones necesarias en ese archivo
from emulator.cartridge.cartridge import Cartridge
from emulator.cartridge.mapper_factory import create_mapperQué implementa esta parte
- CpuBus acepta un cartridge opcional
- CpuBus crea un mapper a partir de ese cartridge en __post_init__
- CpuBus rechaza adjuntar a la vez program_rom y cartridge
Qué NO implementa todavía esta parte
- La CPU lee de la PRG ROM del cartridge
Ese comportamiento de lectura se prueba en la parte 2.
Por qué existe este paso
Añadir soporte de cartridge tiene dos responsabilidades separadas
1. construction-time wiring
2. read-time routingMantenerlas separadas facilita seguir el tutorial. Los estudiantes aprenden primero cómo el bus recibe un cartridge y lo convierte en un mapper. Solo después cambian la ruta de lectura para $8000-$FFFF.
Modelo de arquitectura
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 decisionsLímite importante
CpuBus no debería implementar directamente las reglas de mirroring de Mapper000. Debería crear o mantener un mapper, y después delegar las lecturas de PRG en mapper.read_prg(addr).
Forma de implementación esperada
@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)Invariantes
- 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 bytesConcepto erróneo habitual
El cartridge no es en sí mismo un reemplazo de MemoryDevice para program_rom. Es metadatos más las cargas útiles de ROM; create_mapper(cartridge) suministra el objeto consciente de direcciones que usará el bus.
Fuera del alcance de este paso
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.Ejecutar esta lección
uv run pytest tests/chapter_02_rom_loading/test_221_cpu_bus_cartridge_integration_part1.py -v