aboutsummaryrefslogtreecommitdiff
path: root/engines/cruise/gfxModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/cruise/gfxModule.cpp')
-rw-r--r--engines/cruise/gfxModule.cpp72
1 files changed, 71 insertions, 1 deletions
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 003a335e42..b3ac68edae 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -26,6 +26,8 @@
#include "common/system.h"
#include "common/endian.h"
+#include "common/list.h"
+#include "common/rect.h"
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
@@ -41,6 +43,12 @@ palEntry lpalette[256];
int palDirtyMin = 256;
int palDirtyMax = -1;
+typedef Common::List<Common::Rect> RectList;
+RectList _dirtyRects;
+RectList _priorFrameRects;
+
+bool _dirtyRectScreen = false;
+
gfxModuleDataStruct gfxModuleData = {
0, // use Tandy
0, // use EGA
@@ -229,7 +237,47 @@ void gfxModuleData_flipScreen(void) {
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 +293,29 @@ void flip() {
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();
}