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>
Deadzone (and future prefs like locale) now live in their own
settingsfile_t/settings.c, loaded eagerly at boot and saved immediately
on Apply, instead of inside savefile_t - a setting shouldn't reset or
diverge just because the player is on a different save slot, and this
also fixes settings changes not actually reaching disk until the next
full game Save.
PSP settings use a new plain sceIo path rather than sceUtilitySavedata,
since that dialog would flash its native icon on every settings tweak.
GameCube reuses the save system's existing memory card mount rather than
mounting it twice (settingsInit() now runs after saveInit()).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds three new pieces of save-file state, all following the same shape:
the save file is the single source of truth, not a separate live runtime
copy that gets synced in/out.
- globalitemstore.h/.c: per-global-entity-ID "collected" flags
(savefile_t.globalItemCollected), so a global item entity's init
callback can check whether it was already picked up in a prior session
without needing to keep the entity itself alive to remember that.
- Gamepad deadzone: removed input_t.deadzone entirely. The setting UI and
every platform's actual deadzone-applying code (inputGetDeadzoneDolphin/
SDL2, previously hardcoded per-platform literals that the settings menu
didn't actually affect) now read savefile_t.deadzone directly via
saveGet(SAVE_ACTIVE_SLOT). Default lives in savefile.h
(SAVE_DEADZONE_DEFAULT), stamped onto every slot in saveInit().
- Story flags: STORY_FLAG_VALUES (a live, codegen-initialized array) is
replaced by savefile_t.storyFlags, read/written via the existing
storyFlagGet()/storyFlagSet() call sites (now macros/functions over the
active save file instead of a separate array). tools/story.py now
generates STORY_FLAG_DEFAULTS (const) instead; storyFlagInitDefaults()
stamps those onto a save the first time it's used (file->exists false),
called from rpgInit().
Added SAVE_ACTIVE_SLOT (0) to savefile.h as the one shared "which slot is
actually being played" constant, replacing three different local/implicit
0s (uigamemenu.c, rpg.c, and now the settings/input call sites).
Verified round-trip on Linux (all three together in one save/load cycle);
both Linux and PSP build clean.