[Scummvm-git-logs] scummvm branch-2-7 -> 21b72c5bc355b549e7f67e488f71d033c317411e

dwatteau noreply at scummvm.org
Sat Feb 4 17:29:05 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
21b72c5bc3 TINSEL: Handle DW2 saves that had Noir-sized SysVars


Commit: 21b72c5bc355b549e7f67e488f71d033c317411e
    https://github.com/scummvm/scummvm/commit/21b72c5bc355b549e7f67e488f71d033c317411e
Author: Einar Johan Trøan Sømåen (somaen at scummvm.org)
Date: 2023-02-04T18:20:36+01:00

Commit Message:
TINSEL: Handle DW2 saves that had Noir-sized SysVars

With this change we now once again can read pre 2.6 savegames.
Similarly savegames created after this fix will be readable by
ScummVM < 2.6.0. We will also be able to load savegames created
by ScummVM 2.6.x.

The only limitation is that since we now create the same kind
of savegames as older versions again, ScummVM 2.6.x will be
unable to load savegames created after this.

This fixes bug #13897

(cherry picked from commit 366c1e505dc174bdd88558431c6612ced665354e)

Changed paths:
    engines/tinsel/saveload.cpp
    engines/tinsel/savescn.h
    engines/tinsel/sysvar.cpp
    engines/tinsel/sysvar.h


diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index fbab7cea7e9..dd31e6f67f6 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -287,7 +287,7 @@ static void syncSoundReel(Common::Serializer &s, SOUNDREELS &sr) {
 	s.syncAsSint32LE(sr.actorCol);
 }
 
-static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd, int numInterp) {
+static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd, int numInterp, int numSystemVars) {
 	s.syncAsUint32LE(sd.SavedSceneHandle);
 	s.syncAsUint32LE(sd.SavedBgroundHandle);
 	for (int i = 0; i < MAX_MOVERS; ++i)
@@ -335,7 +335,7 @@ static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd, int numInterp)
 			s.syncAsUint32LE(sd.SavedTune[i]);
 		s.syncAsByte(sd.bTinselDim);
 		s.syncAsSint32LE(sd.SavedScrollFocus);
-		for (int i = 0; i < SV_TOPVALID; ++i)
+		for (int i = 0; i < numSystemVars; ++i)
 			s.syncAsSint32LE(sd.SavedSystemVars[i]);
 		for (int i = 0; i < MAX_SOUNDREELS; ++i)
 			syncSoundReel(s, sd.SavedSoundReels[i]);
@@ -447,7 +447,7 @@ char *ListEntry(int i, letype which) {
 		return NULL;
 }
 
