diff options
author | uruk | 2014-05-30 11:14:47 +0200 |
---|---|---|
committer | uruk | 2014-05-30 11:14:47 +0200 |
commit | bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d (patch) | |
tree | 9a1e28cfb1eb1a322225c05adc0962a2f96ea521 /engines/mads/palette.cpp | |
parent | 5ad4e157e5398347651a0da0db07f9daf01bf373 (diff) | |
parent | 0a46d67baea121bed0511ce45bfdd8438a43d35d (diff) | |
download | scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.gz scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.bz2 scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.zip |
Merge branch 'master' of https://github.com/scummvm/scummvm into cge2
Diffstat (limited to 'engines/mads/palette.cpp')
-rw-r--r-- | engines/mads/palette.cpp | 830 |
1 files changed, 830 insertions, 0 deletions
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp new file mode 100644 index 0000000000..755f7bcf5c --- /dev/null +++ b/engines/mads/palette.cpp @@ -0,0 +1,830 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "mads/mads.h" +#include "mads/msurface.h" +#include "mads/staticres.h" + +namespace MADS { + +#define VGA_COLOR_TRANS(x) ((x) * 255 / 63) + +void RGB6::load(Common::SeekableReadStream *f) { + r = VGA_COLOR_TRANS(f->readByte()); + g = VGA_COLOR_TRANS(f->readByte()); + b = VGA_COLOR_TRANS(f->readByte()); + _palIndex = f->readByte(); + _u2 = f->readByte(); + _flags = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +PaletteUsage::PaletteUsage(MADSEngine *vm) { + _vm = vm; + _data = nullptr; +} + +void PaletteUsage::load(Common::Array<UsageEntry> *data) { + _data = data; +} + +void PaletteUsage::getKeyEntries(Common::Array<RGB6> &palette) { + _data->clear(); + + for (uint i = 0; i < palette.size(); ++i) { + byte *uPtr = &palette[i]._flags; + if ((*uPtr & 0x10) && _data->size() < 3) { + _data->push_back(UsageEntry(i)); + } + } +} + +static bool sortHelper(const PaletteUsage::UsageEntry &ue1, const PaletteUsage::UsageEntry &ue2) { + return ue1._sortValue < ue2._sortValue; +} + +void PaletteUsage::prioritize(Common::Array<RGB6> &palette) { + for (uint i = 0; i < _data->size(); ++i) { + RGB6 &palEntry = palette[(*_data)[i]._palIndex]; + (*_data)[i]._sortValue = _vm->_palette->rgbMerge(palEntry); + } + + Common::sort(_data->begin(), _data->end(), sortHelper); +} + +static bool rangeSorter(const PaletteUsage::UsageRange &ur1, const PaletteUsage::UsageRange &ur2) { + return ur1._v2 < ur2._v2; +} + +int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { + int palLow; + int palHigh = (flags & 0x800) ? 0x100 : 0xFC; + int palIdx; + + PaletteUsage tempUsage(_vm); + Common::Array<UsageEntry> tempUsageData; + tempUsage.load(&tempUsageData); + + if (flags & 0x4000) { + palLow = 0; + palIdx = palHigh; + } else { + palLow = _vm->_palette->_lowRange; + if ((PALETTE_COUNT - _vm->_palette->_highRange) > palHigh) { + palIdx = palHigh; + } else { + palIdx = PALETTE_COUNT - _vm->_palette->_highRange; + } + } + + int rgbIndex = _vm->_palette->_rgbList.scan(); + uint32 rgbMask = 1 << rgbIndex; + bool noUsageFlag = flags & 0x8000; + bool hasUsage = _data != nullptr; + bool flag1 = false; + + if (hasUsage) { + if (noUsageFlag || _data->size() == 0) + hasUsage = false; + + if (noUsageFlag && _data->size() > 0) + flag1 = true; + } + + if (hasUsage) { + tempUsage.getKeyEntries(palette); + tempUsage.prioritize(palette); + } + + int freeIndex; + int palCount = getGamePalFreeIndex(&freeIndex); + Common::Array<UsageRange> palRange; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + byte pal2 = palIndex; + byte pal1 = 0; + + if (!(palette[palIndex]._flags & 0x80)) { + pal1 = 0x40; + } + if (palette[palIndex]._flags & 0x60) { + pal1 |= 0x20; + } + + palRange.push_back(UsageRange(pal1, pal2)); + } + + Common::sort(palRange.begin(), palRange.end(), rangeSorter); + + int var3A = (flags & 0x4000) ? 0xffff : 0xfffe; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + bool var48 = false; + int var4 = 0xffff; + int v1 = palRange[palIndex]._v2; + + if (palette[v1]._flags & 8) { + var48 = true; + var4 = 0xFD; + } + + if (hasUsage && palette[v1]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < tempUsage._data->size() && !var48; ++usageIndex) { + if ((*tempUsage._data)[usageIndex]._palIndex == palIndex) { + var48 = true; + int dataIndex = MIN(usageIndex, _data->size() - 1); + var4 = (*_data)[dataIndex]._palIndex; + } + } + } + + if (flag1 && palette[palIndex]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < _data->size() && !var48; ++usageIndex) { + if ((*_data)[usageIndex]._palIndex == palIndex) { + var48 = true; + var4 = 0xF0 + usageIndex; + + // Copy data into the high end of the main palette + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[var4 * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + if (!var48 && !noUsageFlag) { + int var2 = (palette[palIndex]._flags & 0x20) || + (((flags & 0x2000) || (palette[palIndex]._flags & 0x4000)) && + ((flags & 0x1000) || (palCount == 0))) ? 0x7fff : 1; + int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2; + + for (int idx = palLow; idx < palIdx; ++idx) { + uint32 v = _vm->_palette->_palFlags[idx]; + if ((v & var3A) && !(v & var36)) { + int var10; + + if (var2 > 1) { + var10 = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]); + } + else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r || + _vm->_palette->_mainPalette[idx * 3 + 1] != palette[palIndex].g || + _vm->_palette->_mainPalette[idx * 3 + 2] != palette[palIndex].b) { + var10 = 1; + } else { + var10 = 0; + } + + if (var2 > var10) { + var48 = true; + var4 = idx; + var2 = var10; + } + } + } + } + + if (!var48 && (!(flags & 0x1000) || (!(palette[palIndex]._flags & 0x60) && !(flags & 0x2000)))) { + for (int idx = freeIndex; idx < palIdx && !var48; ++idx) { + if (!_vm->_palette->_palFlags[idx]) { + --palCount; + ++freeIndex; + var48 = true; + var4 = idx; + + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[idx * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + assert(var48); + int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0; + + _vm->_palette->_palFlags[var4] |= var52 | rgbMask; + palette[palIndex]._palIndex = var4; + } + + _vm->_palette->_rgbList[rgbIndex] = true; + + return rgbIndex; +} + +void PaletteUsage::transform(Common::Array<RGB6> &palette) { + if (!empty()) { + for (uint i = 0; i < _data->size(); ++i) { + int palIndex = (*_data)[i]._palIndex; + (*_data)[i]._palIndex = palette[palIndex]._palIndex; + } + } +} + +void PaletteUsage::updateUsage(Common::Array<int> &usageList, int sceneUsageIndex) { + uint32 mask1 = 0xFFFFFFFF; + uint32 mask2 = 0; + + for (uint idx = 0; idx < usageList.size(); ++idx) { + uint32 bitMask = 1 << usageList[idx]; + mask1 ^= bitMask; + mask2 |= bitMask; + _vm->_palette->_rgbList[usageList[idx]] = false; + } + + uint32 mask3 = 1 << sceneUsageIndex; + + for (uint idx = 0; idx < PALETTE_COUNT; ++idx) { + uint32 mask = mask2 & _vm->_palette->_palFlags[idx]; + if (mask) { + _vm->_palette->_palFlags[idx] = (_vm->_palette->_palFlags[idx] & + mask1) | mask3; + } + } + + _vm->_palette->_rgbList[sceneUsageIndex] = true; +} + +void PaletteUsage::resetPalFlags(int idx) { + if (idx >= 0 && idx < 32) { + uint32 rgbMask = ~(1 << idx); + + uint32 *flagP = _vm->_palette->_palFlags; + for (int i = 0; i < 256; ++i, ++flagP) { + *flagP &= rgbMask; + if (*flagP == 2) + *flagP = 0; + } + + _vm->_palette->_rgbList[idx] = 0; + } +} + +int PaletteUsage::getGamePalFreeIndex(int *palIndex) { + *palIndex = -1; + int count = 0; + + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (!_vm->_palette->_palFlags[i]) { + ++count; + if (*palIndex < 0) + *palIndex = i; + } + } + + return count; +} + +int PaletteUsage::rgbFactor(byte *palEntry, RGB6 &pal6) { + int total = 0; + total += (palEntry[0] - pal6.r) * (palEntry[0] - pal6.r); + total += (palEntry[1] - pal6.g) * (palEntry[1] - pal6.g); + total += (palEntry[2] - pal6.b) * (palEntry[2] - pal6.b); + + return total; +} + +/*------------------------------------------------------------------------*/ + +void RGBList::clear() { + for (int i = 0; i < 32; i++) + _data[i] = false; +} + +void RGBList::reset() { + for (int i = 2; i < 32; i++) + _data[i] = false; +} + +int RGBList::scan() { + for (int i = 0; i < 32; ++i) { + if (!_data[i]) + return i; + } + + error("RGBList was full"); +} + +void RGBList::copy(RGBList &src) { + Common::copy(&src._data[0], &src._data[32], &_data[0]); +} + +/*------------------------------------------------------------------------*/ + +Fader::Fader(MADSEngine *vm) + : _vm(vm) { + _colorFlags[0] = _colorFlags[1] = _colorFlags[2] = true; + _colorFlags[3] = false; + _colorValues[0] = _colorValues[1] = 0; + _colorValues[2] = _colorValues[3] = 0; + + // TODO: It would be better if the fader routines could be refactored + // to work directly with 8-bit RGB values rather than 6-bit RGB values + Common::fill(&_rgb64Map[0], &_rgb64Map[PALETTE_COUNT], 0); + for (int i = 0; i < 64; ++i) + _rgb64Map[VGA_COLOR_TRANS(i)] = i; + byte v = 0; + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (_rgb64Map[i]) + v = _rgb64Map[i]; + else + _rgb64Map[i] = v; + } +} + + +void Fader::setPalette(const byte *colors, uint start, uint num) { + g_system->getPaletteManager()->setPalette(colors, start, num); +} + +void Fader::grabPalette(byte *colors, uint start, uint num) { + g_system->getPaletteManager()->grabPalette(colors, start, num); +} + +void Fader::fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + int intensity; + byte palIndex[PALETTE_COUNT][3]; + int8 signs[PALETTE_COUNT][3]; + + mapToGreyRamp(palette, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } else { + intensity = map[index]._intensity >> ABS(shiftSign); + } + } else { + intensity = _colorValues[colorCtr]; + } + + int diff = intensity - _rgb64Map[palette[palCtr * 3 + colorCtr]]; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } + + if (paletteMap != nullptr) { + for (int palCtr = 0; palCtr < numColors; palCtr++) { + paletteMap[palCtr] = map[palCtr]._mapColor; + } + } +} + +void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + byte tempPal[PALETTE_SIZE];; + int8 signs[PALETTE_COUNT][3]; + byte palIndex[PALETTE_COUNT][3]; + int intensity; + + Common::copy(destPalette, destPalette + PALETTE_SIZE, tempPal); + + mapToGreyRamp(tempPal, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } + else { + intensity = map[index]._intensity >> abs(shiftSign); + } + } + else { + intensity = _colorValues[colorCtr]; + } + + int diff = _rgb64Map[destPalette[palCtr * 3 + colorCtr]] - intensity; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + + map[index]._accum[colorCtr] = 0; + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } +} + +void Fader::mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors, + int baseGrey, int numGreys, GreyEntry *map) { + byte greyList[PALETTE_COUNT]; + byte greyMapping[PALETTE_COUNT]; + byte greyTable[64]; + byte greyIntensity[64]; + int intensity, shiftSign; + + getGreyValues(palette, greyList, baseColor, numColors); + greyPopularity(greyList, greyTable, numColors); + + for (int idx = 0; idx < numColors; ++idx) { + greyMapping[idx] = idx; + Common::fill(&map[idx]._accum[0], &map[idx]._accum[3], 0); + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) { + map[idx]._mapColor = (byte)idx; + } + + // Sort the mapping lists + insertionSort(numColors, greyList, greyMapping); + + // Initialize state variables + int greySum = 0; + int greyScan = 0; + int greyMark = 0; + int greyColors = 0; + int greyAccum = 0; + int firstColor = 0; + + for (int greyCtr = 0; greyCtr < 64; ++greyCtr) { + for (int idx = 0; idx < greyTable[greyCtr]; ++idx) { + greySum += greyList[greyScan++]; + ++greyColors; + + greyAccum += numGreys; + while (greyAccum >= numColors) { + greyAccum -= numColors; + if (greyColors > 0) { + greyIntensity[greyMark] = (byte)(greySum / greyColors); + } + + for (int rescan = firstColor; rescan < greyScan; ++rescan) { + map[greyMapping[rescan]]._intensity = greyIntensity[greyMark]; + map[greyMapping[rescan]]._mapColor = (byte)(greyMark + baseGrey); + } + + firstColor = greyScan; + greySum = 0; + greyColors = 0; + ++greyMark; + } + } + } + + // Set the palette range of greyscale values to be used + byte *palP = &palette[baseGrey * 3]; + for (int greys = 0; greys < numGreys; ++greys) { + for (int color = 0; color < 3; ++color) { + if (_colorFlags[color]) { + shiftSign = (byte)_colorValues[color]; + if (shiftSign >= 0) { + intensity = greyIntensity[greys] << shiftSign; + } else { + intensity = greyIntensity[greys] >> abs(shiftSign); + } + } else { + intensity = _colorValues[color]; + } + *palP++ = VGA_COLOR_TRANS(intensity); + } + } +} + +void Fader::getGreyValues(const byte palette[PALETTE_SIZE], + byte greyList[PALETTE_COUNT], int baseColor, int numColors) { + const byte *palP = &palette[baseColor * 3]; + + for (int i = 0; i < numColors; ++i, palP += 3) { + int v = rgbMerge(palP[0], palP[1], palP[2]); + greyList[i] = v >> 7; + } +} + +void Fader::greyPopularity(const byte greyList[PALETTE_COUNT], + byte greyTable[64], int numColors) { + Common::fill(&greyTable[0], &greyTable[64], 0); + for (int i = 0; i < numColors; ++i) { + int idx = greyList[i]; + ++greyTable[idx]; + } +} + +void Fader::insertionSort(int size, byte *id, byte *value) { + bool restartFlag; + int endIndex = size - 1; + + do { + restartFlag = false; + if (endIndex <= 0) + break; + + for (int arrIndex = 0; arrIndex < endIndex && !restartFlag; ++arrIndex) { + byte *idP = id + arrIndex; + byte *valueP = value + arrIndex; + + // Check whether the next index is out of order with the one following it + if (*idP > *(idP + 1)) { + // Found an incorrect ordering + restartFlag = true; + + // Save id/value at current index + byte savedId = *idP; + byte savedValue = *valueP; + + int moveCount = size - arrIndex - 1; + if (moveCount > 0) { + Common::copy(idP + 1, idP + moveCount + 2, idP); + Common::copy(valueP + 1, valueP + moveCount + 2, valueP); + } + + // Scan for insert spot + int idx = 0; + if (endIndex > 0) { + bool breakFlag = false; + for (; idx <= endIndex && !breakFlag; ++idx) { + breakFlag = savedId < id[idx]; + } + } + + // Set up an insert point for entry + moveCount = size - idx - 1; + if (moveCount > 0) { + Common::copy_backward(id + idx, id + idx + moveCount, id + idx + moveCount + 1); + Common::copy_backward(value + idx, value + idx + moveCount, value + idx + moveCount + 1); + } + + // Set shifted values at the new position + id[idx] = savedId; + value[idx] = savedValue; + } + } + } while (restartFlag); +} + +int Fader::rgbMerge(RGB6 &palEntry) { + return rgbMerge(palEntry.r, palEntry.g, palEntry.b); +} + +int Fader::rgbMerge(byte r, byte g, byte b) { + return _rgb64Map[r] * 38 + _rgb64Map[g] * 76 + _rgb64Map[b] * 14; +} + +/*------------------------------------------------------------------------*/ + +Palette::Palette(MADSEngine *vm) : Fader(vm), _paletteUsage(vm) { + _lockFl = false; + _lowRange = 0; + _highRange = 0; + Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0); + Common::fill(&_palFlags[0], &_palFlags[PALETTE_COUNT], 0); +} + +void Palette::setEntry(byte palIndex, byte r, byte g, byte b) { + _mainPalette[palIndex * 3] = VGA_COLOR_TRANS(r); + _mainPalette[palIndex * 3 + 1] = VGA_COLOR_TRANS(g); + _mainPalette[palIndex * 3 + 2] = VGA_COLOR_TRANS(b); + + setPalette((const byte *)&_mainPalette[palIndex * 3], palIndex, 1); +} + +uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, byte *paletteData) { + byte index = 0; + int32 minDist = 0x7fffffff; + byte palData[PALETTE_SIZE]; + + if (paletteData == NULL) { + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); + paletteData = &palData[0]; + } + + for (int palIndex = 0; palIndex < PALETTE_COUNT; ++palIndex) { + int Rdiff = r - paletteData[palIndex * 3]; + int Gdiff = g - paletteData[palIndex * 3 + 1]; + int Bdiff = b - paletteData[palIndex * 3 + 2]; + + if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) { + minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; + index = (uint8)palIndex; + } + } + + return (uint8)index; +} + +void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2) { + int rgbCurrent = rgbValue2; + int rgbDiff = -(rgbValue2 - rgbValue1); + + if (count > 0) { + byte *pDest = palette + start * 3; + int endVal = count - 1; + int numLeft = count; + + int rgbCtr = 0; + do { + pDest[0] = pDest[1] = pDest[2] = rgbCurrent; + + if (numLeft > 1) { + rgbCtr += rgbDiff; + if (rgbCtr >= endVal) { + do { + ++rgbCurrent; + rgbCtr += 1 - numLeft; + } while (rgbCtr >= endVal); + } + } + + pDest += 3; + } while (--numLeft > 0); + } +} + +void Palette::setSystemPalette() { + byte palData[4 * 3]; + palData[0 * 3] = palData[0 * 3 + 1] = palData[0 * 3 + 2] = 0; + palData[1 * 3] = palData[1 * 3 + 1] = palData[1 * 3 + 2] = 0x54; + palData[2 * 3] = palData[2 * 3 + 1] = palData[2 * 3 + 2] = 0xb4; + palData[3 * 3] = palData[3 * 3 + 1] = palData[3 * 3 + 2] = 0xff; + + setPalette(palData, 0, 4); +} + +void Palette::resetGamePalette(int lowRange, int highRange) { + Common::fill((byte *)&_palFlags[0], (byte *)&_palFlags[PALETTE_COUNT], 0); + initVGAPalette(_mainPalette); + + // Reserve the start of the palette for things like on-screen text + if (lowRange) { + Common::fill(&_palFlags[0], &_palFlags[lowRange], 1); + } + + // Reserve the high end of the palette for dialog display + if (highRange) { + Common::fill(&_palFlags[256 - highRange], &_palFlags[256], 1); + } + + _rgbList.clear(); + _rgbList[0] = _rgbList[1] = true; + + _lockFl = false; + _lowRange = lowRange; + _highRange = highRange; +} + +void Palette::initPalette() { + uint32 palMask = 1; + + if (_vm->_game->_player._spritesLoaded && _vm->_game->_player._numSprites) { + + for (int idx = 0; idx < _vm->_game->_player._numSprites; ++idx) { + SpriteAsset *asset = _vm->_game->_scene._sprites[ + _vm->_game->_player._spritesStart + idx]; + + uint32 mask = 1; + if (asset->_usageIndex) + mask <<= asset->_usageIndex; + + palMask = mask; + } + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) + _palFlags[idx] = palMask; + + _lockFl = false; + _rgbList.reset(); +} + +void Palette::initVGAPalette(byte *palette) { + byte *destP = palette; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_LOW_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } + + destP = &palette[0xF0 * 3]; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_HIGH_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } +} + +void Palette::setLowRange() { + _mainPalette[0] = _mainPalette[1] = _mainPalette[2] = VGA_COLOR_TRANS(0); + _mainPalette[3] = _mainPalette[4] = _mainPalette[5] = VGA_COLOR_TRANS(0x15); + _mainPalette[6] = _mainPalette[7] = _mainPalette[8] = VGA_COLOR_TRANS(0x2A); + _mainPalette[9] = _mainPalette[10] = _mainPalette[11] = VGA_COLOR_TRANS(0x3F); + _vm->_palette->setPalette(_mainPalette, 0, 4); +} + +void Palette::setColorFlags(byte r, byte g, byte b) { + _colorFlags[0] = r; + _colorFlags[1] = g; + _colorFlags[2] = b; +} + +void Palette::setColorValues(byte r, byte g, byte b) { + _colorValues[0] = r; + _colorValues[1] = g; + _colorValues[2] = b; +} + +void Palette::lock() { + if (_rgbList[31] && !_lockFl) + error("Palette Lock - Unexpected values"); + + _lockFl = true; + _rgbList[31] = true; + + for (int i = 0; i < 256; i++) { + if (_palFlags[i]) + _palFlags[i] |= 0x80000000; + } +} + +void Palette::unlock() { + if (!_lockFl) + return; + + for (int i = 0; i < 256; i++) + _palFlags[i] &= 0x7FFFFFFF; + + _rgbList[31] = false; + _lockFl = false; +} + +void Palette::refreshSceneColors() { + int val = 18; + if (_vm->_game->_scene._cyclingActive) + val += _vm->_game->_scene._totalCycleColors; + + setPalette(_mainPalette + (val * 3), val, 256 - val); +} + +} // End of namespace MADS |