add __packed_ws_be__

This commit is contained in:
Martin Michelsen
2026-04-26 17:55:39 -07:00
parent 80391df8b7
commit 826eb88e2e
15 changed files with 41 additions and 100 deletions
+2 -6
View File
@@ -14,11 +14,9 @@ struct BMLHeaderT {
parray<uint8_t, 0x04> unknown_a1;
U32T<BE> num_entries;
parray<uint8_t, 0x38> unknown_a2;
} __attribute__((packed));
} __packed_ws_be__(BMLHeaderT, 0x40);
using BMLHeader = BMLHeaderT<false>;
using BMLHeaderBE = BMLHeaderT<true>;
check_struct_size(BMLHeader, 0x40);
check_struct_size(BMLHeaderBE, 0x40);
template <bool BE>
struct BMLHeaderEntryT {
@@ -29,11 +27,9 @@ struct BMLHeaderEntryT {
U32T<BE> compressed_gvm_size;
U32T<BE> decompressed_gvm_size;
parray<uint8_t, 0x0C> unknown_a2;
} __attribute__((packed));
} __packed_ws_be__(BMLHeaderEntryT, 0x40);
using BMLHeaderEntry = BMLHeaderEntryT<false>;
using BMLHeaderEntryBE = BMLHeaderEntryT<true>;
check_struct_size(BMLHeaderEntry, 0x40);
check_struct_size(BMLHeaderEntryBE, 0x40);
template <bool BE>
void BMLArchive::load_t() {
+1 -3
View File
@@ -40,11 +40,9 @@ struct ChoiceSearchConfigT {
}
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(ChoiceSearchConfigT, 0x18);
using ChoiceSearchConfig = ChoiceSearchConfigT<false>;
using ChoiceSearchConfigBE = ChoiceSearchConfigT<true>;
check_struct_size(ChoiceSearchConfig, 0x18);
check_struct_size(ChoiceSearchConfigBE, 0x18);
struct ChoiceSearchCategory {
struct Choice {
+11 -23
View File
@@ -251,14 +251,13 @@ struct S_StartFileDownloads_Patch_11 {
// 14 (S->C): Reconnect
// Same format and usage as command 19 on the game server (described below), except the port field is big-endian.
template <typename PortT>
template <bool BE>
struct S_ReconnectT {
be_uint32_t address = 0;
PortT port = 0;
U16T<BE> port = 0;
le_uint16_t unused = 0;
} __attribute__((packed));
using S_Reconnect_Patch_14 = S_ReconnectT<be_uint16_t>;
check_struct_size(S_Reconnect_Patch_14, 0x08);
} __packed_ws_be__(S_ReconnectT, 0x08);
using S_Reconnect_Patch_14 = S_ReconnectT<false>;
// 15 (S->C): Login failure
// No arguments. The client shows a message like "Incorrect game ID or password" and disconnects.
@@ -724,8 +723,7 @@ struct C_WriteFileConfirmation_V3_BB_13_A7 {
// connection; the server should send an appropriate command to enable it when the client connects. PSO Xbox seems to
// ignore the address field, which makes sense given its networking architecture.
using S_Reconnect_19 = S_ReconnectT<le_uint16_t>;
check_struct_size(S_Reconnect_19, 8);
using S_Reconnect_19 = S_ReconnectT<false>;
// Sylverant implements an IPv6 version of this command, but it's not obvious why. IPv6 technically did exist as a
// draft standard at the time of PSO's development, but it wasn't widely used until over a decade later. IPv6 support
@@ -3767,12 +3765,10 @@ struct G_UpdateEnemyStateT_6x0A {
// 40000000 = entity is object (some entities have both this and 20000000 set; this appears to make TWindowLockOn
// not show anything but the entity is still attackable, see TWindowLockOn_should_show_for_entity)
// 80000000 = entity is item
typename std::conditional_t<BE, be_uint32_t, le_uint32_t> game_flags = 0;
} __attribute__((packed));
U32T<BE> game_flags = 0;
} __packed_ws_be__(G_UpdateEnemyStateT_6x0A, 0x0C);
using G_UpdateEnemyState_GC_6x0A = G_UpdateEnemyStateT_6x0A<true>;
using G_UpdateEnemyState_DC_PC_XB_BB_6x0A = G_UpdateEnemyStateT_6x0A<false>;
check_struct_size(G_UpdateEnemyState_GC_6x0A, 0x0C);
check_struct_size(G_UpdateEnemyState_DC_PC_XB_BB_6x0A, 0x0C);
// 6x0B: Update object state
@@ -3838,11 +3834,9 @@ struct G_DragonBossActionsT_6x12 {
le_uint32_t target_client_id = 0xFFFF; // 0xFFFF (not 0xFFFFFFFF) means no target
F32T<BE> x = 0.0f;
F32T<BE> z = 0.0f;
} __attribute__((packed));
} __packed_ws_be__(G_DragonBossActionsT_6x12, 0x14);
using G_DragonBossActions_DC_PC_XB_BB_6x12 = G_DragonBossActionsT_6x12<false>;
using G_DragonBossActions_GC_6x12 = G_DragonBossActionsT_6x12<true>;
check_struct_size(G_DragonBossActions_DC_PC_XB_BB_6x12, 0x14);
check_struct_size(G_DragonBossActions_GC_6x12, 0x14);
// 6x13: De Rol Le boss actions (not valid on Episode 3)
@@ -4875,11 +4869,9 @@ struct G_WordSelectT_6x74 {
uint8_t size = 0;
U16T<BE> client_id = 0;
WordSelectMessage message;
} __attribute__((packed));
} __packed_ws_be__(G_WordSelectT_6x74, 0x20);
using G_WordSelect_6x74 = G_WordSelectT_6x74<false>;
using G_WordSelectBE_6x74 = G_WordSelectT_6x74<true>;
check_struct_size(G_WordSelect_6x74, 0x20);
check_struct_size(G_WordSelectBE_6x74, 0x20);
// 6x75: Update quest flag
// This command does nothing on Episode 3.
@@ -5007,11 +4999,9 @@ struct G_BattleScoresT_6x7F {
} __packed_ws__(Entry, 8);
G_UnusedHeader header;
parray<Entry, 4> entries;
} __attribute__((packed));
} __packed_ws_be__(G_BattleScoresT_6x7F, 0x24);
using G_BattleScores_6x7F = G_BattleScoresT_6x7F<false>;
using G_BattleScoresBE_6x7F = G_BattleScoresT_6x7F<true>;
check_struct_size(G_BattleScores_6x7F, 0x24);
check_struct_size(G_BattleScoresBE_6x7F, 0x24);
// 6x80: Trigger trap (not valid on Episode 3)
@@ -5370,11 +5360,9 @@ struct G_GolDragonBossActionsT_6xA8 {
F32T<BE> z = 0.0f;
uint8_t unknown_a5 = 0;
parray<uint8_t, 3> unused;
} __attribute__((packed));
} __packed_ws_be__(G_GolDragonBossActionsT_6xA8, 0x18);
using G_GolDragonBossActions_XB_BB_6xA8 = G_GolDragonBossActionsT_6xA8<false>;
using G_GolDragonBossActions_GC_6xA8 = G_GolDragonBossActionsT_6xA8<true>;
check_struct_size(G_GolDragonBossActions_XB_BB_6xA8, 0x18);
check_struct_size(G_GolDragonBossActions_GC_6xA8, 0x18);
// 6xA9: Barba Ray boss actions (not valid on pre-V3 or Episode 3)
+2 -6
View File
@@ -131,11 +131,9 @@ struct ArrayRefT {
/* 00 */ U32T<BE> count;
/* 04 */ U32T<BE> offset;
/* 08 */
} __attribute__((packed));
} __packed_ws_be__(ArrayRefT, 8);
using ArrayRef = ArrayRefT<false>;
using ArrayRefBE = ArrayRefT<true>;
check_struct_size(ArrayRef, 8);
check_struct_size(ArrayRefBE, 8);
template <bool BE>
struct RELFileFooterT {
@@ -159,8 +157,6 @@ struct RELFileFooterT {
parray<U32T<BE>, 2> unused1;
U32T<BE> root_offset = 0;
parray<U32T<BE>, 3> unused2;
} __attribute__((packed));
} __packed_ws_be__(RELFileFooterT, 0x20);
using RELFileFooter = RELFileFooterT<false>;
using RELFileFooterBE = RELFileFooterT<true>;
check_struct_size(RELFileFooter, 0x20);
check_struct_size(RELFileFooterBE, 0x20);
+1 -4
View File
@@ -244,11 +244,9 @@ public:
/* 50 */ U32T<BE> box_item_class_prob_table_offset;
// There are several unused fields here.
} __attribute__((packed));
} __packed_ws_be__(OffsetsT, 0x54);
using Offsets = OffsetsT<false>;
using OffsetsBE = OffsetsT<true>;
check_struct_size(Offsets, 0x54);
check_struct_size(OffsetsBE, 0x54);
};
bool operator==(const CommonItemSet& other) const = default;
@@ -337,7 +335,6 @@ public:
ValueT value;
WeightT weight;
} __attribute__((packed));
using WeightTableEntry8 = WeightTableEntry<uint8_t>;
using WeightTableEntry32 = WeightTableEntry<be_uint32_t>;
check_struct_size(WeightTableEntry8, 2);
+1 -4
View File
@@ -15,12 +15,9 @@ struct GSLHeaderEntryT {
U32T<BE> offset; // In pages, so actual offset is this * 0x800
U32T<BE> size;
uint64_t unused;
} __attribute__((packed));
} __packed_ws_be__(GSLHeaderEntryT, 0x30);
using GSLHeaderEntry = GSLHeaderEntryT<false>;
using GSLHeaderEntryBE = GSLHeaderEntryT<true>;
check_struct_size(GSLHeaderEntry, 0x30);
check_struct_size(GSLHeaderEntryBE, 0x30);
template <bool BE>
void GSLArchive::load_t() {
+3 -9
View File
@@ -33,11 +33,9 @@ struct CharacterStatsT {
ret.lck = this->lck;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(CharacterStatsT, 0x0E);
using CharacterStats = CharacterStatsT<false>;
using CharacterStatsBE = CharacterStatsT<true>;
check_struct_size(CharacterStats, 0x0E);
check_struct_size(CharacterStatsBE, 0x0E);
template <bool BE>
struct PlayerStatsT {
@@ -61,11 +59,9 @@ struct PlayerStatsT {
ret.meseta = this->meseta;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(PlayerStatsT, 0x24);
using PlayerStats = PlayerStatsT<false>;
using PlayerStatsBE = PlayerStatsT<true>;
check_struct_size(PlayerStats, 0x24);
check_struct_size(PlayerStatsBE, 0x24);
template <bool BE>
struct LevelStatsDeltaT {
@@ -89,11 +85,9 @@ struct LevelStatsDeltaT {
ps.mst += this->mst;
ps.lck += this->lck;
}
} __attribute__((packed));
} __packed_ws_be__(LevelStatsDeltaT, 0x0C);
using LevelStatsDelta = LevelStatsDeltaT<false>;
using LevelStatsDeltaBE = LevelStatsDeltaT<true>;
check_struct_size(LevelStatsDelta, 0x0C);
check_struct_size(LevelStatsDeltaBE, 0x0C);
class LevelTable {
// This is the base class for all the LevelTable implementations. The public interface here only defines functions
+1 -3
View File
@@ -343,11 +343,9 @@ public:
ret.store_raw(this->value);
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(ChallengeTimeT, 4);
using ChallengeTime = ChallengeTimeT<false>;
using ChallengeTimeBE = ChallengeTimeT<true>;
check_struct_size(ChallengeTime, 4);
check_struct_size(ChallengeTimeBE, 4);
std::string decrypt_v2_registry_value(const void* data, size_t size);
+3 -9
View File
@@ -76,11 +76,9 @@ struct PlayerInventoryItemT {
bool is_equipped() const {
return (this->flags & 8);
}
} __attribute__((packed));
} __packed_ws_be__(PlayerInventoryItemT, 0x1C);
using PlayerInventoryItem = PlayerInventoryItemT<false>;
using PlayerInventoryItemBE = PlayerInventoryItemT<true>;
check_struct_size(PlayerInventoryItem, 0x1C);
check_struct_size(PlayerInventoryItemBE, 0x1C);
template <bool BE>
struct PlayerBankItemT {
@@ -100,11 +98,9 @@ struct PlayerBankItemT {
ret.present = this->present;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(PlayerBankItemT, 0x18);
using PlayerBankItem = PlayerBankItemT<false>;
using PlayerBankItemBE = PlayerBankItemT<true>;
check_struct_size(PlayerBankItem, 0x18);
check_struct_size(PlayerBankItemBE, 0x18);
template <bool BE>
struct PlayerInventoryT {
@@ -291,11 +287,9 @@ struct PlayerInventoryT {
ret.items = this->items;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(PlayerInventoryT, 0x34C);
using PlayerInventory = PlayerInventoryT<false>;
using PlayerInventoryBE = PlayerInventoryT<true>;
check_struct_size(PlayerInventory, 0x34C);
check_struct_size(PlayerInventoryBE, 0x34C);
template <size_t SlotCount, bool BE>
struct PlayerBankT {
+7 -20
View File
@@ -312,11 +312,9 @@ struct PlayerVisualConfigT {
ret.proportion_y = this->proportion_y;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(PlayerVisualConfigT, 0x50);
using PlayerVisualConfig = PlayerVisualConfigT<false>;
using PlayerVisualConfigBE = PlayerVisualConfigT<true>;
check_struct_size(PlayerVisualConfig, 0x50);
check_struct_size(PlayerVisualConfigBE, 0x50);
template <bool BE>
struct PlayerDispDataDCPCV3T {
@@ -331,11 +329,9 @@ struct PlayerDispDataDCPCV3T {
}
PlayerDispDataBB to_bb(Language to_language, Language from_language) const;
} __attribute__((packed));
} __packed_ws_be__(PlayerDispDataDCPCV3T, 0xD0);
using PlayerDispDataDCPCV3 = PlayerDispDataDCPCV3T<false>;
using PlayerDispDataDCPCV3BE = PlayerDispDataDCPCV3T<true>;
check_struct_size(PlayerDispDataDCPCV3, 0xD0);
check_struct_size(PlayerDispDataDCPCV3BE, 0xD0);
struct PlayerDispDataBBPreview {
/* 00 */ le_uint32_t experience = 0;
@@ -598,11 +594,9 @@ struct ChallengeAwardStateT {
ret.maximum_rank = this->maximum_rank;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(ChallengeAwardStateT, 8);
using ChallengeAwardState = ChallengeAwardStateT<false>;
using ChallengeAwardStateBE = ChallengeAwardStateT<true>;
check_struct_size(ChallengeAwardState, 8);
check_struct_size(ChallengeAwardStateBE, 8);
template <TextEncoding UnencryptedEncoding, TextEncoding EncryptedEncoding>
struct PlayerRecordsChallengeDCPCT {
@@ -673,11 +667,9 @@ struct PlayerRecordsChallengeV3T {
/* 00D8:00F4 */ pstring<TextEncoding::CHALLENGE8, 0x0C> rank_title;
/* 00E4:0100 */ parray<uint8_t, 0x1C> unknown_l7;
/* 0100:011C */
} __attribute__((packed));
} __packed_ws_be__(PlayerRecordsChallengeV3T, 0x100);
using PlayerRecordsChallengeV3 = PlayerRecordsChallengeV3T<false>;
using PlayerRecordsChallengeV3BE = PlayerRecordsChallengeV3T<true>;
check_struct_size(PlayerRecordsChallengeV3, 0x100);
check_struct_size(PlayerRecordsChallengeV3BE, 0x100);
struct PlayerRecordsChallengeEp3 {
/* 00:1C */ be_uint16_t title_color = 0x7FFF; // XRGB1555
@@ -704,8 +696,7 @@ struct PlayerRecordsChallengeEp3 {
/* C8:E4 */ ChallengeAwardStateT<true> ep2_online_award_state;
/* D0:EC */ ChallengeAwardStateT<true> ep1_offline_award_state;
/* D8:F4 */
} __attribute__((packed));
check_struct_size(PlayerRecordsChallengeEp3, 0xD8);
} __packed_ws__(PlayerRecordsChallengeEp3, 0xD8);
struct PlayerRecordsChallengeBB {
/* 0000 */ le_uint16_t title_color = 0x7FFF; // XRGB1555
@@ -833,11 +824,9 @@ struct PlayerRecordsBattleT {
}
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(PlayerRecordsBattleT, 0x18);
using PlayerRecordsBattle = PlayerRecordsBattleT<false>;
using PlayerRecordsBattleBE = PlayerRecordsBattleT<true>;
check_struct_size(PlayerRecordsBattle, 0x18);
check_struct_size(PlayerRecordsBattleBE, 0x18);
template <typename DestT, typename SrcT = DestT>
DestT convert_player_disp_data(const SrcT&, Language, Language) {
@@ -1112,11 +1101,9 @@ struct SymbolChatT {
ret.face_parts = this->face_parts;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(SymbolChatT, 0x3C);
using SymbolChat = SymbolChatT<false>;
using SymbolChatBE = SymbolChatT<true>;
check_struct_size(SymbolChat, 0x3C);
check_struct_size(SymbolChatBE, 0x3C);
struct TelepipeState {
/* 00 */ le_uint16_t owner_client_id = 0xFFFF;
+1 -3
View File
@@ -51,11 +51,9 @@ struct PSOMemCardDLQFileEncryptedHeaderT {
le_uint32_t decompressed_size;
le_uint32_t round3_seed;
// Data follows here.
} __attribute__((packed));
} __packed_ws_be__(PSOMemCardDLQFileEncryptedHeaderT, 0x10);
using PSOVMSDLQFileEncryptedHeader = PSOMemCardDLQFileEncryptedHeaderT<false>;
using PSOGCIDLQFileEncryptedHeader = PSOMemCardDLQFileEncryptedHeaderT<true>;
check_struct_size(PSOVMSDLQFileEncryptedHeader, 0x10);
check_struct_size(PSOGCIDLQFileEncryptedHeader, 0x10);
template <bool BE>
string decrypt_download_quest_data_section(
+1 -3
View File
@@ -93,11 +93,9 @@ protected:
/* 08 */ U32T<BE> box_areas_offset; // -> parray<uint8_t, 0x1E>
/* 0C */ U32T<BE> box_rares_offset; // -> parray<PackedDrop, 0x1E>
/* 10 */
} __attribute__((packed));
} __packed_ws_be__(OffsetsT, 0x10);
using Offsets = OffsetsT<false>;
using OffsetsBE = OffsetsT<true>;
check_struct_size(Offsets, 0x10);
check_struct_size(OffsetsBE, 0x10);
struct BoxRare {
uint8_t area_norm_plus_1;
+1 -3
View File
@@ -158,11 +158,9 @@ struct WordSelectMessageT {
ret.unknown_a4 = this->unknown_a4;
return ret;
}
} __attribute__((packed));
} __packed_ws_be__(WordSelectMessageT, 0x1C);
using WordSelectMessage = WordSelectMessageT<false>;
using WordSelectMessageBE = WordSelectMessageT<true>;
check_struct_size(WordSelectMessage, 0x1C);
check_struct_size(WordSelectMessageBE, 0x1C);
template <bool BE, TextEncoding Encoding, size_t MaxChars>
struct SaveFileChatShortcutEntryT {
+5
View File
@@ -23,6 +23,11 @@
__attribute__((packed)); \
check_struct_size(StructT, Size)
#define __packed_ws_be__(StructT, Size) \
__attribute__((packed)); \
check_struct_size(StructT<false>, Size); \
check_struct_size(StructT<true>, Size)
// Conversion functions
std::string encode_utf8_char(uint32_t ch);
+1 -4
View File
@@ -40,12 +40,9 @@ struct NonWindowsRootT {
U32T<BE> table4;
U32T<BE> article_types_table;
U32T<BE> table6;
} __attribute__((packed));
} __packed_ws_be__(NonWindowsRootT, 0x1C);
using NonWindowsRoot = NonWindowsRootT<false>;
using NonWindowsRootBE = NonWindowsRootT<true>;
check_struct_size(NonWindowsRoot, 0x1C);
check_struct_size(NonWindowsRootBE, 0x1C);
struct PCV2Root {
le_uint32_t unknown_a1;