From 1f357bb6afb918d4cf333f5aab87d4751fbfa6af Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Wed, 17 May 2023 15:07:28 -0300 Subject: TProtocol: Add (and match) the `SndPsoData` related command senders, along with a few other senders Man, those `SndPsoData` functions took way longer then they should've to figure out, mostly due to typecasting, and general weirdness. --- context.h | 108 +++++++++++++++++++++++++++++-- include/pso/TProtocol.h | 14 ++++ include/pso/packet_classes.h | 94 +++++++++++++++++++++++++-- src/pso/TProtocol.cpp | 151 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 355 insertions(+), 12 deletions(-) diff --git a/context.h b/context.h index cfc430d..fff939a 100644 --- a/context.h +++ b/context.h @@ -899,8 +899,8 @@ struct send_buffs { // pso/packet_classes.h struct game_command_header { - u8 command; - u8 size; + char command; + char size; u16 id; void bswap() { @@ -918,6 +918,24 @@ struct extended_game_command_header { }; }; +struct long_game_command { + game_command_header header; + u8 data[1460-sizeof(game_command_header)]; + + void bswap() { + header.bswap(); + }; +}; + +struct extended_long_game_command { + extended_game_command_header header; + u8 data[1460-sizeof(extended_game_command_header)]; + + void bswap() { + header.bswap(); + }; +}; + struct game_command { game_command_header header; u8 data[1024-sizeof(game_command_header)]; @@ -973,6 +991,12 @@ union game_command_union { u8 bytes[1024]; }; +union long_game_command_union { + struct long_game_command game_cmd; + struct extended_long_game_command ext_game_cmd; + u8 bytes[1460]; +}; + // pso/TObject.h // Enum defs. enum object_flags { @@ -1402,6 +1426,47 @@ public: }; // pso/packet_classes.h +class TCreateGame { +public: + packet_header header; + TPlyGuildCardTag tag; + char name[16]; + char password[16]; + u8 difficulty; + u8 battle_mode; + u8 challenge_mode; + u8 episode; +public: + void bswap() { + header.bswap(); + tag.bswap(); + }; +}; + +class TFindUser { +public: + packet_header header; + TPlyGuildCardTag tag; + u32 target_gc; +public: + void bswap() { + header.bswap(); + tag.bswap(); + bswap_32(&target_gc); + }; +}; + +class TRoomChange { +public: + packet_header header; + TPlyGuildCardTag tag; +public: + void bswap() { + header.bswap(); + tag.bswap(); + }; +}; + class TRegister { public: packet_header header; @@ -1509,11 +1574,32 @@ public: }; }; -class TPsoData { +class TPsoDataBuf { +public: + void recv_pso_data_buf(size_t size) {}; +}; + +class TPsoDataLong : public TPsoDataBuf { +public: + union { + union long_game_command_union pkt; + u8 bytes[0x8000]; + }; +}; + +class TPsoData : public TPsoDataBuf { public: union game_command_union pkt; +}; + +class TRecvPsoDataLong { public: - void recv_pso_data_buf(size_t size) {}; + packet_header header; + TPsoDataLong data; +public: + void bswap() { + header.bswap(); + }; }; class TRecvPsoData { @@ -1833,4 +1919,18 @@ public: void send_text_list(); // 0x61 void send_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board); + // 0x98 + void send_update_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board); + // 0x60 + void send_pso_data(game_command &packet, u32 size); + // 0x62 + void send_pso_data2(u32 flags, game_command &packet, u32 size); + // 0x6D + void send_pso_data_long2(char flags, long_game_command &packet, size_t size); + // 0x84 + void send_room_change(int idx); + // 0x40 + void send_find_user(TPlyGuildCardTag &tag, u32 gc_num); + // 0xC1 + void send_create_game(char *name, char *password, u8 difficulty, u8 battle_mode, u8 challenge_mode, u8 episode); }; diff --git a/include/pso/TProtocol.h b/include/pso/TProtocol.h index 98976b7..ca80ffe 100644 --- a/include/pso/TProtocol.h +++ b/include/pso/TProtocol.h @@ -266,6 +266,20 @@ public: void send_text_list(); // 0x61 void send_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board); + // 0x98 + void send_update_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board); + // 0x60 + void send_pso_data(game_command &packet, u32 size); + // 0x62 + void send_pso_data2(u32 flags, game_command &packet, u32 size); + // 0x6D + void send_pso_data_long2(char flags, long_game_command &packet, size_t size); + // 0x84 + void send_room_change(int idx); + // 0x40 + void send_find_user(TPlyGuildCardTag &tag, u32 gc_num); + // 0xC1 + void send_create_game(char *name, char *password, u8 difficulty, u8 battle_mode, u8 challenge_mode, u8 episode); }; #endif diff --git a/include/pso/packet_classes.h b/include/pso/packet_classes.h index e0a78bd..d49c49a 100644 --- a/include/pso/packet_classes.h +++ b/include/pso/packet_classes.h @@ -25,8 +25,8 @@ struct TPlyText { }; struct game_command_header { - u8 command; - u8 size; + char command; + char size; u16 id; void bswap() { @@ -44,6 +44,24 @@ struct extended_game_command_header { }; }; +struct long_game_command { + game_command_header header; + u8 data[1460-sizeof(game_command_header)]; + + void bswap() { + header.bswap(); + }; +}; + +struct extended_long_game_command { + extended_game_command_header header; + u8 data[1460-sizeof(extended_game_command_header)]; + + void bswap() { + header.bswap(); + }; +}; + struct game_command { game_command_header header; u8 data[1024-sizeof(game_command_header)]; @@ -85,6 +103,53 @@ union game_command_union { u8 bytes[1024]; }; +union long_game_command_union { + struct long_game_command game_cmd; + struct extended_long_game_command ext_game_cmd; + u8 bytes[1460]; +}; + +class TCreateGame { +public: + packet_header header; + TPlyGuildCardTag tag; + char name[16]; + char password[16]; + u8 difficulty; + u8 battle_mode; + u8 challenge_mode; + u8 episode; +public: + void bswap() { + header.bswap(); + tag.bswap(); + }; +}; + +class TFindUser { +public: + packet_header header; + TPlyGuildCardTag tag; + u32 target_gc; +public: + void bswap() { + header.bswap(); + tag.bswap(); + bswap_32(&target_gc); + }; +}; + +class TRoomChange { +public: + packet_header header; + TPlyGuildCardTag tag; +public: + void bswap() { + header.bswap(); + tag.bswap(); + }; +}; + class TBlockedSenders { public: packet_header header; @@ -275,11 +340,32 @@ public: }; }; -class TPsoData { +class TPsoDataBuf { +public: + void recv_pso_data_buf(size_t size) {}; +}; + +class TPsoDataLong : public TPsoDataBuf { +public: + union { + union long_game_command_union pkt; + u8 bytes[0x8000]; + }; +}; + +class TPsoData : public TPsoDataBuf { public: union game_command_union pkt; +}; + +class TRecvPsoDataLong { public: - void recv_pso_data_buf(size_t size) {}; + packet_header header; + TPsoDataLong data; +public: + void bswap() { + header.bswap(); + }; }; class TRecvPsoData { diff --git a/src/pso/TProtocol.cpp b/src/pso/TProtocol.cpp index 3b7cbd3..3c410aa 100644 --- a/src/pso/TProtocol.cpp +++ b/src/pso/TProtocol.cpp @@ -24,6 +24,149 @@ void copy_packet(struct packet *pkt) { } +void TProtocol::send_create_game(char *name, char *password, u8 difficulty, u8 battle_mode, u8 challenge_mode, u8 episode) { + if (m_connected) { + TCreateGame tmp; + tmp.header.command = 0xC1; + tmp.header.flags = 3; + tmp.header.size = sizeof(tmp); + tmp.tag = TPlyGuildCardTag(0, 0); + tmp.difficulty = difficulty; + tmp.battle_mode = battle_mode; + tmp.challenge_mode = challenge_mode; + tmp.episode = episode; + strncpy(tmp.name, name, sizeof(tmp.name)); + strncpy(tmp.password, password, sizeof(tmp.password)); + tmp.bswap(); + send(as(u8 *, &tmp), sizeof(tmp)); + } +} + +void TProtocol::send_find_user(TPlyGuildCardTag &tag, u32 gc_num) { + if (m_connected) { + TFindUser tmp; + memset(&tmp, 0, sizeof(tmp)); + tmp.header.command = 0x40; + tmp.header.size = sizeof(tmp); + tmp.tag = tag; + tmp.target_gc = gc_num; + tmp.bswap(); + send(as(u8 *, &tmp), sizeof(tmp)); + } +} + +void TProtocol::send_room_change(int idx) { + if (m_connected) { + TRoomChange tmp; + tmp.header.command = 0x84; + tmp.header.flags = 0; + tmp.header.size = sizeof(tmp); + tmp.tag = m_lobby_entries[idx].tag; + tmp.bswap(); + send(as(u8 *, &tmp), sizeof(tmp)); + } +} + +void TProtocol::send_pso_data_long2(char flags, long_game_command &packet, size_t size) { + const int header_size = sizeof(packet_header); + const int command_size = sizeof(long_game_command); + if (m_connected) { + TRecvPsoDataLong *tmp = new TRecvPsoDataLong; + u8 *pkt = as(u8 *, tmp); + int packet_size; + int cmd_count; + int leftover; + int offset; + + memcpy(tmp->data.bytes, &packet, size); + tmp->header.command = 0x6d; + tmp->header.flags = flags; + tmp->header.size = size + header_size; + tmp->bswap(); + + packet_size = (int)size + header_size; + cmd_count = packet_size/command_size; + leftover = packet_size - (cmd_count * command_size); + + for (offset = 0; cmd_count > 0; --cmd_count, offset += command_size) { + if (test_connection()) { + goto end; + } else { + send(&pkt[offset], command_size); + } + } + + if (!test_connection() && leftover > 0) { + send(&pkt[offset], leftover); + } + + end: + delete tmp; + } +} + +void TProtocol::send_pso_data2(u32 flags, game_command &packet, u32 size) { + char tmp_str[128]; + sprintf(tmp_str, "SndPsoData2 %d %d %d", packet.header.command, size, flags); + if (m_connected) { + TRecvPsoData tmp; + int packet_size; + packet_size = (u16)(size + sizeof(packet_header)); + tmp.header.command = 0x62; + tmp.header.flags = flags; + packet_size = (u16)(size + sizeof(packet_header)); + tmp.header.size = packet_size; + memcpy(&tmp.data, &packet, size); + tmp.bswap(); + send(as(u8 *, &tmp), packet_size); + } +} + +void TProtocol::send_pso_data(game_command &packet, u32 size) { + char tmp_str[128]; + sprintf(tmp_str, "SndPsoData %d %d", packet.header.command, size); + if (m_connected) { + TRecvPsoData tmp; + int packet_size; + tmp.header.command = 0x60; + tmp.header.flags = 0; + packet_size = (u16)(size + sizeof(packet_header)); + tmp.header.size = packet_size; + memcpy(&tmp.data, &packet, (u32)size); + tmp.bswap(); + send(as(u8 *, &tmp), packet_size); + } +} + +void TProtocol::send_update_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board) { + if (m_connected) { + char_data.m_disp_data.m_disp_part2.is_valid(); + m_character_data = char_data; + TPlyJoinData tmp; + memset(&tmp, 0, sizeof(tmp)); + + + tmp.header.command = 0x98; + tmp.header.flags = 3; + tmp.header.size = sizeof(tmp); + tmp.char_data = m_character_data; + tmp.challenge = challenge; + tmp.choice_search_config = choice_search_config; + strncpy(tmp.info_board, info_board, sizeof(tmp.info_board)); + for (int i = 0; i < blocked_senders.header.flags; ++i) { + tmp.blocked_senders[i] = blocked_senders.blocked_senders[i]; + } + tmp.auto_reply_enabled = auto_reply.header.flags; + strncpy(tmp.auto_reply, auto_reply.text, sizeof(tmp.auto_reply)-1); + const int packet_size = strlen(tmp.auto_reply) + offsetof(TPlyJoinData, auto_reply) + sizeof(packet_header); + + tmp.header.size = packet_size & ~3; + tmp.char_data.some_stub(); + tmp.bswap(); + send(as(u8 *, &tmp), packet_size & ~3); + } +} + void TProtocol::send_chara_data_v2(TPlyCharData &char_data, TPlyChallenge &challenge, TPlyChoiceSearchConfig &choice_search_config, TBlockedSenders &blocked_senders, TPlyText<512> &auto_reply, char *info_board) { if (m_connected) { char_data.m_disp_data.m_disp_part2.is_valid(); @@ -399,15 +542,15 @@ void TProtocol::recv_generate_id(packet &pkt) { }; void TProtocol::recv_pso_data_long(packet &pkt) { - TRecvPsoData &tmp = as(TRecvPsoData &, pkt); - pkt.pkt.bswap(); - tmp.data.recv_pso_data_buf(tmp.header.size - 4); + TRecvPsoDataLong &tmp = as(TRecvPsoDataLong &, pkt); + tmp.bswap(); + tmp.data.recv_pso_data_buf(tmp.header.size - sizeof(packet_header)); }; void TProtocol::recv_pso_data(packet &pkt) { TRecvPsoData tmp = as(TRecvPsoData &, pkt); tmp.bswap(); - tmp.data.recv_pso_data_buf(tmp.header.size - 4); + tmp.data.recv_pso_data_buf(tmp.header.size - sizeof(packet_header)); }; void TProtocol::recv_system_file(packet &pkt) {}; -- cgit v1.2.3-13-gbd6f