aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2016-09-28 13:05:50 -0500
committerColin Snover2016-09-29 19:39:16 -0500
commite412eaffbc47e5087401dc57912863bd59dcbf48 (patch)
tree0a5afb6caae9ce9d759a39b389270e620c58bb0d /engines/sci
parent7ad9418583a6a5a15356d1ee6920d2cfa56f7d4d (diff)
downloadscummvm-rg350-e412eaffbc47e5087401dc57912863bd59dcbf48.tar.gz
scummvm-rg350-e412eaffbc47e5087401dc57912863bd59dcbf48.tar.bz2
scummvm-rg350-e412eaffbc47e5087401dc57912863bd59dcbf48.zip
SCI32: Clean up and document GfxPalette32
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/kgraphics32.cpp30
-rw-r--r--engines/sci/graphics/celobj32.cpp2
-rw-r--r--engines/sci/graphics/palette32.cpp499
-rw-r--r--engines/sci/graphics/palette32.h451
4 files changed, 535 insertions, 447 deletions
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index cceb710f33..49215b27f4 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -961,17 +961,17 @@ reg_t kPaletteSetGamma(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) {
- uint16 fromColor = argv[0].toUint16();
- uint16 toColor = argv[1].toUint16();
- uint16 percent = argv[2].toUint16();
+ const uint16 fromColor = argv[0].toUint16();
+ const uint16 toColor = argv[1].toUint16();
+ const uint16 percent = argv[2].toUint16();
g_sci->_gfxPalette32->setFade(percent, fromColor, toColor);
return s->r_acc;
}
reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[0].toUint16();
- int time = argc > 1 ? argv[1].toSint16() * 60 : 0;
- int16 percent = argc > 2 ? argv[2].toSint16() : 100;
+ const GuiResourceId paletteId = argv[0].toUint16();
+ const int32 time = argc > 1 ? argv[1].toSint16() * 60 : 0;
+ const int16 percent = argc > 2 ? argv[2].toSint16() : 100;
int16 fromColor;
int16 toColor;
@@ -987,9 +987,9 @@ reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPalVarySetPercent(EngineState *s, int argc, reg_t *argv) {
- int time = argc > 0 ? argv[0].toSint16() * 60 : 0;
- int16 percent = argc > 1 ? argv[1].toSint16() : 0;
- g_sci->_gfxPalette32->setVaryPercent(percent, time, -1, -1);
+ const int32 time = argc > 0 ? argv[0].toSint16() * 60 : 0;
+ const int16 percent = argc > 1 ? argv[1].toSint16() : 0;
+ g_sci->_gfxPalette32->setVaryPercent(percent, time);
return s->r_acc;
}
@@ -1003,31 +1003,31 @@ reg_t kPalVaryOff(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPalVaryMergeTarget(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[0].toUint16();
+ const GuiResourceId paletteId = argv[0].toUint16();
g_sci->_gfxPalette32->kernelPalVaryMergeTarget(paletteId);
return make_reg(0, g_sci->_gfxPalette32->getVaryPercent());
}
reg_t kPalVarySetTime(EngineState *s, int argc, reg_t *argv) {
- int time = argv[0].toSint16() * 60;
+ const int32 time = argv[0].toSint16() * 60;
g_sci->_gfxPalette32->setVaryTime(time);
return s->r_acc;
}
reg_t kPalVarySetTarget(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[0].toUint16();
+ const GuiResourceId paletteId = argv[0].toUint16();
g_sci->_gfxPalette32->kernelPalVarySetTarget(paletteId);
return make_reg(0, g_sci->_gfxPalette32->getVaryPercent());
}
reg_t kPalVarySetStart(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[0].toUint16();
+ const GuiResourceId paletteId = argv[0].toUint16();
g_sci->_gfxPalette32->kernelPalVarySetStart(paletteId);
return make_reg(0, g_sci->_gfxPalette32->getVaryPercent());
}
reg_t kPalVaryMergeStart(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[0].toUint16();
+ const GuiResourceId paletteId = argv[0].toUint16();
g_sci->_gfxPalette32->kernelPalVaryMergeStart(paletteId);
return make_reg(0, g_sci->_gfxPalette32->getVaryPercent());
}
@@ -1043,7 +1043,6 @@ reg_t kPalCycleSetCycle(EngineState *s, int argc, reg_t *argv) {
const uint16 toColor = argv[1].toUint16();
const int16 direction = argv[2].toSint16();
const uint16 delay = argc > 3 ? argv[3].toUint16() : 0;
-
g_sci->_gfxPalette32->setCycle(fromColor, toColor, direction, delay);
return s->r_acc;
}
@@ -1051,7 +1050,6 @@ reg_t kPalCycleSetCycle(EngineState *s, int argc, reg_t *argv) {
reg_t kPalCycleDoCycle(EngineState *s, int argc, reg_t *argv) {
const uint16 fromColor = argv[0].toUint16();
const int16 speed = argc > 1 ? argv[1].toSint16() : 1;
-
g_sci->_gfxPalette32->doCycle(fromColor, speed);
return s->r_acc;
}
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index 5aa6ea3fb3..75140527d0 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -568,7 +568,7 @@ uint8 CelObj::readPixel(uint16 x, const uint16 y, bool mirrorX) const {
void CelObj::submitPalette() const {
if (_hunkPaletteOffset) {
- HunkPalette palette(getResPointer() + _hunkPaletteOffset);
+ const HunkPalette palette(getResPointer() + _hunkPaletteOffset);
g_sci->_gfxPalette32->submit(palette);
}
}
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 135badb5a2..6b719f8e86 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -52,7 +52,7 @@ HunkPalette::HunkPalette(byte *rawPalette) :
}
}
-void HunkPalette::setVersion(const uint32 version) {
+void HunkPalette::setVersion(const uint32 version) const {
if (_numPalettes != _data[10]) {
error("Invalid HunkPalette");
}
@@ -93,9 +93,9 @@ const Palette HunkPalette::toPalette() const {
if (_numPalettes) {
const EntryHeader header = getEntryHeader();
- byte *data = getPalPointer() + kEntryHeaderSize;
+ const byte *data = getPalPointer() + kEntryHeaderSize;
- int16 end = header.startColor + header.numColors;
+ const int16 end = header.startColor + header.numColors;
assert(end <= 256);
if (header.sharedUsed) {
@@ -118,20 +118,19 @@ const Palette HunkPalette::toPalette() const {
return outPalette;
}
-
#pragma mark -
#pragma mark GfxPalette32
GfxPalette32::GfxPalette32(ResourceManager *resMan)
: _resMan(resMan),
+
// Palette versioning
_version(1),
_needsUpdate(false),
_currentPalette(),
_sourcePalette(),
_nextPalette(),
- // Clut
- _clutTable(nullptr),
+
// Palette varying
_varyStartPalette(nullptr),
_varyTargetPalette(nullptr),
@@ -142,6 +141,7 @@ GfxPalette32::GfxPalette32(ResourceManager *resMan)
_varyDirection(0),
_varyTargetPercent(0),
_varyNumTimesPaused(0),
+
// Palette cycling
_cyclers(),
_cycleMap() {
@@ -161,44 +161,6 @@ GfxPalette32::~GfxPalette32() {
cycleAllOff();
}
-inline void mergePaletteInternal(Palette *const to, const Palette *const from) {
- // The last color is always white, so it is not copied.
- // (Some palettes try to set the last color, which causes
- // churning in the palettes when they are merged)
- for (int i = 0, len = ARRAYSIZE(to->colors) - 1; i < len; ++i) {
- if (from->colors[i].used) {
- to->colors[i] = from->colors[i];
- }
- }
-}
-
-void GfxPalette32::submit(const Palette &palette) {
- const Palette oldSourcePalette(_sourcePalette);
- mergePaletteInternal(&_sourcePalette, &palette);
-
- if (!_needsUpdate && _sourcePalette != oldSourcePalette) {
- ++_version;
- _needsUpdate = true;
- }
-}
-
-void GfxPalette32::submit(HunkPalette &hunkPalette) {
- if (hunkPalette.getVersion() == _version) {
- return;
- }
-
- const Palette oldSourcePalette(_sourcePalette);
- const Palette palette = hunkPalette.toPalette();
- mergePaletteInternal(&_sourcePalette, &palette);
-
- if (!_needsUpdate && oldSourcePalette != _sourcePalette) {
- ++_version;
- _needsUpdate = true;
- }
-
- hunkPalette.setVersion(_version);
-}
-
bool GfxPalette32::loadPalette(const GuiResourceId resourceId) {
Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
@@ -206,7 +168,7 @@ bool GfxPalette32::loadPalette(const GuiResourceId resourceId) {
return false;
}
- HunkPalette palette(palResource->data);
+ const HunkPalette palette(palResource->data);
submit(palette);
return true;
}
@@ -241,6 +203,33 @@ int16 GfxPalette32::matchColor(const uint8 r, const uint8 g, const uint8 b) {
return bestIndex;
}
+void GfxPalette32::submit(const Palette &palette) {
+ const Palette oldSourcePalette(_sourcePalette);
+ mergePalette(_sourcePalette, palette);
+
+ if (!_needsUpdate && _sourcePalette != oldSourcePalette) {
+ ++_version;
+ _needsUpdate = true;
+ }
+}
+
+void GfxPalette32::submit(const HunkPalette &hunkPalette) {
+ if (hunkPalette.getVersion() == _version) {
+ return;
+ }
+
+ const Palette oldSourcePalette(_sourcePalette);
+ const Palette palette = hunkPalette.toPalette();
+ mergePalette(_sourcePalette, palette);
+
+ if (!_needsUpdate && oldSourcePalette != _sourcePalette) {
+ ++_version;
+ _needsUpdate = true;
+ }
+
+ hunkPalette.setVersion(_version);
+}
+
bool GfxPalette32::updateForFrame() {
applyAll();
_needsUpdate = false;
@@ -266,10 +255,10 @@ void GfxPalette32::updateHardware(const bool updateScreen) {
_currentPalette.colors[i] = _nextPalette.colors[i];
// NOTE: If the brightness option in the user configuration file is set,
- // SCI engine adjusts palette brightnesses here by mapping RGB values to values
- // in some hard-coded brightness tables. There is no reason on modern hardware
- // to implement this, unless it is discovered that some game uses a non-standard
- // brightness setting by default
+ // SCI engine adjusts palette brightnesses here by mapping RGB values to
+ // values in some hard-coded brightness tables. There is no reason on
+ // modern hardware to implement this, unless it is discovered that some
+ // game uses a non-standard brightness setting by default
// All color entries MUST be copied, not just "used" entries, otherwise
// uninitialised memory from bpal makes its way into the system palette.
@@ -299,6 +288,29 @@ void GfxPalette32::updateHardware(const bool updateScreen) {
}
}
+Palette GfxPalette32::getPaletteFromResource(const GuiResourceId resourceId) const {
+ Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
+
+ if (!palResource) {
+ error("Could not load vary palette %d", resourceId);
+ }
+
+ const HunkPalette rawPalette(palResource->data);
+ return rawPalette.toPalette();
+}
+
+void GfxPalette32::mergePalette(Palette &to, const Palette &from) {
+ // The last color is always white in SCI, so it is not copied. (Some
+ // palettes, particularly in KQ7, try to set the last color, which causes
+ // unnecessary palette updates since the last color is forced by SSCI to a
+ // specific value)
+ for (int i = 0; i < ARRAYSIZE(to.colors) - 1; ++i) {
+ if (from.colors[i].used) {
+ to.colors[i] = from.colors[i];
+ }
+ }
+}
+
void GfxPalette32::applyAll() {
applyVary();
applyCycles();
@@ -306,81 +318,43 @@ void GfxPalette32::applyAll() {
}
#pragma mark -
-#pragma mark Colour look-up
-
-#ifdef ENABLE_SCI3_GAMES
-bool GfxPalette32::loadClut(uint16 clutId) {
- // loadClut() will load a color lookup table from a clu file and set
- // the palette found in the file. This is to be used with Phantasmagoria 2.
-
- unloadClut();
-
- Common::String filename = Common::String::format("%d.clu", clutId);
- Common::File clut;
-
- if (!clut.open(filename) || clut.size() != 0x10000 + 236 * 3)
- return false;
-
- // Read in the lookup table
- // It maps each RGB565 color to a palette index
- _clutTable = new byte[0x10000];
- clut.read(_clutTable, 0x10000);
+#pragma mark Varying
- Palette pal;
- memset(&pal, 0, sizeof(Palette));
+void GfxPalette32::setVary(const Palette &target, const int16 percent, const int32 ticks, const int16 fromColor, const int16 toColor) {
+ setTarget(target);
+ setVaryTime(percent, ticks);
- // Setup 1:1 mapping
- for (int i = 0; i < 256; i++) {
- pal.mapping[i] = i;
+ if (fromColor > -1) {
+ _varyFromColor = fromColor;
}
-
- // Now load in the palette
- for (int i = 1; i <= 236; i++) {
- pal.colors[i].used = 1;
- pal.colors[i].r = clut.readByte();
- pal.colors[i].g = clut.readByte();
- pal.colors[i].b = clut.readByte();
+ if (toColor > -1) {
+ assert(toColor < 256);
+ _varyToColor = toColor;
}
-
- set(&pal, true);
- setOnScreen();
- return true;
}
-byte GfxPalette32::matchClutColor(uint16 color) {
- // Match a color in RGB565 format to a palette index based on the loaded CLUT
- assert(_clutTable);
- return _clutTable[color];
-}
+void GfxPalette32::setVaryPercent(const int16 percent, const int32 ticks) {
+ if (_varyTargetPalette != nullptr) {
+ setVaryTime(percent, ticks);
+ }
-void GfxPalette32::unloadClut() {
- // This will only unload the actual table, but not reset any palette
- delete[] _clutTable;
- _clutTable = nullptr;
+ // NOTE: SSCI had two additional parameters for this function to change the
+ // `_varyFromColor`, but they were always hardcoded to be ignored
}
-#endif
-#pragma mark -
-#pragma mark Varying
-
-inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId resourceId) const {
- Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
-
- if (!palResource) {
- error("Could not load vary palette %d", resourceId);
+void GfxPalette32::setVaryTime(const int32 time) {
+ if (_varyTargetPalette != nullptr) {
+ setVaryTime(_varyTargetPercent, time);
}
-
- HunkPalette rawPalette(palResource->data);
- return rawPalette.toPalette();
}
-inline void GfxPalette32::setVaryTimeInternal(const int16 percent, const int time) {
+void GfxPalette32::setVaryTime(const int16 percent, const int32 ticks) {
_varyLastTick = g_sci->getTickCount();
- if (!time || _varyPercent == percent) {
+ if (!ticks || _varyPercent == percent) {
_varyDirection = 0;
_varyTargetPercent = _varyPercent = percent;
} else {
- _varyTime = time / (percent - _varyPercent);
+ _varyTime = ticks / (percent - _varyPercent);
_varyTargetPercent = percent;
if (_varyTime > 0) {
@@ -395,72 +369,6 @@ inline void GfxPalette32::setVaryTimeInternal(const int16 percent, const int tim
}
}
-void GfxPalette32::kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor) {
- Palette palette = getPaletteFromResourceInternal(paletteId);
- setVary(&palette, percent, time, fromColor, toColor);
-}
-
-void GfxPalette32::kernelPalVaryMergeTarget(GuiResourceId paletteId) {
- Palette palette = getPaletteFromResourceInternal(paletteId);
- mergeTarget(&palette);
-}
-
-void GfxPalette32::kernelPalVarySetTarget(GuiResourceId paletteId) {
- Palette palette = getPaletteFromResourceInternal(paletteId);
- setTarget(&palette);
-}
-
-void GfxPalette32::kernelPalVarySetStart(GuiResourceId paletteId) {
- Palette palette = getPaletteFromResourceInternal(paletteId);
- setStart(&palette);
-}
-
-void GfxPalette32::kernelPalVaryMergeStart(GuiResourceId paletteId) {
- Palette palette = getPaletteFromResourceInternal(paletteId);
- mergeStart(&palette);
-}
-
-void GfxPalette32::kernelPalVaryPause(bool pause) {
- if (pause) {
- varyPause();
- } else {
- varyOn();
- }
-}
-
-void GfxPalette32::setVary(const Palette *const target, const int16 percent, const int time, const int16 fromColor, const int16 toColor) {
- setTarget(target);
- setVaryTimeInternal(percent, time);
-
- if (fromColor > -1) {
- _varyFromColor = fromColor;
- }
- if (toColor > -1) {
- assert(toColor < 256);
- _varyToColor = toColor;
- }
-}
-
-void GfxPalette32::setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate) {
- if (_varyTargetPalette != nullptr) {
- setVaryTimeInternal(percent, time);
- }
-
- // This looks like a mistake in the actual SCI engine (both SQ6 and Lighthouse);
- // the values are always hardcoded to -1 in kPalVary, so this code can never
- // actually be executed
- if (fromColor > -1) {
- _varyFromColor = fromColor;
- }
- if (fromColorAlternate > -1) {
- _varyFromColor = fromColorAlternate;
- }
-}
-
-int16 GfxPalette32::getVaryPercent() const {
- return ABS(_varyPercent);
-}
-
void GfxPalette32::varyOff() {
_varyNumTimesPaused = 0;
_varyPercent = _varyTargetPercent = 0;
@@ -479,14 +387,6 @@ void GfxPalette32::varyOff() {
}
}
-void GfxPalette32::mergeTarget(const Palette *const palette) {
- if (_varyTargetPalette != nullptr) {
- mergePaletteInternal(_varyTargetPalette, palette);
- } else {
- _varyTargetPalette = new Palette(*palette);
- }
-}
-
void GfxPalette32::varyPause() {
_varyDirection = 0;
++_varyNumTimesPaused;
@@ -497,51 +397,44 @@ void GfxPalette32::varyOn() {
--_varyNumTimesPaused;
}
- if (_varyTargetPalette != nullptr && _varyNumTimesPaused == 0 && _varyPercent != _varyTargetPercent) {
- if (_varyTime == 0) {
- _varyPercent = _varyTargetPercent;
- } else if (_varyTargetPercent < _varyPercent) {
- _varyDirection = -1;
+ if (_varyTargetPalette != nullptr && _varyNumTimesPaused == 0) {
+ if (_varyPercent != _varyTargetPercent && _varyTime != 0) {
+ _varyDirection = (_varyTargetPercent - _varyPercent > 0) ? 1 : -1;
} else {
- _varyDirection = 1;
+ _varyPercent = _varyTargetPercent;
}
}
}
-void GfxPalette32::setVaryTime(const int time) {
- if (_varyTargetPalette == nullptr) {
- return;
- }
-
- setVaryTimeInternal(_varyTargetPercent, time);
+void GfxPalette32::setTarget(const Palette &palette) {
+ delete _varyTargetPalette;
+ _varyTargetPalette = new Palette(palette);
}
-void GfxPalette32::setTarget(const Palette *const palette) {
- if (_varyTargetPalette != nullptr) {
- delete _varyTargetPalette;
- }
-
- _varyTargetPalette = new Palette(*palette);
+void GfxPalette32::setStart(const Palette &palette) {
+ delete _varyStartPalette;
+ _varyStartPalette = new Palette(palette);
}
-void GfxPalette32::setStart(const Palette *const palette) {
+void GfxPalette32::mergeStart(const Palette &palette) {
if (_varyStartPalette != nullptr) {
- delete _varyStartPalette;
+ mergePalette(*_varyStartPalette, palette);
+ } else {
+ _varyStartPalette = new Palette(palette);
}
-
- _varyStartPalette = new Palette(*palette);
}
-void GfxPalette32::mergeStart(const Palette *const palette) {
- if (_varyStartPalette != nullptr) {
- mergePaletteInternal(_varyStartPalette, palette);
+void GfxPalette32::mergeTarget(const Palette &palette) {
+ if (_varyTargetPalette != nullptr) {
+ mergePalette(*_varyTargetPalette, palette);
} else {
- _varyStartPalette = new Palette(*palette);
+ _varyTargetPalette = new Palette(palette);
}
}
void GfxPalette32::applyVary() {
- while (g_sci->getTickCount() - _varyLastTick > (uint32)_varyTime && _varyDirection != 0) {
+ const uint32 now = g_sci->getTickCount();
+ while ((int32)(now - _varyLastTick) > _varyTime && _varyDirection != 0) {
_varyLastTick += _varyTime;
if (_varyPercent == _varyTargetPercent) {
@@ -552,7 +445,7 @@ void GfxPalette32::applyVary() {
}
if (_varyPercent == 0 || _varyTargetPalette == nullptr) {
- for (int i = 0, len = ARRAYSIZE(_nextPalette.colors); i < len; ++i) {
+ for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) {
if (_varyStartPalette != nullptr && i >= _varyFromColor && i <= _varyToColor) {
_nextPalette.colors[i] = _varyStartPalette->colors[i];
} else {
@@ -560,7 +453,7 @@ void GfxPalette32::applyVary() {
}
}
} else {
- for (int i = 0, len = ARRAYSIZE(_nextPalette.colors); i < len; ++i) {
+ for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) {
if (i >= _varyFromColor && i <= _varyToColor) {
Color targetColor = _varyTargetPalette->colors[i];
Color sourceColor;
@@ -591,82 +484,67 @@ void GfxPalette32::applyVary() {
}
}
-#pragma mark -
-#pragma mark Cycling
-
-inline void GfxPalette32::clearCycleMap(const uint16 fromColor, const uint16 numColorsToClear) {
- bool *mapEntry = _cycleMap + fromColor;
- const bool *lastEntry = _cycleMap + numColorsToClear;
- while (mapEntry < lastEntry) {
- *mapEntry++ = false;
- }
+void GfxPalette32::kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int32 ticks, const int16 fromColor, const int16 toColor) {
+ const Palette palette = getPaletteFromResource(paletteId);
+ setVary(palette, percent, ticks, fromColor, toColor);
}
-inline void GfxPalette32::setCycleMap(const uint16 fromColor, const uint16 numColorsToSet) {
- bool *mapEntry = _cycleMap + fromColor;
- const bool *lastEntry = _cycleMap + numColorsToSet;
- while (mapEntry < lastEntry) {
- if (*mapEntry != false) {
- error("Cycles intersect");
- }
- *mapEntry++ = true;
- }
+void GfxPalette32::kernelPalVaryMergeTarget(const GuiResourceId paletteId) {
+ const Palette palette = getPaletteFromResource(paletteId);
+ mergeTarget(palette);
}
-inline PalCycler *GfxPalette32::getCycler(const uint16 fromColor) {
- const int numCyclers = ARRAYSIZE(_cyclers);
-
- for (int cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
- PalCycler *cycler = _cyclers[cyclerIndex];
- if (cycler != nullptr && cycler->fromColor == fromColor) {
- return cycler;
- }
- }
+void GfxPalette32::kernelPalVarySetTarget(const GuiResourceId paletteId) {
+ const Palette palette = getPaletteFromResource(paletteId);
+ setTarget(palette);
+}
- return nullptr;
+void GfxPalette32::kernelPalVarySetStart(const GuiResourceId paletteId) {
+ const Palette palette = getPaletteFromResource(paletteId);
+ setStart(palette);
}
-inline void doCycleInternal(PalCycler *cycler, const int16 speed) {
- int16 currentCycle = cycler->currentCycle;
- const uint16 numColorsToCycle = cycler->numColorsToCycle;
+void GfxPalette32::kernelPalVaryMergeStart(const GuiResourceId paletteId) {
+ const Palette palette = getPaletteFromResource(paletteId);
+ mergeStart(palette);
+}
- if (cycler->direction == 0) {
- currentCycle = (currentCycle - (speed % numColorsToCycle)) + numColorsToCycle;
+void GfxPalette32::kernelPalVaryPause(const bool pause) {
+ if (pause) {
+ varyPause();
} else {
- currentCycle = currentCycle + speed;
+ varyOn();
}
-
- cycler->currentCycle = (uint8) (currentCycle % numColorsToCycle);
}
+#pragma mark -
+#pragma mark Cycling
+
void GfxPalette32::setCycle(const uint8 fromColor, const uint8 toColor, const int16 direction, const int16 delay) {
assert(fromColor < toColor);
- int cyclerIndex;
- const int numCyclers = ARRAYSIZE(_cyclers);
-
PalCycler *cycler = getCycler(fromColor);
if (cycler != nullptr) {
clearCycleMap(fromColor, cycler->numColorsToCycle);
} else {
- for (cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
- if (_cyclers[cyclerIndex] == nullptr) {
- cycler = new PalCycler;
- _cyclers[cyclerIndex] = cycler;
+ for (int i = 0; i < kNumCyclers; ++i) {
+ if (_cyclers[i] == nullptr) {
+ _cyclers[i] = cycler = new PalCycler;
break;
}
}
}
- // SCI engine overrides the first oldest cycler that it finds where
- // “oldest” is determined by the difference between the tick and now
+ // If there are no free cycler slots, SCI engine overrides the first oldest
+ // cycler that it finds, where "oldest" is determined by the difference
+ // between the tick and now
if (cycler == nullptr) {
const uint32 now = g_sci->getTickCount();
uint32 minUpdateDelta = 0xFFFFFFFF;
- for (cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
- PalCycler *candidate = _cyclers[cyclerIndex];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const candidate = _cyclers[i];
const uint32 updateDelta = now - candidate->lastUpdateTick;
if (updateDelta < minUpdateDelta) {
@@ -678,11 +556,11 @@ void GfxPalette32::setCycle(const uint8 fromColor, const uint8 toColor, const in
clearCycleMap(cycler->fromColor, cycler->numColorsToCycle);
}
- const uint16 numColorsToCycle = 1 + ((uint8) toColor) - fromColor;
- cycler->fromColor = (uint8) fromColor;
- cycler->numColorsToCycle = (uint8) numColorsToCycle;
- cycler->currentCycle = (uint8) fromColor;
- cycler->direction = direction < 0 ? PalCycleBackward : PalCycleForward;
+ const uint16 numColorsToCycle = toColor - fromColor + 1;
+ cycler->fromColor = fromColor;
+ cycler->numColorsToCycle = numColorsToCycle;
+ cycler->currentCycle = fromColor;
+ cycler->direction = direction < 0 ? kPalCycleBackward : kPalCycleForward;
cycler->delay = delay;
cycler->lastUpdateTick = g_sci->getTickCount();
cycler->numTimesPaused = 0;
@@ -691,30 +569,30 @@ void GfxPalette32::setCycle(const uint8 fromColor, const uint8 toColor, const in
}
void GfxPalette32::doCycle(const uint8 fromColor, const int16 speed) {
- PalCycler *cycler = getCycler(fromColor);
+ PalCycler *const cycler = getCycler(fromColor);
if (cycler != nullptr) {
cycler->lastUpdateTick = g_sci->getTickCount();
- doCycleInternal(cycler, speed);
+ updateCycler(*cycler, speed);
}
}
void GfxPalette32::cycleOn(const uint8 fromColor) {
- PalCycler *cycler = getCycler(fromColor);
+ PalCycler *const cycler = getCycler(fromColor);
if (cycler != nullptr && cycler->numTimesPaused > 0) {
--cycler->numTimesPaused;
}
}
void GfxPalette32::cyclePause(const uint8 fromColor) {
- PalCycler *cycler = getCycler(fromColor);
+ PalCycler *const cycler = getCycler(fromColor);
if (cycler != nullptr) {
++cycler->numTimesPaused;
}
}
void GfxPalette32::cycleAllOn() {
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr && cycler->numTimesPaused > 0) {
--cycler->numTimesPaused;
}
@@ -724,8 +602,8 @@ void GfxPalette32::cycleAllOn() {
void GfxPalette32::cycleAllPause() {
// NOTE: The original engine did not check for null pointers in the
// palette cyclers pointer array.
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr) {
// This seems odd, because currentCycle is 0..numColorsPerCycle,
// but fromColor is 0..255. When applyAllCycles runs, the values
@@ -736,8 +614,8 @@ void GfxPalette32::cycleAllPause() {
applyAllCycles();
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr) {
++cycler->numTimesPaused;
}
@@ -745,8 +623,8 @@ void GfxPalette32::cycleAllPause() {
}
void GfxPalette32::cycleOff(const uint8 fromColor) {
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr && cycler->fromColor == fromColor) {
clearCycleMap(fromColor, cycler->numColorsToCycle);
delete cycler;
@@ -757,8 +635,8 @@ void GfxPalette32::cycleOff(const uint8 fromColor) {
}
void GfxPalette32::cycleAllOff() {
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr) {
clearCycleMap(cycler->fromColor, cycler->numColorsToCycle);
delete cycler;
@@ -767,16 +645,57 @@ void GfxPalette32::cycleAllOff() {
}
}
+void GfxPalette32::updateCycler(PalCycler &cycler, const int16 speed) {
+ int16 currentCycle = cycler.currentCycle;
+ const uint16 numColorsToCycle = cycler.numColorsToCycle;
+
+ if (cycler.direction == kPalCycleBackward) {
+ currentCycle = (currentCycle - (speed % numColorsToCycle)) + numColorsToCycle;
+ } else {
+ currentCycle = currentCycle + speed;
+ }
+
+ cycler.currentCycle = currentCycle % numColorsToCycle;
+}
+
+void GfxPalette32::clearCycleMap(const uint16 fromColor, const uint16 numColorsToClear) {
+ bool *mapEntry = _cycleMap + fromColor;
+ const bool *const lastEntry = _cycleMap + numColorsToClear;
+ while (mapEntry < lastEntry) {
+ *mapEntry++ = false;
+ }
+}
+
+void GfxPalette32::setCycleMap(const uint16 fromColor, const uint16 numColorsToSet) {
+ bool *mapEntry = _cycleMap + fromColor;
+ const bool *const lastEntry = _cycleMap + numColorsToSet;
+ while (mapEntry < lastEntry) {
+ if (*mapEntry != false) {
+ error("Cycles intersect");
+ }
+ *mapEntry++ = true;
+ }
+}
+
+PalCycler *GfxPalette32::getCycler(const uint16 fromColor) {
+ for (int cyclerIndex = 0; cyclerIndex < kNumCyclers; ++cyclerIndex) {
+ PalCycler *cycler = _cyclers[cyclerIndex];
+ if (cycler != nullptr && cycler->fromColor == fromColor) {
+ return cycler;
+ }
+ }
+
+ return nullptr;
+}
+
void GfxPalette32::applyAllCycles() {
Color paletteCopy[256];
memcpy(paletteCopy, _nextPalette.colors, sizeof(Color) * 256);
- for (int cyclerIndex = 0, numCyclers = ARRAYSIZE(_cyclers); cyclerIndex < numCyclers; ++cyclerIndex) {
- PalCycler *cycler = _cyclers[cyclerIndex];
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler != nullptr) {
- cycler->currentCycle = (uint8) ((((int) cycler->currentCycle) + 1) % cycler->numColorsToCycle);
- // Disassembly was not fully evaluated to verify this is exactly the same
- // as the code from applyCycles, but it appeared to be at a glance
+ cycler->currentCycle = (((int) cycler->currentCycle) + 1) % cycler->numColorsToCycle;
for (int j = 0; j < cycler->numColorsToCycle; j++) {
_nextPalette.colors[cycler->fromColor + j] = paletteCopy[cycler->fromColor + (cycler->currentCycle + j) % cycler->numColorsToCycle];
}
@@ -788,15 +707,16 @@ void GfxPalette32::applyCycles() {
Color paletteCopy[256];
memcpy(paletteCopy, _nextPalette.colors, sizeof(Color) * 256);
- for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
- PalCycler *cycler = _cyclers[i];
+ const uint32 now = g_sci->getTickCount();
+ for (int i = 0; i < kNumCyclers; ++i) {
+ PalCycler *const cycler = _cyclers[i];
if (cycler == nullptr) {
continue;
}
if (cycler->delay != 0 && cycler->numTimesPaused == 0) {
- while ((cycler->delay + cycler->lastUpdateTick) < g_sci->getTickCount()) {
- doCycleInternal(cycler, 1);
+ while ((cycler->delay + cycler->lastUpdateTick) < now) {
+ updateCycler(*cycler, 1);
cycler->lastUpdateTick += cycler->delay;
}
}
@@ -810,7 +730,7 @@ void GfxPalette32::applyCycles() {
#pragma mark -
#pragma mark Fading
-void GfxPalette32::setFade(uint16 percent, uint8 fromColor, uint16 toColor) {
+void GfxPalette32::setFade(const uint16 percent, const uint8 fromColor, uint16 toColor) {
if (fromColor > toColor) {
return;
}
@@ -827,13 +747,14 @@ void GfxPalette32::setFade(uint16 percent, uint8 fromColor, uint16 toColor) {
}
void GfxPalette32::fadeOff() {
- setFade(100, 0, 256);
+ setFade(100, 0, 255);
}
void GfxPalette32::applyFade() {
for (int i = 0; i < ARRAYSIZE(_fadeTable); ++i) {
- if (_fadeTable[i] == 100)
+ if (_fadeTable[i] == 100) {
continue;
+ }
Color &color = _nextPalette.colors[i];
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index dc2158022f..81e9bbbfd3 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -24,30 +24,33 @@
#define SCI_GRAPHICS_PALETTE32_H
#include "sci/graphics/palette.h"
-
namespace Sci {
+#pragma mark HunkPalette
+
/**
- * HunkPalette represents a raw palette resource
- * read from disk.
+ * HunkPalette represents a raw palette resource read from disk. The data
+ * structure of a HunkPalette allows palettes to be smaller than 256 colors. It
+ * also allows multiple palettes to be stored in one HunkPalette, though in
+ * SCI32 games there seems to only ever be one palette per HunkPalette.
*/
class HunkPalette {
public:
HunkPalette(byte *rawPalette);
/**
- * Gets the version of the palette.
+ * Gets the version of the palette. Used to avoid resubmitting a HunkPalette
+ * which has already been submitted for the next frame.
*/
uint32 getVersion() const { return _version; }
/**
* Sets the version of the palette.
*/
- void setVersion(const uint32 version);
+ void setVersion(const uint32 version) const;
/**
- * Converts the hunk palette to a standard
- * palette.
+ * Converts the hunk palette to a standard Palette.
*/
const Palette toPalette() const;
@@ -64,15 +67,14 @@ private:
kEntryHeaderSize = 22,
/**
- * The offset of the hunk palette version
- * within the palette entry header.
+ * The offset of the hunk palette version within the palette entry
+ * header.
*/
kEntryVersionOffset = 18
};
/**
- * The header for a palette inside the
- * HunkPalette.
+ * The header for a palette inside the HunkPalette.
*/
struct EntryHeader {
/**
@@ -81,8 +83,7 @@ private:
uint8 startColor;
/**
- * The number of palette colors in this
- * entry.
+ * The number of palette colors in this entry.
*/
uint16 numColors;
@@ -92,8 +93,7 @@ private:
bool used;
/**
- * Whether or not all palette entries
- * share the same `used` value in
+ * Whether or not all palette entries share the same `used` value in
* `defaultFlag`.
*/
bool sharedUsed;
@@ -105,14 +105,14 @@ private:
};
/**
- * The version number from the last time this
- * palette was submitted to GfxPalette32.
+ * The version number from the last time this palette was submitted to
+ * GfxPalette32.
*/
- uint32 _version;
+ mutable uint32 _version;
/**
- * The number of palettes stored in the hunk
- * palette. In SCI32 games this is always 1.
+ * The number of palettes stored in the hunk palette. In SCI32 games this is
+ * always 1.
*/
uint8 _numPalettes;
@@ -122,41 +122,44 @@ private:
byte *_data;
/**
- * Returns a struct that describes the palette
- * held by this HunkPalette. The entry header
- * is reconstructed on every call from the raw
- * palette data.
+ * Returns a struct that describes the palette held by this HunkPalette. The
+ * entry header is reconstructed on every call from the raw palette data.
*/
const EntryHeader getEntryHeader() const;
/**
- * Returns a pointer to the palette data within
- * the hunk palette.
+ * Returns a pointer to the palette data within the hunk palette.
*/
byte *getPalPointer() const {
return _data + kHunkPaletteHeaderSize + (2 * _numPalettes);
}
};
+#pragma mark -
+#pragma mark PalCycler
+
enum PalCyclerDirection {
- PalCycleBackward = 0,
- PalCycleForward = 1
+ kPalCycleBackward = 0,
+ kPalCycleForward = 1
};
+/**
+ * PalCycler represents a range of palette entries that are rotated on a timer.
+ */
struct PalCycler {
/**
- * The color index of the palette cycler. This value is effectively used as the ID for the
- * cycler.
+ * The color index of this palette cycler. This value is used as the unique
+ * key for this PalCycler object.
*/
uint8 fromColor;
/**
- * The number of palette slots which are cycled by the palette cycler.
+ * The number of palette slots which are to be cycled by this cycler.
*/
uint16 numColorsToCycle;
/**
- * The position of the cursor in its cycle.
+ * The current position of the first palette entry.
*/
uint8 currentCycle;
@@ -166,15 +169,15 @@ struct PalCycler {
PalCyclerDirection direction;
/**
- * The cycle tick at the last time the cycler’s currentCycle was updated.
- * 795 days of game time ought to be enough for everyone? :)
+ * The last tick the cycler cycled.
*/
uint32 lastUpdateTick;
/**
- * The amount of time in ticks each cycle should take to complete. In other words,
- * the higher the delay, the slower the cycle animation. If delay is 0, the cycler
- * does not automatically cycle and needs to be pumped manually with DoCycle.
+ * The amount of time in ticks each cycle should take to complete. In other
+ * words, the higher the delay, the slower the cycle animation. If delay is
+ * 0, the cycler does not automatically cycle and needs to be cycled
+ * manually by calling `doCycle`.
*/
int16 delay;
@@ -184,17 +187,72 @@ struct PalCycler {
uint16 numTimesPaused;
};
+#pragma mark -
+#pragma mark GfxPalette32
+
class GfxPalette32 {
public:
GfxPalette32(ResourceManager *resMan);
~GfxPalette32();
+ void saveLoadWithSerializer(Common::Serializer &s);
+
+ /**
+ * Gets the palette that will be use for the next frame.
+ */
+ inline const Palette &getNextPalette() const { return _nextPalette; };
+
+ /**
+ * Gets the palette that is used for the current frame.
+ */
+ inline const Palette &getCurrentPalette() const { return _currentPalette; };
+
+ /**
+ * Loads a palette into GfxPalette32 with the given resource ID.
+ */
+ bool loadPalette(const GuiResourceId resourceId);
+
+ /**
+ * Finds the nearest color in the current palette matching the given RGB
+ * value.
+ */
+ int16 matchColor(const uint8 r, const uint8 g, const uint8 b);
+
+ /**
+ * Submits a palette to display. Entries marked as "used" in the submitted
+ * palette are merged into `_sourcePalette`.
+ */
+ void submit(const Palette &palette);
+ void submit(const HunkPalette &palette);
+
+ /**
+ * Applies all fades, cycles, remaps, and varies for the current frame to
+ * `nextPalette`.
+ */
+ bool updateForFrame();
+
+ /**
+ * Copies all palette entries from `sourcePalette` to `nextPalette` and
+ * applies remaps. Unlike `updateForFrame`, this call does not apply fades,
+ * cycles, or varies.
+ */
+ void updateFFrame();
+
+ /**
+ * Copies all entries from `nextPalette` to `currentPalette` and updates the
+ * backend's raw palette.
+ *
+ * @param updateScreen If true, this call will also tell the backend to draw
+ * to the screen.
+ */
+ void updateHardware(const bool updateScreen = true);
+
private:
ResourceManager *_resMan;
/**
- * The palette revision version. Increments once per game
- * loop that changes the source palette.
+ * The palette revision version. Increments once per game loop that changes
+ * the source palette.
*/
uint32 _version;
@@ -209,90 +267,140 @@ private:
Palette _currentPalette;
/**
- * The unmodified source palette loaded by kPalette. Additional
- * palette entries may be mixed into the source palette by
- * CelObj objects, which contain their own palettes.
+ * The unmodified source palette loaded by kPalette. Additional palette
+ * entries may be mixed into the source palette by CelObj objects, which
+ * contain their own palettes.
*/
Palette _sourcePalette;
/**
* The palette to be used when the hardware is next updated.
- * On update, _nextPalette is transferred to _currentPalette.
+ * On update, `_nextPalette` is transferred to `_currentPalette`.
*/
Palette _nextPalette;
- bool createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const;
- Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const;
+ /**
+ * Creates and returns a new Palette object with data from the given
+ * resource ID.
+ */
+ Palette getPaletteFromResource(const GuiResourceId paletteId) const;
+
+ /**
+ * Merges used colors in the `from` palette into the `to` palette.
+ */
+ void mergePalette(Palette &to, const Palette &from);
+
+ /**
+ * Applies all varies, cycles, and fades to `_nextPalette`.
+ */
+ void applyAll();
+#pragma mark -
+#pragma mark Varying
public:
- void saveLoadWithSerializer(Common::Serializer &s);
- inline const Palette &getNextPalette() const { return _nextPalette; };
- inline const Palette &getCurrentPalette() const { return _currentPalette; };
+ /**
+ * Blends the `target` palette into the current palette over `time` ticks.
+ *
+ * @param target The target palette.
+ * @param percent The amount that the target palette should be blended into
+ * the source palette by the end of the vary.
+ * @param ticks The number of ticks that it should take for the blend to be
+ * completed.
+ * @param fromColor The first palette entry that should be blended.
+ * @param toColor The last palette entry that should be blended.
+ */
+ void setVary(const Palette &target, const int16 percent, const int32 ticks, const int16 fromColor, const int16 toColor);
/**
- * Loads a palette into GfxPalette32 with the given resource
- * ID.
+ * Gets the current vary blend amount.
*/
- bool loadPalette(const GuiResourceId resourceId);
+ inline int16 getVaryPercent() const { return ABS(_varyPercent); }
/**
- * Finds the nearest color in the current palette matching the
- * given RGB value.
+ * Changes the percentage of the current vary to `percent`, to be completed
+ * over `time` ticks, if there is a currently active vary target palette.
*/
- int16 matchColor(const uint8 r, const uint8 g, const uint8 b);
+ void setVaryPercent(const int16 percent, const int32 time);
/**
- * Submits a palette to display. Entries marked as “used” in the
- * submitted palette are merged into the existing entries of
- * _sourcePalette.
+ * Changes the amount of time, in ticks, an in-progress palette vary should
+ * take to finish.
*/
- void submit(const Palette &palette);
- void submit(HunkPalette &palette);
+ void setVaryTime(const int32 ticks);
- bool updateForFrame();
- void updateFFrame();
- void updateHardware(const bool updateScreen = true);
- void applyAll();
+ /**
+ * Changes the vary percent and time to perform the vary.
+ */
+ void setVaryTime(const int16 percent, const int32 ticks);
-#pragma mark -
-#pragma mark Color look-up
-private:
/**
- * An optional lookup table used to remap RGB565 colors to a palette
- * index. Used by Phantasmagoria 2 in 8-bit color environments.
+ * Removes the active palette vary.
*/
- byte *_clutTable;
+ void varyOff();
-public:
- bool loadClut(uint16 clutId);
- byte matchClutColor(uint16 color);
- void unloadClut();
+ /**
+ * Pauses any active palette vary.
+ */
+ void varyPause();
+
+ /**
+ * Unpauses any paused palette vary.
+ */
+ void varyOn();
+
+ /**
+ * Sets the target palette for the blend.
+ */
+ void setTarget(const Palette &palette);
+
+ /**
+ * Sets the start palette for the blend.
+ */
+ void setStart(const Palette &palette);
+
+ /**
+ * Merges a new start palette into the existing start palette.
+ */
+ void mergeStart(const Palette &palette);
+
+ /**
+ * Merges a new target palette into the existing target palette.
+ */
+ void mergeTarget(const Palette &palette);
+
+ /**
+ * Applies any active palette vary to `_nextPalette`.
+ */
+ void applyVary();
+
+ void kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int32 ticks, const int16 fromColor, const int16 toColor);
+ void kernelPalVaryMergeTarget(const GuiResourceId paletteId);
+ void kernelPalVarySetTarget(const GuiResourceId paletteId);
+ void kernelPalVarySetStart(const GuiResourceId paletteId);
+ void kernelPalVaryMergeStart(const GuiResourceId paletteId);
+ void kernelPalVaryPause(const bool pause);
-#pragma mark -
-#pragma mark Varying
private:
/**
- * An optional palette used to describe the source colors used
- * in a palette vary operation. If this palette is not specified,
- * sourcePalette is used instead.
+ * An optional palette used to provide source colors for a palette vary
+ * operation. If this palette is not specified, `_sourcePalette` is used
+ * instead.
*/
Palette *_varyStartPalette;
/**
- * An optional palette used to describe the target colors used
- * in a palette vary operation.
+ * An optional palette used to provide target colors for a palette vary
+ * operation.
*/
Palette *_varyTargetPalette;
/**
- * The minimum palette index that has been varied from the
- * source palette. 0–255
+ * The minimum palette index that has been varied from the source palette.
*/
uint8 _varyFromColor;
/**
- * The maximum palette index that is has been varied from the
- * source palette. 0-255
+ * The maximum palette index that has been varied from the source palette.
*/
uint8 _varyToColor;
@@ -302,10 +410,10 @@ private:
uint32 _varyLastTick;
/**
- * The amount of time to elapse, in ticks, between each cycle
- * of a palette vary animation.
+ * The amount of time that should elapse, in ticks, between each cycle of a
+ * palette vary animation.
*/
- int _varyTime;
+ int32 _varyTime;
/**
* The direction of change: -1, 0, or 1.
@@ -313,97 +421,158 @@ private:
int16 _varyDirection;
/**
- * The amount, in percent, that the vary color is currently
- * blended into the source color.
+ * The amount, in percent, that the vary color is currently blended into the
+ * source color.
*/
int16 _varyPercent;
/**
- * The target amount that a vary color will be blended into
- * the source color.
+ * The target amount that a vary color will be blended into the source
+ * color.
*/
int16 _varyTargetPercent;
/**
- * The number of time palette varying has been paused.
+ * The number of times palette varying has been paused.
*/
uint16 _varyNumTimesPaused;
-public:
- void kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
- void kernelPalVaryMergeTarget(const GuiResourceId paletteId);
- void kernelPalVarySetTarget(const GuiResourceId paletteId);
- void kernelPalVarySetStart(const GuiResourceId paletteId);
- void kernelPalVaryMergeStart(const GuiResourceId paletteId);
- void kernelPalVaryPause(bool pause);
-
- void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
- void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate);
- int16 getVaryPercent() const;
- void varyOff();
- void mergeTarget(const Palette *const palette);
- void varyPause();
- void varyOn();
- void setVaryTime(const int time);
- void setTarget(const Palette *const palette);
- void setStart(const Palette *const palette);
- void mergeStart(const Palette *const palette);
- void setVaryTimeInternal(const int16 percent, const int time);
- void applyVary();
-
#pragma mark -
#pragma mark Cycling
-private:
- // SQ6 defines 10 cyclers
- PalCycler *_cyclers[10];
+public:
+ inline const bool *getCycleMap() const { return _cycleMap; }
/**
- * The cycle map is used to detect overlapping cyclers.
- * According to SCI engine code, when two cyclers overlap,
- * a fatal error has occurred and the engine will display
- * an error and then exit.
+ * Cycle palette entries between `fromColor` and `toColor`, inclusive.
+ * Palette cyclers may not overlap. `fromColor` is used in other methods as
+ * the key for looking up a cycler.
*
- * The cycle map is also by the color remapping system to
- * avoid attempting to remap to palette entries that are
- * cycling (so won't be the expected color once the cycler
- * runs again).
+ * @param fromColor The first color in the cycle.
+ * @param toColor The last color in the cycle.
+ * @param delay The number of ticks that should elapse between cycles.
+ * @param direction A negative `direction` will cycle backwards instead of
+ * forwards. The numeric value of this argument is ignored;
+ * only its sign is used to determine direction.
*/
- bool _cycleMap[256];
- inline void clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
- inline void setCycleMap(uint16 fromColor, uint16 numColorsToClear);
- inline PalCycler *getCycler(uint16 fromColor);
-
-public:
void setCycle(const uint8 fromColor, const uint8 toColor, const int16 direction, const int16 delay);
+
+ /**
+ * Performs a round of palette cycling.
+ *
+ * @param fromColor The color key for the cycler.
+ * @param speed The number of entries that should be cycled this round.
+ */
void doCycle(const uint8 fromColor, const int16 speed);
+
+ /**
+ * Unpauses the cycler starting at `fromColor`.
+ */
void cycleOn(const uint8 fromColor);
+
+ /**
+ * Pauses the cycler starting at `fromColor`.
+ */
void cyclePause(const uint8 fromColor);
+
+ /**
+ * Unpauses all cyclers.
+ */
void cycleAllOn();
+
+ /**
+ * Pauses all cyclers.
+ */
void cycleAllPause();
+
+ /**
+ * Removes the cycler starting at `fromColor`.
+ */
void cycleOff(const uint8 fromColor);
+
+ /**
+ * Removes all cyclers.
+ */
void cycleAllOff();
+
+private:
+ enum {
+ kNumCyclers = 10
+ };
+
+ PalCycler *_cyclers[kNumCyclers];
+
+ /**
+ * Updates the `currentCycle` of the given `cycler` by `speed` entries.
+ */
+ void updateCycler(PalCycler &cycler, const int16 speed);
+
+ /**
+ * The cycle map is used to detect overlapping cyclers, and to avoid
+ * remapping to palette entries that are being cycled.
+ *
+ * According to SCI engine code, when two cyclers overlap, a fatal error has
+ * occurred and the engine will display an error and then exit.
+ *
+ * The color remapping system avoids attempts to remap to palette entries
+ * that are cycling because they won't be the expected color once the cycler
+ * updates the palette entries.
+ */
+ bool _cycleMap[256];
+
+ /**
+ * Marks `numColorsToClear` colors starting at `fromColor` in the cycle
+ * map as inactive.
+ */
+ void clearCycleMap(const uint16 fromColor, const uint16 numColorsToClear);
+
+ /**
+ * Marks `numColorsToClear` colors starting at `fromColor` in the cycle
+ * map as active.
+ */
+ void setCycleMap(const uint16 fromColor, const uint16 numColorsToClear);
+
+ /**
+ * Gets the cycler object that starts at the given `fromColor`, or NULL if
+ * there is no cycler for that color.
+ */
+ PalCycler *getCycler(const uint16 fromColor);
+
+ /**
+ * Advances all cyclers by one step, regardless of whether or not it is time
+ * to perform another cycle.
+ */
void applyAllCycles();
+
+ /**
+ * Advances, by one step, only the cyclers whose time has come to cycle.
+ */
void applyCycles();
- inline const bool *getCycleMap() const { return _cycleMap; }
#pragma mark -
#pragma mark Fading
-private:
+public:
/**
- * The fade table records the expected intensity level of each pixel
- * in the palette that will be displayed on the next frame.
+ * Sets the intensity level for a range of palette entries. An intensity of
+ * zero indicates total darkness. Intensity may also be set above 100
+ * percent to increase the intensity of a palette entry.
*/
- uint16 _fadeTable[256];
+ void setFade(const uint16 percent, const uint8 fromColor, const uint16 toColor);
-public:
/**
- * Sets the intensity level for a range of palette
- * entries. An intensity of zero indicates total
- * darkness. Intensity may be set to over 100 percent.
+ * Resets the intensity of all palette entries to 100%.
*/
- void setFade(const uint16 percent, const uint8 fromColor, const uint16 toColor);
void fadeOff();
+
+ /**
+ * Applies intensity values to the palette entries in `_nextPalette`.
+ */
void applyFade();
+
+private:
+ /**
+ * The intensity levels of each palette entry, in percent. Defaults to 100.
+ */
+ uint16 _fadeTable[256];
};
} // End of namespace Sci