diff options
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/game.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kevent.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/kmisc.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 97 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 283 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 46 |
8 files changed, 197 insertions, 251 deletions
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<uint16>(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 |