$FFFA is a ROM location. Doing
bit $FFFA will not read the state of the PPU.
The state of the NMI generator is at $2002, but there's a race condition associated with reading it. Normally you want to make $FFFA point at a routine that modifies a variable in RAM, then make your main program wait for that variable to change.
If you want an analogy to high-level languages, then $FFFA, $FFFC, and $FFFE contain hardcoded function pointers to
listeners for NMI, reset, and IRQ events respectively, and the NMI and IRQ listeners run in a separate thread with priority over the main thread.
Code: Select all
volatile unsigned char nmis = 0;
volatile unsigned char display_list_ready = 0;
int main() {
RegisterNMIListener(NMI);
// Omitted: init code
while (!gameover) {
PollControllers();
GameLogic();
PrepareDisplayList();
display_list_ready = 1;
vsync();
}
}
static void vsync() {
unsigned char oldnmis;
while (oldnmis == nmis) { }
}
static void NMI() {
nmis += 1;
if (display_list_ready) {
BlitOAM();
BlitVRAM();
display_list_ready = 0;
}
}
In 6502 assembly language, you
RegisterNMIListener() by putting a function pointer at $FFFA.