nesdev.com
http://forums.nesdev.com/

Question about NMI and triggering.
http://forums.nesdev.com/viewtopic.php?f=3&t=16413
Page 1 of 1

Author:  urbanspr1nter [ Sat Aug 26, 2017 7:14 am ]
Post subject:  Question about NMI and triggering.

Hi, I have my CPU for an NES emulator working and it passes nestest.nes. Now I am getting started with writing the PPU, but I am having a hard time actually knowing when an NMI is triggered for a VBLANK.

I am just trying to get the nametable to be written for Donkey Kong -- for something simple first...

If my understanding is correct, the NMI bit is controlled in BIT_7 in $2000. I am turning on this bit when my scanlines hit 241. I set the NMI bit, then the Vblank bit in 2002.

So my cycle is like this (in pseudo-code):

Code:
run() {
    fetchOpcode();
    executeOpcode();
    ppuRun();
    // check NMI here. and execute NMI.
}

ppuRun() {
    incrementPPUCycles();
    if(cycles === 341) ppuScanlines++;
    if(ppuScanlines >= 241 && ppuScanlines <= 260) {
        ppuSetNmi(1);
        ppuSetVblank(1);
    }

    if(ppuScanlines == 261) {
       ppuSetNmi(0);
       ppuSetVblank(0);
    }

    if(ppuScanlines == 262) {
       outputFrame();
       ppuScanlines = 0;
    }
}


Do I have the right idea here? If so, I am having problems actually going into NMI. I actually go into the NMI handler in FFFA/FFFB, but then the instructions are
Code:
PHA
over and over again. My guess is that it's going into the NMI routine in every CPU cycle. Just making sure if i have things conceptually right before going further.

Author:  tepples [ Sat Aug 26, 2017 7:49 am ]
Post subject:  Re: Question about NMI and triggering.

/NMI on a 6502 is edge-sensitive. This means if goes from high (unasserted) to low (asserted), the CPU will call the NMI handler. It will not call the NMI handler again until /NMI goes high then low again. This is why you usually* see only one call to the NMI handler per vblank.

/IRQ, by contrast, is level-sensitive. If a CLI or PHP instruction clears the interrupt priority level bit (I, bit 2 of P) while /IRQ remains low, the CPU will call the IRQ handler again.


* A couple games, such as Bases Loaded, clear bit 7 of $2000 and then set it again without reading $2002 to acknowledge the NMI. These games expect this to cause the CPU to call the NMI handler again.

Author:  urbanspr1nter [ Sat Aug 26, 2017 7:52 am ]
Post subject:  Re: Question about NMI and triggering.

So then, it would make sense to do something along the lines of keeping the previous NMI flag and then check --

if the currentNMI is true, and the previousNMI was false, then run NMI handler?

Author:  tepples [ Sat Aug 26, 2017 8:09 am ]
Post subject:  Re: Question about NMI and triggering.

Yes, you will need to keep track of the previous state of /NMI. Someone familiar with Visual 6502 could find exactly the node that stores the previous state.

Author:  urbanspr1nter [ Sat Aug 26, 2017 8:17 am ]
Post subject:  Re: Question about NMI and triggering.

Cool! that looks like it fixed it...

Looks like my emu isn't stupidly executing PHA over and over again. :)

As far as the IRQ bit goes, that's just as far as checking if the bit is asserted/deasserted on every opcode execution?

Author:  Zepper [ Sat Aug 26, 2017 6:43 pm ]
Post subject:  Re: Question about NMI and triggering.

Not sure if it's useful, information from test ROMs. "Reading flag" means reading $2002 bit $80 (VBlank flag).
Code:
Reading flag 4 PPU clocks before set shouldn't suppress NMI
Reading flag 3 PPU clocks before set shouldn't suppress NMI
Reading flag 2 PPU clocks before set shouldn't suppress NMI
*Reading flag 1 PPU clock before set should suppress NMI
*Reading flag when it's set should suppress NMI
*Reading flag 1 PPU clock after set should suppress NMI
Reading flag 2 PPU clocks after set shouldn't suppress NMI
Reading flag 3 PPU clocks after set shouldn't suppress NMI
Reading flag 4 PPU clocks after set shouldn't suppress NMI

Page 1 of 1 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/