diff options
-rw-r--r-- | engines/mads/mads.cpp | 2 | ||||
-rw-r--r-- | engines/mads/msurface.cpp | 39 | ||||
-rw-r--r-- | engines/mads/msurface.h | 2 | ||||
-rw-r--r-- | engines/mads/palette.cpp | 179 | ||||
-rw-r--r-- | engines/mads/palette.h | 142 |
5 files changed, 233 insertions, 131 deletions
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 0ddb6bf401..36b5ec51f5 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -71,7 +71,7 @@ void MADSEngine::initialise() { MSprite::setVm(this); _events = new EventsManager(this); - _palette = new Palette(this); + _palette = Palette::init(this); _font = Font::init(this); _resources = new ResourcesManager(this); _screen = MSurface::init(true); diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp index b3a4510793..e7cc08e636 100644 --- a/engines/mads/msurface.cpp +++ b/engines/mads/msurface.cpp @@ -234,9 +234,9 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo } else { byte destPixel = *tempDst; byte r, g, b; - r = CLIP((info.palette[destPixel].r * pixel) >> 10, 0, 31); - g = CLIP((info.palette[destPixel].g * pixel) >> 10, 0, 31); - b = CLIP((info.palette[destPixel].b * pixel) >> 10, 0, 31); + r = CLIP((info.palette[destPixel * 3] * pixel) >> 10, 0, 31); + g = CLIP((info.palette[destPixel * 3 + 1] * pixel) >> 10, 0, 31); + b = CLIP((info.palette[destPixel * 3 + 2] * pixel) >> 10, 0, 31); pixel = info.inverseColorTable[(b << 10) | (g << 5) | r]; } } @@ -429,10 +429,10 @@ void MSurfaceMADS::loadBackground(int roomNumber, RGBList **palData) { tileDataUncomp = tileData.getItemStream(2); // Set palette if (!palData) { - _vm->_palette->setMadsPalette(tileDataUncomp, 4); + _vm->_palette->loadPalette(tileDataUncomp, 4); } else { int numColors; - RGB8 *rgbList = _vm->_palette->decodeMadsPalette(tileDataUncomp, &numColors); + byte *rgbList = _vm->_palette->decodePalette(tileDataUncomp, &numColors); *palData = new RGBList(numColors, rgbList, true); } delete tileDataUncomp; @@ -495,18 +495,16 @@ void MSurfaceMADS::loadInterface(int index, RGBList **palData) { char resourceName[20]; sprintf(resourceName, "i%d.int", index); MadsPack intFile(resourceName, _vm); - RGB8 *palette = new RGB8[16]; + byte *palette = new byte[16 * 3]; // Chunk 0, palette Common::SeekableReadStream *intStream = intFile.getItemStream(0); for (int i = 0; i < 16; i++) { - palette[i].r = intStream->readByte() << 2; - palette[i].g = intStream->readByte() << 2; - palette[i].b = intStream->readByte() << 2; - intStream->readByte(); - intStream->readByte(); - intStream->readByte(); + palette[i * 3] = intStream->readByte() << 2; + palette[i * 3 + 1] = intStream->readByte() << 2; + palette[i * 3 + 2] = intStream->readByte() << 2; + intStream->skip(3); } *palData = new RGBList(16, palette, true); delete intStream; @@ -551,10 +549,10 @@ void MSurfaceNebular::loadBackgroundStream(Common::SeekableReadStream *source, R // Set palette if (!palData) { - _vm->_palette->setMadsPalette(sourceUnc, 4); + _vm->_palette->loadPalette(sourceUnc, 4); } else { int numColors; - RGB8 *rgbList = _vm->_palette->decodeMadsPalette(sourceUnc, &numColors); + byte *rgbList = _vm->_palette->decodePalette(sourceUnc, &numColors); *palData = new RGBList(numColors, rgbList, true); } delete sourceUnc; @@ -598,7 +596,7 @@ void MSurfaceM4::loadBackgroundStream(Common::SeekableReadStream *source) { MSurface *tileBuffer = MSurface::init(); uint curTileX = 0, curTileY = 0; int clipX = 0, clipY = 0; - RGB8 palette[256]; + byte palette[256]; source->skip(4); /*uint32 size =*/ source->readUint32LE(); @@ -612,12 +610,13 @@ void MSurfaceM4::loadBackgroundStream(Common::SeekableReadStream *source) { // BGR data, which is converted to RGB8 for (uint i = 0; i < 256; i++) { - palette[i].b = source->readByte() << 2; - palette[i].g = source->readByte() << 2; - palette[i].r = source->readByte() << 2; - palette[i].u = source->readByte() << 2; + byte r, g, b; + palette[i * 3] = r = source->readByte() << 2; + palette[i * 3 + 1] = g = source->readByte() << 2; + palette[i * 3 + 2] = b = source->readByte() << 2; + source->skip(1); - if ((blackIndex == 0) && !palette[i].r && !palette[i].g && !palette[i].b) + if ((blackIndex == 0) && !r && !g && !b) blackIndex = i; } diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h index 05777d3b8f..fe6d1f22b4 100644 --- a/engines/mads/msurface.h +++ b/engines/mads/msurface.h @@ -43,7 +43,7 @@ struct SpriteInfo { int scaleX, scaleY; uint8 encoding; byte *inverseColorTable; - RGB8 *palette; + byte *palette; }; /* diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index cfd8568407..6a5d507c13 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -28,12 +28,12 @@ namespace MADS { -RGBList::RGBList(int numEntries, RGB8 *srcData, bool freeData) { +RGBList::RGBList(int numEntries, byte *srcData, bool freeData) { _size = numEntries; - assert(numEntries <= 256); + assert(numEntries <= PALETTE_COUNT); if (srcData == NULL) { - _data = new RGB8[numEntries]; + _data = new byte[numEntries * 3]; _freeData = true; } else { _data = srcData; @@ -54,10 +54,18 @@ RGBList::~RGBList() { #define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) +Palette *Palette::init(MADSEngine *vm) { + if (vm->getGameFeatures() & GF_MADS) { + return new PaletteMADS(vm); + } else { + return new PaletteM4(vm); + } +} + Palette::Palette(MADSEngine *vm) : _vm(vm) { reset(); _fading_in_progress = false; - Common::fill(&_usageCount[0], &_usageCount[256], 0); + Common::fill(&_usageCount[0], &_usageCount[PALETTE_COUNT], 0); } void Palette::setPalette(const byte *colors, uint start, uint num) { @@ -65,31 +73,26 @@ void Palette::setPalette(const byte *colors, uint start, uint num) { reset(); } -void Palette::setPalette(const RGB8 *colors, uint start, uint num) { - g_system->getPaletteManager()->setPalette((const byte *)colors, start, num); - reset(); -} - void Palette::grabPalette(byte *colors, uint start, uint num) { g_system->getPaletteManager()->grabPalette(colors, start, num); reset(); } -uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, RGB8 *paletteData) { +uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, byte *paletteData) { byte index = 0; int32 minDist = 0x7fffffff; - RGB8 palData[256]; + byte palData[PALETTE_SIZE]; int Rdiff, Gdiff, Bdiff; if (paletteData == NULL) { - g_system->getPaletteManager()->grabPalette((byte *)palData, 0, 256); + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); paletteData = &palData[0]; } - for (int palIndex = 0; palIndex < 256; ++palIndex) { - Rdiff = r - paletteData[palIndex].r; - Gdiff = g - paletteData[palIndex].g; - Bdiff = b - paletteData[palIndex].b; + for (int palIndex = 0; palIndex < PALETTE_COUNT; ++palIndex) { + Rdiff = r - paletteData[palIndex * 3]; + Gdiff = g - paletteData[palIndex * 3 + 1]; + Bdiff = b - paletteData[palIndex * 3 + 2]; if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) { minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; @@ -101,8 +104,8 @@ uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, RGB8 *paletteData) { } void Palette::reset() { - RGB8 palData[256]; - g_system->getPaletteManager()->grabPalette((byte *)palData, 0, 256); + byte palData[PALETTE_SIZE]; + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); BLACK = palIndexFromRgb(0, 0, 0, palData); BLUE = palIndexFromRgb(0, 0, 255, palData); @@ -126,13 +129,13 @@ void Palette::fadeIn(int numSteps, uint delayAmount, RGBList *destPalette) { fadeIn(numSteps, delayAmount, destPalette->data(), destPalette->size()); } -void Palette::fadeIn(int numSteps, uint delayAmount, RGB8 *destPalette, int numColors) { +void Palette::fadeIn(int numSteps, uint delayAmount, byte *destPalette, int numColors) { if (_fading_in_progress) return; _fading_in_progress = true; - RGB8 blackPalette[256]; - Common::fill((byte *)&blackPalette[0], (byte *)&blackPalette[256], 0); + byte blackPalette[PALETTE_SIZE]; + Common::fill(&blackPalette[0], &blackPalette[PALETTE_SIZE], 0); // Initially set the black palette _vm->_palette->setPalette(blackPalette, 0, numColors); @@ -143,52 +146,8 @@ void Palette::fadeIn(int numSteps, uint delayAmount, RGB8 *destPalette, int numC _fading_in_progress = false; } -RGB8 *Palette::decodeMadsPalette(Common::SeekableReadStream *palStream, int *numColors) { - *numColors = palStream->readUint16LE(); - assert(*numColors <= 252); - - RGB8 *palData = new RGB8[*numColors]; - Common::fill((byte *)&palData[0], (byte *)&palData[*numColors], 0); - - for (int i = 0; i < *numColors; ++i) { - byte r = palStream->readByte(); - byte g = palStream->readByte(); - byte b = palStream->readByte(); - palData[i].r = VGA_COLOR_TRANS(r); - palData[i].g = VGA_COLOR_TRANS(g); - palData[i].b = VGA_COLOR_TRANS(b); - - // The next 3 bytes are unused - palStream->skip(3); - } - - return palData; -} - -int Palette::setMadsPalette(Common::SeekableReadStream *palStream, int indexStart) { - int colorCount; - RGB8 *palData = Palette::decodeMadsPalette(palStream, &colorCount); - _vm->_palette->setPalette(palData, indexStart, colorCount); - delete palData; - return colorCount; -} - -void Palette::setMadsSystemPalette() { - // Rex Nebular default system palette - resetColorCounts(); - - RGB8 palData[4]; - palData[0].r = palData[0].g = palData[0].b = 0; - palData[1].r = palData[1].g = palData[1].b = 0x54; - palData[2].r = palData[2].g = palData[2].b = 0xb4; - palData[3].r = palData[3].g = palData[3].b = 0xff; - - setPalette(palData, 0, 4); - blockRange(0, 4); -} - void Palette::resetColorCounts() { - Common::fill(&_usageCount[0], &_usageCount[256], 0); + Common::fill(&_usageCount[0], &_usageCount[PALETTE_COUNT], 0); } void Palette::blockRange(int startIndex, int size) { @@ -197,41 +156,41 @@ void Palette::blockRange(int startIndex, int size) { } void Palette::addRange(RGBList *list) { - RGB8 *data = list->data(); + byte *data = list->data(); byte *palIndexes = list->palIndexes(); - RGB8 palData[256]; - g_system->getPaletteManager()->grabPalette((byte *)&palData[0], 0, 256); + byte palData[PALETTE_COUNT]; + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); bool paletteChanged = false; for (int colIndex = 0; colIndex < list->size(); ++colIndex) { // Scan through for an existing copy of the RGB value int palIndex = -1; - while (++palIndex < 256) { + while (++palIndex < PALETTE_COUNT) { if (_usageCount[palIndex] <= 0) // Palette index is to be skipped continue; - if ((palData[palIndex].r == data[colIndex].r) && - (palData[palIndex].g == data[colIndex].g) && - (palData[palIndex].b == data[colIndex].b)) + if ((palData[palIndex * 3] == data[colIndex * 3]) && + (palData[palIndex * 3 + 1] == data[colIndex * 3 + 1]) && + (palData[palIndex * 3 + 2] == data[colIndex * 3 + 2])) // Match found break; } - if (palIndex == 256) { + if (palIndex == PALETTE_COUNT) { // No match found, so find a free slot to use palIndex = -1; - while (++palIndex < 256) { + while (++palIndex < PALETTE_COUNT) { if (_usageCount[palIndex] == 0) break; } - if (palIndex == 256) + if (palIndex == PALETTE_COUNT) error("addRange - Ran out of palette space to allocate"); - palData[palIndex].r = data[colIndex].r; - palData[palIndex].g = data[colIndex].g; - palData[palIndex].b = data[colIndex].b; + palData[palIndex * 3] = data[colIndex * 3]; + palData[palIndex * 3 + 1] = data[colIndex * 3 + 1]; + palData[palIndex * 3 + 2] = data[colIndex * 3 + 2]; paletteChanged = true; } @@ -240,7 +199,7 @@ void Palette::addRange(RGBList *list) { } if (paletteChanged) { - g_system->getPaletteManager()->setPalette((byte *)&palData[0], 0, 256); + g_system->getPaletteManager()->setPalette(&palData[0], 0, 256); reset(); } } @@ -259,9 +218,9 @@ void Palette::deleteAllRanges() { _usageCount[colIndex] = 0; } -void Palette::fadeRange(RGB8 *srcPal, RGB8 *destPal, int startIndex, int endIndex, +void Palette::fadeRange(byte *srcPal, byte *destPal, int startIndex, int endIndex, int numSteps, uint delayAmount) { - RGB8 tempPal[256]; + byte tempPal[256 * 3]; // perform the fade for(int stepCtr = 1; stepCtr <= numSteps; ++stepCtr) { @@ -274,16 +233,62 @@ void Palette::fadeRange(RGB8 *srcPal, RGB8 *destPal, int startIndex, int endInd for (int i = startIndex; i <= endIndex; ++i) { // Handle the intermediate rgb values for fading - tempPal[i].r = (byte) (srcPal[i].r + (destPal[i].r - srcPal[i].r) * stepCtr / numSteps); - tempPal[i].g = (byte) (srcPal[i].g + (destPal[i].g - srcPal[i].g) * stepCtr / numSteps); - tempPal[i].b = (byte) (srcPal[i].b + (destPal[i].b - srcPal[i].b) * stepCtr / numSteps); + tempPal[i * 3] = (byte) (srcPal[i * 3] + (destPal[i * 3] - srcPal[i * 3]) * stepCtr / numSteps); + tempPal[i * 3 + 1] = (byte) (srcPal[i * 3 + 1] + (destPal[i * 3 + 1] - srcPal[i * 3 + 1]) * stepCtr / numSteps); + tempPal[i * 3 + 2] = (byte) (srcPal[i * 3 + 2] + (destPal[i * 3 + 2] - srcPal[i * 3 + 2]) * stepCtr / numSteps); } - _vm->_palette->setPalette(&tempPal[startIndex], startIndex, endIndex - startIndex + 1); + _vm->_palette->setPalette(&tempPal[startIndex * 3], startIndex, endIndex - startIndex + 1); } // Make sure the end palette exactly matches what is wanted - _vm->_palette->setPalette(&destPal[startIndex], startIndex, endIndex - startIndex + 1); + _vm->_palette->setPalette(&destPal[startIndex * 3], startIndex, endIndex - startIndex + 1); +} + +/*------------------------------------------------------------------------*/ + +byte *PaletteMADS::decodePalette(Common::SeekableReadStream *palStream, int *numColors) { + *numColors = palStream->readUint16LE(); + assert(*numColors <= 252); + + byte *palData = new byte[*numColors * 3]; + Common::fill(&palData[0], &palData[*numColors * 3], 0); + + for (int i = 0; i < *numColors; ++i) { + byte r = palStream->readByte(); + byte g = palStream->readByte(); + byte b = palStream->readByte(); + palData[i * 3] = VGA_COLOR_TRANS(r); + palData[i * 3 + 1] = VGA_COLOR_TRANS(g); + palData[i * 3 + 2] = VGA_COLOR_TRANS(b); + + // The next 3 bytes are unused + palStream->skip(3); + } + + return palData; +} + +int PaletteMADS::loadPalette(Common::SeekableReadStream *palStream, int indexStart) { + int colorCount; + byte *palData = decodePalette(palStream, &colorCount); + _vm->_palette->setPalette(palData, indexStart, colorCount); + + delete palData; + return colorCount; +} + +void PaletteMADS::setSystemPalette() { + resetColorCounts(); + + byte palData[4 * 3]; + palData[0 * 3] = palData[0 * 3 + 1] = palData[0 * 3 + 2] = 0; + palData[1 * 3] = palData[1 * 3 + 1] = palData[1 * 3 + 2] = 0x54; + palData[2 * 3] = palData[2 * 3 + 1] = palData[2 * 3 + 2] = 0xb4; + palData[3 * 3] = palData[3 * 3 + 1] = palData[3 * 3 + 2] = 0xff; + + setPalette(palData, 0, 4); + blockRange(0, 4); } } // End of namespace MADS diff --git a/engines/mads/palette.h b/engines/mads/palette.h index ab03d8d20b..a5d9c6ad1e 100644 --- a/engines/mads/palette.h +++ b/engines/mads/palette.h @@ -29,63 +29,137 @@ namespace MADS { class MADSEngine; -struct RGB8 { - uint8 r, g, b, u; -}; - +/** + * Used to store a list of RGB values + */ class RGBList { private: int _size; - RGB8 *_data; + byte *_data; byte *_palIndexes; bool _freeData; public: - RGBList(int numEntries = 256, RGB8 *srcData = NULL, bool freeData = true); + /** + * Constructor + */ + RGBList(int numEntries = 256, byte *srcData = NULL, bool freeData = true); + + /** + * Destructor + */ ~RGBList(); - RGB8 *data() { return _data; } + /** + * Returns the raw data containing the RGB values as 3 bytes per entry + */ + byte *data() { return _data; } + + /** + * Returns the list of palette indexes each RGB tuple maps to in the current palette + */ byte *palIndexes() { return _palIndexes; } - int size() { return _size; } + + /** + * Returns the size of the palette + */ + int size() const { return _size; } }; #define PALETTE_COUNT 256 +#define PALETTE_SIZE (256 * 3) class Palette { private: + /** + * Support method used by the fading code + */ + void fadeRange(byte *srcPal, byte *destPal, int startIndex, int endIndex, + int numSteps, uint delayAmount); +protected: MADSEngine *_vm; bool _colorsChanged; + bool _fading_in_progress; byte _originalPalette[PALETTE_COUNT * 4]; byte _fadedPalette[PALETTE_COUNT * 4]; int _usageCount[PALETTE_COUNT]; + Palette(MADSEngine *vm); void reset(); public: - Palette(MADSEngine *vm); - + /** + * Creates a new palette instance + */ + static Palette *init(MADSEngine *vm); + + /** + * Sets a new palette + */ void setPalette(const byte *colors, uint start, uint num); - void setPalette(const RGB8 *colors, uint start, uint num); - void grabPalette(byte *colors, uint start, uint num); - void grabPalette(RGB8 *colors, uint start, uint num) { - grabPalette((byte *)colors, start, num); - } - uint8 palIndexFromRgb(byte r, byte g, byte b, RGB8 *paletteData = NULL); - void fadeIn(int numSteps, uint delayAmount, RGB8 *destPalette, int numColors); + /** + * Returns a subset of the currently loaded palette + */ + void grabPalette(byte *colors, uint start, uint num); + + /** + * Returns the palette index in the palette that most closely matches the + * specified RGB pair + */ + uint8 palIndexFromRgb(byte r, byte g, byte b, byte *paletteData = nullptr); + + /** + * Performs a fade in + */ + void fadeIn(int numSteps, uint delayAmount, byte *destPalette, int numColors); + + /** + * Performs a fade in + */ void fadeIn(int numSteps, uint delayAmount, RGBList *destPalette); - static RGB8 *decodeMadsPalette(Common::SeekableReadStream *palStream, int *numColors); - int setMadsPalette(Common::SeekableReadStream *palStream, int indexStart = 0); - void setMadsSystemPalette(); - void fadeRange(RGB8 *srcPal, RGB8 *destPal, int startIndex, int endIndex, - int numSteps, uint delayAmount); // Methods used for reference counting color usage + /** + * Resets the usage counts for the palette + */ void resetColorCounts(); + + /** + * Blocks out a range of the palette from being used + */ void blockRange(int startIndex, int size); + + /** + * Adds the data of an RGBList into the current palette and increment usage counts. + */ void addRange(RGBList *list); + + /** + * Delets a range from the current palette, dercementing the accompanying usage counts. + */ void deleteRange(RGBList *list); + + /** + * Deletes all loaded RGB lists are their usage references. + */ void deleteAllRanges(); + // Virtual method table + /** + * Decode a palette and return it, without affecting the Palette itself + */ + virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors) = 0; + + /** + * Loads a palette from a stream + */ + virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0) = 0; + + /** + * Sets a small set of system/core colors needed by the game + */ + virtual void setSystemPalette() = 0; + // Color indexes uint8 BLACK; uint8 BLUE; @@ -105,6 +179,30 @@ public: uint8 WHITE; }; +class PaletteMADS: protected Palette { + friend class Palette; +protected: + PaletteMADS(MADSEngine *vm): Palette(vm) {} +public: + virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors); + virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0); + virtual void setSystemPalette(); +}; + +class PaletteM4: protected Palette { + friend class Palette; +protected: + PaletteM4(MADSEngine *vm): Palette(vm) {} +public: + virtual byte *decodePalette(Common::SeekableReadStream *palStream, int *numColors) { + return nullptr; + } + virtual int loadPalette(Common::SeekableReadStream *palStream, int indexStart = 0) { + return 0; + } + virtual void setSystemPalette() {} +}; + } // End of namespace MADS #endif /* MADS_PALETTE_H */ |