CPU/PPU timing

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

CPU/PPU timing

Post by ulfalizer »

Given that the exact master clock timing of stuff like reading and setting PPU flags isn't know, what model have other people here used in their emulators, and what has worked best in practice?

One model would be to run three PPU ticks before every CPU tick and pretend that those PPU ticks took place during the CPU tick, i.e.

Code: Select all

[PPU TICK][PPU TICK][PPU TICK] <- Run these first
[          CPU TICK          ] <- Then run this
One assumption you'd be making there is that a flag setting at e.g. the last PPU tick would be seen by the CPU tick (which could be e.g. a read).

Lots of other models are possible too of course. Any input?
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: CPU/PPU timing

Post by James »

ulfalizer wrote:

Code: Select all

[PPU TICK][PPU TICK][PPU TICK] <- Run these first
[          CPU TICK          ] <- Then run this
That's how I do it and it works well.
get nemulator
http://nemulator.com
beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Re: CPU/PPU timing

Post by beannaich »

Code: Select all

ppu.Update(6); // run for 6 master cycles
byte data = Read(address); // read from address, possibly a PPU register
ppu.Update(6); // run for another 6 master cycles
Technically this shouldn't matter, you have a periodic execution, in which x dots are run before the cpu, and 3-x dots are run after. I have found that using the above allowed me to pass some tests I didn't before.
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Re: CPU/PPU timing

Post by WedNESday »

1 CPU cycle then 3 PPU cycles for me. Never had any problems.
x0000
Posts: 43
Joined: Thu Feb 28, 2013 11:14 am
Contact:

Re: CPU/PPU timing

Post by x0000 »

I have something like this:

Code: Select all

[ppu][ppu][ppu]
-----++++++++++
[     cpu     ]
("+" is where write/read is effective)
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: CPU/PPU timing

Post by ulfalizer »

Would be really nice if someone with a logic analyzer could do some timing. As it stands right now there's a lot of guesswork and fudging involved. :|

By looking at the PPU VRAM accesses you could figure out where you are (e.g. in ppu.svg). The CPU/PPU master clock alignment (0-3) could be figured out by looking at M2 (goes low when CPU tick starts) and ALE (goes high at the beginning of a PPU VRAM fetch). You could then see what happens when you read different flags (VBL stuff/sprite zero stuff/etc.) at different offsets.

By trying out different alignments you could nail down the behavior down to starting the read at master clock n, which would cover everything you'd ever need to know.

For reference (for anyone joining from viewtopic.php?f=9&t=10037), see e.g. http://wiki.nesdev.com/w/index.php/PPU_ ... lag_Timing . A PPU timing diagram can be found in http://wiki.nesdev.com/w/images/d/d1/Ntsc_timing.png. Please ask if you have questions, since I realize what needs to be done might be a bit vague. :)

Edit: ALE correction.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: CPU/PPU timing

Post by lidnariq »

I've got a saleae logic (8 channel, 24MS/s); what do you want measured?
User avatar
HardWareMan
Posts: 209
Joined: Mon Jan 01, 2007 11:12 am

Re: CPU/PPU timing

Post by HardWareMan »

8 channel not enough. Look here:
Image
Image
Image
Need more channels.
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: CPU/PPU timing

Post by ulfalizer »

HardWareMan wrote:Need more channels.
Looking at A12/A13 like some mappers do might be sufficient. That lets you tell nametable and tile fetches apart.

