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