Skip to content

Commit

Permalink
attribute(ms_struct) is only valid for x86
Browse files Browse the repository at this point in the history
  • Loading branch information
th-otto committed Mar 24, 2024
1 parent 77e2da0 commit b6699ff
Show file tree
Hide file tree
Showing 12 changed files with 535 additions and 212 deletions.
9 changes: 7 additions & 2 deletions common/bitfields.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
6 changes: 2 additions & 4 deletions common/combuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 *****************************
Expand Down
4 changes: 1 addition & 3 deletions redalert/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -554,7 +553,6 @@ typedef union
#endif
} Sub;
} TARGET_COMPOSITE;
#pragma pack(pop)
inline TARGET Build_Target(RTTIType kind, int value)
{
TARGET_COMPOSITE target;
Expand Down
1 change: 1 addition & 0 deletions redalert/ipxgconn.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ typedef struct
{
CommHeaderType Header;
unsigned short ProductID;
unsigned short pad;
} GlobalHeaderType;

inline void SwapGlobalHeaderType(GlobalHeaderType* ght)
Expand Down
51 changes: 36 additions & 15 deletions redalert/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions redalert/special.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
#endif
12 changes: 12 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,15 @@ target_include_directories(test_drawbuff PUBLIC .. ../common)
target_compile_definitions(test_drawbuff PUBLIC TRUE_FALSE_DEFINED ENGLISH $<$<CONFIG:DEBUG>:_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} $<TARGET_FILE:test_drawbuff>)

add_executable(test_structsizetd structsizetd.cpp)
target_compile_definitions(test_structsizetd PUBLIC $<$<CONFIG:Debug>:_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} $<TARGET_FILE:test_structsizetd>)

add_executable(test_structsizera structsizera.cpp)
target_compile_definitions(test_structsizera PUBLIC $<$<CONFIG:Debug>:_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} $<TARGET_FILE:test_structsizera>)
1 change: 0 additions & 1 deletion tests/drawbuff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
bool GameInFocus;
int ScreenWidth;
int WindowList[9][9];
extern "C" char* _ShapeBuffer = 0;
WWKeyboardClass* Keyboard;

void Process_Network()
Expand Down
72 changes: 72 additions & 0 deletions tests/structsizera.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "redalert/function.h"

#include <stdint.h>
#include <string.h>
#include <stdio.h>

#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;
}
74 changes: 74 additions & 0 deletions tests/structsizetd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "tiberiandawn/function.h"
#include "tiberiandawn/tile.h"

#include <stdint.h>
#include <string.h>
#include <stdio.h>

#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;
}
Loading

0 comments on commit b6699ff

Please sign in to comment.