Difference (Unl) shakes in my emulator

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

I injected some logging into my PPU implementation. It records $2005 and $2006 writes along with the scanline, scanline cycle and w, t, v and x registers before and after the write. Also, by monitoring the pixel colors, it can differentiate between a good and bad frame.

Here's a good frame (scrollY = 203 at the split):

Code: Select all

[$2005] = 00, scanline = 192, cycle = 287 w_before = false, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = true, t_after = 0000, v_after = 1300, x_after = 00, scrollY_after = 193
[$2005] = 00, scanline = 192, cycle = 305 w_before = true, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = false, t_after = 0000, v_after = 1300, x_after = 00, scrollY_after = 193
[$2006] = 3F, scanline = 192, cycle = 323 w_before = false, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = true, t_after = 3F00, v_after = 1300, x_after = 00, scrollY_after = 193
[$2006] = 01, scanline = 193, cycle = 0 w_before = true, t_before = 3F00, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = false, t_after = 3F01, v_after = 3F01, x_after = 00, scrollY_after = 435
[$2006] = 27, scanline = 193, cycle = 186 w_before = false, t_before = 3F01, v_before = 3F08, x_before = 00, scrollY_before = 435 w_after = true, t_after = 2701, v_after = 3F08, x_after = 00, scrollY_after = 435
[$2006] = 00, scanline = 193, cycle = 204 w_before = true, t_before = 2701, v_before = 3F08, x_before = 00, scrollY_before = 435 w_after = false, t_after = 2700, v_after = 2700, x_after = 00, scrollY_after = 194
Here's a bad frame (scrollY = 202 at the split):

Code: Select all

[$2005] = 00, scanline = 192, cycle = 300 w_before = false, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = true, t_after = 0000, v_after = 1300, x_after = 00, scrollY_after = 193
[$2005] = 00, scanline = 192, cycle = 318 w_before = true, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = false, t_after = 0000, v_after = 1300, x_after = 00, scrollY_after = 193
[$2006] = 3F, scanline = 192, cycle = 336 w_before = false, t_before = 0000, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = true, t_after = 3F00, v_after = 1300, x_after = 00, scrollY_after = 193
[$2006] = 01, scanline = 193, cycle = 13 w_before = true, t_before = 3F00, v_before = 1300, x_before = 00, scrollY_before = 193 w_after = false, t_after = 3F01, v_after = 3F01, x_after = 00, scrollY_after = 435
[$2006] = 27, scanline = 193, cycle = 199 w_before = false, t_before = 3F01, v_before = 3F08, x_before = 00, scrollY_before = 435 w_after = true, t_after = 2701, v_after = 3F08, x_after = 00, scrollY_after = 435
[$2006] = 00, scanline = 193, cycle = 217 w_before = true, t_before = 2701, v_before = 3F08, x_before = 00, scrollY_before = 435 w_after = false, t_after = 2700, v_after = 2700, x_after = 00, scrollY_after = 194
I cannot detect any race conditions based on those values. Perhaps someone else will notice something. Thanks for looking.

Edit: Further logging revealed the core issue. The game disables rendering, it does the writes above and then it enables rendering. There is a timing issue where rendering is enabled just prior or just after the Y-increment, which causes the shaking. The Y-increment doesn't get called when rendering is disabled. I'll study this further.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

Well, you see the $2006 write and the Y-increment... but not the race condition. You're very good by digging something else... :shock: :roll: :roll: :lol: :lol:
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

Zepper wrote:Well, you see the $2006 write and the Y-increment... but not the race condition. You're very good by digging something else... :shock: :roll: :roll: :lol: :lol:
The cause is actually a $2001 write that takes place slightly after the dot where the Y-increment should take place. Meaning, it's a missed Y-increment.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

zeroone wrote:
Zepper wrote:Well, you see the $2006 write and the Y-increment... but not the race condition. You're very good by digging something else... :shock: :roll: :roll: :lol: :lol:
The cause is actually a $2001 write that takes place slightly after the dot where the Y-increment should take place. Meaning, it's a missed Y-increment.
I would justify me again, but do whatever you want to believe.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

Do registers $2005 and $2006 update the v, t and w registers immediately? Or, are they updated after a brief delay (i.e. a PPU cycle or 2)?
Alyosha_TAS
Posts: 173
Joined: Wed Jun 15, 2016 11:49 am

Re: Difference (Unl) shakes in my emulator

Post by Alyosha_TAS »

fred wrote:I very briefly tested writes to 0x2006 a while back in visual nes. It did seem like setting vramaddr_v to vramaddr_t in the second write was delayed a few ticks (~3?). I don't know the inner workings of the ppu enough to tell for certain.

The status bar in bart vs the space mutants that relies on a 6-5-5-6 series of writes stops shaking in my emulator if i delay the v = t effect for 3 ppu ticks. My cpu-ppu sync is not good enough to prove anything though, as evident by battletoads stage 2 crashing even faster with this change.
This is very interesting. Thanks for pointing this out. I wonder what other writes take a tick or 2 to take effect?
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

