From e9898096653965b5cee0d73b4c802f19b07ab57a Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 16 Dec 2002 06:21:08 +0000 Subject: New debugger core. Doesn't really have anything implemented yet, but is far more expandable and userfriendly than our previous. Enable experimental console debugger by default, as I havn't written the text console code yet :) svn-id: r5990 --- gui/console.cpp | 2 +- scumm/debugger.cpp | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scumm/debugger.h | 72 ++++++++++++++++ scumm/module.mk | 3 +- scumm/scummvm.cpp | 7 +- 5 files changed, 316 insertions(+), 8 deletions(-) create mode 100644 scumm/debugger.cpp create mode 100644 scumm/debugger.h diff --git a/gui/console.cpp b/gui/console.cpp index ef8aa12a26..1e3c2c1226 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -37,7 +37,7 @@ This code is not finished, so please don't complain :-) */ -#define PROMPT "$ " +#define PROMPT ") " /* TODO: * - it is very inefficient to redraw the full thingy when just one char is added/removed. diff --git a/scumm/debugger.cpp b/scumm/debugger.cpp new file mode 100644 index 0000000000..50c69495e0 --- /dev/null +++ b/scumm/debugger.cpp @@ -0,0 +1,240 @@ +#include "stdafx.h" +#include "scumm.h" +#include "sound.h" +#include "actor.h" +#include "debugger.h" +#include "common/util.h" + +// The new debugger doesn't actually have the guts for text console coded yet ;) + +#define USE_CONSOLE + +// Choose between text console or ScummConsole +#ifdef USE_CONSOLE + #include "gui/console.h" + #define Debug_Printf _s->_debuggerDialog->printf +#else + #define Debug_Printf printf +#endif + +// Initialisation Functions +void ScummDebugger::attach(Scumm *s) +{ + if (_s) + detach(); + + _s = s; + s->_debugger = this; + _frame_countdown = 1; + _detach_now = false; + + if (_dvar_count < 1) { // We need to register our variables + DVar_Register("debug_countdown", &_frame_countdown, DVAR_INT, 0); + + DVar_Register("scumm_speed", &_s->_fastMode, DVAR_INT, 0); + DVar_Register("scumm_room", &_s->_currentRoom, DVAR_INT, 0); + DVar_Register("scumm_roomresource", &_s->_roomResource, DVAR_INT, 0); + DVar_Register("scumm_vars", &_s->_vars, DVAR_INTARRAY, _s->_numVariables); + + DVar_Register("scumm_gamename", &_s->_game_name, DVAR_STRING, 0); + DVar_Register("scumm_exename", &_s->_exe_name, DVAR_STRING, 0); + DVar_Register("scumm_gameid", &_s->_gameId, DVAR_INT, 0); + } + + if (_dcmd_count < 1) { // We need to register our commands + DCmd_Register("exit", &ScummDebugger::Cmd_Exit); + DCmd_Register("quit", &ScummDebugger::Cmd_Exit); + } +} + +void ScummDebugger::detach() +{ +#ifdef USE_CONSOLE + if (_s->_debuggerDialog) + _s->_debuggerDialog->setInputeCallback(0, 0); +#endif + + _s->_debugger = NULL; + _s = NULL; + _detach_now = false; +} + + +// Temporary execution handler +void ScummDebugger::on_frame() { + if (_frame_countdown == 0) + return; + --_frame_countdown; + + if (!_frame_countdown) { + // Pause sound output + bool old_soundsPaused = _s->_sound->_soundsPaused; + _s->_sound->pauseSounds(true); + + // Enter debugger + enter(); + + _s->_sound->pauseSounds(old_soundsPaused); // Resume previous sound state + + if (_detach_now) // Detach if we're finished with the debugger + detach(); + } +} + +// Console handler +#ifdef USE_CONSOLE +bool ScummDebugger::debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon) +{ + ScummDebugger *debugger = (ScummDebugger *)refCon; + + return debugger->RunCommand((char*)input); +} +#endif + +/////////////////////////////////////////////////// +// Now the fun stuff: + +// Command/Variable registration functions +void ScummDebugger::DVar_Register(char *varname, void *pointer, int type, int optional) { + strcpy(_dvars[_dvar_count].name, varname); + _dvars[_dvar_count].type = type; + _dvars[_dvar_count].variable = pointer; + _dvars[_dvar_count].optional = optional; + + _dvar_count++; +} + +void ScummDebugger::DCmd_Register(char *cmdname, DebugProc pointer) { + strcpy(_dcmds[_dcmd_count].name, cmdname); + _dcmds[_dcmd_count].function = pointer; + + _dcmd_count++; +} + +// Main Debugger Loop +void ScummDebugger::enter() +{ +#ifdef USE_CONSOLE + if (!_s->_debuggerDialog) { + _s->_debuggerDialog = new ConsoleDialog(_s->_newgui); + Debug_Printf("Debugger started, type 'exit' to return to the game\n"); + } + + _s->_debuggerDialog->setInputeCallback(debuggerInputCallback, this); + _s->_debuggerDialog->runModal(); +#else + printf("Debugger entered, please switch to this console for input.\n"); +// while(1) { +// ; +// } +#endif +} + +// Command execution loop +bool ScummDebugger::RunCommand(char *input) { + int i = 0, num_parms = 0; + char parm[255][255]; + + // Parse out any params + char *tok = strtok(input, " "); + if (tok) { + do { + strcpy(parm[num_parms++], tok); + } while ((tok = strtok(NULL, " ")) != NULL); + } else + strcpy(parm[0], input); + + for(i=0;i<_dcmd_count;i++) { + if (!strcmp(_dcmds[i].name, parm[0])) { + DebugProc cmd; + + cmd = _dcmds[i].function; + return (this->*cmd)(); + } + } + + // 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, parm[0], strlen(_dvars[i].name))) { + if (num_parms > 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_INT: + *(int *)_dvars[i].variable = atoi(parm[1]); + Debug_Printf("(int)%s = %d\n", parm[0], *(int *)_dvars[i].variable); + break; + + // Integer Array + case DVAR_INTARRAY: { + char *chr = strchr(parm[0], '['); + if (!chr) { + Debug_Printf("You must access this array as %s[element]\n", parm[0]); + } else { + int element = atoi(chr+1); + int16 *var = *(int16 **)_dvars[i].variable; + if (element > _dvars[i].optional) { + Debug_Printf("%s is out of range (array is %d elements big)\n", parm[0], _dvars[i].optional); + } else { + var[element] = atoi(parm[1]); + Debug_Printf("(int)%s = %d\n", parm[0], var[element]); + + } + } + } + break; + + default: + Debug_Printf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name, parm[1]); + break; + } + } else { + // And again, type-dependent prints/defrefs. The array one is still ugly. + switch(_dvars[i].type) { + // Integer + case DVAR_INT: + Debug_Printf("(int)%s = %d\n", parm[0], *(int *)_dvars[i].variable); + break; + + // Integer array + case DVAR_INTARRAY: { + char *chr = strchr(parm[0], '['); + if (!chr) { + Debug_Printf("You must access this array as %s[element]\n", parm[0]); + } else { + int element = atoi(chr+1); + int16 *var = *(int16 **)_dvars[i].variable; + if (element > _dvars[i].optional) { + Debug_Printf("%s is out of range (array is %d elements big)\n", parm[0], _dvars[i].optional); + } else { + Debug_Printf("(int)%s = %d\n", parm[0], var[element]); + + } + } + } + break; + + // String + case DVAR_STRING: + Debug_Printf("(string)%s = %s\n", parm[0], *(char **)_dvars[i].variable); + break; + + default: + Debug_Printf("%s = (unknown type)\n", parm[0]); + break; + } + } + + return true; + } + } + + Debug_Printf("Unknown command or variable\n"); + return true; +} + +// Commands +bool ScummDebugger::Cmd_Exit() { + _detach_now = true; + return false; +} diff --git a/scumm/debugger.h b/scumm/debugger.h new file mode 100644 index 0000000000..7029b441e5 --- /dev/null +++ b/scumm/debugger.h @@ -0,0 +1,72 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#ifndef DEBUG_H +#define DEBUG_H + +class Scumm; +typedef bool (ScummDebugger::*DebugProc)(); + +enum { + 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; +}; + +class ScummDebugger { +public: + void on_frame(); + void attach(Scumm *s); + +protected: + Scumm *_s; + int _frame_countdown, _dvar_count, _dcmd_count; + DVar _dvars[255]; + DCmd _dcmds[255]; + bool _detach_now; + + void enter(); + void detach(); + + void DVar_Register(char *varname, void *pointer, int type, int optional); + void DCmd_Register(char *cmdname, DebugProc pointer); + bool RunCommand(char *input); + + // Commands + bool Cmd_Exit(); + +#ifdef USE_CONSOLE + static bool ScummDebugger::debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon); +#endif +}; + +#endif diff --git a/scumm/module.mk b/scumm/module.mk index b7caaf620b..57266d38ec 100644 --- a/scumm/module.mk +++ b/scumm/module.mk @@ -6,8 +6,7 @@ SCUMM_OBJS = \ scumm/boxes.o \ scumm/bundle.o \ scumm/costume.o \ - scumm/debug.o \ - scumm/debugrl.o \ + scumm/debugger.o \ scumm/dialogs.o \ scumm/gfx.o \ scumm/imuse.o \ diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index b9d7e19e66..59f68e691c 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -46,6 +46,7 @@ extern void drawError(char*); // Use g_scumm from error() ONLY Scumm *g_scumm = 0; +ScummDebugger g_debugger; extern NewGui *g_gui; @@ -1003,9 +1004,7 @@ void Scumm::saveloadDialog() void Scumm::debuggerDialog() { - if (!_debuggerDialog) - _debuggerDialog = new ConsoleDialog(_newgui); - runDialog(_debuggerDialog); + g_debugger.attach(this); } void Scumm::optionsDialog() @@ -1374,8 +1373,6 @@ void NORETURN CDECL error(const char *s, ...) exit(1); } -ScummDebugger g_debugger; - void Scumm::waitForTimer(int msec_delay) { OSystem::Event event; uint32 start_time; -- cgit v1.2.3