[Scummvm-cvs-logs] scummvm master -> 7edc5cd891d903e8ae114238745a965c319d7fa3
wjp
wjp at usecode.org
Fri Jul 1 00:54:15 CEST 2016
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c6c9593840 Revert "SCI32: Fix broken Remap implementation"
5a3d8337a6 SCI32: Change kRemapColors naming for consistency
ed64d5b020 SCI32: Move GfxRemap32 to separate files
14e57ac867 SCI32: Add missing remap CelObj calls
0aed08681e SCI32: Separate remap types
0c799e1bd9 SCI32: Move matchColor to GfxRemap32
ca279390a3 SCI32: Fix broken Remap implementation
7edc5cd891 Merge branch 'remap'
Commit: c6c95938405b09204898c7a993ebdfe6ceafcb0e
https://github.com/scummvm/scummvm/commit/c6c95938405b09204898c7a993ebdfe6ceafcb0e
Author: Willem Jan Palenstijn (wjp at usecode.org)
Date: 2016-07-01T00:18:07+02:00
Commit Message:
Revert "SCI32: Fix broken Remap implementation"
This reverts commit cfda8b9ecd8a6e3c003abe533ea2e2981d8ba984.
This is only to re-apply it immediately in a series of smaller commits.
Changed paths:
R engines/sci/graphics/remap32.cpp
R engines/sci/graphics/remap32.h
engines/sci/engine/kernel.h
engines/sci/engine/kernel_tables.h
engines/sci/engine/kgraphics.cpp
engines/sci/engine/kgraphics32.cpp
engines/sci/engine/savegame.cpp
engines/sci/engine/savegame.h
engines/sci/graphics/celobj32.cpp
engines/sci/graphics/frameout.cpp
engines/sci/graphics/palette32.cpp
engines/sci/graphics/palette32.h
engines/sci/graphics/plane32.cpp
engines/sci/graphics/remap.cpp
engines/sci/graphics/remap.h
engines/sci/graphics/view.h
engines/sci/module.mk
engines/sci/sci.cpp
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 1202982..b269e97 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -412,7 +412,7 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
reg_t kShow(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv);
reg_t kDummy(EngineState *s, int argc, reg_t *argv);
reg_t kEmpty(EngineState *s, int argc, reg_t *argv);
reg_t kStub(EngineState *s, int argc, reg_t *argv);
@@ -482,13 +482,13 @@ reg_t kScrollWindowDestroy(EngineState *s, int argc, reg_t *argv);
reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsOff(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColorsBlockRange(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapOff(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv);
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv);
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index dacaafe..19bee35 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -414,12 +414,12 @@ static const SciKernelMapSubEntry kList_subops[] = {
// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kRemapColors_subops[] = {
- { SIG_SCI32, 0, MAP_CALL(RemapColorsOff), "(i)", NULL },
- { SIG_SCI32, 1, MAP_CALL(RemapColorsByRange), "iiii(i)", NULL },
- { SIG_SCI32, 2, MAP_CALL(RemapColorsByPercent), "ii(i)", NULL },
- { SIG_SCI32, 3, MAP_CALL(RemapColorsToGray), "ii(i)", NULL },
- { SIG_SCI32, 4, MAP_CALL(RemapColorsToPercentGray), "iii(i)", NULL },
- { SIG_SCI32, 5, MAP_CALL(RemapColorsBlockRange), "ii", NULL },
+ { SIG_SCI32, 0, MAP_CALL(RemapOff), "(i)", NULL },
+ { SIG_SCI32, 1, MAP_CALL(RemapByRange), "iiii(i)", NULL },
+ { SIG_SCI32, 2, MAP_CALL(RemapByPercent), "ii(i)", NULL },
+ { SIG_SCI32, 3, MAP_CALL(RemapToGray), "ii(i)", NULL },
+ { SIG_SCI32, 4, MAP_CALL(RemapToPercentGray), "iii(i)", NULL },
+ { SIG_SCI32, 5, MAP_CALL(RemapSetNoMatchRange), "ii", NULL },
SCI_SUBOPENTRY_TERMINATOR
};
@@ -634,9 +634,9 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL },
{ MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, kReadNumber_workarounds },
- { MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
+ { "RemapColors", kRemapColors16, SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
#ifdef ENABLE_SCI32
- { "RemapColors", kRemapColors32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", kRemapColors_subops, NULL },
+ { MAP_CALL(RemapColors), SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", kRemapColors_subops, NULL },
#endif
{ MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL },
{ MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index cae5a09..73236b9 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -1258,7 +1258,7 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) {
}
// Early variant of the SCI32 kRemapColors kernel function, used in the demo of QFG4
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv) {
uint16 operation = argv[0].toUint16();
switch (operation) {
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 019a069..9270c81 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -54,7 +54,6 @@
#include "sci/graphics/frameout.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
#include "sci/graphics/text32.h"
#endif
@@ -926,69 +925,57 @@ reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
if (!s)
return make_reg(0, getSciVersion());
error("not supposed to call this");
}
-reg_t kRemapColorsOff(EngineState *s, int argc, reg_t *argv) {
- if (argc == 0) {
- g_sci->_gfxRemap32->remapAllOff();
- } else {
- const uint8 color = argv[0].toUint16();
- g_sci->_gfxRemap32->remapOff(color);
- }
+reg_t kRemapOff(EngineState *s, int argc, reg_t *argv) {
+ byte color = (argc >= 1) ? argv[0].toUint16() : 0;
+ g_sci->_gfxRemap32->remapOff(color);
return s->r_acc;
}
-reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv) {
- const uint8 color = argv[0].toUint16();
- const int16 from = argv[1].toSint16();
- const int16 to = argv[2].toSint16();
- const int16 base = argv[3].toSint16();
- // NOTE: There is an optional last parameter after `base`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
- g_sci->_gfxRemap32->remapByRange(color, from, to, base);
+reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte from = argv[1].toUint16();
+ byte to = argv[2].toUint16();
+ byte base = argv[3].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingRange(color, from, to, base);
return s->r_acc;
}
-reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv) {
- const uint8 color = argv[0].toUint16();
- const int16 percent = argv[1].toSint16();
- // NOTE: There is an optional last parameter after `percent`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
- g_sci->_gfxRemap32->remapByPercent(color, percent);
+reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte percent = argv[1].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingPercent(color, percent);
return s->r_acc;
}
-reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv) {
- const uint8 color = argv[0].toUint16();
- const int16 gray = argv[1].toSint16();
- // NOTE: There is an optional last parameter after `gray`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
- g_sci->_gfxRemap32->remapToGray(color, gray);
+reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte gray = argv[1].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingToGray(color, gray);
return s->r_acc;
}
-reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv) {
- const uint8 color = argv[0].toUint16();
- const int16 gray = argv[1].toSint16();
- const int16 percent = argv[2].toSint16();
- // NOTE: There is an optional last parameter after `percent`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
- g_sci->_gfxRemap32->remapToPercentGray(color, gray, percent);
+reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte gray = argv[1].toUint16();
+ byte percent = argv[2].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingToPercentGray(color, gray, percent);
return s->r_acc;
}
-reg_t kRemapColorsBlockRange(EngineState *s, int argc, reg_t *argv) {
- const uint8 from = argv[0].toUint16();
- const uint8 count = argv[1].toUint16();
- g_sci->_gfxRemap32->blockRange(from, count);
+reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv) {
+ byte from = argv[0].toUint16();
+ byte count = argv[1].toUint16();
+ g_sci->_gfxRemap32->setNoMatchRange(from, count);
return s->r_acc;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 0972aec..302f046 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -48,9 +48,8 @@
#include "sci/sound/music.h"
#ifdef ENABLE_SCI32
-#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
+#include "sci/graphics/frameout.h"
#endif
namespace Sci {
@@ -808,33 +807,6 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
-
-void GfxRemap32::saveLoadWithSerializer(Common::Serializer &s) {
- if (s.getVersion() < 35) {
- return;
- }
-
- s.syncAsByte(_numActiveRemaps);
- s.syncAsByte(_blockedRangeStart);
- s.syncAsSint16LE(_blockedRangeCount);
-
- for (uint i = 0; i < _remaps.size(); ++i) {
- SingleRemap &singleRemap = _remaps[i];
- s.syncAsByte(singleRemap._type);
- if (s.isLoading() && singleRemap._type != kRemapNone) {
- singleRemap.reset();
- }
- s.syncAsByte(singleRemap._from);
- s.syncAsByte(singleRemap._to);
- s.syncAsByte(singleRemap._delta);
- s.syncAsByte(singleRemap._percent);
- s.syncAsByte(singleRemap._gray);
- }
-
- if (s.isLoading()) {
- _needsUpdate = true;
- }
-}
#endif
void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 43909ac..459e992 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,7 +37,6 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
- * 35 - SCI32 remap
* 34 - SCI32 palettes, and store play time in ticks
* 33 - new overridePriority flag in MusicEntry
* 32 - new playBed flag in MusicEntry
@@ -60,7 +59,7 @@ struct EngineState;
*/
enum {
- CURRENT_SAVEGAME_VERSION = 35,
+ CURRENT_SAVEGAME_VERSION = 34,
MINIMUM_SAVEGAME_VERSION = 14
};
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index befa5cd..3018c6b 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -26,12 +26,13 @@
#include "sci/graphics/celobj32.h"
#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
+#include "sci/graphics/picture.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/text32.h"
+#include "sci/graphics/view.h"
namespace Sci {
#pragma mark CelScaler
-
CelScaler *CelObj::_scaler = nullptr;
void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) {
@@ -322,10 +323,6 @@ public:
#pragma mark -
#pragma mark CelObj - Remappers
-/**
- * Pixel mapper for a CelObj with transparent pixels and no
- * remapping data.
- */
struct MAPPER_NoMD {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
if (pixel != skipColor) {
@@ -333,49 +330,25 @@ struct MAPPER_NoMD {
}
}
};
-
-/**
- * Pixel mapper for a CelObj with no transparent pixels and
- * no remapping data.
- */
struct MAPPER_NoMDNoSkip {
inline void draw(byte *target, const byte pixel, const uint8) const {
*target = pixel;
}
};
-/**
- * Pixel mapper for a CelObj with transparent pixels,
- * remapping data, and remapping enabled.
- */
struct MAPPER_Map {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
if (pixel != skipColor) {
- // NOTE: For some reason, SSCI never checks if the source
- // pixel is *above* the range of remaps.
if (pixel < g_sci->_gfxRemap32->getStartColor()) {
*target = pixel;
- } else if (g_sci->_gfxRemap32->remapEnabled(pixel)) {
- *target = g_sci->_gfxRemap32->remapColor(pixel, *target);
+ } else {
+ if (g_sci->_gfxRemap32->remapEnabled(pixel))
+ *target = g_sci->_gfxRemap32->remapColor(pixel, *target);
}
}
}
};
-/**
- * Pixel mapper for a CelObj with transparent pixels,
- * remapping data, and remapping disabled.
- */
-struct MAPPER_NoMap {
- inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
- // NOTE: For some reason, SSCI never checks if the source
- // pixel is *above* the range of remaps.
- if (pixel != skipColor && pixel < g_sci->_gfxRemap32->getStartColor()) {
- *target = pixel;
- }
- }
-};
-
void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect) const {
const Common::Point &scaledPosition = screenItem._scaledPosition;
const Ratio &scaleX = screenItem._ratioX;
@@ -550,7 +523,6 @@ void CelObj::submitPalette() const {
#pragma mark -
#pragma mark CelObj - Caching
-
int CelObj::_nextCacheId = 1;
CelCache *CelObj::_cache = nullptr;
@@ -652,35 +624,33 @@ void dummyFill(Buffer &target, const Common::Rect &targetRect) {
}
void CelObj::drawHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- render<MAPPER_NoMap, SCALER_NoScale<true, READER_Compressed> >(target, targetRect, scaledPosition);
+ debug("drawHzFlip");
+ dummyFill(target, targetRect);
}
void CelObj::drawNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- render<MAPPER_NoMap, SCALER_NoScale<false, READER_Compressed> >(target, targetRect, scaledPosition);
+ debug("drawNoFlip");
+ dummyFill(target, targetRect);
}
void CelObj::drawUncompNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- render<MAPPER_NoMap, SCALER_NoScale<false, READER_Uncompressed> >(target, targetRect, scaledPosition);
+ debug("drawUncompNoFlip");
+ dummyFill(target, targetRect);
}
void CelObj::drawUncompHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- render<MAPPER_NoMap, SCALER_NoScale<true, READER_Uncompressed> >(target, targetRect, scaledPosition);
+ debug("drawUncompHzFlip");
+ dummyFill(target, targetRect);
}
void CelObj::scaleDraw(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored) {
- render<MAPPER_NoMap, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- } else {
- render<MAPPER_NoMap, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- }
+ debug("scaleDraw");
+ dummyFill(target, targetRect);
}
void CelObj::scaleDrawUncomp(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored) {
- render<MAPPER_NoMap, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- } else {
- render<MAPPER_NoMap, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- }
+ debug("scaleDrawUncomp");
+ dummyFill(target, targetRect);
}
void CelObj::drawHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
@@ -700,19 +670,17 @@ void CelObj::drawUncompHzFlipMap(Buffer &target, const Common::Rect &targetRect,
}
void CelObj::scaleDrawMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored) {
+ if (_drawMirrored)
render<MAPPER_Map, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- } else {
+ else
render<MAPPER_Map, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- }
}
void CelObj::scaleDrawUncompMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored) {
+ if (_drawMirrored)
render<MAPPER_Map, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- } else {
+ else
render<MAPPER_Map, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- }
}
void CelObj::drawNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
@@ -747,16 +715,14 @@ void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &sca
}
void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored) {
+ if (_drawMirrored)
render<MAPPER_NoMD, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- } else {
+ else
render<MAPPER_NoMD, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- }
}
#pragma mark -
#pragma mark CelObjView
-
CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) {
_info.type = kCelTypeView;
_info.resourceId = viewId;
@@ -874,12 +840,8 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
bool CelObjView::analyzeUncompressedForRemap() const {
byte *pixels = getResPointer() + READ_SCI11ENDIAN_UINT32(getResPointer() + _celHeaderOffset + 24);
for (int i = 0; i < _width * _height; ++i) {
- const byte pixel = pixels[i];
- if (
- pixel >= g_sci->_gfxRemap32->getStartColor() &&
- pixel <= g_sci->_gfxRemap32->getEndColor() &&
- pixel != _transparentColor
- ) {
+ byte pixel = pixels[i];
+ if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
return true;
}
}
@@ -891,12 +853,8 @@ bool CelObjView::analyzeForRemap() const {
for (int y = 0; y < _height; y++) {
const byte *curRow = reader.getRow(y);
for (int x = 0; x < _width; x++) {
- const byte pixel = curRow[x];
- if (
- pixel >= g_sci->_gfxRemap32->getStartColor() &&
- pixel <= g_sci->_gfxRemap32->getEndColor() &&
- pixel != _transparentColor
- ) {
+ byte pixel = curRow[x];
+ if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
return true;
}
}
@@ -923,7 +881,6 @@ byte *CelObjView::getResPointer() const {
#pragma mark -
#pragma mark CelObjPic
-
CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
_info.type = kCelTypePic;
_info.resourceId = picId;
@@ -1045,7 +1002,6 @@ byte *CelObjPic::getResPointer() const {
#pragma mark -
#pragma mark CelObjMem
-
CelObjMem::CelObjMem(const reg_t bitmapObject) {
_info.type = kCelTypeMem;
_info.bitmap = bitmapObject;
@@ -1075,7 +1031,6 @@ byte *CelObjMem::getResPointer() const {
#pragma mark -
#pragma mark CelObjColor
-
CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 height) {
_info.type = kCelTypeColor;
_info.color = color;
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index fd37020..5771ab5 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -42,13 +42,15 @@
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/font.h"
+#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
+#include "sci/graphics/picture.h"
+#include "sci/graphics/remap.h"
+#include "sci/graphics/text32.h"
#include "sci/graphics/plane32.h"
-#include "sci/graphics/remap32.h"
#include "sci/graphics/screen_item32.h"
-#include "sci/graphics/text32.h"
#include "sci/graphics/frameout.h"
#include "sci/video/robot_decoder.h"
@@ -1005,7 +1007,7 @@ void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showLi
}
void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) {
- Palette sourcePalette(_palette->getNextPalette());
+ Palette sourcePalette(*_palette->getNextPalette());
alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16();
@@ -1045,7 +1047,7 @@ void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry
drawScreenItemList(screenItemLists[i]);
}
- Palette nextPalette(_palette->getNextPalette());
+ Palette nextPalette(*_palette->getNextPalette());
if (prevRoom < 1000) {
for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 0840e82..6844011 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -28,7 +28,7 @@
#include "sci/event.h"
#include "sci/resource.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
namespace Sci {
@@ -78,6 +78,10 @@ inline void mergePaletteInternal(Palette *const to, const Palette *const from) {
}
}
+const Palette *GfxPalette32::getNextPalette() const {
+ return &_nextPalette;
+}
+
void GfxPalette32::submit(Palette &palette) {
// TODO: The resource manager in SCI32 retains raw data of palettes from
// the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and
@@ -174,6 +178,49 @@ void GfxPalette32::set(Palette *newPalette, bool force, bool forceRealMerge) {
submit(*newPalette);
}
+// In SCI32 engine this method is SOLPalette::Match(Rgb24 *, int, int *, int *)
+// and is used by Remap
+// TODO: Anything that calls GfxPalette::matchColor(int, int, int) is going to
+// match using an algorithm from SCI16 engine right now. This needs to be
+// corrected in the future so either nothing calls
+// GfxPalette::matchColor(int, int, int), or it is fixed to match the other
+// SCI32 algorithms.
+int16 GfxPalette32::matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) {
+ int16 bestIndex = -1;
+ int bestDifference = 0xFFFFF;
+ int difference = defaultDifference;
+
+ // SQ6 DOS really does check only the first 236 entries
+ for (int i = 0, channelDifference; i < 236; ++i) {
+ if (matchTable[i] == 0) {
+ continue;
+ }
+
+ difference = _sysPalette.colors[i].r - r;
+ difference *= difference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ channelDifference = _sysPalette.colors[i].g - g;
+ difference += channelDifference * channelDifference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ channelDifference = _sysPalette.colors[i].b - b;
+ difference += channelDifference * channelDifference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ bestDifference = difference;
+ bestIndex = i;
+ }
+
+ // NOTE: This value is only valid if the last index to
+ // perform a difference calculation was the best index
+ lastCalculatedDifference = difference;
+ return bestIndex;
+}
+
bool GfxPalette32::updateForFrame() {
applyAll();
_versionUpdated = false;
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index 7dda53e..1902d00 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -113,12 +113,12 @@ private:
public:
virtual void saveLoadWithSerializer(Common::Serializer &s) override;
- inline const Palette &getNextPalette() const { return _nextPalette; };
- inline const Palette &getCurrentPalette() const { return _sysPalette; };
+ const Palette *getNextPalette() const;
bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
void set(Palette *newPalette, bool force, bool forceRealMerge = false) override;
+ int16 matchColor(const byte matchRed, const byte matchGreen, const byte matchBlue, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable);
/**
* Submits a palette to display. Entries marked as “used” in the
@@ -240,11 +240,6 @@ private:
* 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 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).
*/
bool _cycleMap[256];
inline void clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
@@ -262,7 +257,7 @@ public:
void cycleAllOff();
void applyAllCycles();
void applyCycles();
- inline const bool *getCycleMap() const { return _cycleMap; }
+ const bool *getCyclemap() { return _cycleMap; }
#pragma mark -
#pragma mark Fading
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 175875c..6f5ad42 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -27,7 +27,7 @@
#include "sci/graphics/frameout.h"
#include "sci/graphics/lists32.h"
#include "sci/graphics/plane32.h"
-#include "sci/graphics/remap32.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/screen_item32.h"
diff --git a/engines/sci/graphics/remap.cpp b/engines/sci/graphics/remap.cpp
index 2abf03e..ff49e52 100644
--- a/engines/sci/graphics/remap.cpp
+++ b/engines/sci/graphics/remap.cpp
@@ -21,23 +21,31 @@
*/
#include "sci/sci.h"
+#include "sci/resource.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/palette32.h"
#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
namespace Sci {
+#pragma mark -
+#pragma mark SCI16 remapping (QFG4 demo)
+
GfxRemap::GfxRemap(GfxPalette *palette)
: _palette(palette) {
_remapOn = false;
resetRemapping();
}
+GfxRemap::~GfxRemap() {
+}
+
byte GfxRemap::remapColor(byte remappedColor, byte screenColor) {
assert(_remapOn);
- if (_remappingType[remappedColor] == kRemapByRange)
+ if (_remappingType[remappedColor] == kRemappingByRange)
return _remappingByRange[screenColor];
- else if (_remappingType[remappedColor] == kRemapByPercent)
+ else if (_remappingType[remappedColor] == kRemappingByPercent)
return _remappingByPercent[screenColor];
else
error("remapColor(): Color %d isn't remapped", remappedColor);
@@ -50,7 +58,7 @@ void GfxRemap::resetRemapping() {
_remappingPercentToSet = 0;
for (int i = 0; i < 256; i++) {
- _remappingType[i] = kRemapNone;
+ _remappingType[i] = kRemappingNone;
_remappingByPercent[i] = i;
_remappingByRange[i] = i;
}
@@ -72,7 +80,7 @@ void GfxRemap::setRemappingPercent(byte color, byte percent) {
_remappingByPercent[i] = _palette->kernelFindColor(r, g, b);
}
- _remappingType[color] = kRemapByPercent;
+ _remappingType[color] = kRemappingByPercent;
}
void GfxRemap::setRemappingRange(byte color, byte from, byte to, byte base) {
@@ -82,7 +90,7 @@ void GfxRemap::setRemappingRange(byte color, byte from, byte to, byte base) {
_remappingByRange[i] = i + base;
}
- _remappingType[color] = kRemapByRange;
+ _remappingType[color] = kRemappingByRange;
}
void GfxRemap::updateRemapping() {
@@ -96,4 +104,277 @@ void GfxRemap::updateRemapping() {
}
}
}
+
+#pragma mark -
+#pragma mark SCI32 remapping
+
+#ifdef ENABLE_SCI32
+
+GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _noMapStart = _noMapCount = 0;
+ _update = false;
+ _remapCount = 0;
+
+ // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle.
+ // All versions of KQ7 are using the older remap range semantics.
+ _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) ? 244 : 254;
+}
+
+void GfxRemap32::remapOff(byte color) {
+ if (!color) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+
+ _remapCount = 0;
+ } else {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remapCount--;
+ }
+
+ _update = true;
+}
+
+void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingPercent(byte color, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToGray(byte color, byte gray) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setNoMatchRange(byte from, byte count) {
+ _noMapStart = from;
+ _noMapCount = count;
+}
+
+bool GfxRemap32::remapEnabled(byte color) const {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ return (_remaps[index].type != kRemappingNone);
+}
+
+byte GfxRemap32::remapColor(byte color, byte target) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ if (_remaps[index].type != kRemappingNone)
+ return _remaps[index].remap[target];
+ else
+ return target;
+}
+
+void GfxRemap32::initColorArrays(byte index) {
+ Palette *curPalette = &_palette->_sysPalette;
+ RemapParams *curRemap = &_remaps[index];
+
+ memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+ memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+}
+
+bool GfxRemap32::updateRemap(byte index, bool palChanged) {
+ int result;
+ RemapParams *curRemap = &_remaps[index];
+ const Palette *curPalette = &_palette->_sysPalette;
+ const Palette *nextPalette = _palette->getNextPalette();
+ bool changed = false;
+
+ if (!_update && !palChanged)
+ return false;
+
+ Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
+
+ switch (curRemap->type) {
+ case kRemappingNone:
+ return false;
+ case kRemappingByRange:
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (curRemap->from <= i && i <= curRemap->to)
+ result = i + curRemap->base;
+ else
+ result = i;
+
+ if (curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ }
+
+ curRemap->colorChanged[i] = true;
+ }
+ return changed;
+ case kRemappingByPercent:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ // NOTE: This method uses nextPalette instead of curPalette
+ Color color = nextPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) {
+ byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255);
+ byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255);
+ byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ return changed;
+ case kRemappingToGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ case kRemappingToPercentGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ lumosity = lumosity * curRemap->percent / 100;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ default:
+ return false;
+ }
+}
+
+static int colorDistance(Color a, Color b) {
+ int rDiff = (a.r - b.r) * (a.r - b.r);
+ int gDiff = (a.g - b.g) * (a.g - b.g);
+ int bDiff = (a.b - b.b) * (a.b - b.b);
+ return rDiff + gDiff + bDiff;
+}
+
+bool GfxRemap32::applyRemap(byte index) {
+ RemapParams *curRemap = &_remaps[index];
+ const bool *cycleMap = _palette->getCyclemap();
+ bool unmappedColors[NON_REMAPPED_COLOR_COUNT];
+ bool changed = false;
+
+ Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false);
+ if (_noMapCount)
+ Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true);
+
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (cycleMap[i])
+ unmappedColors[i] = true;
+ }
+
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color targetColor = curRemap->targetColor[i];
+ bool colorChanged = curRemap->colorChanged[curRemap->remap[i]];
+
+ if (!_targetChanged[i] && !colorChanged)
+ continue;
+
+ if (_targetChanged[i] && colorChanged)
+ if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i])
+ continue;
+
+ int diff = 0;
+ int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
+ if (result != -1 && curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ curRemap->distance[i] = diff;
+ }
+ }
+
+ return changed;
+}
+
+bool GfxRemap32::remapAllTables(bool palChanged) {
+ bool changed = false;
+
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++) {
+ changed |= updateRemap(i, palChanged);
+ }
+
+ _update = false;
+ return changed;
+}
+
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/remap.h b/engines/sci/graphics/remap.h
index 98177f6..d012568 100644
--- a/engines/sci/graphics/remap.h
+++ b/engines/sci/graphics/remap.h
@@ -24,36 +24,42 @@
#define SCI_GRAPHICS_REMAP_H
#include "common/array.h"
-#include "common/serializer.h"
+#include "sci/graphics/helpers.h"
namespace Sci {
class GfxScreen;
+enum ColorRemappingType {
+ kRemappingNone = 0,
+ kRemappingByRange = 1,
+ kRemappingByPercent = 2,
+ kRemappingToGray = 3,
+ kRemappingToPercentGray = 4
+};
+
+#define REMAP_COLOR_COUNT 9
+#define NON_REMAPPED_COLOR_COUNT 236
+
/**
- * This class handles color remapping for the QFG4 demo.
+ * Remap class, handles color remapping
*/
class GfxRemap {
-private:
- enum ColorRemappingType {
- kRemapNone = 0,
- kRemapByRange = 1,
- kRemapByPercent = 2
- };
-
public:
GfxRemap(GfxPalette *_palette);
+ ~GfxRemap();
void resetRemapping();
void setRemappingPercent(byte color, byte percent);
void setRemappingRange(byte color, byte from, byte to, byte base);
bool isRemapped(byte color) const {
- return _remapOn && (_remappingType[color] != kRemapNone);
+ return _remapOn && (_remappingType[color] != kRemappingNone);
}
byte remapColor(byte remappedColor, byte screenColor);
void updateRemapping();
private:
+ GfxScreen *_screen;
GfxPalette *_palette;
bool _remapOn;
@@ -62,6 +68,87 @@ private:
byte _remappingByRange[256];
uint16 _remappingPercentToSet;
};
+
+#ifdef ENABLE_SCI32
+
+struct RemapParams {
+ byte from;
+ byte to;
+ byte base;
+ byte gray;
+ byte oldGray;
+ byte percent;
+ byte oldPercent;
+ ColorRemappingType type;
+ Color curColor[256];
+ Color targetColor[256];
+ byte distance[256];
+ byte remap[256];
+ bool colorChanged[256];
+
+ RemapParams() {
+ from = to = base = gray = oldGray = percent = oldPercent = 0;
+ type = kRemappingNone;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+
+ RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, ColorRemappingType type_) {
+ from = from_;
+ to = to_;
+ base = base_;
+ gray = oldGray = gray_;
+ percent = oldPercent = percent_;
+ type = type_;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+};
+
+class GfxRemap32 {
+public:
+ GfxRemap32(GfxPalette32 *palette);
+ ~GfxRemap32() {}
+
+ void remapOff(byte color);
+ void setRemappingRange(byte color, byte from, byte to, byte base);
+ void setRemappingPercent(byte color, byte percent);
+ void setRemappingToGray(byte color, byte gray);
+ void setRemappingToPercentGray(byte color, byte gray, byte percent);
+ void setNoMatchRange(byte from, byte count);
+ bool remapEnabled(byte color) const;
+ byte remapColor(byte color, byte target);
+ bool remapAllTables(bool palChanged);
+ int getRemapCount() const { return _remapCount; }
+ int getStartColor() const { return _remapEndColor - REMAP_COLOR_COUNT + 1; }
+ int getEndColor() const { return _remapEndColor; }
+private:
+ GfxPalette32 *_palette;
+ RemapParams _remaps[REMAP_COLOR_COUNT];
+ bool _update;
+ byte _noMapStart, _noMapCount;
+ bool _targetChanged[NON_REMAPPED_COLOR_COUNT];
+ byte _remapEndColor;
+ int _remapCount;
+
+ void initColorArrays(byte index);
+ bool applyRemap(byte index);
+ bool updateRemap(byte index, bool palChanged);
+};
+#endif
+
} // End of namespace Sci
#endif
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
deleted file mode 100644
index d5a2362..0000000
--- a/engines/sci/graphics/remap32.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "sci/sci.h"
-#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
-
-namespace Sci {
-
-#pragma mark SingleRemap
-
-void SingleRemap::reset() {
- _lastPercent = 100;
- _lastGray = 0;
-
- const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
- const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
- for (uint i = 0; i < remapStartColor; ++i) {
- const Color &color = currentPalette.colors[i];
- _remapColors[i] = i;
- _originalColors[i] = color;
- _originalColorsChanged[i] = true;
- _idealColors[i] = color;
- _idealColorsChanged[i] = false;
- _matchDistances[i] = 0;
- }
-}
-
-bool SingleRemap::update() {
- switch (_type) {
- case kRemapNone:
- break;
- case kRemapByRange:
- return updateRange();
- case kRemapByPercent:
- return updateBrightness();
- case kRemapToGray:
- return updateSaturation();
- case kRemapToPercentGray:
- return updateSaturationAndBrightness();
- default:
- error("Illegal remap type %d", _type);
- }
-
- return false;
-}
-
-bool SingleRemap::updateRange() {
- const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
- bool updated = false;
-
- for (uint i = 0; i < remapStartColor; ++i) {
- uint8 targetColor;
- if (_from <= i && i <= _to) {
- targetColor = i + _delta;
- } else {
- targetColor = i;
- }
-
- if (_remapColors[i] != targetColor) {
- updated = true;
- _remapColors[i] = targetColor;
- }
-
- _originalColorsChanged[i] = true;
- }
-
- return updated;
-}
-
-bool SingleRemap::updateBrightness() {
- const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
- const Palette &nextPalette = g_sci->_gfxPalette32->getNextPalette();
- for (uint i = 1; i < remapStartColor; ++i) {
- Color color(nextPalette.colors[i]);
-
- if (_originalColors[i] != color) {
- _originalColorsChanged[i] = true;
- _originalColors[i] = color;
- }
-
- if (_percent != _lastPercent || _originalColorsChanged[i]) {
- // NOTE: SSCI checked if percent was over 100 and only
- // then clipped values, but we always unconditionally
- // ensure the result is in the correct range
- color.r = MIN(255, (uint16)color.r * _percent / 100);
- color.g = MIN(255, (uint16)color.g * _percent / 100);
- color.b = MIN(255, (uint16)color.b * _percent / 100);
-
- if (_idealColors[i] != color) {
- _idealColorsChanged[i] = true;
- _idealColors[i] = color;
- }
- }
- }
-
- const bool updated = apply();
- Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
- Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
- _lastPercent = _percent;
- return updated;
-}
-
-bool SingleRemap::updateSaturation() {
- const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
- const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
- for (uint i = 1; i < remapStartColor; ++i) {
- Color color(currentPalette.colors[i]);
- if (_originalColors[i] != color) {
- _originalColorsChanged[i] = true;
- _originalColors[i] = color;
- }
-
- if (_gray != _lastGray || _originalColorsChanged[i]) {
- const int luminosity = (((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8) * _percent / 100;
-
- color.r = MIN(255, color.r - ((color.r - luminosity) * _gray / 100));
- color.g = MIN(255, color.g - ((color.g - luminosity) * _gray / 100));
- color.b = MIN(255, color.b - ((color.b - luminosity) * _gray / 100));
-
- if (_idealColors[i] != color) {
- _idealColorsChanged[i] = true;
- _idealColors[i] = color;
- }
- }
- }
-
- const bool updated = apply();
- Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
- Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
- _lastGray = _gray;
- return updated;
-}
-
-bool SingleRemap::updateSaturationAndBrightness() {
- const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
- const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
- for (uint i = 1; i < remapStartColor; i++) {
- Color color(currentPalette.colors[i]);
- if (_originalColors[i] != color) {
- _originalColorsChanged[i] = true;
- _originalColors[i] = color;
- }
-
- if (_percent != _lastPercent || _gray != _lastGray || _originalColorsChanged[i]) {
- const int luminosity = (((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8) * _percent / 100;
-
- color.r = MIN(255, color.r - ((color.r - luminosity) * _gray) / 100);
- color.g = MIN(255, color.g - ((color.g - luminosity) * _gray) / 100);
- color.b = MIN(255, color.b - ((color.b - luminosity) * _gray) / 100);
-
- if (_idealColors[i] != color) {
- _idealColorsChanged[i] = true;
- _idealColors[i] = color;
- }
- }
- }
-
- const bool updated = apply();
- Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
- Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
- _lastPercent = _percent;
- _lastGray = _gray;
- return updated;
-}
-
-bool SingleRemap::apply() {
- const GfxRemap32 *const gfxRemap32 = g_sci->_gfxRemap32;
- const uint8 remapStartColor = gfxRemap32->getStartColor();
-
- // Blocked colors are not allowed to be used as target
- // colors for the remap
- bool blockedColors[236];
- Common::fill(blockedColors, blockedColors + remapStartColor, false);
-
- const bool *const paletteCycleMap = g_sci->_gfxPalette32->getCycleMap();
-
- const int16 blockedRangeCount = gfxRemap32->getBlockedRangeCount();
- if (blockedRangeCount) {
- const uint8 blockedRangeStart = gfxRemap32->getBlockedRangeStart();
- Common::fill(blockedColors + blockedRangeStart, blockedColors + blockedRangeStart + blockedRangeCount, true);
- }
-
- for (uint i = 0; i < remapStartColor; ++i) {
- if (paletteCycleMap[i]) {
- blockedColors[i] = true;
- }
- }
-
- // NOTE: SSCI did a loop over colors here to create a
- // new array of updated, unblocked colors, but then
- // never used it
-
- bool updated = false;
- for (uint i = 1; i < remapStartColor; ++i) {
- int distance;
-
- if (!_idealColorsChanged[i] && !_originalColorsChanged[_remapColors[i]]) {
- continue;
- }
-
- if (
- _idealColorsChanged[i] &&
- _originalColorsChanged[_remapColors[i]] &&
- _matchDistances[i] < 100 &&
- colorDistance(_idealColors[i], _originalColors[_remapColors[i]]) <= _matchDistances[i]
- ) {
- continue;
- }
-
- const int16 bestColor = matchColor(_idealColors[i], _matchDistances[i], distance, blockedColors);
-
- if (bestColor != -1 && _remapColors[i] != bestColor) {
- updated = true;
- _remapColors[i] = bestColor;
- _matchDistances[i] = distance;
- }
- }
-
- return updated;
-}
-
-int SingleRemap::colorDistance(const Color &a, const Color &b) const {
- int channelDistance = a.r - b.r;
- int distance = channelDistance * channelDistance;
- channelDistance = a.g - b.g;
- distance += channelDistance * channelDistance;
- channelDistance = a.b - b.b;
- distance += channelDistance * channelDistance;
- return distance;
-}
-
-int16 SingleRemap::matchColor(const Color &color, const int minimumDistance, int &outDistance, const bool *const blockedIndexes) const {
- int16 bestIndex = -1;
- int bestDistance = 0xFFFFF;
- int distance = minimumDistance;
- const Palette &nextPalette = g_sci->_gfxPalette32->getNextPalette();
-
- for (uint i = 0, channelDistance; i < g_sci->_gfxRemap32->getStartColor(); ++i) {
- if (blockedIndexes[i]) {
- continue;
- }
-
- distance = nextPalette.colors[i].r - color.r;
- distance *= distance;
- if (bestDistance <= distance) {
- continue;
- }
- channelDistance = nextPalette.colors[i].g - color.g;
- distance += channelDistance * channelDistance;
- if (bestDistance <= distance) {
- continue;
- }
- channelDistance = nextPalette.colors[i].b - color.b;
- distance += channelDistance * channelDistance;
- if (bestDistance <= distance) {
- continue;
- }
- bestDistance = distance;
- bestIndex = i;
- }
-
- // This value is only valid if the last index to
- // perform a distance calculation was the best index
- outDistance = distance;
- return bestIndex;
-}
-
-#pragma mark -
-#pragma mark GfxRemap32
-
-GfxRemap32::GfxRemap32() :
- _needsUpdate(false),
- _blockedRangeStart(0),
- _blockedRangeCount(0),
- _remapStartColor(236),
- _numActiveRemaps(0) {
- // The `_remapStartColor` seems to always be 236 in SSCI,
- // but if it is ever changed then the various C-style
- // member arrays hard-coded to 236 need to be changed to
- // match the highest possible value of `_remapStartColor`
- assert(_remapStartColor == 236);
-
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) {
- _remaps.resize(9);
- } else {
- _remaps.resize(19);
- }
-
- _remapEndColor = _remapStartColor + _remaps.size() - 1;
-}
-
-void GfxRemap32::remapOff(const uint8 color) {
- if (color == 0) {
- remapAllOff();
- return;
- }
-
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
- if (color < _remapStartColor || color > _remapEndColor) {
- warning("GfxRemap32::remapOff: %d out of remap range", color);
- return;
- }
-
- const uint8 index = _remapEndColor - color;
- SingleRemap &singleRemap = _remaps[index];
- singleRemap._type = kRemapNone;
- --_numActiveRemaps;
- _needsUpdate = true;
-}
-
-void GfxRemap32::remapAllOff() {
- for (uint i = 0, len = _remaps.size(); i < len; ++i) {
- _remaps[i]._type = kRemapNone;
- }
-
- _numActiveRemaps = 0;
- _needsUpdate = true;
-}
-
-void GfxRemap32::remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
- if (color < _remapStartColor || color > _remapEndColor) {
- warning("GfxRemap32::remapByRange: %d out of remap range", color);
- return;
- }
-
- if (from < 0) {
- warning("GfxRemap32::remapByRange: attempt to remap negative color %d", from);
- return;
- }
-
- if (to >= _remapStartColor) {
- warning("GfxRemap32::remapByRange: attempt to remap into the remap zone at %d", to);
- return;
- }
-
- const uint8 index = _remapEndColor - color;
- SingleRemap &singleRemap = _remaps[index];
-
- if (singleRemap._type == kRemapNone) {
- ++_numActiveRemaps;
- singleRemap.reset();
- }
-
- singleRemap._from = from;
- singleRemap._to = to;
- singleRemap._delta = delta;
- singleRemap._type = kRemapByRange;
- _needsUpdate = true;
-}
-
-void GfxRemap32::remapByPercent(const uint8 color, const int16 percent) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
- if (color < _remapStartColor || color > _remapEndColor) {
- warning("GfxRemap32::remapByPercent: %d out of remap range", color);
- return;
- }
-
- const uint8 index = _remapEndColor - color;
- SingleRemap &singleRemap = _remaps[index];
-
- if (singleRemap._type == kRemapNone) {
- ++_numActiveRemaps;
- singleRemap.reset();
- }
-
- singleRemap._percent = percent;
- singleRemap._type = kRemapByPercent;
- _needsUpdate = true;
-}
-
-void GfxRemap32::remapToGray(const uint8 color, const int8 gray) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
- if (color < _remapStartColor || color > _remapEndColor) {
- warning("GfxRemap32::remapToGray: %d out of remap range", color);
- return;
- }
-
- if (gray < 0 || gray > 100) {
- error("RemapToGray percent out of range; gray = %d", gray);
- }
-
- const uint8 index = _remapEndColor - color;
- SingleRemap &singleRemap = _remaps[index];
-
- if (singleRemap._type == kRemapNone) {
- ++_numActiveRemaps;
- singleRemap.reset();
- }
-
- singleRemap._gray = gray;
- singleRemap._type = kRemapToGray;
- _needsUpdate = true;
-}
-
-void GfxRemap32::remapToPercentGray(const uint8 color, const int16 gray, const int16 percent) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
- if (color < _remapStartColor || color > _remapEndColor) {
- warning("GfxRemap32::remapToPercentGray: %d out of remap range", color);
- return;
- }
-
- const uint8 index = _remapEndColor - color;
- SingleRemap &singleRemap = _remaps[index];
-
- if (singleRemap._type == kRemapNone) {
- ++_numActiveRemaps;
- singleRemap.reset();
- }
-
- singleRemap._percent = percent;
- singleRemap._gray = gray;
- singleRemap._type = kRemapToPercentGray;
- _needsUpdate = true;
-}
-
-void GfxRemap32::blockRange(const uint8 from, const int16 count) {
- _blockedRangeStart = from;
- _blockedRangeCount = count;
-}
-
-bool GfxRemap32::remapAllTables(const bool paletteUpdated) {
- if (!_needsUpdate && !paletteUpdated) {
- return false;
- }
-
- bool updated = false;
-
- for (SingleRemapsList::iterator it = _remaps.begin(); it != _remaps.end(); ++it) {
- if (it->_type != kRemapNone) {
- updated |= it->update();
- }
- }
-
- _needsUpdate = false;
- return updated;
-}
-} // End of namespace Sci
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
deleted file mode 100644
index 5f629d7..0000000
--- a/engines/sci/graphics/remap32.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCI_GRAPHICS_REMAP32_H
-#define SCI_GRAPHICS_REMAP32_H
-
-#include "common/algorithm.h"
-#include "common/array.h"
-#include "common/scummsys.h"
-#include "sci/graphics/helpers.h"
-
-namespace Sci {
-class GfxPalette32;
-
-enum RemapType {
- kRemapNone = 0,
- kRemapByRange = 1,
- kRemapByPercent = 2,
- kRemapToGray = 3,
- kRemapToPercentGray = 4
-};
-
-#pragma mark -
-#pragma mark SingleRemap
-
-/**
- * SingleRemap objects each manage one remapping operation.
- */
-class SingleRemap {
-public:
- SingleRemap() : _type(kRemapNone) {}
-
- /**
- * The type of remap.
- */
- RemapType _type;
-
- /**
- * The first color that should be shifted by a range
- * remap.
- */
- uint8 _from;
-
- /**
- * The last color that should be shifted a range remap.
- */
- uint8 _to;
-
- /**
- * The direction and amount that the colors should be
- * shifted in a range remap.
- */
- int16 _delta;
-
- /**
- * The difference in brightness that should be
- * applied by a brightness (percent) remap.
- *
- * This value may be be greater than 100, in
- * which case the color will be oversaturated.
- */
- int16 _percent;
-
- /**
- * The amount of desaturation that should be
- * applied by a saturation (gray) remap, where
- * 0 is full saturation and 100 is full
- * desaturation.
- */
- uint8 _gray;
-
- /**
- * The final array used by CelObj renderers to composite
- * remapped pixels to the screen buffer.
- *
- * Here is how it works:
- *
- * The source bitmap being rendered will have pixels
- * within the remap range (236-245 or 236-254), and the
- * target buffer will have colors in the non-remapped
- * range (0-235).
- *
- * To arrive at the correct color, first the source
- * pixel is used to look up the correct SingleRemap for
- * that pixel. Then, the final composited color is
- * looked up in this array using the target's pixel
- * color. In other words,
- * `target = _remaps[remapEndColor - source].remapColors[target]`.
- */
- uint8 _remapColors[236];
-
- /**
- * Resets this SingleRemap's color information to
- * default values.
- */
- void reset();
-
- /**
- * Recalculates and reapplies remap colors to the
- * `_remapColors` array.
- */
- bool update();
-
-private:
- /**
- * The previous brightness value. Used to
- * determine whether or not targetColors needs
- * to be updated.
- */
- int16 _lastPercent;
-
- /**
- * The previous saturation value. Used to
- * determine whether or not targetColors needs
- * to be updated.
- */
- uint8 _lastGray;
-
- /**
- * The colors from the current GfxPalette32 palette
- * before this SingleRemap is applied.
- */
- Color _originalColors[236];
-
- /**
- * Map of colors that changed in `_originalColors`
- * when this SingleRemap was updated. This map is
- * transient and gets reset to `false` after the
- * SingleRemap finishes updating.
- */
- bool _originalColorsChanged[236];
-
- /**
- * The ideal target RGB color values for each generated
- * remap color.
- */
- Color _idealColors[236];
-
- /**
- * Map of colors that changed in `_idealColors` when
- * this SingleRemap was updated. This map is transient
- * and gets reset to `false` after the SingleRemap
- * finishes applying.
- */
- bool _idealColorsChanged[236];
-
- /**
- * When applying a SingleRemap, finding an appropriate
- * color in the palette is the responsibility of a
- * distance function. Once a match is found, the
- * distance of that match is stored here so that the
- * next time the SingleRemap is applied, it can check
- * the distance from the previous application and avoid
- * triggering an expensive redraw of the entire screen
- * if the new palette value only changed slightly.
- */
- int _matchDistances[236];
-
- /**
- * Computes the final target values for a range remap
- * and applies them directly to the `_remaps` map.
- *
- * @note Was ByRange in SSCI.
- */
- bool updateRange();
-
- /**
- * Computes the intermediate target values for a
- * brightness remap and applies them indirectly via
- * the `apply` method.
- *
- * @note Was ByPercent in SSCI.
- */
- bool updateBrightness();
-
- /**
- * Computes the intermediate target values for a
- * saturation remap and applies them indirectly via
- * the `apply` method.
- *
- * @note Was ToGray in SSCI.
- */
- bool updateSaturation();
-
- /**
- * Computes the intermediate target values for a
- * saturation + brightness bitmap and applies them
- * indirectly via the `apply` method.
- *
- * @note Was ToPercentGray in SSCI.
- */
- bool updateSaturationAndBrightness();
-
- /**
- * Computes and applies the final values to the
- * `_remaps` map.
- *
- * @note In SSCI, a boolean array of changed values
- * was passed into this method, but this was done by
- * creating arrays on the stack in the caller. Instead
- * of doing this, we simply add another member property
- * `_idealColorsChanged` and use that instead.
- */
- bool apply();
-
- /**
- * Calculates the square distance of two colors.
- *
- * @note In SSCI this method is Rgb24::Dist, but it is
- * only used by SingleRemap.
- */
- int colorDistance(const Color &a, const Color &b) const;
-
- /**
- * Finds the closest index in the next palette matching
- * the given RGB color. Returns -1 if no match can be
- * found that is closer than `minimumDistance`.
- *
- * @note In SSCI, this method is SOLPalette::Match, but
- * this particular signature is only used by
- * SingleRemap.
- */
- int16 matchColor(const Color &color, const int minimumDistance, int &outDistance, const bool *const blockedIndexes) const;
-};
-
-#pragma mark -
-#pragma mark GfxRemap32
-
-/**
- * This class provides color remapping support for SCI32
- * games.
- */
-class GfxRemap32 : public Common::Serializable {
-public:
- GfxRemap32();
-
- void saveLoadWithSerializer(Common::Serializer &s);
-
- inline uint8 getRemapCount() const { return _numActiveRemaps; }
- inline uint8 getStartColor() const { return _remapStartColor; }
- inline uint8 getEndColor() const { return _remapEndColor; }
- inline uint8 getBlockedRangeStart() const { return _blockedRangeStart; }
- inline int16 getBlockedRangeCount() const { return _blockedRangeCount; }
-
- /**
- * Turns off remapping of the given color. If `color` is
- * 0, all remaps are turned off.
- */
- void remapOff(const uint8 color);
-
- /**
- * Turns off all color remaps.
- */
- void remapAllOff();
-
- /**
- * Configures a SingleRemap for the remap color `color`.
- * The SingleRemap will shift palette colors between
- * `from` and `to` (inclusive) by `delta` palette
- * entries when the remap is applied.
- */
- void remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta);
-
- /**
- * Configures a SingleRemap for the remap color `color`
- * to modify the brightness of remapped colors by
- * `percent`.
- */
- void remapByPercent(const uint8 color, const int16 percent);
-
- /**
- * Configures a SingleRemap for the remap color `color`
- * to modify the saturation of remapped colors by
- * `gray`.
- */
- void remapToGray(const uint8 color, const int8 gray);
-
- /**
- * Configures a SingleRemap for the remap color `color`
- * to modify the brightness of remapped colors by
- * `percent`, and saturation of remapped colors by
- * `gray`.
- */
- void remapToPercentGray(const uint8 color, const int16 gray, const int16 percent);
-
- /**
- * Prevents GfxRemap32 from using the given range of
- * palette entries as potential remap targets.
- *
- * @NOTE Was DontMapToRange in SSCI.
- */
- void blockRange(const uint8 from, const int16 count);
-
- /**
- * Determines whether or not the given color has an
- * active remapper. If it does not, it is treated as a
- * skip color and the pixel is not drawn.
- *
- * @note SSCI uses a boolean array to decide whether a
- * a pixel is remapped, but it is possible to get the
- * same information from `_remaps`, as this function
- * does.
- * Presumably, the separate array was created for
- * performance reasons, since this is called a lot in
- * the most critical section of the renderer.
- */
- inline bool remapEnabled(uint8 color) const {
- const uint8 index = _remapEndColor - color;
- assert(index < _remaps.size());
- return (_remaps[index]._type != kRemapNone);
- }
-
- /**
- * Calculates the correct color for a target by looking
- * up the target color in the SingleRemap that controls
- * the given sourceColor. If there is no remap for the
- * given color, it will be treated as a skip color.
- */
- inline uint8 remapColor(const uint8 sourceColor, const uint8 targetColor) const {
- const uint8 index = _remapEndColor - sourceColor;
- assert(index < _remaps.size());
- const SingleRemap &singleRemap = _remaps[index];
- assert(singleRemap._type != kRemapNone);
- return singleRemap._remapColors[targetColor];
- }
-
- /**
- * Updates all active remaps in response to a palette
- * change or a remap settings change.
- *
- * `paletteChanged` is true if the next palette in
- * GfxPalette32 has been previously modified by other
- * palette operations.
- */
- bool remapAllTables(const bool paletteUpdated);
-
-private:
- typedef Common::Array<SingleRemap> SingleRemapsList;
-
- /**
- * The first index of the remap area in the system
- * palette.
- */
- const uint8 _remapStartColor;
-
- /**
- * The last index of the remap area in the system
- * palette.
- */
- uint8 _remapEndColor;
-
- /**
- * The number of currently active remaps.
- */
- uint8 _numActiveRemaps;
-
- /**
- * The list of SingleRemaps.
- */
- SingleRemapsList _remaps;
-
- /**
- * If true, indicates that one or more SingleRemaps were
- * reconfigured and all remaps need to be recalculated.
- */
- bool _needsUpdate;
-
- /**
- * The first color that is blocked from being used as a
- * remap target color.
- */
- uint8 _blockedRangeStart;
-
- /**
- * The size of the range of blocked colors. If zero,
- * all colors are potential targets for remapping.
- */
- int16 _blockedRangeCount;
-};
-} // End of namespace Sci
-#endif
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index 96b48c0..9159020 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -55,7 +55,6 @@ struct LoopInfo {
class GfxScreen;
class GfxPalette;
-class Resource;
/**
* View class, handles loading of view resources and drawing contained cels to screen
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 5d54e2a..ba6c853 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -88,7 +88,6 @@ MODULE_OBJS += \
graphics/paint32.o \
graphics/plane32.o \
graphics/palette32.o \
- graphics/remap32.o \
graphics/screen_item32.o \
graphics/text32.o \
sound/audio32.o \
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 41fa144..b80456c 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -65,10 +65,9 @@
#ifdef ENABLE_SCI32
#include "sci/graphics/controls32.h"
-#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap32.h"
#include "sci/graphics/text32.h"
+#include "sci/graphics/frameout.h"
#include "sci/sound/audio32.h"
#include "sci/video/robot_decoder.h"
#endif
@@ -700,7 +699,7 @@ void SciEngine::initGraphics() {
if (getSciVersion() >= SCI_VERSION_2) {
_gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen);
_gfxPalette16 = _gfxPalette32;
- _gfxRemap32 = new GfxRemap32();
+ _gfxRemap32 = new GfxRemap32(_gfxPalette32);
} else {
#endif
_gfxPalette16 = new GfxPalette(_resMan, _gfxScreen);
Commit: 5a3d8337a68cd74277beac0ed0e51610723f6265
https://github.com/scummvm/scummvm/commit/5a3d8337a68cd74277beac0ed0e51610723f6265
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Change kRemapColors naming for consistency
Changed paths:
engines/sci/engine/kernel.h
engines/sci/engine/kernel_tables.h
engines/sci/engine/kgraphics.cpp
engines/sci/engine/kgraphics32.cpp
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index b269e97..1202982 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -412,7 +412,7 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
reg_t kShow(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
reg_t kDummy(EngineState *s, int argc, reg_t *argv);
reg_t kEmpty(EngineState *s, int argc, reg_t *argv);
reg_t kStub(EngineState *s, int argc, reg_t *argv);
@@ -482,13 +482,13 @@ reg_t kScrollWindowDestroy(EngineState *s, int argc, reg_t *argv);
reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapOff(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsOff(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColorsBlockRange(EngineState *s, int argc, reg_t *argv);
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv);
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 19bee35..dacaafe 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -414,12 +414,12 @@ static const SciKernelMapSubEntry kList_subops[] = {
// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kRemapColors_subops[] = {
- { SIG_SCI32, 0, MAP_CALL(RemapOff), "(i)", NULL },
- { SIG_SCI32, 1, MAP_CALL(RemapByRange), "iiii(i)", NULL },
- { SIG_SCI32, 2, MAP_CALL(RemapByPercent), "ii(i)", NULL },
- { SIG_SCI32, 3, MAP_CALL(RemapToGray), "ii(i)", NULL },
- { SIG_SCI32, 4, MAP_CALL(RemapToPercentGray), "iii(i)", NULL },
- { SIG_SCI32, 5, MAP_CALL(RemapSetNoMatchRange), "ii", NULL },
+ { SIG_SCI32, 0, MAP_CALL(RemapColorsOff), "(i)", NULL },
+ { SIG_SCI32, 1, MAP_CALL(RemapColorsByRange), "iiii(i)", NULL },
+ { SIG_SCI32, 2, MAP_CALL(RemapColorsByPercent), "ii(i)", NULL },
+ { SIG_SCI32, 3, MAP_CALL(RemapColorsToGray), "ii(i)", NULL },
+ { SIG_SCI32, 4, MAP_CALL(RemapColorsToPercentGray), "iii(i)", NULL },
+ { SIG_SCI32, 5, MAP_CALL(RemapColorsBlockRange), "ii", NULL },
SCI_SUBOPENTRY_TERMINATOR
};
@@ -634,9 +634,9 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL },
{ MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, kReadNumber_workarounds },
- { "RemapColors", kRemapColors16, SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
#ifdef ENABLE_SCI32
- { MAP_CALL(RemapColors), SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", kRemapColors_subops, NULL },
+ { "RemapColors", kRemapColors32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", kRemapColors_subops, NULL },
#endif
{ MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL },
{ MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 73236b9..cae5a09 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -1258,7 +1258,7 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) {
}
// Early variant of the SCI32 kRemapColors kernel function, used in the demo of QFG4
-reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
uint16 operation = argv[0].toUint16();
switch (operation) {
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 9270c81..80e8d4a 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -925,19 +925,19 @@ reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
if (!s)
return make_reg(0, getSciVersion());
error("not supposed to call this");
}
-reg_t kRemapOff(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsOff(EngineState *s, int argc, reg_t *argv) {
byte color = (argc >= 1) ? argv[0].toUint16() : 0;
g_sci->_gfxRemap32->remapOff(color);
return s->r_acc;
}
-reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv) {
byte color = argv[0].toUint16();
byte from = argv[1].toUint16();
byte to = argv[2].toUint16();
@@ -947,7 +947,7 @@ reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv) {
byte color = argv[0].toUint16();
byte percent = argv[1].toUint16();
// The last parameter, depth, is unused
@@ -955,7 +955,7 @@ reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv) {
byte color = argv[0].toUint16();
byte gray = argv[1].toUint16();
// The last parameter, depth, is unused
@@ -963,7 +963,7 @@ reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv) {
byte color = argv[0].toUint16();
byte gray = argv[1].toUint16();
byte percent = argv[2].toUint16();
@@ -972,7 +972,7 @@ reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColorsBlockRange(EngineState *s, int argc, reg_t *argv) {
byte from = argv[0].toUint16();
byte count = argv[1].toUint16();
g_sci->_gfxRemap32->setNoMatchRange(from, count);
Commit: ed64d5b020e819b1b90cbd77682a8b36a6554950
https://github.com/scummvm/scummvm/commit/ed64d5b020e819b1b90cbd77682a8b36a6554950
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Move GfxRemap32 to separate files
Changed paths:
A engines/sci/graphics/remap32.cpp
A engines/sci/graphics/remap32.h
engines/sci/engine/kgraphics32.cpp
engines/sci/graphics/celobj32.cpp
engines/sci/graphics/frameout.cpp
engines/sci/graphics/palette32.cpp
engines/sci/graphics/plane32.cpp
engines/sci/graphics/remap.cpp
engines/sci/graphics/remap.h
engines/sci/module.mk
engines/sci/sci.cpp
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 80e8d4a..e85d2a9 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -54,6 +54,7 @@
#include "sci/graphics/frameout.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/text32.h"
#endif
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index 3018c6b..6559bba 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -26,10 +26,8 @@
#include "sci/graphics/celobj32.h"
#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/picture.h"
-#include "sci/graphics/remap.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/text32.h"
-#include "sci/graphics/view.h"
namespace Sci {
#pragma mark CelScaler
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 5771ab5..9d3ab04 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -42,15 +42,13 @@
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/font.h"
-#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/picture.h"
-#include "sci/graphics/remap.h"
-#include "sci/graphics/text32.h"
#include "sci/graphics/plane32.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/screen_item32.h"
+#include "sci/graphics/text32.h"
#include "sci/graphics/frameout.h"
#include "sci/video/robot_decoder.h"
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 6844011..6c6234d 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -28,7 +28,7 @@
#include "sci/event.h"
#include "sci/resource.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/remap.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/screen.h"
namespace Sci {
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 6f5ad42..175875c 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -27,7 +27,7 @@
#include "sci/graphics/frameout.h"
#include "sci/graphics/lists32.h"
#include "sci/graphics/plane32.h"
-#include "sci/graphics/remap.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/screen_item32.h"
diff --git a/engines/sci/graphics/remap.cpp b/engines/sci/graphics/remap.cpp
index ff49e52..7f5721b 100644
--- a/engines/sci/graphics/remap.cpp
+++ b/engines/sci/graphics/remap.cpp
@@ -104,277 +104,4 @@ void GfxRemap::updateRemapping() {
}
}
}
-
-#pragma mark -
-#pragma mark SCI32 remapping
-
-#ifdef ENABLE_SCI32
-
-GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
- for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
- _noMapStart = _noMapCount = 0;
- _update = false;
- _remapCount = 0;
-
- // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle.
- // All versions of KQ7 are using the older remap range semantics.
- _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) ? 244 : 254;
-}
-
-void GfxRemap32::remapOff(byte color) {
- if (!color) {
- for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
-
- _remapCount = 0;
- } else {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
- _remapCount--;
- }
-
- _update = true;
-}
-
-void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
-
-void GfxRemap32::setRemappingPercent(byte color, byte percent) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
-
-void GfxRemap32::setRemappingToGray(byte color, byte gray) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
-
-void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
-
-void GfxRemap32::setNoMatchRange(byte from, byte count) {
- _noMapStart = from;
- _noMapCount = count;
-}
-
-bool GfxRemap32::remapEnabled(byte color) const {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- return (_remaps[index].type != kRemappingNone);
-}
-
-byte GfxRemap32::remapColor(byte color, byte target) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- if (_remaps[index].type != kRemappingNone)
- return _remaps[index].remap[target];
- else
- return target;
-}
-
-void GfxRemap32::initColorArrays(byte index) {
- Palette *curPalette = &_palette->_sysPalette;
- RemapParams *curRemap = &_remaps[index];
-
- memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
- memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
-}
-
-bool GfxRemap32::updateRemap(byte index, bool palChanged) {
- int result;
- RemapParams *curRemap = &_remaps[index];
- const Palette *curPalette = &_palette->_sysPalette;
- const Palette *nextPalette = _palette->getNextPalette();
- bool changed = false;
-
- if (!_update && !palChanged)
- return false;
-
- Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
-
- switch (curRemap->type) {
- case kRemappingNone:
- return false;
- case kRemappingByRange:
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
- if (curRemap->from <= i && i <= curRemap->to)
- result = i + curRemap->base;
- else
- result = i;
-
- if (curRemap->remap[i] != result) {
- changed = true;
- curRemap->remap[i] = result;
- }
-
- curRemap->colorChanged[i] = true;
- }
- return changed;
- case kRemappingByPercent:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- // NOTE: This method uses nextPalette instead of curPalette
- Color color = nextPalette->colors[i];
-
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
-
- if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) {
- byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255);
- byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255);
- byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
- }
- }
-
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldPercent = curRemap->percent;
- return changed;
- case kRemappingToGray:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color color = curPalette->colors[i];
-
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
-
- if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
- byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
- byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
- byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
- byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
- }
- }
-
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldGray = curRemap->gray;
- return changed;
- case kRemappingToPercentGray:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color color = curPalette->colors[i];
-
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
-
- if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
- byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
- lumosity = lumosity * curRemap->percent / 100;
- byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
- byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
- byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
- }
- }
-
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldPercent = curRemap->percent;
- curRemap->oldGray = curRemap->gray;
- return changed;
- default:
- return false;
- }
-}
-
-static int colorDistance(Color a, Color b) {
- int rDiff = (a.r - b.r) * (a.r - b.r);
- int gDiff = (a.g - b.g) * (a.g - b.g);
- int bDiff = (a.b - b.b) * (a.b - b.b);
- return rDiff + gDiff + bDiff;
-}
-
-bool GfxRemap32::applyRemap(byte index) {
- RemapParams *curRemap = &_remaps[index];
- const bool *cycleMap = _palette->getCyclemap();
- bool unmappedColors[NON_REMAPPED_COLOR_COUNT];
- bool changed = false;
-
- Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false);
- if (_noMapCount)
- Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true);
-
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
- if (cycleMap[i])
- unmappedColors[i] = true;
- }
-
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color targetColor = curRemap->targetColor[i];
- bool colorChanged = curRemap->colorChanged[curRemap->remap[i]];
-
- if (!_targetChanged[i] && !colorChanged)
- continue;
-
- if (_targetChanged[i] && colorChanged)
- if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i])
- continue;
-
- int diff = 0;
- int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
- if (result != -1 && curRemap->remap[i] != result) {
- changed = true;
- curRemap->remap[i] = result;
- curRemap->distance[i] = diff;
- }
- }
-
- return changed;
-}
-
-bool GfxRemap32::remapAllTables(bool palChanged) {
- bool changed = false;
-
- for (int i = 0; i < REMAP_COLOR_COUNT; i++) {
- changed |= updateRemap(i, palChanged);
- }
-
- _update = false;
- return changed;
-}
-
-#endif
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/remap.h b/engines/sci/graphics/remap.h
index d012568..d758a97 100644
--- a/engines/sci/graphics/remap.h
+++ b/engines/sci/graphics/remap.h
@@ -38,9 +38,6 @@ enum ColorRemappingType {
kRemappingToPercentGray = 4
};
-#define REMAP_COLOR_COUNT 9
-#define NON_REMAPPED_COLOR_COUNT 236
-
/**
* Remap class, handles color remapping
*/
@@ -68,87 +65,6 @@ private:
byte _remappingByRange[256];
uint16 _remappingPercentToSet;
};
-
-#ifdef ENABLE_SCI32
-
-struct RemapParams {
- byte from;
- byte to;
- byte base;
- byte gray;
- byte oldGray;
- byte percent;
- byte oldPercent;
- ColorRemappingType type;
- Color curColor[256];
- Color targetColor[256];
- byte distance[256];
- byte remap[256];
- bool colorChanged[256];
-
- RemapParams() {
- from = to = base = gray = oldGray = percent = oldPercent = 0;
- type = kRemappingNone;
-
- // curColor and targetColor are initialized in GfxRemap32::initColorArrays
- memset(curColor, 0, 256 * sizeof(Color));
- memset(targetColor, 0, 256 * sizeof(Color));
- memset(distance, 0, 256);
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
- remap[i] = i;
- Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
- }
-
- RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, ColorRemappingType type_) {
- from = from_;
- to = to_;
- base = base_;
- gray = oldGray = gray_;
- percent = oldPercent = percent_;
- type = type_;
-
- // curColor and targetColor are initialized in GfxRemap32::initColorArrays
- memset(curColor, 0, 256 * sizeof(Color));
- memset(targetColor, 0, 256 * sizeof(Color));
- memset(distance, 0, 256);
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
- remap[i] = i;
- Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
- }
-};
-
-class GfxRemap32 {
-public:
- GfxRemap32(GfxPalette32 *palette);
- ~GfxRemap32() {}
-
- void remapOff(byte color);
- void setRemappingRange(byte color, byte from, byte to, byte base);
- void setRemappingPercent(byte color, byte percent);
- void setRemappingToGray(byte color, byte gray);
- void setRemappingToPercentGray(byte color, byte gray, byte percent);
- void setNoMatchRange(byte from, byte count);
- bool remapEnabled(byte color) const;
- byte remapColor(byte color, byte target);
- bool remapAllTables(bool palChanged);
- int getRemapCount() const { return _remapCount; }
- int getStartColor() const { return _remapEndColor - REMAP_COLOR_COUNT + 1; }
- int getEndColor() const { return _remapEndColor; }
-private:
- GfxPalette32 *_palette;
- RemapParams _remaps[REMAP_COLOR_COUNT];
- bool _update;
- byte _noMapStart, _noMapCount;
- bool _targetChanged[NON_REMAPPED_COLOR_COUNT];
- byte _remapEndColor;
- int _remapCount;
-
- void initColorArrays(byte index);
- bool applyRemap(byte index);
- bool updateRemap(byte index, bool palChanged);
-};
-#endif
-
} // End of namespace Sci
#endif
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
new file mode 100644
index 0000000..5516d0e
--- /dev/null
+++ b/engines/sci/graphics/remap32.cpp
@@ -0,0 +1,294 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap32.h"
+
+namespace Sci {
+
+GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _noMapStart = _noMapCount = 0;
+ _update = false;
+ _remapCount = 0;
+
+ // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle.
+ // All versions of KQ7 are using the older remap range semantics.
+ _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) ? 244 : 254;
+}
+
+void GfxRemap32::remapOff(byte color) {
+ if (!color) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+
+ _remapCount = 0;
+ } else {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remapCount--;
+ }
+
+ _update = true;
+}
+
+void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingPercent(byte color, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToGray(byte color, byte gray) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setNoMatchRange(byte from, byte count) {
+ _noMapStart = from;
+ _noMapCount = count;
+}
+
+bool GfxRemap32::remapEnabled(byte color) const {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ return (_remaps[index].type != kRemappingNone);
+}
+
+byte GfxRemap32::remapColor(byte color, byte target) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ if (_remaps[index].type != kRemappingNone)
+ return _remaps[index].remap[target];
+ else
+ return target;
+}
+
+void GfxRemap32::initColorArrays(byte index) {
+ Palette *curPalette = &_palette->_sysPalette;
+ RemapParams *curRemap = &_remaps[index];
+
+ memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+ memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+}
+
+bool GfxRemap32::updateRemap(byte index, bool palChanged) {
+ int result;
+ RemapParams *curRemap = &_remaps[index];
+ const Palette *curPalette = &_palette->_sysPalette;
+ const Palette *nextPalette = _palette->getNextPalette();
+ bool changed = false;
+
+ if (!_update && !palChanged)
+ return false;
+
+ Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
+
+ switch (curRemap->type) {
+ case kRemappingNone:
+ return false;
+ case kRemappingByRange:
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (curRemap->from <= i && i <= curRemap->to)
+ result = i + curRemap->base;
+ else
+ result = i;
+
+ if (curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ }
+
+ curRemap->colorChanged[i] = true;
+ }
+ return changed;
+ case kRemappingByPercent:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ // NOTE: This method uses nextPalette instead of curPalette
+ Color color = nextPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) {
+ byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255);
+ byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255);
+ byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ return changed;
+ case kRemappingToGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ case kRemappingToPercentGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ lumosity = lumosity * curRemap->percent / 100;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ default:
+ return false;
+ }
+}
+
+static int colorDistance(Color a, Color b) {
+ int rDiff = (a.r - b.r) * (a.r - b.r);
+ int gDiff = (a.g - b.g) * (a.g - b.g);
+ int bDiff = (a.b - b.b) * (a.b - b.b);
+ return rDiff + gDiff + bDiff;
+}
+
+bool GfxRemap32::applyRemap(byte index) {
+ RemapParams *curRemap = &_remaps[index];
+ const bool *cycleMap = _palette->getCyclemap();
+ bool unmappedColors[NON_REMAPPED_COLOR_COUNT];
+ bool changed = false;
+
+ Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false);
+ if (_noMapCount)
+ Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true);
+
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (cycleMap[i])
+ unmappedColors[i] = true;
+ }
+
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color targetColor = curRemap->targetColor[i];
+ bool colorChanged = curRemap->colorChanged[curRemap->remap[i]];
+
+ if (!_targetChanged[i] && !colorChanged)
+ continue;
+
+ if (_targetChanged[i] && colorChanged)
+ if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i])
+ continue;
+
+ int diff = 0;
+ int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
+ if (result != -1 && curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ curRemap->distance[i] = diff;
+ }
+ }
+
+ return changed;
+}
+
+bool GfxRemap32::remapAllTables(bool palChanged) {
+ bool changed = false;
+
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++) {
+ changed |= updateRemap(i, palChanged);
+ }
+
+ _update = false;
+ return changed;
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
new file mode 100644
index 0000000..ff871f6
--- /dev/null
+++ b/engines/sci/graphics/remap32.h
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCI_GRAPHICS_REMAP32_H
+#define SCI_GRAPHICS_REMAP32_H
+
+#include "common/array.h"
+#include "sci/graphics/remap.h"
+
+namespace Sci {
+
+#define REMAP_COLOR_COUNT 9
+#define NON_REMAPPED_COLOR_COUNT 236
+
+struct RemapParams {
+ byte from;
+ byte to;
+ byte base;
+ byte gray;
+ byte oldGray;
+ byte percent;
+ byte oldPercent;
+ ColorRemappingType type;
+ Color curColor[256];
+ Color targetColor[256];
+ byte distance[256];
+ byte remap[256];
+ bool colorChanged[256];
+
+ RemapParams() {
+ from = to = base = gray = oldGray = percent = oldPercent = 0;
+ type = kRemappingNone;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+
+ RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, ColorRemappingType type_) {
+ from = from_;
+ to = to_;
+ base = base_;
+ gray = oldGray = gray_;
+ percent = oldPercent = percent_;
+ type = type_;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+};
+
+class GfxRemap32 {
+public:
+ GfxRemap32(GfxPalette32 *palette);
+ ~GfxRemap32() {}
+
+ void remapOff(byte color);
+ void setRemappingRange(byte color, byte from, byte to, byte base);
+ void setRemappingPercent(byte color, byte percent);
+ void setRemappingToGray(byte color, byte gray);
+ void setRemappingToPercentGray(byte color, byte gray, byte percent);
+ void setNoMatchRange(byte from, byte count);
+ bool remapEnabled(byte color) const;
+ byte remapColor(byte color, byte target);
+ bool remapAllTables(bool palChanged);
+ int getRemapCount() const { return _remapCount; }
+ int getStartColor() const { return _remapEndColor - REMAP_COLOR_COUNT + 1; }
+ int getEndColor() const { return _remapEndColor; }
+private:
+ GfxPalette32 *_palette;
+ RemapParams _remaps[REMAP_COLOR_COUNT];
+ bool _update;
+ byte _noMapStart, _noMapCount;
+ bool _targetChanged[NON_REMAPPED_COLOR_COUNT];
+ byte _remapEndColor;
+ int _remapCount;
+
+ void initColorArrays(byte index);
+ bool applyRemap(byte index);
+ bool updateRemap(byte index, bool palChanged);
+};
+
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index ba6c853..5d54e2a 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -88,6 +88,7 @@ MODULE_OBJS += \
graphics/paint32.o \
graphics/plane32.o \
graphics/palette32.o \
+ graphics/remap32.o \
graphics/screen_item32.o \
graphics/text32.o \
sound/audio32.o \
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index b80456c..243c12b 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -65,9 +65,10 @@
#ifdef ENABLE_SCI32
#include "sci/graphics/controls32.h"
+#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap32.h"
#include "sci/graphics/text32.h"
-#include "sci/graphics/frameout.h"
#include "sci/sound/audio32.h"
#include "sci/video/robot_decoder.h"
#endif
Commit: 14e57ac867076e754f5299ff1418b3f184a9bf67
https://github.com/scummvm/scummvm/commit/14e57ac867076e754f5299ff1418b3f184a9bf67
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Add missing remap CelObj calls
Changed paths:
engines/sci/graphics/celobj32.cpp
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index 6559bba..befa5cd 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -31,6 +31,7 @@
namespace Sci {
#pragma mark CelScaler
+
CelScaler *CelObj::_scaler = nullptr;
void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) {
@@ -321,6 +322,10 @@ public:
#pragma mark -
#pragma mark CelObj - Remappers
+/**
+ * Pixel mapper for a CelObj with transparent pixels and no
+ * remapping data.
+ */
struct MAPPER_NoMD {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
if (pixel != skipColor) {
@@ -328,25 +333,49 @@ struct MAPPER_NoMD {
}
}
};
+
+/**
+ * Pixel mapper for a CelObj with no transparent pixels and
+ * no remapping data.
+ */
struct MAPPER_NoMDNoSkip {
inline void draw(byte *target, const byte pixel, const uint8) const {
*target = pixel;
}
};
+/**
+ * Pixel mapper for a CelObj with transparent pixels,
+ * remapping data, and remapping enabled.
+ */
struct MAPPER_Map {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
if (pixel != skipColor) {
+ // NOTE: For some reason, SSCI never checks if the source
+ // pixel is *above* the range of remaps.
if (pixel < g_sci->_gfxRemap32->getStartColor()) {
*target = pixel;
- } else {
- if (g_sci->_gfxRemap32->remapEnabled(pixel))
- *target = g_sci->_gfxRemap32->remapColor(pixel, *target);
+ } else if (g_sci->_gfxRemap32->remapEnabled(pixel)) {
+ *target = g_sci->_gfxRemap32->remapColor(pixel, *target);
}
}
}
};
+/**
+ * Pixel mapper for a CelObj with transparent pixels,
+ * remapping data, and remapping disabled.
+ */
+struct MAPPER_NoMap {
+ inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
+ // NOTE: For some reason, SSCI never checks if the source
+ // pixel is *above* the range of remaps.
+ if (pixel != skipColor && pixel < g_sci->_gfxRemap32->getStartColor()) {
+ *target = pixel;
+ }
+ }
+};
+
void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect) const {
const Common::Point &scaledPosition = screenItem._scaledPosition;
const Ratio &scaleX = screenItem._ratioX;
@@ -521,6 +550,7 @@ void CelObj::submitPalette() const {
#pragma mark -
#pragma mark CelObj - Caching
+
int CelObj::_nextCacheId = 1;
CelCache *CelObj::_cache = nullptr;
@@ -622,33 +652,35 @@ void dummyFill(Buffer &target, const Common::Rect &targetRect) {
}
void CelObj::drawHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("drawHzFlip");
- dummyFill(target, targetRect);
+ render<MAPPER_NoMap, SCALER_NoScale<true, READER_Compressed> >(target, targetRect, scaledPosition);
}
void CelObj::drawNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("drawNoFlip");
- dummyFill(target, targetRect);
+ render<MAPPER_NoMap, SCALER_NoScale<false, READER_Compressed> >(target, targetRect, scaledPosition);
}
void CelObj::drawUncompNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("drawUncompNoFlip");
- dummyFill(target, targetRect);
+ render<MAPPER_NoMap, SCALER_NoScale<false, READER_Uncompressed> >(target, targetRect, scaledPosition);
}
void CelObj::drawUncompHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("drawUncompHzFlip");
- dummyFill(target, targetRect);
+ render<MAPPER_NoMap, SCALER_NoScale<true, READER_Uncompressed> >(target, targetRect, scaledPosition);
}
void CelObj::scaleDraw(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("scaleDraw");
- dummyFill(target, targetRect);
+ if (_drawMirrored) {
+ render<MAPPER_NoMap, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ } else {
+ render<MAPPER_NoMap, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ }
}
void CelObj::scaleDrawUncomp(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- debug("scaleDrawUncomp");
- dummyFill(target, targetRect);
+ if (_drawMirrored) {
+ render<MAPPER_NoMap, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ } else {
+ render<MAPPER_NoMap, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ }
}
void CelObj::drawHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
@@ -668,17 +700,19 @@ void CelObj::drawUncompHzFlipMap(Buffer &target, const Common::Rect &targetRect,
}
void CelObj::scaleDrawMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored)
+ if (_drawMirrored) {
render<MAPPER_Map, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- else
+ } else {
render<MAPPER_Map, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ }
}
void CelObj::scaleDrawUncompMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored)
+ if (_drawMirrored) {
render<MAPPER_Map, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- else
+ } else {
render<MAPPER_Map, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ }
}
void CelObj::drawNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
@@ -713,14 +747,16 @@ void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &sca
}
void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- if (_drawMirrored)
+ if (_drawMirrored) {
render<MAPPER_NoMD, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
- else
+ } else {
render<MAPPER_NoMD, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ }
}
#pragma mark -
#pragma mark CelObjView
+
CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) {
_info.type = kCelTypeView;
_info.resourceId = viewId;
@@ -838,8 +874,12 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
bool CelObjView::analyzeUncompressedForRemap() const {
byte *pixels = getResPointer() + READ_SCI11ENDIAN_UINT32(getResPointer() + _celHeaderOffset + 24);
for (int i = 0; i < _width * _height; ++i) {
- byte pixel = pixels[i];
- if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
+ const byte pixel = pixels[i];
+ if (
+ pixel >= g_sci->_gfxRemap32->getStartColor() &&
+ pixel <= g_sci->_gfxRemap32->getEndColor() &&
+ pixel != _transparentColor
+ ) {
return true;
}
}
@@ -851,8 +891,12 @@ bool CelObjView::analyzeForRemap() const {
for (int y = 0; y < _height; y++) {
const byte *curRow = reader.getRow(y);
for (int x = 0; x < _width; x++) {
- byte pixel = curRow[x];
- if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
+ const byte pixel = curRow[x];
+ if (
+ pixel >= g_sci->_gfxRemap32->getStartColor() &&
+ pixel <= g_sci->_gfxRemap32->getEndColor() &&
+ pixel != _transparentColor
+ ) {
return true;
}
}
@@ -879,6 +923,7 @@ byte *CelObjView::getResPointer() const {
#pragma mark -
#pragma mark CelObjPic
+
CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
_info.type = kCelTypePic;
_info.resourceId = picId;
@@ -1000,6 +1045,7 @@ byte *CelObjPic::getResPointer() const {
#pragma mark -
#pragma mark CelObjMem
+
CelObjMem::CelObjMem(const reg_t bitmapObject) {
_info.type = kCelTypeMem;
_info.bitmap = bitmapObject;
@@ -1029,6 +1075,7 @@ byte *CelObjMem::getResPointer() const {
#pragma mark -
#pragma mark CelObjColor
+
CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 height) {
_info.type = kCelTypeColor;
_info.color = color;
Commit: 0aed08681eff9589dd7747b0285b07ef5a7cc155
https://github.com/scummvm/scummvm/commit/0aed08681eff9589dd7747b0285b07ef5a7cc155
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Separate remap types
Changed paths:
engines/sci/graphics/remap.cpp
engines/sci/graphics/remap.h
engines/sci/graphics/remap32.cpp
engines/sci/graphics/remap32.h
engines/sci/graphics/view.h
diff --git a/engines/sci/graphics/remap.cpp b/engines/sci/graphics/remap.cpp
index 7f5721b..2abf03e 100644
--- a/engines/sci/graphics/remap.cpp
+++ b/engines/sci/graphics/remap.cpp
@@ -21,31 +21,23 @@
*/
#include "sci/sci.h"
-#include "sci/resource.h"
#include "sci/graphics/palette.h"
-#include "sci/graphics/palette32.h"
#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
namespace Sci {
-#pragma mark -
-#pragma mark SCI16 remapping (QFG4 demo)
-
GfxRemap::GfxRemap(GfxPalette *palette)
: _palette(palette) {
_remapOn = false;
resetRemapping();
}
-GfxRemap::~GfxRemap() {
-}
-
byte GfxRemap::remapColor(byte remappedColor, byte screenColor) {
assert(_remapOn);
- if (_remappingType[remappedColor] == kRemappingByRange)
+ if (_remappingType[remappedColor] == kRemapByRange)
return _remappingByRange[screenColor];
- else if (_remappingType[remappedColor] == kRemappingByPercent)
+ else if (_remappingType[remappedColor] == kRemapByPercent)
return _remappingByPercent[screenColor];
else
error("remapColor(): Color %d isn't remapped", remappedColor);
@@ -58,7 +50,7 @@ void GfxRemap::resetRemapping() {
_remappingPercentToSet = 0;
for (int i = 0; i < 256; i++) {
- _remappingType[i] = kRemappingNone;
+ _remappingType[i] = kRemapNone;
_remappingByPercent[i] = i;
_remappingByRange[i] = i;
}
@@ -80,7 +72,7 @@ void GfxRemap::setRemappingPercent(byte color, byte percent) {
_remappingByPercent[i] = _palette->kernelFindColor(r, g, b);
}
- _remappingType[color] = kRemappingByPercent;
+ _remappingType[color] = kRemapByPercent;
}
void GfxRemap::setRemappingRange(byte color, byte from, byte to, byte base) {
@@ -90,7 +82,7 @@ void GfxRemap::setRemappingRange(byte color, byte from, byte to, byte base) {
_remappingByRange[i] = i + base;
}
- _remappingType[color] = kRemappingByRange;
+ _remappingType[color] = kRemapByRange;
}
void GfxRemap::updateRemapping() {
diff --git a/engines/sci/graphics/remap.h b/engines/sci/graphics/remap.h
index d758a97..a9cd76a 100644
--- a/engines/sci/graphics/remap.h
+++ b/engines/sci/graphics/remap.h
@@ -30,33 +30,30 @@ namespace Sci {
class GfxScreen;
-enum ColorRemappingType {
- kRemappingNone = 0,
- kRemappingByRange = 1,
- kRemappingByPercent = 2,
- kRemappingToGray = 3,
- kRemappingToPercentGray = 4
-};
-
/**
- * Remap class, handles color remapping
+ * This class handles color remapping for the QFG4 demo.
*/
class GfxRemap {
+private:
+ enum ColorRemappingType {
+ kRemapNone = 0,
+ kRemapByRange = 1,
+ kRemapByPercent = 2
+ };
+
public:
GfxRemap(GfxPalette *_palette);
- ~GfxRemap();
void resetRemapping();
void setRemappingPercent(byte color, byte percent);
void setRemappingRange(byte color, byte from, byte to, byte base);
bool isRemapped(byte color) const {
- return _remapOn && (_remappingType[color] != kRemappingNone);
+ return _remapOn && (_remappingType[color] != kRemapNone);
}
byte remapColor(byte remappedColor, byte screenColor);
void updateRemapping();
private:
- GfxScreen *_screen;
GfxPalette *_palette;
bool _remapOn;
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
index 5516d0e..774c4ca 100644
--- a/engines/sci/graphics/remap32.cpp
+++ b/engines/sci/graphics/remap32.cpp
@@ -28,7 +28,7 @@ namespace Sci {
GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
_noMapStart = _noMapCount = 0;
_update = false;
_remapCount = 0;
@@ -41,13 +41,13 @@ GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
void GfxRemap32::remapOff(byte color) {
if (!color) {
for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
_remapCount = 0;
} else {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
const byte index = _remapEndColor - color;
- _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
_remapCount--;
}
@@ -56,7 +56,7 @@ void GfxRemap32::remapOff(byte color) {
void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange);
+ _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemapByRange);
initColorArrays(_remapEndColor - color);
_remapCount++;
_update = true;
@@ -64,7 +64,7 @@ void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
void GfxRemap32::setRemappingPercent(byte color, byte percent) {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemapByPercent);
initColorArrays(_remapEndColor - color);
_remapCount++;
_update = true;
@@ -72,7 +72,7 @@ void GfxRemap32::setRemappingPercent(byte color, byte percent) {
void GfxRemap32::setRemappingToGray(byte color, byte gray) {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemapToGray);
initColorArrays(_remapEndColor - color);
_remapCount++;
_update = true;
@@ -80,7 +80,7 @@ void GfxRemap32::setRemappingToGray(byte color, byte gray) {
void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemapToPercentGray);
initColorArrays(_remapEndColor - color);
_remapCount++;
_update = true;
@@ -94,13 +94,13 @@ void GfxRemap32::setNoMatchRange(byte from, byte count) {
bool GfxRemap32::remapEnabled(byte color) const {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
const byte index = _remapEndColor - color;
- return (_remaps[index].type != kRemappingNone);
+ return (_remaps[index].type != kRemapNone);
}
byte GfxRemap32::remapColor(byte color, byte target) {
assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
const byte index = _remapEndColor - color;
- if (_remaps[index].type != kRemappingNone)
+ if (_remaps[index].type != kRemapNone)
return _remaps[index].remap[target];
else
return target;
@@ -127,9 +127,9 @@ bool GfxRemap32::updateRemap(byte index, bool palChanged) {
Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
switch (curRemap->type) {
- case kRemappingNone:
+ case kRemapNone:
return false;
- case kRemappingByRange:
+ case kRemapByRange:
for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
if (curRemap->from <= i && i <= curRemap->to)
result = i + curRemap->base;
@@ -144,7 +144,7 @@ bool GfxRemap32::updateRemap(byte index, bool palChanged) {
curRemap->colorChanged[i] = true;
}
return changed;
- case kRemappingByPercent:
+ case kRemapByPercent:
for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
// NOTE: This method uses nextPalette instead of curPalette
Color color = nextPalette->colors[i];
@@ -172,7 +172,7 @@ bool GfxRemap32::updateRemap(byte index, bool palChanged) {
Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
curRemap->oldPercent = curRemap->percent;
return changed;
- case kRemappingToGray:
+ case kRemapToGray:
for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
Color color = curPalette->colors[i];
@@ -200,7 +200,7 @@ bool GfxRemap32::updateRemap(byte index, bool palChanged) {
Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
curRemap->oldGray = curRemap->gray;
return changed;
- case kRemappingToPercentGray:
+ case kRemapToPercentGray:
for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
Color color = curPalette->colors[i];
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
index ff871f6..3d5b67d 100644
--- a/engines/sci/graphics/remap32.h
+++ b/engines/sci/graphics/remap32.h
@@ -24,13 +24,20 @@
#define SCI_GRAPHICS_REMAP32_H
#include "common/array.h"
-#include "sci/graphics/remap.h"
namespace Sci {
#define REMAP_COLOR_COUNT 9
#define NON_REMAPPED_COLOR_COUNT 236
+enum RemapType {
+ kRemapNone = 0,
+ kRemapByRange = 1,
+ kRemapByPercent = 2,
+ kRemapToGray = 3,
+ kRemapToPercentGray = 4
+};
+
struct RemapParams {
byte from;
byte to;
@@ -39,7 +46,7 @@ struct RemapParams {
byte oldGray;
byte percent;
byte oldPercent;
- ColorRemappingType type;
+ RemapType type;
Color curColor[256];
Color targetColor[256];
byte distance[256];
@@ -48,7 +55,7 @@ struct RemapParams {
RemapParams() {
from = to = base = gray = oldGray = percent = oldPercent = 0;
- type = kRemappingNone;
+ type = kRemapNone;
// curColor and targetColor are initialized in GfxRemap32::initColorArrays
memset(curColor, 0, 256 * sizeof(Color));
@@ -59,7 +66,7 @@ struct RemapParams {
Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
}
- RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, ColorRemappingType type_) {
+ RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, RemapType type_) {
from = from_;
to = to_;
base = base_;
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index 9159020..96b48c0 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -55,6 +55,7 @@ struct LoopInfo {
class GfxScreen;
class GfxPalette;
+class Resource;
/**
* View class, handles loading of view resources and drawing contained cels to screen
Commit: 0c799e1bd910231ba05c8ed7f182577314ac967b
https://github.com/scummvm/scummvm/commit/0c799e1bd910231ba05c8ed7f182577314ac967b
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Move matchColor to GfxRemap32
Changed paths:
engines/sci/graphics/palette32.cpp
engines/sci/graphics/palette32.h
engines/sci/graphics/remap32.cpp
engines/sci/graphics/remap32.h
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 6c6234d..5c9bfd6 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -82,6 +82,11 @@ const Palette *GfxPalette32::getNextPalette() const {
return &_nextPalette;
}
+const Palette *GfxPalette32::getCurrentPalette() const {
+ return &_sysPalette;
+}
+
+
void GfxPalette32::submit(Palette &palette) {
// TODO: The resource manager in SCI32 retains raw data of palettes from
// the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and
@@ -178,49 +183,6 @@ void GfxPalette32::set(Palette *newPalette, bool force, bool forceRealMerge) {
submit(*newPalette);
}
-// In SCI32 engine this method is SOLPalette::Match(Rgb24 *, int, int *, int *)
-// and is used by Remap
-// TODO: Anything that calls GfxPalette::matchColor(int, int, int) is going to
-// match using an algorithm from SCI16 engine right now. This needs to be
-// corrected in the future so either nothing calls
-// GfxPalette::matchColor(int, int, int), or it is fixed to match the other
-// SCI32 algorithms.
-int16 GfxPalette32::matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) {
- int16 bestIndex = -1;
- int bestDifference = 0xFFFFF;
- int difference = defaultDifference;
-
- // SQ6 DOS really does check only the first 236 entries
- for (int i = 0, channelDifference; i < 236; ++i) {
- if (matchTable[i] == 0) {
- continue;
- }
-
- difference = _sysPalette.colors[i].r - r;
- difference *= difference;
- if (bestDifference <= difference) {
- continue;
- }
- channelDifference = _sysPalette.colors[i].g - g;
- difference += channelDifference * channelDifference;
- if (bestDifference <= difference) {
- continue;
- }
- channelDifference = _sysPalette.colors[i].b - b;
- difference += channelDifference * channelDifference;
- if (bestDifference <= difference) {
- continue;
- }
- bestDifference = difference;
- bestIndex = i;
- }
-
- // NOTE: This value is only valid if the last index to
- // perform a difference calculation was the best index
- lastCalculatedDifference = difference;
- return bestIndex;
-}
-
bool GfxPalette32::updateForFrame() {
applyAll();
_versionUpdated = false;
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index 1902d00..ec75b58 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -114,11 +114,11 @@ private:
public:
virtual void saveLoadWithSerializer(Common::Serializer &s) override;
const Palette *getNextPalette() const;
+ const Palette *getCurrentPalette() const;
bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
void set(Palette *newPalette, bool force, bool forceRealMerge = false) override;
- int16 matchColor(const byte matchRed, const byte matchGreen, const byte matchBlue, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable);
/**
* Submits a palette to display. Entries marked as “used” in the
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
index 774c4ca..ef27c84 100644
--- a/engines/sci/graphics/remap32.cpp
+++ b/engines/sci/graphics/remap32.cpp
@@ -269,7 +269,7 @@ bool GfxRemap32::applyRemap(byte index) {
continue;
int diff = 0;
- int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
+ int16 result = matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
if (result != -1 && curRemap->remap[i] != result) {
changed = true;
curRemap->remap[i] = result;
@@ -291,4 +291,48 @@ bool GfxRemap32::remapAllTables(bool palChanged) {
return changed;
}
+// In SCI32 engine this method is SOLPalette::Match(Rgb24 *, int, int *, int *)
+// and is used by Remap
+// TODO: Anything that calls GfxPalette::matchColor(int, int, int) is going to
+// match using an algorithm from SCI16 engine right now. This needs to be
+// corrected in the future so either nothing calls
+// GfxPalette::matchColor(int, int, int), or it is fixed to match the other
+// SCI32 algorithms.
+int16 GfxRemap32::matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) const {
+ int16 bestIndex = -1;
+ int bestDifference = 0xFFFFF;
+ int difference = defaultDifference;
+ const Palette &_sysPalette = *g_sci->_gfxPalette32->getCurrentPalette();
+
+ // SQ6 DOS really does check only the first 236 entries
+ for (int i = 0, channelDifference; i < 236; ++i) {
+ if (matchTable[i] == 0) {
+ continue;
+ }
+
+ difference = _sysPalette.colors[i].r - r;
+ difference *= difference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ channelDifference = _sysPalette.colors[i].g - g;
+ difference += channelDifference * channelDifference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ channelDifference = _sysPalette.colors[i].b - b;
+ difference += channelDifference * channelDifference;
+ if (bestDifference <= difference) {
+ continue;
+ }
+ bestDifference = difference;
+ bestIndex = i;
+ }
+
+ // NOTE: This value is only valid if the last index to
+ // perform a difference calculation was the best index
+ lastCalculatedDifference = difference;
+ return bestIndex;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
index 3d5b67d..52736f5 100644
--- a/engines/sci/graphics/remap32.h
+++ b/engines/sci/graphics/remap32.h
@@ -113,6 +113,7 @@ private:
void initColorArrays(byte index);
bool applyRemap(byte index);
bool updateRemap(byte index, bool palChanged);
+ int16 matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) const;
};
} // End of namespace Sci
Commit: ca279390a36d0f87be134c6788c6420a748b99b8
https://github.com/scummvm/scummvm/commit/ca279390a36d0f87be134c6788c6420a748b99b8
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-01T00:18:32+02:00
Commit Message:
SCI32: Fix broken Remap implementation
Remap would crash SCI2.1early games with 19 remap slots, and
did not actually work in most cases in SCI2.1mid+ games.
1. Avoid accidental corruption of values from the VM that may be
valid when signed or larger than 8 bits
2. Fix bad `matchColor` function.
3. Remove unnecessary initialisation of SingleRemaps
4. Update architecture to more closely mirror how SSCI worked
5. Split large `apply` function into smaller units
6. Fix buffer overrun when loading a SCI2.1early game with remap
7. Warn instead of crashing with an error on invalid input (to
match SSCI more closely)
8. Add save/load function
Changed paths:
engines/sci/engine/kgraphics32.cpp
engines/sci/engine/savegame.cpp
engines/sci/engine/savegame.h
engines/sci/graphics/frameout.cpp
engines/sci/graphics/palette32.cpp
engines/sci/graphics/palette32.h
engines/sci/graphics/remap.h
engines/sci/graphics/remap32.cpp
engines/sci/graphics/remap32.h
engines/sci/sci.cpp
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index e85d2a9..019a069 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -933,50 +933,62 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
}
reg_t kRemapColorsOff(EngineState *s, int argc, reg_t *argv) {
- byte color = (argc >= 1) ? argv[0].toUint16() : 0;
- g_sci->_gfxRemap32->remapOff(color);
+ if (argc == 0) {
+ g_sci->_gfxRemap32->remapAllOff();
+ } else {
+ const uint8 color = argv[0].toUint16();
+ g_sci->_gfxRemap32->remapOff(color);
+ }
return s->r_acc;
}
reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv) {
- byte color = argv[0].toUint16();
- byte from = argv[1].toUint16();
- byte to = argv[2].toUint16();
- byte base = argv[3].toUint16();
- // The last parameter, depth, is unused
- g_sci->_gfxRemap32->setRemappingRange(color, from, to, base);
+ const uint8 color = argv[0].toUint16();
+ const int16 from = argv[1].toSint16();
+ const int16 to = argv[2].toSint16();
+ const int16 base = argv[3].toSint16();
+ // NOTE: There is an optional last parameter after `base`
+ // which was only used by the priority map debugger, which
+ // does not exist in release versions of SSCI
+ g_sci->_gfxRemap32->remapByRange(color, from, to, base);
return s->r_acc;
}
reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv) {
- byte color = argv[0].toUint16();
- byte percent = argv[1].toUint16();
- // The last parameter, depth, is unused
- g_sci->_gfxRemap32->setRemappingPercent(color, percent);
+ const uint8 color = argv[0].toUint16();
+ const int16 percent = argv[1].toSint16();
+ // NOTE: There is an optional last parameter after `percent`
+ // which was only used by the priority map debugger, which
+ // does not exist in release versions of SSCI
+ g_sci->_gfxRemap32->remapByPercent(color, percent);
return s->r_acc;
}
reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv) {
- byte color = argv[0].toUint16();
- byte gray = argv[1].toUint16();
- // The last parameter, depth, is unused
- g_sci->_gfxRemap32->setRemappingToGray(color, gray);
+ const uint8 color = argv[0].toUint16();
+ const int16 gray = argv[1].toSint16();
+ // NOTE: There is an optional last parameter after `gray`
+ // which was only used by the priority map debugger, which
+ // does not exist in release versions of SSCI
+ g_sci->_gfxRemap32->remapToGray(color, gray);
return s->r_acc;
}
reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv) {
- byte color = argv[0].toUint16();
- byte gray = argv[1].toUint16();
- byte percent = argv[2].toUint16();
- // The last parameter, depth, is unused
- g_sci->_gfxRemap32->setRemappingToPercentGray(color, gray, percent);
+ const uint8 color = argv[0].toUint16();
+ const int16 gray = argv[1].toSint16();
+ const int16 percent = argv[2].toSint16();
+ // NOTE: There is an optional last parameter after `percent`
+ // which was only used by the priority map debugger, which
+ // does not exist in release versions of SSCI
+ g_sci->_gfxRemap32->remapToPercentGray(color, gray, percent);
return s->r_acc;
}
reg_t kRemapColorsBlockRange(EngineState *s, int argc, reg_t *argv) {
- byte from = argv[0].toUint16();
- byte count = argv[1].toUint16();
- g_sci->_gfxRemap32->setNoMatchRange(from, count);
+ const uint8 from = argv[0].toUint16();
+ const uint8 count = argv[1].toUint16();
+ g_sci->_gfxRemap32->blockRange(from, count);
return s->r_acc;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 302f046..0972aec 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -48,8 +48,9 @@
#include "sci/sound/music.h"
#ifdef ENABLE_SCI32
-#include "sci/graphics/palette32.h"
#include "sci/graphics/frameout.h"
+#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap32.h"
#endif
namespace Sci {
@@ -807,6 +808,33 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
+
+void GfxRemap32::saveLoadWithSerializer(Common::Serializer &s) {
+ if (s.getVersion() < 35) {
+ return;
+ }
+
+ s.syncAsByte(_numActiveRemaps);
+ s.syncAsByte(_blockedRangeStart);
+ s.syncAsSint16LE(_blockedRangeCount);
+
+ for (uint i = 0; i < _remaps.size(); ++i) {
+ SingleRemap &singleRemap = _remaps[i];
+ s.syncAsByte(singleRemap._type);
+ if (s.isLoading() && singleRemap._type != kRemapNone) {
+ singleRemap.reset();
+ }
+ s.syncAsByte(singleRemap._from);
+ s.syncAsByte(singleRemap._to);
+ s.syncAsByte(singleRemap._delta);
+ s.syncAsByte(singleRemap._percent);
+ s.syncAsByte(singleRemap._gray);
+ }
+
+ if (s.isLoading()) {
+ _needsUpdate = true;
+ }
+}
#endif
void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 459e992..43909ac 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,6 +37,7 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
+ * 35 - SCI32 remap
* 34 - SCI32 palettes, and store play time in ticks
* 33 - new overridePriority flag in MusicEntry
* 32 - new playBed flag in MusicEntry
@@ -59,7 +60,7 @@ struct EngineState;
*/
enum {
- CURRENT_SAVEGAME_VERSION = 34,
+ CURRENT_SAVEGAME_VERSION = 35,
MINIMUM_SAVEGAME_VERSION = 14
};
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 9d3ab04..fd37020 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -1005,7 +1005,7 @@ void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showLi
}
void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) {
- Palette sourcePalette(*_palette->getNextPalette());
+ Palette sourcePalette(_palette->getNextPalette());
alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16();
@@ -1045,7 +1045,7 @@ void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry
drawScreenItemList(screenItemLists[i]);
}
- Palette nextPalette(*_palette->getNextPalette());
+ Palette nextPalette(_palette->getNextPalette());
if (prevRoom < 1000) {
for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 5c9bfd6..0840e82 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -78,15 +78,6 @@ inline void mergePaletteInternal(Palette *const to, const Palette *const from) {
}
}
-const Palette *GfxPalette32::getNextPalette() const {
- return &_nextPalette;
-}
-
-const Palette *GfxPalette32::getCurrentPalette() const {
- return &_sysPalette;
-}
-
-
void GfxPalette32::submit(Palette &palette) {
// TODO: The resource manager in SCI32 retains raw data of palettes from
// the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index ec75b58..7dda53e 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -113,8 +113,8 @@ private:
public:
virtual void saveLoadWithSerializer(Common::Serializer &s) override;
- const Palette *getNextPalette() const;
- const Palette *getCurrentPalette() const;
+ inline const Palette &getNextPalette() const { return _nextPalette; };
+ inline const Palette &getCurrentPalette() const { return _sysPalette; };
bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
@@ -240,6 +240,11 @@ private:
* 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 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).
*/
bool _cycleMap[256];
inline void clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
@@ -257,7 +262,7 @@ public:
void cycleAllOff();
void applyAllCycles();
void applyCycles();
- const bool *getCyclemap() { return _cycleMap; }
+ inline const bool *getCycleMap() const { return _cycleMap; }
#pragma mark -
#pragma mark Fading
diff --git a/engines/sci/graphics/remap.h b/engines/sci/graphics/remap.h
index a9cd76a..98177f6 100644
--- a/engines/sci/graphics/remap.h
+++ b/engines/sci/graphics/remap.h
@@ -24,7 +24,7 @@
#define SCI_GRAPHICS_REMAP_H
#include "common/array.h"
-#include "sci/graphics/helpers.h"
+#include "common/serializer.h"
namespace Sci {
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
index ef27c84..d5a2362 100644
--- a/engines/sci/graphics/remap32.cpp
+++ b/engines/sci/graphics/remap32.cpp
@@ -26,313 +26,443 @@
namespace Sci {
-GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
- for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
- _noMapStart = _noMapCount = 0;
- _update = false;
- _remapCount = 0;
-
- // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle.
- // All versions of KQ7 are using the older remap range semantics.
- _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) ? 244 : 254;
+#pragma mark SingleRemap
+
+void SingleRemap::reset() {
+ _lastPercent = 100;
+ _lastGray = 0;
+
+ const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
+ const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
+ for (uint i = 0; i < remapStartColor; ++i) {
+ const Color &color = currentPalette.colors[i];
+ _remapColors[i] = i;
+ _originalColors[i] = color;
+ _originalColorsChanged[i] = true;
+ _idealColors[i] = color;
+ _idealColorsChanged[i] = false;
+ _matchDistances[i] = 0;
+ }
}
-void GfxRemap32::remapOff(byte color) {
- if (!color) {
- for (int i = 0; i < REMAP_COLOR_COUNT; i++)
- _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
-
- _remapCount = 0;
- } else {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemapNone);
- _remapCount--;
+bool SingleRemap::update() {
+ switch (_type) {
+ case kRemapNone:
+ break;
+ case kRemapByRange:
+ return updateRange();
+ case kRemapByPercent:
+ return updateBrightness();
+ case kRemapToGray:
+ return updateSaturation();
+ case kRemapToPercentGray:
+ return updateSaturationAndBrightness();
+ default:
+ error("Illegal remap type %d", _type);
}
- _update = true;
+ return false;
}
-void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemapByRange);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
+bool SingleRemap::updateRange() {
+ const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
+ bool updated = false;
-void GfxRemap32::setRemappingPercent(byte color, byte percent) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemapByPercent);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
+ for (uint i = 0; i < remapStartColor; ++i) {
+ uint8 targetColor;
+ if (_from <= i && i <= _to) {
+ targetColor = i + _delta;
+ } else {
+ targetColor = i;
+ }
-void GfxRemap32::setRemappingToGray(byte color, byte gray) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemapToGray);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
+ if (_remapColors[i] != targetColor) {
+ updated = true;
+ _remapColors[i] = targetColor;
+ }
-void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemapToPercentGray);
- initColorArrays(_remapEndColor - color);
- _remapCount++;
- _update = true;
-}
+ _originalColorsChanged[i] = true;
+ }
-void GfxRemap32::setNoMatchRange(byte from, byte count) {
- _noMapStart = from;
- _noMapCount = count;
+ return updated;
}
-bool GfxRemap32::remapEnabled(byte color) const {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- return (_remaps[index].type != kRemapNone);
-}
+bool SingleRemap::updateBrightness() {
+ const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
+ const Palette &nextPalette = g_sci->_gfxPalette32->getNextPalette();
+ for (uint i = 1; i < remapStartColor; ++i) {
+ Color color(nextPalette.colors[i]);
-byte GfxRemap32::remapColor(byte color, byte target) {
- assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
- const byte index = _remapEndColor - color;
- if (_remaps[index].type != kRemapNone)
- return _remaps[index].remap[target];
- else
- return target;
-}
+ if (_originalColors[i] != color) {
+ _originalColorsChanged[i] = true;
+ _originalColors[i] = color;
+ }
-void GfxRemap32::initColorArrays(byte index) {
- Palette *curPalette = &_palette->_sysPalette;
- RemapParams *curRemap = &_remaps[index];
+ if (_percent != _lastPercent || _originalColorsChanged[i]) {
+ // NOTE: SSCI checked if percent was over 100 and only
+ // then clipped values, but we always unconditionally
+ // ensure the result is in the correct range
+ color.r = MIN(255, (uint16)color.r * _percent / 100);
+ color.g = MIN(255, (uint16)color.g * _percent / 100);
+ color.b = MIN(255, (uint16)color.b * _percent / 100);
+
+ if (_idealColors[i] != color) {
+ _idealColorsChanged[i] = true;
+ _idealColors[i] = color;
+ }
+ }
+ }
- memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
- memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+ const bool updated = apply();
+ Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
+ Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
+ _lastPercent = _percent;
+ return updated;
}
-bool GfxRemap32::updateRemap(byte index, bool palChanged) {
- int result;
- RemapParams *curRemap = &_remaps[index];
- const Palette *curPalette = &_palette->_sysPalette;
- const Palette *nextPalette = _palette->getNextPalette();
- bool changed = false;
-
- if (!_update && !palChanged)
- return false;
-
- Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
-
- switch (curRemap->type) {
- case kRemapNone:
- return false;
- case kRemapByRange:
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
- if (curRemap->from <= i && i <= curRemap->to)
- result = i + curRemap->base;
- else
- result = i;
-
- if (curRemap->remap[i] != result) {
- changed = true;
- curRemap->remap[i] = result;
- }
-
- curRemap->colorChanged[i] = true;
+bool SingleRemap::updateSaturation() {
+ const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
+ const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
+ for (uint i = 1; i < remapStartColor; ++i) {
+ Color color(currentPalette.colors[i]);
+ if (_originalColors[i] != color) {
+ _originalColorsChanged[i] = true;
+ _originalColors[i] = color;
}
- return changed;
- case kRemapByPercent:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- // NOTE: This method uses nextPalette instead of curPalette
- Color color = nextPalette->colors[i];
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
+ if (_gray != _lastGray || _originalColorsChanged[i]) {
+ const int luminosity = (((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8) * _percent / 100;
- if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) {
- byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255);
- byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255);
- byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
+ color.r = MIN(255, color.r - ((color.r - luminosity) * _gray / 100));
+ color.g = MIN(255, color.g - ((color.g - luminosity) * _gray / 100));
+ color.b = MIN(255, color.b - ((color.b - luminosity) * _gray / 100));
+
+ if (_idealColors[i] != color) {
+ _idealColorsChanged[i] = true;
+ _idealColors[i] = color;
}
}
-
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldPercent = curRemap->percent;
- return changed;
- case kRemapToGray:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color color = curPalette->colors[i];
+ }
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
+ const bool updated = apply();
+ Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
+ Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
+ _lastGray = _gray;
+ return updated;
+}
- if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
- byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
- byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
- byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
- byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
- }
+bool SingleRemap::updateSaturationAndBrightness() {
+ const uint8 remapStartColor = g_sci->_gfxRemap32->getStartColor();
+ const Palette ¤tPalette = g_sci->_gfxPalette32->getCurrentPalette();
+ for (uint i = 1; i < remapStartColor; i++) {
+ Color color(currentPalette.colors[i]);
+ if (_originalColors[i] != color) {
+ _originalColorsChanged[i] = true;
+ _originalColors[i] = color;
}
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldGray = curRemap->gray;
- return changed;
- case kRemapToPercentGray:
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color color = curPalette->colors[i];
+ if (_percent != _lastPercent || _gray != _lastGray || _originalColorsChanged[i]) {
+ const int luminosity = (((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8) * _percent / 100;
- if (curRemap->curColor[i] != color) {
- curRemap->colorChanged[i] = true;
- curRemap->curColor[i] = color;
- }
+ color.r = MIN(255, color.r - ((color.r - luminosity) * _gray) / 100);
+ color.g = MIN(255, color.g - ((color.g - luminosity) * _gray) / 100);
+ color.b = MIN(255, color.b - ((color.b - luminosity) * _gray) / 100);
- if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
- byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
- lumosity = lumosity * curRemap->percent / 100;
- byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
- byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
- byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
- byte used = curRemap->targetColor[i].used;
-
- Color newColor = { used, red, green, blue };
- if (curRemap->targetColor[i] != newColor) {
- _targetChanged[i] = true;
- curRemap->targetColor[i] = newColor;
- }
+ if (_idealColors[i] != color) {
+ _idealColorsChanged[i] = true;
+ _idealColors[i] = color;
}
}
-
- changed = applyRemap(index);
- Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
- curRemap->oldPercent = curRemap->percent;
- curRemap->oldGray = curRemap->gray;
- return changed;
- default:
- return false;
}
-}
-static int colorDistance(Color a, Color b) {
- int rDiff = (a.r - b.r) * (a.r - b.r);
- int gDiff = (a.g - b.g) * (a.g - b.g);
- int bDiff = (a.b - b.b) * (a.b - b.b);
- return rDiff + gDiff + bDiff;
+ const bool updated = apply();
+ Common::fill(_originalColorsChanged, _originalColorsChanged + remapStartColor, false);
+ Common::fill(_idealColorsChanged, _idealColorsChanged + remapStartColor, false);
+ _lastPercent = _percent;
+ _lastGray = _gray;
+ return updated;
}
-bool GfxRemap32::applyRemap(byte index) {
- RemapParams *curRemap = &_remaps[index];
- const bool *cycleMap = _palette->getCyclemap();
- bool unmappedColors[NON_REMAPPED_COLOR_COUNT];
- bool changed = false;
+bool SingleRemap::apply() {
+ const GfxRemap32 *const gfxRemap32 = g_sci->_gfxRemap32;
+ const uint8 remapStartColor = gfxRemap32->getStartColor();
+
+ // Blocked colors are not allowed to be used as target
+ // colors for the remap
+ bool blockedColors[236];
+ Common::fill(blockedColors, blockedColors + remapStartColor, false);
- Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false);
- if (_noMapCount)
- Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true);
+ const bool *const paletteCycleMap = g_sci->_gfxPalette32->getCycleMap();
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
- if (cycleMap[i])
- unmappedColors[i] = true;
+ const int16 blockedRangeCount = gfxRemap32->getBlockedRangeCount();
+ if (blockedRangeCount) {
+ const uint8 blockedRangeStart = gfxRemap32->getBlockedRangeStart();
+ Common::fill(blockedColors + blockedRangeStart, blockedColors + blockedRangeStart + blockedRangeCount, true);
}
- for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
- Color targetColor = curRemap->targetColor[i];
- bool colorChanged = curRemap->colorChanged[curRemap->remap[i]];
+ for (uint i = 0; i < remapStartColor; ++i) {
+ if (paletteCycleMap[i]) {
+ blockedColors[i] = true;
+ }
+ }
- if (!_targetChanged[i] && !colorChanged)
- continue;
+ // NOTE: SSCI did a loop over colors here to create a
+ // new array of updated, unblocked colors, but then
+ // never used it
- if (_targetChanged[i] && colorChanged)
- if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i])
- continue;
+ bool updated = false;
+ for (uint i = 1; i < remapStartColor; ++i) {
+ int distance;
- int diff = 0;
- int16 result = matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
- if (result != -1 && curRemap->remap[i] != result) {
- changed = true;
- curRemap->remap[i] = result;
- curRemap->distance[i] = diff;
+ if (!_idealColorsChanged[i] && !_originalColorsChanged[_remapColors[i]]) {
+ continue;
}
- }
- return changed;
-}
+ if (
+ _idealColorsChanged[i] &&
+ _originalColorsChanged[_remapColors[i]] &&
+ _matchDistances[i] < 100 &&
+ colorDistance(_idealColors[i], _originalColors[_remapColors[i]]) <= _matchDistances[i]
+ ) {
+ continue;
+ }
-bool GfxRemap32::remapAllTables(bool palChanged) {
- bool changed = false;
+ const int16 bestColor = matchColor(_idealColors[i], _matchDistances[i], distance, blockedColors);
- for (int i = 0; i < REMAP_COLOR_COUNT; i++) {
- changed |= updateRemap(i, palChanged);
+ if (bestColor != -1 && _remapColors[i] != bestColor) {
+ updated = true;
+ _remapColors[i] = bestColor;
+ _matchDistances[i] = distance;
+ }
}
- _update = false;
- return changed;
+ return updated;
}
-// In SCI32 engine this method is SOLPalette::Match(Rgb24 *, int, int *, int *)
-// and is used by Remap
-// TODO: Anything that calls GfxPalette::matchColor(int, int, int) is going to
-// match using an algorithm from SCI16 engine right now. This needs to be
-// corrected in the future so either nothing calls
-// GfxPalette::matchColor(int, int, int), or it is fixed to match the other
-// SCI32 algorithms.
-int16 GfxRemap32::matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) const {
+int SingleRemap::colorDistance(const Color &a, const Color &b) const {
+ int channelDistance = a.r - b.r;
+ int distance = channelDistance * channelDistance;
+ channelDistance = a.g - b.g;
+ distance += channelDistance * channelDistance;
+ channelDistance = a.b - b.b;
+ distance += channelDistance * channelDistance;
+ return distance;
+}
+
+int16 SingleRemap::matchColor(const Color &color, const int minimumDistance, int &outDistance, const bool *const blockedIndexes) const {
int16 bestIndex = -1;
- int bestDifference = 0xFFFFF;
- int difference = defaultDifference;
- const Palette &_sysPalette = *g_sci->_gfxPalette32->getCurrentPalette();
+ int bestDistance = 0xFFFFF;
+ int distance = minimumDistance;
+ const Palette &nextPalette = g_sci->_gfxPalette32->getNextPalette();
- // SQ6 DOS really does check only the first 236 entries
- for (int i = 0, channelDifference; i < 236; ++i) {
- if (matchTable[i] == 0) {
+ for (uint i = 0, channelDistance; i < g_sci->_gfxRemap32->getStartColor(); ++i) {
+ if (blockedIndexes[i]) {
continue;
}
- difference = _sysPalette.colors[i].r - r;
- difference *= difference;
- if (bestDifference <= difference) {
+ distance = nextPalette.colors[i].r - color.r;
+ distance *= distance;
+ if (bestDistance <= distance) {
continue;
}
- channelDifference = _sysPalette.colors[i].g - g;
- difference += channelDifference * channelDifference;
- if (bestDifference <= difference) {
+ channelDistance = nextPalette.colors[i].g - color.g;
+ distance += channelDistance * channelDistance;
+ if (bestDistance <= distance) {
continue;
}
- channelDifference = _sysPalette.colors[i].b - b;
- difference += channelDifference * channelDifference;
- if (bestDifference <= difference) {
+ channelDistance = nextPalette.colors[i].b - color.b;
+ distance += channelDistance * channelDistance;
+ if (bestDistance <= distance) {
continue;
}
- bestDifference = difference;
+ bestDistance = distance;
bestIndex = i;
}
- // NOTE: This value is only valid if the last index to
- // perform a difference calculation was the best index
- lastCalculatedDifference = difference;
+ // This value is only valid if the last index to
+ // perform a distance calculation was the best index
+ outDistance = distance;
return bestIndex;
}
+#pragma mark -
+#pragma mark GfxRemap32
+
+GfxRemap32::GfxRemap32() :
+ _needsUpdate(false),
+ _blockedRangeStart(0),
+ _blockedRangeCount(0),
+ _remapStartColor(236),
+ _numActiveRemaps(0) {
+ // The `_remapStartColor` seems to always be 236 in SSCI,
+ // but if it is ever changed then the various C-style
+ // member arrays hard-coded to 236 need to be changed to
+ // match the highest possible value of `_remapStartColor`
+ assert(_remapStartColor == 236);
+
+ if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7) {
+ _remaps.resize(9);
+ } else {
+ _remaps.resize(19);
+ }
+
+ _remapEndColor = _remapStartColor + _remaps.size() - 1;
+}
+
+void GfxRemap32::remapOff(const uint8 color) {
+ if (color == 0) {
+ remapAllOff();
+ return;
+ }
+
+ // NOTE: SSCI simply ignored invalid input values, but
+ // we at least give a warning so games can be investigated
+ // for script bugs
+ if (color < _remapStartColor || color > _remapEndColor) {
+ warning("GfxRemap32::remapOff: %d out of remap range", color);
+ return;
+ }
+
+ const uint8 index = _remapEndColor - color;
+ SingleRemap &singleRemap = _remaps[index];
+ singleRemap._type = kRemapNone;
+ --_numActiveRemaps;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::remapAllOff() {
+ for (uint i = 0, len = _remaps.size(); i < len; ++i) {
+ _remaps[i]._type = kRemapNone;
+ }
+
+ _numActiveRemaps = 0;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta) {
+ // NOTE: SSCI simply ignored invalid input values, but
+ // we at least give a warning so games can be investigated
+ // for script bugs
+ if (color < _remapStartColor || color > _remapEndColor) {
+ warning("GfxRemap32::remapByRange: %d out of remap range", color);
+ return;
+ }
+
+ if (from < 0) {
+ warning("GfxRemap32::remapByRange: attempt to remap negative color %d", from);
+ return;
+ }
+
+ if (to >= _remapStartColor) {
+ warning("GfxRemap32::remapByRange: attempt to remap into the remap zone at %d", to);
+ return;
+ }
+
+ const uint8 index = _remapEndColor - color;
+ SingleRemap &singleRemap = _remaps[index];
+
+ if (singleRemap._type == kRemapNone) {
+ ++_numActiveRemaps;
+ singleRemap.reset();
+ }
+
+ singleRemap._from = from;
+ singleRemap._to = to;
+ singleRemap._delta = delta;
+ singleRemap._type = kRemapByRange;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::remapByPercent(const uint8 color, const int16 percent) {
+ // NOTE: SSCI simply ignored invalid input values, but
+ // we at least give a warning so games can be investigated
+ // for script bugs
+ if (color < _remapStartColor || color > _remapEndColor) {
+ warning("GfxRemap32::remapByPercent: %d out of remap range", color);
+ return;
+ }
+
+ const uint8 index = _remapEndColor - color;
+ SingleRemap &singleRemap = _remaps[index];
+
+ if (singleRemap._type == kRemapNone) {
+ ++_numActiveRemaps;
+ singleRemap.reset();
+ }
+
+ singleRemap._percent = percent;
+ singleRemap._type = kRemapByPercent;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::remapToGray(const uint8 color, const int8 gray) {
+ // NOTE: SSCI simply ignored invalid input values, but
+ // we at least give a warning so games can be investigated
+ // for script bugs
+ if (color < _remapStartColor || color > _remapEndColor) {
+ warning("GfxRemap32::remapToGray: %d out of remap range", color);
+ return;
+ }
+
+ if (gray < 0 || gray > 100) {
+ error("RemapToGray percent out of range; gray = %d", gray);
+ }
+
+ const uint8 index = _remapEndColor - color;
+ SingleRemap &singleRemap = _remaps[index];
+
+ if (singleRemap._type == kRemapNone) {
+ ++_numActiveRemaps;
+ singleRemap.reset();
+ }
+
+ singleRemap._gray = gray;
+ singleRemap._type = kRemapToGray;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::remapToPercentGray(const uint8 color, const int16 gray, const int16 percent) {
+ // NOTE: SSCI simply ignored invalid input values, but
+ // we at least give a warning so games can be investigated
+ // for script bugs
+ if (color < _remapStartColor || color > _remapEndColor) {
+ warning("GfxRemap32::remapToPercentGray: %d out of remap range", color);
+ return;
+ }
+
+ const uint8 index = _remapEndColor - color;
+ SingleRemap &singleRemap = _remaps[index];
+
+ if (singleRemap._type == kRemapNone) {
+ ++_numActiveRemaps;
+ singleRemap.reset();
+ }
+
+ singleRemap._percent = percent;
+ singleRemap._gray = gray;
+ singleRemap._type = kRemapToPercentGray;
+ _needsUpdate = true;
+}
+
+void GfxRemap32::blockRange(const uint8 from, const int16 count) {
+ _blockedRangeStart = from;
+ _blockedRangeCount = count;
+}
+
+bool GfxRemap32::remapAllTables(const bool paletteUpdated) {
+ if (!_needsUpdate && !paletteUpdated) {
+ return false;
+ }
+
+ bool updated = false;
+
+ for (SingleRemapsList::iterator it = _remaps.begin(); it != _remaps.end(); ++it) {
+ if (it->_type != kRemapNone) {
+ updated |= it->update();
+ }
+ }
+
+ _needsUpdate = false;
+ return updated;
+}
} // End of namespace Sci
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
index 52736f5..5f629d7 100644
--- a/engines/sci/graphics/remap32.h
+++ b/engines/sci/graphics/remap32.h
@@ -23,12 +23,13 @@
#ifndef SCI_GRAPHICS_REMAP32_H
#define SCI_GRAPHICS_REMAP32_H
+#include "common/algorithm.h"
#include "common/array.h"
+#include "common/scummsys.h"
+#include "sci/graphics/helpers.h"
namespace Sci {
-
-#define REMAP_COLOR_COUNT 9
-#define NON_REMAPPED_COLOR_COUNT 236
+class GfxPalette32;
enum RemapType {
kRemapNone = 0,
@@ -38,84 +39,362 @@ enum RemapType {
kRemapToPercentGray = 4
};
-struct RemapParams {
- byte from;
- byte to;
- byte base;
- byte gray;
- byte oldGray;
- byte percent;
- byte oldPercent;
- RemapType type;
- Color curColor[256];
- Color targetColor[256];
- byte distance[256];
- byte remap[256];
- bool colorChanged[256];
-
- RemapParams() {
- from = to = base = gray = oldGray = percent = oldPercent = 0;
- type = kRemapNone;
-
- // curColor and targetColor are initialized in GfxRemap32::initColorArrays
- memset(curColor, 0, 256 * sizeof(Color));
- memset(targetColor, 0, 256 * sizeof(Color));
- memset(distance, 0, 256);
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
- remap[i] = i;
- Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
- }
+#pragma mark -
+#pragma mark SingleRemap
- RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, RemapType type_) {
- from = from_;
- to = to_;
- base = base_;
- gray = oldGray = gray_;
- percent = oldPercent = percent_;
- type = type_;
-
- // curColor and targetColor are initialized in GfxRemap32::initColorArrays
- memset(curColor, 0, 256 * sizeof(Color));
- memset(targetColor, 0, 256 * sizeof(Color));
- memset(distance, 0, 256);
- for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
- remap[i] = i;
- Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
- }
+/**
+ * SingleRemap objects each manage one remapping operation.
+ */
+class SingleRemap {
+public:
+ SingleRemap() : _type(kRemapNone) {}
+
+ /**
+ * The type of remap.
+ */
+ RemapType _type;
+
+ /**
+ * The first color that should be shifted by a range
+ * remap.
+ */
+ uint8 _from;
+
+ /**
+ * The last color that should be shifted a range remap.
+ */
+ uint8 _to;
+
+ /**
+ * The direction and amount that the colors should be
+ * shifted in a range remap.
+ */
+ int16 _delta;
+
+ /**
+ * The difference in brightness that should be
+ * applied by a brightness (percent) remap.
+ *
+ * This value may be be greater than 100, in
+ * which case the color will be oversaturated.
+ */
+ int16 _percent;
+
+ /**
+ * The amount of desaturation that should be
+ * applied by a saturation (gray) remap, where
+ * 0 is full saturation and 100 is full
+ * desaturation.
+ */
+ uint8 _gray;
+
+ /**
+ * The final array used by CelObj renderers to composite
+ * remapped pixels to the screen buffer.
+ *
+ * Here is how it works:
+ *
+ * The source bitmap being rendered will have pixels
+ * within the remap range (236-245 or 236-254), and the
+ * target buffer will have colors in the non-remapped
+ * range (0-235).
+ *
+ * To arrive at the correct color, first the source
+ * pixel is used to look up the correct SingleRemap for
+ * that pixel. Then, the final composited color is
+ * looked up in this array using the target's pixel
+ * color. In other words,
+ * `target = _remaps[remapEndColor - source].remapColors[target]`.
+ */
+ uint8 _remapColors[236];
+
+ /**
+ * Resets this SingleRemap's color information to
+ * default values.
+ */
+ void reset();
+
+ /**
+ * Recalculates and reapplies remap colors to the
+ * `_remapColors` array.
+ */
+ bool update();
+
+private:
+ /**
+ * The previous brightness value. Used to
+ * determine whether or not targetColors needs
+ * to be updated.
+ */
+ int16 _lastPercent;
+
+ /**
+ * The previous saturation value. Used to
+ * determine whether or not targetColors needs
+ * to be updated.
+ */
+ uint8 _lastGray;
+
+ /**
+ * The colors from the current GfxPalette32 palette
+ * before this SingleRemap is applied.
+ */
+ Color _originalColors[236];
+
+ /**
+ * Map of colors that changed in `_originalColors`
+ * when this SingleRemap was updated. This map is
+ * transient and gets reset to `false` after the
+ * SingleRemap finishes updating.
+ */
+ bool _originalColorsChanged[236];
+
+ /**
+ * The ideal target RGB color values for each generated
+ * remap color.
+ */
+ Color _idealColors[236];
+
+ /**
+ * Map of colors that changed in `_idealColors` when
+ * this SingleRemap was updated. This map is transient
+ * and gets reset to `false` after the SingleRemap
+ * finishes applying.
+ */
+ bool _idealColorsChanged[236];
+
+ /**
+ * When applying a SingleRemap, finding an appropriate
+ * color in the palette is the responsibility of a
+ * distance function. Once a match is found, the
+ * distance of that match is stored here so that the
+ * next time the SingleRemap is applied, it can check
+ * the distance from the previous application and avoid
+ * triggering an expensive redraw of the entire screen
+ * if the new palette value only changed slightly.
+ */
+ int _matchDistances[236];
+
+ /**
+ * Computes the final target values for a range remap
+ * and applies them directly to the `_remaps` map.
+ *
+ * @note Was ByRange in SSCI.
+ */
+ bool updateRange();
+
+ /**
+ * Computes the intermediate target values for a
+ * brightness remap and applies them indirectly via
+ * the `apply` method.
+ *
+ * @note Was ByPercent in SSCI.
+ */
+ bool updateBrightness();
+
+ /**
+ * Computes the intermediate target values for a
+ * saturation remap and applies them indirectly via
+ * the `apply` method.
+ *
+ * @note Was ToGray in SSCI.
+ */
+ bool updateSaturation();
+
+ /**
+ * Computes the intermediate target values for a
+ * saturation + brightness bitmap and applies them
+ * indirectly via the `apply` method.
+ *
+ * @note Was ToPercentGray in SSCI.
+ */
+ bool updateSaturationAndBrightness();
+
+ /**
+ * Computes and applies the final values to the
+ * `_remaps` map.
+ *
+ * @note In SSCI, a boolean array of changed values
+ * was passed into this method, but this was done by
+ * creating arrays on the stack in the caller. Instead
+ * of doing this, we simply add another member property
+ * `_idealColorsChanged` and use that instead.
+ */
+ bool apply();
+
+ /**
+ * Calculates the square distance of two colors.
+ *
+ * @note In SSCI this method is Rgb24::Dist, but it is
+ * only used by SingleRemap.
+ */
+ int colorDistance(const Color &a, const Color &b) const;
+
+ /**
+ * Finds the closest index in the next palette matching
+ * the given RGB color. Returns -1 if no match can be
+ * found that is closer than `minimumDistance`.
+ *
+ * @note In SSCI, this method is SOLPalette::Match, but
+ * this particular signature is only used by
+ * SingleRemap.
+ */
+ int16 matchColor(const Color &color, const int minimumDistance, int &outDistance, const bool *const blockedIndexes) const;
};
-class GfxRemap32 {
+#pragma mark -
+#pragma mark GfxRemap32
+
+/**
+ * This class provides color remapping support for SCI32
+ * games.
+ */
+class GfxRemap32 : public Common::Serializable {
public:
- GfxRemap32(GfxPalette32 *palette);
- ~GfxRemap32() {}
-
- void remapOff(byte color);
- void setRemappingRange(byte color, byte from, byte to, byte base);
- void setRemappingPercent(byte color, byte percent);
- void setRemappingToGray(byte color, byte gray);
- void setRemappingToPercentGray(byte color, byte gray, byte percent);
- void setNoMatchRange(byte from, byte count);
- bool remapEnabled(byte color) const;
- byte remapColor(byte color, byte target);
- bool remapAllTables(bool palChanged);
- int getRemapCount() const { return _remapCount; }
- int getStartColor() const { return _remapEndColor - REMAP_COLOR_COUNT + 1; }
- int getEndColor() const { return _remapEndColor; }
+ GfxRemap32();
+
+ void saveLoadWithSerializer(Common::Serializer &s);
+
+ inline uint8 getRemapCount() const { return _numActiveRemaps; }
+ inline uint8 getStartColor() const { return _remapStartColor; }
+ inline uint8 getEndColor() const { return _remapEndColor; }
+ inline uint8 getBlockedRangeStart() const { return _blockedRangeStart; }
+ inline int16 getBlockedRangeCount() const { return _blockedRangeCount; }
+
+ /**
+ * Turns off remapping of the given color. If `color` is
+ * 0, all remaps are turned off.
+ */
+ void remapOff(const uint8 color);
+
+ /**
+ * Turns off all color remaps.
+ */
+ void remapAllOff();
+
+ /**
+ * Configures a SingleRemap for the remap color `color`.
+ * The SingleRemap will shift palette colors between
+ * `from` and `to` (inclusive) by `delta` palette
+ * entries when the remap is applied.
+ */
+ void remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta);
+
+ /**
+ * Configures a SingleRemap for the remap color `color`
+ * to modify the brightness of remapped colors by
+ * `percent`.
+ */
+ void remapByPercent(const uint8 color, const int16 percent);
+
+ /**
+ * Configures a SingleRemap for the remap color `color`
+ * to modify the saturation of remapped colors by
+ * `gray`.
+ */
+ void remapToGray(const uint8 color, const int8 gray);
+
+ /**
+ * Configures a SingleRemap for the remap color `color`
+ * to modify the brightness of remapped colors by
+ * `percent`, and saturation of remapped colors by
+ * `gray`.
+ */
+ void remapToPercentGray(const uint8 color, const int16 gray, const int16 percent);
+
+ /**
+ * Prevents GfxRemap32 from using the given range of
+ * palette entries as potential remap targets.
+ *
+ * @NOTE Was DontMapToRange in SSCI.
+ */
+ void blockRange(const uint8 from, const int16 count);
+
+ /**
+ * Determines whether or not the given color has an
+ * active remapper. If it does not, it is treated as a
+ * skip color and the pixel is not drawn.
+ *
+ * @note SSCI uses a boolean array to decide whether a
+ * a pixel is remapped, but it is possible to get the
+ * same information from `_remaps`, as this function
+ * does.
+ * Presumably, the separate array was created for
+ * performance reasons, since this is called a lot in
+ * the most critical section of the renderer.
+ */
+ inline bool remapEnabled(uint8 color) const {
+ const uint8 index = _remapEndColor - color;
+ assert(index < _remaps.size());
+ return (_remaps[index]._type != kRemapNone);
+ }
+
+ /**
+ * Calculates the correct color for a target by looking
+ * up the target color in the SingleRemap that controls
+ * the given sourceColor. If there is no remap for the
+ * given color, it will be treated as a skip color.
+ */
+ inline uint8 remapColor(const uint8 sourceColor, const uint8 targetColor) const {
+ const uint8 index = _remapEndColor - sourceColor;
+ assert(index < _remaps.size());
+ const SingleRemap &singleRemap = _remaps[index];
+ assert(singleRemap._type != kRemapNone);
+ return singleRemap._remapColors[targetColor];
+ }
+
+ /**
+ * Updates all active remaps in response to a palette
+ * change or a remap settings change.
+ *
+ * `paletteChanged` is true if the next palette in
+ * GfxPalette32 has been previously modified by other
+ * palette operations.
+ */
+ bool remapAllTables(const bool paletteUpdated);
+
private:
- GfxPalette32 *_palette;
- RemapParams _remaps[REMAP_COLOR_COUNT];
- bool _update;
- byte _noMapStart, _noMapCount;
- bool _targetChanged[NON_REMAPPED_COLOR_COUNT];
- byte _remapEndColor;
- int _remapCount;
-
- void initColorArrays(byte index);
- bool applyRemap(byte index);
- bool updateRemap(byte index, bool palChanged);
- int16 matchColor(const byte r, const byte g, const byte b, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable) const;
-};
+ typedef Common::Array<SingleRemap> SingleRemapsList;
-} // End of namespace Sci
+ /**
+ * The first index of the remap area in the system
+ * palette.
+ */
+ const uint8 _remapStartColor;
+
+ /**
+ * The last index of the remap area in the system
+ * palette.
+ */
+ uint8 _remapEndColor;
+ /**
+ * The number of currently active remaps.
+ */
+ uint8 _numActiveRemaps;
+
+ /**
+ * The list of SingleRemaps.
+ */
+ SingleRemapsList _remaps;
+
+ /**
+ * If true, indicates that one or more SingleRemaps were
+ * reconfigured and all remaps need to be recalculated.
+ */
+ bool _needsUpdate;
+
+ /**
+ * The first color that is blocked from being used as a
+ * remap target color.
+ */
+ uint8 _blockedRangeStart;
+
+ /**
+ * The size of the range of blocked colors. If zero,
+ * all colors are potential targets for remapping.
+ */
+ int16 _blockedRangeCount;
+};
+} // End of namespace Sci
#endif
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 243c12b..41fa144 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -700,7 +700,7 @@ void SciEngine::initGraphics() {
if (getSciVersion() >= SCI_VERSION_2) {
_gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen);
_gfxPalette16 = _gfxPalette32;
- _gfxRemap32 = new GfxRemap32(_gfxPalette32);
+ _gfxRemap32 = new GfxRemap32();
} else {
#endif
_gfxPalette16 = new GfxPalette(_resMan, _gfxScreen);
Commit: 7edc5cd891d903e8ae114238745a965c319d7fa3
https://github.com/scummvm/scummvm/commit/7edc5cd891d903e8ae114238745a965c319d7fa3
Author: Willem Jan Palenstijn (wjp at usecode.org)
Date: 2016-07-01T00:50:44+02:00
Commit Message:
Merge branch 'remap'
Changed paths:
More information about the Scummvm-git-logs
mailing list