diff --git a/Dependencies/Utility/Utility/CppMacros.h b/Dependencies/Utility/Utility/CppMacros.h
index 9de4334c40f..57aaa75abc8 100644
--- a/Dependencies/Utility/Utility/CppMacros.h
+++ b/Dependencies/Utility/Utility/CppMacros.h
@@ -43,3 +43,7 @@
#else
#define REGISTER register
#endif
+
+#if __cplusplus < 201103L
+#define static_assert(expr, msg)
+#endif
diff --git a/Dependencies/Utility/Utility/endian_compat.h b/Dependencies/Utility/Utility/endian_compat.h
new file mode 100644
index 00000000000..56b35c33bef
--- /dev/null
+++ b/Dependencies/Utility/Utility/endian_compat.h
@@ -0,0 +1,246 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// This file contains macros to help with endian conversions between different endian systems.
+#pragma once
+
+// VC6 does not support pragma once
+#ifndef ENDIAN_COMPAT_H
+#define ENDIAN_COMPAT_H
+
+#include
+#include
+
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#include
+
+#elif defined(__APPLE__)
+#include
+
+#define htobe16(x) OSSwapHostToBigInt16(x)
+#define htole16(x) OSSwapHostToLittleInt16(x)
+#define be16toh(x) OSSwapBigToHostInt16(x)
+#define le16toh(x) OSSwapLittleToHostInt16(x)
+
+#define htobe32(x) OSSwapHostToBigInt32(x)
+#define htole32(x) OSSwapHostToLittleInt32(x)
+#define be32toh(x) OSSwapBigToHostInt32(x)
+#define le32toh(x) OSSwapLittleToHostInt32(x)
+
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+
+#elif defined(__OpenBSD__)
+#include
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#include
+
+#define be16toh(x) betoh16(x)
+#define le16toh(x) letoh16(x)
+
+#define be32toh(x) betoh32(x)
+#define le32toh(x) letoh32(x)
+
+#define be64toh(x) betoh64(x)
+#define le64toh(x) letoh64(x)
+
+#elif defined(_WIN32) || defined(_WIN64)
+#if !(defined(_MSC_VER) && _MSC_VER < 1300)
+#include
+#define htobe16(x) _byteswap_ushort(x)
+#define htole16(x) (x)
+#define be16toh(x) _byteswap_ushort(x)
+#define le16toh(x) (x)
+
+#define htobe32(x) _byteswap_ulong(x)
+#define htole32(x) (x)
+#define be32toh(x) _byteswap_ulong(x)
+#define le32toh(x) (x)
+
+#define htobe64(x) _byteswap_uint64(x)
+#define htole64(x) (x)
+#define be64toh(x) _byteswap_uint64(x)
+#define le64toh(x) (x)
+#else
+#define bswap16(x) ( (uint16_t)( ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8) ) )
+#define bswap32(x) ( ((x & 0xFF000000) >> 24) | \
+ ((x & 0x00FF0000) >> 8) | \
+ ((x & 0x0000FF00) << 8) | \
+ ((x & 0x000000FF) << 24) )
+#define bswap64(x) ( (((uint64_t)(x) & 0xFF00000000000000) >> 56) | \
+ (((uint64_t)(x) & 0x00FF000000000000) >> 40) | \
+ (((uint64_t)(x) & 0x0000FF0000000000) >> 24) | \
+ (((uint64_t)(x) & 0x000000FF00000000) >> 8) | \
+ (((uint64_t)(x) & 0x00000000FF000000) << 8) | \
+ (((uint64_t)(x) & 0x0000000000FF0000) << 24) | \
+ (((uint64_t)(x) & 0x000000000000FF00) << 40) | \
+ (((uint64_t)(x) & 0x00000000000000FF) << 56) )
+
+#define htobe16(x) bswap16(x)
+#define htole16(x) (x)
+#define be16toh(x) bswap16(x)
+#define le16toh(x) (x)
+
+#define htobe32(x) bswap32(x)
+#define htole32(x) (x)
+#define be32toh(x) bswap32(x)
+#define le32toh(x) (x)
+
+#define htobe64(x) bswap64(x)
+#define htole64(x) (x)
+#define be64toh(x) bswap64(x)
+#define le64toh(x) (x)
+
+#endif // _MSC_VER
+
+#else
+#error platform not supported
+#endif
+
+
+// Endian helper function data types
+#if defined(__linux__) || defined(__CYGWIN__)
+typedef uint16_t SwapType16;
+typedef uint32_t SwapType32;
+typedef uint64_t SwapType64;
+
+#elif defined(__APPLE__)
+typedef UInt16 SwapType16;
+typedef UInt32 SwapType32;
+typedef UInt64 SwapType64;
+
+#elif defined(__OpenBSD__)
+typedef uint16_t SwapType16;
+typedef uint32_t SwapType32;
+typedef uint64_t SwapType64;
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+typedef uint16_t SwapType16;
+typedef uint32_t SwapType32;
+typedef uint64_t SwapType64;
+
+#elif defined(_WIN32) || defined(_WIN64)
+typedef uint16_t SwapType16;
+typedef uint32_t SwapType32;
+typedef uint64_t SwapType64;
+
+#else
+#error platform not supported
+#endif
+
+
+// Endian helper functions
+static_assert(sizeof(SwapType16) == 2, "expected size does not match");
+static_assert(sizeof(SwapType32) == 4, "expected size does not match");
+static_assert(sizeof(SwapType64) == 8, "expected size does not match");
+
+// VC6 compatible overloaded endian functions
+#if defined(_MSC_VER) && _MSC_VER < 1300
+
+// Big endian to host
+inline int16_t betoh(int16_t value) { return be16toh(value); }
+inline uint16_t betoh(uint16_t value) { return be16toh(value); }
+inline int32_t betoh(int32_t value) { return be32toh(value); }
+inline uint32_t betoh(uint32_t value) { return be32toh(value); }
+inline int64_t betoh(int64_t value) { return be64toh(value); }
+inline uint64_t betoh(uint64_t value) { return be64toh(value); }
+// Host to big endian
+inline int16_t htobe(int16_t value) { return htobe16(value); }
+inline uint16_t htobe(uint16_t value) { return htobe16(value); }
+inline int32_t htobe(int32_t value) { return htobe32(value); }
+inline uint32_t htobe(uint32_t value) { return htobe32(value); }
+inline int64_t htobe(int64_t value) { return htobe64(value); }
+inline uint64_t htobe(uint64_t value) { return htobe64(value); }
+// Little endian to host
+inline int16_t letoh(int16_t value) { return le16toh(value); }
+inline uint16_t letoh(uint16_t value) { return le16toh(value); }
+inline int32_t letoh(int32_t value) { return le32toh(value); }
+inline uint32_t letoh(uint32_t value) { return le32toh(value); }
+inline int64_t letoh(int64_t value) { return le64toh(value); }
+inline uint64_t letoh(uint64_t value) { return le64toh(value); }
+// Host to little endian
+inline int16_t htole(int16_t value) { return htole16(value); }
+inline uint16_t htole(uint16_t value) { return htole16(value); }
+inline int32_t htole(int32_t value) { return htole32(value); }
+inline uint32_t htole(uint32_t value) { return htole32(value); }
+inline int64_t htole(int64_t value) { return htole64(value); }
+inline uint64_t htole(uint64_t value) { return htole64(value); }
+
+#else
+
+namespace Endian
+{
+template struct htobeHelper;
+template struct htoleHelper;
+template struct betohHelper;
+template struct letohHelper;
+
+// 2 byte integer, enum
+template struct htobeHelper { static inline Type swap(Type value) { return static_cast(htobe16(static_cast(value))); } };
+template struct htoleHelper { static inline Type swap(Type value) { return static_cast(htole16(static_cast(value))); } };
+template struct betohHelper { static inline Type swap(Type value) { return static_cast(be16toh(static_cast(value))); } };
+template struct letohHelper { static inline Type swap(Type value) { return static_cast(le16toh(static_cast(value))); } };
+// 4 byte integer, enum
+template struct htobeHelper { static inline Type swap(Type value) { return static_cast(htobe32(static_cast(value))); } };
+template struct htoleHelper { static inline Type swap(Type value) { return static_cast(htole32(static_cast(value))); } };
+template struct betohHelper { static inline Type swap(Type value) { return static_cast(be32toh(static_cast(value))); } };
+template struct letohHelper { static inline Type swap(Type value) { return static_cast(le16toh(static_cast(value))); } };
+// 8 byte integer, enum
+template struct htobeHelper { static inline Type swap(Type value) { return static_cast(htobe64(static_cast(value))); } };
+template struct htoleHelper { static inline Type swap(Type value) { return static_cast(htole64(static_cast(value))); } };
+template struct betohHelper { static inline Type swap(Type value) { return static_cast(be64toh(static_cast(value))); } };
+template struct letohHelper { static inline Type swap(Type value) { return static_cast(le16toh(static_cast(value))); } };
+// float
+template <> struct htobeHelper { static inline float swap(float value) { SwapType32 v = htobe32(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct htoleHelper { static inline float swap(float value) { SwapType32 v = htole32(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct betohHelper { static inline float swap(float value) { SwapType32 v = be32toh(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct letohHelper { static inline float swap(float value) { SwapType32 v = le16toh(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+// double
+template <> struct htobeHelper { static inline double swap(double value) { SwapType64 v = htobe64(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct htoleHelper { static inline double swap(double value) { SwapType64 v = htole64(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct betohHelper { static inline double swap(double value) { SwapType64 v = be64toh(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+template <> struct letohHelper { static inline double swap(double value) { SwapType64 v = le16toh(*reinterpret_cast(&value)); return *reinterpret_cast(&v); } };
+} // namespace Endian
+
+// c++ template functions, takes any 2, 4, 8 bytes, including float, double, enum
+
+// Host to big endian
+template inline Type htobe(Type value) { return Endian::htobeHelper::swap(value); }
+// Host to little endian
+template inline Type htole(Type value) { return Endian::htoleHelper::swap(value); }
+// Big endian to host
+template inline Type betoh(Type value) { return Endian::betohHelper::swap(value); }
+// Little endian to host
+template inline Type letoh(Type value) { return Endian::letohHelper::swap(value); }
+
+// Host to big endian
+template inline void htobe_ref(Type &value) { value = Endian::htobeHelper::swap(value); }
+// Host to little endian
+template inline void htole_ref(Type &value) { value = Endian::htoleHelper::swap(value); }
+// Big endian to host
+template inline void betoh_ref(Type &value) { value = Endian::betohHelper::swap(value); }
+// Little endian to host
+template inline void letoh_ref(Type &value) { value = Endian::letohHelper::swap(value); }
+
+#endif // _MSC_VER < 1300
+
+#endif // ENDIAN_COMPAT_H
\ No newline at end of file
diff --git a/Generals/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp b/Generals/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
index 8da71ff2c44..11ebc499a34 100644
--- a/Generals/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
+++ b/Generals/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
@@ -26,7 +26,6 @@
// Bryan Cleveland, August 2002
/////////////////////////////////////////////////////////////
-#include
#include "Common/AudioAffect.h"
#include "Common/ArchiveFile.h"
#include "Common/ArchiveFileSystem.h"
@@ -36,6 +35,7 @@
#include "Common/LocalFileSystem.h"
#include "Win32Device/Common/Win32BIGFile.h"
#include "Win32Device/Common/Win32BIGFileSystem.h"
+#include "Utility/endian_compat.h"
#ifdef RTS_INTERNAL
// for occasional debugging...
@@ -107,7 +107,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
// read in the number of files contained in this BIG file.
// change the order of the bytes cause the file size is in reverse byte order for some reason.
fp->read(&numLittleFiles, 4);
- numLittleFiles = ntohl(numLittleFiles);
+ numLittleFiles = betoh(numLittleFiles);
DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
// for (Int i = 0; i < 2; ++i) {
@@ -127,8 +127,8 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
fp->read(&fileOffset, 4);
fp->read(&filesize, 4);
- filesize = ntohl(filesize);
- fileOffset = ntohl(fileOffset);
+ filesize = betoh(filesize);
+ fileOffset = betoh(fileOffset);
fileInfo->m_archiveFilename = archiveFileName;
fileInfo->m_offset = fileOffset;
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp b/GeneralsMD/Code/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp
index 318478f20e8..76a6ffb0dfe 100644
--- a/GeneralsMD/Code/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp
+++ b/GeneralsMD/Code/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp
@@ -36,6 +36,7 @@
#include "StdDevice/Common/StdBIGFile.h"
#include "StdDevice/Common/StdBIGFileSystem.h"
#include "Common/Registry.h"
+#include "Utility/endian_compat.h"
static const char *BIGFileIdentifier = "BIGF";
@@ -113,7 +114,7 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) {
// read in the number of files contained in this BIG file.
// change the order of the bytes cause the file size is in reverse byte order for some reason.
fp->read(&numLittleFiles, 4);
- numLittleFiles = ntohl(numLittleFiles);
+ numLittleFiles = betoh(numLittleFiles);
DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
// for (Int i = 0; i < 2; ++i) {
@@ -133,8 +134,8 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) {
fp->read(&fileOffset, 4);
fp->read(&filesize, 4);
- filesize = ntohl(filesize);
- fileOffset = ntohl(fileOffset);
+ filesize = betoh(filesize);
+ fileOffset = betoh(fileOffset);
fileInfo->m_archiveFilename = archiveFileName;
fileInfo->m_offset = fileOffset;
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp b/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
index c0281151149..e9c0bc91e2b 100644
--- a/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
+++ b/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp
@@ -26,7 +26,6 @@
// Bryan Cleveland, August 2002
/////////////////////////////////////////////////////////////
-#include
#include "Common/AudioAffect.h"
#include "Common/ArchiveFile.h"
#include "Common/ArchiveFileSystem.h"
@@ -37,6 +36,7 @@
#include "Win32Device/Common/Win32BIGFile.h"
#include "Win32Device/Common/Win32BIGFileSystem.h"
#include "Common/Registry.h"
+#include "Utility/endian_compat.h"
#ifdef RTS_INTERNAL
// for occasional debugging...
@@ -120,7 +120,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
// read in the number of files contained in this BIG file.
// change the order of the bytes cause the file size is in reverse byte order for some reason.
fp->read(&numLittleFiles, 4);
- numLittleFiles = ntohl(numLittleFiles);
+ numLittleFiles = betoh(numLittleFiles);
DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
// for (Int i = 0; i < 2; ++i) {
@@ -140,8 +140,8 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
fp->read(&fileOffset, 4);
fp->read(&filesize, 4);
- filesize = ntohl(filesize);
- fileOffset = ntohl(fileOffset);
+ filesize = betoh(filesize);
+ fileOffset = betoh(fileOffset);
fileInfo->m_archiveFilename = archiveFileName;
fileInfo->m_offset = fileOffset;