-static bool DoSync(Common::Serializer &s, int numInterp) {
+static bool DoSync(Common::Serializer &s, int numInterp, int numSystemVars) {
 	int	sg = 0;
 
 	if (TinselVersion >= 2) {
@@ -459,8 +459,7 @@ static bool DoSync(Common::Serializer &s, int numInterp) {
 			_vm->_dialogs->holdItem(INV_NOICON);
 	}
 
-
-	syncSavedData(s, *g_srsd, numInterp);
+	syncSavedData(s, *g_srsd, numInterp, numSystemVars);
 	syncGlobInfo(s);		// Glitter globals
 	_vm->_dialogs->syncInvInfo(s); // Inventory data
 
@@ -489,7 +488,7 @@ static bool DoSync(Common::Serializer &s, int numInterp) {
 	if (*g_SaveSceneSsCount != 0) {
 		SAVED_DATA *sdPtr = g_SaveSceneSsData;
 		for (int i = 0; i < *g_SaveSceneSsCount; ++i, ++sdPtr)
-			syncSavedData(s, *sdPtr, numInterp);
+			syncSavedData(s, *sdPtr, numInterp, numSystemVars);
 
 		// 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
@@ -529,23 +528,52 @@ static bool DoRestore() {
 	// 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
+	int numberOfTries = ((hdr.ver >= 2) ? 1 : 2);
+	int numSystemVars = SV_TOPVALID; // Appropriate for both Noir and DW2
+	for (int tryNumber = 0; tryNumber < numberOfTries; ++tryNumber) {
 		if (tryNumber == 1) {
 			f->seek(currentPos);
-			numInterpreters = 80;
+			// If it's the second loop iteration, try with the 1.5 savegame number of interpreter contexts
+			if (hdr.ver < 2) {
+				numInterpreters = 80;
+			}
 		}
 
 		// Load the savegame data
-		if (DoSync(s, numInterpreters))
+		bool successfullSync = DoSync(s, numInterpreters, numSystemVars);
+
+		uint32 id = f->readSint32LE();
+
+		int remaining = f->size() - f->pos();
+		// BUG #13897: Older savegames won't run on ScummVM 2.6.x
+		// The reason being that the system vars for Noir were added increasing the SV_TOPVALID value,
+		// which also affected DW2 unintentionally, creating some v3 savegames that had additional data
+		// stored there. To properly load these savegames, we'll have to try again, with the knowledge
+		// that we have to skip this data.
+		if (hdr.id == DW2_SAVEGAME_ID && hdr.ver == 3 && remaining != 0) {
+			if (tryNumber == 0) {
+				numberOfTries++;
+				// Make the second attempt read the Noir amount of sys-vars, so that the problematic
+				// savegames can be loaded.
+				numSystemVars = SV_TOPVALID_T3;
+			}
+			continue;
+		}
+
+		if (successfullSync) {
+			if (id != (uint32)0xFEEDFACE) {
+				error("Incompatible saved game");
+			}
+
 			// Data load was successful (or likely), so break out of loop
 			break;
+		}
 	}
 
-	uint32 id = f->readSint32LE();
-	if (id != (uint32)0xFEEDFACE)
-		error("Incompatible saved game");
-
+	int remainingBytes = f->size() - f->pos();
+	if (remainingBytes != 0) {
+		error("%d bytes of savegame not read", remainingBytes);
+	}
 	bool failed = (f->eos() || f->err());
 
 	delete f;
@@ -628,7 +656,7 @@ static void DoSave() {
 		return;
 	}
 
-	DoSync(s, hdr.numInterpreters);
+	DoSync(s, hdr.numInterpreters, SV_TOPVALID);
 
 	// Write out the special Id for Discworld savegames
 	f->writeUint32LE(0xFEEDFACE);
diff --git a/engines/tinsel/savescn.h b/engines/tinsel/savescn.h
index b8abe61f78a..66030e22ee4 100644
--- a/engines/tinsel/savescn.h
+++ b/engines/tinsel/savescn.h
@@ -59,7 +59,7 @@ struct SAVED_DATA {
 	uint32		SavedTune[3];			// Music
 	bool		bTinselDim;
 	int			SavedScrollFocus;
-	int			SavedSystemVars[SV_TOPVALID];
+	int			SavedSystemVars[SV_TOPVALID_T3];
 	SOUNDREELS	SavedSoundReels[MAX_SOUNDREELS];
 };
 
diff --git a/engines/tinsel/sysvar.cpp b/engines/tinsel/sysvar.cpp
index fe707386751..2041e644ea5 100644
--- a/engines/tinsel/sysvar.cpp
+++ b/engines/tinsel/sysvar.cpp
@@ -42,7 +42,7 @@ extern int NewestSavedGame();
 
 // These vars are reset upon engine destruction
 
-static int g_systemVars[SV_TOPVALID];
+static int g_systemVars[SV_TOPVALID_T3];
 static SCNHANDLE g_systemStrings[SS_MAX_VALID];
 
 //----------------- FUNCTIONS --------------------------------
@@ -57,7 +57,7 @@ void ResetVarsSysVar() {
  */
 
 void InitSysVars() {
-	int initialSystemVars[SV_TOPVALID] = {
+	int initialSystemVars[SV_TOPVALID_T3] = {
 	    INV_1, // Default inventory
 
 	    10,  // Y-offset of Conversation(TOP)
diff --git a/engines/tinsel/sysvar.h b/engines/tinsel/sysvar.h
index efcbfa54ed6..0c99bfadffc 100644
--- a/engines/tinsel/sysvar.h
+++ b/engines/tinsel/sysvar.h
@@ -83,6 +83,8 @@ typedef enum {	SV_DEFAULT_INV,
 		ISV_GHOST_BASE_T2 = 0x2B,
 		ISV_GHOST_COLOR_T2 = 0x2C,
 
+		SV_TOPVALID_T2 = 0x2D,
+
 		SV_SPRITER_SCENE_ID = 0x2F, // Noir, loaded scene
 		ISV_DIVERT_ACTOR_T3 = 0x32,
 		ISV_NO_BLOCKING_T3 = 0x33,
@@ -92,13 +94,14 @@ typedef enum {	SV_DEFAULT_INV,
 		SV_SPRITER_SCALE = 0x37, // Noir, scale used for 3D rendering
 		SV_SPRITER_OVERLAY = 0x38, // Noir, if additional model is loaded
 
-		SV_TOPVALID } SYSVARS;
+		SV_TOPVALID_T3 } SYSVARS;
 
 #define ISV_DIVERT_ACTOR ((TinselVersion == 3) ? ISV_DIVERT_ACTOR_T3 : ISV_DIVERT_ACTOR_T2)
 #define ISV_NO_BLOCKING ((TinselVersion == 3) ? ISV_NO_BLOCKING_T3 : ISV_NO_BLOCKING_T2)
 #define ISV_GHOST_ACTOR ((TinselVersion == 3) ? ISV_GHOST_ACTOR_T3 : ISV_GHOST_ACTOR_T2)
 #define ISV_GHOST_BASE ((TinselVersion == 3) ? ISV_GHOST_BASE_T3 : ISV_GHOST_BASE_T2)
 #define ISV_GHOST_COLOR ((TinselVersion == 3) ? ISV_GHOST_COLOR_T3 : ISV_GHOST_COLOR_T2)
+#define SV_TOPVALID ((TinselVersion == 3) ? SV_TOPVALID_T3 : SV_TOPVALID_T2)
 
 typedef enum {
 




More information about the Scummvm-git-logs mailing list