diff options
author | Colin Snover | 2016-07-09 12:41:12 -0500 |
---|---|---|
committer | Colin Snover | 2016-07-11 10:39:50 -0500 |
commit | 4cfc3876026f15aa394dfa45809c4a340eef60f0 (patch) | |
tree | ec318675dd04d86bf8bcbebc99df27c1933cddee | |
parent | 7f53a26d9e8b55a865efea2f912189b01ca56258 (diff) | |
download | scummvm-rg350-4cfc3876026f15aa394dfa45809c4a340eef60f0.tar.gz scummvm-rg350-4cfc3876026f15aa394dfa45809c4a340eef60f0.tar.bz2 scummvm-rg350-4cfc3876026f15aa394dfa45809c4a340eef60f0.zip |
SCI32: Split GfxPalette and GfxPalette32 + HunkPalette
-rw-r--r-- | engines/sci/console.cpp | 15 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 3 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 5 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics32.cpp | 13 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 11 | ||||
-rw-r--r-- | engines/sci/graphics/celobj32.cpp | 7 | ||||
-rw-r--r-- | engines/sci/graphics/palette.h | 10 | ||||
-rw-r--r-- | engines/sci/graphics/palette32.cpp | 234 | ||||
-rw-r--r-- | engines/sci/graphics/palette32.h | 158 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 13 |
10 files changed, 336 insertions, 133 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 2c74fe4b0c..6898745858 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -497,8 +497,10 @@ bool Console::cmdGetVersion(int argc, const char **argv) { if (getSciVersion() <= SCI_VERSION_1_1) { debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "yes" : "no"); } - debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no"); - debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no"); + if (getSciVersion() < SCI_VERSION_2) { + debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no"); + debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no"); + } debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); @@ -1620,7 +1622,7 @@ bool Console::cmdParserNodes(int argc, const char **argv) { bool Console::cmdSetPalette(int argc, const char **argv) { if (argc < 2) { - debugPrintf("Sets a palette resource\n"); + debugPrintf("Sets a palette resource (SCI16)\n"); debugPrintf("Usage: %s <resourceId>\n", argv[0]); debugPrintf("where <resourceId> is the number of the palette resource to set\n"); return true; @@ -1628,6 +1630,13 @@ bool Console::cmdSetPalette(int argc, const char **argv) { uint16 resourceId = atoi(argv[1]); +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + debugPrintf("This SCI version does not support this command\n"); + return true; + } +#endif + _engine->_gfxPalette16->kernelSetFromResource(resourceId, true); return true; } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 143903b96d..5ff4f932be 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -547,7 +547,8 @@ reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv); reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv); reg_t kSetScroll(EngineState *s, int argc, reg_t *argv); -reg_t kPalCycle(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv); reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv); reg_t kPalCycle(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 0e1262b299..8a1176eed8 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -291,12 +291,13 @@ static const SciKernelMapSubEntry kPalVary_subops[] = { // version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kPalette_subops[] = { - { SIG_SCIALL, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, + { SIG_SCI16, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, { SIG_SCI16, 2, MAP_CALL(PaletteSetFlag), "iii", NULL }, { SIG_SCI16, 3, MAP_CALL(PaletteUnsetFlag), "iii", kPaletteUnsetFlag_workarounds }, #ifdef ENABLE_SCI32 + { SIG_SCI32, 1, MAP_CALL(PaletteSetFromResource32), "i(i)", NULL }, { SIG_SCI32, 2, MAP_CALL(PaletteSetFade), "iii", NULL }, - { SIG_SCI32, 3, MAP_CALL(PaletteFindColor), "iii", NULL }, + { SIG_SCI32, 3, MAP_CALL(PaletteFindColor32), "iii", NULL }, #endif { SIG_SCI16, 4, MAP_CALL(PaletteSetIntensity), "iii(i)", NULL }, { SIG_SCI16, 5, MAP_CALL(PaletteFindColor), "iii", NULL }, diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index f0c08d105b..9cfe53255b 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -790,6 +790,19 @@ reg_t kMorphOn(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv) { + const GuiResourceId paletteId = argv[0].toUint16(); + g_sci->_gfxPalette32->loadPalette(paletteId); + return s->r_acc; +} + +reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv) { + const uint8 r = argv[0].toUint16(); + const uint8 g = argv[1].toUint16(); + const uint8 b = argv[2].toUint16(); + return make_reg(0, g_sci->_gfxPalette32->matchColor(r, g, b)); +} + reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) { uint16 fromColor = argv[0].toUint16(); uint16 toColor = argv[1].toUint16(); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 0972aec4a4..31fb848a2c 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -398,8 +398,13 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { _segMan->saveLoadWithSerializer(s); g_sci->_soundCmd->syncPlayList(s); - // NOTE: This will be GfxPalette32 for SCI32 engine games - g_sci->_gfxPalette16->saveLoadWithSerializer(s); + +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + g_sci->_gfxPalette32->saveLoadWithSerializer(s); + } else +#endif + g_sci->_gfxPalette16->saveLoadWithSerializer(s); } void Vocabulary::saveLoadWithSerializer(Common::Serializer &s) { @@ -767,7 +772,7 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint16LE(_varyFromColor); s.syncAsSint16LE(_varyToColor); s.syncAsUint16LE(_varyNumTimesPaused); - s.syncAsByte(_versionUpdated); + s.syncAsByte(_needsUpdate); s.syncAsSint32LE(_varyTime); s.syncAsUint32LE(_varyLastTick); diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp index da41879efe..48de054a31 100644 --- a/engines/sci/graphics/celobj32.cpp +++ b/engines/sci/graphics/celobj32.cpp @@ -570,12 +570,7 @@ uint8 CelObj::readPixel(uint16 x, const uint16 y, bool mirrorX) const { void CelObj::submitPalette() const { if (_hunkPaletteOffset) { - Palette palette; - - byte *res = getResPointer(); - // NOTE: In SCI engine this uses HunkPalette::Init. - // TODO: Use a better size value - g_sci->_gfxPalette32->createFromData(res + _hunkPaletteOffset, 999999, &palette); + HunkPalette palette(getResPointer() + _hunkPaletteOffset); g_sci->_gfxPalette32->submit(palette); } } diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 7335dc59d0..2178de8a91 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -51,7 +51,7 @@ public: bool setAmiga(); void modifyAmigaPalette(byte *data); void setEGA(); - virtual void set(Palette *sciPal, bool force, bool forceRealMerge = false); + void set(Palette *sciPal, bool force, bool forceRealMerge = false); bool insert(Palette *newPalette, Palette *destPalette); bool merge(Palette *pFrom, bool force, bool forceRealMerge); uint16 matchColor(byte r, byte g, byte b); @@ -63,11 +63,11 @@ public: void drewPicture(GuiResourceId pictureId); - virtual bool kernelSetFromResource(GuiResourceId resourceId, bool force); + bool kernelSetFromResource(GuiResourceId resourceId, bool force); void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag); void kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag); void kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 intensity, bool setPalette); - virtual int16 kernelFindColor(uint16 r, uint16 g, uint16 b); + int16 kernelFindColor(uint16 r, uint16 g, uint16 b); bool kernelAnimate(byte fromColor, byte toColor, int speed); void kernelAnimateSet(); reg_t kernelSave(); @@ -81,7 +81,7 @@ public: int16 kernelPalVaryGetCurrentStep(); int16 kernelPalVaryChangeTarget(GuiResourceId resourceId); void kernelPalVaryChangeTicks(uint16 ticks); - virtual void kernelPalVaryPause(bool pause); + void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); void palVaryUpdate(); void palVaryPrepareForTransition(); @@ -89,7 +89,7 @@ public: Palette _sysPalette; - virtual void saveLoadWithSerializer(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void palVarySaveLoadPalette(Common::Serializer &s, Palette *palette); byte findMacIconBarColor(byte r, byte g, byte b); diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp index 0840e82a40..3a321bf0b1 100644 --- a/engines/sci/graphics/palette32.cpp +++ b/engines/sci/graphics/palette32.cpp @@ -27,19 +27,109 @@ #include "sci/sci.h" #include "sci/event.h" #include "sci/resource.h" +#include "sci/util.h" #include "sci/graphics/palette32.h" #include "sci/graphics/remap32.h" #include "sci/graphics/screen.h" namespace Sci { -GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen) - : GfxPalette(resMan, screen), +#pragma mark HunkPalette + +HunkPalette::HunkPalette(byte *rawPalette) : + _version(0), + // NOTE: The header size in palettes is garbage. In at least KQ7 2.00b and + // Phant1, the 999.pal sets this value to 0. In most other palettes it is + // set to 14, but the *actual* size of the header structure used in SSCI is + // 13, which is reflected by `kHunkPaletteHeaderSize`. + // _headerSize(rawPalette[0]), + _numPalettes(rawPalette[10]), + _data(nullptr) { + assert(_numPalettes == 0 || _numPalettes == 1); + if (_numPalettes) { + _data = rawPalette; + _version = getEntryHeader().version; + } +} + +void HunkPalette::setVersion(const uint32 version) { + if (_numPalettes != _data[10]) { + error("Invalid HunkPalette"); + } + + if (_numPalettes) { + const EntryHeader header = getEntryHeader(); + if (header.version != _version) { + error("Invalid HunkPalette"); + } + + WRITE_SCI11ENDIAN_UINT32(getPalPointer() + kEntryVersionOffset, version); + _version = version; + } +} + +const HunkPalette::EntryHeader HunkPalette::getEntryHeader() const { + const byte *const data = getPalPointer(); + + EntryHeader header; + header.startColor = data[10]; + header.numColors = READ_SCI11ENDIAN_UINT16(data + 14); + header.used = data[16]; + header.sharedUsed = data[17]; + header.version = READ_SCI11ENDIAN_UINT32(data + kEntryVersionOffset); + + return header; +} + +const Palette HunkPalette::toPalette() const { + Palette outPalette; + + for (int16 i = 0; i < ARRAYSIZE(outPalette.colors); ++i) { + outPalette.colors[i].used = false; + outPalette.colors[i].r = 0; + outPalette.colors[i].g = 0; + outPalette.colors[i].b = 0; + } + + if (_numPalettes) { + const EntryHeader header = getEntryHeader(); + byte *data = getPalPointer() + kEntryHeaderSize; + + int16 end = header.startColor + header.numColors; + assert(end <= 256); + + if (header.sharedUsed) { + for (int16 i = header.startColor; i < end; ++i) { + outPalette.colors[i].used = header.used; + outPalette.colors[i].r = *data++; + outPalette.colors[i].g = *data++; + outPalette.colors[i].b = *data++; + } + } else { + for (int16 i = header.startColor; i < end; ++i) { + outPalette.colors[i].used = *data++; + outPalette.colors[i].r = *data++; + outPalette.colors[i].g = *data++; + outPalette.colors[i].b = *data++; + } + } + } + + return outPalette; +} + + +#pragma mark - +#pragma mark GfxPalette32 + +GfxPalette32::GfxPalette32(ResourceManager *resMan) + : _resMan(resMan), // Palette versioning _version(1), - _versionUpdated(false), - _sourcePalette(_sysPalette), - _nextPalette(_sysPalette), + _needsUpdate(false), + _currentPalette(), + _sourcePalette(_currentPalette), + _nextPalette(_currentPalette), // Clut _clutTable(nullptr), // Palette varying @@ -59,13 +149,14 @@ GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen) for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) { _fadeTable[i] = 100; } - // NOTE: In SCI engine, the palette manager constructor loads - // the default palette, but in ScummVM this initialisation - // is performed by SciEngine::run; see r49523 for details + + loadPalette(999); } GfxPalette32::~GfxPalette32() { +#ifdef ENABLE_SCI3_GAMES unloadClut(); +#endif varyOff(); cycleAllOff(); } @@ -78,79 +169,64 @@ inline void mergePaletteInternal(Palette *const to, const Palette *const from) { } } -void GfxPalette32::submit(Palette &palette) { - // TODO: The resource manager in SCI32 retains raw data of palettes from - // the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and - // the version number for submitted palettes is set in the raw palette - // data in memory as an int at an offset - // `rawData + *rawData[0x0a] * 2 + 31`. However, ScummVM does not retain - // resource data like this, so this versioning code, while accurate to - // the original engine, does not do much. - // (Hopefully this was an optimisation mechanism in SCI engine and not a - // clever thing to keep the same palette submitted many times from - // overwriting other palette entries.) - if (palette.timestamp == _version) { +void GfxPalette32::submit(const Palette &palette) { + const Palette oldSourcePalette(_sourcePalette); + mergePaletteInternal(&_sourcePalette, &palette); + + if (!_needsUpdate && _sourcePalette != oldSourcePalette) { + ++_version; + _needsUpdate = true; + } +} + +void GfxPalette32::submit(HunkPalette &hunkPalette) { + if (hunkPalette.getVersion() == _version) { return; } - Palette oldSourcePalette(_sourcePalette); + const Palette oldSourcePalette(_sourcePalette); + const Palette palette = hunkPalette.toPalette(); mergePaletteInternal(&_sourcePalette, &palette); - if (!_versionUpdated && _sourcePalette != oldSourcePalette) { + if (!_needsUpdate && oldSourcePalette != _sourcePalette) { ++_version; - _versionUpdated = true; + _needsUpdate = true; } - // Technically this information is supposed to be persisted through a - // HunkPalette object; right now it would just be lost once the temporary - // palette was destroyed. - palette.timestamp = _version; + hunkPalette.setVersion(_version); } -bool GfxPalette32::kernelSetFromResource(GuiResourceId resourceId, bool force) { - // TODO: In SCI32, palettes that come from resources come in as - // HunkPalette objects, not SOLPalette objects. The HunkPalettes - // have some extra persistence stuff associated with them, such that - // when they are passed to GfxPalette32::submit, they would get the - // version number of GfxPalette32 assigned to them. - Palette palette; +bool GfxPalette32::loadPalette(const GuiResourceId resourceId) { + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); - if (createPaletteFromResourceInternal(resourceId, &palette)) { - submit(palette); - return true; + if (!palResource) { + return false; } - return false; + HunkPalette palette(palResource->data); + submit(palette); + return true; } -// In SCI32 engine this method is SOLPalette::Match(Rgb24 *) -// and is called as PaletteMgr.Current().Match(color) -int16 GfxPalette32::kernelFindColor(uint16 r, uint16 g, uint16 b) { - // SQ6 SCI32 engine takes the 16-bit r, g, b arguments from the - // VM and puts them into al, ah, dl. For compatibility, make sure - // to discard any high bits here too - r = r & 0xFF; - g = g & 0xFF; - b = b & 0xFF; +int16 GfxPalette32::matchColor(const uint8 r, const uint8 g, const uint8 b) { int16 bestIndex = 0; int bestDifference = 0xFFFFF; int difference; - // SQ6 DOS really does check only the first 236 entries - for (int i = 0, channelDifference; i < 236; ++i) { - difference = _sysPalette.colors[i].r - r; + for (int i = 0, channelDifference; i < g_sci->_gfxRemap32->getStartColor(); ++i) { + difference = _currentPalette.colors[i].r - r; difference *= difference; if (bestDifference <= difference) { continue; } - channelDifference = _sysPalette.colors[i].g - g; + channelDifference = _currentPalette.colors[i].g - g; difference += channelDifference * channelDifference; if (bestDifference <= difference) { continue; } - channelDifference = _sysPalette.colors[i].b - b; + channelDifference = _currentPalette.colors[i].b - b; difference += channelDifference * channelDifference; if (bestDifference <= difference) { continue; @@ -162,51 +238,39 @@ int16 GfxPalette32::kernelFindColor(uint16 r, uint16 g, uint16 b) { return bestIndex; } -// TODO: set is overridden for the time being to send palettes coming from -// various draw methods like GfxPicture::drawSci32Vga and GfxView::draw to -// _nextPalette instead of _sysPalette. In the SCI32 engine, CelObj palettes -// (which are stored as Hunk palettes) are submitted by GraphicsMgr::FrameOut -// to PaletteMgr::Submit by way of calls to CelObj::SubmitPalette. -// GfxPalette::set is very similar to GfxPalette32::submit, except that SCI32 -// does not do any fancy best-fit merging and so does not accept arguments -// like `force` and `forceRealMerge`. -void GfxPalette32::set(Palette *newPalette, bool force, bool forceRealMerge) { - submit(*newPalette); -} - bool GfxPalette32::updateForFrame() { applyAll(); - _versionUpdated = false; - return g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette); + _needsUpdate = false; + return g_sci->_gfxRemap32->remapAllTables(_nextPalette != _currentPalette); } void GfxPalette32::updateFFrame() { for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) { _nextPalette.colors[i] = _sourcePalette.colors[i]; } - _versionUpdated = false; - g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette); + _needsUpdate = false; + g_sci->_gfxRemap32->remapAllTables(_nextPalette != _currentPalette); } void GfxPalette32::updateHardware() { - if (_sysPalette == _nextPalette) { + if (_currentPalette == _nextPalette) { return; } byte bpal[3 * 256]; - for (int i = 0; i < ARRAYSIZE(_sysPalette.colors); ++i) { - _sysPalette.colors[i] = _nextPalette.colors[i]; + for (int i = 0; i < ARRAYSIZE(_currentPalette.colors); ++i) { + _currentPalette.colors[i] = _nextPalette.colors[i]; // NOTE: If the brightness option in the user configuration file is set, // SCI engine adjusts palette brightnesses here by mapping RGB values to values // in some hard-coded brightness tables. There is no reason on modern hardware // to implement this, unless it is discovered that some game uses a non-standard // brightness setting by default - if (_sysPalette.colors[i].used) { - bpal[i * 3 ] = _sysPalette.colors[i].r; - bpal[i * 3 + 1] = _sysPalette.colors[i].g; - bpal[i * 3 + 2] = _sysPalette.colors[i].b; + if (_currentPalette.colors[i].used) { + bpal[i * 3 ] = _currentPalette.colors[i].r; + bpal[i * 3 + 1] = _currentPalette.colors[i].g; + bpal[i * 3 + 2] = _currentPalette.colors[i].b; } } @@ -223,6 +287,7 @@ void GfxPalette32::applyAll() { #pragma mark - #pragma mark Colour look-up +#ifdef ENABLE_SCI3_GAMES bool GfxPalette32::loadClut(uint16 clutId) { // loadClut() will load a color lookup table from a clu file and set // the palette found in the file. This is to be used with Phantasmagoria 2. @@ -272,27 +337,20 @@ void GfxPalette32::unloadClut() { delete[] _clutTable; _clutTable = nullptr; } +#endif #pragma mark - #pragma mark Varying -inline bool GfxPalette32::createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const { - Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, paletteId), false); +inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId resourceId) const { + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (!palResource) { - return false; + error("Could not load vary target %d", resourceId); } - createFromData(palResource->data, palResource->size, out); - return true; -} - -inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId paletteId) const { - Palette palette; - if (!createPaletteFromResourceInternal(paletteId, &palette)) { - error("Could not load vary target %d", paletteId); - } - return palette; + HunkPalette rawPalette(palResource->data); + return rawPalette.toPalette(); } inline void GfxPalette32::setVaryTimeInternal(const int16 percent, const int time) { diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h index 7dda53e5c1..6c773cc5c0 100644 --- a/engines/sci/graphics/palette32.h +++ b/engines/sci/graphics/palette32.h @@ -26,6 +26,118 @@ #include "sci/graphics/palette.h" namespace Sci { + +/** + * HunkPalette represents a raw palette resource + * read from disk. + */ +class HunkPalette { +public: + HunkPalette(byte *rawPalette); + + /** + * Gets the version of the palette. + */ + uint32 getVersion() const { return _version; } + + /** + * Sets the version of the palette. + */ + void setVersion(const uint32 version); + + /** + * Converts the hunk palette to a standard + * palette. + */ + const Palette toPalette() const; + +private: + enum { + /** + * The size of the HunkPalette header. + */ + kHunkPaletteHeaderSize = 13, + + /** + * The size of a palette entry header. + */ + kEntryHeaderSize = 22, + + /** + * The offset of the hunk palette version + * within the palette entry header. + */ + kEntryVersionOffset = 18 + }; + + /** + * The header for a palette inside the + * HunkPalette. + */ + struct EntryHeader { + /** + * The start color. + */ + uint8 startColor; + + /** + * The number of palette colors in this + * entry. + */ + uint16 numColors; + + /** + * The default `used` flag. + */ + bool used; + + /** + * Whether or not all palette entries + * share the same `used` value in + * `defaultFlag`. + */ + bool sharedUsed; + + /** + * The palette version. + */ + uint32 version; + }; + + /** + * The version number from the last time this + * palette was submitted to GfxPalette32. + */ + uint32 _version; + + /** + * The number of palettes stored in the hunk + * palette. In SCI32 games this is always 1. + */ + uint8 _numPalettes; + + /** + * The raw palette data for this hunk palette. + */ + byte *_data; + + /** + * Returns a struct that describes the palette + * held by this HunkPalette. The entry header + * is reconstructed on every call from the raw + * palette data. + */ + const EntryHeader getEntryHeader() const; + + /** + * Returns a pointer to the palette data within + * the hunk palette. + */ + byte *getPalPointer() const { + return _data + kHunkPaletteHeaderSize + (2 * _numPalettes); + } +}; + enum PalCyclerDirection { PalCycleBackward = 0, PalCycleForward = 1 @@ -72,28 +184,29 @@ struct PalCycler { uint16 numTimesPaused; }; -class GfxPalette32 : public GfxPalette { +class GfxPalette32 { public: - GfxPalette32(ResourceManager *resMan, GfxScreen *screen); + GfxPalette32(ResourceManager *resMan); ~GfxPalette32(); private: - // NOTE: currentPalette in SCI engine is called _sysPalette - // here. + ResourceManager *_resMan; + + /** + * The currently displayed palette. + */ + Palette _currentPalette; /** * The palette revision version. Increments once per game - * loop that changes the source palette. TODO: Possibly - * other areas also change _version, double-check once it - * is all implemented. + * loop that changes the source palette. */ uint32 _version; /** - * Whether or not the palette manager version was updated - * during this loop. + * Whether or not the hardware palette needs updating. */ - bool _versionUpdated; + bool _needsUpdate; /** * The unmodified source palette loaded by kPalette. Additional @@ -104,7 +217,7 @@ private: /** * The palette to be used when the hardware is next updated. - * On update, _nextPalette is transferred to _sysPalette. + * On update, _nextPalette is transferred to _currentPalette. */ Palette _nextPalette; @@ -112,20 +225,29 @@ private: Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const; public: - virtual void saveLoadWithSerializer(Common::Serializer &s) override; + void saveLoadWithSerializer(Common::Serializer &s); inline const Palette &getNextPalette() const { return _nextPalette; }; - inline const Palette &getCurrentPalette() const { return _sysPalette; }; + inline const Palette &getCurrentPalette() const { return _currentPalette; }; - 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; + /** + * Loads a palette into GfxPalette32 with the given resource + * ID. + */ + bool loadPalette(const GuiResourceId resourceId); + + /** + * Finds the nearest color in the current palette matching the + * given RGB value. + */ + int16 matchColor(const uint8 r, const uint8 g, const uint8 b); /** * Submits a palette to display. Entries marked as “used” in the * submitted palette are merged into the existing entries of * _sourcePalette. */ - void submit(Palette &palette); + void submit(const Palette &palette); + void submit(HunkPalette &palette); bool updateForFrame(); void updateFFrame(); @@ -213,7 +335,7 @@ public: void kernelPalVarySetTarget(const GuiResourceId paletteId); void kernelPalVarySetStart(const GuiResourceId paletteId); void kernelPalVaryMergeStart(const GuiResourceId paletteId); - virtual void kernelPalVaryPause(bool pause) override; + void kernelPalVaryPause(bool pause); void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor); void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index cf03c50039..f9481bb301 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -167,9 +167,7 @@ SciEngine::~SciEngine() { DebugMan.clearAllDebugChannels(); #ifdef ENABLE_SCI32 - // _gfxPalette32 is the same as _gfxPalette16 - // and will be destroyed when _gfxPalette16 is - // destroyed + delete _gfxPalette32; delete _gfxControls32; delete _gfxPaint32; delete _gfxText32; @@ -717,8 +715,7 @@ void SciEngine::initGraphics() { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { - _gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen); - _gfxPalette16 = _gfxPalette32; + _gfxPalette32 = new GfxPalette32(_resMan); _gfxRemap32 = new GfxRemap32(); } else { #endif @@ -767,8 +764,10 @@ void SciEngine::initGraphics() { } #endif - // Set default (EGA, amiga or resource 999) palette - _gfxPalette16->setDefault(); + if (getSciVersion() < SCI_VERSION_2) { + // Set default (EGA, amiga or resource 999) palette + _gfxPalette16->setDefault(); + } } void SciEngine::initStackBaseWithSelector(Selector selector) { |