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
This commit is contained in:
parent
90422f6bd3
commit
62499054a0
11 changed files with 240 additions and 310 deletions
|
@ -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("<no execution stack: pc,obj,fp omitted>\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<cmd_param_t> &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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]));
|
||||
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]));
|
||||
|
||||
debugState.isValid = old_debugstate;
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
+ 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(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;
|
||||
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;
|
||||
temp = ((opparams[1] >> 1) + scriptState.restadjust + 1);
|
||||
s_temp = scriptState.xs->sp;
|
||||
scriptState.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
|
||||
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) {
|
||||
|
|
|
@ -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
|
||||
* @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, 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);
|
||||
|
||||
/**
|
||||
* Initializes a EngineState block
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue