It is currently Sun Dec 17, 2017 8:32 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: nmi timing?
PostPosted: Wed Apr 13, 2016 6:00 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Hmm... let me give you more info. :wink:
I have two flags, nmi_request and nmi_assert. At the end of an instruction, if nmi_assert == 1, a NMI is triggered. Well, if nmi_request == 1, a NMI has been requested, but not asserted yet. A diagram might help...
Code:
#define _INT_ASSERT() nmi_assert = nmi_request;

unsigned char cpu_readvalue(int addr)
{
_INT_ASSERT();
ppu_run(); //3 cycles
return cpu->reads[addr>>13](addr&0x1FFF); //CPU reads/writes
//alt: writevalue(addr,value);
}

//at the end of an instruction:

if(nmi_assert) NMI_TRIGGER();
else if(irq_assert) IRQ_TRIGGER();

//next instruction - fetch opcode data.


NOTE: For instructions with addressing mode "IMPLICIT", I have to update _INT_ASSERT() only at the end of the instruction; otherwise I get errors in the CPU tests.


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Wed Apr 13, 2016 6:21 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
EDIT 2: Actually I thought about it some more and I'm not sure this is your problem. =x

I'm out of time tonight, I'll have to check this another time.

Can you post the code that sets nmi_request to true?


=========================
NOTE -- everything below is probably wrong
=========================


Okay -- I see a possible problem...

Code:
unsigned char cpu_readvalue(int addr)
{
_INT_ASSERT();
ppu_run();   // <-  if VBlank flag ($2002.7) is raised here...
return cpu->reads[addr>>13](addr&0x1FFF); // <- will it be read here?


If the answer to that question is "yes", then that is almost certainly your problem.

Before I'll type out a long explanation as to why it's a problem, I'll wait for you to answer. =)


EDIT:

Quote:
NOTE: For instructions with addressing mode "IMPLICIT", I have to update _INT_ASSERT() only at the end of the instruction; otherwise I get errors in the CPU tests.


Yeah.. see... that should be a sign that you're doing something wrong. You should not have to do anything differently for any instructions. There's no special behavior here.


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Thu Apr 14, 2016 2:51 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
The only difference with Nintendulator is about clocking the PPU after the CPU cycle. In my emulator, I just follow what should be. If $2002 is read 1 PPU cycle before VBlank, $2002:$80 is NOT set; hence, NMIs are not triggered too.


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Thu Apr 14, 2016 3:48 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
I don't have Nintendulator's code handy =x

But basically I just want to make sure that $2002:$80 and nmi_request are both set at the exact same time, right?


Are you doing something weird like skipping the odd-frame cycle even when the PPU is off?


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Thu Apr 14, 2016 4:26 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
EDIT: ok, let me answer... 8-)
Disch wrote:
But basically I just want to make sure that $2002:$80 and nmi_request are both set at the exact same time, right?

Yes, right. :)
Quote:
Are you doing something weird like skipping the odd-frame cycle even when the PPU is off?

No. My code is pretty clean and without hacks. The only "problem" regarding such thing is about skipping the odd-frame cycle at PPU dot 338. Other than that, the test rom fails. I remember of seeing such PPU dot number as "correct".

Uh... let me change the question. ^_^;;

Does the NMI trigger if requested during the last cycle of an instruction? Should it be triggered only in the next instruction?


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 12:20 am 
Offline

Joined: Fri Dec 30, 2011 7:15 am
Posts: 43
Location: Sweden
Zepper wrote:
Does the NMI trigger if requested during the last cycle of an instruction? Should it be triggered only in the next instruction?

I'm no expert on the subject, but I tried triggering an nmi at various points in an instruction in visual6502. It would seem that an nmi gets delayed til after the next instruction if it was triggered during the last two cycles of an instruction.

Code:
STA absolute
Read  - op1   < nmi after current
Read  - op2   < nmi after current
Write - write < nmi after next
Read  - fetch < nmi after next


However, currently I'm always delaying an nmi til after the next instruction in my emulator and it passes all the nmi tests. The cpu interrupts page on the wiki suggests that the nmi edge detector is only checked on the final cycle of an instruction, so maybe an nmi will always be delayed? I'm having a hard time interpreting this.

I may be entirely wrong with everything i just said, haha.


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 3:49 am 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
Zepper wrote:
Does the NMI trigger if requested during the last cycle of an instruction? Should it be triggered only in the next instruction?


