aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2012-08-06 20:03:56 +1000
committerPaul Gilbert2012-08-06 20:03:56 +1000
commit2dee92a908b84ae870bfdbfd00318549485b7984 (patch)
tree58e315841855fb19fed257bb5b8086a8fde70e29
parent5c522575c7aff4706f3fefe0d7f89272aecd2b66 (diff)
downloadscummvm-rg350-2dee92a908b84ae870bfdbfd00318549485b7984.tar.gz
scummvm-rg350-2dee92a908b84ae870bfdbfd00318549485b7984.tar.bz2
scummvm-rg350-2dee92a908b84ae870bfdbfd00318549485b7984.zip
TINSEL: Fixed portability issue with earlier savegames
-rw-r--r--engines/tinsel/dialogs.cpp14
-rw-r--r--engines/tinsel/dialogs.h2
-rw-r--r--engines/tinsel/saveload.cpp50
3 files changed, 56 insertions, 10 deletions
diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp
index dde34841cf..56ee2ea752 100644
--- a/engines/tinsel/dialogs.cpp
+++ b/engines/tinsel/dialogs.cpp
@@ -1263,6 +1263,20 @@ static INV_OBJECT *GetInvObject(int id) {
}
/**
+ * Returns true if the given id represents a valid inventory object
+ */
+bool GetIsInvObject(int id) {
+ INV_OBJECT *pObject = g_invObjects;
+
+ for (int i = 0; i < g_numObjects; i++, pObject++) {
+ if (pObject->id == id)
+ return true;
+ }
+
+ return false;
+}
+
+/**
* Convert item ID number to index.
*/
static int GetObjectIndex(int id) {
diff --git a/engines/tinsel/dialogs.h b/engines/tinsel/dialogs.h
index 8c48eb8b76..ab53ba771c 100644
--- a/engines/tinsel/dialogs.h
+++ b/engines/tinsel/dialogs.h
@@ -152,6 +152,8 @@ void InvSetLimit(int invno, int n);
void InvSetSize(int invno, int MinWidth, int MinHeight,
int StartWidth, int StartHeight, int MaxWidth, int MaxHeight);
+bool GetIsInvObject(int id);
+
int WhichInventoryOpen();
bool IsTopWindow();
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index 0a552c8c2b..518e27f02b 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -55,8 +55,7 @@ namespace Tinsel {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 1
-// TODO: Not yet used
+#define CURRENT_VER 2
/**
* An auxillary macro, used to specify savegame versions. We use this instead
@@ -97,12 +96,13 @@ struct SaveGameHeader {
TimeDate dateTime;
bool scnFlag;
byte language;
+ uint16 numInterpreters; // Savegame version 2 or later only
};
enum {
DW1_SAVEGAME_ID = 0x44575399, // = 'DWSc' = "DiscWorld 1 ScummVM"
DW2_SAVEGAME_ID = 0x44573253, // = 'DW2S' = "DiscWorld 2 ScummVM"
- SAVEGAME_HEADER_SIZE = 4 + 4 + 4 + SG_DESC_LEN + 7 + 1 + 1
+ SAVEGAME_HEADER_SIZE = 4 + 4 + 4 + SG_DESC_LEN + 7 + 1 + 1 + 2
};
#define SAVEGAME_ID (TinselV2 ? (uint32)DW2_SAVEGAME_ID : (uint32)DW1_SAVEGAME_ID)
@@ -186,6 +186,15 @@ static bool syncSaveGameHeader(Common::Serializer &s, SaveGameHeader &hdr) {
}
}
+ // Handle the number of interpreter contexts that will be saved in the savegame
+ if (tmp >= 2) {
+ tmp -= 2;
+ hdr.numInterpreters = NUM_INTERPRET;
+ s.syncAsUint16LE(hdr.numInterpreters);
+ } else {
+ hdr.numInterpreters = (TinselV2 ? 70 : 64) - 20;
+ }
+
// Skip over any extra bytes
s.skip(tmp);
return true;
@@ -262,7 +271,7 @@ static void syncSoundReel(Common::Serializer &s, SOUNDREELS &sr) {
s.syncAsSint32LE(sr.actorCol);
}
-static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd) {
+static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd, int numInterp) {
s.syncAsUint32LE(sd.SavedSceneHandle);
s.syncAsUint32LE(sd.SavedBgroundHandle);
for (int i = 0; i < MAX_MOVERS; ++i)
@@ -273,7 +282,7 @@ static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd) {
s.syncAsSint32LE(sd.NumSavedActors);
s.syncAsSint32LE(sd.SavedLoffset);
s.syncAsSint32LE(sd.SavedToffset);
- for (int i = 0; i < NUM_INTERPRET; ++i)
+ for (int i = 0; i < numInterp; ++i)
sd.SavedICInfo[i].syncWithSerializer(s);
for (int i = 0; i < MAX_POLY; ++i)
s.syncAsUint32LE(sd.SavedDeadPolys[i]);
@@ -422,7 +431,7 @@ char *ListEntry(int i, letype which) {
return NULL;
}
-static void DoSync(Common::Serializer &s) {
+static bool DoSync(Common::Serializer &s, int numInterp) {
int sg = 0;
if (TinselV2) {
@@ -434,7 +443,7 @@ static void DoSync(Common::Serializer &s) {
if (TinselV2 && s.isLoading())
HoldItem(INV_NOICON);
- syncSavedData(s, *g_srsd);
+ syncSavedData(s, *g_srsd, numInterp);
syncGlobInfo(s); // Glitter globals
syncInvInfo(s); // Inventory data
@@ -443,6 +452,10 @@ static void DoSync(Common::Serializer &s) {
sg = WhichItemHeld();
s.syncAsSint32LE(sg);
if (s.isLoading()) {
+ if (sg != -1 && !GetIsInvObject(sg))
+ // Not a valid inventory object, so return false
+ return false;
+
if (TinselV2)
g_thingHeld = sg;
else
@@ -459,7 +472,7 @@ static void DoSync(Common::Serializer &s) {
if (*g_SaveSceneSsCount != 0) {
SAVED_DATA *sdPtr = g_SaveSceneSsData;
for (int i = 0; i < *g_SaveSceneSsCount; ++i, ++sdPtr)
- syncSavedData(s, *sdPtr);
+ syncSavedData(s, *sdPtr, numInterp);
// Flag that there is a saved scene to return to. Note that in this context 'saved scene'
// is a stored scene to return to from another scene, such as from the Summoning Book close-up
@@ -469,6 +482,8 @@ static void DoSync(Common::Serializer &s) {
if (!TinselV2)
syncAllActorsAlive(s);
+
+ return true;
}
/**
@@ -487,8 +502,23 @@ static bool DoRestore() {
delete f; // Invalid header, or savegame too new -> skip it
return false;
}
+
+ // Load in the data. For older savegame versions, we potentially need to load the data twice, once
+ // for pre 1.5 savegames, and if that fails, a second time for 1.5 savegames
+ int numInterpreters = hdr.numInterpreters;
+ int32 currentPos = f->pos();
+ for (int tryNumber = 0; tryNumber < ((hdr.ver >= 2) ? 1 : 2); ++tryNumber) {
+ // If it's the second loop iteration, try with the 1.5 savegame number of interpreter contexts
+ if (tryNumber == 1) {
+ f->seek(currentPos);
+ numInterpreters = 80;
+ }
- DoSync(s);
+ // Load the savegame data
+ if (DoSync(s, numInterpreters))
+ // Data load was successful (or likely), so break out of loop
+ break;
+ }
uint32 id = f->readSint32LE();
if (id != (uint32)0xFEEDFACE)
@@ -575,7 +605,7 @@ static void DoSave() {
return;
}
- DoSync(s);
+ DoSync(s, hdr.numInterpreters);
// Write out the special Id for Discworld savegames
f->writeUint32LE(0xFEEDFACE);