aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2009-05-18 18:15:45 +0000
committerMax Horn2009-05-18 18:15:45 +0000
commitb0c1cf52e0e4d1e092f9cc25fce9eb86b68b7670 (patch)
treec3da948dfbf54a0f78efc34762b71b6f6aa34400
parentb2b08cc606597dcbc93dcb346f845083e9dc5182 (diff)
downloadscummvm-rg350-b0c1cf52e0e4d1e092f9cc25fce9eb86b68b7670.tar.gz
scummvm-rg350-b0c1cf52e0e4d1e092f9cc25fce9eb86b68b7670.tar.bz2
scummvm-rg350-b0c1cf52e0e4d1e092f9cc25fce9eb86b68b7670.zip
SCI: Got rid of EngineState::execution_stack_pos; overally, the resulting code should be even stricter in detecting invalid VM stack access (and some bugs when loading saves might be fixed now...)
svn-id: r40694
-rw-r--r--engines/sci/engine/game.cpp1
-rw-r--r--engines/sci/engine/gc.cpp4
-rw-r--r--engines/sci/engine/kernel.cpp2
-rw-r--r--engines/sci/engine/kfile.cpp2
-rw-r--r--engines/sci/engine/kscripts.cpp6
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/engine/sciconsole.cpp8
-rw-r--r--engines/sci/engine/scriptdebug.cpp24
-rw-r--r--engines/sci/engine/state.cpp1
-rw-r--r--engines/sci/engine/state.h1
-rw-r--r--engines/sci/engine/vm.cpp93
-rw-r--r--engines/sci/engine/vm.h106
12 files changed, 121 insertions, 129 deletions
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index 6f55e2655b..6fefa6ab96 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -430,7 +430,6 @@ int script_init_engine(EngineState *s, sci_version_t version) {
s->_executionStack.clear(); // Start without any execution stack
s->execution_stack_base = -1; // No vm is running yet
- s->execution_stack_pos = -1; // Start at execution stack position 0
vocabulary_get_knames(s->resmgr, s->_kernelNames);
script_map_kernel(s);
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index 9de5357b38..cf556869ee 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -86,7 +86,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
// Init: Value Stack
// We do this one by hand since the stack doesn't know the current execution stack
{
- ExecStack &xs = s->_executionStack[s->execution_stack_pos];
+ ExecStack &xs = s->_executionStack.back();
reg_t *pos;
for (pos = s->stack_base; pos < xs.sp; pos++)
@@ -97,7 +97,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
#endif
// Init: Execution Stack
- for (i = 0; (int)i <= s->execution_stack_pos; i++) {
+ for (i = 0; i < s->_executionStack.size(); i++) {
ExecStack &es = s->_executionStack[i];
if (es.type != EXEC_STACK_TYPE_KERNEL) {
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index cb89e04f9f..8cfdf0115c 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -263,7 +263,7 @@ reg_t kRestartGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
old_save_dir = strdup(deref_save_dir);
s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; // This appears to help
- s->execution_stack_pos = s->execution_stack_base;
+ s->_executionStack.resize(s->execution_stack_base + 1);
script_abort_flag = 1; // Force vm to abort ASAP
return NULL_REG;
}
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 23c9d90047..a27268798f 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -652,7 +652,7 @@ reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (newstate) {
s->successor = newstate;
script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
- s->execution_stack_pos = s->execution_stack_base;
+ s->_executionStack.resize(s->execution_stack_base + 1);
} else {
s->r_acc = make_reg(0, 1);
sciprintf("Restoring failed (game_id = '%s').\n", game_id);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 1598cdcc56..8610478b05 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -92,7 +92,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, int noinvalid
// Write "kernel" call to the stack, for debugging:
xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, k_argc, k_argp - 1, 0, NULL_REG,
- s->execution_stack_pos, SCI_XS_CALLEE_LOCALS);
+ s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
xstack->selector = -42 - kfunct; // Evil debugging hack to identify kernel function
xstack->type = EXEC_STACK_TYPE_KERNEL;
@@ -104,7 +104,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, int noinvalid
run_vm(s, 0); // Start a new vm
- --(s->execution_stack_pos); // Get rid of the extra stack entry
+ s->_executionStack.pop_back(); // Get rid of the extra stack entry
return 0;
}
@@ -269,7 +269,7 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int id = s->seg_manager->segGet(script);
Script *scr = s->seg_manager->getScriptIfLoaded(id);
if (scr) {
- if (s->_executionStack[s->execution_stack_pos].addr.pc.segment != id)
+ if (s->_executionStack.back().addr.pc.segment != id)
scr->setLockers(1);
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 1339b0368a..0bd715719f 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -794,7 +794,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
// Set exec stack base to zero
retval->execution_stack_base = 0;
- retval->execution_stack_pos = 0;
+ retval->_executionStack.clear();
// Now copy all current state information
// Graphics and input state:
diff --git a/engines/sci/engine/sciconsole.cpp b/engines/sci/engine/sciconsole.cpp
index 7bbe5f83c4..2a116506c2 100644
--- a/engines/sci/engine/sciconsole.cpp
+++ b/engines/sci/engine/sciconsole.cpp
@@ -221,10 +221,10 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
rel_offsetting = 1;
if (!scumm_strnicmp(str + 1, "PC", 2)) {
- *dest = s->_executionStack[s->execution_stack_pos].addr.pc;
+ *dest = s->_executionStack.back().addr.pc;
offsetting = str + 3;
} else if (!scumm_strnicmp(str + 1, "P", 1)) {
- *dest = s->_executionStack[s->execution_stack_pos].addr.pc;
+ *dest = s->_executionStack.back().addr.pc;
offsetting = str + 2;
} else if (!scumm_strnicmp(str + 1, "PREV", 4)) {
*dest = s->r_prev;
@@ -236,10 +236,10 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
*dest = s->r_acc;
offsetting = str + 2;
} else if (!scumm_strnicmp(str + 1, "OBJ", 3)) {
- *dest = s->_executionStack[s->execution_stack_pos].objp;
+ *dest = s->_executionStack.back().objp;
offsetting = str + 4;
} else if (!scumm_strnicmp(str + 1, "O", 1)) {
- *dest = s->_executionStack[s->execution_stack_pos].objp;
+ *dest = s->_executionStack.back().objp;
offsetting = str + 2;
} else
return 1; // No matching register
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 73ccc357b9..171c1435ea 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -692,7 +692,7 @@ int c_debuginfo(EngineState *s) {
sciprintf("acc="PREG" prev="PREG" &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), *p_restadjust);
- if (!s->_executionStack.empty() && s->execution_stack_pos >= 0) {
+ if (!s->_executionStack.empty()) {
sciprintf("pc="PREG" obj="PREG" fp="PSTK" sp="PSTK"\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp));
} else
sciprintf("<no execution stack: pc,obj,fp omitted>\n");
@@ -728,7 +728,7 @@ int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ ||
opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) {
_debug_seeking = _DEBUG_SEEK_SO;
- _debug_seek_level = s->execution_stack_pos;
+ _debug_seek_level = s->_executionStack.size()-1;
// Store in _debug_seek_special the offset of the next command after send
switch (opcode) {
case 0x46: // calle W
@@ -1103,7 +1103,7 @@ int c_restore_game(EngineState *s, const Common::Array<cmd_param_t> &cmdParams)
script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
_debugstate_valid = 0;
- s->execution_stack_pos = s->execution_stack_base;
+ s->_executionStack.resize(s->execution_stack_base + 1);
return 0;
} else {
sciprintf("Restoring gamestate '%s' failed.\n", cmdParams[0].str);
@@ -1151,12 +1151,12 @@ int c_stack(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
return 1;
}
- if (s->execution_stack_pos < 0) {
+ if (s->_executionStack.empty()) {
sciprintf("No exec stack!");
return 1;
}
- ExecStack &xs = s->_executionStack[s->execution_stack_pos];
+ ExecStack &xs = s->_executionStack.back();
for (int i = cmdParams[0].val ; i > 0; i--) {
if ((xs.sp - xs.fp - i) == 0)
@@ -1526,15 +1526,13 @@ int c_vmvars(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
}
static int c_backtrace(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- int i;
-
if (!_debugstate_valid) {
sciprintf("Not in debug state\n");
return 1;
}
sciprintf("Call stack (current base: 0x%x):\n", s->execution_stack_base);
- for (i = 0; i <= s->execution_stack_pos; i++) {
+ for (uint i = 0; i < s->_executionStack.size(); i++) {
ExecStack &call = s->_executionStack[i];
const char *objname = obj_get_name(s, call.sendp);
int paramc, totalparamc;
@@ -2121,7 +2119,7 @@ static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
static int c_sret(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
_debug_seeking = _DEBUG_SEEK_LEVEL_RET;
- _debug_seek_level = s->execution_stack_pos;
+ _debug_seek_level = s->_executionStack.size()-1;
_debugstate_valid = 0;
return 0;
}
@@ -2176,7 +2174,7 @@ static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
stackframe[i] = cmdParams[i].reg;
xstack = add_exec_stack_entry(s, fptr, s->_executionStack[0].sp + cmdParams.size(), object, cmdParams.size() - 2,
- s->_executionStack[0].sp - 1, 0, object, s->execution_stack_pos, SCI_XS_CALLEE_LOCALS);
+ s->_executionStack[0].sp - 1, 0, object, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
xstack->selector = selector_id;
xstack->type = selector_type == kSelectorVariable ? EXEC_STACK_TYPE_VARSELECTOR : EXEC_STACK_TYPE_CALL;
@@ -2904,13 +2902,13 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
}
case _DEBUG_SEEK_LEVEL_RET: {
- if ((op != op_ret) || (_debug_seek_level < s->execution_stack_pos))
+ if ((op != op_ret) || (_debug_seek_level < (int)s->_executionStack.size()-1))
return;
break;
}
case _DEBUG_SEEK_SO:
- if (!REG_EQ(*pc, _debug_seek_reg) || s->execution_stack_pos != _debug_seek_level)
+ if (!REG_EQ(*pc, _debug_seek_reg) || (int)s->_executionStack.size()-1 != _debug_seek_level)
return;
break;
@@ -2920,7 +2918,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
return;
if ((op & 0x3) > 1)
return; // param or temp
- if ((op & 0x3) && s->_executionStack[s->execution_stack_pos].local_segment > 0)
+ if ((op & 0x3) && s->_executionStack.back().local_segment > 0)
return; // locals and not running in script.000
if (paramf1 != _debug_seek_special)
return; // CORRECT global?
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 374f997fdb..f60697d83c 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -104,7 +104,6 @@ EngineState::EngineState() : _dirseeker(this) {
kernel_opt_flags = 0;
- execution_stack_pos = 0;
execution_stack_base = 0;
_executionStackPosChanged = false;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 5ab90f442a..c178016a6e 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -208,7 +208,6 @@ public:
/* VM Information */
Common::Array<ExecStack> _executionStack; /**< The execution stack */
- int execution_stack_pos; /**< Position on the execution stack */
/**
* When called from kernel functions, the vm is re-started recursively on
* the same stack. This variable contains the stack base for the current vm.
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 151e4ff572..a51a49ffb3 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -279,49 +279,43 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
}
}
- return add_exec_stack_entry(s, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->execution_stack_pos, seg);
+ return add_exec_stack_entry(s, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg);
}
static void _exec_varselectors(EngineState *s) {
// Executes all varselector read/write ops on the TOS
// Now check the TOS to execute all varselector entries
- if (s->execution_stack_pos >= 0)
- while (s->_executionStack[s->execution_stack_pos].type == EXEC_STACK_TYPE_VARSELECTOR) {
+ if (!s->_executionStack.empty())
+ while (s->_executionStack.back().type == EXEC_STACK_TYPE_VARSELECTOR) {
// varselector access?
- if (s->_executionStack[s->execution_stack_pos].argc) { // write?
- reg_t temp = s->_executionStack[s->execution_stack_pos].variables_argp[1];
- *(s->_executionStack[s->execution_stack_pos].addr.varp) = temp;
+ if (s->_executionStack.back().argc) { // write?
+ reg_t temp = s->_executionStack.back().variables_argp[1];
+ *(s->_executionStack.back().addr.varp) = temp;
} else // No, read
- s->r_acc = *(s->_executionStack[s->execution_stack_pos].addr.varp);
+ s->r_acc = *(s->_executionStack.back().addr.varp);
- --(s->execution_stack_pos);
+ s->_executionStack.pop_back();
}
}
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) {
// send_obj and work_obj are equal for anything but 'super'
// Returns a pointer to the TOS exec_stack element
-#ifdef VM_DEBUG_SEND
- int i;
-#endif
+ assert(s);
+
reg_t *varp;
reg_t funcp;
int selector;
int argc;
- int origin = s->execution_stack_pos; // Origin: Used for debugging
+ int origin = s->_executionStack.size()-1; // Origin: Used for debugging
int print_send_action = 0;
// We return a pointer to the new active ExecStack
// The selector calls we catch are stored below:
Common::Stack<CallsStruct> sendCalls;
- if (NULL == s) {
- sciprintf("vm.c: ExecStack(): NULL passed for \"s\"\n");
- return NULL;
- }
-
while (framesize > 0) {
selector = validate_arithmetic(*argp++);
argc = validate_arithmetic(*argp);
@@ -423,7 +417,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
#ifdef VM_DEBUG_SEND
sciprintf("Funcselector(");
- for (i = 0; i < argc; i++) {
+ for (int i = 0; i < argc; i++) {
sciprintf(PREG, PRINT_REG(argp[i+1]));
if (i + 1 < argc)
sciprintf(", ");
@@ -467,7 +461,9 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
_exec_varselectors(s);
- return &(s->_executionStack[s->execution_stack_pos]);
+ if (s->_executionStack.empty())
+ return NULL;
+ return &(s->_executionStack.back());
}
ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, reg_t *address, int origin) {
@@ -485,36 +481,34 @@ ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t obj
// Returns new TOS element for the execution stack
// locals_segment may be -1 if derived from the called object
- ++s->execution_stack_pos;
- if (s->execution_stack_pos >= (int)s->_executionStack.size()) // Out of stack space?
- s->_executionStack.resize(s->execution_stack_pos+1);
-
//sciprintf("Exec stack: [%d/%d], origin %d, at %p\n", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack);
- ExecStack *xstack = &(s->_executionStack[s->execution_stack_pos]);
+ ExecStack xstack;
- xstack->objp = objp;
+ xstack.objp = objp;
if (locals_segment != SCI_XS_CALLEE_LOCALS)
- xstack->local_segment = locals_segment;
+ xstack.local_segment = locals_segment;
else
- xstack->local_segment = pc.segment;
+ xstack.local_segment = pc.segment;
- xstack->sendp = sendp;
- xstack->addr.pc = pc;
- xstack->fp = xstack->sp = sp;
- xstack->argc = argc;
+ xstack.sendp = sendp;
+ xstack.addr.pc = pc;
+ xstack.fp = xstack.sp = sp;
+ xstack.argc = argc;
- xstack->variables_argp = argp; // Parameters
+ xstack.variables_argp = argp; // Parameters
*argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc
// Additional debug information
- xstack->selector = selector;
- xstack->origin = origin;
+ xstack.selector = selector;
+ xstack.origin = origin;
- xstack->type = EXEC_STACK_TYPE_CALL; // Normal call
+ xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
- return xstack;
+ s->_executionStack.push_back(xstack);
+
+ return &(s->_executionStack.back());
}
#ifdef DISABLE_VALIDATONS
@@ -585,7 +579,7 @@ void run_vm(EngineState *s, int restoring) {
int restadjust = s->r_amp_rest;
// &rest adjusts the parameter count by this value
// Current execution data:
- ExecStack *xs = &(s->_executionStack[s->execution_stack_pos]);
+ ExecStack *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);
@@ -604,7 +598,7 @@ void run_vm(EngineState *s, int restoring) {
}
if (!restoring)
- s->execution_stack_base = s->execution_stack_pos;
+ s->execution_stack_base = s->_executionStack.size()-1;
#ifndef DISABLE_VALIDATIONS
// Initialize maximum variable count
@@ -640,7 +634,7 @@ void run_vm(EngineState *s, int restoring) {
if (s->_executionStackPosChanged) {
Script *scr;
- xs = &(s->_executionStack[s->execution_stack_pos]);
+ xs = &(s->_executionStack.back());
s->_executionStackPosChanged = false;
scr = script_locate_by_segment(s, xs->addr.pc.segment);
@@ -988,7 +982,7 @@ void run_vm(EngineState *s, int restoring) {
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->execution_stack_pos, xs->local_segment);
+ call_base, NULL_SELECTOR, xs->objp, s->_executionStack.size()-1, xs->local_segment);
restadjust = 0; // Used up the &rest adjustment
xs->sp = call_base;
@@ -1026,7 +1020,7 @@ void run_vm(EngineState *s, int restoring) {
// Calculate xs again: The kernel function might
// have spawned a new VM
- xs_new = &(s->_executionStack[s->execution_stack_pos]);
+ xs_new = &(s->_executionStack.back());
s->_executionStackPosChanged = true;
if (!(s->flags & GF_SCI0_OLD))
@@ -1064,12 +1058,12 @@ void run_vm(EngineState *s, int restoring) {
do {
StackPtr old_sp2 = xs->sp;
StackPtr old_fp = xs->fp;
- ExecStack *old_xs = &(s->_executionStack[s->execution_stack_pos]);
+ ExecStack *old_xs = &(s->_executionStack.back());
- if (s->execution_stack_pos == s->execution_stack_base) { // Have we reached the base?
+ if ((int)s->_executionStack.size()-1 == s->execution_stack_base) { // Have we reached the base?
s->execution_stack_base = old_execution_stack_base; // Restore stack base
- --(s->execution_stack_pos);
+ s->_executionStack.pop_back();
s->_executionStackPosChanged = true;
s->r_amp_rest = restadjust; // Update &rest
@@ -1085,10 +1079,10 @@ void run_vm(EngineState *s, int restoring) {
}
// Not reached the base, so let's do a soft return
- --(s->execution_stack_pos);
+ s->_executionStack.pop_back();
xs = old_xs - 1;
s->_executionStackPosChanged = true;
- xs = &(s->_executionStack[s->execution_stack_pos]);
+ xs = &(s->_executionStack.back());
if (xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer
|| xs->type != EXEC_STACK_TYPE_CALL) {
@@ -1452,8 +1446,8 @@ void run_vm(EngineState *s, int restoring) {
xs = xs_new;
#ifndef DISABLE_VALIDATIONS
- if (xs != &(s->_executionStack[s->execution_stack_pos])) {
- sciprintf("Error: xs is stale (%d vs %d); last command was %02x\n", (int)(xs - &s->_executionStack[0]), s->execution_stack_pos, opnumber);
+ if (xs != &(s->_executionStack.back())) {
+ sciprintf("Error: xs is stale (%d vs %d); last command was %02x\n", (int)(xs - &s->_executionStack[0]), s->_executionStack.size()-1, opnumber);
}
#endif
if (script_error_flag) {
@@ -1991,7 +1985,6 @@ static EngineState *_game_run(EngineState *s, int restoring) {
if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested?
successor = NULL;
s->_executionStack.clear();
- s->execution_stack_pos = -1;
s->_executionStackPosChanged = false;
game_exit(s);
@@ -2017,7 +2010,7 @@ static EngineState *_game_run(EngineState *s, int restoring) {
if (script_abort_flag == SCRIPT_ABORT_WITH_REPLAY) {
sciprintf("Restarting with replay()\n");
- s->execution_stack_pos = -1; // Restart with replay
+ s->_executionStack.clear(); // Restart with replay
_init_stack_base_with_selector(s, s->selector_map.replay);
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 5b9c87decb..a6e232472e 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -808,73 +808,77 @@ typedef int kernel_function(struct EngineState *s);
extern kernel_function* kfuncs[];
extern int max_instance;
-/*inline*/
+/**
+ * Executes function pubfunct of the specified script.
+ * Parameters: (EngineState *) s: The state which is to be executed with
+ * (uint16) script: The script which is called
+ * (uint16) pubfunct: The exported script function which is to be called
+ * (StackPtr) sp: Stack pointer position
+ * (reg_t) calling_obj: The heap address of the object which executed the call
+ * (uint16) argc: Number of arguments supplied
+ * (StackPtr) argp: Pointer to the first supplied argument
+ * Returns : (ExecStack *): A pointer to the new exec stack TOS entry
+ */
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj,
uint16 argc, StackPtr argp);
-/* Executes function pubfunct of the specified script.
-** Parameters: (EngineState *) s: The state which is to be executed with
-** (uint16) script: The script which is called
-** (uint16) pubfunct: The exported script function which is to be called
-** (StackPtr) sp: Stack pointer position
-** (reg_t) calling_obj: The heap address of the object which executed the call
-** (uint16) argc: Number of arguments supplied
-** (StackPtr) argp: Pointer to the first supplied argument
-** Returns : (ExecStack *): A pointer to the new exec stack TOS entry
-*/
+/**
+ * Executes a "send" or related operation to a selector.
+ * Parameters: (EngineState *) s: The EngineState to operate on
+ * (reg_t) send_obj: Heap address of the object to send to
+ * (reg_t) work_obj: Heap address of the object initiating the send
+ * (StackPtr) sp: Stack pointer position
+ * (int) framesize: Size of the send as determined by the "send" operation
+ * (StackPtr) argp: Pointer to the beginning of the heap block containing the
+ * data to be sent. This area is a succession of one or more
+ * sequences of [selector_number][argument_counter] and then
+ * "argument_counter" word entries with the parameter values.
+ * Returns : (ExecStack *): A pointer to the new execution stack TOS entry
+ */
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
StackPtr sp, int framesize, StackPtr argp);
-/* Executes a "send" or related operation to a selector
-** Parameters: (EngineState *) s: The EngineState to operate on
-** (reg_t) send_obj: Heap address of the object to send to
-** (reg_t) work_obj: Heap address of the object initiating the send
-** (StackPtr) sp: Stack pointer position
-** (int) framesize: Size of the send as determined by the "send" operation
-** (StackPtr) argp: Pointer to the beginning of the heap block containing the
-** data to be send. This area is a succession of one or more
-** sequences of [selector_number][argument_counter] and then
-** "argument_counter" word entries with the parameter values.
-** Returns : (ExecStack *): A pointer to the new execution stack TOS entry
-*/
#define SCI_XS_CALLEE_LOCALS -1
+/**
+ * Adds an entry to the top of the execution stack.
+ *
+ * @param s The state with which to execute
+ * @param pc The initial program counter
+ * @param sp The initial stack pointer
+ * @param objp Pointer to the beginning of the current object
+ * @param argc Number of parameters to call with
+ * @param argp Heap pointer to the first parameter
+ * @param selector The selector by which it was called or
+ * NULL_SELECTOR if n.a. For debugging.
+ * @param sendp Pointer to the object which the message was sent to.
+ * Equal to objp for anything but super.
+ * @param origin Number of the execution stack element this entry was created by
+ * (usually the current TOS number, except for multiple sends).
+ * @param local_segment The segment to use for local variables,
+ * or SCI_XS_CALLEE_LOCALS to use obj's segment.
+ * @return a pointer to the new exec stack TOS entry
+ */
ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t objp, int argc,
StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId local_segment);
-/* Adds an entry to the top of the execution stack
-** Parameters: (EngineState *) s: The state with which to execute
-** (reg_t) pc: The initial program counter
-** (StackPtr) sp: The initial stack pointer
-** (reg_t) objp: Pointer to the beginning of the current object
-** (int) argc: Number of parameters to call with
-** (StackPtr) argp: Heap pointer to the first parameter
-** (Selector) selector: The selector by which it was called or
-** NULL_SELECTOR if n.a. For debugging.
-** (reg_t) sendp: Pointer to the object which the message was sent to.
-** Equal to objp for anything but super.
-** (int) origin: Number of the execution stack element this entry was created by
-** (usually the current TOS number, except for multiple sends).
-** (SegmentId) local_segment: The segment to use for local variables,
-** or SCI_XS_CALLEE_LOCALS to use obj's segment.
-** Returns : (ExecStack *): A pointer to the new exec stack TOS entry
-*/
+/**
+ * Adds one varselector access to the execution stack.
+ * Parameters: (EngineState *) s: The EngineState to use
+ * (reg_t) objp: Pointer to the object owning the selector
+ * (int) argc: 1 for writing, 0 for reading
+ * (StackPtr) argp: Pointer to the address of the data to write -2
+ * (int) selector: Selector name
+ * (reg_t *) address: Heap address of the selector
+ * (int) origin: Stack frame which the access originated from
+ * Returns : (ExecStack *): Pointer to the new exec-TOS element
+ * This function is called from send_selector only.
+ */
ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp,
Selector selector, reg_t *address, int origin);
-/* Adds one varselector access to the execution stack
-** Parameters: (EngineState *) s: The EngineState to use
-** (reg_t) objp: Pointer to the object owning the selector
-** (int) argc: 1 for writing, 0 for reading
-** (StackPtr) argp: Pointer to the address of the data to write -2
-** (int) selector: Selector name
-** (reg_t *) address: Heap address of the selector
-** (int) origin: Stack frame which the access originated from
-** Returns : (ExecStack *): Pointer to the new exec-TOS element
-** This function is called from send_selector only.
-*/
void run_vm(EngineState *s, int restoring);