aboutsummaryrefslogtreecommitdiff
path: root/devtools/create_titanic
diff options
context:
space:
mode:
authorPaul Gilbert2017-08-12 20:08:49 -0400
committerPaul Gilbert2017-08-12 20:08:49 -0400
commit6a5c52019458e13941abb3f6ab3f4cd1607c3989 (patch)
treedd69ca2f915987ba0ef567811d4dac5d512c0e7f /devtools/create_titanic
parenta03183760a428144987832956355054736173878 (diff)
downloadscummvm-rg350-6a5c52019458e13941abb3f6ab3f4cd1607c3989.tar.gz
scummvm-rg350-6a5c52019458e13941abb3f6ab3f4cd1607c3989.tar.bz2
scummvm-rg350-6a5c52019458e13941abb3f6ab3f4cd1607c3989.zip
DEVTOOLS: Add compression for titanic.dat bitmaps
Diffstat (limited to 'devtools/create_titanic')
-rw-r--r--devtools/create_titanic/create_titanic_dat.cpp62
-rw-r--r--devtools/create_titanic/module.mk3
-rw-r--r--devtools/create_titanic/zlib.cpp455
-rw-r--r--devtools/create_titanic/zlib.h136
4 files changed, 643 insertions, 13 deletions
diff --git a/devtools/create_titanic/create_titanic_dat.cpp b/devtools/create_titanic/create_titanic_dat.cpp
index 6d9b713846..4a24ec98d4 100644
--- a/devtools/create_titanic/create_titanic_dat.cpp
+++ b/devtools/create_titanic/create_titanic_dat.cpp
@@ -29,11 +29,17 @@
#undef main
#endif // main
+#ifndef USE_ZLIB
+#error "Project should have USE_ZLIB defined"
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common/language.h"
+#include "common/memstream.h"
#include "common/rect.h"
+#include "zlib.h"
#include "winexe_pe.h"
#include "file.h"
#include "script_preresponses.h"
@@ -54,8 +60,8 @@
* ASCIIZ - name of the resource
*/
-#define VERSION_NUMBER 1
-#define HEADER_SIZE 0x1200
+#define VERSION_NUMBER 2
+#define HEADER_SIZE 0x1380
Common::File inputFile, outputFile;
Common::PEResources resEng, resGer;
@@ -1022,14 +1028,24 @@ void NORETURN_PRE error(const char *s, ...) {
exit(1);
}
-void writeEntryHeader(const char *name, uint offset, uint size) {
+void writeEntryHeader(const char *name, uint offset, uint size, uint flags) {
assert(headerOffset < HEADER_SIZE);
outputFile.seek(headerOffset);
outputFile.writeLong(offset);
outputFile.writeLong(size);
+ outputFile.writeWord(flags);
outputFile.writeString(name);
- headerOffset += 8 + strlen(name) + 1;
+ headerOffset += 10 + strlen(name) + 1;
+}
+
+void writeEntryHeader(const char *name, uint offset, uint size) {
+ writeEntryHeader(name, offset, size, 0);
+}
+
+void writeEntryHeader(const char *name, uint offset, uint size, bool isCompressed) {
+ uint flags = isCompressed ? 1 : 0;
+ writeEntryHeader(name, offset, size, flags);
}
void writeFinalEntryHeader() {
@@ -1039,6 +1055,10 @@ void writeFinalEntryHeader() {
outputFile.writeLong(0);
}
+void writeCompressedRes(Common::File *src) {
+
+}
+
void writeStringArray(const char *name, uint offset, int count) {
outputFile.seek(dataOffset);
@@ -1130,18 +1150,36 @@ void writeResource(const char *sectionStr, const char *resId, bool isEnglish = t
void writeBitmap(const char *name, Common::File *file) {
outputFile.seek(dataOffset);
+ // Set up a memory stream for the compressed data, and wrap
+ // it with a zlib compressor
+ Common::MemoryWriteStreamDynamic *compressedData =
+ new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+ Common::WriteStream *zlib = Common::wrapCompressedWriteStream(compressedData);
+
// Write out the necessary bitmap header so that the ScummVM
// BMP decoder can properly handle decoding the bitmaps
- outputFile.write("BM", 2);
- outputFile.writeLong(file->size() + 14); // Filesize
- outputFile.writeLong(0); // res1 & res2
- outputFile.writeLong(0x436); // image offset
+ zlib->write("BM", 2);
+ zlib->writeUint32LE(file->size() + 14); // Filesize
+ zlib->writeUint32LE(0); // res1 & res2
+ zlib->writeUint32LE(0x436); // image offset
- outputFile.write(*file, file->size());
+ // Transfer the bitmap data
+ int srcSize = file->size();
+ byte *data = new byte[srcSize];
+ file->read(data, srcSize);
+ zlib->write(data, srcSize);
- writeEntryHeader(name, dataOffset, file->size() + 14);
- dataOffset += file->size() + 14;
- delete file;
+ delete[] data;
+ zlib->finalize();
+
+ // Write out the compressed data
+ outputFile.write(compressedData->getData(), compressedData->size());
+
+ writeEntryHeader(name, dataOffset, compressedData->size() + 14, true);
+ dataOffset += compressedData->size() + 14;
+
+ // Free the zlib write stream
+ delete zlib;
}
void writeBitmap(const char *sectionStr, const char *resId, bool isEnglish = true) {
diff --git a/devtools/create_titanic/module.mk b/devtools/create_titanic/module.mk
index 9f77866d45..a762af3ab2 100644
--- a/devtools/create_titanic/module.mk
+++ b/devtools/create_titanic/module.mk
@@ -13,7 +13,8 @@ MODULE_OBJS := \
str.o \
tag_maps.o \
winexe.o \
- winexe_pe.o
+ winexe_pe.o \
+ zlib.o
# Set the name of the executable
TOOL_EXECUTABLE := create_titanic
diff --git a/devtools/create_titanic/zlib.cpp b/devtools/create_titanic/zlib.cpp
new file mode 100644
index 0000000000..3221d61813
--- /dev/null
+++ b/devtools/create_titanic/zlib.cpp
@@ -0,0 +1,455 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use zlib.h
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "zlib.h"
+#include "common/ptr.h"
+#include "common/util.h"
+#include "common/stream.h"
+
+#if defined(USE_ZLIB)
+ #ifdef __SYMBIAN32__
+ #include <zlib\zlib.h>
+ #else
+ #include <zlib.h>
+ #endif
+
+ #if ZLIB_VERNUM < 0x1204
+ #error Version 1.2.0.4 or newer of zlib is required for this code
+ #endif
+#endif
+
+
+namespace Common {
+
+/**
+ * Stubs for ScummVM stuff I don't want to have to link in
+ */
+void debug(int level, const char *s, ...) {}
+
+char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
+ return nullptr;
+}
+
+String SeekableReadStream::readLine() {
+ return String();
+}
+
+#if defined(USE_ZLIB)
+
+bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen) {
+ return Z_OK == ::uncompress(dst, dstLen, src, srcLen);
+}
+
+bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict, uint dictLen) {
+ if (!dst || !dstLen || !src || !srcLen)
+ return false;
+
+ // Initialize zlib
+ z_stream stream;
+ stream.next_in = const_cast<byte *>(src);
+ stream.avail_in = srcLen;
+ stream.next_out = dst;
+ stream.avail_out = dstLen;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ // Negative MAX_WBITS tells zlib there's no zlib header
+ int err = inflateInit2(&stream, -MAX_WBITS);
+ if (err != Z_OK)
+ return false;
+
+ // Set the dictionary, if provided
+ if (dict != 0) {
+ err = inflateSetDictionary(&stream, const_cast<byte *>(dict), dictLen);
+ if (err != Z_OK)
+ return false;
+ }
+
+ err = inflate(&stream, Z_SYNC_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return false;
+ }
+
+ inflateEnd(&stream);
+ return true;
+}
+
+enum {
+ kTempBufSize = 65536
+};
+
+bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcLen) {
+ if (!dst || !dstLen || !src || !srcLen)
+ return false;
+
+ // See if we have sync bytes. If so, just use our function for that.
+ if (srcLen >= 4 && READ_BE_UINT32(src + srcLen - 4) == 0xFFFF)
+ return inflateZlibHeaderless(dst, dstLen, src, srcLen);
+
+ // Otherwise, we have some custom code we get to use here.
+
+ byte *temp = (byte *)malloc(kTempBufSize);
+
+ uint32 bytesRead = 0, bytesProcessed = 0;
+ while (bytesRead < srcLen) {
+ uint16 chunkSize = READ_LE_UINT16(src + bytesRead);
+ bytesRead += 2;
+
+ // Initialize zlib
+ z_stream stream;
+ stream.next_in = const_cast<byte *>(src + bytesRead);
+ stream.avail_in = chunkSize;
+ stream.next_out = temp;
+ stream.avail_out = kTempBufSize;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ // Negative MAX_WBITS tells zlib there's no zlib header
+ int err = inflateInit2(&stream, -MAX_WBITS);
+ if (err != Z_OK)
+ return false;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_OK && err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ free(temp);
+ return false;
+ }
+
+ memcpy(dst + bytesProcessed, temp, stream.total_out);
+ bytesProcessed += stream.total_out;
+
+ inflateEnd(&stream);
+ bytesRead += chunkSize;
+ }
+
+ free(temp);
+ return true;
+}
+
+#ifndef RELEASE_BUILD
+static bool _shownBackwardSeekingWarning = false;
+#endif
+
+/**
+ * A simple wrapper class which can be used to wrap around an arbitrary
+ * other SeekableReadStream and will then provide on-the-fly decompression support.
+ * Assumes the compressed data to be in gzip format.
+ */
+class GZipReadStream : public SeekableReadStream {
+protected:
+ enum {
+ BUFSIZE = 16384 // 1 << MAX_WBITS
+ };
+
+ byte _buf[BUFSIZE];
+
+ ScopedPtr<SeekableReadStream> _wrapped;
+ z_stream _stream;
+ int _zlibErr;
+ uint32 _pos;
+ uint32 _origSize;
+ bool _eos;
+
+public:
+
+ GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() {
+ assert(w != 0);
+
+ // Verify file header is correct
+ w->seek(0, SEEK_SET);
+ uint16 header = w->readUint16BE();
+ assert(header == 0x1F8B ||
+ ((header & 0x0F00) == 0x0800 && header % 31 == 0));
+
+ if (header == 0x1F8B) {
+ // Retrieve the original file size
+ w->seek(-4, SEEK_END);
+ _origSize = w->readUint32LE();
+ } else {
+ // Original size not available in zlib format
+ // use an otherwise known size if supplied.
+ _origSize = knownSize;
+ }
+ _pos = 0;
+ w->seek(0, SEEK_SET);
+ _eos = false;
+
+ // Adding 32 to windowBits indicates to zlib that it is supposed to
+ // automatically detect whether gzip or zlib headers are used for
+ // the compressed file. This feature was added in zlib 1.2.0.4,
+ // released 10 August 2003.
+ // Note: This is *crucial* for savegame compatibility, do *not* remove!
+ _zlibErr = inflateInit2(&_stream, MAX_WBITS + 32);
+ if (_zlibErr != Z_OK)
+ return;
+
+ // Setup input buffer
+ _stream.next_in = _buf;
+ _stream.avail_in = 0;
+ }
+
+ ~GZipReadStream() {
+ inflateEnd(&_stream);
+ }
+
+ bool err() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); }
+ void clearErr() {
+ // only reset _eos; I/O errors are not recoverable
+ _eos = false;
+ }
+
+ uint32 read(void *dataPtr, uint32 dataSize) {
+ _stream.next_out = (byte *)dataPtr;
+ _stream.avail_out = dataSize;
+
+ // Keep going while we get no error
+ while (_zlibErr == Z_OK && _stream.avail_out) {
+ if (_stream.avail_in == 0 && !_wrapped->eos()) {
+ // If we are out of input data: Read more data, if available.
+ _stream.next_in = _buf;
+ _stream.avail_in = _wrapped->read(_buf, BUFSIZE);
+ }
+ _zlibErr = inflate(&_stream, Z_NO_FLUSH);
+ }
+
+ // Update the position counter
+ _pos += dataSize - _stream.avail_out;
+
+ if (_zlibErr == Z_STREAM_END && _stream.avail_out > 0)
+ _eos = true;
+
+ return dataSize - _stream.avail_out;
+ }
+
+ bool eos() const {
+ return _eos;
+ }
+ int32 pos() const {
+ return _pos;
+ }
+ int32 size() const {
+ return _origSize;
+ }
+ bool seek(int32 offset, int whence = SEEK_SET) {
+ int32 newPos = 0;
+ switch (whence) {
+ case SEEK_SET:
+ newPos = offset;
+ break;
+ case SEEK_CUR:
+ newPos = _pos + offset;
+ break;
+ case SEEK_END:
+ // NOTE: This can be an expensive operation (see below).
+ newPos = size() + offset;
+ break;
+ }
+
+ assert(newPos >= 0);
+
+ if ((uint32)newPos < _pos) {
+ // To search backward, we have to restart the whole decompression
+ // from the start of the file. A rather wasteful operation, best
+ // to avoid it. :/
+
+#ifndef RELEASE_BUILD
+ if (!_shownBackwardSeekingWarning) {
+ // We only throw this warning once per stream, to avoid
+ // getting the console swarmed with warnings when consecutive
+ // seeks are made.
+ debug(1, "Backward seeking in GZipReadStream detected");
+ _shownBackwardSeekingWarning = true;
+ }
+#endif
+
+ _pos = 0;
+ _wrapped->seek(0, SEEK_SET);
+ _zlibErr = inflateReset(&_stream);
+ if (_zlibErr != Z_OK)
+ return false; // FIXME: STREAM REWRITE
+ _stream.next_in = _buf;
+ _stream.avail_in = 0;
+ }
+
+ offset = newPos - _pos;
+
+ // Skip the given amount of data (very inefficient if one tries to skip
+ // huge amounts of data, but usually client code will only skip a few
+ // bytes, so this should be fine.
+ byte tmpBuf[1024];
+ while (!err() && offset > 0) {
+ offset -= read(tmpBuf, MIN((int32)sizeof(tmpBuf), offset));
+ }
+
+ _eos = false;
+ return true; // FIXME: STREAM REWRITE
+ }
+};
+
+/**
+ * A simple wrapper class which can be used to wrap around an arbitrary
+ * other WriteStream and will then provide on-the-fly compression support.
+ * The compressed data is written in the gzip format.
+ */
+class GZipWriteStream : public WriteStream {
+protected:
+ enum {
+ BUFSIZE = 16384 // 1 << MAX_WBITS
+ };
+
+ byte _buf[BUFSIZE];
+ ScopedPtr<WriteStream> _wrapped;
+ z_stream _stream;
+ int _zlibErr;
+ uint32 _pos;
+
+ void processData(int flushType) {
+ // This function is called by both write() and finalize().
+ while (_zlibErr == Z_OK && (_stream.avail_in || flushType == Z_FINISH)) {
+ if (_stream.avail_out == 0) {
+ if (_wrapped->write(_buf, BUFSIZE) != BUFSIZE) {
+ _zlibErr = Z_ERRNO;
+ break;
+ }
+ _stream.next_out = _buf;
+ _stream.avail_out = BUFSIZE;
+ }
+ _zlibErr = deflate(&_stream, flushType);
+ }
+ }
+
+public:
+ GZipWriteStream(WriteStream *w) : _wrapped(w), _stream(), _pos(0) {
+ assert(w != 0);
+
+ // Adding 16 to windowBits indicates to zlib that it is supposed to
+ // write gzip headers. This feature was added in zlib 1.2.0.4,
+ // released 10 August 2003.
+ // Note: This is *crucial* for savegame compatibility, do *not* remove!
+ _zlibErr = deflateInit2(&_stream,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ MAX_WBITS + 16,
+ 8,
+ Z_DEFAULT_STRATEGY);
+ assert(_zlibErr == Z_OK);
+
+ _stream.next_out = _buf;
+ _stream.avail_out = BUFSIZE;
+ _stream.avail_in = 0;
+ _stream.next_in = 0;
+ }
+
+ ~GZipWriteStream() {
+ finalize();
+ deflateEnd(&_stream);
+ }
+
+ bool err() const {
+ // CHECKME: does Z_STREAM_END make sense here?
+ return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->err();
+ }
+
+ void clearErr() {
+ // Note: we don't reset the _zlibErr here, as it is not
+ // clear in general how
+ _wrapped->clearErr();
+ }
+
+ void finalize() {
+ if (_zlibErr != Z_OK)
+ return;
+
+ // Process whatever remaining data there is.
+ processData(Z_FINISH);
+
+ // Since processData only writes out blocks of size BUFSIZE,
+ // we may have to flush some stragglers.
+ uint remainder = BUFSIZE - _stream.avail_out;
+ if (remainder > 0) {
+ if (_wrapped->write(_buf, remainder) != remainder) {
+ _zlibErr = Z_ERRNO;
+ }
+ }
+
+ // Finalize the wrapped savefile, too
+ _wrapped->finalize();
+ }
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ if (err())
+ return 0;
+
+ // Hook in the new data ...
+ // Note: We need to make a const_cast here, as zlib is not aware
+ // of the const keyword.
+ _stream.next_in = const_cast<byte *>((const byte *)dataPtr);
+ _stream.avail_in = dataSize;
+
+ // ... and flush it to disk
+ processData(Z_NO_FLUSH);
+
+ _pos += dataSize - _stream.avail_in;
+ return dataSize - _stream.avail_in;
+ }
+
+ virtual int32 pos() const { return _pos; }
+};
+
+#endif // USE_ZLIB
+
+SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped, uint32 knownSize) {
+ if (toBeWrapped) {
+ uint16 header = toBeWrapped->readUint16BE();
+ bool isCompressed = (header == 0x1F8B ||
+ ((header & 0x0F00) == 0x0800 &&
+ header % 31 == 0));
+ toBeWrapped->seek(-2, SEEK_CUR);
+ if (isCompressed) {
+#if defined(USE_ZLIB)
+ return new GZipReadStream(toBeWrapped, knownSize);
+#else
+ delete toBeWrapped;
+ return NULL;
+#endif
+ }
+ }
+ return toBeWrapped;
+}
+
+WriteStream *wrapCompressedWriteStream(WriteStream *toBeWrapped) {
+#if defined(USE_ZLIB)
+ if (toBeWrapped)
+ return new GZipWriteStream(toBeWrapped);
+#endif
+ return toBeWrapped;
+}
+
+
+} // End of namespace Common
diff --git a/devtools/create_titanic/zlib.h b/devtools/create_titanic/zlib.h
new file mode 100644
index 0000000000..5adba64076
--- /dev/null
+++ b/devtools/create_titanic/zlib.h
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMMON_ZLIB_H
+#define COMMON_ZLIB_H
+
+#include "common/scummsys.h"
+
+namespace Common {
+
+class SeekableReadStream;
+class WriteStream;
+
+#if defined(USE_ZLIB)
+
+/**
+ * Thin wrapper around zlib's uncompress() function. This wrapper makes
+ * it possible to uncompress data in engines without being forced to link
+ * them against zlib, thus simplifying the build system.
+ *
+ * Taken from the zlib manual:
+ * Decompresses the src buffer into the dst buffer.
+ * srcLen is the byte length of the source buffer. Upon entry, dstLen is the
+ * total size of the destination buffer, which must be large enough to hold
+ * the entire uncompressed data. Upon exit, dstLen is the actual size of the
+ * compressed buffer.
+ *
+ * @param dst the buffer to store into.
+ * @param dstLen a pointer to the size of the destination buffer.
+ * @param src the data to be decompressed.
+ * @param srcLen the size of the compressed data.
+ *
+ * @return true on success (i.e. Z_OK), false otherwise.
+ */
+bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen);
+
+/**
+ * Wrapper around zlib's inflate functions. This function will call the
+ * necessary inflate functions to uncompress data compressed with deflate
+ * but *not* with the standard zlib header.
+ *
+ * Decompresses the src buffer into the dst buffer.
+ * srcLen is the byte length of the source buffer, dstLen is the byte
+ * length of the output buffer.
+ * It decompress as much data as possible, up to dstLen bytes.
+ * If a dictionary is provided through the dict buffer, uses it to initializes
+ * the internal decompression dictionary, before the decompression takes place.
+ *
+ * @param dst the buffer to store into.
+ * @param dstLen the size of the destination buffer.
+ * @param src the data to be decompressed.
+ * @param srcLen the size of the compressed data.
+ * @param dict (optional) a decompress dictionary.
+ * @param dictLen (optional) the size of the dictionary.
+ * Mandatory if dict is not 0.
+ *
+ * @return true on success (Z_OK or Z_STREAM_END), false otherwise.
+ */
+bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict = 0, uint dictLen = 0);
+
+/**
+ * Wrapper around zlib's inflate functions. This function will call the
+ * necessary inflate functions to uncompress data compressed for InstallShield
+ * cabinet files.
+ *
+ * Decompresses the src buffer into the dst buffer.
+ * srcLen is the byte length of the source buffer, dstLen is the byte
+ * length of the output buffer.
+ * It decompress as much data as possible, up to dstLen bytes.
+ *
+ * @param dst the buffer to store into.
+ * @param dstLen the size of the destination buffer.
+ * @param src the data to be decompressed.
+ * @param srcLen the size of the compressed data.
+ *
+ * @return true on success (Z_OK or Z_STREAM_END), false otherwise.
+ */
+bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcLen);
+
+#endif
+
+/**
+ * Take an arbitrary SeekableReadStream and wrap it in a custom stream which
+ * provides transparent on-the-fly decompression. Assumes the data it
+ * retrieves from the wrapped stream to be either uncompressed or in gzip
+ * format. In the former case, the original stream is returned unmodified
+ * (and in particular, not wrapped). In the latter case the stream is
+ * returned wrapped, unless there is no ZLIB support, then NULL is returned
+ * and the old stream is destroyed.
+ *
+ * Certain GZip-formats don't supply an easily readable length, if you
+ * still need the length carried along with the stream, and you know
+ * the decompressed length at wrap-time, then it can be supplied as knownSize
+ * here. knownSize will be ignored if the GZip-stream DOES include a length.
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ *
+ * @param toBeWrapped the stream to be wrapped (if it is in gzip-format)
+ * @param knownSize a supplied length of the compressed data (if not available directly)
+ */
+SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped, uint32 knownSize = 0);
+
+/**
+ * Take an arbitrary WriteStream and wrap it in a custom stream which provides
+ * transparent on-the-fly compression. The compressed data is written in the
+ * gzip format, unless ZLIB support has been disabled, in which case the given
+ * stream is returned unmodified (and in particular, not wrapped).
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+WriteStream *wrapCompressedWriteStream(WriteStream *toBeWrapped);
+
+} // End of namespace Common
+
+#endif