diff options
-rw-r--r-- | engines/sci/engine/kernel.cpp | 11 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 26 | ||||
-rw-r--r-- | engines/sci/engine/kernel32.cpp | 14 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 34 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 15 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 2 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 3 |
7 files changed, 78 insertions, 27 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 27fbc9f55d..e8d4589d79 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -379,12 +379,9 @@ SciKernelFunction kfunct_mappers[] = { {NULL, NULL, NULL} // Terminator }; -Kernel::Kernel(ResourceManager *resMan, Common::String gameId) : _resMan(resMan) { +Kernel::Kernel(ResourceManager *resMan) : _resMan(resMan) { loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use - - loadKernelNames(gameId); - mapFunctions(); // Map the kernel functions } Kernel::~Kernel() { @@ -777,17 +774,19 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { } } -bool Kernel::loadKernelNames(Common::String gameId) { +bool Kernel::loadKernelNames(Common::String gameId, EngineState *s) { _kernelNames.clear(); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2_1) - setKernelNamesSci21(gameId); + setKernelNamesSci21(s); else if (getSciVersion() == SCI_VERSION_2) setKernelNamesSci2(); else #endif setDefaultKernelNames(gameId); + + mapFunctions(); return true; } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 3eccf7bd72..4516b814f9 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -112,7 +112,7 @@ public: /** * Initializes the SCI kernel */ - Kernel(ResourceManager *resMan, Common::String gameId); + Kernel(ResourceManager *resMan); ~Kernel(); uint getSelectorNamesSize() const; @@ -122,6 +122,17 @@ public: const Common::String &getKernelName(uint number) const; /** + * Loads the kernel function names. + * + * This function reads the kernel function name table from resource_map, + * and fills the _kernelNames array with them. + * The resulting list has the same format regardless of the format of the + * name table of the resource (the format changed between version 0 and 1). + * @return true on success, false on failure + */ + bool loadKernelNames(Common::String gameId, EngineState *s); + + /** * Determines the selector ID of a selector by its name * @param selectorName Name of the selector to look up * @return The appropriate selector ID, or -1 on error @@ -139,17 +150,6 @@ public: private: /** - * Loads the kernel function names. - * - * This function reads the kernel function name table from resource_map, - * and fills the _kernelNames array with them. - * The resulting list has the same format regardless of the format of the - * name table of the resource (the format changed between version 0 and 1). - * @return true on success, false on failure - */ - bool loadKernelNames(Common::String gameId); - - /** * Sets the default kernel function names, based on the SCI version used */ void setDefaultKernelNames(Common::String gameId); @@ -163,7 +163,7 @@ private: /** * Sets the default kernel function names to the SCI2.1 kernel functions */ - void setKernelNamesSci21(Common::String gameId); + void setKernelNamesSci21(EngineState *s); #endif /** diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 5bbf0db814..31344c6ec9 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -372,11 +372,15 @@ void Kernel::setKernelNamesSci2() { _kernelNames = Common::StringList(sci2_default_knames, kKernelEntriesSci2); } -void Kernel::setKernelNamesSci21(Common::String gameId) { - // The Gabriel Knight 2 demo uses a different kernel function set. It's pretty much a cross between - // the SCI2 and SCI2.1 set. Strangely, the GK2 executable still has the 2.100.002 version string, - // even though it wouldn't be compatible with the other 2.100.002 games... - if (gameId == "gk2" && ((SciEngine *)g_engine)->isDemo()) { +void Kernel::setKernelNamesSci21(EngineState *s) { + // Some SCI games use a modified SCI2 kernel table instead of the SCI2.1/SCI3 kernel table. + // The GK2 demo does this as well as at least one version of KQ7. We detect which version + // to use based on where kDoSound is called from Sound::play(). + + // This is interesting because they all have the same interpreter version (2.100.002), yet + // they would not be compatible with other games of the same interpreter. + + if (s->detectSci21KernelType() == SCI_VERSION_2) { _kernelNames = Common::StringList(sci2_default_knames, kKernelEntriesGk2Demo); // OnMe is IsOnMe here, but they should be compatible _kernelNames[0x23] = "Robot"; // Graph in SCI2 diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index d9e4dcb0e0..7002834a9f 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -78,6 +78,10 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, _lofsType = SCI_VERSION_NONE; _gfxFunctionsType = SCI_VERSION_NONE; _moveCountType = kMoveCountUninitialized; + +#ifdef ENABLE_SCI32 + _sci21KernelType = SCI_VERSION_NONE; +#endif _usesCdTrack = Common::File::exists("cdaudio.map"); @@ -246,6 +250,13 @@ bool EngineState::autoDetectFeature(FeatureDetection featureDetection, int metho objName = "Game"; objAddr = _segMan->findObjectByName(objName); break; +#ifdef ENABLE_SCI32 + case kDetectSci21KernelTable: + objName = "Sound"; + objAddr = _segMan->findObjectByName(objName); + slc = _kernel->_selectorCache.play; + break; +#endif default: warning("autoDetectFeature: invalid featureDetection value %x", featureDetection); return false; @@ -422,6 +433,17 @@ bool EngineState::autoDetectFeature(FeatureDetection featureDetection, int metho 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; } @@ -629,6 +651,18 @@ SciVersion EngineState::detectGfxFunctionsType() { return _gfxFunctionsType; } +#ifdef ENABLE_SCI32 +SciVersion EngineState::detectSci21KernelType() { + if (_sci21KernelType == SCI_VERSION_NONE) + if (!autoDetectFeature(kDetectSci21KernelTable)) + error("Could not detect the SCI2.1 kernel table type"); + + debugC(1, kDebugLevelVM, "Detected SCI2.1 kernel type: %s", getSciVersionDesc(_sci21KernelType).c_str()); + + return _sci21KernelType; +} +#endif + MoveCountType EngineState::detectMoveCountType() { if (_moveCountType == kMoveCountUninitialized) { // SCI0/SCI01 games always increment move count diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 6bd6fed78f..98296fce91 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -110,7 +110,8 @@ enum FeatureDetection { kDetectMoveCountType = 1, kDetectSoundType = 2, kDetectSetCursorType = 3, - kDetectLofsType = 4 + kDetectLofsType = 4, + kDetectSci21KernelTable = 5 }; class FileHandle { @@ -227,6 +228,14 @@ public: * @return Graphics functions type, SCI_VERSION_0_EARLY / SCI_VERSION_0_LATE */ SciVersion detectGfxFunctionsType(); + +#ifdef ENABLE_SCI32 + /** + * Autodetects the kernel functions used in SCI2.1 + * @return Graphics functions type, SCI_VERSION_2 / SCI_VERSION_2_1 + */ + SciVersion detectSci21KernelType(); +#endif /** * Applies to all versions before 0.000.502 @@ -270,6 +279,10 @@ private: bool autoDetectFeature(FeatureDetection featureDetection, int methodNum = -1); SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType; +#ifdef ENABLE_SCI32 + SciVersion _sci21KernelType; +#endif + MoveCountType _moveCountType; kLanguage charToLanguage(const char c) const; bool _usesCdTrack; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 759d36d825..28a43dd9a2 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -198,7 +198,7 @@ struct SelectorCache { Selector setCursor; ///< For cursor semantics autodetection #ifdef ENABLE_SCI32 - Selector data; // Used by Array() + Selector data; // Used by Array()/String() Selector picture; // Used to hold the picture ID for SCI32 pictures Selector plane; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index a2c355cb48..6977348c36 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -140,7 +140,7 @@ Common::Error SciEngine::run() { // Create debugger console. It requires GFX to be initialized _console = new Console(this); - _kernel = new Kernel(_resMan, getGameID()); + _kernel = new Kernel(_resMan); // Only SCI0 and SCI01 games used a parser _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; _audio = new AudioPlayer(_resMan); @@ -163,6 +163,7 @@ Common::Error SciEngine::run() { } script_adjust_opcode_formats(_gamestate); + _kernel->loadKernelNames(getGameID(), _gamestate); // Set the savegame dir (actually, we set it to a fake value, // since we cannot let the game control where saves are stored) |