diff options
author | Paul Gilbert | 2015-05-16 10:52:38 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-05-16 10:52:38 -0400 |
commit | 7897b72f655c8f65fd206aea12cfd06921d75124 (patch) | |
tree | 2aa4b7e42275c3e6194c40ea3c970ef822ea9ba9 /engines | |
parent | 602741172d9e1b187228655f4361f8850d44155b (diff) | |
download | scummvm-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.cpp | 46 | ||||
-rw-r--r-- | engines/sherlock/resources.h | 4 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 4 |
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); } |