From b40b87fdb5b4ee869cce55d852af409896b20c98 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 4 Mar 2011 18:24:46 +0100 Subject: 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. --- engines/sci/graphics/picture.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'engines/sci/graphics/picture.cpp') diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 7e71c1a258..91fa2e71e8 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; -- cgit v1.2.3