aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorColin Snover2016-08-28 16:20:37 -0500
committerColin Snover2016-09-29 19:39:16 -0500
commit3201440d11dde487e0ef5434cfa30066f261660f (patch)
treed5ce8daacc65a645939adf690d8269f26ce144ee /engines/sci/engine
parentb784357f5df98a3998ef0728b75b446e0e905621 (diff)
downloadscummvm-rg350-3201440d11dde487e0ef5434cfa30066f261660f.tar.gz
scummvm-rg350-3201440d11dde487e0ef5434cfa30066f261660f.tar.bz2
scummvm-rg350-3201440d11dde487e0ef5434cfa30066f261660f.zip
SCI: Generalize code for getting information on the current call
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/state.cpp42
-rw-r--r--engines/sci/engine/state.h16
-rw-r--r--engines/sci/engine/vm.cpp6
-rw-r--r--engines/sci/engine/vm_types.cpp2
-rw-r--r--engines/sci/engine/workarounds.cpp46
-rw-r--r--engines/sci/engine/workarounds.h10
6 files changed, 72 insertions, 50 deletions
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index a338beffc9..d253d316ca 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -380,4 +380,46 @@ void SciEngine::checkVocabularySwitch() {
}
}
+SciCallOrigin EngineState::getCurrentCallOrigin() const {
+ // IMPORTANT: This method must always return values that match *exactly* the
+ // values in the workaround tables in workarounds.cpp, or workarounds will
+ // be broken
+
+ Common::String curObjectName = _segMan->getObjectName(xs->sendp);
+ Common::String curMethodName;
+ const Script *localScript = _segMan->getScriptIfLoaded(xs->local_segment);
+ int curScriptNr = localScript->getScriptNumber();
+
+ if (xs->debugLocalCallOffset != -1) {
+ // if lastcall was actually a local call search back for a real call
+ Common::List<ExecStack>::const_iterator callIterator = _executionStack.end();
+ while (callIterator != _executionStack.begin()) {
+ callIterator--;
+ const ExecStack &loopCall = *callIterator;
+ if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) {
+ xs->debugSelector = loopCall.debugSelector;
+ xs->debugExportId = loopCall.debugExportId;
+ break;
+ }
+ }
+ }
+
+ if (xs->type == EXEC_STACK_TYPE_CALL) {
+ if (xs->debugSelector != -1) {
+ curMethodName = g_sci->getKernel()->getSelectorName(xs->debugSelector);
+ } else if (xs->debugExportId != -1) {
+ curObjectName = "";
+ curMethodName = Common::String::format("export %d", xs->debugExportId);
+ }
+ }
+
+ SciCallOrigin reply;
+ reply.objectName = curObjectName;
+ reply.methodName = curMethodName;
+ reply.scriptNr = curScriptNr;
+ reply.localCallOffset = xs->debugLocalCallOffset;
+ reply.roomNr = currentRoomNumber();
+ return reply;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index baa912b60e..f1ec5d3f10 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -99,6 +99,17 @@ struct VideoState {
}
};
+/**
+ * Trace information about a VM function call.
+ */
+struct SciCallOrigin {
+ int scriptNr; //< The source script of the function
+ Common::String objectName; //< The name of the object being called
+ Common::String methodName; //< The name of the method being called
+ int localCallOffset; //< The byte offset of a local script subroutine called by the origin method. -1 if not in a local subroutine.
+ int roomNr; //< The room that was loaded at the time of the call
+};
+
struct EngineState : public Common::Serializable {
public:
EngineState(SegManager *segMan);
@@ -209,6 +220,11 @@ public:
* Resets the engine state.
*/
void reset(bool isRestoring);
+
+ /**
+ * Finds and returns the origin of the current call.
+ */
+ SciCallOrigin getCurrentCallOrigin() const;
};
} // End of namespace Sci
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 548fd477bf..72e340dd5c 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -124,7 +124,7 @@ static reg_t read_var(EngineState *s, int type, int index) {
case VAR_TEMP: {
// Uninitialized read on a temp
// We need to find correct replacements for each situation manually
- SciTrackOriginReply originReply;
+ SciCallOrigin originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply);
if (solution.type == WORKAROUND_NONE) {
#ifdef RELEASE_BUILD
@@ -361,7 +361,7 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
if (kernelCall.signature
&& !kernel->signatureMatch(kernelCall.signature, argc, argv)) {
// signature mismatch, check if a workaround is available
- SciTrackOriginReply originReply;
+ SciCallOrigin originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply);
switch (solution.type) {
case WORKAROUND_NONE: {
@@ -429,7 +429,7 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId];
if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) {
// Signature mismatch
- SciTrackOriginReply originReply;
+ SciCallOrigin originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply);
switch (solution.type) {
case WORKAROUND_NONE: {
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index d74e2b194c..1076863ea5 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -66,7 +66,7 @@ void reg_t::setOffset(uint32 offset) {
}
reg_t reg_t::lookForWorkaround(const reg_t right, const char *operation) const {
- SciTrackOriginReply originReply;
+ SciCallOrigin originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, arithmeticWorkarounds, &originReply);
if (solution.type == WORKAROUND_NONE)
error("Invalid arithmetic operation (%s - params: %04x:%04x and %04x:%04x) from method %s::%s (room %d, script %d, localCall %x)",
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 7aaea0902a..68f5f4c7d6 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -776,8 +776,7 @@ const SciWorkaroundEntry kScrollWindowAdd_workarounds[] = {
{ GID_PHANTASMAGORIA, 45, 64907, 0, "ScrollableWindow", "addString", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // ScrollWindow interface passes the last two parameters twice
};
-
-SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) {
+SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciCallOrigin *trackOrigin) {
// HACK for SCI3: Temporarily ignore this
if (getSciVersion() == SCI_VERSION_3) {
warning("SCI3 HACK: trackOriginAndFindWorkaround() called, ignoring");
@@ -789,37 +788,14 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun
const EngineState *state = g_sci->getEngineState();
ExecStack *lastCall = state->xs;
- const Script *localScript = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
- int curScriptNr = localScript->getScriptNumber();
- int curLocalCallOffset = lastCall->debugLocalCallOffset;
-
- if (curLocalCallOffset != -1) {
- // if lastcall was actually a local call search back for a real call
- Common::List<ExecStack>::const_iterator callIterator = state->_executionStack.end();
- while (callIterator != state->_executionStack.begin()) {
- callIterator--;
- const ExecStack &loopCall = *callIterator;
- if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) {
- lastCall->debugSelector = loopCall.debugSelector;
- lastCall->debugExportId = loopCall.debugExportId;
- break;
- }
- }
- }
-
- Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp);
- Common::String curMethodName;
const SciGameId gameId = g_sci->getGameId();
- const int curRoomNumber = state->currentRoomNumber();
-
- if (lastCall->type == EXEC_STACK_TYPE_CALL) {
- if (lastCall->debugSelector != -1) {
- curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector);
- } else if (lastCall->debugExportId != -1) {
- curObjectName = "";
- curMethodName = Common::String::format("export %d", lastCall->debugExportId);
- }
- }
+
+ *trackOrigin = state->getCurrentCallOrigin();
+ const Common::String &curObjectName = trackOrigin->objectName;
+ const Common::String &curMethodName = trackOrigin->methodName;
+ const int &curRoomNumber = trackOrigin->roomNr;
+ const int &curScriptNr = trackOrigin->scriptNr;
+ const int &curLocalCallOffset = trackOrigin->localCallOffset;
if (workaroundList) {
// Search if there is a workaround for this one
@@ -895,12 +871,6 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun
} while (!searchObject.isNull()); // no parent left?
}
- // give caller origin data
- trackOrigin->objectName = curObjectName;
- trackOrigin->methodName = curMethodName;
- trackOrigin->scriptNr = curScriptNr;
- trackOrigin->localCallOffset = lastCall->debugLocalCallOffset;
-
SciWorkaroundSolution noneFound;
noneFound.type = WORKAROUND_NONE;
noneFound.value = 0;
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 2cccd05475..2f7a9e56e2 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -24,6 +24,7 @@
#define SCI_ENGINE_WORKAROUNDS_H
#include "sci/engine/vm_types.h"
+#include "sci/engine/state.h"
#include "sci/sci.h"
namespace Sci {
@@ -35,13 +36,6 @@ enum SciWorkaroundType {
WORKAROUND_FAKE // fake kernel call / replace temp value / fake opcode
};
-struct SciTrackOriginReply {
- int scriptNr;
- Common::String objectName;
- Common::String methodName;
- int localCallOffset;
-};
-
struct SciWorkaroundSolution {
SciWorkaroundType type;
uint16 value;
@@ -103,7 +97,7 @@ extern const SciWorkaroundEntry kUnLoad_workarounds[];
extern const SciWorkaroundEntry kStringPutAt_workarounds[];
extern const SciWorkaroundEntry kScrollWindowAdd_workarounds[];
-extern SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin);
+extern SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciCallOrigin *trackOrigin);
} // End of namespace Sci