aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/features.cpp
diff options
context:
space:
mode:
authorFilippos Karapetis2010-11-21 00:44:04 +0000
committerFilippos Karapetis2010-11-21 00:44:04 +0000
commitd275461958b650023373383ed2243cc77fd5c736 (patch)
treeb5929df4ffdcd8986141015428f30ddbbefdf662 /engines/sci/engine/features.cpp
parent5616bde4e7ec28f886aeb2c98c6a2fec52f9fa9d (diff)
downloadscummvm-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.cpp63
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() {