Skip to content

Commit bff165e

Browse files
committed
[ZH] Add endian compat for StdBIGFileSystem
1 parent ce5d683 commit bff165e

File tree

2 files changed

+182
-3
lines changed

2 files changed

+182
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
// This file contains macros to help with endian conversions between different endian systems.
20+
#pragma once
21+
22+
// Check for accidental inclusion into a VC6 build
23+
#if defined(_MSC_VER) && (_MSC_VER < 1300)
24+
#error "This header is incompatible with Microsoft Visual C++ 6.0"
25+
#endif
26+
27+
#if defined(__linux__) || defined(__CYGWIN__)
28+
#include <endian.h>
29+
30+
#elif defined(__APPLE__)
31+
#include <libkern/OSByteOrder.h>
32+
33+
#define htobe16(x) OSSwapHostToBigInt16(x)
34+
#define htole16(x) OSSwapHostToLittleInt16(x)
35+
#define be16toh(x) OSSwapBigToHostInt16(x)
36+
#define le16toh(x) OSSwapLittleToHostInt16(x)
37+
38+
#define htobe32(x) OSSwapHostToBigInt32(x)
39+
#define htole32(x) OSSwapHostToLittleInt32(x)
40+
#define be32toh(x) OSSwapBigToHostInt32(x)
41+
#define le32toh(x) OSSwapLittleToHostInt32(x)
42+
43+
#define htobe64(x) OSSwapHostToBigInt64(x)
44+
#define htole64(x) OSSwapHostToLittleInt64(x)
45+
#define be64toh(x) OSSwapBigToHostInt64(x)
46+
#define le64toh(x) OSSwapLittleToHostInt64(x)
47+
48+
#elif defined(__OpenBSD__)
49+
#include <sys/endian.h>
50+
51+
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
52+
#include <sys/endian.h>
53+
54+
#define be16toh(x) betoh16(x)
55+
#define le16toh(x) letoh16(x)
56+
57+
#define be32toh(x) betoh32(x)
58+
#define le32toh(x) letoh32(x)
59+
60+
#define be64toh(x) betoh64(x)
61+
#define le64toh(x) letoh64(x)
62+
63+
#elif defined(_WIN32) || defined(_WIN64)
64+
#if defined (_MSC_VER)
65+
#include <intrin.h>
66+
#else
67+
#include <stdlib.h>
68+
#endif // _MSC_VER
69+
70+
#define htobe16(x) _byteswap_ushort(x)
71+
#define htole16(x) (x)
72+
#define be16toh(x) _byteswap_ushort(x)
73+
#define le16toh(x) (x)
74+
75+
#define htobe32(x) _byteswap_ulong(x)
76+
#define htole32(x) (x)
77+
#define be32toh(x) _byteswap_ulong(x)
78+
#define le32toh(x) (x)
79+
80+
#define htobe64(x) _byteswap_uint64(x)
81+
#define htole64(x) (x)
82+
#define be64toh(x) _byteswap_uint64(x)
83+
#define le64toh(x) (x)
84+
85+
#else
86+
#error platform not supported
87+
#endif
88+
89+
90+
//Endian helper function data types
91+
#if defined(__linux__) || defined(__CYGWIN__)
92+
typedef uint16_t SwapType16;
93+
typedef uint32_t SwapType32;
94+
typedef uint64_t SwapType64;
95+
96+
#elif defined(__APPLE__)
97+
typedef UInt16 SwapType16;
98+
typedef UInt32 SwapType32;
99+
typedef UInt64 SwapType64;
100+
101+
#elif defined(__OpenBSD__)
102+
typedef uint16_t SwapType16;
103+
typedef uint32_t SwapType32;
104+
typedef uint64_t SwapType64;
105+
106+
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
107+
typedef uint16_t SwapType16;
108+
typedef uint32_t SwapType32;
109+
typedef uint64_t SwapType64;
110+
111+
#elif defined(_WIN32) || defined(_WIN64)
112+
typedef unsigned short SwapType16;
113+
typedef unsigned long SwapType32;
114+
typedef unsigned long long SwapType64;
115+
116+
#else
117+
#error platform not supported
118+
#endif
119+
120+
121+
//Endian helper functions
122+
static_assert(sizeof(SwapType16) == 2, "expected size does not match");
123+
static_assert(sizeof(SwapType32) == 4, "expected size does not match");
124+
static_assert(sizeof(SwapType64) == 8, "expected size does not match");
125+
126+
namespace Detail
127+
{
128+
template <typename Type, size_t Size = sizeof(Type)> struct htobeHelper;
129+
template <typename Type, size_t Size = sizeof(Type)> struct htoleHelper;
130+
template <typename Type, size_t Size = sizeof(Type)> struct betohHelper;
131+
template <typename Type, size_t Size = sizeof(Type)> struct letohHelper;
132+
133+
// 2 byte integer, enum
134+
template <typename Type> struct htobeHelper<Type, 2> { static inline Type swap(Type value) { return static_cast<Type>(htobe16(static_cast<SwapType16>(value))); } };
135+
template <typename Type> struct htoleHelper<Type, 2> { static inline Type swap(Type value) { return static_cast<Type>(htole16(static_cast<SwapType16>(value))); } };
136+
template <typename Type> struct betohHelper<Type, 2> { static inline Type swap(Type value) { return static_cast<Type>(be16toh(static_cast<SwapType16>(value))); } };
137+
template <typename Type> struct letohHelper<Type, 2> { static inline Type swap(Type value) { return static_cast<Type>(le16toh(static_cast<SwapType16>(value))); } };
138+
// 4 byte integer, enum
139+
template <typename Type> struct htobeHelper<Type, 4> { static inline Type swap(Type value) { return static_cast<Type>(htobe32(static_cast<SwapType32>(value))); } };
140+
template <typename Type> struct htoleHelper<Type, 4> { static inline Type swap(Type value) { return static_cast<Type>(htole32(static_cast<SwapType32>(value))); } };
141+
template <typename Type> struct betohHelper<Type, 4> { static inline Type swap(Type value) { return static_cast<Type>(be32toh(static_cast<SwapType32>(value))); } };
142+
template <typename Type> struct letohHelper<Type, 4> { static inline Type swap(Type value) { return static_cast<Type>(le16toh(static_cast<SwapType32>(value))); } };
143+
// 8 byte integer, enum
144+
template <typename Type> struct htobeHelper<Type, 8> { static inline Type swap(Type value) { return static_cast<Type>(htobe64(static_cast<SwapType64>(value))); } };
145+
template <typename Type> struct htoleHelper<Type, 8> { static inline Type swap(Type value) { return static_cast<Type>(htole64(static_cast<SwapType64>(value))); } };
146+
template <typename Type> struct betohHelper<Type, 8> { static inline Type swap(Type value) { return static_cast<Type>(be64toh(static_cast<SwapType64>(value))); } };
147+
template <typename Type> struct letohHelper<Type, 8> { static inline Type swap(Type value) { return static_cast<Type>(le16toh(static_cast<SwapType64>(value))); } };
148+
// float
149+
template <> struct htobeHelper<float, 4> { static inline float swap(float value) { SwapType32 v = htobe32(*reinterpret_cast<SwapType32*>(&value)); return *reinterpret_cast<float*>(&v); } };
150+
template <> struct htoleHelper<float, 4> { static inline float swap(float value) { SwapType32 v = htole32(*reinterpret_cast<SwapType32*>(&value)); return *reinterpret_cast<float*>(&v); } };
151+
template <> struct betohHelper<float, 4> { static inline float swap(float value) { SwapType32 v = be32toh(*reinterpret_cast<SwapType32*>(&value)); return *reinterpret_cast<float*>(&v); } };
152+
template <> struct letohHelper<float, 4> { static inline float swap(float value) { SwapType32 v = le16toh(*reinterpret_cast<SwapType32*>(&value)); return *reinterpret_cast<float*>(&v); } };
153+
// double
154+
template <> struct htobeHelper<double, 8> { static inline double swap(double value) { SwapType64 v = htobe64(*reinterpret_cast<SwapType64*>(&value)); return *reinterpret_cast<double*>(&v); } };
155+
template <> struct htoleHelper<double, 8> { static inline double swap(double value) { SwapType64 v = htole64(*reinterpret_cast<SwapType64*>(&value)); return *reinterpret_cast<double*>(&v); } };
156+
template <> struct betohHelper<double, 8> { static inline double swap(double value) { SwapType64 v = be64toh(*reinterpret_cast<SwapType64*>(&value)); return *reinterpret_cast<double*>(&v); } };
157+
template <> struct letohHelper<double, 8> { static inline double swap(double value) { SwapType64 v = le16toh(*reinterpret_cast<SwapType64*>(&value)); return *reinterpret_cast<double*>(&v); } };
158+
} // namespace Detail
159+
160+
// c++ template functions, takes any 2, 4, 8 bytes, including float, double, enum
161+
162+
// Host to big endian
163+
template<typename Type> inline Type htobe(Type value) { return Detail::htobeHelper<Type>::swap(value); }
164+
// Host to little endian
165+
template<typename Type> inline Type htole(Type value) { return Detail::htoleHelper<Type>::swap(value); }
166+
// Big endian to host
167+
template<typename Type> inline Type betoh(Type value) { return Detail::betohHelper<Type>::swap(value); }
168+
// Little endian to host
169+
template<typename Type> inline Type letoh(Type value) { return Detail::letohHelper<Type>::swap(value); }
170+
171+
// Host to big endian
172+
template<typename Type> inline void htobe_ref(Type &value) { value = Detail::htobeHelper<Type>::swap(value); }
173+
// Host to little endian
174+
template<typename Type> inline void htole_ref(Type &value) { value = Detail::htoleHelper<Type>::swap(value); }
175+
// Big endian to host
176+
template<typename Type> inline void betoh_ref(Type &value) { value = Detail::betohHelper<Type>::swap(value); }
177+
// Little endian to host
178+
template<typename Type> inline void letoh_ref(Type &value) { value = Detail::letohHelper<Type>::swap(value); }

GeneralsMD/Code/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "StdDevice/Common/StdBIGFile.h"
3737
#include "StdDevice/Common/StdBIGFileSystem.h"
3838
#include "Common/Registry.h"
39+
#include "Utility/endian_compat.h"
3940

4041
static const char *BIGFileIdentifier = "BIGF";
4142

@@ -113,7 +114,7 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) {
113114
// read in the number of files contained in this BIG file.
114115
// change the order of the bytes cause the file size is in reverse byte order for some reason.
115116
fp->read(&numLittleFiles, 4);
116-
numLittleFiles = ntohl(numLittleFiles);
117+
numLittleFiles = betoh(numLittleFiles);
117118

118119
DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
119120
// for (Int i = 0; i < 2; ++i) {
@@ -133,8 +134,8 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) {
133134
fp->read(&fileOffset, 4);
134135
fp->read(&filesize, 4);
135136

136-
filesize = ntohl(filesize);
137-
fileOffset = ntohl(fileOffset);
137+
filesize = betoh(filesize);
138+
fileOffset = betoh(fileOffset);
138139

139140
fileInfo->m_archiveFilename = archiveFileName;
140141
fileInfo->m_offset = fileOffset;

0 commit comments

Comments
 (0)