diff options
| author | D G Turner | 2012-10-12 17:03:32 +0100 | 
|---|---|---|
| committer | D G Turner | 2012-10-12 17:03:32 +0100 | 
| commit | 151b7beb47ec4b964862d6779bd48e3a33482bbd (patch) | |
| tree | 867717c5266d0908d95edd82560599be20a4ede9 /common/zlib.cpp | |
| parent | 80af0e239473f85c49cc2da3c848dfcde41d4a37 (diff) | |
| parent | 2b55837650c4229dc3d75b660cecfc7a3292e5e0 (diff) | |
| download | scummvm-rg350-151b7beb47ec4b964862d6779bd48e3a33482bbd.tar.gz scummvm-rg350-151b7beb47ec4b964862d6779bd48e3a33482bbd.tar.bz2 scummvm-rg350-151b7beb47ec4b964862d6779bd48e3a33482bbd.zip | |
Merge branch 'master' into teenagentRefactor
Conflicts:
	engines/teenagent/callbacks.cpp
Diffstat (limited to 'common/zlib.cpp')
| -rw-r--r-- | common/zlib.cpp | 63 | 
1 files changed, 59 insertions, 4 deletions
| diff --git a/common/zlib.cpp b/common/zlib.cpp index 7d765fc539..fc8f351054 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. @@ -107,7 +161,7 @@ protected:  public: -	GZipReadStream(SeekableReadStream *w) : _wrapped(w), _stream() { +	GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() {  		assert(w != 0);  		// Verify file header is correct @@ -122,7 +176,8 @@ public:  			_origSize = w->readUint32LE();  		} else {  			// Original size not available in zlib format -			_origSize = 0; +			// use an otherwise known size if supplied. +			_origSize = knownSize;  		}  		_pos = 0;  		w->seek(0, SEEK_SET); @@ -336,7 +391,7 @@ public:  #endif	// USE_ZLIB -SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped) { +SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped, uint32 knownSize) {  #if defined(USE_ZLIB)  	if (toBeWrapped) {  		uint16 header = toBeWrapped->readUint16BE(); @@ -345,7 +400,7 @@ SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped) {  				      header % 31 == 0));  		toBeWrapped->seek(-2, SEEK_CUR);  		if (isCompressed) -			return new GZipReadStream(toBeWrapped); +			return new GZipReadStream(toBeWrapped, knownSize);  	}  #endif  	return toBeWrapped; | 
