NMI & IRQ

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

FentonCole
Posts: 4
Joined: Sun Dec 30, 2007 4:42 am

Post by FentonCole » Tue Jan 01, 2008 5:11 am

It seems like the print functions (print_x, print_y etc.) leaves the PPU rendering ON, causing it to go into its +0/-1 odd-frame-cycle mode. Won't this cause a problem for the sync_nmi routine (it says the rendering should be OFF)? If I disable it manually before sync_nmi is executed, the test passes, but otherwise not since the NMI will then occur a few PPU clocks too early (before LDA) on the 2nd run.

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Tue Jan 01, 2008 9:18 am

I'm having the same trouble as FentonCole. I get the following when I run the demo:

Code: Select all

$23 $00
$23 $00
$21 $00
$21 $00
$20 $00
$20 $00
$20 $00
$20 $00
$20 $00
$20 $00
$20 $00
$24 $20
It's not totally wrong -- it's just shifted down; there's an extra $23 $00 in there and it's as if the first NMI is occuring 1 clock earlier than it should. But when I take out my skip-odd-cycle implimentation, I get a pass.

I'll have to look at this more later

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Tue Jan 01, 2008 2:51 pm

Ugh ugh ugh, all my fault. I ported my dev stuff to ca65 yesterday so others can more easily modify things. I can't test the final code on my NES very easily since it can't run normal ROMs, so I only test using a runtime that prints things over serial rather than to the screen.

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Tue Jan 01, 2008 10:51 pm

New, improved, properly tested on my NES at reset time, ca65 source that can be built on anyone's machine, lots of nifty reusable library routines and scrolling text console, and some description of the code organization and philosophy: nmi_during_irq2.zip

At this point I'm not sure how to interpret the result (what's actually happening at each clock), but at least you have something you can compare your emulator to a NES with. And if I've still screwed up like before, don't hesitate to call me on it. Testing on a NES using a more normal devcart would be appreciated.

User avatar
Zepper
Formerly Fx3
Posts: 3191
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Wed Jan 02, 2008 5:51 am

Can't you upload into another server? I'm unable to downl... oh, I already said that, right? :|

EDIT: ...got it.

Code: Select all

http://www.proxyhustle.com/

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Wed Jan 02, 2008 8:12 am

Thanks for all the excellent work blargg! It's definately appreciated.

I'm having some trouble though. I get the right sequence of numbers... but it still says I failed.

Code: Select all

23 00
21 00
21 00
20 00
20 00
20 00
20 00
20 00
20 00
20 00
24 20
24 20

30BFCFCA
FAILED: 2

Similar problem with the new BRK test. I get the same results as before (except there's an extra 27 36 00 line in front) but it's saying I'm failing, whereas I pass the old test.

Did the correct output change? Is my checksum wrong? If so, what problem does that indicate?

FentonCole
Posts: 4
Joined: Sun Dec 30, 2007 4:42 am

Post by FentonCole » Wed Jan 02, 2008 1:02 pm

Thanks again for your much valuable tests. It seems like the NMI is delayed for another instruction if it's past the point of being able to steal the interrupt from BRK/IRQ, i.e. somewhere around ~5/6 CPU cycles into the ISR. Going with that, I now pass the tests.

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Wed Jan 02, 2008 4:41 pm

Disch, the last two lines of the nmi_during_irq test should have 25 for the NMI flag, so carry is set, indicating that for these two the NMI is occurring after the SEC at the beginning of the IRQ handler, not before as is apparently happening for yours. What really seems to be going on (to me) internally is that NMI will replace the IRQ if it is asserted during the first five clocks of the IRQ handling; if it occurs during the last two, it will occur after the first instruction of the IRQ handler (fitting in with the usual behavior of NMI). This would mean that the first two "20 00" lines are where the NMI is being asserted during the first and second clocks of the CLC, not the IRQ handling itself.

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Wed Jan 02, 2008 6:43 pm

blargg wrote:What really seems to be going on (to me) internally is that NMI will replace the IRQ if it is asserted during the first five clocks of the IRQ handling; if it occurs during the last two, it will occur after the first instruction of the IRQ handler (fitting in with the usual behavior of NMI).
Rather than trying to understand why this is so (it doesn't really make any logical sense to me), I'll just accept that that's how it works.

Anyway I have both working now, and since correct numbers for the new tests have not yet been posted, here they are:

Code: Select all

nmi_during_brk:

27 30 00
26 36 00
26 36 00
36 00 00
36 00 00
36 00 00
36 00 00
36 00 00
27 36 00
27 36 00



nmi_during_irq:

23 00
21 00
21 00
20 00
20 00
20 00
20 00
20 00
20 00
20 00
25 20
25 20

And a recap of behavior for good measure:

-) if an NMI occurs during the first 5 cycles of BRK or IRQ, status is pushed to stack as if it were a BRK/IRQ, but the NMI vector is jumped to instead. IRQ/BRK is effectively supressed. Though an IRQ would still be pending and will occur after RTI unless acknowledged -- but the BRK is completely skipped over.

-) if an NMI occurs during the last 2 cycles of BRK or IRQ, BRK/IRQ proceeds as normal, and NMI occurs after the first instruction following the BRK/IRQ.

