mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-22 18:37:01 +00:00
Revert "SCI32: Fix broken Remap implementation"
This reverts commit cfda8b9ecd8a6e3c003abe533ea2e2981d8ba984. This is only to re-apply it immediately in a series of smaller commits.
This commit is contained in:
parent
a40e43f777
commit
c6c9593840
@ -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);
|
||||
|
@ -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 },
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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/plane32.h"
|
||||
#include "sci/graphics/remap32.h"
|
||||
#include "sci/graphics/screen_item32.h"
|
||||
#include "sci/graphics/picture.h"
|
||||
#include "sci/graphics/remap.h"
|
||||
#include "sci/graphics/text32.h"
|
||||
#include "sci/graphics/plane32.h"
|
||||
#include "sci/graphics/screen_item32.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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user