Maybe now is a good time to talk about a couple of gripes I have with the Nerdy Nights tutorials. One is the use of 0 as the IRQ vector... There's always a chance you'll accidentally enable IRQs, or execute a BRK instruction, in which case the CPU will jump to address $0000 and crash. The fix for this is very simple and doesn't consume any extra resources: just point the IRQ vector to the RTI instruction at the end of the NMI handler:
Code: Select all
NMI:
;(do all your NMI stuff here)
IRQ: ;<-- point the IRQ vector to this label, instead of 0
rti ;returns from either the NMI or the IRQ
If at some point you end up needing an actual IRQ handler (for an audio engine or an scanline counter), just give the NMI handler its own RTI back.
Now for the biggest problem in the Nerdy Nights tutorials: the entire game logic runs during vblank! The NMI signal is there to notify the CPU that vblank has started, so that you can make the most out of that short period and do all your video updates (sprites, name tables, palettes, etc.). But that's not how the tutorials use it, instead they do a bunch of tasks that have no place running during vblank, such as reading the controllers and reading sprite, and only after that will it carry out the necessary video updates.
Since video updates can only be done during vblank, this means that both the game logic and the video updates have to fit in the vblank period, witch is a measly 20 scanlines out of 262. That's right, Nerdy Nights programs can only use less than 8% of the CPU power of the NES before they start to glitch.
I'm not sure if they fix this in later lessons (I hope they do!), but sometimes you see people trying to create basic games such as Pong using Nerdy Nights as a base, and the games suddenly breaks because they added too much logic and the video updates started spilling out o vblank and into rendering time.
The simplest fix here is to invert the order in which you do things in the NMI handler: first do the video updates (using data computed during the previous NMI), then process the game logic for the *next* frame. Just be careful to not do a glitchy round of video updates the first time the NMI handler runs, possibly by having a flag signal whether the NMI handler is supposed to do any video updates. A flag like this is normally needed anyway for cases when you want to disable rendering and do big name table updates, so the NMI handler won't interfere with those.