aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2015-05-16 10:52:38 -0400
committerPaul Gilbert2015-05-16 10:52:38 -0400
commit7897b72f655c8f65fd206aea12cfd06921d75124 (patch)
tree2aa4b7e42275c3e6194c40ea3c970ef822ea9ba9 /engines
parent602741172d9e1b187228655f4361f8850d44155b (diff)
downloadscummvm-rg350-7897b72f655c8f65fd206aea12cfd06921d75124.tar.gz
scummvm-rg350-7897b72f655c8f65fd206aea12cfd06921d75124.tar.bz2
scummvm-rg350-7897b72f655c8f65fd206aea12cfd06921d75124.zip
SHERLOCK: Fix decompression for Rose Tattoo
Diffstat (limited to 'engines')
-rw-r--r--engines/sherlock/resources.cpp46
-rw-r--r--engines/sherlock/resources.h4
-rw-r--r--engines/sherlock/scene.cpp4
3 files changed, 35 insertions, 19 deletions
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index bff80c2347..02030119c0 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -76,7 +76,7 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
// Check whether the file is compressed
if (signature == MKTAG('L', 'Z', 'V', 26)) {
// It's compressed, so decompress the file and store it's data in the cache entry
- Common::SeekableReadStream *decompressed = _vm->_res->decompressLZ(stream);
+ Common::SeekableReadStream *decompressed = _vm->_res->decompress(stream);
cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size());
@@ -170,7 +170,7 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
if (resStream->readUint32BE() == MKTAG('L', 'Z', 'V', 26)) {
resStream->seek(0);
// It's compressed, so decompress the sub-file and return it
- Common::SeekableReadStream *decompressed = decompressLZ(*resStream);
+ Common::SeekableReadStream *decompressed = decompress(*resStream);
delete stream;
delete resStream;
return decompressed;
@@ -413,27 +413,45 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
/**
* Decompress an LZW compressed resource
*/
-Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source) {
- if (_vm->getGameID() == GType_SerratedScalpel) {
- uint32 id = source.readUint32BE();
- assert(id == MKTAG('L', 'Z', 'V', 0x1A));
- }
+Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source) {
+ // This variation can't be used by Rose Tattoo, since compressed resources include the input size,
+ // not the output size. Which means their decompression has to be done via passed buffers
+ assert(_vm->getGameID() == GType_SerratedScalpel);
+
+ uint32 id = source.readUint32BE();
+ assert(id == MKTAG('L', 'Z', 'V', 0x1A));
+
+ uint32 outputSize = source.readUint32LE();
+ return decompressLZ(source, outputSize);
+}
+
+/**
+ * Decompress an LZW compressed resource
+ */
+void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
+ assert(_vm->getGameID() == GType_RoseTattoo);
- uint32 size = source.readUint32LE();
- return decompressLZ(source, size);
+ uint32 inputSize = source.readUint32LE();
+ decompressLZ(source, buffer, outSize, inputSize);
}
/**
* Decompresses an LZW block of data with a specified output size
*/
Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
+ byte *outBuffer = (byte *)malloc(outSize);
+ Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ decompressLZ(source, outSize);
+ return outStream;
+}
+
+void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize) {
byte lzWindow[4096];
uint16 lzWindowPos;
uint16 cmd;
-
- byte *outBuffer = (byte *)malloc(outSize);
byte *outBufferEnd = outBuffer + outSize;
- Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+ uint32 endPos = source.pos() + inSize;
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
@@ -463,9 +481,7 @@ Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
- } while (outBuffer < outBufferEnd);
-
- return outS;
+ } while ((!outSize || outBuffer < outBufferEnd) && (!inSize || source.pos() < endPos));
}
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index 041f1c64a9..0765ce4642 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -90,8 +90,10 @@ public:
int resourceIndex() const;
+ Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
+ void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
+ static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
- Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source);
};
struct ImageFrame {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0a25d3dd0f..e473217ba9 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -303,9 +303,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in background
if (_lzwMode) {
- Common::SeekableReadStream *stream = res.decompressLZ(*rrmStream);
- stream->read(screen._backBuffer1.getPixels(), stream->size());
- delete stream;
+ res.decompress(*rrmStream, (byte *)screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
} else {
rrmStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
}