The basic idea would be to run some test program like the following:
  1. Do whatever simple setup stuff is needed (e.g. http://wiki.nesdev.com/w/index.php/PPU_power_up_state, Best Practice section).
  2. Wait an adjustable amount of time using e.g. some time-wasting loops.
  3. Read the register under investigation and see what happens (what value you get back, and what special behavior triggers for e.g. VBL).
By looking at the PPU and CPU trace in the logic analyzer, you could then figure out where the read started relative to the PPU (e.g. "n master clock ticks after <some convenient PPU event that's easy to track down>"). At this point you would know exactly where the read started and what behavior that triggered, which is what you want to know.

Would the above approach be feasible? Can you think of any simplifications? A good first target would be to nail down where the VBL flag ($2002:7) starts reading as true. (NMI behavior could be tracked down later.)

BTW, just to clarify:

Since the PPU divides the master clock by 4 while the CPU uses it divided by 12, there's four different relative master clock alignments possible, where you get one at random during reset:

Code: Select all

* * * * * * * * * * * * * <- Master clock
-----------CPU----------- <- CPU cycle
---PPU---                 <- Alignment 1
  ---PPU---               <- Alignment 2
    ---PPU---             <- Alignment 3
      ---PPU---           <- Alignment 4
Hence by adjusting the wait time and resetting a few times you could nail the behavior down to the master clock.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: CPU/PPU timing

Post by blargg »

It's possible in software to detect which of these four alignments the NES powered/reset into. So we just need to figure out the alignments in terms of CPU cycles and PPU dots. The problem I ran into was that neither clock is directly available, hence me using the CPU's M2 and the PPU's ALE.

Once that is figured out, then we can figure out where the /NMI occurs relative to my methods of synchronizing the CPU to it, which will then tell us all the timings of my tests at the hardware level. From there, it can all be done in software. We would have enough information to make tests that prompt the user to press reset possibly multiple times until it detects the proper alignment, then runs whatever test. So in code we could software test PPU events down to the master clock.


[Edited for clock/dot/cycle precision --Layne's Fairy]
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: CPU/PPU timing

Post by ulfalizer »

blargg wrote:It's possible in software to detect which of these four alignments the NES powered/reset into. So we just need to figure out the alignments in terms of CPU and PPU clocks. The problem I ran into was that neither clock is directly available, hence me using the CPU's M2 and the PPU's ALE.
Out of curiosity, how do you do this? Do you just mean in the sense that you get four different behaviors that can be detected but don't know the precise alignments they correspond to?
blargg wrote:Once that is figured out, then we can figure out where the /NMI occurs relative to my methods of synchronizing the CPU to it, which will then tell us all the timings of my tests at the hardware level. From there, it can all be done in software. We would have enough information to make tests that prompt the user to press reset possibly multiple times until it detects the proper alignment, then runs whatever test. So in code we could software test PPU events down to the PPU cycle (actually, down to the master cycle).
Not sure if I'm getting this. Do you mean something like the following?
  1. Figure out the precise CPU/PPU alignments the four possibilities correspond to with a logic analyzer.
  2. Make a test that detects which alignment it's in and then times where different things happen.
  3. Combine (1) and (2) to figure out the behavior at the master clock level.
Are you sure it's just four alignments by the way? Maybe the PPU can start n ticks before/after the CPU as well, and the tests still pass if they use relative timings. :?
But maybe it won't matter...
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: CPU/PPU timing

Post by blargg »

ulfalizer wrote:
blargg wrote:It's possible in software to detect which of these four alignments the NES powered/reset into. [...]
Out of curiosity, how do you do this? Do you just mean in the sense that you get four different behaviors that can be detected but don't know the precise alignments they correspond to?
Right. Before I tested with a scope recently, I knew the signatures of the four, and had them in what turns out correct order, based on the way more events would occur earlier in one direction, and more later in the other.
blargg wrote:Once that is figured out, then we can figure out where the /NMI occurs relative to my methods of synchronizing the CPU to it, which will then tell us all the timings of my tests at the hardware level. From there, it can all be done in software. We would have enough information to make tests that prompt the user to press reset possibly multiple times until it detects the proper alignment, then runs whatever test. So in code we could software test PPU events down to the PPU cycle (actually, down to the master cycle).
Not sure if I'm getting this. Do you mean something like the following?
  1. Figure out the precise CPU/PPU alignments the four possibilities correspond to with a logic analyzer.
  2. Make a test that detects which alignment it's in and then times where different things happen.
  3. Combine (1) and (2) to figure out the behavior at the master clock level.
Yeah. By prompting the user to press reset until the correct alignment is reached, the test program can, under its own control, initiate a CPU read or write at any point in the PPU frame, to master clock accuracy.
Are you sure it's just four alignments by the way? Maybe the PPU can start n ticks before/after the CPU as well, and the tests still pass if they use relative timings. :?
But maybe it won't matter...
It can't be more. The CPU and PPU run off (AFAIK) the same edge of the master clock (PPU's color uses both edges, but that's separate). The CPU divides by 12, the PPU 4. Using previous terminology, cycle = CPU, dot = PPU. So you get three whole dots per cycle. There are only four different alignments of this, based on the PPU's divide-by-4.

Going to the entire frame, the PPU's frame is never a multiple of 3 dots, so every frame the alignment of the frame itself to a cycle shifts. This ensures that it doesn't matter what alignment a cycle to a frame has at power. If every frame were a multiple of 3 dots, then yes, you'd have 12 different alignments, corresponding to the CPU's divide-by-12.

And of course this is NTSC. According to the Wiki, PAL frame length's fraction is half a CPU cycle, and CPU divider is 16, so there are potentially 8 different CPU-frame alignments at power/reset.

To clarify about alignments, we have two different kinds. One, a cycle relative to a dot (not any particular one in the frame). The other, a cycle relative to the first dot of the frame. And of alignment, there are (obviously) various ones for each dot, since the CPU and PPU run at different rates. Of all the different possible alignments, for a given length of operation after power/reset, only a subset can ever be encountered. I take the topic to be talking about the number of distinct subsets. For an NTSC, there are four of these, both for cycle-dot alignment and cycle-frame alignment. For PAL, my calculation above suggests one cycle-dot alignment and 8 cycle-frame alignments.

Yet another way of putting the concept is that the relative synchronization of the CPU, PPU, and frame dividers reliably generates a random value at power/reset and preserves it during operation, regardless of what the CPU does (enable/disable rendering, whatever). On NTSC, this value has four states, and on PAL, eight states.
User avatar
HardWareMan
Posts: 209
Joined: Mon Jan 01, 2007 11:12 am

Re: CPU/PPU timing

Post by HardWareMan »

In famiclone PPU reset are tied to VCC. So, reset button did not affect to PPU. But what if PPU reset will be connected to CPU reset? Will it do some sort of syncronization (PPU render are off when PPU reset is active)?
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: CPU/PPU timing

Post by ulfalizer »

blargg wrote:It can't be more. The CPU and PPU run off (AFAIK) the same edge of the master clock (PPU's color uses both edges, but that's separate). The CPU divides by 12, the PPU 4. Using previous terminology, cycle = CPU, dot = PPU. So you get three whole dots per cycle. There are only four different alignments of this, based on the PPU's divide-by-4.
I was thinking in the sense that the time between the CPU and PPU running their first tick might be longer than a PPU tick, e.g.

Code: Select all

* * * * * * * * * * * * * * *... (Master)
            ---------CPU-----... (First CPU tick)
---PPU---...                     (First PPU tick)  
Edit: I realize this wouldn't affect the possible alignments, but it would affect your knowledge if where you are relative to the frame.

But maybe that's a stupid idea. Were the behaviors for the different alignments derived by waiting a variable amount after power-on before doing the read? What causes the alignment at power-on to be nondeterministic anyway?

If I'm thinking straight, you'd need to at least have some point where you can say with confidence that a particular CPU tick starts at a particular master clock offset within the frame. Once you have that you could do the rest in SW.

Edit: I guess you could do the wait-29781-CPU-ticks-to-advance-frame-alignment-by-one-PPU-tick trick, and see how frames (PPU ticks) it takes before stuff happens. Was that what you did?
Last edited by ulfalizer on Mon Apr 22, 2013 2:13 pm, edited 3 times in total.
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: CPU/PPU timing

Post by ulfalizer »

@blargg:
Since you've obviously thought this through more than me, what information would you need from a logic analyzer btw?
Post Reply