diff options
author | Norbert Lange | 2009-08-24 12:39:03 +0000 |
---|---|---|
committer | Norbert Lange | 2009-08-24 12:39:03 +0000 |
commit | 184aae3c8c863541771fbeb09ce5f1a72ecabb95 (patch) | |
tree | ec822b0d376e9cb7ab3e8f1830cd3b87f5c10d11 /common | |
parent | 40aac5fbf7a2f582ecc38d99c67a52e5fefdff17 (diff) | |
download | scummvm-rg350-184aae3c8c863541771fbeb09ce5f1a72ecabb95.tar.gz scummvm-rg350-184aae3c8c863541771fbeb09ce5f1a72ecabb95.tar.bz2 scummvm-rg350-184aae3c8c863541771fbeb09ce5f1a72ecabb95.zip |
Enable alternative palettse for Amiga Monkey Island - Patch ID: 2819787
use tables for palette colors instead of code with constants
svn-id: r43696
Diffstat (limited to 'common')
-rw-r--r-- | common/endian.h | 302 | ||||
-rw-r--r-- | common/stream.h | 101 |
2 files changed, 268 insertions, 135 deletions
diff --git a/common/endian.h b/common/endian.h index c889371a2f..2e52af139b 100644 --- a/common/endian.h +++ b/common/endian.h @@ -32,23 +32,47 @@ // Endian conversion functions, macros etc., follow from here! // +// Sanity check +#if !defined(SCUMM_LITTLE_ENDIAN) && !defined(SCUMM_BIG_ENDIAN) +# error No endianness defined +#endif + /** * Swap the bytes in a 32 bit word in order to convert LE encoded data to BE * and vice versa. + * compilerspecific variants come first, fallback last */ -FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { - return ((a >> 24) & 0x000000FF) | - ((a >> 8) & 0x0000FF00) | - ((a << 8) & 0x00FF0000) | - ((a << 24) & 0xFF000000); -} + +// Test for GCC >= 4.3.0 as this version added the bswap builtin +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + + FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { + return __builtin_bswap32(a); + } + +// test for MSVC 7 or newer +#elif defined(_MSC_VER) && _MSC_VER >= 1300 + + FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { + return _byteswap_ulong(a); + } + +// generic fallback +#else + + inline uint32 SWAP_BYTES_32(uint32 a) { + const uint16 low = (uint16)a, high = (uint16)(a >> 16); + return ((uint32)(uint16)((low >> 8) | (low << 8)) << 16) + | (uint16)((high >> 8) | (high << 8)); + } +#endif /** * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE * and vice versa. */ -FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) { - return ((a >> 8) & 0x00FF) + ((a << 8) & 0xFF00); +FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) { + return (a >> 8) | (a << 8); } @@ -70,25 +94,123 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) { * For the latter systems we provide the INVERSE_MKID override. */ #if defined(INVERSE_MKID) -#define MKID_BE(a) ((uint32) \ - (((a) >> 24) & 0x000000FF) | \ - (((a) >> 8) & 0x0000FF00) | \ - (((a) << 8) & 0x00FF0000) | \ - (((a) << 24) & 0xFF000000)) +#define MKID_BE(a) ((uint32)( \ + (((a) >> 24) & 0x00FF) | \ + (((a) >> 8) & 0xFF00) | \ + (((a) & 0xFF00) << 8) | \ + (((a) & 0x00FF) << 24) )) #else # define MKID_BE(a) ((uint32)(a)) #endif +// Functions for reading/writing native Integers, +// this transparently handles the need for alignment + +#if !defined(SCUMM_NEED_ALIGNMENT) + + FORCEINLINE uint16 READ_UINT16(const void *ptr) { + return *(const uint16 *)(ptr); + } + + FORCEINLINE uint32 READ_UINT32(const void *ptr) { + return *(const uint32 *)(ptr); + } + + FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { + *(uint16 *)(ptr) = value; + } + + FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) { + *(uint32 *)(ptr) = value; + } + +// test for GCC >= 4.0. these implementations will automatically use CPU-specific +// instructions for unaligned data when they are available (eg. MIPS) +#elif defined(__GNUC__) && (__GNUC__ >= 4) + + FORCEINLINE uint16 READ_UINT16(const void *ptr) { + struct Unaligned16 { uint16 val; } __attribute__ ((__packed__)); + return ((const Unaligned16 *)ptr)->val; + } + + FORCEINLINE uint32 READ_UINT32(const void *ptr) { + struct Unaligned32 { uint32 val; } __attribute__ ((__packed__)); + return ((const Unaligned32 *)ptr)->val; + } + + FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { + struct Unaligned16 { uint16 val; } __attribute__ ((__packed__)); + ((Unaligned16 *)ptr)->val = value; + } + + FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) { + struct Unaligned32 { uint32 val; } __attribute__ ((__packed__)); + ((Unaligned32 *)ptr)->val = value; + } + +// use software fallback by loading each byte explicitely +#else + +# if defined(SCUMM_LITTLE_ENDIAN) + + FORCEINLINE uint16 READ_UINT16(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[1] << 8) | b[0]; + } + inline uint32 READ_UINT32(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]); + } + FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); + } + inline void WRITE_UINT32(void *ptr, uint32 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); + } + +# elif defined(SCUMM_BIG_ENDIAN) + + FORCEINLINE uint16 READ_UINT16(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[0] << 8) | b[1]; + } + inline uint32 READ_UINT32(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); + } + FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 8); + b[1] = (uint8)(value >> 0); + } + inline void WRITE_UINT32(void *ptr, uint32 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 24); + b[1] = (uint8)(value >> 16); + b[2] = (uint8)(value >> 8); + b[3] = (uint8)(value >> 0); + } + +# endif +#endif + +// Map Funtions for reading/writing BE/LE integers depending on native endianess #if defined(SCUMM_LITTLE_ENDIAN) - #define READ_UINT16(a) READ_LE_UINT16(a) - #define READ_UINT32(a) READ_LE_UINT32(a) + #define READ_LE_UINT16(a) READ_UINT16(a) + #define READ_LE_UINT32(a) READ_UINT32(a) - #define WRITE_UINT16(a, v) WRITE_LE_UINT16(a, v) - #define WRITE_UINT32(a, v) WRITE_LE_UINT32(a, v) + #define WRITE_LE_UINT16(a, v) WRITE_UINT16(a, v) + #define WRITE_LE_UINT32(a, v) WRITE_UINT32(a, v) #define FROM_LE_32(a) ((uint32)(a)) #define FROM_LE_16(a) ((uint16)(a)) @@ -102,16 +224,57 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) { #define TO_BE_32(a) SWAP_BYTES_32(a) #define TO_BE_16(a) SWAP_BYTES_16(a) +# if defined(SCUMM_NEED_ALIGNMENT) + + FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[0] << 8) | b[1]; + } + inline uint32 READ_BE_UINT32(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); + } + FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 8); + b[1] = (uint8)(value >> 0); + } + inline void WRITE_BE_UINT32(void *ptr, uint32 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 24); + b[1] = (uint8)(value >> 16); + b[2] = (uint8)(value >> 8); + b[3] = (uint8)(value >> 0); + } +# else + + FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) { + return SWAP_BYTES_16(*(const uint16 *)ptr); + } + FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) { + return SWAP_BYTES_32(*(const uint32 *)ptr); + } + FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) { + *(uint16 *)ptr = SWAP_BYTES_16(value); + } + FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) { + *(uint32 *)ptr = SWAP_BYTES_32(value); + } + +# endif // if defined(SCUMM_NEED_ALIGNMENT) + #elif defined(SCUMM_BIG_ENDIAN) + // I thought this would be compiler-specific and not dependent + // on endianess after the comments above? #define MKID(a) ((uint32)(a)) #define MKID_BE(a) ((uint32)(a)) - #define READ_UINT16(a) READ_BE_UINT16(a) - #define READ_UINT32(a) READ_BE_UINT32(a) + #define READ_BE_UINT16(a) READ_UINT16(a) + #define READ_BE_UINT32(a) READ_UINT32(a) - #define WRITE_UINT16(a, v) WRITE_BE_UINT16(a, v) - #define WRITE_UINT32(a, v) WRITE_BE_UINT32(a, v) + #define WRITE_BE_UINT16(a, v) WRITE_UINT16(a, v) + #define WRITE_BE_UINT32(a, v) WRITE_UINT32(a, v) #define FROM_LE_32(a) SWAP_BYTES_32(a) #define FROM_LE_16(a) SWAP_BYTES_16(a) @@ -125,96 +288,55 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) { #define TO_BE_32(a) ((uint32)(a)) #define TO_BE_16(a) ((uint16)(a)) -#else - - #error No endianness defined - - -#endif - +# if defined(SCUMM_NEED_ALIGNMENT) -#if defined(SCUMM_NEED_ALIGNMENT) || !defined(SCUMM_LITTLE_ENDIAN) FORCEINLINE uint16 READ_LE_UINT16(const void *ptr) { - const byte *b = (const byte *)ptr; - return (b[1] << 8) + b[0]; + const uint8 *b = (const uint8 *)ptr; + return (b[1] << 8) | b[0]; } - FORCEINLINE uint32 READ_LE_UINT32(const void *ptr) { - const byte *b = (const byte *)ptr; - return (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0]); + inline uint32 READ_LE_UINT32(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]); } FORCEINLINE void WRITE_LE_UINT16(void *ptr, uint16 value) { - byte *b = (byte *)ptr; - b[0] = (byte)(value >> 0); - b[1] = (byte)(value >> 8); + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); } - FORCEINLINE void WRITE_LE_UINT32(void *ptr, uint32 value) { - byte *b = (byte *)ptr; - b[0] = (byte)(value >> 0); - b[1] = (byte)(value >> 8); - b[2] = (byte)(value >> 16); - b[3] = (byte)(value >> 24); + inline void WRITE_LE_UINT32(void *ptr, uint32 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); } -#else +# else + FORCEINLINE uint16 READ_LE_UINT16(const void *ptr) { - return *(const uint16 *)(ptr); + return SWAP_BYTES_16(*(const uint16 *)ptr); } FORCEINLINE uint32 READ_LE_UINT32(const void *ptr) { - return *(const uint32 *)(ptr); + return SWAP_BYTES_32(*(const uint32 *)ptr); } FORCEINLINE void WRITE_LE_UINT16(void *ptr, uint16 value) { - *(uint16 *)(ptr) = value; + *(uint16 *)ptr = SWAP_BYTES_16(value); } FORCEINLINE void WRITE_LE_UINT32(void *ptr, uint32 value) { - *(uint32 *)(ptr) = value; + *(uint32 *)ptr = SWAP_BYTES_32(value); } -#endif - + +# endif // if defined(SCUMM_NEED_ALIGNMENT) -#if defined(SCUMM_NEED_ALIGNMENT) || !defined(SCUMM_BIG_ENDIAN) - FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) { - const byte *b = (const byte *)ptr; - return (b[0] << 8) + b[1]; - } - FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) { - const byte *b = (const byte*)ptr; - return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3]); - } - FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) { - byte *b = (byte *)ptr; - b[0] = (byte)(value >> 8); - b[1] = (byte)(value >> 0); - } - FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) { - byte *b = (byte *)ptr; - b[0] = (byte)(value >> 24); - b[1] = (byte)(value >> 16); - b[2] = (byte)(value >> 8); - b[3] = (byte)(value >> 0); - } -#else - FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) { - return *(const uint16 *)(ptr); - } - FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) { - return *(const uint32 *)(ptr); - } - FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) { - *(uint16 *)(ptr) = value; - } - FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) { - *(uint32 *)(ptr) = value; - } -#endif +#endif // if defined(SCUMM_LITTLE_ENDIAN) FORCEINLINE uint32 READ_LE_UINT24(const void *ptr) { - const byte *b = (const byte *)ptr; - return (b[2] << 16) + (b[1] << 8) + (b[0]); + const uint8 *b = (const uint8 *)ptr; + return (b[2] << 16) | (b[1] << 8) | (b[0]); } FORCEINLINE uint32 READ_BE_UINT24(const void *ptr) { - const byte *b = (const byte*)ptr; - return (b[0] << 16) + (b[1] << 8) + (b[2]); + const uint8 *b = (const uint8 *)ptr; + return (b[0] << 16) | (b[1] << 8) | (b[2]); } - #endif diff --git a/common/stream.h b/common/stream.h index 86e8e71134..9475f6fa2d 100644 --- a/common/stream.h +++ b/common/stream.h @@ -27,6 +27,7 @@ #define COMMON_STREAM_H #include "common/scummsys.h" +#include "common/endian.h" namespace Common { @@ -106,38 +107,38 @@ public: } void writeUint16LE(uint16 value) { - writeByte((byte)(value & 0xff)); - writeByte((byte)(value >> 8)); + value = TO_LE_16(value); + write(&value, 2); } void writeUint32LE(uint32 value) { - writeUint16LE((uint16)(value & 0xffff)); - writeUint16LE((uint16)(value >> 16)); + value = TO_LE_32(value); + write(&value, 4); } void writeUint16BE(uint16 value) { - writeByte((byte)(value >> 8)); - writeByte((byte)(value & 0xff)); + value = TO_BE_16(value); + write(&value, 2); } void writeUint32BE(uint32 value) { - writeUint16BE((uint16)(value >> 16)); - writeUint16BE((uint16)(value & 0xffff)); + value = TO_BE_32(value); + write(&value, 4); } - void writeSint16LE(int16 value) { + FORCEINLINE void writeSint16LE(int16 value) { writeUint16LE((uint16)value); } - void writeSint32LE(int32 value) { + FORCEINLINE void writeSint32LE(int32 value) { writeUint32LE((uint32)value); } - void writeSint16BE(int16 value) { + FORCEINLINE void writeSint16BE(int16 value) { writeUint16BE((uint16)value); } - void writeSint32BE(int32 value) { + FORCEINLINE void writeSint32BE(int32 value) { writeUint32BE((uint32)value); } @@ -188,7 +189,7 @@ public: * calling err() and eos() ). */ byte readByte() { - byte b = 0; + byte b = 0; // FIXME: remove initialisation read(&b, 1); return b; } @@ -200,7 +201,7 @@ public: * calling err() and eos() ). */ int8 readSByte() { - int8 b = 0; + int8 b = 0; // FIXME: remove initialisation read(&b, 1); return b; } @@ -213,9 +214,9 @@ public: * calling err() and eos() ). */ uint16 readUint16LE() { - uint16 a = readByte(); - uint16 b = readByte(); - return a | (b << 8); + uint16 val; + read(&val, 2); + return FROM_LE_16(val); } /** @@ -226,9 +227,9 @@ public: * calling err() and eos() ). */ uint32 readUint32LE() { - uint32 a = readUint16LE(); - uint32 b = readUint16LE(); - return (b << 16) | a; + uint32 val; + read(&val, 4); + return FROM_LE_32(val); } /** @@ -239,9 +240,9 @@ public: * calling err() and eos() ). */ uint16 readUint16BE() { - uint16 b = readByte(); - uint16 a = readByte(); - return a | (b << 8); + uint16 val; + read(&val, 2); + return FROM_BE_16(val); } /** @@ -252,9 +253,9 @@ public: * calling err() and eos() ). */ uint32 readUint32BE() { - uint32 b = readUint16BE(); - uint32 a = readUint16BE(); - return (b << 16) | a; + uint32 val; + read(&val, 4); + return FROM_BE_32(val); } /** @@ -264,7 +265,7 @@ public: * if a read error occurred (for which client code can check by * calling err() and eos() ). */ - int16 readSint16LE() { + FORCEINLINE int16 readSint16LE() { return (int16)readUint16LE(); } @@ -275,7 +276,7 @@ public: * if a read error occurred (for which client code can check by * calling err() and eos() ). */ - int32 readSint32LE() { + FORCEINLINE int32 readSint32LE() { return (int32)readUint32LE(); } @@ -286,7 +287,7 @@ public: * if a read error occurred (for which client code can check by * calling err() and eos() ). */ - int16 readSint16BE() { + FORCEINLINE int16 readSint16BE() { return (int16)readUint16BE(); } @@ -297,7 +298,7 @@ public: * if a read error occurred (for which client code can check by * calling err() and eos() ). */ - int32 readSint32BE() { + FORCEINLINE int32 readSint32BE() { return (int32)readUint32BE(); } @@ -460,26 +461,31 @@ public: * @see SubReadStream */ class SeekableSubReadStreamEndian : public SeekableSubReadStream { -public: - bool _bigEndian; +private: + const bool _bigEndian; +public: SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, bool disposeParentStream = false) : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) { } - inline uint16 readUint16() { - return (_bigEndian) ? readUint16BE() : readUint16LE(); + uint16 readUint16() { + uint16 val; + read(&val, 2); + return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val); } - inline uint32 readUint32() { - return (_bigEndian) ? readUint32BE() : readUint32LE(); + uint32 readUint32() { + uint32 val; + read(&val, 4); + return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val); } - inline int16 readSint16() { + FORCEINLINE int16 readSint16() { return (int16)readUint16(); } - inline int32 readSint32() { + FORCEINLINE int32 readSint32() { return (int32)readUint32(); } }; @@ -582,23 +588,28 @@ public: */ class MemoryReadStreamEndian : public Common::MemoryReadStream { private: + const bool _bigEndian; + public: - bool _bigEndian; MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {} - inline uint16 readUint16() { - return (_bigEndian) ? readUint16BE() : readUint16LE(); + uint16 readUint16() { + uint16 val; + read(&val, 2); + return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val); } - inline uint32 readUint32() { - return (_bigEndian) ? readUint32BE() : readUint32LE(); + uint32 readUint32() { + uint32 val; + read(&val, 4); + return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val); } - inline int16 readSint16() { + FORCEINLINE int16 readSint16() { return (int16)readUint16(); } - inline int32 readSint32() { + FORCEINLINE int32 readSint32() { return (int32)readUint32(); } }; |