Before the last cycle = NMI after this instruction.
On or after last cycle = NMI after next instruction.

viewtopic.php?f=3&t=14074#p168381 <- This diagram is as clear as I can explain it. Fred's diagram is also correct.

Really, I don't see what you're doing wrong. Based on what I'm seeing, your logic is fine... you just might have some bug somewhere that we can't see. =(


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 2:38 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Hmm... hmm... :roll:

1. I really need a log of another emulator to compare with mine, just THAT piece is fine. Test ROM is packaged with ppu_vbl_nmi.zip (file 05-nmi_timing.nes). A few emulators are open source, but I'm not in the mood for mods.

2. Just a recap. There's a NMI landing in a LDX #$03instruction, but in the last cycle of this instruction and at same time of the VBlank start. Usually, it should trigger in the next instruction, but it gives me an error. If I don't allow this NMI to trigger at the end of the current instruction, the test ROM fails. I'm calling it "edge case". There are 3 PPU cycles to run (a full cycle). Who could help me? _Q? blargg?

3. As a critical problem, my emulator seems to be off by 1 cycle. After thinking, the only possible conclusion is to run the PPU after a CPU clock, and not before as I am doing now. There is no agreement about it. Nintendulator clocks the PPU after the CPU cycle, for example.


Last edited by Zepper on Fri Apr 15, 2016 3:12 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 2:56 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19355
Location: NE Indiana, USA (NTSC)
By STA #$03, do you mean the unofficial instruction 89 03, which is at the position in the grid where STA #ii would be if it were valid? This opcode is a 2-byte, 2-cycle NOP on 6502 and BIT #ii on 65C02 and 65816.


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 3:13 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
tepples wrote:
By STA #$03, do you mean the unofficial instruction 89 03, which is at the position in the grid where STA #ii would be if it were valid? This opcode is a 2-byte, 2-cycle NOP on 6502 and BIT #ii on 65C02 and 65816.


Oops! Thanks. It's LDX #$03. :oops: :oops: :oops: :oops: :oops:


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Fri Apr 15, 2016 5:59 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Disch wrote:
Really, I don't see what you're doing wrong. Based on what I'm seeing, your logic is fine... you just might have some bug somewhere that we can't see. =(

Removing my "hack" causes NMI suppression test to fail with error 10 - Reading flag 2 PPU clocks after set shouldn't suppress NMI.
Interesting.

EDIT 3: The error code is #7;) NMI occurred 1 PPU clock too late.

EDIT 2: There was a problem with NMI suppression test. Even with the fix, nmi_timing still fails without the assertion in the edge case. :cry: :oops: :cry:

EDIT 1: I'll explain the "edge case" with an example... BIT $2002
Code:
===================
PPU: -- line 261, cycle 334
CPU: fetch opcode data ($2C);
===================
PPU: -- line 261, cycle 337
CPU: fetch low address;
===================
PPU: -- line 261, cycle 340. The PPU is now aligned with the CPU. The next PPU cycle is the VBlank start.
CPU: fetch high address.
=================== EDGE ===
PPU: -- line 0, cycle 0. VBlank start. An NMI is requested with 3 cycles to run.
CPU: read from effective address ($2002).
===================

As you can see, the NMI is being requested at the 4th cycle (last one), so it'll be triggered only in the next instruction. Notice now the EDGE - if the requested NMI is requested & asserted right in the 3rd cycle, it'll be triggered at the end of the 4th cycle. It's the expected behaviour.

My question is... Asserting the NMI in the EDGE case fixes the NMI timing, but is this OKay?


Top
 Profile  
 
 Post subject: Re: nmi timing?
PostPosted: Sun Apr 17, 2016 8:00 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Well, my veredict follows. ^_^;; Since I put the PPU to run prior to a CPU read/write, there IS a problem regarding the NMI triggering. If the next CPU clock starts PPU VBlank (scanline 0, cycle 0), the NMI must be requested 1 PPU cycle before. In other words, the NMI must be requested at PPU line 261, cycle 340 (edge case). Otherwise, the test rom gives the obvious error "NMI occurred 1 PPU clock too late". I don't know if such problem isn't present when the PPU is clocked after a CPU read/write. Probably yes.

lines 0-19 = VBlank
line 20 = pre-rendered scanline
lines 21-240 = visible scanlines (rendering)
line 261 = dummy scanline


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group