User avatar
Zepper
Formerly Fx3
Posts: 3191
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Tue Feb 05, 2008 11:30 am

I have no clues what's happening here, I got:

Code: Select all

23 00
21 00
21 00
25 21
25 21
25 21
...
- Could you help me?

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Tue Feb 05, 2008 12:51 pm

The first column is the flags on entry to the NMI, the second IRQ, or 00 if that handler wasn't executed. The time the IRQ (would) occur is fixed, while the time for the NMI is one clock later on each successive row. This is the code section where the interrupts occur:

Code: Select all

clv
sec
	; Z and C set, others clear
	
; NMI occurs here first,
lda #1		; clear Z flag
; then here for two clocks,
clc 		; clear C flag
; then here.
	
; IRQ should occur here, but yours seems to be occurring before the clc
nop
The first result row you got was 23 00, so the NMI is firing when the C and Z flags are set, and it's before the LDA #1. Then the next two lines, it's firing when just the C flag is set, so you can see that it must be just after the LDA #1 which clears the Z flag. Then you have 25 21, so the NMI is firing when the I and C flags are set, and the IRQ is firing with just the C flag set. So apparently your IRQ is firing before the CLC, and before the NMI as well (since the NMI occurs when the I flag is set, as it would be inside the IRQ handler). The source code includes similar commentary on the correct sequence for comparison.

User avatar
hap
Posts: 355
Joined: Thu Mar 24, 2005 3:17 pm
Contact:

Post by hap » Wed Feb 06, 2008 9:19 am

Thanks for the test roms blargg.
(small typo by Disch 3 posts above me, nmi_during_brk 1st line "27 30 00" should of course be "27 36 00")

User avatar
Zepper
Formerly Fx3
Posts: 3191
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Wed Feb 06, 2008 8:15 pm

@blargg

- You're using frameIRQs. My emulator passes in all APU (and NMI) test ROMs, with no hacks. During the sequence #4 (line 5, or "20 00"), the IRQs start firing (making a request to trigger) before the CLC instruction. This way, a 7-cycles IRQ is started, but a NMI is requested during the 1st of those 7 cycles.

- Is my IRQ timing off even if it passes the APU test ROMs???

Code: Select all

23 00
21 00
21 00
20 00
25 21 <- here
25 20
25 21
25 20
25 21
25 20
25 21
25 20
EDIT: I fixed my code and it passes. There's an exception though: I cannot figure why a NMI is being requested during a LDX #$01 instruction (2nd byte fetch to be exact), making to trigger right in the end of the instruction, instead of triggering in the next one. I added an hack to acknowledge the NMI request during such instruction. This issue happens on nmi_timing test ROM.

Post Reply