diff options
| -rw-r--r-- | engines/tony/gfxcore.cpp | 79 | ||||
| -rw-r--r-- | engines/tony/gfxcore.h | 22 | ||||
| -rw-r--r-- | engines/tony/gfxengine.cpp | 4 | ||||
| -rw-r--r-- | engines/tony/gfxengine.h | 4 | ||||
| -rw-r--r-- | engines/tony/loc.cpp | 34 | ||||
| -rw-r--r-- | engines/tony/loc.h | 3 | ||||
| -rw-r--r-- | engines/tony/tony.cpp | 3 | ||||
| -rw-r--r-- | engines/tony/utils.cpp | 4 | ||||
| -rw-r--r-- | engines/tony/utils.h | 1 | ||||
| -rw-r--r-- | engines/tony/window.cpp | 35 | ||||
| -rw-r--r-- | engines/tony/window.h | 3 | 
11 files changed, 167 insertions, 25 deletions
| diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp index e168d2b7c9..d34923e455 100644 --- a/engines/tony/gfxcore.cpp +++ b/engines/tony/gfxcore.cpp @@ -256,6 +256,7 @@ RMGfxClearTask RMGfxTargetBuffer::taskClear;  RMGfxTargetBuffer::RMGfxTargetBuffer() {  	_otlist = NULL;  	_otSize = 0; +	_trackDirtyRects = false;  //	csModifyingOT = g_system->createMutex();  } @@ -380,6 +381,66 @@ void RMGfxTargetBuffer::addClearTask(void) {  	addPrim(new RMGfxPrimitive(&taskClear));  } +void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) { +	assert(r.isValidRect()); +	if (_trackDirtyRects && r.width() > 0 && r.height() > 0) +		_currentDirtyRects.push_back(r);	 +} + +Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() { +	// Copy rects from both the current and previous frame into the output dirty rects list +	Common::List<Common::Rect>::iterator i; +	_dirtyRects.clear(); +	for (i = _previousDirtyRects.begin(); i != _previousDirtyRects.end(); ++i) +		_dirtyRects.push_back(*i); +	for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i) +		_dirtyRects.push_back(*i); + +	mergeDirtyRects(); +	return _dirtyRects; +} + +/** + * Move the set of dirty rects from the finished current frame into the previous frame list. + */ +void RMGfxTargetBuffer::clearDirtyRects() { +	Common::List<Common::Rect>::iterator i; +	_previousDirtyRects.clear(); +	for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i) +		_previousDirtyRects.push_back(*i); + +	_currentDirtyRects.clear(); +} + +/** + * Merges any clipping rectangles that overlap to try and reduce + * the total number of clip rectangles. + */ +void RMGfxTargetBuffer::mergeDirtyRects() { +	if (_dirtyRects.size() <= 1) +		return; + +	Common::List<Common::Rect>::iterator rOuter, rInner; + +	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) { +		rInner = rOuter; +		while (++rInner != _dirtyRects.end()) { + +			if ((*rOuter).intersects(*rInner)) { +				// these two rectangles overlap or +				// are next to each other - merge them + +				(*rOuter).extend(*rInner); + +				// remove the inner rect from the list +				_dirtyRects.erase(rInner); + +				// move back to beginning of list +				rInner = rOuter; +			} +		} +	} +}  /****************************************************************************\  *               RMGfxSourceBufferPal Methods @@ -550,6 +611,9 @@ void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimit  			buf += bufx - width;  		}  	} + +	// Specify the drawn area +	bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));  }  RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy, bool bUseDDraw) @@ -660,7 +724,8 @@ void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrim  		}  	} -	return; +	// Specify the drawn area +	bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));  } @@ -857,6 +922,9 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri  			buf += bigBuf.getDimx();  		}  	} + +	// Specify the drawn area +	bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));  } @@ -1709,6 +1777,9 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri  		// Skip to the next line  		buf += bigBuf.getDimx();  	} + +	// Specify the drawn area +	bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));  } @@ -1871,6 +1942,9 @@ void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimi  			raw += _dimx;  		}  	} + +	// Specify the drawn area +	bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + dimx, y1 + dimy));  }  void RMGfxSourceBuffer16::prepareImage(void) { @@ -1922,6 +1996,9 @@ void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim)  	uint16 *buf = bigBuf;  	RMRect rcDst; +	// Specify the drawn area +	bigBuf.addDirtyRect(rcDst); +  	// It takes the destination rectangle  	rcDst = prim->getDst();  	buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1; diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h index 9a00ed1646..82862d6846 100644 --- a/engines/tony/gfxcore.h +++ b/engines/tony/gfxcore.h @@ -112,11 +112,13 @@ public:  		_task = NULL;  		_src.setEmpty();  		_dst.setEmpty(); +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task) {  		_task = task;  		_bFlag = 0; +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMRect &dst) { @@ -132,6 +134,7 @@ public:  		_src.topLeft() = src;  		_dst = dst;  		_bFlag = 0; +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMPoint &dst) { @@ -139,6 +142,7 @@ public:  		_src.topLeft() = src;  		_dst.topLeft() = dst;  		_bFlag = 0; +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMPoint &dst) { @@ -146,6 +150,7 @@ public:  		_src = src;  		_dst.topLeft() = dst;  		_bFlag = 0; +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task, const RMRect &dst) { @@ -153,6 +158,7 @@ public:  		_dst = dst;  		_src.setEmpty();  		_bFlag = 0; +		_bStretch = false;  	}  	RMGfxPrimitive(RMGfxTask *task, const RMPoint &dst) { @@ -160,6 +166,7 @@ public:  		_dst.topLeft() = dst;  		_src.setEmpty();  		_bFlag = 0; +		_bStretch = false;  	}  	virtual ~RMGfxPrimitive() { } @@ -553,6 +560,10 @@ private:  		}  	}; +	bool _trackDirtyRects; +	Common::List<Common::Rect> _currentDirtyRects, _previousDirtyRects, _dirtyRects; + +	void mergeDirtyRects();  private:  //	OSystem::MutexRef csModifyingOT; @@ -587,6 +598,17 @@ public:  	void offsetY(int nLines) {  		RMGfxBuffer::offsetY(nLines, 16);  	} + +	// Dirty rect methods +	void addDirtyRect(const Common::Rect &r); +	Common::List<Common::Rect> &getDirtyRects(); +	void clearDirtyRects(); +	void setTrackDirtyRects(bool v) { +		_trackDirtyRects = v; +	} +	bool getTrackDirtyRects() const { +		return _trackDirtyRects; +	}  }; diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp index deae0cb641..3ea83a8867 100644 --- a/engines/tony/gfxengine.cpp +++ b/engines/tony/gfxengine.cpp @@ -63,6 +63,7 @@ RMGfxEngine::RMGfxEngine() {  	// Create big buffer where the frame will be rendered  	_bigBuf.create(RM_BBX, RM_BBY, 16);  	_bigBuf.offsetY(RM_SKIPY); +	_bigBuf.setTrackDirtyRects(true);  	_csMainLoop = NULL;  	_nCurLoc = 0; @@ -475,8 +476,7 @@ void RMGfxEngine::init() {  	delete load;  	// Display 'Loading' screen -	// TODO: The loading screen isn't currently optimal, since the game doesn't respond to events -	// whilst the mpalInit code is being executed.  +	_bigBuf.addDirtyRect(Common::Rect(0, 0, RM_SX, RM_SY));  	_vm->_window.getNewFrame(*this, NULL);  	_vm->_window.repaint(); diff --git a/engines/tony/gfxengine.h b/engines/tony/gfxengine.h index 18c13d8d3d..1a37de98e1 100644 --- a/engines/tony/gfxengine.h +++ b/engines/tony/gfxengine.h @@ -109,8 +109,8 @@ public:  	void enableMouse(void);  	void disableMouse(void); -	operator byte *() { -		return (byte *)_bigBuf; +	operator RMGfxTargetBuffer &() { +		return _bigBuf;  	}  	RMInput &getInput() {  		return _input; diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp index b2bf3b3565..26a13037c0 100644 --- a/engines/tony/loc.cpp +++ b/engines/tony/loc.cpp @@ -710,14 +710,13 @@ void RMItem::setStatus(int nStatus) {  }  void RMItem::setPattern(int nPattern, bool bPlayP0) { -	int i; -  	assert(nPattern >= 0 && nPattern <= _nPatterns); -	if (_sfx) +	if (_sfx) {  		if (_nCurPattern > 0)  			_patterns[_nCurPattern].stopSfx(_sfx); - +	} +	  	// Remember the current pattern  	_nCurPattern = nPattern; @@ -728,10 +727,12 @@ void RMItem::setPattern(int nPattern, bool bPlayP0) {  		_nCurSprite = -1;  		// Look for the sound effect for pattern 0 -		if (bPlayP0) -			for (i = 0; i < _nSfx; i++) +		if (bPlayP0) { +			for (int i = 0; i < _nSfx; i++) {  				if (strcmp(_sfx[i]._name, "p0") == 0)  					_sfx[i].play(); +			} +		}  	}  } @@ -783,6 +784,8 @@ RMItem::RMItem() {  	_bPal = 0;  	_nCurSprite = 0; +	_bIsActive = false; +  	_hEndPattern = CoroScheduler.createEvent(false, false);  } @@ -1933,6 +1936,8 @@ RMLocation::RMLocation() {  	_nItems = 0;  	_items = NULL;  	_buf = NULL; +	_prevScroll.set(-1, -1); +	_prevFixedScroll.set(-1, -1);  } @@ -1967,11 +1972,8 @@ bool RMLocation::load(const char *lpszFileName) {   * @returns     True if succeeded OK, false in case of error.   */  bool RMLocation::load(Common::File &file) { -	int size;  	bool bRet; -	// Get the file size -	size = file.size();  	file.seek(0);  	RMFileStreamSlow fs; @@ -2126,6 +2128,8 @@ bool RMLocation::loadLOX(RMDataStream &ds) {   */  void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {  	CORO_BEGIN_CONTEXT; +		bool priorTracking; +		bool hasChanges;  	CORO_END_CONTEXT(_ctx);  	CORO_BEGIN_CODE(_ctx); @@ -2137,9 +2141,21 @@ void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri  	prim->setDst(_fixedScroll); +	// Check whether dirty rects are being tracked, and if there are changes, leave tracking +	// turned on so a dirty rect will be added for the entire background +	_ctx->priorTracking = bigBuf.getTrackDirtyRects(); +	_ctx->hasChanges = (_prevScroll != _curScroll) || (_prevFixedScroll != _fixedScroll); +	bigBuf.setTrackDirtyRects(_ctx->priorTracking && _ctx->hasChanges); +  	// Invoke the drawing method fo the image class, which will draw the location background  	CORO_INVOKE_2(_buf->draw, bigBuf, prim); +	if (_ctx->hasChanges) { +		_prevScroll = _curScroll; +		_prevFixedScroll = _fixedScroll; +	} +	bigBuf.setTrackDirtyRects(_ctx->priorTracking); +  	CORO_END_CODE;  } diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 4231c99eab..944e206ae2 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -539,6 +539,9 @@ private:  	RMPoint _curScroll;            // Current scroll position  	RMPoint _fixedScroll; +	RMPoint _prevScroll;			// Previous scroll position +	RMPoint _prevFixedScroll; +  public:  	// @@@@@@@@@@@@@@@@@@@@@@@  	RMPoint TEMPTonyStart; diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index b1e45c8bfa..28726f0a33 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -623,8 +623,9 @@ Common::Error TonyEngine::saveGameState(int slot, const Common::String &desc) {  	if (!GLOBALS._gfxEngine)  		return Common::kUnknownError; +	RMGfxTargetBuffer &bigBuf = *GLOBALS._gfxEngine;  	RMSnapshot s; -	s.grabScreenshot(*GLOBALS._gfxEngine, 4, _curThumbnail); +	s.grabScreenshot(bigBuf, 4, _curThumbnail);  	GLOBALS._gfxEngine->saveState(getSaveStateFileName(slot), (byte *)_curThumbnail, desc);  	return Common::kNoError; diff --git a/engines/tony/utils.cpp b/engines/tony/utils.cpp index 8e751a811a..f9c2622eb2 100644 --- a/engines/tony/utils.cpp +++ b/engines/tony/utils.cpp @@ -922,6 +922,10 @@ int RMRect::size() const {  	return width() * height();  } +RMRect::operator Common::Rect() const { +	return Common::Rect(_x1, _y1, _x2, _y2); +} +  bool RMRect::isEmpty() const {  	return (_x1 == 0 && _y1 == 0 && _x2 == 0 && _y2 == 0);  } diff --git a/engines/tony/utils.h b/engines/tony/utils.h index 33e2db7d7e..82c5bb020c 100644 --- a/engines/tony/utils.h +++ b/engines/tony/utils.h @@ -268,6 +268,7 @@ public:  	int height() const;  	bool isEmpty() const;  	int size() const; +	operator Common::Rect() const;  	// Set  	void setRect(int x1, int y1, int x2, int y2); diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp index db21be0ded..bf0094ff2a 100644 --- a/engines/tony/window.cpp +++ b/engines/tony/window.cpp @@ -40,7 +40,6 @@ namespace Tony {  \****************************************************************************/  RMWindow::RMWindow() { -  }  RMWindow::~RMWindow() { @@ -61,6 +60,7 @@ void RMWindow::init() {  	_bGrabScreenshot = false;  	_bGrabThumbnail = false;  	_bGrabMovie = false; +	_wiping = false;  }  /** @@ -108,13 +108,29 @@ void RMWindow::wipeEffect(Common::Rect &rcBoundEllipse) {  	}  } -void RMWindow::getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse) { +void RMWindow::getNewFrame(RMGfxTargetBuffer &bigBuf, Common::Rect *rcBoundEllipse) { +	// Get a pointer to the bytes of the source buffer +	byte *lpBuf = bigBuf; +  	if (rcBoundEllipse != NULL) {  		// Circular wipe effect  		getNewFrameWipe(lpBuf, *rcBoundEllipse); -	} else { -		// Standard screen copy +		_wiping = true; +	} else if (_wiping) { +		// Just finished a wiping effect, so copy the full screen  		g_system->copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY); +		_wiping = false; + +	} else { +		// Standard screen copy - iterate through the dirty rects +		Common::List<Common::Rect> dirtyRects = bigBuf.getDirtyRects(); +		Common::List<Common::Rect>::iterator i; + +		for (i = dirtyRects.begin(); i != dirtyRects.end(); ++i) { +			Common::Rect &r = *i; +			const byte *lpSrc = lpBuf + (RM_SX * 2) * r.top + (r.left * 2); +			g_system->copyRectToScreen(lpSrc, RM_SX * 2, r.left, r.top, r.width(), r.height()); +		}  	}  	if (_bGrabThumbnail) { @@ -124,6 +140,9 @@ void RMWindow::getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse) {  		s.grabScreenshot(lpBuf, 4, _wThumbBuf);  		_bGrabThumbnail = false;  	} + +	// Clear the dirty rect list +	bigBuf.clearDirtyRects();  }  /** @@ -214,10 +233,7 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) {  	int dimx = RM_SX / dezoom;  	int dimy = RM_SY / dezoom; -	int u, v, curv; -  	uint32 k = 0; -	int sommar, sommab, sommag;  	uint16 *cursrc;  	if (lpDestBuf == NULL) @@ -247,10 +263,11 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) {  		for (int y = 0; y < dimy; y++) {  			for (int x = 0; x < dimx; x++) {  				cursrc = &src[RM_SKIPX + x * dezoom]; +				int sommar, sommab, sommag, curv;  				sommar = sommab = sommag = 0; -				for (v = 0; v < dezoom; v++) { -					for (u = 0; u < dezoom; u++) { +				for (int v = 0; v < dezoom; v++) { +					for (int u = 0; u < dezoom; u++) {  						if (lpDestBuf == NULL)  							curv = -v;  						else diff --git a/engines/tony/window.h b/engines/tony/window.h index 34f0c1cb51..6189dd391f 100644 --- a/engines/tony/window.h +++ b/engines/tony/window.h @@ -64,6 +64,7 @@ protected:  	int lastsecond, lastfcount;  	int mskRed, mskGreen, mskBlue; +	bool _wiping;  	bool _bGrabScreenshot;  	bool _bGrabThumbnail; @@ -90,7 +91,7 @@ public:  	void switchFullscreen(bool bFull) {}  	// Reads the next frame -	void getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse); +	void getNewFrame(RMGfxTargetBuffer &lpBuf, Common::Rect *rcBoundEllipse);  	// Request a thumbnail be grabbed during the next frame  	void grabThumbnail(uint16 *buf); | 
