diff options
author | Filippos Karapetis | 2009-10-13 20:25:51 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-10-13 20:25:51 +0000 |
commit | b49d6d950b1bca350baea7a9437071cf5823af5f (patch) | |
tree | 64376210aec03501140231df0f7137bd5639bb01 /engines/sci/gui32 | |
parent | 73fa80d94088cfac87f4302112bff5c3b2fb9754 (diff) | |
download | scummvm-rg350-b49d6d950b1bca350baea7a9437071cf5823af5f.tar.gz scummvm-rg350-b49d6d950b1bca350baea7a9437071cf5823af5f.tar.bz2 scummvm-rg350-b49d6d950b1bca350baea7a9437071cf5823af5f.zip |
Moved some old GUI specific code from kgraphics.cpp into gui32.cpp
svn-id: r45047
Diffstat (limited to 'engines/sci/gui32')
-rw-r--r-- | engines/sci/gui32/gui32.cpp | 460 |
1 files changed, 387 insertions, 73 deletions
diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index 83c12d5c37..e6a525dd9b 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -66,6 +66,393 @@ namespace Sci { +#undef DEBUG_LSRECT + +// This is the real width of a text with a specified width of 0 +#define MAX_TEXT_WIDTH_MAGIC_VALUE 192 + +#define ADD_TO_CURRENT_PORT(widget) \ + {if (s->port) \ + s->port->add((GfxContainer *)s->port, widget); \ + else \ + s->picture_port->add((GfxContainer *)s->visual, widget);} + +#define ADD_TO_CURRENT_PICTURE_PORT(widget) \ + {if (s->port) \ + s->port->add((GfxContainer *)s->port, widget); \ + else \ + s->picture_port->add((GfxContainer *)s->picture_port, widget);} + +#define ADD_TO_WINDOW_PORT(widget) \ + s->wm_port->add((GfxContainer *)s->wm_port, widget); + +#define FULL_REDRAW()\ + if (s->visual) \ + s->visual->draw(gfxw_point_zero); \ + gfxop_update(s->gfx_state); + +#if 0 +// Used for debugging +#define FULL_INSPECTION()\ + if (s->visual) \ + s->visual->print(s->visual, 0); +#endif + +// was static +void assert_primary_widget_lists(EngineState *s) { + if (!s->dyn_views) { + rect_t bounds = s->picture_port->_bounds; + + s->dyn_views = gfxw_new_list(bounds, GFXW_LIST_SORTED); + s->dyn_views->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; + ADD_TO_CURRENT_PICTURE_PORT(s->dyn_views); + } + + if (!s->drop_views) { + rect_t bounds = s->picture_port->_bounds; + + s->drop_views = gfxw_new_list(bounds, GFXW_LIST_SORTED); + s->drop_views->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS; + ADD_TO_CURRENT_PICTURE_PORT(s->drop_views); + } +} + +// static +void reparentize_primary_widget_lists(EngineState *s, GfxPort *newport) { + if (!newport) + newport = s->picture_port; + + if (s->dyn_views) { + gfxw_remove_widget_from_container(s->dyn_views->_parent, s->dyn_views); + + newport->add((GfxContainer *)newport, s->dyn_views); + } +} + +int _find_view_priority(EngineState *s, int y) { + /*if (s->version <= SCI_VERSION_LTU_PRIORITY_OB1) + ++y; */ + + if (s->pic_priority_table) { // SCI01 priority table set? + int j; + for (j = 0; j < 15; j++) + if (y < s->pic_priority_table[j+1]) + return j; + return 14; // Maximum + } else { + if (!s->usesOldGfxFunctions()) + return SCI0_VIEW_PRIORITY_14_ZONES(y); + else + return SCI0_VIEW_PRIORITY(y) == 15 ? 14 : SCI0_VIEW_PRIORITY(y); + } +} + +int _find_priority_band(EngineState *s, int nr) { + if (!s->usesOldGfxFunctions() && (nr < 0 || nr > 14)) { + if (nr == 15) + return 0xffff; + else { + warning("Attempt to get priority band %d", nr); + } + return 0; + } + + if (s->usesOldGfxFunctions() && (nr < 0 || nr > 15)) { + warning("Attempt to get priority band %d", nr); + return 0; + } + + if (s->pic_priority_table) // SCI01 priority table set? + return s->pic_priority_table[nr]; + else { + int retval; + + if (!s->usesOldGfxFunctions()) + retval = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr); + else + retval = SCI0_PRIORITY_BAND_FIRST(nr); + +/* if (s->version <= SCI_VERSION_LTU_PRIORITY_OB1) + --retval; */ + return retval; + } +} + +reg_t graph_save_box(EngineState *s, rect_t area) { + reg_t handle = kalloc(s->_segMan, "graph_save_box()", sizeof(gfxw_snapshot_t *)); + gfxw_snapshot_t **ptr = (gfxw_snapshot_t **)kmem(s->_segMan, handle); + + // FIXME: gfxw_make_snapshot returns a pointer. Now why do we store a + // pointer to real memory inside the SCI heap? + // If we save and the load again, this cannot work in general. + // This seems like bad design. Either the snapshot data itself should be + // stored in the heap, or a unique persistent id. + *ptr = gfxw_make_snapshot(s->visual, area); + + return handle; +} + +void graph_restore_box(EngineState *s, reg_t handle) { + gfxw_snapshot_t **ptr; + int port_nr = s->port->_ID; + + if (!handle.segment) { + warning("Attempt to restore box with zero handle"); + return; + } + + ptr = (gfxw_snapshot_t **)kmem(s->_segMan, handle); + + if (!ptr) { + warning("Attempt to restore invalid handle %04x:%04x", PRINT_REG(handle)); + return; + } + + while (port_nr > 2 && !(s->port->_flags & GFXW_FLAG_IMMUNE_TO_SNAPSHOTS) && (gfxw_widget_matches_snapshot(*ptr, s->port))) { + // This shouldn't ever happen, actually, since windows (ports w/ ID > 2) should all be immune + GfxPort *newport = s->visual->getPort(port_nr); + error("Port %d is not immune against snapshots", s->port->_ID); + port_nr--; + if (newport) + s->port = newport; + } + + if (s->dyn_views && gfxw_widget_matches_snapshot(*ptr, s->dyn_views->_parent)) { + GfxContainer *parent = s->dyn_views->_parent; + + do { + parent = parent->_parent; + } while (parent && (gfxw_widget_matches_snapshot(*ptr, parent))); + + if (!parent) { + error("Attempted widget mass destruction by a snapshot"); + } + + reparentize_primary_widget_lists(s, (GfxPort *) parent); + } + + + if (!ptr) { + error("Attempt to restore invalid snaphot with handle %04x:%04x", PRINT_REG(handle)); + return; + } + + gfxw_restore_snapshot(s->visual, *ptr); + free(*ptr); + *ptr = NULL; + + kfree(s->_segMan, handle); +} + +PaletteEntry get_pic_color(EngineState *s, int color) { + if (!s->resMan->isVGA()) + return s->ega_colors[color].visual; + + if (color == -1 || color == 255) // -1 occurs in Eco Quest 1. Not sure if this is the best approach, but it seems to work + return PaletteEntry(255,255,255); + else if (color < s->gfx_state->gfxResMan->getColorCount()) + return s->gfx_state->gfxResMan->getColor(color); + else { + // Happens in the beginning of EcoQuest 2, when the dialog box of the customs officer shows up + warning("Color index %d out of bounds for pic %d (%d max)", color, s->gfx_state->pic_nr, s->gfx_state->gfxResMan->getColorCount()); + return PaletteEntry(0,0,0); + } +} + +void _k_redraw_box(EngineState *s, int x1, int y1, int x2, int y2) { + warning("_k_redraw_box(): Unimplemented"); +#if 0 + int i; + ViewObject *list = s->dyn_views; + + printf("Reanimating views\n", s->dyn_views_nr); + + for (i = 0;i < s->dyn_views_nr;i++) { + *(list[i].underBitsp) = graph_save_box(s, list[i].nsLeft, list[i].nsTop, list[i].nsRight - list[i].nsLeft, + list[i].nsBottom - list[i].nsTop, SCI_MAP_VISUAL | SCI_MAP_PRIORITY); + draw_view0(s->pic, s->ports[0], list[i].nsLeft, list[i].nsTop, list[i].priority, list[i].loop, + list[i].cel, 0, list[i].view); + } + + graph_update_box(s, x1, y1, x2 - x1, y2 - y1); + + for (i = 0;i < s->dyn_views_nr;i++) { + graph_restore_box(s, *(list[i].underBitsp)); + list[i].underBits = 0; + } +#endif +} + +Common::Rect set_base(EngineState *s, reg_t object) { + SegManager *segMan = s->_segMan; + int x, y, original_y, z, ystep, xsize, ysize; + int xbase, ybase, xend, yend; + int view, loop, cel; + int oldloop, oldcel; + int xmod = 0, ymod = 0; + Common::Rect retval; + + x = (int16)GET_SEL32V(object, x); + original_y = 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 + + ystep = (int16)GET_SEL32V(object, yStep); + + view = (int16)GET_SEL32V(object, view); + int l = GET_SEL32V(object, loop); + oldloop = loop = (l & 0x80) ? l - 256 : l; + int c = GET_SEL32V(object, cel); + oldcel = cel = (c & 0x80) ? c - 256 : c; + + Common::Point offset = Common::Point(0, 0); + + if (loop != oldloop) { + loop = 0; + PUT_SEL32V(object, loop, 0); + debugC(2, kDebugLevelGraphics, "Resetting loop for %04x:%04x!\n", PRINT_REG(object)); + } + + if (cel != oldcel) { + cel = 0; + PUT_SEL32V(object, cel, 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; + ybase = yend - ystep; + + debugC(2, kDebugLevelBaseSetter, "(%d,%d)+/-(%d,%d), (%d x %d) -> (%d, %d) to (%d, %d)\n", + x, y, xmod, ymod, xsize, ysize, xbase, ybase, xend, yend); + + retval.left = xbase; + retval.top = ybase; + retval.right = xend; + retval.bottom = yend; + + return retval; +} + +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_nsrect(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); + int l = (int16)GET_SEL32V(object, loop); + loop = (l & 0x80) ? l - 256 : l; + int c = (int16)GET_SEL32V(object, cel); + cel = (c & 0x80) ? c - 256 : c; + + 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; +} + +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); + int l = (int16)GET_SEL32V(object, loop); + loop = (l & 0x80) ? l - 256 : l; + int c = (int16)GET_SEL32V(object, cel); + cel = (c & 0x80) ? c - 256 : c; + + 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; +} + +// ====================================================================================================== + SciGui32::SciGui32( EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette, SciGuiCursor *cursor) : s(state) { _cursor = cursor; @@ -1081,79 +1468,6 @@ enum { _K_MAKE_VIEW_LIST_DRAW_TO_CONTROL_MAP = 4 }; -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; |