aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorFilippos Karapetis2009-11-20 16:39:31 +0000
committerFilippos Karapetis2009-11-20 16:39:31 +0000
commitcf1d7f92591685db315e0f970787a64e835b6518 (patch)
tree60cb99d4c16efd8a084b268fc2b18054a540b138 /engines/sci/engine
parent22c09f521aa5d4a220d53a8f8b3b277623b128a6 (diff)
downloadscummvm-rg350-cf1d7f92591685db315e0f970787a64e835b6518.tar.gz
scummvm-rg350-cf1d7f92591685db315e0f970787a64e835b6518.tar.bz2
scummvm-rg350-cf1d7f92591685db315e0f970787a64e835b6518.zip
- Removed the non-static selectors "overlay" and "setCursor" from the list of static selectors and introduced a new method for discovering the relevant features when selectors are missing - currently used for determining the graphics functions and setCursor types
- Simplified setCursor detection a bit svn-id: r46012
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/state.cpp117
-rw-r--r--engines/sci/engine/state.h1
-rw-r--r--engines/sci/engine/static_selectors.cpp11
3 files changed, 119 insertions, 10 deletions
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 286f423eba..265e5d1a92 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -233,6 +233,70 @@ Common::String EngineState::strSplit(const char *str, const char *sep) {
return retval;
}
+bool EngineState::callsKernelFunc(reg_t objAddr, int kernelFunc) {
+ Script *script = _segMan->getScript(objAddr.segment);
+ uint16 offset = objAddr.offset;
+
+ do {
+ uint16 kFuncNum;
+ int opsize = script->_buf[offset++];
+ uint opcode = opsize >> 1;
+ int i = 0;
+ byte argc;
+
+ while (g_opcode_formats[opcode][i]) {
+ switch (g_opcode_formats[opcode][i++]) {
+ case Script_Invalid:
+ break;
+ case Script_SByte:
+ case Script_Byte:
+ offset++;
+ break;
+ case Script_Word:
+ case Script_SWord:
+ offset += 2;
+ break;
+ case Script_SVariable:
+ case Script_Variable:
+ case Script_Property:
+ case Script_Global:
+ case Script_Local:
+ case Script_Temp:
+ case Script_Param:
+ if (opsize & 1)
+ kFuncNum = script->_buf[offset++];
+ else {
+ kFuncNum = 0xffff & (script->_buf[offset] | (script->_buf[offset + 1] << 8));
+ offset += 2;
+ }
+
+ if (opcode == op_callk) {
+ argc = script->_buf[offset++];
+
+ if (kFuncNum == kernelFunc)
+ return true;
+ }
+ break;
+
+ case Script_Offset:
+ case Script_SRelative:
+ offset++;
+ if (!opsize & 1)
+ offset++;
+ break;
+ case Script_End:
+ offset = 0; // exit loop
+ break;
+ default:
+ warning("opcode %02x: Invalid", opcode);
+
+ }
+ }
+ } while (offset > 0);
+
+ return false; // not found
+}
+
bool EngineState::autoDetectFeature(FeatureDetection featureDetection, int methodNum) {
Common::String objName;
Selector slc;
@@ -276,7 +340,7 @@ bool EngineState::autoDetectFeature(FeatureDetection featureDetection, int metho
return false;
}
- if (featureDetection != kDetectLofsType) {
+ if (methodNum == -1) {
if (lookup_selector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) {
warning("autoDetectFeature: target selector is not a method of object %s", objName.c_str());
return false;
@@ -460,8 +524,34 @@ SciVersion EngineState::detectSetCursorType() {
if (getSciVersion() <= SCI_VERSION_01) {
// SCI0/SCI01 games never use cursor views
_setCursorType = SCI_VERSION_0_EARLY;
+ } else if (getSciVersion() >= SCI_VERSION_1_1) {
+ // SCI1.1 games always use cursor views
+ _setCursorType = SCI_VERSION_1_1;
} else {
- if (!autoDetectFeature(kDetectSetCursorType)) {
+ bool found = false;
+
+ if (_kernel->_selectorCache.setCursor == -1) {
+ // Find which function of the Game object calls setCursor
+ int foundMethod = -1;
+
+ Object *obj = _segMan->getObject(_segMan->findObjectByName("Game"));
+ for (uint m = 0; m < obj->getMethodCount(); m++) {
+ found = callsKernelFunc(obj->getFunction(m), 40); // kSetCursor (SCI0-SCI11)
+
+ if (found) {
+ foundMethod = m;
+ break;
+ }
+ }
+
+ if (found)
+ found = autoDetectFeature(kDetectSetCursorType, foundMethod);
+ } else {
+ found = autoDetectFeature(kDetectSetCursorType);
+ }
+
+ if (!found) {
+ // Quite normal in several demos which don't have a cursor
warning("SetCursor detection failed, taking an educated guess");
if (getSciVersion() >= SCI_VERSION_1_1)
@@ -533,7 +623,26 @@ SciVersion EngineState::detectGfxFunctionsType() {
_gfxFunctionsType = SCI_VERSION_0_LATE;
} else {
// No shiftparser selector, check if the game is using an overlay
- if (_kernel->_selectorCache.overlay == -1) {
+ bool hasOverlaySelector = (_kernel->_selectorCache.overlay != -1);
+ int foundMethod = -1;
+
+ if (!hasOverlaySelector) {
+ // No overlay selector found, check if any method of the Rm object
+ // is calling kDrawPic, as the overlay selector might be missing in demos
+
+ Object *obj = _segMan->getObject(_segMan->findObjectByName("Rm"));
+ bool found = false;
+ for (uint m = 0; m < obj->getMethodCount(); m++) {
+ found = callsKernelFunc(obj->getFunction(m), 8); // kDrawPic (SCI0 - SCI11)
+
+ if (found) {
+ foundMethod = m;
+ break;
+ }
+ }
+ }
+
+ if (!hasOverlaySelector && foundMethod == -1) {
// No overlay selector found, therefore the game is definitely
// using old graphics functions
_gfxFunctionsType = SCI_VERSION_0_EARLY;
@@ -543,7 +652,7 @@ SciVersion EngineState::detectGfxFunctionsType() {
// overlay. Therefore, check it to see how it calls kDrawPic to
// determine the graphics functions type used
- if (!autoDetectFeature(kDetectGfxFunctions)) {
+ if (!autoDetectFeature(kDetectGfxFunctions, foundMethod)) {
warning("Graphics functions detection failed, taking an educated guess");
// Try detecting the graphics function types from the existence of the motionCue
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 486f5cda87..aa46855475 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -294,6 +294,7 @@ public:
private:
bool autoDetectFeature(FeatureDetection featureDetection, int methodNum = -1);
+ bool callsKernelFunc(reg_t objAddr, int kernelFunc);
SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType;
MoveCountType _moveCountType;
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 828043cf67..3252106e70 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -63,23 +63,22 @@ static const char * const sci1Selectors[] = {
// Taken from Codename: Iceman (Full Game)
static const SelectorRemap sci0SelectorRemap[] = {
- { "moveDone", 170 }, { "setCursor", 254 }, { "overlay", 270 },
- { "points", 316 }, { "flags", 368 }, { 0, 0 }
+ { "moveDone", 170 }, { "points", 316 }, { "flags", 368 },
+ { 0, 0 }
};
// Taken from Leisure Suit Larry 1 VGA (Full Game)
static const SelectorRemap sci1SelectorRemap[] = {
{ "nodePtr", 44 }, { "cantBeHere", 57 }, { "topString", 101 },
- { "flags", 102 }, { "setCursor", 183 }, { "syncTime", 247 },
- { "syncCue", 248 }, { 0, 0 }
+ { "flags", 102 }, { "syncTime", 247 }, { "syncCue", 248 },
+ { 0, 0 }
};
// Taken from KQ6 floppy (Full Game)
static const SelectorRemap sci11SelectorRemap[] = {
{ "nodePtr", 41 }, { "cantBeHere", 54 }, { "topString", 98 },
{ "flags", 99 }, { "scaleX", 104 }, { "scaleY", 105 },
- { "setCursor", 197 }, { "syncTime", 279 }, { "syncCue", 280 },
- { 0, 0 }
+ { "syncTime", 279 }, { "syncCue", 280 }, { 0, 0 }
};
Common::StringList Kernel::checkStaticSelectorNames() {