Taking a look, I can now see why it was getting graphical glitches on powerup - you must do the...
Code:
lda #%10000000
sta $2000
lda #%00011110
sta $2001
...
after the "jsr load_palette". Also, you should really be doing...
Code:
lda #0
sta $2000
sta $2001
...immediately after the SEI/CLD at the top of your reset routine.
The reason it doesn't actually detect anything properly is because the Zapper only detects white
as it is rendered - in other words, you need to
constantly poll $4017 for the entire duration of the frame (and give up if another NMI comes along) and wait if it ever senses white. Evidently, NNNesterJ does
not emulate the Zapper with correct timing - the latest build of my emulator (over at
http://nintendulator.sourceforge.net/) has reasonably correct behavior (verified against actual hardware) if you want to perform additional testing.