aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics
diff options
context:
space:
mode:
authorMartin Kiewitz2010-01-31 12:35:15 +0000
committerMartin Kiewitz2010-01-31 12:35:15 +0000
commit7929255cd9723ebba451d5b9dd4d4597ed32e6a7 (patch)
tree8cd2c05a2e023aa0d8e56eec338c06690888cddc /engines/sci/graphics
parent5278b82f33dd1083b99470bb8dcf941debb6b446 (diff)
downloadscummvm-rg350-7929255cd9723ebba451d5b9dd4d4597ed32e6a7.tar.gz
scummvm-rg350-7929255cd9723ebba451d5b9dd4d4597ed32e6a7.tar.bz2
scummvm-rg350-7929255cd9723ebba451d5b9dd4d4597ed32e6a7.zip
SCI: cleaned up graphics classes, removed gfx&windowmgr, added gfxports, gfxcompare, gfxpaint16, gfxcache. kernel uses gfxports directly w/o going through SciGui
svn-id: r47745
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r--engines/sci/graphics/animate.cpp66
-rw-r--r--engines/sci/graphics/animate.h10
-rw-r--r--engines/sci/graphics/cache.cpp66
-rw-r--r--engines/sci/graphics/cache.h (renamed from engines/sci/graphics/windowmgr.h)46
-rw-r--r--engines/sci/graphics/compare.cpp131
-rw-r--r--engines/sci/graphics/compare.h55
-rw-r--r--engines/sci/graphics/controls.cpp41
-rw-r--r--engines/sci/graphics/controls.h8
-rw-r--r--engines/sci/graphics/gfx.cpp613
-rw-r--r--engines/sci/graphics/gui.cpp317
-rw-r--r--engines/sci/graphics/gui.h25
-rw-r--r--engines/sci/graphics/gui32.cpp31
-rw-r--r--engines/sci/graphics/gui32.h7
-rw-r--r--engines/sci/graphics/menu.cpp99
-rw-r--r--engines/sci/graphics/menu.h5
-rw-r--r--engines/sci/graphics/paint16.cpp333
-rw-r--r--engines/sci/graphics/paint16.h (renamed from engines/sci/graphics/gfx.h)95
-rw-r--r--engines/sci/graphics/picture.cpp36
-rw-r--r--engines/sci/graphics/picture.h8
-rw-r--r--engines/sci/graphics/ports.cpp530
-rw-r--r--engines/sci/graphics/ports.h122
-rw-r--r--engines/sci/graphics/robot.cpp1
-rw-r--r--engines/sci/graphics/text.cpp85
-rw-r--r--engines/sci/graphics/text.h8
-rw-r--r--engines/sci/graphics/view.cpp1
-rw-r--r--engines/sci/graphics/view.h3
-rw-r--r--engines/sci/graphics/windowmgr.cpp295
27 files changed, 1641 insertions, 1396 deletions
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