An NMI handler is a routine the 6502 starts when the NES PPU raises its non-maskable interrupt at vBlank. The CPU pauses its current work, jumps to the address named in the interrupt vector table, runs the handler, then returns to the interrupted code. Because vBlank occurs after the PPU finishes a screen and before it begins the next one, the handler provides a regular point for screen updates. section 1.5.4 section 5.13
Use the handler for PPU work that must happen during vBlank: transferring sprite data, copying palette data, setting scroll and control values, and enabling rendering. Music and sound effects can also be triggered there. Keep its work controlled: the available vBlank period is short, and VRAM changes while the PPU draws can produce incorrect output. section 1.5.4 section 5.13
A safe NMI handler follows this sequence:
- Save A, X, and Y on the stack immediately, since the interrupt can arrive while other code is using them. section 5.13
- Check a zero-page readiness flag when updates should be deferred or rendering must be disabled for larger video-memory changes. section 5.13
- Send prepared data to the PPU, such as the sprite table through DMA and the 32-byte palette table through PPU VRAM I/O. section 5.13
- Restore Y, X, and A in reverse order, then use RTI to resume the interrupted code without corrupting its state. section 5.13
A frame update in an NES game
Reserve a 256-byte OAM area for sprites and a 32-byte palette buffer. Each vBlank, the handler saves registers, transfers the OAM page, writes the palette to PPU address $3F00, restores PPU control settings, clears nmi_ready to mark the update complete, restores registers, and returns with RTI. The main loop prepares those values while rendering is not being updated. section 6.4 section 5.13
Listing 6.12 NMI routine (megablast.s)
.segment "CODE"
.proc nmi
pha #1
txa
pha
tya
pha
bit PPU_STATUS
lda #>oam #2
sta SPRITE_DMA
This annotated routine shows the handler’s opening: preserve the interrupted registers, read PPU status, and begin sprite DMA from the OAM page. section 6.4
