VBlank and NMI timing

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
ashkalov
Posts: 9
Joined: Thu May 14, 2020 3:58 am

VBlank and NMI timing

Post by ashkalov » Fri Aug 28, 2020 2:42 am

Hello. Well, tell the fool.
I am currently dealing with vbl and nmi timings in my emulator.
The question torments me. NMI interrupts are called with the vblank setting, during 241 scanlines and 1 cycle? Or the NMI is invoked with a delay, and if so, why? I know ... the question is stupid, but I'm confused.
Nostalgia is our little time machine

User avatar
dougeff
Posts: 2735
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: VBlank and NMI timing

Post by dougeff » Fri Aug 28, 2020 5:32 am

I think the slight delay is just part of how the 6502 functions. The chip needs to push a PC address to the stack, push the flags to the stack, and jump to the NMI vector. That all takes time.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
Quietust
Posts: 1596
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: VBlank and NMI timing

Post by Quietust » Fri Aug 28, 2020 6:23 am

dougeff wrote:
Fri Aug 28, 2020 5:32 am
I think the slight delay is just part of how the 6502 functions. The chip needs to push a PC address to the stack, push the flags to the stack, and jump to the NMI vector. That all takes time.
Additionally, it needs to wait for the current instruction to finish executing before it can start handling the interrupt, which could be up to 7 cycles depending on what instruction it was executing at the time (e.g. "INC $0300,X").
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

User avatar
ashkalov
Posts: 9
Joined: Thu May 14, 2020 3:58 am

Re: VBlank and NMI timing

Post by ashkalov » Fri Aug 28, 2020 10:07 am

No, the question is not about how late the 6502 handles interrupts. And about whether there is a delay in calling this interrupt from the PPU during the onset of the VBlank period.
Nostalgia is our little time machine

User avatar
Quietust
Posts: 1596
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: VBlank and NMI timing

Post by Quietust » Fri Aug 28, 2020 10:21 am

Hopefully, some of these statements should answer the question you were trying to ask:
1. When the PPU reaches the beginning of scanline 241, VBLANK begins and PPU register $2002 bit 7 ($80) is set.
2. When the PPU reaches the end of scanline 261, VBLANK ends and PPU register $2002 bit 7 is cleared.
3. After the CPU reads from PPU register $2002, bit 7 is cleared afterwards.
4a. If PPU register $2000 bit 7 (NMI enable) is already on when PPU register $2002 bit 7 (VBLANK) gets turned on, an NMI will be generated.
4b. Similarly, If PPU register $2000 bit 7 is turned on when PPU register $2002 bit 7 is already on, another NMI will be generated.
4c. In other words, the NMI signal is equivalent to $2000 bit 7 AND $2002 bit 7 (though it's actually NAND, because the interrupt lines are active-low, meaning 0 is "trigger interrupt" and 1 is "don't trigger interrupt"). This means you can toggle $2000.7 repeatedly and generate multiple NMIs in a single frame.
5. When the CPU receives an NMI, it will finish the instruction it's currently executing and then service the interrupt. Logically, it's actually executing a BRK instruction with some special logic (not incrementing PC twice, pushing flags with B=0, and fetching the NMI vector from $FFFA-$FFFB).
6. The CPU cannot ignore an NMI (the "NM" stands for "Non-Maskable"), and even if the interrupt line is only active for a single cycle, the CPU will still service it (the interrupt is edge-triggered). This differs from the IRQ signal, which is both maskable (using the "SEI" instruction) and level-sensitive (if the IRQ line is only active for a short period of time, it's possible for the CPU to miss it).
7. If the CPU reads from register $2002 at roughly the same time that bit 7 was going to be set, "strange things" can happen depending on the exact timing (e.g. it could read D7=0 but still trigger NMI, or it could actually suppress NMI).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

User avatar
ashkalov
Posts: 9
Joined: Thu May 14, 2020 3:58 am

Re: VBlank and NMI timing

Post by ashkalov » Fri Aug 28, 2020 10:37 am

Quietust wrote:
Fri Aug 28, 2020 10:21 am
4a. If PPU register $2000 bit 7 (NMI enable) is already on when PPU register $2002 bit 7 (VBLANK) gets turned on, an NMI will be generated.
4b. Similarly, If PPU register $2000 bit 7 is turned on when PPU register $2002 bit 7 is already on, another NMI will be generated.
When does this happen? That is, compliance with these conditions at the time of writing to $2002 or $2000, you must call the NMI interrupt?
Nostalgia is our little time machine

User avatar
Quietust
Posts: 1596
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: VBlank and NMI timing

Post by Quietust » Fri Aug 28, 2020 11:45 am

ashkalov wrote:
Fri Aug 28, 2020 10:37 am
Quietust wrote:
Fri Aug 28, 2020 10:21 am
4a. If PPU register $2000 bit 7 (NMI enable) is already on when PPU register $2002 bit 7 (VBLANK) gets turned on, an NMI will be generated.
4b. Similarly, If PPU register $2000 bit 7 is turned on when PPU register $2002 bit 7 is already on, another NMI will be generated.
When does this happen? That is, compliance with these conditions at the time of writing to $2002 or $2000, you must call the NMI interrupt?
The first one is the "normal" workflow - if you write $80 (or any value with bit 7 set) to $2000 to enable NMI, then the PPU will generate an NMI at the beginning of scanline 241 each frame.

The second one is an "abnormal" scenario which emulators really only need to implement in order to be compatible with test ROMs - if you did something like "LDA #$00; STA $2000; LDA #$80; STA $2000" during VBLANK (and you didn't read $2002), then the PPU will generate another NMI. It's completely useless, but it's how the PPU actually works.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

User avatar
ashkalov
Posts: 9
Joined: Thu May 14, 2020 3:58 am

Re: VBlank and NMI timing

Post by ashkalov » Fri Aug 28, 2020 11:48 am

Thank you so much! This is what I wanted to understand. You have explained very clearly.
Nostalgia is our little time machine

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: VBlank and NMI timing

Post by Controllerhead » Fri Aug 28, 2020 12:22 pm

Quietust wrote:
Fri Aug 28, 2020 11:45 am
The second one is an "abnormal" scenario which emulators really only need to implement in order to be compatible with test ROMs - if you did something like "LDA #$00; STA $2000; LDA #$80; STA $2000" during VBLANK (and you didn't read $2002), then the PPU will generate another NMI. It's completely useless, but it's how the PPU actually works.
It is certainly something to consider in development!

I was enabling NMI before my initialization code was complete and wondering what the heck was happening until i stepped through it. I had assumed an NMI was only generated at the start of line 241. This is not so! I ended up reading $2002 to prevent this and also doing it last.

I suppose if your code finishes a little late past 240 (if NMI was off) you could "try" not to "miss" a frame with this? Maybe... Enabling NMI during rendering will cause a little visible glitch though across a few dots (i think this happens in SMB?) so it's probably not the best idea...

I'm also using bit 7 of status to just not render the background if drawing takes too long, and keeping the latch reset beforehand. This is certainly helpful. A quick little 1 frame "blink" beats a quick little 1 frame glitched screen.
Image

Post Reply