From b0828a3dfe8d6d00a6b6819c9fcf149039d7c8d2 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 21 Apr 2022 15:54:44 -0700 Subject: [PATCH] add set-block-function-calls proxy command --- src/CommandFormats.hh | 10 +++++++--- src/ProxyCommands.cc | 22 +++++++++++++++++++++- src/ProxyServer.cc | 1 + src/ProxyServer.hh | 1 + src/ServerShell.cc | 13 +++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index c930bc14..7a810086 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -878,14 +878,18 @@ struct S_QuestMenuEntry_BB_A2_A4 { // For example: 2022:03:30: 15:36:42.000 // Client will respond with a 99 command. -// B2 (S->C): Write memory +// B2 (S->C): Execute code // GC v1.0 and v1.1 only. // Format unknown. // Client will respond with a B3 command. -// B3 (C->S): Write memory response +// B3 (C->S): Execute code response // GC v1.0 and v1.1 only. -// Format unknown. + +struct C_ExecuteCodeResponse_GC_B3 { + le_uint32_t return_value; + le_uint32_t unused; +}; // B4: Invalid command // B5: Invalid command diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index 92e2535c..5f011a97 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -306,6 +306,26 @@ static bool process_server_88(shared_ptr, return true; } +static bool process_server_gc_B2(shared_ptr, + ProxyServer::LinkedSession& session, uint16_t, uint32_t flag, string& data) { + if (session.save_files) { + string output_filename = string_printf("code.bin.%" PRId64, now()); + save_file(output_filename, data); + session.log(INFO, "Wrote code from server to file %s", output_filename.c_str()); + } + + if (session.function_call_return_value >= 0) { + session.log(INFO, "Blocking function call from server"); + C_ExecuteCodeResponse_GC_B3 cmd; + cmd.return_value = session.function_call_return_value; + cmd.unused = 0; + session.send_to_end(true, 0xB3, flag, &cmd, sizeof(cmd)); + return false; + } else { + return true; + } +} + template static bool process_server_C4(shared_ptr, ProxyServer::LinkedSession& session, uint16_t, uint32_t flag, string& data) { @@ -792,7 +812,7 @@ static process_command_t gc_server_handlers[0x100] = { /* 80 */ defh, process_server_81, defh, defh, defh, defh, defh, defh, process_server_88, defh, defh, defh, defh, defh, defh, defh, /* 90 */ defh, defh, defh, defh, defh, defh, defh, defh, defh, defh, process_server_gc_9A, defh, defh, defh, defh, defh, /* A0 */ defh, defh, defh, defh, defh, defh, process_server_44_A6, process_server_13_A7, defh, defh, defh, defh, defh, defh, defh, defh, - /* B0 */ defh, defh, defh, defh, defh, defh, defh, defh, process_server_gc_B8, defh, defh, defh, defh, defh, defh, defh, + /* B0 */ defh, defh, process_server_gc_B2, defh, defh, defh, defh, defh, process_server_gc_B8, defh, defh, defh, defh, defh, defh, defh, /* C0 */ defh, defh, defh, defh, process_server_C4, defh, defh, defh, defh, process_server_60_62_6C_6D_C9_CB, defh, process_server_60_62_6C_6D_C9_CB, defh, defh, defh, defh, /* D0 */ defh, defh, defh, defh, defh, process_server_gc_1A_D5, defh, defh, defh, defh, defh, defh, defh, defh, defh, defh, /* E0 */ defh, defh, defh, defh, process_server_gc_E4, defh, defh, defh, defh, defh, defh, defh, defh, defh, defh, defh, diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index aa0d517c..fdf5b187 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -374,6 +374,7 @@ ProxyServer::LinkedSession::LinkedSession( enable_chat_filter(true), enable_switch_assist(false), save_files(false), + function_call_return_value(-1), override_section_id(-1), override_lobby_event(-1), override_lobby_number(-1), diff --git a/src/ProxyServer.hh b/src/ProxyServer.hh index 2a968e87..36712da8 100644 --- a/src/ProxyServer.hh +++ b/src/ProxyServer.hh @@ -58,6 +58,7 @@ public: bool enable_chat_filter; bool enable_switch_assist; bool save_files; + int64_t function_call_return_value; // -1 = don't block function calls G_SwitchStateChanged_6x05 last_switch_enabled_command; int16_t override_section_id; int16_t override_lobby_event; diff --git a/src/ServerShell.cc b/src/ServerShell.cc index f8a4791a..62bcb6eb 100644 --- a/src/ServerShell.cc +++ b/src/ServerShell.cc @@ -141,6 +141,11 @@ Proxy commands (these will only work when exactly one client is connected):\n\ on, any file that the remote server sends to the client will be saved to\n\ the current directory. This includes data like quests, Episode 3 card\n\ definitions, and GBA games.\n\ + set-block-function-calls [return-value]\n\ + Enable blocking of function calls from the server. When enabled, the proxy\n\ + responds as if the function was called (with the given return value), but\n\ + does not send the code to the client. To stop blocking function calls, omit\n\ + the return value.\n\ "); @@ -372,6 +377,14 @@ Proxy commands (these will only work when exactly one client is connected):\n\ auto session = this->get_proxy_session(); set_boolean(&session->save_files, command_args); + } else if (command_name == "set-block-function-calls") { + auto session = this->get_proxy_session(); + if (command_args.empty()) { + session->function_call_return_value = -1; + } else { + session->function_call_return_value = stoul(command_args); + } + } else { throw invalid_argument("unknown command; try \'help\'"); }