From d275461958b650023373383ed2243cc77fd5c736 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 21 Nov 2010 00:44:04 +0000 Subject: SCI: Added a heuristic to detect the modified late SCI2.1/SCI3 kString/kArray kernel functions svn-id: r54398 --- engines/sci/engine/features.cpp | 63 +++++++++++++++++++++++++++++++++++++++-- engines/sci/engine/features.h | 15 ++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 909fe972e6..fbb18dab49 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -40,16 +40,16 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) _gfxFunctionsType = SCI_VERSION_NONE; _messageFunctionType = SCI_VERSION_NONE; _moveCountType = kMoveCountUninitialized; - #ifdef ENABLE_SCI32 _sci21KernelType = SCI_VERSION_NONE; + _sci2StringFunctionType = kSci2StringFunctionUninitialized; #endif _usesCdTrack = Common::File::exists("cdaudio.map"); } reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc, int methodNum) { // Get address of target object - reg_t objAddr = _segMan->findObjectByName(objName); + reg_t objAddr = _segMan->findObjectByName(objName, 0); reg_t addr; if (objAddr.isNull()) { @@ -528,6 +528,65 @@ SciVersion GameFeatures::detectSci21KernelType() { } return _sci21KernelType; } + +Sci2StringFunctionType GameFeatures::detectSci2StringFunctionType() { + if (_sci2StringFunctionType == kSci2StringFunctionUninitialized) { + if (getSciVersion() <= SCI_VERSION_1_1) { + error("detectSci21StringFunctionType() called from SCI1.1 or earlier"); + } else if (getSciVersion() == SCI_VERSION_2) { + // SCI2 games are always using the old type + _sci2StringFunctionType = kSci2StringFunctionOld; + } else if (getSciVersion() == SCI_VERSION_3) { + // SCI3 games are always using the new type + _sci2StringFunctionType = kSci2StringFunctionNew; + } else { // SCI2.1 + if (!autoDetectSci21StringFunctionType()) + _sci2StringFunctionType = kSci2StringFunctionOld; + else + _sci2StringFunctionType = kSci2StringFunctionNew; + } + } + + debugC(1, kDebugLevelVM, "Detected SCI2 kString type: %s", (_sci2StringFunctionType == kSci2StringFunctionOld) ? "old" : "new"); + + return _sci2StringFunctionType; +} + +bool GameFeatures::autoDetectSci21StringFunctionType() { + // Look up the script address + reg_t addr = getDetectionAddr("Str", SELECTOR(size)); + + if (!addr.segment) + return false; + + uint16 offset = addr.offset; + Script *script = _segMan->getScript(addr.segment); + + while (true) { + int16 opparams[4]; + byte extOpcode; + byte opcode; + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); + opcode = extOpcode >> 1; + + // Check for end of script + if (opcode == op_ret || offset >= script->getBufSize()) + break; + + if (opcode == op_callk) { + uint16 kFuncNum = opparams[0]; + + // SCI2.1 games which use the new kString functions call kString(8). + // Earlier ones call the callKernel script function, but not kString + // directly + if (_kernel->getKernelName(kFuncNum) == "String") + return true; + } + } + + return false; // not found a call to kString +} + #endif bool GameFeatures::autoDetectMoveCountType() { diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 336520f0d9..83cb58aa2d 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -37,6 +37,12 @@ enum MoveCountType { kIncrementMoveCount }; +enum Sci2StringFunctionType { + kSci2StringFunctionUninitialized, + kSci2StringFunctionOld, + kSci2StringFunctionNew +}; + class GameFeatures { public: GameFeatures(SegManager *segMan, Kernel *kernel); @@ -79,6 +85,13 @@ public: * @return Graphics functions type, SCI_VERSION_2 / SCI_VERSION_2_1 */ SciVersion detectSci21KernelType(); + + /** + * Autodetects the string subfunctions used in SCI2 - SCI3 + * @return string subfunctions type, kSci2StringFunctionOld / kSci2StringFunctionNew + */ + Sci2StringFunctionType detectSci2StringFunctionType(); + #endif /** @@ -109,11 +122,13 @@ private: bool autoDetectMoveCountType(); #ifdef ENABLE_SCI32 bool autoDetectSci21KernelType(); + bool autoDetectSci21StringFunctionType(); #endif SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType, _messageFunctionType; #ifdef ENABLE_SCI32 SciVersion _sci21KernelType; + Sci2StringFunctionType _sci2StringFunctionType; #endif MoveCountType _moveCountType; -- cgit v1.2.3