clementgallet / libTAS

GNU/Linux software to (hopefully) give TAS tools to games
GNU General Public License v3.0
476 stars 56 forks source link

Dandara determinism issues #402

Open marcelopio opened 3 years ago

marcelopio commented 3 years ago

I am having sync and determinism issues with Dandara.

I attached a movie file that should lead to the boss in most cases, but may get buggy due to the first issue.

Dandara.x86_64.zip

clementgallet commented 3 years ago

This game calls usleep() in the middle of gameplay (2 ms and 10 ms), and fast-forwarding makes more/less calls and earlier/later, ultimately causing more non-draw frames.

2 ms call stacktrace:

/usr/local/bin/libtas.so(+0x1fe1c) [0x7f890c604e1c]
/usr/local/bin/libtas.so(usleep+0x11d) [0x7f890c616e4d]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17cb73f]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17b00da]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17a9c52]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe530d5]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe53e30]
/home/clement/Games/Dandara/Dandara.x86_64() [0xc4809a]
/home/clement/Games/Dandara/Dandara.x86_64() [0xc48158]
/home/clement/Games/Dandara/Dandara.x86_64() [0xc4b6d0]
/home/clement/Games/Dandara/Dandara.x86_64() [0x44dc07]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea) [0x7f890c0c2cca]
/home/clement/Games/Dandara/Dandara.x86_64() [0x45a601]

10 ms call stacktrace:

/usr/local/bin/libtas.so(+0x1fe1c) [0x7f890c604e1c]
/usr/local/bin/libtas.so(usleep+0x11d) [0x7f890c616e4d]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17cb73f]
/home/clement/Games/Dandara/Dandara.x86_64() [0x181d2ba]
/home/clement/Games/Dandara/Dandara.x86_64() [0x181d558]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17ddb3f]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17d39c6]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17d9c4f]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17d39c6]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17ad91e]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17ae9a1]
/home/clement/Games/Dandara/Dandara.x86_64() [0x182b387]
/home/clement/Games/Dandara/Dandara.x86_64() [0x182b5ef]
/home/clement/Games/Dandara/Dandara.x86_64() [0x17d2a32]
/home/clement/Games/Dandara/Dandara.x86_64() [0x1797b13]
/home/clement/Games/Dandara/Dandara.x86_64() [0x1791706]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe50561]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe225ff]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe22b7e]
/home/clement/Games/Dandara/Dandara.x86_64() [0xe1efc9]
/home/clement/Games/Dandara/Dandara.x86_64() [0xd7c1f1]
/home/clement/Games/Dandara/Dandara.x86_64() [0xd8605e]
/home/clement/Games/Dandara/Dandara.x86_64() [0xa25d1b]
/home/clement/Games/Dandara/Dandara.x86_64() [0xa25dde]
[0x40617061]
clementgallet commented 3 years ago

The top function 0x17cb730is just a wrapper around usleep(). Parent function for the first case contains multiple calls of sleep while waiting for a variable to change (so, by another thread):

  while (((*(uint *)(param_1 + 0x29) & 0xfffffffd) != 0 || (*(char *)((long)param_1 + 0x54) != '\0'))) {
    FUN_017cb730(2);
  }

and

      while ((*(byte *)(param_1 + 10) & 0x40) == 0) {
        FUN_017cb730(2);
      }

This function uses the symbol _ZN4FMOD7gGlobalE, so it is probably waiting FMOD thread to do something.

The other case presents the same kind of loops:

      while (iVar2 != 0) {
        FUN_017cb730(10);
        iVar2 = *(int *)(param_1 + 0x1a8);
      }

Edit: Disabling those specific usleep() removes all the non-draw frames, but it doesn't fix the variable loading times :(

marcelopio commented 3 years ago

Hmmm, variable loading times I could mitigate by putting the game in a tempfs. I am sure that it is related to caching, since:

1 - Save a state previous to a scene change 2 - Wait for scene to load 3 - Movie is desynced 4 - Go back to savestate 5 - Wait for scene to load 6 - Movie is synced

I can stop the game and reload and generally the cache will continue, so it is probably related to reading scene from disk.

Edit: Putting the game in slow motion also makes loading times a lot more consistent.