223. Validation cpu executes tiny ines rom

ВАЛИДАЦИОННЫЙ ТЕСТ: CPU выполняет крошечный сгенерированный iNES ROM.

Урок 223 из 356 · tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.py

Это не шаг реализации для студента.

Проверяемые предварительные условия

- 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: lda

Последовательность валидации

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.

Запустите именно эту валидацию с помощью

pytest -q tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.py

Полная проверяемая граница:

iNES bytes
    -> Cartridge.from_ines_bytes(data)
    -> CpuBus(cartridge=cartridge)
    -> create_mapper(cartridge)
    -> Mapper000
    -> CPU.reset()
    -> CPU.step()

Почему этот шаг нужен

Валидация существует потому, что модульные тесты могут доказать корректность каждой части по отдельности, в то время как ошибки всё равно проявляются на границах компонентов. Этот тест не добавляет производственной реализации; он доказывает, что уроки 212-222 работают вместе, так что CPU может выбрать и выполнить инструкцию из PRG ROM, поддерживаемой картриджем, используя вектор сброса.

ROM генерируется внутри теста. Она намеренно крошечная и не использует PPU, APU, контроллеры, прерывания или любые возможности за пределами текущей области эмулятора.

Крошечная программа, размещённая по адресу CPU $8000:

A9 42    LDA #$42
EA       NOP

Вектор сброса

CPU $FFFC = $00
CPU $FFFD = $80

Таким образом, после сброса

PC = $8000

Важная деталь Mapper000

Для 16КБ картриджа NROM CPU $FFFC-$FFFD отображается на смещения PRG ROM $3FFC-$3FFD, потому что $C000-$FFFF зеркалирует 16КБ банк PRG.

Инварианты

Полезная нагрузка iNES полная и находится в памяти; номер mapper'а и размеры банков переживают разбор; чтения вектора сброса и выборки опкода/операнда используют маршрутизацию PRG, поддерживаемую картриджем; сброс выбирает $8000; и одна инструкция потребляет ровно два байта. Распространённое заблуждение — размещать вектор по смещению $7FFC, как в раскладке 32КБ/FakeROM, или утверждать, что NOP был проверен уже после одного шага.

Вне рамок

Не добавляйте производственный код для этой валидации. Построение/маршрутизация регистров PPU (предстоящий переход к Главе 3), APU, контроллеры, прерывания, тайминг, записи в PRG, чтения CHR/PPU, внешние файлы ROM и последующая интеграция консоли/PPU намеренно не задействованы и не подразумеваются здесь.

Запустить этот урок

uv run pytest tests/chapter_02_rom_loading/test_223_VALIDATION_cpu_executes_tiny_ines_rom.py -v