2009-02-17 15:02:16 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-20 21:38:38 +00:00
|
|
|
// Script debugger functionality. Absolutely not threadsafe.
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-27 02:23:00 +00:00
|
|
|
#include "sci/sci.h"
|
2009-06-04 11:28:05 +00:00
|
|
|
#include "sci/debug.h"
|
2009-02-27 02:23:40 +00:00
|
|
|
#include "sci/engine/state.h"
|
2009-02-27 02:23:00 +00:00
|
|
|
#include "sci/engine/gc.h"
|
2009-02-17 20:26:57 +00:00
|
|
|
#include "sci/engine/kernel_types.h"
|
2009-02-27 02:23:00 +00:00
|
|
|
#include "sci/engine/kernel.h"
|
2009-03-12 03:26:21 +00:00
|
|
|
#include "sci/engine/savegame.h"
|
2009-02-21 22:50:35 +00:00
|
|
|
#include "sci/gfx/gfx_widgets.h"
|
2009-03-25 12:52:03 +00:00
|
|
|
#include "sci/gfx/gfx_gui.h"
|
2009-04-24 10:46:20 +00:00
|
|
|
#include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual
|
2009-05-15 14:07:45 +00:00
|
|
|
#include "sci/resource.h"
|
|
|
|
#include "sci/vocabulary.h"
|
2009-03-06 18:11:12 +00:00
|
|
|
#include "sci/sfx/iterator.h"
|
2009-02-27 02:23:00 +00:00
|
|
|
#include "sci/sfx/sci_midi.h"
|
2009-02-17 20:26:57 +00:00
|
|
|
|
|
|
|
#include "common/util.h"
|
2009-02-20 23:41:15 +00:00
|
|
|
#include "common/savefile.h"
|
2009-02-17 20:26:57 +00:00
|
|
|
|
2009-03-04 07:31:31 +00:00
|
|
|
#include "sound/audiostream.h"
|
|
|
|
|
2009-02-21 10:23:36 +00:00
|
|
|
namespace Sci {
|
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
int g_debugstate_valid = 0; // Set to 1 while script_debug is running
|
|
|
|
int g_debug_step_running = 0; // Set to >0 to allow multiple stepping
|
|
|
|
static bool s_debug_commands_hooked = false; // Commands hooked to the console yet?
|
|
|
|
int g_debug_seeking = 0; // Stepping forward until some special condition is met
|
|
|
|
static int s_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth
|
|
|
|
static int s_debug_seek_special = 0; // Used for special seeks(1)
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#define _DEBUG_SEEK_NOTHING 0
|
2009-02-20 21:38:38 +00:00
|
|
|
#define _DEBUG_SEEK_CALLK 1 // Step forward until callk is found
|
|
|
|
#define _DEBUG_SEEK_LEVEL_RET 2 // Step forward until returned from this level
|
|
|
|
#define _DEBUG_SEEK_SPECIAL_CALLK 3 // Step forward until a /special/ callk is found
|
|
|
|
#define _DEBUG_SEEK_SO 5 // Step forward until specified PC (after the send command) and stack depth
|
|
|
|
#define _DEBUG_SEEK_GLOBAL 6 // Step forward until one specified global variable is modified
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
static reg_t *p_pc;
|
2009-02-28 11:12:59 +00:00
|
|
|
static StackPtr *p_sp;
|
|
|
|
static StackPtr *p_pp;
|
2009-02-15 06:10:59 +00:00
|
|
|
static reg_t *p_objp;
|
|
|
|
static int *p_restadjust;
|
2009-02-28 11:12:59 +00:00
|
|
|
static SegmentId *p_var_segs;
|
2009-02-15 06:10:59 +00:00
|
|
|
static reg_t **p_vars;
|
|
|
|
static reg_t **p_var_base;
|
2009-02-20 21:38:38 +00:00
|
|
|
static int *p_var_max; // May be NULL even in valid state!
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
char inputbuf[256] = "";
|
|
|
|
|
2009-05-30 10:22:53 +00:00
|
|
|
union cmd_param_t {
|
|
|
|
int32 val;
|
|
|
|
const char *str;
|
|
|
|
reg_t reg;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef int (*ConCommand)(EngineState *s, const Common::Array<cmd_param_t> &cmdParams);
|
|
|
|
|
|
|
|
struct cmd_mm_entry_t {
|
|
|
|
const char *name;
|
|
|
|
const char *description;
|
|
|
|
}; // All later structures must "extend" this
|
|
|
|
|
|
|
|
struct cmd_command_t : public cmd_mm_entry_t {
|
|
|
|
ConCommand command;
|
|
|
|
const char *param;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Dummy function, so that it compiles
|
|
|
|
int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
int c_step(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debugstate_valid = 0;
|
2009-05-11 13:31:37 +00:00
|
|
|
if (cmdParams.size() && (cmdParams[0].val > 0))
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_step_running = cmdParams[0].val - 1;
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
2009-02-15 22:28:12 +00:00
|
|
|
_parse_eoi,
|
|
|
|
_parse_token_pareno,
|
|
|
|
_parse_token_parenc,
|
|
|
|
_parse_token_nil,
|
|
|
|
_parse_token_number
|
2009-02-15 06:10:59 +00:00
|
|
|
};
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
int _parse_getinp(int *i, int *nr, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-05-11 18:02:48 +00:00
|
|
|
const char *token;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
if ((unsigned)*i == cmdParams.size())
|
2009-02-15 22:28:12 +00:00
|
|
|
return _parse_eoi;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
token = cmdParams[(*i)++].str;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
if (!strcmp(token, "("))
|
|
|
|
return _parse_token_pareno;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
if (!strcmp(token, ")"))
|
|
|
|
return _parse_token_parenc;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
if (!strcmp(token, "nil"))
|
|
|
|
return _parse_token_nil;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
*nr = strtol(token, NULL, 0);
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
return _parse_token_number;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
int _parse_nodes(EngineState *s, int *i, int *pos, int type, int nr, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-02-15 22:28:12 +00:00
|
|
|
int nexttk, nextval, newpos, oldpos;
|
|
|
|
|
|
|
|
if (type == _parse_token_nil)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (type == _parse_token_number) {
|
|
|
|
s->parser_nodes[*pos += 1].type = PARSE_TREE_NODE_LEAF;
|
|
|
|
s->parser_nodes[*pos].content.value = nr;
|
|
|
|
return *pos;
|
|
|
|
}
|
|
|
|
if (type == _parse_eoi) {
|
|
|
|
sciprintf("Unbalanced parentheses\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (type == _parse_token_parenc) {
|
|
|
|
sciprintf("Syntax error at token %d\n", *i);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
s->parser_nodes[oldpos = ++(*pos)].type = PARSE_TREE_NODE_BRANCH;
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
nexttk = _parse_getinp(i, &nextval, cmdParams);
|
|
|
|
if ((newpos = s->parser_nodes[oldpos].content.branches[0] = _parse_nodes(s, i, pos, nexttk, nextval, cmdParams)) == -1)
|
2009-02-15 22:28:12 +00:00
|
|
|
return -1;
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
nexttk = _parse_getinp(i, &nextval, cmdParams);
|
|
|
|
if ((newpos = s->parser_nodes[oldpos].content.branches[1] = _parse_nodes(s, i, pos, nexttk, nextval, cmdParams)) == -1)
|
2009-02-15 22:28:12 +00:00
|
|
|
return -1;
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
if (_parse_getinp(i, &nextval, cmdParams) != _parse_token_parenc)
|
2009-02-15 22:28:12 +00:00
|
|
|
sciprintf("Expected ')' at token %d\n", *i);
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
return oldpos;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
int c_set_parse_nodes(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-02-15 22:28:12 +00:00
|
|
|
int i = 0;
|
|
|
|
int foo, bar;
|
|
|
|
int pos = -1;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
if (!s) {
|
|
|
|
sciprintf("Not in debug state\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
bar = _parse_getinp(&i, &foo, cmdParams);
|
|
|
|
if (_parse_nodes(s, &i, &pos, bar, foo, cmdParams) == -1)
|
2009-02-15 22:28:12 +00:00
|
|
|
return 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
vocab_dump_parse_tree("debug-parse-tree", s->parser_nodes);
|
|
|
|
return 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 23:29:58 +00:00
|
|
|
extern const char *selector_name(EngineState *s, int selector);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 10:47:56 +00:00
|
|
|
int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) {
|
2009-02-28 11:12:59 +00:00
|
|
|
Object *obj = obj_get(s, objp);
|
2009-02-15 06:10:59 +00:00
|
|
|
byte *selectoroffset;
|
|
|
|
int selectors;
|
|
|
|
|
|
|
|
if (!obj) {
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("Applied prop_ofs_to_id on non-object at %04x:%04x\n", PRINT_REG(objp));
|
2009-02-15 06:10:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-05-12 23:30:42 +00:00
|
|
|
selectors = obj->_variables.size();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 21:44:39 +00:00
|
|
|
if (s->_version < SCI_VERSION_1_1)
|
2009-02-15 22:28:12 +00:00
|
|
|
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
|
|
|
|
else {
|
2009-05-12 23:30:42 +00:00
|
|
|
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) {
|
|
|
|
obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
2009-02-20 21:38:38 +00:00
|
|
|
selectoroffset = (byte *)obj->base_vars;
|
|
|
|
} else
|
|
|
|
selectoroffset = (byte *)obj->base_vars;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) {
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("Applied prop_ofs_to_id to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n",
|
2009-02-20 21:38:38 +00:00
|
|
|
prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp));
|
2009-02-15 06:10:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-03-07 16:14:20 +00:00
|
|
|
return READ_LE_UINT16(selectoroffset + prop_ofs);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 10:47:56 +00:00
|
|
|
reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) {
|
2009-02-20 21:38:38 +00:00
|
|
|
// Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered.
|
2009-05-03 22:46:38 +00:00
|
|
|
MemObject *mobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_SCRIPT);
|
2009-02-28 11:12:59 +00:00
|
|
|
Script *script_entity = NULL;
|
2009-02-15 06:10:59 +00:00
|
|
|
byte *scr;
|
|
|
|
int scr_size;
|
|
|
|
reg_t retval = make_reg(pos.segment, pos.offset + 1);
|
2009-02-21 21:16:41 +00:00
|
|
|
uint16 param_value;
|
2009-02-15 06:10:59 +00:00
|
|
|
int opsize;
|
2009-05-26 15:06:21 +00:00
|
|
|
uint opcode;
|
2009-02-15 06:10:59 +00:00
|
|
|
int bytecount = 1;
|
|
|
|
int i = 0;
|
|
|
|
|
2009-05-03 22:46:38 +00:00
|
|
|
if (!mobj) {
|
2009-02-20 21:38:38 +00:00
|
|
|
sciprintf("Disassembly failed: Segment %04x non-existant or not a script\n", pos.segment);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
2009-02-20 21:38:38 +00:00
|
|
|
} else
|
2009-05-03 22:46:38 +00:00
|
|
|
script_entity = (Script *)mobj;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
scr = script_entity->buf;
|
|
|
|
scr_size = script_entity->buf_size;
|
|
|
|
|
|
|
|
if (pos.offset >= scr_size) {
|
|
|
|
sciprintf("Trying to disassemble beyond end of script\n");
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
opsize = scr[pos.offset];
|
|
|
|
opcode = opsize >> 1;
|
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (!g_debugstate_valid) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Not in debug state\n");
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-02-20 21:38:38 +00:00
|
|
|
opsize &= 1; // byte if true, word if false
|
2009-02-15 22:28:12 +00:00
|
|
|
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("%04x:%04x: ", PRINT_REG(pos));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (print_bytecode) {
|
2009-04-20 19:28:33 +00:00
|
|
|
while (g_opcode_formats[opcode][i]) {
|
|
|
|
switch (g_opcode_formats[opcode][i++]) {
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
case Script_SByte:
|
2009-02-15 22:28:12 +00:00
|
|
|
case Script_Byte:
|
|
|
|
bytecount++;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Script_Word:
|
2009-02-15 22:28:12 +00:00
|
|
|
case Script_SWord:
|
|
|
|
bytecount += 2;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Script_SVariable:
|
|
|
|
case Script_Variable:
|
|
|
|
case Script_Property:
|
|
|
|
case Script_Global:
|
|
|
|
case Script_Local:
|
|
|
|
case Script_Temp:
|
|
|
|
case Script_Param:
|
|
|
|
case Script_SRelative:
|
|
|
|
if (opsize)
|
|
|
|
bytecount ++;
|
|
|
|
else
|
|
|
|
bytecount += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pos.offset + bytecount > scr_size) {
|
|
|
|
sciprintf("Operation arguments extend beyond end of script\n");
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < bytecount; i++)
|
|
|
|
sciprintf("%02x ", scr[pos.offset + i]);
|
|
|
|
|
|
|
|
for (i = bytecount; i < 5; i++)
|
|
|
|
sciprintf(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (print_bw_tag)
|
2009-02-15 22:28:12 +00:00
|
|
|
sciprintf("[%c] ", opsize ? 'B' : 'W');
|
2009-06-01 14:12:43 +00:00
|
|
|
sciprintf("%s", s->_kernel->getOpcode(opcode).name.c_str());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
i = 0;
|
2009-04-20 19:28:33 +00:00
|
|
|
while (g_opcode_formats[opcode][i]) {
|
|
|
|
switch (g_opcode_formats[opcode][i++]) {
|
2009-02-15 22:28:12 +00:00
|
|
|
case Script_Invalid:
|
|
|
|
sciprintf("-Invalid operation-");
|
|
|
|
break;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
case Script_SByte:
|
2009-02-15 22:28:12 +00:00
|
|
|
case Script_Byte:
|
|
|
|
sciprintf(" %02x", scr[retval.offset++]);
|
|
|
|
break;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
case Script_Word:
|
|
|
|
case Script_SWord:
|
2009-02-20 21:38:38 +00:00
|
|
|
sciprintf(" %04x", 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)));
|
2009-02-15 06:10:59 +00:00
|
|
|
retval.offset += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Script_SVariable:
|
|
|
|
case Script_Variable:
|
|
|
|
case Script_Property:
|
|
|
|
case Script_Global:
|
|
|
|
case Script_Local:
|
|
|
|
case Script_Temp:
|
|
|
|
case Script_Param:
|
|
|
|
if (opsize)
|
|
|
|
param_value = scr[retval.offset++];
|
|
|
|
else {
|
2009-02-20 21:38:38 +00:00
|
|
|
param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8));
|
2009-02-15 06:10:59 +00:00
|
|
|
retval.offset += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opcode == op_callk)
|
2009-06-04 21:42:24 +00:00
|
|
|
sciprintf(" %s[%x]", (param_value < s->_kernel->_kernelFuncs.size()) ?
|
2009-06-01 14:12:43 +00:00
|
|
|
((param_value < s->_kernel->getKernelNamesSize()) ? s->_kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]")
|
2009-02-20 21:38:38 +00:00
|
|
|
: "<invalid>", param_value);
|
|
|
|
else
|
|
|
|
sciprintf(opsize ? " %02x" : " %04x", param_value);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Script_Offset:
|
|
|
|
if (opsize)
|
|
|
|
param_value = scr[retval.offset++];
|
|
|
|
else {
|
2009-02-20 21:38:38 +00:00
|
|
|
param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8));
|
2009-02-15 06:10:59 +00:00
|
|
|
retval.offset += 2;
|
|
|
|
}
|
2009-02-21 04:25:56 +00:00
|
|
|
sciprintf(opsize ? " %02x" : " %04x", param_value);
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Script_SRelative:
|
|
|
|
if (opsize)
|
|
|
|
param_value = scr[retval.offset++];
|
|
|
|
else {
|
2009-02-20 21:38:38 +00:00
|
|
|
param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8));
|
2009-02-15 06:10:59 +00:00
|
|
|
retval.offset += 2;
|
|
|
|
}
|
2009-02-15 22:28:12 +00:00
|
|
|
sciprintf(opsize ? " %02x [%04x]" : " %04x [%04x]", param_value, (0xffff) & (retval.offset + param_value));
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
case Script_End:
|
|
|
|
retval = NULL_REG;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
sciprintf("Internal assertion failed in 'disassemble', %s, L%d\n", __FILE__, __LINE__);
|
|
|
|
|
|
|
|
}
|
2009-02-20 21:38:38 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-21 17:18:46 +00:00
|
|
|
if (pos == *p_pc) { // Extra information if debugging the current opcode
|
2009-02-20 21:38:38 +00:00
|
|
|
if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) ||
|
|
|
|
(opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int prop_ofs = scr[pos.offset + 1];
|
|
|
|
int prop_id = prop_ofs_to_id(s, prop_ofs, *p_objp);
|
|
|
|
|
|
|
|
sciprintf(" (%s)", selector_name(s, prop_id));
|
|
|
|
}
|
2009-02-20 21:38:38 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
sciprintf("\n");
|
|
|
|
|
2009-05-21 17:18:46 +00:00
|
|
|
if (pos == *p_pc) { // Extra information if debugging the current opcode
|
2009-02-15 06:10:59 +00:00
|
|
|
if (opcode == op_callk) {
|
2009-02-20 21:38:38 +00:00
|
|
|
int stackframe = (scr[pos.offset + 2] >> 1) + (*p_restadjust);
|
2009-02-15 06:10:59 +00:00
|
|
|
int argc = ((*p_sp)[- stackframe - 1]).offset;
|
|
|
|
|
2009-06-04 21:44:39 +00:00
|
|
|
if (!(s->_flags & GF_SCI0_OLD))
|
2009-02-15 06:10:59 +00:00
|
|
|
argc += (*p_restadjust);
|
|
|
|
|
|
|
|
sciprintf(" Kernel params: (");
|
|
|
|
|
2009-02-15 21:12:21 +00:00
|
|
|
for (int j = 0; j < argc; j++) {
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("%04x:%04x", PRINT_REG((*p_sp)[j - stackframe]));
|
2009-02-15 22:28:12 +00:00
|
|
|
if (j + 1 < argc)
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf(", ");
|
|
|
|
}
|
|
|
|
sciprintf(")\n");
|
2009-02-15 22:28:12 +00:00
|
|
|
} else if ((opcode == op_send) || (opcode == op_self)) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int restmod = *p_restadjust;
|
|
|
|
int stackframe = (scr[pos.offset + 1] >> 1) + restmod;
|
|
|
|
reg_t *sb = *p_sp;
|
2009-02-21 21:16:41 +00:00
|
|
|
uint16 selector;
|
2009-02-15 06:10:59 +00:00
|
|
|
reg_t fun_ref;
|
|
|
|
|
|
|
|
while (stackframe > 0) {
|
|
|
|
int argc = sb[- stackframe + 1].offset;
|
|
|
|
const char *name = NULL;
|
2009-02-15 14:52:51 +00:00
|
|
|
reg_t called_obj_addr = *p_objp;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (opcode == op_send)
|
|
|
|
called_obj_addr = s->r_acc;
|
|
|
|
else if (opcode == op_self)
|
|
|
|
called_obj_addr = *p_objp;
|
|
|
|
|
|
|
|
selector = sb[- stackframe].offset;
|
|
|
|
|
|
|
|
name = obj_get_name(s, called_obj_addr);
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
name = "<invalid>";
|
|
|
|
|
2009-06-01 14:12:43 +00:00
|
|
|
sciprintf(" %s::%s[", name, (selector > s->_kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 11:38:20 +00:00
|
|
|
switch (lookup_selector(s, called_obj_addr, selector, 0, &fun_ref)) {
|
2009-02-28 11:12:59 +00:00
|
|
|
case kSelectorMethod:
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("FUNCT");
|
|
|
|
argc += restmod;
|
|
|
|
restmod = 0;
|
|
|
|
break;
|
2009-02-28 11:12:59 +00:00
|
|
|
case kSelectorVariable:
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("VAR");
|
|
|
|
break;
|
2009-02-28 11:12:59 +00:00
|
|
|
case kSelectorNone:
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("INVALID");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sciprintf("](");
|
|
|
|
|
|
|
|
while (argc--) {
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("%04x:%04x", PRINT_REG(sb[- stackframe + 2]));
|
2009-02-15 06:10:59 +00:00
|
|
|
if (argc)
|
|
|
|
sciprintf(", ");
|
|
|
|
stackframe--;
|
|
|
|
}
|
|
|
|
|
|
|
|
sciprintf(")\n");
|
|
|
|
stackframe -= 2;
|
2009-02-20 21:38:38 +00:00
|
|
|
} // while (stackframe > 0)
|
|
|
|
} // Send-like opcodes
|
|
|
|
} // (heappos == *p_pc)
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_disasm_addr(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
|
|
|
reg_t vpc = cmdParams[0].reg;
|
2009-02-15 06:10:59 +00:00
|
|
|
int op_count = 1;
|
|
|
|
int do_bwc = 0;
|
|
|
|
int do_bytes = 0;
|
2009-02-15 10:29:34 +00:00
|
|
|
unsigned int i;
|
2009-02-15 06:10:59 +00:00
|
|
|
int invalid = 0;
|
|
|
|
int size;
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-21 23:27:24 +00:00
|
|
|
s->seg_manager->dereference(vpc, &size);
|
2009-02-20 21:38:38 +00:00
|
|
|
size += vpc.offset; // total segment size
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
for (i = 1; i < cmdParams.size(); i++) {
|
|
|
|
if (!scumm_stricmp(cmdParams[i].str, "bwt"))
|
2009-02-15 22:28:12 +00:00
|
|
|
do_bwc = 1;
|
2009-05-11 13:31:37 +00:00
|
|
|
else if (!scumm_stricmp(cmdParams[i].str, "bc"))
|
2009-02-15 22:28:12 +00:00
|
|
|
do_bytes = 1;
|
2009-05-11 13:31:37 +00:00
|
|
|
else if (toupper(cmdParams[i].str[0]) == 'C')
|
|
|
|
op_count = atoi(cmdParams[i].str + 1);
|
2009-02-15 22:28:12 +00:00
|
|
|
else {
|
|
|
|
invalid = 1;
|
2009-05-11 13:31:37 +00:00
|
|
|
sciprintf("Invalid option '%s'\n", cmdParams[i].str);
|
2009-02-15 22:28:12 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (invalid || op_count < 0)
|
|
|
|
return invalid;
|
|
|
|
|
|
|
|
do {
|
|
|
|
vpc = disassemble(s, vpc, do_bwc, do_bytes);
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
} while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--op_count));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_disasm(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
|
|
|
Object *obj = obj_get(s, cmdParams[0].reg);
|
2009-06-01 14:12:43 +00:00
|
|
|
int selector_id = s->_kernel->findSelector(cmdParams[1].str);
|
2009-02-15 06:10:59 +00:00
|
|
|
reg_t addr;
|
|
|
|
|
|
|
|
if (!obj) {
|
|
|
|
sciprintf("Not an object.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selector_id < 0) {
|
|
|
|
sciprintf("Not a valid selector name.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
if (lookup_selector(s, cmdParams[0].reg, selector_id, NULL, &addr) != kSelectorMethod) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Not a method.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
addr = disassemble(s, addr, 0, 0);
|
|
|
|
} while (addr.offset > 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_sg(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = _DEBUG_SEEK_GLOBAL;
|
|
|
|
s_debug_seek_special = cmdParams[0].val;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int callk_index;
|
|
|
|
char *endptr;
|
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (!g_debugstate_valid) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Not in debug state\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
if (cmdParams.size() > 0) {
|
2009-02-15 06:10:59 +00:00
|
|
|
/* Try to convert the parameter to a number. If the conversion stops
|
|
|
|
before end of string, assume that the parameter is a function name
|
|
|
|
and scan the function table to find out the index. */
|
2009-05-11 13:31:37 +00:00
|
|
|
callk_index = strtoul(cmdParams [0].str, &endptr, 0);
|
2009-02-15 22:28:12 +00:00
|
|
|
if (*endptr != '\0') {
|
|
|
|
callk_index = -1;
|
2009-06-01 14:12:43 +00:00
|
|
|
for (uint i = 0; i < s->_kernel->getKernelNamesSize(); i++)
|
|
|
|
if (cmdParams [0].str == s->_kernel->getKernelName(i)) {
|
2009-02-15 22:28:12 +00:00
|
|
|
callk_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (callk_index == -1) {
|
2009-05-11 13:31:37 +00:00
|
|
|
sciprintf("Unknown kernel function '%s'\n", cmdParams[0].str);
|
2009-02-15 22:28:12 +00:00
|
|
|
return 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-15 22:28:12 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK;
|
|
|
|
s_debug_seek_special = callk_index;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
} else {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = _DEBUG_SEEK_CALLK;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_sret(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = _DEBUG_SEEK_LEVEL_RET;
|
|
|
|
s_debug_seek_level = s->_executionStack.size()-1;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_go(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = 0;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
|
|
|
reg_t object = cmdParams[0].reg;
|
2009-05-11 18:02:48 +00:00
|
|
|
const char *selector_name = cmdParams[1].str;
|
2009-05-28 22:42:18 +00:00
|
|
|
StackPtr stackframe = s->_executionStack.front().sp;
|
2009-02-21 04:10:21 +00:00
|
|
|
int selector_id;
|
2009-02-28 11:12:59 +00:00
|
|
|
unsigned int i;
|
|
|
|
ExecStack *xstack;
|
|
|
|
Object *o;
|
2009-02-15 06:10:59 +00:00
|
|
|
reg_t fptr;
|
|
|
|
|
2009-06-01 14:12:43 +00:00
|
|
|
selector_id = s->_kernel->findSelector(selector_name);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:28:12 +00:00
|
|
|
if (selector_id < 0) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Unknown selector: \"%s\"\n", selector_name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
o = obj_get(s, object);
|
2009-02-15 22:28:12 +00:00
|
|
|
if (o == NULL) {
|
2009-05-21 17:18:46 +00:00
|
|
|
sciprintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
|
2009-02-15 06:10:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-06-06 11:38:20 +00:00
|
|
|
SelectorType selector_type = lookup_selector(s, object, selector_id, 0, &fptr);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-28 11:12:59 +00:00
|
|
|
if (selector_type == kSelectorNone) {
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Object does not support selector: \"%s\"\n", selector_name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
stackframe[0] = make_reg(0, selector_id);
|
2009-05-11 13:31:37 +00:00
|
|
|
stackframe[1] = make_reg(0, cmdParams.size() - 2);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
for (i = 2; i < cmdParams.size(); i++)
|
|
|
|
stackframe[i] = cmdParams[i].reg;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-28 22:42:18 +00:00
|
|
|
xstack = add_exec_stack_entry(s, fptr,
|
|
|
|
s->_executionStack.front().sp + cmdParams.size(),
|
|
|
|
object, cmdParams.size() - 2,
|
|
|
|
s->_executionStack.front().sp - 1, 0, object,
|
|
|
|
s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
|
2009-02-15 22:28:12 +00:00
|
|
|
xstack->selector = selector_id;
|
2009-02-28 11:12:59 +00:00
|
|
|
xstack->type = selector_type == kSelectorVariable ? EXEC_STACK_TYPE_VARSELECTOR : EXEC_STACK_TYPE_CALL;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-20 21:38:38 +00:00
|
|
|
// Now commit the actual function:
|
2009-05-11 13:31:37 +00:00
|
|
|
xstack = send_selector(s, object, object, stackframe, cmdParams.size() - 2, stackframe);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
xstack->sp += cmdParams.size();
|
|
|
|
xstack->fp += cmdParams.size();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-28 15:58:19 +00:00
|
|
|
s->_executionStackPosChanged = true;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-20 21:38:38 +00:00
|
|
|
// Breakpoint commands
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-11 13:31:37 +00:00
|
|
|
int c_se(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
|
2009-06-04 11:28:05 +00:00
|
|
|
g_stop_on_event = 1;
|
|
|
|
g_debugstate_valid = 0;
|
2009-02-20 21:38:38 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-28 11:12:59 +00:00
|
|
|
void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, int *restadjust,
|
|
|
|
SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) {
|
2009-02-20 21:38:38 +00:00
|
|
|
// Do we support a separate console?
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
int old_debugstate = g_debugstate_valid;
|
2009-05-30 15:40:49 +00:00
|
|
|
|
|
|
|
p_var_segs = segids;
|
|
|
|
p_vars = variables;
|
|
|
|
p_var_max = variables_nr;
|
|
|
|
p_var_base = variables_base;
|
|
|
|
p_pc = pc;
|
|
|
|
p_sp = sp;
|
|
|
|
p_pp = pp;
|
|
|
|
p_objp = objp;
|
|
|
|
p_restadjust = restadjust;
|
|
|
|
sciprintf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc));
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debugstate_valid = 1;
|
2009-05-30 15:40:49 +00:00
|
|
|
disassemble(s, *pc, 0, 1);
|
2009-06-04 11:28:05 +00:00
|
|
|
if (g_debug_seeking == _DEBUG_SEEK_GLOBAL)
|
|
|
|
sciprintf("Global %d (0x%x) = %04x:%04x\n", s_debug_seek_special,
|
|
|
|
s_debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[s_debug_seek_special]));
|
2009-05-30 15:40:49 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debugstate_valid = old_debugstate;
|
2009-05-30 15:40:49 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (g_debug_seeking && !bp) { // Are we looking for something special?
|
2009-05-03 22:46:38 +00:00
|
|
|
MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-03 22:46:38 +00:00
|
|
|
if (mobj) {
|
|
|
|
Script *scr = (Script *)mobj;
|
2009-02-15 06:10:59 +00:00
|
|
|
byte *code_buf = scr->buf;
|
|
|
|
int code_buf_size = scr->buf_size;
|
2009-02-15 22:28:12 +00:00
|
|
|
int opcode = pc->offset >= code_buf_size ? 0 : code_buf[pc->offset];
|
2009-02-15 06:10:59 +00:00
|
|
|
int op = opcode >> 1;
|
2009-02-15 22:28:12 +00:00
|
|
|
int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1];
|
2009-03-07 16:14:20 +00:00
|
|
|
int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
switch (g_debug_seeking) {
|
2009-02-15 06:10:59 +00:00
|
|
|
case _DEBUG_SEEK_SPECIAL_CALLK:
|
2009-06-04 11:28:05 +00:00
|
|
|
if (paramb1 != s_debug_seek_special)
|
2009-02-15 06:10:59 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case _DEBUG_SEEK_CALLK: {
|
2009-02-20 21:38:38 +00:00
|
|
|
if (op != op_callk)
|
|
|
|
return;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case _DEBUG_SEEK_LEVEL_RET: {
|
2009-06-04 11:28:05 +00:00
|
|
|
if ((op != op_ret) || (s_debug_seek_level < (int)s->_executionStack.size()-1))
|
2009-02-20 21:38:38 +00:00
|
|
|
return;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case _DEBUG_SEEK_GLOBAL:
|
|
|
|
if (op < op_sag)
|
|
|
|
return;
|
|
|
|
if ((op & 0x3) > 1)
|
2009-02-20 21:38:38 +00:00
|
|
|
return; // param or temp
|
2009-05-18 18:15:45 +00:00
|
|
|
if ((op & 0x3) && s->_executionStack.back().local_segment > 0)
|
2009-02-20 21:38:38 +00:00
|
|
|
return; // locals and not running in script.000
|
2009-06-04 11:28:05 +00:00
|
|
|
if (paramf1 != s_debug_seek_special)
|
2009-02-20 21:38:38 +00:00
|
|
|
return; // CORRECT global?
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
2009-02-20 21:38:38 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debug_seeking = _DEBUG_SEEK_NOTHING;
|
2009-02-20 21:38:38 +00:00
|
|
|
// OK, found whatever we were looking for
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-20 21:38:38 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
g_debugstate_valid = (g_debug_step_running == 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (g_debugstate_valid) {
|
2009-02-15 06:10:59 +00:00
|
|
|
p_pc = pc;
|
|
|
|
p_sp = sp;
|
|
|
|
p_pp = pp;
|
|
|
|
p_objp = objp;
|
|
|
|
p_restadjust = restadjust;
|
|
|
|
p_var_segs = segids;
|
|
|
|
p_vars = variables;
|
|
|
|
p_var_max = variables_nr;
|
|
|
|
p_var_base = variables_base;
|
2009-06-02 23:29:58 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
sciprintf("Step #%d\n", script_step_counter);
|
|
|
|
disassemble(s, *pc, 0, 1);
|
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (!s_debug_commands_hooked) {
|
|
|
|
s_debug_commands_hooked = true;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n"
|
2009-02-15 22:28:12 +00:00
|
|
|
" s 4\n\n Execute 4 commands\n\n s\n\n Execute next command");
|
2009-02-15 06:10:59 +00:00
|
|
|
con_hook_command(c_disasm_addr, "disasm-addr", "!as*", "Disassembles one or more commands\n\n"
|
2009-02-15 22:28:12 +00:00
|
|
|
"USAGE\n\n disasm-addr [startaddr] <options>\n\n"
|
|
|
|
" Valid options are:\n"
|
|
|
|
" bwt : Print byte/word tag\n"
|
|
|
|
" c<x> : Disassemble <x> bytes\n"
|
|
|
|
" bc : Print bytecode\n\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
con_hook_command(c_disasm, "disasm", "!as", "Disassembles a method by name\n\nUSAGE\n\n disasm <obj> <method>\n\n");
|
|
|
|
con_hook_command(c_snk, "snk", "s*", "Steps forward until it hits the next\n callk operation.\n"
|
2009-02-15 22:28:12 +00:00
|
|
|
" If invoked with a parameter, it will\n look for that specific callk.\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
con_hook_command(c_se, "se", "", "Steps forward until an SCI event is received.\n");
|
|
|
|
con_hook_command(c_send, "send", "!asa*", "Sends a message to an object\nExample: send ?fooScript cue");
|
2009-02-20 21:38:38 +00:00
|
|
|
con_hook_command(c_sret, "sret", "", "Steps forward until ret is called\n on the current execution stack\n level.");
|
2009-02-15 06:10:59 +00:00
|
|
|
con_hook_command(c_go, "go", "", "Executes the script.\n");
|
|
|
|
con_hook_command(c_set_parse_nodes, "set_parse_nodes", "s*", "Sets the contents of all parse nodes.\n"
|
2009-02-15 22:28:12 +00:00
|
|
|
" Input token must be separated by\n blanks.");
|
2009-02-15 06:10:59 +00:00
|
|
|
con_hook_command(c_sg, "sg", "!i",
|
2009-02-15 22:28:12 +00:00
|
|
|
"Steps until the global variable with the\n"
|
|
|
|
"specified index is modified.\n\nSEE ALSO\n\n"
|
|
|
|
" s.1, snk.1, so.1, bpx.1");
|
2009-02-20 21:38:38 +00:00
|
|
|
} // If commands were not hooked up
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-06-04 11:28:05 +00:00
|
|
|
if (g_debug_step_running)
|
|
|
|
g_debug_step_running--;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-21 10:23:36 +00:00
|
|
|
|
|
|
|
} // End of namespace Sci
|