deltabeard / Peanut-GB

A Game Boy (DMG) emulator single header library written in C99. Performance is prioritised over accuracy.
https://projects.deltabeard.com/peanutgb/
276 stars 35 forks source link

Problem saving games #101

Closed pierreblavy2 closed 3 months ago

pierreblavy2 commented 3 months ago

Hello

I've got a problem when I'm using game that save progression like Link's Awakening : as long as I don't power off the console, everything looks all right. As soon as I switch it off, I lost my game. I'm speaking about the in game save mechanic not the emulator "savestate" that dumps the full ram of any game.

I'm using a port of the Peanut-GB on a raspberry pi pico.

Details I've seen that the emulator is created with
gb_init(&gb, &gb_rom_read, &gb_cart_ram_read, &gb_cart_ram_write, &gb_error, NULL);

Thanks

deltabeard commented 3 months ago

Where is the code for the Raspberry Pi Pico port you are using? Links Awakening saves properly in the SDL2 example in this repository, so it's likely that the port you are using is not saving data properly or at all.

deltabeard commented 3 months ago

See also https://github.com/deltabeard/Peanut-GB/issues/100

pierreblavy2 commented 3 months ago

The emulator is here https://github.com/YouMakeTech/Pico-GB

I've changed the button mapping, so I can press all button to access the save menu I've also tried to save by dying ingame

I've replaced the YouMakeTech peanut_gb.h file with your own, and the problem is not fixed. How do we register a callback that saves/load in peanut_gb ?

pierreblavy2 commented 3 months ago

After some search I think I found the problem : the gameboy actualy doesn"t save anything is uses persistant RAM in the cartridge, and this is why I'm confused. Is there a way find which area are concerned , I can trigger the save to disk function only when battery protected cardridge ram is touched ?

I'm new to gameboy and I'm still a little bit confused.

deltabeard commented 3 months ago

Is the gb_cart_ram_write the one responsible for saving the game or is it the function doing a savestate?

gb_cart_ram_write is used when the game is trying to write to the cartridge RAM. The cartridge RAM will also be the save file, but games could also use the cartridge RAM for other purposes other than saving player progress. Usually, the cartridge RAM is written and read from very frequently, so it isn't possible to trigger a save file write to SD on each write to the cartridge RAM.

Peanut-GB does not have save state support, but other projects might just be implementing that by saving the emulator context. I don't think that Pico-GB does that.

In Pico-GB, the relevant function is write_cart_ram_file which write the cartridge RAM to SD card and is triggered by default after pressing start+select. From https://github.com/deltabeard/Peanut-GB/issues/100 it was found that start+select is used by Links Awakening to save, so the button combination clashed with what is used by default in Pico-GB. Change the button combination from start+select in Pico-GB to something else, and then check to see if it works then.

In my other project at https://github.com/deltabeard/DBGC, I used an FRAM chip to hold the current save file, and I wrote the cartridge RAM to the FRAM chip every second. Since the FRAM chip doesn't wear within 100 years, the frequency of the writes isn't an issue, but FRAM chips are a bit expensive.

This isn't an issue with Peanut-GB. Try playing another game with Pico-GB and see if saving works in that game. Is Links Awakening the only problematic game you have? The title of this bug report suggests other games have this issue too.

pierreblavy2 commented 3 months ago

Thank a lot for your answer, it's much clear.

=> I've wired more buttons, so I don't need to used key combination, and using a dedicated SAVE button seems to fix the problem : I save in game, I press SAVE, and everything seems to work.

=> I had a lot of confusion because previously save worked by chance. probably because I've triggered the start + select combination while playing game, which actually saved to the SD card.

=> I may program something that autosave every 60 seconds, when the RAM has changed, I think a SD card can handle it.

=> Works with pokemon red (I've just tried to leave the house and save).

Thank a lot for your help, I think I consider the problem fixed, I'll program the autosave latter on. Thank for your idea of using a FRAM too. I'll have a look at some datasheets.

Have a nice day