aboutsummaryrefslogtreecommitdiff
path: root/engines/agi/console.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agi/console.cpp')
-rw-r--r--engines/agi/console.cpp423
1 files changed, 400 insertions, 23 deletions
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index 6d7f9384cd..9a4a357b44 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -22,6 +22,7 @@
#include "agi/agi.h"
#include "agi/opcodes.h"
+#include "agi/graphics.h"
#include "agi/preagi.h"
#include "agi/preagi_mickey.h"
@@ -32,22 +33,28 @@ namespace Agi {
Console::Console(AgiEngine *vm) : GUI::Debugger() {
_vm = vm;
- registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug));
- registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont));
- registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver));
- registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags));
- registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0));
- registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs));
- registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
- registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode));
- registerCmd("step", WRAP_METHOD(Console, Cmd_Step));
- registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger));
- registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars));
- registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar));
- registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
- registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj));
- registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
- registerCmd("bt", WRAP_METHOD(Console, Cmd_BT));
+ registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug));
+ registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont));
+ registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver));
+ registerCmd("version", WRAP_METHOD(Console, Cmd_Version));
+ registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags));
+ registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0));
+ registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs));
+ registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
+ registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode));
+ registerCmd("step", WRAP_METHOD(Console, Cmd_Step));
+ registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger));
+ registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars));
+ registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar));
+ registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
+ registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj));
+ registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
+ registerCmd("bt", WRAP_METHOD(Console, Cmd_BT));
+ registerCmd("show_map", WRAP_METHOD(Console, Cmd_ShowMap));
+ registerCmd("screenobj", WRAP_METHOD(Console, Cmd_ScreenObj));
+ registerCmd("vmvars", WRAP_METHOD(Console, Cmd_VmVars));
+ registerCmd("vmflags", WRAP_METHOD(Console, Cmd_VmFlags));
+ registerCmd("disableautosave", WRAP_METHOD(Console, Cmd_DisableAutomaticSave));
}
bool Console::Cmd_SetVar(int argc, const char **argv) {
@@ -57,7 +64,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) {
}
int p1 = (int)atoi(argv[1]);
int p2 = (int)atoi(argv[2]);
- _vm->setvar(p1, p2);
+ _vm->setVar(p1, p2);
return true;
}
@@ -69,7 +76,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) {
}
int p1 = (int)atoi(argv[1]);
int p2 = (int)atoi(argv[2]);
- _vm->setflag(p1, !!p2);
+ _vm->setFlag(p1, !!p2);
return true;
}
@@ -125,11 +132,154 @@ bool Console::Cmd_Agiver(int argc, const char **argv) {
maj = (ver >> 12) & 0xf;
min = ver & 0xfff;
+ debugPrintf("AGI version: ");
debugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min);
return true;
}
+#define CONSOLE_VERSION_MAXLEN 10
+
+bool Console::Cmd_Version(int argc, const char **argv) {
+ AgiGame *game = &_vm->_game;
+ int scriptNr = 0;
+ int scriptTextCount = 0;
+ int scriptTextNr = 0;
+ const char *scriptTextPtr = NULL;
+ const char *wordScanPtr = NULL;
+ const char *wordStartPtr = NULL;
+ const char *versionStartPtr = NULL;
+ int wordLen = 0;
+ char curChar = 0;
+ int versionLen = 0;
+ bool wordFound = false;
+ bool versionFound = false;
+ char versionString[CONSOLE_VERSION_MAXLEN];
+ bool scriptLoadedByUs = false;
+
+ // Show AGI version
+ Cmd_Agiver(argc, argv);
+
+ // And now try to figure out the version of the game
+ // We do this by scanning through all script texts
+ // This is the best we can do about it. There is no special location for the game version number.
+ // There are multiple variations, like "ver. X.XX", "ver X.XX" and even "verion X.XX".
+ for (scriptNr = 0; scriptNr < MAX_DIRECTORY_ENTRIES; scriptNr++) {
+ if (game->dirLogic[scriptNr].offset != _EMPTY) {
+ // Script is supposed to exist?
+ scriptLoadedByUs = false;
+ if (!(game->dirLogic[scriptNr].flags & RES_LOADED)) {
+ // But not currently loaded? -> load it now
+ if (_vm->agiLoadResource(RESOURCETYPE_LOGIC, scriptNr) != errOK) {
+ // In case we can't load the source, skip it
+ continue;
+ }
+ scriptLoadedByUs = true;
+ }
+ // Script currently loaded
+ // Now scan all texts
+ scriptTextCount = game->logics[scriptNr].numTexts;
+ for (scriptTextNr = 0; scriptTextNr < scriptTextCount; scriptTextNr++) {
+ scriptTextPtr = game->logics[scriptNr].texts[scriptTextNr];
+
+ // Now scan this text for version information
+ wordScanPtr = scriptTextPtr;
+
+ do {
+ curChar = *wordScanPtr;
+
+ if ((curChar == 'V') || (curChar == 'v')) {
+ // "V" gefunden, ggf. beginning of version?
+ wordStartPtr = wordScanPtr;
+ wordFound = false;
+
+ do {
+ curChar = *wordScanPtr;
+ if (curChar == ' ') {
+ break;
+ }
+ wordScanPtr++;
+ } while (curChar);
+
+ if (curChar) {
+ // end of "version" found
+ wordLen = wordScanPtr - wordStartPtr;
+
+ if (wordLen >= 3) {
+ if (strncmp(wordStartPtr, "ver", wordLen) == 0)
+ wordFound = true;
+ if (strncmp(wordStartPtr, "Ver", wordLen) == 0)
+ wordFound = true;
+ }
+ if ((!wordFound) && (wordLen >= 4)) {
+ if (strncmp(wordStartPtr, "ver.", wordLen) == 0)
+ wordFound = true;
+ if (strncmp(wordStartPtr, "Ver.", wordLen) == 0)
+ wordFound = true;
+ }
+ if ((!versionFound) && (wordLen >= 7)) {
+ if (strncmp(wordStartPtr, "version", wordLen) == 0)
+ wordFound = true;
+ if (strncmp(wordStartPtr, "Version", wordLen) == 0)
+ wordFound = true;
+ if (strncmp(wordStartPtr, "VERSION", wordLen) == 0)
+ wordFound = true;
+ }
+
+ if (wordFound) {
+ // We found something interesting
+ //debugPrintf("%d: %s\n", scriptNr, scriptTextPtr);
+
+ wordScanPtr++; // skip space
+ versionStartPtr = wordScanPtr;
+ curChar = *wordScanPtr;
+ if ((curChar >= '0') && (curChar <= '9')) {
+ // Next word starts with a number
+ wordScanPtr++;
+ curChar = *wordScanPtr;
+ if (curChar == '.') {
+ // Followed by a point? then we assume that we found a version number
+ // Now we try to find the end of it
+ wordScanPtr++;
+ do {
+ curChar = *wordScanPtr;
+ if ((curChar == ' ') || (curChar == '\\') || (!curChar))
+ break; // space or potential new line or NUL? -> found the end
+ wordScanPtr++;
+ } while (1);
+
+ versionLen = wordScanPtr - versionStartPtr;
+ if (versionLen < CONSOLE_VERSION_MAXLEN) {
+ // Looks fine, now extract and show it
+ memcpy(versionString, versionStartPtr, versionLen);
+ versionString[versionLen] = 0;
+ debugPrintf("Scanned game version: %s\n", versionString);
+ versionFound = true;
+ }
+ }
+ }
+ }
+ }
+
+ // Seek back
+ wordScanPtr = wordStartPtr;
+ }
+ wordScanPtr++;
+ } while (curChar);
+ }
+
+ if (scriptLoadedByUs) {
+ _vm->agiUnloadResource(RESOURCETYPE_LOGIC, scriptNr);
+ }
+ }
+ }
+
+ if (!versionFound) {
+ debugPrintf("Scanned game version: [not found]\n");
+ }
+ return true;
+}
+
bool Console::Cmd_Flags(int argc, const char **argv) {
int i, j;
@@ -141,7 +291,7 @@ bool Console::Cmd_Flags(int argc, const char **argv) {
for (i = 0; i < 255;) {
debugPrintf("%3d ", i);
for (j = 0; j < 10; j++, i++) {
- debugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F');
+ debugPrintf("%c ", _vm->getFlag(i) ? 'T' : 'F');
}
debugPrintf("\n");
}
@@ -154,7 +304,7 @@ bool Console::Cmd_Vars(int argc, const char **argv) {
for (i = 0; i < 255;) {
for (j = 0; j < 5; j++, i++) {
- debugPrintf("%03d:%3d ", i, _vm->getvar(i));
+ debugPrintf("%03d:%3d ", i, _vm->getVar(i));
}
debugPrintf("\n");
}
@@ -199,7 +349,7 @@ bool Console::Cmd_Trigger(int argc, const char **argv) {
debugPrintf("Usage: trigger on|off\n");
return true;
}
- _vm->_debug.ignoretriggers = strcmp (argv[1], "on");
+ _vm->_debug.ignoretriggers = strcmp(argv[1], "on");
return true;
}
@@ -236,13 +386,13 @@ bool Console::Cmd_Room(int argc, const char **argv) {
_vm->newRoom(strtoul(argv[1], NULL, 0));
}
- debugPrintf("Current room: %d\n", _vm->getvar(0));
+ debugPrintf("Current room: %d\n", _vm->getVar(0));
return true;
}
bool Console::Cmd_BT(int argc, const char **argv) {
- debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size());
+ debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.curLogicNr, _vm->_game.execStack.size());
uint8 *code = NULL;
uint8 op = 0;
@@ -268,6 +418,233 @@ bool Console::Cmd_BT(int argc, const char **argv) {
return true;
}
+bool Console::Cmd_ShowMap(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Switches to one of the following screen maps\n");
+ debugPrintf("Usage: %s <screen map>\n", argv[0]);
+ debugPrintf("Screen maps:\n");
+ debugPrintf("- 0: visual map\n");
+ debugPrintf("- 1: priority map\n");
+ return true;
+ }
+
+ int map = atoi(argv[1]);
+
+ switch (map) {
+ case 0:
+ case 1:
+ _vm->_gfx->debugShowMap(map);
+ break;
+
+ default:
+ debugPrintf("Map %d is not available.\n", map);
+ return true;
+ }
+ return cmdExit(0, 0);
+}
+
+bool Console::Cmd_ScreenObj(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Shows information about a specific screen object\n");
+ debugPrintf("Usage: %s <screenobj number>\n", argv[0]);
+ return true;
+ }
+
+ int16 screenObjNr = atoi(argv[1]);
+
+ if ((screenObjNr >= 0) && (screenObjNr < SCREENOBJECTS_MAX)) {
+ ScreenObjEntry *screenObj = &_vm->_game.screenObjTable[screenObjNr];
+
+ debugPrintf("Screen Object ID %d\n", screenObj->objectNr);
+ debugPrintf("current view: %d, loop: %d, cel: %d\n", screenObj->currentViewNr, screenObj->currentLoopNr, screenObj->currentCelNr);
+
+ // Figure out flags
+ Common::String flagsString;
+
+ if (screenObj->flags & fDrawn)
+ flagsString += "Drawn ";
+ if (screenObj->flags & fIgnoreBlocks)
+ flagsString += "IgnoreBlocks ";
+ if (screenObj->flags & fFixedPriority)
+ flagsString += "FixedPriority ";
+ if (screenObj->flags & fIgnoreHorizon)
+ flagsString += "IgnoreHorizon ";
+ if (screenObj->flags & fUpdate)
+ flagsString += "Update ";
+ if (screenObj->flags & fCycling)
+ flagsString += "Cycling ";
+ if (screenObj->flags & fAnimated)
+ flagsString += "Animated ";
+ if (screenObj->flags & fMotion)
+ flagsString += "Motion ";
+ if (screenObj->flags & fOnWater)
+ flagsString += "OnWater ";
+ if (screenObj->flags & fIgnoreObjects)
+ flagsString += "IgnoreObjects ";
+ if (screenObj->flags & fUpdatePos)
+ flagsString += "UpdatePos ";
+ if (screenObj->flags & fOnLand)
+ flagsString += "OnLand ";
+ if (screenObj->flags & fDontupdate)
+ flagsString += "DontUpdate ";
+ if (screenObj->flags & fFixLoop)
+ flagsString += "FixLoop ";
+ if (screenObj->flags & fDidntMove)
+ flagsString += "DidntMove ";
+ if (screenObj->flags & fAdjEgoXY)
+ flagsString += "AdjEgoXY ";
+
+ if (flagsString.size() == 0) {
+ flagsString += "*none*";
+ }
+
+ debugPrintf("flags: %s\n", flagsString.c_str());
+
+ debugPrintf("\n");
+ debugPrintf("xPos: %d, yPos: %d, xSize: %d, ySize: %d\n", screenObj->xPos, screenObj->yPos, screenObj->xSize, screenObj->ySize);
+ debugPrintf("previous: xPos: %d, yPos: %d, xSize: %d, ySize: %d\n", screenObj->xPos_prev, screenObj->yPos_prev, screenObj->xSize_prev, screenObj->ySize_prev);
+ debugPrintf("direction: %d, priority: %d\n", screenObj->direction, screenObj->priority);
+ debugPrintf("stepTime: %d, timeCount: %d, size: %d\n", screenObj->stepTime, screenObj->stepTimeCount, screenObj->stepSize);
+ debugPrintf("cycleTime: %d, timeCount: %d\n", screenObj->cycleTime, screenObj->cycleTimeCount);
+
+ switch (screenObj->motionType) {
+ case kMotionNormal:
+ debugPrintf("motion: normal\n");
+ break;
+ case kMotionWander:
+ debugPrintf("motion: wander\n");
+ debugPrintf("wanderCount: %d\n", screenObj->wander_count);
+ break;
+ case kMotionFollowEgo:
+ debugPrintf("motion: follow ego\n");
+ debugPrintf("stepSize: %d, flag: %x, count: %d", screenObj->follow_stepSize, screenObj->follow_flag, screenObj->follow_count);
+ break;
+ case kMotionMoveObj:
+ case kMotionEgo:
+ if (screenObj->motionType == kMotionMoveObj) {
+ debugPrintf("motion: move obj\n");
+ } else {
+ debugPrintf("motion: ego\n");
+ }
+ debugPrintf("x: %d, y: %d, stepSize: %d, flag: %x\n", screenObj->move_x, screenObj->move_y, screenObj->move_stepSize, screenObj->move_flag);
+ break;
+ }
+ }
+ return true;
+}
+
+bool Console::Cmd_VmVars(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Shows the content of a VM variable / sets it\n");
+ debugPrintf("Usage: %s <variable number> [<value>]\n", argv[0]);
+ return true;
+ }
+
+ int varNr = 0;
+ int newValue = 0;
+
+ if (!parseInteger(argv[1], varNr))
+ return true;
+
+ if ((varNr < 0) || (varNr > 255)) {
+ debugPrintf("invalid variable number\n");
+ return true;
+ }
+
+ if (argc < 3) {
+ // show contents
+ debugPrintf("variable %d == %d\n", varNr, _vm->getVar(varNr));
+ } else {
+ if (!parseInteger(argv[2], newValue))
+ return true;
+
+ _vm->setVar(varNr, newValue);
+
+ debugPrintf("value set.\n");
+ }
+ return true;
+}
+
+bool Console::Cmd_VmFlags(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Shows the content of a VM flag / sets it\n");
+ debugPrintf("Usage: %s <flag number> [<value>]\n", argv[0]);
+ return true;
+ }
+
+ int flagNr = 0;
+ int newFlagState = 0;
+
+ if (!parseInteger(argv[1], flagNr))
+ return true;
+
+ if ((flagNr < 0) || (flagNr > 255)) {
+ debugPrintf("invalid flag number\n");
+ return true;
+ }
+
+ if (argc < 3) {
+ // show contents
+ if (_vm->getFlag(flagNr)) {
+ debugPrintf("flag %d == set\n", flagNr);
+ } else {
+ debugPrintf("flag %d == not set\n", flagNr);
+ }
+ } else {
+ if (!parseInteger(argv[2], newFlagState))
+ return true;
+
+ if ((newFlagState != 0) && (newFlagState != 1)) {
+ debugPrintf("new state must bei either 0 or 1\n");
+ return true;
+ }
+
+ if (!newFlagState) {
+ _vm->setFlag(flagNr, false);
+ debugPrintf("flag %d reset.\n", flagNr);
+ } else {
+ _vm->setFlag(flagNr, true);
+ debugPrintf("flag %d set.\n", flagNr);
+ }
+ }
+ return true;
+}
+
+bool Console::Cmd_DisableAutomaticSave(int argc, const char **argv) {
+ if (!_vm->_game.automaticSave) {
+ debugPrintf("Automatic saving is currently not enabled\n");
+ return true;
+ }
+
+ _vm->_game.automaticSave = false;
+
+ debugPrintf("Automatic saving DISABLED!\n");
+ return true;
+}
+
+bool Console::parseInteger(const char *argument, int &result) {
+ char *endPtr = 0;
+ int idxLen = strlen(argument);
+ const char *lastChar = argument + idxLen - (idxLen == 0 ? 0 : 1);
+
+ if ((strncmp(argument, "0x", 2) == 0) || (*lastChar == 'h')) {
+ // hexadecimal number
+ result = strtol(argument, &endPtr, 16);
+ if ((*endPtr != 0) && (*endPtr != 'h')) {
+ debugPrintf("Invalid hexadecimal number '%s'\n", argument);
+ return false;
+ }
+ } else {
+ // decimal number
+ result = strtol(argument, &endPtr, 10);
+ if (*endPtr != 0) {
+ debugPrintf("Invalid decimal number '%s'\n", argument);
+ return false;
+ }
+ }
+ return true;
+}
+
MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() {
_mickey = mickey;