aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorWalter van Niftrik2009-08-17 15:49:22 +0000
committerWalter van Niftrik2009-08-17 15:49:22 +0000
commit260a2019b6c57646ef32274c2fb197658f542803 (patch)
tree2207277639070c07caf7fdcc2a90e325828eb63e /engines
parent516dd5c9a4157ab63b20c6e04b698a63dcf8cd65 (diff)
downloadscummvm-rg350-260a2019b6c57646ef32274c2fb197658f542803.tar.gz
scummvm-rg350-260a2019b6c57646ef32274c2fb197658f542803.tar.bz2
scummvm-rg350-260a2019b6c57646ef32274c2fb197658f542803.zip
SCI: Add autodetection for DoSound. Cleanup.
svn-id: r43482
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/kernel.cpp87
-rw-r--r--engines/sci/engine/kernel.h14
-rw-r--r--engines/sci/engine/ksound.cpp23
-rw-r--r--engines/sci/engine/savegame.cpp3
-rw-r--r--engines/sci/engine/state.cpp75
-rw-r--r--engines/sci/engine/state.h15
-rw-r--r--engines/sci/resource.cpp2
-rw-r--r--engines/sci/resource.h3
-rw-r--r--engines/sci/sci.cpp3
9 files changed, 136 insertions, 89 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 6d027d5788..e5a4377d2d 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -370,8 +370,8 @@ static const char *argtype_description[] = {
Kernel::Kernel(ResourceManager *resmgr) : _resmgr(resmgr) {
memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t
- detectSciFeatures(); // must be called before loadSelectorNames()
loadSelectorNames();
+ detectSciFeatures();
mapSelectors(); // Map a few special selectors for later use
loadOpcodes();
loadKernelNames();
@@ -382,61 +382,30 @@ Kernel::~Kernel() {
}
void Kernel::detectSciFeatures() {
- // FIXME Much of this is unreliable
+ SciVersion version = _resmgr->sciVersion();
- Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0);
-
- Common::StringList staticSelectorTable;
-
- if (!r) { // No such resource?
- staticSelectorTable = checkStaticSelectorNames();
- if (staticSelectorTable.empty())
- error("Kernel: Could not retrieve selector names");
- }
-
- int count = staticSelectorTable.empty() ? READ_LE_UINT16(r->data) + 1 : staticSelectorTable.size(); // Counter is slightly off
features = 0;
// Initialize features based on SCI version
- switch (_resmgr->sciVersion()) {
- case SCI_VERSION_0_EARLY:
- features |= kFeatureOldScriptHeader;
- /* Fallthrough */
- case SCI_VERSION_0_LATE:
- features |= kFeatureOldGfxFunctions;
- break;
- default:
- break;
- }
- for (int i = 0; i < count; i++) {
- Common::String tmp;
-
- if (staticSelectorTable.empty()) {
- int offset = READ_LE_UINT16(r->data + 2 + i * 2);
- int len = READ_LE_UINT16(r->data + offset);
-
- tmp = Common::String((const char *)r->data + offset + 2, len);
- } else {
- tmp = staticSelectorTable[i];
- }
-
- if (tmp == "motionCue")
- features &= ~kFeatureOldGfxFunctions;
+ // Script header and graphics functions
+ if (version == SCI_VERSION_0_EARLY) {
+ features |= kFeatureOldScriptHeader | kFeatureOldGfxFunctions;
+ } else if (version == SCI_VERSION_0_LATE) {
+ if (findSelector("motionCue") == -1)
+ features |= kFeatureOldGfxFunctions;
+ }
- if (tmp == "egoMoveSpeed" && _resmgr->sciVersion() < SCI_VERSION_1_1)
+ // Lofs absolute/relative
+ if (version >= SCI_VERSION_1_MIDDLE && version < SCI_VERSION_1_1) {
+ // Assume all games use absolute lofs
+ features |= kFeatureLofsAbsolute;
+ } else if (version == SCI_VERSION_1_EARLY) {
+ // Use heuristic
+ if (findSelector("egoMoveSpeed") != -1)
features |= kFeatureLofsAbsolute;
-
- if (tmp == "setVol")
- features |= kFeatureSci1Sound;
-
- if (tmp == "nodePtr")
- features |= kFeatureSci01Sound;
}
- if (features & kFeatureSci1Sound)
- features &= ~kFeatureSci01Sound;
-
printf("Kernel auto-detected features:\n");
printf("Graphics functions: ");
@@ -445,19 +414,13 @@ void Kernel::detectSciFeatures() {
else
printf("new\n");
- printf("lofs parameters: ");
- if (features & kFeatureLofsAbsolute)
- printf("absolute\n");
- else
- printf("relative\n");
-
- printf("Sound functions: ");
- if (features & kFeatureSci1Sound)
- printf("SCI1\n");
- else if (features & kFeatureSci01Sound)
- printf("SCI01\n");
- else
- printf("SCI0\n");
+ if (version < SCI_VERSION_1_1) {
+ printf("lofs parameters: ");
+ if (features & kFeatureLofsAbsolute)
+ printf("absolute\n");
+ else
+ printf("relative\n");
+ }
}
void Kernel::loadSelectorNames() {
@@ -473,7 +436,7 @@ void Kernel::loadSelectorNames() {
for (uint32 i = 0; i < staticSelectorTable.size(); i++) {
_selectorNames.push_back(staticSelectorTable[i]);
- if (features & kFeatureOldScriptHeader)
+ if (_resmgr->sciVersion() == SCI_VERSION_0_EARLY)
_selectorNames.push_back(staticSelectorTable[i]);
}
@@ -492,7 +455,7 @@ void Kernel::loadSelectorNames() {
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle. To compensate for that, we add every selector name twice.
- if (features & kFeatureOldScriptHeader)
+ if (_resmgr->sciVersion() == SCI_VERSION_0_EARLY)
_selectorNames.push_back(tmp);
}
}
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index bb5563a876..8be51549f6 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -60,9 +60,7 @@ struct KernelFuncWithSignature {
enum AutoDetectedFeatures {
kFeatureOldScriptHeader = 1 << 0,
kFeatureOldGfxFunctions = 1 << 1,
- kFeatureLofsAbsolute = 1 << 2,
- kFeatureSci01Sound = 1 << 3,
- kFeatureSci1Sound = 1 << 4
+ kFeatureLofsAbsolute = 1 << 2
};
class Kernel {
@@ -119,16 +117,6 @@ public:
*/
bool hasLofsAbsolute() const { return (features & kFeatureLofsAbsolute); }
- /**
- * Determines if the game is using SCI01 sound functions
- */
- bool usesSci01SoundFunctions() const { return (features & kFeatureSci01Sound); }
-
- /**
- * Determines if the game is using SCI1 sound functions
- */
- bool usesSci1SoundFunctions() const { return (features & kFeatureSci1Sound); }
-
// Script dissection/dumping functions
void dissectScript(int scriptNumber, Vocabulary *vocab);
void dumpScriptObject(char *data, int seeker, int objsize);
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 38baeafad8..44b2404e41 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -204,7 +204,7 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their
}
-reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+reg_t kDoSoundSci0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
uint16 command = argv[0].toUint16();
SongHandle handle = FROBNICATE_HANDLE(obj);
@@ -383,7 +383,7 @@ reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
-reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+reg_t kDoSoundSci1Early(EngineState *s, int funct_nr, int argc, reg_t *argv) {
uint16 command = argv[0].toUint16();
reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
SongHandle handle = FROBNICATE_HANDLE(obj);
@@ -673,7 +673,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+reg_t kDoSoundSci1Late(EngineState *s, int funct_nr, int argc, reg_t *argv) {
uint16 command = argv[0].toUint16();
reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
SongHandle handle = FROBNICATE_HANDLE(obj);
@@ -988,12 +988,17 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) {
* Used for synthesized music playback
*/
reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- if (((SciEngine*)g_engine)->getKernel()->usesSci1SoundFunctions())
- return kDoSound_SCI1(s, funct_nr, argc, argv);
- else if (((SciEngine*)g_engine)->getKernel()->usesSci01SoundFunctions())
- return kDoSound_SCI01(s, funct_nr, argc, argv);
- else
- return kDoSound_SCI0(s, funct_nr, argc, argv);
+ switch(s->detectDoSoundType()) {
+ case EngineState::kDoSoundTypeSci0:
+ return kDoSoundSci0(s, funct_nr, argc, argv);
+ case EngineState::kDoSoundTypeSci1Early:
+ return kDoSoundSci1Early(s, funct_nr, argc, argv);
+ case EngineState::kDoSoundTypeSci1Late:
+ return kDoSoundSci1Late(s, funct_nr, argc, argv);
+ default:
+ warning("Unknown DoSound type");
+ return NULL_REG;
+ }
}
/**
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 1768695244..b53e9d522c 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -701,8 +701,7 @@ static void reconstruct_sounds(EngineState *s) {
Song *seeker;
SongIteratorType it_type;
- if (((SciEngine *)g_engine)->getKernel()->usesSci01SoundFunctions()
- || ((SciEngine *)g_engine)->getKernel()->usesSci1SoundFunctions())
+ if (s->_version > SCI_VERSION_01)
it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
else
it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index fd45ef5834..c45868ca56 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -24,6 +24,8 @@
*/
#include "sci/engine/state.h"
+#include "sci/engine/vm.h"
+#include "sci/console.h" // For parse_reg_t
namespace Sci {
@@ -116,6 +118,8 @@ EngineState::EngineState(ResourceManager *res, SciVersion version, uint32 flags)
successor = 0;
speedThrottler = new SpeedThrottler(version);
+
+ _doSoundType = kDoSoundTypeUnknown;
}
EngineState::~EngineState() {
@@ -242,4 +246,75 @@ Common::String EngineState::strSplit(const char *str, const char *sep) {
return retval;
}
+EngineState::DoSoundType EngineState::detectDoSoundType() {
+ if (_doSoundType == kDoSoundTypeUnknown) {
+ reg_t soundClass;
+ const uint checkBytes = 6; // Number of bytes to check
+
+ if (!parse_reg_t(this, "?Sound", &soundClass)) {
+ reg_t fptr;
+
+ Object *obj = obj_get(this, soundClass);
+ SelectorType sel = lookup_selector(this, soundClass, ((SciEngine*)g_engine)->getKernel()->_selectorMap.play, NULL, &fptr);
+
+ if (obj && (sel == kSelectorMethod)) {
+ Script *script = seg_manager->getScript(fptr.segment);
+
+ if (fptr.offset > checkBytes) {
+ // Go to the last portion of Sound::init, should be right before the play function
+ fptr.offset -= checkBytes;
+ byte *buf = script->buf + fptr.offset;
+
+ // Check the call to DoSound's INIT_HANDLE function.
+ // It's either subfunction 0, 5 or 6, depending on the version of DoSound.
+ uint sum = 0;
+ for (uint i = 0; i < checkBytes; i++)
+ sum += buf[i];
+
+ switch(sum) {
+ case 0x1B2: // SCI0
+ case 0x1AE: // SCI01
+ _doSoundType = kDoSoundTypeSci0;
+ break;
+ case 0x13D:
+ _doSoundType = kDoSoundTypeSci1Early;
+ break;
+ case 0x13E:
+ _doSoundType = kDoSoundTypeSci1Late;
+ }
+ }
+ }
+ }
+
+ if (_doSoundType == kDoSoundTypeUnknown) {
+ warning("DoSound detection failed, taking an educated guess");
+
+ if (_version >= SCI_VERSION_1_MIDDLE)
+ _doSoundType = kDoSoundTypeSci1Late;
+ else if (_version > SCI_VERSION_01)
+ _doSoundType = kDoSoundTypeSci1Early;
+ else
+ _doSoundType = kDoSoundTypeSci0;
+ }
+
+ debugCN(1, kDebugLevelSound, "Detected DoSound type: ");
+
+ switch(_doSoundType) {
+ case kDoSoundTypeSci0:
+ debugC(1, kDebugLevelSound, "SCI0");
+ break;
+ case kDoSoundTypeSci1Early:
+ debugC(1, kDebugLevelSound, "SCI1 Early");
+ break;
+ case kDoSoundTypeSci1Late:
+ debugC(1, kDebugLevelSound, "SCI1 Late");
+ break;
+ default:
+ break;
+ }
+ }
+
+ return _doSoundType;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index c8e9139f27..a3983f6ae4 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -163,6 +163,14 @@ struct EngineState : public Common::Serializable {
public:
EngineState(ResourceManager *res, SciVersion version, uint32 flags);
virtual ~EngineState();
+
+ enum DoSoundType {
+ kDoSoundTypeUnknown,
+ kDoSoundTypeSci0,
+ kDoSoundTypeSci1Early,
+ kDoSoundTypeSci1Late
+ };
+
virtual void saveLoadWithSerializer(Common::Serializer &ser);
kLanguage getLanguage();
@@ -272,6 +280,12 @@ public:
*/
Common::String strSplit(const char *str, const char *sep = "\r----------\r");
+ /**
+ * Autodetects the DoSound type
+ * @return DoSound type
+ */
+ DoSoundType detectDoSoundType();
+
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -301,6 +315,7 @@ public:
EngineState *successor; /**< Successor of this state: Used for restoring */
private:
+ DoSoundType _doSoundType;
kLanguage charToLanguage(const char c) const;
Common::String getLanguageString(const char *str, kLanguage lang) const;
};
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index ef31fcdd7d..7b201d0506 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1480,7 +1480,7 @@ SciVersion ResourceManager::detectSciVersion() {
// If this turns out to be unreliable, we could do some pic resource checks instead.
return SCI_VERSION_1_EARLY;
case kResVersionSci1Middle:
- return SCI_VERSION_1_LATE;
+ return SCI_VERSION_1_MIDDLE;
case kResVersionSci1Late:
if (_viewType == kViewVga11) {
// SCI1.1 resources, assume SCI1.1
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index d38cff87df..0a5336fd3f 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -52,7 +52,8 @@ enum SciVersion {
SCI_VERSION_01, // KQ1 and multilingual games (S.old.*)
SCI_VERSION_1_EGA, // EGA with parser, QFG2
SCI_VERSION_1_EARLY, // KQ5. (EGA/VGA)
- SCI_VERSION_1_LATE, // ECO1, LSL1, LSL5. (EGA/VGA)
+ SCI_VERSION_1_MIDDLE, // LSL1, JONESCD. (EGA?/VGA)
+ SCI_VERSION_1_LATE, // ECO1, LSL5. (EGA/VGA)
SCI_VERSION_1_1, // KQ6, ECO2
SCI_VERSION_32 // GK
};
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index b799af9e83..64e89a638e 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -44,13 +44,14 @@ namespace Sci {
class GfxDriver;
// FIXME: error-prone
-const char *versionNames[9] = {
+const char *versionNames[10] = {
"Autodetect",
"SCI0 Early",
"SCI0 Late",
"SCI01",
"SCI1 EGA",
"SCI1 Early",
+ "SCI1 Middle",
"SCI1 Late",
"SCI1.1",
"SCI32"