aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2010-11-21 00:44:04 +0000
committerFilippos Karapetis2010-11-21 00:44:04 +0000
commitd275461958b650023373383ed2243cc77fd5c736 (patch)
treeb5929df4ffdcd8986141015428f30ddbbefdf662
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
-rw-r--r--engines/sci/engine/features.cpp63
-rw-r--r--engines/sci/engine/features.h15
2 files changed, 76 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() {
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;