aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kernel.cpp11
-rw-r--r--engines/sci/engine/kernel.h26
-rw-r--r--engines/sci/engine/kernel32.cpp14
-rw-r--r--engines/sci/engine/state.cpp34
-rw-r--r--engines/sci/engine/state.h15
-rw-r--r--engines/sci/engine/vm.h2
-rw-r--r--engines/sci/sci.cpp3
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)