I've rewritten my VBL/NMI tests that test timing and behavior of the VBL flag and NMI. These should cover almost everything, including obscure details. A failed test now prints more information, which makes finding the cause easier. Most of the timing tests run on successive PPU clocks and print the result from each, so you can see a graphical display of timing and easily diagnose off-by-one errors visually. Full ca65 source is included.
nes_vbl_nmi_tests.zip
Example output for NMI suppression test:
01 N-
02 N-
03 N-
04 --
05 -V
06 -V
07 NV
08 NV
09 NV
The test reads $2002 and shows whether NMI occurred normally that frame, and whether the VBL flag was set in the byte read from $2002. It runs multiple times, each one PPU clock later. The left column is the relative time of the $2002 read, in PPU clocks. The N means NMI occurred (wasn't suppressed), and V means the VBL flag was set in the byte read from $2002.
nes_vbl_nmi_tests.zip
Example output for NMI suppression test:
01 N-
02 N-
03 N-
04 --
05 -V
06 -V
07 NV
08 NV
09 NV
The test reads $2002 and shows whether NMI occurred normally that frame, and whether the VBL flag was set in the byte read from $2002. It runs multiple times, each one PPU clock later. The left column is the relative time of the $2002 read, in PPU clocks. The N means NMI occurred (wasn't suppressed), and V means the VBL flag was set in the byte read from $2002.