[Scummvm-cvs-logs] SF.net SVN: scummvm:[44373] scummvm/branches/branch-1-0-0/engines/cruise

dreammaster at users.sourceforge.net dreammaster at users.sourceforge.net
Sat Sep 26 06:38:25 CEST 2009


Revision: 44373
          http://scummvm.svn.sourceforge.net/scummvm/?rev=44373&view=rev
Author:   dreammaster
Date:     2009-09-26 04:38:25 +0000 (Sat, 26 Sep 2009)

Log Message:
-----------
Backport of dirty rect handling for Cruise engine

Modified Paths:
--------------
    scummvm/branches/branch-1-0-0/engines/cruise/background.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/background.h
    scummvm/branches/branch-1-0-0/engines/cruise/backgroundIncrust.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/cell.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/cruise.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/function.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.cpp
    scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.h
    scummvm/branches/branch-1-0-0/engines/cruise/mainDraw.cpp

Modified: scummvm/branches/branch-1-0-0/engines/cruise/background.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/background.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/background.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -30,6 +30,7 @@
 uint8 colorMode = 0;
 
 uint8 *backgroundScreens[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };	// wasn't initialized in original, but it's probably better
+bool backgroundChanged[8] = { false, false, false, false, false, false, false, false };
 backgroundTableStruct backgroundTable[8];
 
 char hwPage[64000];
@@ -101,6 +102,8 @@
 		return (-2);
 	}
 
+	backgroundChanged[idx] = true;
+
 	ptrToFree = gfxModuleData.pPage10;
 	if (loadFileSub1(&ptrToFree, name, NULL) < 0) {
 		if (ptrToFree != gfxModuleData.pPage10)

Modified: scummvm/branches/branch-1-0-0/engines/cruise/background.h
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/background.h	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/background.h	2009-09-26 04:38:25 UTC (rev 44373)
@@ -36,6 +36,7 @@
 extern short int cvtPalette[0x20];
 extern int CVTLoaded;
 extern uint8 *backgroundScreens[8];
+extern bool backgroundChanged[8];
 extern backgroundTableStruct backgroundTable[8];
 
 int loadBackground(const char *name, int idx);

Modified: scummvm/branches/branch-1-0-0/engines/cruise/backgroundIncrust.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/backgroundIncrust.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/backgroundIncrust.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -71,6 +71,8 @@
 	if (pBackground == NULL)
 		return;
 
+	backgroundChanged[pIncrust->backgroundIdx] = true;
+
 	int X = pIncrust->savedX;
 	int Y = pIncrust->savedY;
 	int width = pIncrust->saveWidth;
@@ -108,6 +110,8 @@
 
 	backgroundPtr = backgroundScreens[backgroundIdx];
 
+	backgroundChanged[backgroundIdx] = true;
+
 	assert(backgroundPtr != NULL);
 
 	currentHead = pHead;
@@ -218,6 +222,8 @@
 				// Poly
 				addBackgroundIncrustSub1(frame, pl->X, pl->Y, NULL, pl->scale, (char*)backgroundScreens[pl->backgroundIdx], (char *)filesDatabase[frame].subData.ptr);
 			}
+
+			backgroundChanged[pl->backgroundIdx] = true;
 		}
 
 		pl = pl2;

Modified: scummvm/branches/branch-1-0-0/engines/cruise/cell.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/cell.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/cell.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -176,6 +176,11 @@
 	if (ax) {
 		pNewElement->gfxPtr = renderText(width, ax);
 	}
+
+	// WORKAROUND: This is needed for the new dirty rect handling so as to properly refresh the screen
+	// when the copy protection screen is being shown
+	if ((messageIdx == 0) && !strcmp(overlayTable[overlayIdx].overlayName, "XX2"))
+		backgroundChanged[0] = true;
 }
 
 void removeCell(cellStruct *objPtr, int ovlNumber, int objectIdx, int objType, int backgroundPlane) {

Modified: scummvm/branches/branch-1-0-0/engines/cruise/cruise.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/cruise.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/cruise.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -200,6 +200,8 @@
 		flipScreen();
 		changeCursor(_savedCursor);
 	}
+
+	gfxModuleData_addDirtyRect(Common::Rect(64, 100, 256, 117));
 }
 
 Common::Error CruiseEngine::loadGameState(int slot) {

Modified: scummvm/branches/branch-1-0-0/engines/cruise/function.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/function.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/function.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -510,6 +510,8 @@
 		gfxModuleData_gfxWaitVSync();
 
 		result = loadBackground(bgName, bgIdx);
+
+		gfxModuleData_addDirtyRect(Common::Rect(0, 0, 320, 200));
 	}
 
 	changeCursor(CURSOR_NORMAL);
