I hope that this isn't already answered somwhere else but the search function seems to not be working.
I'm making an NES emulator just for fun. It's using a catch-up design with timestamps and can catch-up other components in the middle of a CPU instruction. It can run many simple demos and games and passes many test roms. No sound yet. So only CPU, PPU and simple mappers are emulated.
Before starting to add more things I wanted to design a system to handle everything that can interrupt the CPU's normal execution like NMI, IRQ, DMA, DMC etc. But I ran into trouble almost directly with just trying to get NMI working correctly. I use Blargg's vbl_nmi_timing test roms for testing and I pass tests #1-#4, but not the last three. In test #5 nmi_supression I either get error #3 or #4.
I made a diagram for these tests. I hope it makes some sense and that it's correct:
Now some questions:
1. Is vblank flag set before or after the first cycle in vblank? Or where exactly is cycle 0 from the diagram?
2. NMI is edge-triggered right? Then why is NMI suppressed on cycle 0 and 1? The condition for NMI (Vblank and NMI) is true before both.
If there is no delay between condition and NMI it should be generated on these cycles shouldn't it? It seems to me that this edge must last for 3 PPU-clocks to be generated or is it one CPU-clock to accommodate for PAL where one CPU-clock is 3.2 PPU-clocks not 3? Maybe it need to last this long to filter out electrical interference.
3. Am I right if I say that PPU generates NMI with no delay but the CPU
need at least one extra cycel to catch it?
4. Could someone please describe how NMIs are generated and how the CPU handles them. Very detailed and low-level would be nice.
Maybe I'm just stupid or NMI suppression on cycle 0 and 1 are just special cases.
Finally I'm wondering if someone have come up with a nice, simple and fast way of dealing with things that can interrupt the CPU in a catch-up emulator?
Any help is much appreciated.
I'm making an NES emulator just for fun. It's using a catch-up design with timestamps and can catch-up other components in the middle of a CPU instruction. It can run many simple demos and games and passes many test roms. No sound yet. So only CPU, PPU and simple mappers are emulated.
Before starting to add more things I wanted to design a system to handle everything that can interrupt the CPU's normal execution like NMI, IRQ, DMA, DMC etc. But I ran into trouble almost directly with just trying to get NMI working correctly. I use Blargg's vbl_nmi_timing test roms for testing and I pass tests #1-#4, but not the last three. In test #5 nmi_supression I either get error #3 or #4.
I made a diagram for these tests. I hope it makes some sense and that it's correct:
Code:
| read 0x2002 | write 0x2000
| returns | sets | | disable NMI
ppu clock | vbl as | vbl | NMI | NMI
-4 0 1 yes no
-3 0 1 yes no
-2 0 1 yes no
-1 0 0 no no VBlank suppressed
0 (VBlank) 1 0 no no <-Why?
1 1 0 no no <-Why?
2 1 0 yes yes
3 1 0 yes yes
4 1 0 yes yes
| returns | sets | | disable NMI
ppu clock | vbl as | vbl | NMI | NMI
-4 0 1 yes no
-3 0 1 yes no
-2 0 1 yes no
-1 0 0 no no VBlank suppressed
0 (VBlank) 1 0 no no <-Why?
1 1 0 no no <-Why?
2 1 0 yes yes
3 1 0 yes yes
4 1 0 yes yes
Now some questions:
1. Is vblank flag set before or after the first cycle in vblank? Or where exactly is cycle 0 from the diagram?
2. NMI is edge-triggered right? Then why is NMI suppressed on cycle 0 and 1? The condition for NMI (Vblank and NMI) is true before both.
If there is no delay between condition and NMI it should be generated on these cycles shouldn't it? It seems to me that this edge must last for 3 PPU-clocks to be generated or is it one CPU-clock to accommodate for PAL where one CPU-clock is 3.2 PPU-clocks not 3? Maybe it need to last this long to filter out electrical interference.
3. Am I right if I say that PPU generates NMI with no delay but the CPU
need at least one extra cycel to catch it?
4. Could someone please describe how NMIs are generated and how the CPU handles them. Very detailed and low-level would be nice.
Maybe I'm just stupid or NMI suppression on cycle 0 and 1 are just special cases.
Finally I'm wondering if someone have come up with a nice, simple and fast way of dealing with things that can interrupt the CPU in a catch-up emulator?
Any help is much appreciated.