libretro / mgba

mGBA Game Boy Advance Emulator
https://mgba.io/
Mozilla Public License 2.0
68 stars 72 forks source link

Save States for GB/GBC games are glitchy #126

Open dagreatbuzzsaw opened 5 years ago

dagreatbuzzsaw commented 5 years ago

Whenever I use a save state for a GB/GBC game and load it, it seems to work but the game glitches up and it appears you are in the same place before you load the state. It's hard for me to describe, you'd have to see it for yourself.

I should note that save States for GBA games work fine without any problems, and once again this is for the Wii U version of RetroArch.

endrift commented 5 years ago

What game and core version?

dagreatbuzzsaw commented 5 years ago

So far I've played Donkey Kong '94, Super Mario Land's 1 and 2, and Wario Land: SML3, and have experienced glitches, so I'm assuming it is like this for every game. And the core version is 0.7-b1 426934d.

endrift commented 5 years ago

Hmmm. That should have been fixed by then. I'll try to look at this later this week.

dagreatbuzzsaw commented 5 years ago

Update:

I tested other ROMs and they all seem to work fine. I also retested DK94 and SML and found no problems with save states now. Don't know why I listed them before, so I apologize.

The only glitchy games I found were with SML2 and WL:SML3. I even tried redownloading the ROMs from other sites and the same things happened. The core seems to have a problem with just those two games. I hope this helps. If I run into anymore trouble, I'll let you know.

meepingsnesroms commented 5 years ago

I believe both of those games use the SRAM as regular RAM since the GB(C) doesnt have enough to store the level uncompressed, is SRAM being stored in save states?

endrift commented 5 years ago

There WAS an open bug regarding those in mGBA for a while but it should have been fixed. That fix did require changes in the libretro code, but that was applied a while ago. Hmmm.

meepingsnesroms commented 5 years ago

It likely wasn't fully fixed, I dont know of any other games that do that and those are the only 2 that are broken.

endrift commented 5 years ago

@dagreatbuzzsaw I'm assuming you tried making new states with the latest version and didn't use old ones? Older ones don't contain the SRAM data so they will never load properly. New ones should work, however, so if they're new ones it's curious.

meepingsnesroms commented 5 years ago

In libretro.c retro_serialize(): mCoreSaveStateNamed(core, vfm, SAVESTATE_SAVEDATA | SAVESTATE_RTC);

In libretro.c retro_unserialize(): bool success = mCoreLoadStateNamed(core, vfm, SAVESTATE_RTC);

SAVESTATE_SAVEDATA is not set in load state.

This is the issue in mCoreLoadStateNamed():

if (flags & SAVESTATE_SAVEDATA) {
        void* sram = NULL;
            core->savedataRestore(core, item.data, item.size, flags & SAVESTATE_SAVEDATA);
        }
}
dagreatbuzzsaw commented 5 years ago

@endrift Yes, they are new save states. I don't think I reused any old ones.

endrift commented 5 years ago

That's intentional. It will always temporarily load it specifically because of this situation but it won't write it back unless it's written to again. If you pass SAVESTATE_SAVEDATA every savestate will overwrite the savedata on load, which will piss off many Pokémon players.

meepingsnesroms commented 5 years ago

But if you dont overwrite the SRAM on load you have half of the old level in RAM in SML2/3.

Isnt the expected behavior of a save state to save and load everything?

endrift commented 5 years ago

In SML2/3 it will end up overwriting everything due to how the games work, yes. But in GBA games savedata is almost always only accessed at save time, so if someone saves their game, loads a savestate and then doesn't save their game, the next time they load the game they're not usually going to want the save from the last time they saved in the savestate; they'll want whenever they last saved. This is the best middle ground approach I could come up with, though it might not actually work in RetroArch anyway due to how poorly designed the save game API is.

meepingsnesroms commented 5 years ago

Yeah the file on disk dosent matter as long as the in SRAM is loaded with the game then SML2 will write its level data which will make the change permanent, but I think its not loading SRAM at all. core->savedataRestore / _GBCoreSavedataRestore is only called if that flag is set, in that function there is other logic which is essentially dead code because that function cant be called with the flag not set.

See in my post above it calls the function with the flag after checking if it should call the finction at all with the same flag.

This is supposed to be performed in that function whether the flag is set or not: memcpy(gb->memory.sram, sram, size);

endrift commented 5 years ago

I can't find your lines in the source. They look like a spliced misindented version of two different functions.

meepingsnesroms commented 5 years ago

Researched, yes they where misspliced, sorry I copyed from search, discard what I said above.

EDIT: Heres proof of the SRAM being used as WRAM: https://youtu.be/FPzuYWbnln4?t=323

endrift commented 5 years ago

That explains that :D I'll see if I can figure out what's going on later when I actually have time.

dagreatbuzzsaw commented 5 years ago

Another interesting save state glitch i've found, though it's not as major as the others:

In Wario Land II (the GBC version), when I save a state, grab some nearby coins, then load the state, the coins I grabbed before are there, but I can't grab them when I walk over to them. When I walk away until the coins are offscreen and go back, the coins are gone.

Almost as if loading the state just brought back the sprites of the coins but not the coins themselves. Or rather, loading the state brought back the coins but still acknowledges I grabbed them after I saved the state.

It's confusing, I know. It's not all that important, I just wanted to point that out. 😕

meepingsnesroms commented 5 years ago

These games are using the save data as regular RAM for storing variables and level data and the SRAM is not being loaded in the save state, so that makes sense, its like the game has mid stage Alzheimers, it still remembers the coins were collected, but not that they dont exist anymore, even though those 2 states contradict each other and could never occur together in reality.

What is "remembered" or "forgotten" is dependent on what variables the game stores in SRAM, if only save data and no variables are stored there it works fine, if 1 or more variables or buffers are stored there there will be bugs, the more data stored there the more of the loaded state is "forgotten" and the worse the corruption is.

So Wario Land II just stores less data in the broken region then the other games.

Its still helpful to get more information on the bug though, when writing emus the more specific the bug reports the better.

dagreatbuzzsaw commented 5 years ago

Ok, I have a new issue: Donkey Kong Land for GB. When I try to load a savestate, the whole system freezes up, forcing me to do a hard reboot. I tested the other two DKL games and the save/load states all work fine with no problems. Don't know why it's just this game.

The core is 1.7.5 - mGBA 0.7-b1 6db8583

BTW, thanks for the recent update! The previous games I mentioned all have working savestates with no glitches, even though any items (coins, bananas, etc.) you got before loading was still already acquired. Awesome job guys! If I run into anymore glitches, I'll let you know! 👍

ghost commented 5 years ago

turning on Settings > Saving > Dont overwrite SRAM when loading states also causes this issue for games/cores using sram as additional...

dagreatbuzzsaw commented 5 years ago

New issue:

Been playing Mega Man in Dr.Wily's Revenge, Mega Man II, and Mega Man IV for GB, when I try to load a Save State, the whole thing freezes up and I am forced to reboot. Oddly, this doesn't happen to Mega Man III, the save state loads normally and it doesn't freeze, and I haven't gotten to Mega Man V yet.

Update: Mega Man V freezes up too. At first it doesn't, but when you get late into the game, then it freezes up. :(