libretro / libretro-cap32

caprice32 4.2.0 libretro
21 stars 34 forks source link

[enhancement] SRAM DSK support #111

Closed DSkywalk closed 8 months ago

DSkywalk commented 2 years ago

SRAM disk save support

@Jamiras: If a game has in-game save support, that must be managed by the libretro SRAM interface. Modifying the original files will cause the hashing algorithm to no longer be able to identify the game on subsequent loads.

Requeriments:

Snapouille commented 1 year ago

@DSkywalk: do you manage to use the in-game save? I tried with Shadow of Sergoth (quit and save) and "Superpix" (logically autosave) and the both doesn't work.

I try these saves to go with the retroachievements hardcore mode.

DSkywalk commented 1 year ago

@Snapouille As you can see since this is an ISSUE/Enhancement it is something that needs to be programmed :wink:

Snapouille commented 1 year ago

@DSkywalk anything new about that issue?

DSkywalk commented 8 months ago

WIP

I don't know if it is a requirement to use retro_get_memory_size/retro_get_memory_data, because it is a DSK and those are changes to a floppy (or some floppys) I think is too complex for a single memory buffer. Is it necessary to use these functions for the achievements, or is the requirement just to not modify the original DSKs?

Play a game and saving to DSK:

[INFO] [slots::dsk_diff] HEAD [tracks 40, sides 1]
[DEBUG] [slots::dsk_diff_track] [18/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 18/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_track] [21/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 21/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_track] [22/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 22/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_track] [27/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 27/40, side 0/0, sectors: 15, size: 3840
[INFO] [slots::dsk_diff] DSK diff Saved: /.../.config/retroarch/saves/game.dsk.sav

Reopen RA and Reload game DSK:

[INFO] [slots::dsk_diff_load] Loading DSK changes saved at: /.../.config/retroarch/saves/game.dsk.sav
[DEBUG] [slots::dsk_diff_load] track: 18/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_load] track: 21/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_load] track: 22/40, side 0/0, sectors: 15, size: 3840
[DEBUG] [slots::dsk_diff_load] track: 27/40, side 0/0, sectors: 15, size: 3840

A better visual test using AMSDOS/BASIC DSK: 1 - basic test DSK: imagen

2 - Create a simple program and save to DSK imagen

3 - New Catalogue: imagen

Closing RA:

[INFO] [slots::dsk_diff] HEAD [tracks 40, sides 1]
[DEBUG] [slots::dsk_diff_track] [0/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 0/40, side 0/0, sectors: 9, size: 4608
[DEBUG] [slots::dsk_diff_track] [4/0] Data changed.
[DEBUG] [slots::dsk_diff] track: 4/40, side 0/0, sectors: 9, size: 4608
[INFO] [slots::dsk_diff] DSK changes saved: /.../.config/retroarch/saves/mode3tst.dsk.sav

Reopen RA:

[libretro INFO] [computer_load_file] Disk (1) inserted into drive A: ../assets/DISKS/mode3tst.dsk
[INFO] [slots::dsk_diff_load] Loading DSK changes saved at: /.../.config/retroarch/saves/mode3tst.dsk.sav
[DEBUG] [slots::dsk_diff_load] track: 0/40, side 0/0, sectors: 9, size: 4608
[DEBUG] [slots::dsk_diff_load] track: 4/40, side 0/0, sectors: 9, size: 4608

imagen

DSkywalk commented 8 months ago

@Snapouille @Jamiras :eyes:

Jamiras commented 8 months ago

Is it necessary to use these functions for the achievements, or is the requirement just to not modify the original DSKs?

Just to not modify the original files. We hash the game files when they're loaded to ensure the player isn't using a modified version of the game (hacked code, trainer, etc) or an incompatible version (memory may shift between releases). If saving to the disk modifies the file, we can't tell that it's because the user saved to the disk and assume they're using a bad version of the game.

The libretro SRAM interface is designed for managing volatile data between sessions. Technically, you don't have to use it - you could put the modified files somewhere else. But using the SRAM interface lets the frontend manage where the persistent files get stored.

It looks like you're writing files directly to the libretro save directory:

[INFO] [slots::dsk_diff] DSK diff Saved: /.../.config/retroarch/saves/game.dsk.sav

I imagine this should work, but I don't know enough about how libretro manages it directories to know when the directory will be created, or what permissions it will have across the ecosystem of operating systems RetroArch suppports.

Jamiras commented 8 months ago

I don't know if it is a requirement to use retro_get_memory_size/retro_get_memory_data, because it is a DSK and those are changes to a floppy (or some floppys) I think is too complex for a single memory buffer.

The simplest solution is just to return a buffer large enough to hold the entire disk and just dump the whole disk into the buffer. There's probably some ways to optimize that so it only captures the disk when it's been modified, but I'm less certain about how the data gets passed back in to the core - if the buffer size needs to be big enough to hold a fully modified disk, it becomes pointless to even check if the disk is modified before flushing it through the SRAM API.

DSkywalk commented 8 months ago

Yes, the SRAM system is designed for simple memories and that is why I created a custom DSK-DIFF system. We have access to the path where the user saves his games, in the case of the example I have it configured in a different path to where the ROMs are.

Anyway if your requirement is not to modify the original file, then I can pass the new feature to the cleaning phase and final testing. Thank you very much!!! :+1:

DSkywalk commented 8 months ago

Testing with Shadows of Sergoth imagen