[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