mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
SCI: adding capability to resolve local calls as well for valgrind-sci, adding another workaround for a script bug in sq1 (this time export 1 gets called locally)
svn-id: r50308
This commit is contained in:
parent
70e4a8605b
commit
258494f036
@ -72,7 +72,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
|
||||
* @return A pointer to the new exec stack TOS entry
|
||||
*/
|
||||
static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp,
|
||||
reg_t objp, int argc, StackPtr argp, Selector selector, int exportId,
|
||||
reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset,
|
||||
reg_t sendp, int origin, SegmentId local_segment);
|
||||
|
||||
|
||||
@ -188,19 +188,22 @@ struct UninitializedReadWorkaround {
|
||||
int scriptNr;
|
||||
const char *objectName;
|
||||
const char *methodName;
|
||||
int localCallOffset;
|
||||
int index;
|
||||
uint16 newValue;
|
||||
};
|
||||
|
||||
static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = {
|
||||
{ GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room
|
||||
{ GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0
|
||||
{ GID_SQ1, 703, "", "export 1", 0, 0 }, // sub that's called from several objects
|
||||
{ GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller
|
||||
{ (SciGameId)0, -1, NULL, NULL, 0, 0 }
|
||||
{ GID_LAURABOW2, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu
|
||||
{ GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room
|
||||
{ GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0
|
||||
{ GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects
|
||||
{ GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally
|
||||
{ GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // export 1 sub, but called locally
|
||||
{ GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller
|
||||
{ (SciGameId)0, -1, NULL, NULL, -1, 0, 0 }
|
||||
};
|
||||
|
||||
static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) {
|
||||
@ -209,20 +212,34 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
|
||||
// Uninitialized read on a temp
|
||||
// We need to find correct replacements for each situation manually
|
||||
EngineState *state = g_sci->getEngineState();
|
||||
ExecStack *call = state->xs;
|
||||
Script *local_script = state->_segMan->getScriptIfLoaded(call->local_segment);
|
||||
ExecStack *lastCall = state->xs;
|
||||
Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
|
||||
int curScriptNr = local_script->_nr;
|
||||
|
||||
Common::String curObjectName = state->_segMan->getObjectName(call->sendp);
|
||||
if (lastCall->localCallOffset != -1) {
|
||||
// if lastcall was actually a local call search back for a real call
|
||||
Common::List<ExecStack>::iterator callIterator = state->_executionStack.end();
|
||||
while (callIterator != state->_executionStack.begin()) {
|
||||
callIterator--;
|
||||
ExecStack loopCall = *callIterator;
|
||||
if ((loopCall.selector != -1) || (loopCall.exportId != -1)) {
|
||||
lastCall->selector = loopCall.selector;
|
||||
lastCall->exportId = loopCall.exportId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp);
|
||||
Common::String curMethodName;
|
||||
const SciGameId gameId = g_sci->getGameId();
|
||||
|
||||
if (call->type == EXEC_STACK_TYPE_CALL) {
|
||||
if (call->selector != -1) {
|
||||
curMethodName = g_sci->getKernel()->getSelectorName(call->selector);
|
||||
} else if (call->exportId != -1) {
|
||||
if (lastCall->type == EXEC_STACK_TYPE_CALL) {
|
||||
if (lastCall->selector != -1) {
|
||||
curMethodName = g_sci->getKernel()->getSelectorName(lastCall->selector);
|
||||
} else if (lastCall->exportId != -1) {
|
||||
curObjectName = "";
|
||||
curMethodName = curMethodName.printf("export %d", call->exportId);
|
||||
curMethodName = curMethodName.printf("export %d", lastCall->exportId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,14 +247,14 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
|
||||
const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds;
|
||||
while (workaround->objectName) {
|
||||
if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName
|
||||
&& workaround->methodName == curMethodName && workaround->index == index) {
|
||||
&& workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) {
|
||||
// Workaround found
|
||||
r[index] = make_reg(0, workaround->newValue);
|
||||
return r[index];
|
||||
}
|
||||
workaround++;
|
||||
}
|
||||
error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr);
|
||||
error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %lx)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset);
|
||||
}
|
||||
return r[index];
|
||||
} else
|
||||
@ -345,7 +362,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
|
||||
}
|
||||
}
|
||||
|
||||
return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, calling_obj, s->_executionStack.size()-1, seg);
|
||||
return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);
|
||||
}
|
||||
|
||||
|
||||
@ -543,7 +560,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
|
||||
else
|
||||
add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,
|
||||
call.argc, call.argp,
|
||||
call.selector, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);
|
||||
call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);
|
||||
}
|
||||
|
||||
_exec_varselectors(s);
|
||||
@ -552,7 +569,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
|
||||
}
|
||||
|
||||
static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
|
||||
ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, objp, origin, SCI_XS_CALLEE_LOCALS);
|
||||
ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS);
|
||||
// Store selector address in sp
|
||||
|
||||
xstack->addr.varp = address;
|
||||
@ -562,7 +579,7 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack,
|
||||
}
|
||||
|
||||
static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc,
|
||||
StackPtr argp, Selector selector, int exportId, reg_t sendp, int origin, SegmentId _localsSegment) {
|
||||
StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) {
|
||||
// Returns new TOS element for the execution stack
|
||||
// _localsSegment may be -1 if derived from the called object
|
||||
|
||||
@ -588,6 +605,7 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t
|
||||
// Additional debug information
|
||||
xstack.selector = selector;
|
||||
xstack.exportId = exportId;
|
||||
xstack.localCallOffset = localCallOffset;
|
||||
xstack.origin = origin;
|
||||
|
||||
xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
|
||||
@ -642,7 +660,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {
|
||||
// This is useful in debugger backtraces if this
|
||||
// kernel function calls a script itself.
|
||||
ExecStack *xstack;
|
||||
xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, NULL_REG,
|
||||
xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
|
||||
s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
|
||||
xstack->selector = kernelFuncNum;
|
||||
xstack->type = EXEC_STACK_TYPE_KERNEL;
|
||||
@ -1199,11 +1217,13 @@ void run_vm(EngineState *s, bool restoring) {
|
||||
StackPtr call_base = s->xs->sp - argc;
|
||||
s->xs->sp[1].offset += s->restAdjust;
|
||||
|
||||
uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0];
|
||||
|
||||
xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment,
|
||||
s->xs->addr.pc.offset + opparams[0]),
|
||||
localCallOffset),
|
||||
s->xs->sp, s->xs->objp,
|
||||
(validate_arithmetic(*call_base)) + s->restAdjust,
|
||||
call_base, NULL_SELECTOR, -1, s->xs->objp,
|
||||
call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,
|
||||
s->_executionStack.size()-1, s->xs->local_segment);
|
||||
s->restAdjust = 0; // Used up the &rest adjustment
|
||||
s->xs->sp = call_base;
|
||||
|
@ -104,6 +104,7 @@ struct ExecStack {
|
||||
|
||||
Selector selector; // The selector which was used to call or -1 if not applicable
|
||||
int exportId; // The exportId which was called or -1 if not applicable
|
||||
int localCallOffset; // Local call offset 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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user