diff options
author | Filippos Karapetis | 2009-11-20 16:39:31 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-11-20 16:39:31 +0000 |
commit | cf1d7f92591685db315e0f970787a64e835b6518 (patch) | |
tree | 60cb99d4c16efd8a084b268fc2b18054a540b138 | |
parent | 22c09f521aa5d4a220d53a8f8b3b277623b128a6 (diff) | |
download | scummvm-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
-rw-r--r-- | engines/sci/engine/state.cpp | 117 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/static_selectors.cpp | 11 |
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() { |