Skip to content

Commit c760c60

Browse files
committed
having this seems reasonable
1 parent 5c77245 commit c760c60

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

src/utils/binarytools/BitConverter.h

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <limits>
5+
#include <vector>
6+
#include <cstring>
7+
8+
#ifdef _MSC_VER
9+
#define BSWAP16 _byteswap_ushort
10+
#define BSWAP32 _byteswap_ulong
11+
#define BSWAP64 _byteswap_uint64
12+
#else
13+
#define BSWAP16 __builtin_bswap16
14+
#define BSWAP32 __builtin_bswap32
15+
#define BSWAP64 __builtin_bswap64
16+
#endif
17+
18+
enum class Endianness {
19+
Little = 0,
20+
Big = 1,
21+
22+
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__)
23+
Native = Big,
24+
#else
25+
Native = Little,
26+
#endif
27+
};
28+
29+
class BitConverter {
30+
public:
31+
static inline int8_t ToInt8BE(const uint8_t* data, int32_t offset) {
32+
return (uint8_t)data[offset + 0];
33+
}
34+
35+
static inline int8_t ToInt8BE(const std::vector<uint8_t>& data, int32_t offset) {
36+
return (uint8_t)data[offset + 0];
37+
}
38+
39+
static inline uint8_t ToUInt8BE(const uint8_t* data, int32_t offset) {
40+
return (uint8_t)data[offset + 0];
41+
}
42+
43+
static inline uint8_t ToUInt8BE(const std::vector<uint8_t>& data, int32_t offset) {
44+
return (uint8_t)data[offset + 0];
45+
}
46+
47+
static inline int16_t ToInt16BE(const uint8_t* data, int32_t offset) {
48+
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
49+
}
50+
51+
static inline int16_t ToInt16BE(const std::vector<uint8_t>& data, int32_t offset) {
52+
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
53+
}
54+
55+
static inline uint16_t ToUInt16BE(const uint8_t* data, int32_t offset) {
56+
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
57+
}
58+
59+
static inline uint16_t ToUInt16BE(const std::vector<uint8_t>& data, int32_t offset) {
60+
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
61+
}
62+
63+
static inline int32_t ToInt32BE(const uint8_t* data, int32_t offset) {
64+
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
65+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
66+
}
67+
68+
static inline int32_t ToInt32BE(const std::vector<uint8_t>& data, int32_t offset) {
69+
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
70+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
71+
}
72+
73+
static inline uint32_t ToUInt32BE(const uint8_t* data, int32_t offset) {
74+
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
75+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
76+
}
77+
78+
static inline uint32_t ToUInt32BE(const std::vector<uint8_t>& data, int32_t offset) {
79+
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
80+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
81+
}
82+
83+
static inline int64_t ToInt64BE(const uint8_t* data, int32_t offset) {
84+
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
85+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
86+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
87+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
88+
}
89+
90+
static inline int64_t ToInt64BE(const std::vector<uint8_t>& data, int32_t offset) {
91+
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
92+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
93+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
94+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
95+
}
96+
97+
static inline uint64_t ToUInt64BE(const uint8_t* data, int32_t offset) {
98+
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
99+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
100+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
101+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
102+
}
103+
104+
static inline uint64_t ToUInt64BE(const std::vector<uint8_t>& data, int32_t offset) {
105+
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
106+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
107+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
108+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
109+
}
110+
111+
static inline float ToFloatBE(const uint8_t* data, int32_t offset) {
112+
float value;
113+
uint32_t floatData = ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
114+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
115+
static_assert(sizeof(uint32_t) == sizeof(float), "expected 32-bit float");
116+
std::memcpy(&value, &floatData, sizeof(value));
117+
return value;
118+
}
119+
120+
static inline float ToFloatBE(const std::vector<uint8_t>& data, int32_t offset) {
121+
float value;
122+
uint32_t floatData = ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
123+
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
124+
static_assert(sizeof(uint32_t) == sizeof(float), "expected 32-bit float");
125+
std::memcpy(&value, &floatData, sizeof(value));
126+
return value;
127+
}
128+
129+
static inline double ToDoubleBE(const uint8_t* data, int32_t offset) {
130+
double value;
131+
uint64_t floatData = ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
132+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
133+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
134+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
135+
static_assert(sizeof(uint64_t) == sizeof(double), "expected 64-bit double");
136+
// Checks if the float format on the platform the ZAPD binary is running on supports the
137+
// same float format as the object file.
138+
static_assert(std::numeric_limits<float>::is_iec559, "expected IEC559 floats on host machine");
139+
std::memcpy(&value, &floatData, sizeof(value));
140+
return value;
141+
}
142+
143+
static inline double ToDoubleBE(const std::vector<uint8_t>& data, int32_t offset) {
144+
double value;
145+
uint64_t floatData = ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
146+
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
147+
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
148+
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
149+
static_assert(sizeof(uint64_t) == sizeof(double), "expected 64-bit double");
150+
// Checks if the float format on the platform the ZAPD binary is running on supports the
151+
// same float format as the object file.
152+
static_assert(std::numeric_limits<double>::is_iec559, "expected IEC559 doubles on host machine");
153+
std::memcpy(&value, &floatData, sizeof(value));
154+
return value;
155+
}
156+
157+
// Rewrites the rom data in-place to be in BigEndian/z64 format
158+
static inline void RomToBigEndian(uint8_t* rom, size_t romSize) {
159+
if (romSize <= 0) {
160+
return;
161+
}
162+
163+
// Use the first byte to determine byte order
164+
uint8_t firstByte = rom[0];
165+
166+
switch (firstByte) {
167+
case 0x37: // v64
168+
for (size_t pos = 0; pos < (romSize / 2); pos++) {
169+
((uint16_t*)rom)[pos] = ToUInt16BE(rom, pos * 2);
170+
}
171+
break;
172+
case 0x40: // n64
173+
for (size_t pos = 0; pos < (romSize / 4); pos++) {
174+
((uint32_t*)rom)[pos] = ToUInt32BE(rom, pos * 4);
175+
}
176+
break;
177+
case 0x80: // z64
178+
break; // Already BE, no need to swap
179+
}
180+
}
181+
};

0 commit comments

Comments
 (0)