diff options
Diffstat (limited to 'common/zlib.cpp')
-rw-r--r-- | common/zlib.cpp | 73 |
1 files changed, 73 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 |