BizHawk icon indicating copy to clipboard operation
BizHawk copied to clipboard

[F.Rq.] "Un-loadstate" / Mitigate accidental overwriting of SaveRAM with savestates

Open RetroEdit opened this issue 5 years ago • 5 comments

Note: EmuHawk does not currently have un-loadstate. However, if rewind is enabled, it's making savestates periodically. You may be able to restore your progress by rewinding back "through" the loadstate. Original text follows.


bramcn0745 brought this up in #2157, and I think this option would be extremely valuable. Loading savestates can be very destructive for casual users, as it can immediately overwrite a save file on disk without any warning. In my very early days, I have had this happen a few times, and it's easy to not even be aware of the dangers of loading savestates, or load a savestate without thinking.

One option is a warning like: "Loading a savestate will overwrite your save file. Are you sure you want to do this?" It could even have an option "Backup my save file". A warning might be overkill, but if it had an easy dialog option "don't warn me again", that might be a nice compromise.

Alternatively, BizHawk could create a backup SaveRAM file when loading a savestate for the first time in a session of a particular game, and then any savestate loading mishaps are thus made easily recoverable. The more I think about it, the more this second option seems ideal for casual players and TASers alike, as it's a nice safety catch mechanism, but also doesn't disruptive to power-users.

RetroEdit avatar Jun 28 '20 00:06 RetroEdit

This has been litigated to death. It is standard practice for emulators. People need to learn it. This confusing as hell situation is known as "clobber's lament."

There will be no warning on loaded savestates.

I have spent a long time thinking about this and dealing with the nuisance. I only consider two things acceptable for solving this, and they both need to be done eventually:

  1. Make backups of saverams EVERY SINGLE TIME a state is flushed (unless in a movie session). The disk will be littered with saves. Users can deal with it. Users can learn how to clean up their mistakes from backups. Put careful thought into how it's organized; perhaps put them in a backups subdirectory. We can do this now.

  2. Later, when we're feeling bold: users must choose to flush manually. 1) still applies--backups are always made first. The pressure for part 2 will be reduced by part 1. Moreover, for an interim learning period (or perhaps forever), backups will also be made directly at the point where the emulator would ordinarily automatically flush. So, as with part 1, people at least have the files needed to go in and clean up after themselves.

zeromus avatar Jun 28 '20 00:06 zeromus

Can we just close this, please? A user who is freely interleaving saveram saves and savestate saves is going to teach themselves a life lesson sooner or later regardless of how many coats of paint we put on the dung pile. Then there's the problem of systems and games where failing to include saveram in the savestate produces an incoherent save that can crash the emulated game on load...

nattthebear avatar Jun 28 '20 01:06 nattthebear

Then there's the problem of systems and games where failing to include saveram in the savestate produces an incoherent save that can crash the emulated game on load...

This is why I didn't suggest excluding the SaveRAM from a loaded savestate, as that can be problematic.

RetroEdit avatar Jun 28 '20 02:06 RetroEdit

As a casual user, despite #3061 working around this issue in its own way, I think Load States should not affect SaveRAM saves. I'll get to why, but I'd like to say that I've never experienced an emulator working this way until I used Bizhawk.

Of the modern emulators on my machine (3), and emulators I can remember using up to now (at least 9), none of them have ever done this. I went out of my way to test the 3 I have to see if they operate in this way and perhaps I had just not noticed, but the result was "They do not." If it was once standard, then I expect it is no longer standard. At least for emulators intended to be used by casual players, rather than TASers.

Even if it was standard, I think it's a poor design choice because it is unintuitive. To explain why I think that, I'm going to cover information most people probably already know, but I think is necessary.

Game systems usually have 2 types of storage:

  1. Nonvolatile - We'll call it "disk" for lack of a better universal term. Storage that doesn't fail if it stops losing power. Some don't, like the Gameboy since it requires batteries in all its carts to preserve saves, but most do. I get that, in actuality, everything a Gameboy has is stored in RAM, but there is a special place in that RAM that is not written over without a user actioning it, and that is stored in perpetuity, at least until the battery dies.
  2. Volatile - RAM, typically. Storage that fails if it stops receiving power. Typically, where the active game state is stored. And there's the key. Most people would consider what's in volatile RAM to be the "active game state". Saves are typically "not that".

