From 38e7eecb710a3f7e8c5a637d525fed60d0712386 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Wed, 17 Dec 2008 16:06:16 +0000 Subject: Added support for caching the palette LUT to a file svn-id: r35412 --- engines/gob/gob.cpp | 2 +- engines/gob/indeo3.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++---- engines/gob/indeo3.h | 9 ++++-- engines/gob/video.h | 8 ++++-- engines/gob/video_v6.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 145 insertions(+), 14 deletions(-) (limited to 'engines/gob') diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index a053ff2ea3..f30cf7517e 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -184,7 +184,7 @@ Common::Error GobEngine::init() { } _video->setSize(is640()); - _video->init(); + _video->init(_targetName.c_str()); // On some systems it's not safe to run CD audio games from the CD. if (isCD()) diff --git a/engines/gob/indeo3.cpp b/engines/gob/indeo3.cpp index 8f439626fe..6182983fe3 100644 --- a/engines/gob/indeo3.cpp +++ b/engines/gob/indeo3.cpp @@ -31,7 +31,6 @@ #include "common/system.h" #include "common/endian.h" -#include "common/stream.h" #include "common/frac.h" #include "common/file.h" @@ -44,20 +43,25 @@ namespace Gob { PaletteLUT::PaletteLUT(byte depth, PaletteFormat format) { assert((depth > 1) && (depth < 9)); + // For adjusting depth _depth1 = depth; _depth2 = 2 * _depth1; _shift = 8 - _depth1; + // The table's dimensions _dim1 = (1 << _depth1); _dim2 = _dim1 * _dim1; _dim3 = _dim1 * _dim1 * _dim1; _format = format; + // What's already built _got = _dim1; - _lut = new byte[_dim3]; _gots = new byte[_dim1]; + // The lookup table + _lut = new byte[_dim3]; + memset(_lutPal, 0, 768); memset(_realPal, 0, 768); memset(_gots, 1, _dim1); @@ -70,6 +74,7 @@ void PaletteLUT::setPalette(const byte *palette, PaletteFormat format, byte dept int shift = 8 - depth; + // Checking for the table's and the palette's pixel format if ((_format == kPaletteRGB) && (format == kPaletteYUV)) { byte *newPal = _realPal; const byte *oldPal = palette; @@ -85,10 +90,12 @@ void PaletteLUT::setPalette(const byte *palette, PaletteFormat format, byte dept } else memcpy(_realPal, palette, 768); + // Using the specified depth for the lookup byte *newPal = _lutPal, *oldPal = _realPal; for (int i = 0; i < 768; i++) *newPal++ = (*oldPal++) >> _shift; + // Everything has to be rebuilt _got = 0; memset(_gots, 0, _dim1); } @@ -105,17 +112,20 @@ void PaletteLUT::buildNext() { build(_got++); } +// Building one "slice" void PaletteLUT::build(int d1) { + // First dimension byte *lut = _lut + d1 * _dim2; -// warning("LUT %d/%d", d1, _dim1 - 1); - - for (int j = 0; j < _dim1; j++) { - for (int k = 0; k < _dim1; k++) { + // Second dimension + for (uint32 j = 0; j < _dim1; j++) { + // Third dimension + for (uint32 k = 0; k < _dim1; k++) { const byte *p = _lutPal; uint32 d = 0xFFFFFFFF; byte n = 0; + // Going over every palette entry, searching for the closest for (int c = 0; c < 256; c++, p += 3) { uint32 di = SQR(d1 - p[0]) + SQR(j - p[1]) + SQR(k - p[2]); if (di < d) { @@ -130,6 +140,7 @@ void PaletteLUT::build(int d1) { } } + // Got this slice now _gots[d1] = 1; } @@ -148,6 +159,7 @@ byte PaletteLUT::findNearest(byte c1, byte c2, byte c3) { } byte PaletteLUT::findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3) { + // If we don't have the required "slice" yet, build it if (!_gots[c1 >> _shift]) build(c1 >> _shift); @@ -161,6 +173,52 @@ byte PaletteLUT::findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, by return palIndex; } +bool PaletteLUT::save(Common::WriteStream &stream) { + // The table has to be completely built before we can save + while (_got < _dim1) + buildNext(); + + stream.writeByte(_depth1); + if (stream.write(_realPal, 768) != 768) + return false; + if (stream.write(_lutPal, 768) != 768) + return false; + if (stream.write(_lut, _dim3) != _dim3) + return false; + if (!stream.flush()) + return false; + + if (stream.err()) + return false; + + return true; +} + +bool PaletteLUT::load(Common::SeekableReadStream &stream) { + // _realPal + _lutPal + _lut + _depth1 + int32 needSize = 768 + 768 + _dim3 + 1; + + if ((stream.size() - stream.pos()) < needSize) + return false; + + byte depth1 = stream.readByte(); + + if (depth1 != _depth1) + return false; + + if (stream.read(_realPal, 768) != 768) + return false; + if (stream.read(_lutPal, 768) != 768) + return false; + if (stream.read(_lut, _dim3) != _dim3) + return false; + + _got = _dim1; + memset(_gots, 1, _dim1); + + return true; +} + SierraLight::SierraLight(int16 width, int16 height, PaletteLUT *palLUT) { assert((width > 0) && (height > 0)); @@ -168,6 +226,7 @@ SierraLight::SierraLight(int16 width, int16 height, PaletteLUT *palLUT) { _height = height; _palLUT = palLUT; + // Big buffer for the errors of the current and next line _errorBuf = new int32[3 * (2 * (_width + 2*1))]; memset(_errorBuf, 0, (3 * (2 * (_width + 2*1))) * sizeof(int32)); diff --git a/engines/gob/indeo3.h b/engines/gob/indeo3.h index 6cedecc2af..28eba336e5 100644 --- a/engines/gob/indeo3.h +++ b/engines/gob/indeo3.h @@ -33,6 +33,8 @@ #ifndef GOB_INDEO3_H #define GOB_INDEO3_H +#include "common/stream.h" + namespace Gob { class PaletteLUT { @@ -64,17 +66,20 @@ public: byte findNearest(byte c1, byte c2, byte c3); byte findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3); + bool save(Common::WriteStream &stream); + bool load(Common::SeekableReadStream &stream); + private: byte _depth1, _depth2; byte _shift; - int _dim1, _dim2, _dim3; + uint32 _dim1, _dim2, _dim3; PaletteFormat _format; byte _lutPal[768]; byte _realPal[768]; - int _got; + uint32 _got; byte *_gots; byte *_lut; diff --git a/engines/gob/video.h b/engines/gob/video.h index 4826c9ef84..42eafae5de 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -178,7 +178,7 @@ public: int16 srcHeight, int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) = 0; - virtual void init() { } + virtual void init(const char *target = "") { } Video(class GobEngine *vm); virtual ~Video(); @@ -226,7 +226,7 @@ public: virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom, int16 color); - virtual void init(); + virtual void init(const char *target = ""); Video_v6(GobEngine *vm); virtual ~Video_v6() {} @@ -234,6 +234,10 @@ public: private: static const byte _ditherPalette[768]; + bool loadPalLUT(const char *target); + bool savePalLUT(const char *target); + void buildPalLUT(); + void shadeRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength); diff --git a/engines/gob/video_v6.cpp b/engines/gob/video_v6.cpp index d90b623947..c465a07ef5 100644 --- a/engines/gob/video_v6.cpp +++ b/engines/gob/video_v6.cpp @@ -24,6 +24,7 @@ */ #include "common/endian.h" +#include "common/savefile.h" #include "gob/gob.h" #include "gob/video.h" @@ -35,12 +36,74 @@ namespace Gob { Video_v6::Video_v6(GobEngine *vm) : Video_v2(vm) { } -void Video_v6::init() { - _palLUT->setPalette(_ditherPalette, PaletteLUT::kPaletteYUV, 8); - +void Video_v6::init(const char *target) { initOSD(); + if (loadPalLUT(target)) + return; + + buildPalLUT(); + + savePalLUT(target); +} + +bool Video_v6::loadPalLUT(const char *target) { + if (target[0] == '\0') + return false; + + char *pltSave = new char[strlen(target) + 5]; + + strcpy(pltSave, target); + strcat(pltSave, ".plt"); + + Common::InSaveFile *saveFile; + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + if (!(saveFile = saveMan->openForLoading(pltSave))) { + delete[] pltSave; + return false; + } + + drawOSDText("Loading palette table"); + + bool loaded = _palLUT->load(*saveFile); + + delete[] pltSave; + delete saveFile; + + return loaded; +} + +bool Video_v6::savePalLUT(const char *target) { + if (target[0] == '\0') + return false; + + char *pltSave = new char[strlen(target) + 5]; + + strcpy(pltSave, target); + strcat(pltSave, ".plt"); + + Common::OutSaveFile *saveFile; + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + if (!(saveFile = saveMan->openForSaving(pltSave))) { + delete[] pltSave; + return false; + } + + drawOSDText("Saving palette table"); + + _palLUT->save(*saveFile); + + delete[] pltSave; + delete saveFile; +} + +void Video_v6::buildPalLUT() { char text[30]; + + _palLUT->setPalette(_ditherPalette, PaletteLUT::kPaletteYUV, 8); + for (int i = 0; (i < 64) && !_vm->shouldQuit(); i++) { sprintf(text, "Building palette table: %02d/63", i); drawOSDText(text); -- cgit v1.2.3