NMI behaviour
Moderator: ZSNES Mods
NMI behaviour
I was wondering if anyone had figured out if NMI triggers on a different line when $2133 (screen resolution) is changed. Also if anyone if the NMI is different on a PAL SNES or is the same as NTSC.
Yes. If $2133.d2 is clear, NMI occurs on scanline 225. Otherwise, it occurs on scanline 240. NMI is lowered even if $4200.d7 is clear, unlike IRQ. The bit just prevents the NMI interrupt from occuring, but $4210.d7 is still set.
From what I can tell, PAL is the same. The only difference with PAL is that there are 50 extra scanlines per field, and 50fps instead of 60. I'm not sure how PAL handles long dots, missing dots, and things like that, though.
I have a lot of edge-case information too, if you want. Things like NMI being set in $4210 twice, triggering multiple NMIs in the same frame, etc.
From what I can tell, PAL is the same. The only difference with PAL is that there are 50 extra scanlines per field, and 50fps instead of 60. I'm not sure how PAL handles long dots, missing dots, and things like that, though.
I have a lot of edge-case information too, if you want. Things like NMI being set in $4210 twice, triggering multiple NMIs in the same frame, etc.
Thanks for the info byuu, thats pretty much what I thought, but I just wanted to be sure 
That NMI info would be great, especially regarding the info on $4210, there is a bug in Cu-On-Pa that is checking $4210 for the vblank bit set from what I think to be an NMI but the NMI is running earlier than it should be. Needless to say snes9x also suffers from the same problem so I was not able to find any answers there either.

That NMI info would be great, especially regarding the info on $4210, there is a bug in Cu-On-Pa that is checking $4210 for the vblank bit set from what I think to be an NMI but the NMI is running earlier than it should be. Needless to say snes9x also suffers from the same problem so I was not able to find any answers there either.
I see... they both get locked up in the load game menu...
http://byuu.cinnamonpirate.com/temp/nmi_pf.zip
There are two NMI tests in there. test_nmi is just used to verify exact hardware timing positions, ZSNES will never pass this so don't worry about it. However, ZSNES should be able to pass demo_nmi if you add the special cases I mention. I'd bet that ZSNES would play Cu-On-Pa if it passed this test.
To see your progress in demo_nmi, look at SRAM after ZSNES fails, and it will tell you the test # that failed (there's only four, ZSNES fails the first presently).
That said, I'll paraphrase the notes:
1)
a) $4210.d7 is clear at reset/power on
b) $4210.d7 is set even when $4200.d7 is clear (NMIs are disabled)
c) $4210.d7 is cleared at the start of a new frame
2) Test 2 just verifies that NMIs fire correctly by running 32 frames and counting how many NMIs triggered (should be 32, obviously).
3)
a) NMI should still trigger if you enable it for the first time in the frame after V=225
b) NMI should NOT trigger if you enable it after V=0 (the trigger is cleared at the start of a new frame)
c) Clearing and setting $4200.d7 without reading $4210 will allow multiple NMIs to trigger in the same frame
4) If NMIs are disabled, you cross V=225, and $4210.d7 is set... if you then read from $4210 and THEN enable NMIs, an NMI will not occur
test_nmi verifies the following edge cases:
Don't confuse HC with H (OPHCT). HC is H cycles, it's the exact cycle position on a scanline, so HC=6 is the same as H=1.5
* NMI is tested at the start of the last bus cycle of each opcode, not at the end of each opcode.
* NMI goes low when tested at V=225/240,HC=6 or later.
* $4210.d7 is set at V=225/240,HC=2 or later.
* If you read $4210 at V=225/240,HC=2 or 4, then $4210.d7 will stay set! This is important: if a game were poorly written and did something like this:
loop:
- lda $4210 : bpl - ;wait for NMI to fire
;do something
bra loop
It is possible that this loop could reach "do something" twice in one frame.
I have yet to test what happens to NMIs when a DMA crosses over V=225. anomie says the NMI triggers ~2 opcodes after the DMA completes... this causes a bug in Wild Guns in bsnes because I don't handle this case.
Lastly, I wanted to say that you've done excellent work as of late. The latest WIP finally gets Metroid 3 looking perfect, and SFA2 as well! Excellent job. BTW, I take it you modified the scanline rendering to occur at the start of hblank, rather than the start of each line, to fix Metroid? That would also fix the status menu in Dai Kaijuu Monogatari 2 battles.
It's a lose-lose situation, because real hardware renders dot by dot, but no emulator even tries to do that yet... but I think rendering at the start of hblank (H=274) is much safer, since tons of games write to screen control registers after H=0.
http://byuu.cinnamonpirate.com/temp/nmi_pf.zip
There are two NMI tests in there. test_nmi is just used to verify exact hardware timing positions, ZSNES will never pass this so don't worry about it. However, ZSNES should be able to pass demo_nmi if you add the special cases I mention. I'd bet that ZSNES would play Cu-On-Pa if it passed this test.
To see your progress in demo_nmi, look at SRAM after ZSNES fails, and it will tell you the test # that failed (there's only four, ZSNES fails the first presently).
That said, I'll paraphrase the notes:
1)
a) $4210.d7 is clear at reset/power on
b) $4210.d7 is set even when $4200.d7 is clear (NMIs are disabled)
c) $4210.d7 is cleared at the start of a new frame
2) Test 2 just verifies that NMIs fire correctly by running 32 frames and counting how many NMIs triggered (should be 32, obviously).
3)
a) NMI should still trigger if you enable it for the first time in the frame after V=225
b) NMI should NOT trigger if you enable it after V=0 (the trigger is cleared at the start of a new frame)
c) Clearing and setting $4200.d7 without reading $4210 will allow multiple NMIs to trigger in the same frame
4) If NMIs are disabled, you cross V=225, and $4210.d7 is set... if you then read from $4210 and THEN enable NMIs, an NMI will not occur
test_nmi verifies the following edge cases:
Don't confuse HC with H (OPHCT). HC is H cycles, it's the exact cycle position on a scanline, so HC=6 is the same as H=1.5
* NMI is tested at the start of the last bus cycle of each opcode, not at the end of each opcode.
* NMI goes low when tested at V=225/240,HC=6 or later.
* $4210.d7 is set at V=225/240,HC=2 or later.
* If you read $4210 at V=225/240,HC=2 or 4, then $4210.d7 will stay set! This is important: if a game were poorly written and did something like this:
loop:
- lda $4210 : bpl - ;wait for NMI to fire
;do something
bra loop
It is possible that this loop could reach "do something" twice in one frame.
I have yet to test what happens to NMIs when a DMA crosses over V=225. anomie says the NMI triggers ~2 opcodes after the DMA completes... this causes a bug in Wild Guns in bsnes because I don't handle this case.
Lastly, I wanted to say that you've done excellent work as of late. The latest WIP finally gets Metroid 3 looking perfect, and SFA2 as well! Excellent job. BTW, I take it you modified the scanline rendering to occur at the start of hblank, rather than the start of each line, to fix Metroid? That would also fix the status menu in Dai Kaijuu Monogatari 2 battles.
It's a lose-lose situation, because real hardware renders dot by dot, but no emulator even tries to do that yet... but I think rendering at the start of hblank (H=274) is much safer, since tons of games write to screen control registers after H=0.