Detect whether to use the modified SCI2 or SCI2.1 kernel table based on the kDoSound call used in Sound::play(), which fixes at least my version of KQ7 - probably others. The kernel table initialization now occurs after the script signatures are adjusted as we need it adjusted before checking through Sound::play for the kDoSound call.

svn-id: r47645
This commit is contained in:
Matthew Hoops 2010-01-28 18:57:31 +00:00
parent 8ecd76e415
commit d883b6215f
7 changed files with 78 additions and 27 deletions

View File

@ -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;
}

View File

@ -112,7 +112,7 @@ public:
/**
* Initializes the SCI kernel
*/
Kernel(ResourceManager *resMan, Common::String gameId);
Kernel(ResourceManager *resMan);
~Kernel();
uint getSelectorNamesSize() const;
@ -121,6 +121,17 @@ public:
uint getKernelNamesSize() const;
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
@ -138,17 +149,6 @@ public:
KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions */
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
*/
@ -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
/**

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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)