223. Validación: la CPU ejecuta una pequeña ROM iNES
PRUEBA DE VALIDACIÓN: la CPU ejecuta una pequeña ROM iNES generada.
Lección 223 de 356 · tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.py
Este no es un paso de implementación para el estudiante.
Requisitos previos bajo validación
- this file: make_tiny_ines_rom and
test_cpu_executes_tiny_generated_ines_rom_from_reset_vector
- emulator/cartridge/ines.py: PRG_ROM_BANK_SIZE, CHR_ROM_BANK_SIZE,
parse_ines_header, and parse_ines_rom
- emulator/cartridge/cartridge.py: Cartridge.from_ines_bytes
- emulator/cartridge/mapper_factory.py: create_mapper
- emulator/cartridge/mapper000.py: Mapper000.read_prg
- emulator/bus/cpu_bus.py: CpuBus.__post_init__ and CpuBus.read
- emulator/cpu/cpu.py: CPU.reset, CPU.fetch_byte, and CPU.step
- emulator/cpu/opcodes.py: OPCODE_TABLE entry $A9
- emulator/cpu/instructions.py: ldaSecuencia de validación
1. make_tiny_ines_rom builds a 16-byte iNES header declaring mapper 0, one
16KB PRG bank, one 8KB CHR bank, and no trainer.
2. It writes A9 42 (LDA #$42) and EA (NOP) at PRG offsets $0000-$0002,
corresponding to CPU $8000-$8002.
3. It writes reset-vector bytes 00 80 at PRG offsets $3FFC-$3FFD. Mapper000's
16KB mirror makes CPU reads $FFFC-$FFFD observe those bytes.
4. Cartridge.from_ines_bytes parses and slices the generated bytes.
5. CpuBus(cartridge=cartridge) creates Mapper000 through create_mapper.
6. CPU.reset reads the vector through CpuBus and Mapper000, producing
PC=$8000.
7. One CPU.step fetches $A9 through the same path, dispatches lda, fetches
operand $42, and leaves A=$42 and PC=$8002. The trailing NOP is fixture
data and is not executed by this test.Ejecuta exactamente esta validación con
pytest -q tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.pyEl límite completo bajo validación es
iNES bytes
-> Cartridge.from_ines_bytes(data)
-> CpuBus(cartridge=cartridge)
-> create_mapper(cartridge)
-> Mapper000
-> CPU.reset()
-> CPU.step()Por qué existe este paso
La validación existe porque las pruebas unitarias pueden demostrar cada parte de forma aislada mientras que aún pueden aparecer errores en los límites entre componentes. Esta prueba no añade implementación de producción; demuestra que las lecciones 212-222 funcionan juntas para que la CPU pueda buscar y ejecutar una instrucción desde la PRG ROM respaldada por el cartridge usando el vector de reset.
La ROM se genera dentro de la prueba. Es intencionadamente pequeña y no usa la PPU, la APU, mandos, interrupciones ni ninguna característica fuera del alcance actual del emulador.
Programa pequeño colocado en la dirección de CPU $8000:
A9 42 LDA #$42
EA NOPVector de reset
CPU $FFFC = $00
CPU $FFFD = $80Así que tras el reset
PC = $8000Detalle importante de Mapper000
Para un cartridge NROM de 16KB, $FFFC-$FFFD de la CPU se corresponden con los desplazamientos $3FFC-$3FFD de la PRG ROM porque $C000-$FFFF refleja el banco de PRG de 16KB.
Invariantes
La carga útil iNES está completa y en memoria; el número de mapper y los tamaños de banco sobreviven al análisis; las lecturas del vector de reset y las búsquedas de opcode/operando usan todas el enrutamiento de PRG respaldado por el cartridge; el reset selecciona $8000; y una instrucción consume exactamente dos bytes. Un concepto erróneo habitual es colocar el vector en el desplazamiento $7FFC como en un diseño de 32KB/FakeROM, o afirmar que el NOP quedó validado tras un solo paso.
Fuera de alcance
No añadas código de producción para esta validación. La construcción/enrutamiento de registros de la PPU (la siguiente transición del Capítulo 3), la APU, los mandos, las interrupciones, la temporización, las escrituras de PRG, las lecturas de CHR/PPU, los archivos de ROM externos y la integración posterior de consola/PPU se dejan intencionadamente sin ejercitar ni implicar aquí.
Ejecutar esta lección
uv run pytest tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.py -v