factor out common debugger code
svn-id: r10984
This commit is contained in:
parent
fbd6528e36
commit
a4d2a47820
7 changed files with 659 additions and 802 deletions
358
common/debugger.cpp
Normal file
358
common/debugger.cpp
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001-2003 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "common/debugger.h"
|
||||||
|
|
||||||
|
#if USE_CONSOLE
|
||||||
|
#include "gui/console.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
extern void force_keyboard(bool);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Debugger<T>::Debugger(NewGui *gui) {
|
||||||
|
_frame_countdown = 0;
|
||||||
|
_dvar_count = 0;
|
||||||
|
_dcmd_count = 0;
|
||||||
|
_detach_now = false;
|
||||||
|
_isAttached = false;
|
||||||
|
_errStr = NULL;
|
||||||
|
_firstTime = true;
|
||||||
|
_debuggerDialog = new ConsoleDialog(gui, 1.0, 0.67F);
|
||||||
|
_debuggerDialog->setInputCallback(debuggerInputCallback, this);
|
||||||
|
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Debugger<T>::~Debugger() {
|
||||||
|
delete _debuggerDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Initialisation Functions
|
||||||
|
template <class T>
|
||||||
|
int Debugger<T>::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Debugger<T>::attach(const char *entry) {
|
||||||
|
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
force_keyboard(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
_errStr = strdup(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
_frame_countdown = 1;
|
||||||
|
_detach_now = false;
|
||||||
|
_isAttached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Debugger<T>::detach() {
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
force_keyboard(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_detach_now = false;
|
||||||
|
_isAttached = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary execution handler
|
||||||
|
template <class T>
|
||||||
|
void Debugger<T>::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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main Debugger Loop
|
||||||
|
template <class T>
|
||||||
|
void Debugger<T>::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 <class T>
|
||||||
|
bool Debugger<T>::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_INT:
|
||||||
|
*(int *)_dvars[i].variable = atoi(param[1]);
|
||||||
|
DebugPrintf("(int)%s = %d\n", param[0], *(int *)_dvars[i].variable);
|
||||||
|
break;
|
||||||
|
// Integer Array
|
||||||
|
case DVAR_INTARRAY: {
|
||||||
|
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);
|
||||||
|
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_INT:
|
||||||
|
DebugPrintf("(int)%s = %d\n", param[0], *(int *)_dvars[i].variable);
|
||||||
|
break;
|
||||||
|
// Integer array
|
||||||
|
case DVAR_INTARRAY: {
|
||||||
|
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);
|
||||||
|
int16 *var = *(int16 **)_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 <class T>
|
||||||
|
bool Debugger<T>::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 <class T>
|
||||||
|
void Debugger<T>::DVar_Register(const char *varname, void *pointer, int type, int optional) {
|
||||||
|
assert(_dvar_count < (int)sizeof(_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 <class T>
|
||||||
|
void Debugger<T>::DCmd_Register(const char *cmdname, DebugProc pointer) {
|
||||||
|
assert(_dcmd_count < (int)sizeof(_dcmds));
|
||||||
|
strcpy(_dcmds[_dcmd_count].name, cmdname);
|
||||||
|
_dcmds[_dcmd_count].function = pointer;
|
||||||
|
|
||||||
|
_dcmd_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Console handler
|
||||||
|
#if USE_CONSOLE
|
||||||
|
template <class T>
|
||||||
|
bool Debugger<T>::debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon) {
|
||||||
|
Debugger *debugger = (Debugger *)refCon;
|
||||||
|
|
||||||
|
return debugger->RunCommand(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool Debugger<T>::debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon) {
|
||||||
|
Debugger *debugger = (Debugger *)refCon;
|
||||||
|
|
||||||
|
return debugger->TabComplete(input, completion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // End of namespace Common
|
98
common/debugger.h
Normal file
98
common/debugger.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2002-2003 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 COMMON_DEBUGGER_H
|
||||||
|
#define COMMON_DEBUGGER_H
|
||||||
|
|
||||||
|
class ConsoleDialog;
|
||||||
|
class NewGui;
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// Choose between text console or ScummConsole
|
||||||
|
#define USE_CONSOLE 1
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Debugger {
|
||||||
|
public:
|
||||||
|
Debugger(NewGui *gui);
|
||||||
|
virtual ~Debugger();
|
||||||
|
|
||||||
|
int DebugPrintf(const char *format, ...);
|
||||||
|
|
||||||
|
virtual void onFrame();
|
||||||
|
|
||||||
|
virtual void attach(const char *entry = 0);
|
||||||
|
bool isAttached() const { return _isAttached; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef bool (T::*DebugProc)(int argc, const char **argv);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
int _frame_countdown, _dvar_count, _dcmd_count;
|
||||||
|
DVar _dvars[256];
|
||||||
|
DCmd _dcmds[256];
|
||||||
|
bool _detach_now;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _isAttached;
|
||||||
|
char *_errStr;
|
||||||
|
bool _firstTime;
|
||||||
|
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);
|
||||||
|
|
||||||
|
#if USE_CONSOLE
|
||||||
|
static bool debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon);
|
||||||
|
static bool debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Common
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,30 +33,15 @@
|
||||||
#include "scumm/scumm.h"
|
#include "scumm/scumm.h"
|
||||||
#include "scumm/sound.h"
|
#include "scumm/sound.h"
|
||||||
|
|
||||||
#if USE_CONSOLE
|
#include "common/debugger.cpp"
|
||||||
#include "gui/console.h"
|
|
||||||
#define Debug_Printf _debuggerDialog->printf
|
|
||||||
#else
|
|
||||||
#define Debug_Printf printf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
extern void force_keyboard(bool);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern uint16 _debugLevel;
|
extern uint16 _debugLevel;
|
||||||
|
|
||||||
namespace Scumm {
|
namespace Scumm {
|
||||||
|
|
||||||
ScummDebugger::ScummDebugger(ScummEngine *s) {
|
ScummDebugger::ScummDebugger(ScummEngine *s)
|
||||||
|
: Common::Debugger<ScummDebugger>(s->_newgui) {
|
||||||
_vm = s;
|
_vm = s;
|
||||||
_frame_countdown = 0;
|
|
||||||
_dvar_count = 0;
|
|
||||||
_dcmd_count = 0;
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = false;
|
|
||||||
_errStr = NULL;
|
|
||||||
_debuggerDialog = NULL;
|
|
||||||
|
|
||||||
// Register variables
|
// Register variables
|
||||||
DVar_Register("debug_countdown", &_frame_countdown, DVAR_INT, 0);
|
DVar_Register("debug_countdown", &_frame_countdown, DVAR_INT, 0);
|
||||||
|
@ -103,248 +88,20 @@ ScummDebugger::ScummDebugger(ScummEngine *s) {
|
||||||
DCmd_Register("imuse", &ScummDebugger::Cmd_IMuse);
|
DCmd_Register("imuse", &ScummDebugger::Cmd_IMuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialisation Functions
|
void ScummDebugger::preEnter() {
|
||||||
void ScummDebugger::attach(const char *entry) {
|
// Pause sound output
|
||||||
|
_old_soundsPaused = _vm->_sound->_soundsPaused;
|
||||||
#ifdef _WIN32_WCE
|
_vm->_sound->pauseSounds(true);
|
||||||
force_keyboard(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
_errStr = strdup(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
_frame_countdown = 1;
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScummDebugger::detach() {
|
void ScummDebugger::postEnter() {
|
||||||
#if USE_CONSOLE
|
// Resume previous sound state
|
||||||
if (_debuggerDialog) {
|
_vm->_sound->pauseSounds(_old_soundsPaused);
|
||||||
_debuggerDialog->setInputCallback(0, 0);
|
|
||||||
_debuggerDialog->setCompletionCallback(0, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
force_keyboard(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary execution handler
|
|
||||||
void ScummDebugger::onFrame() {
|
|
||||||
if (_frame_countdown == 0)
|
|
||||||
return;
|
|
||||||
--_frame_countdown;
|
|
||||||
|
|
||||||
if (!_frame_countdown) {
|
|
||||||
// Pause sound output
|
|
||||||
bool old_soundsPaused = _vm->_sound->_soundsPaused;
|
|
||||||
_vm->_sound->pauseSounds(true);
|
|
||||||
|
|
||||||
// Enter debugger
|
|
||||||
enter();
|
|
||||||
|
|
||||||
_vm->_sound->pauseSounds(old_soundsPaused); // Resume previous sound state
|
|
||||||
|
|
||||||
if (_detach_now) // Detach if we're finished with the debugger
|
|
||||||
detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Console handler
|
|
||||||
#if USE_CONSOLE
|
|
||||||
bool ScummDebugger::debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon) {
|
|
||||||
ScummDebugger *debugger = (ScummDebugger *)refCon;
|
|
||||||
|
|
||||||
return debugger->RunCommand(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ScummDebugger::debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon) {
|
|
||||||
ScummDebugger *debugger = (ScummDebugger *)refCon;
|
|
||||||
|
|
||||||
return debugger->TabComplete(input, completion);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
// Now the fun stuff:
|
// Now the fun stuff:
|
||||||
|
|
||||||
// Command/Variable registration functions
|
|
||||||
void ScummDebugger::DVar_Register(const char *varname, void *pointer, int type, int optional) {
|
|
||||||
assert(_dvar_count < (int)sizeof(_dvars));
|
|
||||||
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(const char *cmdname, DebugProc pointer) {
|
|
||||||
assert(_dcmd_count < (int)sizeof(_dcmds));
|
|
||||||
strcpy(_dcmds[_dcmd_count].name, cmdname);
|
|
||||||
_dcmds[_dcmd_count].function = pointer;
|
|
||||||
|
|
||||||
_dcmd_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main Debugger Loop
|
|
||||||
void ScummDebugger::enter() {
|
|
||||||
#if USE_CONSOLE
|
|
||||||
if (!_debuggerDialog) {
|
|
||||||
_debuggerDialog = new ConsoleDialog(_vm->_newgui, 1.0, 0.67F);
|
|
||||||
|
|
||||||
Debug_Printf("Debugger started, type 'exit' to return to the game.\n");
|
|
||||||
Debug_Printf("Type 'help' to see a little list of commands and variables.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_errStr) {
|
|
||||||
Debug_Printf("ERROR: %s\n\n", _errStr);
|
|
||||||
free(_errStr);
|
|
||||||
_errStr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_debuggerDialog->setInputCallback(debuggerInputCallback, this);
|
|
||||||
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
|
|
||||||
_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
|
|
||||||
bool ScummDebugger::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 = (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_INT:
|
|
||||||
*(int *)_dvars[i].variable = atoi(param[1]);
|
|
||||||
Debug_Printf("(int)%s = %d\n", param[0], *(int *)_dvars[i].variable);
|
|
||||||
break;
|
|
||||||
// Integer Array
|
|
||||||
case DVAR_INTARRAY: {
|
|
||||||
char *chr = strchr(param[0], '[');
|
|
||||||
if (!chr) {
|
|
||||||
Debug_Printf("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) {
|
|
||||||
Debug_Printf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional);
|
|
||||||
} else {
|
|
||||||
var[element] = atoi(param[1]);
|
|
||||||
Debug_Printf("(int)%s = %d\n", param[0], var[element]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug_Printf("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_INT:
|
|
||||||
Debug_Printf("(int)%s = %d\n", param[0], *(int *)_dvars[i].variable);
|
|
||||||
break;
|
|
||||||
// Integer array
|
|
||||||
case DVAR_INTARRAY: {
|
|
||||||
char *chr = strchr(param[0], '[');
|
|
||||||
if (!chr) {
|
|
||||||
Debug_Printf("You must access this array as %s[element]\n", param[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", param[0], _dvars[i].optional);
|
|
||||||
} else {
|
|
||||||
Debug_Printf("(int)%s = %d\n", param[0], var[element]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// String
|
|
||||||
case DVAR_STRING:
|
|
||||||
Debug_Printf("(string)%s = %s\n", param[0], ((Common::String *)_dvars[i].variable)->c_str());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug_Printf("%s = (unknown type)\n", param[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug_Printf("Unknown command or variable\n");
|
|
||||||
free(input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
bool ScummDebugger::Cmd_Exit(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_Exit(int argc, const char **argv) {
|
||||||
_detach_now = true;
|
_detach_now = true;
|
||||||
|
@ -360,61 +117,61 @@ bool ScummDebugger::Cmd_Restart(int argc, const char **argv) {
|
||||||
|
|
||||||
bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) {
|
||||||
if (!_vm->_imuse && !_vm->_musicEngine) {
|
if (!_vm->_imuse && !_vm->_musicEngine) {
|
||||||
Debug_Printf("No iMuse engine is active.\n");
|
DebugPrintf("No iMuse engine is active.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if (!strcmp(argv[1], "panic")) {
|
if (!strcmp(argv[1], "panic")) {
|
||||||
_vm->_musicEngine->stopAllSounds();
|
_vm->_musicEngine->stopAllSounds();
|
||||||
Debug_Printf("AAAIIIEEEEEE!\n");
|
DebugPrintf("AAAIIIEEEEEE!\n");
|
||||||
Debug_Printf("Shutting down all music tracks\n");
|
DebugPrintf("Shutting down all music tracks\n");
|
||||||
return true;
|
return true;
|
||||||
} else if (!strcmp (argv[1], "multimidi")) {
|
} else if (!strcmp (argv[1], "multimidi")) {
|
||||||
if (argc > 2 && (!strcmp(argv[2], "on") || !strcmp(argv[2], "off"))) {
|
if (argc > 2 && (!strcmp(argv[2], "on") || !strcmp(argv[2], "off"))) {
|
||||||
if (_vm->_imuse)
|
if (_vm->_imuse)
|
||||||
_vm->_imuse->property(IMuse::PROP_MULTI_MIDI, !strcmp(argv[2], "on"));
|
_vm->_imuse->property(IMuse::PROP_MULTI_MIDI, !strcmp(argv[2], "on"));
|
||||||
Debug_Printf("MultiMidi mode switched %s.\n", argv[2]);
|
DebugPrintf("MultiMidi mode switched %s.\n", argv[2]);
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Specify \"on\" or \"off\" to switch.\n");
|
DebugPrintf("Specify \"on\" or \"off\" to switch.\n");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (!strcmp(argv[1], "play")) {
|
} else if (!strcmp(argv[1], "play")) {
|
||||||
if (argc > 2 && (!strcmp(argv[2], "random") || atoi(argv[2]) != 0)) {
|
if (argc > 2 && (!strcmp(argv[2], "random") || atoi(argv[2]) != 0)) {
|
||||||
int sound = atoi(argv[2]);
|
int sound = atoi(argv[2]);
|
||||||
if (!strcmp(argv[2], "random")) {
|
if (!strcmp(argv[2], "random")) {
|
||||||
Debug_Printf("Selecting from %d songs...\n", _vm->getNumSounds());
|
DebugPrintf("Selecting from %d songs...\n", _vm->getNumSounds());
|
||||||
sound = _vm->_rnd.getRandomNumber(_vm->getNumSounds());
|
sound = _vm->_rnd.getRandomNumber(_vm->getNumSounds());
|
||||||
}
|
}
|
||||||
_vm->ensureResourceLoaded(rtSound, sound);
|
_vm->ensureResourceLoaded(rtSound, sound);
|
||||||
_vm->_musicEngine->startSound(sound);
|
_vm->_musicEngine->startSound(sound);
|
||||||
|
|
||||||
Debug_Printf("Attempted to start music %d.\n", sound);
|
DebugPrintf("Attempted to start music %d.\n", sound);
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Specify a music resource # from 1-255.\n");
|
DebugPrintf("Specify a music resource # from 1-255.\n");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (!strcmp(argv[1], "stop")) {
|
} else if (!strcmp(argv[1], "stop")) {
|
||||||
if (argc > 2 && (!strcmp(argv[2], "all") || atoi(argv[2]) != 0)) {
|
if (argc > 2 && (!strcmp(argv[2], "all") || atoi(argv[2]) != 0)) {
|
||||||
if (!strcmp(argv[2], "all")) {
|
if (!strcmp(argv[2], "all")) {
|
||||||
_vm->_musicEngine->stopAllSounds();
|
_vm->_musicEngine->stopAllSounds();
|
||||||
Debug_Printf("Shutting down all music tracks.\n");
|
DebugPrintf("Shutting down all music tracks.\n");
|
||||||
} else {
|
} else {
|
||||||
_vm->_musicEngine->stopSound(atoi(argv[2]));
|
_vm->_musicEngine->stopSound(atoi(argv[2]));
|
||||||
Debug_Printf("Attempted to stop music %d.\n", atoi(argv[2]));
|
DebugPrintf("Attempted to stop music %d.\n", atoi(argv[2]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Specify a music resource # or \"all\".\n");
|
DebugPrintf("Specify a music resource # or \"all\".\n");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug_Printf("Available iMuse commands:\n");
|
DebugPrintf("Available iMuse commands:\n");
|
||||||
Debug_Printf(" panic - Stop all music tracks\n");
|
DebugPrintf(" panic - Stop all music tracks\n");
|
||||||
Debug_Printf(" multimidi on/off - Toggle dual MIDI drivers\n");
|
DebugPrintf(" multimidi on/off - Toggle dual MIDI drivers\n");
|
||||||
Debug_Printf(" play # - Play a music resource\n");
|
DebugPrintf(" play # - Play a music resource\n");
|
||||||
Debug_Printf(" stop # - Stop a music resource\n");
|
DebugPrintf(" stop # - Stop a music resource\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +184,7 @@ bool ScummDebugger::Cmd_Room(int argc, const char **argv) {
|
||||||
_vm->_fullRedraw = 1;
|
_vm->_fullRedraw = 1;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource);
|
DebugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,7 +201,7 @@ bool ScummDebugger::Cmd_LoadGame(int argc, const char **argv) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug_Printf("Syntax: loadgame <slotnum>\n");
|
DebugPrintf("Syntax: loadgame <slotnum>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +214,7 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) {
|
||||||
_vm->_saveLoadFlag = 1;
|
_vm->_saveLoadFlag = 1;
|
||||||
_vm->_saveLoadCompatible = false;
|
_vm->_saveLoadCompatible = false;
|
||||||
} else
|
} else
|
||||||
Debug_Printf("Syntax: savegame <slotnum> <name>\n");
|
DebugPrintf("Syntax: savegame <slotnum> <name>\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -465,18 +222,18 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) {
|
||||||
bool ScummDebugger::Cmd_Show(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_Show(int argc, const char **argv) {
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Syntax: show <parameter>\n");
|
DebugPrintf("Syntax: show <parameter>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(argv[1], "hex")) {
|
if (!strcmp(argv[1], "hex")) {
|
||||||
_vm->_hexdumpScripts = true;
|
_vm->_hexdumpScripts = true;
|
||||||
Debug_Printf("Script hex dumping on\n");
|
DebugPrintf("Script hex dumping on\n");
|
||||||
} else if (!strncmp(argv[1], "sta", 3)) {
|
} else if (!strncmp(argv[1], "sta", 3)) {
|
||||||
_vm->_showStack = 1;
|
_vm->_showStack = 1;
|
||||||
Debug_Printf("Stack tracing on\n");
|
DebugPrintf("Stack tracing on\n");
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]);
|
DebugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -484,18 +241,18 @@ bool ScummDebugger::Cmd_Show(int argc, const char **argv) {
|
||||||
bool ScummDebugger::Cmd_Hide(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_Hide(int argc, const char **argv) {
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Syntax: hide <parameter>\n");
|
DebugPrintf("Syntax: hide <parameter>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(argv[1], "hex")) {
|
if (!strcmp(argv[1], "hex")) {
|
||||||
_vm->_hexdumpScripts = false;
|
_vm->_hexdumpScripts = false;
|
||||||
Debug_Printf("Script hex dumping off\n");
|
DebugPrintf("Script hex dumping off\n");
|
||||||
} else if (!strncmp(argv[1], "sta", 3)) {
|
} else if (!strncmp(argv[1], "sta", 3)) {
|
||||||
_vm->_showStack = 0;
|
_vm->_showStack = 0;
|
||||||
Debug_Printf("Stack tracing off\n");
|
DebugPrintf("Stack tracing off\n");
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]);
|
DebugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +261,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
|
||||||
int scriptnum;
|
int scriptnum;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
Debug_Printf("Syntax: script <scriptnum> <command>\n");
|
DebugPrintf("Syntax: script <scriptnum> <command>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +269,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
|
||||||
|
|
||||||
// FIXME: what is the max range on these?
|
// FIXME: what is the max range on these?
|
||||||
// if (scriptnum >= _vm->_maxScripts) {
|
// if (scriptnum >= _vm->_maxScripts) {
|
||||||
// Debug_Printf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_maxScripts);
|
// DebugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_maxScripts);
|
||||||
// return true;
|
// return true;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -522,7 +279,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
|
||||||
_vm->runScript(scriptnum, 0, 0, 0);
|
_vm->runScript(scriptnum, 0, 0, 0);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]);
|
DebugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -534,7 +291,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
|
||||||
int resnum;
|
int resnum;
|
||||||
|
|
||||||
if (argc != 4) {
|
if (argc != 4) {
|
||||||
Debug_Printf("Syntax: importres <restype> <filename> <resnum>\n");
|
DebugPrintf("Syntax: importres <restype> <filename> <resnum>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +301,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
|
||||||
if (!strncmp(argv[1], "scr", 3)) {
|
if (!strncmp(argv[1], "scr", 3)) {
|
||||||
file.open(argv[2], "");
|
file.open(argv[2], "");
|
||||||
if (file.isOpen() == false) {
|
if (file.isOpen() == false) {
|
||||||
Debug_Printf("Could not open file %s\n", argv[2]);
|
DebugPrintf("Could not open file %s\n", argv[2]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (_vm->_features & GF_SMALL_HEADER) {
|
if (_vm->_features & GF_SMALL_HEADER) {
|
||||||
|
@ -565,25 +322,25 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
|
||||||
file.read(_vm->createResource(rtScript, resnum, size), size);
|
file.read(_vm->createResource(rtScript, resnum, size), size);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
Debug_Printf("Unknown importres type '%s'\n", argv[1]);
|
DebugPrintf("Unknown importres type '%s'\n", argv[1]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScummDebugger::Cmd_PrintScript(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_PrintScript(int argc, const char **argv) {
|
||||||
int i;
|
int i;
|
||||||
ScriptSlot *ss = _vm->vm.slot;
|
ScriptSlot *ss = _vm->vm.slot;
|
||||||
Debug_Printf("+--------------------------------------+\n");
|
DebugPrintf("+--------------------------------------+\n");
|
||||||
Debug_Printf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n");
|
DebugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n");
|
||||||
Debug_Printf("+--+----+-----+---+---+--+---+--+---+\n");
|
DebugPrintf("+--+----+-----+---+---+--+---+--+---+\n");
|
||||||
for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) {
|
for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) {
|
||||||
if (ss->number) {
|
if (ss->number) {
|
||||||
Debug_Printf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n",
|
DebugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n",
|
||||||
i, ss->number, ss->offs, ss->status, ss->where,
|
i, ss->number, ss->offs, ss->status, ss->where,
|
||||||
ss->freezeResistant, ss->recursive,
|
ss->freezeResistant, ss->recursive,
|
||||||
ss->freezeCount, ss->cutsceneOverride);
|
ss->freezeCount, ss->cutsceneOverride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug_Printf("+--------------------------------------+\n");
|
DebugPrintf("+--------------------------------------+\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -594,13 +351,13 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) {
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
Debug_Printf("Syntax: actor <actornum> <command> <parameter>\n");
|
DebugPrintf("Syntax: actor <actornum> <command> <parameter>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
actnum = atoi(argv[1]);
|
actnum = atoi(argv[1]);
|
||||||
if (actnum >= _vm->_numActors) {
|
if (actnum >= _vm->_numActors) {
|
||||||
Debug_Printf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors);
|
DebugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,31 +366,31 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) {
|
||||||
|
|
||||||
if (!strcmp(argv[2], "ignoreboxes")) {
|
if (!strcmp(argv[2], "ignoreboxes")) {
|
||||||
a->ignoreBoxes = (value > 0);
|
a->ignoreBoxes = (value > 0);
|
||||||
Debug_Printf("Actor[%d].ignoreBoxes = %d\n", actnum, a->ignoreBoxes);
|
DebugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->ignoreBoxes);
|
||||||
} else if (!strcmp(argv[2], "x")) {
|
} else if (!strcmp(argv[2], "x")) {
|
||||||
a->putActor(value, a->_pos.y, a->room);
|
a->putActor(value, a->_pos.y, a->room);
|
||||||
Debug_Printf("Actor[%d].x = %d\n", actnum, a->_pos.x);
|
DebugPrintf("Actor[%d].x = %d\n", actnum, a->_pos.x);
|
||||||
_vm->_fullRedraw = 1;
|
_vm->_fullRedraw = 1;
|
||||||
} else if (!strcmp(argv[2], "y")) {
|
} else if (!strcmp(argv[2], "y")) {
|
||||||
a->putActor(a->_pos.x, value, a->room);
|
a->putActor(a->_pos.x, value, a->room);
|
||||||
Debug_Printf("Actor[%d].y = %d\n", actnum, a->_pos.y);
|
DebugPrintf("Actor[%d].y = %d\n", actnum, a->_pos.y);
|
||||||
_vm->_fullRedraw = 1;
|
_vm->_fullRedraw = 1;
|
||||||
} else if (!strcmp(argv[2], "elevation")) {
|
} else if (!strcmp(argv[2], "elevation")) {
|
||||||
a->elevation = value;
|
a->elevation = value;
|
||||||
Debug_Printf("Actor[%d].elevation = %d\n", actnum, a->elevation);
|
DebugPrintf("Actor[%d].elevation = %d\n", actnum, a->elevation);
|
||||||
_vm->_fullRedraw = 1;
|
_vm->_fullRedraw = 1;
|
||||||
} else if (!strcmp(argv[2], "costume")) {
|
} else if (!strcmp(argv[2], "costume")) {
|
||||||
if (value >= _vm->res.num[rtCostume])
|
if (value >= _vm->res.num[rtCostume])
|
||||||
Debug_Printf("Costume not changed as %d exceeds max of %d\n", value, _vm->res.num[rtCostume]);
|
DebugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->res.num[rtCostume]);
|
||||||
else {
|
else {
|
||||||
a->setActorCostume( value );
|
a->setActorCostume( value );
|
||||||
_vm->_fullRedraw = 1;
|
_vm->_fullRedraw = 1;
|
||||||
Debug_Printf("Actor[%d].costume = %d\n", actnum, a->costume);
|
DebugPrintf("Actor[%d].costume = %d\n", actnum, a->costume);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[2], "name")) {
|
} else if (!strcmp(argv[2], "name")) {
|
||||||
Debug_Printf("Name of actor %d: %s\n", actnum, _vm->getObjOrActorName(actnum));
|
DebugPrintf("Name of actor %d: %s\n", actnum, _vm->getObjOrActorName(actnum));
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]);
|
DebugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -643,35 +400,35 @@ bool ScummDebugger::Cmd_PrintActor(int argc, const char **argv) {
|
||||||
int i;
|
int i;
|
||||||
Actor *a;
|
Actor *a;
|
||||||
|
|
||||||
Debug_Printf("+----------------------------------------------------------------+\n");
|
DebugPrintf("+----------------------------------------------------------------+\n");
|
||||||
Debug_Printf("|# |room| x | y |elev|cos|width|box|mov| zp|frame|scale|dir|cls|\n");
|
DebugPrintf("|# |room| x | y |elev|cos|width|box|mov| zp|frame|scale|dir|cls|\n");
|
||||||
Debug_Printf("+--+----+----+----+----+---+-----+---+---+---+-----+-----+---+---+\n");
|
DebugPrintf("+--+----+----+----+----+---+-----+---+---+---+-----+-----+---+---+\n");
|
||||||
for (i = 1; i < _vm->_numActors; i++) {
|
for (i = 1; i < _vm->_numActors; i++) {
|
||||||
a = &_vm->_actors[i];
|
a = &_vm->_actors[i];
|
||||||
if (a->visible)
|
if (a->visible)
|
||||||
Debug_Printf("|%2d|%4d|%4d|%4d|%4d|%3d|%5d|%3d|%3d|%3d|%5d|%5d|%3d|$%02x|\n",
|
DebugPrintf("|%2d|%4d|%4d|%4d|%4d|%3d|%5d|%3d|%3d|%3d|%5d|%5d|%3d|$%02x|\n",
|
||||||
a->number, a->room, a->_pos.x, a->_pos.y, a->elevation, a->costume,
|
a->number, a->room, a->_pos.x, a->_pos.y, a->elevation, a->costume,
|
||||||
a->width, a->walkbox, a->moving, a->forceClip, a->frame,
|
a->width, a->walkbox, a->moving, a->forceClip, a->frame,
|
||||||
a->scalex, a->getFacing(), int(_vm->_classData[a->number]&0xFF));
|
a->scalex, a->getFacing(), int(_vm->_classData[a->number]&0xFF));
|
||||||
}
|
}
|
||||||
Debug_Printf("+----------------------------------------------------------------+\n");
|
DebugPrintf("+----------------------------------------------------------------+\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScummDebugger::Cmd_PrintObjects(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_PrintObjects(int argc, const char **argv) {
|
||||||
int i;
|
int i;
|
||||||
ObjectData *o;
|
ObjectData *o;
|
||||||
Debug_Printf("Objects in current room\n");
|
DebugPrintf("Objects in current room\n");
|
||||||
Debug_Printf("+---------------------------------+--+\n");
|
DebugPrintf("+---------------------------------+--+\n");
|
||||||
Debug_Printf("|num | x | y |width|height|state|fl|\n");
|
DebugPrintf("|num | x | y |width|height|state|fl|\n");
|
||||||
Debug_Printf("+----+----+----+-----+------+-----+--+\n");
|
DebugPrintf("+----+----+----+-----+------+-----+--+\n");
|
||||||
|
|
||||||
for (i = 1; (i < _vm->_numLocalObjects) && (_vm->_objs[i].obj_nr != 0) ; i++) {
|
for (i = 1; (i < _vm->_numLocalObjects) && (_vm->_objs[i].obj_nr != 0) ; i++) {
|
||||||
o = &(_vm->_objs[i]);
|
o = &(_vm->_objs[i]);
|
||||||
Debug_Printf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|\n",
|
DebugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|\n",
|
||||||
o->obj_nr, o->x_pos, o->y_pos, o->width, o->height, o->state, o->fl_object_index);
|
o->obj_nr, o->x_pos, o->y_pos, o->width, o->height, o->state, o->fl_object_index);
|
||||||
}
|
}
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,13 +437,13 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
|
||||||
int obj;
|
int obj;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
Debug_Printf("Syntax: object <objectnum> <command> <parameter>\n");
|
DebugPrintf("Syntax: object <objectnum> <command> <parameter>\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = atoi(argv[1]);
|
obj = atoi(argv[1]);
|
||||||
if (obj >= _vm->_numGlobalObjects) {
|
if (obj >= _vm->_numGlobalObjects) {
|
||||||
Debug_Printf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects);
|
DebugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,9 +472,9 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
|
||||||
//is BgNeedsRedraw enough?
|
//is BgNeedsRedraw enough?
|
||||||
_vm->_BgNeedsRedraw = true;
|
_vm->_BgNeedsRedraw = true;
|
||||||
} else if (!strcmp(argv[2], "name")) {
|
} else if (!strcmp(argv[2], "name")) {
|
||||||
Debug_Printf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj));
|
DebugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj));
|
||||||
} else {
|
} else {
|
||||||
Debug_Printf("Unknown object command '%s'\nUse <pickup | state> as command\n", argv[2]);
|
DebugPrintf("Unknown object command '%s'\nUse <pickup | state> as command\n", argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -728,35 +485,35 @@ bool ScummDebugger::Cmd_Help(int argc, const char **argv) {
|
||||||
// wrap around nicely
|
// wrap around nicely
|
||||||
int width = 0, size, i;
|
int width = 0, size, i;
|
||||||
|
|
||||||
Debug_Printf("Commands are:\n");
|
DebugPrintf("Commands are:\n");
|
||||||
for (i = 0 ; i < _dcmd_count ; i++) {
|
for (i = 0 ; i < _dcmd_count ; i++) {
|
||||||
size = strlen(_dcmds[i].name) + 1;
|
size = strlen(_dcmds[i].name) + 1;
|
||||||
|
|
||||||
if ((width + size) >= 39) {
|
if ((width + size) >= 39) {
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
width = size;
|
width = size;
|
||||||
} else
|
} else
|
||||||
width += size;
|
width += size;
|
||||||
|
|
||||||
Debug_Printf("%s ", _dcmds[i].name);
|
DebugPrintf("%s ", _dcmds[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
width = 0;
|
width = 0;
|
||||||
|
|
||||||
Debug_Printf("\n\nVariables are:\n");
|
DebugPrintf("\n\nVariables are:\n");
|
||||||
for (i = 0 ; i < _dvar_count ; i++) {
|
for (i = 0 ; i < _dvar_count ; i++) {
|
||||||
size = strlen(_dvars[i].name) + 1;
|
size = strlen(_dvars[i].name) + 1;
|
||||||
|
|
||||||
if ((width + size) >= 39) {
|
if ((width + size) >= 39) {
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
width = size;
|
width = size;
|
||||||
} else
|
} else
|
||||||
width += size;
|
width += size;
|
||||||
|
|
||||||
Debug_Printf("%s ", _dvars[i].name);
|
DebugPrintf("%s ", _dvars[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -764,20 +521,20 @@ bool ScummDebugger::Cmd_Help(int argc, const char **argv) {
|
||||||
bool ScummDebugger::Cmd_DebugLevel(int argc, const char **argv) {
|
bool ScummDebugger::Cmd_DebugLevel(int argc, const char **argv) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
if (_vm->_debugMode == false)
|
if (_vm->_debugMode == false)
|
||||||
Debug_Printf("Debugging is not enabled at this time\n");
|
DebugPrintf("Debugging is not enabled at this time\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Debugging is currently set at level %d\n", _debugLevel);
|
DebugPrintf("Debugging is currently set at level %d\n", _debugLevel);
|
||||||
} else { // set level
|
} else { // set level
|
||||||
int level = atoi(argv[1]);
|
int level = atoi(argv[1]);
|
||||||
_debugLevel = level;
|
_debugLevel = level;
|
||||||
if (level > 0) {
|
if (level > 0) {
|
||||||
_vm->_debugMode = true;
|
_vm->_debugMode = true;
|
||||||
Debug_Printf("Debug level set to level %d\n", level);
|
DebugPrintf("Debug level set to level %d\n", level);
|
||||||
} else if (level == 0) {
|
} else if (level == 0) {
|
||||||
_vm->_debugMode = false;
|
_vm->_debugMode = false;
|
||||||
Debug_Printf("Debugging is now disabled\n");
|
DebugPrintf("Debugging is now disabled\n");
|
||||||
} else
|
} else
|
||||||
Debug_Printf("Not a valid debug level\n");
|
DebugPrintf("Not a valid debug level\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -791,7 +548,7 @@ bool ScummDebugger::Cmd_PrintBox(int argc, const char **argv) {
|
||||||
printBox(atoi(argv[i]));
|
printBox(atoi(argv[i]));
|
||||||
} else {
|
} else {
|
||||||
num = _vm->getNumBoxes();
|
num = _vm->getNumBoxes();
|
||||||
Debug_Printf("\nWalk boxes:\n");
|
DebugPrintf("\nWalk boxes:\n");
|
||||||
for (i = 0; i < num; i++)
|
for (i = 0; i < num; i++)
|
||||||
printBox(i);
|
printBox(i);
|
||||||
}
|
}
|
||||||
|
@ -803,22 +560,22 @@ bool ScummDebugger::Cmd_PrintBoxMatrix(int argc, const char **argv) {
|
||||||
int num = _vm->getNumBoxes();
|
int num = _vm->getNumBoxes();
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
Debug_Printf("Walk matrix:\n");
|
DebugPrintf("Walk matrix:\n");
|
||||||
if (_vm->_version <= 2)
|
if (_vm->_version <= 2)
|
||||||
boxm += num;
|
boxm += num;
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
Debug_Printf("%d: ", i);
|
DebugPrintf("%d: ", i);
|
||||||
if (_vm->_version <= 2) {
|
if (_vm->_version <= 2) {
|
||||||
for (j = 0; j < num; j++)
|
for (j = 0; j < num; j++)
|
||||||
Debug_Printf("[%d] ", *boxm++);
|
DebugPrintf("[%d] ", *boxm++);
|
||||||
} else {
|
} else {
|
||||||
while (*boxm != 0xFF) {
|
while (*boxm != 0xFF) {
|
||||||
Debug_Printf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]);
|
DebugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]);
|
||||||
boxm += 3;
|
boxm += 3;
|
||||||
}
|
}
|
||||||
boxm++;
|
boxm++;
|
||||||
}
|
}
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -833,7 +590,7 @@ void ScummDebugger::printBox(int box) {
|
||||||
_vm->getBoxCoordinates(box, &coords);
|
_vm->getBoxCoordinates(box, &coords);
|
||||||
|
|
||||||
// Print out coords, flags, zbuffer mask
|
// Print out coords, flags, zbuffer mask
|
||||||
Debug_Printf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n",
|
DebugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n",
|
||||||
box,
|
box,
|
||||||
coords.ul.x, coords.ul.y, coords.ll.x, coords.ll.y,
|
coords.ul.x, coords.ul.y, coords.ll.x, coords.ll.y,
|
||||||
coords.ur.x, coords.ur.y, coords.lr.x, coords.lr.y,
|
coords.ur.x, coords.ur.y, coords.lr.x, coords.lr.y,
|
||||||
|
@ -990,7 +747,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
|
||||||
int i, base, draft;
|
int i, base, draft;
|
||||||
|
|
||||||
if (_vm->_gameId != GID_LOOM && _vm->_gameId != GID_LOOM256) {
|
if (_vm->_gameId != GID_LOOM && _vm->_gameId != GID_LOOM256) {
|
||||||
Debug_Printf("Command only works with Loom/LoomCD\n");
|
DebugPrintf("Command only works with Loom/LoomCD\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,7 +789,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
|
||||||
// the distaff, but I don't know if that's a safe
|
// the distaff, but I don't know if that's a safe
|
||||||
// thing to do.
|
// thing to do.
|
||||||
|
|
||||||
Debug_Printf("Learned all drafts and notes.\n");
|
DebugPrintf("Learned all drafts and notes.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +801,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
|
||||||
if (strcmp(argv[1], "fix") == 0) {
|
if (strcmp(argv[1], "fix") == 0) {
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
_vm->_scummVars[base + 2 * i + 1] = odds[i];
|
_vm->_scummVars[base + 2 * i + 1] = odds[i];
|
||||||
Debug_Printf(
|
DebugPrintf(
|
||||||
"An attempt has been made to repair\n"
|
"An attempt has been made to repair\n"
|
||||||
"the internal drafts data structure.\n"
|
"the internal drafts data structure.\n"
|
||||||
"Continue on your own risk.\n");
|
"Continue on your own risk.\n");
|
||||||
|
@ -1056,7 +813,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
draft = _vm->_scummVars[base + i * 2];
|
draft = _vm->_scummVars[base + i * 2];
|
||||||
Debug_Printf("%d %-13s %c%c%c%c %c%c %5d %c\n",
|
DebugPrintf("%d %-13s %c%c%c%c %c%c %5d %c\n",
|
||||||
base + 2 * i,
|
base + 2 * i,
|
||||||
names[i],
|
names[i],
|
||||||
notes[draft & 0x0007],
|
notes[draft & 0x0007],
|
||||||
|
@ -1072,55 +829,4 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if something has been completed
|
|
||||||
// completion has to be delete[]-ed then
|
|
||||||
bool ScummDebugger::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Scumm
|
} // End of namespace Scumm
|
||||||
|
|
|
@ -18,64 +18,25 @@
|
||||||
* $Header$
|
* $Header$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DEBUG_H
|
#ifndef DEBUGGER_H
|
||||||
#define DEBUG_H
|
#define DEBUGGER_H
|
||||||
|
|
||||||
class ConsoleDialog;
|
#include "common/debugger.h"
|
||||||
|
|
||||||
namespace Scumm {
|
namespace Scumm {
|
||||||
|
|
||||||
// Choose between text console or ScummConsole
|
|
||||||
#define USE_CONSOLE 1
|
|
||||||
|
|
||||||
class ScummEngine;
|
class ScummEngine;
|
||||||
class ScummDebugger;
|
|
||||||
|
|
||||||
typedef bool (ScummDebugger::*DebugProc)(int argc, const char **argv);
|
class ScummDebugger : public Common::Debugger<ScummDebugger> {
|
||||||
|
|
||||||
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:
|
public:
|
||||||
ScummDebugger(ScummEngine *s);
|
ScummDebugger(ScummEngine *s);
|
||||||
|
|
||||||
void onFrame();
|
|
||||||
void attach(const char *entry = 0);
|
|
||||||
|
|
||||||
bool isAttached() const { return _isAttached; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ScummEngine *_vm;
|
ScummEngine *_vm;
|
||||||
int _frame_countdown, _dvar_count, _dcmd_count;
|
bool _old_soundsPaused;
|
||||||
DVar _dvars[256];
|
|
||||||
DCmd _dcmds[256];
|
|
||||||
bool _detach_now;
|
|
||||||
bool _isAttached;
|
|
||||||
char *_errStr;
|
|
||||||
ConsoleDialog *_debuggerDialog;
|
|
||||||
|
|
||||||
void enter();
|
virtual void preEnter();
|
||||||
void detach();
|
virtual void postEnter();
|
||||||
|
|
||||||
void DVar_Register(const char *varname, void *pointer, int type, int optional);
|
|
||||||
void DCmd_Register(const char *cmdname, DebugProc pointer);
|
|
||||||
bool RunCommand(const char *input);
|
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
bool Cmd_Exit(int argc, const char **argv);
|
bool Cmd_Exit(int argc, const char **argv);
|
||||||
|
@ -106,14 +67,6 @@ protected:
|
||||||
|
|
||||||
void printBox(int box);
|
void printBox(int box);
|
||||||
void drawBox(int box);
|
void drawBox(int box);
|
||||||
|
|
||||||
#if USE_CONSOLE
|
|
||||||
static bool debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon);
|
|
||||||
static bool debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool TabComplete(const char *input, char*& completion);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Scumm
|
} // End of namespace Scumm
|
||||||
|
|
|
@ -31,12 +31,7 @@
|
||||||
#include "bs2/save_rest.h"
|
#include "bs2/save_rest.h"
|
||||||
#include "bs2/startup.h"
|
#include "bs2/startup.h"
|
||||||
|
|
||||||
// FIXME: Much of this is copied from scumm/debugger.cpp which is a pretty
|
#include "common/debugger.cpp"
|
||||||
// lousy form of code reuse.
|
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
extern void force_keyboard(bool);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Sword2 {
|
namespace Sword2 {
|
||||||
|
|
||||||
|
@ -52,14 +47,9 @@ static void Var_set(int var, int val) {
|
||||||
Debug_Printf("now %d\n", VAR(var));
|
Debug_Printf("now %d\n", VAR(var));
|
||||||
}
|
}
|
||||||
|
|
||||||
Debugger::Debugger(Sword2Engine *s) {
|
Debugger::Debugger(Sword2Engine *s)
|
||||||
|
: Common::Debugger<Debugger>(s->_newgui) {
|
||||||
_vm = s;
|
_vm = s;
|
||||||
_frame_countdown = 0;
|
|
||||||
_dcmd_count = 0;
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = false;
|
|
||||||
_errStr = NULL;
|
|
||||||
_debuggerDialog = NULL;
|
|
||||||
|
|
||||||
// Register commands
|
// Register commands
|
||||||
|
|
||||||
|
@ -113,174 +103,28 @@ Debugger::Debugger(Sword2Engine *s) {
|
||||||
DCmd_Register("polish", &Debugger::Cmd_Polish);
|
DCmd_Register("polish", &Debugger::Cmd_Polish);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::attach(const char *entry) {
|
void Debugger::preEnter() {
|
||||||
|
// Pause sound output
|
||||||
#ifdef _WIN32_WCE
|
g_sound->pauseFx();
|
||||||
force_keyboard(true);
|
g_sound->pauseSpeech();
|
||||||
#endif
|
g_sound->pauseMusic();
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
_errStr = strdup(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
_frame_countdown = 1;
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::detach() {
|
void Debugger::postEnter() {
|
||||||
#if USE_CONSOLE
|
// Resume previous sound state
|
||||||
if (_debuggerDialog) {
|
g_sound->unpauseFx();
|
||||||
_debuggerDialog->setInputCallback(0, 0);
|
g_sound->unpauseSpeech();
|
||||||
_debuggerDialog->setCompletionCallback(0, 0);
|
g_sound->unpauseMusic();
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
// Restore old mouse cursor
|
||||||
force_keyboard(false);
|
g_display->drawMouse();
|
||||||
#endif
|
|
||||||
|
|
||||||
_detach_now = false;
|
|
||||||
_isAttached = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary execution handler
|
|
||||||
void Debugger::onFrame() {
|
|
||||||
if (_frame_countdown == 0)
|
|
||||||
return;
|
|
||||||
--_frame_countdown;
|
|
||||||
|
|
||||||
if (!_frame_countdown) {
|
|
||||||
// Pause sound output
|
|
||||||
|
|
||||||
g_sound->pauseFx();
|
|
||||||
g_sound->pauseSpeech();
|
|
||||||
g_sound->pauseMusic();
|
|
||||||
|
|
||||||
// Enter debugger
|
|
||||||
enter();
|
|
||||||
|
|
||||||
// Resume previous sound state
|
|
||||||
|
|
||||||
g_sound->unpauseFx();
|
|
||||||
g_sound->unpauseSpeech();
|
|
||||||
g_sound->unpauseMusic();
|
|
||||||
|
|
||||||
// Restore old mouse cursor
|
|
||||||
g_display->drawMouse();
|
|
||||||
|
|
||||||
// Detach if we're finished with the debugger
|
|
||||||
if (_detach_now)
|
|
||||||
detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Console handler
|
|
||||||
#if USE_CONSOLE
|
|
||||||
bool Debugger::debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon) {
|
|
||||||
Debugger *debugger = (Debugger *) refCon;
|
|
||||||
|
|
||||||
return debugger->RunCommand(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Debugger::debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon) {
|
|
||||||
Debugger *debugger = (Debugger *) refCon;
|
|
||||||
|
|
||||||
return debugger->TabComplete(input, completion);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
// Now the fun stuff:
|
// Now the fun stuff:
|
||||||
|
|
||||||
void Debugger::DCmd_Register(const char *cmdname, DebugProc pointer) {
|
|
||||||
assert(_dcmd_count < (int) sizeof(_dcmds));
|
|
||||||
strcpy(_dcmds[_dcmd_count].name, cmdname);
|
|
||||||
_dcmds[_dcmd_count].function = pointer;
|
|
||||||
|
|
||||||
_dcmd_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main Debugger Loop
|
|
||||||
void Debugger::enter() {
|
|
||||||
#if USE_CONSOLE
|
|
||||||
if (!_debuggerDialog) {
|
|
||||||
_debuggerDialog = new ConsoleDialog(_vm->_newgui, 1.0, 0.67F);
|
|
||||||
|
|
||||||
Debug_Printf("Debugger started, type 'exit' to return to the game.\n");
|
|
||||||
Debug_Printf("Type 'help' to see a little list of commands and variables.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_errStr) {
|
|
||||||
Debug_Printf("ERROR: %s\n\n", _errStr);
|
|
||||||
free(_errStr);
|
|
||||||
_errStr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_debuggerDialog->setInputCallback(debuggerInputCallback, this);
|
|
||||||
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
|
|
||||||
_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
|
|
||||||
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 = (this->*_dcmds[i].function)(num_params, param);
|
|
||||||
free(input);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug_Printf("Unknown command\n");
|
|
||||||
free(input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
|
|
||||||
bool Debugger::Cmd_Exit(int argc, const char **argv) {
|
bool Debugger::Cmd_Exit(int argc, const char **argv) {
|
||||||
|
@ -293,20 +137,20 @@ bool Debugger::Cmd_Help(int argc, const char **argv) {
|
||||||
// wrap around nicely
|
// wrap around nicely
|
||||||
int width = 0, size, i;
|
int width = 0, size, i;
|
||||||
|
|
||||||
Debug_Printf("Commands are:\n");
|
DebugPrintf("Commands are:\n");
|
||||||
for (i = 0 ; i < _dcmd_count ; i++) {
|
for (i = 0 ; i < _dcmd_count ; i++) {
|
||||||
size = strlen(_dcmds[i].name) + 1;
|
size = strlen(_dcmds[i].name) + 1;
|
||||||
|
|
||||||
if ((width + size) >= 39) {
|
if ((width + size) >= 39) {
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
width = size;
|
width = size;
|
||||||
} else
|
} else
|
||||||
width += size;
|
width += size;
|
||||||
|
|
||||||
Debug_Printf("%s ", _dcmds[i].name);
|
DebugPrintf("%s ", _dcmds[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug_Printf("\n");
|
DebugPrintf("\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +160,7 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Tony(int argc, const char **argv) {
|
bool Debugger::Cmd_Tony(int argc, const char **argv) {
|
||||||
Debug_Printf("What about him?\n");
|
DebugPrintf("What about him?\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +178,7 @@ bool Debugger::Cmd_Start(int argc, const char **argv) {
|
||||||
uint8 pal[4] = { 255, 255, 255, 0 };
|
uint8 pal[4] = { 255, 255, 255, 0 };
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s number\n", argv[0]);
|
DebugPrintf("Usage: %s number\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,9 +191,9 @@ bool Debugger::Cmd_Info(int argc, const char **argv) {
|
||||||
displayDebugText = !displayDebugText;
|
displayDebugText = !displayDebugText;
|
||||||
|
|
||||||
if (displayDebugText)
|
if (displayDebugText)
|
||||||
Debug_Printf("Info text on\n");
|
DebugPrintf("Info text on\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Info Text off\n");
|
DebugPrintf("Info Text off\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -358,9 +202,9 @@ bool Debugger::Cmd_WalkGrid(int argc, const char **argv) {
|
||||||
displayWalkGrid = !displayWalkGrid;
|
displayWalkGrid = !displayWalkGrid;
|
||||||
|
|
||||||
if (displayWalkGrid)
|
if (displayWalkGrid)
|
||||||
Debug_Printf("Walk-grid display on\n");
|
DebugPrintf("Walk-grid display on\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Walk-grid display off\n");
|
DebugPrintf("Walk-grid display off\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -369,9 +213,9 @@ bool Debugger::Cmd_Mouse(int argc, const char **argv) {
|
||||||
displayMouseMarker = !displayMouseMarker;
|
displayMouseMarker = !displayMouseMarker;
|
||||||
|
|
||||||
if (displayMouseMarker)
|
if (displayMouseMarker)
|
||||||
Debug_Printf("Mouse marker on\n");
|
DebugPrintf("Mouse marker on\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Mouse marker off\n");
|
DebugPrintf("Mouse marker off\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -380,16 +224,16 @@ bool Debugger::Cmd_Player(int argc, const char **argv) {
|
||||||
displayPlayerMarker = !displayPlayerMarker;
|
displayPlayerMarker = !displayPlayerMarker;
|
||||||
|
|
||||||
if (displayPlayerMarker)
|
if (displayPlayerMarker)
|
||||||
Debug_Printf("Player feet marker on\n");
|
DebugPrintf("Player feet marker on\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Player feet marker off\n");
|
DebugPrintf("Player feet marker off\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_ResLook(int argc, const char **argv) {
|
bool Debugger::Cmd_ResLook(int argc, const char **argv) {
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
Debug_Printf("Usage: %s number\n", argv[0]);
|
DebugPrintf("Usage: %s number\n", argv[0]);
|
||||||
else
|
else
|
||||||
res_man.examine(atoi(argv[1]));
|
res_man.examine(atoi(argv[1]));
|
||||||
return true;
|
return true;
|
||||||
|
@ -407,14 +251,14 @@ bool Debugger::Cmd_RunList(int argc, const char **argv) {
|
||||||
|
|
||||||
bool Debugger::Cmd_Kill(int argc, const char **argv) {
|
bool Debugger::Cmd_Kill(int argc, const char **argv) {
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
Debug_Printf("Usage: %s number\n", argv[0]);
|
DebugPrintf("Usage: %s number\n", argv[0]);
|
||||||
else
|
else
|
||||||
res_man.kill(atoi(argv[1]));
|
res_man.kill(atoi(argv[1]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Nuke(int argc, const char **argv) {
|
bool Debugger::Cmd_Nuke(int argc, const char **argv) {
|
||||||
Debug_Printf("Killing all resources except variable file and player object\n");
|
DebugPrintf("Killing all resources except variable file and player object\n");
|
||||||
res_man.killAll(true);
|
res_man.killAll(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +272,7 @@ bool Debugger::Cmd_Var(int argc, const char **argv) {
|
||||||
Var_set(atoi(argv[1]), atoi(argv[2]));
|
Var_set(atoi(argv[1]), atoi(argv[2]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug_Printf("Usage: %s number value\n", argv[0]);
|
DebugPrintf("Usage: %s number value\n", argv[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,9 +283,9 @@ bool Debugger::Cmd_Rect(int argc, const char **argv) {
|
||||||
definingRectangles = !definingRectangles;
|
definingRectangles = !definingRectangles;
|
||||||
|
|
||||||
if (definingRectangles)
|
if (definingRectangles)
|
||||||
Debug_Printf("Mouse rectangles enabled\n");
|
DebugPrintf("Mouse rectangles enabled\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Mouse rectangles disabled\n");
|
DebugPrintf("Mouse rectangles disabled\n");
|
||||||
|
|
||||||
draggingRectangle = 0;
|
draggingRectangle = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -458,7 +302,7 @@ bool Debugger::Cmd_DebugOn(int argc, const char **argv) {
|
||||||
displayMouseMarker = true;
|
displayMouseMarker = true;
|
||||||
displayPlayerMarker = true;
|
displayPlayerMarker = true;
|
||||||
displayTextNumbers = true;
|
displayTextNumbers = true;
|
||||||
Debug_Printf("Enabled all on-screen debug info\n");
|
DebugPrintf("Enabled all on-screen debug info\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +312,7 @@ bool Debugger::Cmd_DebugOff(int argc, const char **argv) {
|
||||||
displayMouseMarker = false;
|
displayMouseMarker = false;
|
||||||
displayPlayerMarker = false;
|
displayPlayerMarker = false;
|
||||||
displayTextNumbers = false;
|
displayTextNumbers = false;
|
||||||
Debug_Printf("Disabled all on-screen debug info\n");
|
DebugPrintf("Disabled all on-screen debug info\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,22 +320,22 @@ bool Debugger::Cmd_SaveRest(int argc, const char **argv) {
|
||||||
testingSnR = !testingSnR;
|
testingSnR = !testingSnR;
|
||||||
|
|
||||||
if (testingSnR)
|
if (testingSnR)
|
||||||
Debug_Printf("Enabled S&R logic_script stability checking\n");
|
DebugPrintf("Enabled S&R logic_script stability checking\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Disabled S&R logic_script stability checking\n");
|
DebugPrintf("Disabled S&R logic_script stability checking\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_ListSaveGames(int argc, const char **argv) {
|
bool Debugger::Cmd_ListSaveGames(int argc, const char **argv) {
|
||||||
Debug_Printf("Savegames:\n");
|
DebugPrintf("Savegames:\n");
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
uint8 description[SAVE_DESCRIPTION_LEN];
|
uint8 description[SAVE_DESCRIPTION_LEN];
|
||||||
|
|
||||||
// if there is a save game print the name
|
// if there is a save game print the name
|
||||||
if (GetSaveDescription(i, description) == SR_OK)
|
if (GetSaveDescription(i, description) == SR_OK)
|
||||||
Debug_Printf("%d: \"%s\"\n", i, description);
|
DebugPrintf("%d: \"%s\"\n", i, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -504,13 +348,13 @@ bool Debugger::Cmd_SaveGame(int argc, const char **argv) {
|
||||||
uint32 rv;
|
uint32 rv;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
Debug_Printf("Usage: %s slot description\n", argv[0]);
|
DebugPrintf("Usage: %s slot description\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if mouse if off, or system menu is locked off
|
// if mouse if off, or system menu is locked off
|
||||||
if (mouse_status || mouse_mode_locked) {
|
if (mouse_status || mouse_mode_locked) {
|
||||||
Debug_Printf("WARNING: Cannot save game while control menu unavailable!\n");
|
DebugPrintf("WARNING: Cannot save game while control menu unavailable!\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,11 +381,11 @@ bool Debugger::Cmd_SaveGame(int argc, const char **argv) {
|
||||||
rv = SaveGame(slotNo, (uint8 *) description);
|
rv = SaveGame(slotNo, (uint8 *) description);
|
||||||
|
|
||||||
if (rv == SR_OK)
|
if (rv == SR_OK)
|
||||||
Debug_Printf("Saved game \"%s\" to file \"savegame.%.3d\"\n", description, slotNo);
|
DebugPrintf("Saved game \"%s\" to file \"savegame.%.3d\"\n", description, slotNo);
|
||||||
else if (rv == SR_ERR_FILEOPEN)
|
else if (rv == SR_ERR_FILEOPEN)
|
||||||
Debug_Printf("ERROR: Cannot open file \"savegame.%.3d\"\n", slotNo);
|
DebugPrintf("ERROR: Cannot open file \"savegame.%.3d\"\n", slotNo);
|
||||||
else // SR_ERR_WRITEFAIL
|
else // SR_ERR_WRITEFAIL
|
||||||
Debug_Printf("ERROR: Write error on file \"savegame.%.3d\"\n", slotNo);
|
DebugPrintf("ERROR: Write error on file \"savegame.%.3d\"\n", slotNo);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -552,13 +396,13 @@ bool Debugger::Cmd_RestoreGame(int argc, const char **argv) {
|
||||||
uint32 rv;
|
uint32 rv;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s slot\n", argv[0]);
|
DebugPrintf("Usage: %s slot\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if mouse if off, or system menu is locked off
|
// if mouse if off, or system menu is locked off
|
||||||
if (mouse_status || mouse_mode_locked) {
|
if (mouse_status || mouse_mode_locked) {
|
||||||
Debug_Printf("WARNING: Cannot restore game while control menu unavailable!\n");
|
DebugPrintf("WARNING: Cannot restore game while control menu unavailable!\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,13 +411,13 @@ bool Debugger::Cmd_RestoreGame(int argc, const char **argv) {
|
||||||
|
|
||||||
if (rv == SR_OK) {
|
if (rv == SR_OK) {
|
||||||
GetSaveDescription(slotNo, description);
|
GetSaveDescription(slotNo, description);
|
||||||
Debug_Printf("Restored game \"%s\" from file \"savegame.%.3d\"\n", description, slotNo);
|
DebugPrintf("Restored game \"%s\" from file \"savegame.%.3d\"\n", description, slotNo);
|
||||||
} else if (rv == SR_ERR_FILEOPEN)
|
} else if (rv == SR_ERR_FILEOPEN)
|
||||||
Debug_Printf("ERROR: Cannot open file \"savegame.%.3d\"\n", slotNo);
|
DebugPrintf("ERROR: Cannot open file \"savegame.%.3d\"\n", slotNo);
|
||||||
else if (rv == SR_ERR_INCOMPATIBLE)
|
else if (rv == SR_ERR_INCOMPATIBLE)
|
||||||
Debug_Printf("ERROR: \"savegame.%.3d\" is no longer compatible with current player/variable resources\n", slotNo);
|
DebugPrintf("ERROR: \"savegame.%.3d\" is no longer compatible with current player/variable resources\n", slotNo);
|
||||||
else // SR_ERR_READFAIL
|
else // SR_ERR_READFAIL
|
||||||
Debug_Printf("ERROR: Read error on file \"savegame.%.3d\"\n", slotNo);
|
DebugPrintf("ERROR: Read error on file \"savegame.%.3d\"\n", slotNo);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -582,15 +426,15 @@ bool Debugger::Cmd_RestoreGame(int argc, const char **argv) {
|
||||||
|
|
||||||
bool Debugger::Cmd_BltFxOn(int argc, const char **argv) {
|
bool Debugger::Cmd_BltFxOn(int argc, const char **argv) {
|
||||||
// g_display->setBltFx();
|
// g_display->setBltFx();
|
||||||
// Debug_Printf("Blit fx enabled\n");
|
// DebugPrintf("Blit fx enabled\n");
|
||||||
Debug_Printf("FIXME: The setBltFx() function no longer exists\n");
|
DebugPrintf("FIXME: The setBltFx() function no longer exists\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_BltFxOff(int argc, const char **argv) {
|
bool Debugger::Cmd_BltFxOff(int argc, const char **argv) {
|
||||||
// g_display->clearBltFx();
|
// g_display->clearBltFx();
|
||||||
// Debug_Printf("Blit fx disabled\n");
|
// DebugPrintf("Blit fx disabled\n");
|
||||||
Debug_Printf("FIXME: The clearBltFx() function no longer exists\n");
|
DebugPrintf("FIXME: The clearBltFx() function no longer exists\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,13 +444,13 @@ bool Debugger::Cmd_TimeOn(int argc, const char **argv) {
|
||||||
else if (startTime == 0)
|
else if (startTime == 0)
|
||||||
startTime = SVM_timeGetTime();
|
startTime = SVM_timeGetTime();
|
||||||
displayTime = true;
|
displayTime = true;
|
||||||
Debug_Printf("Timer display on\n");
|
DebugPrintf("Timer display on\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_TimeOff(int argc, const char **argv) {
|
bool Debugger::Cmd_TimeOff(int argc, const char **argv) {
|
||||||
displayTime = false;
|
displayTime = false;
|
||||||
Debug_Printf("Timer display off\n");
|
DebugPrintf("Timer display off\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,9 +458,9 @@ bool Debugger::Cmd_Text(int argc, const char **argv) {
|
||||||
displayTextNumbers = !displayTextNumbers;
|
displayTextNumbers = !displayTextNumbers;
|
||||||
|
|
||||||
if (displayTextNumbers)
|
if (displayTextNumbers)
|
||||||
Debug_Printf("Text numbers on\n");
|
DebugPrintf("Text numbers on\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("Text numbers off\n");
|
DebugPrintf("Text numbers off\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +470,7 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) {
|
||||||
int32 varNo;
|
int32 varNo;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s number\n", argv[0]);
|
DebugPrintf("Usage: %s number\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,11 +487,11 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) {
|
||||||
if (showVar[showVarNo] == 0) {
|
if (showVar[showVarNo] == 0) {
|
||||||
// empty slot - add it to the list at this slot
|
// empty slot - add it to the list at this slot
|
||||||
showVar[showVarNo] = varNo;
|
showVar[showVarNo] = varNo;
|
||||||
Debug_Printf("var(%d) added to the watch-list\n", varNo);
|
DebugPrintf("var(%d) added to the watch-list\n", varNo);
|
||||||
} else
|
} else
|
||||||
Debug_Printf("var(%d) already in the watch-list!\n", varNo);
|
DebugPrintf("var(%d) already in the watch-list!\n", varNo);
|
||||||
} else
|
} else
|
||||||
Debug_Printf("Sorry - no more allowed - hide one or extend the system watch-list\n");
|
DebugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +501,7 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) {
|
||||||
int32 varNo;
|
int32 varNo;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s number\n", argv[0]);
|
DebugPrintf("Usage: %s number\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,9 +514,9 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) {
|
||||||
if (showVarNo < MAX_SHOWVARS) {
|
if (showVarNo < MAX_SHOWVARS) {
|
||||||
// We've found 'varNo' in the list - clear this slot
|
// We've found 'varNo' in the list - clear this slot
|
||||||
showVar[showVarNo] = 0;
|
showVar[showVarNo] = 0;
|
||||||
Debug_Printf("var(%d) removed from watch-list\n", varNo);
|
DebugPrintf("var(%d) removed from watch-list\n", varNo);
|
||||||
} else
|
} else
|
||||||
Debug_Printf("Sorry - can't find var(%d) in the list\n", varNo);
|
DebugPrintf("Sorry - can't find var(%d) in the list\n", varNo);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -713,30 +557,30 @@ bool Debugger::Cmd_Version(int argc, const char **argv) {
|
||||||
dateStamp[24] = 0; // fudge over the newline character!
|
dateStamp[24] = 0; // fudge over the newline character!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Debug_Printf("\"Broken Sword II\" (c) Revolution Software 1997.\n");
|
DebugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Debug_Printf("v%s created on %s for %s\n", version, dateStamp, unencoded_name + HEAD_LEN);
|
DebugPrintf("v%s created on %s for %s\n", version, dateStamp, unencoded_name + HEAD_LEN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// THE FOLLOWING LINES ARE TO BE COMMENTED OUT OF THE FINAL VERSION
|
// THE FOLLOWING LINES ARE TO BE COMMENTED OUT OF THE FINAL VERSION
|
||||||
Debug_Printf("This program has a personalised fingerprint encrypted into the code.\n");
|
DebugPrintf("This program has a personalised fingerprint encrypted into the code.\n");
|
||||||
Debug_Printf("If this CD was not sent directly to you by Virgin Interactive or Revolution Software\n");
|
DebugPrintf("If this CD was not sent directly to you by Virgin Interactive or Revolution Software\n");
|
||||||
Debug_Printf("then please contact James Long at Revolution on (+44) 1904 639698.\n");
|
DebugPrintf("then please contact James Long at Revolution on (+44) 1904 639698.\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_SoftHard(int argc, const char **argv) {
|
bool Debugger::Cmd_SoftHard(int argc, const char **argv) {
|
||||||
Debug_Printf("ScummVM doesn't distinguish between software and hardware rendering.\n");
|
DebugPrintf("ScummVM doesn't distinguish between software and hardware rendering.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
|
bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s value\n", argv[0]);
|
DebugPrintf("Usage: %s value\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,13 +590,13 @@ bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
|
||||||
// Same as typing "VAR 912 <value>" at the console
|
// Same as typing "VAR 912 <value>" at the console
|
||||||
Var_set(912, atoi(argv[1]));
|
Var_set(912, atoi(argv[1]));
|
||||||
|
|
||||||
Debug_Printf("Setting flag 'system_testing_anims'\n");
|
DebugPrintf("Setting flag 'system_testing_anims'\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_TextTest(int argc, const char **argv) {
|
bool Debugger::Cmd_TextTest(int argc, const char **argv) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Debug_Printf("Usage: %s value\n", argv[0]);
|
DebugPrintf("Usage: %s value\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,14 +608,14 @@ bool Debugger::Cmd_TextTest(int argc, const char **argv) {
|
||||||
|
|
||||||
displayTextNumbers = true;
|
displayTextNumbers = true;
|
||||||
|
|
||||||
Debug_Printf("Setting flag 'system_testing_text'\n");
|
DebugPrintf("Setting flag 'system_testing_text'\n");
|
||||||
Debug_Printf("Text numbers on\n");
|
DebugPrintf("Text numbers on\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_LineTest(int argc, const char **argv) {
|
bool Debugger::Cmd_LineTest(int argc, const char **argv) {
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
Debug_Printf("Usage: %s value1 value2\n", argv[0]);
|
DebugPrintf("Usage: %s value1 value2\n", argv[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,37 +630,37 @@ bool Debugger::Cmd_LineTest(int argc, const char **argv) {
|
||||||
|
|
||||||
displayTextNumbers = true;
|
displayTextNumbers = true;
|
||||||
|
|
||||||
Debug_Printf("Setting flag 'system_testing_text'\n");
|
DebugPrintf("Setting flag 'system_testing_text'\n");
|
||||||
Debug_Printf("Setting flag 'system_test_line_no'\n");
|
DebugPrintf("Setting flag 'system_test_line_no'\n");
|
||||||
Debug_Printf("Text numbers on\n");
|
DebugPrintf("Text numbers on\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Grab(int argc, const char **argv) {
|
bool Debugger::Cmd_Grab(int argc, const char **argv) {
|
||||||
Debug_Printf("FIXME: Continuous screen-grabbing not implemented\n");
|
DebugPrintf("FIXME: Continuous screen-grabbing not implemented\n");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
grabbingSequences = !grabbingSequences;
|
grabbingSequences = !grabbingSequences;
|
||||||
|
|
||||||
if (grabbingSequences)
|
if (grabbingSequences)
|
||||||
Debug_Printf("PCX-grabbing enabled\n");
|
DebugPrintf("PCX-grabbing enabled\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("PCX-grabbing disabled\n");
|
DebugPrintf("PCX-grabbing disabled\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Events(int argc, const char **argv) {
|
bool Debugger::Cmd_Events(int argc, const char **argv) {
|
||||||
Debug_Printf("EVENT LIST:\n");
|
DebugPrintf("EVENT LIST:\n");
|
||||||
|
|
||||||
for (uint32 i = 0; i < MAX_events; i++) {
|
for (uint32 i = 0; i < MAX_events; i++) {
|
||||||
if (event_list[i].id) {
|
if (event_list[i].id) {
|
||||||
uint32 target = event_list[i].id;
|
uint32 target = event_list[i].id;
|
||||||
uint32 script = event_list[i].interact_id;
|
uint32 script = event_list[i].interact_id;
|
||||||
|
|
||||||
Debug_Printf("slot %d: id = %s (%d)\n", i, FetchObjectName(target), target);
|
DebugPrintf("slot %d: id = %s (%d)\n", i, FetchObjectName(target), target);
|
||||||
Debug_Printf(" script = %s (%d) pos %d\n", FetchObjectName(script / 65536), script / 65536, script % 65536);
|
DebugPrintf(" script = %s (%d) pos %d\n", FetchObjectName(script / 65536), script / 65536, script % 65536);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,79 +671,28 @@ bool Debugger::Cmd_Sfx(int argc, const char **argv) {
|
||||||
wantSfxDebug = !wantSfxDebug;
|
wantSfxDebug = !wantSfxDebug;
|
||||||
|
|
||||||
if (wantSfxDebug)
|
if (wantSfxDebug)
|
||||||
Debug_Printf("SFX logging activated\n");
|
DebugPrintf("SFX logging activated\n");
|
||||||
else
|
else
|
||||||
Debug_Printf("SFX logging deactivated\n");
|
DebugPrintf("SFX logging deactivated\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_English(int argc, const char **argv) {
|
bool Debugger::Cmd_English(int argc, const char **argv) {
|
||||||
g_sword2->initialiseFontResourceFlags(DEFAULT_TEXT);
|
g_sword2->initialiseFontResourceFlags(DEFAULT_TEXT);
|
||||||
Debug_Printf("Default fonts selected\n");
|
DebugPrintf("Default fonts selected\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Finnish(int argc, const char **argv) {
|
bool Debugger::Cmd_Finnish(int argc, const char **argv) {
|
||||||
g_sword2->initialiseFontResourceFlags(FINNISH_TEXT);
|
g_sword2->initialiseFontResourceFlags(FINNISH_TEXT);
|
||||||
Debug_Printf("Finnish fonts selected\n");
|
DebugPrintf("Finnish fonts selected\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Cmd_Polish(int argc, const char **argv) {
|
bool Debugger::Cmd_Polish(int argc, const char **argv) {
|
||||||
g_sword2->initialiseFontResourceFlags(POLISH_TEXT);
|
g_sword2->initialiseFontResourceFlags(POLISH_TEXT);
|
||||||
Debug_Printf("Polish fonts selected\n");
|
DebugPrintf("Polish fonts selected\n");
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,19 +20,10 @@
|
||||||
#ifndef C_ONSOLE_H
|
#ifndef C_ONSOLE_H
|
||||||
#define C_ONSOLE_H
|
#define C_ONSOLE_H
|
||||||
|
|
||||||
|
#include "common/debugger.h"
|
||||||
#include "bs2/memory.h"
|
#include "bs2/memory.h"
|
||||||
|
|
||||||
// Choose between text console or graphical console
|
#define Debug_Printf g_sword2->_debugger->DebugPrintf
|
||||||
#define USE_CONSOLE 1
|
|
||||||
|
|
||||||
#if USE_CONSOLE
|
|
||||||
#include "gui/console.h"
|
|
||||||
#define Debug_Printf g_sword2->_debugger->_debuggerDialog->printf
|
|
||||||
#else
|
|
||||||
#define Debug_Printf printf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ConsoleDialog;
|
|
||||||
|
|
||||||
namespace Sword2 {
|
namespace Sword2 {
|
||||||
|
|
||||||
|
@ -40,53 +31,16 @@ extern bool grabbingSequences;
|
||||||
extern bool wantSfxDebug; // sfx debug file enabled/disabled from console
|
extern bool wantSfxDebug; // sfx debug file enabled/disabled from console
|
||||||
|
|
||||||
class Sword2Engine;
|
class Sword2Engine;
|
||||||
class Debugger;
|
|
||||||
|
|
||||||
typedef bool (Debugger::*DebugProc)(int argc, const char **argv);
|
class Debugger : public Common::Debugger<Debugger> {
|
||||||
|
|
||||||
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 Debugger {
|
|
||||||
public:
|
public:
|
||||||
Debugger(Sword2Engine *s);
|
Debugger(Sword2Engine *s);
|
||||||
|
|
||||||
void onFrame();
|
|
||||||
void attach(const char *entry = 0);
|
|
||||||
|
|
||||||
bool isAttached() const { return _isAttached; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Sword2Engine *_vm;
|
Sword2Engine *_vm;
|
||||||
int _frame_countdown, _dcmd_count;
|
|
||||||
DCmd _dcmds[256];
|
|
||||||
bool _detach_now;
|
|
||||||
bool _isAttached;
|
|
||||||
char *_errStr;
|
|
||||||
public:
|
|
||||||
ConsoleDialog *_debuggerDialog; // Should be protected, but is public now for Debug_Printf
|
|
||||||
|
|
||||||
protected:
|
virtual void preEnter();
|
||||||
void enter();
|
virtual void postEnter();
|
||||||
void detach();
|
|
||||||
|
|
||||||
void DCmd_Register(const char *cmdname, DebugProc pointer);
|
|
||||||
bool RunCommand(const char *input);
|
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
bool Cmd_Exit(int argc, const char **argv);
|
bool Cmd_Exit(int argc, const char **argv);
|
||||||
|
@ -132,13 +86,6 @@ protected:
|
||||||
bool Cmd_English(int argc, const char **argv);
|
bool Cmd_English(int argc, const char **argv);
|
||||||
bool Cmd_Finnish(int argc, const char **argv);
|
bool Cmd_Finnish(int argc, const char **argv);
|
||||||
bool Cmd_Polish(int argc, const char **argv);
|
bool Cmd_Polish(int argc, const char **argv);
|
||||||
|
|
||||||
#if USE_CONSOLE
|
|
||||||
static bool debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon);
|
|
||||||
static bool debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool TabComplete(const char *input, char*& completion);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Sword2
|
} // End of namespace Sword2
|
||||||
|
|
|
@ -34,6 +34,8 @@ enum BSGameId {
|
||||||
GID_SWORD2_DEMO
|
GID_SWORD2_DEMO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NewGui;
|
||||||
|
|
||||||
namespace Sword2 {
|
namespace Sword2 {
|
||||||
|
|
||||||
// Bodge for PCF76 version so that their demo CD can be labelled "PCF76"
|
// Bodge for PCF76 version so that their demo CD can be labelled "PCF76"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue