CPU - PPU clock alignment
Moderator: Moderators
CPU - PPU clock alignment
I want someone to confirm my troughs...
NTSC : 1 CPU Cycle = 3 PPU Cycles, so there is 1 * 3 = 3 possible alignments on reset
PAL : 5 CPU Cycles = 16 PPU Cycles, so there is 5 * 16 = 80 possible alignments on reset
Is this right ? I just got surprised that a program I wrote using raster effects behaves differently depending on resets and I want to understand why.
NTSC : 1 CPU Cycle = 3 PPU Cycles, so there is 1 * 3 = 3 possible alignments on reset
PAL : 5 CPU Cycles = 16 PPU Cycles, so there is 5 * 16 = 80 possible alignments on reset
Is this right ? I just got surprised that a program I wrote using raster effects behaves differently depending on resets and I want to understand why.
Useless, lumbering half-wits don't scare us.
Nope, there are four for NTSC. Here are some notes I made a while back:
After power/reset, PPU is randomly in one of four synchronizations with CPU. This synchronization cannot be changed without resetting/powering down. Trials of 50-60 power/resets were done to determine likelihoods. The third synchronization is the preferred one for emulators and test ROMs, due to the least special cases, and highest likelihood.
Why four instead of three? It's due to the PPU and CPU using separate dividers. The CPU divides the master clock by 12, the PPU by 4. Thus, the CPU has four possible positions it can be in relative to the PPU:
I expect the same for the PAL system. The CPU divides the master clock by 16, the PPU by 5.
Look at that, there is only ONE overall synchronization for PAL. The CPU hits all five sub-synchronizations from one clock to the next, though. That makes it both easier and harder for emulation of all the PAL special cases. It's easier in that there's only one to research, and no choice of which to emulate, but harder in that all 5 sub-synchronizations must be checked for different effects.
After power/reset, PPU is randomly in one of four synchronizations with CPU. This synchronization cannot be changed without resetting/powering down. Trials of 50-60 power/resets were done to determine likelihoods. The third synchronization is the preferred one for emulators and test ROMs, due to the least special cases, and highest likelihood.
Code: Select all
NMI VBL Hit Overflow Likelihood
Reset Reset Set Reset Set
6819+ 7502+ 6819+ 7290+ Power Reset
-------------------------------------------------------------
-1 -1 -1 0 -1 -1 27% 26%
0 -1 0 0 0 0 15% 22%
0 0 0 0 0 0 31% 30%
0 0 0 +1 0 0 27% 22%
Code: Select all
PPU X---X---X---X---X---X---X---X---X---X---X-...
CPU 1 X-----------X-----------X-----------X-----...
CPU 2 -X-----------X-----------X-----------X----...
CPU 3 --X-----------X-----------X-----------X---...
CPU 4 ---X-----------X-----------X-----------X--...
Code: Select all
PPU X----X----X----X----X----X----X----X----X----X----X----X----X----X----X----X----X--...
CPU X---------------X---------------X---------------X---------------X---------------X--...
Mmh... Thank you very much for your diagrams, they clarify things a lot.
So I really don't understand why my program using a raster effect has a line who seems to sometimes flicker, and sometimes be solid depending on resets on my PAL NES. I didn't mean it to be a test demo or anything - I just want to understand what is happening.
I synchronize from VBlank NMI for the effect, so I don't see how this can be an issue (but maybe it can ?).
So I really don't understand why my program using a raster effect has a line who seems to sometimes flicker, and sometimes be solid depending on resets on my PAL NES. I didn't mean it to be a test demo or anything - I just want to understand what is happening.
I synchronize from VBlank NMI for the effect, so I don't see how this can be an issue (but maybe it can ?).
Useless, lumbering half-wits don't scare us.
Interesting. Can you remove unncessary bits from your code until you're left with a very small amount which still displays different stable behavior depending on some power-up state? Or wait, we didn't examine the possible CPU synchronizations with respect to VBL. Basically consider all the possible number of PPU clocks between two VBL settings, and see if any are multiples of 5. Let's say the PPU frame length was 160000 (just some made-up value). That's a multiple of 16, so VBL would fall on the same relative CPU position every frame. It could be something like this going on.
wow
Holy cow Blargg, you are frigin hard core with this RE'ing stuff. Haha, that is awesome. I'll tuck this post away for a much later date when I get to the point of fine tuning my emulator and so I can add an option to randomize these power up states to make it as close to the original as possible. THANKS!blargg wrote:After power/reset, PPU is randomly in one of four synchronizations with CPU. This synchronization cannot be changed without resetting/powering down. Trials of 50-60 power/resets were done to determine likelihoods. The third synchronization is the preferred one for emulators and test ROMs, due to the least special cases, and highest likelihood.
Bregalad, have you tested to be sure there really is some state that can only be changed by resetting/powering down and then up? That is, you power up, run your program many times, get one particular visual effect, then reset, run your program, and consistently get a different effect, then reset, and get another effect consistently (or maybe the first again)?
Yes I am sure, it's like you said.blargg wrote:Bregalad, have you tested to be sure there really is some state that can only be changed by resetting/powering down and then up? That is, you power up, run your program many times, get one particular visual effect, then reset, run your program, and consistently get a different effect, then reset, and get another effect consistently (or maybe the first again)?
I did originally not meant to release it as a standalone, but anyway it is for the good of NESdev, so I uploaded it here.
The last line of the logo sometimes flicker, and is sometimes solid depending on resets. (note : I think the flickering is due to the second $2006 writes being sometimes slightly past cc 256, and as a result the adress loaded is incorrect). It seems it never flickers on power on, and other lines show fine.
PS : Note that the point of this thread is NOT to solve the flickering issue (which I know how to deal with) but to understand why timing depends on resets.
Useless, lumbering half-wits don't scare us.
Been doing some PAL testing today (some info already known, just verifying). 312 scanlines per frame, 341 PPU clocks per scanline. 3.2 CPU clocks per PPU clock/0.3125 PPU clocks per CPU clock. Every frame is 312*341 PPU clocks, regardless of rendering being enabled; there's no skipped clock on odd rendered frames as on NTSC. This means that every frame is 33247.5 CPU clocks. It also means that there are eight PPU-CPU synchronizations that it can power up/reset into! There are so many partly because of the lack of a short frame as on NTSC. There are 16 different positions a PPU clock can fall within a CPU clock, and since the frame length ends in half a CPU clock, this is halved to 8, as it toggles between two synchronizations every frame.
You lost me there. You told me before there was only one. Altough I definitely confirm a demo of mine, along with another old OAM reading demo, acted differently between resets, so you last theory seems much more realist to me.It also means that there are eight PPU-CPU synchronizations that it can power up/reset into!
I still don't understand why there is 8 alignements.
Useless, lumbering half-wits don't scare us.
Yeah, I'm still trying to get my head around this.
OK, there is one CPU clock every 16 master clocks. Therefore, VBL can begin at 16 different positions within a CPU clock. VBL occurs every 312*341 PPU clocks. There are 5 master clocks in a PPU clock, so VBL occurs every 312*341*5=531960 master clocks. This is a multiple of 8, but not 16, so VBL's position within a CPU clock will alternate between two points, each a half CPU clock apart. For a given power/reset, it will never fall on anything other than these two points in a CPU cycle. Since there are 16 points available, 16/2=8 possible states it could power/reset into.
The above was from the CPU's point of view, which would be relevant for things like NMI. From the PPU's point of view, CPU reads/writes can occur in one of 5 positions within a PPU clock, which the CPU constantly cycles through every 5 CPU clocks. Every successive CPU clock begins one master clock (1/5 PPU clock) later within a PPU clock. This would suggest that the state at power/reset is irrelevant from the PPU's view, but PPU clocks aren't the only regular event in the PPU: there's also VBL. As above, after a power/reset, a CPU clock can begin in only two possible positions relative to VBL, each 8 master clocks apart.
I've been working on tests which are able to show how many different power/reset states it can be in, by being able to have it print which one it's on, and never print anything different except after another power/reset.
OK, there is one CPU clock every 16 master clocks. Therefore, VBL can begin at 16 different positions within a CPU clock. VBL occurs every 312*341 PPU clocks. There are 5 master clocks in a PPU clock, so VBL occurs every 312*341*5=531960 master clocks. This is a multiple of 8, but not 16, so VBL's position within a CPU clock will alternate between two points, each a half CPU clock apart. For a given power/reset, it will never fall on anything other than these two points in a CPU cycle. Since there are 16 points available, 16/2=8 possible states it could power/reset into.
The above was from the CPU's point of view, which would be relevant for things like NMI. From the PPU's point of view, CPU reads/writes can occur in one of 5 positions within a PPU clock, which the CPU constantly cycles through every 5 CPU clocks. Every successive CPU clock begins one master clock (1/5 PPU clock) later within a PPU clock. This would suggest that the state at power/reset is irrelevant from the PPU's view, but PPU clocks aren't the only regular event in the PPU: there's also VBL. As above, after a power/reset, a CPU clock can begin in only two possible positions relative to VBL, each 8 master clocks apart.
I've been working on tests which are able to show how many different power/reset states it can be in, by being able to have it print which one it's on, and never print anything different except after another power/reset.