aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/gfx.cpp112
-rw-r--r--scumm/script_v8.cpp7
-rw-r--r--scumm/scumm.h1
3 files changed, 114 insertions, 6 deletions
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index 68a14f76fe..dc97567ae7 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -2821,6 +2821,118 @@ void Scumm::darkenPalette(int redScale, int greenScale, int blueScale, int start
}
}
+static double value(double n1, double n2, double hue)
+{
+ if (hue > 360.0)
+ hue = hue - 360.0;
+ else if (hue < 0.0)
+ hue = hue + 360.0;
+
+ if (hue < 60.0)
+ return n1 + (n2 - n1) * hue / 60.0;
+ if (hue < 180.0)
+ return n2;
+ if (hue < 240.0)
+ return n1 + (n2 - n1) * (240.0 - hue) / 60.0;
+ return n1;
+}
+
+void Scumm::desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor)
+{
+ // This function scales the HSL (Hue, Saturation and Lightness)
+ // components of the palette colours. It's used in CMI when Guybrush
+ // walks from the beach towards the swamp.
+ //
+ // I don't know if this function is correct, but the output seems to
+ // match the original fairly closely.
+ //
+ // FIXME: Rewrite using integer arithmetics only?
+
+ if (startColor <= endColor) {
+ byte *cptr, *cur;
+ int j;
+
+ cptr = getPalettePtr() + startColor * 3;
+ cur = _currentPalette + startColor * 3;
+
+ for (j = startColor; j <= endColor; j++) {
+ double R, G, B;
+ double H, S, L;
+ double min, max;
+ int red, green, blue;
+
+ R = ((double) *cptr++) / 255.0;
+ G = ((double) *cptr++) / 255.0;
+ B = ((double) *cptr++) / 255.0;
+
+ // RGB to HLS (Foley and VanDam)
+
+ min = MIN(R, MIN(G, B));
+ max = MAX(R, MAX(G, B));
+
+ L = (max + min) / 2.0;
+
+ if (max != min) {
+ if (L <= 0.5)
+ S = (max - min) / (max + min);
+ else
+ S = (max - min) / (2.0 - max - min);
+
+ if (R == max)
+ H = (G - B) / (max - min);
+ else if (G == max)
+ H = 2.0 + (B - R) / (max - min);
+ else
+ H = 4.0 + (R - G) / (max - min);
+
+ H = H * 60.0;
+ if (H < 0.0)
+ H = H + 360.0;
+ } else {
+ S = 0.0;
+ H = 0.0; // undefined
+ }
+
+ // Scale the result
+
+ H = (H * hueScale) / 255.0;
+ S = (S * satScale) / 255.0;
+ L = (L * lightScale) / 255.0;
+
+ // HLS to RGB (Foley and VanDam)
+
+ double m1, m2;
+
+ if (min != max) {
+ if (L <= 0.5)
+ m2 = L * (1 + S);
+ else
+ m2 = L + S - L * S;
+
+ m1 = 2.0 * L - m2;
+
+ R = value(m1, m2, H + 120);
+ G = value(m1, m2, H);
+ B = value(m1, m2, H - 120);
+ } else {
+ R = L;
+ G = L;
+ B = L;
+ }
+
+ red = (int) (255.0 * R + 0.5);
+ green = (int) (255.0 * G + 0.5);
+ blue = (int) (255.0 * B + 0.5);
+
+ *cur++ = red;
+ *cur++ = green;
+ *cur++ = blue;
+ }
+
+ setDirtyColors(startColor, endColor);
+ }
+}
+
int Scumm::remapPaletteColor(int r, int g, int b, uint threshold) {
int i;
int ar, ag, ab;
diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp
index 349528d679..1c651ccbc7 100644
--- a/scumm/script_v8.cpp
+++ b/scumm/script_v8.cpp
@@ -998,12 +998,7 @@ void Scumm_v8::o8_roomOps() {
c = pop();
b = pop();
a = pop();
- // FIXME - this probably has the same format as for darkenPalette:
- // thre values for R, G, B and a start/end palette range to modify.
- // Now, how on earth does on modify the saturation of a single color channel?
- // Change the hue/saturation of a color, no problem, I know how to do that,
- // but for only a channel alone, I don't even know what that should mean... :-/
-// warning("o8_roomOps: SO_ROOM_SATURATION(%d, %d, %d, %d, %d)", a, b, c, d, e);
+ desaturatePalette(a, b, c, d, e);
break;
default:
error("o8_roomOps: default case 0x%x", subOp);
diff --git a/scumm/scumm.h b/scumm/scumm.h
index 63450f30ee..3b035ed391 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -803,6 +803,7 @@ public:
void setupShadowPalette(int slot, int redScale, int greenScale, int blueScale, int startColor, int endColor);
void setupShadowPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor);
void darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor);
+ void desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor);
void setCursor(int cursor);
void setCursorImg(uint img, uint room, uint imgindex);