Renames savefile_t to saveslot_t and folds last session's standalone
settings.h/.c module back in as savemeta_t, so there's one save system
(SAVE.slots[] + SAVE.meta) instead of two parallel ones - while letting
each platform pick its own physical format for the two concepts:
- Linux now writes human-editable JSON (slot0.json, settings.json, ...)
via yyjson's mutable writer API, so players can hand-fix a bad setting.
- PSP folds meta into the same sceUtilitySavedata binary payload as its
one save slot (SAVE_SLOT_COUNT_MAX=1 there - a future save picker will
let players manage multiple named saves via the OS's own browser).
- GameCube consolidates the 3 per-slot memory card files and the separate
settings file into one combined card file.
Also fixes two bugs surfaced while building this: the CRC finalize step
seeked to a hardcoded offset (only safe for one section per file, breaks
once meta+slots share a buffer), and save.c's async/sync dispatch left an
unconditional fallback call that doesn't exist on PSP-only platforms.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Fixed the actual reason saving never worked on any platform: saveWrite()
never stamped file->header/file->version before serializing, so every
written save file had a zeroed magic header and failed its own
validation on the next load. Confirmed via a manual write/load round
trip that this alone fully explains "saving doesn't work."
- Re-enabled saveInit()/saveDispose() in engine.c (previously commented out
under "Temporarily disable save code").
- Added SAVE.available + saveIsAvailable(), refreshed by every real
save/load/delete attempt. saveInit() no longer treats an unreachable
save medium as fatal to booting - it logs and continues, since a missing
memory card/stick shouldn't prevent playing.
- Hardened PSP's saveInitPSP() to actually detect a missing memory stick
(sceIoGetstat on ms0:/) instead of assuming success, and fixed
single-level sceIoMkdir to build the full PSP/SAVEDATA directory chain.
- Added busy-retry (CARD_ERROR_BUSY) and a not-mounted guard to Dolphin's
live savestreamdolphin.c path, extending the same handling already
backported into savedolphin.c.
- Added a "Save" entry to the game menu wired to saveWrite(0), showing a
clear message on success, on failure, and when saveIsAvailable() is false.