aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorvanfanel2015-11-11 17:56:12 +0100
committervanfanel2015-11-11 17:56:12 +0100
commit99739a13fe844c807d3cdd87e67e207e888fd48a (patch)
tree6afbf4763326277efbf528f0bb9e587bf7a01788 /common
parent37e157a11c3fc731dfdcf6ec6b6a5a448550219b (diff)
parent7e44493fe8877a3c6a65f83b9ed84a5f59169005 (diff)
downloadscummvm-rg350-99739a13fe844c807d3cdd87e67e207e888fd48a.tar.gz
scummvm-rg350-99739a13fe844c807d3cdd87e67e207e888fd48a.tar.bz2
scummvm-rg350-99739a13fe844c807d3cdd87e67e207e888fd48a.zip
Merge branch 'master' into dispmanx
Diffstat (limited to 'common')
-rw-r--r--common/algorithm.h6
-rw-r--r--common/dcl.cpp221
-rw-r--r--common/dcl.h17
-rw-r--r--common/endian.h8
-rw-r--r--common/fft.cpp8
-rw-r--r--common/fft.h2
-rw-r--r--common/scummsys.h2
-rw-r--r--common/xmlparser.cpp48
8 files changed, 213 insertions, 99 deletions
diff --git a/common/algorithm.h b/common/algorithm.h
index 6453073ae5..cbd6eae708 100644
--- a/common/algorithm.h
+++ b/common/algorithm.h
@@ -177,7 +177,8 @@ T sortChoosePivot(T first, T last) {
template<typename T, class StrictWeakOrdering>
T sortPartition(T first, T last, T pivot, StrictWeakOrdering &comp) {
--last;
- SWAP(*pivot, *last);
+ if (pivot != last)
+ SWAP(*pivot, *last);
T sorted;
for (sorted = first; first != last; ++first) {
@@ -188,7 +189,8 @@ T sortPartition(T first, T last, T pivot, StrictWeakOrdering &comp) {
}
}
- SWAP(*last, *sorted);
+ if (last != sorted)
+ SWAP(*last, *sorted);
return sorted;
}
diff --git a/common/dcl.cpp b/common/dcl.cpp
index 2f4cdeda6b..5993c218cb 100644
--- a/common/dcl.cpp
+++ b/common/dcl.cpp
@@ -30,17 +30,15 @@ namespace Common {
class DecompressorDCL {
public:
- bool unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked);
+ bool unpack(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize);
protected:
/**
* Initialize decompressor.
- * @param src source stream to read from
- * @param dest destination stream to write to
- * @param nPacked size of packed data
- * @param nUnpacked size of unpacked data
+ * @param sourceStream source stream to read from
+ * @param targetStream target memory stream to write to
*/
- void init(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked);
+ void init(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize);
/**
* Get a number of bits from _src stream, starting with the least
@@ -66,36 +64,38 @@ protected:
int huffman_lookup(const int *tree);
- uint32 _dwBits; ///< bits buffer
- byte _nBits; ///< number of unread bits in _dwBits
- uint32 _szPacked; ///< size of the compressed data
- uint32 _szUnpacked; ///< size of the decompressed data
- uint32 _dwRead; ///< number of bytes read from _src
- uint32 _dwWrote; ///< number of bytes written to _dest
- ReadStream *_src;
- byte *_dest;
+ uint32 _dwBits; ///< bits buffer
+ byte _nBits; ///< number of unread bits in _dwBits
+ uint32 _sourceSize; ///< size of the source stream
+ uint32 _targetSize; ///< size of the target stream (if fixed)
+ bool _targetFixedSize; ///< if target stream is fixed size or dynamic size
+ uint32 _bytesRead; ///< number of bytes read from _sourceStream
+ uint32 _bytesWritten; ///< number of bytes written to _targetStream
+ SeekableReadStream *_sourceStream;
+ WriteStream *_targetStream;
};
-void DecompressorDCL::init(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
- _src = src;
- _dest = dest;
- _szPacked = nPacked;
- _szUnpacked = nUnpacked;
+void DecompressorDCL::init(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize) {
+ _sourceStream = sourceStream;
+ _targetStream = targetStream;
+ _sourceSize = sourceStream->size();
+ _targetSize = targetSize;
+ _targetFixedSize = targetFixedSize;
_nBits = 0;
- _dwRead = _dwWrote = 0;
+ _bytesRead = _bytesWritten = 0;
_dwBits = 0;
}
void DecompressorDCL::fetchBitsLSB() {
while (_nBits <= 24) {
- _dwBits |= ((uint32)_src->readByte()) << _nBits;
+ _dwBits |= ((uint32)_sourceStream->readByte()) << _nBits;
_nBits += 8;
- _dwRead++;
+ _bytesRead++;
}
}
uint32 DecompressorDCL::getBitsLSB(int n) {
- // fetching more data to buffer if needed
+ // Fetching more data to buffer if needed
if (_nBits < n)
fetchBitsLSB();
uint32 ret = (_dwBits & ~((~0) << n));
@@ -109,7 +109,8 @@ byte DecompressorDCL::getByteLSB() {
}
void DecompressorDCL::putByte(byte b) {
- _dest[_dwWrote++] = b;
+ _targetStream->writeByte(b);
+ _bytesWritten++;
}
#define HUFFMAN_LEAF 0x40000000
@@ -331,97 +332,189 @@ int DecompressorDCL::huffman_lookup(const int *tree) {
#define DCL_BINARY_MODE 0
#define DCL_ASCII_MODE 1
-bool DecompressorDCL::unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
- init(src, dest, nPacked, nUnpacked);
+#define MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE 4096
+bool DecompressorDCL::unpack(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize) {
+ byte dictionary[MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE];
+ uint16 dictionaryPos = 0;
+ uint16 dictionarySize = 0;
+ uint16 dictionaryMask = 0;
int value;
- uint32 val_distance, val_length;
+ uint16 tokenOffset = 0;
+ uint16 tokenLength = 0;
- int mode = getByteLSB();
- int length_param = getByteLSB();
+ init(sourceStream, targetStream, targetSize, targetFixedSize);
+
+ byte mode = getByteLSB();
+ byte dictionaryType = getByteLSB();
if (mode != DCL_BINARY_MODE && mode != DCL_ASCII_MODE) {
warning("DCL-INFLATE: Error: Encountered mode %02x, expected 00 or 01", mode);
return false;
}
- if (length_param < 3 || length_param > 6)
- warning("Unexpected length_param value %d (expected in [3,6])", length_param);
+ // TODO: original code supported 3 as well???
+ // Was this an accident or on purpose? And the original code did just give out a warning
+ // and didn't error out at all
+ switch (dictionaryType) {
+ case 4:
+ dictionarySize = 1024;
+ break;
+ case 5:
+ dictionarySize = 2048;
+ break;
+ case 6:
+ dictionarySize = 4096;
+ break;
+ default:
+ warning("DCL-INFLATE: Error: unsupported dictionary type %02x", dictionaryType);
+ return false;
+ }
+ dictionaryMask = dictionarySize - 1;
- while (_dwWrote < _szUnpacked) {
+ while ((!targetFixedSize) || (_bytesWritten < _targetSize)) {
if (getBitsLSB(1)) { // (length,distance) pair
value = huffman_lookup(length_tree);
if (value < 8)
- val_length = value + 2;
+ tokenLength = value + 2;
else
- val_length = 8 + (1 << (value - 7)) + getBitsLSB(value - 7);
+ tokenLength = 8 + (1 << (value - 7)) + getBitsLSB(value - 7);
+
+ if (tokenLength == 519)
+ break; // End of stream signal
debug(8, " | ");
value = huffman_lookup(distance_tree);
- if (val_length == 2)
- val_distance = (value << 2) | getBitsLSB(2);
+ if (tokenLength == 2)
+ tokenOffset = (value << 2) | getBitsLSB(2);
else
- val_distance = (value << length_param) | getBitsLSB(length_param);
- val_distance ++;
+ tokenOffset = (value << dictionaryType) | getBitsLSB(dictionaryType);
+ tokenOffset++;
- debug(8, "\nCOPY(%d from %d)\n", val_length, val_distance);
+ debug(8, "\nCOPY(%d from %d)\n", tokenLength, tokenOffset);
- if (val_length + _dwWrote > _szUnpacked) {
- warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes (declared unpacked size is %d bytes, current is %d + %d bytes)",
- val_length, _szUnpacked, _dwWrote, val_length);
- return false;
+ if (_targetFixedSize) {
+ if (tokenLength + _bytesWritten > _targetSize) {
+ warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes (declared unpacked size is %d bytes, current is %d + %d bytes)",
+ tokenLength, _targetSize, _bytesWritten, tokenLength);
+ return false;
+ }
}
- if (_dwWrote < val_distance) {
+ if (_bytesWritten < tokenOffset) {
warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream (declared unpacked size is %d bytes, current is %d bytes)",
- _szUnpacked, _dwWrote);
+ _targetSize, _bytesWritten);
return false;
}
- while (val_length) {
- uint32 copy_length = (val_length > val_distance) ? val_distance : val_length;
- assert(val_distance >= copy_length);
- uint32 pos = _dwWrote - val_distance;
- for (uint32 i = 0; i < copy_length; i++)
- putByte(dest[pos + i]);
+ uint16 dictionaryBaseIndex = (dictionaryPos - tokenOffset) & dictionaryMask;
+ uint16 dictionaryIndex = dictionaryBaseIndex;
+ uint16 dictionaryNextIndex = dictionaryPos;
+
+ while (tokenLength) {
+ // Write byte from dictionary
+ putByte(dictionary[dictionaryIndex]);
+ debug(9, "\33[32;31m%02x\33[37;37m ", dictionary[dictionaryIndex]);
+
+ dictionary[dictionaryNextIndex] = dictionary[dictionaryIndex];
- for (uint32 i = 0; i < copy_length; i++)
- debug(9, "\33[32;31m%02x\33[37;37m ", dest[pos + i]);
- debug(9, "\n");
+ dictionaryNextIndex = (dictionaryNextIndex + 1) & dictionaryMask;
+ dictionaryIndex = (dictionaryIndex + 1) & dictionaryMask;
- val_length -= copy_length;
- val_distance += copy_length;
+ if (dictionaryIndex == dictionaryPos)
+ dictionaryIndex = dictionaryBaseIndex;
+ if (dictionaryNextIndex == dictionarySize)
+ dictionaryNextIndex = 0;
+
+ tokenLength--;
}
+ dictionaryPos = dictionaryNextIndex;
+ debug(9, "\n");
} else { // Copy byte verbatim
value = (mode == DCL_ASCII_MODE) ? huffman_lookup(ascii_tree) : getByteLSB();
putByte(value);
+
+ // Also remember it inside dictionary
+ dictionary[dictionaryPos] = value;
+ dictionaryPos++;
+ if (dictionaryPos >= dictionarySize)
+ dictionaryPos = 0;
+
debug(9, "\33[32;31m%02x \33[37;37m", value);
}
}
- return _dwWrote == _szUnpacked;
+ if (_targetFixedSize) {
+ return _bytesWritten == _targetSize;
+ }
+ return true; // For targets featuring dynamic size we always succeed
}
bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpackedSize) {
+ bool success = false;
+ DecompressorDCL dcl;
+
if (!src || !dest)
return false;
+ byte *sourceBufferPtr = (byte *)malloc(packedSize);
+ if (!sourceBufferPtr)
+ return false;
+
+ // Read source into memory
+ src->read(sourceBufferPtr, packedSize);
+
+ Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::NO);
+ Common::MemoryWriteStream *targetStream = new MemoryWriteStream(dest, unpackedSize);
+
+ success = dcl.unpack(sourceStream, targetStream, unpackedSize, true);
+ delete sourceStream;
+ delete targetStream;
+ return success;
+}
+
+SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream, uint32 packedSize, uint32 unpackedSize) {
+ bool success = false;
+ byte *targetPtr = nullptr;
+ Common::MemoryWriteStream *targetStream;
DecompressorDCL dcl;
- return dcl.unpack(src, dest, packedSize, unpackedSize);
+
+ targetPtr = (byte *)malloc(unpackedSize);
+ if (!targetPtr)
+ return nullptr;
+
+ targetStream = new MemoryWriteStream(targetPtr, unpackedSize);
+
+ success = dcl.unpack(sourceStream, targetStream, unpackedSize, true);
+ delete targetStream;
+
+ if (!success) {
+ free(targetPtr);
+ return nullptr;
+ }
+ return new MemoryReadStream(targetPtr, unpackedSize, DisposeAfterUse::YES);
}
-SeekableReadStream *decompressDCL(ReadStream *src, uint32 packedSize, uint32 unpackedSize) {
- byte *data = (byte *)malloc(unpackedSize);
+// This one figures out the unpacked size by itself
+// Needed for at least Simon 2, because the unpacked size is not stored anywhere
+SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream) {
+ Common::MemoryWriteStreamDynamic *targetStream;
+ DecompressorDCL dcl;
- if (decompressDCL(src, data, packedSize, unpackedSize))
- return new MemoryReadStream(data, unpackedSize, DisposeAfterUse::YES);
+ targetStream = new MemoryWriteStreamDynamic(DisposeAfterUse::NO);
- free(data);
- return 0;
+ if (dcl.unpack(sourceStream, targetStream, 0, false)) {
+ byte *targetPtr = targetStream->getData();
+ uint32 unpackedSize = targetStream->size();
+ delete targetStream;
+ return new MemoryReadStream(targetPtr, unpackedSize, DisposeAfterUse::YES);
+ }
+ delete targetStream;
+ return nullptr;
}
} // End of namespace Common
diff --git a/common/dcl.h b/common/dcl.h
index 0e96f74c07..f90bc23c8d 100644
--- a/common/dcl.h
+++ b/common/dcl.h
@@ -22,7 +22,8 @@
/**
* @file
- * PKWARE DCL ("explode") decompressor used in engines:
+ * PKWARE DCL ("explode") ("PKWARE data compression library") decompressor used in engines:
+ * - agos (exclusively for Simon 2 setup.shr file)
* - mohawk
* - sci
*/
@@ -38,16 +39,22 @@ class ReadStream;
class SeekableReadStream;
/**
- * Try to decompress a PKWARE DCL compressed stream. Returns true if
+ * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns true if
* successful.
*/
-bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpackedSize);
+bool decompressDCL(ReadStream *sourceStream, byte *dest, uint32 packedSize, uint32 unpackedSize);
/**
- * Try to decompress a PKWARE DCL compressed stream. Returns a valid pointer
+ * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns a valid pointer
* if successful and 0 otherwise.
*/
-SeekableReadStream *decompressDCL(ReadStream *src, uint32 packedSize, uint32 unpackedSize);
+SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream, uint32 packedSize, uint32 unpackedSize);
+
+/**
+ * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns a valid pointer
+ * if successful and 0 otherwise. This method is meant for cases, where the unpacked size is not known.
+ */
+SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream);
} // End of namespace Common
diff --git a/common/endian.h b/common/endian.h
index 0c6b3db621..7278265961 100644
--- a/common/endian.h
+++ b/common/endian.h
@@ -322,7 +322,7 @@
#ifdef HAVE_INT64
inline uint64 READ_UINT64(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
- return (b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]);
+ return ((uint64)b[7] << 56) | ((uint64)b[6] << 48) | ((uint64)b[5] << 40) | ((uint64)b[4] << 32) | ((uint64)b[3] << 24) | ((uint64)b[2] << 16) | ((uint64)b[1] << 8) | ((uint64)b[0]);
}
inline void WRITE_UINT64(void *ptr, uint64 value) {
uint8 *b = (uint8 *)ptr;
@@ -362,7 +362,7 @@
#ifdef HAVE_INT64
inline uint64 READ_UINT64(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
- return (b[0] << 56) | (b[1] << 48) | (b[2] << 40) | (b[3] << 32) | (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7]);
+ return ((uint64)b[0] << 56) | ((uint64)b[1] << 48) | ((uint64)b[2] << 40) | ((uint64)b[3] << 32) | ((uint64)b[4] << 24) | ((uint64)b[5] << 16) | ((uint64)b[6] << 8) | ((uint64)b[7]);
}
inline void WRITE_UINT64(void *ptr, uint64 value) {
uint8 *b = (uint8 *)ptr;
@@ -446,7 +446,7 @@
#ifdef HAVE_INT64
inline uint64 READ_BE_UINT64(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
- return (b[0] << 56) | (b[1] << 48) | (b[2] << 40) | (b[3] << 32) | (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7]);
+ return ((uint64)b[0] << 56) | ((uint64)b[1] << 48) | ((uint64)b[2] << 40) | ((uint64)b[3] << 32) | ((uint64)b[4] << 24) | ((uint64)b[5] << 16) | ((uint64)b[6] << 8) | ((uint64)b[7]);
}
inline void WRITE_BE_UINT64(void *ptr, uint64 value) {
uint8 *b = (uint8 *)ptr;
@@ -550,7 +550,7 @@
#ifdef HAVE_INT64
inline uint64 READ_LE_UINT64(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
- return (b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]);
+ return ((uint64)b[7] << 56) | ((uint64)b[6] << 48) | ((uint64)b[5] << 40) | ((uint64)b[4] << 32) | ((uint64)b[3] << 24) | ((uint64)b[2] << 16) | ((uint64)b[1] << 8) | ((uint64)b[0]);
}
inline void WRITE_LE_UINT64(void *ptr, uint64 value) {
uint8 *b = (uint8 *)ptr;
diff --git a/common/fft.cpp b/common/fft.cpp
index ac7386083f..27a04abb6a 100644
--- a/common/fft.cpp
+++ b/common/fft.cpp
@@ -56,11 +56,19 @@ FFT::FFT(int bits, int inverse) : _bits(bits), _inverse(inverse) {
}
FFT::~FFT() {
+ for (int i = 0; i < ARRAYSIZE(_cosTables); i++) {
+ delete _cosTables[i];
+ }
+
delete[] _revTab;
delete[] _expTab;
delete[] _tmpBuf;
}
+const uint16 *FFT::getRevTab() const {
+ return _revTab;
+}
+
void FFT::permute(Complex *z) {
int np = 1 << _bits;
diff --git a/common/fft.h b/common/fft.h
index 6eb72c3f84..ed66d32b71 100644
--- a/common/fft.h
+++ b/common/fft.h
@@ -47,6 +47,8 @@ public:
FFT(int bits, int inverse);
~FFT();
+ const uint16 *getRevTab() const;
+
/** Do the permutation needed BEFORE calling calc(). */
void permute(Complex *z);
diff --git a/common/scummsys.h b/common/scummsys.h
index 0c4687e03e..b8cf7678a4 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -46,7 +46,7 @@
#if defined(WIN32)
- #ifdef _MSC_VER
+ #if defined(_MSC_VER) && _MSC_VER <= 1800
// FIXME: The placement of the workaround functions for MSVC below
// require us to include stdio.h and stdarg.h for MSVC here. This
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 67a3d36cec..da4f577e3c 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -97,36 +97,38 @@ bool XMLParser::parserError(const String &errStr) {
assert(_stream->pos() == startPosition);
currentPosition = startPosition;
- int keyOpening = 0;
- int keyClosing = 0;
-
- while (currentPosition-- && keyOpening == 0) {
- _stream->seek(-2, SEEK_CUR);
- c = _stream->readByte();
+ Common::String errorMessage = Common::String::format("\n File <%s>, line %d:\n", _fileName.c_str(), lineCount);
- if (c == '<')
- keyOpening = currentPosition - 1;
- else if (c == '>')
- keyClosing = currentPosition;
- }
+ if (startPosition > 1) {
+ int keyOpening = 0;
+ int keyClosing = 0;
- _stream->seek(startPosition, SEEK_SET);
- currentPosition = startPosition;
- while (keyClosing == 0 && c && currentPosition++) {
- c = _stream->readByte();
+ while (currentPosition-- && keyOpening == 0) {
+ _stream->seek(-2, SEEK_CUR);
+ c = _stream->readByte();
- if (c == '>')
- keyClosing = currentPosition;
- }
+ if (c == '<')
+ keyOpening = currentPosition - 1;
+ else if (c == '>')
+ keyClosing = currentPosition;
+ }
- Common::String errorMessage = Common::String::format("\n File <%s>, line %d:\n", _fileName.c_str(), lineCount);
+ _stream->seek(startPosition, SEEK_SET);
+ currentPosition = startPosition;
+ while (keyClosing == 0 && c && currentPosition++) {
+ c = _stream->readByte();
- currentPosition = (keyClosing - keyOpening);
- _stream->seek(keyOpening, SEEK_SET);
+ if (c == '>')
+ keyClosing = currentPosition;
+ }
- while (currentPosition--)
- errorMessage += (char)_stream->readByte();
+ currentPosition = (keyClosing - keyOpening);
+ _stream->seek(keyOpening, SEEK_SET);
+ while (currentPosition--)
+ errorMessage += (char)_stream->readByte();
+ }
+
errorMessage += "\n\nParser error: ";
errorMessage += errStr;
errorMessage += "\n\n";