| 1 | #ifndef SEAD_ENDIAN_H_ |
| 2 | #define SEAD_ENDIAN_H_ |
| 3 | |
| 4 | #include <basis/seadRawPrint.h> |
| 5 | #include <basis/seadTypes.h> |
| 6 | #include <prim/seadBitUtil.h> |
| 7 | |
| 8 | namespace sead |
| 9 | { |
| 10 | class Endian |
| 11 | { |
| 12 | public: |
| 13 | enum Types |
| 14 | { |
| 15 | cBig = 0, |
| 16 | cLittle = 1, |
| 17 | }; |
| 18 | |
| 19 | struct ConvFuncTable |
| 20 | { |
| 21 | typedef u8 (*CONV8FUNC)(u8); |
| 22 | typedef u16 (*CONV16FUNC)(u16); |
| 23 | typedef u32 (*CONV32FUNC)(u32); |
| 24 | typedef u64 (*CONV64FUNC)(u64); |
| 25 | |
| 26 | CONV8FUNC conv8[2]; |
| 27 | CONV16FUNC conv16[2]; |
| 28 | CONV32FUNC conv32[2]; |
| 29 | CONV64FUNC conv64[2]; |
| 30 | }; |
| 31 | |
| 32 | static Types getHostEndian() { return cHostEndian; } |
| 33 | |
| 34 | static Types markToEndian(u16 bom) |
| 35 | { |
| 36 | u8* bom_ = reinterpret_cast<u8*>(&bom); |
| 37 | if (*bom_ == 0xff && *(bom_ + 1) == 0xfe) |
| 38 | return cLittle; |
| 39 | |
| 40 | if (*bom_ == 0xfe && *(bom_ + 1) == 0xff) |
| 41 | return cBig; |
| 42 | |
| 43 | SEAD_ASSERT_MSG(false, "Undefined endian mark(0x%02x 0x%02x)" , bom_[0], bom_[1]); |
| 44 | return cLittle; |
| 45 | } |
| 46 | |
| 47 | static u16 endianToMark(Types endian) { return endian == cBig ? 0xFEFF : 0xFFFE; } |
| 48 | |
| 49 | static u8 swapU8(u8 v) { return cConvFuncTable.conv8[1](v); } |
| 50 | static u16 swapU16(u16 v) { return cConvFuncTable.conv16[1](v); } |
| 51 | static u32 swapU32(u32 v) { return cConvFuncTable.conv32[1](v); } |
| 52 | static u64 swapU64(u64 v) { return cConvFuncTable.conv64[1](v); } |
| 53 | static s8 swapS8(s8 v) { return swapU8(v); } |
| 54 | static s16 swapS16(s16 v) { return swapU16(v); } |
| 55 | static s32 swapS32(s32 v) { return swapU32(v); } |
| 56 | static s64 swapS64(s64 v) { return swapU64(v); } |
| 57 | static f32 swapF32(f32 v) { return BitUtil::bitCast<f32>(value: swapU32(v: BitUtil::bitCast<u32>(value: v))); } |
| 58 | |
| 59 | static u8 convertU8(Types from, Types to, u8 v) { return cConvFuncTable.conv8[from ^ to](v); } |
| 60 | static u16 convertU16(Types from, Types to, u16 v) |
| 61 | { |
| 62 | return cConvFuncTable.conv16[from ^ to](v); |
| 63 | } |
| 64 | static u32 convertU32(Types from, Types to, u32 v) |
| 65 | { |
| 66 | return cConvFuncTable.conv32[from ^ to](v); |
| 67 | } |
| 68 | static u64 convertU64(Types from, Types to, u64 v) |
| 69 | { |
| 70 | return cConvFuncTable.conv64[from ^ to](v); |
| 71 | } |
| 72 | |
| 73 | static s8 convertS8(Types from, Types to, s8 v) { return convertU8(from, to, v); } |
| 74 | static s16 convertS16(Types from, Types to, s16 v) { return convertU16(from, to, v); } |
| 75 | static s32 convertS32(Types from, Types to, s32 v) { return convertU32(from, to, v); } |
| 76 | static s64 convertS64(Types from, Types to, s64 v) { return convertU64(from, to, v); } |
| 77 | static u32 convertF32(Types from, Types to, const void* ptr) |
| 78 | { |
| 79 | return convertU32(from, to, v: *static_cast<const u32*>(ptr)); |
| 80 | } |
| 81 | |
| 82 | static u8 toHostU8(Types from, u8 v) { return convertU8(from, to: cHostEndian, v); } |
| 83 | static u16 toHostU16(Types from, u16 v) { return convertU16(from, to: cHostEndian, v); } |
| 84 | static u32 toHostU32(Types from, u32 v) { return convertU32(from, to: cHostEndian, v); } |
| 85 | static u64 toHostU64(Types from, u64 v) { return convertU64(from, to: cHostEndian, v); } |
| 86 | |
| 87 | static u8 fromHostU8(Types to, u8 v) { return convertU8(from: cHostEndian, to, v); } |
| 88 | static u16 fromHostU16(Types to, u16 v) { return convertU16(from: cHostEndian, to, v); } |
| 89 | static u32 fromHostU32(Types to, u32 v) { return convertU32(from: cHostEndian, to, v); } |
| 90 | static u64 fromHostU64(Types to, u64 v) { return convertU64(from: cHostEndian, to, v); } |
| 91 | |
| 92 | static s8 toHostS8(Types from, s8 v) { return toHostU8(from, v); } |
| 93 | static s16 toHostS16(Types from, s16 v) { return toHostU16(from, v); } |
| 94 | static s32 toHostS32(Types from, s32 v) { return toHostU32(from, v); } |
| 95 | static s64 toHostS64(Types from, s64 v) { return toHostU64(from, v); } |
| 96 | |
| 97 | static s8 fromHostS8(Types to, s8 v) { return fromHostU8(to, v); } |
| 98 | static s16 fromHostS16(Types to, s16 v) { return fromHostU8(to, v); } |
| 99 | static s32 fromHostS32(Types to, s32 v) { return fromHostU8(to, v); } |
| 100 | static s64 fromHostS64(Types to, s64 v) { return fromHostU8(to, v); } |
| 101 | |
| 102 | static f32 toHostF32(Types from, const u32* ptr) |
| 103 | { |
| 104 | return BitUtil::bitCast<f32>(value: convertF32(from, to: cHostEndian, ptr)); |
| 105 | } |
| 106 | static u32 fromHostF32(Types to, const f32* ptr) { return convertF32(from: cHostEndian, to, ptr); } |
| 107 | |
| 108 | private: |
| 109 | static const Types cHostEndian; |
| 110 | static const ConvFuncTable cConvFuncTable; |
| 111 | }; |
| 112 | } // namespace sead |
| 113 | |
| 114 | #endif // SEAD_ENDIAN_H_ |
| 115 | |