diff options
author | Martin Kiewitz | 2016-02-23 20:17:18 +0100 |
---|---|---|
committer | Martin Kiewitz | 2016-02-23 20:17:18 +0100 |
commit | 82165bb6f63290635cedb41b3a8dff1a5d1f5745 (patch) | |
tree | edaf769ebe342f18ca19a31a89d93c20f9c1d6ee /engines/sci | |
parent | 64e21078dae76e900ed2c8e338e27fe57b4cae4d (diff) | |
download | scummvm-rg350-82165bb6f63290635cedb41b3a8dff1a5d1f5745.tar.gz scummvm-rg350-82165bb6f63290635cedb41b3a8dff1a5d1f5745.tar.bz2 scummvm-rg350-82165bb6f63290635cedb41b3a8dff1a5d1f5745.zip |
SCI: Improve kAnimate fastcast detection, Remove EQ1 hack
- Add "kAnimate fast cast state" to "version" debug command
- Make it possible for script patcher signatures to get fully
used outside of the regular script patcher
- Remove previous fastcast detections and replace them with
a signature heuristic
- Remove object name checking, when fastcast global is set
- Heuristic detects "fast cast" support incorrectly for multilingual
KQ5, but it seems the game never sets the global, so it won't
matter. KQ5 CD (also SCI1 late) has fastcast support.
- Remove hack in GfxView::draw
- Add lots of comments to ScriptPatcher class
This fixes EcoQuest 1 Floppy showing the anemone on top of the
message box (see bug #5170)
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/console.cpp | 3 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 260 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.h | 21 | ||||
-rw-r--r-- | engines/sci/graphics/animate.cpp | 92 | ||||
-rw-r--r-- | engines/sci/graphics/animate.h | 10 | ||||
-rw-r--r-- | engines/sci/graphics/view.cpp | 13 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 2 | ||||
-rw-r--r-- | engines/sci/sci.h | 2 |
8 files changed, 250 insertions, 153 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a395552c81..cbc6dfaf74 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -491,6 +491,9 @@ bool Console::cmdGetVersion(int argc, const char **argv) { debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); #endif debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); + if (getSciVersion() <= SCI_VERSION_1_1) { + debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "yes" : "no"); + } debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no"); debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no"); debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index fe6475224e..0ddc8d3c4f 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -3615,20 +3615,20 @@ bool ScriptPatcher::verifySignature(uint32 byteOffset, const uint16 *signatureDa } // will return -1 if no match was found, otherwise an offset to the start of the signature match -int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize) { +int32 ScriptPatcher::findSignature(uint32 magicDWord, int magicOffset, const uint16 *signatureData, const char *patchDescription, const byte *scriptData, const uint32 scriptSize) { if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay return -1; - const uint32 magicDWord = runtimeEntry->magicDWord; // is platform-specific BE/LE form, so that the later match will work + // magicDWord is in platform-specific BE/LE form, so that the later match will work, this was done for performance const uint32 searchLimit = scriptSize - 3; uint32 DWordOffset = 0; // first search for the magic DWORD while (DWordOffset < searchLimit) { if (magicDWord == READ_UINT32(scriptData + DWordOffset)) { // magic DWORD found, check if actual signature matches - uint32 offset = DWordOffset + runtimeEntry->magicOffset; + uint32 offset = DWordOffset + magicOffset; - if (verifySignature(offset, patchEntry->signatureData, patchEntry->description, scriptData, scriptSize)) + if (verifySignature(offset, signatureData, patchDescription, scriptData, scriptSize)) return offset; } DWordOffset++; @@ -3637,22 +3637,146 @@ int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciS return -1; } -// This method calculates the magic DWORD for each entry in the signature table -// and it also initializes the selector table for selectors used in the signatures/patches of the current game -void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) { - const SciScriptPatcherEntry *curEntry = patchTable; - SciScriptPatcherRuntimeEntry *curRuntimeEntry; +int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, const SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize) { + return findSignature(runtimeEntry->magicDWord, runtimeEntry->magicOffset, patchEntry->signatureData, patchEntry->description, scriptData, scriptSize); +} + +// Attention: Magic DWord is returns using platform specific byte order. This is done on purpose for performance. +void ScriptPatcher::calculateMagicDWordAndVerify(const char *signatureDescription, const uint16 *signatureData, bool magicDWordIncluded, uint32 &calculatedMagicDWord, int &calculatedMagicDWordOffset) { Selector curSelector = -1; - int step; int magicOffset; byte magicDWord[4]; int magicDWordLeft = 0; - const uint16 *curData; uint16 curWord; uint16 curCommand; uint32 curValue; byte byte1 = 0; byte byte2 = 0; + + memset(magicDWord, 0, sizeof(magicDWord)); + + curWord = *signatureData; + magicOffset = 0; + while (curWord != SIG_END) { + curCommand = curWord & SIG_COMMANDMASK; + curValue = curWord & SIG_VALUEMASK; + switch (curCommand) { + case SIG_MAGICDWORD: { + if (magicDWordIncluded) { + if ((calculatedMagicDWord) || (magicDWordLeft)) + error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", signatureDescription); + magicDWordLeft = 4; + calculatedMagicDWordOffset = magicOffset; + } else { + error("Script-Patcher: Magic-DWORD sequence found in patch data\nFaulty patch: '%s'", signatureDescription); + } + break; + } + case SIG_CODE_ADDTOOFFSET: { + magicOffset -= curValue; + if (magicDWordLeft) + error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", signatureDescription); + break; + } + case SIG_CODE_UINT16: + case SIG_CODE_SELECTOR16: { + // UINT16 or 1 + switch (curCommand) { + case SIG_CODE_UINT16: { + signatureData++; curWord = *signatureData; + if (curWord & SIG_COMMANDMASK) + error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", signatureDescription); + if (!_isMacSci11) { + byte1 = curValue; + byte2 = curWord & SIG_BYTEMASK; + } else { + byte1 = curWord & SIG_BYTEMASK; + byte2 = curValue; + } + break; + } + case SIG_CODE_SELECTOR16: { + curSelector = _selectorIdTable[curValue]; + if (curSelector == -1) { + curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); + _selectorIdTable[curValue] = curSelector; + } + if (!_isMacSci11) { + byte1 = curSelector & 0x00FF; + byte2 = curSelector >> 8; + } else { + byte1 = curSelector >> 8; + byte2 = curSelector & 0x00FF; + } + break; + } + } + magicOffset -= 2; + if (magicDWordLeft) { + // Remember current word for Magic DWORD + magicDWord[4 - magicDWordLeft] = byte1; + magicDWordLeft--; + if (magicDWordLeft) { + magicDWord[4 - magicDWordLeft] = byte2; + magicDWordLeft--; + } + if (!magicDWordLeft) { + // Magic DWORD is now known, convert to platform specific byte order + calculatedMagicDWord = READ_LE_UINT32(magicDWord); + } + } + break; + } + case SIG_CODE_BYTE: + case SIG_CODE_SELECTOR8: { + if (curCommand == SIG_CODE_SELECTOR8) { + curSelector = _selectorIdTable[curValue]; + if (curSelector == -1) { + curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); + _selectorIdTable[curValue] = curSelector; + if (curSelector != -1) { + if (curSelector & 0xFF00) + error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", signatureDescription); + } + } + curValue = curSelector; + } + magicOffset--; + if (magicDWordLeft) { + // Remember current byte for Magic DWORD + magicDWord[4 - magicDWordLeft] = (byte)curValue; + magicDWordLeft--; + if (!magicDWordLeft) { + calculatedMagicDWord = READ_LE_UINT32(magicDWord); + } + } + break; + } + case PATCH_CODE_GETORIGINALBYTEADJUST: { + signatureData++; // skip over extra uint16 + break; + } + default: + break; + } + signatureData++; + curWord = *signatureData; + } + + if (magicDWordLeft) + error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", signatureDescription); + if (magicDWordIncluded) { + if (!calculatedMagicDWord) { + error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", signatureDescription); + } + } +} + +// This method calculates the magic DWORD for each entry in the signature table +// and it also initializes the selector table for selectors used in the signatures/patches of the current game +void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) { + const SciScriptPatcherEntry *curEntry = patchTable; + SciScriptPatcherRuntimeEntry *curRuntimeEntry; int patchEntryCount = 0; // Count entries and allocate runtime data @@ -3666,120 +3790,14 @@ void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) { curRuntimeEntry = _runtimeTable; while (curEntry->signatureData) { // process signature - memset(magicDWord, 0, sizeof(magicDWord)); - curRuntimeEntry->active = curEntry->defaultActive; curRuntimeEntry->magicDWord = 0; curRuntimeEntry->magicOffset = 0; - for (step = 0; step < 2; step++) { - switch (step) { - case 0: curData = curEntry->signatureData; break; - case 1: curData = curEntry->patchData; break; - } - - curWord = *curData; - magicOffset = 0; - while (curWord != SIG_END) { - curCommand = curWord & SIG_COMMANDMASK; - curValue = curWord & SIG_VALUEMASK; - switch (curCommand) { - case SIG_MAGICDWORD: { - if (step == 0) { - if ((curRuntimeEntry->magicDWord) || (magicDWordLeft)) - error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", curEntry->description); - magicDWordLeft = 4; - curRuntimeEntry->magicOffset = magicOffset; - } - break; - } - case SIG_CODE_ADDTOOFFSET: { - magicOffset -= curValue; - if (magicDWordLeft) - error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", curEntry->description); - break; - } - case SIG_CODE_UINT16: - case SIG_CODE_SELECTOR16: { - // UINT16 or 1 - switch (curCommand) { - case SIG_CODE_UINT16: { - curData++; curWord = *curData; - if (curWord & SIG_COMMANDMASK) - error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", curEntry->description); - if (!_isMacSci11) { - byte1 = curValue; - byte2 = curWord & SIG_BYTEMASK; - } else { - byte1 = curWord & SIG_BYTEMASK; - byte2 = curValue; - } - break; - } - case SIG_CODE_SELECTOR16: { - curSelector = _selectorIdTable[curValue]; - if (curSelector == -1) { - curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); - _selectorIdTable[curValue] = curSelector; - } - if (!_isMacSci11) { - byte1 = curSelector & 0x00FF; - byte2 = curSelector >> 8; - } else { - byte1 = curSelector >> 8; - byte2 = curSelector & 0x00FF; - } - break; - } - } - magicOffset -= 2; - if (magicDWordLeft) { - // Remember current word for Magic DWORD - magicDWord[4 - magicDWordLeft] = byte1; - magicDWordLeft--; - if (magicDWordLeft) { - magicDWord[4 - magicDWordLeft] = byte2; - magicDWordLeft--; - } - if (!magicDWordLeft) { - curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord); - } - } - break; - } - case SIG_CODE_BYTE: - case SIG_CODE_SELECTOR8: { - if (curCommand == SIG_CODE_SELECTOR8) { - curSelector = _selectorIdTable[curValue]; - if (curSelector == -1) { - curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); - _selectorIdTable[curValue] = curSelector; - if (curSelector != -1) { - if (curSelector & 0xFF00) - error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", curEntry->description); - } - } - curValue = curSelector; - } - magicOffset--; - if (magicDWordLeft) { - // Remember current byte for Magic DWORD - magicDWord[4 - magicDWordLeft] = (byte)curValue; - magicDWordLeft--; - if (!magicDWordLeft) { - curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord); - } - } - } - } - curData++; - curWord = *curData; - } - } - if (magicDWordLeft) - error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", curEntry->description); - if (!curRuntimeEntry->magicDWord) - error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", curEntry->description); + // We verify the signature data and remember the calculated magic DWord from the signature data + calculateMagicDWordAndVerify(curEntry->description, curEntry->signatureData, true, curRuntimeEntry->magicDWord, curRuntimeEntry->magicOffset); + // We verify the patch data + calculateMagicDWordAndVerify(curEntry->description, curEntry->patchData, false, curRuntimeEntry->magicDWord, curRuntimeEntry->magicOffset); curEntry++; curRuntimeEntry++; } diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h index d15fce321b..645e0946b3 100644 --- a/engines/sci/engine/script_patches.h +++ b/engines/sci/engine/script_patches.h @@ -90,13 +90,32 @@ public: ScriptPatcher(); ~ScriptPatcher(); + // Calculates the magic DWord for fast search and verifies signature/patch data + // Returns the magic DWord in platform-specific byte-order. This is done on purpose for performance. + void calculateMagicDWordAndVerify(const char *signatureDescription, const uint16 *signatureData, bool magicDWordIncluded, uint32 &calculatedMagicDWord, int &calculatedMagicDWordOffset); + + // Called when a script is loaded to check for signature matches and apply patches in such cases void processScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); + + // Verifies, if a given signature matches the given script data (pointed to by additional byte offset) bool verifySignature(uint32 byteOffset, const uint16 *signatureData, const char *signatureDescription, const byte *scriptData, const uint32 scriptSize); + // searches for a given signature inside script data + // returns -1 in case it was not found or an offset to the matching data + int32 findSignature(uint32 magicDWord, int magicOffset, const uint16 *signatureData, const char *patchDescription, const byte *scriptData, const uint32 scriptSize); + private: + // Initializes a patch table and creates run time information for it (for enabling/disabling), also calculates magic DWORD) void initSignature(const SciScriptPatcherEntry *patchTable); + + // Enables a patch inside the patch table (used for optional patches like CD+Text support for KQ6 & LB2) void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription); - int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize); + + // Searches for a given signature entry inside script data + // returns -1 in case it was not found or an offset to the matching data + int32 findSignature(const SciScriptPatcherEntry *patchEntry, const SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize); + + // Applies a patch to a given script + offset (overwrites parts) void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset); Selector *_selectorIdTable; diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index fdd81a8caa..98278397b7 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -28,6 +28,7 @@ #include "sci/sci.h" #include "sci/event.h" #include "sci/engine/kernel.h" +#include "sci/engine/script_patches.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -44,8 +45,8 @@ namespace Sci { -GfxAnimate::GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions) - : _s(state), _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _palette(palette), _cursor(cursor), _transitions(transitions) { +GfxAnimate::GfxAnimate(EngineState *state, ScriptPatcher *scriptPatcher, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions) + : _s(state), _scriptPatcher(scriptPatcher), _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _palette(palette), _cursor(cursor), _transitions(transitions) { init(); } @@ -55,16 +56,77 @@ GfxAnimate::~GfxAnimate() { void GfxAnimate::init() { _lastCastData.clear(); - _ignoreFastCast = false; - // fastCast object is not found in any SCI games prior SCI1 - if (getSciVersion() <= SCI_VERSION_01) - _ignoreFastCast = true; - // Also if fastCast object exists at gamestartup, we can assume that the interpreter doesn't do kAnimate aborts - // (found in Larry 1) - if (getSciVersion() > SCI_VERSION_0_EARLY) { - if (!_s->_segMan->findObjectByName("fastCast").isNull()) - _ignoreFastCast = true; + _fastCastEnabled = false; + if (getSciVersion() == SCI_VERSION_1_1) { + // Seems to have been available for all SCI1.1 games + _fastCastEnabled = true; + } else if (getSciVersion() >= SCI_VERSION_1_EARLY) { + // fastCast only exists for some games between SCI1 early and SCI1 late + // Try to detect it by code signature + // It's extremely important, that we only enable it for games that actually need it + if (detectFastCast()) { + _fastCastEnabled = true; + } + } +} + +// Signature for fastCast detection +static const uint16 fastCastSignature[] = { + SIG_MAGICDWORD, + 0x35, 0x00, // ldi 00 + 0xa1, 84, // sag global[84d] + SIG_END +}; + +// Fast cast in games: + +// SCI1 Early: +// KQ5 - no fastcast, LSL1 (demo) - no fastcast, Mixed Up Fairy Tales - *has fastcast*, XMas Card 1990 - no fastcast, +// SQ4Floppy - no fastcast, Mixed Up Mother Goose - no fastcast +// +// SCI1 Middle: +// LSL5 demo - no fastfast, Conquest of the Longbow demo - no fastcast, LSL1 - no fastcast, +// Astro Chicken II - no fastcast +// +// SCI1 Late: +// Castle of Dr. Brain demo - has fastcast, Castle of Dr. Brain - has fastcast, +// Conquests of the Longbow - has fastcast, Space Quest 1 EGA - has fastcast, +// King's Quest 5 multilingual - *NO* fastcast, Police Quest 3 demo - *NO* fastcast, +// LSL5 multilingual - has fastcast, Police Quest 3 - has fastcast, +// EcoQuest 1 - has fastcast, Mixed Up Fairy Tales demo - has fastcast, +// Space Quest 4 multilingual - *NO* fastcast +// +// SCI1.1 +// Quest for Glory 3 demo - has fastcast, Police Quest 1 - hast fastcast, Quest for Glory 1 - has fastcast +// Laura Bow 2 Floppy - has fastcast, Mixed Up Mother Goose - has fastcast, Quest for Glory 3 - has fastcast +// Island of Dr. Brain - has fastcast, King's Quest 6 - has fastcast, Space Quest 5 - has fastcast +// Hoyle 4 - has fastcast, Laura Bow 2 CD - has fastcast, Freddy Pharkas CD - has fastcast +bool GfxAnimate::detectFastCast() { + SegManager *segMan = _s->_segMan; + const reg_t gameVMObject = g_sci->getGameObject(); + reg_t gameSuperVMObject = segMan->getObject(gameVMObject)->getSuperClassSelector(); + uint32 magicDWord = 0; // platform-specific BE/LE for performance + int magicDWordOffset = 0; + + if (gameSuperVMObject.isNull()) { + gameSuperVMObject = gameVMObject; // Just in case. According to sci.cpp this may happen in KQ5CD, when loading saved games before r54510 + } + + Script *objectScript = segMan->getScript(gameSuperVMObject.getSegment()); + byte *scriptData = const_cast<byte *>(objectScript->getBuf(0)); + uint32 scriptSize = objectScript->getBufSize(); + + _scriptPatcher->calculateMagicDWordAndVerify("fast cast detection", fastCastSignature, true, magicDWord, magicDWordOffset); + + // Signature is found for multilingual King's Quest 5 too, but it looks as if the fast cast global is never set + // within that game. Which means even though we detect it as having the capability, it's never actually used. + // The original multilingual KQ5 interpreter did have this feature disabled. + // Sierra probably used latest system scripts and that's why we detect it. + if (_scriptPatcher->findSignature(magicDWord, magicDWordOffset, fastCastSignature, "fast cast detection", scriptData, scriptSize) >= 0) { + // Signature found, game seems to use fast cast for kAnimate + return true; } + return false; } void GfxAnimate::disposeLastCast() { @@ -80,12 +142,14 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { while (curNode) { curObject = curNode->value; - if (!_ignoreFastCast) { + if (_fastCastEnabled) { // Check if the game has a fastCast object set // if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes. if (!_s->variables[VAR_GLOBAL][84].isNull()) { - if (!strcmp(_s->_segMan->getObjectName(_s->variables[VAR_GLOBAL][84]), "fastCast")) - return false; + // This normally points to an object called "fastCast", + // but for example in Eco Quest 1 it may also point to an object called "EventHandler" (see bug #5170) + // Original SCI only checked, if this global was not 0. + return false; } } diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 6c1822c903..ac7078093c 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -87,9 +87,13 @@ class GfxView; */ class GfxAnimate { public: - GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions); + GfxAnimate(EngineState *state, ScriptPatcher *scriptPatcher, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions); virtual ~GfxAnimate(); + bool isFastCastEnabled() { + return _fastCastEnabled; + } + void disposeLastCast(); bool invoke(List *list, int argc, reg_t *argv); void makeSortedList(List *list); @@ -110,6 +114,7 @@ public: private: void init(); + bool detectFastCast(); void addToPicSetPicNotValid(); void animateShowPic(); @@ -119,6 +124,7 @@ private: void setNsRect(GfxView *view, AnimateList::iterator it); EngineState *_s; + ScriptPatcher *_scriptPatcher; GfxCache *_cache; GfxPorts *_ports; GfxPaint16 *_paint16; @@ -130,7 +136,7 @@ private: AnimateList _list; AnimateArray _lastCastData; - bool _ignoreFastCast; + bool _fastCastEnabled; }; } // End of namespace Sci diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 2ee18b5c9a..4116eda876 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -833,19 +833,6 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left); - // WORKAROUND: EcoQuest French and German draw the fish and anemone sprites - // with priority 15 in scene 440. Afterwards, a dialog is shown on top of - // these sprites with priority 15 as well. This is undefined behavior - // actually, as the sprites and dialog share the same priority, so in our - // implementation the sprites get drawn incorrectly on top of the dialog. - // Perhaps this worked by mistake in SSCI because of subtle differences in - // how sprites are drawn. We compensate for this by resetting the priority - // of all sprites that have a priority of 15 in scene 440 to priority 14, - // so that the speech bubble can be drawn correctly on top of them. Fixes - // bug #3040625. - if (g_sci->getGameId() == GID_ECOQUEST && g_sci->getEngineState()->currentRoomNumber() == 440 && priority == 15) - priority = 14; - if (!_EGAmapping) { for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index cce0235fd5..577abb2a8b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -717,7 +717,7 @@ void SciEngine::initGraphics() { _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette16); _gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette16, _gfxTransitions, _audio); _gfxPaint = _gfxPaint16; - _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions); + _gfxAnimate = new GfxAnimate(_gamestate, _scriptPatcher, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions); _gfxText16 = new GfxText16(_gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); _gfxControls16 = new GfxControls16(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); _gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 5c86d92355..3945e68e33 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -282,7 +282,7 @@ public: inline EngineState *getEngineState() const { return _gamestate; } inline Vocabulary *getVocabulary() const { return _vocabulary; } inline EventManager *getEventManager() const { return _eventMan; } - inline reg_t getGameObject() const { return _gameObjectAddress; } + inline reg_t getGameObject() const { return _gameObjectAddress; } // Gets the game object VM address Common::RandomSource &getRNG() { return _rng; } |