SCI: Better fix for bug #3035058 - ECOQUEST demo: Missing subtitles

The demo really uses kGetMessage and not kMessage. We now detect which version of the message function is used. Thanks to Walter for pointing this out.

svn-id: r51384
This commit is contained in:
Matthew Hoops 2010-07-27 19:07:39 +00:00
parent 3cae0f3452
commit 828434456f
5 changed files with 52 additions and 19 deletions

View file

@ -38,6 +38,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan)
_doSoundType = SCI_VERSION_NONE; _doSoundType = SCI_VERSION_NONE;
_lofsType = SCI_VERSION_NONE; _lofsType = SCI_VERSION_NONE;
_gfxFunctionsType = SCI_VERSION_NONE; _gfxFunctionsType = SCI_VERSION_NONE;
_messageFunctionType = SCI_VERSION_NONE;
_moveCountType = kMoveCountUninitialized; _moveCountType = kMoveCountUninitialized;
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
@ -407,6 +408,41 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
return _gfxFunctionsType; return _gfxFunctionsType;
} }
SciVersion GameFeatures::detectMessageFunctionType() {
if (_messageFunctionType != SCI_VERSION_NONE)
return _messageFunctionType;
if (getSciVersion() > SCI_VERSION_1_1) {
_messageFunctionType = SCI_VERSION_1_1;
return _messageFunctionType;
} else if (getSciVersion() < SCI_VERSION_1_1) {
_messageFunctionType = SCI_VERSION_1_LATE;
return _messageFunctionType;
}
Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);
if (resources->empty()) {
// No messages found, so this doesn't really matter anyway...
_messageFunctionType = SCI_VERSION_1_1;
return _messageFunctionType;
}
Resource *res = g_sci->getResMan()->findResource(*resources->begin(), false);
assert(res);
// Only v2 Message resources use the kGetMessage kernel function.
// v3-v5 use the kMessage kernel function.
if (READ_SCI11ENDIAN_UINT32(res->data) / 1000 == 2)
_messageFunctionType = SCI_VERSION_1_LATE;
else
_messageFunctionType = SCI_VERSION_1_1;
debugC(1, kDebugLevelVM, "Detected message function type: %s", getSciVersionDesc(_messageFunctionType));
return _messageFunctionType;
}
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
bool GameFeatures::autoDetectSci21KernelType() { bool GameFeatures::autoDetectSci21KernelType() {
// First, check if the Sound object is loaded // First, check if the Sound object is loaded

View file

@ -67,6 +67,12 @@ public:
*/ */
SciVersion detectGfxFunctionsType(); SciVersion detectGfxFunctionsType();
/**
* Autodetects the message function used
* @return Message function type, SCI_VERSION_1_LATE / SCI_VERSION_1_1
*/
SciVersion detectMessageFunctionType();
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
/** /**
* Autodetects the kernel functions used in SCI2.1 * Autodetects the kernel functions used in SCI2.1
@ -105,7 +111,7 @@ private:
bool autoDetectSci21KernelType(); bool autoDetectSci21KernelType();
#endif #endif
SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType; SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType, _messageFunctionType;
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
SciVersion _sci21KernelType; SciVersion _sci21KernelType;
#endif #endif

View file

@ -670,7 +670,7 @@ bool Kernel::debugSetFunctionLogging(const char *kernelName, bool logging) {
return true; return true;
} }
void Kernel::setDefaultKernelNames() { void Kernel::setDefaultKernelNames(GameFeatures *features) {
_kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames));
// Some (later) SCI versions replaced CanBeHere by CantBeHere // Some (later) SCI versions replaced CanBeHere by CantBeHere
@ -722,6 +722,10 @@ void Kernel::setDefaultKernelNames() {
} }
_kernelNames[0x71] = "PalVary"; _kernelNames[0x71] = "PalVary";
// At least EcoQuest 1 demo uses kGetMessage instead of kMessage.
// Detect which function to use.
if (features->detectMessageFunctionType() == SCI_VERSION_1_1)
_kernelNames[0x7c] = "Message"; _kernelNames[0x7c] = "Message";
break; break;
@ -774,7 +778,7 @@ void Kernel::loadKernelNames(GameFeatures *features) {
setKernelNamesSci2(); setKernelNamesSci2();
else else
#endif #endif
setDefaultKernelNames(); setDefaultKernelNames(features);
mapFunctions(); mapFunctions();
} }

View file

@ -225,7 +225,7 @@ private:
/** /**
* Sets the default kernel function names, based on the SCI version used. * Sets the default kernel function names, based on the SCI version used.
*/ */
void setDefaultKernelNames(); void setDefaultKernelNames(GameFeatures *features);
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
/** /**

View file

@ -456,8 +456,7 @@ enum kMessageFunc {
K_MESSAGE_REFNOUN, K_MESSAGE_REFNOUN,
K_MESSAGE_PUSH, K_MESSAGE_PUSH,
K_MESSAGE_POP, K_MESSAGE_POP,
K_MESSAGE_LASTMESSAGE, K_MESSAGE_LASTMESSAGE
K_MESSAGE_ECOQUEST1_DEMO = 99
}; };
reg_t kGetMessage(EngineState *s, int argc, reg_t *argv) { reg_t kGetMessage(EngineState *s, int argc, reg_t *argv) {
@ -559,18 +558,6 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) {
return NULL_REG; return NULL_REG;
} }
case K_MESSAGE_ECOQUEST1_DEMO:
// The EcoQuest 1 demo uses a special version of kMessage. It's one of the
// earliest SCI 1.1 games. The noun is always 99 in this case, so we can
// treat it as a subop. If any other games require this syntax, we can change
// this to work with those games too.
if (g_sci->getGameId() != GID_ECOQUEST || !g_sci->isDemo())
error("kMessage called with EcoQuest 1 demo syntax in a different game");
tuple.noun = argv[0].toUint16();
tuple.verb = argv[2].toUint16();
return make_reg(0, s->_msgState->getMessage(argv[1].toUint16(), tuple, argv[3]));
default: default:
warning("Message: subfunction %i invoked (not implemented)", func); warning("Message: subfunction %i invoked (not implemented)", func);
} }