Add compressed combined save format for PSP and Dolphin
Memory sticks/cards don't suit N+1 separate save files the way Linux's filesystem does, so add an opt-in SAVE_DEVICE_DATA_RAW mode: settings and all save slots get serialized to JSON, concatenated, zlib-compressed, and framed with a magic/version/checksum/generation header, then read/written as a single blob through one combined platform hook instead of four. - PSP and Dolphin's SD/NAND backends write via a temp file + atomic rename, so a crash mid-write can never leave a half-written save behind. - GameCube memory cards have no rename or resize primitive, so they ping-pong between two fixed files instead, picking whichever is valid and has the higher generation counter on load. - Linux is untouched (still four separate JSON files); saveslot.h/ savesettings.h drop their now-unnecessary pack(1) now that nothing persists them as raw bytes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,20 @@
|
||||
#define SAVE_DEVICE_DOLPHIN_GAME_CODE "DUSK"
|
||||
#endif
|
||||
|
||||
// Memory cards have no rename primitive and files can't be resized once
|
||||
// created, so a single "current" file can't be replaced atomically the way
|
||||
// the other backends do. Instead saveDeviceDolphinCardDataWrite() ping-pongs
|
||||
// between these two fixed files - every store targets whichever one is NOT
|
||||
// the currently valid+newest copy (by saveDeviceRawIsValid()'s generation
|
||||
// counter), so a crash mid-write can only ever corrupt the copy nobody
|
||||
// would load from; the other one stays intact as the fallback.
|
||||
#ifndef SAVE_DEVICE_DOLPHIN_CARD_FILENAME_0
|
||||
#define SAVE_DEVICE_DOLPHIN_CARD_FILENAME_0 "DUSKSAVE0"
|
||||
#endif
|
||||
#ifndef SAVE_DEVICE_DOLPHIN_CARD_FILENAME_1
|
||||
#define SAVE_DEVICE_DOLPHIN_CARD_FILENAME_1 "DUSKSAVE1"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// Set from this device's index into SAVE.devices - device 0 is
|
||||
// CARD_SLOTA, device 1 is CARD_SLOTB.
|
||||
@@ -82,3 +96,38 @@ bool_t saveDeviceDolphinCardHasFreeSpace(const int32_t channel);
|
||||
* @return Error state if any.
|
||||
*/
|
||||
errorret_t saveDeviceDolphinCardDispose(savedevice_t *device);
|
||||
|
||||
/**
|
||||
* Writes the combined save data blob out to whichever of the two fixed
|
||||
* card files (see SAVE_DEVICE_DOLPHIN_CARD_FILENAME_0/1 above) is not
|
||||
* currently the valid+newest copy - ping-pong in place of the atomic
|
||||
* rename the other backends use, since the CARD API has neither a rename
|
||||
* nor a way to resize an existing file.
|
||||
*
|
||||
* @param device The save device to write to.
|
||||
* @param buffer The raw bytes to write.
|
||||
* @param size The number of bytes to write.
|
||||
* @return Error state if any.
|
||||
*/
|
||||
errorret_t saveDeviceDolphinCardDataWrite(
|
||||
savedevice_t *device,
|
||||
const uint8_t *buffer,
|
||||
size_t size
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads whichever of the two fixed card files is valid and has the higher
|
||||
* generation counter. If neither file exists or validates, this is not an
|
||||
* error - *outBuffer is set to NULL and *outSize to 0.
|
||||
*
|
||||
* @param device The save device to read from.
|
||||
* @param outBuffer Receives a memoryAlign'd (32-byte) buffer the caller
|
||||
* must free with memoryFree, or NULL if nothing has been saved yet.
|
||||
* @param outSize Receives the number of bytes in *outBuffer.
|
||||
* @return Error state if any.
|
||||
*/
|
||||
errorret_t saveDeviceDolphinCardDataRead(
|
||||
savedevice_t *device,
|
||||
uint8_t **outBuffer,
|
||||
size_t *outSize
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user