aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorPaul Gilbert2015-10-12 15:18:03 -0400
committerPaul Gilbert2015-10-12 15:18:03 -0400
commitb0016071ecf3f5ffbc6f1619af610ab648bbba3a (patch)
treef00f6b17bfd3475200e454cdfc09eba94d764f01 /common
parent652a6623156b6c6bba8ca49e038945fd0c2b7780 (diff)
parentfbcf667b6a57593a2b85622ad1e1380c8aef7210 (diff)
downloadscummvm-rg350-b0016071ecf3f5ffbc6f1619af610ab648bbba3a.tar.gz
scummvm-rg350-b0016071ecf3f5ffbc6f1619af610ab648bbba3a.tar.bz2
scummvm-rg350-b0016071ecf3f5ffbc6f1619af610ab648bbba3a.zip
Merge branch 'msvc_2015' into xeen
Diffstat (limited to 'common')
-rw-r--r--common/dcl.cpp221
-rw-r--r--common/dcl.h17
-rw-r--r--common/endian.h219
-rw-r--r--common/fft.cpp8
-rw-r--r--common/fft.h2
-rw-r--r--common/scummsys.h2
-rw-r--r--common/stream.h96
7 files changed, 486 insertions, 79 deletions
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 6d6563f802..7278265961 100644
--- a/common/endian.h
+++ b/common/endian.h
@@ -49,6 +49,18 @@
# error No endianness defined
#endif
+#ifdef HAVE_INT64
+#define SWAP_CONSTANT_64(a) \
+ ((uint64)((((a) >> 56) & 0x000000FF) | \
+ (((a) >> 40) & 0x0000FF00) | \
+ (((a) >> 24) & 0x00FF0000) | \
+ (((a) >> 8) & 0xFF000000) | \
+ (((a) & 0xFF000000) << 8) | \
+ (((a) & 0x00FF0000) << 24) | \
+ (((a) & 0x0000FF00) << 40) | \
+ (((a) & 0x000000FF) << 56) ))
+#endif
+
#define SWAP_CONSTANT_32(a) \
((uint32)((((a) >> 24) & 0x00FF) | \
(((a) >> 8) & 0xFF00) | \
@@ -59,6 +71,36 @@
((uint16)((((a) >> 8) & 0x00FF) | \
(((a) << 8) & 0xFF00) ))
+
+
+/**
+ * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE
+ * and vice versa.
+ */
+
+// compilerspecific variants come first, fallback last
+
+// Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does)
+#if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2))
+
+ FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) {
+ if (__builtin_constant_p(a)) {
+ return SWAP_CONSTANT_16(a);
+ } else {
+ uint16 result;
+ __asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a));
+ return result;
+ }
+ }
+#else
+
+ inline uint16 SWAP_BYTES_16(const uint16 a) {
+ return (a >> 8) | (a << 8);
+ }
+#endif
+
+
+
/**
* Swap the bytes in a 32 bit word in order to convert LE encoded data to BE
* and vice versa.
@@ -108,32 +150,60 @@
}
#endif
+#ifdef HAVE_INT64
/**
- * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE
+ * Swap the bytes in a 64 bit word in order to convert LE encoded data to BE
* and vice versa.
*/
-// compilerspecific variants come first, fallback last
+// machine/compiler-specific variants come first, fallback last
// Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does)
+//
#if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2))
- FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) {
+ FORCEINLINE uint64 SWAP_BYTES_64(const uint64 a) {
if (__builtin_constant_p(a)) {
- return SWAP_CONSTANT_16(a);
+ return SWAP_CONSTANT_64(a);
} else {
- uint16 result;
- __asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a));
- return result;
+ uint32 low = (uint32)a, high = (uint32)(a >> 32);
+ low = SWAP_BYTES_32(low);
+ high = SWAP_BYTES_32(high);
+
+ return (((uint64)low) << 32) | high;
}
}
+
+// Test for GCC >= 4.3.0 as this version added the bswap builtin
+#elif GCC_ATLEAST(4, 3)
+
+ FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) {
+ return __builtin_bswap64(a);
+ }
+
+#elif defined(_MSC_VER)
+
+ FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) {
+ return _byteswap_uint64(a);
+ }
+
+// generic fallback
#else
- inline uint16 SWAP_BYTES_16(const uint16 a) {
- return (a >> 8) | (a << 8);
+ inline uint64 SWAP_BYTES_64(uint64 a) {
+ uint32 low = (uint32)a, high = (uint32)(a >> 32);
+ uint16 lowLow = (uint16)low, lowHigh = (uint16)(low >> 16),
+ highLow = (uint16)high, highHigh = (uint16)(high >> 16);
+
+ return ((uint64)(((uint32)(uint16)((lowLow >> 8) | (lowLow << 8)) << 16) |
+ (uint16)((lowHigh >> 8) | (lowHigh << 8))) << 32) |
+ (((uint32)(uint16)((highLow >> 8) | (highLow << 8)) << 16) |
+ (uint16)((highHigh >> 8) | (highHigh << 8)));
}
#endif
+#endif // HAVE_INT64
+
/**
* A wrapper macro used around four character constants, like 'DATA', to
@@ -183,6 +253,18 @@
((Unaligned32 *)ptr)->val = value;
}
+#ifdef HAVE_INT64
+ FORCEINLINE uint64 READ_UINT64(const void *ptr) {
+ struct Unaligned64 { uint64 val; } __attribute__ ((__packed__, __may_alias__));
+ return ((const Unaligned64 *)ptr)->val;
+ }
+
+ FORCEINLINE void WRITE_UINT64(void *ptr, uint64 value) {
+ struct Unaligned64 { uint64 val; } __attribute__((__packed__, __may_alias__));
+ ((Unaligned64 *)ptr)->val = value;
+ }
+#endif
+
#elif !defined(SCUMM_NEED_ALIGNMENT)
FORCEINLINE uint16 READ_UINT16(const void *ptr) {
@@ -201,6 +283,16 @@
*(uint32 *)(ptr) = value;
}
+#ifdef HAVE_INT64
+ FORCEINLINE uint64 READ_UINT64(const void *ptr) {
+ return *(const uint64 *)(ptr);
+ }
+
+ FORCEINLINE void WRITE_UINT64(void *ptr, uint64 value) {
+ *(uint64 *)(ptr) = value;
+ }
+#endif
+
// use software fallback by loading each byte explicitely
#else
@@ -227,6 +319,23 @@
b[2] = (uint8)(value >> 16);
b[3] = (uint8)(value >> 24);
}
+#ifdef HAVE_INT64
+ inline uint64 READ_UINT64(const void *ptr) {
+ const uint8 *b = (const uint8 *)ptr;
+ 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;
+ b[0] = (uint8)(value >> 0);
+ b[1] = (uint8)(value >> 8);
+ b[2] = (uint8)(value >> 16);
+ b[3] = (uint8)(value >> 24);
+ b[4] = (uint8)(value >> 32);
+ b[5] = (uint8)(value >> 40);
+ b[6] = (uint8)(value >> 48);
+ b[7] = (uint8)(value >> 56);
+ }
+#endif
# elif defined(SCUMM_BIG_ENDIAN)
@@ -250,6 +359,23 @@
b[2] = (uint8)(value >> 8);
b[3] = (uint8)(value >> 0);
}
+#ifdef HAVE_INT64
+ inline uint64 READ_UINT64(const void *ptr) {
+ const uint8 *b = (const uint8 *)ptr;
+ 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;
+ b[0] = (uint8)(value >> 56);
+ b[1] = (uint8)(value >> 48);
+ b[2] = (uint8)(value >> 40);
+ b[3] = (uint8)(value >> 32);
+ b[4] = (uint8)(value >> 24);
+ b[5] = (uint8)(value >> 16);
+ b[6] = (uint8)(value >> 8);
+ b[7] = (uint8)(value >> 0);
+ }
+#endif
# endif
@@ -283,6 +409,17 @@
#define CONSTANT_BE_32(a) SWAP_CONSTANT_32(a)
#define CONSTANT_BE_16(a) SWAP_CONSTANT_16(a)
+#ifdef HAVE_INT64
+ #define READ_LE_UINT64(a) READ_UINT64(a)
+ #define WRITE_LE_UINT64(a, v) WRITE_UINT64(a, v)
+ #define FROM_LE_64(a) ((uint64)(a))
+ #define FROM_BE_64(a) SWAP_BYTES_64(a)
+ #define TO_LE_64(a) ((uint64)(a))
+ #define TO_BE_64(a) SWAP_BYTES_64(a)
+ #define CONSTANT_LE_64(a) ((uint64)(a))
+ #define CONSTANT_BE_64(a) SWAP_CONSTANT_64(a)
+#endif
+
// if the unaligned load and the byteswap take alot instructions its better to directly read and invert
# if defined(SCUMM_NEED_ALIGNMENT) && !defined(__mips__)
@@ -306,6 +443,24 @@
b[2] = (uint8)(value >> 8);
b[3] = (uint8)(value >> 0);
}
+#ifdef HAVE_INT64
+ inline uint64 READ_BE_UINT64(const void *ptr) {
+ const uint8 *b = (const uint8 *)ptr;
+ 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;
+ b[0] = (uint8)(value >> 56);
+ b[1] = (uint8)(value >> 48);
+ b[2] = (uint8)(value >> 40);
+ b[3] = (uint8)(value >> 32);
+ b[4] = (uint8)(value >> 24);
+ b[5] = (uint8)(value >> 16);
+ b[6] = (uint8)(value >> 8);
+ b[7] = (uint8)(value >> 0);
+ }
+#endif
+
# else
inline uint16 READ_BE_UINT16(const void *ptr) {
@@ -320,6 +475,14 @@
inline void WRITE_BE_UINT32(void *ptr, uint32 value) {
WRITE_UINT32(ptr, SWAP_BYTES_32(value));
}
+#ifdef HAVE_INT64
+ inline uint64 READ_BE_UINT64(const void *ptr) {
+ return SWAP_BYTES_64(READ_UINT64(ptr));
+ }
+ inline void WRITE_BE_UINT64(void *ptr, uint64 value) {
+ WRITE_UINT64(ptr, SWAP_BYTES_64(value));
+ }
+#endif
# endif // if defined(SCUMM_NEED_ALIGNMENT)
@@ -349,6 +512,17 @@
#define CONSTANT_BE_32(a) ((uint32)(a))
#define CONSTANT_BE_16(a) ((uint16)(a))
+#ifdef HAVE_INT64
+ #define READ_BE_UINT64(a) READ_UINT64(a)
+ #define WRITE_BE_UINT64(a, v) WRITE_UINT64(a, v)
+ #define FROM_LE_64(a) SWAP_BYTES_64(a)
+ #define FROM_BE_64(a) ((uint64)(a))
+ #define TO_LE_64(a) SWAP_BYTES_64(a)
+ #define TO_BE_64(a) ((uint64)(a))
+ #define CONSTANT_LE_64(a) SWAP_CONSTANT_64(a)
+ #define CONSTANT_BE_64(a) ((uint64)(a))
+#endif
+
// if the unaligned load and the byteswap take alot instructions its better to directly read and invert
# if defined(SCUMM_NEED_ALIGNMENT) && !defined(__mips__)
@@ -372,6 +546,25 @@
b[2] = (uint8)(value >> 16);
b[3] = (uint8)(value >> 24);
}
+
+#ifdef HAVE_INT64
+ inline uint64 READ_LE_UINT64(const void *ptr) {
+ const uint8 *b = (const uint8 *)ptr;
+ 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;
+ b[0] = (uint8)(value >> 0);
+ b[1] = (uint8)(value >> 8);
+ b[2] = (uint8)(value >> 16);
+ b[3] = (uint8)(value >> 24);
+ b[4] = (uint8)(value >> 32);
+ b[5] = (uint8)(value >> 40);
+ b[6] = (uint8)(value >> 48);
+ b[7] = (uint8)(value >> 56);
+ }
+#endif
+
# else
inline uint16 READ_LE_UINT16(const void *ptr) {
@@ -386,6 +579,14 @@
inline void WRITE_LE_UINT32(void *ptr, uint32 value) {
WRITE_UINT32(ptr, SWAP_BYTES_32(value));
}
+#ifdef HAVE_INT64
+ inline uint64 READ_LE_UINT64(const void *ptr) {
+ return SWAP_BYTES_64(READ_UINT64(ptr));
+ }
+ inline void WRITE_LE_UINT64(void *ptr, uint64 value) {
+ WRITE_UINT64(ptr, SWAP_BYTES_64(value));
+ }
+#endif
# endif // if defined(SCUMM_NEED_ALIGNMENT)
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/stream.h b/common/stream.h
index 2702068cf3..abe5192b70 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -125,6 +125,13 @@ public:
write(&value, 4);
}
+#ifdef HAVE_INT64
+ void writeUint64LE(uint64 value) {
+ value = TO_LE_64(value);
+ write(&value, 8);
+ }
+#endif
+
void writeUint16BE(uint16 value) {
value = TO_BE_16(value);
write(&value, 2);
@@ -135,6 +142,13 @@ public:
write(&value, 4);
}
+#ifdef HAVE_INT64
+ void writeUint64BE(uint64 value) {
+ value = TO_BE_64(value);
+ write(&value, 8);
+ }
+#endif
+
FORCEINLINE void writeSint16LE(int16 value) {
writeUint16LE((uint16)value);
}
@@ -143,6 +157,12 @@ public:
writeUint32LE((uint32)value);
}
+#ifdef HAVE_INT64
+ FORCEINLINE void writeSint64LE(int64 value) {
+ writeUint64LE((uint64)value);
+ }
+#endif
+
FORCEINLINE void writeSint16BE(int16 value) {
writeUint16BE((uint16)value);
}
@@ -151,6 +171,12 @@ public:
writeUint32BE((uint32)value);
}
+#ifdef HAVE_INT64
+ FORCEINLINE void writeSint64BE(int64 value) {
+ writeUint64BE((uint64)value);
+ }
+#endif
+
/**
* Write the given string to the stream.
* This writes str.size() characters, but no terminating zero byte.
@@ -241,6 +267,21 @@ public:
return FROM_LE_32(val);
}
+#ifdef HAVE_INT64
+ /**
+ * Read an unsigned 64-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling err() and eos() ).
+ */
+ uint64 readUint64LE() {
+ uint64 val;
+ read(&val, 8);
+ return FROM_LE_64(val);
+ }
+#endif
+
/**
* Read an unsigned 16-bit word stored in big endian (MSB first) order
* from the stream and return it.
@@ -267,6 +308,21 @@ public:
return FROM_BE_32(val);
}
+#ifdef HAVE_INT64
+ /**
+ * Read an unsigned 64-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling err() and eos() ).
+ */
+ uint64 readUint64BE() {
+ uint64 val;
+ read(&val, 8);
+ return FROM_BE_64(val);
+ }
+#endif
+
/**
* Read a signed 16-bit word stored in little endian (LSB first) order
* from the stream and return it.
@@ -289,6 +345,19 @@ public:
return (int32)readUint32LE();
}
+#ifdef HAVE_INT64
+ /**
+ * Read a signed 64-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling err() and eos() ).
+ */
+ FORCEINLINE int64 readSint64LE() {
+ return (int64)readUint64LE();
+ }
+#endif
+
/**
* Read a signed 16-bit word stored in big endian (MSB first) order
* from the stream and return it.
@@ -311,6 +380,19 @@ public:
return (int32)readUint32BE();
}
+#ifdef HAVE_INT64
+ /**
+ * Read a signed 64-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling err() and eos() ).
+ */
+ FORCEINLINE int64 readSint64BE() {
+ return (int64)readUint64BE();
+ }
+#endif
+
/**
* Read the specified amount of data into a malloc'ed buffer
* which then is wrapped into a MemoryReadStream.
@@ -435,6 +517,14 @@ public:
return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
}
+#ifdef HAVE_INT64
+ uint64 readUint64() {
+ uint64 val;
+ read(&val, 8);
+ return (_bigEndian) ? TO_BE_64(val) : TO_LE_64(val);
+ }
+#endif
+
FORCEINLINE int16 readSint16() {
return (int16)readUint16();
}
@@ -442,6 +532,12 @@ public:
FORCEINLINE int32 readSint32() {
return (int32)readUint32();
}
+
+#ifdef HAVE_INT64
+ FORCEINLINE int64 readSint64() {
+ return (int64)readUint64();
+ }
+#endif
};
/**