@@ -788,6 +790,7 @@
 
 	if ((bgIdx >= 0) && (bgIdx < NBSCREENS) && (backgroundScreens[bgIdx])) {
 		memset(backgroundScreens[bgIdx], 0, 320 * 200);
+		backgroundChanged[bgIdx] = true;
 		strcpy(backgroundTable[0].name, "");
 	}
 
@@ -922,6 +925,7 @@
 	if (newPlane >= 0 && newPlane < NBSCREENS) {
 		if (backgroundScreens[newPlane]) {
 			masterScreen = newPlane;
+			backgroundChanged[newPlane] = true;
 			switchPal = 1;
 		}
 	}
@@ -936,8 +940,10 @@
 		if (backgroundScreens[backgroundIdx])
 			free(backgroundScreens[backgroundIdx]);
 
-		if (masterScreen == backgroundIdx)
+		if (masterScreen == backgroundIdx) {
 			masterScreen = 0;
+			backgroundChanged[0] = true;
+		}
 
 		strcpy(backgroundTable[backgroundIdx].name, "");
 	} else {

Modified: scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -41,6 +41,10 @@
 int palDirtyMin = 256;
 int palDirtyMax = -1;
 
+typedef Common::List<Common::Rect> RectList;
+RectList _dirtyRects;
+RectList _priorFrameRects;
+
 gfxModuleDataStruct gfxModuleData = {
 	0,			// use Tandy
 	0,			// use EGA
@@ -229,7 +233,47 @@
 	flip();
 }
 
+void gfxModuleData_addDirtyRect(const Common::Rect &r) {
+	_dirtyRects.push_back(Common::Rect(	MAX(r.left, (int16)0), MAX(r.top, (int16)0), 
+		MIN(r.right, (int16)320), MIN(r.bottom, (int16)200)));
+}
+
+/**
+ * Creates the union of two rectangles.
+ */
+static bool unionRectangle(Common::Rect &pDest, const Common::Rect &pSrc1, const Common::Rect &pSrc2) {
+	pDest.left   = MIN(pSrc1.left, pSrc2.left);
+	pDest.top    = MIN(pSrc1.top, pSrc2.top);
+	pDest.right  = MAX(pSrc1.right, pSrc2.right);
+	pDest.bottom = MAX(pSrc1.bottom, pSrc2.bottom);
+
+	return !pDest.isEmpty();
+}
+
+static void mergeClipRects() {
+	RectList::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, so translate it to a bigger rectangle
+				// that contains both of them
+				unionRectangle(*rOuter, *rOuter, *rInner);
+
+				// remove the inner rect from the list
+				_dirtyRects.erase(rInner);
+
+				// move back to beginning of list
+				rInner = rOuter;
+			}
+		}
+	}
+}
+
 void flip() {
+	RectList::iterator dr;
 	int i;
 	byte paletteRGBA[256 * 4];
 
@@ -245,7 +289,29 @@
 		palDirtyMax = -1;
 	}
 
-	g_system->copyRectToScreen(globalScreen, 320, 0, 0, 320, 200);
+	// Make a copy of the prior frame's dirty rects, and then backup the current frame's rects
+	RectList tempList = _priorFrameRects;
+	_priorFrameRects = _dirtyRects;
+
+	// Merge the prior frame's dirty rects into the current frame's list
+	for (dr = tempList.begin(); dr != tempList.end(); ++dr) {
+		Common::Rect &r = *dr;
+		_dirtyRects.push_back(Common::Rect(r.left, r.top, r.right, r.bottom));
+	}
+
+	// Merge any overlapping rects to simplify the drawing process
+	mergeClipRects();
+
+	// Copy any modified areas
+	for (dr = _dirtyRects.begin(); dr != _dirtyRects.end(); ++dr) {
+		Common::Rect &r = *dr;
+		g_system->copyRectToScreen(globalScreen + 320 * r.top + r.left, 320, 
+			r.left, r.top, r.width(), r.height());
+	}
+
+	_dirtyRects.clear();
+
+	// Allow the screen to update
 	g_system->updateScreen();
 }
 
@@ -260,4 +326,46 @@
 	memset(dataPtr, 0, dataSize);
 }
 
