aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-05-12 23:35:02 -0500
committerColin Snover2017-05-13 22:46:25 -0500
commit1911b19e154b4e946d29dbf143b18cb6c9e4b660 (patch)
tree0985f13635dea33872e45082ea7a1819254e407e
parent262ef4de61727ebe6ede497f871ef858253c9956 (diff)
downloadscummvm-rg350-1911b19e154b4e946d29dbf143b18cb6c9e4b660.tar.gz
scummvm-rg350-1911b19e154b4e946d29dbf143b18cb6c9e4b660.tar.bz2
scummvm-rg350-1911b19e154b4e946d29dbf143b18cb6c9e4b660.zip
SCI32: Make sure all save game validity checks are in kCheckSaveGame32
Save game metadata validity checks in SCI32 should all exist within kCheckSaveGame32 since this allows most games to recover successfully from an attempt to load an invalid save game. If gamestate_restore fails, the game will usually crash because the engine is left in an inconsistent state (game scripts have cleaned up objects in preparation for a game load that is no longer happening).
-rw-r--r--engines/sci/engine/file.cpp2
-rw-r--r--engines/sci/engine/file.h2
-rw-r--r--engines/sci/engine/kfile.cpp15
-rw-r--r--engines/sci/engine/savegame.cpp35
4 files changed, 38 insertions, 16 deletions
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index 91cf189d0a..2128433b90 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -357,6 +357,8 @@ bool fillSavegameDesc(const Common::String &filename, SavegameDesc *desc) {
desc->time = meta.saveTime;
desc->version = meta.version;
desc->gameVersion = meta.gameVersion;
+ desc->script0Size = meta.script0Size;
+ desc->gameObjectOffset = meta.gameObjectOffset;
#ifdef ENABLE_SCI32
if (g_sci->getGameId() == GID_SHIVERS) {
desc->lowScore = meta.lowScore;
diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h
index 1c9a092063..fee628aad5 100644
--- a/engines/sci/engine/file.h
+++ b/engines/sci/engine/file.h
@@ -64,6 +64,8 @@ struct SavegameDesc {
int version;
char name[SCI_MAX_SAVENAME_LENGTH];
Common::String gameVersion;
+ uint32 script0Size;
+ uint32 gameObjectOffset;
#ifdef ENABLE_SCI32
// Used by Shivers 1
uint16 lowScore;
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index e386b1315d..fd6fab6506 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -1328,6 +1328,21 @@ reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
+ if (save.gameObjectOffset > 0 && save.script0Size > 0) {
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ assert(script0);
+
+ if (save.script0Size != script0->size()) {
+ warning("Save game was created for a game with a script 0 size of %u, but the current game script 0 size is %u", save.script0Size, script0->size());
+ return NULL_REG;
+ }
+
+ if (save.gameObjectOffset != g_sci->getGameObject().getOffset()) {
+ warning("Save game was created for a game with the main game object at offset %u, but the current main game object offset is %u", save.gameObjectOffset, g_sci->getGameObject().getOffset());
+ return NULL_REG;
+ }
+ }
+
return TRUE_REG;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 5172de3f43..dce6430946 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -1257,26 +1257,29 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
return;
}
- if ((meta.version < MINIMUM_SAVEGAME_VERSION) || (meta.version > CURRENT_SAVEGAME_VERSION)) {
- if (meta.version < MINIMUM_SAVEGAME_VERSION) {
- showScummVMDialog(_("The format of this saved game is obsolete, unable to load it"));
- } else {
- Common::String msg = Common::String::format(_("Savegame version is %d, maximum supported is %0d"), meta.version, CURRENT_SAVEGAME_VERSION);
- showScummVMDialog(msg);
- }
-
- s->r_acc = TRUE_REG; // signal failure
- return;
- }
-
- if (meta.gameObjectOffset > 0 && meta.script0Size > 0) {
- Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
- if (script0->size() != meta.script0Size || g_sci->getGameObject().getOffset() != meta.gameObjectOffset) {
- showScummVMDialog(_("This saved game was created with a different version of the game, unable to load it"));
+ // In SCI32 these checks are all in kCheckSaveGame32
+ if (getSciVersion() < SCI_VERSION_2) {
+ if ((meta.version < MINIMUM_SAVEGAME_VERSION) || (meta.version > CURRENT_SAVEGAME_VERSION)) {
+ if (meta.version < MINIMUM_SAVEGAME_VERSION) {
+ showScummVMDialog(_("The format of this saved game is obsolete, unable to load it"));
+ } else {
+ Common::String msg = Common::String::format(_("Savegame version is %d, maximum supported is %0d"), meta.version, CURRENT_SAVEGAME_VERSION);
+ showScummVMDialog(msg);
+ }
s->r_acc = TRUE_REG; // signal failure
return;
}
+
+ if (meta.gameObjectOffset > 0 && meta.script0Size > 0) {
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ if (script0->size() != meta.script0Size || g_sci->getGameObject().getOffset() != meta.gameObjectOffset) {
+ showScummVMDialog(_("This saved game was created with a different version of the game, unable to load it"));
+
+ s->r_acc = TRUE_REG; // signal failure
+ return;
+ }
+ }
}
// We don't need the thumbnail here, so just read it and discard it