Mame has macros (at least it did have.. also this is off the top of my head so actual names will be different) along the lines of emulation_be_read_16 and emulation_le_read_16 for when an emulated game has a big or little endian CPU and needs to read memory values from the host machine.
So on a big endian cpu such as a power pc this gets defined as :
#define emulation_be_read_16(x) return ram[x];
but on an intel this would be defined as:
#define emulation_be_read_16(x) return ram[x]>>8|| ram[x]
and the other way around if it was emulation_le_read_16
(acutally thinking about it that might not be the right way around)
So looking at the xbox port (with the xbox specific parts removed we have something like this):
#ifdef LSB_FIRST // just so this burn lib is still compilable under windows, etc
#define swapByte(i) (i)
#define swapWord(i) (i)
#define swapLong(i) (i)
#define swapLongLong(x) (x)
#else
#define swapByte(i)(i^1) // might be needed for addresses (e.g. see some of the drivers that ^1 the address on reads)
#define swapWord(i)((((i) & 0xff) << 8) | (((i) & 0xff00) >> 8))
#define swapLong(i) _byteswap_ulong(i) // swap intrinsics are faster on Xbox 360
#define swapLong(i) ((((i) & 0xFF000000) >> 24) | \
(((i) & 0x00FF0000) >> 8) | \
(((i) & 0x0000FF00) << 8) | \
(((i) & 0x000000FF) << 24) )
static inline uint64_t _byteswap_uint64(uint64_t x)
{
union {
uint64_t ll;
struct {
uint32_t l,h;
} l;
} r;
r.l.l = swapLong (x);
r.l.h = swapLong (x>>32);
return r.ll;
}
#endif
typedef union {
#ifdef LSB_FIRST
struct { uint8_t l,h,h2,h3; } b;
struct { uint16_t l,h; } w;
#else
struct { uint8_t h3,h2,h,l; } b;
struct { uint16_t h,l; } w;
#endif
uint32_t d;
} PAIR;
Then we can just put all the word reads through the #defined macros (see the code for fbanext to see some examples)
Also its worth noting the union definition changes on BE vs LE platforms. That's important for the CPU cores.