problem with the even/odd frames test

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

problem with the even/odd frames test

Post by n6 »

Hi

I get Error #4 (Pattern B--B- (one even, one odd) should skip 1 clock)
I can only about two things that it may depend on

1. What iam doing is in wrong order...
This is what my emulate-sequence look like:

1. Call NMI (if enabled)
2. Run 6820 PPU cycles (I don't have a CPU cycle counter, only PPU)
3. Clear Status flags (vbl, spritehit, overflow)
4. Add one cycle to the PPU clock if its an odd frame and BG enabled
5. Set up sprites for the frame
6. Run up to 89342 cycles

2. if the cycle counter overflow I call the instruction anyway, is it important to first find out how many cycles the instruction will take, then call it if its enough time left?

What happens if a 6 CPU cycle instruction appears at 89340, is it executed after NMI? In order to pass the timing tests is this important?

thanks
mattmatteh
Posts: 345
Joined: Fri Jul 29, 2005 3:40 pm
Location: near chicago

Post by mattmatteh »

looks like you got the idea. you might have to explain more on how your ppu work, and how the cpu is run.

matt
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

Well.. What I need to know is:

1. is NMI called in the beginning of a frame or at the end.
2. is all instructions performed at its very last cycle, and like my earlier example, if half an instruction is executed before NMI is its "action" made directly after NMI in this case? is this true for all opcodes, CLI is different huh? but what about the others...

Since I always let the instruction to be executed even if it should be right after NMI, may this cause errors in timing?
mattmatteh
Posts: 345
Joined: Fri Jul 29, 2005 3:40 pm
Location: near chicago

Post by mattmatteh »

n6 wrote:1. is NMI called in the beginning of a frame or at the end.
the term frame is kinda misleading. what do you mean by frame? i assume its the 20 scanlines of vblank, 1 pre line, 240 drawing lines, and 1 post line. nmi would happen inbetween the last cycle of the post line and the first cycle of vblank. so the answer is yes to your OR question. it happens at the begining and at the end because they are the same.
n6 wrote:2. is all instructions performed at its very last cycle, and like my earlier example, if half an instruction is executed before NMI is its "action" made directly after NMI in this case? is this true for all opcodes, CLI is different huh? but what about the others...
i dont understand what you are asking. well, maybe... blargg just posted something about this, when the cpu checks the nmi or irq, might look at recent post

matt
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

the term frame is kinda misleading. what do you mean by frame? i assume its the 20 scanlines of vblank, 1 pre line, 240 drawing lines, and 1 post line. nmi would happen inbetween the last cycle of the post line and the first cycle of vblank. so the answer is yes to your OR question. it happens at the begining and at the end because they are the same.
yeah thats what I wondered, thanks!
i dont understand what you are asking. well, maybe... blargg just posted something about this, when the cpu checks the nmi or irq, might look at recent post
some psuedo code might help.

My way:

do
{
RunNextOp();
PPUClock += OpCycles();
} while (PPUClock < 89xxx)

probably the right way:

while (1)
{
PPUClock += OpCycles();
if (PPUClock < 89xxx)
RunNextOp();
else
{
// Find out how many cycles that are left of the current instruction and
// run it after NMI
break;
}
}
mattmatteh
Posts: 345
Joined: Fri Jul 29, 2005 3:40 pm
Location: near chicago

Post by mattmatteh »

you might have a problem with the ppu cycle in the cpu instruction. since the ppu is (ntsc) 3 times faster then the cpu, and the average cpu instruction is about 4 cycles long, that leaves 3 * 4 = 12 possible values to be read from if the cpu was reading a ppu register. so are you rounding your reads and writes to the intruction boundary? or updating on the exact ppu cycle ?

i have a cpu clock and a ppu clock. i run the cpu till predicted nmi or irq. and catch up the ppu where needed. this works, i might change it alittle, but i think it will always be a catch-up. and i dont lock mine to render frames because i might use the sound call back some day for timing. and the sound call back might never line up with the render frame.

also, i posted a while ago about save states. i took that into consideration too. so i can pause my emulation on a save frame.

sucks that search is STILL broke, but there is alot of info in the old posts.

matt
Last edited by mattmatteh on Mon Sep 11, 2006 12:38 pm, edited 1 time in total.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Since the first two sub tests of 3.even_odd_frames.nes passed, it suggests something more subtle is going on. Test 2 keeps BG disabled the whole time, and passes. Test 3 enables BG for two consecutive frames, then disables it, and expects that only one PPU clock was skipped. Test 4, which fails, enabled BG for one frame, disables it for two, then enables it for one more frame, also expecting only one PPU clock to be skipped.

Oh, wait, maybe I'm assuming too much again. Have you verified that 1.frame_basics.nes and 2.vbl_timing.nes both pass? Ugh.
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

Yeah. both pass! But isnt it possible for example that you read the status register at PPU clock 89341 and I get error cause this read is finished before NMI or something like that.

btw, do all instructions do their thing at its last cycle? if NMI is triggered inside an instruction, where is the programcounter? pointing to the instruction, the parameter, the next instruction or does it depend on how far the instruction have come (in cycles)?
mattmatteh
Posts: 345
Joined: Fri Jul 29, 2005 3:40 pm
Location: near chicago

Post by mattmatteh »

n6 wrote:do all instructions do their thing at its last cycle?
what do you mean by your thing ? i think you mean when does the read or write occur? if so then that is what i was trying to explain in my last post. you need to determine the exact ppu cycle a ppu register is read on. you can not round that to the end of the instruction.

matt
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

Yeah but what I mean is... LDA $2002 for example, when do the read occur? it takes 12 CPU Cycles to run but at which cycle is the value catched? isnt this the same even if its WRAM or mapper or whatever?
mattmatteh
Posts: 345
Joined: Fri Jul 29, 2005 3:40 pm
Location: near chicago

Post by mattmatteh »

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

Post by blargg »

LDA $2002:

1: Read opcode
2: Read low byte of address
3: Read high byte of address
4: Read from $2002

There's also a fifth cycle, but this is overlapped with the opcode fetch for the next instruction so it's usually ignored. The NMI and IRQ lines are checked during cycle 3 in the above example. If either is set, then the interrupt will occur after the instruction finishes, and the program counter saved on the stack will be for the next instruction.
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

I see interesting.. so if it's less then 3, the opcode is executed after NMI? and the program counter points to?

since the opcode is finished in the 3 or above case, do this mean that the opcode restarts if its less then 3?

Is there a complete table of where NMI/IRQ checks are made for each op code?

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

Post by blargg »

All interrupts occur between completely executed instructions; an instruction is never interrupted before completion. The saved program counter on the stack is where execution should continue once the interrupt has been handled. My tests indicate that it's always the second from last cycle of an instruction that the IRQ/NMI inputs are examined, or the next-to-last cycle if you're ignoring the final cycle that's overlapped with the opcode fetch of the next instruction. This checking is effectively two cycles before it takes effect, so if IRQ/NMI is asserted in the third cycle of LDA in the example above, then an interrupt will occur after LDA completes.
n6
Posts: 60
Joined: Tue Jul 11, 2006 10:12 am

Post by n6 »

Okey.. last question...

if it just one cycle left until NMI when an LDA $2002 appears, is it ignored? and just executed after NMI?

opcodes that take different time like branches.. are NMI/IRQ checked at different places depending on if it takes 2 or 4 cycles?
Post Reply