libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.24k stars 1.83k forks source link

If rewind and cheevos are enabled at the same time, rewind breaks unless it is toggled after content is loaded #15933

Closed cheatfreak47 closed 11 months ago

cheatfreak47 commented 11 months ago

Description

Enabling Retro Achievements in normal mode (not hardcore) and enabling Rewind at the same time in the latest Nightly seems to cause Rewind to not function and instead, when you press the rewind key, it loads the last loaded save state, or resets the game if no states have been loaded, rather than actually rewinding. If you, from the quick menu, toggle rewind off and back on again- it begins working again.

Expected behavior

This should just work as intended, rewind is supposed to work when cheevos are enabled as long as you're not in hardcore mode, and even if you are, it should just act as if rewind is disabled in that case, not reset the game or load the last loaded state.

Steps to reproduce the bug

  1. Extract/Install the latest nightly on Windows (at the time of issue posting and issue observed on git 598a0c0)
  2. Grab a core (Mesen and Snex9x are what I used.)
  3. Enable Rewind, and enable and enter credentials for Retro Achievements from the Settings menu. (Not the Quick Menu!)
  4. Load any rom with Achievements (I tested against Super Mario Bros. and Yoshi's Island)
  5. Play a bit and attempt to rewind with the rewind hotkey. It will reset the game. Alternatively, load a state, play a bit and attempt to rewind. It will go back to the loaded state.
  6. If you then toggle the rewind setting after content is loaded from the Quick Menu, Rewind suddenly works again.

Bisect Results

I don't have a dev env, but I do know that the last buildbot nightly this doesn't happen on is build 936ff842, from November 15th, 2023, but I think that build was overwritten by another one on the 15th that it does happen on. So that would mean the last one on the buildbot that doesn't have the problem would be 38c77e9 from the 14th.

Version/Commit

Environment information

cheatfreak47 commented 11 months ago

It looks like this bug was introduced by https://github.com/libretro/RetroArch/commit/bbe7afcd824a9c127b12a1f501bc3590f0b76b03 from the looks of what it changed, but like I said, I don't have a devenv for building RetroArch set up at the moment, so I can't verify.

Jamiras commented 11 months ago

RetroAchievements disables rewind while we load the game and re-enable it after the game has loaded as the achievement state also has to be remembered while rewinding. It looks like rewind is getting re-enabled before the achievements are ready, so when it does start trying to serialize the achievement state, the buffer isn't large enough, so it goes back to the last valid captured frame before achievements were enabled.

Will continue to investigate.

dontsnm commented 10 months ago

The bug still in the latest nightly build

Jamiras commented 10 months ago

Seems to be working fine for me on Windows with the lastest master.

Note that rewind is disabled entirely if the game has achievements and you have achievements hardcore mode enabled.

Which nightly are you using (OS/build/date)?

dontsnm commented 10 months ago

I'm using 1.16.0 retroarch version, 17c9227 git version, 5 December compilation date for Android.

I have hardcore disabled and it only happen in a few cores like Snes9x and Genesis Plus Gx.

In Snes9x core the first time I press rewind button, it reset the game and next times it doesn't nothing.

In Genesis Plus Gx core for megadrive ROMs the core crash at game start and it works fine for master system ROMs.

Maybe other cores are affected too.

CottonWoolee commented 10 months ago

Thank you for your contribution, but I have found that this issue arises again when the game being loaded is a ROM unrecognized by the database of retroachievements.

Jamiras commented 10 months ago

Thank you for your contribution, but I have found that this issue arises again when the game being loaded is a ROM unrecognized by the database of retroachievements.

That doesn't seem to be the source either. If the game is not recognized, hardcore is immediately disabled and rewind is immediately fully functional. No additional information needs to be captured in the rewind states, so the rewind code doesn't need to be reinitialized.

Jamiras commented 10 months ago

I have hardcore disabled and it only happen in a few cores like Snes9x and Genesis Plus Gx.

This is the thing that gets me. This problem - and the fix - affect all cores. It shouldn't just be "a few cores"

I'm using 1.16.0 retroarch version, https://github.com/libretro/RetroArch/commit/17c9227a9c58ae328d1ad445e54abbc2d6015be7 git version, 5 December compilation date for Android.

That commit is newer than the rewind fix, so you should have it.

In Snes9x core the first time I press rewind button, it reset the game and next times it doesn't nothing.

I don't see this in the Windows build. Is there any way you can capture a log file?

You should either see this (hardcore disabled before loading game):

[INFO] [RCHEEVOS]: All 19 achievements activated for this session.
[INFO] Initializing rewind buffer with size: 104 MB

or this (hardcore paused while in game):

[INFO] [RCHEEVOS]: Hardcore disabled
[INFO] Initializing rewind buffer with size: 104 MB

If the "Initializing rewind buffer" message only occurs before the RCHEEVOS logs, then you don't have the fix.

If you do have the fix, then you're experiencing a different issue.

dontsnm commented 10 months ago

I have hardcore disabled and it only happen in a few cores like Snes9x and Genesis Plus Gx.

This is the thing that gets me. This problem - and the fix - affect all cores. It shouldn't just be "a few cores"

I'm using 1.16.0 retroarch version, 17c9227 git version, 5 December compilation date for Android.

That commit is newer than the rewind fix, so you should have it.

In Snes9x core the first time I press rewind button, it reset the game and next times it doesn't nothing.

I don't see this in the Windows build. Is there any way you can capture a log file?

You should either see this (hardcore disabled before loading game):

[INFO] [RCHEEVOS]: All 19 achievements activated for this session.
[INFO] Initializing rewind buffer with size: 104 MB

or this (hardcore paused while in game):

[INFO] [RCHEEVOS]: Hardcore disabled
[INFO] Initializing rewind buffer with size: 104 MB

If the "Initializing rewind buffer" message only occurs before the RCHEEVOS logs, then you don't have the fix.

If you do have the fix, then you're experiencing a different issue.

With today nightly compilation for Android the issue still the same. Before the new cheevos code change, all cores working fine and I don't understand why only few cores are affected...

CottonWoolee commented 10 months ago

I need to clarify: “The Rom could not being recognized by retroachievements“ and “no one have created achievements for it on retroachievements.org“ are two different things. Although both will display 'No achievements to display' in the achievements setting in quick menu, only the former situation triggers a 'Game could not be identified' notification upon entering the game and the game won’t appear in the recent play list in retroachievements.org’s personal profile. I will provide a more detailed description of my testing environment to help solve the issue.

OS:iPadOS RetroArch version:1.16.0 Build Date:Dec 6 2023 Achievements:on Hardcore mode:off Core: Mupen64Plus-Next Rewind buffer size:200MB(Simply for the purpose of having longer rewind in N64 games, and coincidentally, I've been playing N64 games these days😊. There is no specific intention regarding this issue which also occurs in other cores. The efforts of the poster indeed have allowed games recognized rewind normally).

Case 1:Mario Kart 64 (USA) Scenario: Identifiable, achievements have been created on retroachievements.org. Result: Rewind works perfectly, thanks to those who put effort into this work.

Case 2: Bomberman 64 (Japan ) Scenario: Identifiable, no achievement has been created. Result: Rewind still works perfectly.

Case 3: Super Mario 64 (Japan) (Rev 3) (Shindou Edition), I believe many ROMs released later or with lower circulation rates would be in the same situation. Scenario: Could not be identified, no achievement has been created certainly. Result: Rewind could not work and reset the game.

Jamiras commented 10 months ago

Thanks for the detailed information.

I can reproduce with an unknown game, but not on the first load, and only with hardcore enabled.

The first load has to contact the RetroAchievements server to determine that the game is unknown. Subsequent loads already know that the game is unknown, so hardcore is immediately paused, and the code tries to enable rewind. However, as this is all happening in the achievement initialization code (because the server call was unnecessary), the core info has not yet been initialized, and the rewind initialization is aborted: https://github.com/libretro/RetroArch/blob/5a0317b440b1226b11dc8deb3970ee0c736d0bd5/state_manager.c#L602-L608

However, a few lines higher up, the fact that a rewind initialization attempt occurred is registered, so when the normal initialization is called later, it thinks it's already initialized and refuses to initialize again.

If hardcore is not enabled, the attempt to pause hardcore doesn't cause rewind to be flagged as initialized despite not doing so.

The first load requires a server hit, so when hardcore is paused, the core info is available and rewind gets initialized normally.

This doesn't happen with known games (even known games with 0 achievements) because we still fetch the achievement definitions even if the hash is known from loading the game previously. As a result, the automatic hardcore pause happens later and rewind gets initialized normally.

I'll work on a fix for the "hardcore enabled, load unknown game repeatedly" scenario, but @dontsnm claims to have hardcore disabled, which would not be explained by this. Let me know if you find any other ways to recreate the problem.

dontsnm commented 10 months ago

I'll work on a fix for the "hardcore enabled, load unknown game repeatedly" scenario, but @dontsnm claims to have hardcore disabled, which would not be explained by this. Let me know if you find any other ways to recreate the problem.

I try it again with latest version of retroarch and cores. Same bug as before.

Screenshot_20231210-174005 Screenshot_20231210-173955

I can reproduce it with Super Metroid, Super Mario World and many others.

My smartphone has Snapdragon 870, 8gb ram and Android 12. The bug still with GL and Vulkan. And yes I have hardcore disabled.

Clydefrosch22 commented 5 months ago

I've run into the same issue on 1.18.0 (Build Date April 21 2024, 64 bit) with games that dont have retroachievements, for example, the Pokemon Gold 97 romhack (gbc), Chalvo 55 (gb), or the TwinBee 3 translation (nes). Hardcore is disabled

Both, turning off and on hardcore mode in achievements menu or turning off and on rewind will make rewind work for the session. having hardcore mode enabled from the start also makes rewind work normally.

I'm playing on a RG35xx H, which I believe is a Linux based handheld, if that matters.

magpie514 commented 4 months ago

I have this issue too. Pulled to commit 6e057ab just to make sure (running on desktop Linux, Ubuntu 23.10 x86-64). I just need to disable/enable rewind for it to work again, and seems to be related to games unrecognized ("could not be identified") by the cheevos database as well. I'm debugging some homebrew (that doesn't have an entry in the database for obvious reasons) and it's so easy to forget to cycle rewind before accidentally resetting.

Jamiras commented 4 months ago

When RetroAchievements fails to identify the game, a dummy "Unknown Game" is loaded. This causes the rewind logic to try to serialize the RetroAchievements state along with the game state, which is too much data to fit into the pre-calculated buffer, so no rewind states are captured after the "Unknown Game" is loaded and rewind immediately goes back to the last state captured before the "Unknown Game" was loaded.

Toggling rewind (or hardcore which indirectly toggles rewind) re-calculates the size of the buffer needed, which fixes the problem.

A better solution to not require additional space for the "Unknown Game" is pending.

magpie514 commented 4 months ago

Seems the above merge prevents the reset at least, I just pulled and it seems to work fine now.

Will do the job while the better solution arrives. Thank you so much!