It is currently Wed Dec 13, 2017 10:02 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 43 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: PPU timing?
PostPosted: Thu Jan 07, 2016 7:08 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
note: i'm discussing the ntsc standards, as 1 cpu cycle = 3 ppu dots.
For the 1st time, I played with the PPU timing. What's up? Well, there's an unfinished discussion about clocking the PPU (running for 3 cycles) before or after a CPU clock. Since a few games have flickering scorebars, I decided to play with the PPU timing. For my surprise, things are "completely fixed" when the number of PPU cycles alternates between 3 and 2 for every CPU cycle.

Anything about it?


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Fri Jan 08, 2016 12:47 am 
Offline

Joined: Mon Sep 27, 2004 2:57 pm
Posts: 1248
The CPU's clock signal is divided from the same crystal the PPU's clock signal comes from, and the CPU's clock is 1/3 the PPU's clock, so there should always be 3 PPU cycles between each CPU cycle.

Shaking status bars usually come from a badly-timed screen split, so there may be a problem somewhere else, like with the timing of the scanline counter, the CPU's interrupts, etc. There should definitely always be 3 PPU cycles to every 1 CPU cycle though.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Fri Jan 08, 2016 9:54 am 
Offline

Joined: Mon Apr 01, 2013 11:17 pm
Posts: 437
Zepper wrote:
Well, there's an unfinished discussion about clocking the PPU (running for 3 cycles) before or after a CPU clock.

It doesn't matter which you choose, as long as you write it so that events where one depends on the other (reads, writes, NMI, etc.) occur as if the two were running in parallel.
Zepper wrote:
For my surprise, things are "completely fixed" when the number of PPU cycles alternates between 3 and 2 for every CPU cycle.

Since slowing down the PPU makes status bars appear normal, you probably aren't giving your CPU enough time to respond to the interrupt. You might be triggering the interrupt at the wrong time, or spending too many CPU cycles on receiving the interrupt.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sat Jan 09, 2016 6:39 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
With respect, but keep saying "running in parallel" sucks. A lot of picky cases of reading $2002 1 cycle before/after VBlank, or cases regarding APU reading ($4015) make me think that clocking the PPU before/after the CPU MAKES difference in emulation. As I said, I already debugged the test suites for PPU/APU like crazy, and my conclusion is still correct!


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sat Jan 09, 2016 4:34 pm 
Offline

Joined: Mon Apr 01, 2013 11:17 pm
Posts: 437
If you clock the CPU first, then when you clock the PPU, the PPU needs to decide what the CPU will see if it performs a read during its next cycle, because the current CPU cycle has already finished.

You don't have to run them in parallel, you have to make them look like they're running in parallel.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sat Jan 09, 2016 6:12 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Joe wrote:
(...) the PPU needs to decide what the CPU will see if it performs a read during its next cycle (...)


How so?


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sat Jan 09, 2016 8:18 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
I'm confused what you're actually asking, Zepper.

You employed a hack and it happened to fix some games, and now you're asking if the hack is correct? The answer to that question is "no". There are definitely 3 PPU cycles to every 1 CPU cycle.

If you want to figure out why games have a shaking screen in your emu, I would dump a trace log and look at the timestamps of when interrupts and PPU writes are happening. Shaky status bars should be pretty easy to spot in a tracelog if you include scanline/dot number in the log. If you count the cycles between interrupt and PPU write you should be able to see the window the game is working with, and should be able to spot where the timing in your emu is off.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 7:13 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Disch wrote:
I'm confused what you're actually asking, Zepper.

You employed a hack and it happened to fix some games, and now you're asking if the hack is correct? The answer to that question is "no". There are definitely 3 PPU cycles to every 1 CPU cycle.

It's about executing ppu_run()->cpu_run(), or the reverse. I'm saying the order does matter for picky readings, mostly $2002 and $4015. Well, ANes guy (or aNes?) had great results when he did such change (ppu first, then cpu). If someone keeps saying "runs in parallel", it's not making sense to me, at least in C. :oops: Got it?

Quote:
If you want to figure out why games have a shaking screen in your emu, I would dump a trace log and look at the timestamps of when interrupts and PPU writes are happening. Shaky status bars should be pretty easy to spot in a tracelog if you include scanline/dot number in the log. If you count the cycles between interrupt and PPU write you should be able to see the window the game is working with, and should be able to spot where the timing in your emu is off.

You mean NMIs..? The shaking/flickering scorebars occur due to a "bad timing" regarding $2006 (and possibly $2005) writes. On other side, it could be my gfx engine.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 8:36 am 
Offline

Joined: Mon Apr 01, 2013 11:17 pm
Posts: 437
Zepper wrote:
It's about executing ppu_run()->cpu_run(), or the reverse. I'm saying the order does matter for picky readings, mostly $2002 and $4015. Well, ANes guy (or aNes?) had great results when he did such change (ppu first, then cpu). If someone keeps saying "runs in parallel", it's not making sense to me, at least in C. :oops: Got it?

The order of execution is fundamental to an emulator's design. It should be no surprise that changing it makes a big difference in how things work.

Let's say I have an emulator that runs the CPU first, then the PPU. When the CPU performs a write to $2002 during its time slice, the PPU will receive that write during its time slice. But what about a read from $2002? If the PPU tries to return the value during its time slice, it will be too late: the CPU has already finished, so it can't receive the correct value.

