From 919092e5fcd0389b4cbd862e9e8cceab202e6741 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 16 Sep 2006 16:58:27 +0000 Subject: Overhaul of the debugger code * Moved Common::Debuggger to GUI::Debugger (mainly to satisfy linker restrictions) * Change the base Debugger class to *not* be a template class anymore; instead, a thin (template based) wrapper class is used to hook up debugger commands * Removed duplicate Cmd_Exit and Cmd_Help methods in favor of a single version of each in GUI::Debugger * New Cmd_Help doesn't word wrap after 39/78 chars, but rather queries the console to determine when to wrap * Debugger::preEnter and postEnter aren't pure virtual anymore svn-id: r23890 --- common/debugger.cpp | 411 --------------------------------------- common/debugger.h | 110 ----------- engines/agi/console.cpp | 65 ++----- engines/agi/console.h | 6 +- engines/kyra/debugger.cpp | 51 ++--- engines/kyra/debugger.h | 6 +- engines/lure/debugger.cpp | 58 +----- engines/lure/debugger.h | 9 +- engines/queen/debug.cpp | 48 +---- engines/queen/debug.h | 6 +- engines/saga/console.cpp | 68 +------ engines/saga/console.h | 11 +- engines/scumm/debugger.cpp | 96 +++------- engines/scumm/debugger.h | 10 +- engines/simon/debugger.cpp | 48 +---- engines/simon/debugger.h | 6 +- engines/sky/debug.cpp | 46 +---- engines/sky/debug.h | 6 +- engines/sword2/console.cpp | 112 ++++------- engines/sword2/console.h | 6 +- gui/console.h | 2 +- gui/debugger.cpp | 466 +++++++++++++++++++++++++++++++++++++++++++++ gui/debugger.h | 158 +++++++++++++++ gui/module.mk | 1 + 24 files changed, 780 insertions(+), 1026 deletions(-) delete mode 100644 common/debugger.cpp delete mode 100644 common/debugger.h create mode 100644 gui/debugger.cpp create mode 100644 gui/debugger.h diff --git a/common/debugger.cpp b/common/debugger.cpp deleted file mode 100644 index e0ad40eea9..0000000000 --- a/common/debugger.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2001-2006 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/stdafx.h" - -#include "common/debugger.h" -#include "common/system.h" - -#if USE_CONSOLE - #include "gui/console.h" -#endif - -namespace Common { - -template -Debugger::Debugger() { - _frame_countdown = 0; - _dvar_count = 0; - _dcmd_count = 0; - _detach_now = false; - _isAttached = false; - _errStr = NULL; - _firstTime = true; - _debuggerDialog = new GUI::ConsoleDialog(1.0, 0.67F); - _debuggerDialog->setInputCallback(debuggerInputCallback, this); - _debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this); - - DCmd_Register("debugflag_list", &Debugger::Cmd_DebugFlagsList); - DCmd_Register("debugflag_enable", &Debugger::Cmd_DebugFlagEnable); - DCmd_Register("debugflag_disable", &Debugger::Cmd_DebugFlagDisable); -} - -template -Debugger::~Debugger() { - delete _debuggerDialog; -} - - -// Initialisation Functions -template -int Debugger::DebugPrintf(const char *format, ...) { - va_list argptr; - - va_start(argptr, format); - int count; -#if USE_CONSOLE - count = _debuggerDialog->vprintf(format, argptr); -#else - count = ::vprintf(format, argptr); -#endif - va_end (argptr); - return count; -} - -#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) -template -void Debugger::attach(const char *entry) { - - g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - - if (entry) { - _errStr = strdup(entry); - } - - _frame_countdown = 1; - _detach_now = false; - _isAttached = true; -} - -template -void Debugger::detach() { - g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - - _detach_now = false; - _isAttached = false; -} - -// Temporary execution handler -template -void Debugger::onFrame() { - if (_frame_countdown == 0) - return; - --_frame_countdown; - - if (!_frame_countdown) { - - preEnter(); - enter(); - postEnter(); - - // Detach if we're finished with the debugger - if (_detach_now) - detach(); - } -} -#endif // of ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) - -// Main Debugger Loop -template -void Debugger::enter() { -#if USE_CONSOLE - if (_firstTime) { - DebugPrintf("Debugger started, type 'exit' to return to the game.\n"); - DebugPrintf("Type 'help' to see a little list of commands and variables.\n"); - _firstTime = false; - } - - if (_errStr) { - DebugPrintf("ERROR: %s\n\n", _errStr); - free(_errStr); - _errStr = NULL; - } - - _debuggerDialog->runModal(); -#else - // TODO: compared to the console input, this here is very bare bone. - // For example, no support for tab completion and no history. At least - // we should re-add (optional) support for the readline library. - // Or maybe instead of choosing between a console dialog and stdio, - // we should move that choice into the ConsoleDialog class - that is, - // the console dialog code could be #ifdef'ed to not print to the dialog - // but rather to stdio. This way, we could also reuse the command history - // and tab completion of the console. It would still require a lot of - // work, but at least no dependency on a 3rd party library... - - printf("Debugger entered, please switch to this console for input.\n"); - - int i; - char buf[256]; - - do { - printf("debug> "); - if (!fgets(buf, sizeof(buf), stdin)) - return; - - i = strlen(buf); - while (i > 0 && buf[i - 1] == '\n') - buf[--i] = 0; - - if (i == 0) - continue; - } while (RunCommand(buf)); - -#endif -} - -// Command execution loop -template -bool Debugger::RunCommand(const char *inputOrig) { - int i = 0, num_params = 0; - const char *param[256]; - char *input = strdup(inputOrig); // One of the rare occasions using strdup is OK (although avoiding strtok might be more elegant here). - - // Parse out any params - char *tok = strtok(input, " "); - if (tok) { - do { - param[num_params++] = tok; - } while ((tok = strtok(NULL, " ")) != NULL); - } else { - param[num_params++] = input; - } - - for (i=0; i < _dcmd_count; i++) { - if (!strcmp(_dcmds[i].name, param[0])) { - bool result = (((T *)this)->*_dcmds[i].function)(num_params, param); - free(input); - return result; - } - } - - // It's not a command, so things get a little tricky for variables. Do fuzzy matching to ignore things like subscripts. - for (i = 0; i < _dvar_count; i++) { - if (!strncmp(_dvars[i].name, param[0], strlen(_dvars[i].name))) { - if (num_params > 1) { - // Alright, we need to check the TYPE of the variable to deref and stuff... the array stuff is a bit ugly :) - switch (_dvars[i].type) { - // Integer - case DVAR_BYTE: - *(byte *)_dvars[i].variable = atoi(param[1]); - DebugPrintf("byte%s = %d\n", param[0], *(byte *)_dvars[i].variable); - break; - case DVAR_INT: - *(int32 *)_dvars[i].variable = atoi(param[1]); - DebugPrintf("(int)%s = %d\n", param[0], *(int32 *)_dvars[i].variable); - break; - // Integer Array - case DVAR_INTARRAY: { - char *chr = (char *)strchr(param[0], '['); - if (!chr) { - DebugPrintf("You must access this array as %s[element]\n", param[0]); - } else { - int element = atoi(chr+1); - int32 *var = *(int32 **)_dvars[i].variable; - if (element >= _dvars[i].optional) { - DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional); - } else { - var[element] = atoi(param[1]); - DebugPrintf("(int)%s = %d\n", param[0], var[element]); - } - } - } - break; - default: - DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name, param[1]); - break; - } - } else { - // And again, type-dependent prints/defrefs. The array one is still ugly. - switch (_dvars[i].type) { - // Integer - case DVAR_BYTE: - DebugPrintf("(byte)%s = %d\n", param[0], *(const byte *)_dvars[i].variable); - break; - case DVAR_INT: - DebugPrintf("(int)%s = %d\n", param[0], *(const int32 *)_dvars[i].variable); - break; - // Integer array - case DVAR_INTARRAY: { - const char *chr = strchr(param[0], '['); - if (!chr) { - DebugPrintf("You must access this array as %s[element]\n", param[0]); - } else { - int element = atoi(chr+1); - const int32 *var = *(const int32 **)_dvars[i].variable; - if (element >= _dvars[i].optional) { - DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional); - } else { - DebugPrintf("(int)%s = %d\n", param[0], var[element]); - } - } - } - break; - // String - case DVAR_STRING: - DebugPrintf("(string)%s = %s\n", param[0], ((Common::String *)_dvars[i].variable)->c_str()); - break; - default: - DebugPrintf("%s = (unknown type)\n", param[0]); - break; - } - } - - free(input); - return true; - } - } - - DebugPrintf("Unknown command or variable\n"); - free(input); - return true; -} - -// returns true if something has been completed -// completion has to be delete[]-ed then -template -bool Debugger::TabComplete(const char *input, char*& completion) { - // very basic tab completion - // for now it just supports command completions - - // adding completions of command parameters would be nice (but hard) :-) - // maybe also give a list of possible command completions? - // (but this will require changes to console) - - if (strchr(input, ' ')) - return false; // already finished the first word - - unsigned int inputlen = strlen(input); - - unsigned int matchlen = 0; - char match[30]; // the max. command name is 30 chars - - for (int i = 0; i < _dcmd_count; i++) { - if (!strncmp(_dcmds[i].name, input, inputlen)) { - unsigned int commandlen = strlen(_dcmds[i].name); - if (commandlen == inputlen) { // perfect match - return false; - } - if (commandlen > inputlen) { // possible match - // no previous match - if (matchlen == 0) { - strcpy(match, _dcmds[i].name + inputlen); - matchlen = commandlen - inputlen; - } else { - // take common prefix of previous match and this command - unsigned int j; - for (j = 0; j < matchlen; j++) { - if (match[j] != _dcmds[i].name[inputlen + j]) break; - } - matchlen = j; - } - if (matchlen == 0) - return false; - } - } - } - if (matchlen == 0) - return false; - - completion = new char[matchlen + 1]; - memcpy(completion, match, matchlen); - completion[matchlen] = 0; - return true; -} - -// Variable registration function -template -void Debugger::DVar_Register(const char *varname, void *pointer, int type, int optional) { - assert(_dvar_count < ARRAYSIZE(_dvars)); - strcpy(_dvars[_dvar_count].name, varname); - _dvars[_dvar_count].type = type; - _dvars[_dvar_count].variable = pointer; - _dvars[_dvar_count].optional = optional; - - _dvar_count++; -} - -// Command registration function -template -void Debugger::DCmd_Register(const char *cmdname, DebugProc pointer) { - assert(_dcmd_count < ARRAYSIZE(_dcmds)); - strcpy(_dcmds[_dcmd_count].name, cmdname); - _dcmds[_dcmd_count].function = pointer; - - _dcmd_count++; -} - -template -bool Debugger::Cmd_DebugFlagsList(int argc, const char **argv) { - const Common::Array &debugLevels = Common::listSpecialDebugLevels(); - - DebugPrintf("Engine debug levels:\n"); - DebugPrintf("--------------------\n"); - if (!debugLevels.size()) { - DebugPrintf("No engine debug levels\n"); - return true; - } - for (uint i = 0; i < debugLevels.size(); ++i) { - DebugPrintf("'%s' - Description: %s\n", debugLevels[i].option.c_str(), debugLevels[i].description.c_str()); - } - DebugPrintf("\n"); - return true; -} - -template -bool Debugger::Cmd_DebugFlagEnable(int argc, const char **argv) { - if (argc < 2) { - DebugPrintf("debugflag_enable \n"); - } else { - if (Common::enableSpecialDebugLevel(argv[1])) { - DebugPrintf("Enabled debug flag '%s'\n", argv[1]); - } else { - DebugPrintf("Failed to enable debug flag '%s'\n", argv[1]); - } - } - return true; -} - -template -bool Debugger::Cmd_DebugFlagDisable(int argc, const char **argv) { - if (argc < 2) { - DebugPrintf("debugflag_disable \n"); - } else { - if (Common::disableSpecialDebugLevel(argv[1])) { - DebugPrintf("Disabled debug flag '%s'\n", argv[1]); - } else { - DebugPrintf("Failed to disable debug flag '%s'\n", argv[1]); - } - } - return true; -} - -// Console handler -#if USE_CONSOLE -template -bool Debugger::debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon) { - Debugger *debugger = (Debugger *)refCon; - - return debugger->RunCommand(input); -} - - -template -bool Debugger::debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon) { - Debugger *debugger = (Debugger *)refCon; - - return debugger->TabComplete(input, completion); -} - -#endif - -} // End of namespace Common diff --git a/common/debugger.h b/common/debugger.h deleted file mode 100644 index 25ddff8ac2..0000000000 --- a/common/debugger.h +++ /dev/null @@ -1,110 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2006 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - */ - -#ifndef COMMON_DEBUGGER_H -#define COMMON_DEBUGGER_H - -namespace GUI { - class ConsoleDialog; -} - -namespace Common { - -// Choose between text console or ScummConsole -#define USE_CONSOLE 1 - -template -class Debugger { -public: - Debugger(); - virtual ~Debugger(); - - int DebugPrintf(const char *format, ...); - -#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) - virtual void onFrame(); - - virtual void attach(const char *entry = 0); -#else - void onFrame() {} - void attach(const char *entry = 0) {} -#endif - bool isAttached() const { return _isAttached; } - -protected: - typedef bool (T::*DebugProc)(int argc, const char **argv); - - enum { - DVAR_BYTE, - DVAR_INT, - DVAR_BOOL, - DVAR_INTARRAY, - DVAR_STRING - }; - - struct DVar { - char name[30]; - void *variable; - int type, optional; - }; - - struct DCmd { - char name[30]; - DebugProc function; - }; - - int _frame_countdown, _dvar_count, _dcmd_count; - DVar _dvars[256]; - DCmd _dcmds[256]; - bool _detach_now; - -private: - bool _isAttached; - char *_errStr; - bool _firstTime; - GUI::ConsoleDialog *_debuggerDialog; - -protected: - void detach(); - void enter(); - - virtual void preEnter() = 0; - virtual void postEnter() = 0; - - bool RunCommand(const char *input); - bool TabComplete(const char *input, char*& completion); - - void DVar_Register(const char *varname, void *pointer, int type, int optional); - void DCmd_Register(const char *cmdname, DebugProc pointer); - - bool Cmd_DebugFlagsList(int argc, const char **argv); - bool Cmd_DebugFlagEnable(int argc, const char **argv); - bool Cmd_DebugFlagDisable(int argc, const char **argv); - -#if USE_CONSOLE - static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon); - static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon); -#endif -}; - -} // End of namespace Common - -#endif diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index 1c761f1c6f..abf66ced48 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -32,33 +32,28 @@ #include "agi/opcodes.h" #include "agi/console.h" -#include "common/debugger.cpp" - namespace Agi { struct agi_debug debug_; -Console::Console(AgiEngine *vm) : Common::Debugger() { +Console::Console(AgiEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("debug", &Console::Cmd_Debug); - DCmd_Register("cont", &Console::Cmd_Cont); - DCmd_Register("exit", &Console::Cmd_Exit); - DCmd_Register("quit", &Console::Cmd_Exit); - DCmd_Register("help", &Console::Cmd_Help); - DCmd_Register("agiver", &Console::Cmd_Agiver); - DCmd_Register("crc", &Console::Cmd_Crc); - DCmd_Register("flags", &Console::Cmd_Flags); - DCmd_Register("logic0", &Console::Cmd_Logic0); - DCmd_Register("objs", &Console::Cmd_Objs); - DCmd_Register("runopcode", &Console::Cmd_RunOpcode); - DCmd_Register("opcode", &Console::Cmd_Opcode); - DCmd_Register("step", &Console::Cmd_Step); - DCmd_Register("trigger", &Console::Cmd_Trigger); - DCmd_Register("vars", &Console::Cmd_Vars); - DCmd_Register("setvar", &Console::Cmd_SetVar); - DCmd_Register("setflag", &Console::Cmd_SetFlag); - DCmd_Register("setobj", &Console::Cmd_SetObj); + DCmd_Register("debug", WRAP_METHOD(Console, Cmd_Debug)); + DCmd_Register("cont", WRAP_METHOD(Console, Cmd_Cont)); + DCmd_Register("agiver", WRAP_METHOD(Console, Cmd_Agiver)); + DCmd_Register("crc", WRAP_METHOD(Console, Cmd_Crc)); + DCmd_Register("flags", WRAP_METHOD(Console, Cmd_Flags)); + DCmd_Register("logic0", WRAP_METHOD(Console, Cmd_Logic0)); + DCmd_Register("objs", WRAP_METHOD(Console, Cmd_Objs)); + DCmd_Register("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode)); + DCmd_Register("opcode", WRAP_METHOD(Console, Cmd_Opcode)); + DCmd_Register("step", WRAP_METHOD(Console, Cmd_Step)); + DCmd_Register("trigger", WRAP_METHOD(Console, Cmd_Trigger)); + DCmd_Register("vars", WRAP_METHOD(Console, Cmd_Vars)); + DCmd_Register("setvar", WRAP_METHOD(Console, Cmd_SetVar)); + DCmd_Register("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); + DCmd_Register("setobj", WRAP_METHOD(Console, Cmd_SetObj)); } Console::~Console() { @@ -70,34 +65,6 @@ void Console::preEnter() { void Console::postEnter() { } -bool Console::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Console::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - - DebugPrintf("\n"); - - return true; -} - bool Console::Cmd_SetVar(int argc, const char **argv) { if (argc != 3) { DebugPrintf("Usage: setvar "); diff --git a/engines/agi/console.h b/engines/agi/console.h index c94a9099e5..e0f108afce 100644 --- a/engines/agi/console.h +++ b/engines/agi/console.h @@ -25,7 +25,7 @@ #ifndef AGI_CONSOLE_H #define AGI_CONSOLE_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Agi { @@ -41,7 +41,7 @@ struct agi_debug { int ignoretriggers; }; -class Console : public Common::Debugger { +class Console : public GUI::Debugger { public: Console(AgiEngine *vm); virtual ~Console(void); @@ -51,8 +51,6 @@ protected: virtual void postEnter(); private: - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_SetVar(int argc, const char **argv); bool Cmd_SetFlag(int argc, const char **argv); bool Cmd_SetObj(int argc, const char **argv); diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index 7e3b109448..30ec201f27 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -22,7 +22,7 @@ #include "common/stdafx.h" #include "common/config-manager.h" -#include "common/debugger.cpp" +#include "common/system.h" #include "kyra/debugger.h" #include "kyra/kyra.h" #include "kyra/screen.h" @@ -30,21 +30,18 @@ namespace Kyra { Debugger::Debugger(KyraEngine *vm) - : Common::Debugger() { + : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", &Debugger::cmd_exit); - DCmd_Register("exit", &Debugger::cmd_exit); - DCmd_Register("help", &Debugger::cmd_help); - DCmd_Register("quit", &Debugger::cmd_exit); - DCmd_Register("enter", &Debugger::cmd_enterRoom); - DCmd_Register("rooms", &Debugger::cmd_listRooms); - DCmd_Register("flags", &Debugger::cmd_listFlags); - DCmd_Register("toggleflag", &Debugger::cmd_toggleFlag); - DCmd_Register("queryflag", &Debugger::cmd_queryFlag); - DCmd_Register("timers", &Debugger::cmd_listTimers); - DCmd_Register("settimercountdown", &Debugger::cmd_setTimerCountdown); - DCmd_Register("give", &Debugger::cmd_giveItem); + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); + DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); + DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags)); + DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag)); + DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag)); + DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers)); + DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown)); + DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem)); } void Debugger::preEnter() { @@ -93,32 +90,6 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { return true; } -bool Debugger::cmd_exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Debugger::cmd_help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - DebugPrintf("\n"); - return true; -} - bool Debugger::cmd_listRooms(int argc, const char **argv) { for (int i = 0; i < _vm->_roomTableSize; i++) { DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index 69766f3fc0..91f90ee3ef 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -23,13 +23,13 @@ #ifndef KYRA_DEBUGGER_H #define KYRA_DEBUGGER_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Kyra { class KyraEngine; -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { public: Debugger(KyraEngine *vm); virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ @@ -40,8 +40,6 @@ protected: virtual void preEnter(); virtual void postEnter(); - bool cmd_exit(int argc, const char **argv); - bool cmd_help(int argc, const char **argv); bool cmd_enterRoom(int argc, const char **argv); bool cmd_listRooms(int argc, const char **argv); bool cmd_listFlags(int argc, const char **argv); diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp index 4c67176a27..1d26556917 100644 --- a/engines/lure/debugger.cpp +++ b/engines/lure/debugger.cpp @@ -22,7 +22,6 @@ #include "common/stdafx.h" #include "common/config-manager.h" -#include "common/debugger.cpp" #include "lure/debugger.h" #include "lure/res.h" #include "lure/res_struct.h" @@ -31,19 +30,16 @@ namespace Lure { -Debugger::Debugger(): Common::Debugger() { - DCmd_Register("continue", &Debugger::cmd_exit); - DCmd_Register("exit", &Debugger::cmd_exit); - DCmd_Register("help", &Debugger::cmd_help); - DCmd_Register("quit", &Debugger::cmd_exit); - DCmd_Register("enter", &Debugger::cmd_enterRoom); - DCmd_Register("rooms", &Debugger::cmd_listRooms); - DCmd_Register("fields", &Debugger::cmd_listFields); - DCmd_Register("setfield", &Debugger::cmd_setField); - DCmd_Register("queryfield", &Debugger::cmd_queryField); - DCmd_Register("give", &Debugger::cmd_giveItem); - DCmd_Register("hotspots", &Debugger::cmd_hotspots); - DCmd_Register("hotspot", &Debugger::cmd_hotspot); +Debugger::Debugger(): GUI::Debugger() { + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); + DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); + DCmd_Register("fields", WRAP_METHOD(Debugger, cmd_listFields)); + DCmd_Register("setfield", WRAP_METHOD(Debugger, cmd_setField)); + DCmd_Register("queryfield", WRAP_METHOD(Debugger, cmd_queryField)); + DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem)); + DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); + DCmd_Register("hotspot", WRAP_METHOD(Debugger, cmd_hotspot)); } static int strToInt(const char *s) { @@ -73,14 +69,6 @@ static int strToInt(const char *s) { return result; } -void Debugger::preEnter() { - // NO IMPLEMENTATION -} - -void Debugger::postEnter() { - // NO IMPLEMENTATION -} - bool Debugger::cmd_enterRoom(int argc, const char **argv) { Resources &res = Resources::getReference(); Room &room = Room::getReference(); @@ -114,32 +102,6 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { return true; } -bool Debugger::cmd_exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Debugger::cmd_help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 69) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - DebugPrintf("\n"); - return true; -} - bool Debugger::cmd_listRooms(int argc, const char **argv) { RoomDataList &rooms = Resources::getReference().roomData(); RoomDataList::iterator i; diff --git a/engines/lure/debugger.h b/engines/lure/debugger.h index cfd48ec274..6080c76fb5 100644 --- a/engines/lure/debugger.h +++ b/engines/lure/debugger.h @@ -23,23 +23,18 @@ #ifndef LURE_DEBUGGER_H #define LURE_DEBUGGER_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Lure { class KyraEngine; -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { public: Debugger(); virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ protected: - virtual void preEnter(); - virtual void postEnter(); - - bool cmd_exit(int argc, const char **argv); - bool cmd_help(int argc, const char **argv); bool cmd_enterRoom(int argc, const char **argv); bool cmd_listRooms(int argc, const char **argv); bool cmd_listFields(int argc, const char **argv); diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp index 63fc40f444..8f49753d17 100644 --- a/engines/queen/debug.cpp +++ b/engines/queen/debug.cpp @@ -29,24 +29,20 @@ #include "queen/resource.h" #include "queen/sound.h" -#include "common/debugger.cpp" - namespace Queen { Debugger::Debugger(QueenEngine *vm) : _vm(vm), _flags(0) { - DCmd_Register("exit", &Debugger::Cmd_Exit); - DCmd_Register("help", &Debugger::Cmd_Help); - DCmd_Register("areas", &Debugger::Cmd_Areas); - DCmd_Register("asm", &Debugger::Cmd_Asm); - DCmd_Register("bob", &Debugger::Cmd_Bob); - DCmd_Register("bobs", &Debugger::Cmd_PrintBobs); - DCmd_Register("gs", &Debugger::Cmd_GameState); - DCmd_Register("info", &Debugger::Cmd_Info); - DCmd_Register("items", &Debugger::Cmd_Items); - DCmd_Register("room", &Debugger::Cmd_Room); - DCmd_Register("song", &Debugger::Cmd_Song); + DCmd_Register("areas", WRAP_METHOD(Debugger, Cmd_Areas)); + DCmd_Register("asm", WRAP_METHOD(Debugger, Cmd_Asm)); + DCmd_Register("bob", WRAP_METHOD(Debugger, Cmd_Bob)); + DCmd_Register("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs)); + DCmd_Register("gs", WRAP_METHOD(Debugger, Cmd_GameState)); + DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); + DCmd_Register("items", WRAP_METHOD(Debugger, Cmd_Items)); + DCmd_Register("room", WRAP_METHOD(Debugger, Cmd_Room)); + DCmd_Register("song", WRAP_METHOD(Debugger, Cmd_Song)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -57,32 +53,6 @@ void Debugger::postEnter() { _vm->graphics()->setupMouseCursor(); } -bool Debugger::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Debugger::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - DebugPrintf("\n"); - return true; -} - bool Debugger::Cmd_Asm(int argc, const char **argv) { if (argc == 2) { uint16 sm = atoi(argv[1]); diff --git a/engines/queen/debug.h b/engines/queen/debug.h index 40cb8bb6ff..0959686a45 100644 --- a/engines/queen/debug.h +++ b/engines/queen/debug.h @@ -23,13 +23,13 @@ #ifndef QUEENDEBUG_H #define QUEENDEBUG_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Queen { class QueenEngine; -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { public: Debugger(QueenEngine *vm); @@ -46,8 +46,6 @@ protected: virtual void preEnter(); virtual void postEnter(); - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_Areas(int argc, const char **argv); bool Cmd_Asm(int argc, const char **argv); bool Cmd_Bob(int argc, const char **argv); diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp index 3455c8c1c3..6aa7c60de9 100644 --- a/engines/saga/console.cpp +++ b/engines/saga/console.cpp @@ -32,26 +32,21 @@ #include "saga/console.h" -#include "common/debugger.cpp" - namespace Saga { -Console::Console(SagaEngine *vm) : Common::Debugger() { +Console::Console(SagaEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", &Console::Cmd_Exit); - DCmd_Register("exit", &Console::Cmd_Exit); - DCmd_Register("quit", &Console::Cmd_Exit); - DCmd_Register("help", &Console::Cmd_Help); + DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit)); // CVAR_Register_I(&_soundEnabled, "sound", NULL, CVAR_CFG, 0, 1); // CVAR_Register_I(&_musicEnabled, "music", NULL, CVAR_CFG, 0, 1); // Actor commands - DCmd_Register("actor_walk_to", &Console::cmdActorWalkTo); + DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); // Animation commands - DCmd_Register("anim_info", &Console::Cmd_AnimInfo); + DCmd_Register("anim_info", WRAP_METHOD(Console, Cmd_AnimInfo)); // Game stuff @@ -66,63 +61,14 @@ Console::Console(SagaEngine *vm) : Common::Debugger() { #endif // Scene commands - DCmd_Register("scene_change", &Console::cmdSceneChange); - DCmd_Register("action_map_info", &Console::cmdActionMapInfo); - DCmd_Register("object_map_info", &Console::cmdObjectMapInfo); + DCmd_Register("scene_change", WRAP_METHOD(Console, cmdSceneChange)); + DCmd_Register("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo)); + DCmd_Register("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo)); } Console::~Console() { } -void Console::preEnter() { -} - -void Console::postEnter() { -} - -bool Console::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Console::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - - width = 0; - - DebugPrintf("\n\nVariables are:\n"); - for (i = 0 ; i < _dvar_count ; i++) { - size = strlen(_dvars[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dvars[i].name); - } - - DebugPrintf("\n"); - - return true; -} - bool Console::cmdActorWalkTo(int argc, const char **argv) { if (argc != 4) DebugPrintf("Usage: %s \n", argv[0]); diff --git a/engines/saga/console.h b/engines/saga/console.h index c93373960f..1a2693e25e 100644 --- a/engines/saga/console.h +++ b/engines/saga/console.h @@ -27,23 +27,16 @@ #ifndef SAGA_CONSOLE_H_ #define SAGA_CONSOLE_H_ -#include "common/debugger.h" +#include "gui/debugger.h" namespace Saga { -class Console : public Common::Debugger { +class Console : public GUI::Debugger { public: Console(SagaEngine *vm); virtual ~Console(void); -protected: - virtual void preEnter(); - virtual void postEnter(); - private: - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); - bool cmdActorWalkTo(int argc, const char **argv); bool Cmd_AnimInfo(int argc, const char **argv); diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index c064405b15..fe4f13ead7 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -36,8 +36,6 @@ #include "scumm/scumm.h" #include "scumm/sound.h" -#include "common/debugger.cpp" - namespace Scumm { // Debug channel lookup table for Debugger console @@ -71,7 +69,7 @@ void CDECL debugC(int channel, const char *s, ...) { } ScummDebugger::ScummDebugger(ScummEngine *s) - : Common::Debugger() { + : GUI::Debugger() { _vm = s; // Register variables @@ -87,38 +85,35 @@ ScummDebugger::ScummDebugger(ScummEngine *s) DVar_Register("scumm_gameid", &_vm->_game.id, DVAR_BYTE, 0); // Register commands - DCmd_Register("continue", &ScummDebugger::Cmd_Exit); - DCmd_Register("exit", &ScummDebugger::Cmd_Exit); - DCmd_Register("quit", &ScummDebugger::Cmd_Exit); - DCmd_Register("restart", &ScummDebugger::Cmd_Restart); - - DCmd_Register("actor", &ScummDebugger::Cmd_Actor); - DCmd_Register("actors", &ScummDebugger::Cmd_PrintActor); - DCmd_Register("box", &ScummDebugger::Cmd_PrintBox); - DCmd_Register("matrix", &ScummDebugger::Cmd_PrintBoxMatrix); - DCmd_Register("camera", &ScummDebugger::Cmd_Camera); - DCmd_Register("room", &ScummDebugger::Cmd_Room); - DCmd_Register("objects", &ScummDebugger::Cmd_PrintObjects); - DCmd_Register("object", &ScummDebugger::Cmd_Object); - DCmd_Register("script", &ScummDebugger::Cmd_Script); - DCmd_Register("scr", &ScummDebugger::Cmd_Script); - DCmd_Register("scripts", &ScummDebugger::Cmd_PrintScript); - DCmd_Register("importres", &ScummDebugger::Cmd_ImportRes); + DCmd_Register("continue", WRAP_METHOD(ScummDebugger, Cmd_Exit)); + DCmd_Register("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart)); + + DCmd_Register("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor)); + DCmd_Register("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor)); + DCmd_Register("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox)); + DCmd_Register("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix)); + DCmd_Register("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera)); + DCmd_Register("room", WRAP_METHOD(ScummDebugger, Cmd_Room)); + DCmd_Register("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects)); + DCmd_Register("object", WRAP_METHOD(ScummDebugger, Cmd_Object)); + DCmd_Register("script", WRAP_METHOD(ScummDebugger, Cmd_Script)); + DCmd_Register("scr", WRAP_METHOD(ScummDebugger, Cmd_Script)); + DCmd_Register("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript)); + DCmd_Register("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes)); if (_vm->_game.id == GID_LOOM) - DCmd_Register("drafts", &ScummDebugger::Cmd_PrintDraft); + DCmd_Register("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft)); - DCmd_Register("loadgame", &ScummDebugger::Cmd_LoadGame); - DCmd_Register("savegame", &ScummDebugger::Cmd_SaveGame); + DCmd_Register("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame)); + DCmd_Register("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame)); - DCmd_Register("level", &ScummDebugger::Cmd_DebugLevel); - DCmd_Register("debug", &ScummDebugger::Cmd_Debug); - DCmd_Register("help", &ScummDebugger::Cmd_Help); + DCmd_Register("level", WRAP_METHOD(ScummDebugger, Cmd_DebugLevel)); + DCmd_Register("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug)); - DCmd_Register("show", &ScummDebugger::Cmd_Show); - DCmd_Register("hide", &ScummDebugger::Cmd_Hide); + DCmd_Register("show", WRAP_METHOD(ScummDebugger, Cmd_Show)); + DCmd_Register("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide)); - DCmd_Register("imuse", &ScummDebugger::Cmd_IMuse); + DCmd_Register("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse)); } ScummDebugger::~ScummDebugger() {} // we need this here for __SYMBIAN32__ @@ -138,11 +133,6 @@ void ScummDebugger::postEnter() { // Now the fun stuff: // Commands -bool ScummDebugger::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - bool ScummDebugger::Cmd_Restart(int argc, const char **argv) { _vm->restart(); @@ -518,44 +508,6 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { return true; } -bool ScummDebugger::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - - width = 0; - - DebugPrintf("\n\nVariables are:\n"); - for (i = 0 ; i < _dvar_count ; i++) { - size = strlen(_dvars[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dvars[i].name); - } - - DebugPrintf("\n"); - - return true; -} - bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { int numChannels = sizeof(debugChannels) / sizeof(dbgChannelDesc); diff --git a/engines/scumm/debugger.h b/engines/scumm/debugger.h index 664c28923d..d781b957de 100644 --- a/engines/scumm/debugger.h +++ b/engines/scumm/debugger.h @@ -19,16 +19,16 @@ * $Id$ */ -#ifndef DEBUGGER_H -#define DEBUGGER_H +#ifndef SCUMM_DEBUGGER_H +#define SCUMM_DEBUGGER_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Scumm { class ScummEngine; -class ScummDebugger : public Common::Debugger { +class ScummDebugger : public GUI::Debugger { public: ScummDebugger(ScummEngine *s); virtual ~ScummDebugger(); // we need this here for __SYMBIAN32__ @@ -41,7 +41,6 @@ protected: virtual void postEnter(); // Commands - bool Cmd_Exit(int argc, const char **argv); bool Cmd_Room(int argc, const char **argv); bool Cmd_LoadGame(int argc, const char **argv); bool Cmd_SaveGame(int argc, const char **argv); @@ -62,7 +61,6 @@ protected: bool Cmd_Debug(int argc, const char **argv); bool Cmd_DebugLevel(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_Show(int argc, const char **argv); bool Cmd_Hide(int argc, const char **argv); diff --git a/engines/simon/debugger.cpp b/engines/simon/debugger.cpp index 5f3ac44be8..7e2694966a 100644 --- a/engines/simon/debugger.cpp +++ b/engines/simon/debugger.cpp @@ -24,7 +24,6 @@ #include "common/stdafx.h" #include "common/config-manager.h" -#include "common/debugger.cpp" #include "simon/debugger.h" #include "simon/simon.h" @@ -32,20 +31,17 @@ namespace Simon { Debugger::Debugger(SimonEngine *vm) - : Common::Debugger() { + : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", &Debugger::Cmd_Exit); - DCmd_Register("exit", &Debugger::Cmd_Exit); - DCmd_Register("help", &Debugger::Cmd_Help); - DCmd_Register("quit", &Debugger::Cmd_Exit); - DCmd_Register("level", &Debugger::Cmd_DebugLevel); - DCmd_Register("music", &Debugger::Cmd_PlayMusic); - DCmd_Register("sound", &Debugger::Cmd_PlaySound); - DCmd_Register("voice", &Debugger::Cmd_PlayVoice); - DCmd_Register("bit", &Debugger::Cmd_SetBit); - DCmd_Register("var", &Debugger::Cmd_SetVar); - DCmd_Register("sub", &Debugger::Cmd_StartSubroutine); + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("level", WRAP_METHOD(Debugger, Cmd_DebugLevel)); + DCmd_Register("music", WRAP_METHOD(Debugger, Cmd_PlayMusic)); + DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); + DCmd_Register("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice)); + DCmd_Register("bit", WRAP_METHOD(Debugger, Cmd_SetBit)); + DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_SetVar)); + DCmd_Register("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine)); } @@ -60,32 +56,6 @@ void Debugger::postEnter() { } -bool Debugger::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Debugger::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size, i; - - DebugPrintf("Commands are:\n"); - for (i = 0 ; i < _dcmd_count ; i++) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - DebugPrintf("\n"); - return true; -} - bool Debugger::Cmd_DebugLevel(int argc, const char **argv) { if (argc == 1) { if (_vm->_debugMode == false) diff --git a/engines/simon/debugger.h b/engines/simon/debugger.h index bfb2183e13..2c8e28d20e 100644 --- a/engines/simon/debugger.h +++ b/engines/simon/debugger.h @@ -24,13 +24,13 @@ #ifndef SIMON_DEBUGGER_H #define SIMON_DEBUGGER_H -#include "common/debugger.h" +#include "gui/debugger.h" namespace Simon { class SimonEngine; -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { public: Debugger(SimonEngine *vm); virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ @@ -41,8 +41,6 @@ protected: virtual void preEnter(); virtual void postEnter(); - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_PlayMusic(int argc, const char **argv); bool Cmd_PlaySound(int argc, const char **argv); diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp index d7e8f6694c..24d52aa59d 100644 --- a/engines/sky/debug.cpp +++ b/engines/sky/debug.cpp @@ -23,7 +23,6 @@ #include "common/stdafx.h" #include "common/endian.h" #include "common/util.h" -#include "common/debugger.cpp" #include "sky/debug.h" #include "sky/grid.h" @@ -1280,16 +1279,14 @@ void Debug::mcode(uint32 mcode, uint32 a, uint32 b, uint32 c) { Debugger::Debugger(Logic *logic, Mouse *mouse, Screen *screen, SkyCompact *skyCompact) -: Common::Debugger(), _logic(logic), _mouse(mouse), _screen(screen), _skyCompact(skyCompact), _showGrid(false) { - DCmd_Register("exit", &Debugger::Cmd_Exit); - DCmd_Register("help", &Debugger::Cmd_Help); - DCmd_Register("info", &Debugger::Cmd_Info); - DCmd_Register("showgrid", &Debugger::Cmd_ShowGrid); - DCmd_Register("reloadgrid", &Debugger::Cmd_ReloadGrid); - DCmd_Register("compact", &Debugger::Cmd_ShowCompact); - DCmd_Register("logiccmd", &Debugger::Cmd_LogicCommand); - DCmd_Register("scriptvar", &Debugger::Cmd_ScriptVar); - DCmd_Register("section", &Debugger::Cmd_Section); +: GUI::Debugger(), _logic(logic), _mouse(mouse), _screen(screen), _skyCompact(skyCompact), _showGrid(false) { + DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); + DCmd_Register("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid)); + DCmd_Register("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid)); + DCmd_Register("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact)); + DCmd_Register("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand)); + DCmd_Register("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar)); + DCmd_Register("section", WRAP_METHOD(Debugger, Cmd_Section)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -1302,33 +1299,6 @@ void Debugger::postEnter() { _mouse->resetCursor(); } -bool Debugger::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - return false; -} - -bool Debugger::Cmd_Help(int argc, const char **argv) { - // console normally has 39 line width - // wrap around nicely - int width = 0, size; - - DebugPrintf("Commands are:\n"); - for (int i = 0; i < _dcmd_count; ++i) { - size = strlen(_dcmds[i].name) + 1; - - if ((width + size) >= 39) { - DebugPrintf("\n"); - width = size; - } else { - width += size; - } - - DebugPrintf("%s ", _dcmds[i].name); - } - DebugPrintf("\n"); - return true; -} - bool Debugger::Cmd_ShowGrid(int argc, const char **argv) { _showGrid = !_showGrid; DebugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); diff --git a/engines/sky/debug.h b/engines/sky/debug.h index 8fdb46d2e1..ec43f40edd 100644 --- a/engines/sky/debug.h +++ b/engines/sky/debug.h @@ -25,7 +25,7 @@ #include "common/stdafx.h" #include "common/scummsys.h" -#include "common/debugger.h" +#include "gui/debugger.h" namespace Sky { @@ -34,7 +34,7 @@ class Mouse; class Screen; class SkyCompact; -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { public: Debugger(Logic *logic, Mouse *mouse, Screen *screen, SkyCompact *skyCompact); virtual ~Debugger(); // we need this here for __SYMBIAN32__ archaic gcc/UIQ @@ -44,8 +44,6 @@ protected: virtual void preEnter(); virtual void postEnter(); - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_ShowGrid(int argc, const char **argv); bool Cmd_ReloadGrid(int argc, const char **argv); bool Cmd_ShowCompact(int argc, const char **argv); diff --git a/engines/sword2/console.cpp b/engines/sword2/console.cpp index 02f85418ad..4e8e0eda24 100644 --- a/engines/sword2/console.cpp +++ b/engines/sword2/console.cpp @@ -21,6 +21,7 @@ #include "common/stdafx.h" #include "common/rect.h" +#include "common/system.h" #include "sword2/sword2.h" #include "sword2/defs.h" @@ -34,12 +35,10 @@ #include "sword2/screen.h" #include "sword2/sound.h" -#include "common/debugger.cpp" - namespace Sword2 { Debugger::Debugger(Sword2Engine *vm) - : Common::Debugger() { + : GUI::Debugger() { _vm = vm; memset(_debugTextBlocks, 0, sizeof(_debugTextBlocks)); @@ -79,47 +78,44 @@ Debugger::Debugger(Sword2Engine *vm) // Register commands - DCmd_Register("continue", &Debugger::Cmd_Exit); - DCmd_Register("exit", &Debugger::Cmd_Exit); - DCmd_Register("quit", &Debugger::Cmd_Exit); - DCmd_Register("q", &Debugger::Cmd_Exit); - DCmd_Register("help", &Debugger::Cmd_Help); - DCmd_Register("mem", &Debugger::Cmd_Mem); - DCmd_Register("tony", &Debugger::Cmd_Tony); - DCmd_Register("res", &Debugger::Cmd_Res); - DCmd_Register("reslist", &Debugger::Cmd_ResList); - DCmd_Register("starts", &Debugger::Cmd_Starts); - DCmd_Register("start", &Debugger::Cmd_Start); - DCmd_Register("s", &Debugger::Cmd_Start); - DCmd_Register("info", &Debugger::Cmd_Info); - DCmd_Register("walkgrid", &Debugger::Cmd_WalkGrid); - DCmd_Register("mouse", &Debugger::Cmd_Mouse); - DCmd_Register("player", &Debugger::Cmd_Player); - DCmd_Register("reslook", &Debugger::Cmd_ResLook); - DCmd_Register("cur", &Debugger::Cmd_CurrentInfo); - DCmd_Register("runlist", &Debugger::Cmd_RunList); - DCmd_Register("kill", &Debugger::Cmd_Kill); - DCmd_Register("nuke", &Debugger::Cmd_Nuke); - DCmd_Register("var", &Debugger::Cmd_Var); - DCmd_Register("rect", &Debugger::Cmd_Rect); - DCmd_Register("clear", &Debugger::Cmd_Clear); - DCmd_Register("debugon", &Debugger::Cmd_DebugOn); - DCmd_Register("debugoff", &Debugger::Cmd_DebugOff); - DCmd_Register("saverest", &Debugger::Cmd_SaveRest); - DCmd_Register("timeon", &Debugger::Cmd_TimeOn); - DCmd_Register("timeoff", &Debugger::Cmd_TimeOff); - DCmd_Register("text", &Debugger::Cmd_Text); - DCmd_Register("showvar", &Debugger::Cmd_ShowVar); - DCmd_Register("hidevar", &Debugger::Cmd_HideVar); - DCmd_Register("version", &Debugger::Cmd_Version); - DCmd_Register("animtest", &Debugger::Cmd_AnimTest); - DCmd_Register("texttest", &Debugger::Cmd_TextTest); - DCmd_Register("linetest", &Debugger::Cmd_LineTest); - DCmd_Register("events", &Debugger::Cmd_Events); - DCmd_Register("sfx", &Debugger::Cmd_Sfx); - DCmd_Register("english", &Debugger::Cmd_English); - DCmd_Register("finnish", &Debugger::Cmd_Finnish); - DCmd_Register("polish", &Debugger::Cmd_Polish); + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("q", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("mem", WRAP_METHOD(Debugger, Cmd_Mem)); + DCmd_Register("tony", WRAP_METHOD(Debugger, Cmd_Tony)); + DCmd_Register("res", WRAP_METHOD(Debugger, Cmd_Res)); + DCmd_Register("reslist", WRAP_METHOD(Debugger, Cmd_ResList)); + DCmd_Register("starts", WRAP_METHOD(Debugger, Cmd_Starts)); + DCmd_Register("start", WRAP_METHOD(Debugger, Cmd_Start)); + DCmd_Register("s", WRAP_METHOD(Debugger, Cmd_Start)); + DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); + DCmd_Register("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid)); + DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + DCmd_Register("player", WRAP_METHOD(Debugger, Cmd_Player)); + DCmd_Register("reslook", WRAP_METHOD(Debugger, Cmd_ResLook)); + DCmd_Register("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo)); + DCmd_Register("runlist", WRAP_METHOD(Debugger, Cmd_RunList)); + DCmd_Register("kill", WRAP_METHOD(Debugger, Cmd_Kill)); + DCmd_Register("nuke", WRAP_METHOD(Debugger, Cmd_Nuke)); + DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_Var)); + DCmd_Register("rect", WRAP_METHOD(Debugger, Cmd_Rect)); + DCmd_Register("clear", WRAP_METHOD(Debugger, Cmd_Clear)); + DCmd_Register("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn)); + DCmd_Register("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff)); + DCmd_Register("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest)); + DCmd_Register("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn)); + DCmd_Register("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff)); + DCmd_Register("text", WRAP_METHOD(Debugger, Cmd_Text)); + DCmd_Register("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar)); + DCmd_Register("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar)); + DCmd_Register("version", WRAP_METHOD(Debugger, Cmd_Version)); + DCmd_Register("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest)); + DCmd_Register("texttest", WRAP_METHOD(Debugger, Cmd_TextTest)); + DCmd_Register("linetest", WRAP_METHOD(Debugger, Cmd_LineTest)); + DCmd_Register("events", WRAP_METHOD(Debugger, Cmd_Events)); + DCmd_Register("sfx", WRAP_METHOD(Debugger, Cmd_Sfx)); + DCmd_Register("english", WRAP_METHOD(Debugger, Cmd_English)); + DCmd_Register("finnish", WRAP_METHOD(Debugger, Cmd_Finnish)); + DCmd_Register("polish", WRAP_METHOD(Debugger, Cmd_Polish)); } void Debugger::varGet(int var) { @@ -157,34 +153,6 @@ void Debugger::postEnter() { // Now the fun stuff: Commands -bool Debugger::Cmd_Exit(int argc, const char **argv) { - _detach_now = true; - _vm->clearInputEvents(); - return false; -} - -bool Debugger::Cmd_Help(int argc, const char **argv) { - // console normally has 78 line width - // wrap around nicely - int width = 0; - - DebugPrintf("Commands are:\n"); - for (int i = 0 ; i < _dcmd_count ; i++) { - int size = strlen(_dcmds[i].name) + 1; - - if (width + size >= 75) { - DebugPrintf("\n"); - width = size; - } else - width += size; - - DebugPrintf("%s ", _dcmds[i].name); - } - - DebugPrintf("\n"); - return true; -} - static int compare_blocks(const void *p1, const void *p2) { const MemBlock *m1 = *(const MemBlock * const *)p1; const MemBlock *m2 = *(const MemBlock * const *)p2; diff --git a/engines/sword2/console.h b/engines/sword2/console.h index 858149d7cb..35c6d582e7 100644 --- a/engines/sword2/console.h +++ b/engines/sword2/console.h @@ -22,12 +22,12 @@ #ifndef SWORD2_CONSOLE_H #define SWORD2_CONSOLE_H -#include "common/debugger.h" +#include "gui/debugger.h" #include "sword2/debug.h" namespace Sword2 { -class Debugger : public Common::Debugger { +class Debugger : public GUI::Debugger { private: void varGet(int var); void varSet(int var, int val); @@ -83,8 +83,6 @@ protected: virtual void postEnter(); // Commands - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); bool Cmd_Mem(int argc, const char **argv); bool Cmd_Tony(int argc, const char **argv); bool Cmd_Res(int argc, const char **argv); diff --git a/gui/console.h b/gui/console.h index d6ac4e3350..8079e2620b 100644 --- a/gui/console.h +++ b/gui/console.h @@ -36,7 +36,6 @@ public: typedef bool (*InputCallbackProc)(ConsoleDialog *console, const char *input, void *refCon); typedef bool (*CompletionCallbackProc)(ConsoleDialog* console, const char *input, char*& completion, void *refCon); -protected: enum { kBufferSize = 32768, kCharsPerLine = 128, @@ -45,6 +44,7 @@ protected: kHistorySize = 20 }; +protected: const Graphics::Font *_font; char _buffer[kBufferSize]; diff --git a/gui/debugger.cpp b/gui/debugger.cpp new file mode 100644 index 0000000000..cde8b22a03 --- /dev/null +++ b/gui/debugger.cpp @@ -0,0 +1,466 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2006 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" + +#include "common/system.h" + +#include "gui/debugger.h" +#if USE_CONSOLE + #include "gui/console.h" +#endif + +namespace GUI { + +Debugger::Debugger() { + _frame_countdown = 0; + _dvar_count = 0; + _dcmd_count = 0; + _detach_now = false; + _isAttached = false; + _errStr = NULL; + _firstTime = true; + _debuggerDialog = new GUI::ConsoleDialog(1.0, 0.67F); + _debuggerDialog->setInputCallback(debuggerInputCallback, this); + _debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this); + + //DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("quit", WRAP_METHOD(Debugger, Cmd_Exit)); + + DCmd_Register("help", WRAP_METHOD(Debugger, Cmd_Help)); + + DCmd_Register("debugflag_list", WRAP_METHOD(Debugger, Cmd_DebugFlagsList)); + DCmd_Register("debugflag_enable", WRAP_METHOD(Debugger, Cmd_DebugFlagEnable)); + DCmd_Register("debugflag_disable", WRAP_METHOD(Debugger, Cmd_DebugFlagDisable)); +} + +Debugger::~Debugger() { + for (int i = 0; i < _dcmd_count; i++) { + delete _dcmds[i].debuglet; + _dcmds[i].debuglet = 0; + } + delete _debuggerDialog; +} + + +// Initialisation Functions +int Debugger::DebugPrintf(const char *format, ...) { + va_list argptr; + + va_start(argptr, format); + int count; +#if USE_CONSOLE + count = _debuggerDialog->vprintf(format, argptr); +#else + count = ::vprintf(format, argptr); +#endif + va_end (argptr); + return count; +} + +#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) +void Debugger::attach(const char *entry) { + + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + + if (entry) { + _errStr = strdup(entry); + } + + _frame_countdown = 1; + _detach_now = false; + _isAttached = true; +} + +void Debugger::detach() { + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + + _detach_now = false; + _isAttached = false; +} + +// Temporary execution handler +void Debugger::onFrame() { + if (_frame_countdown == 0) + return; + --_frame_countdown; + + if (!_frame_countdown) { + + preEnter(); + enter(); + postEnter(); + + // Detach if we're finished with the debugger + if (_detach_now) + detach(); + } +} +#endif // of ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) + +// Main Debugger Loop +void Debugger::enter() { +#if USE_CONSOLE + if (_firstTime) { + DebugPrintf("Debugger started, type 'exit' to return to the game.\n"); + DebugPrintf("Type 'help' to see a little list of commands and variables.\n"); + _firstTime = false; + } + + if (_errStr) { + DebugPrintf("ERROR: %s\n\n", _errStr); + free(_errStr); + _errStr = NULL; + } + + _debuggerDialog->runModal(); +#else + // TODO: compared to the console input, this here is very bare bone. + // For example, no support for tab completion and no history. At least + // we should re-add (optional) support for the readline library. + // Or maybe instead of choosing between a console dialog and stdio, + // we should move that choice into the ConsoleDialog class - that is, + // the console dialog code could be #ifdef'ed to not print to the dialog + // but rather to stdio. This way, we could also reuse the command history + // and tab completion of the console. It would still require a lot of + // work, but at least no dependency on a 3rd party library... + + printf("Debugger entered, please switch to this console for input.\n"); + + int i; + char buf[256]; + + do { + printf("debug> "); + if (!fgets(buf, sizeof(buf), stdin)) + return; + + i = strlen(buf); + while (i > 0 && buf[i - 1] == '\n') + buf[--i] = 0; + + if (i == 0) + continue; + } while (parseCommand(buf)); + +#endif +} + +bool Debugger::handleCommand(int argc, const char **argv, bool &result) { + for (int i = 0; i < _dcmd_count; ++i) { + if (!strcmp(_dcmds[i].name, argv[0])) { + Debuglet *debuglet = _dcmds[i].debuglet; + assert(debuglet); + result = (*debuglet)(argc, argv); + return true; + } + } + + return false; +} + +// Command execution loop +bool Debugger::parseCommand(const char *inputOrig) { + int i = 0, num_params = 0; + const char *param[256]; + char *input = strdup(inputOrig); // One of the rare occasions using strdup is OK (although avoiding strtok might be more elegant here). + + // Parse out any params + char *tok = strtok(input, " "); + if (tok) { + do { + param[num_params++] = tok; + } while ((tok = strtok(NULL, " ")) != NULL); + } else { + param[num_params++] = input; + } + + // Handle commands first + bool result; + if (handleCommand(num_params, param, result)) { + free(input); + return result; + } + + // It's not a command, so things get a little tricky for variables. Do fuzzy matching to ignore things like subscripts. + for (i = 0; i < _dvar_count; i++) { + if (!strncmp(_dvars[i].name, param[0], strlen(_dvars[i].name))) { + if (num_params > 1) { + // Alright, we need to check the TYPE of the variable to deref and stuff... the array stuff is a bit ugly :) + switch (_dvars[i].type) { + // Integer + case DVAR_BYTE: + *(byte *)_dvars[i].variable = atoi(param[1]); + DebugPrintf("byte%s = %d\n", param[0], *(byte *)_dvars[i].variable); + break; + case DVAR_INT: + *(int32 *)_dvars[i].variable = atoi(param[1]); + DebugPrintf("(int)%s = %d\n", param[0], *(int32 *)_dvars[i].variable); + break; + // Integer Array + case DVAR_INTARRAY: { + char *chr = (char *)strchr(param[0], '['); + if (!chr) { + DebugPrintf("You must access this array as %s[element]\n", param[0]); + } else { + int element = atoi(chr+1); + int32 *var = *(int32 **)_dvars[i].variable; + if (element >= _dvars[i].optional) { + DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional); + } else { + var[element] = atoi(param[1]); + DebugPrintf("(int)%s = %d\n", param[0], var[element]); + } + } + } + break; + default: + DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name, param[1]); + break; + } + } else { + // And again, type-dependent prints/defrefs. The array one is still ugly. + switch (_dvars[i].type) { + // Integer + case DVAR_BYTE: + DebugPrintf("(byte)%s = %d\n", param[0], *(const byte *)_dvars[i].variable); + break; + case DVAR_INT: + DebugPrintf("(int)%s = %d\n", param[0], *(const int32 *)_dvars[i].variable); + break; + // Integer array + case DVAR_INTARRAY: { + const char *chr = strchr(param[0], '['); + if (!chr) { + DebugPrintf("You must access this array as %s[element]\n", param[0]); + } else { + int element = atoi(chr+1); + const int32 *var = *(const int32 **)_dvars[i].variable; + if (element >= _dvars[i].optional) { + DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional); + } else { + DebugPrintf("(int)%s = %d\n", param[0], var[element]); + } + } + } + break; + // String + case DVAR_STRING: + DebugPrintf("(string)%s = %s\n", param[0], ((Common::String *)_dvars[i].variable)->c_str()); + break; + default: + DebugPrintf("%s = (unknown type)\n", param[0]); + break; + } + } + + free(input); + return true; + } + } + + DebugPrintf("Unknown command or variable\n"); + free(input); + return true; +} + +// returns true if something has been completed +// completion has to be delete[]-ed then +bool Debugger::tabComplete(const char *input, char*& completion) { + // very basic tab completion + // for now it just supports command completions + + // adding completions of command parameters would be nice (but hard) :-) + // maybe also give a list of possible command completions? + // (but this will require changes to console) + + if (strchr(input, ' ')) + return false; // already finished the first word + + unsigned int inputlen = strlen(input); + + unsigned int matchlen = 0; + char match[30]; // the max. command name is 30 chars + + for (int i = 0; i < _dcmd_count; i++) { + if (!strncmp(_dcmds[i].name, input, inputlen)) { + unsigned int commandlen = strlen(_dcmds[i].name); + if (commandlen == inputlen) { // perfect match + return false; + } + if (commandlen > inputlen) { // possible match + // no previous match + if (matchlen == 0) { + strcpy(match, _dcmds[i].name + inputlen); + matchlen = commandlen - inputlen; + } else { + // take common prefix of previous match and this command + unsigned int j; + for (j = 0; j < matchlen; j++) { + if (match[j] != _dcmds[i].name[inputlen + j]) break; + } + matchlen = j; + } + if (matchlen == 0) + return false; + } + } + } + if (matchlen == 0) + return false; + + completion = new char[matchlen + 1]; + memcpy(completion, match, matchlen); + completion[matchlen] = 0; + return true; +} + +// Variable registration function +void Debugger::DVar_Register(const char *varname, void *pointer, int type, int optional) { + assert(_dvar_count < ARRAYSIZE(_dvars)); + strcpy(_dvars[_dvar_count].name, varname); + _dvars[_dvar_count].type = type; + _dvars[_dvar_count].variable = pointer; + _dvars[_dvar_count].optional = optional; + + _dvar_count++; +} + +// Command registration function +void Debugger::DCmd_Register(const char *cmdname, Debuglet *debuglet) { + assert(_dcmd_count < ARRAYSIZE(_dcmds)); + strcpy(_dcmds[_dcmd_count].name, cmdname); + _dcmds[_dcmd_count].debuglet = debuglet; + + _dcmd_count++; +} + + +// Detach ("exit") the debugger +bool Debugger::Cmd_Exit(int argc, const char **argv) { + _detach_now = true; + return false; +} + +// Print a list of all registered commands (and variables, if any), +// nicely word-wrapped. +bool Debugger::Cmd_Help(int argc, const char **argv) { + + int width, size, i; + + DebugPrintf("Commands are:\n"); + width = 0; + for (i = 0; i < _dcmd_count; i++) { + size = strlen(_dcmds[i].name) + 1; + + if ((width + size) >= GUI::ConsoleDialog::kCharsPerLine) { + DebugPrintf("\n"); + width = size; + } else + width += size; + + DebugPrintf("%s ", _dcmds[i].name); + } + DebugPrintf("\n"); + + if (_dvar_count > 0) { + DebugPrintf("\n"); + DebugPrintf("Variables are:\n"); + width = 0; + for (i = 0; i < _dvar_count; i++) { + size = strlen(_dvars[i].name) + 1; + + if ((width + size) >= GUI::ConsoleDialog::kCharsPerLine) { + DebugPrintf("\n"); + width = size; + } else + width += size; + + DebugPrintf("%s ", _dvars[i].name); + } + DebugPrintf("\n"); + } + + return true; +} + +bool Debugger::Cmd_DebugFlagsList(int argc, const char **argv) { + const Common::Array &debugLevels = Common::listSpecialDebugLevels(); + + DebugPrintf("Engine debug levels:\n"); + DebugPrintf("--------------------\n"); + if (!debugLevels.size()) { + DebugPrintf("No engine debug levels\n"); + return true; + } + for (uint i = 0; i < debugLevels.size(); ++i) { + DebugPrintf("'%s' - Description: %s\n", debugLevels[i].option.c_str(), debugLevels[i].description.c_str()); + } + DebugPrintf("\n"); + return true; +} + +bool Debugger::Cmd_DebugFlagEnable(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("debugflag_enable \n"); + } else { + if (Common::enableSpecialDebugLevel(argv[1])) { + DebugPrintf("Enabled debug flag '%s'\n", argv[1]); + } else { + DebugPrintf("Failed to enable debug flag '%s'\n", argv[1]); + } + } + return true; +} + +bool Debugger::Cmd_DebugFlagDisable(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("debugflag_disable \n"); + } else { + if (Common::disableSpecialDebugLevel(argv[1])) { + DebugPrintf("Disabled debug flag '%s'\n", argv[1]); + } else { + DebugPrintf("Failed to disable debug flag '%s'\n", argv[1]); + } + } + return true; +} + +// Console handler +#if USE_CONSOLE +bool Debugger::debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon) { + Debugger *debugger = (Debugger *)refCon; + + return debugger->parseCommand(input); +} + + +bool Debugger::debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon) { + Debugger *debugger = (Debugger *)refCon; + + return debugger->tabComplete(input, completion); +} + +#endif + +} // End of namespace GUI diff --git a/gui/debugger.h b/gui/debugger.h new file mode 100644 index 0000000000..7b07b1bca3 --- /dev/null +++ b/gui/debugger.h @@ -0,0 +1,158 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2006 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef GUI_DEBUGGER_H +#define GUI_DEBUGGER_H + +namespace GUI { + +// Choose between text console or ScummConsole +#define USE_CONSOLE 1 + +#ifdef USE_CONSOLE +class ConsoleDialog; +#endif + +class Debugger { +public: + Debugger(); + virtual ~Debugger(); + + int DebugPrintf(const char *format, ...); + +#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :) + // FIXME: Fingolfin asks: This code *used* to be a problem when GUI::Debugger + // was a template class. But is it really still causing problems, or can + // this hack go away now? + virtual void onFrame(); + + virtual void attach(const char *entry = 0); +#else + void onFrame() {} + void attach(const char *entry = 0) {} +#endif + bool isAttached() const { return _isAttached; } + +protected: + class Debuglet { + public: + virtual ~Debuglet() {} + virtual bool operator()(int argc, const char **argv) = 0; + }; + + template + class DelegateDebuglet : public Debuglet { + typedef bool (T::*Method)(int argc, const char **argv); + + T *_delegate; + const Method _method; + public: + DelegateDebuglet(T *delegate, Method method) + : _delegate(delegate), _method(method) { + assert(delegate != 0); + } + virtual bool operator()(int argc, const char **argv) { + return (_delegate->*_method)(argc, argv); + }; + }; + + // Convenicence macro for registering a method of a debugger class + // as the current command. + #define WRAP_METHOD(cls, method) \ + new DelegateDebuglet(this, &cls::method) + + enum { + DVAR_BYTE, + DVAR_INT, + DVAR_BOOL, + DVAR_INTARRAY, + DVAR_STRING + }; + + struct DVar { + char name[30]; + void *variable; + int type, optional; + }; + + struct DCmd { + char name[30]; + Debuglet *debuglet; + }; + + int _frame_countdown; + bool _detach_now; + + // TODO: Consider replacing the following two arrays by a Hashmap + + int _dvar_count; + DVar _dvars[256]; + + int _dcmd_count; + DCmd _dcmds[256]; + +private: + bool _isAttached; + char *_errStr; + bool _firstTime; + GUI::ConsoleDialog *_debuggerDialog; + +protected: + // Hook for subclasses: Called just before enter() is run + virtual void preEnter() {} + + // Hook for subclasses: Called just after enter() was run + virtual void postEnter() {} + + // Hook for subclasses: Process the given command line. + // Should return true if and only if argv[0] is a known command and was + // handled, false otherwise. + virtual bool handleCommand(int argc, const char **argv, bool &keepRunning); + + +private: +//protected: + void detach(); + void enter(); + + bool parseCommand(const char *input); + bool tabComplete(const char *input, char*& completion); + +protected: + void DVar_Register(const char *varname, void *pointer, int type, int optional); + void DCmd_Register(const char *cmdname, Debuglet *debuglet); + + bool Cmd_Exit(int argc, const char **argv); + bool Cmd_Help(int argc, const char **argv); + bool Cmd_DebugFlagsList(int argc, const char **argv); + bool Cmd_DebugFlagEnable(int argc, const char **argv); + bool Cmd_DebugFlagDisable(int argc, const char **argv); + +#if USE_CONSOLE +private: + static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon); + static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon); +#endif +}; + +} // End of namespace GUI + +#endif diff --git a/gui/module.mk b/gui/module.mk index 4ec0140be8..bab4b31c94 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS := \ browser.o \ chooser.o \ console.o \ + debugger.o \ dialog.o \ editable.o \ EditTextWidget.o \ -- cgit v1.2.3