fix some endianness differences on GC/XB

This commit is contained in:
Martin Michelsen
2023-11-07 16:35:21 -08:00
parent d46e6de4f0
commit 01f3ed7bc6
2 changed files with 119 additions and 17 deletions
+36 -4
View File
@@ -3768,12 +3768,18 @@ struct G_Unknown_6x09 {
// 6x0A: Enemy hit
template <bool IsBigEndian>
struct G_EnemyHitByPlayer_6x0A {
G_EnemyIDHeader header;
// Note: enemy_id (in header) is in the range [0x1000, 0x4000)
le_uint16_t enemy_id = 0;
le_uint16_t remaining_hp = 0;
be_uint32_t flags = 0;
typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type flags = 0;
} __packed__;
struct G_EnemyHitByPlayer_GC_6x0A : G_EnemyHitByPlayer_6x0A<true> {
} __packed__;
struct G_EnemyHitByPlayer_DC_PC_XB_BB_6x0A : G_EnemyHitByPlayer_6x0A<false> {
} __packed__;
// 6x0B: Box destroyed
@@ -3814,7 +3820,22 @@ struct G_Unknown_6x10_6x11_6x12_6x14 {
// Same format as 6x10
// 6x12: Dragon boss actions (not valid on Episode 3)
// Same format as 6x10
template <bool IsBigEndian>
struct G_DragonBossActions_6x12 {
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
G_EnemyIDHeader header;
le_uint16_t unknown_a2 = 0;
le_uint16_t unknown_a3 = 0;
le_uint32_t unknown_a4 = 0;
F32T x = 0.0f;
F32T z = 0.0f;
} __packed__;
struct G_DragonBossActions_DC_PC_XB_BB_6x12 : G_DragonBossActions_6x12<false> {
} __packed__;
struct G_DragonBossActions_GC_6x12 : G_DragonBossActions_6x12<true> {
} __packed__;
// 6x13: De Rol Le boss actions (not valid on Episode 3)
@@ -5068,11 +5089,22 @@ struct G_ModifyTradeProposal_6xA6 {
// 6xA8: Gol Dragon boss actions (not valid on pre-V3 or Episode 3)
template <bool IsBigEndian>
struct G_GolDragonBossActions_6xA8 {
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
G_EnemyIDHeader header;
le_uint16_t unknown_a1 = 0;
le_uint16_t unknown_a2 = 0;
le_uint32_t unknown_a3 = 0;
le_uint16_t unknown_a3 = 0;
le_uint32_t unknown_a4 = 0;
F32T x = 0.0f;
F32T z = 0.0f;
uint8_t unknown_a5 = 0;
parray<uint8_t, 3> unused;
} __packed__;
struct G_GolDragonBossActions_XB_BB_6xA8 : G_GolDragonBossActions_6xA8<false> {
} __packed__;
struct G_GolDragonBossActions_GC_6xA8 : G_GolDragonBossActions_6xA8<true> {
} __packed__;
// 6xA9: Barba Ray boss actions (not valid on pre-V3 or Episode 3)
+83 -13
View File
@@ -729,7 +729,7 @@ static void on_player_drop_item(shared_ptr<Client> c, uint8_t command, uint8_t f
}
template <typename CmdT>
void forward_subcommand_with_mag_transcode_t(shared_ptr<Client> c, uint8_t command, uint8_t flag, const CmdT& cmd) {
void forward_subcommand_with_item_transcode_t(shared_ptr<Client> c, uint8_t command, uint8_t flag, const CmdT& cmd) {
// I'm lazy and this should never happen for item commands (since all players
// need to stay in sync)
if (command_is_private(command)) {
@@ -784,7 +784,7 @@ static void on_create_inventory_item_t(shared_ptr<Client> c, uint8_t command, ui
p->print_inventory(stderr, c->version(), s->item_name_index);
}
forward_subcommand_with_mag_transcode_t(c, command, flag, cmd);
forward_subcommand_with_item_transcode_t(c, command, flag, cmd);
}
static void on_create_inventory_item(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
@@ -830,7 +830,7 @@ static void on_drop_partial_stack_t(shared_ptr<Client> c, uint8_t command, uint8
c->game_data.player()->print_inventory(stderr, c->version(), s->item_name_index);
}
forward_subcommand_with_mag_transcode_t(c, command, flag, cmd);
forward_subcommand_with_item_transcode_t(c, command, flag, cmd);
}
static void on_drop_partial_stack(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
@@ -924,7 +924,7 @@ static void on_buy_shop_item(shared_ptr<Client> c, uint8_t command, uint8_t flag
p->print_inventory(stderr, c->version(), s->item_name_index);
}
forward_subcommand_with_mag_transcode_t(c, command, flag, cmd);
forward_subcommand_with_item_transcode_t(c, command, flag, cmd);
}
template <typename CmdT>
@@ -1547,14 +1547,74 @@ static void on_set_quest_flag(shared_ptr<Client> c, uint8_t command, uint8_t fla
}
}
static void on_enemy_hit(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->base_version == GameVersion::BB) {
const auto& cmd = check_size_t<G_EnemyHitByPlayer_6x0A>(data, size);
static void on_dragon_actions(shared_ptr<Client> c, uint8_t command, uint8_t, const void* data, size_t size) {
const auto& cmd = check_size_t<G_DragonBossActions_DC_PC_XB_BB_6x12>(data, size);
if (!l->is_game()) {
return;
if (command_is_private(command)) {
return;
}
auto l = c->require_lobby();
if (!l->is_game()) {
return;
}
G_DragonBossActions_GC_6x12 sw_cmd = {{{cmd.header.subcommand, cmd.header.size, cmd.header.enemy_id},
cmd.unknown_a2, cmd.unknown_a3, cmd.unknown_a4, cmd.x.load(), cmd.z.load()}};
bool sender_is_gc = (c->version() == GameVersion::GC);
for (auto lc : l->clients) {
if (lc && (lc != c)) {
if ((lc->version() == GameVersion::GC) == sender_is_gc) {
send_command_t(lc, 0x60, 0x00, cmd);
} else {
send_command_t(lc, 0x60, 0x00, sw_cmd);
}
}
}
}
static void on_gol_dragon_actions(shared_ptr<Client> c, uint8_t command, uint8_t, const void* data, size_t size) {
const auto& cmd = check_size_t<G_GolDragonBossActions_XB_BB_6xA8>(data, size);
if (command_is_private(command)) {
return;
}
auto l = c->require_lobby();
if (!l->is_game()) {
return;
}
G_GolDragonBossActions_GC_6xA8 sw_cmd = {{{cmd.header.subcommand, cmd.header.size, cmd.header.enemy_id},
cmd.unknown_a2,
cmd.unknown_a3,
cmd.unknown_a4,
cmd.x.load(),
cmd.z.load(),
cmd.unknown_a5,
0}};
bool sender_is_gc = (c->version() == GameVersion::GC);
for (auto lc : l->clients) {
if (lc && (lc != c)) {
if ((lc->version() == GameVersion::GC) == sender_is_gc) {
send_command_t(lc, 0x60, 0x00, cmd);
} else {
send_command_t(lc, 0x60, 0x00, sw_cmd);
}
}
}
}
static void on_enemy_hit(shared_ptr<Client> c, uint8_t command, uint8_t, const void* data, size_t size) {
const auto& cmd = check_size_t<G_EnemyHitByPlayer_DC_PC_XB_BB_6x0A>(data, size);
if (command_is_private(command)) {
return;
}
auto l = c->require_lobby();
if (!l->is_game()) {
return;
}
if (l->base_version == GameVersion::BB) {
if (c->lobby_client_id > 3) {
throw logic_error("client ID is above 3");
}
@@ -1573,7 +1633,17 @@ static void on_enemy_hit(shared_ptr<Client> c, uint8_t command, uint8_t flag, co
enemy.last_hit_by_client_id = c->lobby_client_id;
}
forward_subcommand(c, command, flag, data, size);
G_EnemyHitByPlayer_GC_6x0A sw_cmd = {{{cmd.header.subcommand, cmd.header.size, cmd.header.enemy_id}, cmd.enemy_id, cmd.remaining_hp, cmd.flags.load()}};
bool sender_is_gc = (c->version() == GameVersion::GC);
for (auto lc : l->clients) {
if (lc && (lc != c)) {
if ((lc->version() == GameVersion::GC) == sender_is_gc) {
send_command_t(lc, 0x60, 0x00, cmd);
} else {
send_command_t(lc, 0x60, 0x00, sw_cmd);
}
}
}
}
static void on_charge_attack_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
@@ -2225,7 +2295,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
/* 6x0F */ nullptr,
/* 6x10 */ nullptr,
/* 6x11 */ nullptr,
/* 6x12 */ on_forward_check_size_game,
/* 6x12 */ on_dragon_actions,
/* 6x13 */ on_forward_check_size_game,
/* 6x14 */ on_forward_check_size_game,
/* 6x15 */ on_forward_check_size_game,
@@ -2375,7 +2445,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
/* 6xA5 */ on_forward_check_size_game,
/* 6xA6 */ on_forward_check_size,
/* 6xA7 */ nullptr,
/* 6xA8 */ on_forward_check_size_game,
/* 6xA8 */ on_gol_dragon_actions,
/* 6xA9 */ on_forward_check_size_game,
/* 6xAA */ on_forward_check_size_game,
/* 6xAB */ on_forward_check_size_client,