From 54e94c572aeb58e160537e2145c0fff44e862be3 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Thu, 12 Jan 2017 10:55:13 -0600 Subject: SCI32: Add workarounds, transitions, fixes for PQ4CD --- engines/sci/engine/kernel_tables.h | 8 ++--- engines/sci/engine/workarounds.cpp | 25 ++++++++++++++ engines/sci/engine/workarounds.h | 3 ++ engines/sci/graphics/paint32.cpp | 6 ++-- engines/sci/graphics/transitions32.cpp | 61 ++++++++++++++++++++++++++++++---- engines/sci/graphics/transitions32.h | 6 ++++ 6 files changed, 95 insertions(+), 14 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index c611af4aee..ac4987e603 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -287,7 +287,7 @@ static const SciKernelMapSubEntry kPalVary_subops[] = { { SIG_SCI32, 6, MAP_CALL(PalVaryPauseResume), "i", NULL }, { SIG_SCI32, 7, MAP_CALL(PalVarySetTarget), "i", NULL }, { SIG_SCI32, 8, MAP_CALL(PalVarySetStart), "i", NULL }, - { SIG_SCI32, 9, MAP_CALL(PalVaryMergeStart), "i", NULL }, + { SIG_SCI32, 9, MAP_CALL(PalVaryMergeStart), "i", kPalVaryMergeStart_workarounds }, #endif SCI_SUBOPENTRY_TERMINATOR }; @@ -512,7 +512,7 @@ static const SciKernelMapSubEntry kArray_subops[] = { { SIG_SCI32, 2, MAP_CALL(ArrayGetElement), "ri", NULL }, { SIG_SCI32, 3, MAP_CALL(ArraySetElements), "ri(.*)", kArraySetElements_workarounds }, { SIG_SCI32, 4, MAP_CALL(ArrayFree), "[0r]", NULL }, - { SIG_SCI32, 5, MAP_CALL(ArrayFill), "riii", NULL }, + { SIG_SCI32, 5, MAP_CALL(ArrayFill), "riii", kArrayFill_workarounds }, { SIG_SCI32, 6, MAP_CALL(ArrayCopy), "ririi", NULL }, // there is no subop 7 { SIG_SCI32, 8, MAP_CALL(ArrayDuplicate), "r", NULL }, @@ -531,7 +531,7 @@ static const SciKernelMapSubEntry kString_subops[] = { { SIG_THRU_SCI21MID, 2, MAP_CALL(StringGetChar), "ri", NULL }, { SIG_THRU_SCI21MID, 3, MAP_CALL(ArraySetElements), "ri(i*)", kArraySetElements_workarounds }, { SIG_THRU_SCI21MID, 4, MAP_CALL(StringFree), "[0r]", NULL }, - { SIG_THRU_SCI21MID, 5, MAP_CALL(ArrayFill), "rii", NULL }, + { SIG_THRU_SCI21MID, 5, MAP_CALL(ArrayFill), "rii", kArrayFill_workarounds }, { SIG_THRU_SCI21MID, 6, MAP_CALL(ArrayCopy), "ririi", NULL }, { SIG_SCI32, 7, MAP_CALL(StringCompare), "rr(i)", NULL }, @@ -860,7 +860,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, { "DisposeTextBitmap", kBitmapDestroy, SIG_SCI2, SIGFOR_ALL, "[r!]", NULL, NULL }, - { MAP_CALL(FrameOut), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(FrameOut), SIG_EVERYWHERE, "(i)", NULL, kFrameOut_workarounds }, { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 1201b9f029..560a383e24 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -352,6 +352,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_PEPPER, -1, 894, 0, "Package", "doVerb", NULL, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 { GID_PEPPER, 150, 928, 0, "Narrator", "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper { GID_PQ4, -1, 25, 0, "iconToggle", "select", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not + { GID_PQ4, 275, 64964, -1, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when Sherry walks out of the morgue on day 3 + { GID_PQ4, 240, 64964, -1, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when encountering Sherry and the reporter outside the morgue at the end of day 3 { GID_PQSWAT, -1, 64950, 0, NULL, "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using any menus in-game { GID_PQSWAT, -1, 73, 0, "theLashInterface", "transmit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Clicking the transmit button in LASH { GID_PQSWAT, 2990, 2990, 0, "talkToSchienbly", "changeState", NULL, 1, { WORKAROUND_FAKE, 0 } }, // When the video of Schienbly talking for the first time ends @@ -427,6 +429,12 @@ const SciWorkaroundEntry kArraySetElements_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround +const SciWorkaroundEntry kArrayFill_workarounds[] = { + { GID_PQ4, 540, 64918, 0, "Str", "callKernel", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when clicking on Hate Crimes in the computer on day 2 + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kCelHigh_workarounds[] = { { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 @@ -593,6 +601,17 @@ const SciWorkaroundEntry kFindKey_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround +const SciWorkaroundEntry kFrameOut_workarounds[] = { + { GID_PQ4, 360, 360, 0, "copCarInset", "init", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When clicking hand on the impounded police car on day 3 + { GID_PQ4, 360, 360, 0, "copCarInset", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When exiting the impounded police car on day 3 + { GID_PQ4, 275, 275, 0, "checkSherry", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When encountering Sherry and Sam in the morgue on day 3 + { GID_PQ4, 725, 725, 0, "fridgeInset", "init", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When opening the refrigerator at the end of day 4 + { GID_PQ4, 725, 725, 0, "fridgeInset", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When exiting the refrigerator at the end of day 4 + { GID_PQ4, 735, 735, 0, "medInset", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 1 } }, // When exiting the medicine cabinet at the end of day 4 + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphDrawLine_workarounds[] = { { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter @@ -724,6 +743,12 @@ const SciWorkaroundEntry kPalVarySetPercent_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround +const SciWorkaroundEntry kPalVaryMergeStart_workarounds[] = { + { GID_PQ4, 170, 170, 0, "getHit", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Three extra parameters passed during the gunfight at the end of day 1 + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kPlatform32_workarounds[] = { { GID_HOYLE5, -1, 0, 0, "hoyle4", "newRoom", NULL, 0, { WORKAROUND_FAKE, 1 } }, // at the start of the game, incorrectly uses SCI16 calling convention for kPlatform diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h index 86b4ee2902..cb928faf09 100644 --- a/engines/sci/engine/workarounds.h +++ b/engines/sci/engine/workarounds.h @@ -72,6 +72,7 @@ extern const SciWorkaroundEntry kDoSoundPlay_workarounds[]; extern const SciWorkaroundEntry kDoSoundFade_workarounds[]; extern const SciWorkaroundEntry kFileIOOpen_workarounds[]; extern const SciWorkaroundEntry kFindKey_workarounds[]; +extern const SciWorkaroundEntry kFrameOut_workarounds[]; extern const SciWorkaroundEntry kDeleteKey_workarounds[]; extern const SciWorkaroundEntry kGetAngle_workarounds[]; extern const SciWorkaroundEntry kGraphDrawLine_workarounds[]; @@ -87,6 +88,7 @@ extern const SciWorkaroundEntry kMemory_workarounds[]; extern const SciWorkaroundEntry kMoveCursor_workarounds[]; extern const SciWorkaroundEntry kNewWindow_workarounds[]; extern const SciWorkaroundEntry kPalVarySetPercent_workarounds[]; +extern const SciWorkaroundEntry kPalVaryMergeStart_workarounds[]; extern const SciWorkaroundEntry kPlatform32_workarounds[]; extern const SciWorkaroundEntry kRandom_workarounds[]; extern const SciWorkaroundEntry kReadNumber_workarounds[]; @@ -94,6 +96,7 @@ extern const SciWorkaroundEntry kResCheck_workarounds[]; extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[]; extern const SciWorkaroundEntry kSetCursor_workarounds[]; extern const SciWorkaroundEntry kArraySetElements_workarounds[]; +extern const SciWorkaroundEntry kArrayFill_workarounds[]; extern const SciWorkaroundEntry kSetPort_workarounds[]; extern const SciWorkaroundEntry kStrAt_workarounds[]; extern const SciWorkaroundEntry kStrCpy_workarounds[]; diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index bf7c73623e..8a63365f03 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -121,7 +121,7 @@ void GfxPaint32::plotter(int x, int y, int color, void *data) { reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, uint16 pattern, uint8 thickness, Common::Rect &outRect) { const uint8 skipColor = color != kDefaultSkipColor ? kDefaultSkipColor : 0; - // Line thickness is expected to be 2 * thickness + 1 + // Line thickness is expected to be 2n + 1 thickness = (MAX(1, thickness) - 1) | 1; const uint8 halfThickness = thickness >> 1; @@ -130,8 +130,8 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common:: outRect.left = MIN(startPoint.x, endPoint.x); outRect.top = MIN(startPoint.y, endPoint.y); - outRect.right = MAX(startPoint.x, endPoint.x) + 1 + 1; // rect lower edge + thickness offset - outRect.bottom = MAX(startPoint.y, endPoint.y) + 1 + 1; // rect lower edge + thickness offset + outRect.right = MAX(startPoint.x, endPoint.x) + 1; + outRect.bottom = MAX(startPoint.y, endPoint.y) + 1; outRect.grow(halfThickness); outRect.clip(Common::Rect(scriptWidth, scriptHeight)); diff --git a/engines/sci/graphics/transitions32.cpp b/engines/sci/graphics/transitions32.cpp index a1ae352b6c..bc2825ba77 100644 --- a/engines/sci/graphics/transitions32.cpp +++ b/engines/sci/graphics/transitions32.cpp @@ -319,16 +319,20 @@ void GfxTransitions32::kernelSetShowStyle(const uint16 argc, const reg_t planeOb if (createNewEntry) { if (getSciVersion() <= SCI_VERSION_2_1_EARLY) { switch (entry->type) { + case kShowStyleWipeLeft: + case kShowStyleWipeRight: + configure21EarlyHorizontalWipe(*entry, priority); + break; case kShowStyleIrisOut: case kShowStyleIrisIn: configure21EarlyIris(*entry, priority); - break; + break; case kShowStyleDissolve: configure21EarlyDissolve(*entry, priority, plane->_gameRect); - break; + break; default: // do nothing - break; + break; } } @@ -377,6 +381,8 @@ ShowStyleList::iterator GfxTransitions32::deleteShowStyle(const ShowStyleList::i g_sci->_gfxFrameout->deleteScreenItem(*showStyle->bitmapScreenItem); } break; + case kShowStyleWipeLeft: + case kShowStyleWipeRight: case kShowStyleIrisOut: case kShowStyleIrisIn: if (getSciVersion() <= SCI_VERSION_2_1_EARLY) { @@ -406,6 +412,33 @@ ShowStyleList::iterator GfxTransitions32::deleteShowStyle(const ShowStyleList::i return _showStyles.erase(showStyle); } +void GfxTransitions32::configure21EarlyHorizontalWipe(PlaneShowStyle &showStyle, const int16 priority) { + showStyle.numEdges = 1; + const int divisions = showStyle.divisions; + showStyle.screenItems.reserve(divisions); + + CelInfo32 celInfo; + celInfo.type = kCelTypeColor; + celInfo.color = showStyle.color; + + for (int i = 0; i < divisions; ++i) { + Common::Rect rect; + rect.left = showStyle.width * i / divisions; + rect.top = 0; + rect.right = showStyle.width * (i + 1) / divisions; + rect.bottom = showStyle.height; + showStyle.screenItems.push_back(new ScreenItem(showStyle.plane, celInfo, rect)); + showStyle.screenItems.back()->_priority = priority; + showStyle.screenItems.back()->_fixedPriority = true; + } + + if (showStyle.fadeUp) { + for (int i = 0; i < divisions; ++i) { + g_sci->_gfxFrameout->addScreenItem(*showStyle.screenItems[i]); + } + } +} + void GfxTransitions32::configure21EarlyIris(PlaneShowStyle &showStyle, const int16 priority) { showStyle.numEdges = 4; const int numScreenItems = showStyle.numEdges * showStyle.divisions; @@ -506,13 +539,23 @@ bool GfxTransitions32::processShowStyle(PlaneShowStyle &showStyle, uint32 now) { case kShowStyleHShutterIn: case kShowStyleVShutterOut: case kShowStyleVShutterIn: - case kShowStyleWipeLeft: - case kShowStyleWipeRight: case kShowStyleWipeUp: case kShowStyleWipeDown: case kShowStyleDissolveNoMorph: case kShowStyleMorph: return processMorph(showStyle); + case kShowStyleWipeLeft: + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processMorph(showStyle); + } else { + return processWipe(-1, showStyle); + } + case kShowStyleWipeRight: + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processMorph(showStyle); + } else { + return processWipe(1, showStyle); + } case kShowStyleDissolve: if (getSciVersion() > SCI_VERSION_2_1_EARLY) { return processMorph(showStyle); @@ -608,11 +651,15 @@ void GfxTransitions32::processVShutterIn(PlaneShowStyle &showStyle) { } void GfxTransitions32::processWipeLeft(PlaneShowStyle &showStyle) { - error("WipeLeft is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + error("WipeLeft is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + } } void GfxTransitions32::processWipeRight(PlaneShowStyle &showStyle) { - error("WipeRight is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + error("WipeRight is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + } } void GfxTransitions32::processWipeUp(PlaneShowStyle &showStyle) { diff --git a/engines/sci/graphics/transitions32.h b/engines/sci/graphics/transitions32.h index 0c828a20f7..685012fada 100644 --- a/engines/sci/graphics/transitions32.h +++ b/engines/sci/graphics/transitions32.h @@ -330,6 +330,12 @@ private: */ ShowStyleList::iterator deleteShowStyle(const ShowStyleList::iterator &showStyle); + /** + * Initializes the given PlaneShowStyle for a + * horizontal wipe effect for SCI2 to 2.1early. + */ + void configure21EarlyHorizontalWipe(PlaneShowStyle &showStyle, const int16 priority); + /** * Initializes the given PlaneShowStyle for an * iris effect for SCI2 to 2.1early. -- cgit v1.2.3