From 798db14bb5a74ce38b017b12373a74d8da409ca9 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 8 Sep 2026 12:49:20 -0500 Subject: [PATCH] Recover from a corrupt or version-mismatched save file instead of crashing saveLoadSettings()/saveLoadSlot() previously let a read failure (e.g. a version mismatch from the new schema check) propagate all the way up through saveUpdate()/engineUpdate() to main(), which just prints the error and exits - taking down the whole game over one bad file. Both now catch the failure, log it, and fall back to init defaults instead, matching the existing "no file yet" convention. --- src/dusk/save/save.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/dusk/save/save.c b/src/dusk/save/save.c index 4586b0af..bc7ae1ce 100644 --- a/src/dusk/save/save.c +++ b/src/dusk/save/save.c @@ -9,6 +9,7 @@ #include "util/memory.h" #include "assert/assert.h" #include "rpg/cutscene/cutscenesystem.h" +#include "console/console.h" save_t SAVE; @@ -186,10 +187,18 @@ errorret_t saveSaveSettings() { errorret_t saveLoadSettings() { assertTrue(SAVE.deviceCurrent != 0xFF, "No current device"); - errorChain(saveDeviceSettingsRead( + errorret_t ret = saveDeviceSettingsRead( &SAVE.devices[SAVE.deviceCurrent], &SAVE.settings - )); + ); + if(errorIsNotOk(ret)) { + // Corrupt or incompatible (e.g. wrong/missing schema version) settings + // file - don't take the whole game down over it, just reset to + // defaults and carry on. + errorCatch(errorPrint(ret)); + consolePrint("Settings file could not be loaded, resetting to defaults.\n"); + saveSettingsInit(&SAVE.settings); + } SAVE.settingsDirty = false; errorOk(); @@ -222,12 +231,24 @@ errorret_t saveLoadSlot() { errorOk(); } - errorChain(saveDeviceSlotRead( + errorret_t ret = saveDeviceSlotRead( &SAVE.devices[SAVE.deviceCurrent], &SAVE.slot, SAVE.slotCurrent - )); - + ); + if(errorIsNotOk(ret)) { + // Corrupt or incompatible (e.g. wrong/missing schema version) slot + // file - don't take the whole game down over it, treat it the same as + // an empty/unused slot. + errorCatch(errorPrint(ret)); + consolePrint( + "Save slot %u could not be loaded, treating as empty.\n", + (uint32_t)SAVE.slotCurrent + ); + saveSlotInit(&SAVE.slot); + } + + // Update cache SAVE.caches[SAVE.slotCurrent] = SAVE.slot.cachedData; SAVE.slotDirty = false;