diff options
author | Paul Gilbert | 2019-09-08 12:25:46 -0700 |
---|---|---|
committer | Paul Gilbert | 2019-09-25 20:13:27 -0700 |
commit | c03b7a50eafe3c6a559c55746ec88d5a37885e9a (patch) | |
tree | be028fbaead87b7d1445f9fe74dc1ad731239e3d /common | |
parent | 855b75f6dfd602879b7153e576124749d8c47c92 (diff) | |
download | scummvm-rg350-c03b7a50eafe3c6a559c55746ec88d5a37885e9a.tar.gz scummvm-rg350-c03b7a50eafe3c6a559c55746ec88d5a37885e9a.tar.bz2 scummvm-rg350-c03b7a50eafe3c6a559c55746ec88d5a37885e9a.zip |
GLK: ADRIFT: Implement zlib decompression
Diffstat (limited to 'common')
-rw-r--r-- | common/zlib.cpp | 73 | ||||
-rw-r--r-- | common/zlib.h | 12 |
2 files changed, 85 insertions, 0 deletions
diff --git a/common/zlib.cpp b/common/zlib.cpp index 6afffb14d2..e4a3d47e35 100644 --- a/common/zlib.cpp +++ b/common/zlib.cpp @@ -141,6 +141,79 @@ bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcL return true; } +bool inflateZlibHeaderless(Common::WriteStream *dst, Common::SeekableReadStream *src) { + byte *inBuffer, *outBuffer; + z_stream stream; + int status; + + // Allocate buffers + inBuffer = new byte[kTempBufSize]; + outBuffer = new byte[kTempBufSize]; + + /* Initialize Zlib inflation functions. */ + stream.next_out = outBuffer; + stream.avail_out = kTempBufSize; + stream.next_in = inBuffer; + stream.avail_in = 0; + + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + status = inflateInit(&stream); + if (status != Z_OK) { + delete[] inBuffer; + delete[] outBuffer; + return false; + } + + // Inflate the input buffers. */ + for (;;) { + int inBytes, outBytes; + + /* If the input buffer is empty, try to obtain more data. */ + if (stream.avail_in == 0) { + inBytes = src->read(inBuffer, kTempBufSize); + stream.next_in = inBuffer; + stream.avail_in = inBytes; + } + + // Decompress as much stream data as we can. */ + status = inflate(&stream, Z_SYNC_FLUSH); + if (status != Z_STREAM_END && status != Z_OK) { + delete[] inBuffer; + delete[] outBuffer; + return false; + } + outBytes = kTempBufSize - stream.avail_out; + + // See if decompressed data is available. */ + if (outBytes > 0) { + // Add data from the buffer to the output + int consumed = dst->write(outBuffer, outBytes); + + // Move unused buffer data to buffer start + memmove(outBuffer, outBuffer + consumed, kTempBufSize - consumed); + + // Reset inflation stream for available space + stream.next_out = outBuffer + outBytes - consumed; + stream.avail_out += consumed; + } + + // If at inflation stream end and output is empty, leave loop + if (status == Z_STREAM_END && stream.avail_out == kTempBufSize) + break; + } + + // End inflation buffers + status = inflateEnd(&stream); + delete[] inBuffer; + delete[] outBuffer; + + // Return result + return (status == Z_OK); +} + #ifndef RELEASE_BUILD static bool _shownBackwardSeekingWarning = false; #endif diff --git a/common/zlib.h b/common/zlib.h index eb0548344d..a172399511 100644 --- a/common/zlib.h +++ b/common/zlib.h @@ -96,6 +96,18 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, */ bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcLen); +/** + * Wrapper around zlib's inflate functions. This function is used by Glk to + * decompress TAF 4.0 files, which are headerless Zlib compressed streams with a + * custom header + * + * @param dst the destination stream to write decompressed data out to + * @param src the Source stream + * + * @return true on success (Z_OK or Z_STREAM_END), false otherwise. + */ +bool inflateZlibHeaderless(Common::WriteStream *dst, Common::SeekableReadStream *src); + #endif /** |