From 28967b617f53dbda91d549007dc8af2581dbae3a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 28 Oct 2014 22:37:57 +0100 Subject: SCI: properly reversed color matching thanks wjp --- engines/sci/graphics/palette.cpp | 82 +++++++++++++++++++++++----------------- engines/sci/graphics/palette.h | 4 ++ 2 files changed, 52 insertions(+), 34 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 36b9660d4e..4d2c874e04 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -73,6 +73,8 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) // to detect if the current game is merging or copying _useMerging = _resMan->detectPaletteMergingSci11(); _use16bitColorMatch = _useMerging; + // Note: Laura Bow 2 floppy uses the new palette format and is detected + // as 8 bit color matching because of that. } else { // SCI32 _useMerging = false; @@ -473,8 +475,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { // check if exact color could be matched res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); - if (res & 0x8000) { // exact match was found - newPalette->mapping[i] = res & 0xFF; + if (res & SCI_PALETTE_MATCH_PERFECT) { // exact match was found + newPalette->mapping[i] = res & SCI_PALETTE_MATCH_COLORMASK; continue; } @@ -495,8 +497,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { // if still no luck - set an approximate color if (j == 256) { - newPalette->mapping[i] = res & 0xFF; - _sysPalette.colors[res & 0xFF].used |= 0x10; + newPalette->mapping[i] = res & SCI_PALETTE_MATCH_COLORMASK; + _sysPalette.colors[res & SCI_PALETTE_MATCH_COLORMASK].used |= 0x10; } } @@ -518,38 +520,50 @@ void GfxPalette::drewPicture(GuiResourceId pictureId) { } } -uint16 GfxPalette::matchColor(byte r, byte g, byte b) { - byte found = 0xFF; - int diff = 0x2FFFF, cdiff; - int16 dr,dg,db; - - for (int i = 1; i < 255; i++) { - if ((!_sysPalette.colors[i].used)) - continue; - dr = _sysPalette.colors[i].r - r; - dg = _sysPalette.colors[i].g - g; - db = _sysPalette.colors[i].b - b; - if (!_use16bitColorMatch) { - // remove upper bits for most SCI1.1 games - // this bug was introduced with Quest For Glory 3 interpreter - // we have to implement it, otherwise some colors will be "wrong" - // See Space Quest 5 bug #6455 - dr &= 0xFF; - dg &= 0xFF; - db &= 0xFF; +uint16 GfxPalette::matchColor(byte matchRed, byte matchGreen, byte matchBlue) { + int16 colorNr; + int16 differenceRed, differenceGreen, differenceBlue; + int16 differenceTotal = 0; + int16 bestDifference = 0x7FFF; + uint16 bestColor = 255; + + if (_use16bitColorMatch) { + // used by SCI0 to SCI1, also by the first few SCI1.1 games + for (colorNr = 0; colorNr < 256; colorNr++) { + if ((!_sysPalette.colors[colorNr].used)) + continue; + differenceRed = ABS(_sysPalette.colors[colorNr].r - matchRed); + differenceGreen = ABS(_sysPalette.colors[colorNr].g - matchGreen); + differenceBlue = ABS(_sysPalette.colors[colorNr].b - matchBlue); + differenceTotal = differenceRed + differenceGreen + differenceBlue; + if (differenceTotal <= bestDifference) { + bestDifference = differenceTotal; + bestColor = colorNr; + } } -// minimum squares match - cdiff = (dr*dr) + (dg*dg) + (db*db); -// minimum sum match (Sierra's) -// cdiff = ABS(dr) + ABS(dg) + ABS(db); - if (cdiff < diff) { - if (cdiff == 0) - return i | 0x8000; // setting this flag to indicate exact match - found = i; - diff = cdiff; + } else { + // SCI1.1, starting with QfG3 introduced a bug in the matching code + // we have to implement it as well, otherwise some colors will be "wrong" in comparison to the original interpreter + // See Space Quest 5 bug #6455 + for (colorNr = 0; colorNr < 256; colorNr++) { + if ((!_sysPalette.colors[colorNr].used)) + continue; + differenceRed = (uint8)ABS(_sysPalette.colors[colorNr].r - matchRed); + differenceGreen = (uint8)ABS(_sysPalette.colors[colorNr].g - matchGreen); + differenceBlue = (uint8)ABS(_sysPalette.colors[colorNr].b - matchBlue); + differenceTotal = differenceRed + differenceGreen + differenceBlue; + if (differenceTotal < 0) { + differenceTotal = differenceTotal; + } + if (differenceTotal <= bestDifference) { + bestDifference = differenceTotal; + bestColor = colorNr; + } } } - return found; + if (differenceTotal == 0) // original interpreter does not do this, instead it does 2 calls for merges in the worst case + return colorNr | SCI_PALETTE_MATCH_PERFECT; // we set this flag, so that we can optimize during palette merge + return bestColor; } void GfxPalette::getSys(Palette *pal) { @@ -639,7 +653,7 @@ void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 int } int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) { - return matchColor(r, g, b) & 0xFF; + return matchColor(r, g, b) & SCI_PALETTE_MATCH_COLORMASK; } // Returns true, if palette got changed diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 93cc2a8189..500a45eccf 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -31,6 +31,10 @@ namespace Sci { class ResourceManager; class GfxScreen; +// Special flag implemented by us for optimization in palette merge +#define SCI_PALETTE_MATCH_PERFECT 0x8000 +#define SCI_PALETTE_MATCH_COLORMASK 0xFF + enum ColorRemappingType { kRemappingNone = 0, kRemappingByRange = 1, -- cgit v1.2.3