diff options
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 144 | ||||
-rw-r--r-- | engines/sci/gui/gui.cpp | 25 | ||||
-rw-r--r-- | engines/sci/gui/gui.h | 3 | ||||
-rw-r--r-- | engines/sci/gui/gui_gfx.cpp | 18 | ||||
-rw-r--r-- | engines/sci/gui/gui_gfx.h | 16 | ||||
-rw-r--r-- | engines/sci/gui/gui_picture.cpp | 4 | ||||
-rw-r--r-- | engines/sci/gui32/gui32.cpp | 136 | ||||
-rw-r--r-- | engines/sci/gui32/gui32.h | 3 |
8 files changed, 189 insertions, 160 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2d67efebdf..27073a42e5 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -646,148 +646,20 @@ reg_t kDirLoop(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -#define GASEOUS_VIEW_MASK_ACTIVE (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_IGNORE_ACTOR) -#define GASEOUS_VIEW_MASK_PASSIVE (_K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_IGNORE_ACTOR) - static Common::Rect nsrect_clip(EngineState *s, int y, Common::Rect retval, int priority); -static int collides_with(EngineState *s, Common::Rect area, reg_t other_obj, int use_nsrect, int view_mask, int argc, reg_t *argv) { - SegManager *segMan = s->_segMan; - int other_signal = GET_SEL32V(other_obj, signal); - int other_priority = GET_SEL32V(other_obj, priority); - int y = (int16)GET_SEL32V(other_obj, y); - Common::Rect other_area; - - if (use_nsrect) { - other_area = get_nsrect(s, other_obj, 0); - other_area = nsrect_clip(s, y, other_area, other_priority); - } else { - other_area.left = GET_SEL32V(other_obj, brLeft); - other_area.right = GET_SEL32V(other_obj, brRight); - other_area.top = GET_SEL32V(other_obj, brTop); - other_area.bottom = GET_SEL32V(other_obj, brBottom); - } - - if (other_area.right < 0 || other_area.bottom < 0 || area.right < 0 || area.bottom < 0) - return 0; // Out of scope - - if (other_area.left >= 320 || other_area.top >= 190 || area.right >= 320 || area.bottom >= 190) - return 0; // Out of scope - - debugC(2, kDebugLevelBresen, "OtherSignal=%04x, z=%04x obj=%04x:%04x\n", other_signal, (other_signal & view_mask), PRINT_REG(other_obj)); - - if ((other_signal & (view_mask)) == 0) { - // check whether the other object ignores actors - - debugC(2, kDebugLevelBresen, " against (%d,%d) to (%d,%d)\n", other_area.left, other_area.top, other_area.right, other_area.bottom); - - if (area.intersects(other_area)) - return 1; - /* CR (from :Bob Heitman:) Collision rects have Mac semantics, ((0,0),(1,1)) only - ** covers the coordinate (0,0) */ - } - - debugC(2, kDebugLevelBresen, " (no)\n"); - return 0; -} - reg_t kCanBeHere(EngineState *s, int argc, reg_t *argv) { - SegManager *segMan = s->_segMan; - reg_t obj = argv[0]; - reg_t cliplist_ref = (argc > 1) ? argv[1] : NULL_REG; - List *cliplist = NULL; - GfxPort *port = s->picture_port; - uint16 signal; - int retval; - - Common::Rect abs_zone; - rect_t zone; - uint16 edgehit; - uint16 illegal_bits; - - abs_zone.left = (int16)GET_SEL32V(obj, brLeft); - abs_zone.right = (int16)GET_SEL32V(obj, brRight); - abs_zone.top = (int16)GET_SEL32V(obj, brTop); - abs_zone.bottom = (int16)GET_SEL32V(obj, brBottom); - - zone = gfx_rect(abs_zone.left + port->zone.x, abs_zone.top + port->zone.y, abs_zone.width(), abs_zone.height()); - - signal = GET_SEL32V(obj, signal); - debugC(2, kDebugLevelBresen, "Checking collision: (%d,%d) to (%d,%d) ([%d..%d]x[%d..%d]), obj=%04x:%04x, sig=%04x, cliplist=%04x:%04x\n", - GFX_PRINT_RECT(zone), abs_zone.left, abs_zone.right, abs_zone.top, abs_zone.bottom, - PRINT_REG(obj), signal, PRINT_REG(cliplist_ref)); - - illegal_bits = GET_SEL32V(obj, illegalBits); - - retval = !(illegal_bits & (edgehit = gfxop_scan_bitmask(s->gfx_state, zone, GFX_MASK_CONTROL))); - - debugC(2, kDebugLevelBresen, "edgehit = %04x (illegalBits %04x)\n", edgehit, illegal_bits); - if (retval == 0) { - debugC(2, kDebugLevelBresen, " -> %04x\n", retval); - return NULL_REG; // Can't BeHere - } - - retval = 0; - - if ((illegal_bits & 0x8000) // If we are vulnerable to those views at all... - && s->dyn_views) { // ...check against all stop-updated dynviews - GfxDynView *widget = (GfxDynView *)s->dyn_views->_contents; - - debugC(2, kDebugLevelBresen, "Checking vs dynviews:\n"); - - while (widget) { - if (widget->_ID && (widget->signal & _K_VIEW_SIG_FLAG_STOPUPD) - && ((widget->_ID != obj.segment) || (widget->_subID != obj.offset)) - && s->_segMan->isObject(make_reg(widget->_ID, widget->_subID))) - if (collides_with(s, abs_zone, make_reg(widget->_ID, widget->_subID), 1, GASEOUS_VIEW_MASK_ACTIVE, argc, argv)) - return NULL_REG; - - widget = (GfxDynView *)widget->_next; - } - } - - if (signal & GASEOUS_VIEW_MASK_ACTIVE) { - retval = signal & GASEOUS_VIEW_MASK_ACTIVE; // CanBeHere- it's either being disposed, or it ignores actors anyway - debugC(2, kDebugLevelBresen, " -> %04x\n", retval); - return make_reg(0, retval); // CanBeHere - } - - if (cliplist_ref.segment) - cliplist = s->_segMan->lookupList(cliplist_ref); - - if (cliplist) { - Node *node = s->_segMan->lookupNode(cliplist->first); + reg_t curObject = argv[0]; + reg_t listReference = (argc > 1) ? argv[1] : NULL_REG; - retval = 0; // Assume that we Can'tBeHere... - - while (node) { // Check each object in the list against our bounding rectangle - reg_t other_obj = node->value; - debugC(2, kDebugLevelBresen, " comparing against %04x:%04x\n", PRINT_REG(other_obj)); - - if (!s->_segMan->isObject(other_obj)) { - warning("CanBeHere() cliplist contains non-object %04x:%04x", PRINT_REG(other_obj)); - } else if (other_obj != obj) { // Clipping against yourself is not recommended - - if (collides_with(s, abs_zone, other_obj, 0, GASEOUS_VIEW_MASK_PASSIVE, argc, argv)) { - debugC(2, kDebugLevelBresen, " -> %04x\n", retval); - return NULL_REG; - } - - } // if (other_obj != obj) - node = s->_segMan->lookupNode(node->succ); // move on - } - } - - if (!retval) - retval = 1; - debugC(2, kDebugLevelBresen, " -> %04x\n", retval); - - return make_reg(0, retval); -} // CanBeHere + if (s->_gui->canBeHere(curObject, listReference)) + return make_reg(0, 1); + return NULL_REG; +} +// kCantBeHere does the same thing as kCanBeHere, except that +// it returns the opposite result. reg_t kCantBeHere(EngineState *s, int argc, reg_t *argv) { - // kCantBeHere does the same thing as kCanBeHere, except that - // it returns the opposite result. reg_t result = kCanBeHere(s, argc, argv); result.offset = !result.offset; return result; diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index 5ef2cf9575..45145c5958 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -375,9 +375,9 @@ void SciGui::paletteAnimate(int fromColor, int toColor, int speed) { _palette->animate(fromColor, toColor, speed); } -int16 SciGui::onControl(byte screenMask, Common::Rect rect) { +uint16 SciGui::onControl(byte screenMask, Common::Rect rect) { GuiPort *oldPort = _gfx->SetPort((GuiPort *)_windowMgr->_picWind); - int16 result; + uint16 result; result = _gfx->onControl(screenMask, rect); _gfx->SetPort(oldPort); @@ -471,6 +471,27 @@ void SciGui::setNowSeen(reg_t objectReference) { _gfx->SetNowSeen(objectReference); } +bool SciGui::canBeHere(reg_t curObject, reg_t listReference) { + SegManager *segMan = _s->_segMan; + GuiPort *oldPort = _gfx->SetPort((GuiPort *)_windowMgr->_picWind); + Common::Rect checkRect; + uint16 signal, controlMask; + bool result; + + checkRect.left = GET_SEL32V(curObject, brLeft); + checkRect.top = GET_SEL32V(curObject, brTop); + checkRect.right = GET_SEL32V(curObject, brRight); + checkRect.bottom = GET_SEL32V(curObject, brBottom); + signal = GET_SEL32V(curObject, signal); + controlMask = GET_SEL32V(curObject, illegalBits); + result = (_gfx->onControl(SCI_SCREEN_MASK_CONTROL, checkRect) & controlMask) ? false : true; + if ((!result) && (signal & (SCI_ANIMATE_SIGNAL_IGNOREACTOR | SCI_ANIMATE_SIGNAL_REMOVEVIEW))) { + result = true; + } + _gfx->SetPort(oldPort); + return result; +} + void SciGui::hideCursor() { _cursor->hide(); } diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h index caeda61d6c..47a038a8b3 100644 --- a/engines/sci/gui/gui.h +++ b/engines/sci/gui/gui.h @@ -82,11 +82,12 @@ public: virtual void paletteSetIntensity(int fromColor, int toColor, int intensity, bool setPalette); virtual void paletteAnimate(int fromColor, int toColor, int speed); - virtual int16 onControl(byte screenMask, Common::Rect rect); + virtual uint16 onControl(byte screenMask, Common::Rect rect); virtual void animate(reg_t listReference, bool cycle, int argc, reg_t *argv); virtual void addToPicList(reg_t listReference, int argc, reg_t *argv); virtual void addToPicView(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); virtual void setNowSeen(reg_t objectReference); + virtual bool canBeHere(reg_t curObject, reg_t listReference); virtual void hideCursor(); virtual void showCursor(); diff --git a/engines/sci/gui/gui_gfx.cpp b/engines/sci/gui/gui_gfx.cpp index b296668acd..6f1c03a73e 100644 --- a/engines/sci/gui/gui_gfx.cpp +++ b/engines/sci/gui/gui_gfx.cpp @@ -1040,10 +1040,10 @@ void SciGuiGfx::drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo } } -int16 SciGuiGfx::onControl(uint16 screenMask, Common::Rect rect) { +uint16 SciGuiGfx::onControl(uint16 screenMask, Common::Rect rect) { Common::Rect outRect(rect.left, rect.top, rect.right, rect.bottom); int16 x, y; - int16 result = 0; + uint16 result = 0; outRect.clip(_curPort->rect); if (outRect.isEmpty()) // nothing to control @@ -1123,20 +1123,6 @@ void SciGuiGfx::AnimateDisposeLastCast() { //_lastCast->DeleteList(); } -enum { - SCI_ANIMATE_SIGNAL_STOPUPDATE = 0x0001, - SCI_ANIMATE_SIGNAL_VIEWUPDATED = 0x0002, - SCI_ANIMATE_SIGNAL_NOUPDATE = 0x0004, - SCI_ANIMATE_SIGNAL_HIDDEN = 0x0008, - SCI_ANIMATE_SIGNAL_FIXEDPRIORITY = 0x0010, - SCI_ANIMATE_SIGNAL_ALWAYSUPDATE = 0x0020, - SCI_ANIMATE_SIGNAL_FORCEUPDATE = 0x0040, - SCI_ANIMATE_SIGNAL_REMOVEVIEW = 0x0080, - SCI_ANIMATE_SIGNAL_FROZEN = 0x0100, - SCI_ANIMATE_SIGNAL_IGNOREACTOR = 0x4000, - SCI_ANIMATE_SIGNAL_DISPOSEME = 0x8000 -}; - void SciGuiGfx::AnimateInvoke(List *list, int argc, reg_t *argv) { SegManager *segMan = _s->_segMan; reg_t curAddress = list->first; diff --git a/engines/sci/gui/gui_gfx.h b/engines/sci/gui/gui_gfx.h index 4e9f0b2288..51d43439bf 100644 --- a/engines/sci/gui/gui_gfx.h +++ b/engines/sci/gui/gui_gfx.h @@ -34,6 +34,20 @@ namespace Sci { #define SCI_PATTERN_CODE_USE_TEXTURE 0x20 #define SCI_PATTERN_CODE_PENSIZE 0x07 +enum { + SCI_ANIMATE_SIGNAL_STOPUPDATE = 0x0001, + SCI_ANIMATE_SIGNAL_VIEWUPDATED = 0x0002, + SCI_ANIMATE_SIGNAL_NOUPDATE = 0x0004, + SCI_ANIMATE_SIGNAL_HIDDEN = 0x0008, + SCI_ANIMATE_SIGNAL_FIXEDPRIORITY = 0x0010, + SCI_ANIMATE_SIGNAL_ALWAYSUPDATE = 0x0020, + SCI_ANIMATE_SIGNAL_FORCEUPDATE = 0x0040, + SCI_ANIMATE_SIGNAL_REMOVEVIEW = 0x0080, + SCI_ANIMATE_SIGNAL_FROZEN = 0x0100, + SCI_ANIMATE_SIGNAL_IGNOREACTOR = 0x4000, + SCI_ANIMATE_SIGNAL_DISPOSEME = 0x8000 +}; + class SciGuiScreen; class SciGuiPalette; class SciGuiFont; @@ -99,7 +113,7 @@ public: void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId); void drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo); - int16 onControl(uint16 screenMask, Common::Rect rect); + uint16 onControl(uint16 screenMask, Common::Rect rect); void PriorityBandsInit(int16 top, int16 bottom); void PriorityBandsInit(byte *data); diff --git a/engines/sci/gui/gui_picture.cpp b/engines/sci/gui/gui_picture.cpp index 15387d05d9..4a093be42e 100644 --- a/engines/sci/gui/gui_picture.cpp +++ b/engines/sci/gui/gui_picture.cpp @@ -336,7 +336,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { break; case PIC_OP_SET_PRIORITY: - pic_priority = data[curPos++]; + pic_priority = data[curPos++] & 0x0F; if (isEGA) { pic_priority = EGApriority[pic_priority]; } @@ -346,7 +346,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { break; case PIC_OP_SET_CONTROL: - pic_control = data[curPos++]; + pic_control = data[curPos++] & 0x0F; break; case PIC_OP_DISABLE_CONTROL: pic_control = 255; diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index c93c452b92..05627fa79c 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -739,7 +739,7 @@ void SciGui32::paletteAnimate(int fromColor, int toColor, int speed) { //warning("STUB"); } -int16 SciGui32::onControl(byte screenMask, Common::Rect rect) { +uint16 SciGui32::onControl(byte screenMask, Common::Rect rect) { gfx_map_mask_t map = (gfx_map_mask_t)screenMask; rect_t gfxrect = gfx_rect(rect.left, rect.top + 10, rect.width(), rect.height()); @@ -2010,6 +2010,140 @@ void SciGui32::setNowSeen(reg_t objectReference) { _k_set_now_seen(objectReference); } +static int collides_with(EngineState *s, Common::Rect area, reg_t other_obj, int use_nsrect, int view_mask) { + SegManager *segMan = s->_segMan; + int other_signal = GET_SEL32V(other_obj, signal); + int other_priority = GET_SEL32V(other_obj, priority); + int y = (int16)GET_SEL32V(other_obj, y); + Common::Rect other_area; + + if (use_nsrect) { + other_area = get_nsrect(s, other_obj, 0); + other_area = nsrect_clip(s, y, other_area, other_priority); + } else { + other_area.left = GET_SEL32V(other_obj, brLeft); + other_area.right = GET_SEL32V(other_obj, brRight); + other_area.top = GET_SEL32V(other_obj, brTop); + other_area.bottom = GET_SEL32V(other_obj, brBottom); + } + + if (other_area.right < 0 || other_area.bottom < 0 || area.right < 0 || area.bottom < 0) + return 0; // Out of scope + + if (other_area.left >= 320 || other_area.top >= 190 || area.right >= 320 || area.bottom >= 190) + return 0; // Out of scope + + debugC(2, kDebugLevelBresen, "OtherSignal=%04x, z=%04x obj=%04x:%04x\n", other_signal, (other_signal & view_mask), PRINT_REG(other_obj)); + + if ((other_signal & (view_mask)) == 0) { + // check whether the other object ignores actors + + debugC(2, kDebugLevelBresen, " against (%d,%d) to (%d,%d)\n", other_area.left, other_area.top, other_area.right, other_area.bottom); + + if (area.intersects(other_area)) + return 1; + /* CR (from :Bob Heitman:) Collision rects have Mac semantics, ((0,0),(1,1)) only + ** covers the coordinate (0,0) */ + } + + debugC(2, kDebugLevelBresen, " (no)\n"); + return 0; +} + +#define GASEOUS_VIEW_MASK_ACTIVE (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_IGNORE_ACTOR) +#define GASEOUS_VIEW_MASK_PASSIVE (_K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_IGNORE_ACTOR) + +bool SciGui32::canBeHere(reg_t curObject, reg_t listReference) { + SegManager *segMan = s->_segMan; + List *cliplist = NULL; + GfxPort *port = s->picture_port; + uint16 signal; + bool retval; + + Common::Rect abs_zone; + rect_t zone; + uint16 edgehit; + uint16 illegal_bits; + + abs_zone.left = (int16)GET_SEL32V(curObject, brLeft); + abs_zone.right = (int16)GET_SEL32V(curObject, brRight); + abs_zone.top = (int16)GET_SEL32V(curObject, brTop); + abs_zone.bottom = (int16)GET_SEL32V(curObject, brBottom); + + zone = gfx_rect(abs_zone.left + port->zone.x, abs_zone.top + port->zone.y, abs_zone.width(), abs_zone.height()); + + signal = GET_SEL32V(curObject, signal); + debugC(2, kDebugLevelBresen, "Checking collision: (%d,%d) to (%d,%d) ([%d..%d]x[%d..%d]), obj=%04x:%04x, sig=%04x, cliplist=%04x:%04x\n", + GFX_PRINT_RECT(zone), abs_zone.left, abs_zone.right, abs_zone.top, abs_zone.bottom, + PRINT_REG(curObject), signal, PRINT_REG(listReference)); + + illegal_bits = GET_SEL32V(curObject, illegalBits); + + retval = !(illegal_bits & (edgehit = gfxop_scan_bitmask(s->gfx_state, zone, GFX_MASK_CONTROL))); + + debugC(2, kDebugLevelBresen, "edgehit = %04x (illegalBits %04x)\n", edgehit, illegal_bits); + if (!retval) { + debugC(2, kDebugLevelBresen, " -> %04x\n", retval); + return false; // Can't BeHere + } + + retval = false; + + if ((illegal_bits & 0x8000) // If we are vulnerable to those views at all... + && s->dyn_views) { // ...check against all stop-updated dynviews + GfxDynView *widget = (GfxDynView *)s->dyn_views->_contents; + + debugC(2, kDebugLevelBresen, "Checking vs dynviews:\n"); + + while (widget) { + if (widget->_ID && (widget->signal & _K_VIEW_SIG_FLAG_STOPUPD) + && ((widget->_ID != curObject.segment) || (widget->_subID != curObject.offset)) + && s->_segMan->isObject(make_reg(widget->_ID, widget->_subID))) + if (collides_with(s, abs_zone, make_reg(widget->_ID, widget->_subID), 1, GASEOUS_VIEW_MASK_ACTIVE)) + return false; + + widget = (GfxDynView *)widget->_next; + } + } + + if (signal & GASEOUS_VIEW_MASK_ACTIVE) { + retval = (signal & GASEOUS_VIEW_MASK_ACTIVE) ? true : false; // CanBeHere- it's either being disposed, or it ignores actors anyway + debugC(2, kDebugLevelBresen, " -> %04x\n", retval); + return retval; // CanBeHere + } + + if (listReference.segment) + cliplist = s->_segMan->lookupList(listReference); + + if (cliplist) { + Node *node = s->_segMan->lookupNode(cliplist->first); + + retval = false; // Assume that we Can'tBeHere... + + while (node) { // Check each object in the list against our bounding rectangle + reg_t other_obj = node->value; + debugC(2, kDebugLevelBresen, " comparing against %04x:%04x\n", PRINT_REG(other_obj)); + + if (!s->_segMan->isObject(other_obj)) { + warning("CanBeHere() cliplist contains non-object %04x:%04x", PRINT_REG(other_obj)); + } else if (other_obj != curObject) { // Clipping against yourself is not recommended + + if (collides_with(s, abs_zone, other_obj, 0, GASEOUS_VIEW_MASK_PASSIVE)) { + debugC(2, kDebugLevelBresen, " -> %04x\n", retval); + return false; + } + + } // if (other_obj != obj) + node = s->_segMan->lookupNode(node->succ); // move on + } + } + + if (!retval) + retval = true; + debugC(2, kDebugLevelBresen, " -> %04x\n", retval); + return retval; +} + void SciGui32::hideCursor() { CursorMan.showMouse(false); } diff --git a/engines/sci/gui32/gui32.h b/engines/sci/gui32/gui32.h index 7a9b4d2013..67e3de9024 100644 --- a/engines/sci/gui32/gui32.h +++ b/engines/sci/gui32/gui32.h @@ -74,11 +74,12 @@ public: void paletteSetIntensity(int fromColor, int toColor, int intensity, bool setPalette); void paletteAnimate(int fromColor, int toColor, int speed); - int16 onControl(byte screenMask, Common::Rect rect); + uint16 onControl(byte screenMask, Common::Rect rect); void animate(reg_t castListReference, bool cycle, int argc, reg_t *argv); void addToPicList(reg_t listReference, int argc, reg_t *argv); void addToPicView(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); void setNowSeen(reg_t objectReference); + bool canBeHere(reg_t curObject, reg_t listReference); void hideCursor(); void showCursor(); |