| ||
Before exploring various methods of converting data, let us first examine the method most often needed: The endian conversion! The handling of big- and little-endian was initially discussed in Chapter 3 but let us re-examine.
If your application is designed to be multiplatform , then having multiple endian declarations might make your life easier. Having Endian16(), Endian32(), Endian64(), and Endian128() conversion functions are one thing, but having extra declarations such as BigEndian64() versus LittleEndian64() that map to either a stub macro or an Endian64 converter will save you some time. The data file being read will be in a known endian orientation. The target platform knows what it needs, so if the big-endian label is used if the source data is known to be big-endian and vice versa for little-endian, then the use of that declaration will resolve any confusion. This will work for any platform!
Source Data | Big-Endian Machine | Little-Endian Machine |
---|---|---|
BigEndian() | -stub- | Byte swap |
LittleEndian() | Byte swap | -stub- |
These endian wrappers are shown only for little-endian as this book is mostly meant for little-endian. If you are truly interested, my Vector Game Math Processors book contains both sets.
Hint | Use descriptive big- versus little-endian macros to simplify endian conversion. |
#define VMP_LITTLE_ENDIAN
This is oversimplifying it and there are better methods such as the BSWAP instruction on the 80x86, but this is a generic method for cross-platform portability.
int32 VMP_ENDIAN32(int32 val) { uint8 buf[4]; buf[ 0 ]=*(((uint8*)&val)+3); // = [3] buf[ 1 ]=*(((uint8*)&val)+2); // = [2] buf[ 2 ]=*(((uint8*)&val)+1); // = [1] buf[ 3 ]=*(((uint8*)&val)+0); // = [0] return *(int32*)buf; }
int16 VMP_ENDIAN16(int16 val) { uint8 buf[2]; buf[ 0 ]=*(((uint8*)&val)+1); // = [1] buf[ 1 ]=*(((uint8*)&val)+0); // = [0] return *(int16*)buf; }
The typecasting camouflages it a bit, but it is merely a byte read-write with inverse offsets. I will leave the actual endian implementation up to you! Just remember that it is preferable to have the tools handle your endian conversion so that a game application does not have to. And since tools exercise the same data over and over for the length of a project, you might as well make them as efficient as possible.
For cross-platform compatibility I refer to the following as a little pretzel logic. It looks a little twisted, but if you dig a little deeper it becomes what it is slicker 'n snail snot!
#ifdef VMP_LITTLE_ENDIAN // Little-endian processor // Big-endian data on little-endian processor #define VMP_BIG_ENDIAN32 VMP_ENDIAN32 #define VMP_BIG_ENDIAN16 VMP_ENDIAN16 // Little-endian data on little-endian processor #define VMP_LITTLE_ENDIAN32 // stub #define VMP_LITTLE_ENDIAN16 // stub #endif
Note that same endian to same endian assignment merely stubs out the macro, so no conversion is needed or implemented. One only needs to know what byte order the data is in and what order is needed, and use the appropriate macro. It will then be cross-platform compatible to all other platforms as long as the endian flag is set properly for that platform.
Neat, huh? No extra #ifdef cluttering up the code!
BSWAP destination
Mnemonic
P
PII
K6
3D!
3Mx+
SSE
SSE2
A64
SSE3
E64T
BSWAP
EAN: 2147483647
Pages: 191
If you may any questions please contact us: flylib@qtcs.net