aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sword1/animation.cpp125
-rw-r--r--engines/sword1/animation.h11
2 files changed, 121 insertions, 15 deletions
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index d55a08293e..be9e02f64f 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -72,7 +72,7 @@ MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::
_decoderType = decoderType;
_decoder = decoder;
- _white = 255;
+ _c1Color = _c2Color = _c3Color = _c4Color = 255;
_black = 0;
}
@@ -127,8 +127,16 @@ bool MoviePlayer::load(uint32 id) {
warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);
continue;
}
-
- _movieTexts.push_back(MovieText(startFrame, endFrame, ptr));
+
+ int color = 0;
+ if (*ptr == '@') {
+ ++ptr;
+ color = strtoul(ptr, const_cast<char **>(&ptr), 10);
+ while (*ptr && isspace(static_cast<unsigned char>(*ptr)))
+ ptr++;
+ }
+
+ _movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
lastEnd = endFrame;
}
f.close();
@@ -188,6 +196,7 @@ void MoviePlayer::performPostProcessing(byte *screen) {
_textHeight = _resMan->toUint16(frame->height);
_textX = 320 - _textWidth / 2;
_textY = 420 - _textHeight;
+ _textColor = _movieTexts.front()._color;
}
if (_decoder->getCurFrame() == _movieTexts.front()._endFrame) {
_textMan->releaseText(2, false);
@@ -209,7 +218,7 @@ void MoviePlayer::performPostProcessing(byte *screen) {
dst[x] = findBlackPalIndex();
break;
case LETTER_COL:
- dst[x] = findWhitePalIndex();
+ dst[x] = findTextColorPalIndex();
break;
}
}
@@ -258,12 +267,29 @@ bool MoviePlayer::playVideo() {
if (_decoder->hasDirtyPalette()) {
_decoder->setSystemPalette();
- uint32 maxWeight = 0;
uint32 minWeight = 0xFFFFFFFF;
uint32 weight;
+ float c1Weight = 1e+30;
+ float c2Weight = 1e+30;
+ float c3Weight = 1e+30;
+ float c4Weight = 1e+30;
byte r, g, b;
+ float h, s, v, hd, hsvWeight;
const byte *palette = _decoder->getPalette();
+
+ // Color comparaison for the subtitles colors is done in HSL
+ // C1 color is used for George and is almost white (R = 248, G = 252, B = 248)
+ const float h1 = 0.333333f, s1 = 0.02f, v1 = 0.99f;
+
+ // C2 color is used for George as a narrator and is grey (R = 184, G = 188, B = 184)
+ const float h2 = 0.333333f, s2 = 0.02f, v2 = 0.74f;
+
+ // C3 color is used for Nicole and is rose (R = 200, G = 120, B = 184)
+ const float h3 = 0.866667f, s3 = 0.4f, v3 = 0.78f;
+
+ // C4 color is used for Maguire and is blue (R = 80, G = 152, B = 184)
+ const float h4 = 0.55f, s4 = 0.57f, v4 = 0.72f;
for (int i = 0; i < 256; i++) {
r = *palette++;
@@ -272,15 +298,55 @@ bool MoviePlayer::playVideo() {
weight = 3 * r * r + 6 * g * g + 2 * b * b;
- if (weight >= maxWeight) {
- maxWeight = weight;
- _white = i;
- }
-
if (weight <= minWeight) {
minWeight = weight;
_black = i;
}
+
+ convertColor(r, g, b, h, s, v);
+
+ // C1 color
+ // It is almost achromatic (very low saturation) so the hue as litle impact on the color.
+ // Therefore use a low weight on hue and high weight on saturation.
+ hd = h - h1;
+ hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f;
+ hsvWeight = 1.0f * hd * hd + 4.0f * (s - s1) * (s - s1) + 3.0f * (v - v1) * (v - v1);
+ if (hsvWeight <= c1Weight) {
+ c1Weight = hsvWeight;
+ _c1Color = i;
+ }
+
+ // C2 color
+ // Also an almost achromatic color so use the same weights as for C1 color.
+ hd = h - h2;
+ hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f;
+ hsvWeight = 1.0f * hd * hd + 4.0f * (s - s2) * (s - s2) + 3.0f * (v - v2) * (v - v2);
+ if (hsvWeight <= c2Weight) {
+ c2Weight = hsvWeight;
+ _c2Color = i;
+ }
+
+ // C3 color
+ // A light rose. Use a high weight on the hue to get a rose.
+ // The color is a bit gray and the saturation has not much impact so use a low weight.
+ hd = h - h3;
+ hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f;
+ hsvWeight = 4.0f * hd * hd + 1.0f * (s - s3) * (s - s3) + 2.0f * (v - v3) * (v - v3);
+ if (hsvWeight <= c3Weight) {
+ c3Weight = hsvWeight;
+ _c3Color = i;
+ }
+
+ // C4 color
+ // Blue. Use a hight weight on the hue to get a blue.
+ // The color is darker and more saturated than C3 and the saturation has more impact.
+ hd = h - h4;
+ hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f;
+ hsvWeight = 5.0f * hd * hd + 3.0f * (s - s4) * (s - s4) + 2.0f * (v - v4) * (v - v4);
+ if (hsvWeight <= c4Weight) {
+ c4Weight = hsvWeight;
+ _c4Color = i;
+ }
}
}
@@ -304,9 +370,44 @@ bool MoviePlayer::playVideo() {
byte MoviePlayer::findBlackPalIndex() {
return _black;
}
+
+byte MoviePlayer::findTextColorPalIndex() {
+ switch (_textColor) {
+ case 1:
+ return _c1Color;
+ case 2:
+ return _c2Color;
+ case 3:
+ return _c3Color;
+ case 4:
+ return _c4Color;
+ }
+ return _c1Color;
+}
-byte MoviePlayer::findWhitePalIndex() {
- return _white;
+void MoviePlayer::convertColor(byte r, byte g, byte b, float &h, float &s, float &v) {
+ float varR = r / 255.0f;
+ float varG = g / 255.0f;
+ float varB = b / 255.0f;
+
+ float min = MIN(varR, MIN(varG, varB));
+ float max = MAX(varR, MAX(varG, varB));
+
+ v = max;
+ float d = max - min;
+ s = max == 0.0f ? 0.0f : d / max;
+
+ if (min == max) {
+ h = 0.0f; // achromatic
+ } else {
+ if (max == varR)
+ h = (varG - varB) / d + (varG < varB ? 6.0f : 0.0f);
+ else if (max == varG)
+ h = (varB - varR) / d + 2.0f;
+ else
+ h = (varR - varG) / d + 4.0f;
+ h /= 6.0f;
+ }
}
DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index 1c03c66342..c436607211 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -45,11 +45,13 @@ class MovieText {
public:
uint16 _startFrame;
uint16 _endFrame;
+ uint16 _color;
Common::String _text;
- MovieText(int startFrame, int endFrame, const Common::String &text) {
+ MovieText(int startFrame, int endFrame, const Common::String &text, int color) {
_startFrame = startFrame;
_endFrame = endFrame;
_text = text;
+ _color = color;
}
};
@@ -80,7 +82,9 @@ protected:
OSystem *_system;
Common::List<MovieText> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
- byte _white, _black;
+ int _textColor;
+ byte _black;
+ byte _c1Color, _c2Color, _c3Color, _c4Color;
DecoderType _decoderType;
Video::VideoDecoder *_decoder;
@@ -91,7 +95,8 @@ protected:
void performPostProcessing(byte *screen);
byte findBlackPalIndex();
- byte findWhitePalIndex();
+ byte findTextColorPalIndex();
+ void convertColor(byte r, byte g, byte b, float &h, float &s, float &v);
};
MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system);