aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/resources.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2015-05-16 09:29:40 -0400
committerPaul Gilbert2015-05-16 09:29:40 -0400
commitaf651e19a421781a1498de0e66909a2e9450611c (patch)
treeee5991b696600dd4fe03338b04a684a605215a7c /engines/sherlock/resources.cpp
parent32d7690e549f5af8fb5f88d9434ae0f54c0e6c69 (diff)
parent96e929f5233b23917169c7d0121e9c1e264455c1 (diff)
downloadscummvm-rg350-af651e19a421781a1498de0e66909a2e9450611c.tar.gz
scummvm-rg350-af651e19a421781a1498de0e66909a2e9450611c.tar.bz2
scummvm-rg350-af651e19a421781a1498de0e66909a2e9450611c.zip
Merge branch 'sherlock' into sherlock2
Conflicts: engines/sherlock/decompress.cpp engines/sherlock/objects.cpp engines/sherlock/objects.h engines/sherlock/scene.cpp engines/sherlock/scene.h engines/sherlock/sound.cpp
Diffstat (limited to 'engines/sherlock/resources.cpp')
-rw-r--r--engines/sherlock/resources.cpp90
1 files changed, 78 insertions, 12 deletions
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 9f2704ac62..bff80c2347 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -21,14 +21,14 @@
*/
#include "sherlock/resources.h"
-#include "sherlock/decompress.h"
#include "sherlock/screen.h"
#include "sherlock/sherlock.h"
#include "common/debug.h"
+#include "common/memstream.h"
namespace Sherlock {
-Cache::Cache() {
+Cache::Cache(SherlockEngine *vm): _vm(vm) {
}
/**
@@ -66,20 +66,17 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
if (_resources.contains(name))
return;
- // Check whether the file is compressed
- const char LZW_HEADER[5] = { "LZV\x1a" };
- char header[5];
- stream.read(header, 5);
- bool isCompressed = !strncmp(header, LZW_HEADER, 5);
+ int32 signature = stream.readUint32BE();
stream.seek(0);
// Allocate a new cache entry
_resources[name] = CacheEntry();
CacheEntry &cacheEntry = _resources[name];
- if (isCompressed) {
+ // 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 = decompressLZ(stream);
+ Common::SeekableReadStream *decompressed = _vm->_res->decompressLZ(stream);
cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size());
@@ -102,7 +99,7 @@ Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
/*----------------------------------------------------------------*/
-Resources::Resources() {
+Resources::Resources(SherlockEngine *vm): _vm(vm), _cache(vm) {
_resourceIndex = -1;
addToCache("vgs.lib");
@@ -169,8 +166,19 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
stream->seek(entry._offset);
Common::SeekableReadStream *resStream = stream->readStream(entry._size);
- delete stream;
- return resStream;
+ // Check whether the file is compressed
+ 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);
+ delete stream;
+ delete resStream;
+ return decompressed;
+ } else {
+ resStream->seek(0);
+ delete stream;
+ return resStream;
+ }
}
}
@@ -402,4 +410,62 @@ 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));
+ }
+
+ uint32 size = source.readUint32LE();
+ return decompressLZ(source, size);
+}
+
+/**
+ * Decompresses an LZW block of data with a specified output size
+ */
+Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
+ 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);
+
+ memset(lzWindow, 0xFF, 0xFEE);
+ lzWindowPos = 0xFEE;
+ cmd = 0;
+
+ do {
+ cmd >>= 1;
+ if (!(cmd & 0x100))
+ cmd = source.readByte() | 0xFF00;
+
+ if (cmd & 1) {
+ byte literal = source.readByte();
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ } else {
+ int copyPos, copyLen;
+ copyPos = source.readByte();
+ copyLen = source.readByte();
+ copyPos = copyPos | ((copyLen & 0xF0) << 4);
+ copyLen = (copyLen & 0x0F) + 3;
+ while (copyLen--) {
+ byte literal = lzWindow[copyPos];
+ copyPos = (copyPos + 1) & 0x0FFF;
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ }
+ }
+ } while (outBuffer < outBufferEnd);
+
+ return outS;
+}
+
} // End of namespace Sherlock