diff options
| -rw-r--r-- | engines/sci/graphics/picture.cpp | 24 | ||||
| -rw-r--r-- | engines/sci/graphics/screen.cpp | 29 | ||||
| -rw-r--r-- | engines/sci/graphics/screen.h | 2 | 
3 files changed, 40 insertions, 15 deletions
| 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; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index ef2bffce76..ace69c6972 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 fc1f38ed41..6f9b08deff 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); | 
