[Scummvm-cvs-logs] scummvm master -> b40b87fdb5b4ee869cce55d852af409896b20c98

wjp wjp at usecode.org
Fri Mar 4 18:33:35 CET 2011


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b40b87fdb5 SCI: Fix flood fill matching in EGA mode


Commit: b40b87fdb5b4ee869cce55d852af409896b20c98
    https://github.com/scummvm/scummvm/commit/b40b87fdb5b4ee869cce55d852af409896b20c98
Author: Willem Jan Palenstijn (wjp at usecode.org)
Date: 2011-03-04T09:24:46-08:00

Commit Message:
SCI: Fix flood fill matching in EGA mode

In EGA games a pixel in the framebuffer is only 4 bits. We store a full
byte per pixel to allow undithering, but when comparing pixels for
flood-fill purposes, we should only compare the visible color of a
pixel.

This fixes bug #3078365 in Iceman.

Changed paths:
    engines/sci/graphics/picture.cpp
    engines/sci/graphics/screen.cpp
    engines/sci/graphics/screen.h



diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 7e71c1a..91fa2e7 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -866,6 +866,8 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
 	byte matchedMask, matchMask;
 	int16 w, e, a_set, b_set;
 
+	bool isEGA = (_resMan->getViewType() == kViewEga);
+
 	p.x = x + curPort->left;
 	p.y = y + curPort->top;
 	stack.push(p);
@@ -874,6 +876,18 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
 	byte searchPriority = _screen->getPriority(p.x, p.y);
 	byte searchControl = _screen->getControl(p.x, p.y);
 
+	if (isEGA) {
+		// In EGA games a pixel in the framebuffer is only 4 bits. We store
+		// a full byte per pixel to allow undithering, but when comparing
+		// pixels for flood-fill purposes, we should only compare the
+		// visible color of a pixel.
+
+		if ((x ^ y) & 1)
+			searchColor = (searchColor ^ (searchColor >> 4)) & 0x0F;
+		else
+			searchColor = searchColor & 0x0F;
+	}
+
 	// This logic was taken directly from sierra sci, floodfill will get aborted on various occations
 	if (screenMask & GFX_SCREEN_MASK_VISUAL) {
 		if ((color == _screen->getColorWhite()) || (searchColor != _screen->getColorWhite()))
@@ -913,20 +927,20 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
 	int b = curPort->rect.bottom + curPort->top - 1;
 	while (stack.size()) {
 		p = stack.pop();
-		if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl)) == 0) // already filled
+		if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled
 			continue;
 		_screen->putPixel(p.x, p.y, screenMask, color, priority, control);
 		w = p.x;
 		e = p.x;
 		// moving west and east pointers as long as there is a matching color to fill
-		while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+		while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
 			_screen->putPixel(--w, p.y, screenMask, color, priority, control);
-		while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+		while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
 			_screen->putPixel(++e, p.y, screenMask, color, priority, control);
 		// checking lines above and below for possible flood targets
 		a_set = b_set = 0;
 		while (w <= e) {
-			if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl))) { // one line above
+			if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above
 				if (a_set == 0) {
 					p1.x = w;
 					p1.y = p.y - 1;
@@ -936,7 +950,7 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
 			} else
 				a_set = 0;
 
-			if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl))) { // one line below
+			if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below
 				if (b_set == 0) {
 					p1.x = w;
 					p1.y = p.y + 1;
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index ef2bffc..ace69c6 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -353,19 +353,30 @@ byte GfxScreen::getControl(int x, int y) {
 	return _controlScreen[y * _width + x];
 }
 
-byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con) {
+byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) {
 	int offset = y * _width + x;
 	byte match = 0;
 
 	// FIXME:
-	// This does not behave properly in EGA games where a pixel in the
-	// framebuffer is only 4 bits. We store a full byte per pixel to allow
-	// undithering, but when comparing pixels for flood-fill purposes, we
-	// should only compare the visible color of a pixel (with dithering
-	// enabled). See bug #3078365. Also see IS_BOUNDARY in FreeSCI's picfill.
-
-	if ((screenMask & GFX_SCREEN_MASK_VISUAL) && *(_visualScreen + offset) == t_color)
-		match |= GFX_SCREEN_MASK_VISUAL;
+	if (screenMask & GFX_SCREEN_MASK_VISUAL) {
+		if (!isEGA) {
+			if (*(_visualScreen + offset) == t_color)
+				match |= GFX_SCREEN_MASK_VISUAL;
+		} else {
+			// In EGA games a pixel in the framebuffer is only 4 bits. We store
+			// a full byte per pixel to allow undithering, but when comparing
+			// pixels for flood-fill purposes, we should only compare the
+			// visible color of a pixel.
+
+			byte c = *(_visualScreen + offset);
+			if ((x ^ y) & 1)
+				c = (c ^ (c >> 4)) & 0x0F;
+			else
+				c = c & 0x0F;
+			if (c == t_color)
+				match |= GFX_SCREEN_MASK_VISUAL;
+		}
+	}
 	if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == t_pri)
 		match |= GFX_SCREEN_MASK_PRIORITY;
 	if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == t_con)
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index fc1f38e..6f9b08d 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -99,7 +99,7 @@ public:
 	byte getVisual(int x, int y);
 	byte getPriority(int x, int y);
 	byte getControl(int x, int y);
-	byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con);
+	byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
 
 	int bitsGetDataSize(Common::Rect rect, byte mask);
 	void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);






More information about the Scummvm-git-logs mailing list