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/endian.h | |
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/endian.h')
-rw-r--r-- | common/endian.h | 302 |
1 files changed, 212 insertions, 90 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 |