aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
authorSven Hesse2008-12-17 16:06:16 +0000
committerSven Hesse2008-12-17 16:06:16 +0000
commit38e7eecb710a3f7e8c5a637d525fed60d0712386 (patch)
tree723639e090dfb7965a64373fc634976c4bbf68f3 /engines/gob
parent10e471bb5b0b4ac6f2475c060703e55168601846 (diff)
downloadscummvm-rg350-38e7eecb710a3f7e8c5a637d525fed60d0712386.tar.gz
scummvm-rg350-38e7eecb710a3f7e8c5a637d525fed60d0712386.tar.bz2
scummvm-rg350-38e7eecb710a3f7e8c5a637d525fed60d0712386.zip
Added support for caching the palette LUT to a file
svn-id: r35412
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/gob.cpp2
-rw-r--r--engines/gob/indeo3.cpp71
-rw-r--r--engines/gob/indeo3.h9
-rw-r--r--engines/gob/video.h8
-rw-r--r--engines/gob/video_v6.cpp69
5 files changed, 145 insertions, 14 deletions
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);