aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2016-07-03 12:59:59 +0200
committerGitHub2016-07-03 12:59:59 +0200
commit02acf2e6ee8b3dca41090433ab811655e41fd8b6 (patch)
tree4629c75584b73fecd20684da90366b6bc551cf59 /engines/sci
parent6a1dbf97b4e724c2f12339eabf0849cc847ec641 (diff)
parent4b72a42da93da5560ecde38010d328196ff727fd (diff)
downloadscummvm-rg350-02acf2e6ee8b3dca41090433ab811655e41fd8b6.tar.gz
scummvm-rg350-02acf2e6ee8b3dca41090433ab811655e41fd8b6.tar.bz2
scummvm-rg350-02acf2e6ee8b3dca41090433ab811655e41fd8b6.zip
Merge pull request #741 from wjp/sci-call
SCI: Clean up some aspects of call handling
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp5
-rw-r--r--engines/sci/engine/kernel.cpp14
-rw-r--r--engines/sci/engine/kernel.h1
-rw-r--r--engines/sci/engine/kmisc.cpp20
-rw-r--r--engines/sci/engine/vm.cpp23
-rw-r--r--engines/sci/engine/vm.h14
-rw-r--r--engines/sci/engine/workarounds.cpp2
7 files changed, 54 insertions, 25 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 27ac4fac49..2c74fe4b0c 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -3094,7 +3094,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
break;
case EXEC_STACK_TYPE_KERNEL: // Kernel function
- debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str());
+ if (call.debugKernelSubFunction == -1)
+ debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugKernelFunction).c_str());
+ else
+ debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugKernelFunction, call.debugKernelSubFunction).c_str());
break;
case EXEC_STACK_TYPE_VARSELECTOR:
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 796dea2382..2fc338b618 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -84,13 +84,19 @@ uint Kernel::getKernelNamesSize() const {
}
const Common::String &Kernel::getKernelName(uint number) const {
- // FIXME: The following check is a temporary workaround for an issue
- // leading to crashes when using the debugger's backtrace command.
- if (number >= _kernelNames.size())
- return _invalid;
+ assert(number < _kernelFuncs.size());
return _kernelNames[number];
}
+Common::String Kernel::getKernelName(uint number, uint subFunction) const {
+ assert(number < _kernelFuncs.size());
+ const KernelFunction &kernelCall = _kernelFuncs[number];
+
+ assert(subFunction < kernelCall.subFunctionCount);
+ return kernelCall.subFunctions[subFunction].name;
+}
+
+
int Kernel::findKernelFuncPos(Common::String kernelFuncName) {
for (uint32 i = 0; i < _kernelNames.size(); i++)
if (_kernelNames[i] == kernelFuncName)
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 1202982986..d95e228045 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -158,6 +158,7 @@ public:
uint getKernelNamesSize() const;
const Common::String &getKernelName(uint number) const;
+ Common::String getKernelName(uint number, uint subFunction) const;
/**
* Determines the selector ID of a selector by its name.
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 0a5f26476f..065625f85f 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -605,18 +605,28 @@ reg_t kEmpty(EngineState *s, int argc, reg_t *argv) {
reg_t kStub(EngineState *s, int argc, reg_t *argv) {
Kernel *kernel = g_sci->getKernel();
int kernelCallNr = -1;
+ int kernelSubCallNr = -1;
Common::List<ExecStack>::const_iterator callIterator = s->_executionStack.end();
if (callIterator != s->_executionStack.begin()) {
callIterator--;
ExecStack lastCall = *callIterator;
- kernelCallNr = lastCall.debugSelector;
+ kernelCallNr = lastCall.debugKernelFunction;
+ kernelSubCallNr = lastCall.debugKernelSubFunction;
}
- Common::String warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) +
- Common::String::format("[%x]", kernelCallNr) +
- " invoked. Params: " +
- Common::String::format("%d", argc) + " (";
+ Common::String warningMsg;
+ if (kernelSubCallNr == -1) {
+ warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) +
+ Common::String::format("[%x]", kernelCallNr);
+ } else {
+ warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr, kernelSubCallNr) +
+ Common::String::format("[%x:%x]", kernelCallNr, kernelSubCallNr);
+
+ }
+
+ warningMsg += " invoked. Params: " +
+ Common::String::format("%d", argc) + " (";
for (int i = 0; i < argc; i++) {
warningMsg += Common::String::format("%04x:%04x", PRINT_REG(argv[i]));
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 64e6c045db..3e12084ed6 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -239,8 +239,9 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
// Check if a breakpoint is set on this method
g_sci->checkExportBreakpoint(script, pubfunct);
+ assert(argp[0].toUint16() == argc); // The first argument is argc
ExecStack xstack(calling_obj, calling_obj, sp, argc, argp,
- seg, make_reg32(seg, exportAddr), -1, pubfunct, -1,
+ seg, make_reg32(seg, exportAddr), -1, -1, -1, pubfunct, -1,
s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL);
s->_executionStack.push_back(xstack);
return &(s->_executionStack.back());
@@ -312,8 +313,9 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
if (activeBreakpointTypes || DebugMan.isDebugChannelEnabled(kDebugLevelScripts))
debugSelectorCall(send_obj, selector, argc, argp, varp, funcp, s->_segMan, selectorType);
+ assert(argp[0].toUint16() == argc); // The first argument is argc
ExecStack xstack(work_obj, send_obj, curSP, argc, argp,
- 0xFFFF, curFP, selector, -1, -1,
+ 0xFFFF, curFP, selector, -1, -1, -1, -1,
origin, stackType);
if (selectorType == kSelectorVariable)
@@ -335,12 +337,12 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
return s->_executionStack.empty() ? NULL : &(s->_executionStack.back());
}
-static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) {
+static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int kernelSubCallNr, int argc, reg_t *argv) {
// Add stack frame to indicate we're executing a callk.
// This is useful in debugger backtraces if this
// kernel function calls a script itself.
ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, make_reg32(0, 0),
- kernelCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL);
+ -1, kernelCallNr, kernelSubCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL);
s->_executionStack.push_back(xstack);
}
@@ -386,7 +388,8 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
// Call kernel function
if (!kernelCall.subFunctionCount) {
- addKernelCallToExecStack(s, kernelCallNr, argc, argv);
+ argv[-1] = make_reg(0, argc); // The first argument is argc
+ addKernelCallToExecStack(s, kernelCallNr, -1, argc, argv);
s->r_acc = kernelCall.function(s, argc, argv);
if (kernelCall.debugLogging)
@@ -444,7 +447,8 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
}
if (!kernelSubCall.function)
error("[VM] k%s: subfunction ID %d requested, but not available", kernelCall.name, subId);
- addKernelCallToExecStack(s, kernelCallNr, argc, argv);
+ argv[-1] = make_reg(0, argc); // The first argument is argc
+ addKernelCallToExecStack(s, kernelCallNr, subId, argc, argv);
s->r_acc = kernelSubCall.function(s, argc, argv);
if (kernelSubCall.debugLogging)
@@ -834,14 +838,15 @@ void run_vm(EngineState *s) {
int argc = (opparams[1] >> 1) // Given as offset, but we need count
+ 1 + s->r_rest;
StackPtr call_base = s->xs->sp - argc;
- s->xs->sp[1].incOffset(s->r_rest);
uint32 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0];
+ int final_argc = (call_base->requireUint16()) + s->r_rest;
+ call_base[0] = make_reg(0, final_argc); // The first argument is argc
ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp,
- (call_base->requireUint16()) + s->r_rest, call_base,
+ final_argc, call_base,
s->xs->local_segment, make_reg32(s->xs->addr.pc.getSegment(), localCallOffset),
- NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1,
+ NULL_SELECTOR, -1, -1, -1, localCallOffset, s->_executionStack.size() - 1,
EXEC_STACK_TYPE_CALL);
s->_executionStack.push_back(xstack);
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 514bf58b64..c41060dc32 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -93,16 +93,19 @@ struct ExecStack {
SegmentId local_segment; // local variables etc
- Selector debugSelector; // The selector which was used to call or -1 if not applicable
- int debugExportId; // The exportId which was called or -1 if not applicable
- int debugLocalCallOffset; // Local call offset or -1 if not applicable
- int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call
+ Selector debugSelector; // The selector which was used to call or -1 if not applicable
+ int debugExportId; // The exportId which was called or -1 if not applicable
+ int debugLocalCallOffset; // Local call offset or -1 if not applicable
+ int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call
+ int debugKernelFunction; // The kernel function called, or -1 if not applicable
+ int debugKernelSubFunction; // The kernel subfunction called, or -1 if not applicable
ExecStackType type;
reg_t* getVarPointer(SegManager *segMan) const;
ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_,
SegmentId localsSegment_, reg32_t pc_, Selector debugSelector_,
+ int debugKernelFunction_, int debugKernelSubFunction_,
int debugExportId_, int debugLocalCallOffset_, int debugOrigin_,
ExecStackType type_) {
objp = objp_;
@@ -112,12 +115,13 @@ struct ExecStack {
fp = sp = sp_;
argc = argc_;
variables_argp = argp_;
- *variables_argp = make_reg(0, argc); // The first argument is argc
if (localsSegment_ != 0xFFFF)
local_segment = localsSegment_;
else
local_segment = pc_.getSegment();
debugSelector = debugSelector_;
+ debugKernelFunction = debugKernelFunction_;
+ debugKernelSubFunction = debugKernelSubFunction_;
debugExportId = debugExportId_;
debugLocalCallOffset = debugLocalCallOffset_;
debugOrigin = debugOrigin_;
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 073bb93983..2a2540b470 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -780,7 +780,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun
Common::List<ExecStack>::const_iterator callIterator = state->_executionStack.end();
while (callIterator != state->_executionStack.begin()) {
callIterator--;
- ExecStack loopCall = *callIterator;
+ const ExecStack &loopCall = *callIterator;
if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) {
lastCall->debugSelector = loopCall.debugSelector;
lastCall->debugExportId = loopCall.debugExportId;