[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