From 62499054a0639fd9bca6b0573bca3b664e8561fe Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 8 Jul 2009 10:25:37 +0000 Subject: Some cleanup for the script debugger code: - Renamed struct DebugState to ScriptState and r_amp_rest to restAdjust inside EngineState. Changed restAdjust to be a uint16 (actually it is a uint16, but it was being casted back and forth from an unsigned integer, so this clears up its type and size) - Moved the script state variables from inside the run_vm() into the ScriptState struct, so that they can be accessed by the console commands and the script debugger all the time, and removed the weird isValid code svn-id: r42260 --- engines/sci/console.cpp | 80 +++++------ engines/sci/debug.h | 20 ++- engines/sci/engine/game.cpp | 2 +- engines/sci/engine/kevent.cpp | 12 +- engines/sci/engine/kmisc.cpp | 4 +- engines/sci/engine/scriptdebug.cpp | 97 ++++--------- engines/sci/engine/state.cpp | 2 +- engines/sci/engine/state.h | 2 +- engines/sci/engine/vm.cpp | 283 ++++++++++++++++++------------------- engines/sci/engine/vm.h | 46 ++---- engines/sci/sci.cpp | 8 +- 11 files changed, 243 insertions(+), 313 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 2d11f39835..667a39c063 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -190,11 +190,10 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { "Dirty frames management\n"); */ - debugState.isValid = false; - debugState.seeking = kDebugSeekNothing; - debugState.seekLevel = 0; - debugState.runningStep = 0; - debugState.stopOnEvent = false; + scriptState.seeking = kDebugSeekNothing; + scriptState.seekLevel = 0; + scriptState.runningStep = 0; + scriptState.stopOnEvent = false; } Console::~Console() { @@ -546,13 +545,13 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), *debugState.p_restadjust); + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), scriptState.restadjust); if (!_vm->_gamestate->_executionStack.empty()) { EngineState *s = _vm->_gamestate; // for PRINT_STK DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", - PRINT_REG(*debugState.p_pc), PRINT_REG(*debugState.p_objp), - PRINT_STK(*debugState.p_pp), PRINT_STK(*debugState.p_sp)); + PRINT_REG(scriptState.xs->addr.pc), PRINT_REG(scriptState.xs->objp), + PRINT_STK(scriptState.xs->fp), PRINT_STK(scriptState.xs->sp)); } else DebugPrintf("\n"); @@ -846,7 +845,6 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { _vm->_gamestate->successor = newstate; // Set successor script_abort_flag = 2; // Abort current game with replay - debugState.isValid = false; shrink_execution_stack(_vm->_gamestate, _vm->_gamestate->execution_stack_base + 1); return 0; @@ -877,7 +875,6 @@ bool Console::cmdRestartGame(int argc, const char **argv) { _vm->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; script_abort_flag = 1; - debugState.isValid = false; return false; } @@ -1705,9 +1702,9 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { DebugPrintf("Addresses of variables in the VM:\n"); for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(debugState.p_var_segs[i], debugState.p_vars[i] - debugState.p_var_base[i]))); - if (debugState.p_var_max) - DebugPrintf(" total %d", debugState.p_var_max[i]); + DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(scriptState.variables_seg[i], scriptState.variables[i] - scriptState.variables_base[i]))); + if (scriptState.variables_max) + DebugPrintf(" total %d", scriptState.variables_max[i]); DebugPrintf("\n"); } @@ -1743,17 +1740,17 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } - if ((debugState.p_var_max) && (debugState.p_var_max[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", debugState.p_var_max[vartype], debugState.p_var_max[vartype]); + if ((scriptState.variables_max) && (scriptState.variables_max[vartype] <= idx)) { + DebugPrintf("Max. index is %d (0x%x)\n", scriptState.variables_max[vartype], scriptState.variables_max[vartype]); return true; } switch (argc) { case 2: - DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(debugState.p_vars[vartype][idx])); + DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(scriptState.variables[vartype][idx])); break; case 3: - if (parse_reg_t(_vm->_gamestate, argv[3], &debugState.p_vars[vartype][idx])) { + if (parse_reg_t(_vm->_gamestate, argv[3], &scriptState.variables[vartype][idx])) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; @@ -1992,7 +1989,7 @@ bool Console::cmdViewObject(int argc, const char **argv) { bool Console::cmdViewActiveObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class:\n"); - printObject(_vm->_gamestate, *debugState.p_objp); + printObject(_vm->_gamestate, scriptState.xs->objp); return true; } @@ -2099,24 +2096,21 @@ bool Console::cmdBacktrace(int argc, const char **argv) { } bool Console::cmdStep(int argc, const char **argv) { - debugState.isValid = false; if (argc == 2 && atoi(argv[1]) > 0) - debugState.runningStep = atoi(argv[1]) - 1; + scriptState.runningStep = atoi(argv[1]) - 1; return true; } bool Console::cmdStepEvent(int argc, const char **argv) { - debugState.stopOnEvent = true; - debugState.isValid = false; + scriptState.stopOnEvent = true; return true; } bool Console::cmdStepRet(int argc, const char **argv) { - debugState.seeking = kDebugSeekLevelRet; - debugState.seekLevel = _vm->_gamestate->_executionStack.size() - 1; - debugState.isValid = false; + scriptState.seeking = kDebugSeekLevelRet; + scriptState.seekLevel = _vm->_gamestate->_executionStack.size() - 1; return true; } @@ -2128,9 +2122,8 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { return true; } - debugState.seeking = kDebugSeekGlobal; - debugState.seekSpecial = atoi(argv[1]); - debugState.isValid = false; + scriptState.seeking = kDebugSeekGlobal; + scriptState.seekSpecial = atoi(argv[1]); return true; } @@ -2158,12 +2151,10 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } } - debugState.seeking = kDebugSeekSpecialCallk; - debugState.seekSpecial = callk_index; - debugState.isValid = false; + scriptState.seeking = kDebugSeekSpecialCallk; + scriptState.seekSpecial = callk_index; } else { - debugState.seeking = kDebugSeekCallk; - debugState.isValid = false; + scriptState.seeking = kDebugSeekCallk; } return true; @@ -2339,8 +2330,7 @@ bool Console::cmdSend(int argc, const char **argv) { } bool Console::cmdGo(int argc, const char **argv) { - debugState.seeking = kDebugSeekNothing; - debugState.isValid = false; + scriptState.seeking = kDebugSeekNothing; return true; } @@ -2754,9 +2744,8 @@ bool Console::cmdExit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully script_abort_flag = 1; // Terminate VM - debugState.isValid = false; - debugState.seeking = kDebugSeekNothing; - debugState.runningStep = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully @@ -3245,34 +3234,33 @@ int c_stepover(EngineState *s, const Common::Array &cmdParams) { return 1; } - debugState.isValid = false; opcode = s->_heap[*p_pc]; opnumber = opcode >> 1; if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { - debugState.seeking = kDebugSeekSO; - debugState.seekLevel = s->_executionStack.size()-1; - // Store in debugState.seekSpecial the offset of the next command after send + scriptState.seeking = kDebugSeekSO; + scriptState.seekLevel = s->_executionStack.size()-1; + // Store in scriptState.seekSpecial the offset of the next command after send switch (opcode) { case 0x46: // calle W - debugState.seekSpecial = *p_pc + 5; + scriptState.seekSpecial = *p_pc + 5; break; case 0x44: // callb W case 0x47: // calle B case 0x56: // super W - debugState.seekSpecial = *p_pc + 4; + scriptState.seekSpecial = *p_pc + 4; break; case 0x45: // callb B case 0x57: // super B case 0x4A: // send W case 0x54: // self W - debugState.seekSpecial = *p_pc + 3; + scriptState.seekSpecial = *p_pc + 3; break; default: - debugState.seekSpecial = *p_pc + 2; + scriptState.seekSpecial = *p_pc + 2; } } diff --git a/engines/sci/debug.h b/engines/sci/debug.h index fbd98e0d6f..ccf0602600 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -37,8 +37,7 @@ enum DebugSeeking { kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified }; -struct DebugState { - bool isValid; +struct ScriptState { bool stopOnEvent; DebugSeeking seeking; // Stepping forward until some special condition is met int runningStep; // Set to > 0 to allow multiple stepping @@ -46,15 +45,12 @@ struct DebugState { int seekSpecial; // Used for special seeks int old_pc_offset; StackPtr old_sp; - reg_t *p_pc; - StackPtr *p_sp; - StackPtr *p_pp; - reg_t *p_objp; - int *p_restadjust; - SegmentId *p_var_segs; - reg_t **p_vars; - reg_t **p_var_base; - int *p_var_max; // May be NULL even in valid state! + ExecStack *xs; + uint16 restadjust; + reg_t *variables[4]; // global, local, temp, param, as immediate pointers + reg_t *variables_base[4]; // Used for referencing VM ops + SegmentId variables_seg[4]; // Same as above, contains segment IDs + int variables_max[4]; // Max. values for all variables }; // Various global variables used for debugging are declared here @@ -62,7 +58,7 @@ extern int g_debug_sleeptime_factor; extern int g_debug_simulated_key; extern bool g_debug_track_mouse_clicks; extern bool g_debug_weak_validations; -extern DebugState debugState; +extern ScriptState scriptState; } // End of namespace Sci diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 861294cfa6..5b4c30f6b3 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -365,7 +365,7 @@ int script_init_engine(EngineState *s) { s->r_acc = s->r_prev = NULL_REG; - s->r_amp_rest = 0; + s->restAdjust = 0; s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 744a965ef3..c4b3f5d71a 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -88,12 +88,12 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { case SCI_EVT_KEYBOARD: if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { printf("Debug mode activated\n"); - debugState.seeking = kDebugSeekNothing; - debugState.runningStep = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { printf("Debug mode activated\n"); - debugState.seeking = kDebugSeekNothing; - debugState.runningStep = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event s->r_acc = make_reg(0, 1); @@ -137,8 +137,8 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (debugState.stopOnEvent)) { - debugState.stopOnEvent = false; + if ((s->r_acc.offset) && (scriptState.stopOnEvent)) { + scriptState.stopOnEvent = false; // A SCI event occured, and we have been asked to stop, so open the debug console Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 8381bc2e13..7e0aca5b7a 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -96,8 +96,8 @@ reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) { printf("Debug mode activated\n"); - debugState.seeking = kDebugSeekNothing; - debugState.runningStep = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; return s->r_acc; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index d5f0a21385..9f69d21e2a 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -34,7 +34,7 @@ namespace Sci { extern const char *selector_name(EngineState *s, int selector); -DebugState debugState; +ScriptState scriptState; int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { Object *obj = obj_get(s, objp); @@ -97,11 +97,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod opsize = scr[pos.offset]; opcode = opsize >> 1; - if (!debugState.isValid) { - warning("Not in debug state"); - return retval; - } - opsize &= 1; // byte if true, word if false printf("%04x:%04x: ", PRINT_REG(pos)); @@ -226,11 +221,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } } - if (pos == *debugState.p_pc) { // Extra information if debugging the current opcode + if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode 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)) { int prop_ofs = scr[pos.offset + 1]; - int prop_id = propertyOffsetToId(s, prop_ofs, *debugState.p_objp); + int prop_id = propertyOffsetToId(s, prop_ofs, scriptState.xs->objp); printf(" (%s)", selector_name(s, prop_id)); } @@ -238,38 +233,38 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod printf("\n"); - if (pos == *debugState.p_pc) { // Extra information if debugging the current opcode + if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (*debugState.p_restadjust); - int argc = ((*debugState.p_sp)[- stackframe - 1]).offset; + int stackframe = (scr[pos.offset + 2] >> 1) + (scriptState.restadjust); + int argc = ((scriptState.xs->sp)[- stackframe - 1]).offset; if (!s->_kernel->hasOldScriptHeader()) - argc += (*debugState.p_restadjust); + argc += (scriptState.restadjust); printf(" Kernel params: ("); for (int j = 0; j < argc; j++) { - printf("%04x:%04x", PRINT_REG((*debugState.p_sp)[j - stackframe])); + printf("%04x:%04x", PRINT_REG((scriptState.xs->sp)[j - stackframe])); if (j + 1 < argc) printf(", "); } printf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = *debugState.p_restadjust; + int restmod = scriptState.restadjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; - reg_t *sb = *debugState.p_sp; + reg_t *sb = scriptState.xs->sp; uint16 selector; reg_t fun_ref; while (stackframe > 0) { int argc = sb[- stackframe + 1].offset; const char *name = NULL; - reg_t called_obj_addr = *debugState.p_objp; + reg_t called_obj_addr = scriptState.xs->objp; if (opcode == op_send) called_obj_addr = s->r_acc; else if (opcode == op_self) - called_obj_addr = *debugState.p_objp; + called_obj_addr = scriptState.xs->objp; selector = sb[- stackframe].offset; @@ -313,45 +308,30 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } -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) { +void script_debug(EngineState *s, bool bp) { // Do we support a separate console? - bool old_debugstate = debugState.isValid; - - debugState.p_var_segs = segids; - debugState.p_vars = variables; - debugState.p_var_max = variables_nr; - debugState.p_var_base = variables_base; - debugState.p_pc = pc; - debugState.p_sp = sp; - debugState.p_pp = pp; - debugState.p_objp = objp; - debugState.p_restadjust = restadjust; printf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); - debugState.isValid = true; - disassemble(s, *pc, 0, 1); - if (debugState.seeking == kDebugSeekGlobal) - printf("Global %d (0x%x) = %04x:%04x\n", debugState.seekSpecial, - debugState.seekSpecial, PRINT_REG(s->script_000->locals_block->_locals[debugState.seekSpecial])); - - debugState.isValid = old_debugstate; + disassemble(s, scriptState.xs->addr.pc, 0, 1); + if (scriptState.seeking == kDebugSeekGlobal) + printf("Global %d (0x%x) = %04x:%04x\n", scriptState.seekSpecial, + scriptState.seekSpecial, PRINT_REG(s->script_000->locals_block->_locals[scriptState.seekSpecial])); - if (debugState.seeking && !bp) { // Are we looking for something special? - MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); + if (scriptState.seeking && !bp) { // Are we looking for something special? + MemObject *mobj = GET_SEGMENT(*s->seg_manager, scriptState.xs->addr.pc.segment, MEM_OBJ_SCRIPT); if (mobj) { Script *scr = (Script *)mobj; byte *code_buf = scr->buf; int code_buf_size = scr->buf_size; - int opcode = pc->offset >= code_buf_size ? 0 : code_buf[pc->offset]; + int opcode = scriptState.xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset]; int op = opcode >> 1; - int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1)); + int paramb1 = scriptState.xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (scriptState.xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + scriptState.xs->addr.pc.offset + 1)); - switch (debugState.seeking) { + switch (scriptState.seeking) { case kDebugSeekSpecialCallk: - if (paramb1 != debugState.seekSpecial) + if (paramb1 != scriptState.seekSpecial) return; case kDebugSeekCallk: { @@ -361,7 +341,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } case kDebugSeekLevelRet: { - if ((op != op_ret) || (debugState.seekLevel < (int)s->_executionStack.size()-1)) + if ((op != op_ret) || (scriptState.seekLevel < (int)s->_executionStack.size()-1)) return; break; } @@ -373,7 +353,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * return; // param or temp if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 - if (paramf1 != debugState.seekSpecial) + if (paramf1 != scriptState.seekSpecial) return; // CORRECT global? break; @@ -382,32 +362,17 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * break; case kDebugSeekNothing: - // FIXME: Unhandled? + // We seek nothing, so just continue break; } - debugState.seeking = kDebugSeekNothing; + scriptState.seeking = kDebugSeekNothing; // OK, found whatever we were looking for } } - - debugState.isValid = (debugState.runningStep == 0); - - if (debugState.isValid) { - debugState.p_pc = pc; - debugState.p_sp = sp; - debugState.p_pp = pp; - debugState.p_objp = objp; - debugState.p_restadjust = restadjust; - debugState.p_var_segs = segids; - debugState.p_vars = variables; - debugState.p_var_max = variables_nr; - debugState.p_var_base = variables_base; - - printf("Step #%d\n", script_step_counter); - disassemble(s, *pc, 0, 1); - } - + + printf("Step #%d\n", script_step_counter); + disassemble(s, scriptState.xs->addr.pc, 0, 1); } } // End of namespace Sci diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index e618077d54..c43fe9b6de 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -87,7 +87,7 @@ EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 fla _executionStackPosChanged = false; r_acc = NULL_REG; - r_amp_rest = 0; + restAdjust = 0; r_prev = NULL_REG; stack_segment = 0; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index ecfb9fe6f7..92a5b5e411 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -208,7 +208,7 @@ public: bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ - unsigned int r_amp_rest; /**< &rest register (only used for save games) */ + uint16 restAdjust; /**< &rest register (only used for save games) */ reg_t r_prev; /**< previous comparison result */ SegmentId stack_segment; /**< Heap area for the stack to use */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c6643b8a90..9bbdb90e0c 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -177,8 +177,8 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #endif -#define READ_VAR(type, index, def) validate_read_var(variables[type], s->stack_base, type, variables_max[type], index, __LINE__, def) -#define WRITE_VAR(type, index, value) validate_write_var(variables[type], s->stack_base, type, variables_max[type], index, __LINE__, value) +#define READ_VAR(type, index, def) validate_read_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, def) +#define WRITE_VAR(type, index, value) validate_write_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, value) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) @@ -220,15 +220,15 @@ reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t call #define PUSH(v) PUSH32(make_reg(0, v)) #define POP() (validate_arithmetic(POP32())) // 32 bit: -#define PUSH32(a) (*(validate_stack_addr(s, (xs->sp)++)) = (a)) -#define POP32() (*(validate_stack_addr(s, --(xs->sp)))) +#define PUSH32(a) (*(validate_stack_addr(s, (scriptState.xs->sp)++)) = (a)) +#define POP32() (*(validate_stack_addr(s, --(scriptState.xs->sp)))) // Getting instruction parameters -#define GET_OP_BYTE() ((uint8)code_buf[(xs->addr.pc.offset)++]) -#define GET_OP_WORD() (READ_LE_UINT16(code_buf + ((xs->addr.pc.offset) += 2) - 2)) +#define GET_OP_BYTE() ((uint8)code_buf[(scriptState.xs->addr.pc.offset)++]) +#define GET_OP_WORD() (READ_LE_UINT16(code_buf + ((scriptState.xs->addr.pc.offset) += 2) - 2)) #define GET_OP_FLEX() ((opcode & 1)? GET_OP_BYTE() : GET_OP_WORD()) -#define GET_OP_SIGNED_BYTE() ((int8)(code_buf[(xs->addr.pc.offset)++])) -#define GET_OP_SIGNED_WORD() (((int16)READ_LE_UINT16(code_buf + ((xs->addr.pc.offset) += 2) - 2))) +#define GET_OP_SIGNED_BYTE() ((int8)(code_buf[(scriptState.xs->addr.pc.offset)++])) +#define GET_OP_SIGNED_WORD() (((int16)READ_LE_UINT16(code_buf + ((scriptState.xs->addr.pc.offset) += 2) - 2))) #define GET_OP_SIGNED_FLEX() ((opcode & 1)? GET_OP_SIGNED_BYTE() : GET_OP_SIGNED_WORD()) ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { @@ -388,7 +388,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt break; #ifdef STRICT_SEND default: - debugState.seeking = debugState.runningStep = 0; + scriptState.seeking = scriptState.runningStep = 0; error("Send error: Variable selector %04x in %04x:%04x called with %04x params", selector, PRINT_REG(send_obj), argc); #endif } @@ -543,11 +543,7 @@ static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1}; void run_vm(EngineState *s, int restoring) { assert(s); - reg_t *variables[4]; // global, local, temp, param, as immediate pointers - reg_t *variables_base[4]; // Used for referencing VM ops - SegmentId variables_seg[4]; // Same as above, contains segment IDs #ifndef DISABLE_VALIDATIONS - int variables_max[4]; // Max. values for all variables unsigned int code_buf_size = 0 ; // (Avoid spurious warning) #endif int temp; @@ -556,13 +552,13 @@ void run_vm(EngineState *s, int restoring) { StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - int restadjust = s->r_amp_rest; + scriptState.restadjust = s->restAdjust; // &rest adjusts the parameter count by this value // Current execution data: - ExecStack *xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; - Object *obj = obj_get(s, xs->objp); - Script *local_script = script_locate_by_segment(s, xs->local_segment); + Object *obj = obj_get(s, scriptState.xs->objp); + Script *local_script = script_locate_by_segment(s, scriptState.xs->local_segment); int old_execution_stack_base = s->execution_stack_base; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) @@ -577,22 +573,20 @@ void run_vm(EngineState *s, int restoring) { #ifndef DISABLE_VALIDATIONS // Initialize maximum variable count if (s->script_000->locals_block) - variables_max[VAR_GLOBAL] = s->script_000->locals_block->_locals.size(); + scriptState.variables_max[VAR_GLOBAL] = s->script_000->locals_block->_locals.size(); else - variables_max[VAR_GLOBAL] = 0; + scriptState.variables_max[VAR_GLOBAL] = 0; #endif - variables_seg[VAR_GLOBAL] = s->script_000->locals_segment; - variables_seg[VAR_TEMP] = variables_seg[VAR_PARAM] = s->stack_segment; - variables_base[VAR_TEMP] = variables_base[VAR_PARAM] = s->stack_base; + scriptState.variables_seg[VAR_GLOBAL] = s->script_000->locals_segment; + scriptState.variables_seg[VAR_TEMP] = scriptState.variables_seg[VAR_PARAM] = s->stack_segment; + scriptState.variables_base[VAR_TEMP] = scriptState.variables_base[VAR_PARAM] = s->stack_base; // SCI code reads the zeroeth argument to determine argc if (s->script_000->locals_block) - variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = s->script_000->locals_block->_locals.begin(); + scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = s->script_000->locals_block->_locals.begin(); else - variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = NULL; - - + scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = NULL; s->_executionStackPosChanged = true; // Force initialization @@ -602,58 +596,58 @@ void run_vm(EngineState *s, int restoring) { int var_type; // See description below int var_number; - debugState.old_pc_offset = xs->addr.pc.offset; - debugState.old_sp = xs->sp; + scriptState.old_pc_offset = scriptState.xs->addr.pc.offset; + scriptState.old_sp = scriptState.xs->sp; if (s->_executionStackPosChanged) { Script *scr; - xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; - scr = script_locate_by_segment(s, xs->addr.pc.segment); + scr = script_locate_by_segment(s, scriptState.xs->addr.pc.segment); if (!scr) { // No script? Implicit return via fake instruction buffer - warning("Running on non-existant script in segment %x", xs->addr.pc.segment); + warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment); code_buf = _fake_return_buffer; #ifndef DISABLE_VALIDATIONS code_buf_size = 2; #endif - xs->addr.pc.offset = 1; + scriptState.xs->addr.pc.offset = 1; scr = NULL; obj = NULL; } else { - obj = obj_get(s, xs->objp); + obj = obj_get(s, scriptState.xs->objp); code_buf = scr->buf; #ifndef DISABLE_VALIDATIONS code_buf_size = scr->buf_size; #endif - local_script = script_locate_by_segment(s, xs->local_segment); + local_script = script_locate_by_segment(s, scriptState.xs->local_segment); if (!local_script) { - warning("Could not find local script from segment %x", xs->local_segment); + warning("Could not find local script from segment %x", scriptState.xs->local_segment); local_script = NULL; - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL; + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS - variables_max[VAR_LOCAL] = 0; + scriptState.variables_max[VAR_LOCAL] = 0; #endif } else { - variables_seg[VAR_LOCAL] = local_script->locals_segment; + scriptState.variables_seg[VAR_LOCAL] = local_script->locals_segment; if (local_script->locals_block) - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = local_script->locals_block->_locals.begin(); + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = local_script->locals_block->_locals.begin(); else - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL; + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS if (local_script->locals_block) - variables_max[VAR_LOCAL] = local_script->locals_block->_locals.size(); + scriptState.variables_max[VAR_LOCAL] = local_script->locals_block->_locals.size(); else - variables_max[VAR_LOCAL] = 0; - variables_max[VAR_TEMP] = xs->sp - xs->fp; - variables_max[VAR_PARAM] = xs->argc + 1; + scriptState.variables_max[VAR_LOCAL] = 0; + scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp; + scriptState.variables_max[VAR_PARAM] = scriptState.xs->argc + 1; #endif } - variables[VAR_TEMP] = xs->fp; - variables[VAR_PARAM] = xs->variables_argp; + scriptState.variables[VAR_TEMP] = scriptState.xs->fp; + scriptState.variables[VAR_PARAM] = scriptState.xs->variables_argp; } } @@ -665,24 +659,18 @@ void run_vm(EngineState *s, int restoring) { #if 0 // Debug if this has been requested: if (script_debug_flag || sci_debug_flags) { - script_debug(s, &(xs->addr.pc), &(xs->sp), &(xs->fp), &(xs->objp), &restadjust, variables_seg, variables, variables_base, -#ifdef DISABLE_VALIDATIONS - NULL, -#else - variables_max, -#endif - breakpointFlag); + script_debug(s, breakpointFlag); breakpointFlag = false; } #endif #ifndef DISABLE_VALIDATIONS - if (xs->sp < xs->fp) + if (scriptState.xs->sp < scriptState.xs->fp) error("run_vm(): stack underflow"); - variables_max[VAR_TEMP] = xs->sp - xs->fp; + scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp; - if (xs->addr.pc.offset >= code_buf_size) + if (scriptState.xs->addr.pc.offset >= code_buf_size) error("run_vm(): program counter gone astray"); #endif @@ -900,16 +888,16 @@ void run_vm(EngineState *s, int restoring) { case 0x17: // bt if (s->r_acc.offset || s->r_acc.segment) - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x18: // bnt if (!(s->r_acc.offset || s->r_acc.segment)) - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x19: // jmp - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x1a: // ldi @@ -925,33 +913,36 @@ void run_vm(EngineState *s, int restoring) { break; case 0x1d: // toss - xs->sp--; + scriptState.xs->sp--; break; case 0x1e: // dup - r_temp = xs->sp[-1]; + r_temp = scriptState.xs->sp[-1]; PUSH32(r_temp); break; case 0x1f: { // link int i; for (i = 0; i < opparams[0]; i++) - xs->sp[i] = NULL_REG; - xs->sp += opparams[0]; + scriptState.xs->sp[i] = NULL_REG; + scriptState.xs->sp += opparams[0]; break; } case 0x20: { // call int argc = (opparams[1] >> 1) // Given as offset, but we need count - + 1 + restadjust; - StackPtr call_base = xs->sp - argc; - xs->sp[1].offset += restadjust; - - xs_new = add_exec_stack_entry(s, make_reg(xs->addr.pc.segment, xs->addr.pc.offset + opparams[0]), - xs->sp, xs->objp, (validate_arithmetic(*call_base)) + restadjust, - call_base, NULL_SELECTOR, xs->objp, s->_executionStack.size()-1, xs->local_segment); - restadjust = 0; // Used up the &rest adjustment - xs->sp = call_base; + + 1 + scriptState.restadjust; + StackPtr call_base = scriptState.xs->sp - argc; + scriptState.xs->sp[1].offset += scriptState.restadjust; + + xs_new = add_exec_stack_entry(s, make_reg(scriptState.xs->addr.pc.segment, + scriptState.xs->addr.pc.offset + opparams[0]), + scriptState.xs->sp, scriptState.xs->objp, + (validate_arithmetic(*call_base)) + scriptState.restadjust, + call_base, NULL_SELECTOR, scriptState.xs->objp, + s->_executionStack.size()-1, scriptState.xs->local_segment); + scriptState.restadjust = 0; // Used up the &rest adjustment + scriptState.xs->sp = call_base; s->_executionStackPosChanged = true; break; @@ -960,25 +951,28 @@ void run_vm(EngineState *s, int restoring) { case 0x21: // callk gc_countdown(s); - xs->sp -= (opparams[1] >> 1) + 1; + scriptState.xs->sp -= (opparams[1] >> 1) + 1; if (!s->_kernel->hasOldScriptHeader()) { - xs->sp -= restadjust; - s->r_amp_rest = 0; // We just used up the restadjust, remember? + scriptState.xs->sp -= scriptState.restadjust; + s->restAdjust = 0; // We just used up the restadjust, remember? } if (opparams[0] >= (int)s->_kernel->_kernelFuncs.size()) { error("Invalid kernel function 0x%x requested\n", opparams[0]); } else { - int argc = ASSERT_ARITHMETIC(xs->sp[0]); + int argc = ASSERT_ARITHMETIC(scriptState.xs->sp[0]); if (!s->_kernel->hasOldScriptHeader()) - argc += restadjust; + argc += scriptState.restadjust; if (s->_kernel->_kernelFuncs[opparams[0]].signature - && !kernel_matches_signature(s, s->_kernel->_kernelFuncs[opparams[0]].signature, argc, xs->sp + 1)) { + && !kernel_matches_signature(s, + s->_kernel->_kernelFuncs[opparams[0]].signature, argc, + scriptState.xs->sp + 1)) { error("[VM] Invalid arguments to kernel call %x\n", opparams[0]); } else { - s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1); + s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], + argc, scriptState.xs->sp + 1); } // Call kernel function @@ -989,31 +983,33 @@ void run_vm(EngineState *s, int restoring) { s->_executionStackPosChanged = true; if (!s->_kernel->hasOldScriptHeader()) - restadjust = s->r_amp_rest; + scriptState.restadjust = s->restAdjust; } break; case 0x22: // callb - temp = ((opparams[1] >> 1) + restadjust + 1); - s_temp = xs->sp; - xs->sp -= temp; - - xs->sp[0].offset += restadjust; - xs_new = execute_method(s, 0, opparams[0], s_temp, xs->objp, xs->sp[0].offset, xs->sp); - restadjust = 0; // Used up the &rest adjustment + temp = ((opparams[1] >> 1) + scriptState.restadjust + 1); + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= temp; + + scriptState.xs->sp[0].offset += scriptState.restadjust; + xs_new = execute_method(s, 0, opparams[0], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset, scriptState.xs->sp); + scriptState.restadjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case 0x23: // calle - temp = ((opparams[2] >> 1) + restadjust + 1); - s_temp = xs->sp; - xs->sp -= temp; + temp = ((opparams[2] >> 1) + scriptState.restadjust + 1); + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= temp; - xs->sp[0].offset += restadjust; - xs_new = execute_method(s, opparams[0], opparams[1], s_temp, xs->objp, xs->sp[0].offset, xs->sp); - restadjust = 0; // Used up the &rest adjustment + scriptState.xs->sp[0].offset += scriptState.restadjust; + xs_new = execute_method(s, opparams[0], opparams[1], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset, scriptState.xs->sp); + scriptState.restadjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; @@ -1021,8 +1017,8 @@ void run_vm(EngineState *s, int restoring) { case 0x24: // ret do { - StackPtr old_sp2 = xs->sp; - StackPtr old_fp = xs->fp; + StackPtr old_sp2 = scriptState.xs->sp; + StackPtr old_fp = scriptState.xs->fp; ExecStack *old_xs = &(s->_executionStack.back()); if ((int)s->_executionStack.size()-1 == s->execution_stack_base) { // Have we reached the base? @@ -1031,7 +1027,7 @@ void run_vm(EngineState *s, int restoring) { s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - s->r_amp_rest = restadjust; // Update &rest + s->restAdjust = scriptState.restadjust; // Update &rest return; // "Hard" return } @@ -1046,80 +1042,84 @@ void run_vm(EngineState *s, int restoring) { // Not reached the base, so let's do a soft return s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); - if (xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer - || xs->type != EXEC_STACK_TYPE_CALL) { - xs->sp = old_sp2; - xs->fp = old_fp; + if (scriptState.xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer + || scriptState.xs->type != EXEC_STACK_TYPE_CALL) { + scriptState.xs->sp = old_sp2; + scriptState.xs->fp = old_fp; } - } while (xs->type == EXEC_STACK_TYPE_VARSELECTOR); + } while (scriptState.xs->type == EXEC_STACK_TYPE_VARSELECTOR); // Iterate over all varselector accesses s->_executionStackPosChanged = true; - xs_new = xs; + xs_new = scriptState.xs; break; case 0x25: // send - s_temp = xs->sp; - xs->sp -= ((opparams[0] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restadjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, (int)(opparams[0] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restadjust; + xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, + (int)(opparams[0] >> 1) + scriptState.restadjust, scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restadjust = 0; break; case 0x28: // class - s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, xs->addr.pc); + s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, + scriptState.xs->addr.pc); break; case 0x2a: // self - s_temp = xs->sp; - xs->sp -= ((opparams[0] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restadjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, xs->objp, xs->objp, s_temp, (int)(opparams[0] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restadjust; + xs_new = send_selector(s, scriptState.xs->objp, scriptState.xs->objp, + s_temp, (int)(opparams[0] >> 1) + scriptState.restadjust, + scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restadjust = 0; break; case 0x2b: // super - r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, xs->addr.pc); + r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc); if (!r_temp.segment) error("[VM]: Invalid superclass in object"); else { - s_temp = xs->sp; - xs->sp -= ((opparams[1] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[1] >> 1) + scriptState.restadjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, r_temp, xs->objp, s_temp, (int)(opparams[1] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restadjust; + xs_new = send_selector(s, r_temp, scriptState.xs->objp, s_temp, + (int)(opparams[1] >> 1) + scriptState.restadjust, + scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restadjust = 0; } break; case 0x2c: // &rest temp = (uint16) opparams[0]; // First argument - restadjust = xs->argc - temp + 1; // +1 because temp counts the paramcount while argc doesn't - if (restadjust < 0) - restadjust = 0; + scriptState.restadjust = MAX(scriptState.xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't - for (; temp <= xs->argc; temp++) - PUSH32(xs->variables_argp[temp]); + for (; temp <= scriptState.xs->argc; temp++) + PUSH32(scriptState.xs->variables_argp[temp]); break; @@ -1128,8 +1128,8 @@ void run_vm(EngineState *s, int restoring) { var_number = temp & 0x03; // Get variable type // Get variable block offset - r_temp.segment = variables_seg[var_number]; - r_temp.offset = variables[var_number] - variables_base[var_number]; + r_temp.segment = scriptState.variables_seg[var_number]; + r_temp.offset = scriptState.variables[var_number] - scriptState.variables_base[var_number]; if (temp & 0x08) // Add accumulator offset if requested r_temp.offset += signed_validate_arithmetic(s->r_acc); @@ -1142,7 +1142,7 @@ void run_vm(EngineState *s, int restoring) { case 0x2e: // selfID - s->r_acc = xs->objp; + s->r_acc = scriptState.xs->objp; break; case 0x30: // pprev @@ -1189,7 +1189,7 @@ void run_vm(EngineState *s, int restoring) { case 0x39: // lofsa - s->r_acc.segment = xs->addr.pc.segment; + s->r_acc.segment = scriptState.xs->addr.pc.segment; if (s->_version >= SCI_VERSION_1_1) { s->r_acc.offset = opparams[0] + local_script->script_size; @@ -1197,7 +1197,7 @@ void run_vm(EngineState *s, int restoring) { if (s->_kernel->hasLofsAbsolute()) s->r_acc.offset = opparams[0]; else - s->r_acc.offset = xs->addr.pc.offset + opparams[0]; + s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0]; } #ifndef DISABLE_VALIDATIONS @@ -1209,7 +1209,7 @@ void run_vm(EngineState *s, int restoring) { break; case 0x3a: // lofss - r_temp.segment = xs->addr.pc.segment; + r_temp.segment = scriptState.xs->addr.pc.segment; if (s->_version >= SCI_VERSION_1_1) { r_temp.offset = opparams[0] + local_script->script_size; @@ -1217,7 +1217,7 @@ void run_vm(EngineState *s, int restoring) { if (s->_kernel->hasLofsAbsolute()) r_temp.offset = opparams[0]; else - r_temp.offset = xs->addr.pc.offset + opparams[0]; + r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0]; } #ifndef DISABLE_VALIDATIONS @@ -1242,7 +1242,7 @@ void run_vm(EngineState *s, int restoring) { break; case 0x3e: // pushSelf - PUSH32(xs->objp); + PUSH32(scriptState.xs->objp); break; case 0x40: // lag @@ -1410,12 +1410,12 @@ void run_vm(EngineState *s, int restoring) { } // switch(opcode >> 1) if (s->_executionStackPosChanged) // Force initialization - xs = xs_new; + scriptState.xs = xs_new; //#ifndef DISABLE_VALIDATIONS - if (xs != &(s->_executionStack.back())) { + if (scriptState.xs != &(s->_executionStack.back())) { warning("xs is stale (%p vs %p); last command was %02x", - (void *)xs, (void *)&(s->_executionStack.back()), + (void *)scriptState.xs, (void *)&(s->_executionStack.back()), opnumber); } //#endif @@ -2037,9 +2037,8 @@ const char *obj_get_name(EngineState *s, reg_t pos) { void quit_vm() { script_abort_flag = 1; // Terminate VM - debugState.isValid = false; - debugState.seeking = kDebugSeekNothing; - debugState.runningStep = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } void shrink_execution_stack(EngineState *s, uint size) { diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index a3fabbe44b..1472fae97c 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -243,24 +243,23 @@ enum ExecStackType { }; struct ExecStack { - reg_t objp; - reg_t sendp; /**< Pointer to the object containing the invoked method */ + reg_t objp; // Pointer to the beginning of the current object + reg_t sendp; // Pointer to the object containing the invoked method union { - ObjVarRef varp; /**< Variable pointer for r/w access */ - reg_t pc; /**< Not accurate for the TOS element */ + ObjVarRef varp; // Variable pointer for r/w access + reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element } addr; - StackPtr fp; /**< Frame pointer */ - StackPtr sp; /**< Stack pointer */ + StackPtr fp; // Frame pointer + StackPtr sp; // Stack pointer int argc; - /* former variables[4]: [all other values are derived] */ - StackPtr variables_argp; /**< Argument pointer */ - SegmentId local_segment; /**< local variables etc. */ + StackPtr variables_argp; // Argument pointer + SegmentId local_segment; // local variables etc - Selector selector; /**< The selector which was used to call or -1 if not applicable */ - int origin; /**< The stack frame position the call was made from, or -1 if it was the initial call. */ + Selector selector; // The selector which was used to call or -1 if not applicable + int origin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; reg_t* getVarPointer(EngineState *s) const; @@ -409,27 +408,10 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file); /** * Debugger functionality - * @param[in] s The state at which debugging should take - * place - * @param[in] pc Pointer to the program counter - * @param[in] sp Pointer to the stack pointer - * @param[in] pp Pointer to the frame pointer - * @param[in] objp Pointer to the object base pointer - * @param[in] restadjust Pointer to the &rest adjustment value - * @param[in] segids four-element array containing segment IDs - * for locals etc. - * @param[in] variables four-element array referencing registers - * for globals etc. - * @param[in] variables_base four-element array referencing register - * bases for temps etc. - * @param[in] variables_nr four-element array giving sizes for params - * etc. (may be NULL) - * @param[in] bp Flag, set to 1 when a breakpoint is - * triggered - */ -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); + * @param[in] s The state at which debugging should take place + * @param[in] bp Flag, set to true when a breakpoint is triggered + */ +void script_debug(EngineState *s, bool bp); /** * Initializes a EngineState block diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 09c433edc2..9c94e2edde 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -240,12 +240,12 @@ Common::Error SciEngine::run() { GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { ExecStack *xs = &(_gamestate->_executionStack.back()); - xs->addr.pc.offset = debugState.old_pc_offset; - xs->sp = debugState.old_sp; + xs->addr.pc.offset = scriptState.old_pc_offset; + xs->sp = scriptState.old_sp; } - debugState.runningStep = 0; // Stop multiple execution - debugState.seeking = kDebugSeekNothing; // Stop special seeks + scriptState.runningStep = 0; // Stop multiple execution + scriptState.seeking = kDebugSeekNothing; // Stop special seeks return _console; } -- cgit v1.2.3 From a764f274f83b72c4fafa5ad1c72127462c7c9410 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 8 Jul 2009 10:35:51 +0000 Subject: Fixed saving/loading again (broken with the latest changes for game feature auto-detection) svn-id: r42261 --- engines/sci/engine/savegame.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index f44af2b1cd..83f65db81c 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -756,6 +756,22 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. retval = new EngineState(s->resmgr, s->_version, s->_flags); + // static parser information: + assert(0 == retval->_vocabulary); + retval->_vocabulary = s->_vocabulary; +// s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, +// else it could be freed when the old EngineState is freed. Luckily, this freeing currently +// never happens, so we don't need to. + + retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); + + // static VM/Kernel information: + assert(0 == retval->_kernel); + retval->_kernel = s->_kernel; +// s->_kernel = 0; // FIXME: We should set s->_kernel to 0 here, +// else it could be freed when the old EngineState is freed. Luckily, this freeing currently +// never happens, so we don't need to. + // Copy some old data retval->gfx_state = s->gfx_state; retval->sound_mute = s->sound_mute; @@ -813,22 +829,6 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->last_wait_time = g_system->getMillis(); retval->game_start_time = g_system->getMillis() - retval->game_time * 1000; - // static parser information: - assert(0 == retval->_vocabulary); - retval->_vocabulary = s->_vocabulary; -// s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, -// else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. - - retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); - - // static VM/Kernel information: - assert(0 == retval->_kernel); - retval->_kernel = s->_kernel; -// s->_kernel = 0; // FIXME: We should set s->_kernel to 0 here, -// else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. - // Copy breakpoint information from current game instance retval->have_bp = s->have_bp; retval->bp_list = s->bp_list; -- cgit v1.2.3 From d351c7b9cb6cb46da9bb141c9ca90aba021c1602 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 8 Jul 2009 10:44:25 +0000 Subject: Only the kernel needs to be initialized before anything else, when saving/loading svn-id: r42262 --- engines/sci/engine/savegame.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 83f65db81c..e167e7eca8 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -756,18 +756,9 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. retval = new EngineState(s->resmgr, s->_version, s->_flags); - // static parser information: - assert(0 == retval->_vocabulary); - retval->_vocabulary = s->_vocabulary; -// s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, -// else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. - - retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); - // static VM/Kernel information: assert(0 == retval->_kernel); - retval->_kernel = s->_kernel; + retval->_kernel = s->_kernel; // needs to be initialized before _reset_graphics_input is called // s->_kernel = 0; // FIXME: We should set s->_kernel to 0 here, // else it could be freed when the old EngineState is freed. Luckily, this freeing currently // never happens, so we don't need to. @@ -829,6 +820,15 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->last_wait_time = g_system->getMillis(); retval->game_start_time = g_system->getMillis() - retval->game_time * 1000; + // static parser information: + assert(0 == retval->_vocabulary); + retval->_vocabulary = s->_vocabulary; +// s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, +// else it could be freed when the old EngineState is freed. Luckily, this freeing currently +// never happens, so we don't need to. + + retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); + // Copy breakpoint information from current game instance retval->have_bp = s->have_bp; retval->bp_list = s->bp_list; -- cgit v1.2.3 From 5ca94c5cce2ca0b42bb678835d9e141456bbae5b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 8 Jul 2009 13:08:51 +0000 Subject: - Moved printObject inside the Console class - Enabled the parts where disassemble() is called svn-id: r42263 --- engines/sci/console.cpp | 41 +++++++++++++++++++---------------------- engines/sci/console.h | 4 +++- engines/sci/engine/vm.cpp | 5 ++--- 3 files changed, 24 insertions(+), 26 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 667a39c063..7f20e4013d 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1927,7 +1927,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; case KSIG_OBJECT: DebugPrintf("object\n"); - printObject(_vm->_gamestate, reg); + printObject(reg); break; case KSIG_REF: { int size; @@ -1982,21 +1982,21 @@ bool Console::cmdViewObject(int argc, const char **argv) { } DebugPrintf("Information on the object at the given address:\n"); - printObject(_vm->_gamestate, addr); + printObject(addr); return true; } bool Console::cmdViewActiveObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class:\n"); - printObject(_vm->_gamestate, scriptState.xs->objp); + printObject(scriptState.xs->objp); return true; } bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); - printObject(_vm->_gamestate, _vm->_gamestate->r_acc); + printObject(_vm->_gamestate->r_acc); return true; } @@ -2195,8 +2195,7 @@ bool Console::cmdDissassemble(int argc, const char **argv) { } do { - // TODO - //addr = disassemble(_vm->_gamestate, addr, 0, 0); + addr = disassemble(_vm->_gamestate, addr, 0, 0); } while (addr.offset > 0); return true; @@ -2247,9 +2246,7 @@ bool Console::cmdDissassembleAddress(int argc, const char **argv) { } do { - // TODO - //vpc = disassemble(_vm->_gamestate, vpc, do_bwc, do_bytes); - + vpc = disassemble(_vm->_gamestate, vpc, do_bwc, do_bytes); } while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--op_count)); return true; @@ -3029,47 +3026,47 @@ int Console::printNode(reg_t addr) { return 0; } -int printObject(EngineState *s, reg_t pos) { +int Console::printObject(reg_t pos) { + EngineState *s = _vm->_gamestate; // for the several defines in this function Object *obj = obj_get(s, pos); Object *var_container = obj; int i; - Console *con = ((SciEngine *)g_engine)->getSciDebugger(); if (!obj) { - con->DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); + DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); return 1; } // Object header - printf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s, pos), + DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s, pos), obj->_variables.size(), obj->methods_nr); if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) var_container = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); - printf(" -- member variables:\n"); + DebugPrintf(" -- member variables:\n"); for (i = 0; (uint)i < obj->_variables.size(); i++) { printf(" "); if (i < var_container->variable_names_nr) { - printf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); + DebugPrintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); } else - printf("p#%x = ", i); + DebugPrintf("p#%x = ", i); reg_t val = obj->_variables[i]; - printf("%04x:%04x", PRINT_REG(val)); + DebugPrintf("%04x:%04x", PRINT_REG(val)); Object *ref = obj_get(s, val); if (ref) - printf(" (%s)", obj_get_name(s, val)); + DebugPrintf(" (%s)", obj_get_name(s, val)); - printf("\n"); + DebugPrintf("\n"); } - printf(" -- methods:\n"); + DebugPrintf(" -- methods:\n"); for (i = 0; i < obj->methods_nr; i++) { reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, i); - printf(" [%03x] %s = %04x:%04x\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); + DebugPrintf(" [%03x] %s = %04x:%04x\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); } if (s->seg_manager->_heap[pos.segment]->getType() == MEM_OBJ_SCRIPT) - printf("\nOwner script:\t%d\n", s->seg_manager->getScript(pos.segment)->nr); + DebugPrintf("\nOwner script:\t%d\n", s->seg_manager->getScript(pos.segment)->nr); return 0; } diff --git a/engines/sci/console.h b/engines/sci/console.h index bc07ddb530..8d1299dd1e 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -37,7 +37,7 @@ struct List; // Refer to the "addresses" command on how to pass address parameters int parse_reg_t(EngineState *s, const char *str, reg_t *dest); -int printObject(EngineState *s, reg_t pos); +reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode); class Console : public GUI::Debugger { public: @@ -46,6 +46,8 @@ public: void preEnter(); void postEnter(); + int printObject(reg_t pos); + private: // General bool cmdHelp(int argc, const char **argv); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9bbdb90e0c..e0ac60f152 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1972,8 +1972,6 @@ static EngineState *_game_run(EngineState *&s, int restoring) { return s; } -int printObject(EngineState *s, reg_t pos); - int game_run(EngineState **_s) { EngineState *s = *_s; @@ -1982,7 +1980,8 @@ int game_run(EngineState **_s) { // Now: Register the first element on the execution stack- if (!send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base)) { - printObject(s, s->game_obj); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + con->printObject(s->game_obj); warning("Failed to run the game! Aborting..."); return 1; } -- cgit v1.2.3