diff options
-rw-r--r-- | engines/sci/engine/state.cpp | 42 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 16 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/vm_types.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.cpp | 46 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.h | 10 | ||||
-rw-r--r-- | engines/sci/graphics/paint16.cpp | 2 |
7 files changed, 73 insertions, 51 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 diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 91817d4060..53449fbeb4 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -541,7 +541,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, uint16 languageSplitter, int a break; default: - SciTrackOriginReply originReply; + SciCallOrigin originReply; SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kDisplay_workarounds, &originReply); if (solution.type == WORKAROUND_NONE) error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)", |