diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 1202982986a..b269e9789d1 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 dacaafe7571..19bee359c53 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 cae5a09789c..73236b98ed2 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 019a06930cc..9270c81c028 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 0972aec4a4f..302f0464585 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 43909accf26..459e992e244 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 befa5cda18a..3018c6b1c5c 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 >(target, targetRect, scaledPosition); + debug("drawHzFlip"); + dummyFill(target, targetRect); } void CelObj::drawNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - render >(target, targetRect, scaledPosition); + debug("drawNoFlip"); + dummyFill(target, targetRect); } void CelObj::drawUncompNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - render >(target, targetRect, scaledPosition); + debug("drawUncompNoFlip"); + dummyFill(target, targetRect); } void CelObj::drawUncompHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - render >(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 >(target, targetRect, scaledPosition, scaleX, scaleY); - } else { - render >(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 >(target, targetRect, scaledPosition, scaleX, scaleY); - } else { - render >(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 >(target, targetRect, scaledPosition, scaleX, scaleY); - } else { + else render >(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 >(target, targetRect, scaledPosition, scaleX, scaleY); - } else { + else render >(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 >(target, targetRect, scaledPosition, scaleX, scaleY); - } else { + else render >(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 fd370208960..5771ab59ff1 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/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) { diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp index 0840e82a40d..68440116750 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 7dda53e5c1c..1902d00ed73 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 175875c4148..6f5ad424fd4 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 2abf03ea29f..ff49e52f13a 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(color.r * curRemap->percent / 100, 0, 255); + byte green = CLIP(color.g * curRemap->percent / 100, 0, 255); + byte blue = CLIP(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(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255); + byte green = CLIP(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255); + byte blue = CLIP(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(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255); + byte green = CLIP(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255); + byte blue = CLIP(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 98177f6d195..d012568f7f2 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 d5a2362f14e..00000000000 --- 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 5f629d733e1..00000000000 --- 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 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 96b48c0477f..91590208c12 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 5d54e2a52c2..ba6c8530754 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 41fa144b068..b80456c09c1 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);