aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2012-07-24 22:34:03 +0300
committerFilippos Karapetis2012-07-24 22:34:46 +0300
commit6f351302040be620aa039a7c605f3c23463b27db (patch)
tree381b86f3bb2424f6f82e18d59056c92fbbec6083
parentd83764f05591ab552316fb6aa59ac92abc7c4680 (diff)
downloadscummvm-rg350-6f351302040be620aa039a7c605f3c23463b27db.tar.gz
scummvm-rg350-6f351302040be620aa039a7c605f3c23463b27db.tar.bz2
scummvm-rg350-6f351302040be620aa039a7c605f3c23463b27db.zip
SCI: More work on color remapping
More transparency/color mapping effects are now working (e.g. the flashlight at the Gedde tomb in GK1, the rays of light at Schloss Ritter in GK1, the torch in the QFG4 demo and the shadows in QFG4, PQ4 and KQ7)
-rw-r--r--engines/sci/engine/kgraphics.cpp17
-rw-r--r--engines/sci/engine/kgraphics32.cpp47
-rw-r--r--engines/sci/graphics/palette.cpp64
-rw-r--r--engines/sci/graphics/palette.h12
-rw-r--r--engines/sci/graphics/view.cpp9
5 files changed, 97 insertions, 52 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index bd78c56416..55c0202048 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -1228,15 +1228,18 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
switch (operation) {
case 0: { // remap by percent
uint16 percent = argv[1].toUint16();
- g_sci->_gfxPalette->toggleRemap(true);
- g_sci->_gfxPalette->setRemappingPercent(percent);
+ g_sci->_gfxPalette->toggleRemapping(true);
+ g_sci->_gfxPalette->resetRemapping();
+ g_sci->_gfxPalette->setRemappingPercent(254, percent);
}
break;
- case 1: { // set remapping base
- //int16 unk1 = argv[1].toSint16();
- //int16 unk2 = argv[2].toSint16();
- //int16 unk3 = argv[3].toSint16();
- kStub(s, argc, argv);
+ case 1: { // remap by range
+ uint16 from = argv[1].toUint16();
+ uint16 to = argv[2].toUint16();
+ uint16 base = argv[3].toUint16();
+ g_sci->_gfxPalette->toggleRemapping(true);
+ g_sci->_gfxPalette->resetRemapping();
+ g_sci->_gfxPalette->setRemappingRange(254, from, to, base);
}
break;
case 2: // turn remapping off (unused)
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 1b7b628e7d..7240308f4a 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -737,46 +737,44 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
uint16 operation = argv[0].toUint16();
switch (operation) {
- case 0: { // Set remapping to base. 0 turns remapping off.
+ case 0: { // turn remapping off
int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
- if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning
- warning("kRemapColors: Set remapping to base %d", base);
+ if (base > 0)
+ warning("kRemapColors(0) called with base %d", base);
+ g_sci->_gfxPalette->toggleRemapping(false);
+ g_sci->_gfxPalette->resetRemapping();
}
- // TODO: Don't turn remapping off always
- g_sci->_gfxPalette->toggleRemap(false);
- g_sci->_gfxPalette->setRemappingPercent(0);
break;
- case 1: { // set remapping base
- //int16 unk1 = argv[1].toSint16();
- //int16 unk2 = argv[2].toSint16();
- //int16 unk3 = argv[3].toSint16();
- //uint16 unk4 = argv[4].toUint16();
- //uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
- kStub(s, argc, argv);
+ case 1: { // remap by range
+ uint16 color = argv[1].toUint16();
+ uint16 from = argv[2].toUint16();
+ uint16 to = argv[3].toUint16();
+ uint16 base = argv[4].toUint16();
+ uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
+ if (unk5 > 0)
+ warning("kRemapColors(1) called with 6 parameters, unknown parameter is %d", unk5);
+ g_sci->_gfxPalette->toggleRemapping(true);
+ g_sci->_gfxPalette->setRemappingRange(color, from, to, base);
}
break;
case 2: { // remap by percent
- // TODO: Use the color index. The -10 offset is wrong.
- /*int16 color = argv[1].toSint16();
- if (color >= 10)
- color -= 10;*/
+ uint16 color = argv[1].toUint16();
uint16 percent = argv[2].toUint16(); // 0 - 100
if (argc >= 4)
warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
- g_sci->_gfxPalette->toggleRemap(true);
- g_sci->_gfxPalette->setRemappingPercent(percent);
+ g_sci->_gfxPalette->toggleRemapping(true);
+ g_sci->_gfxPalette->setRemappingPercent(color, percent);
}
break;
case 3: { // remap to gray
- // NOTE: This adjusts the alpha value of a specific color, and it operates on
- // an RGBA palette
int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10
int16 percent = argv[2].toSint16(); // 0 - 100
uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3);
+ // TODO
}
break;
- case 4: { // unknown
+ case 4: { // remap to percent gray
//int16 unk1 = argv[1].toSint16();
//uint16 unk2 = argv[2].toUint16();
//uint16 unk3 = argv[3].toUint16();
@@ -784,10 +782,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
kStub(s, argc, argv);
}
break;
- case 5: { // set color intensity
- // TODO: This isn't right, it should be setting a mapping table instead.
- // For PQ4, we can emulate this with kernelSetIntensity(). In QFG4, this
- // won't do.
+ case 5: { // don't map to range
//int16 mapping = argv[1].toSint16();
uint16 intensity = argv[2].toUint16();
// HACK for PQ4
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index f16d607a29..b5154ef860 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -102,7 +102,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen)
}
_remapOn = false;
- _remappingPercent = 0;
+ resetRemapping();
}
GfxPalette::~GfxPalette() {
@@ -332,24 +332,62 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) {
}
}
-bool GfxPalette::isRemapColor(byte color) {
- // TODO: Expand this for SCI32 (more than one remap color can be set).
- // Now, it is assumed that colors 253 and 254 are the remap colors.
- return _remapOn && (color == 253 || color == 254);
+bool GfxPalette::isRemapMask(byte color) {
+ return (_remapOn && (color >= _remappingMaskFrom && color <= _remappingMaskTo));
+}
+
+void GfxPalette::resetRemapping() {
+ _remappingMaskFrom = 0;
+ _remappingMaskTo = 0;
+ _remappingPercentToSet = 0;
+
+ for (int i = 0; i < 256; i++) {
+ _remappingTable[i] = i;
+ }
+}
+
+void GfxPalette::setRemappingPercent(byte color, byte percent) {
+ // We need to defer the setup of the remapping table until something is
+ // shown on screen, otherwise kernelFindColor() won't find correct
+ // colors. The actual setup of the remapping table will be performed in
+ // remapColor().
+ _remappingPercentToSet = percent;
+
+ if (_remappingMaskFrom > color || _remappingMaskFrom == 0)
+ _remappingMaskFrom = color;
+ if (_remappingMaskTo < color)
+ _remappingMaskTo = color;
+}
+
+void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) {
+ for (int i = from; i <= to; i++) {
+ _remappingTable[i] = i + base;
+ }
+
+ if (_remappingMaskFrom > color || _remappingMaskFrom == 0)
+ _remappingMaskFrom = color;
+ if (_remappingMaskTo < color)
+ _remappingMaskTo = color;
}
byte GfxPalette::remapColor(byte color) {
assert(_remapOn);
- // TODO: Change this to use a table instead, like the original.
- if (_remappingPercent) {
- byte r = _sysPalette.colors[color].r * _remappingPercent / 100;
- byte g = _sysPalette.colors[color].g * _remappingPercent / 100;
- byte b = _sysPalette.colors[color].b * _remappingPercent / 100;
- return kernelFindColor(r, g, b);
- } else {
- return color;
+ // Check if we need to set remapping by percent. This can only be
+ // performed when something is shown on screen, so that the screen
+ // palette is set up and kernelFindColor() can work correctly.
+ if (_remappingPercentToSet) {
+ for (int i = 0; i < 256; i++) {
+ byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100;
+ byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100;
+ byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100;
+ _remappingTable[i] = kernelFindColor(r, g, b);
+ }
+
+ _remappingPercentToSet = 0;
}
+
+ return _remappingTable[color];
}
bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) {
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 6774094810..372f3c7090 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -53,9 +53,11 @@ public:
void getSys(Palette *pal);
uint16 getTotalColorCount() const { return _totalScreenColors; }
- void toggleRemap(bool remap) { _remapOn = remap; }
- void setRemappingPercent(uint16 percent) { _remappingPercent = percent; }
- bool isRemapColor(byte color);
+ void toggleRemapping(bool remap) { _remapOn = remap; }
+ void resetRemapping();
+ void setRemappingPercent(byte color, byte percent);
+ void setRemappingRange(byte color, byte from, byte to, byte base);
+ bool isRemapMask(byte color);
byte remapColor(byte color);
void setOnScreen();
@@ -129,7 +131,9 @@ private:
uint16 _totalScreenColors;
bool _remapOn;
- uint16 _remappingPercent;
+ byte _remappingTable[256];
+ uint16 _remappingMaskFrom, _remappingMaskTo;
+ uint16 _remappingPercentToSet;
void loadMacIconBarPalette();
byte *_macClut;
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index ae135d141c..f68ed1443a 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -742,7 +742,7 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
const int y2 = clipRectTranslated.top + y;
if (!upscaledHires) {
if (priority >= _screen->getPriority(x2, y2)) {
- if (!_palette->isRemapColor(palette->mapping[color])) {
+ if (!_palette->isRemapMask(palette->mapping[color])) {
_screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
} else {
byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2));
@@ -857,7 +857,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect,
const int x2 = clipRectTranslated.left + x;
const int y2 = clipRectTranslated.top + y;
if (color != clearKey && priority >= _screen->getPriority(x2, y2)) {
- _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
+ if (!_palette->isRemapMask(palette->mapping[color])) {
+ _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
+ } else {
+ byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2));
+ _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0);
+ }
}
}
}