aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/gfx.cpp108
1 files changed, 64 insertions, 44 deletions
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index a56de5ed4f..aa74fa30bd 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -2557,62 +2557,82 @@ void Scumm::palManipulate()
}
}
-void Scumm::unkRoomFunc3(int unk1, int unk2, int rfact, int gfact, int bfact)
+void Scumm::unkRoomFunc3(int palstart, int palend, int rfact, int gfact, int bfact)
{
- byte *pal = _currentPalette;
+ byte *basepal = getPalettePtr();
+ byte *pal = basepal;
+ byte *compareptr;
byte *table = _shadowPalette;
int i;
- warning("unkRoomFunc3(%d,%d,%d,%d,%d): not fully implemented", unk1, unk2, rfact, gfact, bfact);
-
- // TODO - correctly implement this function (see also patch #588501)
- //
- // Some "typical" examples of how this function is being invoked in real life:
- //
- // 1)
- // unkRoomFunc3(16, 255, 200, 200, 200)
- //
- // FOA: Sets up the colors for the boat and submarine shadows in the
- // diving scene. Are the shadows too light? Maybe unk1 is used to
- // darken the colors?
- //
- // 2)
- // unkRoomFunc3(0, 255, 700, 700, 700)
- //
- // FOA: Sets up the colors for the subway car headlight when it first
- // goes on. This seems to work ok.
- //
- // 3)
- // unkRoomFunc3(160, 191, 300, 300, 300)
- // unkRoomFunc3(160, 191, 289, 289, 289)
- // ...
- // unkRoomFunc3(160, 191, 14, 14, 14)
- // unkRoomFunc3(160, 191, 3, 3, 3)
- //
- // 4)
- // FOA: Sets up the colors for the subway car headlight for the later
- // half of the trip, where it fades out. This currently doesn't work
- // at all. The colors are too dark to be brightened. At first I thought
- // unk1 and unk2 were used to tell which color interval to manipulate,
- // but as far as I can tell the colors 160-191 aren't used at all to
- // draw the light, that can't be it. Apparently unk1 and/or unk2 are
- // used to brighten the colors.
+ // This is a correction of the patch supplied for BUG #588501.
+ // It has been tested in all four known rooms where unkRoomFunc3 is used:
//
- // 5)
- // unkRoomFunc3(16,255,500,500,500)
+ // 1) FOA Room 53: subway departing Knossos for Atlantis.
+ // 2) FOA Room 48: subway crashing into the Atlantis entrance area
+ // 3) FOA Room 82: boat/sub shadows while diving near Thera
+ // 4) FOA Room 23: the big machine room inside Atlantis
//
- // FOA: Used in the Inner Sanctum after you activated the machine using the
- // stone discs (briefly before the Nazis arrive). No idea at all if it is
- // right here; also note that palManipulateInit() is called at the same time.
+ // The implementation behaves well in all tests.
+ // Pixel comparisons show that the resulting palette entries being
+ // derived from the shadow palette generated here occassionally differ
+ // slightly from the ones derived in the LEC executable.
+ // Not sure yet why, but the differences are VERY minor.
//
- //
-
+ // There seems to be no explanation for why this function is called
+ // from within Room 23 (the big machine), as it has no shadow effects
+ // and thus doesn't result in any visual differences.
+
for (i = 0; i <= 255; i++) {
int r = (int) (*pal++ * rfact) >> 8;
int g = (int) (*pal++ * gfact) >> 8;
int b = (int) (*pal++ * bfact) >> 8;
- *table++ = remapPaletteColor(r, g, b, (uint) -1);
+ // The following functionality is similar to remapPaletteColor, except
+ // 1) we have to work off the original CLUT rather than the current palette, and
+ // 2) the target shadow palette entries must be bounded to the upper and lower
+ // bounds provided by the opcode. (This becomes significant in Room 48, but
+ // is not an issue in all other known case studies.)
+ int j;
+ int ar, ag, ab;
+ uint sum, diff, bestsum, bestitem = 0;
+ compareptr = basepal + palstart * 3;
+
+ if (r > 255)
+ r = 255;
+ if (g > 255)
+ g = 255;
+ if (b > 255)
+ b = 255;
+
+ bestsum = (uint) - 1;
+
+ r &= ~3;
+ g &= ~3;
+ b &= ~3;
+
+ for (j = palstart; j <= palend; j++, compareptr += 3) {
+ ar = compareptr[0] & ~3;
+ ag = compareptr[1] & ~3;
+ ab = compareptr[2] & ~3;
+ if (ar == r && ag == g && ab == b) {
+ bestitem = j;
+ break;
+ }
+
+ diff = ar - r;
+ sum = diff * diff * 3;
+ diff = ag - g;
+ sum += diff * diff * 6;
+ diff = ab - b;
+ sum += diff * diff * 2;
+
+ if (sum < bestsum) {
+ bestsum = sum;
+ bestitem = j;
+ }
+ }
+ *table++ = bestitem;
}
}