aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMartin Kiewitz2010-07-23 14:32:24 +0000
committerMartin Kiewitz2010-07-23 14:32:24 +0000
commit20b1d80d598e6f741e28c9a85d186e463d111816 (patch)
tree673da2b35f29f460937a0af92900d0c9104e96ba /engines/sci
parent0bcc3af422754525304203edca34a3e6f44f5cfb (diff)
downloadscummvm-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
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/vm.cpp82
-rw-r--r--engines/sci/engine/workarounds.cpp88
-rw-r--r--engines/sci/engine/workarounds.h10
-rw-r--r--engines/sci/graphics/paint16.cpp11
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;
}
}