diff options
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 1188 | ||||
-rw-r--r-- | engines/sci/gui/gui.cpp | 16 | ||||
-rw-r--r-- | engines/sci/gui/gui.h | 5 | ||||
-rw-r--r-- | engines/sci/gui/gui_gfx.cpp | 4 | ||||
-rw-r--r-- | engines/sci/gui/gui_view.cpp | 1 | ||||
-rw-r--r-- | engines/sci/gui32/gui32.cpp | 1248 | ||||
-rw-r--r-- | engines/sci/gui32/gui32.h | 21 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 1 |
8 files changed, 1315 insertions, 1169 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index edf84ea317..4ef3c79940 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1078,25 +1078,8 @@ Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip) { return retval; } -static void _k_set_now_seen(EngineState *s, reg_t object) { - SegManager *segMan = s->segMan; - Common::Rect absrect = get_nsrect(s, object, 0); - - if (lookup_selector(s->segMan, object, s->_kernel->_selectorCache.nsTop, NULL, NULL) != kSelectorVariable) { - return; - } // This isn't fatal - - PUT_SEL32V(object, nsLeft, absrect.left); - PUT_SEL32V(object, nsRight, absrect.right); - PUT_SEL32V(object, nsTop, absrect.top); - PUT_SEL32V(object, nsBottom, absrect.bottom); -} - reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) { - reg_t object = argv[0]; - - _k_set_now_seen(s, object); - + s->gui->setNowSeen(argv[0]); return s->r_acc; } @@ -1556,91 +1539,6 @@ static void _k_draw_control(EngineState *s, reg_t obj, bool inverse) { } } - -static void draw_rect_to_control_map(EngineState *s, Common::Rect abs_zone) { - GfxBox *box; - gfx_color_t color; - - gfxop_set_color(s->gfx_state, &color, -1, -1, -1, -1, -1, 0xf); - - debugC(2, kDebugLevelGraphics, " adding control block (%d,%d)to(%d,%d)\n", abs_zone.left, abs_zone.top, abs_zone.right, abs_zone.bottom); - - box = gfxw_new_box(s->gfx_state, gfx_rect(abs_zone.left, abs_zone.top, abs_zone.width(), - abs_zone.height()), color, color, GFX_BOX_SHADE_FLAT); - - assert_primary_widget_lists(s); - - ADD_TO_CURRENT_PICTURE_PORT(box); -} - -static void draw_obj_to_control_map(EngineState *s, GfxDynView *view) { - reg_t obj = make_reg(view->_ID, view->_subID); - - if (!s->segMan->isObject(obj)) - warning("View %d does not contain valid object reference %04x:%04x", view->_ID, PRINT_REG(obj)); - - reg_t* sp = view->signalp.getPointer(s->segMan); - if (!(sp && (sp->offset & _K_VIEW_SIG_FLAG_IGNORE_ACTOR))) { - Common::Rect abs_zone = get_nsrect(s, make_reg(view->_ID, view->_subID), 1); - draw_rect_to_control_map(s, abs_zone); - } -} - -static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { - SegManager *segMan = s->segMan; - GfxDynView *widget = (GfxDynView *) list->_contents; - - while (widget) { - reg_t obj = make_reg(widget->_ID, widget->_subID); - - /* - * this fixes a few problems, but doesn't match SSCI's logic. - * The semantics of the private flag need to be verified before this can be uncommented. - * Fixes bug #326 (CB1, ego falls down stairs) - * if ((widget->signal & (_K_VIEW_SIG_FLAG_PRIVATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == _K_VIEW_SIG_FLAG_PRIVATE) { - */ - if ((widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == 0) { - int has_nsrect = lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL) == kSelectorVariable; - - if (has_nsrect) { - int temp; - - temp = GET_SEL32V(obj, nsLeft); - PUT_SEL32V(obj, lsLeft, temp); - - temp = GET_SEL32V(obj, nsRight); - PUT_SEL32V(obj, lsRight, temp); - - temp = GET_SEL32V(obj, nsTop); - PUT_SEL32V(obj, lsTop, temp); - - temp = GET_SEL32V(obj, nsBottom); - PUT_SEL32V(obj, lsBottom, temp); -#ifdef DEBUG_LSRECT - fprintf(stderr, "lsRected %04x:%04x\n", PRINT_REG(obj)); -#endif - } -#ifdef DEBUG_LSRECT - else - fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL)); -#endif - - if (widget->signal & _K_VIEW_SIG_FLAG_HIDDEN) - widget->signal |= _K_VIEW_SIG_FLAG_REMOVE; - } -#ifdef DEBUG_LSRECT - fprintf(stderr, "obj %04x:%04x has pflags %x\n", PRINT_REG(obj), (widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE))); -#endif - - reg_t* sp = widget->signalp.getPointer(s->segMan); - if (sp) { - *sp = make_reg(0, widget->signal & 0xffff); /* Write back signal */ - } - - widget = (GfxDynView *)widget->_next; - } -} - void _k_view_list_mark_free(EngineState *s, reg_t off) { if (s->dyn_views) { @@ -1657,554 +1555,30 @@ void _k_view_list_mark_free(EngineState *s, reg_t off) { } } -static bool _k_animate_ran = false; // FIXME: Avoid non-const global vars - -int _k_view_list_dispose_loop(EngineState *s, List *list, GfxDynView *widget, int argc, reg_t *argv) { -// disposes all list members flagged for disposal -// returns non-zero IFF views were dropped - int signal; - int dropped = 0; - SegManager *segMan = s->segMan; - - _k_animate_ran = false; - - if (widget) { - int retval; - // Recurse: - retval = _k_view_list_dispose_loop(s, list, (GfxDynView *)widget->_next, argc, argv); - - if (retval == -1) // Bail out on annihilation, rely on re-start from Animate() - return -1; - - if (GFXW_IS_DYN_VIEW(widget) && (widget->_ID != GFXW_NO_ID)) { - signal = widget->signalp.getPointer(segMan)->offset; - if (signal & _K_VIEW_SIG_FLAG_DISPOSE_ME) { - reg_t obj = make_reg(widget->_ID, widget->_subID); - reg_t under_bits = NULL_REG; - - if (!s->segMan->isObject(obj)) { - error("Non-object %04x:%04x present in view list during delete time", PRINT_REG(obj)); - obj = NULL_REG; - } else { - reg_t *ubp = widget->under_bitsp.getPointer(segMan); - if (ubp) { // Is there a bg picture left to clean? - reg_t mem_handle = *ubp; - - if (mem_handle.segment) { - if (!kfree(s->segMan, mem_handle)) { - *ubp = make_reg(0, widget->under_bits = 0); - } else { - warning("Treating viewobj %04x:%04x as no longer present", PRINT_REG(obj)); - obj = NULL_REG; - } - } - } - } - if (segMan->isObject(obj)) { - if (invoke_selector(INV_SEL(obj, delete_, kContinueOnInvalidSelector), 0)) - warning("Object at %04x:%04x requested deletion, but does not have a delete funcselector", PRINT_REG(obj)); - if (_k_animate_ran) { - warning("Object at %04x:%04x invoked kAnimate() during deletion", PRINT_REG(obj)); - return dropped; - } - - reg_t *ubp = widget->under_bitsp.getPointer(segMan); - if (ubp) - under_bits = *ubp; - - if (under_bits.segment) { - *ubp = make_reg(0, 0); - graph_restore_box(s, under_bits); - } - - debugC(2, kDebugLevelGraphics, "Freeing %04x:%04x with signal=%04x\n", PRINT_REG(obj), signal); - - if (!(signal & _K_VIEW_SIG_FLAG_HIDDEN)) { - debugC(2, kDebugLevelGraphics, "Adding view at %04x:%04x to background\n", PRINT_REG(obj)); - if (!(gfxw_remove_id(widget->_parent, widget->_ID, widget->_subID) == widget)) { - error("Attempt to remove view with ID %x:%x from list failed", widget->_ID, widget->_subID); - } - - s->drop_views->add((GfxContainer *)s->drop_views, gfxw_picviewize_dynview(widget)); - - draw_obj_to_control_map(s, widget); - widget->draw_bounds.y += s->dyn_views->_bounds.y - widget->_parent->_bounds.y; - widget->draw_bounds.x += s->dyn_views->_bounds.x - widget->_parent->_bounds.x; - dropped = 1; - } else { - debugC(2, kDebugLevelGraphics, "Deleting view at %04x:%04x\n", PRINT_REG(obj)); - widget->_flags |= GFXW_FLAG_VISIBLE; - gfxw_annihilate(widget); - return -1; // restart: Done in Animate() - } - } - } - } - - } - - return dropped; -} - -enum { - _K_MAKE_VIEW_LIST_CYCLE = 1, - _K_MAKE_VIEW_LIST_CALC_PRIORITY = 2, - _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP = 4 -}; - -static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, int nr, int argc, reg_t *argv) { - SegManager *segMan = s->segMan; - short oldloop, oldcel; - int cel, loop, view_nr = (int16)GET_SEL32V(obj, view); - int palette; - int signal; - reg_t under_bits; - Common::Point pos; - int z; - GfxDynView *widget; - - debugC(2, kDebugLevelGraphics, " - Adding %04x:%04x\n", PRINT_REG(obj)); - - obj = obj; - - pos.x = (int16)GET_SEL32V(obj, x); - pos.y = (int16)GET_SEL32V(obj, y); - - pos.y++; // magic: Sierra appears to do something like this - - z = (int16)GET_SEL32V(obj, z); - - // !-- nsRect used to be checked here! - loop = oldloop = sign_extend_byte(GET_SEL32V(obj, loop)); - cel = oldcel = sign_extend_byte(GET_SEL32V(obj, cel)); - - if (s->_kernel->_selectorCache.palette) - palette = GET_SEL32V(obj, palette); - else - palette = 0; - - // Clip loop and cel, write back if neccessary - gfxop_check_cel(s->gfx_state, view_nr, &loop, &cel); - - if (loop != oldloop) - loop = 0; - if (cel != oldcel) - cel = 0; - - if (oldloop != loop) - PUT_SEL32V(obj, loop, loop); - - if (oldcel != cel) { - PUT_SEL32V(obj, cel, cel); - } - - ObjVarRef under_bitsp; - if (lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.underBits, &(under_bitsp), NULL) != kSelectorVariable) { - under_bitsp.obj = NULL_REG; - under_bits = NULL_REG; - debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no underBits\n", PRINT_REG(obj)); - } else - under_bits = *under_bitsp.getPointer(s->segMan); - - ObjVarRef signalp; - if (lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.signal, &(signalp), NULL) != kSelectorVariable) { - signalp.obj = NULL_REG; - signal = 0; - debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no signal selector\n", PRINT_REG(obj)); - } else { - signal = signalp.getPointer(s->segMan)->offset; - debugC(2, kDebugLevelGraphics, " with signal = %04x\n", signal); - } - - widget = gfxw_new_dyn_view(s->gfx_state, pos, z, view_nr, loop, cel, palette, -1, -1, ALIGN_CENTER, ALIGN_BOTTOM, nr); - - if (widget) { - widget = (GfxDynView *) gfxw_set_id(widget, obj.segment, obj.offset); - widget = gfxw_dyn_view_set_params(widget, under_bits.segment, under_bitsp, signal, signalp); - widget->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; // Only works the first time 'round' - - return widget; - } else { - warning("Could not generate dynview widget for %d/%d/%d", view_nr, loop, cel); - return NULL; - } -} - -static void _k_make_view_list(EngineState *s, GfxList **widget_list, List *list, int options, int argc, reg_t *argv) { -/* Creates a view_list from a node list in heap space. Returns the list, stores the -** number of list entries in *list_nr. Calls doit for each entry if cycle is set. -** argc, argv should be the same as in the calling kernel function. -*/ - SegManager *segMan = s->segMan; - Node *node; - int sequence_nr = 0; - GfxDynView *widget; - - if (!*widget_list) { - error("make_view_list with widget_list == ()"); - }; - - assert_primary_widget_lists(s); - // In case one of the views' doit() does a DrawPic... - // Yes, this _does_ happen! - - if (!list) { // list sanity check - error("Attempt to make list from non-list"); - } - - reg_t next_node = list->first; - node = lookup_node(s, next_node); - while (node) { - reg_t obj = node->value; // The object we're using - GfxDynView *tempWidget; - - if (options & _K_MAKE_VIEW_LIST_CYCLE) { - unsigned int signal = GET_SEL32V(obj, signal); - - if (!(signal & _K_VIEW_SIG_FLAG_FROZEN)) { - - debugC(2, kDebugLevelGraphics, " invoking %04x:%04x::doit()\n", PRINT_REG(obj)); - invoke_selector(INV_SEL(obj, doit, kContinueOnInvalidSelector), 0); // Call obj::doit() if neccessary - - - // Lookup node again, since the NodeTable it was in may - // have been re-allocated. - node = lookup_node(s, next_node); - } - } - - next_node = node->succ; // In case the cast list was changed - - if (list->first.segment == 0 && list->first.offset == 0) // The cast list was completely emptied! - break; - - tempWidget = _k_make_dynview_obj(s, obj, options, sequence_nr--, argc, argv); - if (tempWidget) - (*widget_list)->add((GfxContainer *)(*widget_list), tempWidget); - - node = lookup_node(s, next_node); // Next node - } - - widget = (GfxDynView *)(*widget_list)->_contents; - - while (widget) { // Read back widget values - reg_t *sp = widget->signalp.getPointer(s->segMan); - if (sp) - widget->signal = sp->offset; - - widget = (GfxDynView *)widget->_next; - } -} - -static void _k_prepare_view_list(EngineState *s, GfxList *list, int options) { - SegManager *segMan = s->segMan; - GfxDynView *view = (GfxDynView *) list->_contents; - while (view) { - reg_t obj = make_reg(view->_ID, view->_subID); - int priority, _priority; - int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL) == kSelectorVariable; - int oldsignal = view->signal; - - _k_set_now_seen(s, obj); - _priority = /*GET_SELECTOR(obj, y); */((view->_pos.y)); - _priority = _find_view_priority(s, _priority - 1); - - if (options & _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP) { // Picview - priority = (int16)GET_SEL32V(obj, priority); - if (priority < 0) - priority = _priority; // Always for picviews - } else { // Dynview - if (has_nsrect && !(view->signal & _K_VIEW_SIG_FLAG_FIX_PRI_ON)) { // Calculate priority - if (options & _K_MAKE_VIEW_LIST_CALC_PRIORITY) - PUT_SEL32V(obj, priority, _priority); - - priority = _priority; - - } else // DON'T calculate the priority - priority = (int16)GET_SEL32V(obj, priority); - } - - view->_color.priority = priority; - - if (priority > -1) - view->_color.mask |= GFX_MASK_PRIORITY; - else - view->_color.mask &= ~GFX_MASK_PRIORITY; - - // CR (from :Bob Heitman:) stopupdated views (like pic views) have - // their clipped nsRect drawn to the control map - if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { - view->signal |= _K_VIEW_SIG_FLAG_STOPUPD; - debugC(2, kDebugLevelGraphics, "Setting magic STOP_UPD for %04x:%04x\n", PRINT_REG(obj)); - } - - if ((options & _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP)) - draw_obj_to_control_map(s, view); - - // Extreme Pattern Matching ugliness ahead... - if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { - if (((view->signal & (_K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_FORCE_UPDATE))) // 9.1.1.1 - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) == _K_VIEW_SIG_FLAG_HIDDEN) - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) == _K_VIEW_SIG_FLAG_REMOVE) // 9.1.1.2 - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) // 9.1.1.3 - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE))) { // 9.1.1.4 - s->pic_not_valid++; - view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; - } - - else if (((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == 0) - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) - || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == _K_VIEW_SIG_FLAG_HIDDEN)) { - view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; - } - } else { - if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { - s->pic_not_valid++; - view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; - } else { // if not STOP_UPDATE - if (view->signal & _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) - s->pic_not_valid++; - view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; - } - } - - debugC(2, kDebugLevelGraphics, " dv[%04x:%04x]: signal %04x -> %04x\n", PRINT_REG(obj), oldsignal, view->signal); - - // Never happens -/* if (view->signal & 0) { - view->signal &= ~_K_VIEW_SIG_FLAG_STOPUPD; - fprintf(stderr, "Unsetting magic StopUpd for view %04x:%04x\n", PRINT_REG(obj)); - } */ - - view = (GfxDynView *)view->_next; - } -} - -static void _k_update_signals_in_view_list(GfxList *old_list, GfxList *new_list) { - // O(n^2)... a bit painful, but much faster than the redraws it helps prevent - GfxDynView *old_widget = (GfxDynView *)old_list->_contents; - - /* Traverses all old widgets, updates them with signals from the new widgets. - ** This is done to avoid evil hacks in widget.c; widgets with unique IDs are - ** replaced there iff they are NOT equal_to a new widget with the same ID. - ** If they were replaced every time, we'd be doing far too many redraws. - */ - - while (old_widget) { - GfxDynView *new_widget = (GfxDynView *) new_list->_contents; - - while (new_widget - && (new_widget->_ID != old_widget->_ID - || new_widget->_subID != old_widget->_subID)) - new_widget = (GfxDynView *)new_widget->_next; - - if (new_widget) { - int carry = old_widget->signal & _K_VIEW_SIG_FLAG_STOPUPD; - // Transfer 'stopupd' flag - - if ((new_widget->_pos.x != old_widget->_pos.x) - || (new_widget->_pos.y != old_widget->_pos.y) - // No idea why this is supposed to be bad -/* || (new_widget->z != old_widget->z) - || (new_widget->view != old_widget->view) - || (new_widget->loop != old_widget->loop) - || (new_widget->cel != old_widget->cel) - */) - carry = 0; - - old_widget->signal = new_widget->signal |= carry; - } - - old_widget = (GfxDynView *)old_widget->_next; - } -} - -static void _k_view_list_kryptonize(GfxWidget *v) { - if (v) { - v->_flags &= ~GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; - _k_view_list_kryptonize(v->_next); - } -} - -static void _k_raise_topmost_in_view_list(EngineState *s, GfxList *list, GfxDynView *view) { - if (view) { - GfxDynView *next = (GfxDynView *)view->_next; - - // step 11 - if ((view->signal & (_K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == 0) { - debugC(2, kDebugLevelGraphics, "Forcing precedence 2 at [%04x:%04x] with %04x\n", PRINT_REG(make_reg(view->_ID, view->_subID)), view->signal); - view->force_precedence = 2; - - if ((view->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_HIDDEN)) == _K_VIEW_SIG_FLAG_REMOVE) { - view->signal &= ~_K_VIEW_SIG_FLAG_REMOVE; - } - } - - gfxw_remove_widget_from_container(view->_parent, view); - - if (view->signal & _K_VIEW_SIG_FLAG_HIDDEN) - gfxw_hide_widget(view); - else - gfxw_show_widget(view); - - list->add((GfxContainer *)list, view); - - _k_raise_topmost_in_view_list(s, list, next); - } -} - -static void _k_redraw_view_list(EngineState *s, GfxList *list) { - GfxDynView *view = (GfxDynView *) list->_contents; - while (view) { - - debugC(2, kDebugLevelGraphics, " dv[%04x:%04x]: signal %04x\n", PRINT_REG(make_reg(view->_ID, view->_subID)), view->signal); - - // step 1 of subalgorithm - if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { - if (view->signal & _K_VIEW_SIG_FLAG_FORCE_UPDATE) - view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; - - if (view->signal & _K_VIEW_SIG_FLAG_UPDATED) - view->signal &= ~(_K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE); - } else { // NO_UPD is not set - if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { - view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; - view->signal |= _K_VIEW_SIG_FLAG_NO_UPDATE; - } - } - - debugC(2, kDebugLevelGraphics, " at substep 6: signal %04x\n", view->signal); - - if (view->signal & _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) - view->signal &= ~(_K_VIEW_SIG_FLAG_STOP_UPDATE | _K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_FORCE_UPDATE); - - debugC(2, kDebugLevelGraphics, " at substep 11/14: signal %04x\n", view->signal); - - if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { - if (view->signal & _K_VIEW_SIG_FLAG_HIDDEN) - view->signal |= _K_VIEW_SIG_FLAG_REMOVE; - else - view->signal &= ~_K_VIEW_SIG_FLAG_REMOVE; - } else if (!(view->signal & _K_VIEW_SIG_FLAG_HIDDEN)) - view->force_precedence = 1; - - debugC(2, kDebugLevelGraphics, " -> signal %04x\n", view->signal); - - view = (GfxDynView *)view->_next; - } -} - -// Flags for _k_draw_view_list -// Whether some magic with the base object's "signal" selector should be done: -#define _K_DRAW_VIEW_LIST_USE_SIGNAL 1 -// This flag draws all views with the "DISPOSE_ME" flag set: -#define _K_DRAW_VIEW_LIST_DISPOSEABLE 2 -// Use this one to draw all views with "DISPOSE_ME" NOT set: -#define _K_DRAW_VIEW_LIST_NONDISPOSEABLE 4 -// Draw as picviews -#define _K_DRAW_VIEW_LIST_PICVIEW 8 - -void _k_draw_view_list(EngineState *s, GfxList *list, int flags) { - // Draws list_nr members of list to s->pic. - GfxDynView *widget = (GfxDynView *) list->_contents; - - if ((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) - return; // Return if the pictures are meant for a different port - - while (widget) { - if (flags & _K_DRAW_VIEW_LIST_PICVIEW) - widget = gfxw_picviewize_dynview(widget); - - if (GFXW_IS_DYN_VIEW(widget) && widget->_ID) { - uint16 signal = (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) ? widget->signalp.getPointer(s->segMan)->offset : 0; - - if (signal & _K_VIEW_SIG_FLAG_HIDDEN) - gfxw_hide_widget(widget); - else - gfxw_show_widget(widget); - - if (!(flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) - || ((flags & _K_DRAW_VIEW_LIST_DISPOSEABLE) && (signal & _K_VIEW_SIG_FLAG_DISPOSE_ME)) - || ((flags & _K_DRAW_VIEW_LIST_NONDISPOSEABLE) && !(signal & _K_VIEW_SIG_FLAG_DISPOSE_ME))) { - - if (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) { - signal &= ~(_K_VIEW_SIG_FLAG_STOP_UPDATE | _K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_FORCE_UPDATE); - // Clear all of those flags - - if (signal & _K_VIEW_SIG_FLAG_HIDDEN) - gfxw_hide_widget(widget); - else - gfxw_show_widget(widget); - - *widget->signalp.getPointer(s->segMan) = make_reg(0, signal); // Write the changes back - }; - - } // ...if we're drawing disposeables and this one is disposeable, or if we're drawing non- - // disposeables and this one isn't disposeable - } - - widget = (GfxDynView *)widget->_next; - } // while (widget) - -} - reg_t kAddToPic(EngineState *s, int argc, reg_t *argv) { - GfxList *pic_views; - reg_t list_ref = argv[0]; + sciResourceId viewId; + uint16 loopNo, cellNo; + int16 leftPos, topPos, priority, control; - assert_primary_widget_lists(s); - - if (argc > 1) { - int view, cel, loop, x, y, priority, control; - GfxWidget *widget; - - view = argv[0].toUint16(); - loop = argv[1].toUint16(); - cel = argv[2].toUint16(); - x = argv[3].toSint16(); - y = argv[4].toSint16() + 1 /* magic + 1 */; + switch (argc) { + case 0: + break; + case 1: + s->gui->addToPicList(argv[0], argc, argv); + break; + case 7: + viewId = argv[0].toUint16(); + loopNo = argv[1].toUint16(); + cellNo = argv[2].toUint16(); + leftPos = argv[3].toSint16(); + topPos = argv[4].toSint16(); priority = argv[5].toSint16(); control = argv[6].toSint16(); - - widget = gfxw_new_dyn_view(s->gfx_state, Common::Point(x, y), 0, view, loop, cel, 0, - priority, -1 /* No priority */ , ALIGN_CENTER, ALIGN_BOTTOM, 0); - - if (!widget) { - error("Attempt to single-add invalid picview (%d/%d/%d)", view, loop, cel); - } else { - widget->_ID = -1; - if (control >= 0) { - Common::Rect abs_zone = nsrect_clip(s, y, calculate_nsrect(s, x, y, view, loop, cel), priority); - draw_rect_to_control_map(s, abs_zone); - } - ADD_TO_CURRENT_PICTURE_PORT(gfxw_picviewize_dynview((GfxDynView *) widget)); - } - } else { - List *list; - - if (!list_ref.segment) { - warning("Attempt to AddToPic single non-list: %04x:%04x", PRINT_REG(list_ref)); - return s->r_acc; - } - - list = lookup_list(s, list_ref); - - pic_views = gfxw_new_list(s->picture_port->_bounds, 1); - - debugC(2, kDebugLevelGraphics, "Preparing picview list...\n"); - _k_make_view_list(s, &pic_views, list, 0, argc, argv); - _k_prepare_view_list(s, pic_views, _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP); - // Store pic views for later re-use - - debugC(2, kDebugLevelGraphics, "Drawing picview list...\n"); - ADD_TO_CURRENT_PICTURE_PORT(pic_views); - _k_draw_view_list(s, pic_views, _K_DRAW_VIEW_LIST_NONDISPOSEABLE | _K_DRAW_VIEW_LIST_DISPOSEABLE | _K_DRAW_VIEW_LIST_PICVIEW); - // Draw relative to the bottom center - debugC(2, kDebugLevelGraphics, "Returning.\n"); + s->gui->addToPicView(viewId, loopNo, cellNo, leftPos, topPos, priority, control); + break; + default: + error("kAddToPic with unsupported parameter count %d", argc); } - reparentize_primary_widget_lists(s, s->port); - return s->r_acc; } @@ -2285,527 +1659,11 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) { return s->gui->newWindow(rect1, rect2, style, priority, colorPen, colorBack, title.c_str()); } -#define K_ANIMATE_CENTER_OPEN_H 0 // horizontally open from center -#define K_ANIMATE_CENTER_OPEN_V 1 // vertically open from center -#define K_ANIMATE_RIGHT_OPEN 2 // open from right -#define K_ANIMATE_LEFT_OPEN 3 // open from left -#define K_ANIMATE_BOTTOM_OPEN 4 // open from bottom -#define K_ANIMATE_TOP_OPEN 5 // open from top -#define K_ANIMATE_BORDER_OPEN_F 6 // open from edges to center -#define K_ANIMATE_CENTER_OPEN_F 7 // open from center to edges -#define K_ANIMATE_OPEN_CHECKERS 8 // open random checkboard -#define K_ANIMATE_BORDER_CLOSE_H_CENTER_OPEN_H 9 // horizontally close to center,reopen from center -#define K_ANIMATE_BORDER_CLOSE_V_CENTER_OPEN_V 10 // vertically close to center, reopen from center -#define K_ANIMATE_LEFT_CLOSE_RIGHT_OPEN 11 // close to right, reopen from right -#define K_ANIMATE_RIGHT_CLOSE_LEFT_OPEN 12 // close to left, reopen from left -#define K_ANIMATE_TOP_CLOSE_BOTTOM_OPEN 13 // close to bottom, reopen from bottom -#define K_ANIMATE_BOTTOM_CLOSE_TOP_OPEN 14 // close to top, reopen from top -#define K_ANIMATE_CENTER_CLOSE_F_BORDER_OPEN_F 15 // close from center to edges, -// reopen from edges to center -#define K_ANIMATE_BORDER_CLOSE_F_CENTER_OPEN_F 16 // close from edges to center, reopen from -// center to edges */ -#define K_ANIMATE_CLOSE_CHECKERS_OPEN_CHECKERS 17 // close random checkboard, reopen -#define K_ANIMATE_PALETTE_FADEOUT_FADEIN 0x1e -#define K_ANIMATE_SCROLL_LEFT 0x28 -#define K_ANIMATE_SCROLL_RIGHT 0x29 -#define K_ANIMATE_SCROLL_DOWN 0x2a -#define K_ANIMATE_SCROLL_UP 0x2b - -#define GRAPH_BLANK_BOX(s, x, y, xl, yl, color) gfxop_fill_box(s->gfx_state, \ - gfx_rect(x, (((y) < 10)? 10 : (y)), xl, (((y) < 10)? ((y) - 10) : 0) + (yl)), s->ega_colors[color]); - -#define GRAPH_UPDATE_BOX(s, x, y, xl, yl) gfxop_draw_pixmap(s->gfx_state, newscreen, \ - gfx_rect(x, (((y) < 10)? 10 : (y)) - 10, xl, (((y) < 10)? ((y) - 10) : 0) + (yl)), Common::Point(x, ((y) < 10)? 10 : (y) )); - -static void animate_do_animation(EngineState *s, int argc, reg_t *argv) { - long animation_delay = 5; - int i, remaining_checkers; - int update_counter; - // Number of animation steps to perform betwen updates for transition animations - int animation_granularity = 4; - int granularity0 = animation_granularity << 1; - int granularity1 = animation_granularity; - int granularity2 = animation_granularity >> 2; - int granularity3 = animation_granularity >> 4; - char checkers[32 * 19]; - gfx_pixmap_t *newscreen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190)); - - if (!granularity2) - granularity2 = 1; - if (!granularity3) - granularity3 = 1; - - gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen); - - if (!newscreen) { - error("Failed to allocate 'newscreen'"); - return; - } - - gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320, 190), Common::Point(0, 10)); - gfxop_update_box(s->gfx_state, gfx_rect(0, 0, 320, 200)); - - //debugC(2, kDebugLevelGraphics, "Animating pic opening type %x\n", s->pic_animate); - - gfxop_enable_dirty_frames(s->gfx_state); - - switch (s->pic_animate) { - case K_ANIMATE_BORDER_CLOSE_H_CENTER_OPEN_H : - for (i = 0; i < 159 + granularity1; i += granularity1) { - GRAPH_BLANK_BOX(s, i, 10, granularity1, 190, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, 319 - i, 10, granularity1, 190, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_CENTER_OPEN_H : - - for (i = 159; i >= 1 - granularity1; i -= granularity1) { - GRAPH_UPDATE_BOX(s, i, 10, granularity1, 190); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, 319 - i, 10, granularity1, 190); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_BORDER_CLOSE_V_CENTER_OPEN_V : - - for (i = 0; i < 94 + granularity2; i += granularity2) { - GRAPH_BLANK_BOX(s, 0, i + 10, 320, granularity2, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, 0, 199 - i, 320, granularity2, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, 2 * animation_delay / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_CENTER_OPEN_V : - - for (i = 94; i >= 1 - granularity2; i -= granularity2) { - GRAPH_UPDATE_BOX(s, 0, i + 10, 320, granularity2); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, 0, 199 - i, 320, granularity2); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, 2 * animation_delay / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_LEFT_CLOSE_RIGHT_OPEN : - - for (i = 0; i < 319 + granularity0; i += granularity0) { - GRAPH_BLANK_BOX(s, i, 10, granularity0, 190, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_RIGHT_OPEN : - for (i = 319; i >= 1 - granularity0; i -= granularity0) { - GRAPH_UPDATE_BOX(s, i, 10, granularity0, 190); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_RIGHT_CLOSE_LEFT_OPEN : - - for (i = 319; i >= 1 - granularity0; i -= granularity0) { - GRAPH_BLANK_BOX(s, i, 10, granularity0, 190, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_LEFT_OPEN : - - for (i = 0; i < 319 + granularity0; i += granularity0) { - GRAPH_UPDATE_BOX(s, i, 10, granularity0, 190); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_TOP_CLOSE_BOTTOM_OPEN : - - for (i = 10; i < 199 + granularity1; i += granularity1) { - GRAPH_BLANK_BOX(s, 0, i, 320, granularity1, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_BOTTOM_OPEN : - - for (i = 199; i >= 11 - granularity1; i -= granularity1) { - GRAPH_UPDATE_BOX(s, 0, i, 320, granularity1); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_BOTTOM_CLOSE_TOP_OPEN : - - for (i = 199; i >= 11 - granularity1; i -= granularity1) { - GRAPH_BLANK_BOX(s, 0, i, 320, granularity1, 0); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); - - case K_ANIMATE_TOP_OPEN : - - for (i = 10; i < 199 + granularity1; i += granularity1) { - GRAPH_UPDATE_BOX(s, 0, i, 320, granularity1); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, animation_delay / 1000); - process_sound_events(s); - } - break; - - - case K_ANIMATE_CENTER_CLOSE_F_BORDER_OPEN_F : - - for (i = 31; i >= 1 - granularity3; i -= granularity3) { - int real_i = (i < 0) ? 0 : i; - int height_l = 3 * (granularity3 - real_i + i); - int width_l = 5 * (granularity3 - real_i + i); - int height = real_i * 3; - int width = real_i * 5; - - GRAPH_BLANK_BOX(s, width, 10 + height, width_l, 190 - 2 * height, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height, 0); - gfxop_update(s->gfx_state); - - GRAPH_BLANK_BOX(s, width, 10 + height, 320 - 2 * width, height_l, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l, 0); - gfxop_update(s->gfx_state); - - gfxop_sleep(s->gfx_state, 4 * animation_delay / 1000); - process_sound_events(s); - } - - case K_ANIMATE_BORDER_OPEN_F : - - for (i = 0; i < 31 + granularity3; i += granularity3) { - int real_i = (i < 0) ? 0 : i; - int height_l = 3 * (granularity3 - real_i + i); - int width_l = 5 * (granularity3 - real_i + i); - int height = real_i * 3; - int width = real_i * 5; - - GRAPH_UPDATE_BOX(s, width, 10 + height, width_l, 190 - 2 * height); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height); - gfxop_update(s->gfx_state); - - GRAPH_UPDATE_BOX(s, width, 10 + height, 320 - 2 * width, height_l); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l); - gfxop_update(s->gfx_state); - - gfxop_sleep(s->gfx_state, 4 * animation_delay / 1000); - process_sound_events(s); - } - - break; - - case K_ANIMATE_BORDER_CLOSE_F_CENTER_OPEN_F : - - for (i = 0; i < 31 + granularity3; i += granularity3) { - int real_i = (i < 0) ? 0 : i; - int height_l = 3 * (granularity3 - real_i + i); - int width_l = 5 * (granularity3 - real_i + i); - int height = real_i * 3; - int width = real_i * 5; - - GRAPH_BLANK_BOX(s, width, 10 + height, width_l, 190 - 2 * height, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height, 0); - gfxop_update(s->gfx_state); - - GRAPH_BLANK_BOX(s, width, 10 + height, 320 - 2 * width, height_l, 0); - gfxop_update(s->gfx_state); - GRAPH_BLANK_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l, 0); - gfxop_update(s->gfx_state); - - gfxop_sleep(s->gfx_state, 7 * animation_delay / 1000); - process_sound_events(s); - } - - case K_ANIMATE_CENTER_OPEN_F : - - for (i = 31; i >= 1 - granularity3; i -= granularity3) { - int real_i = (i < 0) ? 0 : i; - int height_l = 3 * (granularity3 - real_i + i); - int width_l = 5 * (granularity3 - real_i + i); - int height = real_i * 3; - int width = real_i * 5; - - GRAPH_UPDATE_BOX(s, width, 10 + height, width_l, 190 - 2 * height); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2*height); - gfxop_update(s->gfx_state); - - GRAPH_UPDATE_BOX(s, width, 10 + height, 320 - 2 * width, height_l); - gfxop_update(s->gfx_state); - GRAPH_UPDATE_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l); - gfxop_update(s->gfx_state); - - gfxop_sleep(s->gfx_state, 7 * animation_delay / 1000); - process_sound_events(s); - } - break; - - case K_ANIMATE_PALETTE_FADEOUT_FADEIN: - warning("TODO: Palette fadeout/fadein"); - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - break; - - case K_ANIMATE_CLOSE_CHECKERS_OPEN_CHECKERS : - - memset(checkers, 0, sizeof(checkers)); - remaining_checkers = 19 * 32; - update_counter = granularity1; - - while (remaining_checkers) { - int x, y, checker = 1 + (int)(1.0 * remaining_checkers * rand() / (RAND_MAX + 1.0)); - i = -1; - - while (checker) - if (checkers[++i] == 0) - --checker; - checkers[i] = 1; // Mark checker as used - - x = i % 32; - y = i / 32; - - GRAPH_BLANK_BOX(s, x * 10, 10 + y * 10, 10, 10, 0); - if (!(update_counter--) || (remaining_checkers == 1)) { - gfxop_update(s->gfx_state); - update_counter = granularity1; - } - - if (remaining_checkers & 1) { - gfxop_sleep(s->gfx_state, animation_delay / 4 / 1000); - } - - --remaining_checkers; - process_sound_events(s); - } - - case K_ANIMATE_OPEN_CHECKERS : - - memset(checkers, 0, sizeof(checkers)); - remaining_checkers = 19 * 32; - update_counter = granularity1; - - while (remaining_checkers) { - int x, y, checker = 1 + (int)(1.0 * remaining_checkers * rand() / (RAND_MAX + 1.0)); - i = -1; - - while (checker) - if (checkers[++i] == 0) --checker; - checkers[i] = 1; // Mark checker as used - - x = i % 32; - y = i / 32; - - GRAPH_UPDATE_BOX(s, x * 10, 10 + y * 10, 10, 10); - - if (!(update_counter--) || (remaining_checkers == 1)) { - gfxop_update(s->gfx_state); - update_counter = granularity1; - } - - if (remaining_checkers & 1) { - gfxop_sleep(s->gfx_state, animation_delay / 4 / 1000); - } - - --remaining_checkers; - process_sound_events(s); - } - break; - - - case K_ANIMATE_SCROLL_LEFT : - - for (i = 0; i < 319; i += granularity0) { - gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(320 - i, 0, i, 190), Common::Point(0, 10)); - gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320 - i, 190), Common::Point(i, 10)); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); - } - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - break; - - case K_ANIMATE_SCROLL_RIGHT : - - for (i = 0; i < 319; i += granularity0) { - gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 0, i, 190), Common::Point(319 - i, 10)); - gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(i, 0, 320 - i, 190), Common::Point(0, 10)); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); - } - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - break; - - case K_ANIMATE_SCROLL_UP : - - for (i = 0; i < 189; i += granularity0) { - gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 190 - i, 320, i), Common::Point(0, 10)); - gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320, 190 - i), Common::Point(0, 10 + i)); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); - } - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - break; - - case K_ANIMATE_SCROLL_DOWN : - - for (i = 0; i < 189; i += granularity0) { - gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 0, 320, i), Common::Point(0, 200 - i)); - gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, i, 320, 190 - i), Common::Point(0, 10)); - gfxop_update(s->gfx_state); - gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); - } - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - break; - - default: - warning("Unknown opening animation 0x%02x", s->pic_animate); - GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); - - } - - gfxop_free_pixmap(s->gfx_state, s->old_screen); - gfxop_free_pixmap(s->gfx_state, newscreen); - s->old_screen = NULL; -} - reg_t kAnimate(EngineState *s, int argc, reg_t *argv) { - // Animations are supposed to take a maximum of animation_delay milliseconds. - reg_t cast_list_ref = (argc > 0) ? argv[0] : NULL_REG; - int cycle = (argc > 1) ? argv[1].toUint16() : 0; - List *cast_list = NULL; - int open_animation = 0; - - process_sound_events(s); // Take care of incoming events (kAnimate is called semi-regularly) - _k_animate_ran = true; // Used by some of the invoked functions to check for recursion, which may, - // after all, damage the cast list - - if (cast_list_ref.segment) { - cast_list = lookup_list(s, cast_list_ref); - if (!cast_list) - return s->r_acc; - } - - open_animation = (s->pic_is_new) && (s->pic_not_valid); - s->pic_is_new = 0; - - assert_primary_widget_lists(s); - - if (!s->dyn_views->_contents // Only reparentize empty dynview list - && (((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) // If dynviews are on other port... - || (s->dyn_views->_next))) // ... or not on top of the view list - reparentize_primary_widget_lists(s, s->port); - - if (cast_list) { - GfxList *templist = gfxw_new_list(s->dyn_views->_bounds, 0); - - _k_make_view_list(s, &(templist), cast_list, (cycle ? _K_MAKE_VIEW_LIST_CYCLE : 0) - | _K_MAKE_VIEW_LIST_CALC_PRIORITY, argc, argv); - - // Make sure that none of the doits() did something evil - assert_primary_widget_lists(s); - - if (!s->dyn_views->_contents // Only reparentize empty dynview list - && (((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) // If dynviews are on other port... - || (s->dyn_views->_next))) // ... or not on top of the view list - reparentize_primary_widget_lists(s, s->port); - // End of doit() recovery code - - if (s->pic_is_new) { // Happens if DrawPic() is executed by a dynview (yes, that happens) - return kAnimate(s, argc, argv); /* Tail-recurse */ - } - - debugC(2, kDebugLevelGraphics, "Handling Dynviews (..step 9 inclusive):\n"); - _k_prepare_view_list(s, templist, _K_MAKE_VIEW_LIST_CALC_PRIORITY); - - if (s->pic_not_valid) { - debugC(2, kDebugLevelGraphics, "PicNotValid=%d -> Subalgorithm:\n", s->pic_not_valid); - _k_redraw_view_list(s, templist); - } - - _k_update_signals_in_view_list(s->dyn_views, templist); - s->dyn_views->tag(); - - _k_raise_topmost_in_view_list(s, s->dyn_views, (GfxDynView *)templist->_contents); - - delete templist; - s->dyn_views->free_tagged((GfxContainer *)s->dyn_views); // Free obsolete dynviews - } // if (cast_list) - - if (open_animation) { - gfxop_clear_box(s->gfx_state, gfx_rect(0, 10, 320, 190)); // Propagate pic - s->visual->add_dirty_abs((GfxContainer *)s->visual, gfx_rect_fullscreen, 0); - // Mark screen as dirty so picviews will be drawn correctly - FULL_REDRAW(); - - animate_do_animation(s, argc, argv); - } // if (open_animation) - - if (cast_list) { - int retval; - int reparentize = 0; - - s->pic_not_valid = 0; - - _k_view_list_do_postdraw(s, s->dyn_views); - - // _k_view_list_dispose_loop() returns -1 if it requested a re-start, so we do just that. - while ((retval = _k_view_list_dispose_loop(s, cast_list, (GfxDynView *) s->dyn_views->_contents, argc, argv) < 0)) - reparentize = 1; - - if (s->drop_views->_contents) { - s->drop_views = gfxw_new_list(s->dyn_views->_bounds, GFXW_LIST_SORTED); - s->drop_views->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; - ADD_TO_CURRENT_PICTURE_PORT(s->drop_views); - } else { - assert(s->drop_views); - gfxw_remove_widget_from_container(s->drop_views->_parent, s->drop_views); - ADD_TO_CURRENT_PICTURE_PORT(s->drop_views); - } - - if ((reparentize | retval) - && ((GfxContainer *)s->port == (GfxContainer *)s->dyn_views->_parent) // If dynviews are on the same port... - && (s->dyn_views->_next)) // ... and not on top of the view list... - reparentize_primary_widget_lists(s, s->port); // ...then reparentize. - - _k_view_list_kryptonize(s->dyn_views->_contents); - } + reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG; + bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false; - FULL_REDRAW(); + s->gui->animate(castListReference, cycle, argc, argv); return s->r_acc; } diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index f9660462eb..a01aed81cd 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -325,6 +325,22 @@ int16 SciGUI::onControl(byte screenMask, Common::Rect rect) { return result; } +void SciGUI::animate(reg_t castListReference, bool cycle, int argc, reg_t *argv) { + // FIXME: port over from gregs engine +} + +void SciGUI::addToPicList(reg_t listReference, int argc, reg_t *argv) { + // FIXME: port over from gregs engine +} + +void SciGUI::addToPicView(sciResourceId viewId, uint16 loopNo, uint16 cellNo, int16 leftPos, int16 topPos, int16 priority, int16 control) { + // FIXME: port over from gregs engine +} + +void SciGUI::setNowSeen(reg_t objectReference) { + // FIXME: port over from gregs engine +} + void SciGUI::moveCursor(int16 x, int16 y) { Common::Point newPos; diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h index de2353733e..bffaa0f1a9 100644 --- a/engines/sci/gui/gui.h +++ b/engines/sci/gui/gui.h @@ -75,6 +75,11 @@ public: virtual void paletteAnimate(int fromColor, int toColor, int speed); virtual int16 onControl(byte screenMask, Common::Rect rect); + // FIXME: argc/argv because of gui32.cpp, should get removed sometime + 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(sciResourceId viewId, uint16 loopNo, uint16 cellNo, int16 leftPos, int16 topPos, int16 priority, int16 control); + virtual void setNowSeen(reg_t objectReference); virtual void moveCursor(int16 x, int16 y); diff --git a/engines/sci/gui/gui_gfx.cpp b/engines/sci/gui/gui_gfx.cpp index b417eb4fe8..4001ea06c5 100644 --- a/engines/sci/gui/gui_gfx.cpp +++ b/engines/sci/gui/gui_gfx.cpp @@ -916,7 +916,7 @@ void SciGUIgfx::Draw_Line(int16 left, int16 top, int16 right, int16 bottom, byte void SciGUIgfx::Draw_Horiz(int16 left, int16 right, int16 top, byte flag, byte color, byte prio, byte control) { if (right < left) SWAP(right, left); - for (int i = left; i <= right; i++) + for (int i = left; i < right; i++) _screen->Put_Pixel(i, top, flag, color, prio, control); } @@ -924,7 +924,7 @@ void SciGUIgfx::Draw_Horiz(int16 left, int16 right, int16 top, byte flag, byte c void SciGUIgfx::Draw_Vert(int16 top, int16 bottom, int16 left, byte flag, byte color, byte prio, byte control) { if (top > bottom) SWAP(top, bottom); - for (int i = top; i <= bottom; i++) + for (int i = top; i < bottom; i++) _screen->Put_Pixel(left, i, flag, color, prio, control); } diff --git a/engines/sci/gui/gui_view.cpp b/engines/sci/gui/gui_view.cpp index f190d5245a..f795565483 100644 --- a/engines/sci/gui/gui_view.cpp +++ b/engines/sci/gui/gui_view.cpp @@ -241,7 +241,6 @@ byte *SciGUIview::getBitmap(uint16 loopNo, uint16 cellNo) { uint16 width = _loop[loopNo].cell[cellNo].width; uint16 height = _loop[loopNo].cell[cellNo].height; -// byte *ptr = _resourceData + _loop[loopNo].cell[cellNo].offset; // allocating memory to store cel's bitmap assert(width * height <= 64000); uint16 pixelCount = width * height; diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index 83ad251eb5..7163ca422b 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -73,6 +73,7 @@ SciGUI32::~SciGUI32() { void SciGUI32::init(bool oldGfxFunctions) { _usesOldGfxFunctions = oldGfxFunctions; + _k_animate_ran = false; activated_icon_bar = false; port_origin_x = 0; port_origin_y = 0; @@ -716,7 +717,7 @@ int16 SciGUI32::onControl(byte screenMask, Common::Rect rect) { rect_t gfxrect = gfx_rect(rect.left, rect.top + 10, rect.width(), rect.height()); return gfxop_scan_bitmask(s->gfx_state, gfxrect, map); -// old code +// old code, just for reference // int xstart, ystart; // int xlen = 1, ylen = 1; // @@ -738,6 +739,1251 @@ int16 SciGUI32::onControl(byte screenMask, Common::Rect rect) { // return make_reg(0, gfxop_scan_bitmask(s->gfx_state, gfx_rect(xstart, ystart + 10, xlen, ylen), map)); } +enum { + _K_MAKE_VIEW_LIST_CYCLE = 1, + _K_MAKE_VIEW_LIST_CALC_PRIORITY = 2, + _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP = 4 +}; + +static inline int sign_extend_byte(int value) { + if (value & 0x80) + return value - 256; + else + return value; +} + +static Common::Rect nsrect_clip(EngineState *s, int y, Common::Rect retval, int priority) { + int pri_top; + + if (priority == -1) + priority = _find_view_priority(s, y); + + pri_top = _find_priority_band(s, priority) + 1; + // +1: Don't know why, but this seems to be happening + + if (retval.top < pri_top) + retval.top = pri_top; + + if (retval.bottom < retval.top) + retval.top = retval.bottom - 1; + + return retval; +} + +static Common::Rect calculate_nsrect(EngineState *s, int x, int y, int view, int loop, int cel) { + int xbase, ybase, xend, yend, xsize, ysize; + int xmod = 0, ymod = 0; + Common::Rect retval(0, 0, 0, 0); + + Common::Point offset = Common::Point(0, 0); + + gfxop_get_cel_parameters(s->gfx_state, view, loop, cel, &xsize, &ysize, &offset); + + xmod = offset.x; + ymod = offset.y; + + xbase = x - xmod - (xsize >> 1); + xend = xbase + xsize; + yend = y - ymod + 1; // +1: magic modifier + ybase = yend - ysize; + + retval.left = xbase; + retval.top = ybase; + retval.right = xend; + retval.bottom = yend; + + return retval; +} + +Common::Rect get_nsrect32(EngineState *s, reg_t object, byte clip) { + SegManager *segMan = s->segMan; + int x, y, z; + int view, loop, cel; + Common::Rect retval; + + x = (int16)GET_SEL32V(object, x); + y = (int16)GET_SEL32V(object, y); + + if (s->_kernel->_selectorCache.z > -1) + z = (int16)GET_SEL32V(object, z); + else + z = 0; + + y -= z; // Subtract z offset + + view = (int16)GET_SEL32V(object, view); + loop = sign_extend_byte((int16)GET_SEL32V(object, loop)); + cel = sign_extend_byte((int16)GET_SEL32V(object, cel)); + + retval = calculate_nsrect(s, x, y, view, loop, cel); + + if (clip) { + int priority = (int16)GET_SEL32V(object, priority); + return nsrect_clip(s, y, retval, priority); + } + + return retval; +} + +GfxDynView *SciGUI32::_k_make_dynview_obj(reg_t obj, int options, int nr, int argc, reg_t *argv) { + SegManager *segMan = s->segMan; + short oldloop, oldcel; + int cel, loop, view_nr = (int16)GET_SEL32V(obj, view); + int palette; + int signal; + reg_t under_bits; + Common::Point pos; + int z; + GfxDynView *widget; + + debugC(2, kDebugLevelGraphics, " - Adding %04x:%04x\n", PRINT_REG(obj)); + + obj = obj; + + pos.x = (int16)GET_SEL32V(obj, x); + pos.y = (int16)GET_SEL32V(obj, y); + + pos.y++; // magic: Sierra appears to do something like this + + z = (int16)GET_SEL32V(obj, z); + + // !-- nsRect used to be checked here! + loop = oldloop = sign_extend_byte(GET_SEL32V(obj, loop)); + cel = oldcel = sign_extend_byte(GET_SEL32V(obj, cel)); + + if (s->_kernel->_selectorCache.palette) + palette = GET_SEL32V(obj, palette); + else + palette = 0; + + // Clip loop and cel, write back if neccessary + gfxop_check_cel(s->gfx_state, view_nr, &loop, &cel); + + if (loop != oldloop) + loop = 0; + if (cel != oldcel) + cel = 0; + + if (oldloop != loop) + PUT_SEL32V(obj, loop, loop); + + if (oldcel != cel) { + PUT_SEL32V(obj, cel, cel); + } + + ObjVarRef under_bitsp; + if (lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.underBits, &(under_bitsp), NULL) != kSelectorVariable) { + under_bitsp.obj = NULL_REG; + under_bits = NULL_REG; + debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no underBits\n", PRINT_REG(obj)); + } else + under_bits = *under_bitsp.getPointer(s->segMan); + + ObjVarRef signalp; + if (lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.signal, &(signalp), NULL) != kSelectorVariable) { + signalp.obj = NULL_REG; + signal = 0; + debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no signal selector\n", PRINT_REG(obj)); + } else { + signal = signalp.getPointer(s->segMan)->offset; + debugC(2, kDebugLevelGraphics, " with signal = %04x\n", signal); + } + + widget = gfxw_new_dyn_view(s->gfx_state, pos, z, view_nr, loop, cel, palette, -1, -1, ALIGN_CENTER, ALIGN_BOTTOM, nr); + + if (widget) { + widget = (GfxDynView *) gfxw_set_id(widget, obj.segment, obj.offset); + widget = gfxw_dyn_view_set_params(widget, under_bits.segment, under_bitsp, signal, signalp); + widget->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; // Only works the first time 'round' + + return widget; + } else { + warning("Could not generate dynview widget for %d/%d/%d", view_nr, loop, cel); + return NULL; + } +} + +void SciGUI32::_k_make_view_list(GfxList **widget_list, List *list, int options, int argc, reg_t *argv) { +/* Creates a view_list from a node list in heap space. Returns the list, stores the +** number of list entries in *list_nr. Calls doit for each entry if cycle is set. +** argc, argv should be the same as in the calling kernel function. +*/ + SegManager *segMan = s->segMan; + Node *node; + int sequence_nr = 0; + GfxDynView *widget; + + if (!*widget_list) { + error("make_view_list with widget_list == ()"); + }; + + assert_primary_widget_lists(s); + // In case one of the views' doit() does a DrawPic... + // Yes, this _does_ happen! + + if (!list) { // list sanity check + error("Attempt to make list from non-list"); + } + + reg_t next_node = list->first; + node = lookup_node(s, next_node); + while (node) { + reg_t obj = node->value; // The object we're using + GfxDynView *tempWidget; + + if (options & _K_MAKE_VIEW_LIST_CYCLE) { + unsigned int signal = GET_SEL32V(obj, signal); + + if (!(signal & _K_VIEW_SIG_FLAG_FROZEN)) { + + debugC(2, kDebugLevelGraphics, " invoking %04x:%04x::doit()\n", PRINT_REG(obj)); + invoke_selector(INV_SEL(obj, doit, kContinueOnInvalidSelector), 0); // Call obj::doit() if neccessary + + + // Lookup node again, since the NodeTable it was in may + // have been re-allocated. + node = lookup_node(s, next_node); + } + } + + next_node = node->succ; // In case the cast list was changed + + if (list->first.segment == 0 && list->first.offset == 0) // The cast list was completely emptied! + break; + + tempWidget = _k_make_dynview_obj(obj, options, sequence_nr--, argc, argv); + if (tempWidget) + (*widget_list)->add((GfxContainer *)(*widget_list), tempWidget); + + node = lookup_node(s, next_node); // Next node + } + + widget = (GfxDynView *)(*widget_list)->_contents; + + while (widget) { // Read back widget values + reg_t *sp = widget->signalp.getPointer(s->segMan); + if (sp) + widget->signal = sp->offset; + + widget = (GfxDynView *)widget->_next; + } +} + +void SciGUI32::draw_rect_to_control_map(Common::Rect abs_zone) { + GfxBox *box; + gfx_color_t color; + + gfxop_set_color(s->gfx_state, &color, -1, -1, -1, -1, -1, 0xf); + + debugC(2, kDebugLevelGraphics, " adding control block (%d,%d)to(%d,%d)\n", abs_zone.left, abs_zone.top, abs_zone.right, abs_zone.bottom); + + box = gfxw_new_box(s->gfx_state, gfx_rect(abs_zone.left, abs_zone.top, abs_zone.width(), + abs_zone.height()), color, color, GFX_BOX_SHADE_FLAT); + + assert_primary_widget_lists(s); + + ADD_TO_CURRENT_PICTURE_PORT(box); +} + +void SciGUI32::draw_obj_to_control_map(GfxDynView *view) { + reg_t obj = make_reg(view->_ID, view->_subID); + + if (!s->segMan->isObject(obj)) + warning("View %d does not contain valid object reference %04x:%04x", view->_ID, PRINT_REG(obj)); + + reg_t* sp = view->signalp.getPointer(s->segMan); + if (!(sp && (sp->offset & _K_VIEW_SIG_FLAG_IGNORE_ACTOR))) { + Common::Rect abs_zone = get_nsrect32(s, make_reg(view->_ID, view->_subID), 1); + draw_rect_to_control_map(abs_zone); + } +} + +int SciGUI32::_k_view_list_dispose_loop(List *list, GfxDynView *widget, int argc, reg_t *argv) { +// disposes all list members flagged for disposal +// returns non-zero IFF views were dropped + int signal; + int dropped = 0; + SegManager *segMan = s->segMan; + + _k_animate_ran = false; + + if (widget) { + int retval; + // Recurse: + retval = _k_view_list_dispose_loop(list, (GfxDynView *)widget->_next, argc, argv); + + if (retval == -1) // Bail out on annihilation, rely on re-start from Animate() + return -1; + + if (GFXW_IS_DYN_VIEW(widget) && (widget->_ID != GFXW_NO_ID)) { + signal = widget->signalp.getPointer(segMan)->offset; + if (signal & _K_VIEW_SIG_FLAG_DISPOSE_ME) { + reg_t obj = make_reg(widget->_ID, widget->_subID); + reg_t under_bits = NULL_REG; + + if (!s->segMan->isObject(obj)) { + error("Non-object %04x:%04x present in view list during delete time", PRINT_REG(obj)); + obj = NULL_REG; + } else { + reg_t *ubp = widget->under_bitsp.getPointer(segMan); + if (ubp) { // Is there a bg picture left to clean? + reg_t mem_handle = *ubp; + + if (mem_handle.segment) { + if (!kfree(s->segMan, mem_handle)) { + *ubp = make_reg(0, widget->under_bits = 0); + } else { + warning("Treating viewobj %04x:%04x as no longer present", PRINT_REG(obj)); + obj = NULL_REG; + } + } + } + } + if (segMan->isObject(obj)) { + if (invoke_selector(INV_SEL(obj, delete_, kContinueOnInvalidSelector), 0)) + warning("Object at %04x:%04x requested deletion, but does not have a delete funcselector", PRINT_REG(obj)); + if (_k_animate_ran) { + warning("Object at %04x:%04x invoked kAnimate() during deletion", PRINT_REG(obj)); + return dropped; + } + + reg_t *ubp = widget->under_bitsp.getPointer(segMan); + if (ubp) + under_bits = *ubp; + + if (under_bits.segment) { + *ubp = make_reg(0, 0); + graph_restore_box(s, under_bits); + } + + debugC(2, kDebugLevelGraphics, "Freeing %04x:%04x with signal=%04x\n", PRINT_REG(obj), signal); + + if (!(signal & _K_VIEW_SIG_FLAG_HIDDEN)) { + debugC(2, kDebugLevelGraphics, "Adding view at %04x:%04x to background\n", PRINT_REG(obj)); + if (!(gfxw_remove_id(widget->_parent, widget->_ID, widget->_subID) == widget)) { + error("Attempt to remove view with ID %x:%x from list failed", widget->_ID, widget->_subID); + } + + s->drop_views->add((GfxContainer *)s->drop_views, gfxw_picviewize_dynview(widget)); + + draw_obj_to_control_map(widget); + widget->draw_bounds.y += s->dyn_views->_bounds.y - widget->_parent->_bounds.y; + widget->draw_bounds.x += s->dyn_views->_bounds.x - widget->_parent->_bounds.x; + dropped = 1; + } else { + debugC(2, kDebugLevelGraphics, "Deleting view at %04x:%04x\n", PRINT_REG(obj)); + widget->_flags |= GFXW_FLAG_VISIBLE; + gfxw_annihilate(widget); + return -1; // restart: Done in Animate() + } + } + } + } + + } + + return dropped; +} + +void SciGUI32::_k_set_now_seen(reg_t object) { + SegManager *segMan = s->segMan; + Common::Rect absrect = get_nsrect32(s, object, 0); + + if (lookup_selector(s->segMan, object, s->_kernel->_selectorCache.nsTop, NULL, NULL) != kSelectorVariable) { + return; + } // This isn't fatal + + PUT_SEL32V(object, nsLeft, absrect.left); + PUT_SEL32V(object, nsRight, absrect.right); + PUT_SEL32V(object, nsTop, absrect.top); + PUT_SEL32V(object, nsBottom, absrect.bottom); +} + +void SciGUI32::_k_prepare_view_list(GfxList *list, int options) { + SegManager *segMan = s->segMan; + GfxDynView *view = (GfxDynView *) list->_contents; + while (view) { + reg_t obj = make_reg(view->_ID, view->_subID); + int priority, _priority; + int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL) == kSelectorVariable; + int oldsignal = view->signal; + + _k_set_now_seen(obj); + _priority = /*GET_SELECTOR(obj, y); */((view->_pos.y)); + _priority = _find_view_priority(s, _priority - 1); + + if (options & _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP) { // Picview + priority = (int16)GET_SEL32V(obj, priority); + if (priority < 0) + priority = _priority; // Always for picviews + } else { // Dynview + if (has_nsrect && !(view->signal & _K_VIEW_SIG_FLAG_FIX_PRI_ON)) { // Calculate priority + if (options & _K_MAKE_VIEW_LIST_CALC_PRIORITY) + PUT_SEL32V(obj, priority, _priority); + + priority = _priority; + + } else // DON'T calculate the priority + priority = (int16)GET_SEL32V(obj, priority); + } + + view->_color.priority = priority; + + if (priority > -1) + view->_color.mask |= GFX_MASK_PRIORITY; + else + view->_color.mask &= ~GFX_MASK_PRIORITY; + + // CR (from :Bob Heitman:) stopupdated views (like pic views) have + // their clipped nsRect drawn to the control map + if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { + view->signal |= _K_VIEW_SIG_FLAG_STOPUPD; + debugC(2, kDebugLevelGraphics, "Setting magic STOP_UPD for %04x:%04x\n", PRINT_REG(obj)); + } + + if ((options & _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP)) + draw_obj_to_control_map(view); + + // Extreme Pattern Matching ugliness ahead... + if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { + if (((view->signal & (_K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_FORCE_UPDATE))) // 9.1.1.1 + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) == _K_VIEW_SIG_FLAG_HIDDEN) + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) == _K_VIEW_SIG_FLAG_REMOVE) // 9.1.1.2 + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) // 9.1.1.3 + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE))) { // 9.1.1.4 + s->pic_not_valid++; + view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; + } + + else if (((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == 0) + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_REMOVE)) + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) + || ((view->signal & (_K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == _K_VIEW_SIG_FLAG_HIDDEN)) { + view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; + } + } else { + if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { + s->pic_not_valid++; + view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; + } else { // if not STOP_UPDATE + if (view->signal & _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) + s->pic_not_valid++; + view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; + } + } + + debugC(2, kDebugLevelGraphics, " dv[%04x:%04x]: signal %04x -> %04x\n", PRINT_REG(obj), oldsignal, view->signal); + + // Never happens +/* if (view->signal & 0) { + view->signal &= ~_K_VIEW_SIG_FLAG_STOPUPD; + fprintf(stderr, "Unsetting magic StopUpd for view %04x:%04x\n", PRINT_REG(obj)); + } */ + + view = (GfxDynView *)view->_next; + } +} + +void SciGUI32::_k_update_signals_in_view_list(GfxList *old_list, GfxList *new_list) { + // O(n^2)... a bit painful, but much faster than the redraws it helps prevent + GfxDynView *old_widget = (GfxDynView *)old_list->_contents; + + /* Traverses all old widgets, updates them with signals from the new widgets. + ** This is done to avoid evil hacks in widget.c; widgets with unique IDs are + ** replaced there iff they are NOT equal_to a new widget with the same ID. + ** If they were replaced every time, we'd be doing far too many redraws. + */ + + while (old_widget) { + GfxDynView *new_widget = (GfxDynView *) new_list->_contents; + + while (new_widget + && (new_widget->_ID != old_widget->_ID + || new_widget->_subID != old_widget->_subID)) + new_widget = (GfxDynView *)new_widget->_next; + + if (new_widget) { + int carry = old_widget->signal & _K_VIEW_SIG_FLAG_STOPUPD; + // Transfer 'stopupd' flag + + if ((new_widget->_pos.x != old_widget->_pos.x) + || (new_widget->_pos.y != old_widget->_pos.y) + // No idea why this is supposed to be bad +/* || (new_widget->z != old_widget->z) + || (new_widget->view != old_widget->view) + || (new_widget->loop != old_widget->loop) + || (new_widget->cel != old_widget->cel) + */) + carry = 0; + + old_widget->signal = new_widget->signal |= carry; + } + + old_widget = (GfxDynView *)old_widget->_next; + } +} + +void SciGUI32::_k_view_list_kryptonize(GfxWidget *v) { + if (v) { + v->_flags &= ~GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; + _k_view_list_kryptonize(v->_next); + } +} + +void SciGUI32::_k_raise_topmost_in_view_list(GfxList *list, GfxDynView *view) { + if (view) { + GfxDynView *next = (GfxDynView *)view->_next; + + // step 11 + if ((view->signal & (_K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_HIDDEN | _K_VIEW_SIG_FLAG_ALWAYS_UPDATE)) == 0) { + debugC(2, kDebugLevelGraphics, "Forcing precedence 2 at [%04x:%04x] with %04x\n", PRINT_REG(make_reg(view->_ID, view->_subID)), view->signal); + view->force_precedence = 2; + + if ((view->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_HIDDEN)) == _K_VIEW_SIG_FLAG_REMOVE) { + view->signal &= ~_K_VIEW_SIG_FLAG_REMOVE; + } + } + + gfxw_remove_widget_from_container(view->_parent, view); + + if (view->signal & _K_VIEW_SIG_FLAG_HIDDEN) + gfxw_hide_widget(view); + else + gfxw_show_widget(view); + + list->add((GfxContainer *)list, view); + + _k_raise_topmost_in_view_list(list, next); + } +} + +void SciGUI32::_k_redraw_view_list(GfxList *list) { + GfxDynView *view = (GfxDynView *) list->_contents; + while (view) { + + debugC(2, kDebugLevelGraphics, " dv[%04x:%04x]: signal %04x\n", PRINT_REG(make_reg(view->_ID, view->_subID)), view->signal); + + // step 1 of subalgorithm + if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { + if (view->signal & _K_VIEW_SIG_FLAG_FORCE_UPDATE) + view->signal &= ~_K_VIEW_SIG_FLAG_FORCE_UPDATE; + + if (view->signal & _K_VIEW_SIG_FLAG_UPDATED) + view->signal &= ~(_K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE); + } else { // NO_UPD is not set + if (view->signal & _K_VIEW_SIG_FLAG_STOP_UPDATE) { + view->signal &= ~_K_VIEW_SIG_FLAG_STOP_UPDATE; + view->signal |= _K_VIEW_SIG_FLAG_NO_UPDATE; + } + } + + debugC(2, kDebugLevelGraphics, " at substep 6: signal %04x\n", view->signal); + + if (view->signal & _K_VIEW_SIG_FLAG_ALWAYS_UPDATE) + view->signal &= ~(_K_VIEW_SIG_FLAG_STOP_UPDATE | _K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_FORCE_UPDATE); + + debugC(2, kDebugLevelGraphics, " at substep 11/14: signal %04x\n", view->signal); + + if (view->signal & _K_VIEW_SIG_FLAG_NO_UPDATE) { + if (view->signal & _K_VIEW_SIG_FLAG_HIDDEN) + view->signal |= _K_VIEW_SIG_FLAG_REMOVE; + else + view->signal &= ~_K_VIEW_SIG_FLAG_REMOVE; + } else if (!(view->signal & _K_VIEW_SIG_FLAG_HIDDEN)) + view->force_precedence = 1; + + debugC(2, kDebugLevelGraphics, " -> signal %04x\n", view->signal); + + view = (GfxDynView *)view->_next; + } +} + +// Flags for _k_draw_view_list +// Whether some magic with the base object's "signal" selector should be done: +#define _K_DRAW_VIEW_LIST_USE_SIGNAL 1 +// This flag draws all views with the "DISPOSE_ME" flag set: +#define _K_DRAW_VIEW_LIST_DISPOSEABLE 2 +// Use this one to draw all views with "DISPOSE_ME" NOT set: +#define _K_DRAW_VIEW_LIST_NONDISPOSEABLE 4 +// Draw as picviews +#define _K_DRAW_VIEW_LIST_PICVIEW 8 + +void SciGUI32::_k_draw_view_list(GfxList *list, int flags) { + // Draws list_nr members of list to s->pic. + GfxDynView *widget = (GfxDynView *) list->_contents; + + if ((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) + return; // Return if the pictures are meant for a different port + + while (widget) { + if (flags & _K_DRAW_VIEW_LIST_PICVIEW) + widget = gfxw_picviewize_dynview(widget); + + if (GFXW_IS_DYN_VIEW(widget) && widget->_ID) { + uint16 signal = (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) ? widget->signalp.getPointer(s->segMan)->offset : 0; + + if (signal & _K_VIEW_SIG_FLAG_HIDDEN) + gfxw_hide_widget(widget); + else + gfxw_show_widget(widget); + + if (!(flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) + || ((flags & _K_DRAW_VIEW_LIST_DISPOSEABLE) && (signal & _K_VIEW_SIG_FLAG_DISPOSE_ME)) + || ((flags & _K_DRAW_VIEW_LIST_NONDISPOSEABLE) && !(signal & _K_VIEW_SIG_FLAG_DISPOSE_ME))) { + + if (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) { + signal &= ~(_K_VIEW_SIG_FLAG_STOP_UPDATE | _K_VIEW_SIG_FLAG_UPDATED | _K_VIEW_SIG_FLAG_NO_UPDATE | _K_VIEW_SIG_FLAG_FORCE_UPDATE); + // Clear all of those flags + + if (signal & _K_VIEW_SIG_FLAG_HIDDEN) + gfxw_hide_widget(widget); + else + gfxw_show_widget(widget); + + *widget->signalp.getPointer(s->segMan) = make_reg(0, signal); // Write the changes back + }; + + } // ...if we're drawing disposeables and this one is disposeable, or if we're drawing non- + // disposeables and this one isn't disposeable + } + + widget = (GfxDynView *)widget->_next; + } // while (widget) +} + +void SciGUI32::_k_view_list_do_postdraw(GfxList *list) { + SegManager *segMan = s->segMan; + GfxDynView *widget = (GfxDynView *) list->_contents; + + while (widget) { + reg_t obj = make_reg(widget->_ID, widget->_subID); + + /* + * this fixes a few problems, but doesn't match SSCI's logic. + * The semantics of the private flag need to be verified before this can be uncommented. + * Fixes bug #326 (CB1, ego falls down stairs) + * if ((widget->signal & (_K_VIEW_SIG_FLAG_PRIVATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == _K_VIEW_SIG_FLAG_PRIVATE) { + */ + if ((widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == 0) { + int has_nsrect = lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL) == kSelectorVariable; + + if (has_nsrect) { + int temp; + + temp = GET_SEL32V(obj, nsLeft); + PUT_SEL32V(obj, lsLeft, temp); + + temp = GET_SEL32V(obj, nsRight); + PUT_SEL32V(obj, lsRight, temp); + + temp = GET_SEL32V(obj, nsTop); + PUT_SEL32V(obj, lsTop, temp); + + temp = GET_SEL32V(obj, nsBottom); + PUT_SEL32V(obj, lsBottom, temp); +#ifdef DEBUG_LSRECT + fprintf(stderr, "lsRected %04x:%04x\n", PRINT_REG(obj)); +#endif + } +#ifdef DEBUG_LSRECT + else + fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s->segMan, obj, s->_kernel->_selectorCache.nsBottom, NULL, NULL)); +#endif + + if (widget->signal & _K_VIEW_SIG_FLAG_HIDDEN) + widget->signal |= _K_VIEW_SIG_FLAG_REMOVE; + } +#ifdef DEBUG_LSRECT + fprintf(stderr, "obj %04x:%04x has pflags %x\n", PRINT_REG(obj), (widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE))); +#endif + + reg_t* sp = widget->signalp.getPointer(s->segMan); + if (sp) { + *sp = make_reg(0, widget->signal & 0xffff); /* Write back signal */ + } + + widget = (GfxDynView *)widget->_next; + } +} + +#define K_ANIMATE_CENTER_OPEN_H 0 // horizontally open from center +#define K_ANIMATE_CENTER_OPEN_V 1 // vertically open from center +#define K_ANIMATE_RIGHT_OPEN 2 // open from right +#define K_ANIMATE_LEFT_OPEN 3 // open from left +#define K_ANIMATE_BOTTOM_OPEN 4 // open from bottom +#define K_ANIMATE_TOP_OPEN 5 // open from top +#define K_ANIMATE_BORDER_OPEN_F 6 // open from edges to center +#define K_ANIMATE_CENTER_OPEN_F 7 // open from center to edges +#define K_ANIMATE_OPEN_CHECKERS 8 // open random checkboard +#define K_ANIMATE_BORDER_CLOSE_H_CENTER_OPEN_H 9 // horizontally close to center,reopen from center +#define K_ANIMATE_BORDER_CLOSE_V_CENTER_OPEN_V 10 // vertically close to center, reopen from center +#define K_ANIMATE_LEFT_CLOSE_RIGHT_OPEN 11 // close to right, reopen from right +#define K_ANIMATE_RIGHT_CLOSE_LEFT_OPEN 12 // close to left, reopen from left +#define K_ANIMATE_TOP_CLOSE_BOTTOM_OPEN 13 // close to bottom, reopen from bottom +#define K_ANIMATE_BOTTOM_CLOSE_TOP_OPEN 14 // close to top, reopen from top +#define K_ANIMATE_CENTER_CLOSE_F_BORDER_OPEN_F 15 // close from center to edges, +// reopen from edges to center +#define K_ANIMATE_BORDER_CLOSE_F_CENTER_OPEN_F 16 // close from edges to center, reopen from +// center to edges */ +#define K_ANIMATE_CLOSE_CHECKERS_OPEN_CHECKERS 17 // close random checkboard, reopen +#define K_ANIMATE_PALETTE_FADEOUT_FADEIN 0x1e +#define K_ANIMATE_SCROLL_LEFT 0x28 +#define K_ANIMATE_SCROLL_RIGHT 0x29 +#define K_ANIMATE_SCROLL_DOWN 0x2a +#define K_ANIMATE_SCROLL_UP 0x2b + +#define GRAPH_BLANK_BOX(s, x, y, xl, yl, color) gfxop_fill_box(s->gfx_state, \ + gfx_rect(x, (((y) < 10)? 10 : (y)), xl, (((y) < 10)? ((y) - 10) : 0) + (yl)), s->ega_colors[color]); + +#define GRAPH_UPDATE_BOX(s, x, y, xl, yl) gfxop_draw_pixmap(s->gfx_state, newscreen, \ + gfx_rect(x, (((y) < 10)? 10 : (y)) - 10, xl, (((y) < 10)? ((y) - 10) : 0) + (yl)), Common::Point(x, ((y) < 10)? 10 : (y) )); + +void SciGUI32::animate_do_animation(int argc, reg_t *argv) { + long animation_delay = 5; + int i, remaining_checkers; + int update_counter; + // Number of animation steps to perform betwen updates for transition animations + int animation_granularity = 4; + int granularity0 = animation_granularity << 1; + int granularity1 = animation_granularity; + int granularity2 = animation_granularity >> 2; + int granularity3 = animation_granularity >> 4; + char checkers[32 * 19]; + gfx_pixmap_t *newscreen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190)); + + if (!granularity2) + granularity2 = 1; + if (!granularity3) + granularity3 = 1; + + gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen); + + if (!newscreen) { + error("Failed to allocate 'newscreen'"); + return; + } + + gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320, 190), Common::Point(0, 10)); + gfxop_update_box(s->gfx_state, gfx_rect(0, 0, 320, 200)); + + //debugC(2, kDebugLevelGraphics, "Animating pic opening type %x\n", s->pic_animate); + + gfxop_enable_dirty_frames(s->gfx_state); + + switch (s->pic_animate) { + case K_ANIMATE_BORDER_CLOSE_H_CENTER_OPEN_H : + for (i = 0; i < 159 + granularity1; i += granularity1) { + GRAPH_BLANK_BOX(s, i, 10, granularity1, 190, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, 319 - i, 10, granularity1, 190, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_CENTER_OPEN_H : + + for (i = 159; i >= 1 - granularity1; i -= granularity1) { + GRAPH_UPDATE_BOX(s, i, 10, granularity1, 190); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, 319 - i, 10, granularity1, 190); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_BORDER_CLOSE_V_CENTER_OPEN_V : + + for (i = 0; i < 94 + granularity2; i += granularity2) { + GRAPH_BLANK_BOX(s, 0, i + 10, 320, granularity2, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, 0, 199 - i, 320, granularity2, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, 2 * animation_delay / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_CENTER_OPEN_V : + + for (i = 94; i >= 1 - granularity2; i -= granularity2) { + GRAPH_UPDATE_BOX(s, 0, i + 10, 320, granularity2); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, 0, 199 - i, 320, granularity2); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, 2 * animation_delay / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_LEFT_CLOSE_RIGHT_OPEN : + + for (i = 0; i < 319 + granularity0; i += granularity0) { + GRAPH_BLANK_BOX(s, i, 10, granularity0, 190, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_RIGHT_OPEN : + for (i = 319; i >= 1 - granularity0; i -= granularity0) { + GRAPH_UPDATE_BOX(s, i, 10, granularity0, 190); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_RIGHT_CLOSE_LEFT_OPEN : + + for (i = 319; i >= 1 - granularity0; i -= granularity0) { + GRAPH_BLANK_BOX(s, i, 10, granularity0, 190, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_LEFT_OPEN : + + for (i = 0; i < 319 + granularity0; i += granularity0) { + GRAPH_UPDATE_BOX(s, i, 10, granularity0, 190); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 2 / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_TOP_CLOSE_BOTTOM_OPEN : + + for (i = 10; i < 199 + granularity1; i += granularity1) { + GRAPH_BLANK_BOX(s, 0, i, 320, granularity1, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_BOTTOM_OPEN : + + for (i = 199; i >= 11 - granularity1; i -= granularity1) { + GRAPH_UPDATE_BOX(s, 0, i, 320, granularity1); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_BOTTOM_CLOSE_TOP_OPEN : + + for (i = 199; i >= 11 - granularity1; i -= granularity1) { + GRAPH_BLANK_BOX(s, 0, i, 320, granularity1, 0); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + GRAPH_BLANK_BOX(s, 0, 10, 320, 190, 0); + + case K_ANIMATE_TOP_OPEN : + + for (i = 10; i < 199 + granularity1; i += granularity1) { + GRAPH_UPDATE_BOX(s, 0, i, 320, granularity1); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, animation_delay / 1000); + process_sound_events(s); + } + break; + + + case K_ANIMATE_CENTER_CLOSE_F_BORDER_OPEN_F : + + for (i = 31; i >= 1 - granularity3; i -= granularity3) { + int real_i = (i < 0) ? 0 : i; + int height_l = 3 * (granularity3 - real_i + i); + int width_l = 5 * (granularity3 - real_i + i); + int height = real_i * 3; + int width = real_i * 5; + + GRAPH_BLANK_BOX(s, width, 10 + height, width_l, 190 - 2 * height, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height, 0); + gfxop_update(s->gfx_state); + + GRAPH_BLANK_BOX(s, width, 10 + height, 320 - 2 * width, height_l, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l, 0); + gfxop_update(s->gfx_state); + + gfxop_sleep(s->gfx_state, 4 * animation_delay / 1000); + process_sound_events(s); + } + + case K_ANIMATE_BORDER_OPEN_F : + + for (i = 0; i < 31 + granularity3; i += granularity3) { + int real_i = (i < 0) ? 0 : i; + int height_l = 3 * (granularity3 - real_i + i); + int width_l = 5 * (granularity3 - real_i + i); + int height = real_i * 3; + int width = real_i * 5; + + GRAPH_UPDATE_BOX(s, width, 10 + height, width_l, 190 - 2 * height); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height); + gfxop_update(s->gfx_state); + + GRAPH_UPDATE_BOX(s, width, 10 + height, 320 - 2 * width, height_l); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l); + gfxop_update(s->gfx_state); + + gfxop_sleep(s->gfx_state, 4 * animation_delay / 1000); + process_sound_events(s); + } + + break; + + case K_ANIMATE_BORDER_CLOSE_F_CENTER_OPEN_F : + + for (i = 0; i < 31 + granularity3; i += granularity3) { + int real_i = (i < 0) ? 0 : i; + int height_l = 3 * (granularity3 - real_i + i); + int width_l = 5 * (granularity3 - real_i + i); + int height = real_i * 3; + int width = real_i * 5; + + GRAPH_BLANK_BOX(s, width, 10 + height, width_l, 190 - 2 * height, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2 * height, 0); + gfxop_update(s->gfx_state); + + GRAPH_BLANK_BOX(s, width, 10 + height, 320 - 2 * width, height_l, 0); + gfxop_update(s->gfx_state); + GRAPH_BLANK_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l, 0); + gfxop_update(s->gfx_state); + + gfxop_sleep(s->gfx_state, 7 * animation_delay / 1000); + process_sound_events(s); + } + + case K_ANIMATE_CENTER_OPEN_F : + + for (i = 31; i >= 1 - granularity3; i -= granularity3) { + int real_i = (i < 0) ? 0 : i; + int height_l = 3 * (granularity3 - real_i + i); + int width_l = 5 * (granularity3 - real_i + i); + int height = real_i * 3; + int width = real_i * 5; + + GRAPH_UPDATE_BOX(s, width, 10 + height, width_l, 190 - 2 * height); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, 320 - width_l - width, 10 + height, width_l, 190 - 2*height); + gfxop_update(s->gfx_state); + + GRAPH_UPDATE_BOX(s, width, 10 + height, 320 - 2 * width, height_l); + gfxop_update(s->gfx_state); + GRAPH_UPDATE_BOX(s, width, 200 - height_l - height, 320 - 2 * width, height_l); + gfxop_update(s->gfx_state); + + gfxop_sleep(s->gfx_state, 7 * animation_delay / 1000); + process_sound_events(s); + } + break; + + case K_ANIMATE_PALETTE_FADEOUT_FADEIN: + warning("TODO: Palette fadeout/fadein"); + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + break; + + case K_ANIMATE_CLOSE_CHECKERS_OPEN_CHECKERS : + + memset(checkers, 0, sizeof(checkers)); + remaining_checkers = 19 * 32; + update_counter = granularity1; + + while (remaining_checkers) { + int x, y, checker = 1 + (int)(1.0 * remaining_checkers * rand() / (RAND_MAX + 1.0)); + i = -1; + + while (checker) + if (checkers[++i] == 0) + --checker; + checkers[i] = 1; // Mark checker as used + + x = i % 32; + y = i / 32; + + GRAPH_BLANK_BOX(s, x * 10, 10 + y * 10, 10, 10, 0); + if (!(update_counter--) || (remaining_checkers == 1)) { + gfxop_update(s->gfx_state); + update_counter = granularity1; + } + + if (remaining_checkers & 1) { + gfxop_sleep(s->gfx_state, animation_delay / 4 / 1000); + } + + --remaining_checkers; + process_sound_events(s); + } + + case K_ANIMATE_OPEN_CHECKERS : + + memset(checkers, 0, sizeof(checkers)); + remaining_checkers = 19 * 32; + update_counter = granularity1; + + while (remaining_checkers) { + int x, y, checker = 1 + (int)(1.0 * remaining_checkers * rand() / (RAND_MAX + 1.0)); + i = -1; + + while (checker) + if (checkers[++i] == 0) --checker; + checkers[i] = 1; // Mark checker as used + + x = i % 32; + y = i / 32; + + GRAPH_UPDATE_BOX(s, x * 10, 10 + y * 10, 10, 10); + + if (!(update_counter--) || (remaining_checkers == 1)) { + gfxop_update(s->gfx_state); + update_counter = granularity1; + } + + if (remaining_checkers & 1) { + gfxop_sleep(s->gfx_state, animation_delay / 4 / 1000); + } + + --remaining_checkers; + process_sound_events(s); + } + break; + + + case K_ANIMATE_SCROLL_LEFT : + + for (i = 0; i < 319; i += granularity0) { + gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(320 - i, 0, i, 190), Common::Point(0, 10)); + gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320 - i, 190), Common::Point(i, 10)); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); + } + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + break; + + case K_ANIMATE_SCROLL_RIGHT : + + for (i = 0; i < 319; i += granularity0) { + gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 0, i, 190), Common::Point(319 - i, 10)); + gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(i, 0, 320 - i, 190), Common::Point(0, 10)); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); + } + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + break; + + case K_ANIMATE_SCROLL_UP : + + for (i = 0; i < 189; i += granularity0) { + gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 190 - i, 320, i), Common::Point(0, 10)); + gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, 0, 320, 190 - i), Common::Point(0, 10 + i)); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); + } + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + break; + + case K_ANIMATE_SCROLL_DOWN : + + for (i = 0; i < 189; i += granularity0) { + gfxop_draw_pixmap(s->gfx_state, newscreen, gfx_rect(0, 0, 320, i), Common::Point(0, 200 - i)); + gfxop_draw_pixmap(s->gfx_state, s->old_screen, gfx_rect(0, i, 320, 190 - i), Common::Point(0, 10)); + gfxop_update(s->gfx_state); + gfxop_sleep(s->gfx_state, (animation_delay >> 3) / 1000); + } + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + break; + + default: + warning("Unknown opening animation 0x%02x", s->pic_animate); + GRAPH_UPDATE_BOX(s, 0, 10, 320, 190); + + } + + gfxop_free_pixmap(s->gfx_state, s->old_screen); + gfxop_free_pixmap(s->gfx_state, newscreen); + s->old_screen = NULL; +} + +void SciGUI32::animate(reg_t listReference, bool cycle, int argc, reg_t *argv) { + // Animations are supposed to take a maximum of animation_delay milliseconds. + List *cast_list = NULL; + int open_animation = 0; + + process_sound_events(s); // Take care of incoming events (kAnimate is called semi-regularly) + _k_animate_ran = true; // Used by some of the invoked functions to check for recursion, which may, + // after all, damage the cast list + + if (listReference.segment) { + cast_list = lookup_list(s, listReference); + if (!cast_list) + return; + } + + open_animation = (s->pic_is_new) && (s->pic_not_valid); + s->pic_is_new = 0; + + assert_primary_widget_lists(s); + + if (!s->dyn_views->_contents // Only reparentize empty dynview list + && (((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) // If dynviews are on other port... + || (s->dyn_views->_next))) // ... or not on top of the view list + reparentize_primary_widget_lists(s, s->port); + + if (cast_list) { + GfxList *templist = gfxw_new_list(s->dyn_views->_bounds, 0); + + _k_make_view_list(&(templist), cast_list, (cycle ? _K_MAKE_VIEW_LIST_CYCLE : 0) + | _K_MAKE_VIEW_LIST_CALC_PRIORITY, argc, (reg_t *)argv); + + // Make sure that none of the doits() did something evil + assert_primary_widget_lists(s); + + if (!s->dyn_views->_contents // Only reparentize empty dynview list + && (((GfxContainer *)s->port != (GfxContainer *)s->dyn_views->_parent) // If dynviews are on other port... + || (s->dyn_views->_next))) // ... or not on top of the view list + reparentize_primary_widget_lists(s, s->port); + // End of doit() recovery code + + if (s->pic_is_new) { // Happens if DrawPic() is executed by a dynview (yes, that happens) + animate(listReference, cycle, argc, argv); /* Tail-recurse */ + return; + } + + debugC(2, kDebugLevelGraphics, "Handling Dynviews (..step 9 inclusive):\n"); + _k_prepare_view_list(templist, _K_MAKE_VIEW_LIST_CALC_PRIORITY); + + if (s->pic_not_valid) { + debugC(2, kDebugLevelGraphics, "PicNotValid=%d -> Subalgorithm:\n", s->pic_not_valid); + _k_redraw_view_list(templist); + } + + _k_update_signals_in_view_list(s->dyn_views, templist); + s->dyn_views->tag(); + + _k_raise_topmost_in_view_list(s->dyn_views, (GfxDynView *)templist->_contents); + + delete templist; + s->dyn_views->free_tagged((GfxContainer *)s->dyn_views); // Free obsolete dynviews + } // if (cast_list) + + if (open_animation) { + gfxop_clear_box(s->gfx_state, gfx_rect(0, 10, 320, 190)); // Propagate pic + s->visual->add_dirty_abs((GfxContainer *)s->visual, gfx_rect_fullscreen, 0); + // Mark screen as dirty so picviews will be drawn correctly + FULL_REDRAW(); + + animate_do_animation(argc, (reg_t*)argv); + } // if (open_animation) + + if (cast_list) { + int retval; + int reparentize = 0; + + s->pic_not_valid = 0; + + _k_view_list_do_postdraw(s->dyn_views); + + // _k_view_list_dispose_loop() returns -1 if it requested a re-start, so we do just that. + while ((retval = _k_view_list_dispose_loop(cast_list, (GfxDynView *) s->dyn_views->_contents, argc, (reg_t *)argv) < 0)) + reparentize = 1; + + if (s->drop_views->_contents) { + s->drop_views = gfxw_new_list(s->dyn_views->_bounds, GFXW_LIST_SORTED); + s->drop_views->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; + ADD_TO_CURRENT_PICTURE_PORT(s->drop_views); + } else { + assert(s->drop_views); + gfxw_remove_widget_from_container(s->drop_views->_parent, s->drop_views); + ADD_TO_CURRENT_PICTURE_PORT(s->drop_views); + } + + if ((reparentize | retval) + && ((GfxContainer *)s->port == (GfxContainer *)s->dyn_views->_parent) // If dynviews are on the same port... + && (s->dyn_views->_next)) // ... and not on top of the view list... + reparentize_primary_widget_lists(s, s->port); // ...then reparentize. + + _k_view_list_kryptonize(s->dyn_views->_contents); + } + + FULL_REDRAW(); +} + +void SciGUI32::addToPicList(reg_t listReference, int argc, reg_t *argv) { + List *list; + GfxList *pic_views; + + assert_primary_widget_lists(s); + + if (!listReference.segment) { + warning("Attempt to AddToPic single non-list: %04x:%04x", PRINT_REG(listReference)); + return; + } + + list = lookup_list(s, listReference); + + pic_views = gfxw_new_list(s->picture_port->_bounds, 1); + + debugC(2, kDebugLevelGraphics, "Preparing picview list...\n"); + _k_make_view_list(&pic_views, list, 0, argc, argv); + _k_prepare_view_list(pic_views, _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP); + // Store pic views for later re-use + + debugC(2, kDebugLevelGraphics, "Drawing picview list...\n"); + ADD_TO_CURRENT_PICTURE_PORT(pic_views); + _k_draw_view_list(pic_views, _K_DRAW_VIEW_LIST_NONDISPOSEABLE | _K_DRAW_VIEW_LIST_DISPOSEABLE | _K_DRAW_VIEW_LIST_PICVIEW); + // Draw relative to the bottom center + debugC(2, kDebugLevelGraphics, "Returning.\n"); + + reparentize_primary_widget_lists(s, s->port); +} + +void SciGUI32::addToPicView(sciResourceId viewId, uint16 loopNo, uint16 cellNo, int16 leftPos, int16 topPos, int16 priority, int16 control) { + assert_primary_widget_lists(s); + + GfxWidget *widget; + + topPos++; // magic +1 + + widget = gfxw_new_dyn_view(s->gfx_state, Common::Point(leftPos, topPos), 0, viewId, loopNo, cellNo, 0, priority, -1 /* No priority */ , ALIGN_CENTER, ALIGN_BOTTOM, 0); + + if (!widget) { + error("Attempt to single-add invalid picview (%d/%d/%d)", viewId, loopNo, cellNo); + } else { + widget->_ID = -1; + if (control >= 0) { + Common::Rect abs_zone = nsrect_clip(s, topPos, calculate_nsrect(s, leftPos, topPos, viewId, loopNo, cellNo), priority); + draw_rect_to_control_map(abs_zone); + } + ADD_TO_CURRENT_PICTURE_PORT(gfxw_picviewize_dynview((GfxDynView *) widget)); + } + return; +} + +void SciGUI32::setNowSeen(reg_t objectReference) { + _k_set_now_seen(objectReference); +} + + void SciGUI32::moveCursor(int16 x, int16 y) { Common::Point newPos; diff --git a/engines/sci/gui32/gui32.h b/engines/sci/gui32/gui32.h index 5a50b3dd3e..7f5fe7fe64 100644 --- a/engines/sci/gui32/gui32.h +++ b/engines/sci/gui32/gui32.h @@ -68,6 +68,10 @@ public: void paletteAnimate(int fromColor, int toColor, int speed); int16 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(sciResourceId viewId, uint16 loopNo, uint16 cellNo, int16 leftPos, int16 topPos, int16 priority, int16 control); + void setNowSeen(reg_t objectReference); void moveCursor(int16 x, int16 y); @@ -76,6 +80,23 @@ private: EngineState *s; bool _usesOldGfxFunctions; + GfxDynView *_k_make_dynview_obj(reg_t obj, int options, int nr, int argc, reg_t *argv); + void _k_make_view_list(GfxList **widget_list, List *list, int options, int argc, reg_t *argv); + void draw_obj_to_control_map(GfxDynView *view); + void draw_rect_to_control_map(Common::Rect abs_zone); + int _k_view_list_dispose_loop(List *list, GfxDynView *widget, int argc, reg_t *argv); + void _k_set_now_seen(reg_t object); + void _k_prepare_view_list(GfxList *list, int options); + void _k_update_signals_in_view_list(GfxList *old_list, GfxList *new_list); + void _k_view_list_kryptonize(GfxWidget *v); + void _k_raise_topmost_in_view_list(GfxList *list, GfxDynView *view); + void _k_redraw_view_list(GfxList *list); + void _k_draw_view_list(GfxList *list, int flags); + void _k_view_list_do_postdraw(GfxList *list); + void animate_do_animation(int argc, reg_t *argv); + + bool _k_animate_ran; // FIXME: Avoid non-const global vars + bool activated_icon_bar; // FIXME: Avoid non-const global vars int port_origin_x; // FIXME: Avoid non-const global vars int port_origin_y; // FIXME: Avoid non-const global vars diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 11c86d8ed8..33124f50bb 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -35,6 +35,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" +#include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual #include "sci/gui32/gui32.h" #include "sci/gfx/gfx_resource.h" |