/* 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_PALETTE32_H #define SCI_GRAPHICS_PALETTE32_H #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 }; struct PalCycler { /** * The color index of the palette cycler. This value is effectively used as the ID for the * cycler. */ uint8 fromColor; /** * The number of palette slots which are cycled by the palette cycler. */ uint16 numColorsToCycle; /** * The position of the cursor in its cycle. */ uint8 currentCycle; /** * The direction of the cycler. */ PalCyclerDirection direction; /** * The cycle tick at the last time the cycler’s currentCycle was updated. * 795 days of game time ought to be enough for everyone? :) */ uint32 lastUpdateTick; /** * The amount of time in ticks each cycle should take to complete. In other words, * the higher the delay, the slower the cycle animation. If delay is 0, the cycler * does not automatically cycle and needs to be pumped manually with DoCycle. */ int16 delay; /** * The number of times this cycler has been paused. */ uint16 numTimesPaused; }; class GfxPalette32 { public: GfxPalette32(ResourceManager *resMan); ~GfxPalette32(); private: ResourceManager *_resMan; /** * The palette revision version. Increments once per game * loop that changes the source palette. */ uint32 _version; /** * Whether or not the hardware palette needs updating. */ bool _needsUpdate; /** * The currently displayed palette. */ Palette _currentPalette; /** * The unmodified source palette loaded by kPalette. Additional * palette entries may be mixed into the source palette by * CelObj objects, which contain their own palettes. */ Palette _sourcePalette; /** * The palette to be used when the hardware is next updated. * On update, _nextPalette is transferred to _currentPalette. */ Palette _nextPalette; bool createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const; Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const; public: void saveLoadWithSerializer(Common::Serializer &s); inline const Palette &getNextPalette() const { return _nextPalette; }; inline const Palette &getCurrentPalette() const { return _currentPalette; }; /** * Loads a palette into GfxPalette32 with the given resource * ID. */ bool loadPalette(const GuiResourceId resourceId); /** * Finds the nearest color in the current palette matching the * given RGB value. */ int16 matchColor(const uint8 r, const uint8 g, const uint8 b); /** * Submits a palette to display. Entries marked as “used” in the * submitted palette are merged into the existing entries of * _sourcePalette. */ void submit(const Palette &palette); void submit(HunkPalette &palette); bool updateForFrame(); void updateFFrame(); void updateHardware(const bool updateScreen = true); void applyAll(); #pragma mark - #pragma mark Color look-up private: /** * An optional lookup table used to remap RGB565 colors to a palette * index. Used by Phantasmagoria 2 in 8-bit color environments. */ byte *_clutTable; public: bool loadClut(uint16 clutId); byte matchClutColor(uint16 color); void unloadClut(); #pragma mark - #pragma mark Varying private: /** * An optional palette used to describe the source colors used * in a palette vary operation. If this palette is not specified, * sourcePalette is used instead. */ Palette *_varyStartPalette; /** * An optional palette used to describe the target colors used * in a palette vary operation. */ Palette *_varyTargetPalette; /** * The minimum palette index that has been varied from the * source palette. 0–255 */ uint8 _varyFromColor; /** * The maximum palette index that is has been varied from the * source palette. 0-255 */ uint8 _varyToColor; /** * The tick at the last time the palette vary was updated. */ uint32 _varyLastTick; /** * The amount of time to elapse, in ticks, between each cycle * of a palette vary animation. */ int _varyTime; /** * The direction of change: -1, 0, or 1. */ int16 _varyDirection; /** * The amount, in percent, that the vary color is currently * blended into the source color. */ int16 _varyPercent; /** * The target amount that a vary color will be blended into * the source color. */ int16 _varyTargetPercent; /** * The number of time palette varying has been paused. */ uint16 _varyNumTimesPaused; public: void kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor); void kernelPalVaryMergeTarget(const GuiResourceId paletteId); void kernelPalVarySetTarget(const GuiResourceId paletteId); void kernelPalVarySetStart(const GuiResourceId paletteId); void kernelPalVaryMergeStart(const GuiResourceId paletteId); void kernelPalVaryPause(bool pause); void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor); void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate); int16 getVaryPercent() const; void varyOff(); void mergeTarget(const Palette *const palette); void varyPause(); void varyOn(); void setVaryTime(const int time); void setTarget(const Palette *const palette); void setStart(const Palette *const palette); void mergeStart(const Palette *const palette); void setVaryTimeInternal(const int16 percent, const int time); void applyVary(); #pragma mark - #pragma mark Cycling private: // SQ6 defines 10 cyclers PalCycler *_cyclers[10]; /** * The cycle map is used to detect overlapping cyclers. * According to SCI engine code, when two cyclers overlap, * a fatal error has occurred and the engine will display * an error and then exit. * * 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); inline void setCycleMap(uint16 fromColor, uint16 numColorsToClear); inline PalCycler *getCycler(uint16 fromColor); public: void setCycle(const uint8 fromColor, const uint8 toColor, const int16 direction, const int16 delay); void doCycle(const uint8 fromColor, const int16 speed); void cycleOn(const uint8 fromColor); void cyclePause(const uint8 fromColor); void cycleAllOn(); void cycleAllPause(); void cycleOff(const uint8 fromColor); void cycleAllOff(); void applyAllCycles(); void applyCycles(); inline const bool *getCycleMap() const { return _cycleMap; } #pragma mark - #pragma mark Fading private: /** * The fade table records the expected intensity level of each pixel * in the palette that will be displayed on the next frame. */ uint16 _fadeTable[256]; public: /** * Sets the intensity level for a range of palette * entries. An intensity of zero indicates total * darkness. Intensity may be set to over 100 percent. */ void setFade(const uint16 percent, const uint8 fromColor, const uint16 toColor); void fadeOff(); void applyFade(); }; } // End of namespace Sci #endif