[Scummvm-git-logs] scummvm master -> 82a16d71a9633e41b338473bc90c96245e0b0725

bluegr noreply at scummvm.org
Sun May 22 08:20:45 UTC 2022


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:
82a16d71a9 SCI: Add debugging commands for Game Flags


Commit: 82a16d71a9633e41b338473bc90c96245e0b0725
    https://github.com/scummvm/scummvm/commit/82a16d71a9633e41b338473bc90c96245e0b0725
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-05-22T11:20:41+03:00

Commit Message:
SCI: Add debugging commands for Game Flags

Changed paths:
    engines/sci/console.cpp
    engines/sci/console.h
    engines/sci/engine/features.cpp
    engines/sci/engine/features.h


diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 7041328da84..6af90adf3b6 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -75,7 +75,8 @@ bool g_debug_track_mouse_clicks = false;
 static int parse_reg_t(EngineState *s, const char *str, reg_t *dest);
 
 Console::Console(SciEngine *engine) : GUI::Debugger(),
-	_engine(engine), _debugState(engine->_debugState), _videoFrameDelay(0) {
+	_engine(engine), _debugState(engine->_debugState), _videoFrameDelay(0),
+	_gameFlagsGlobal(_engine->_features->getGameFlagsGlobal()) {
 
 	assert(_engine);
 	assert(_engine->_gamestate);
@@ -202,6 +203,13 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
 	registerCmd("go",					WRAP_METHOD(Console, cmdGo));
 	registerCmd("logkernel",          WRAP_METHOD(Console, cmdLogKernel));
 	registerCmd("vocab994",          WRAP_METHOD(Console, cmdMapVocab994));
+	registerCmd("gameflags_init",    WRAP_METHOD(Console, cmdGameFlagsInit));
+	registerCmd("gameflags_test",    WRAP_METHOD(Console, cmdGameFlagsTest));
+	registerCmd("tf",                WRAP_METHOD(Console, cmdGameFlagsTest));
+	registerCmd("gameflags_set",     WRAP_METHOD(Console, cmdGameFlagsSet));
+	registerCmd("sf",                WRAP_METHOD(Console, cmdGameFlagsSet));
+	registerCmd("gameflags_clear",   WRAP_METHOD(Console, cmdGameFlagsClear));
+	registerCmd("cf",                WRAP_METHOD(Console, cmdGameFlagsClear));
 	// Breakpoints
 	registerCmd("bp_list",			WRAP_METHOD(Console, cmdBreakpointList));
 	registerCmd("bplist",				WRAP_METHOD(Console, cmdBreakpointList));			// alias
@@ -419,6 +427,10 @@ bool Console::cmdHelp(int argc, const char **argv) {
 	debugPrintf(" send - Sends a message to an object\n");
 	debugPrintf(" go - Executes the script\n");
 	debugPrintf(" logkernel - Logs kernel calls\n");
+	debugPrintf(" gameflags_init - Initialize gameflag commands if necessary\n");
+	debugPrintf(" gameflags_test / tf - Test game flags\n");
+	debugPrintf(" gameflags_set / sf - Sets game flags\n");
+	debugPrintf(" gameflags_clear / cf - Clears game flags\n");
 	debugPrintf("\n");
 	debugPrintf("Breakpoints:\n");
 	debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
@@ -4561,6 +4573,100 @@ bool Console::cmdMapVocab994(int argc, const char **argv) {
 
 	return true;
 }
+
+bool Console::cmdGameFlagsInit(int argc, const char **argv) {
+	if (argc == 2) {
+		_gameFlagsGlobal = atoi(argv[1]);
+	} else {
+		debugPrintf("Sets the game flags global for tf / sf / cf commands\n");
+		debugPrintf("Usage: %s global_number\n", argv[0]);
+	}
+	Common::String gameFlagGlobalString = "not set";
+	if (_gameFlagsGlobal != 0) {
+		gameFlagGlobalString = Common::String::format("%d", _gameFlagsGlobal);
+	}
+	debugPrintf("Base game flag global is %s\n", gameFlagGlobalString.c_str());
+	return true;
+}
+
+bool Console::cmdGameFlagsTest(int argc, const char **argv) {
+	return processGameFlagsOperation(kGameFlagsTest, argc, argv);
+}
+
+bool Console::cmdGameFlagsSet(int argc, const char **argv) {
+	return processGameFlagsOperation(kGameFlagsSet, argc, argv);
+}
+
+bool Console::cmdGameFlagsClear(int argc, const char **argv) {
+	return processGameFlagsOperation(kGameFlagsClear, argc, argv);
+}
+
+bool Console::processGameFlagsOperation(GameFlagsOperation op, int argc, const char **argv) {
+	if (_gameFlagsGlobal == 0) {
+		debugPrintf("Use gameflags_init to set game flags global\n");
+		return true;
+	}
+
+	if (argc == 1) {
+		const char *opVerb;
+		if (op == kGameFlagsTest) {
+			opVerb = "Tests";
+		} else if (op == kGameFlagsSet) {
+			opVerb = "Sets";
+		} else {
+			opVerb = "Clears";
+		}
+		debugPrintf("%s game flags\n", opVerb);
+		debugPrintf("Usage: %s flag [flag ...]\n", argv[0]);
+		return true;
+	}
+
+	EngineState *s = _engine->_gamestate;
+	for (int i = 1; i < argc; ++i) {
+		int flagNumber;
+		if (!parseInteger(argv[i], flagNumber) || flagNumber < 0) {
+			debugPrintf("Invalid flag: %s\n", argv[i]);
+			continue;
+		}
+		// read the global that contains the flag
+		uint16 globalNumber = _gameFlagsGlobal + (flagNumber / 16);
+		if (globalNumber > s->variablesMax[VAR_GLOBAL]) {
+			debugPrintf("Invalid flag: %d (global var %d is out of range)\n", flagNumber, globalNumber);
+			continue;
+		}
+		reg_t *globalReg = &s->variables[VAR_GLOBAL][globalNumber];
+		if (!globalReg->isNumber()) {
+			debugPrintf("Invalid flag: %d (global var %d is not a number)\n", flagNumber, globalNumber);
+			continue;
+		}
+		uint16 globalValue = globalReg->toUint16();
+		uint16 flagMask = 0x8000 >> (flagNumber % 16);
+		
+		// set or clear the flag
+		bool already = false;
+		if (op == kGameFlagsSet) {
+			if ((globalValue & flagMask)) {
+				already = true;
+			} else {
+				globalValue |= flagMask;
+				globalReg->setOffset(globalValue);
+			}
+		} else if (op == kGameFlagsClear) {
+			if (!(globalValue & flagMask)) {
+				already = true;
+			} else {
+				globalValue &= ~flagMask;
+				globalReg->setOffset(globalValue);
+			}
+		}
+		
+		const char *result = (globalValue & flagMask) ? "set" : "clear";
+		debugPrintf("Flag %d is %s%s (global var %d, flag %04x)\n",
+					flagNumber, already ? "already " : "", result, globalNumber, flagMask);
+	}
+	return true;
+}
+
 bool Console::cmdQuit(int argc, const char **argv) {
 	if (argc != 2) {
 	}
diff --git a/engines/sci/console.h b/engines/sci/console.h
index cf90a4785ac..6772768b485 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -146,6 +146,10 @@ private:
 	bool cmdGo(int argc, const char **argv);
 	bool cmdLogKernel(int argc, const char **argv);
 	bool cmdMapVocab994(int argc, const char **argv);
+	bool cmdGameFlagsInit(int argc, const char **argv);
+	bool cmdGameFlagsTest(int argc, const char **argv);
+	bool cmdGameFlagsSet(int argc, const char **argv);
+	bool cmdGameFlagsClear(int argc, const char **argv);
 	// Breakpoints
 	bool cmdBreakpointList(int argc, const char **argv);
 	bool cmdBreakpointDelete(int argc, const char **argv);
@@ -200,11 +204,19 @@ private:
 #endif
 
 	void writeIntegrityDumpLine(const Common::String &statusName, const Common::String &resourceName, Common::WriteStream &out, Common::ReadStream *const data, const int size, const bool writeHash);
+	
+	enum GameFlagsOperation {
+		kGameFlagsTest,
+		kGameFlagsSet,
+		kGameFlagsClear
+	};
+	bool processGameFlagsOperation(GameFlagsOperation operation, int argc, const char **argv);
 
 	SciEngine *_engine;
 	DebugState &_debugState;
 	Common::String _videoFile;
 	int _videoFrameDelay;
+	uint16 _gameFlagsGlobal;
 };
 
 } // End of namespace Sci
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index ff48352881d..5e02bb34d6c 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -893,4 +893,57 @@ bool GameFeatures::canSaveFromGMM() const {
 	}
 }
 
+uint16 GameFeatures::getGameFlagsGlobal() const {
+	Common::Platform platform = g_sci->getPlatform();
+	bool isCD = g_sci->isCD();
+	switch (g_sci->getGameId()) {
+	case GID_CAMELOT: return 250;
+	case GID_CASTLEBRAIN: return 250;
+	case GID_ECOQUEST: return isCD ? 152 : 150;
+	case GID_ECOQUEST2: return 110;
+	case GID_FAIRYTALES: return 250;
+	case GID_FREDDYPHARKAS: return 186;
+	case GID_GK1: return 127;
+	case GID_GK2: return 150;
+	// ICEMAN uses object properties
+	case GID_ISLANDBRAIN: return 250;
+	case GID_LAURABOW: return 440;
+	case GID_LAURABOW2: return 186;
+	case GID_KQ1: return 150;
+	// KQ4 has no flags
+	case GID_KQ5: return 129;
+	case GID_KQ6: return 137;
+	case GID_KQ7: return 127;
+	case GID_LIGHTHOUSE: return 116;
+	case GID_LONGBOW: return 200;
+	case GID_LSL1: return 111;
+	// LSL2 has no flags
+	case GID_LSL3: return 111;
+	case GID_LSL5: return 186;
+	case GID_LSL6: return 137;
+	// LSL6HIRES uses a flags object
+	case GID_PEPPER: return 134;
+	case GID_PHANTASMAGORIA: return 250;
+	case GID_PHANTASMAGORIA2: return 101;
+	case GID_PQ1: return 134;
+	case GID_PQ2: return (platform != Common::kPlatformPC98) ? 250 : 245;
+	case GID_PQ3: return 165;
+	// PQ4 uses object properties
+	case GID_PQSWAT: return 150;
+	case GID_QFG1: return 350;
+	case GID_QFG1VGA: return 290;
+	case GID_QFG2: return 700;
+	case GID_QFG3: return 500;
+	case GID_QFG4: return 500;
+	case GID_RAMA: return 300;
+	case GID_SHIVERS: return 209;
+	case GID_SQ1: return 118;
+	case GID_SQ4: return 114;
+	case GID_SQ5: return 183;
+	case GID_SQ6: return 250;
+	// TORIN uses a flags object
+	default: return 0;
+	}
+}
+
 } // End of namespace Sci
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 24404cdc53d..ce9b12b3ff6 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -281,6 +281,14 @@ public:
 	 * games which don't follow the normal saving scheme.
 	*/
 	bool canSaveFromGMM() const;
+	
+	/**
+	 * Returns the global variable index to the start of the game's
+	 * global flags array. This is used by the console debugger.
+	 *
+	 * @return Non-zero index if successful, otherwise zero.
+	 */
+	uint16 getGameFlagsGlobal() const;
 
 private:
 	reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1);




More information about the Scummvm-git-logs mailing list