diff --git a/common/bitfields.h b/common/bitfields.h index 85fc59a9..ceb6e6b7 100644 --- a/common/bitfields.h +++ b/common/bitfields.h @@ -16,10 +16,15 @@ /* * Use this macro to mark a structure to be packed in an MSVC compatible way. */ -#if defined __clang__ || defined __GNUC__ -#define BITFIELD_STRUCT __attribute__((ms_struct)) +#if (defined __clang__ || defined __GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define BITFIELD_STRUCT __attribute__((ms_struct)) +#define HAVE_MS_BITFIELDS 1 +#elif defined(_MSC_VER) +#define BITFIELD_STRUCT +#define HAVE_MS_BITFIELDS 1 #else #define BITFIELD_STRUCT +#define HAVE_MS_BITFIELDS 0 #endif #endif /* COMMON_BITFIELDS_H */ diff --git a/common/combuf.h b/common/combuf.h index 674a5650..225bd205 100644 --- a/common/combuf.h +++ b/common/combuf.h @@ -56,8 +56,7 @@ /*--------------------------------------------------------------------------- This is one output queue entry ---------------------------------------------------------------------------*/ -#pragma pack(push, 1) -typedef struct BITFIELD_STRUCT +typedef struct { unsigned int IsActive : 1; // 1 = this entry is ready to be processed unsigned int IsACK : 1; // 1 = ACK received for this packet @@ -73,7 +72,7 @@ typedef struct BITFIELD_STRUCT /*--------------------------------------------------------------------------- This is one input queue entry ---------------------------------------------------------------------------*/ -typedef struct BITFIELD_STRUCT +typedef struct { unsigned int IsActive : 1; // 1 = this entry is ready to be processed unsigned int IsRead : 1; // 1 = caller has read this entry @@ -83,7 +82,6 @@ typedef struct BITFIELD_STRUCT int ExtraLen; // size of extra data char* ExtraBuffer; // extra data buffer } ReceiveQueueType; -#pragma pack(pop) /* ***************************** Class Declaration ***************************** diff --git a/redalert/defines.h b/redalert/defines.h index 22b218bf..d6d0dd15 100644 --- a/redalert/defines.h +++ b/redalert/defines.h @@ -539,11 +539,10 @@ typedef int TARGET; #define TARGET_MANTISSA 24 // Bits of value precision. #define TARGET_EXPONENT 8 -#pragma pack(push, 1) typedef union { TARGET Target; - struct BITFIELD_STRUCT + struct { #ifdef __BIG_ENDIAN__ unsigned Exponent : TARGET_EXPONENT; @@ -554,7 +553,6 @@ typedef union #endif } Sub; } TARGET_COMPOSITE; -#pragma pack(pop) inline TARGET Build_Target(RTTIType kind, int value) { TARGET_COMPOSITE target; diff --git a/redalert/ipxgconn.h b/redalert/ipxgconn.h index 5172752e..a7ec64b3 100644 --- a/redalert/ipxgconn.h +++ b/redalert/ipxgconn.h @@ -93,6 +93,7 @@ typedef struct { CommHeaderType Header; unsigned short ProductID; + unsigned short pad; } GlobalHeaderType; inline void SwapGlobalHeaderType(GlobalHeaderType* ght) diff --git a/redalert/session.h b/redalert/session.h index e157e7dd..5beb61a9 100644 --- a/redalert/session.h +++ b/redalert/session.h @@ -299,26 +299,47 @@ typedef struct { struct BITFIELD_STRUCT { - HousesType House; // player's House - PlayerColorType Color; // player's color or SIGNOFF ID - unsigned int MinVersion; // min version this game supports - unsigned int MaxVersion; // max version this game supports - char Scenario[DESCRIP_MAX]; // Scenario name - unsigned int Credits; // player's credits + HousesType House; // player's House + PlayerColorType Color; // player's color or SIGNOFF ID + unsigned int MinVersion; // min version this game supports + unsigned int MaxVersion; // max version this game supports + char Scenario[DESCRIP_MAX]; // Scenario name + unsigned int Credits; // player's credits +#if HAVE_MS_BITFIELDS unsigned int IsBases : 1; // 1 = bases are allowed unsigned int IsTiberium : 1; // 1 = tiberium is allowed unsigned int IsGoodies : 1; // 1 = goodies are allowed unsigned int IsGhosties : 1; // 1 = ghosts are allowed unsigned int OfficialScenario : 1; // Is this scenario an official Westwood one? - int CheatCheck; // Unique ID of "rules.ini" file. - unsigned char BuildLevel; // buildable level - unsigned char UnitCount; // max # units - unsigned char AIPlayers; // # of AI players allowed - int Seed; // random number seed - SpecialClass Special; // command-line options - unsigned int GameSpeed; // Game Speed - unsigned int ResponseTime; // packet response time - unsigned int FileLength; // Length of scenario file to expect from host. +#else + /* + ** simulate effects of attribute((ms_struct)) + */ +#ifdef __BIG_ENDIAN__ + unsigned int : 27; + unsigned int OfficialScenario : 1; + unsigned int IsGhosties : 1; + unsigned int IsGoodies : 1; + unsigned int IsTiberium : 1; + unsigned int IsBases : 1; +#else + unsigned int IsBases : 1; + unsigned int IsTiberium : 1; + unsigned int IsGoodies : 1; + unsigned int IsGhosties : 1; + unsigned int OfficialScenario : 1; + unsigned int : 27; +#endif +#endif + int CheatCheck; // Unique ID of "rules.ini" file. + unsigned char BuildLevel; // buildable level + unsigned char UnitCount; // max # units + unsigned char AIPlayers; // # of AI players allowed + int Seed; // random number seed + SpecialClass Special; // command-line options + unsigned int GameSpeed; // Game Speed + unsigned int ResponseTime; // packet response time + unsigned int FileLength; // Length of scenario file to expect from host. #ifdef WOLAPI_INTEGRATION char ShortFileName[13]; // Name of scenario file to expect from host #else diff --git a/redalert/special.h b/redalert/special.h index 78dbeb8f..16f1f3f8 100644 --- a/redalert/special.h +++ b/redalert/special.h @@ -55,7 +55,7 @@ class BITFIELD_STRUCT SpecialClass struct { #ifdef __BIG_ENDIAN__ - unsigned int Unused : 20; + unsigned int : 20; unsigned ModernBalance : 1; unsigned IsEarlyWin : 1; unsigned IsMCVDeploy : 1; @@ -128,10 +128,13 @@ class BITFIELD_STRUCT SpecialClass ** New modern balance setting. */ unsigned ModernBalance : 1; +#if !HAVE_MS_BITFIELDS + unsigned int : 20; +#endif #endif }; }; }; #pragma pack(pop) -#endif \ No newline at end of file +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 45fbdca6..2d09863d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -72,3 +72,15 @@ target_include_directories(test_drawbuff PUBLIC .. ../common) target_compile_definitions(test_drawbuff PUBLIC TRUE_FALSE_DEFINED ENGLISH $<$:_DEBUG> _WINDOWS _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE WINSOCK_IPX) target_link_libraries(test_drawbuff PUBLIC commonv ${STATIC_LIBS}) add_test(NAME drawbuff COMMAND ${TARGET_SYSTEM_EMULATOR} $) + +add_executable(test_structsizetd structsizetd.cpp) +target_compile_definitions(test_structsizetd PUBLIC $<$:_DEBUG> ${VANILLA_DEFS} MEGAMAPS) +target_include_directories(test_structsizetd PUBLIC .. ../common) +target_link_libraries(test_structsizetd PUBLIC commonv ${STATIC_LIBS}) +add_test(NAME structsizetd COMMAND ${TARGET_SYSTEM_EMULATOR} $) + +add_executable(test_structsizera structsizera.cpp) +target_compile_definitions(test_structsizera PUBLIC $<$:_DEBUG> ${VANILLA_DEFS}) +target_include_directories(test_structsizera PUBLIC .. ../common) +target_link_libraries(test_structsizera PUBLIC commonv ${STATIC_LIBS}) +add_test(NAME structsizera COMMAND ${TARGET_SYSTEM_EMULATOR} $) diff --git a/tests/drawbuff.cpp b/tests/drawbuff.cpp index b007fe7e..86e4b8cf 100644 --- a/tests/drawbuff.cpp +++ b/tests/drawbuff.cpp @@ -11,7 +11,6 @@ bool GameInFocus; int ScreenWidth; int WindowList[9][9]; -extern "C" char* _ShapeBuffer = 0; WWKeyboardClass* Keyboard; void Process_Network() diff --git a/tests/structsizera.cpp b/tests/structsizera.cpp new file mode 100644 index 00000000..c0bcf9ff --- /dev/null +++ b/tests/structsizera.cpp @@ -0,0 +1,72 @@ +#include "redalert/function.h" + +#include +#include +#include + +#include "common/mixfile.h" +#include "common/vqaloader.h" +#include "common/filepcx.h" + +#pragma pack(push, 2) +typedef struct +{ + int16_t count; + int32_t size; +} FileHeader; +#pragma pack(pop) + +int main(void) +{ + int ret = 0; + +#define check_size(T, n) \ + if (sizeof(T) != n) { \ + fprintf(stderr, "sizeof(" #T "): should be %d, but is %d\n", n, (int)sizeof(T)); \ + ret |= 1; \ + } +#undef check_size +#define check_size(T, n) static_assert(sizeof(T) == n) +#define check_offset(T, m, n) static_assert(__builtin_offsetof(T, m) == n) + + check_size(MFCD::SubBlock, 12); + check_size(FileHeader, 6); + check_size(AUDHeaderType, 12); + check_size(COORDINATE, 4); + check_size(COORD_COMPOSITE, 4); + check_size(CELL, 2); + check_size(CELL_COMPOSITE, 2); + check_size(TARGET, 4); + check_size(TARGET_COMPOSITE, 4); + check_size(Cursor, 10); + check_size(Shape_Type, 26); + check_size(ShapeBlock_Type, 2); + check_size(VQASND1Header, 4); + check_size(VQASN2JHeader, 6); + check_size(VQAHeader, 42); + check_size(SpecialClass, 4); + check_size(EventClass, 20); + check_offset(EventClass, Data, 5); + check_offset(EventClass, Data.MegaMission.Mission, 9); + check_offset(EventClass, Data.MegaMission.Target, 10); + check_size(SerialPacketType, 150); + check_offset(SerialPacketType, ScenarioInfo, 17); + check_offset(SerialPacketType, ScenarioInfo.MinVersion, 19); + check_offset(SerialPacketType, ScenarioInfo.Credits, 71); + check_offset(SerialPacketType, ScenarioInfo.CheatCheck, 79); + check_offset(SerialPacketType, ScenarioInfo.FileDigest, 118); + check_size(GlobalPacketType, 141); + check_offset(GlobalPacketType, GameInfo, 16); + check_size(IControl_Type, 40); + check_size(CompHeaderType, 8); + check_size(RGB, 3); + check_size(PCX_HEADER, 128); + check_size(CommHeaderType, 8); + check_size(IPXAddressClass, 10); + check_size(GlobalHeaderType, 12); + +#undef check_size +#undef check_offset + + return ret; +} diff --git a/tests/structsizetd.cpp b/tests/structsizetd.cpp new file mode 100644 index 00000000..eccf165d --- /dev/null +++ b/tests/structsizetd.cpp @@ -0,0 +1,74 @@ +#include "tiberiandawn/function.h" +#include "tiberiandawn/tile.h" + +#include +#include +#include + +#include "common/mixfile.h" +#include "common/vqaloader.h" +#include "common/filepcx.h" + +#pragma pack(push, 2) +typedef struct +{ + int16_t count; + int32_t size; +} FileHeader; +#pragma pack(pop) + +int main(void) +{ + int ret = 0; + +#define check_size(T, n) \ + if (sizeof(T) != n) { \ + fprintf(stderr, "sizeof(" #T "): should be %d, but is %d\n", n, (int)sizeof(T)); \ + ret |= 1; \ + } +#undef check_size +#define check_size(T, n) static_assert(sizeof(T) == n) +#define check_offset(T, m, n) static_assert(__builtin_offsetof(T, m) == n) + + check_size(MFCD::SubBlock, 12); + check_size(FileHeader, 6); + check_size(AUDHeaderType, 12); + check_size(COORDINATE, 4); + check_size(COORD_COMPOSITE, 4); + check_size(CELL, 2); + check_size(CELL_COMPOSITE, 2); + check_size(TARGET, 4); + check_size(TARGET_COMPOSITE, 4); + check_size(Cursor, 10); + check_size(Shape_Type, 26); + check_size(ShapeBlock_Type, 2); + check_size(VQASND1Header, 4); + check_size(VQASN2JHeader, 6); + check_size(VQAHeader, 42); + check_size(SpecialClass, 16); + check_size(EventClass, 22); + check_offset(EventClass, Data, 6); + check_offset(EventClass, Data.MegaMission.Mission, 10); + check_offset(EventClass, Data.MegaMission.Target, 11); + check_size(SerialPacketType, 88); + check_offset(SerialPacketType, Credits, 21); + check_offset(SerialPacketType, BuildLevel, 29); + check_offset(SerialPacketType, BuildLevel, 29); + check_size(GlobalPacketType, 48); + check_offset(GlobalPacketType, GameInfo, 13); + check_offset(GlobalPacketType, ScenarioInfo, 13); + check_offset(GlobalPacketType, ScenarioInfo.Credits, 14); + check_offset(GlobalPacketType, ScenarioInfo.Seed, 24); + check_size(IControl_Type, 32); + check_size(CompHeaderType, 8); + check_size(RGB, 3); + check_size(PCX_HEADER, 128); + check_size(CommHeaderType, 8); + check_size(IPXAddressClass, 10); + check_size(GlobalHeaderType, 20); + +#undef check_size +#undef check_offset + + return ret; +} diff --git a/tiberiandawn/defines.h b/tiberiandawn/defines.h index 82ff91d8..ee6c6c86 100644 --- a/tiberiandawn/defines.h +++ b/tiberiandawn/defines.h @@ -1711,11 +1711,10 @@ typedef int TARGET; #define TARGET_MANTISSA 24 // Bits of value precision. #define TARGET_EXPONENT 8 -#pragma pack(push, 1) typedef union { TARGET Target; - struct BITFIELD_STRUCT + struct { #ifdef __BIG_ENDIAN__ unsigned Exponent : TARGET_EXPONENT; @@ -1726,7 +1725,6 @@ typedef union #endif } Sub; } TARGET_COMPOSITE; -#pragma pack(pop) #define TARGET_NONE ((TARGET)0) @@ -2729,17 +2727,36 @@ typedef enum SerialCommandType : unsigned short #pragma pack(push, 1) typedef struct BITFIELD_STRUCT { - SerialCommandType Command; // One of the enum's defined above - char Name[MPLAYER_NAME_MAX]; // Player or Game Name - int Version; // game's version number - HousesType House; // player's House - unsigned char Color; // player's color or SIGNOFF ID - unsigned char Scenario; // Scenario # - unsigned int Credits; // player's credits - unsigned int IsBases : 1; // 1 = bases are allowed - unsigned int IsTiberium : 1; // 1 = tiberium is allowed - unsigned int IsGoodies : 1; // 1 = goodies are allowed - unsigned int IsGhosties : 1; // 1 = ghosts are allowed + SerialCommandType Command; // One of the enum's defined above + char Name[MPLAYER_NAME_MAX]; // Player or Game Name + int Version; // game's version number + HousesType House; // player's House + unsigned char Color; // player's color or SIGNOFF ID + unsigned char Scenario; // Scenario # + unsigned int Credits; // player's credits +#if HAVE_MS_BITFIELDS + unsigned int IsBases : 1; // 1 = bases are allowed + unsigned int IsTiberium : 1; // 1 = tiberium is allowed + unsigned int IsGoodies : 1; // 1 = goodies are allowed + unsigned int IsGhosties : 1; // 1 = ghosts are allowed +#else + /* + ** simulate effects of attribute((ms_struct)) + */ +#ifdef __BIG_ENDIAN__ + unsigned int : 28; + unsigned int IsGhosties : 1; + unsigned int IsGoodies : 1; + unsigned int IsTiberium : 1; + unsigned int IsBases : 1; +#else + unsigned int IsBases : 1; + unsigned int IsTiberium : 1; + unsigned int IsGoodies : 1; + unsigned int IsGhosties : 1; + unsigned int : 28; +#endif +#endif unsigned char BuildLevel; // buildable level unsigned char UnitCount; // max # units int Seed; // random number seed @@ -2797,8 +2814,18 @@ typedef struct { struct BITFIELD_STRUCT { - int Version; // game's version number + int Version; // game's version number +#if HAVE_MS_BITFIELDS unsigned int IsOpen : 1; // 1 = game is open for joining +#else +#ifdef __BIG_ENDIAN__ + unsigned int : 31; + unsigned int IsOpen : 1; +#else + unsigned int IsOpen : 1; + unsigned int : 31; +#endif +#endif } GameInfo; struct { @@ -2808,17 +2835,33 @@ typedef struct } PlayerInfo; struct BITFIELD_STRUCT { - unsigned char Scenario; // Scenario # - unsigned int Credits; // player's credits + unsigned char Scenario; // Scenario # + unsigned int Credits; // player's credits +#if HAVE_MS_BITFIELDS unsigned int IsBases : 1; // 1 = bases are allowed unsigned int IsTiberium : 1; // 1 = tiberium is allowed unsigned int IsGoodies : 1; // 1 = goodies are allowed unsigned int IsGhosties : 1; // 1 = ghosts are allowed - unsigned char BuildLevel; // buildable level - unsigned char UnitCount; // max # units - int Seed; // random number seed - SpecialClass Special; // command-line options - unsigned int GameSpeed; // Game Speed +#else +#ifdef __BIG_ENDIAN__ + unsigned int : 28; + unsigned int IsGhosties : 1; + unsigned int IsGoodies : 1; + unsigned int IsTiberium : 1; + unsigned int IsBases : 1; +#else + unsigned int IsBases : 1; + unsigned int IsTiberium : 1; + unsigned int IsGoodies : 1; + unsigned int IsGhosties : 1; + unsigned int : 28; +#endif +#endif + unsigned char BuildLevel; // buildable level + unsigned char UnitCount; // max # units + int Seed; // random number seed + SpecialClass Special; // command-line options + unsigned int GameSpeed; // Game Speed } ScenarioInfo; struct { @@ -3044,4 +3087,4 @@ typedef enum StrategyType : unsigned char #pragma warning(pop) -#endif \ No newline at end of file +#endif diff --git a/tiberiandawn/special.h b/tiberiandawn/special.h index 78ad08fb..760cc891 100644 --- a/tiberiandawn/special.h +++ b/tiberiandawn/special.h @@ -36,6 +36,7 @@ #define SPECIAL_H #include "common/bitfields.h" +#include "common/endianness.h" #include #pragma pack(push, 1) @@ -77,163 +78,238 @@ class BITFIELD_STRUCT SpecialClass ModernBalance = false; } - /* - ** Is the game flagged for easy mode? - */ - unsigned IsEasy : 1; - - /* - ** Is the game flagged for difficult? - */ - unsigned IsDifficult : 1; - - /* - ** Controls the speedy build option -- used for testing. - */ - unsigned IsSpeedBuild : 1; - - /* - ** If the player can build the helipad separate from the helipad and - ** helicopter combo, then this flag will be true. - */ - unsigned IsSeparate : 1; - - /* - ** If the defender has the advantage then this will be true. This flag - ** allows the defender to have a better advantage in combat than the - ** attacker. Moving units will not be able to dish out or take as much - ** damage when this flag is true. - */ - unsigned IsDefenderAdvantage : 1; - - /* - ** If civilian structures are to have a name, then this flag will be - ** set to true. The default case is to just use generic names for - ** civilians. - */ - unsigned IsNamed : 1; - - /* - ** If from install, then play the special installation movie and - ** skip asking them what type of game they want to play. - */ - unsigned IsFromInstall : 1; - - /* - ** If capture the flag mode is on, this flag will be true. With this - ** flag enabled, then the flag is initially placed at the start of - ** the scenario. - */ - unsigned IsCaptureTheFlag : 1; - - /* - ** Is target selecting by other human opponents visible to the player? - */ - unsigned IsVisibleTarget : 1; - - /* - ** If human generated sound effects are to be used, then this - ** flag will be true. - */ - unsigned IsJuvenile : 1; - - /* - ** If friendly units should return fire when fired upon, set this - ** flag to true. The default is only for the enemy units to do this. - */ - unsigned IsSmartDefense : 1; - - /* - ** If targeting of trees is allowed, then this flag will be true. - */ - unsigned IsTreeTarget : 1; - - /* - ** If this flag is true, then the construction yard can undeploy back into an MCV. - */ - unsigned IsMCVDeploy : 1; - - /* - ** Controls whether or not visceroids spawn - */ - unsigned IsVisceroids : 1; - - /* - ** If the monochrome debugging output is enabled, then this flag will be true. - */ - unsigned IsMonoEnabled : 1; - - /* - ** This flags controls whether weapons are inert. An inert weapon doesn't do any - ** damage. Effectively, if this is true, then the units never die. - */ - unsigned IsInert : 1; - - /* - ** When this flag is true, the computer findpath algorithm reveals the route being - ** examined. This is used to trace findpath bugs. - */ - unsigned IsShowPath : 1; - - /* - ** If wheeled vehicles should do a 3-point turn when rotating in place, then - ** this flag is true. - */ - unsigned IsThreePoint : 1; - - /* - ** If Tiberium is allowed to grow, then this flag will be true. - */ - unsigned IsTGrowth : 1; - - /* - ** If Tiberium is allowed to spread, then this flag will be true. - */ - unsigned IsTSpread : 1; - - /* - ** This controls whether Tiberium grows&spreads quickly or not. - */ - unsigned IsTFast : 1; - - /* - ** This flag controls whether the road additional pieces are added to - ** the bottom of buildings. If true, then the roads are NOT added. - */ - unsigned IsRoad : 1; - - /* - ** Controls whether units (especially infantry) will scatter when there - ** is an immediate threat. This gives infantry a "mind of their own" when - ** it comes to self preservation. If set to false, then units will not - ** scatter. - */ - unsigned IsScatter : 1; - - /* - ** Special bonus scenario enabled. - */ - unsigned IsJurassic : 1; - - /* - ** Are score variations allowed? - */ - unsigned IsVariation : 1; - - /* - ** If the gross human splatter marks should be present. - */ - unsigned IsGross : 1; - - /* - ** Disables scrolling over the "options" and "sidebar" tabs. - */ - unsigned IsScrollMod : 1; - - /* - ** New anti-griefing early win mode. ST - 1/31/2020 3:42PM - */ - unsigned IsEarlyWin : 1; + union + { + uint32_t Bitfield; + + struct + { +#if HAVE_MS_BITFIELDS + /* + ** Is the game flagged for easy mode? + */ + unsigned IsEasy : 1; + + /* + ** Is the game flagged for difficult? + */ + unsigned IsDifficult : 1; + + /* + ** Controls the speedy build option -- used for testing. + */ + unsigned IsSpeedBuild : 1; + + /* + ** If the player can build the helipad separate from the helipad and + ** helicopter combo, then this flag will be true. + */ + unsigned IsSeparate : 1; + + /* + ** If the defender has the advantage then this will be true. This flag + ** allows the defender to have a better advantage in combat than the + ** attacker. Moving units will not be able to dish out or take as much + ** damage when this flag is true. + */ + unsigned IsDefenderAdvantage : 1; + + /* + ** If civilian structures are to have a name, then this flag will be + ** set to true. The default case is to just use generic names for + ** civilians. + */ + unsigned IsNamed : 1; + + /* + ** If from install, then play the special installation movie and + ** skip asking them what type of game they want to play. + */ + unsigned IsFromInstall : 1; + + /* + ** If capture the flag mode is on, this flag will be true. With this + ** flag enabled, then the flag is initially placed at the start of + ** the scenario. + */ + unsigned IsCaptureTheFlag : 1; + + /* + ** Is target selecting by other human opponents visible to the player? + */ + unsigned IsVisibleTarget : 1; + + /* + ** If human generated sound effects are to be used, then this + ** flag will be true. + */ + unsigned IsJuvenile : 1; + + /* + ** If friendly units should return fire when fired upon, set this + ** flag to true. The default is only for the enemy units to do this. + */ + unsigned IsSmartDefense : 1; + + /* + ** If targeting of trees is allowed, then this flag will be true. + */ + unsigned IsTreeTarget : 1; + + /* + ** If this flag is true, then the construction yard can undeploy back into an MCV. + */ + unsigned IsMCVDeploy : 1; + + /* + ** Controls whether or not visceroids spawn + */ + unsigned IsVisceroids : 1; + + /* + ** If the monochrome debugging output is enabled, then this flag will be true. + */ + unsigned IsMonoEnabled : 1; + + /* + ** This flags controls whether weapons are inert. An inert weapon doesn't do any + ** damage. Effectively, if this is true, then the units never die. + */ + unsigned IsInert : 1; + + /* + ** When this flag is true, the computer findpath algorithm reveals the route being + ** examined. This is used to trace findpath bugs. + */ + unsigned IsShowPath : 1; + + /* + ** If wheeled vehicles should do a 3-point turn when rotating in place, then + ** this flag is true. + */ + unsigned IsThreePoint : 1; + + /* + ** If Tiberium is allowed to grow, then this flag will be true. + */ + unsigned IsTGrowth : 1; + + /* + ** If Tiberium is allowed to spread, then this flag will be true. + */ + unsigned IsTSpread : 1; + + /* + ** This controls whether Tiberium grows&spreads quickly or not. + */ + unsigned IsTFast : 1; + + /* + ** This flag controls whether the road additional pieces are added to + ** the bottom of buildings. If true, then the roads are NOT added. + */ + unsigned IsRoad : 1; + + /* + ** Controls whether units (especially infantry) will scatter when there + ** is an immediate threat. This gives infantry a "mind of their own" when + ** it comes to self preservation. If set to false, then units will not + ** scatter. + */ + unsigned IsScatter : 1; + + /* + ** Special bonus scenario enabled. + */ + unsigned IsJurassic : 1; + + /* + ** Are score variations allowed? + */ + unsigned IsVariation : 1; + + /* + ** If the gross human splatter marks should be present. + */ + unsigned IsGross : 1; + + /* + ** Disables scrolling over the "options" and "sidebar" tabs. + */ + unsigned IsScrollMod : 1; + + /* + ** New anti-griefing early win mode. ST - 1/31/2020 3:42PM + */ + unsigned IsEarlyWin : 1; +#else + /* + ** simulate effects of attribute((ms_struct)) + */ +#ifdef __BIG_ENDIAN__ + unsigned : 4; + unsigned IsEarlyWin : 1; + unsigned IsScrollMod : 1; + unsigned IsGross : 1; + unsigned IsVariation : 1; + unsigned IsJurassic : 1; + unsigned IsScatter : 1; + unsigned IsRoad : 1; + unsigned IsTFast : 1; + unsigned IsTSpread : 1; + unsigned IsTGrowth : 1; + unsigned IsThreePoint : 1; + unsigned IsShowPath : 1; + unsigned IsInert : 1; + unsigned IsMonoEnabled : 1; + unsigned IsVisceroids : 1; + unsigned IsMCVDeploy : 1; + unsigned IsTreeTarget : 1; + unsigned IsSmartDefense : 1; + unsigned IsJuvenile : 1; + unsigned IsVisibleTarget : 1; + unsigned IsCaptureTheFlag : 1; + unsigned IsFromInstall : 1; + unsigned IsNamed : 1; + unsigned IsDefenderAdvantage : 1; + unsigned IsSeparate : 1; + unsigned IsSpeedBuild : 1; + unsigned IsDifficult : 1; + unsigned IsEasy : 1; +#else + unsigned IsEasy : 1; + unsigned IsDifficult : 1; + unsigned IsSpeedBuild : 1; + unsigned IsSeparate : 1; + unsigned IsDefenderAdvantage : 1; + unsigned IsNamed : 1; + unsigned IsFromInstall : 1; + unsigned IsCaptureTheFlag : 1; + unsigned IsVisibleTarget : 1; + unsigned IsJuvenile : 1; + unsigned IsSmartDefense : 1; + unsigned IsTreeTarget : 1; + unsigned IsMCVDeploy : 1; + unsigned IsVisceroids : 1; + unsigned IsMonoEnabled : 1; + unsigned IsInert : 1; + unsigned IsShowPath : 1; + unsigned IsThreePoint : 1; + unsigned IsTGrowth : 1; + unsigned IsTSpread : 1; + unsigned IsTFast : 1; + unsigned IsRoad : 1; + unsigned IsScatter : 1; + unsigned IsJurassic : 1; + unsigned IsVariation : 1; + unsigned IsGross : 1; + unsigned IsScrollMod : 1; + unsigned IsEarlyWin : 1; + unsigned : 4; +#endif +#endif + }; + }; /* ** Health bar display mode @@ -254,10 +330,31 @@ class BITFIELD_STRUCT SpecialClass RB_ALWAYS, } ResourceBarDisplayMode; - /* - ** New modern balance setting. - */ - unsigned ModernBalance : 1; + union + { + uint32_t Bitfield2; + + struct + { + /* + ** New modern balance setting. + */ +#if HAVE_MS_BITFIELDS + unsigned ModernBalance : 1; +#else + /* + ** simulate effects of attribute((ms_struct)) + */ +#ifdef __BIG_ENDIAN__ + unsigned : 31; + unsigned ModernBalance : 1; +#else + unsigned ModernBalance : 1; + unsigned : 31; +#endif +#endif + }; + }; /* ** Some additional padding in case we need to add data to the class and maintain backwards compatibility for @@ -271,4 +368,4 @@ class BITFIELD_STRUCT SpecialClass }; #pragma pack(pop) -#endif \ No newline at end of file +#endif