TheProjecter / snes9x-rr

Automatically exported from code.google.com/p/snes9x-rr
0 stars 1 forks source link

[1.43] Desync issues #10

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
 Reported by nitsuja-@hotmail.com, Apr 09, 2009

Snes9x probably still has some desync issues, even though it's been getting
better. I think what we should do is make sure should-be-identical
savestates are really identical (with the possible exception of parts of
the savestate that don't affect emulation and change separately from it),
in a methodical way. I checked in a way to verify that savestates are
identical and get a summary of which parts were different, which can be
used for this. Here's an example Lua script for checking desyncs:

    snes9x.frameadvance()

    state = savestate.create()
    state2 = savestate.create()

    while true do
        savestate.save(state)
        snes9x.frameadvance()
        savestate.save(state2) -- compare from here...

        savestate.load(state)
        snes9x.frameadvance()
        savestate.verify(state2) -- ...with here

        snes9x.frameadvance()
    end

Currently, when I run that script, I get some scary listings like:

&CPU::Cycles: byte 3(0x3): 28(0x1C) != 10(0xA)
&CPU::PC: byte 3(0x3): 200(0xC8) != 195(0xC3)
&CPU::PCAtOpcodeStart: byte 3(0x3): 197(0xC5) != 192(0xC0)
&CPU::WaitAddress: byte 3(0x3): 197(0xC5) != 192(0xC0)
&Registers::X.W: byte 0(0x0): 0(0x0) != 33(0x21)
&Registers::PC: byte 1(0x1): 136(0x88) != 131(0x83)
Memory.RAM: byte 72759(0x11C37): 0(0x0) != 8(0x8)
Memory.RAM: byte 72763(0x11C3B): 8(0x8) != 0(0x0)
Memory.FillRAM: byte 16923(0x421B): 0(0x0) != 1(0x1)
&IPPU::Joypads: byte 6(0x6): 0(0x0) != 1(0x1)
&GFX::LastScreen: byte 117882(0x1CC7A): 203(0xCB) != 132(0x84)
&GFX::LastScreen: byte 117883(0x1CC7B): 186(0xBA) != 65(0x41)
&GFX::LastScreen: byte 117884(0x1CC7C): 156(0x9C) != 132(0x84)
&GFX::LastScreen: byte 117885(0x1CC7D): 255(0xFF) != 65(0x41)
&GFX::LastScreen: byte 117886(0x1CC7E): 203(0xCB) != 132(0x84)
&GFX::LastScreen: byte 117887(0x1CC7F): 186(0xBA) != 65(0x41)
&GFX::LastScreen: byte 117890(0x1CC82): 203(0xCB) != 4(0x4)
&GFX::LastScreen: byte 117891(0x1CC83): 186(0xBA) != 41(0x29)
&GFX::LastScreen: byte 117892(0x1CC84): 156(0x9C) != 4(0x4)
&GFX::LastScreen: byte 117893(0x1CC85): 255(0xFF) != 41(0x29)

But sometimes I get lucky and there are barely any entries (especially if I
run it at the very start of emulation), like this:

&IPPU::Joypads: byte 6(0x6): 0(0x0) != 1(0x1)

I'm guessing that means (in this case) that the IPPU.Joypads field is the
culprit and first thing to change, and if we can make it stop showing up as
a mismatch then maybe all or most of those other mismatches will go away
too. (The left-hand side of the != is the "new" value, by the way. Also,
note that there's no need to load a movie to do any of this testing. Also
also, remember that it only works in Debug configuration, the verify
function is disabled in Release.)

Later, once the above test script works for all the games we try it on, we
should make sure that more complicated variations of it work (like
emulating 10 frames instead of just 1, or doing "out-of-order" loads, with
a movie recording, with a movie playing, separate runs of the same movie,
etc.), and it's also very important to make sure that savestates saved on
frame 0 after loading the ROM are identical to each other. (If they aren't,
that simply means the mismatching data is uninitialized and we have to set
it to 0 or something in the appropriate startup function.) This is
basically the process I went through on Gens savestates (especially
SegaCD), and those have become pretty rock-solid as far as I can tell, so
it seems to work well. Of course Snes9x 1.51 probably has even more
problems to track down but I think that should come after we're sure about
1.43.

Delete comment
Comment 1 by gochaism, Apr 09, 2009

Wow, your contribution looks so interesting. I'll read what you wrote when
I have
enough time (Actually, I'm recently busy).

Delete comment
Comment 2 by nitsuja-@hotmail.com, Apr 10, 2009

The joypad issue was a false alarm caused by reloading the Lua script with
keys that
I also use for the joypad. I should've been more careful.

However, this mismatch could be a real problem (seen in Super Star Wars):

&APURegisters::PC: byte 1(0x1): 54(0x36) != 61(0x3D)

Also, I notice "Cycles" is in the SnapAPU struct twice now for some reason.

Delete comment
Comment 3 by nitsuja-@hotmail.com, Apr 12, 2009

I found a bunch of desync problems and hopefully fixed them in revision 72.
Now I
don't see savestate mismatches happening anymore in most games (at least this
includes Super Star Wars, Yoshi's Island, Kirby 3, Kirby Superstar, Super
Ghouls 'N
Ghosts, and Seiken Densetsu 3). However, there are still issues with Mega
Man X2/X3
and Super Mario RPG and probably some more obscure games which I haven't
tried to fix
yet.

(The main problem had to do with the common practice for saving important
internal
things in Snes9x which was to "pack" and "unpack" them into/from certain
integer
variables as part of the saving and loading process. That was quite an
error-prone
way of doing it, in fact in all 3 separate cases where I saw that being
done (ICPU,
IAPU, and SA1) there was some kind of bug that prevented it from restoring
to exactly
the same thing that was saved. So I replaced those with the "regular"
non-clever way
of saving structs and it seems fine now.

Well, the other main problem was that at least one instruction/function in
spc700.cpp
accidentally uses the previous value of a should-be-local global variable
in its
calculations. So I had to add some of those global variables to the
savestates too,
even though they shouldn't need to be saved if Snes9x didn't have bugs like
that.
Incidentally, although we can't fix it in 1.43 without breaking movie
compatibility,
it looks like that bug has already been fixed in 1.51.)

Delete comment
Comment 4 by nitsuja-@hotmail.com, Apr 13, 2009

As of revision 73, Mega Man X2/X3, Super Mario RPG, Super Mario Kart, and
PilotWings
seem to be totally clean now too. The only remaining problem game I know of
is Star
Fox (probably some bug in the SuperFX saving functions, which are written
in assembly).

Original issue reported on code.google.com by andres.d...@gmail.com on 20 Jun 2009 at 1:08

GoogleCodeExporter commented 9 years ago
1.43 support is closed.

Original comment by gochaism on 16 Nov 2009 at 4:52