aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2010-02-07 12:15:35 +0000
committerMax Horn2010-02-07 12:15:35 +0000
commit7c05a24ade8108eed110a40ea9f65b653f4e77c8 (patch)
tree2d6f22dbecf4924a50b8c5495d02152343e42274
parentf3ef11cdc5b88736467e7378abb5f1d0e67a5fdb (diff)
downloadscummvm-rg350-7c05a24ade8108eed110a40ea9f65b653f4e77c8.tar.gz
scummvm-rg350-7c05a24ade8108eed110a40ea9f65b653f4e77c8.tar.bz2
scummvm-rg350-7c05a24ade8108eed110a40ea9f65b653f4e77c8.zip
SCI: Refactor GameFeatures::autoDetectFeature
svn-id: r47960
-rw-r--r--engines/sci/engine/features.cpp197
1 files changed, 105 insertions, 92 deletions
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index cce67fb85a..58d4b1f1ef 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -36,7 +36,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan)
_lofsType = SCI_VERSION_NONE;
_gfxFunctionsType = SCI_VERSION_NONE;
_moveCountType = kMoveCountUninitialized;
-
+
#ifdef ENABLE_SCI32
_sci21KernelType = SCI_VERSION_NONE;
#endif
@@ -47,7 +47,6 @@ bool GameFeatures::autoDetectFeature(FeatureDetection featureDetection, int meth
Common::String objName;
Selector slc = 0;
reg_t objAddr;
- bool foundTarget = false;
// Get address of target script
switch (featureDetection) {
@@ -97,20 +96,98 @@ bool GameFeatures::autoDetectFeature(FeatureDetection featureDetection, int meth
addr = _segMan->getObject(objAddr)->getFunction(methodNum);
}
+ int16 opparams[4];
+ byte opsize;
+ byte opcode;
uint16 offset = addr.offset;
Script *script = _segMan->getScript(addr.segment);
- uint16 intParam = 0xFFFF;
+ uint16 intParam = 0xFFFF; // Only used for kDetectSoundType
+ bool foundTarget = false;
do {
- int16 opparams[4];
- byte opsize;
offset += readPMachineInstruction(script->_buf + offset, opsize, opparams);
- const byte opcode = opsize >> 1;
+ opcode = opsize >> 1;
+
+ switch (featureDetection) {
+ case kDetectGfxFunctions:
+ if (opcode == op_callk) {
+ uint16 kFuncNum = opparams[0];
+ uint16 argc = opparams[1];
+
+ if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11)
+ // If kDrawPic is called with 6 parameters from the
+ // overlay selector, the game is using old graphics functions.
+ // Otherwise, if it's called with 8 parameters, it's using new
+ // graphics functions
+ _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY;
+ return true;
+ }
+ }
+ break;
- if (opcode == op_ret)
+ case kDetectMoveCountType:
+ if (opcode == op_callk) {
+ uint16 kFuncNum = opparams[0];
+
+ // Games which ignore move count call kAbs before calling kDoBresen
+ if (_kernel->getKernelName(kFuncNum) == "Abs") {
+ foundTarget = true;
+ } else if (_kernel->getKernelName(kFuncNum) == "DoBresen") {
+ _moveCountType = foundTarget ? kIgnoreMoveCount : kIncrementMoveCount;
+ return true;
+ }
+ }
break;
- if (featureDetection == kDetectLofsType) {
+ case kDetectSoundType:
+ // The play method of the Sound object pushes the DoSound command
+ // that it'll use just before it calls DoSound. We intercept that here
+ // in order to check what sound semantics are used, cause the position
+ // of the sound commands has changed at some point during SCI1 middle
+ if (opcode == op_pushi) {
+ // Load the pushi parameter
+ intParam = opparams[0];
+
+ // Sanity check
+ if (offset >= script->_bufSize)
+ break;
+ }
+
+
+ if (opcode == op_callk) {
+ uint16 kFuncNum = opparams[0];
+
+ // Late SCI1 games call kIsObject before kDoSound
+ if (kFuncNum == 6) { // kIsObject (SCI0-SCI11)
+ foundTarget = true;
+ } else if (kFuncNum == 45) { // kDoSound (SCI1)
+ // First, check which DoSound function is called by the play method of
+ // the Sound object
+ switch (intParam) {
+ case 1:
+ _doSoundType = SCI_VERSION_0_EARLY;
+ break;
+ case 7:
+ _doSoundType = SCI_VERSION_1_EARLY;
+ break;
+ case 8:
+ _doSoundType = SCI_VERSION_1_LATE;
+ break;
+ default:
+ // Unknown case... should never happen. We fall back to
+ // alternative detection here, which works in general, apart from
+ // some transitive games like Jones CD
+ _doSoundType = foundTarget ? SCI_VERSION_1_LATE : SCI_VERSION_1_EARLY;
+ break;
+ }
+
+ if (_doSoundType != SCI_VERSION_NONE)
+ return true;
+ }
+ }
+ break;
+
+ case kDetectLofsType:
if (opcode == op_lofsa || opcode == op_lofss) {
// Load lofs operand
uint16 lofs = opparams[0];
@@ -133,95 +210,31 @@ bool GameFeatures::autoDetectFeature(FeatureDetection featureDetection, int meth
return true;
// If we reach here, we haven't been able to deduce the lofs
- // parameter type.
- }
- }
-
- if (featureDetection == kDetectSoundType) {
- // The play method of the Sound object pushes the DoSound command
- // that it'll use just before it calls DoSound. We intercept that here
- // in order to check what sound semantics are used, cause the position
- // of the sound commands has changed at some point during SCI1 middle
- if (opcode == op_pushi) {
- // Load the pushi parameter
- intParam = opparams[0];
-
- // Sanity check
- if (offset >= script->_bufSize)
- break;
+ // parameter type so far.
}
- }
+ break;
- if (opcode == op_callk) {
- uint16 kFuncNum = opparams[0];
- uint16 argc = opparams[1];
-
- switch (featureDetection) {
- case kDetectGfxFunctions:
- if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11)
- // If kDrawPic is called with 6 parameters from the
- // overlay selector, the game is using old graphics functions.
- // Otherwise, if it's called with 8 parameters, it's using new
- // graphics functions
- _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY;
- return true;
- }
- break;
- case kDetectMoveCountType:
- // Games which ignore move count call kAbs before calling kDoBresen
- if (_kernel->getKernelName(kFuncNum) == "Abs") {
- foundTarget = true;
- } else if (_kernel->getKernelName(kFuncNum) == "DoBresen") {
- _moveCountType = foundTarget ? kIgnoreMoveCount : kIncrementMoveCount;
- return true;
- }
- break;
- case kDetectSoundType:
- // Late SCI1 games call kIsObject before kDoSound
- if (kFuncNum == 6) { // kIsObject (SCI0-SCI11)
- foundTarget = true;
- } else if (kFuncNum == 45) { // kDoSound (SCI1)
- // First, check which DoSound function is called by the play method of
- // the Sound object
- switch (intParam) {
- case 1:
- _doSoundType = SCI_VERSION_0_EARLY;
- break;
- case 7:
- _doSoundType = SCI_VERSION_1_EARLY;
- break;
- case 8:
- _doSoundType = SCI_VERSION_1_LATE;
- break;
- default:
- // Unknown case... should never happen. We fall back to
- // alternative detection here, which works in general, apart from
- // some transitive games like Jones CD
- _doSoundType = foundTarget ? SCI_VERSION_1_LATE : SCI_VERSION_1_EARLY;
- break;
- }
-
- if (_doSoundType != SCI_VERSION_NONE)
- return true;
- }
- break;
#ifdef ENABLE_SCI32
- case kDetectSci21KernelTable:
- if (kFuncNum == 0x40) {
- _sci21KernelType = SCI_VERSION_2;
- return true;
- } else if (kFuncNum == 0x75) {
- _sci21KernelType = SCI_VERSION_2_1;
- return true;
- }
- break;
-#endif
- default:
- break;
- }
+ case kDetectSci21KernelTable:
+ if (opcode == op_callk) {
+ uint16 kFuncNum = opparams[0];
+
+ // TODO: Explain this check; what are those kernel funcs supposed
+ // to be, why does this check work like it does?
+ if (kFuncNum == 0x40) {
+ _sci21KernelType = SCI_VERSION_2;
+ return true;
+ } else if (kFuncNum == 0x75) {
+ _sci21KernelType = SCI_VERSION_2_1;
+ return true;
}
+ }
+#endif
- } while (offset > 0);
+ default:
+ break;
+ }
+ } while (opcode != op_ret && offset < script->_bufSize);
return false; // not found
}