aboutsummaryrefslogtreecommitdiff
path: root/common/zlib.cpp
diff options
context:
space:
mode:
authorMatthew Hoops2012-05-28 16:54:49 -0400
committerMatthew Hoops2012-05-28 16:54:49 -0400
commitab45e72e67c7effae9a9fecbaf5a77f9427d8df4 (patch)
tree344bc13beb3fddce3134aa0cb953b1523c133251 /common/zlib.cpp
parentf7e515a361dac041e6693ed9a1056df6ad05975e (diff)
downloadscummvm-rg350-ab45e72e67c7effae9a9fecbaf5a77f9427d8df4.tar.gz
scummvm-rg350-ab45e72e67c7effae9a9fecbaf5a77f9427d8df4.tar.bz2
scummvm-rg350-ab45e72e67c7effae9a9fecbaf5a77f9427d8df4.zip
COMMON: Move InstallShield code to common
The code also now works for both data compressed with sync bytes and without
Diffstat (limited to 'common/zlib.cpp')
-rw-r--r--common/zlib.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/common/zlib.cpp b/common/zlib.cpp
index 7d765fc539..98f319f351 100644
--- a/common/zlib.cpp
+++ b/common/zlib.cpp
@@ -85,6 +85,60 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen,
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;
+}
+
/**
* A simple wrapper class which can be used to wrap around an arbitrary
* other SeekableReadStream and will then provide on-the-fly decompression support.