diff options
author | Willem Jan Palenstijn | 2017-07-09 17:25:17 +0200 |
---|---|---|
committer | Willem Jan Palenstijn | 2017-07-09 22:56:04 +0200 |
commit | 820caf370e2c24e6aefd8b1b90227ca29564bab6 (patch) | |
tree | 053eaaf33fc0ea8e63be6c2265942251934181ac /engines | |
parent | 33cfcfd5ff626e8b341fdee3171bf1367191fe65 (diff) | |
download | scummvm-rg350-820caf370e2c24e6aefd8b1b90227ca29564bab6.tar.gz scummvm-rg350-820caf370e2c24e6aefd8b1b90227ca29564bab6.tar.bz2 scummvm-rg350-820caf370e2c24e6aefd8b1b90227ca29564bab6.zip |
SCI32: Fix kObjectIntersect
It was using SCI16 calls to get the NowSeenRects.
This fixes #9855.
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/kgraphics32.cpp | 13 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 73 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.h | 2 |
3 files changed, 64 insertions, 24 deletions
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 76ed27ae68..44a3517458 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -102,20 +102,14 @@ reg_t kSetNowSeen32(EngineState *s, int argc, reg_t *argv) { // NOTE: MGDX is assumed to use the older kSetNowSeen since it was // released before SQ6, but this has not been verified since it cannot be // disassembled at the moment (Phar Lap Windows-only release) + // (See also getNowSeenRect) if (getSciVersion() <= SCI_VERSION_2_1_EARLY || g_sci->getGameId() == GID_SQ6 || g_sci->getGameId() == GID_MOTHERGOOSEHIRES) { - if (!found) { - error("kSetNowSeen: Unable to find screen item %04x:%04x", PRINT_REG(argv[0])); - } return s->r_acc; } - if (!found) { - warning("kSetNowSeen: Unable to find screen item %04x:%04x", PRINT_REG(argv[0])); - } - return make_reg(0, found); } @@ -245,9 +239,8 @@ reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) { } reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) { - Common::Rect objRect1 = g_sci->_gfxCompare->getNSRect(argv[0]); - Common::Rect objRect2 = g_sci->_gfxCompare->getNSRect(argv[1]); - return make_reg(0, objRect1.intersects(objRect2)); + int16 area = g_sci->_gfxFrameout->kernelObjectIntersect(argv[0], argv[1]); + return make_reg(0, area); } reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 7415979f5c..b49332dcb3 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -1253,35 +1253,80 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const return true; } -bool GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { +bool GfxFrameout::getNowSeenRect(const reg_t screenItemObject, Common::Rect &result) const { const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane)); - - Plane *plane = _planes.findByObject(planeObject); + const Plane *plane = _planes.findByObject(planeObject); if (plane == nullptr) { - error("kSetNowSeen: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(screenItemObject)); + error("getNowSeenRect: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(screenItemObject)); } - ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); + const ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); if (screenItem == nullptr) { + // NOTE: MGDX is assumed to use the older getNowSeenRect since it was + // released before SQ6, but this has not been verified since it cannot + // be disassembled at the moment (Phar Lap Windows-only release) + // (See also kSetNowSeen32) + if (getSciVersion() <= SCI_VERSION_2_1_EARLY || + g_sci->getGameId() == GID_SQ6 || + g_sci->getGameId() == GID_MOTHERGOOSEHIRES) { + + error("getNowSeenRect: Unable to find screen item %04x:%04x", PRINT_REG(screenItemObject)); + } + + warning("getNowSeenRect: Unable to find screen item %04x:%04x", PRINT_REG(screenItemObject)); return false; } - Common::Rect result = screenItem->getNowSeenRect(*plane); + result = screenItem->getNowSeenRect(*plane); + + return true; +} + +bool GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { + Common::Rect nsrect; + + bool found = getNowSeenRect(screenItemObject, nsrect); + + if (!found) + return false; if (g_sci->_features->usesAlternateSelectors()) { - writeSelectorValue(_segMan, screenItemObject, SELECTOR(left), result.left); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(top), result.top); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(right), result.right - 1); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(bottom), result.bottom - 1); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(left), nsrect.left); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(top), nsrect.top); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(right), nsrect.right - 1); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(bottom), nsrect.bottom - 1); } else { - writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), result.left); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1); - writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), nsrect.left); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), nsrect.top); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), nsrect.right - 1); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), nsrect.bottom - 1); } return true; } +int16 GfxFrameout::kernelObjectIntersect(const reg_t object1, const reg_t object2) const { + Common::Rect nsrect1, nsrect2; + + bool found1 = getNowSeenRect(object1, nsrect1); + bool found2 = getNowSeenRect(object2, nsrect2); + + // If both objects were not found, SSCI would probably return an + // intersection area of 1 since SSCI's invalid/uninitialized rect has an + // area of 1. We (mostly) ignore that corner case here. + if (!found1 && !found2) + warning("Both objects not found in kObjectIntersect"); + + // If one object was not found, SSCI would use its invalid/uninitialized + // rect for it, which is at coordinates 0x89ABCDEF. This can't intersect + // valid rects, so we return 0. + if (!found1 || !found2) + return 0; + + const Common::Rect intersection = nsrect1.findIntersectingRect(nsrect2); + + return intersection.width() * intersection.height(); +} + void GfxFrameout::remapMarkRedraw() { for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) { Plane *p = *it; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 26732d5c01..93dc35e632 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -66,6 +66,7 @@ public: #pragma mark Screen items private: void remapMarkRedraw(); + bool getNowSeenRect(const reg_t screenItemObject, Common::Rect &result) const; public: /** @@ -97,6 +98,7 @@ public: void kernelUpdateScreenItem(const reg_t object); void kernelDeleteScreenItem(const reg_t object); bool kernelSetNowSeen(const reg_t screenItemObject) const; + int16 kernelObjectIntersect(const reg_t object1, const reg_t object2) const; #pragma mark - #pragma mark Planes |