liveBook · Manning

Nmi handler

As explained in Classic Game Programming on the NES: Make your own retro video game

A program segment that executes in response to a processor interrupt.

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

How Classic Game Programming on the NES: Make your own retro video game covers it

How deep it goes
Works through a complete assembly routine: stack saves, conditional rendering, DMA, palette copying, restoration, and RTI.
Examples
Uses an OAM sprite table, a 32-byte palette buffer, nmi_ready, and a Megablast initialization routine.
What it assumes
Introduces register saves through A, X, Y, stack instructions, labels, and assembler-generated vector addresses.
What you can do after
Build it from scratch as a vBlank handler that safely updates NES display state and resumes interrupted code.
How it connects
Connects non-maskable interrupts with vBlank, PPU VRAM, sprite DMA, interrupt vectors, the stack, and RTI.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Classic Game Programming on the NES: Make your own retro video game. The section links point to the parts of the book it draws on.