Works like a charm. Wow. Even the "race condition" of $2006 vs Y-increment isn't necessary in this case.

Well, Battletoads still hangs during stage 2 - you know... it's a missing sprite zero hit.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

Zepper wrote:Works like a charm. Wow. Even the "race condition" of $2006 vs Y-increment isn't necessary in this case.

Well, Battletoads still hangs during stage 2 - you know... it's a missing sprite zero hit.
Earlier, you suggested to skip a Y-increment if it occurred shortly after a $2006 write. However, by delaying the V-register update, it will overwrite the effect of the Y-increment that occurred slightly before the write.

I suspect any such skip or delay is a actually just a hack that does not reflect how the actual hardware performs. And, it's dangerous to introduce fixes through hacks since it's difficult to detect the affects on all other games with timing issues.

Ultimately, it comes down to how the emulator divides up time. The CPU runs at a third of the rate of the PPU. Consequentially, it's not clear exactly on what dot or perhaps even sub-dot information transfer actually occurs. And, it may even vary depending on the current state of the system. By running the PPU for 3 cycles after every CPU cycle, it's like trying to fit a small sheet on a large bed. You can pull it around, but you'll never fully cover the bed.
fred
Posts: 67
Joined: Fri Dec 30, 2011 7:15 am
Location: Sweden

Re: Difference (Unl) shakes in my emulator

Post by fred »

Here's what i was looking at in visual nes: http://pastebin.com/ket4LxgS
Pastebin because it's a lot of lines. This is two cpu cycles - the write to 0x2006, and fetching the next opcode. As can be seen, vramaddr_t gets set immediately on phi2 of the write cycle (ppu dot 198). vramaddr_v changes in the middle of dot 201.

That's what it looks like to me anyway. I don't want to talk in certainties here, because I only say what visual nes shows. I don't have any real understanding of the nes, if you know what i mean.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

So... that's it. Even Nintendulator does not apply the changes immediately, see $2007 for example.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

Zepper wrote:So... that's it. Even Nintendulator does not apply the changes immediately, see $2007 for example.
In Nintendulator 0.975, the status bar in "The Simpsons: Bart Vs. the Space Mutants" shakes and Battletoads Stage 2 tends to freeze. Those issues do not appear in Nintendulator 0.970; however, that earlier version contains a hack where the X and Y increments take place 4 dots earlier than they actually should. In addition, many of the timing test ROMs fail in both Nintendulator versions.

Nintendulator is an excellent emulator. But, it never fully overcame these problems either.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

Do you still have questions about the $2006 "delay" find?
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Difference (Unl) shakes in my emulator

Post by zeroone »

Zepper wrote:So... that's it. Even Nintendulator does not apply the changes immediately, see $2007 for example.
In Nintendulator, PPU register writes update the v, t and w registers immediately. The delayed writes are for VRAM only.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Difference (Unl) shakes in my emulator

Post by Zepper »

Let me rephrase myself...

1. True, Nintendulator has such "delay" on $2007 only.
2. Do you expect a Nintendulator update to formalize the recent $2006 loopy_v=loopy_t delay find? Yes?
Rahsennor
Posts: 479
Joined: Thu Aug 20, 2015 3:09 am

Re: Difference (Unl) shakes in my emulator

Post by Rahsennor »

I'm seriously out of it from illness and other stuff, but I spent a bit of time playing around in Visual 2C02, and I think I can confirm what fred found.

write_2006_low goes high during the second write to $2006 - no delay.

delayed_write_2006_low goes high after a variable delay: (First number is rising edge, second number is falling edge, times are in the same units as Visual 2C02 so 1 pixel = 4 cycles.)

Code: Select all

  normal    delayed
16.0 23.5  24.0 28.0
16.5 24.0  24.0 28.0
17.0 24.5  28.0 32.0
17.5 25.0  28.0 32.0
18.0 25.5  28.0 32.0
18.5 26.0  28.0 32.0
19.0 26.5  28.0 32.0
19.5 27.0  28.0 32.0
20.0 27.5  28.0 32.0
20.5 28.0  28.0 32.0
21.0 28.5  32.0 36.0
As you can see (by all the numbers being a multiple of 4), delayed_write_2006_low always goes high at the start of a pixel. It in turn drives both copy_vramaddr_vscroll and copy_vramaddr_hscroll half a pixel later, reloading vramaddr_v in time for the start of the next pixel.

So to get from the time of the $2006 write to the time of the v register load, the rule is "add 13 cycles (3.25 pixels) and round down to the nearest multiple of 4 (pixel)". If you don't emulate steps less than a pixel (and why would you) that works out to a three pixel delay from the second $2006 write to the v = t register load.

EDIT: I'm pretty sure that should be 15 cycles = 3.75 pixels. Forgot to account for the time to actually reload v.
Last edited by Rahsennor on Sun Feb 12, 2017 5:29 pm, edited 1 time in total.
Post Reply