Now let's see what happens if I put the PPU first, and then the CPU. When the CPU performs a read from $2002, the PPU has already executed and can return the correct value. But what about a write to $2002? The PPU has already finished, so it won't receive the write until its next time slice.

In order to get timing to work correctly, you must solve that problem. Changing the order of CPU and PPU execution does not solve that problem, it only changes where the problem occurs.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 11:47 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Write to $2002? Never do.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 1:40 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Zepper wrote:
Write to $2002? Never do.


Joe did not mean that PPUSTATUS ($2002) is a register to which data can be written. Rather, he was referring to updates to the sprite overflow flag, the sprite 0 hit flag and the vertical blank flag.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 4:01 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
"Solving" the problem only has 1 solution... AFAIK, PPU clocks before a CPU read; and after a CPU write. I'll explain with examples.

- Reading $4015 or $2002 seems to work only if the PPU is clocked first. Example: the PPU sets flags (sprite zero, VBlank) and the CPU catches them in the subsequent read, and not before.

- Writing to $2000 or $2001 seems to take immediate effect if the PPU is clocked after the CPU write cycle, and not before. Example: setting the screen ON should be done after the CPU write, because if done before, the PPU wouldn't catch the setting during the first 3 PPU cycles.

Correct me if I'm wrong about this. However, the shaking continues. :mrgreen: :mrgreen:


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Sun Jan 10, 2016 7:25 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
This all seems hacky and unnecessary.

Doing things "before" the CPU or "after" shouldn't matter as long as you're consistent.

It's confusing to visualize what happens when the CPU and PPU try to access something at the same time -- so just assume they have one of the bootup syncs where they never do:

Code:
P = ppu cycle
C = cpu cycle

PPPCPPPCPPPCPPPC


You might look at this and say "he's running the PPU first" .. but this sequence could just as easily be rewritten as:

Code:
CPPPCPPPCPPPCPPP


And now the CPU is first. There's no difference -- they're the exact same thing.

The only thing that matters is when something happens on one P cycle, how it impacts the surrounding C cycles (and vice versa). Logically, something that happens on a P cycle can't impact a C cycle that is already complete, so you only have to worry about the next one:

Code:
     PPU generates NMI here
      |
      V
CPPPCPPPCPPP
        ^
        |
        |
      CPU 'sees' NMI here (but won't actually perform
          it until this instruction is complete)


Notice how I "ran the CPU first" here... but this logic doesn't change even if you run the PPU first:

Code:
    PPU generates NMI here
     |
     V
PPPCPPPCPPPC
       ^
       |
       |
     Exactly the same .. even though PPU is "run first"



On this abstract level, it really isn't any more complicated than that. You're making this problem out to be way harder than it really is.


In all liklihood, you're seeing shakey status bars because you have an off-by-1 error somewhere in your code. Maybe you're firing an NMI one ppu cycle too early/late or something like that. That could be easily exposed if you dump a tracelog and examine it.

If you make a trace log that tells you exactly what cycle NMI happens on, and what cycles the CPU is writing to scroll regs, or reading from $2002 -- and compare that to a disassembly of what the code is actually doing, you should be able to spot where your emu is going wrong.



----------------------

Or... if you want to run the CPU as "half-cycles" you might have a pattern like this:

Code:
P = PPU cycle
r = rising edge of CPU clock
f = falling edge of CPU clock

rPfPPrPfPPrPfPP

or

rPPfPrPPfPrPPfP


This might help if you find that writes take effect on the rising edge of a CPU clock, while reads take effect on the falling edge. But I *think* they both take place on the rising edge, so this is probably unnecessary. You could verify that with Visual2a03 + visual2C02 if you want.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Mon Jan 11, 2016 6:15 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Let's say a "sprite hit event" occurs at PPU cycle N. If a $2002 read occurs before N, the sprite hit will be off up to 3 PPU cycles. Else, the sprite hit flag will be set on $2002 read. It's a difference of 1 CPU cycle or up to 3 PPU cycles.

Regarding the shaking, even zeroone had such conclusion - running the CPU prior to PPU fixes the shaking/flickering in a few games, but the general timing is broken and would be needed to be adjusted.


Top
 Profile  
 
 Post subject: Re: PPU timing?
PostPosted: Mon Jan 11, 2016 9:54 am 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
Zepper wrote:
Let's say a "sprite hit event" occurs at PPU cycle N. If a $2002 read occurs before N, the sprite hit will be off up to 3 PPU cycles. Else, the sprite hit flag will be set on $2002 read. It's a difference of 1 CPU cycle or up to 3 PPU cycles.


So what you're saying is.... if the CPU reads $2002 before the sprite hit flag is set, they won't see it as set.

That's obvious. More than that... that's how it should be. $2002 reads should not see into the future. Why do you think this behavior needs to be changed?

Quote:
Regarding the shaking, even zeroone had such conclusion - running the CPU prior to PPU fixes the shaking/flickering in a few games, but the general timing is broken and would be needed to be adjusted.


That's great and all, but it doesn't explain the behavior.

An off-by-1 error seems much more likely to me than requiring CPU reads to look into the future.

Like I said before... make a tracelog. Count the number of cycles between NMI/$2002 and the scroll change. That will let you know what kind of window you're working with. Odds are, the window is really small, and the game is falling outside of the window for some frames resulting in a shaking status bar. But seeing all the data should give you an indication of what behavior SHOULD be happening vs. what your emu is actually doing, and that will give you an idea of how to fix it. As of now, you seem to just be trying random stuff in hopes that it will work. You can't solve a problem if you don't know what the problem is.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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