diff options
author | Filippos Karapetis | 2010-11-21 00:44:04 +0000 |
---|---|---|
committer | Filippos Karapetis | 2010-11-21 00:44:04 +0000 |
commit | d275461958b650023373383ed2243cc77fd5c736 (patch) | |
tree | b5929df4ffdcd8986141015428f30ddbbefdf662 /engines/sci/engine/features.cpp | |
parent | 5616bde4e7ec28f886aeb2c98c6a2fec52f9fa9d (diff) | |
download | scummvm-rg350-d275461958b650023373383ed2243cc77fd5c736.tar.gz scummvm-rg350-d275461958b650023373383ed2243cc77fd5c736.tar.bz2 scummvm-rg350-d275461958b650023373383ed2243cc77fd5c736.zip |
SCI: Added a heuristic to detect the modified late SCI2.1/SCI3 kString/kArray kernel functions
svn-id: r54398
Diffstat (limited to 'engines/sci/engine/features.cpp')
-rw-r--r-- | engines/sci/engine/features.cpp | 63 |
1 files changed, 61 insertions, 2 deletions
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() { |