SCI32: Fix loading autosaves (slot 0)

Fixes bugs in trac #11029:

- Slot 1 loading when user selects slot 0 in ScummVM UI
- Slot 1 loading when slot 0 specified on command line
- QFG4 slot 0 not appearing in game's original Restore UI
This commit is contained in:
sluicebox 2019-09-12 11:58:20 -07:00
parent 5c5130814b
commit 698ca464d7
4 changed files with 27 additions and 14 deletions

View File

@ -349,9 +349,13 @@ void listSavegames(Common::Array<SavegameDesc> &saves) {
const Common::String &filename = *iter;
#ifdef ENABLE_SCI32
const int id = strtol(filename.end() - 3, NULL, 10);
if (id == kNewGameId || id == kAutoSaveId) {
continue;
// exclude new game and autosave slots, except for QFG4,
// whose autosave should appear as a normal saved game
if (g_sci->getGameId() != GID_QFG4) {
const int id = strtol(filename.end() - 3, NULL, 10);
if (id == kNewGameId || id == kAutoSaveId) {
continue;
}
}
#endif

View File

@ -47,8 +47,11 @@ enum {
// SCI engine expects game IDs to start at 0, but slot 0 in ScummVM is
// reserved for autosave, so non-autosave games get their IDs shifted up
// when saving or restoring, and shifted down when enumerating save games
kSaveIdShift = 1
// when saving or restoring, and shifted down when enumerating save games.
// ScummVM slot 0 can't be shifted down as -1 is an illegal SCI save ID
// so it is instead wrapped around to 99 and then back to 0 when shifting up.
kSaveIdShift = 1,
kMaxShiftedSaveId = 99
};
#endif

View File

@ -698,13 +698,15 @@ int GuestAdditions::runSaveRestore(const bool isSave, reg_t outDescription, cons
description.fromString(descriptionString);
}
// The autosave slot in ScummVM takes up slot 0, but in SCI the first
// non-autosave save game number needs to be 0, so reduce the save
// number here to match what would come from the normal SCI save/restore
// dialog. Wrap slot 0 around to kMaxShiftedSaveId so that it remains
// a legal SCI value.
if (saveNo > 0) {
// The autosave slot in ScummVM takes up slot 0, but in SCI the first
// non-autosave save game number needs to be 0, so reduce the save
// number here to match what would come from the normal SCI save/restore
// dialog. There is additional special code for handling the autosave
// game inside of kRestoreGame32.
saveNo -= kSaveIdShift;
} else if (saveNo == 0) {
saveNo = kMaxShiftedSaveId;
}
return saveNo;

View File

@ -1333,6 +1333,8 @@ reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv) {
// Autosave slot 1 is a "new game" save
saveNo = kNewGameId;
}
} else if (saveNo == kMaxShiftedSaveId) {
saveNo = 0;
} else {
saveNo += kSaveIdShift;
}
@ -1394,6 +1396,8 @@ reg_t kRestoreGame32(EngineState *s, int argc, reg_t *argv) {
// Autosave slot 1 is a "new game" save
saveNo = kNewGameId;
}
} else if (saveNo == kMaxShiftedSaveId) {
saveNo = 0;
} else {
saveNo += kSaveIdShift;
}
@ -1419,13 +1423,12 @@ reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv) {
int16 saveNo = argv[1].toSint16();
const Common::String gameVersion = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
Common::Array<SavegameDesc> saves;
listSavegames(saves);
if (gameName == "Autosave" || gameName == "Autosv") {
if (saveNo == 1) {
saveNo = kNewGameId;
}
} else if (saveNo == kMaxShiftedSaveId) {
saveNo = 0;
} else {
saveNo += kSaveIdShift;
}
@ -1488,7 +1491,8 @@ reg_t kGetSaveFiles32(EngineState *s, int argc, reg_t *argv) {
// At least Phant2 requires use of strncpy, since it creates save game
// names of exactly kMaxSaveNameLength
strncpy(target, save.name, kMaxSaveNameLength);
saveIds.setFromInt16(i, save.id - kSaveIdShift);
int16 sciSaveId = (save.id == 0) ? kMaxShiftedSaveId : (save.id - kSaveIdShift);
saveIds.setFromInt16(i, sciSaveId);
}
descriptions.charAt(kMaxSaveNameLength * saves.size()) = '\0';