I explain all that to say that loading a save state should not touch the nonvolatile storage, because when that storage is interacted with should be limited to manual events that trigger doing so. And, from the perspective of most people, nonvolatile storage is not the current state of the game. It might house a former state of the game, via a save function, but the current state of the game does not include that.

Using Microsoft Excel as an example, the recovery feature is functionally an equivalent to automated save states. However, when one is restored, it doesn't affect anything "on disk" unless the user goes out of their way to do so, like clicking "Save" in the File menu. What's "on disk" is not treated as a part of the program's current state.

Much the same, I don't think that restoring a game's Save State should touch the SaveRAM on Disk that represents the system's save for that game. And restoring a Save State is not actioning the events that should interact with that, like going into the menu to click Save in the game itself. The event that should be doing that is not occurring. And that's why it's unintuitive.

As a casual user, from my perspective, it makes sense to update the running RAM with a Save State, but updating the SaveRAM on Disk that represents the manual save is essentially the software doing something I wouldn't expect it to do because that's not part of what I view as its "current active state".

Reading the responses to this Issue don't give me much hope for it to be resolved, but I thought sharing this perspective and reasoning might be helpful, because while I think #3061 would be awesome to have, I see it as offering a workaround for a problem that is itself worthy to fix.

Ultimately, I see this issue as a problem because it works counter to how computers are expected to work. And I think that how most emulators currently treat manual saves relative to Save States affirms that perspective.

If an option were provided to choose the behavior for Save States relative to SaveRAMs, so that it worked as it currently does, or it could be set to work in a way to resolve this issue, that way people could choose for themselves, that'd be nice. But I think that if that were added, it should default to "States don't overwrite SaveRAMs" for the reasons I've given.

Thanks for reading.

Payden-Pringle avatar Mar 29 '23 05:03 Payden-Pringle

You must have used 3 emulators that emulate one system each where access to the nonvolatile media is somewhat guarded. Not all systems are like that. Bizhawk is a multi-system emulator. We have to handle all cases.

Those emulators are emulating detachable nonvolatile media. Bizhawk is simply not emulating that. Bizhawk is dropping something labeled "saveram" as a courtesy. I think it's ill-conceived and I wish we didn't do it. I wish you had to manually export it.

You want an option "States don't overwrite saverams". That's not a logical request. States DON'T overwrite saverams. States reload the state of the system which includes the UNIVERSE (including the saveram). You "choose" to overwrite the saveram by issuing the implicit "command" to flush the saveram (that is, closing the rom, which triggers our courtesy flush). Again, I wish it didn't work that way. If it didn't work that way, then you wouldn't be confused by both when the contents change actually, and when the contents change on your disk: the contents would change, on disk, when you ordered them to.

I'm not going to explain the whole thing, only advise you that generally your understanding of all the possibilities for how game systems can work is very inadequate (I doubt you tested any emulators for systems predating the PSX, and if you did, they were buggy and unreliable); and also give you one other tidbit to contemplate.

Some systems are using the nonvolatile memory as a scratchpad. It's eminently un-"guarded". We don't know when the game is editing the nonvolatile memory. But actually it's likely to be doing it all the time--every frame. So for these games, if things worked the way you wanted, you would load your state, then the game would "save" (or rather it would write scratch data to the nonvolatile storage) and then the courtesy flush would happen later and you'd say "wait why does 'state overwrite saveram' sometimes but not others?"

The situation is fundamentally confusing. I could fix it for everyone, as I threatened to do years ago, but I am waiting until I want to quit the internet to stealth commit that and then bail so I don't have to listen to the grief but retire comfortably knowing it was for everyone's good.

You could also ask for bizhawk to emulate the detachable nonvolatile storage like other emulators do. Which is theoretically possible--for some systems (while utterly absurd for others). For anyone who wants to tackle that on a case by case basis, I suggest not savestating it, else things will get even more complex, and instead treat it like a gamepad input. It's a serial line to a flash device, just like the serial line to the gamepad. Heck, it's even over the same serial bus on a lot of systems--its no coincidence that controllers and storage were literally tightly coupled for such a long time.

And I still think "Make backups of saverams EVERY SINGLE TIME a state is flushed" is a good workaround because even if the problem and/or defining the problem and/or the solutions and/or understanding the solutions are intractably complex, this gives people the means to fix their mistakes.

zeromus avatar Mar 29 '23 07:03 zeromus