Do not save partial savefile on first boot (fixes #583)

With the implementation of save file deletion, I refactored
savefileNew() to re-use the common save file deletion code.

However, savefileDeleteGame() has the side effect of writing
the save back to SRAM. Since the rest of savefileNew() does
not write to SRAM, this means that on first boot it was
possible to get a partially-written save file if the game
was powered off before the first real save (some options had
zero/null values).

To fix this, I created a helper function to update a save file
in memory without writing it back to SRAM. This has the added
benefit of not unnecessarily re-ordering the slots in savefileNew().

I chose not to add a savefileSave() to the end of savefileNew()
since it is called from savefileLoad(), and saving while loading
doesn't seem intuitive. I also don't think it's a good idea to save
in the middle of initialization, in case a user is able to cut
power at the (im)perfect time. The operation should be atomic.
This commit is contained in:
Matt Penny 2024-01-07 14:03:31 -05:00
parent 8d7d047415
commit 3d5b1b860f

View file

@ -77,6 +77,12 @@ int savefileSramLoad(void* sramAddr, void* ramAddr, int size) {
return 1;
}
static void savefileUpdateSlot(int slotIndex, unsigned char testChamber, unsigned char subjectNumber, unsigned char slotOrder) {
gSaveData.saveSlotMetadata[slotIndex].testChamber = testChamber;
gSaveData.saveSlotMetadata[slotIndex].testSubjectNumber = subjectNumber;
gSaveData.saveSlotMetadata[slotIndex].saveSlotOrder = slotOrder;
}
void savefileNew() {
zeroMemory(&gSaveData, sizeof(gSaveData));
gSaveData.header.header = SAVEFILE_HEADER;
@ -85,7 +91,7 @@ void savefileNew() {
gSaveData.header.flags = 0;
for (int i = 0; i < MAX_SAVE_SLOTS; ++i) {
savefileDeleteGame(i);
savefileUpdateSlot(i, NO_TEST_CHAMBER, 0xFF, 0xFF);
}
controllerSetDefaultSource();
@ -162,9 +168,7 @@ void savefileDeleteGame(int slotIndex) {
}
}
gSaveData.saveSlotMetadata[slotIndex].testChamber = NO_TEST_CHAMBER;
gSaveData.saveSlotMetadata[slotIndex].testSubjectNumber = 0xFF;
gSaveData.saveSlotMetadata[slotIndex].saveSlotOrder = 0xFF;
savefileUpdateSlot(slotIndex, NO_TEST_CHAMBER, 0xFF, 0xFF);
savefileSave();
}
@ -184,9 +188,7 @@ void savefileSaveGame(Checkpoint checkpoint, u16* screenshot, int testChamberDis
}
}
gSaveData.saveSlotMetadata[slotIndex].testChamber = testChamberDisplayNumber;
gSaveData.saveSlotMetadata[slotIndex].testSubjectNumber = subjectNumber;
gSaveData.saveSlotMetadata[slotIndex].saveSlotOrder = 0;
savefileUpdateSlot(slotIndex, testChamberDisplayNumber, subjectNumber, 0);
savefileSave();
}