diff options
author | Martin Kiewitz | 2010-07-23 14:32:24 +0000 |
---|---|---|
committer | Martin Kiewitz | 2010-07-23 14:32:24 +0000 |
commit | 20b1d80d598e6f741e28c9a85d186e463d111816 (patch) | |
tree | 673da2b35f29f460937a0af92900d0c9104e96ba | |
parent | 0bcc3af422754525304203edca34a3e6f44f5cfb (diff) | |
download | scummvm-rg350-20b1d80d598e6f741e28c9a85d186e463d111816.tar.gz scummvm-rg350-20b1d80d598e6f741e28c9a85d186e463d111816.tar.bz2 scummvm-rg350-20b1d80d598e6f741e28c9a85d186e463d111816.zip |
SCI: adding table for kDisplay workarounds
and removing hardcoded checks, adding another workaround for kGraph(drawLine) in island of dr. brain (also gene explanation chart)
Moving trackOriginAndFindWorkaround() into workarounds.cpp
svn-id: r51209
-rw-r--r-- | engines/sci/engine/vm.cpp | 82 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.cpp | 88 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.h | 10 | ||||
-rw-r--r-- | engines/sci/graphics/paint16.cpp | 11 |
4 files changed, 103 insertions, 88 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index b1945d1cf4..4cd5fc224f 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -183,88 +183,6 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in return true; } -struct SciTrackOriginReply { - int scriptNr; - Common::String objectName; - Common::String methodName; - int localCallOffset; -}; - -static SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) { - EngineState *state = g_sci->getEngineState(); - ExecStack *lastCall = state->xs; - Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); - int curScriptNr = local_script->getScriptNumber(); - - if (lastCall->debugLocalCallOffset != -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.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 = curMethodName.printf("export %d", lastCall->debugExportId); - } - } - - if (workaroundList) { - // Search if there is a workaround for this one - const SciWorkaroundEntry *workaround; - int16 inheritanceLevel = 0; - Common::String searchObjectName = curObjectName; - reg_t searchObject = lastCall->sendp; - do { - workaround = workaroundList; - while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr - && ((workaround->roomNr == -1) || (workaround->roomNr == curRoomNumber)) - && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) - && (workaround->objectName == searchObjectName) - && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset - && ((workaround->index == -1) || (workaround->index == index))) { - // Workaround found - return workaround->newValue; - } - workaround++; - } - - // Go back to the parent - inheritanceLevel++; - searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); - if (!searchObject.isNull()) - searchObjectName = state->_segMan->getObjectName(searchObject); - } 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; - return noneFound; -} - static bool validate_unsignedInteger(reg_t reg, uint16 &integer) { if (reg.segment) return false; diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 3861ad3228..acc977ce6d 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -23,6 +23,9 @@ * */ +#include "sci/engine/kernel.h" +#include "sci/engine/state.h" +#include "sci/engine/vm.h" #include "sci/engine/workarounds.h" #define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, -1, 0, { WORKAROUND_NONE, 0 } } @@ -101,6 +104,13 @@ const SciWorkaroundEntry kAbs_workarounds[] = { }; // gameID, room,script,lvl, object-name, method-name, call,index, workaround +const SciWorkaroundEntry kDisplay_workarounds[] = { + { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object + { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, 0, { WORKAROUND_IGNORE, 0 } }, // clicking on catalog in roboter sale - a parameter is an object + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, 64, 64, 0, "rm64", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object SCI_WORKAROUNDENTRY_TERMINATOR @@ -115,7 +125,8 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kGraphDrawLine_workarounds[] = { - { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when ordering beer, gets called with 1 extra parameter + { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter + { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -172,4 +183,79 @@ const SciWorkaroundEntry kStrCpy_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) { + EngineState *state = g_sci->getEngineState(); + ExecStack *lastCall = state->xs; + Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); + int curScriptNr = local_script->getScriptNumber(); + + if (lastCall->debugLocalCallOffset != -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.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 = curMethodName.printf("export %d", lastCall->debugExportId); + } + } + + if (workaroundList) { + // Search if there is a workaround for this one + const SciWorkaroundEntry *workaround; + int16 inheritanceLevel = 0; + Common::String searchObjectName = curObjectName; + reg_t searchObject = lastCall->sendp; + do { + workaround = workaroundList; + while (workaround->objectName) { + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr + && ((workaround->roomNr == -1) || (workaround->roomNr == curRoomNumber)) + && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) + && (workaround->objectName == searchObjectName) + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset + && ((workaround->index == -1) || (workaround->index == index))) { + // Workaround found + return workaround->newValue; + } + workaround++; + } + + // Go back to the parent + inheritanceLevel++; + searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); + if (!searchObject.isNull()) + searchObjectName = state->_segMan->getObjectName(searchObject); + } 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; + return noneFound; +} + } // End of namespace Sci diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h index f480fc5f05..ab88505103 100644 --- a/engines/sci/engine/workarounds.h +++ b/engines/sci/engine/workarounds.h @@ -38,6 +38,13 @@ 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; @@ -65,6 +72,7 @@ extern const SciWorkaroundEntry opcodeDivWorkarounds[]; extern const SciWorkaroundEntry opcodeDptoaWorkarounds[]; extern const SciWorkaroundEntry uninitializedReadWorkarounds[]; extern const SciWorkaroundEntry kAbs_workarounds[]; +extern const SciWorkaroundEntry kDisplay_workarounds[]; extern const SciWorkaroundEntry kDisposeScript_workarounds[]; extern const SciWorkaroundEntry kDoSoundFade_workarounds[]; extern const SciWorkaroundEntry kGraphDrawLine_workarounds[]; @@ -76,6 +84,8 @@ extern const SciWorkaroundEntry kSetPort_workarounds[]; extern const SciWorkaroundEntry kUnLoad_workarounds[]; extern const SciWorkaroundEntry kStrCpy_workarounds[]; +extern SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin); + } // End of namespace Sci #endif // SCI_ENGINE_WORKAROUNDS_H diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 907e382c59..bd164b79b8 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -32,6 +32,7 @@ #include "sci/engine/features.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" +#include "sci/engine/workarounds.h" #include "sci/graphics/cache.h" #include "sci/graphics/coordadjuster.h" #include "sci/graphics/ports.h" @@ -544,11 +545,11 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { } break; default: - if ((g_sci->getGameId() == GID_ISLANDBRAIN) && (g_sci->getEngineState()->currentRoomNumber() == 300)) - break; // WORKAROUND: we are called there with an forwarded 0 as additional parameter (script bug) - if ((g_sci->getGameId() == GID_SQ4) && (g_sci->getEngineState()->currentRoomNumber() == 391)) - break; // WORKAROUND: we get a pointer as parameter, skip it (sub 84h) - error("Unknown kDisplay argument %X", displayArg); + SciTrackOriginReply 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)", PRINT_REG(argv[0]), originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + assert(solution.type == WORKAROUND_IGNORE); break; } } |