269. Validation console vblank nmi path

VALIDATION: Console.step drives the full VBlank NMI path.

Lesson 269 of 356 · tests/chapter_04_ppu_timing_and_vblank/test_269_VALIDATION_console_vblank_nmi_path.py

No new implementation should be required for this test if steps 259-268 are complete.

References

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

Why this validation exists

Previous tests verified each mechanism separately

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

This test validates that those pieces work together in one small machine-level scenario.

End-to-end path being validated

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

Tiny program used in this validation

$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 vector setup

$FFFA = $00
$FFFB = $90

Expected result

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

Important

This is still simplified timing. The test intentionally places the PPU near VBlank so the validation is fast and deterministic. This is not dot-accurate NMI latency testing.

Out of scope

  • rendering pixels
  • PPU sprite behavior
  • OAM DMA
  • controller input
  • exact NMI latency
  • dynamic CPU cycle penalties

Run this lesson

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