+/**
+ * This method compares a new background being switched in against the current background,
+ * to figure out rectangles of changed areas for dirty rectangles
+ */
+void switchBackground(const byte *newBg) {
+	const byte *bg = gfxModuleData.pPage00;
+	int sliceXStart, sliceXEnd;
+
+	// If both the upper corners are different, presume it's a full screen change
+	if ((*newBg != *bg) && (*(newBg + 319) != *(bg + 319))) {
+		gfxModuleData_addDirtyRect(Common::Rect(0, 0, 320, 200));
+		return;
+	}
+
+	/* For an optimisation, any changes are stored as a series of slices than have a height of a single
+	 * line each. It is left up to the screen redraw code to automatically merge these together 
+	 */
+
+	for (int yp = 0; yp < 200; ++yp) {
+		sliceXStart = -1; sliceXEnd = -1;
+		for (int xp = 0; xp < 320; ++xp, ++bg, ++newBg) {
+			if (*bg != *newBg) {
+				if (sliceXStart == -1) {
+					// Start of a new slice
+					sliceXStart = xp;
+					sliceXEnd = MIN(xp + 7, 320);
+				} else
+					// Carry on of changed area
+					sliceXEnd = MAX(xp, sliceXEnd);
+
+			} else if ((sliceXEnd != -1) && (xp >= (sliceXEnd + 10))) {
+				// If more than 10 pixels have gone by without any changes, then end the slice
+				gfxModuleData_addDirtyRect(Common::Rect(sliceXStart, yp, sliceXEnd, MIN(yp + 2, 200)));
+				sliceXStart = sliceXEnd = -1;
+			}
+		}
+
+		if (sliceXStart != -1)
+			gfxModuleData_addDirtyRect(Common::Rect(sliceXStart, yp, 320, MIN(yp + 2, 200)));
+	}
+}
+
 } // End of namespace Cruise

Modified: scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.h
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.h	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/gfxModule.h	2009-09-26 04:38:25 UTC (rev 44373)
@@ -62,10 +62,13 @@
 void gfxModuleData_convertOldPalColor(uint16 oldColor, uint8 *pOutput);
 void gfxModuleData_setPalEntries(const byte *ptr, int start, int num);
 void gfxModuleData_setPal256(const byte *ptr);
+void gfxModuleData_addDirtyRect(const Common::Rect &r);
 void flip(void);
 void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 colour);
 void resetBitmap(uint8 *dataPtr, int32 dataSize);
 
+void switchBackground(const byte *newBg);
+
 } // End of namespace Cruise
 
 #endif

Modified: scummvm/branches/branch-1-0-0/engines/cruise/mainDraw.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/cruise/mainDraw.cpp	2009-09-26 04:37:19 UTC (rev 44372)
+++ scummvm/branches/branch-1-0-0/engines/cruise/mainDraw.cpp	2009-09-26 04:38:25 UTC (rev 44373)
@@ -1121,6 +1121,8 @@
 	if (spriteY1 == spriteY2)
 		return;
 
+	gfxModuleData_addDirtyRect(Common::Rect(spriteX2, spriteY2, spriteX1, spriteY1));
+
 	var_8 = 0;
 
 	memset(polygonMask, 0xFF, (320*200) / 8);
@@ -1177,6 +1179,8 @@
 			globalY = 198 - pGfxPtr->height;
 		}
 
+		gfxModuleData_addDirtyRect(Common::Rect(globalX, globalY, globalX + width, globalY + height));
+
 		initialOuput = ouputPtr + (globalY * 320) + globalX;
 
 		for (yp = 0; yp < height; yp++) {
@@ -1206,6 +1210,13 @@
 	int x = 0;
 	int y = 0;
 
+	// Flag the given area as having been changed
+	Common::Point ps = Common::Point(MAX(MIN(xs, 320), 0), MAX(MIN(ys, 200), 0));
+	Common::Point pe = Common::Point(MAX(MIN(xs + width, 320), 0), MAX(MIN(ys + height, 200), 0));
+	if ((ps.x != pe.x) && (ps.y != pe.y))
+		// At least part of sprite is on-screen
+		gfxModuleData_addDirtyRect(Common::Rect(ps.x, ps.y, pe.x, pe.y));
+
 	cellStruct* plWork = currentObjPtr;
 	int workBufferSize = height * (width / 8);
 
@@ -1406,6 +1417,10 @@
 
 	if (bgPtr) {
 		gfxModuleData_gfxCopyScreen(bgPtr, gfxModuleData.pPage10);
+		if (backgroundChanged[masterScreen]) {
+			backgroundChanged[masterScreen] = false;
+			switchBackground(bgPtr);
+		}
 	}
 
 	autoCellHead.next = NULL;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list