269. 验证:Console 的 VBlank NMI 路径

验证:Console.step 驱动完整的 VBlank NMI 路径。

269 / 356 · tests/chapter_04_ppu_timing_and_vblank/test_269_VALIDATION_console_vblank_nmi_path.py

如果第 259-268 步都已完成,这个测试不应该需要任何新的实现。

参考资料

https://www.nesdev.org/wiki/PPU_registers#PPUCTRL
https://www.nesdev.org/wiki/PPU_registers#Vblank_NMI
https://www.nesdev.org/wiki/CPU_interrupts

这个验证存在的原因

之前的测试分别验证了每一个独立的机制

PPU.step() advances timing
PPU enters VBlank and sets VBLANK_STARTED
PPUCTRL bit 7 enables NMI requests
CPU.step() returns CPU cycles
Console.step() advances PPU by cpu_cycles * 3
Console consumes ppu.nmi_requested
CPU.interrupt_nmi() jumps through $FFFA/$FFFB

这个测试验证的是这些部分能否在一个小型的机器级场景中协同工作。

本次要验证的端到端路径

CPU executes LDA #$80
    -> A = $80

CPU executes STA $2000
    -> CpuBus routes $2000 to PPUCTRL
    -> PPUCTRL bit 7 enables NMI

Console.step() keeps advancing CPU and PPU together
    -> CPU cycles advance PPU by cycles * 3
    -> PPU enters VBlank
    -> PPU sets nmi_requested = True
    -> Console consumes the request
    -> CPU.interrupt_nmi() reads $FFFA/$FFFB
    -> CPU jumps to the NMI handler address

本次验证中使用的极小程序

$8000: A9 80       LDA #$80       ; set PPUCTRL NMI-enable bit
$8002: 8D 00 20    STA $2000      ; write A to PPUCTRL
$8005: EA          NOP            ; wait while PPU reaches VBlank
$8006: EA          NOP
...

NMI 向量设置

$FFFA = $00
$FFFB = $90

预期结果

CPU PC becomes $9000 after Console consumes the VBlank NMI request.

重要说明

这仍然是简化后的时序。测试有意把 PPU 设置在接近 VBlank 的位置,以便让验证过程既快速又确定性可控。这并不是逐点精确的 NMI 延迟测试。

不在本步骤范围内

  • 渲染像素
  • PPU 精灵行为
  • OAM DMA
  • 手柄输入
  • 精确的 NMI 延迟
  • 动态的 CPU 周期惩罚

运行本课

uv run pytest tests/chapter_04_ppu_timing_and_vblank/test_269_VALIDATION_console_vblank_nmi_path.py -v