diff options
31 files changed, 1659 insertions, 1406 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8f13c8c42d..782072a229 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -36,6 +36,7 @@ #include "sci/engine/kernel.h" #include "sci/graphics/gui.h" #include "sci/graphics/gui32.h" +#include "sci/graphics/ports.h" #include "sci/graphics/animate.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" @@ -991,19 +992,19 @@ reg_t kAddToPic(EngineState *s, int argc, reg_t *argv) { } reg_t kGetPort(EngineState *s, int argc, reg_t *argv) { - return s->_gui->getPort(); + return s->_gfxPorts->kernelGetActive(); } reg_t kSetPort(EngineState *s, int argc, reg_t *argv) { - uint16 portPtr; + uint16 portId; Common::Rect picRect; int16 picTop, picLeft; bool initPriorityBandsFlag = false; switch (argc) { case 1: - portPtr = argv[0].toSint16(); - s->_gui->setPort(portPtr); + portId = argv[0].toSint16(); + s->_gfxPorts->kernelSetActive(portId); break; case 7: @@ -1016,7 +1017,7 @@ reg_t kSetPort(EngineState *s, int argc, reg_t *argv) { picRect.right = argv[3].toSint16(); picTop = (argc >= 6) ? argv[4].toSint16() : 0; picLeft = (argc >= 6) ? argv[5].toSint16() : 0; - s->_gui->setPortPic(picRect, picTop, picLeft, initPriorityBandsFlag); + s->_gfxPorts->kernelSetPicWindow(picRect, picTop, picLeft, initPriorityBandsFlag); break; default: @@ -1061,12 +1062,12 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { } reg_t kDisposeWindow(EngineState *s, int argc, reg_t *argv) { - int goner_nr = argv[0].toSint16(); + int windowId = argv[0].toSint16(); bool reanimate = false; if ((argc != 2) || (argv[1].isNull())) reanimate = true; - s->_gui->disposeWindow(goner_nr, reanimate); + s->_gfxPorts->kernelDisposeWindow(windowId, reanimate); return s->r_acc; } @@ -1090,7 +1091,7 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) { title = s->strSplit(title.c_str(), NULL); } - return s->_gui->newWindow(rect1, rect2, style, priority, colorPen, colorBack, title.c_str()); + return s->_gfxPorts->kernelNewWindow(rect1, rect2, style, priority, colorPen, colorBack, title.c_str()); } reg_t kAnimate(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index bf0f11c3a6..9c0fd9dc47 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -38,6 +38,7 @@ #include "sci/engine/vm_types.h" #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/graphics/gui.h" +#include "sci/graphics/ports.h" #include "sci/sound/audio.h" #ifdef USE_OLD_MUSIC_FUNCTIONS #include "sci/sound/iterator/core.h" @@ -366,7 +367,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { Common::Rect picPortRect; if (s.isSaving()) - picPortRect = _gui->getPortPic(picPortTop, picPortLeft); + picPortRect = _gfxPorts->kernelGetPicWindow(picPortTop, picPortLeft); s.syncAsSint16LE(picPortRect.top); s.syncAsSint16LE(picPortRect.left); diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index fd751a894b..31c46c4447 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -51,6 +51,7 @@ namespace Sci { class SciEvent; class Menubar; +class GfxPorts; class SciGui; class Cursor; class MessageState; @@ -147,6 +148,7 @@ public: /* Non-VM information */ + GfxPorts *_gfxPorts; // Port managment for 16-bit gui SciGui *_gui; /* Currently active Gui */ #ifdef ENABLE_SCI32 diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 8718fa4f97..55cccdc3a7 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -31,7 +31,9 @@ #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/transitions.h" @@ -39,8 +41,8 @@ namespace Sci { -SciGuiAnimate::SciGuiAnimate(EngineState *state, Gfx *gfx, Screen *screen, SciPalette *palette) - : _s(state), _gfx(gfx), _screen(screen), _palette(palette) { +SciGuiAnimate::SciGuiAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, Screen *screen, SciPalette *palette) + : _s(state), _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _palette(palette) { init(); } @@ -211,7 +213,7 @@ void SciGuiAnimate::fill(byte &old_picNotValid) { curObject = listEntry->object; // Get the corresponding view - view = _gfx->getView(listEntry->viewId); + view = _cache->getView(listEntry->viewId); // adjust loop and cel, if any of those is invalid if (listEntry->loopNo >= view->getLoopCount()) { @@ -238,7 +240,7 @@ void SciGuiAnimate::fill(byte &old_picNotValid) { // Calculate current priority according to y-coordinate if (!(signal & kSignalFixedPriority)) { - listEntry->priority = _gfx->CoordinateToPriority(listEntry->y); + listEntry->priority = _ports->coordinateToPriority(listEntry->y); PUT_SEL32V(_s->_segMan, curObject, priority, listEntry->priority); } @@ -281,10 +283,10 @@ void SciGuiAnimate::update() { if (!(signal & kSignalRemoveView)) { bitsHandle = GET_SEL32(_s->_segMan, curObject, underBits); if (_screen->_picNotValid != 1) { - _gfx->BitsRestore(bitsHandle); + _paint16->bitsRestore(bitsHandle); listEntry->showBitsFlag = true; } else { - _gfx->BitsFree(bitsHandle); + _paint16->bitsFree(bitsHandle); } PUT_SEL32V(_s->_segMan, curObject, underBits, 0); } @@ -306,14 +308,14 @@ void SciGuiAnimate::update() { if (signal & kSignalAlwaysUpdate) { // draw corresponding cel - _gfx->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); + _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); listEntry->showBitsFlag = true; signal &= 0xFFFF ^ (kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); if ((signal & kSignalIgnoreActor) == 0) { rect = listEntry->celRect; - rect.top = CLIP<int16>(_gfx->PriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); - _gfx->FillRect(rect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); + rect.top = CLIP<int16>(_ports->priorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + _paint16->fillRect(rect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); } listEntry->signal = signal; } @@ -333,9 +335,9 @@ void SciGuiAnimate::update() { } else { signal &= 0xFFFF ^ kSignalRemoveView; if (signal & kSignalIgnoreActor) - bitsHandle = _gfx->BitsSave(listEntry->celRect, SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY); + bitsHandle = _paint16->bitsSave(listEntry->celRect, SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY); else - bitsHandle = _gfx->BitsSave(listEntry->celRect, SCI_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(listEntry->celRect, SCI_SCREEN_MASK_ALL); PUT_SEL32(_s->_segMan, curObject, underBits, bitsHandle); } listEntry->signal = signal; @@ -352,13 +354,13 @@ void SciGuiAnimate::update() { if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) { // draw corresponding cel - _gfx->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); + _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); listEntry->showBitsFlag = true; if ((signal & kSignalIgnoreActor) == 0) { rect = listEntry->celRect; - rect.top = CLIP<int16>(_gfx->PriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); - _gfx->FillRect(rect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); + rect.top = CLIP<int16>(_ports->priorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + _paint16->fillRect(rect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); } } listIterator++; @@ -383,11 +385,11 @@ void SciGuiAnimate::drawCels() { if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) { // Save background - bitsHandle = _gfx->BitsSave(listEntry->celRect, SCI_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(listEntry->celRect, SCI_SCREEN_MASK_ALL); PUT_SEL32(_s->_segMan, curObject, underBits, bitsHandle); // draw corresponding cel - _gfx->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); + _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); listEntry->showBitsFlag = true; if (signal & kSignalRemoveView) { @@ -432,14 +434,14 @@ void SciGuiAnimate::updateScreen(byte oldPicNotValid) { workerRect = lsRect; workerRect.extend(listEntry->celRect); } else { - _gfx->BitsShow(lsRect); + _paint16->bitsShow(lsRect); workerRect = listEntry->celRect; } PUT_SEL32V(_s->_segMan, curObject, lsLeft, workerRect.left); PUT_SEL32V(_s->_segMan, curObject, lsTop, workerRect.top); PUT_SEL32V(_s->_segMan, curObject, lsRight, workerRect.right); PUT_SEL32V(_s->_segMan, curObject, lsBottom, workerRect.bottom); - _gfx->BitsShow(workerRect); + _paint16->bitsShow(workerRect); if (signal & kSignalHidden) { listEntry->signal |= kSignalRemoveView; @@ -481,7 +483,7 @@ void SciGuiAnimate::restoreAndDelete(int argc, reg_t *argv) { signal = GET_SEL32V(_s->_segMan, curObject, signal); if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) { - _gfx->BitsRestore(GET_SEL32(_s->_segMan, curObject, underBits)); + _paint16->bitsRestore(GET_SEL32(_s->_segMan, curObject, underBits)); PUT_SEL32V(_s->_segMan, curObject, underBits, 0); } @@ -501,20 +503,20 @@ void SciGuiAnimate::reAnimate(Common::Rect rect) { lastCastEntry = _lastCastData; lastCastCount = _lastCastCount; while (lastCastCount > 0) { - lastCastEntry->castHandle = _gfx->BitsSave(lastCastEntry->celRect, SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY); - _gfx->drawCel(lastCastEntry->viewId, lastCastEntry->loopNo, lastCastEntry->celNo, lastCastEntry->celRect, lastCastEntry->priority, lastCastEntry->paletteNo, lastCastEntry->scaleX, lastCastEntry->scaleY); + lastCastEntry->castHandle = _paint16->bitsSave(lastCastEntry->celRect, SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY); + _paint16->drawCel(lastCastEntry->viewId, lastCastEntry->loopNo, lastCastEntry->celNo, lastCastEntry->celRect, lastCastEntry->priority, lastCastEntry->paletteNo, lastCastEntry->scaleX, lastCastEntry->scaleY); lastCastEntry++; lastCastCount--; } - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); // restoring lastCastCount = _lastCastCount; while (lastCastCount > 0) { lastCastEntry--; - _gfx->BitsRestore(lastCastEntry->castHandle); + _paint16->bitsRestore(lastCastEntry->castHandle); lastCastCount--; } } else { - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } /* @@ -553,19 +555,19 @@ void SciGuiAnimate::addToPicDrawCels() { curObject = listEntry->object; if (listEntry->priority == -1) - listEntry->priority = _gfx->CoordinateToPriority(listEntry->y); + listEntry->priority = _ports->coordinateToPriority(listEntry->y); // Get the corresponding view - view = _gfx->getView(listEntry->viewId); + view = _cache->getView(listEntry->viewId); // Create rect according to coordinates and given cel view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect); // draw corresponding cel - _gfx->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo); + _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo); if ((listEntry->signal & kSignalIgnoreActor) == 0) { - listEntry->celRect.top = CLIP<int16>(_gfx->PriorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1); - _gfx->FillRect(listEntry->celRect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); + listEntry->celRect.top = CLIP<int16>(_ports->priorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1); + _paint16->fillRect(listEntry->celRect, SCI_SCREEN_MASK_CONTROL, 0, 0, 15); } listIterator++; @@ -573,12 +575,12 @@ void SciGuiAnimate::addToPicDrawCels() { } void SciGuiAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control) { - View *view = _gfx->getView(viewId); + View *view = _cache->getView(viewId); Common::Rect celRect; // Create rect according to coordinates and given cel view->getCelRect(loopNo, celNo, leftPos, topPos, priority, &celRect); - _gfx->drawCel(view, loopNo, celNo, celRect, priority, 0); + _paint16->drawCel(view, loopNo, celNo, celRect, priority, 0); } } // End of namespace Sci diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index db09342d4b..8dae1a6d46 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -56,13 +56,15 @@ enum ViewScaleSignals { kScaleSignalUnknown2 = 0x0004 // really unknown }; -class Gfx; +class GfxCache; +class GfxPorts; +class GfxPaint16; class Screen; class SciPalette; class Transitions; class SciGuiAnimate { public: - SciGuiAnimate(EngineState *state, Gfx *gfx, Screen *screen, SciPalette *palette); + SciGuiAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, Screen *screen, SciPalette *palette); ~SciGuiAnimate(); // FIXME: Don't store EngineState @@ -86,7 +88,9 @@ private: void init(); EngineState *_s; - Gfx *_gfx; + GfxCache *_cache; + GfxPorts *_ports; + GfxPaint16 *_paint16; Screen *_screen; SciPalette *_palette; diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp new file mode 100644 index 0000000000..2d204a2314 --- /dev/null +++ b/engines/sci/graphics/cache.cpp @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/font.h" +#include "sci/graphics/view.h" + +namespace Sci { + +GfxCache::GfxCache(ResourceManager *resMan, Screen *screen, SciPalette *palette) + : _resMan(resMan), _screen(screen), _palette(palette) { +} + +GfxCache::~GfxCache() { + purgeCache(); +} + +void GfxCache::purgeCache() { + for (ViewCache::iterator iter = _cachedViews.begin(); iter != _cachedViews.end(); ++iter) { + delete iter->_value; + iter->_value = 0; + } + + _cachedViews.clear(); +} + +View *GfxCache::getView(GuiResourceId viewNum) { + if (_cachedViews.size() >= MAX_CACHED_VIEWS) + purgeCache(); + + if (!_cachedViews.contains(viewNum)) + _cachedViews[viewNum] = new View(_resMan, _screen, _palette, viewNum); + + return _cachedViews[viewNum]; +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/windowmgr.h b/engines/sci/graphics/cache.h index dca6642000..1585003d0e 100644 --- a/engines/sci/graphics/windowmgr.h +++ b/engines/sci/graphics/cache.h @@ -23,47 +23,35 @@ * */ -#ifndef SCI_GRAPHICS_WINDOWMGR_H -#define SCI_GRAPHICS_WINDOWMGR_H +#ifndef SCI_GRAPHICS_CACHE_H +#define SCI_GRAPHICS_CACHE_H -#include "common/list.h" -#include "common/array.h" +#include "sci/graphics/gui.h" -namespace Sci { +#include "common/hashmap.h" -class WindowMgr { -public: - WindowMgr(SciGui *gui, Screen *screen, Gfx *gfx, Text *text); - ~WindowMgr(); +namespace Sci { - void init(Common::String gameId); +class Font; +class View; - int16 isFrontWindow(Window *wnd); - void BeginUpdate(Window *wnd); - void EndUpdate(Window *wnd); - Window *NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw); - void DrawWindow(Window *wnd); - void DisposeWindow(Window *pWnd, bool reanimate); - void UpdateWindow(Window *wnd); +typedef Common::HashMap<int, View *> ViewCache; - Port *getPortById(uint16 id); +class GfxCache { +public: + GfxCache(ResourceManager *resMan, Screen *screen, SciPalette *palette); + ~GfxCache(); - Port *_wmgrPort; - Window *_picWind; + View *getView(GuiResourceId viewNum); private: - typedef Common::List<Port *> PortList; + void purgeCache(); - SciGui *_gui; + ResourceManager *_resMan; Screen *_screen; - Gfx *_gfx; - Text *_text; - - /** The list of open 'windows' (and ports), in visual order. */ - PortList _windowList; + SciPalette *_palette; - /** The list of all open 'windows' (and ports), ordered by their id. */ - Common::Array<Port *> _windowsById; + ViewCache _cachedViews; }; } // End of namespace Sci diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp new file mode 100644 index 0000000000..e00fd52cba --- /dev/null +++ b/engines/sci/graphics/compare.cpp @@ -0,0 +1,131 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/view.h" + +namespace Sci { + +GfxCompare::GfxCompare(SegManager *segMan, Kernel *kernel, GfxCache *cache, Screen *screen) + : _segMan(segMan), _kernel(kernel), _cache(cache), _screen(screen) { +} + +GfxCompare::~GfxCompare() { +} + +uint16 GfxCompare::onControl(uint16 screenMask, Common::Rect rect) { + int16 x, y; + uint16 result = 0; + + if (rect.isEmpty()) + return 0; + + if (screenMask & SCI_SCREEN_MASK_PRIORITY) { + for (y = rect.top; y < rect.bottom; y++) { + for (x = rect.left; x < rect.right; x++) { + result |= 1 << _screen->getPriority(x, y); + } + } + } else { + for (y = rect.top; y < rect.bottom; y++) { + for (x = rect.left; x < rect.right; x++) { + result |= 1 << _screen->getControl(x, y); + } + } + } + return result; +} + +static inline int sign_extend_byte(int value) { + if (value & 0x80) + return value - 256; + else + return value; +} + +bool GfxCompare::CanBeHereCheckRectList(reg_t checkObject, Common::Rect checkRect, List *list) { + reg_t curAddress = list->first; + Node *curNode = _segMan->lookupNode(curAddress); + reg_t curObject; + uint16 signal; + Common::Rect curRect; + + while (curNode) { + curObject = curNode->value; + if (curObject != checkObject) { + signal = GET_SEL32V(_segMan, curObject, signal); + if ((signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate)) == 0) { + curRect.left = GET_SEL32V(_segMan, curObject, brLeft); + curRect.top = GET_SEL32V(_segMan, curObject, brTop); + curRect.right = GET_SEL32V(_segMan, curObject, brRight); + curRect.bottom = GET_SEL32V(_segMan, curObject, brBottom); + // Check if curRect is within checkRect + if (curRect.right > checkRect.left && curRect.left < checkRect.right && curRect.bottom > checkRect.top && curRect.top < checkRect.bottom) { + return false; + } + } + } + curAddress = curNode->succ; + curNode = _segMan->lookupNode(curAddress); + } + return true; +} + +void GfxCompare::SetNowSeen(reg_t objectReference) { + View *view = NULL; + Common::Rect celRect(0, 0); + GuiResourceId viewId = (GuiResourceId)GET_SEL32V(_segMan, objectReference, view); + int16 loopNo = sign_extend_byte((int16)GET_SEL32V(_segMan, objectReference, loop)); + int16 celNo = sign_extend_byte((int16)GET_SEL32V(_segMan, objectReference, cel)); + int16 x = (int16)GET_SEL32V(_segMan, objectReference, x); + int16 y = (int16)GET_SEL32V(_segMan, objectReference, y); + int16 z = 0; + if (_kernel->_selectorCache.z > -1) + z = (int16)GET_SEL32V(_segMan, objectReference, z); + + // now get cel rectangle + view = _cache->getView(viewId); + view->getCelRect(loopNo, celNo, x, y, z, &celRect); + + // TODO: sometimes loop is negative. Check what it means + if (lookup_selector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) { + PUT_SEL32V(_segMan, objectReference, nsLeft, celRect.left); + PUT_SEL32V(_segMan, objectReference, nsRight, celRect.right); + PUT_SEL32V(_segMan, objectReference, nsTop, celRect.top); + PUT_SEL32V(_segMan, objectReference, nsBottom, celRect.bottom); + } +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h new file mode 100644 index 0000000000..f759aad0aa --- /dev/null +++ b/engines/sci/graphics/compare.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_GRAPHICS_GFX_H +#define SCI_GRAPHICS_GFX_H + +#include "sci/graphics/gui.h" + +#include "common/hashmap.h" + +namespace Sci { + +class Screen; + +class GfxCompare { +public: + GfxCompare(SegManager *segMan, Kernel *kernel, GfxCache *cache, Screen *screen); + ~GfxCompare(); + + uint16 onControl(uint16 screenMask, Common::Rect rect); + bool CanBeHereCheckRectList(reg_t checkObject, Common::Rect checkRect, List *list); + void SetNowSeen(reg_t objectReference); + +private: + SegManager *_segMan; + Kernel *_kernel; + GfxCache *_cache; + Screen *_screen; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp index 24336b47da..2b097aaa26 100644 --- a/engines/sci/graphics/controls.cpp +++ b/engines/sci/graphics/controls.cpp @@ -31,15 +31,16 @@ #include "sci/event.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" #include "sci/graphics/font.h" #include "sci/graphics/text.h" #include "sci/graphics/controls.h" namespace Sci { -Controls::Controls(SegManager *segMan, Gfx *gfx, Text *text) - : _segMan(segMan), _gfx(gfx), _text(text) { +Controls::Controls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, Text *text) + : _segMan(segMan), _ports(ports), _paint16(paint16), _text(text) { init(); } @@ -56,7 +57,7 @@ const char controlListDownArrow[2] = { 0x19, 0 }; void Controls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { Common::Rect workerRect = rect; GuiResourceId oldFontId = _text->GetFontId(); - int16 oldPenColor = _gfx->_curPort->penClr; + int16 oldPenColor = _ports->_curPort->penClr; uint16 fontSize = 0; int16 i; const char *listEntry; @@ -64,9 +65,9 @@ void Controls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int int16 lastYpos; // draw basic window - _gfx->EraseRect(workerRect); + _paint16->eraseRect(workerRect); workerRect.grow(1); - _gfx->FrameRect(workerRect); + _paint16->frameRect(workerRect); // draw UP/DOWN arrows // we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel @@ -79,25 +80,25 @@ void Controls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int // Draw inner lines workerRect.top = rect.top + 9; workerRect.bottom -= 10; - _gfx->FrameRect(workerRect); + _paint16->frameRect(workerRect); workerRect.grow(-1); _text->SetFont(fontId); - fontSize = _gfx->_curPort->fontHeight; - _gfx->PenColor(_gfx->_curPort->penClr); _gfx->BackColor(_gfx->_curPort->backClr); + fontSize = _ports->_curPort->fontHeight; + _ports->penColor(_ports->_curPort->penClr); _ports->backColor(_ports->_curPort->backClr); workerRect.bottom = workerRect.top + 9; lastYpos = rect.bottom - fontSize; // Write actual text for (i = upperPos; i < count; i++) { - _gfx->EraseRect(workerRect); + _paint16->eraseRect(workerRect); listEntry = entries[i]; if (listEntry[0]) { - _gfx->MoveTo(workerRect.left, workerRect.top); + _ports->moveTo(workerRect.left, workerRect.top); listEntryLen = strlen(listEntry); _text->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); if ((!isAlias) && (i == cursorPos)) { - _gfx->InvertRect(workerRect); + _paint16->invertRect(workerRect); } } workerRect.translate(0, fontSize); @@ -119,8 +120,8 @@ void Controls::TexteditCursorDraw(Common::Rect rect, const char *text, uint16 cu _texteditCursorRect.top = rect.top; _texteditCursorRect.bottom = _texteditCursorRect.top + _text->_font->getHeight(); _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _text->_font->getCharWidth(text[curPos])); - _gfx->InvertRect(_texteditCursorRect); - _gfx->BitsShow(_texteditCursorRect); + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); _texteditCursorVisible = true; TexteditSetBlinkTime(); } @@ -128,8 +129,8 @@ void Controls::TexteditCursorDraw(Common::Rect rect, const char *text, uint16 cu void Controls::TexteditCursorErase() { if (_texteditCursorVisible) { - _gfx->InvertRect(_texteditCursorRect); - _gfx->BitsShow(_texteditCursorRect); + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); _texteditCursorVisible = false; } TexteditSetBlinkTime(); @@ -209,9 +210,9 @@ void Controls::TexteditChange(reg_t controlObject, reg_t eventObject) { rect = Common::Rect(GET_SEL32V(_segMan, controlObject, nsLeft), GET_SEL32V(_segMan, controlObject, nsTop), GET_SEL32V(_segMan, controlObject, nsRight), GET_SEL32V(_segMan, controlObject, nsBottom)); TexteditCursorErase(); - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); _text->Box(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); _text->SetFont(fontId); TexteditCursorDraw(rect, text.c_str(), cursorPos); _text->SetFont(oldFontId); @@ -219,8 +220,8 @@ void Controls::TexteditChange(reg_t controlObject, reg_t eventObject) { _segMan->strcpy(textReference, text.c_str()); } else { if (g_system->getMillis() >= _texteditBlinkTime) { - _gfx->InvertRect(_texteditCursorRect); - _gfx->BitsShow(_texteditCursorRect); + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); _texteditCursorVisible = !_texteditCursorVisible; TexteditSetBlinkTime(); } diff --git a/engines/sci/graphics/controls.h b/engines/sci/graphics/controls.h index 161dc1a1be..35c1098a0f 100644 --- a/engines/sci/graphics/controls.h +++ b/engines/sci/graphics/controls.h @@ -28,12 +28,13 @@ namespace Sci { -class Gfx; +class GfxPorts; +class GfxPaint16; class Font; class Text; class Controls { public: - Controls(SegManager *segMan, Gfx *gfx, Text *text); + Controls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, Text *text); ~Controls(); void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); @@ -46,7 +47,8 @@ private: void TexteditSetBlinkTime(); SegManager *_segMan; - Gfx *_gfx; + GfxPorts *_ports; + GfxPaint16 *_paint16; Text *_text; // Textedit-Control related diff --git a/engines/sci/graphics/gfx.cpp b/engines/sci/graphics/gfx.cpp deleted file mode 100644 index 652ec2eb58..0000000000 --- a/engines/sci/graphics/gfx.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/util.h" -#include "common/stack.h" -#include "graphics/primitives.h" - -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/gfx.h" -#include "sci/graphics/animate.h" -#include "sci/graphics/font.h" -#include "sci/graphics/picture.h" -#include "sci/graphics/view.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" -#include "sci/graphics/text.h" - -namespace Sci { - -Gfx::Gfx(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, Screen *screen, SciPalette *palette) - : _resMan(resMan), _segMan(segMan), _kernel(kernel), _screen(screen), _palette(palette) { -} - -Gfx::~Gfx() { - purgeCache(); - - delete _mainPort; - delete _menuPort; -} - -void Gfx::init(Text *text) { - _text = text; - - // _mainPort is not known to windowmanager, that's okay according to sierra sci - // its not even used currently in our engine - _mainPort = new Port(0); - SetPort(_mainPort); - OpenPort(_mainPort); - - // _menuPort has actually hardcoded id 0xFFFF. Its not meant to be known to windowmanager according to sierra sci - _menuPort = new Port(0xFFFF); - OpenPort(_menuPort); - _text->SetFont(0); - _menuPort->rect = Common::Rect(0, 0, _screen->getWidth(), _screen->getHeight()); - _menuBarRect = Common::Rect(0, 0, _screen->getWidth(), 9); - _menuRect = Common::Rect(0, 0, _screen->getWidth(), 10); - _menuLine = Common::Rect(0, 9, _screen->getWidth(), 10); - - _EGAdrawingVisualize = false; - - priorityBandsMemoryActive = false; -} - -void Gfx::purgeCache() { - for (ViewCache::iterator iter = _cachedViews.begin(); iter != _cachedViews.end(); ++iter) { - delete iter->_value; - iter->_value = 0; - } - - _cachedViews.clear(); -} - -View *Gfx::getView(GuiResourceId viewNum) { - if (_cachedViews.size() >= MAX_CACHED_VIEWS) - purgeCache(); - - if (!_cachedViews.contains(viewNum)) - _cachedViews[viewNum] = new View(_resMan, _screen, _palette, viewNum); - - return _cachedViews[viewNum]; -} - -Port *Gfx::SetPort(Port *newPort) { - Port *oldPort = _curPort; - _curPort = newPort; - return oldPort; -} - -Port *Gfx::GetPort() { - return _curPort; -} - -void Gfx::SetOrigin(int16 left, int16 top) { - _curPort->left = left; - _curPort->top = top; -} - -void Gfx::MoveTo(int16 left, int16 top) { - _curPort->curTop = top; - _curPort->curLeft = left; -} - -void Gfx::Move(int16 left, int16 top) { - _curPort->curTop += top; - _curPort->curLeft += left; -} - -void Gfx::OpenPort(Port *port) { - port->fontId = 0; - port->fontHeight = 8; - - Port *tmp = _curPort; - _curPort = port; - _text->SetFont(port->fontId); - _curPort = tmp; - - port->top = 0; - port->left = 0; - port->greyedOutput = false; - port->penClr = 0; - port->backClr = 255; - port->penMode = 0; - port->rect = _bounds; -} - -void Gfx::PenColor(int16 color) { - _curPort->penClr = color; -} - -void Gfx::BackColor(int16 color) { - _curPort->backClr = color; -} - -void Gfx::PenMode(int16 mode) { - _curPort->penMode = mode; -} - -void Gfx::TextGreyedOutput(bool state) { - _curPort->greyedOutput = state; -} - -int16 Gfx::GetPointSize() { - return _curPort->fontHeight; -} - -void Gfx::ClearScreen(byte color) { - FillRect(_curPort->rect, SCI_SCREEN_MASK_ALL, color, 0, 0); -} - -void Gfx::InvertRect(const Common::Rect &rect) { - int16 oldpenmode = _curPort->penMode; - _curPort->penMode = 2; - FillRect(rect, 1, _curPort->penClr, _curPort->backClr); - _curPort->penMode = oldpenmode; -} - -void Gfx::EraseRect(const Common::Rect &rect) { - FillRect(rect, 1, _curPort->backClr); -} - -void Gfx::PaintRect(const Common::Rect &rect) { - FillRect(rect, 1, _curPort->penClr); -} - -void Gfx::FillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack, byte bControl) { - Common::Rect r = rect; - r.clip(_curPort->rect); - if (r.isEmpty()) // nothing to fill - return; - - int16 oldPenMode = _curPort->penMode; - OffsetRect(r); - int16 x, y; - byte curVisual; - - // Doing visual first - if (drawFlags & SCI_SCREEN_MASK_VISUAL) { - if (oldPenMode == 2) { // invert mode - for (y = r.top; y < r.bottom; y++) { - for (x = r.left; x < r.right; x++) { - curVisual = _screen->getVisual(x, y); - if (curVisual == clrPen) { - _screen->putPixel(x, y, 1, clrBack, 0, 0); - } else if (curVisual == clrBack) { - _screen->putPixel(x, y, 1, clrPen, 0, 0); - } - } - } - } else { // just fill rect with ClrPen - for (y = r.top; y < r.bottom; y++) { - for (x = r.left; x < r.right; x++) { - _screen->putPixel(x, y, 1, clrPen, 0, 0); - } - } - } - } - - if (drawFlags < 2) - return; - drawFlags &= SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL; - - if (oldPenMode != 2) { - for (y = r.top; y < r.bottom; y++) { - for (x = r.left; x < r.right; x++) { - _screen->putPixel(x, y, drawFlags, 0, clrBack, bControl); - } - } - } else { - for (y = r.top; y < r.bottom; y++) { - for (x = r.left; x < r.right; x++) { - _screen->putPixel(x, y, drawFlags, 0, !_screen->getPriority(x, y), !_screen->getControl(x, y)); - } - } - } -} - -void Gfx::FrameRect(const Common::Rect &rect) { - Common::Rect r; - // left - r = rect; - r.right = rect.left + 1; - PaintRect(r); - // right - r.right = rect.right; - r.left = rect.right - 1; - PaintRect(r); - //top - r.left = rect.left; - r.bottom = rect.top + 1; - PaintRect(r); - //bottom - r.bottom = rect.bottom; - r.top = rect.bottom - 1; - PaintRect(r); -} - -void Gfx::OffsetRect(Common::Rect &r) { - r.top += _curPort->top; - r.bottom += _curPort->top; - r.left += _curPort->left; - r.right += _curPort->left; -} - -void Gfx::OffsetLine(Common::Point &start, Common::Point &end) { - start.x += _curPort->left; - start.y += _curPort->top; - end.x += _curPort->left; - end.y += _curPort->top; -} - -void Gfx::BitsShow(const Common::Rect &rect) { - Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom); - workerRect.clip(_curPort->rect); - if (workerRect.isEmpty()) // nothing to show - return; - - OffsetRect(workerRect); - _screen->copyRectToScreen(workerRect); -} - -void Gfx::BitsShowHires(const Common::Rect &rect) { - _screen->copyDisplayRectToScreen(rect); -} - -reg_t Gfx::BitsSave(const Common::Rect &rect, byte screenMask) { - reg_t memoryId; - byte *memoryPtr; - int size; - - Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom); - workerRect.clip(_curPort->rect); - if (workerRect.isEmpty()) // nothing to save - return NULL_REG; - - if (screenMask == SCI_SCREEN_MASK_DISPLAY) { - // Adjust rect to upscaled hires, but dont adjust according to port - workerRect.top *= 2; workerRect.bottom *= 2; workerRect.bottom++; - workerRect.left *= 2; workerRect.right *= 2; workerRect.right++; - } else { - OffsetRect(workerRect); - } - - // now actually ask _screen how much space it will need for saving - size = _screen->bitsGetDataSize(workerRect, screenMask); - - memoryId = kalloc(_segMan, "SaveBits()", size); - memoryPtr = kmem(_segMan, memoryId); - _screen->bitsSave(workerRect, screenMask, memoryPtr); - return memoryId; -} - -void Gfx::BitsGetRect(reg_t memoryHandle, Common::Rect *destRect) { - byte *memoryPtr = NULL; - - if (!memoryHandle.isNull()) { - memoryPtr = kmem(_segMan, memoryHandle); - - if (memoryPtr) { - _screen->bitsGetRect(memoryPtr, destRect); - } - } -} - -void Gfx::BitsRestore(reg_t memoryHandle) { - byte *memoryPtr = NULL; - - if (!memoryHandle.isNull()) { - memoryPtr = kmem(_segMan, memoryHandle); - - if (memoryPtr) { - _screen->bitsRestore(memoryPtr); - kfree(_segMan, memoryHandle); - } - } -} - -void Gfx::BitsFree(reg_t memoryHandle) { - if (!memoryHandle.isNull()) { - kfree(_segMan, memoryHandle); - } -} - -void Gfx::setEGAdrawingVisualize(bool state) { - _EGAdrawingVisualize = state; -} - -void Gfx::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId) { - SciGuiPicture *picture = new SciGuiPicture(_resMan, this, _screen, _palette, pictureId, _EGAdrawingVisualize); - - // do we add to a picture? if not -> clear screen with white - if (!addToFlag) - ClearScreen(_screen->getColorWhite()); - - picture->draw(animationNr, mirroredFlag, addToFlag, paletteId); - delete picture; -} - -// This one is the only one that updates screen! -void Gfx::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { - View *view = getView(viewId); - Common::Rect celRect; - - if (view) { - celRect.left = leftPos; - celRect.top = topPos; - celRect.right = celRect.left + view->getWidth(loopNo, celNo); - celRect.bottom = celRect.top + view->getHeight(loopNo, celNo); - - drawCel(view, loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); - - if (getSciVersion() >= SCI_VERSION_1_1) { - if (!_screen->_picNotValidSci11) { - BitsShow(celRect); - } - } else { - if (!_screen->_picNotValid) - BitsShow(celRect); - } - } -} - -// This version of drawCel is not supposed to call BitsShow()! -void Gfx::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { - drawCel(getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); -} - -// This version of drawCel is not supposed to call BitsShow()! -void Gfx::drawCel(View *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { - Common::Rect clipRect = celRect; - clipRect.clip(_curPort->rect); - if (clipRect.isEmpty()) // nothing to draw - return; - - Common::Rect clipRectTranslated = clipRect; - OffsetRect(clipRectTranslated); - if (scaleX == 128 && scaleY == 128) { - view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, false); - } else { - view->drawScaled(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, scaleX, scaleY); - } -} - -// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen -// Hires-cels are available only SCI 1.1+ -void Gfx::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) { - View *view = getView(viewId); - Common::Rect celRect, curPortRect, clipRect, clipRectTranslated; - Common::Point curPortPos; - bool upscaledHiresHack = false; - - if (view) { - if ((leftPos == 0) && (topPos == 0)) { - // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle - // I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes - // coordinates to be 0 in the first place - byte *memoryPtr = NULL; - memoryPtr = kmem(_segMan, upscaledHiresHandle); - if (memoryPtr) { - Common::Rect upscaledHiresRect; - _screen->bitsGetRect(memoryPtr, &upscaledHiresRect); - leftPos = upscaledHiresRect.left; - topPos = upscaledHiresRect.top; - upscaledHiresHack = true; - } - } - - celRect.left = leftPos; - celRect.top = topPos; - celRect.right = celRect.left + view->getWidth(loopNo, celNo); - celRect.bottom = celRect.top + view->getHeight(loopNo, celNo); - // adjust curPort to upscaled hires - clipRect = celRect; - curPortRect = _curPort->rect; - curPortRect.top *= 2; curPortRect.bottom *= 2; curPortRect.bottom++; - curPortRect.left *= 2; curPortRect.right *= 2; curPortRect.right++; - clipRect.clip(curPortRect); - if (clipRect.isEmpty()) // nothing to draw - return; - - clipRectTranslated = clipRect; - if (!upscaledHiresHack) { - curPortPos.x = _curPort->left * 2; curPortPos.y = _curPort->top * 2; - clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y; - clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x; - } - - view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, true); - if (!_screen->_picNotValidSci11) { - _screen->copyDisplayRectToScreen(clipRectTranslated); - } - } -} - -uint16 Gfx::onControl(uint16 screenMask, Common::Rect rect) { - int16 x, y; - uint16 result = 0; - - if (rect.isEmpty()) - return 0; - - if (screenMask & SCI_SCREEN_MASK_PRIORITY) { - for (y = rect.top; y < rect.bottom; y++) { - for (x = rect.left; x < rect.right; x++) { - result |= 1 << _screen->getPriority(x, y); - } - } - } else { - for (y = rect.top; y < rect.bottom; y++) { - for (x = rect.left; x < rect.right; x++) { - result |= 1 << _screen->getControl(x, y); - } - } - } - return result; -} - -static inline int sign_extend_byte(int value) { - if (value & 0x80) - return value - 256; - else - return value; -} - -void Gfx::PriorityBandsInit(int16 bandCount, int16 top, int16 bottom) { - int16 y; - int32 bandSize; - - // This code is for 320x200 games only - if (_screen->getHeight() != 200) - return; - - if (bandCount != -1) - _priorityBandCount = bandCount; - - _priorityTop = top; - _priorityBottom = bottom; - - // Do NOT modify this algo or optimize it anyhow, sierra sci used int32 for calculating the - // priority bands and by using double or anything rounding WILL destroy the result - bandSize = ((_priorityBottom - _priorityTop) * 2000) / _priorityBandCount; - - memset(_priorityBands, 0, sizeof(byte) * _priorityTop); - for (y = _priorityTop; y < _priorityBottom; y++) - _priorityBands[y] = 1 + (((y - _priorityTop) * 2000) / bandSize); - if (_priorityBandCount == 15) { - // When having 15 priority bands, we actually replace band 15 with band 14, cause the original sci interpreter also - // does it that way as well - y = _priorityBottom; - while (_priorityBands[--y] == _priorityBandCount) - _priorityBands[y]--; - } - // We fill space that is left over with the highest band (hardcoded 200 limit, because this algo isnt meant to be used on hires) - for (y = _priorityBottom; y < 200; y++) - _priorityBands[y] = _priorityBandCount; -} - -void Gfx::PriorityBandsInit(byte *data) { - int i = 0, inx; - byte priority = 0; - - for (inx = 0; inx < 14; inx++) { - priority = *data++; - while (i < priority) - _priorityBands[i++] = inx; - } - while (i < 200) - _priorityBands[i++] = inx; -} - -// Gets used by picture class to remember priority bands data from sci1.1 pictures that need to get applied when -// transitioning to that picture -void Gfx::PriorityBandsRemember(byte *data) { - int bandNo; - for (bandNo = 0; bandNo < 14; bandNo++) { - priorityBandsMemory[bandNo] = READ_LE_UINT16(data); - data += 2; - } - priorityBandsMemoryActive = true; -} - -void Gfx::PriorityBandsRecall() { - if (priorityBandsMemoryActive) { - PriorityBandsInit((byte *)&priorityBandsMemory); - priorityBandsMemoryActive = false; - } -} - -byte Gfx::CoordinateToPriority(int16 y) { - if (y < _priorityTop) - return _priorityBands[_priorityTop]; - if (y > _priorityBottom) - return _priorityBands[_priorityBottom]; - return _priorityBands[y]; -} - -int16 Gfx::PriorityToCoordinate(byte priority) { - int16 y; - if (priority <= _priorityBandCount) { - for (y = 0; y <= _priorityBottom; y++) - if (_priorityBands[y] == priority) - return y; - } - return _priorityBottom; -} - -bool Gfx::CanBeHereCheckRectList(reg_t checkObject, Common::Rect checkRect, List *list) { - reg_t curAddress = list->first; - Node *curNode = _segMan->lookupNode(curAddress); - reg_t curObject; - uint16 signal; - Common::Rect curRect; - - while (curNode) { - curObject = curNode->value; - if (curObject != checkObject) { - signal = GET_SEL32V(_segMan, curObject, signal); - if ((signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate)) == 0) { - curRect.left = GET_SEL32V(_segMan, curObject, brLeft); - curRect.top = GET_SEL32V(_segMan, curObject, brTop); - curRect.right = GET_SEL32V(_segMan, curObject, brRight); - curRect.bottom = GET_SEL32V(_segMan, curObject, brBottom); - // Check if curRect is within checkRect - if (curRect.right > checkRect.left && curRect.left < checkRect.right && curRect.bottom > checkRect.top && curRect.top < checkRect.bottom) { - return false; - } - } - } - curAddress = curNode->succ; - curNode = _segMan->lookupNode(curAddress); - } - return true; -} - -void Gfx::SetNowSeen(reg_t objectReference) { - View *view = NULL; - Common::Rect celRect(0, 0); - GuiResourceId viewId = (GuiResourceId)GET_SEL32V(_segMan, objectReference, view); - int16 loopNo = sign_extend_byte((int16)GET_SEL32V(_segMan, objectReference, loop)); - int16 celNo = sign_extend_byte((int16)GET_SEL32V(_segMan, objectReference, cel)); - int16 x = (int16)GET_SEL32V(_segMan, objectReference, x); - int16 y = (int16)GET_SEL32V(_segMan, objectReference, y); - int16 z = 0; - if (_kernel->_selectorCache.z > -1) - z = (int16)GET_SEL32V(_segMan, objectReference, z); - - // now get cel rectangle - view = getView(viewId); - view->getCelRect(loopNo, celNo, x, y, z, &celRect); - - // TODO: sometimes loop is negative. Check what it means - if (lookup_selector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) { - PUT_SEL32V(_segMan, objectReference, nsLeft, celRect.left); - PUT_SEL32V(_segMan, objectReference, nsRight, celRect.right); - PUT_SEL32V(_segMan, objectReference, nsTop, celRect.top); - PUT_SEL32V(_segMan, objectReference, nsBottom, celRect.bottom); - } -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 8c662290be..633617eead 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -35,8 +35,10 @@ #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/cursor.h" -#include "sci/graphics/gfx.h" -#include "sci/graphics/windowmgr.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" #include "sci/graphics/animate.h" #include "sci/graphics/controls.h" #include "sci/graphics/menu.h" @@ -48,26 +50,29 @@ namespace Sci { -SciGui::SciGui(EngineState *state, Screen *screen, SciPalette *palette, Cursor *cursor, AudioPlayer *audio) - : _s(state), _screen(screen), _palette(palette), _cursor(cursor), _audio(audio) { +SciGui::SciGui(EngineState *state, Screen *screen, SciPalette *palette, Cursor *cursor, GfxPorts *ports, AudioPlayer *audio) + : _s(state), _screen(screen), _palette(palette), _cursor(cursor), _ports(ports), _audio(audio) { - _gfx = new Gfx(_s->resMan, _s->_segMan, _s->_kernel, _screen, _palette); + _cache = new GfxCache(_s->resMan, _screen, _palette); + _compare = new GfxCompare(_s->_segMan, _s->_kernel, _cache, _screen); + _paint16 = new GfxPaint16(_s->resMan, _s->_segMan, _s->_kernel, _cache, _ports, _screen, _palette); _transitions = new Transitions(this, _screen, _palette, _s->resMan->isVGA()); - _animate = new SciGuiAnimate(_s, _gfx, _screen, _palette); - _text = new Text(_s->resMan, _gfx, _screen); - _windowMgr = new WindowMgr(this, _screen, _gfx, _text); - _controls = new Controls(_s->_segMan, _gfx, _text); - _menu = new Menu(_s->_event, _s->_segMan, this, _gfx, _text, _screen, _cursor); + _animate = new SciGuiAnimate(_s, _cache, _ports, _paint16, _screen, _palette); + _text = new Text(_s->resMan, _ports, _paint16, _screen); + _controls = new Controls(_s->_segMan, _ports, _paint16, _text); + _menu = new Menu(_s->_event, _s->_segMan, this, _ports, _paint16, _text, _screen, _cursor); } SciGui::~SciGui() { delete _menu; delete _controls; - delete _windowMgr; delete _text; delete _animate; delete _transitions; - delete _gfx; + delete _paint16; + delete _ports; + delete _compare; + delete _cache; } void SciGui::resetEngineState(EngineState *s) { @@ -78,19 +83,19 @@ void SciGui::resetEngineState(EngineState *s) { void SciGui::init(bool usesOldGfxFunctions) { _usesOldGfxFunctions = usesOldGfxFunctions; - _gfx->init(_text); - _windowMgr->init(_s->_gameId); + _ports->init(this, _paint16, _text, _s->_gameId); + _paint16->init(_text); initPriorityBands(); } void SciGui::initPriorityBands() { if (_usesOldGfxFunctions) { - _gfx->PriorityBandsInit(15, 42, 200); + _ports->priorityBandsInit(15, 42, 200); } else { if (getSciVersion() >= SCI_VERSION_1_1) - _gfx->PriorityBandsInit(14, 0, 190); + _ports->priorityBandsInit(14, 0, 190); else - _gfx->PriorityBandsInit(14, 42, 190); + _ports->priorityBandsInit(14, 42, 190); } } @@ -105,74 +110,24 @@ void SciGui::wait(int16 ticks) { kernel_sleep(_s->_event, ticks * 1000 / 60); } -void SciGui::setPort(uint16 portPtr) { - switch (portPtr) { - case 0: - _gfx->SetPort(_windowMgr->_wmgrPort); - break; - case 0xFFFF: - _gfx->SetPort(_gfx->_menuPort); - break; - default: - _gfx->SetPort(_windowMgr->getPortById(portPtr)); - }; -} - -Common::Rect SciGui::getPortPic(int16 &picTop, int16 &picLeft) { - picTop = _windowMgr->_picWind->top; - picLeft = _windowMgr->_picWind->left; - return _windowMgr->_picWind->rect; -} - -void SciGui::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft, bool initPriorityBandsFlag) { - _windowMgr->_picWind->rect = rect; - _windowMgr->_picWind->top = picTop; - _windowMgr->_picWind->left = picLeft; - if (initPriorityBandsFlag) - initPriorityBands(); -} - -reg_t SciGui::getPort() { - return make_reg(0, _gfx->GetPort()->id); -} - void SciGui::globalToLocal(int16 *x, int16 *y) { - Port *curPort = _gfx->GetPort(); + Port *curPort = _ports->getPort(); *x = *x - curPort->left; *y = *y - curPort->top; } void SciGui::localToGlobal(int16 *x, int16 *y) { - Port *curPort = _gfx->GetPort(); + Port *curPort = _ports->getPort(); *x = *x + curPort->left; *y = *y + curPort->top; } int16 SciGui::coordinateToPriority(int16 y) { - return _gfx->CoordinateToPriority(y); + return _ports->coordinateToPriority(y); } int16 SciGui::priorityToCoordinate(int16 priority) { - return _gfx->PriorityToCoordinate(priority); -} - -reg_t SciGui::newWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title) { - Window *wnd = NULL; - - if (restoreRect.top != 0 && restoreRect.left != 0 && restoreRect.height() != 0 && restoreRect.width() != 0) - wnd = _windowMgr->NewWindow(dims, &restoreRect, title, style, priority, false); - else - wnd = _windowMgr->NewWindow(dims, NULL, title, style, priority, false); - wnd->penClr = colorPen; - wnd->backClr = colorBack; - _windowMgr->DrawWindow(wnd); - - return make_reg(0, wnd->id); -} - -void SciGui::disposeWindow(uint16 windowPtr, bool reanimate) { - Window *wnd = (Window *)_windowMgr->getPortById(windowPtr); - _windowMgr->DisposeWindow(wnd, reanimate); + return _ports->priorityToCoordinate(priority); } #define SCI_DISPLAY_MOVEPEN 100 @@ -194,19 +149,19 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { Common::Rect rect; // Make a "backup" of the port settings - Port oldPort = *_gfx->GetPort(); + Port oldPort = *_ports->getPort(); // setting defaults - _gfx->PenMode(0); - _gfx->PenColor(0); - _gfx->TextGreyedOutput(false); + _ports->penMode(0); + _ports->penColor(0); + _ports->textGreyedOutput(false); // processing codes in argv while (argc > 0) { displayArg = argv[0].toUint16(); argc--; argv++; switch (displayArg) { case SCI_DISPLAY_MOVEPEN: - _gfx->MoveTo(argv[0].toUint16(), argv[1].toUint16()); + _ports->moveTo(argv[0].toUint16(), argv[1].toUint16()); argc -= 2; argv += 2; break; case SCI_DISPLAY_SETALIGNMENT: @@ -215,7 +170,7 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { break; case SCI_DISPLAY_SETPENCOLOR: colorPen = argv[0].toUint16(); - _gfx->PenColor(colorPen); + _ports->penColor(colorPen); argc--; argv++; break; case SCI_DISPLAY_SETBACKGROUNDCOLOR: @@ -223,7 +178,7 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { argc--; argv++; break; case SCI_DISPLAY_SETGREYEDOUTPUT: - _gfx->TextGreyedOutput(argv[0].isNull() ? false : true); + _ports->textGreyedOutput(argv[0].isNull() ? false : true); argc--; argv++; break; case SCI_DISPLAY_SETFONT: @@ -238,9 +193,9 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { doSaveUnder = true; break; case SCI_DISPLAY_RESTOREUNDER: - _gfx->BitsGetRect(argv[0], &rect); - rect.translate(-_gfx->GetPort()->left, -_gfx->GetPort()->top); - _gfx->BitsRestore(argv[0]); + _paint16->bitsGetRect(argv[0], &rect); + rect.translate(-_ports->getPort()->left, -_ports->getPort()->top); + _paint16->bitsRestore(argv[0]); graphRedrawBox(rect); // finishing loop argc = 0; @@ -256,23 +211,23 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { // now drawing the text _text->Size(rect, text, -1, width); - rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop); + rect.moveTo(_ports->getPort()->curLeft, _ports->getPort()->curTop); if (getSciVersion() >= SCI_VERSION_1_LATE) { int16 leftPos = rect.right <= _screen->getWidth() ? 0 : _screen->getWidth() - rect.right; int16 topPos = rect.bottom <= _screen->getHeight() ? 0 : _screen->getHeight() - rect.bottom; - _gfx->Move(leftPos, topPos); - rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop); + _ports->move(leftPos, topPos); + rect.moveTo(_ports->getPort()->curLeft, _ports->getPort()->curTop); } if (doSaveUnder) - _s->r_acc = _gfx->BitsSave(rect, SCI_SCREEN_MASK_VISUAL); + _s->r_acc = _paint16->bitsSave(rect, SCI_SCREEN_MASK_VISUAL); if (colorBack != -1) - _gfx->FillRect(rect, SCI_SCREEN_MASK_VISUAL, colorBack, 0, 0); + _paint16->fillRect(rect, SCI_SCREEN_MASK_VISUAL, colorBack, 0, 0); _text->Box(text, 0, rect, alignment, -1); if (_screen->_picNotValid == 0 && bRedraw) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); // restoring port and cursor pos - Port *currport = _gfx->GetPort(); + Port *currport = _ports->getPort(); uint16 tTop = currport->curTop; uint16 tLeft = currport->curLeft; *currport = oldPort; @@ -298,22 +253,22 @@ void SciGui::textColors(int argc, reg_t *argv) { } void SciGui::drawStatus(const char *text, int16 colorPen, int16 colorBack) { - Port *oldPort = _gfx->SetPort(_gfx->_menuPort); + Port *oldPort = _ports->setPort(_ports->_menuPort); - _gfx->FillRect(_gfx->_menuBarRect, 1, colorBack); - _gfx->PenColor(colorPen); - _gfx->MoveTo(0, 1); + _paint16->fillRect(_ports->_menuBarRect, 1, colorBack); + _ports->penColor(colorPen); + _ports->moveTo(0, 1); _text->Draw_String(text); - _gfx->BitsShow(_gfx->_menuBarRect); - _gfx->SetPort(oldPort); + _paint16->bitsShow(_ports->_menuBarRect); + _ports->setPort(oldPort); } void SciGui::drawMenuBar(bool clear) { if (!clear) { - Port *oldPort = _gfx->SetPort(_gfx->_menuPort); + Port *oldPort = _ports->setPort(_ports->_menuPort); _menu->drawBar(); - _gfx->BitsShow(_gfx->_menuBarRect); - _gfx->SetPort(oldPort); + _paint16->bitsShow(_ports->_menuBarRect); + _ports->setPort(oldPort); } else { drawStatus("", 0, 0); } @@ -321,7 +276,7 @@ void SciGui::drawMenuBar(bool clear) { void SciGui::menuReset() { delete _menu; - _menu = new Menu(_s->_event, _s->_segMan, this, _gfx, _text, _screen, _cursor); + _menu = new Menu(_s->_event, _s->_segMan, this, _ports, _paint16, _text, _screen, _cursor); } void SciGui::menuAdd(Common::String title, Common::String content, reg_t contentVmPtr) { @@ -341,26 +296,26 @@ reg_t SciGui::menuSelect(reg_t eventObject) { } void SciGui::drawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) { - Port *oldPort = _gfx->SetPort((Port *)_windowMgr->_picWind); + Port *oldPort = _ports->setPort((Port *)_ports->_picWind); - if (_windowMgr->isFrontWindow(_windowMgr->_picWind)) { + if (_ports->isFrontWindow(_ports->_picWind)) { _screen->_picNotValid = 1; - _gfx->drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo); + _paint16->drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo); _transitions->setup(animationNr, animationBlackoutFlag); } else { - _windowMgr->BeginUpdate(_windowMgr->_picWind); - _gfx->drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo); - _windowMgr->EndUpdate(_windowMgr->_picWind); + _ports->beginUpdate(_ports->_picWind); + _paint16->drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo); + _ports->endUpdate(_ports->_picWind); } - _gfx->SetPort(oldPort); + _ports->setPort(oldPort); } void SciGui::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) { // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) { - _gfx->drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo); + _paint16->drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo); } else { - _gfx->drawHiresCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo, upscaledHiresHandle); + _paint16->drawHiresCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo, upscaledHiresHandle); } _palette->setOnScreen(); } @@ -374,40 +329,40 @@ int SciGui::getControlPicNotValid() { void SciGui::drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { if (!hilite) { rect.grow(1); - _gfx->EraseRect(rect); - _gfx->FrameRect(rect); + _paint16->eraseRect(rect); + _paint16->frameRect(rect); rect.grow(-2); - _gfx->TextGreyedOutput(style & 1 ? false : true); + _ports->textGreyedOutput(style & 1 ? false : true); _text->Box(text, 0, rect, SCI_TEXT_ALIGNMENT_CENTER, fontId); - _gfx->TextGreyedOutput(false); + _ports->textGreyedOutput(false); rect.grow(1); if (style & 8) // selected - _gfx->FrameRect(rect); + _paint16->frameRect(rect); if (!getControlPicNotValid()) { rect.grow(1); - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } } else { - _gfx->InvertRect(rect); - _gfx->BitsShow(rect); + _paint16->invertRect(rect); + _paint16->bitsShow(rect); } } void SciGui::drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { if (!hilite) { rect.grow(1); - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); rect.grow(-1); _text->Box(text, 0, rect, alignment, fontId); if (style & 8) { // selected - _gfx->FrameRect(rect); + _paint16->frameRect(rect); } rect.grow(1); if (!getControlPicNotValid()) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } else { - _gfx->InvertRect(rect); - _gfx->BitsShow(rect); + _paint16->invertRect(rect); + _paint16->bitsShow(rect); } } @@ -417,9 +372,9 @@ void SciGui::drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, rect.grow(1); _controls->TexteditCursorErase(); - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); _text->Box(text, 0, textRect, SCI_TEXT_ALIGNMENT_LEFT, fontId); - _gfx->FrameRect(rect); + _paint16->frameRect(rect); if (style & 8) { _text->SetFont(fontId); rect.grow(-1); @@ -428,20 +383,20 @@ void SciGui::drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, rect.grow(1); } if (!getControlPicNotValid()) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } void SciGui::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite) { if (!hilite) { - _gfx->drawCelAndShow(viewId, loopNo, celNo, rect.left, rect.top, priority, 0); + _paint16->drawCelAndShow(viewId, loopNo, celNo, rect.left, rect.top, priority, 0); if (style & 0x20) { - _gfx->FrameRect(rect); + _paint16->frameRect(rect); } if (!getControlPicNotValid()) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } else { - _gfx->InvertRect(rect); - _gfx->BitsShow(rect); + _paint16->invertRect(rect); + _paint16->bitsShow(rect); } } @@ -450,10 +405,10 @@ void SciGui::drawControlList(Common::Rect rect, reg_t obj, int16 maxChars, int16 _controls->drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); rect.grow(1); if (isAlias && (style & 8)) { - _gfx->FrameRect(rect); + _paint16->frameRect(rect); } if (!getControlPicNotValid()) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); } } @@ -469,66 +424,66 @@ void SciGui::editControl(reg_t controlObject, reg_t eventObject) { } void SciGui::graphFillBoxForeground(Common::Rect rect) { - _gfx->PaintRect(rect); + _paint16->paintRect(rect); } void SciGui::graphFillBoxBackground(Common::Rect rect) { - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); } void SciGui::graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) { - _gfx->FillRect(rect, colorMask, color, priority, control); + _paint16->fillRect(rect, colorMask, color, priority, control); } void SciGui::graphFrameBox(Common::Rect rect, int16 color) { - int16 oldColor = _gfx->GetPort()->penClr; - _gfx->PenColor(color); - _gfx->FrameRect(rect); - _gfx->PenColor(oldColor); + int16 oldColor = _ports->getPort()->penClr; + _ports->penColor(color); + _paint16->frameRect(rect); + _ports->penColor(oldColor); } void SciGui::graphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) { - _gfx->OffsetLine(startPoint, endPoint); + _ports->offsetLine(startPoint, endPoint); _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); } reg_t SciGui::graphSaveBox(Common::Rect rect, uint16 screenMask) { - return _gfx->BitsSave(rect, screenMask); + return _paint16->bitsSave(rect, screenMask); } reg_t SciGui::graphSaveUpscaledHiresBox(Common::Rect rect) { - return _gfx->BitsSave(rect, SCI_SCREEN_MASK_DISPLAY); + return _paint16->bitsSave(rect, SCI_SCREEN_MASK_DISPLAY); } void SciGui::graphRestoreBox(reg_t handle) { - _gfx->BitsRestore(handle); + _paint16->bitsRestore(handle); } void SciGui::graphUpdateBox(Common::Rect rect, bool hiresMode) { // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) - _gfx->BitsShow(rect); + _paint16->bitsShow(rect); else - _gfx->BitsShowHires(rect); + _paint16->bitsShowHires(rect); } void SciGui::graphRedrawBox(Common::Rect rect) { localToGlobal(&rect.left, &rect.top); localToGlobal(&rect.right, &rect.bottom); - Port *oldPort = _gfx->SetPort((Port *)_windowMgr->_picWind); + Port *oldPort = _ports->setPort((Port *)_ports->_picWind); globalToLocal(&rect.left, &rect.top); globalToLocal(&rect.right, &rect.bottom); _animate->reAnimate(rect); - _gfx->SetPort(oldPort); + _ports->setPort(oldPort); } void SciGui::graphAdjustPriority(int top, int bottom) { if (_usesOldGfxFunctions) { - _gfx->PriorityBandsInit(15, top, bottom); + _ports->priorityBandsInit(15, top, bottom); } else { - _gfx->PriorityBandsInit(14, top, bottom); + _ports->priorityBandsInit(14, top, bottom); } } @@ -605,20 +560,20 @@ void SciGui::shakeScreen(uint16 shakeCount, uint16 directions) { } uint16 SciGui::onControl(byte screenMask, Common::Rect rect) { - Port *oldPort = _gfx->SetPort((Port *)_windowMgr->_picWind); + Port *oldPort = _ports->setPort((Port *)_ports->_picWind); Common::Rect adjustedRect(rect.left, rect.top, rect.right, rect.bottom); uint16 result; - adjustedRect.clip(_gfx->GetPort()->rect); - _gfx->OffsetRect(adjustedRect); - result = _gfx->onControl(screenMask, adjustedRect); + adjustedRect.clip(_ports->getPort()->rect); + _ports->offsetRect(adjustedRect); + result = _compare->onControl(screenMask, adjustedRect); - _gfx->SetPort(oldPort); + _ports->setPort(oldPort); return result; } void SciGui::animateShowPic() { - Port *picPort = _windowMgr->_picWind; + Port *picPort = _ports->_picWind; Common::Rect picRect = picPort->rect; bool previousCursorState = _cursor->isVisible(); @@ -631,7 +586,7 @@ void SciGui::animateShowPic() { _cursor->show(); // We set SCI1.1 priority band information here - _gfx->PriorityBandsRecall(); + _ports->priorityBandsRecall(); } void SciGui::animate(reg_t listReference, bool cycle, int argc, reg_t *argv) { @@ -653,16 +608,16 @@ void SciGui::animate(reg_t listReference, bool cycle, int argc, reg_t *argv) { return; } - Port *oldPort = _gfx->SetPort((Port *)_windowMgr->_picWind); + Port *oldPort = _ports->setPort((Port *)_ports->_picWind); _animate->disposeLastCast(); _animate->makeSortedList(list); _animate->fill(old_picNotValid); if (old_picNotValid) { - _windowMgr->BeginUpdate(_windowMgr->_picWind); + _ports->beginUpdate(_ports->_picWind); _animate->update(); - _windowMgr->EndUpdate(_windowMgr->_picWind); + _ports->endUpdate(_ports->_picWind); } _animate->drawCels(); @@ -676,7 +631,7 @@ void SciGui::animate(reg_t listReference, bool cycle, int argc, reg_t *argv) { if (_animate->getLastCastCount() > 1) _s->_throttleTrigger = true; - _gfx->SetPort(oldPort); + _ports->setPort(oldPort); } void SciGui::addToPicSetPicNotValid() { @@ -689,7 +644,7 @@ void SciGui::addToPicSetPicNotValid() { void SciGui::addToPicList(reg_t listReference, int argc, reg_t *argv) { List *list; - _gfx->SetPort((Port *)_windowMgr->_picWind); + _ports->setPort((Port *)_ports->_picWind); list = _s->_segMan->lookupList(listReference); if (!list) @@ -702,17 +657,17 @@ void SciGui::addToPicList(reg_t listReference, int argc, reg_t *argv) { } void SciGui::addToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control) { - _gfx->SetPort((Port *)_windowMgr->_picWind); + _ports->setPort((Port *)_ports->_picWind); _animate->addToPicDrawView(viewId, loopNo, celNo, leftPos, topPos, priority, control); addToPicSetPicNotValid(); } void SciGui::setNowSeen(reg_t objectReference) { - _gfx->SetNowSeen(objectReference); + _compare->SetNowSeen(objectReference); } bool SciGui::canBeHere(reg_t curObject, reg_t listReference) { - Port *oldPort = _gfx->SetPort((Port *)_windowMgr->_picWind); + Port *oldPort = _ports->setPort((Port *)_ports->_picWind); Common::Rect checkRect; Common::Rect adjustedRect; uint16 signal, controlMask; @@ -724,25 +679,25 @@ bool SciGui::canBeHere(reg_t curObject, reg_t listReference) { checkRect.bottom = GET_SEL32V(_s->_segMan, curObject, brBottom); adjustedRect = checkRect; - adjustedRect.clip(_gfx->GetPort()->rect); - _gfx->OffsetRect(adjustedRect); + adjustedRect.clip(_ports->getPort()->rect); + _ports->offsetRect(adjustedRect); signal = GET_SEL32V(_s->_segMan, curObject, signal); controlMask = GET_SEL32V(_s->_segMan, curObject, illegalBits); - result = (_gfx->onControl(SCI_SCREEN_MASK_CONTROL, adjustedRect) & controlMask) ? false : true; + result = (_compare->onControl(SCI_SCREEN_MASK_CONTROL, adjustedRect) & controlMask) ? false : true; if ((result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) { List *list = _s->_segMan->lookupList(listReference); if (!list) error("kCanBeHere called with non-list as parameter"); - result = _gfx->CanBeHereCheckRectList(curObject, checkRect, list); + result = _compare->CanBeHereCheckRectList(curObject, checkRect, list); } - _gfx->SetPort(oldPort); + _ports->setPort(oldPort); return result; } bool SciGui::isItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) { - View *tmpView = _gfx->getView(viewId); + View *tmpView = _cache->getView(viewId); CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); position.x = CLIP<int>(position.x, 0, celInfo->width - 1); position.y = CLIP<int>(position.y, 0, celInfo->height - 1); @@ -761,7 +716,7 @@ void SciGui::baseSetter(reg_t object) { int16 loopNo = GET_SEL32V(_s->_segMan, object, loop); int16 celNo = GET_SEL32V(_s->_segMan, object, cel); - View *tmpView = _gfx->getView(viewId); + View *tmpView = _cache->getView(viewId); Common::Rect celRect; tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect); @@ -796,8 +751,8 @@ void SciGui::setCursorView(GuiResourceId viewNum, int loopNum, int cellNum, Comm } void SciGui::setCursorPos(Common::Point pos) { - pos.y += _gfx->GetPort()->top; - pos.x += _gfx->GetPort()->left; + pos.y += _ports->getPort()->top; + pos.x += _ports->getPort()->left; moveCursor(pos); } @@ -806,11 +761,11 @@ Common::Point SciGui::getCursorPos() { } void SciGui::moveCursor(Common::Point pos) { - pos.y += _windowMgr->_picWind->rect.top; - pos.x += _windowMgr->_picWind->rect.left; + pos.y += _ports->_picWind->rect.top; + pos.x += _ports->_picWind->rect.left; - pos.y = CLIP<int16>(pos.y, _windowMgr->_picWind->rect.top, _windowMgr->_picWind->rect.bottom - 1); - pos.x = CLIP<int16>(pos.x, _windowMgr->_picWind->rect.left, _windowMgr->_picWind->rect.right - 1); + pos.y = CLIP<int16>(pos.y, _ports->_picWind->rect.top, _ports->_picWind->rect.bottom - 1); + pos.x = CLIP<int16>(pos.x, _ports->_picWind->rect.left, _ports->_picWind->rect.right - 1); if (pos.x > _screen->getWidth() || pos.y > _screen->getHeight()) { warning("attempt to place cursor at invalid coordinates (%d, %d)", pos.y, pos.x); @@ -829,19 +784,19 @@ void SciGui::setCursorZone(Common::Rect zone) { } int16 SciGui::getCelWidth(GuiResourceId viewId, int16 loopNo, int16 celNo) { - return _gfx->getView(viewId)->getCelInfo(loopNo, celNo)->width; + return _cache->getView(viewId)->getCelInfo(loopNo, celNo)->width; } int16 SciGui::getCelHeight(GuiResourceId viewId, int16 loopNo, int16 celNo) { - return _gfx->getView(viewId)->getCelInfo(loopNo, celNo)->height; + return _cache->getView(viewId)->getCelInfo(loopNo, celNo)->height; } int16 SciGui::getLoopCount(GuiResourceId viewId) { - return _gfx->getView(viewId)->getLoopCount(); + return _cache->getView(viewId)->getLoopCount(); } int16 SciGui::getCelCount(GuiResourceId viewId, int16 loopNo) { - return _gfx->getView(viewId)->getLoopInfo(loopNo)->celCount; + return _cache->getView(viewId)->getLoopInfo(loopNo)->celCount; } void SciGui::syncWithFramebuffer() { @@ -858,7 +813,7 @@ void SciGui::portraitShow(Common::String resourceName, Common::Point position, u // TODO: cache portraits // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates // on kDrawCel, yeah this whole stuff makes sense) - position.x += _gfx->GetPort()->left; position.y += _gfx->GetPort()->top; + position.x += _ports->getPort()->left; position.y += _ports->getPort()->top; position.x *= 2; position.y *= 2; myPortrait->doit(position, resourceId, noun, verb, cond, seq); delete myPortrait; @@ -911,7 +866,7 @@ bool SciGui::debugShowMap(int mapNo) { } bool SciGui::debugEGAdrawingVisualize(bool state) { - _gfx->setEGAdrawingVisualize(state); + _paint16->setEGAdrawingVisualize(state); return false; } diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index 50a2820fe8..a92af7a99b 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -44,7 +44,10 @@ enum { class Screen; class SciPalette; class Cursor; -class Gfx; +class GfxCache; +class GfxCompare; +class GfxPorts; +class GfxPaint16; class WindowMgr; class SciGuiAnimate; class Controls; @@ -54,23 +57,23 @@ class Transitions; class SciGui { public: - SciGui(EngineState *s, Screen *screen, SciPalette *palette, Cursor *cursor, AudioPlayer *audio); + SciGui(EngineState *s, Screen *screen, SciPalette *palette, Cursor *cursor, GfxPorts *ports, AudioPlayer *audio); virtual ~SciGui(); virtual void init(bool usesOldGfxFunctions); virtual void wait(int16 ticks); - virtual void setPort(uint16 portPtr); - virtual Common::Rect getPortPic(int16 &picTop, int16 &picLeft); - virtual void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft, bool initPriorityBandsFlag); - virtual reg_t getPort(); + // virtual void setPort(uint16 portPtr); + // virtual Common::Rect getPortPic(int16 &picTop, int16 &picLeft); + // virtual void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft, bool initPriorityBandsFlag); + // virtual reg_t getPort(); virtual void globalToLocal(int16 *x, int16 *y); virtual void localToGlobal(int16 *x, int16 *y); virtual int16 coordinateToPriority(int16 y); virtual int16 priorityToCoordinate(int16 priority); - virtual reg_t newWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title); - virtual void disposeWindow(uint16 windowPtr, bool reanimate); + // virtual reg_t newWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title); + // virtual void disposeWindow(uint16 windowPtr, bool reanimate); virtual void display(const char *text, int argc, reg_t *argv); @@ -167,7 +170,10 @@ protected: EngineState *_s; Screen *_screen; SciPalette *_palette; - Gfx *_gfx; + GfxCache *_cache; + GfxCompare *_compare; + GfxPorts *_ports; + GfxPaint16 *_paint16; private: virtual void initPriorityBands(); @@ -176,7 +182,6 @@ private: static void palVaryCallback(void *refCon); void doPalVary(); - WindowMgr *_windowMgr; AudioPlayer *_audio; SciGuiAnimate *_animate; Controls *_controls; diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp index bc76b4c22c..781b346480 100644 --- a/engines/sci/graphics/gui32.cpp +++ b/engines/sci/graphics/gui32.cpp @@ -35,7 +35,8 @@ #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/cursor.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" #include "sci/graphics/picture.h" #include "sci/graphics/robot.h" #include "sci/graphics/text.h" @@ -46,11 +47,13 @@ namespace Sci { SciGui32::SciGui32(EngineState *state, Screen *screen, SciPalette *palette, Cursor *cursor) : _s(state), _screen(screen), _palette(palette), _cursor(cursor) { - _gfx = new Gfx(_s->resMan, _s->_segMan, _s->_kernel, _screen, _palette); + _cache = new GfxCache(_s->resMan, _screen, _palette); + _compare = new GfxCompare(_s->_segMan, _s->_kernel, _cache, _screen); } SciGui32::~SciGui32() { - delete _gfx; + delete _compare; + delete _cache; } void SciGui32::resetEngineState(EngineState *s) { @@ -95,12 +98,12 @@ uint16 SciGui32::onControl(byte screenMask, Common::Rect rect) { adjustedRect.translate(0, 10); - result = _gfx->onControl(screenMask, rect); + result = _compare->onControl(screenMask, rect); return result; } void SciGui32::setNowSeen(reg_t objectReference) { - _gfx->SetNowSeen(objectReference); + _compare->SetNowSeen(objectReference); } bool SciGui32::canBeHere(reg_t curObject, reg_t listReference) { @@ -114,19 +117,19 @@ bool SciGui32::canBeHere(reg_t curObject, reg_t listReference) { checkRect.bottom = GET_SEL32V(_s->_segMan, curObject, brBottom); signal = GET_SEL32V(_s->_segMan, curObject, signal); controlMask = GET_SEL32V(_s->_segMan, curObject, illegalBits); - result = (_gfx->onControl(SCI_SCREEN_MASK_CONTROL, checkRect) & controlMask) ? false : true; + result = (_compare->onControl(SCI_SCREEN_MASK_CONTROL, checkRect) & controlMask) ? false : true; if ((result)) { // gui16 && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) { List *list = _s->_segMan->lookupList(listReference); if (!list) error("kCanBeHere called with non-list as parameter"); - result = _gfx->CanBeHereCheckRectList(curObject, checkRect, list); + result = _compare->CanBeHereCheckRectList(curObject, checkRect, list); } return result; } bool SciGui32::isItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) { - View *tmpView = _gfx->getView(viewId); + View *tmpView = _cache->getView(viewId); CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); position.x = CLIP<int>(position.x, 0, celInfo->width - 1); position.y = CLIP<int>(position.y, 0, celInfo->height - 1); @@ -146,7 +149,7 @@ void SciGui32::baseSetter(reg_t object) { int16 celNo = GET_SEL32V(_s->_segMan, object, cel); if (viewId != SIGNAL_OFFSET) { - View *tmpView = _gfx->getView(viewId); + View *tmpView = _cache->getView(viewId); Common::Rect celRect; tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect); @@ -215,19 +218,19 @@ void SciGui32::setCursorZone(Common::Rect zone) { } int16 SciGui32::getCelWidth(GuiResourceId viewId, int16 loopNo, int16 celNo) { - return _gfx->getView(viewId)->getCelInfo(loopNo, celNo)->width; + return _cache->getView(viewId)->getCelInfo(loopNo, celNo)->width; } int16 SciGui32::getCelHeight(GuiResourceId viewId, int16 loopNo, int16 celNo) { - return _gfx->getView(viewId)->getCelInfo(loopNo, celNo)->height; + return _cache->getView(viewId)->getCelInfo(loopNo, celNo)->height; } int16 SciGui32::getLoopCount(GuiResourceId viewId) { - return _gfx->getView(viewId)->getLoopCount(); + return _cache->getView(viewId)->getLoopCount(); } int16 SciGui32::getCelCount(GuiResourceId viewId, int16 loopNo) { - return _gfx->getView(viewId)->getLoopInfo(loopNo)->celCount; + return _cache->getView(viewId)->getLoopInfo(loopNo)->celCount; } void SciGui32::syncWithFramebuffer() { @@ -320,7 +323,7 @@ void SciGui32::frameOut() { if (viewId != 0xffff) { Common::Rect celRect; - View *view = _gfx->getView(viewId); + View *view = _cache->getView(viewId); view->getCelRect(loopNo, celNo, x, y, z, &celRect); diff --git a/engines/sci/graphics/gui32.h b/engines/sci/graphics/gui32.h index 84fe7fef74..a336290776 100644 --- a/engines/sci/graphics/gui32.h +++ b/engines/sci/graphics/gui32.h @@ -33,13 +33,13 @@ namespace Sci { class Screen; class SciPalette; class Cursor; -class Gfx; +class GfxCache; +class GfxCompare; class Text; class SciGui32 { public: SciGui32(EngineState *s, Screen *screen, SciPalette *palette, Cursor *cursor); - SciGui32(); ~SciGui32(); void init(); @@ -93,7 +93,8 @@ protected: EngineState *_s; Screen *_screen; SciPalette *_palette; - Gfx *_gfx; + GfxCache *_cache; + GfxCompare *_compare; private: Common::Array<reg_t> _screenItems; diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index a3b55608d4..0695d98f62 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -31,8 +31,9 @@ #include "sci/event.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/helpers.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/gui.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" #include "sci/graphics/animate.h" #include "sci/graphics/cursor.h" #include "sci/graphics/font.h" @@ -42,8 +43,8 @@ namespace Sci { -Menu::Menu(SciEvent *event, SegManager *segMan, SciGui *gui, Gfx *gfx, Text *text, Screen *screen, Cursor *cursor) - : _event(event), _segMan(segMan), _gui(gui), _gfx(gfx), _text(text), _screen(screen), _cursor(cursor) { +Menu::Menu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, Text *text, Screen *screen, Cursor *cursor) + : _event(event), _segMan(segMan), _gui(gui), _ports(ports), _paint16(paint16), _text(text), _screen(screen), _cursor(cursor) { _listCount = 0; // We actually set active item in here and remember last selection of the user @@ -302,10 +303,10 @@ void Menu::drawBar() { GuiMenuList::iterator listEnd = _list.end(); // Hardcoded black on white and a black line afterwards - _gfx->FillRect(_gfx->_menuBarRect, 1, _screen->getColorWhite()); - _gfx->FillRect(_gfx->_menuLine, 1, 0); - _gfx->PenColor(0); - _gfx->MoveTo(8, 1); + _paint16->fillRect(_ports->_menuBarRect, 1, _screen->getColorWhite()); + _paint16->fillRect(_ports->_menuLine, 1, 0); + _ports->penColor(0); + _ports->moveTo(8, 1); listIterator = _list.begin(); while (listIterator != listEnd) { @@ -410,21 +411,21 @@ reg_t Menu::select(reg_t eventObject) { } if (!_menuSaveHandle.isNull()) { - _gfx->BitsRestore(_menuSaveHandle); + _paint16->bitsRestore(_menuSaveHandle); // Display line inbetween menubar and actual menu Common::Rect menuLine = _menuRect; menuLine.bottom = menuLine.top + 1; - _gfx->BitsShow(menuLine); + _paint16->bitsShow(menuLine); _gui->graphRedrawBox(_menuRect); _menuSaveHandle = NULL_REG; } if (!_barSaveHandle.isNull()) { - _gfx->BitsRestore(_barSaveHandle); - _gfx->BitsShow(_gfx->_menuRect); + _paint16->bitsRestore(_barSaveHandle); + _paint16->bitsShow(_ports->_menuRect); _barSaveHandle = NULL_REG; } if (_oldPort) - _gfx->SetPort(_oldPort); + _ports->setPort(_oldPort); if ((itemEntry) || (forceClaimed)) PUT_SEL32(_segMan, eventObject, claimed, make_reg(0, 1)); @@ -477,18 +478,18 @@ void Menu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { // Remove menu, if one is displayed if (!_menuSaveHandle.isNull()) { - _gfx->BitsRestore(_menuSaveHandle); + _paint16->bitsRestore(_menuSaveHandle); // Display line inbetween menubar and actual menu Common::Rect menuLine = _menuRect; menuLine.bottom = menuLine.top + 1; - _gfx->BitsShow(menuLine); + _paint16->bitsShow(menuLine); _gui->graphRedrawBox(_menuRect); } // First calculate rect of menu and also invert old and new menu text - _menuRect.top = _gfx->_menuBarRect.bottom; - menuTextRect.top = _gfx->_menuBarRect.top; - menuTextRect.bottom = _gfx->_menuBarRect.bottom; + _menuRect.top = _ports->_menuBarRect.bottom; + menuTextRect.top = _ports->_menuBarRect.top; + menuTextRect.bottom = _ports->_menuBarRect.bottom; menuTextRect.left = menuTextRect.right = 7; listIterator = _list.begin(); while (listIterator != listEnd) { @@ -500,20 +501,20 @@ void Menu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { _menuRect.left = menuTextRect.left; if ((listNr == newMenuId) || (listNr == oldMenuId)) { menuTextRect.translate(1, 0); - _gfx->InvertRect(menuTextRect); + _paint16->invertRect(menuTextRect); menuTextRect.translate(-1, 0); } listIterator++; } - _gfx->BitsShow(_gfx->_menuBarRect); + _paint16->bitsShow(_ports->_menuBarRect); _menuRect.bottom = _menuRect.top + 2; listItemIterator = _itemList.begin(); while (listItemIterator != listItemEnd) { listItemEntry = *listItemIterator; if (listItemEntry->menuId == newMenuId) { - _menuRect.bottom += _gfx->_curPort->fontHeight; + _menuRect.bottom += _ports->_curPort->fontHeight; maxTextWidth = MAX<int16>(maxTextWidth, listItemEntry->textWidth); maxTextRightAlignedWidth = MAX<int16>(maxTextRightAlignedWidth, listItemEntry->textRightAlignedWidth); } @@ -525,12 +526,12 @@ void Menu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { _menuRect.right -= 5; // Save background - _menuSaveHandle = _gfx->BitsSave(_menuRect, SCI_SCREEN_MASK_VISUAL); + _menuSaveHandle = _paint16->bitsSave(_menuRect, SCI_SCREEN_MASK_VISUAL); // Do the drawing - _gfx->FillRect(_menuRect, SCI_SCREEN_MASK_VISUAL, 0); + _paint16->fillRect(_menuRect, SCI_SCREEN_MASK_VISUAL, 0); _menuRect.left++; _menuRect.right--; _menuRect.bottom--; - _gfx->FillRect(_menuRect, SCI_SCREEN_MASK_VISUAL, _screen->getColorWhite()); + _paint16->fillRect(_menuRect, SCI_SCREEN_MASK_VISUAL, _screen->getColorWhite()); _menuRect.left += 8; topPos = _menuRect.top + 1; @@ -539,33 +540,33 @@ void Menu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { listItemEntry = *listItemIterator; if (listItemEntry->menuId == newMenuId) { if (!listItemEntry->separatorLine) { - _gfx->TextGreyedOutput(listItemEntry->enabled ? false : true); - _gfx->MoveTo(_menuRect.left, topPos); + _ports->textGreyedOutput(listItemEntry->enabled ? false : true); + _ports->moveTo(_menuRect.left, topPos); _text->Draw_String(listItemEntry->text.c_str()); - _gfx->MoveTo(_menuRect.right - listItemEntry->textRightAlignedWidth - 5, topPos); + _ports->moveTo(_menuRect.right - listItemEntry->textRightAlignedWidth - 5, topPos); _text->Draw_String(listItemEntry->textRightAligned.c_str()); } else { // We dont 100% follow sierra here, we draw the line from left to right. Looks better // BTW. SCI1.1 seems to put 2 pixels and then skip one, we don't do this at all (lsl6) - pixelPos.y = topPos + (_gfx->_curPort->fontHeight >> 1) - 1; + pixelPos.y = topPos + (_ports->_curPort->fontHeight >> 1) - 1; pixelPos.x = _menuRect.left - 7; while (pixelPos.x < (_menuRect.right - 1)) { _screen->putPixel(pixelPos.x, pixelPos.y, SCI_SCREEN_MASK_VISUAL, 0, 0, 0); pixelPos.x += 2; } } - topPos += _gfx->_curPort->fontHeight; + topPos += _ports->_curPort->fontHeight; } listItemIterator++; } - _gfx->TextGreyedOutput(false); + _ports->textGreyedOutput(false); // Draw the black line again - _gfx->FillRect(_gfx->_menuLine, 1, 0); + _paint16->fillRect(_ports->_menuLine, 1, 0); _menuRect.left -= 8; _menuRect.left--; _menuRect.right++; _menuRect.bottom++; - _gfx->BitsShow(_menuRect); + _paint16->bitsShow(_menuRect); } void Menu::invertMenuSelection(uint16 itemId) { @@ -574,12 +575,12 @@ void Menu::invertMenuSelection(uint16 itemId) { if (itemId == 0) return; - itemRect.top += (itemId - 1) * _gfx->_curPort->fontHeight + 1; - itemRect.bottom = itemRect.top + _gfx->_curPort->fontHeight; + itemRect.top += (itemId - 1) * _ports->_curPort->fontHeight + 1; + itemRect.bottom = itemRect.top + _ports->_curPort->fontHeight; itemRect.left++; itemRect.right--; - _gfx->InvertRect(itemRect); - _gfx->BitsShow(itemRect); + _paint16->invertRect(itemRect); + _paint16->bitsShow(itemRect); } void Menu::interactiveShowMouse() { @@ -627,7 +628,7 @@ uint16 Menu::mouseFindMenuItemSelection(Common::Point mousePosition, uint16 menu while (listItemIterator != listItemEnd) { listItemEntry = *listItemIterator; if (listItemEntry->menuId == menuId) { - curYstart += _gfx->_curPort->fontHeight; + curYstart += _ports->_curPort->fontHeight; // Found it if ((!itemId) && (curYstart > mousePosition.y)) itemId = listItemEntry->id; @@ -650,17 +651,17 @@ GuiMenuItemEntry *Menu::interactiveWithKeyboard() { // Also sierra sci didnt allow mouse interaction, when menu was activated via keyboard calculateTextWidth(); - _oldPort = _gfx->SetPort(_gfx->_menuPort); - _barSaveHandle = _gfx->BitsSave(_gfx->_menuRect, SCI_SCREEN_MASK_VISUAL); + _oldPort = _ports->setPort(_ports->_menuPort); + _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, SCI_SCREEN_MASK_VISUAL); - _gfx->PenColor(0); - _gfx->BackColor(_screen->getColorWhite()); + _ports->penColor(0); + _ports->backColor(_screen->getColorWhite()); drawBar(); drawMenu(0, curItemEntry->menuId); invertMenuSelection(curItemEntry->id); - _gfx->BitsShow(_gfx->_menuRect); - _gfx->BitsShow(_menuRect); + _paint16->bitsShow(_ports->_menuRect); + _paint16->bitsShow(_menuRect); while (true) { curEvent = _event->get(SCI_EVENT_ANY); @@ -771,14 +772,14 @@ GuiMenuItemEntry *Menu::interactiveWithMouse() { GuiMenuItemEntry *curItemEntry = NULL; calculateTextWidth(); - _oldPort = _gfx->SetPort(_gfx->_menuPort); - _barSaveHandle = _gfx->BitsSave(_gfx->_menuRect, SCI_SCREEN_MASK_VISUAL); + _oldPort = _ports->setPort(_ports->_menuPort); + _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, SCI_SCREEN_MASK_VISUAL); - _gfx->PenColor(0); - _gfx->BackColor(_screen->getColorWhite()); + _ports->penColor(0); + _ports->backColor(_screen->getColorWhite()); drawBar(); - _gfx->BitsShow(_gfx->_menuRect); + _paint16->bitsShow(_ports->_menuRect); while (true) { curEvent = _event->get(SCI_EVENT_ANY); @@ -812,7 +813,7 @@ GuiMenuItemEntry *Menu::interactiveWithMouse() { // Menu changed, remove cur menu and paint new menu drawMenu(curMenuId, newMenuId); if (firstMenuChange) { - _gfx->BitsShow(_gfx->_menuBarRect); + _paint16->bitsShow(_ports->_menuBarRect); firstMenuChange = false; } curMenuId = newMenuId; diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h index f594bdb496..2446ba40cf 100644 --- a/engines/sci/graphics/menu.h +++ b/engines/sci/graphics/menu.h @@ -78,7 +78,7 @@ typedef Common::List<GuiMenuItemEntry *> GuiMenuItemList; class Menu { public: - Menu(SciEvent *event, SegManager *segMan, SciGui *gui, Gfx *gfx, Text *text, Screen *screen, Cursor *cursor); + Menu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, Text *text, Screen *screen, Cursor *cursor); ~Menu(); void reset(); @@ -105,7 +105,8 @@ private: SciEvent *_event; SegManager *_segMan; SciGui *_gui; - Gfx *_gfx; + GfxPorts *_ports; + GfxPaint16 *_paint16; Text *_text; Screen *_screen; Cursor *_cursor; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp new file mode 100644 index 0000000000..539059c4d2 --- /dev/null +++ b/engines/sci/graphics/paint16.cpp @@ -0,0 +1,333 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/font.h" +#include "sci/graphics/picture.h" +#include "sci/graphics/view.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/palette.h" +#include "sci/graphics/text.h" + +namespace Sci { + +GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, Screen *screen, SciPalette *palette) + : _resMan(resMan), _segMan(segMan), _kernel(kernel), _cache(cache), _ports(ports), _screen(screen), _palette(palette) { +} + +GfxPaint16::~GfxPaint16() { +} + +void GfxPaint16::init(Text *text) { + _text = text; + + _EGAdrawingVisualize = false; +} + +void GfxPaint16::setEGAdrawingVisualize(bool state) { + _EGAdrawingVisualize = state; +} + +void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId) { + SciGuiPicture *picture = new SciGuiPicture(_resMan, _ports, _screen, _palette, pictureId, _EGAdrawingVisualize); + + // do we add to a picture? if not -> clear screen with white + if (!addToFlag) + clearScreen(_screen->getColorWhite()); + + picture->draw(animationNr, mirroredFlag, addToFlag, paletteId); + delete picture; +} + +// This one is the only one that updates screen! +void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { + View *view = _cache->getView(viewId); + Common::Rect celRect; + + if (view) { + celRect.left = leftPos; + celRect.top = topPos; + celRect.right = celRect.left + view->getWidth(loopNo, celNo); + celRect.bottom = celRect.top + view->getHeight(loopNo, celNo); + + drawCel(view, loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); + + if (getSciVersion() >= SCI_VERSION_1_1) { + if (!_screen->_picNotValidSci11) { + bitsShow(celRect); + } + } else { + if (!_screen->_picNotValid) + bitsShow(celRect); + } + } +} + +// This version of drawCel is not supposed to call BitsShow()! +void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { + drawCel(_cache->getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); +} + +// This version of drawCel is not supposed to call BitsShow()! +void GfxPaint16::drawCel(View *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { + Common::Rect clipRect = celRect; + clipRect.clip(_ports->_curPort->rect); + if (clipRect.isEmpty()) // nothing to draw + return; + + Common::Rect clipRectTranslated = clipRect; + _ports->offsetRect(clipRectTranslated); + if (scaleX == 128 && scaleY == 128) { + view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, false); + } else { + view->drawScaled(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, scaleX, scaleY); + } +} + +// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen +// Hires-cels are available only SCI 1.1+ +void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) { + View *view = _cache->getView(viewId); + Common::Rect celRect, curPortRect, clipRect, clipRectTranslated; + Common::Point curPortPos; + bool upscaledHiresHack = false; + + if (view) { + if ((leftPos == 0) && (topPos == 0)) { + // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle + // I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes + // coordinates to be 0 in the first place + byte *memoryPtr = NULL; + memoryPtr = kmem(_segMan, upscaledHiresHandle); + if (memoryPtr) { + Common::Rect upscaledHiresRect; + _screen->bitsGetRect(memoryPtr, &upscaledHiresRect); + leftPos = upscaledHiresRect.left; + topPos = upscaledHiresRect.top; + upscaledHiresHack = true; + } + } + + celRect.left = leftPos; + celRect.top = topPos; + celRect.right = celRect.left + view->getWidth(loopNo, celNo); + celRect.bottom = celRect.top + view->getHeight(loopNo, celNo); + // adjust curPort to upscaled hires + clipRect = celRect; + curPortRect = _ports->_curPort->rect; + curPortRect.top *= 2; curPortRect.bottom *= 2; curPortRect.bottom++; + curPortRect.left *= 2; curPortRect.right *= 2; curPortRect.right++; + clipRect.clip(curPortRect); + if (clipRect.isEmpty()) // nothing to draw + return; + + clipRectTranslated = clipRect; + if (!upscaledHiresHack) { + curPortPos.x = _ports->_curPort->left * 2; curPortPos.y = _ports->_curPort->top * 2; + clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y; + clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x; + } + + view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, true); + if (!_screen->_picNotValidSci11) { + _screen->copyDisplayRectToScreen(clipRectTranslated); + } + } +} + +void GfxPaint16::clearScreen(byte color) { + fillRect(_ports->_curPort->rect, SCI_SCREEN_MASK_ALL, color, 0, 0); +} + +void GfxPaint16::invertRect(const Common::Rect &rect) { + int16 oldpenmode = _ports->_curPort->penMode; + _ports->_curPort->penMode = 2; + fillRect(rect, 1, _ports->_curPort->penClr, _ports->_curPort->backClr); + _ports->_curPort->penMode = oldpenmode; +} + +void GfxPaint16::eraseRect(const Common::Rect &rect) { + fillRect(rect, 1, _ports->_curPort->backClr); +} + +void GfxPaint16::paintRect(const Common::Rect &rect) { + fillRect(rect, 1, _ports->_curPort->penClr); +} + +void GfxPaint16::fillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack, byte bControl) { + Common::Rect r = rect; + r.clip(_ports->_curPort->rect); + if (r.isEmpty()) // nothing to fill + return; + + int16 oldPenMode = _ports->_curPort->penMode; + _ports->offsetRect(r); + int16 x, y; + byte curVisual; + + // Doing visual first + if (drawFlags & SCI_SCREEN_MASK_VISUAL) { + if (oldPenMode == 2) { // invert mode + for (y = r.top; y < r.bottom; y++) { + for (x = r.left; x < r.right; x++) { + curVisual = _screen->getVisual(x, y); + if (curVisual == clrPen) { + _screen->putPixel(x, y, 1, clrBack, 0, 0); + } else if (curVisual == clrBack) { + _screen->putPixel(x, y, 1, clrPen, 0, 0); + } + } + } + } else { // just fill rect with ClrPen + for (y = r.top; y < r.bottom; y++) { + for (x = r.left; x < r.right; x++) { + _screen->putPixel(x, y, 1, clrPen, 0, 0); + } + } + } + } + + if (drawFlags < 2) + return; + drawFlags &= SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL; + + if (oldPenMode != 2) { + for (y = r.top; y < r.bottom; y++) { + for (x = r.left; x < r.right; x++) { + _screen->putPixel(x, y, drawFlags, 0, clrBack, bControl); + } + } + } else { + for (y = r.top; y < r.bottom; y++) { + for (x = r.left; x < r.right; x++) { + _screen->putPixel(x, y, drawFlags, 0, !_screen->getPriority(x, y), !_screen->getControl(x, y)); + } + } + } +} + +void GfxPaint16::frameRect(const Common::Rect &rect) { + Common::Rect r; + // left + r = rect; + r.right = rect.left + 1; + paintRect(r); + // right + r.right = rect.right; + r.left = rect.right - 1; + paintRect(r); + //top + r.left = rect.left; + r.bottom = rect.top + 1; + paintRect(r); + //bottom + r.bottom = rect.bottom; + r.top = rect.bottom - 1; + paintRect(r); +} + +void GfxPaint16::bitsShow(const Common::Rect &rect) { + Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom); + workerRect.clip(_ports->_curPort->rect); + if (workerRect.isEmpty()) // nothing to show + return; + + _ports->offsetRect(workerRect); + _screen->copyRectToScreen(workerRect); +} + +void GfxPaint16::bitsShowHires(const Common::Rect &rect) { + _screen->copyDisplayRectToScreen(rect); +} + +reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) { + reg_t memoryId; + byte *memoryPtr; + int size; + + Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom); + workerRect.clip(_ports->_curPort->rect); + if (workerRect.isEmpty()) // nothing to save + return NULL_REG; + + if (screenMask == SCI_SCREEN_MASK_DISPLAY) { + // Adjust rect to upscaled hires, but dont adjust according to port + workerRect.top *= 2; workerRect.bottom *= 2; workerRect.bottom++; + workerRect.left *= 2; workerRect.right *= 2; workerRect.right++; + } else { + _ports->offsetRect(workerRect); + } + + // now actually ask _screen how much space it will need for saving + size = _screen->bitsGetDataSize(workerRect, screenMask); + + memoryId = kalloc(_segMan, "SaveBits()", size); + memoryPtr = kmem(_segMan, memoryId); + _screen->bitsSave(workerRect, screenMask, memoryPtr); + return memoryId; +} + +void GfxPaint16::bitsGetRect(reg_t memoryHandle, Common::Rect *destRect) { + byte *memoryPtr = NULL; + + if (!memoryHandle.isNull()) { + memoryPtr = kmem(_segMan, memoryHandle); + + if (memoryPtr) { + _screen->bitsGetRect(memoryPtr, destRect); + } + } +} + +void GfxPaint16::bitsRestore(reg_t memoryHandle) { + byte *memoryPtr = NULL; + + if (!memoryHandle.isNull()) { + memoryPtr = kmem(_segMan, memoryHandle); + + if (memoryPtr) { + _screen->bitsRestore(memoryPtr); + kfree(_segMan, memoryHandle); + } + } +} + +void GfxPaint16::bitsFree(reg_t memoryHandle) { + if (!memoryHandle.isNull()) { + kfree(_segMan, memoryHandle); + } +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/gfx.h b/engines/sci/graphics/paint16.h index 284cc6f8f4..2a6f35a360 100644 --- a/engines/sci/graphics/gfx.h +++ b/engines/sci/graphics/paint16.h @@ -23,8 +23,8 @@ * */ -#ifndef SCI_GRAPHICS_GFX_H -#define SCI_GRAPHICS_GFX_H +#ifndef SCI_GRAPHICS_PAINT16_H +#define SCI_GRAPHICS_PAINT16_H #include "sci/graphics/gui.h" @@ -32,56 +32,20 @@ namespace Sci { -#define SCI_TEXT_ALIGNMENT_RIGHT -1 -#define SCI_TEXT_ALIGNMENT_CENTER 1 -#define SCI_TEXT_ALIGNMENT_LEFT 0 - +class GfxPorts; class Screen; class SciPalette; class Font; class SciGuiPicture; class View; -typedef Common::HashMap<int, View *> ViewCache; - -class Gfx { +class GfxPaint16 { public: - Gfx(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, Screen *screen, SciPalette *palette); - ~Gfx(); + GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, Screen *screen, SciPalette *palette); + ~GfxPaint16(); void init(Text *text); - byte *GetSegment(byte seg); - void ResetScreen(); - - Port *SetPort(Port *port); - Port *GetPort(); - void SetOrigin(int16 left, int16 top); - void MoveTo(int16 left, int16 top); - void Move(int16 left, int16 top); - void OpenPort(Port *port); - void PenColor(int16 color); - void BackColor(int16 color); - void PenMode(int16 mode); - void TextGreyedOutput(bool state); - int16 GetPointSize(); - - void ClearScreen(byte color = 255); - void InvertRect(const Common::Rect &rect); - void EraseRect(const Common::Rect &rect); - void PaintRect(const Common::Rect &rect); - void FillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack = 0, byte bControl = 0); - void FrameRect(const Common::Rect &rect); - void OffsetRect(Common::Rect &r); - void OffsetLine(Common::Point &start, Common::Point &end); - - void BitsShow(const Common::Rect &r); - void BitsShowHires(const Common::Rect &rect); - reg_t BitsSave(const Common::Rect &rect, byte screenFlags); - void BitsGetRect(reg_t memoryHandle, Common::Rect *destRect); - void BitsRestore(reg_t memoryHandle); - void BitsFree(reg_t memoryHandle); - void setEGAdrawingVisualize(bool state); void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId); @@ -90,51 +54,32 @@ public: void drawCel(View *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); void drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX = 128, uint16 scaleY = 128); - uint16 onControl(uint16 screenMask, Common::Rect rect); - - void PriorityBandsInit(int16 bandCount, int16 top, int16 bottom); - void PriorityBandsInit(byte *data); - void PriorityBandsRemember(byte *data); - void PriorityBandsRecall(); - byte CoordinateToPriority(int16 y); - int16 PriorityToCoordinate(byte priority); - - bool CanBeHereCheckRectList(reg_t checkObject, Common::Rect checkRect, List *list); - - void SetNowSeen(reg_t objectReference); + void clearScreen(byte color = 255); + void invertRect(const Common::Rect &rect); + void eraseRect(const Common::Rect &rect); + void paintRect(const Common::Rect &rect); + void fillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack = 0, byte bControl = 0); + void frameRect(const Common::Rect &rect); - Port *_menuPort; - Common::Rect _menuBarRect; - Common::Rect _menuRect; - Common::Rect _menuLine; - Port *_curPort; - - View *getView(GuiResourceId viewNum); + void bitsShow(const Common::Rect &r); + void bitsShowHires(const Common::Rect &rect); + reg_t bitsSave(const Common::Rect &rect, byte screenFlags); + void bitsGetRect(reg_t memoryHandle, Common::Rect *destRect); + void bitsRestore(reg_t memoryHandle); + void bitsFree(reg_t memoryHandle); private: - void purgeCache(); - ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; + GfxCache *_cache; + GfxPorts *_ports; Screen *_screen; SciPalette *_palette; Text *_text; - Common::Rect _bounds; - Port *_mainPort; - - // Priority Bands related variables - int16 _priorityTop, _priorityBottom, _priorityBandCount; - byte _priorityBands[200]; - - ViewCache _cachedViews; - // true means make EGA picture drawing visible bool _EGAdrawingVisualize; - - byte priorityBandsMemory[14]; - bool priorityBandsMemoryActive; }; } // End of namespace Sci diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index f914158fb1..9831a60c2c 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -28,13 +28,13 @@ #include "sci/engine/state.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/ports.h" #include "sci/graphics/picture.h" namespace Sci { -SciGuiPicture::SciGuiPicture(ResourceManager *resMan, Gfx *gfx, Screen *screen, SciPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize) - : _resMan(resMan), _gfx(gfx), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) { +SciGuiPicture::SciGuiPicture(ResourceManager *resMan, GfxPorts *ports, Screen *screen, SciPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize) + : _resMan(resMan), _ports(ports), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) { assert(resourceId != -1); initData(resourceId); } @@ -81,7 +81,7 @@ void SciGuiPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, i void SciGuiPicture::reset() { int16 x, y; - for (y = _gfx->GetPort()->top; y < _screen->getHeight(); y++) { + for (y = _ports->getPort()->top; y < _screen->getHeight(); y++) { for (x = 0; x < _screen->getWidth(); x++) { _screen->putPixel(x, y, SCI_SCREEN_MASK_ALL, 255, 0, 0); } @@ -113,7 +113,7 @@ void SciGuiPicture::drawSci11Vga() { drawVectorData(inbuffer + vector_dataPos, vector_size); // Remember priority band information for later - _gfx->PriorityBandsRemember(inbuffer + 40); + _ports->priorityBandsRemember(inbuffer + 40); } #ifdef ENABLE_SCI32 @@ -265,12 +265,12 @@ void SciGuiPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rle memcpy(celBitmap, rlePtr, pixelCount); } - if (_gfx) { + if (_ports) { // Set initial vertical coordinate by using current port - y = callerY + _gfx->GetPort()->top; - lastY = MIN<int16>(height + y, _gfx->GetPort()->rect.bottom + _gfx->GetPort()->top); - leftX = callerX + _gfx->GetPort()->left; - rightX = MIN<int16>(width + leftX, _gfx->GetPort()->rect.right + _gfx->GetPort()->left); + y = callerY + _ports->getPort()->top; + lastY = MIN<int16>(height + y, _ports->getPort()->rect.bottom + _ports->getPort()->top); + leftX = callerX + _ports->getPort()->left; + rightX = MIN<int16>(width + leftX, _ports->getPort()->rect.right + _ports->getPort()->left); } else { y = callerY + 10; // TODO: Implement plane support for SCI32 lastY = y + height; @@ -445,7 +445,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { vectorGetRelCoords(data, curPos, x, y); Common::Point startPoint(oldx, oldy); Common::Point endPoint(x, y); - _gfx->OffsetLine(startPoint, endPoint); + _ports->offsetLine(startPoint, endPoint); _screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control); } break; @@ -456,7 +456,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { vectorGetRelCoordsMed(data, curPos, x, y); Common::Point startPoint(oldx, oldy); Common::Point endPoint(x, y); - _gfx->OffsetLine(startPoint, endPoint); + _ports->offsetLine(startPoint, endPoint); _screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control); } break; @@ -467,7 +467,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { vectorGetAbsCoords(data, curPos, x, y); Common::Point startPoint(oldx, oldy); Common::Point endPoint(x, y); - _gfx->OffsetLine(startPoint, endPoint); + _ports->offsetLine(startPoint, endPoint); _screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control); } break; @@ -550,7 +550,7 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { curPos += size; break; case PIC_OPX_EGA_SET_PRIORITY_TABLE: - _gfx->PriorityBandsInit(data + curPos); + _ports->priorityBandsInit(data + curPos); curPos += 14; break; default: @@ -590,11 +590,11 @@ void SciGuiPicture::drawVectorData(byte *data, int dataSize) { curPos += size; break; case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST: - _gfx->PriorityBandsInit(-1, READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2)); + _ports->priorityBandsInit(-1, READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2)); curPos += 4; break; case PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT: - _gfx->PriorityBandsInit(data + curPos); + _ports->priorityBandsInit(data + curPos); curPos += 14; break; default: @@ -677,7 +677,7 @@ void SciGuiPicture::vectorGetPatternTexture(byte *data, int &curPos, int16 patte // Do not replace w/ some generic code. This algo really needs to behave exactly as the one from sierra void SciGuiPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, byte control) { - Port *curPort = _gfx->GetPort(); + Port *curPort = _ports->getPort(); Common::Stack<Common::Point> stack; Common::Point p, p1; byte screenMask = _screen->getDrawingMask(color, priority, control); @@ -979,7 +979,7 @@ void SciGuiPicture::vectorPattern(int16 x, int16 y, byte color, byte priority, b rect.top = y; rect.left = x; rect.setHeight((size*2)+1); rect.setWidth((size*2)+2); - _gfx->OffsetRect(rect); + _ports->offsetRect(rect); rect.clip(_screen->getWidth(), _screen->getHeight()); if (code & SCI_PATTERN_CODE_RECTANGLE) { diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h index 04a5fb8fd6..34e8988bea 100644 --- a/engines/sci/graphics/picture.h +++ b/engines/sci/graphics/picture.h @@ -32,9 +32,13 @@ namespace Sci { #define SCI_PATTERN_CODE_USE_TEXTURE 0x20 #define SCI_PATTERN_CODE_PENSIZE 0x07 +class GfxPorts; +class Screen; +class SciPalette; + class SciGuiPicture { public: - SciGuiPicture(ResourceManager *resMan, Gfx *gfx, Screen *screen, SciPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize = false); + SciGuiPicture(ResourceManager *resMan, GfxPorts *ports, Screen *screen, SciPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize = false); ~SciGuiPicture(); GuiResourceId getResourceId(); @@ -63,7 +67,7 @@ private: void vectorPatternTexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture); ResourceManager *_resMan; - Gfx *_gfx; + GfxPorts *_ports; Screen *_screen; SciPalette *_palette; diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp new file mode 100644 index 0000000000..2b4a9c9afa --- /dev/null +++ b/engines/sci/graphics/ports.cpp @@ -0,0 +1,530 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/text.h" +#include "sci/graphics/ports.h" + +namespace Sci { + +// window styles +enum { + SCI_WINDOWMGR_STYLE_TRANSPARENT = (1 << 0), + SCI_WINDOWMGR_STYLE_NOFRAME = (1 << 1), + SCI_WINDOWMGR_STYLE_TITLE = (1 << 2), + SCI_WINDOWMGR_STYLE_TOPMOST = (1 << 3), + SCI_WINDOWMGR_STYLE_USER = (1 << 7) +}; + +GfxPorts::GfxPorts(SegManager *segMan, Screen *screen) + : _segMan(segMan), _screen(screen) { +} + +GfxPorts::~GfxPorts() { + // TODO: Clear _windowList and delete all stuff in it? + delete _mainPort; + delete _menuPort; +} + +void GfxPorts::init(SciGui *gui, GfxPaint16 *paint16, Text *text, Common::String gameId) { + int16 offTop = 10; + + _gui = gui; + _paint16 = paint16; + _text = text; + + // _mainPort is not known to windowmanager, that's okay according to sierra sci + // its not even used currently in our engine + _mainPort = new Port(0); + setPort(_mainPort); + openPort(_mainPort); + + // _menuPort has actually hardcoded id 0xFFFF. Its not meant to be known to windowmanager according to sierra sci + _menuPort = new Port(0xFFFF); + openPort(_menuPort); + _text->SetFont(0); + _menuPort->rect = Common::Rect(0, 0, _screen->getWidth(), _screen->getHeight()); + _menuBarRect = Common::Rect(0, 0, _screen->getWidth(), 9); + _menuRect = Common::Rect(0, 0, _screen->getWidth(), 10); + _menuLine = Common::Rect(0, 9, _screen->getWidth(), 10); + + _wmgrPort = new Port(1); + _windowsById.resize(2); + _windowsById[0] = _wmgrPort; // wmgrPort is supposed to be accessible via id 0 + _windowsById[1] = _wmgrPort; // but wmgrPort may not actually have id 0, so we assign id 1 (as well) + // Background: sierra sci replies with the offset of curPort on kGetPort calls. If we reply with 0 there most games + // will work, but some scripts seem to check for 0 and initialize the variable again in that case + // resulting in problems. + + // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. + // This actually meant not skipping the first 10 pixellines in windowMgrPort + if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3") + offTop = 0; + + openPort(_wmgrPort); + setPort(_wmgrPort); + setOrigin(0, offTop); + _wmgrPort->rect.bottom = _screen->getHeight() - offTop; + _wmgrPort->rect.right = _screen->getWidth(); + _wmgrPort->rect.moveTo(0, 0); + _wmgrPort->curTop = 0; + _wmgrPort->curLeft = 0; + _windowList.push_front(_wmgrPort); + + _picWind = newWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); + + priorityBandsMemoryActive = false; +} + +void GfxPorts::kernelSetActive(uint16 portId) { + switch (portId) { + case 0: + setPort(_wmgrPort); + break; + case 0xFFFF: + setPort(_menuPort); + break; + default: + setPort(getPortById(portId)); + }; +} + +Common::Rect GfxPorts::kernelGetPicWindow(int16 &picTop, int16 &picLeft) { + picTop = _picWind->top; + picLeft = _picWind->left; + return _picWind->rect; +} + +void GfxPorts::kernelSetPicWindow(Common::Rect rect, int16 picTop, int16 picLeft, bool initPriorityBandsFlag) { + _picWind->rect = rect; + _picWind->top = picTop; + _picWind->left = picLeft; + // TODO: fixme before joining + //if (initPriorityBandsFlag) + // initPriorityBands(); +} + +reg_t GfxPorts::kernelGetActive() { + return make_reg(0, getPort()->id); +} + +reg_t GfxPorts::kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title) { + Window *wnd = NULL; + + if (restoreRect.top != 0 && restoreRect.left != 0 && restoreRect.height() != 0 && restoreRect.width() != 0) + wnd = newWindow(dims, &restoreRect, title, style, priority, false); + else + wnd = newWindow(dims, NULL, title, style, priority, false); + wnd->penClr = colorPen; + wnd->backClr = colorBack; + drawWindow(wnd); + + return make_reg(0, wnd->id); +} + +void GfxPorts::kernelDisposeWindow(uint16 windowId, bool reanimate) { + Window *wnd = (Window *)getPortById(windowId); + disposeWindow(wnd, reanimate); +} + +int16 GfxPorts::isFrontWindow(Window *pWnd) { + return _windowList.back() == pWnd; +} + +void GfxPorts::beginUpdate(Window *wnd) { + Port *oldPort = setPort(_wmgrPort); + PortList::iterator it = _windowList.reverse_begin(); + const PortList::iterator end = Common::find(_windowList.begin(), _windowList.end(), wnd); + while (it != end) { + // FIXME: We also store Port objects in the window list. + // We should add a check that we really only pass windows here... + updateWindow((Window *)*it); + --it; + } + setPort(oldPort); +} + +void GfxPorts::endUpdate(Window *wnd) { + Port *oldPort = setPort(_wmgrPort); + const PortList::iterator end = _windowList.end(); + PortList::iterator it = Common::find(_windowList.begin(), end, wnd); + + // wnd has to be in _windowList + assert(it != end); + + while (++it != end) { + // FIXME: We also store Port objects in the window list. + // We should add a check that we really only pass windows here... + updateWindow((Window *)*it); + } + + setPort(oldPort); +} + +Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) { + // Find an unused window/port id + uint id = 1; + while (id < _windowsById.size() && _windowsById[id]) { + ++id; + } + if (id == _windowsById.size()) + _windowsById.push_back(0); + assert(0 < id && id < 0xFFFF); + + Window *pwnd = new Window(id); + Common::Rect r; + + if (!pwnd) { + warning("Can't open window!"); + return 0; + } + + _windowsById[id] = pwnd; + if (style & SCI_WINDOWMGR_STYLE_TOPMOST) + _windowList.push_front(pwnd); + else + _windowList.push_back(pwnd); + openPort(pwnd); + r = dims; + pwnd->rect = dims; + if (restoreRect) + pwnd->restoreRect = *restoreRect; + + pwnd->wndStyle = style; + pwnd->hSaved1 = pwnd->hSaved2 = NULL_REG; + pwnd->bDrawn = false; + if ((style & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) + pwnd->saveScreenMask = (priority == -1 ? SCI_SCREEN_MASK_VISUAL : SCI_SCREEN_MASK_VISUAL | SCI_SCREEN_MASK_PRIORITY); + + if (title && (style & SCI_WINDOWMGR_STYLE_TITLE)) { + pwnd->title = title; + } + + r = dims; + if ((style != SCI_WINDOWMGR_STYLE_USER) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME)) { + r.grow(1); + if (style & SCI_WINDOWMGR_STYLE_TITLE) { + r.top -= 10; + r.bottom++; + } + } + + // FIXME: it seems as if shadows may result in the window getting moved one upwards + // so that the shadow is visible (lsl5) + + pwnd->dims = r; + const Common::Rect *wmprect = &_wmgrPort->rect; + int16 oldtop = pwnd->dims.top; + int16 oldleft = pwnd->dims.left; + if (wmprect->top > pwnd->dims.top) + pwnd->dims.moveTo(pwnd->dims.left, wmprect->top); + + if (wmprect->bottom < pwnd->dims.bottom) + pwnd->dims.moveTo(pwnd->dims.left, wmprect->bottom - pwnd->dims.bottom + pwnd->dims.top); + + if (wmprect->right < pwnd->dims.right) + pwnd->dims.moveTo(wmprect->right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top); + + if (wmprect->left > pwnd->dims.left) + pwnd->dims.moveTo(wmprect->left, pwnd->dims.top); + + pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop); + if (restoreRect == 0) + pwnd->restoreRect = pwnd->dims; + + if (!(pwnd->wndStyle & (SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_NOFRAME))) { + // The shadow is drawn slightly outside the window. + // Enlarge restoreRect to cover that. + pwnd->restoreRect.bottom++; + pwnd->restoreRect.right++; + } + + if (draw) + drawWindow(pwnd); + setPort((Port *)pwnd); + setOrigin(pwnd->rect.left, pwnd->rect.top + _wmgrPort->top); + pwnd->rect.moveTo(0, 0); + return pwnd; +} + +void GfxPorts::drawWindow(Window *pWnd) { + if (pWnd->bDrawn) + return; + Common::Rect r; + int16 wndStyle = pWnd->wndStyle; + + pWnd->bDrawn = true; + Port *oldport = setPort(_wmgrPort); + penColor(0); + if ((wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) { + pWnd->hSaved1 = _paint16->bitsSave(pWnd->restoreRect, SCI_SCREEN_MASK_VISUAL); + if (pWnd->saveScreenMask & SCI_SCREEN_MASK_PRIORITY) { + pWnd->hSaved2 = _paint16->bitsSave(pWnd->restoreRect, SCI_SCREEN_MASK_PRIORITY); + if ((wndStyle & SCI_WINDOWMGR_STYLE_USER) == 0) + _paint16->fillRect(pWnd->restoreRect, SCI_SCREEN_MASK_PRIORITY, 0, 15); + } + } + + // drawing frame,shadow and title + if (!(wndStyle & SCI_WINDOWMGR_STYLE_USER)) { + r = pWnd->dims; + if (!(wndStyle & SCI_WINDOWMGR_STYLE_NOFRAME)) { + r.translate(1, 1); + _paint16->frameRect(r);// shadow + r.translate(-1, -1); + _paint16->frameRect(r);// window frame + + if (wndStyle & SCI_WINDOWMGR_STYLE_TITLE) { + _paint16->frameRect(r); + r.grow(-1); + if (getSciVersion() <= SCI_VERSION_0_LATE) + _paint16->fillRect(r, SCI_SCREEN_MASK_VISUAL, 8); // grey titlebar for SCI0 + else + _paint16->fillRect(r, SCI_SCREEN_MASK_VISUAL, 0); // black titlebar for SCI01+ + if (!pWnd->title.empty()) { + int16 oldcolor = getPort()->penClr; + penColor(255); + _text->Box(pWnd->title.c_str(), 1, r, SCI_TEXT_ALIGNMENT_CENTER, 0); + penColor(oldcolor); + } + + r = pWnd->dims; + r.top += 9; + } + + r.grow(-1); + } + + if (!(wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT)) + _paint16->fillRect(r, SCI_SCREEN_MASK_VISUAL, pWnd->backClr); + + _paint16->bitsShow(pWnd->restoreRect); + } + setPort(oldport); +} + +void GfxPorts::disposeWindow(Window *pWnd, bool reanimate) { + setPort(_wmgrPort); + _paint16->bitsRestore(pWnd->hSaved1); + _paint16->bitsRestore(pWnd->hSaved2); + if (!reanimate) + _paint16->bitsShow(pWnd->restoreRect); + else + _gui->graphRedrawBox(pWnd->restoreRect); + _windowList.remove(pWnd); + setPort(_windowList.back()); + _windowsById[pWnd->id] = 0; + delete pWnd; +} + +void GfxPorts::updateWindow(Window *wnd) { + reg_t handle; + + if (wnd->saveScreenMask && wnd->bDrawn) { + handle = _paint16->bitsSave(wnd->restoreRect, SCI_SCREEN_MASK_VISUAL); + _paint16->bitsRestore(wnd->hSaved1); + wnd->hSaved1 = handle; + if (wnd->saveScreenMask & SCI_SCREEN_MASK_PRIORITY) { + handle = _paint16->bitsSave(wnd->restoreRect, SCI_SCREEN_MASK_PRIORITY); + _paint16->bitsRestore(wnd->hSaved2); + wnd->hSaved2 = handle; + } + } +} + +Port *GfxPorts::getPortById(uint16 id) { + if (id > _windowsById.size()) + error("getPortById() received invalid id"); + return _windowsById[id]; +} + + + +Port *GfxPorts::setPort(Port *newPort) { + Port *oldPort = _curPort; + _curPort = newPort; + return oldPort; +} + +Port *GfxPorts::getPort() { + return _curPort; +} + +void GfxPorts::setOrigin(int16 left, int16 top) { + _curPort->left = left; + _curPort->top = top; +} + +void GfxPorts::moveTo(int16 left, int16 top) { + _curPort->curTop = top; + _curPort->curLeft = left; +} + +void GfxPorts::move(int16 left, int16 top) { + _curPort->curTop += top; + _curPort->curLeft += left; +} + +void GfxPorts::openPort(Port *port) { + port->fontId = 0; + port->fontHeight = 8; + + Port *tmp = _curPort; + _curPort = port; + _text->SetFont(port->fontId); + _curPort = tmp; + + port->top = 0; + port->left = 0; + port->greyedOutput = false; + port->penClr = 0; + port->backClr = 255; + port->penMode = 0; + port->rect = _bounds; +} + +void GfxPorts::penColor(int16 color) { + _curPort->penClr = color; +} + +void GfxPorts::backColor(int16 color) { + _curPort->backClr = color; +} + +void GfxPorts::penMode(int16 mode) { + _curPort->penMode = mode; +} + +void GfxPorts::textGreyedOutput(bool state) { + _curPort->greyedOutput = state; +} + +int16 GfxPorts::getPointSize() { + return _curPort->fontHeight; +} + +void GfxPorts::offsetRect(Common::Rect &r) { + r.top += _curPort->top; + r.bottom += _curPort->top; + r.left += _curPort->left; + r.right += _curPort->left; +} + +void GfxPorts::offsetLine(Common::Point &start, Common::Point &end) { + start.x += _curPort->left; + start.y += _curPort->top; + end.x += _curPort->left; + end.y += _curPort->top; +} + +void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) { + int16 y; + int32 bandSize; + + // This code is for 320x200 games only + if (_screen->getHeight() != 200) + return; + + if (bandCount != -1) + _priorityBandCount = bandCount; + + _priorityTop = top; + _priorityBottom = bottom; + + // Do NOT modify this algo or optimize it anyhow, sierra sci used int32 for calculating the + // priority bands and by using double or anything rounding WILL destroy the result + bandSize = ((_priorityBottom - _priorityTop) * 2000) / _priorityBandCount; + + memset(_priorityBands, 0, sizeof(byte) * _priorityTop); + for (y = _priorityTop; y < _priorityBottom; y++) + _priorityBands[y] = 1 + (((y - _priorityTop) * 2000) / bandSize); + if (_priorityBandCount == 15) { + // When having 15 priority bands, we actually replace band 15 with band 14, cause the original sci interpreter also + // does it that way as well + y = _priorityBottom; + while (_priorityBands[--y] == _priorityBandCount) + _priorityBands[y]--; + } + // We fill space that is left over with the highest band (hardcoded 200 limit, because this algo isnt meant to be used on hires) + for (y = _priorityBottom; y < 200; y++) + _priorityBands[y] = _priorityBandCount; +} + +void GfxPorts::priorityBandsInit(byte *data) { + int i = 0, inx; + byte priority = 0; + + for (inx = 0; inx < 14; inx++) { + priority = *data++; + while (i < priority) + _priorityBands[i++] = inx; + } + while (i < 200) + _priorityBands[i++] = inx; +} + +// Gets used by picture class to remember priority bands data from sci1.1 pictures that need to get applied when +// transitioning to that picture +void GfxPorts::priorityBandsRemember(byte *data) { + int bandNo; + for (bandNo = 0; bandNo < 14; bandNo++) { + priorityBandsMemory[bandNo] = READ_LE_UINT16(data); + data += 2; + } + priorityBandsMemoryActive = true; +} + +void GfxPorts::priorityBandsRecall() { + if (priorityBandsMemoryActive) { + priorityBandsInit((byte *)&priorityBandsMemory); + priorityBandsMemoryActive = false; + } +} + +byte GfxPorts::coordinateToPriority(int16 y) { + if (y < _priorityTop) + return _priorityBands[_priorityTop]; + if (y > _priorityBottom) + return _priorityBands[_priorityBottom]; + return _priorityBands[y]; +} + +int16 GfxPorts::priorityToCoordinate(byte priority) { + int16 y; + if (priority <= _priorityBandCount) { + for (y = 0; y <= _priorityBottom; y++) + if (_priorityBands[y] == priority) + return y; + } + return _priorityBottom; +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h new file mode 100644 index 0000000000..a200748e4f --- /dev/null +++ b/engines/sci/graphics/ports.h @@ -0,0 +1,122 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_GRAPHICS_PORTS_H +#define SCI_GRAPHICS_PORTS_H + +#include "common/list.h" +#include "common/array.h" + +namespace Sci { + +class SciGui; +class GfxPaint16; +class Screen; +class Text; + +class GfxPorts { +public: + GfxPorts(SegManager *segMan, Screen *screen); + ~GfxPorts(); + + void init(SciGui *gui, GfxPaint16 *paint16, Text *text, Common::String gameId); + + void kernelSetActive(uint16 portId); + Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft); + void kernelSetPicWindow(Common::Rect rect, int16 picTop, int16 picLeft, bool initPriorityBandsFlag); + reg_t kernelGetActive(); + reg_t kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title); + void kernelDisposeWindow(uint16 windowId, bool reanimate); + + int16 isFrontWindow(Window *wnd); + void beginUpdate(Window *wnd); + void endUpdate(Window *wnd); + Window *newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw); + void drawWindow(Window *wnd); + void disposeWindow(Window *pWnd, bool reanimate); + void updateWindow(Window *wnd); + + Port *getPortById(uint16 id); + + Port *setPort(Port *newPort); + Port *getPort(); + void setOrigin(int16 left, int16 top); + void moveTo(int16 left, int16 top); + void move(int16 left, int16 top); + void openPort(Port *port); + void penColor(int16 color); + void backColor(int16 color); + void penMode(int16 mode); + void textGreyedOutput(bool state); + int16 getPointSize(); + + void offsetRect(Common::Rect &r); + void offsetLine(Common::Point &start, Common::Point &end); + + void priorityBandsInit(int16 bandCount, int16 top, int16 bottom); + void priorityBandsInit(byte *data); + void priorityBandsRemember(byte *data); + void priorityBandsRecall(); + byte coordinateToPriority(int16 y); + int16 priorityToCoordinate(byte priority); + + Port *_wmgrPort; + Window *_picWind; + + Port *_menuPort; + Common::Rect _menuBarRect; + Common::Rect _menuRect; + Common::Rect _menuLine; + Port *_curPort; + +private: + typedef Common::List<Port *> PortList; + + SegManager *_segMan; + SciGui *_gui; + GfxPaint16 *_paint16; + Screen *_screen; + Text *_text; + + /** The list of open 'windows' (and ports), in visual order. */ + PortList _windowList; + + /** The list of all open 'windows' (and ports), ordered by their id. */ + Common::Array<Port *> _windowsById; + + Common::Rect _bounds; + Port *_mainPort; + + // Priority Bands related variables + int16 _priorityTop, _priorityBottom, _priorityBandCount; + byte _priorityBands[200]; + + byte priorityBandsMemory[14]; + bool priorityBandsMemoryActive; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp index 8cc5a84a6e..0f880b40a2 100644 --- a/engines/sci/graphics/robot.cpp +++ b/engines/sci/graphics/robot.cpp @@ -25,7 +25,6 @@ #include "sci/sci.h" #include "sci/engine/state.h" -#include "sci/graphics/gfx.h" #include "sci/graphics/screen.h" #include "sci/graphics/robot.h" diff --git a/engines/sci/graphics/text.cpp b/engines/sci/graphics/text.cpp index c5a6c5ced2..f1be3eb1b5 100644 --- a/engines/sci/graphics/text.cpp +++ b/engines/sci/graphics/text.cpp @@ -29,14 +29,15 @@ #include "sci/sci.h" #include "sci/engine/state.h" -#include "sci/graphics/gfx.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" #include "sci/graphics/font.h" #include "sci/graphics/text.h" namespace Sci { -Text::Text(ResourceManager *resMan, Gfx *gfx, Screen *screen) - : _resMan(resMan), _gfx(gfx), _screen(screen) { +Text::Text(ResourceManager *resMan, GfxPorts *ports, GfxPaint16 *paint16, Screen *screen) + : _resMan(resMan), _ports(ports), _paint16(paint16), _screen(screen) { init(); } @@ -53,13 +54,13 @@ void Text::init() { } GuiResourceId Text::GetFontId() { - return _gfx->_curPort->fontId; + return _ports->_curPort->fontId; } Font *Text::GetFont() { - if ((_font == NULL) || (_font->getResourceId() != _gfx->_curPort->fontId)) { + if ((_font == NULL) || (_font->getResourceId() != _ports->_curPort->fontId)) { delete _font; - _font = new Font(_resMan, _gfx->_curPort->fontId); + _font = new Font(_resMan, _ports->_curPort->fontId); } return _font; @@ -71,8 +72,8 @@ void Text::SetFont(GuiResourceId fontId) { _font = new Font(_resMan, fontId); } - _gfx->_curPort->fontId = _font->getResourceId(); - _gfx->_curPort->fontHeight = _font->getHeight(); + _ports->_curPort->fontId = _font->getResourceId(); + _ports->_curPort->fontHeight = _font->getHeight(); } void Text::CodeSetFonts(int argc, reg_t *argv) { @@ -98,21 +99,21 @@ void Text::CodeSetColors(int argc, reg_t *argv) { } void Text::ClearChar(int16 chr) { - if (_gfx->_curPort->penMode != 1) + if (_ports->_curPort->penMode != 1) return; Common::Rect rect; - rect.top = _gfx->_curPort->curTop; - rect.bottom = rect.top + _gfx->_curPort->fontHeight; - rect.left = _gfx->_curPort->curLeft; + rect.top = _ports->_curPort->curTop; + rect.bottom = rect.top + _ports->_curPort->fontHeight; + rect.left = _ports->_curPort->curLeft; rect.right = rect.left + GetFont()->getCharWidth(chr); - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); } void Text::DrawChar(int16 chr) { chr = chr & 0xFF; ClearChar(chr); StdChar(chr); - _gfx->_curPort->curLeft += GetFont()->getCharWidth(chr); + _ports->_curPort->curLeft += GetFont()->getCharWidth(chr); } void Text::StdChar(int16 chr) { @@ -151,10 +152,10 @@ int16 Text::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 org switch (curCode) { case 'c': // set text color if (curCodeParm == 0) { - _gfx->_curPort->penClr = orgPenColor; + _ports->_curPort->penClr = orgPenColor; } else { if (curCodeParm < _codeColorsCount) { - _gfx->_curPort->penClr = _codeColors[curCodeParm]; + _ports->_curPort->penClr = _codeColors[curCodeParm]; } } break; @@ -177,7 +178,7 @@ int16 Text::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId int16 maxChars = 0, curCharCount = 0; uint16 width = 0; GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _gfx->_curPort->penClr; + int16 oldPenColor = _ports->_curPort->penClr; GetFont(); if (!_font) @@ -202,7 +203,7 @@ int16 Text::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId curCharCount++; case 0: SetFont(oldFontId); - _gfx->PenColor(oldPenColor); + _ports->penColor(oldPenColor); return curCharCount; case ' ': @@ -213,14 +214,14 @@ int16 Text::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId curCharCount++; } SetFont(oldFontId); - _gfx->PenColor(oldPenColor); + _ports->penColor(oldPenColor); return maxChars; } void Text::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { unsigned char curChar; GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _gfx->_curPort->penClr; + int16 oldPenColor = _ports->_curPort->penClr; textWidth = 0; textHeight = 0; @@ -232,7 +233,7 @@ void Text::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontI switch (curChar) { case 0x0A: case 0x0D: - textHeight = MAX<int16> (textHeight, _gfx->_curPort->fontHeight); + textHeight = MAX<int16> (textHeight, _ports->_curPort->fontHeight); break; case 0x7C: if (getSciVersion() >= SCI_VERSION_1_1) { @@ -240,13 +241,13 @@ void Text::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontI break; } default: - textHeight = MAX<int16> (textHeight, _gfx->_curPort->fontHeight); + textHeight = MAX<int16> (textHeight, _ports->_curPort->fontHeight); textWidth += _font->getCharWidth(curChar); } } } SetFont(oldFontId); - _gfx->PenColor(oldPenColor); + _ports->penColor(oldPenColor); return; } @@ -263,7 +264,7 @@ void Text::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColo int16 Text::Size(Common::Rect &rect, const char *str, GuiResourceId fontId, int16 maxWidth) { GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _gfx->_curPort->penClr; + int16 oldPenColor = _ports->_curPort->penClr; int16 charCount; int16 maxTextWidth = 0, textWidth; int16 totalHeight = 0, textHeight; @@ -298,7 +299,7 @@ int16 Text::Size(Common::Rect &rect, const char *str, GuiResourceId fontId, int1 rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth); } SetFont(oldFontId); - _gfx->PenColor(oldPenColor); + _ports->penColor(oldPenColor); return rect.right; } @@ -311,8 +312,8 @@ void Text::Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId if (!_font) return; - rect.top = _gfx->_curPort->curTop; - rect.bottom = rect.top + _gfx->_curPort->fontHeight; + rect.top = _ports->_curPort->curTop; + rect.bottom = rect.top + _ports->_curPort->fontHeight; text += from; while (len--) { curChar = (*text++); @@ -329,14 +330,14 @@ void Text::Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId default: charWidth = _font->getCharWidth(curChar); // clear char - if (_gfx->_curPort->penMode == 1) { - rect.left = _gfx->_curPort->curLeft; + if (_ports->_curPort->penMode == 1) { + rect.left = _ports->_curPort->curLeft; rect.right = rect.left + charWidth; - _gfx->EraseRect(rect); + _paint16->eraseRect(rect); } // CharStd - _font->draw(_screen, curChar, _gfx->_curPort->top + _gfx->_curPort->curTop, _gfx->_curPort->left + _gfx->_curPort->curLeft, _gfx->_curPort->penClr, _gfx->_curPort->greyedOutput); - _gfx->_curPort->curLeft += charWidth; + _font->draw(_screen, curChar, _ports->_curPort->top + _ports->_curPort->curTop, _ports->_curPort->left + _ports->_curPort->curLeft, _ports->_curPort->penClr, _ports->_curPort->greyedOutput); + _ports->_curPort->curLeft += charWidth; } } } @@ -345,12 +346,12 @@ void Text::Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId void Text::Show(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { Common::Rect rect; - rect.top = _gfx->_curPort->curTop; - rect.bottom = rect.top + _gfx->GetPointSize(); - rect.left = _gfx->_curPort->curLeft; + rect.top = _ports->_curPort->curTop; + rect.bottom = rect.top + _ports->getPointSize(); + rect.left = _ports->_curPort->curLeft; Draw(text, from, len, orgFontId, orgPenColor); - rect.right = _gfx->_curPort->curLeft; - _gfx->BitsShow(rect); + rect.right = _ports->_curPort->curLeft; + _paint16->bitsShow(rect); } // Draws a text in rect. @@ -359,7 +360,7 @@ void Text::Box(const char *text, int16 bshow, const Common::Rect &rect, TextAlig int16 offset = 0; int16 hline = 0; GuiResourceId orgFontId = GetFontId(); - int16 orgPenColor = _gfx->_curPort->penClr; + int16 orgPenColor = _ports->_curPort->penClr; if (fontId != -1) SetFont(fontId); @@ -387,7 +388,7 @@ void Text::Box(const char *text, int16 bshow, const Common::Rect &rect, TextAlig default: // left-aligned warning("Invalid alignment %d used in TextBox()", alignment); } - _gfx->MoveTo(rect.left + offset, rect.top + hline); + _ports->moveTo(rect.left + offset, rect.top + hline); if (bshow) { Show(text, 0, charCount, orgFontId, orgPenColor); @@ -399,16 +400,16 @@ void Text::Box(const char *text, int16 bshow, const Common::Rect &rect, TextAlig text += charCount; } SetFont(orgFontId); - _gfx->PenColor(orgPenColor); + _ports->penColor(orgPenColor); } void Text::Draw_String(const char *text) { GuiResourceId orgFontId = GetFontId(); - int16 orgPenColor = _gfx->_curPort->penClr; + int16 orgPenColor = _ports->_curPort->penClr; Draw(text, 0, strlen(text), orgFontId, orgPenColor); SetFont(orgFontId); - _gfx->PenColor(orgPenColor); + _ports->penColor(orgPenColor); } } // End of namespace Sci diff --git a/engines/sci/graphics/text.h b/engines/sci/graphics/text.h index 56f789598c..1e94398558 100644 --- a/engines/sci/graphics/text.h +++ b/engines/sci/graphics/text.h @@ -32,12 +32,13 @@ namespace Sci { #define SCI_TEXT_ALIGNMENT_CENTER 1 #define SCI_TEXT_ALIGNMENT_LEFT 0 -class Gfx; +class GfxPorts; +class GfxPaint16; class Screen; class Font; class Text { public: - Text(ResourceManager *_resMan, Gfx *gfx, Screen *screen); + Text(ResourceManager *_resMan, GfxPorts *ports, GfxPaint16 *paint16, Screen *screen); ~Text(); GuiResourceId GetFontId(); @@ -69,7 +70,8 @@ private: void init(); ResourceManager *_resMan; - Gfx *_gfx; + GfxPorts *_ports; + GfxPaint16 *_paint16; Screen *_screen; int _codeFontsCount; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 29a65aca88..1fff191441 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -25,7 +25,6 @@ #include "sci/sci.h" #include "sci/engine/state.h" -#include "sci/graphics/gfx.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/view.h" diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index 03331bc5a4..ec8f9ef7eb 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -48,6 +48,9 @@ struct LoopInfo { #define SCI_VIEW_EGAMAPPING_SIZE 16 #define SCI_VIEW_EGAMAPPING_COUNT 8 +class Screen; +class SciPalette; + class View { public: View(ResourceManager *resMan, Screen *screen, SciPalette *palette, GuiResourceId resourceId); diff --git a/engines/sci/graphics/windowmgr.cpp b/engines/sci/graphics/windowmgr.cpp deleted file mode 100644 index faa598326c..0000000000 --- a/engines/sci/graphics/windowmgr.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/util.h" - -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/gfx.h" -#include "sci/graphics/animate.h" -#include "sci/graphics/text.h" -#include "sci/graphics/windowmgr.h" - -namespace Sci { - -// window styles -enum { - SCI_WINDOWMGR_STYLE_TRANSPARENT = (1 << 0), - SCI_WINDOWMGR_STYLE_NOFRAME = (1 << 1), - SCI_WINDOWMGR_STYLE_TITLE = (1 << 2), - SCI_WINDOWMGR_STYLE_TOPMOST = (1 << 3), - SCI_WINDOWMGR_STYLE_USER = (1 << 7) -}; - -WindowMgr::WindowMgr(SciGui *gui, Screen *screen, Gfx *gfx, Text *text) - : _gui(gui), _screen(screen), _gfx(gfx), _text(text) { -} - -WindowMgr::~WindowMgr() { - // TODO: Clear _windowList and delete all stuff in it? -} - -void WindowMgr::init(Common::String gameId) { - int16 offTop = 10; - - _wmgrPort = new Port(1); - _windowsById.resize(2); - _windowsById[0] = _wmgrPort; // wmgrPort is supposed to be accessible via id 0 - _windowsById[1] = _wmgrPort; // but wmgrPort may not actually have id 0, so we assign id 1 (as well) - // Background: sierra sci replies with the offset of curPort on kGetPort calls. If we reply with 0 there most games - // will work, but some scripts seem to check for 0 and initialize the variable again in that case - // resulting in problems. - - // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. - // This actually meant not skipping the first 10 pixellines in windowMgrPort - if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3") - offTop = 0; - - _gfx->OpenPort(_wmgrPort); - _gfx->SetPort(_wmgrPort); - _gfx->SetOrigin(0, offTop); - _wmgrPort->rect.bottom = _screen->getHeight() - offTop; - _wmgrPort->rect.right = _screen->getWidth(); - _wmgrPort->rect.moveTo(0, 0); - _wmgrPort->curTop = 0; - _wmgrPort->curLeft = 0; - _windowList.push_front(_wmgrPort); - - _picWind = NewWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); -} - -int16 WindowMgr::isFrontWindow(Window *pWnd) { - return _windowList.back() == pWnd; -} - -void WindowMgr::BeginUpdate(Window *wnd) { - Port *oldPort = _gfx->SetPort(_wmgrPort); - PortList::iterator it = _windowList.reverse_begin(); - const PortList::iterator end = Common::find(_windowList.begin(), _windowList.end(), wnd); - while (it != end) { - // FIXME: We also store Port objects in the window list. - // We should add a check that we really only pass windows here... - UpdateWindow((Window *)*it); - --it; - } - _gfx->SetPort(oldPort); -} - -void WindowMgr::EndUpdate(Window *wnd) { - Port *oldPort = _gfx->SetPort(_wmgrPort); - const PortList::iterator end = _windowList.end(); - PortList::iterator it = Common::find(_windowList.begin(), end, wnd); - - // wnd has to be in _windowList - assert(it != end); - - while (++it != end) { - // FIXME: We also store Port objects in the window list. - // We should add a check that we really only pass windows here... - UpdateWindow((Window *)*it); - } - - _gfx->SetPort(oldPort); -} - -Window *WindowMgr::NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) { - // Find an unused window/port id - uint id = 1; - while (id < _windowsById.size() && _windowsById[id]) { - ++id; - } - if (id == _windowsById.size()) - _windowsById.push_back(0); - assert(0 < id && id < 0xFFFF); - - Window *pwnd = new Window(id); - Common::Rect r; - - if (!pwnd) { - warning("Can't open window!"); - return 0; - } - - _windowsById[id] = pwnd; - if (style & SCI_WINDOWMGR_STYLE_TOPMOST) - _windowList.push_front(pwnd); - else - _windowList.push_back(pwnd); - _gfx->OpenPort(pwnd); - r = dims; - pwnd->rect = dims; - if (restoreRect) - pwnd->restoreRect = *restoreRect; - - pwnd->wndStyle = style; - pwnd->hSaved1 = pwnd->hSaved2 = NULL_REG; - pwnd->bDrawn = false; - if ((style & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) - pwnd->saveScreenMask = (priority == -1 ? SCI_SCREEN_MASK_VISUAL : SCI_SCREEN_MASK_VISUAL | SCI_SCREEN_MASK_PRIORITY); - - if (title && (style & SCI_WINDOWMGR_STYLE_TITLE)) { - pwnd->title = title; - } - - r = dims; - if ((style != SCI_WINDOWMGR_STYLE_USER) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME)) { - r.grow(1); - if (style & SCI_WINDOWMGR_STYLE_TITLE) { - r.top -= 10; - r.bottom++; - } - } - - // FIXME: it seems as if shadows may result in the window getting moved one upwards - // so that the shadow is visible (lsl5) - - pwnd->dims = r; - const Common::Rect *wmprect = &_wmgrPort->rect; - int16 oldtop = pwnd->dims.top; - int16 oldleft = pwnd->dims.left; - if (wmprect->top > pwnd->dims.top) - pwnd->dims.moveTo(pwnd->dims.left, wmprect->top); - - if (wmprect->bottom < pwnd->dims.bottom) - pwnd->dims.moveTo(pwnd->dims.left, wmprect->bottom - pwnd->dims.bottom + pwnd->dims.top); - - if (wmprect->right < pwnd->dims.right) - pwnd->dims.moveTo(wmprect->right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top); - - if (wmprect->left > pwnd->dims.left) - pwnd->dims.moveTo(wmprect->left, pwnd->dims.top); - - pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop); - if (restoreRect == 0) - pwnd->restoreRect = pwnd->dims; - - if (!(pwnd->wndStyle & (SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_NOFRAME))) { - // The shadow is drawn slightly outside the window. - // Enlarge restoreRect to cover that. - pwnd->restoreRect.bottom++; - pwnd->restoreRect.right++; - } - - if (draw) - DrawWindow(pwnd); - _gfx->SetPort((Port *)pwnd); - _gfx->SetOrigin(pwnd->rect.left, pwnd->rect.top + _wmgrPort->top); - pwnd->rect.moveTo(0, 0); - return pwnd; -} - -void WindowMgr::DrawWindow(Window *pWnd) { - if (pWnd->bDrawn) - return; - Common::Rect r; - int16 wndStyle = pWnd->wndStyle; - - pWnd->bDrawn = true; - Port *oldport = _gfx->SetPort(_wmgrPort); - _gfx->PenColor(0); - if ((wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) { - pWnd->hSaved1 = _gfx->BitsSave(pWnd->restoreRect, SCI_SCREEN_MASK_VISUAL); - if (pWnd->saveScreenMask & SCI_SCREEN_MASK_PRIORITY) { - pWnd->hSaved2 = _gfx->BitsSave(pWnd->restoreRect, SCI_SCREEN_MASK_PRIORITY); - if ((wndStyle & SCI_WINDOWMGR_STYLE_USER) == 0) - _gfx->FillRect(pWnd->restoreRect, SCI_SCREEN_MASK_PRIORITY, 0, 15); - } - } - - // drawing frame,shadow and title - if (!(wndStyle & SCI_WINDOWMGR_STYLE_USER)) { - r = pWnd->dims; - if (!(wndStyle & SCI_WINDOWMGR_STYLE_NOFRAME)) { - r.translate(1, 1); - _gfx->FrameRect(r);// shadow - r.translate(-1, -1); - _gfx->FrameRect(r);// window frame - - if (wndStyle & SCI_WINDOWMGR_STYLE_TITLE) { - _gfx->FrameRect(r); - r.grow(-1); - if (getSciVersion() <= SCI_VERSION_0_LATE) - _gfx->FillRect(r, SCI_SCREEN_MASK_VISUAL, 8); // grey titlebar for SCI0 - else - _gfx->FillRect(r, SCI_SCREEN_MASK_VISUAL, 0); // black titlebar for SCI01+ - if (!pWnd->title.empty()) { - int16 oldcolor = _gfx->GetPort()->penClr; - _gfx->PenColor(255); - _text->Box(pWnd->title.c_str(), 1, r, SCI_TEXT_ALIGNMENT_CENTER, 0); - _gfx->PenColor(oldcolor); - } - - r = pWnd->dims; - r.top += 9; - } - - r.grow(-1); - } - - if (!(wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT)) - _gfx->FillRect(r, SCI_SCREEN_MASK_VISUAL, pWnd->backClr); - - _gfx->BitsShow(pWnd->restoreRect); - } - _gfx->SetPort(oldport); -} - -void WindowMgr::DisposeWindow(Window *pWnd, bool reanimate) { - _gfx->SetPort(_wmgrPort); - _gfx->BitsRestore(pWnd->hSaved1); - _gfx->BitsRestore(pWnd->hSaved2); - if (!reanimate) - _gfx->BitsShow(pWnd->restoreRect); - else - _gui->graphRedrawBox(pWnd->restoreRect); - _windowList.remove(pWnd); - _gfx->SetPort(_windowList.back()); - _windowsById[pWnd->id] = 0; - delete pWnd; -} - -void WindowMgr::UpdateWindow(Window *wnd) { - reg_t handle; - - if (wnd->saveScreenMask && wnd->bDrawn) { - handle = _gfx->BitsSave(wnd->restoreRect, SCI_SCREEN_MASK_VISUAL); - _gfx->BitsRestore(wnd->hSaved1); - wnd->hSaved1 = handle; - if (wnd->saveScreenMask & SCI_SCREEN_MASK_PRIORITY) { - handle = _gfx->BitsSave(wnd->restoreRect, SCI_SCREEN_MASK_PRIORITY); - _gfx->BitsRestore(wnd->hSaved2); - wnd->hSaved2 = handle; - } - } -} - -Port *WindowMgr::getPortById(uint16 id) { - if (id > _windowsById.size()) - error("getPortById() received invalid id"); - return _windowsById[id]; -} - -} // End of namespace Sci diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 1383fb7bda..81fc492ac5 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -40,6 +40,7 @@ #include "sci/sound/audio.h" #include "sci/sound/soundcmd.h" #include "sci/graphics/gui.h" +#include "sci/graphics/ports.h" #include "sci/graphics/palette.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" @@ -170,13 +171,16 @@ Common::Error SciEngine::run() { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { + _gamestate->_gfxPorts = 0; _gamestate->_gui = 0; _gamestate->_gui32 = new SciGui32(_gamestate, screen, palette, cursor); } else { - _gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor, _audio); + _gamestate->_gfxPorts = new GfxPorts(segMan, screen); + _gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor, _gamestate->_gfxPorts, _audio); _gamestate->_gui32 = 0; } #else + _gamestate->_ports = new GfxPorts(_segMan, _screen); _gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor, _audio); #endif |