diff options
author | Paul Gilbert | 2015-10-12 15:18:03 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-10-12 15:18:03 -0400 |
commit | b0016071ecf3f5ffbc6f1619af610ab648bbba3a (patch) | |
tree | f00f6b17bfd3475200e454cdfc09eba94d764f01 /common | |
parent | 652a6623156b6c6bba8ca49e038945fd0c2b7780 (diff) | |
parent | fbcf667b6a57593a2b85622ad1e1380c8aef7210 (diff) | |
download | scummvm-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.cpp | 221 | ||||
-rw-r--r-- | common/dcl.h | 17 | ||||
-rw-r--r-- | common/endian.h | 219 | ||||
-rw-r--r-- | common/fft.cpp | 8 | ||||
-rw-r--r-- | common/fft.h | 2 | ||||
-rw-r--r-- | common/scummsys.h | 2 | ||||
-rw-r--r-- | common/stream.h | 96 |
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 }; /** |