diff options
author | Martin Kiewitz | 2009-10-06 16:14:40 +0000 |
---|---|---|
committer | Martin Kiewitz | 2009-10-06 16:14:40 +0000 |
commit | 14dfa5d7b01fba21c3da100830febbcdd1532d8c (patch) | |
tree | aaea4035a41e5b979178fa3220aaf5d780a365e9 /engines/sci/gui/gui_palette.cpp | |
parent | 855af31757d20ace18f8b96c09d44571aacc049b (diff) | |
download | scummvm-rg350-14dfa5d7b01fba21c3da100830febbcdd1532d8c.tar.gz scummvm-rg350-14dfa5d7b01fba21c3da100830febbcdd1532d8c.tar.bz2 scummvm-rg350-14dfa5d7b01fba21c3da100830febbcdd1532d8c.zip |
SCI/newgui: palette functions from SciGuiGfx now in SciGuiPalette
svn-id: r44698
Diffstat (limited to 'engines/sci/gui/gui_palette.cpp')
-rw-r--r-- | engines/sci/gui/gui_palette.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/engines/sci/gui/gui_palette.cpp b/engines/sci/gui/gui_palette.cpp new file mode 100644 index 0000000000..f41bbafa85 --- /dev/null +++ b/engines/sci/gui/gui_palette.cpp @@ -0,0 +1,307 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/timer.h" +#include "common/util.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/tools.h" +#include "sci/gui/gui_screen.h" +#include "sci/gui/gui_palette.h" + +namespace Sci { + +SciGuiPalette::SciGuiPalette(OSystem *system, EngineState *state, SciGui *gui, SciGuiScreen *screen) + : _system(system), _s(state), _gui(gui), _screen(screen) { + init(); +} + +SciGuiPalette::~SciGuiPalette() { +} + +void SciGuiPalette::init() { + int16 i; + for (i = 0; i < 256; i++) { + _sysPalette.colors[i].used = 0; + _sysPalette.colors[i].r = 0; + _sysPalette.colors[i].g = 0; + _sysPalette.colors[i].b = 0; + _sysPalette.intensity[i] = 100; + _sysPalette.mapping[i] = i; + } + _sysPalette.colors[0].used = 1; + _sysPalette.colors[255].used = 1; + _sysPalette.colors[255].r = 255; + _sysPalette.colors[255].g = 255; + _sysPalette.colors[255].b = 255; + + // Load default palette from resource 999 + if (!setFromResource(999, 2)) { + // if not found, we try to set amiga palette + if (!setAmiga()) { + // if that also doesnt work out, set EGA palette + setEGA(); + } + }; + + // Init _clrPowers used in MatchColor + for(i = 0; i < 256; i++) + _clrPowers[i] = i*i; +} + +#define SCI_PAL_FORMAT_CONSTANT 1 +#define SCI_PAL_FORMAT_VARIABLE 0 + +void SciGuiPalette::createFromData(byte *data, GuiPalette *paletteOut) { + int palFormat = 0; + int palOffset = 0; + int palColorStart = 0; + int palColorCount = 0; + int colorNo = 0; + + memset(paletteOut, 0, sizeof(GuiPalette)); + // Setup default mapping + for (colorNo = 0; colorNo < 256; colorNo++) { + paletteOut->mapping[colorNo] = colorNo; + } + if (data[0] == 0 && data[1] == 1) { + // SCI0/SCI1 palette + palFormat = SCI_PAL_FORMAT_VARIABLE; // CONSTANT; + palOffset = 260; + palColorStart = 0; palColorCount = 256; + //memcpy(&paletteOut->mapping, data, 256); + } else { + // SCI1.1 palette + palFormat = data[32]; + palOffset = 37; + palColorStart = READ_LE_UINT16(data + 25); palColorCount = READ_LE_UINT16(data + 29); + } + switch (palFormat) { + case SCI_PAL_FORMAT_CONSTANT: + for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { + paletteOut->colors[colorNo].used = 1; + paletteOut->colors[colorNo].r = data[palOffset++]; + paletteOut->colors[colorNo].g = data[palOffset++]; + paletteOut->colors[colorNo].b = data[palOffset++]; + } + break; + case SCI_PAL_FORMAT_VARIABLE: + for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { + paletteOut->colors[colorNo].used = data[palOffset++]; + paletteOut->colors[colorNo].r = data[palOffset++]; + paletteOut->colors[colorNo].g = data[palOffset++]; + paletteOut->colors[colorNo].b = data[palOffset++]; + } + break; + } +} + + +// Will try to set amiga palette by using "spal" file. If not found, we return false +bool SciGuiPalette::setAmiga() { + Common::File file; + int curColor, byte1, byte2; + + if (file.open("spal")) { + for (curColor = 0; curColor < 32; curColor++) { + byte1 = file.readByte(); + byte2 = file.readByte(); + if ((byte1 == EOF) || (byte2 == EOF)) + error("Amiga palette file ends prematurely"); + _sysPalette.colors[curColor].used = 1; + _sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11; + _sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11; + _sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11; + } + file.close(); + return true; + } + return false; +} + +void SciGuiPalette::setEGA() { + int i; + _sysPalette.colors[1].r = 0x000; _sysPalette.colors[1].g = 0x000; _sysPalette.colors[1].b = 0x0AA; + _sysPalette.colors[2].r = 0x000; _sysPalette.colors[2].g = 0x0AA; _sysPalette.colors[2].b = 0x000; + _sysPalette.colors[3].r = 0x000; _sysPalette.colors[3].g = 0x0AA; _sysPalette.colors[3].b = 0x0AA; + _sysPalette.colors[4].r = 0x0AA; _sysPalette.colors[4].g = 0x000; _sysPalette.colors[4].b = 0x000; + _sysPalette.colors[5].r = 0x0AA; _sysPalette.colors[5].g = 0x000; _sysPalette.colors[5].b = 0x0AA; + _sysPalette.colors[6].r = 0x0AA; _sysPalette.colors[6].g = 0x055; _sysPalette.colors[6].b = 0x000; + _sysPalette.colors[7].r = 0x0AA; _sysPalette.colors[7].g = 0x0AA; _sysPalette.colors[7].b = 0x0AA; + _sysPalette.colors[8].r = 0x055; _sysPalette.colors[8].g = 0x055; _sysPalette.colors[8].b = 0x055; + _sysPalette.colors[9].r = 0x055; _sysPalette.colors[9].g = 0x055; _sysPalette.colors[9].b = 0x0FF; + _sysPalette.colors[10].r = 0x055; _sysPalette.colors[10].g = 0x0FF; _sysPalette.colors[10].b = 0x055; + _sysPalette.colors[11].r = 0x055; _sysPalette.colors[11].g = 0x0FF; _sysPalette.colors[11].b = 0x0FF; + _sysPalette.colors[12].r = 0x0FF; _sysPalette.colors[12].g = 0x055; _sysPalette.colors[12].b = 0x055; + _sysPalette.colors[13].r = 0x0FF; _sysPalette.colors[13].g = 0x055; _sysPalette.colors[13].b = 0x0FF; + _sysPalette.colors[14].r = 0x0FF; _sysPalette.colors[14].g = 0x0FF; _sysPalette.colors[14].b = 0x055; + _sysPalette.colors[15].r = 0x0FF; _sysPalette.colors[15].g = 0x0FF; _sysPalette.colors[15].b = 0x0FF; + for (i = 0; i <= 15; i++) { + _sysPalette.colors[i].used = 1; + } + for (i = 16; i <= 254; i++) { + _sysPalette.colors[i].r = 200; + _sysPalette.colors[i].used = 1; + } + setOnScreen(); +} + +bool SciGuiPalette::setFromResource(int16 resourceNo, int16 flag) { + Resource *palResource = _s->resMan->findResource(ResourceId(kResourceTypePalette, resourceNo), 0); + GuiPalette palette; + + if (palResource) { + createFromData(palResource->data, &palette); + set(&palette, 2); + return true; + } + return false; +} + +void SciGuiPalette::set(GuiPalette *sciPal, int16 flag) { + uint32 systime = _sysPalette.timestamp; + if (flag == 2 || sciPal->timestamp != systime) { + merge(sciPal, &_sysPalette, flag); + sciPal->timestamp = _sysPalette.timestamp; + if (_gui->_picNotValid == 0 && systime != _sysPalette.timestamp) + setOnScreen(); + } +} + +void SciGuiPalette::merge(GuiPalette *pFrom, GuiPalette *pTo, uint16 flag) { + uint16 res; + int i,j; + // colors 0 (black) and 255 (white) are not affected by merging + for (i = 1 ; i < 255; i++) { + if (!pFrom->colors[i].used)// color is not used - so skip it + continue; + // forced palette merging or dest color is not used yet + if (flag == 2 || (!pTo->colors[i].used)) { + pTo->colors[i].used = pFrom->colors[i].used; + pTo->colors[i].r = pFrom->colors[i].r; + pTo->colors[i].g = pFrom->colors[i].g; + pTo->colors[i].b = pFrom->colors[i].b; + pFrom->mapping[i] = i; + continue; + } + // check if exact color could be matched + res = matchColor(pTo, pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b); + if (res & 0x8000) { // exact match was found + pFrom->mapping[i] = res & 0xFF; + continue; + } + // no exact match - see if there is an unused color + for (j = 1; j < 256; j++) + if (!pTo->colors[j].used) { + pTo->colors[j].used = pFrom->colors[i].used; + pTo->colors[j].r = pFrom->colors[i].r; + pTo->colors[j].g = pFrom->colors[i].g; + pTo->colors[j].b = pFrom->colors[i].b; + pFrom->mapping[i] = j; + break; + } + // if still no luck - set an approximate color + if (j == 256) { + pFrom->mapping[i] = res & 0xFF; + pTo->colors[res & 0xFF].used |= 0x10; + } + } + pTo->timestamp = _gui->getTimeTicks(); +} + +uint16 SciGuiPalette::matchColor(GuiPalette*pPal, byte r, byte g, byte b) { + byte found = 0xFF; + int diff = 0x2FFFF, cdiff; + int16 dr,dg,db; + + for (int i = 0; i < 256; i++) { + if ((!pPal->colors[i].used)) + continue; + dr = pPal->colors[i].r - r; + dg = pPal->colors[i].g - g; + db = pPal->colors[i].b - b; +// minimum squares match + cdiff = _clrPowers[ABS(dr)] + _clrPowers[ABS(dg)] + _clrPowers[ABS(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; + } + } + return found; +} + +void SciGuiPalette::getSys(GuiPalette*pal) { + if (pal != &_sysPalette) + memcpy(pal, &_sysPalette,sizeof(GuiPalette)); +} + +void SciGuiPalette::setOnScreen() { +// if (pal != &_sysPalette) +// memcpy(&_sysPalette,pal,sizeof(GuiPalette)); + _screen->setPalette(&_sysPalette); +} + +void SciGuiPalette::setIntensity(int fromColor, int toColor, int intensity, GuiPalette *destPalette) { + memset(destPalette->intensity + fromColor, intensity, toColor - fromColor); +} + +void SciGuiPalette::animate(byte fromColor, byte toColor, int speed) { + GuiColor col; + int len = toColor - fromColor - 1; + uint32 now = _gui->getTimeTicks(); + // search for sheduled animations with the same 'from' value + int sz = _palSchedules.size(); + for (int i = 0; i < sz; i++) { + if (_palSchedules[i].from == fromColor) { + if (_palSchedules[i].schedule < now) { + if (speed > 0) { + col = _sysPalette.colors[fromColor]; + memmove(&_sysPalette.colors[fromColor], &_sysPalette.colors[fromColor + 1], len * sizeof(GuiColor)); + _sysPalette.colors[toColor - 1] = col; + } else { + col = _sysPalette.colors[toColor - 1]; + memmove(&_sysPalette.colors[fromColor + 1], &_sysPalette.colors[fromColor], len * sizeof(GuiColor)); + _sysPalette.colors[fromColor] = col; + } + // removing schedule + _palSchedules.remove_at(i); + } + setOnScreen(); + return; + } + } + // adding a new schedule + GuiPalSchedule sched; + sched.from = fromColor; + sched.schedule = now + ABS(speed); + _palSchedules.push_back(sched); +} + +} // End of namespace Sci |