Killing NMI by polling $2002?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
6502freak
Posts: 92
Joined: Sun Dec 07, 2008 1:11 pm

Killing NMI by polling $2002?

Post by 6502freak »

Hi, I have a short question: is it correct that by continuously polling $2002 in a very tight loop, it may happen that NMI's won't occur? Because that's exactly how Nintendulator and Nestopia behave, but not FCE Ultra.

I'd just like to have a confirmation that this illogical and stupid behaviour also happens on the real hardware. Thanks!
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

yes, it's a quirk in the real hardware.

Which is exactly why you should never poll $2002 when an NMI might occur (never use $2002 to wait for VBlank except when waiting for PPU warm-up)
6502freak
Posts: 92
Joined: Sun Dec 07, 2008 1:11 pm

Post by 6502freak »

Disch wrote:yes, it's a quirk in the real hardware.

Which is exactly why you should never poll $2002 when an NMI might occur (never use $2002 to wait for VBlank except when waiting for PPU warm-up)
I am using Sprite 0 hit detection in my main game loop to split the screen, and I was just wondering why NMI's were occasionally not happening, until I found out that on the NES, the NMI flag apparantly can be cleared before the actual NMI is happening... Of course I already have implemented a workaround for it, but I was just wondering if this stupid behaviour is actually correct. From a hardware designer's standpoint, it absolutely makes no sense at all.

Thanks for the confirmation! ;)
tomaitheous
Posts: 592
Joined: Thu Aug 28, 2008 1:17 am
Contact:

Post by tomaitheous »

Disch wrote:yes, it's a quirk in the real hardware.
Why do you call it a quirk though? Many systems hold the IRQ line active until a port is read (or sometimes written to) to acknowledge the interrupt.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Because it's a race condition. The NMI should fire and THEN the acknowledgment should happen.
6502freak
Posts: 92
Joined: Sun Dec 07, 2008 1:11 pm

Post by 6502freak »

tomaitheous wrote:
Disch wrote:yes, it's a quirk in the real hardware.
Why do you call it a quirk though? Many systems hold the IRQ line active until a port is read (or sometimes written to) to acknowledge the interrupt.
On the NES, either there seems to be a significant delay between setting bit#7 of $2002 and pulling the NMI line (so that it can be cleared before), or reading $2002 sometimes prevents bit#7 to be set at all. Since this behaviour doesn't make any sense, it seems to be a hardware bug which Nintendo did not fix.

I really wonder if the designers were really sure what Sprite 0 hit detection was supposed to accomplish. For collision detection, it's quite useless. And for mid-screen changes, there are lots of factors which make it unnecessarily complex. For example, why doesn't Sprite 0 hit generate an NMI? It wouldn't have cost much extra logic. Or why does the Sprite pixel have to overlap with the background, instead of just setting the flag when Sprite 0 is in range?

They probably did implement this weird method because there are some patents from Commodore and Atari involved for methods of synchronizing the raster beam with the CPU.

Enough ranting. ;)
Celius
Posts: 2159
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

I've always wondered why they couldn't just make a sprite 0 hit when it was drawn. I agree it's overly complex that it has to be a solid sprite pixel on a solid BG pixel. I actually have used it for sprite to BG collision in my REALLY newbie crap demos. In real, professional game design this is just plain sloppy. It's great for split screen effects though, assuming you know that the NMI has already happened in the current frame.
tomaitheous
Posts: 592
Joined: Thu Aug 28, 2008 1:17 am
Contact:

Post by tomaitheous »

6502freak wrote: On the NES, either there seems to be a significant delay between setting bit#7 of $2002 and pulling the NMI line (so that it can be cleared before), or reading $2002 sometimes prevents bit#7 to be set at all.
Oh, so you're saying there's an instance where you won't get the corret status of BIT #7 *and* you'll cause the bit to clear - causing a miss of the interrupt?
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Yes, exactly. Here's the output of a test ROM which reads $2002 every frame, each time one PPU clock (1/3 CPU clock) later. The first column shows an N if NMI occurred normally for that frame, and the second shows a V if the high bit of $2002 was set when read. The test first starts reading a little before VBL, so the high bit isn't set yet. Note how for row 04, NMI doesn't occur AND the VBL flag reads back as clear (reading $2002 again still reads it back as clear). This can only occur every third frame, due to a CPU cycle being 3 PPU clocks.

Code: Select all

01 N-
02 N-
03 N-
04 --
05 -V
06 -V
07 NV
08 NV
09 NV
6502freak
Posts: 92
Joined: Sun Dec 07, 2008 1:11 pm

Post by 6502freak »

blargg wrote:Yes, exactly. Here's the output of a test ROM which reads $2002 every frame, each time one PPU clock (1/3 CPU clock) later. The first column shows an N if NMI occurred normally for that frame, and the second shows a V if the high bit of $2002 was set when read. The test first starts reading a little before VBL, so the high bit isn't set yet. Note how for row 04, NMI doesn't occur AND the VBL flag reads back as clear (reading $2002 again still reads it back as clear). This can only occur every third frame, due to a CPU cycle being 3 PPU clocks.

Code: Select all

01 N-
02 N-
03 N-
04 --
05 -V
06 -V
07 NV
08 NV
09 NV
Thanks for the clarification, blargg!
Roth
Posts: 400
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Post by Roth »

Here is a textbook example of what happens if you poll $2002 to wait for vblank:

http://robertlbryant.com/gaming/download/ttxo_demo.nes

This was the first completed program that I made, and it shows... alot! haha I haven't booted it up in awhile, but I'm pretty sure you can notice it when making a move... or the computer makes a move. I can't remember. Just play it, and you'll be able to hear where the music drags in spots. That is from polling $2002 to wait for vblank, in which you can hear the frames being missed.
Post Reply