From 31616954cc47d6babc73e40cbcc9e25ffa587d61 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sun, 28 Apr 2024 23:48:02 -0700 Subject: [PATCH] implement extended $loadchar on GC --- README.md | 4 +- src/ChatCommands.cc | 51 +++++++++++++++++-- src/FunctionCompiler.cc | 14 +++-- src/FunctionCompiler.hh | 6 ++- src/Main.cc | 3 +- src/ReceiveCommands.cc | 2 +- src/SendCommands.cc | 21 +++++--- src/SendCommands.hh | 9 ++-- .../GetExtendedPlayerInfo.3OE0.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OE1.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OE2.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OJ2.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OJ3.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OJ4.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OJ5.patch.s | 9 ++-- .../GetExtendedPlayerInfo.3OP0.patch.s | 9 ++-- .../GetExtendedPlayerInfoGC.ppc.inc.s | 37 +++++++++----- .../SetExtendedPlayerInfo.3OE0.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OE1.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OE2.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OJ2.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OJ3.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OJ4.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OJ5.patch.s | 12 +++++ .../SetExtendedPlayerInfo.3OP0.patch.s | 12 +++++ .../SetExtendedPlayerInfoGC.ppc.inc.s | 37 ++++++++++++++ .../System/CopyDataWords.ppc.inc.s | 2 +- 27 files changed, 264 insertions(+), 90 deletions(-) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OE0.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OE1.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OE2.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OJ2.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OJ3.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OJ4.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OJ5.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfo.3OP0.patch.s (69%) rename system/client-functions/{GetExtendedPlayerInfo => ExtendedPlayerInfo}/GetExtendedPlayerInfoGC.ppc.inc.s (71%) create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE0.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE1.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE2.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ2.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ3.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ4.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ5.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OP0.patch.s create mode 100644 system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfoGC.ppc.inc.s diff --git a/README.md b/README.md index 58a46c08..8573e3cc 100644 --- a/README.md +++ b/README.md @@ -507,8 +507,8 @@ Some commands only work on the game server and not on the proxy server. The chat * `$patch `: Run a patch on your client. `` must exactly match the name of a patch on the server. * Character data commands (game server only) - * `$savechar `: Saves your current character data on the server in the specified slot (each serial number has 4 slots, numbered 1-4). These slots are separate from BB character slots; using this command does not affect BB characters. - * `$loadchar ` (v1 and v2 only): Loads your character data from the specified slot. The changes will be undone if you join a game - to save your changes, disconnect from the lobby. + * `$savechar `: Saves your current character data on the server in the specified slot (each serial number has 4 slots, numbered 1-4). These slots are separate from BB character slots; using this command does not affect BB characters. On non-Plus GC versions, this command also saves your bank contents and chat shortcuts. + * `$loadchar ` (v1, v2, and GC non-Plus only): Loads your character data from the specified slot. The changes will be undone if you join a game - to save your changes, disconnect from the lobby. * `$bbchar `: Use this command when playing on a non-BB version of PSO. If the username and password are correct, this command converts your current character to BB format and saves it on the server in the given slot (1-4). Any character already in that slot is overwritten. (This command is similar to `$savechar`, except it overwrites a BB character slot, and can transfer characters across accounts.) Note that the character's chat data, quick menu config, and bank contents are not copied, since there is no way for the server to request those types of data. * `$edit `: Modifies your character data. If you are on V3 (GameCube/Xbox), this command does nothing. If you are on V1 or V2 (DC or PC, not BB), your changes will be undone if you join a game - to save your changes, disconnect from the lobby. If cheats are allowed on the server, `` can be any of `atp`, `mst`, `evp`, `hp`, `dfp`, `ata`, `lck`, `meseta`, `exp`, `level`, `namecolor`, `secid`, `name`, `language`, `npc`, or `tech`. If cheats are not allowed, only `namecolor`, `name`, `language`, and `npc` can be used. Changing your character's language is only useful on BB; to do so, use a single-character language code (e.g. to switch your character to English, use `$edit language E`; for Japanese, use `$edit language J`). diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index cf63c87c..b74f9fe8 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -1458,8 +1458,8 @@ static void server_command_savechar(shared_ptr c, const std::string& arg } static void server_command_loadchar(shared_ptr c, const std::string& args) { - if (!is_v1_or_v2(c->version())) { - send_text_message(c, "$C7This command can only\nbe used on v1 or v2"); + if (!is_v1_or_v2(c->version()) && c->version() != Version::GC_V3) { + send_text_message(c, "$C7This command can only\nbe used on v1, v2,\nand GC"); return; } if (c->login->account->check_flag(Account::Flag::IS_SHARED_ACCOUNT)) { @@ -1476,9 +1476,50 @@ static void server_command_loadchar(shared_ptr c, const std::string& arg } c->load_backup_character(c->login->account->account_id, index); - auto s = c->require_server_state(); - send_player_leave_notification(l, c->lobby_client_id); - s->send_lobby_join_notifications(l, c); + if (c->version() == Version::GC_V3) { + // TODO: Support extended player info on other versions + auto s = c->require_server_state(); + if (c->config.check_flag(Client::Flag::NO_SEND_FUNCTION_CALL) || + c->config.check_flag(Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) { + send_text_message_printf(c, "Can\'t load character\ndata on PSO Plus"); + return; + } + + auto gc_char = make_shared(c->character()->to_gc()); + prepare_client_for_patches(c, [wc = weak_ptr(c), gc_char]() { + auto c = wc.lock(); + if (!c) { + return; + } + try { + auto s = c->require_server_state(); + auto fn = s->function_code_index->get_patch("SetExtendedPlayerInfo", c->config.specific_version); + send_function_call(c, fn, {}, gc_char.get(), sizeof(PSOGCCharacterFile::Character)); + c->function_call_response_queue.emplace_back([wc = weak_ptr(c)](uint32_t, uint32_t) -> void { + auto c = wc.lock(); + if (!c) { + return; + } + auto l = c->lobby.lock(); + if (l) { + auto s = c->require_server_state(); + send_player_leave_notification(l, c->lobby_client_id); + s->send_lobby_join_notifications(l, c); + } + }); + } catch (const exception& e) { + c->log.warning("Failed to set extended player info: %s", e.what()); + send_text_message_printf(c, "Failed to set\nplayer info:\n%s", e.what()); + } + }); + + } else { + // On v1 and v2, the client will assign its character data from the lobby + // join command, so it suffices to just resend the join notification. + auto s = c->require_server_state(); + send_player_leave_notification(l, c->lobby_client_id); + s->send_lobby_join_notifications(l, c); + } } static void server_command_save(shared_ptr c, const std::string&) { diff --git a/src/FunctionCompiler.cc b/src/FunctionCompiler.cc index 1c729dfe..a385a47f 100644 --- a/src/FunctionCompiler.cc +++ b/src/FunctionCompiler.cc @@ -50,7 +50,8 @@ const char* name_for_architecture(CompiledFunctionCode::Architecture arch) { template string CompiledFunctionCode::generate_client_command_t( const unordered_map& label_writes, - const string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t override_relocations_offset) const { FooterT footer; footer.num_relocations = this->relocation_deltas.size(); @@ -72,7 +73,9 @@ string CompiledFunctionCode::generate_client_command_t( } else { w.write(this->code); } - w.write(suffix); + if (suffix_size) { + w.write(suffix_data, suffix_size); + } while (w.size() & 3) { w.put_u8(0); } @@ -101,14 +104,15 @@ string CompiledFunctionCode::generate_client_command_t( string CompiledFunctionCode::generate_client_command( const unordered_map& label_writes, - const string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t override_relocations_offset) const { if (this->arch == Architecture::POWERPC) { return this->generate_client_command_t( - label_writes, suffix, override_relocations_offset); + label_writes, suffix_data, suffix_size, override_relocations_offset); } else if ((this->arch == Architecture::X86) || (this->arch == Architecture::SH4)) { return this->generate_client_command_t( - label_writes, suffix, override_relocations_offset); + label_writes, suffix_data, suffix_size, override_relocations_offset); } else { throw logic_error("invalid architecture"); } diff --git a/src/FunctionCompiler.hh b/src/FunctionCompiler.hh index b797e9b4..9ecf46fa 100644 --- a/src/FunctionCompiler.hh +++ b/src/FunctionCompiler.hh @@ -43,11 +43,13 @@ struct CompiledFunctionCode { template std::string generate_client_command_t( const std::unordered_map& label_writes, - const std::string& suffix, + const void* suffix_data = nullptr, + size_t suffix_size = 0, uint32_t override_relocations_offset = 0) const; std::string generate_client_command( const std::unordered_map& label_writes = {}, - const std::string& suffix = "", + const void* suffix_data = nullptr, + size_t suffix_size = 0, uint32_t override_relocations_offset = 0) const; }; diff --git a/src/Main.cc b/src/Main.cc index f5cbcfed..2efac173 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1261,7 +1261,8 @@ Action a_assemble_all_patches( uint32_t override_start_addr) -> void { for (uint8_t encrypted = 0; encrypted < 2; encrypted++) { StringWriter w; - string data = prepare_send_function_call_data(code, {}, "", checksum_addr, checksum_size, override_start_addr, encrypted); + string data = prepare_send_function_call_data( + code, {}, nullptr, 0, checksum_addr, checksum_size, override_start_addr, encrypted); w.put(PSOCommandHeaderDCV3{.command = 0xB2, .flag = code->index, .size = data.size() + 4}); w.write(data); string out_path = code->source_path + (encrypted ? ".enc.bin" : ".std.bin"); diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index b9e7a85e..4ba5bfef 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -2778,7 +2778,7 @@ static void send_dol_file_chunk(shared_ptr c, uint32_t start_addr) { auto fn = s->function_code_index->name_to_function.at("WriteMemory"); unordered_map label_writes( {{"dest_addr", start_addr}, {"size", bytes_to_send}}); - send_function_call(c, fn, label_writes, data_to_send); + send_function_call(c, fn, label_writes, data_to_send.data(), data_to_send.size()); size_t progress_percent = ((offset + bytes_to_send) * 100) / c->loading_dol_file->data.size(); send_ship_info(c, string_printf("%zu%%%%", progress_percent)); diff --git a/src/SendCommands.cc b/src/SendCommands.cc index bb3fa1b9..ac4a0fc0 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -365,7 +365,8 @@ void prepare_client_for_patches(shared_ptr c, function on_comple }; if (!c->config.check_flag(Client::Flag::SEND_FUNCTION_CALL_NO_CACHE_PATCH)) { - send_function_call(c, s->function_code_index->name_to_function.at("CacheClearFix-Phase1"), {}, "", 0x80000000, 8, 0x7F2734EC); + auto fn = s->function_code_index->name_to_function.at("CacheClearFix-Phase1"); + send_function_call(c, fn, {}, nullptr, 0, 0x80000000, 8, 0x7F2734EC); c->function_call_response_queue.emplace_back([s, wc = weak_ptr(c), send_version_detect](uint32_t, uint32_t header_checksum) -> void { auto c = wc.lock(); if (!c) { @@ -397,14 +398,15 @@ void prepare_client_for_patches(shared_ptr c, function on_comple string prepare_send_function_call_data( shared_ptr code, const unordered_map& label_writes, - const string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t checksum_addr, uint32_t checksum_size, uint32_t override_relocations_offset, bool use_encrypted_format) { string data; if (code.get()) { - data = code->generate_client_command(label_writes, suffix, override_relocations_offset); + data = code->generate_client_command(label_writes, suffix_data, suffix_size, override_relocations_offset); if (use_encrypted_format) { uint32_t key = random_object(); @@ -446,7 +448,8 @@ void send_function_call( shared_ptr c, shared_ptr code, const unordered_map& label_writes, - const string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t checksum_addr, uint32_t checksum_size, uint32_t override_relocations_offset) { @@ -455,7 +458,8 @@ void send_function_call( c->config, code, label_writes, - suffix, + suffix_data, + suffix_size, checksum_addr, checksum_size, override_relocations_offset); @@ -466,7 +470,8 @@ void send_function_call( const Client::Config& client_config, shared_ptr code, const unordered_map& label_writes, - const string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t checksum_addr, uint32_t checksum_size, uint32_t override_relocations_offset) { @@ -478,7 +483,7 @@ void send_function_call( } string data = prepare_send_function_call_data( - code, label_writes, suffix, checksum_addr, checksum_size, override_relocations_offset, + code, label_writes, suffix_data, suffix_size, checksum_addr, checksum_size, override_relocations_offset, client_config.check_flag(Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL)); ch.send(0xB2, code ? code->index : 0x00, data); @@ -520,7 +525,7 @@ bool send_protected_command(std::shared_ptr c, const void* data, size_t auto s = c->require_server_state(); auto fn = s->function_code_index->get_patch("CallProtectedHandler", c->config.specific_version); uint32_t size_label_value = is_big_endian(c->version()) ? data.size() : bswap32(data.size()); - send_function_call(c, fn, {{"size", size_label_value}}, data); + send_function_call(c, fn, {{"size", size_label_value}}, data.data(), data.size()); c->function_call_response_queue.emplace_back(empty_function_call_response_handler); if (echo_to_lobby) { auto l = c->lobby.lock(); diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 3bd4026e..b00626fd 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -152,7 +152,8 @@ void prepare_client_for_patches(std::shared_ptr c, std::function std::string prepare_send_function_call_data( std::shared_ptr code, const std::unordered_map& label_writes, - const std::string& suffix, + const void* suffix_data, + size_t suffix_size, uint32_t checksum_addr, uint32_t checksum_size, uint32_t override_relocations_offset, @@ -162,7 +163,8 @@ void send_function_call( const Client::Config& client_config, std::shared_ptr code, const std::unordered_map& label_writes = {}, - const std::string& suffix = "", + const void* suffix_data = nullptr, + size_t suffix_size = 0, uint32_t checksum_addr = 0, uint32_t checksum_size = 0, uint32_t override_relocations_offset = 0); @@ -170,7 +172,8 @@ void send_function_call( std::shared_ptr c, std::shared_ptr code, const std::unordered_map& label_writes = {}, - const std::string& suffix = "", + const void* suffix_data = nullptr, + size_t suffix_size = 0, uint32_t checksum_addr = 0, uint32_t checksum_size = 0, uint32_t override_relocations_offset = 0); diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s index 6d092ca7..ade21c41 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE0.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DB0E0 # malloc9 - .data 0x802021D0 # get_character_file - .data 0x802021AC # get_selected_character_file_index + .data 0x805C5760 # char_file_part1 + .data 0x805C5764 # char_file_part2 .data 0x805C4D80 # root_protocol (anchor: send_05) .data 0x803DB138 # free9 .data 0x800787B0 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s index 86104132..74c07a16 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE1.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DB138 # malloc9 - .data 0x802021D0 # get_character_file - .data 0x802021AC # get_selected_character_file_index + .data 0x805CC740 # char_file_part1 + .data 0x805CC744 # char_file_part2 .data 0x805CBD60 # root_protocol (anchor: send_05) .data 0x803DB190 # free9 .data 0x800787B0 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s index 3ef55ef2..08e34666 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OE2.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DE838 # malloc9 - .data 0x80202BA0 # get_character_file - .data 0x80202B7C # get_selected_character_file_index + .data 0x805D5F60 # char_file_part1 + .data 0x805D5F64 # char_file_part2 .data 0x805D5580 # root_protocol (anchor: send_05) .data 0x803DE890 # free9 .data 0x8007889C # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s index ef0be2aa..34d85c0a 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ2.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803D9E38 # malloc9 - .data 0x802019D4 # get_character_file - .data 0x802019B0 # get_selected_character_file_index + .data 0x805C4E68 # char_file_part1 + .data 0x805C4E6C # char_file_part2 .data 0x805C4488 # root_protocol (anchor: send_05) .data 0x803D9E90 # free9 .data 0x8007848C # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s index fd8b4dc1..5069c130 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ3.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DC818 # malloc9 - .data 0x80202248 # get_character_file - .data 0x80202224 # get_selected_character_file_index + .data 0x805CF430 # char_file_part1 + .data 0x805CF434 # char_file_part2 .data 0x805CEA50 # root_protocol (anchor: send_05) .data 0x803DC870 # free9 .data 0x800785F0 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s index 9ced6eb8..ed3edf84 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ4.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DE6B8 # malloc9 - .data 0x801FD950 # get_character_file - .data 0x80222C0C # get_selected_character_file_index + .data 0x805D68B0 # char_file_part1 + .data 0x805D68B4 # char_file_part2 .data 0x805D5ED0 # root_protocol (anchor: send_05) .data 0x803DE710 # free9 .data 0x80078748 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s index 217b12d1..91a2b1f4 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OJ5.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DE468 # malloc9 - .data 0x8020286C # get_character_file - .data 0x80202848 # get_selected_character_file_index + .data 0x805D6650 # char_file_part1 + .data 0x805D6654 # char_file_part2 .data 0x805D5C70 # root_protocol (anchor: send_05) .data 0x803DE4C0 # free9 .data 0x800786A0 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s similarity index 69% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s index 71605513..43ac0688 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfo.3OP0.patch.s @@ -6,14 +6,11 @@ entry_ptr: reloc0: .offsetof start start: - mflr r12 - bl get_data_addr + .include GetExtendedPlayerInfoGC data: .data 0x803DD328 # malloc9 - .data 0x80202AB4 # get_character_file - .data 0x80202A90 # get_selected_character_file_index + .data 0x805D21A0 # char_file_part1 + .data 0x805D21A4 # char_file_part2 .data 0x805D17C0 # root_protocol (anchor: send_05) .data 0x803DD380 # free9 .data 0x80078820 # TProtocol_wait_send_drain -get_data_addr: - .include GetExtendedPlayerInfoGC diff --git a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s similarity index 71% rename from system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s rename to system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s index 17e54151..c06150e1 100644 --- a/system/client-functions/GetExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s +++ b/system/client-functions/ExtendedPlayerInfo/GetExtendedPlayerInfoGC.ppc.inc.s @@ -1,9 +1,13 @@ stwu [r1 - 0x20], r1 - stw [r1 + 0x24], r12 + mflr r0 + stw [r1 + 0x24], r0 stw [r1 + 0x08], r31 stw [r1 + 0x0C], r30 stw [r1 + 0x10], r29 stw [r1 + 0x14], r28 + + b get_data_ptr +get_data_ptr_ret: mflr r30 li r3, 0x279C @@ -17,21 +21,23 @@ ori r0, r0, 0x9C27 stw [r31], r0 # header = 30 00 9C 27 - lwz r0, [r30 + 0x04] - mtctr r0 - bctrl # get_character_file - mr r28, r3 - - lwz r0, [r30 + 0x08] - mtctr r0 - bctrl # get_selected_character_file_index - mulli r3, r3, 0x2798 - addi r3, r3, 4 - add r4, r3, r28 # r4 = &character_file->characters[selected_char_file_index] - addi r3, r31, 4 - li r5, 0x2798 + lwz r4, [r30 + 0x04] + lwz r4, [r4] # r4 = char_file_part1 + addi r3, r31, 0x0004 + li r5, 0x041C # sizeof(part1) bl memcpy + lwz r4, [r30 + 0x08] + lwz r4, [r4] # r4 = char_file_part2 + addi r3, r31, 0x0420 + li r5, 0x2370 # sizeof(part2) + bl memcpy + + li r0, 0 + stw [r31 + 0x2790], r0 + stw [r31 + 0x2794], r0 + stw [r31 + 0x2798], r0 + mr r28, r31 li r29, 0x279C send_again: @@ -79,3 +85,6 @@ malloc9_failed: memcpy: .include CopyDataWords blr + +get_data_ptr: + bl get_data_ptr_ret diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE0.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE0.patch.s new file mode 100644 index 00000000..85faa736 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE0.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805C5758 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE1.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE1.patch.s new file mode 100644 index 00000000..63027ef8 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE1.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805CC738 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE2.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE2.patch.s new file mode 100644 index 00000000..f5089367 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OE2.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805D5F58 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ2.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ2.patch.s new file mode 100644 index 00000000..3d94fad1 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ2.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805C4E60 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ3.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ3.patch.s new file mode 100644 index 00000000..50e846bc --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ3.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805CF428 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ4.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ4.patch.s new file mode 100644 index 00000000..db1be411 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ4.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805D68A8 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ5.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ5.patch.s new file mode 100644 index 00000000..613b3d1a --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OJ5.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805D6648 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OP0.patch.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OP0.patch.s new file mode 100644 index 00000000..76213c35 --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfo.3OP0.patch.s @@ -0,0 +1,12 @@ +.meta hide_from_patches_menu +.meta name="SetExtendedPlayerInfo" +.meta description="" + +entry_ptr: +reloc0: + .offsetof start +start: + .include SetExtendedPlayerInfoGC +data: + .data 0x805D2198 # character_file + # Server adds a PSOGCCharacterFile::Character here diff --git a/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfoGC.ppc.inc.s b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfoGC.ppc.inc.s new file mode 100644 index 00000000..84b2207d --- /dev/null +++ b/system/client-functions/ExtendedPlayerInfo/SetExtendedPlayerInfoGC.ppc.inc.s @@ -0,0 +1,37 @@ + mflr r12 + bl get_data_ptr +get_data_ptr_ret: + mflr r11 + + lwz r10, [r11] + + # Copy part1 data into place + lwz r3, [r10 + 0x08] + addi r4, r11, 0x0004 + li r5, 0x41C + bl memcpy + + # Copy part2 data into place, but retain the values of a few metadata fields + # so the game won't think the file is corrupt + lwz r3, [r10 + 0x0C] + lwz r7, [r3 + 0x04] # creation_timestamp + lwz r8, [r3 + 0x08] # signature + lwz r9, [r3 + 0x14] # save_count + addi r4, r11, 0x0420 + li r5, 0x2370 + bl memcpy + lwz r3, [r10 + 0x0C] + stw [r3 + 0x04], r7 # creation_timestamp + stw [r3 + 0x08], r8 # signature + stw [r3 + 0x14], r9 # save_count + + li r3, 1 + mtlr r12 + blr + +memcpy: + .include CopyDataWords + blr + +get_data_ptr: + bl get_data_ptr_ret diff --git a/system/client-functions/System/CopyDataWords.ppc.inc.s b/system/client-functions/System/CopyDataWords.ppc.inc.s index 4c4936c5..886a1a82 100644 --- a/system/client-functions/System/CopyDataWords.ppc.inc.s +++ b/system/client-functions/System/CopyDataWords.ppc.inc.s @@ -1,7 +1,7 @@ # r3 = dest ptr # r4 = src ptr # r5 = size - # Clobbers r3, r4, r5 + # Clobbers r3, r4, r5, ctr addi r5, r5, 3 rlwinm r5, r5, 30, 2, 31 # r5 = number of words to copy mtctr r5