diff options
Diffstat (limited to 'engines/sci/graphics/remap.cpp')
-rw-r--r-- | engines/sci/graphics/remap.cpp | 290 |
1 files changed, 271 insertions, 19 deletions
diff --git a/engines/sci/graphics/remap.cpp b/engines/sci/graphics/remap.cpp index 1f1ae4da0e..e331eaf971 100644 --- a/engines/sci/graphics/remap.cpp +++ b/engines/sci/graphics/remap.cpp @@ -23,6 +23,7 @@ #include "sci/sci.h" #include "sci/resource.h" #include "sci/graphics/palette.h" +#include "sci/graphics/palette32.h" #include "sci/graphics/remap.h" #include "sci/graphics/screen.h" @@ -31,8 +32,8 @@ namespace Sci { #pragma mark - #pragma mark SCI16 remapping (QFG4 demo) -GfxRemap::GfxRemap(GfxScreen *screen, GfxPalette *palette) - : _screen(screen), _palette(palette) { +GfxRemap::GfxRemap(GfxPalette *palette) + : _palette(palette) { _remapOn = false; resetRemapping(); } @@ -107,28 +108,279 @@ void GfxRemap::updateRemapping() { #pragma mark - #pragma mark SCI32 remapping -#if 0 -// TODO -void GfxRemap32::setRemappingPercentGray(byte color, byte percent) { - _remapOn = true; +#ifdef ENABLE_SCI32 - // We need to defer the setup of the remapping table every time the screen - // palette is changed, so that kernelFindColor() can find the correct - // colors. Set it once here, in case the palette stays the same and update - // it on each palette change by copySysPaletteToScreen(). - _remappingPercentToSet = percent; +GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) { + for (int i = 0; i < REMAP_COLOR_COUNT; i++) + _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone); + _noMapStart = _noMapCount = 0; + _update = false; + _remapCount = 0; - // Note: This is not what the original does, but the results are the same visually - for (int i = 0; i < 256; i++) { - byte rComponent = (byte)(_sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100); - byte gComponent = (byte)(_sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100); - byte bComponent = (byte)(_sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100); - byte luminosity = rComponent + gComponent + bComponent; - _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity); + // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle + _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) ? 244 : 254; +} + +void GfxRemap32::remapOff(byte color) { + if (!color) { + for (int i = 0; i < REMAP_COLOR_COUNT; i++) + _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone); + + _remapCount = 0; + } else { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + const byte index = _remapEndColor - color; + _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone); + _remapCount--; } - _remappingType[color] = kRemappingByPercent; + _update = true; +} + +void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange); + initColorArrays(_remapEndColor - color); + _remapCount++; + _update = true; +} + +void GfxRemap32::setRemappingPercent(byte color, byte percent) { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent); + initColorArrays(_remapEndColor - color); + _remapCount++; + _update = true; +} + +void GfxRemap32::setRemappingToGray(byte color, byte gray) { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray); + initColorArrays(_remapEndColor - color); + _remapCount++; + _update = true; +} + +void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray); + initColorArrays(_remapEndColor - color); + _remapCount++; + _update = true; +} + +void GfxRemap32::setNoMatchRange(byte from, byte count) { + _noMapStart = from; + _noMapCount = count; +} + +bool GfxRemap32::remapEnabled(byte color) const { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + const byte index = _remapEndColor - color; + return (_remaps[index].type != kRemappingNone); +} + +byte GfxRemap32::remapColor(byte color, byte target) { + assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT); + const byte index = _remapEndColor - color; + if (_remaps[index].type != kRemappingNone) + return _remaps[index].remap[target]; + else + return target; +} + +void GfxRemap32::initColorArrays(byte index) { + Palette *curPalette = &_palette->_sysPalette; + RemapParams *curRemap = &_remaps[index]; + + memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color)); + memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color)); +} + +bool GfxRemap32::updateRemap(byte index, bool palChanged) { + int result; + RemapParams *curRemap = &_remaps[index]; + const Palette *curPalette = &_palette->_sysPalette; + const Palette *nextPalette = _palette->getNextPalette(); + bool changed = false; + + if (!_update && !palChanged) + return false; + + Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false); + + switch (curRemap->type) { + case kRemappingNone: + return false; + case kRemappingByRange: + for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) { + if (curRemap->from <= i && i <= curRemap->to) + result = i + curRemap->base; + else + result = i; + + if (curRemap->remap[i] != result) { + changed = true; + curRemap->remap[i] = result; + } + + curRemap->colorChanged[i] = true; + } + return changed; + case kRemappingByPercent: + for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) { + // NOTE: This method uses nextPalette instead of curPalette + Color color = nextPalette->colors[i]; + + if (curRemap->curColor[i] != color) { + curRemap->colorChanged[i] = true; + curRemap->curColor[i] = color; + } + + if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) { + byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255); + byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255); + byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255); + byte used = curRemap->targetColor[i].used; + + Color newColor = { used, red, green, blue }; + if (curRemap->targetColor[i] != newColor) { + _targetChanged[i] = true; + curRemap->targetColor[i] = newColor; + } + } + } + + changed = applyRemap(index); + Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false); + curRemap->oldPercent = curRemap->percent; + return changed; + case kRemappingToGray: + for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) { + Color color = curPalette->colors[i]; + + if (curRemap->curColor[i] != color) { + curRemap->colorChanged[i] = true; + curRemap->curColor[i] = color; + } + + if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) { + byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8; + byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255); + byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255); + byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255); + byte used = curRemap->targetColor[i].used; + + Color newColor = { used, red, green, blue }; + if (curRemap->targetColor[i] != newColor) { + _targetChanged[i] = true; + curRemap->targetColor[i] = newColor; + } + } + } + + changed = applyRemap(index); + Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false); + curRemap->oldGray = curRemap->gray; + return changed; + case kRemappingToPercentGray: + for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) { + Color color = curPalette->colors[i]; + + if (curRemap->curColor[i] != color) { + curRemap->colorChanged[i] = true; + curRemap->curColor[i] = color; + } + + if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) { + byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8; + lumosity = lumosity * curRemap->percent / 100; + byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255); + byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255); + byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255); + byte used = curRemap->targetColor[i].used; + + Color newColor = { used, red, green, blue }; + if (curRemap->targetColor[i] != newColor) { + _targetChanged[i] = true; + curRemap->targetColor[i] = newColor; + } + } + } + + changed = applyRemap(index); + Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false); + curRemap->oldPercent = curRemap->percent; + curRemap->oldGray = curRemap->gray; + return changed; + default: + return false; + } } + +static int colorDistance(Color a, Color b) { + int rDiff = (a.r - b.r) * (a.r - b.r); + int gDiff = (a.g - b.g) * (a.g - b.g); + int bDiff = (a.b - b.b) * (a.b - b.b); + return rDiff + gDiff + bDiff; +} + +bool GfxRemap32::applyRemap(byte index) { + RemapParams *curRemap = &_remaps[index]; + const bool *cycleMap = _palette->getCyclemap(); + bool unmappedColors[NON_REMAPPED_COLOR_COUNT]; + Color newColors[NON_REMAPPED_COLOR_COUNT]; + bool changed = false; + + Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false); + if (_noMapCount) + Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true); + + for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) { + if (cycleMap[i]) + unmappedColors[i] = true; + } + + int curColor = 0; + for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) { + if (curRemap->colorChanged[i] && !unmappedColors[i]) + newColors[curColor++] = curRemap->curColor[i]; + } + + for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) { + Color targetColor = curRemap->targetColor[i]; + bool colorChanged = curRemap->colorChanged[curRemap->remap[i]]; + + if (!_targetChanged[i] && !colorChanged) + continue; + + if (_targetChanged[i] && colorChanged) + if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i]) + continue; + + int diff = 0; + int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors); + if (result != -1 && curRemap->remap[i] != result) { + changed = true; + curRemap->remap[i] = result; + curRemap->distance[i] = diff; + } + } + + return changed; +} + +bool GfxRemap32::remapAllTables(bool palChanged) { + bool changed = false; + + for (int i = 0; i < REMAP_COLOR_COUNT; i++) { + changed |= updateRemap(i, palChanged); + } + + _update = false; + return changed; +} + #endif } // End of namespace Sci |