[Scummvm-cvs-logs] scummvm master -> 7753f2d51610766fc273e810af1accbbcf013624

m-kiewitz m_kiewitz at users.sourceforge.net
Sat Jul 4 01:50:33 CEST 2015


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
7753f2d516 AGOS: Simon 2: use common PKWARE data comp. lib


Commit: 7753f2d51610766fc273e810af1accbbcf013624
    https://github.com/scummvm/scummvm/commit/7753f2d51610766fc273e810af1accbbcf013624
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-07-04T01:50:07+02:00

Commit Message:
AGOS: Simon 2: use common PKWARE data comp. lib

use PKWARE data compression library code from COMMON/
AdLib drivers will get changed to use streams too

Changed paths:
    engines/agos/midi.cpp
    engines/agos/midi.h



diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index c02dfdb..f817212 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -23,6 +23,7 @@
 #include "common/config-manager.h"
 #include "common/file.h"
 #include "common/textconsole.h"
+#include "common/memstream.h"
 
 #include "agos/agos.h"
 #include "agos/midi.h"
@@ -31,6 +32,9 @@
 // Miles Audio for Simon 2
 #include "audio/miles.h"
 
+// PKWARE data compression library decompressor required for Simon 2
+#include "common/dcl.h"
+
 #include "gui/message.h"
 
 namespace AGOS {
@@ -806,7 +810,7 @@ void MidiPlayer::loadS1D(Common::File *in, bool sfx) {
 #define MIDI_SETUP_BUNDLE_FILEHEADER_SIZE 48
 #define MIDI_SETUP_BUNDLE_FILENAME_MAX_SIZE 12
 
-// PKWARE data compression is used for storing files within SETUP.SHR
+// PKWARE data compression library (called "DCL" in ScummVM) was used for storing files within SETUP.SHR
 // we need it to be able to get the file MIDPAK.AD, otherwise we would have to require the user
 // to "install" the game before being able to actually play it, when using AdLib.
 //
@@ -826,7 +830,7 @@ const byte *MidiPlayer::simon2SetupExtractFile(const Common::String &requestedFi
 	Common::String fileName;
 	uint32         fileCompressedSize = 0;
 	byte          *fileCompressedDataPtr = nullptr;
-	const byte    *extractedDataPtr = nullptr;
+	byte          *extractedDataPtr = nullptr;
 
 	extractedDataSize = 0;
 
@@ -876,12 +880,27 @@ const byte *MidiPlayer::simon2SetupExtractFile(const Common::String &requestedFi
 		if (fileName == requestedFileName) {
 			// requested file found
 			fileCompressedDataPtr = new byte[fileCompressedSize];
+
 			if (setupBundleStream->read(fileCompressedDataPtr, fileCompressedSize) != fileCompressedSize)
 				error("MidiPlayer: setup.shr read error");
 
-			// now extract the data
-			
-			extractedDataPtr = simon2SetupDecompressFile(fileCompressedDataPtr, fileCompressedSize, extractedDataSize);
+			Common::MemoryReadStream *compressedStream = nullptr;
+			Common::SeekableReadStream *extractedStream = nullptr;
+
+			compressedStream = new Common::MemoryReadStream(fileCompressedDataPtr, fileCompressedSize);
+			// we don't know the unpacked size, let decompressor figure it out
+			extractedStream = Common::decompressDCL(compressedStream);
+			delete compressedStream;
+
+			if (extractedStream) {
+				// Successfully extracted the data
+				// TODO: clean up required, but this also requires Miles Audio drivers to use streams
+				extractedDataPtr = new byte[extractedStream->size()];
+				extractedStream->seek(0);
+				extractedStream->read(extractedDataPtr, extractedStream->size());
+				extractedDataSize = extractedStream->size();
+				delete extractedStream;
+			}
 			break;
 		}
 
@@ -897,326 +916,4 @@ const byte *MidiPlayer::simon2SetupExtractFile(const Common::String &requestedFi
 	return extractedDataPtr;
 }
 
-static byte simon2SetupBitsMask[9] = {
-	0,
-	0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
-};
-
-// gets [bitCount] bits from dataPtr, going from LSB to MSB
-inline uint16 MidiPlayer::simon2SetupGetBits(byte bitCount, const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft) {
-	byte   resultBitsLeft = bitCount;
-	byte   resultBitsPos = 0;
-	uint16 result = 0;
-	byte   currentByte = *dataPtr;
-	byte   currentBits = 0;
-
-	// Get bits of current byte
-	while (resultBitsLeft) {
-		if (resultBitsLeft < dataBitsLeft) {
-			// we need less than we have left
-			currentBits = (currentByte >> (8 - dataBitsLeft)) & simon2SetupBitsMask[resultBitsLeft];
-			result |= (currentBits << resultBitsPos);
-			dataBitsLeft -= resultBitsLeft;
-			resultBitsLeft = 0;
-
-		} else {
-			// we need as much as we have left or more
-			resultBitsLeft -= dataBitsLeft;
-			currentBits = currentByte >> (8 - dataBitsLeft);
-			result |= (currentBits << resultBitsPos);
-			resultBitsPos += dataBitsLeft;
-
-			// Go to next byte
-			dataPtr++;
-			if (dataPtr >= dataEndPtr)
-				error("MidiPlayer: setup.shr: unexpected end of compressed data stream");
-
-			dataBitsLeft = 8;
-			if (resultBitsLeft) {
-				currentByte = *dataPtr;
-			}
-		}
-	}
-	return result;
-}
-
-// Decode length from bitstream
-inline uint16 MidiPlayer::simon2SetupGetLength(const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft) {
-	uint16 bits;
-
-	bits = simon2SetupGetBits(2, dataPtr, dataEndPtr, dataBitsLeft);
-
-	switch (bits) {
-	case 3:
-		return 3; // 11b
-	case 2:
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits)
-			return 5; // 011b
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits)
-			return 6; // 0101b
-		return 7;
-	case 1:
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits)
-			return 2; // 101b
-		return 4; // 100b
-	case 0:
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits) {
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits)
-				return 8; // 0011b
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits)
-				return 9; // 00101b
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits)
-				return 11; // 001001b
-			return 10; // 001000b
-
-		} else {
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits) {
-				bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-				if (bits) {
-					bits = simon2SetupGetBits(2, dataPtr, dataEndPtr, dataBitsLeft);
-					return 12 + bits; // 00011XXb
-				} else {
-					bits = simon2SetupGetBits(3, dataPtr, dataEndPtr, dataBitsLeft);
-					return 16 + bits; // 00010XXXb
-				}
-			} else {
-				bits = simon2SetupGetBits(2, dataPtr, dataEndPtr, dataBitsLeft);
-				switch (bits) {
-				case 3:
-					bits = simon2SetupGetBits(4, dataPtr, dataEndPtr, dataBitsLeft);
-					return 24 + bits; // 000011XXXXb
-				case 2:
-					bits = simon2SetupGetBits(6, dataPtr, dataEndPtr, dataBitsLeft);
-					return 72 + bits; // 000001XXXXXXb
-				case 1:
-					bits = simon2SetupGetBits(5, dataPtr, dataEndPtr, dataBitsLeft);
-					return 40 + bits; // 000010XXXXXb
-				case 0:
-					bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-					if (bits) {
-						bits = simon2SetupGetBits(7, dataPtr, dataEndPtr, dataBitsLeft);
-						return 136 + bits; // 0000001XXXXXXXXb
-					} else {
-						bits = simon2SetupGetBits(8, dataPtr, dataEndPtr, dataBitsLeft);
-						return 264 + bits; // 0000000XXXXXXXXb
-					}
-				default:
-					break;
-				}
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-// Decode offset from bitstream
-inline uint16 MidiPlayer::simon2SetupGetOffset(byte lowOrderBits, const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft) {
-	uint16 baseOffset = 0;
-	uint16 bits = 0;
-
-	bits = simon2SetupGetBits(2, dataPtr, dataEndPtr, dataBitsLeft);
-	switch (bits) {
-	case 3:
-		baseOffset = 0; // 11b
-		break;
-	case 2:
-		bits = simon2SetupGetBits(4, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits) {
-			baseOffset = 0x16 - simon2SetupReverseBits(bits, 4);
-		} else {
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			baseOffset = 0x17 - bits;
-		}
-		break;
-	case 1:
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits) {
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits) {
-				baseOffset = 0x01;
-			} else {
-				baseOffset = 0x02;
-			}
-		} else {
-			bits = simon2SetupGetBits(2, dataPtr, dataEndPtr, dataBitsLeft);
-			baseOffset = 0x06 - simon2SetupReverseBits(bits, 2);
-		}
-		break;
-	case 0:
-		bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-		if (bits) {
-			bits = simon2SetupGetBits(4, dataPtr, dataEndPtr, dataBitsLeft);
-			baseOffset = 0x27 - simon2SetupReverseBits(bits, 4);
-		} else {
-			bits = simon2SetupGetBits(1, dataPtr, dataEndPtr, dataBitsLeft);
-			if (bits) {
-				bits = simon2SetupGetBits(3, dataPtr, dataEndPtr, dataBitsLeft);
-				baseOffset = 0x2F - simon2SetupReverseBits(bits, 3);
-			} else {
-				bits = simon2SetupGetBits(4, dataPtr, dataEndPtr, dataBitsLeft);
-				baseOffset = 0x3F - simon2SetupReverseBits(bits, 4);
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	bits = simon2SetupGetBits(lowOrderBits, dataPtr, dataEndPtr, dataBitsLeft);
-	return (baseOffset << lowOrderBits) + bits;
-}
-
-inline uint16 MidiPlayer::simon2SetupReverseBits(uint16 bits, byte bitCount) {
-	uint16 result = 0;
-
-	for (byte bitNr = 0; bitNr < bitCount; bitNr++) {
-		result = (result << 1) | (bits & 0x01);
-		bits = bits >> 1;
-	}
-	return result;
-}
-
-#define MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE 4096
-
-// Implementation of "PKWARE data compression library" decompression
-// Based on information released by Ben Rudiak-Gould in comp.compression on 13.8.2001
-const byte *MidiPlayer::simon2SetupDecompressFile(const byte *compressedDataPtr, uint32 compressedDataSize, uint32 &extractedDataSize) {
-	byte        compressedLiteralType = 0;
-	byte        compressedDictionaryType = 0;
-	uint16      compressedDictionarySize = 0;
-	const byte *readDataPtr = compressedDataPtr;
-	const byte *readDataEndPtr = compressedDataPtr + compressedDataSize;
-	uint32      readBytesLeft = compressedDataSize;
-
-	// check if there are at least 3 bytes of compressed data
-	if (readBytesLeft < 3)
-		error("MidiPlayer: setup.shr compressed file data not enough bytes");
-
-	compressedLiteralType = readDataPtr[0];
-	compressedDictionaryType = readDataPtr[1];
-	readDataPtr += 2;
-	readBytesLeft -= 2;
-
-	if (compressedLiteralType != 0)
-		error("MidiPlayer: setup.shr: unsupported variable length literals");
-
-	switch(compressedDictionaryType) {
-	case 4:
-		compressedDictionarySize = 1024;
-		break;
-	case 5:
-		compressedDictionarySize = 2048;
-		break;
-	case 6:
-		compressedDictionarySize = 4096;
-		break;
-	default:
-		error("MidiPlayer: setup.shr: invalid dictionary size");
-		break;
-	}
-
-	byte   dataBitsLeft = 8;
-
-	byte   tokenType = 0;
-	byte   tokenLiteral = 0;
-	byte   tokenLowOrderBits = 0;
-	uint16 tokenLength = 0;
-	uint16 tokenOffset = 0;
-	byte   dictionary[MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE];
-	uint16 dictionaryPos = 0;
-
-	byte  *outputDataPtr = nullptr;
-	byte  *outputPtr = nullptr;
-	uint32 outputSize = 0;
-
-	// First calculate the size of the uncompressed data
-	do {
-		tokenType = simon2SetupGetBits(1, readDataPtr, readDataEndPtr, dataBitsLeft);
-		if (!tokenType) {
-			// literal
-			tokenLiteral = simon2SetupGetBits(8, readDataPtr, readDataEndPtr, dataBitsLeft);
-			outputSize++;
-		} else {
-			// length+offset
-			tokenLength = simon2SetupGetLength(readDataPtr, readDataEndPtr, dataBitsLeft);
-			if (tokenLength == 519)
-				break; // end of data
-
-			tokenLowOrderBits = (tokenLength == 2) ? 2 : compressedDictionaryType;
-			tokenOffset = simon2SetupGetOffset(tokenLowOrderBits, readDataPtr, readDataEndPtr, dataBitsLeft);
-			outputSize += tokenLength;
-		}
-	} while (1);
-
-	// allocate output buffer
-	outputDataPtr = new byte[outputSize];
-	outputPtr = outputDataPtr;
-
-	// reset everything
-	dataBitsLeft = 8;
-	readDataPtr = compressedDataPtr + 2;
-	dictionaryPos = 0;
-
-	do {
-		tokenType = simon2SetupGetBits(1, readDataPtr, readDataEndPtr, dataBitsLeft);
-		if (!tokenType) {
-			// literal
-			tokenLiteral = simon2SetupGetBits(8, readDataPtr, readDataEndPtr, dataBitsLeft);
-
-			// write literal to output buffer
-			*outputPtr = tokenLiteral;
-			outputPtr++;
-
-			dictionary[dictionaryPos] = tokenLiteral;
-			dictionaryPos++;
-			if (dictionaryPos >= compressedDictionarySize)
-				dictionaryPos = 0;
-
-		} else {
-			// length+offset
-			tokenLength = simon2SetupGetLength(readDataPtr, readDataEndPtr, dataBitsLeft);
-			if (tokenLength == 519)
-				break; // end of data
-
-			tokenLowOrderBits = (tokenLength == 2) ? 2 : compressedDictionaryType;
-			tokenOffset = simon2SetupGetOffset(tokenLowOrderBits, readDataPtr, readDataEndPtr, dataBitsLeft);
-
-			uint16 dictionaryBaseIndex = (dictionaryPos - 1 - tokenOffset) & (compressedDictionarySize - 1);
-			uint16 dictionaryIndex = dictionaryBaseIndex;
-			uint16 dictionaryNextIndex = dictionaryPos;
-			uint16 copyBytesLeft = tokenLength;
-
-			while (copyBytesLeft) {
-				// write byte from dictionary
-				*outputPtr = dictionary[dictionaryIndex];
-				outputPtr++;
-
-				dictionary[dictionaryNextIndex] = dictionary[dictionaryIndex];
-				dictionaryNextIndex++; dictionaryIndex++;
-
-				if (dictionaryIndex >= dictionaryPos)
-					dictionaryIndex = dictionaryBaseIndex;
-				if (dictionaryNextIndex >= compressedDictionarySize)
-					dictionaryNextIndex = 0;
-
-				copyBytesLeft--;
-			}
-			dictionaryPos = dictionaryNextIndex;
-		}
-	} while (1);
-
-	extractedDataSize = outputSize;
-	return outputDataPtr;
-}
-
 } // End of namespace AGOS
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 5e4a2bc..fff87e6 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -130,12 +130,6 @@ private:
 
 private:
 	const byte *simon2SetupExtractFile(const Common::String &requestedFileName, uint32 &extractedDataSize);
-
-	inline uint16 simon2SetupGetBits(byte bitCount, const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft);
-	inline uint16 simon2SetupGetLength(const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft);
-	inline uint16 simon2SetupGetOffset(byte lowOrderBits, const byte *&dataPtr, const byte *dataEndPtr, byte &dataBitsLeft);
-	inline uint16 simon2SetupReverseBits(uint16 bits, byte bitCount);
-	const byte *simon2SetupDecompressFile(const byte *compressedDataPtr, uint32 compressedDataSize, uint32 &extractedDataSize);
 };
 
 } // End of namespace AGOS






More information about the Scummvm-git-logs mailing list