From d6edf1b24dcfea6472cfa5c38cd49ea1adf5dd83 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sun, 14 Apr 2024 21:00:32 -0700 Subject: [PATCH] set up framework for DC patching --- src/Client.cc | 3 + src/FunctionCompiler.cc | 10 ++- src/Main.cc | 20 +++--- src/ProxyCommands.cc | 10 ++- src/ReceiveCommands.cc | 8 ++- src/SendCommands.cc | 14 +++-- src/Version.cc | 12 +++- system/client-functions/VersionDetectDC.sh4.s | 61 +++++++++++++++++++ tests/GC-Episode2PrivateDrops2P.test.txt | 10 +-- tests/GC-Episode3BattleWithSpectator.test.txt | 4 +- ...pisode3TrialEditionLobbySmokeTest.test.txt | 4 +- tests/GC-PoisonRoom.test.txt | 10 +-- 12 files changed, 132 insertions(+), 34 deletions(-) create mode 100644 system/client-functions/VersionDetectDC.sh4.s diff --git a/src/Client.cc b/src/Client.cc index 4d57c646..e5caf2c6 100644 --- a/src/Client.cc +++ b/src/Client.cc @@ -44,6 +44,9 @@ void Client::Config::set_flags_for_version(Version version, int64_t sub_version) case Version::DC_NTE: case Version::DC_V1_11_2000_PROTOTYPE: case Version::DC_V1: + this->set_flag(Flag::NO_D6); + this->set_flag(Flag::NO_SEND_FUNCTION_CALL); + break; case Version::DC_V2: this->set_flag(Flag::NO_D6); this->set_flag(Flag::SEND_FUNCTION_CALL_NO_CACHE_PATCH); diff --git a/src/FunctionCompiler.cc b/src/FunctionCompiler.cc index 7d63e666..bf1e964e 100644 --- a/src/FunctionCompiler.cc +++ b/src/FunctionCompiler.cc @@ -10,6 +10,7 @@ #ifdef HAVE_RESOURCE_FILE #include +#include #include #endif @@ -39,6 +40,8 @@ const char* name_for_architecture(CompiledFunctionCode::Architecture arch) { return "PowerPC"; case CompiledFunctionCode::Architecture::X86: return "x86"; + case CompiledFunctionCode::Architecture::SH4: + return "SH-4"; default: throw logic_error("invalid architecture"); } @@ -165,7 +168,8 @@ shared_ptr compile_function_code( ret = X86Emulator::assemble(load_file(asm_filename), get_include); break; case CompiledFunctionCode::Architecture::SH4: - throw runtime_error("cannot compuile SH-4 assembly"); + ret = SH4Emulator::assemble(load_file(asm_filename), get_include); + break; default: throw runtime_error("unknown architecture"); } @@ -184,6 +188,10 @@ shared_ptr compile_function_code( assembled = PPC32Emulator::assemble(text, get_include); } else if (arch == CompiledFunctionCode::Architecture::X86) { assembled = X86Emulator::assemble(text, get_include); + } else if (arch == CompiledFunctionCode::Architecture::SH4) { + assembled = SH4Emulator::assemble(text, get_include); + } else { + throw runtime_error("invalid architecture"); } ret->code = std::move(assembled.code); ret->label_offsets = std::move(assembled.label_offsets); diff --git a/src/Main.cc b/src/Main.cc index 2c758940..fb77a17a 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1196,10 +1196,8 @@ Action a_assemble_all_patches( two compiled .bin files for each patch (one unencrypted, for most PSO\n\ versions, and one encrypted, for PSO GC JP v1.4, JP Ep3, and Ep3 Trial\n\ Edition). The output files are saved in system/client-functions.\n", - +[](Arguments& args) { - string config_filename = args.get("config"); - auto s = make_shared(config_filename); - s->compile_functions(false); + +[](Arguments&) { + auto fci = make_shared("system/client-functions"); auto process_code = +[](shared_ptr code, uint32_t checksum_addr, @@ -1216,23 +1214,27 @@ Action a_assemble_all_patches( } }; - for (const auto& it : s->function_code_index->name_and_specific_version_to_patch_function) { + for (const auto& it : fci->name_and_specific_version_to_patch_function) { process_code(it.second, 0, 0, 0); } try { - process_code(s->function_code_index->name_to_function.at("VersionDetectGC"), 0, 0, 0); + process_code(fci->name_to_function.at("VersionDetectDC"), 0, 0, 0); } catch (const out_of_range&) { } try { - process_code(s->function_code_index->name_to_function.at("VersionDetectXB"), 0, 0, 0); + process_code(fci->name_to_function.at("VersionDetectGC"), 0, 0, 0); } catch (const out_of_range&) { } try { - process_code(s->function_code_index->name_to_function.at("CacheClearFix-Phase1"), 0x80000000, 8, 0x7F2734EC); + process_code(fci->name_to_function.at("VersionDetectXB"), 0, 0, 0); } catch (const out_of_range&) { } try { - process_code(s->function_code_index->name_to_function.at("CacheClearFix-Phase2"), 0, 0, 0); + process_code(fci->name_to_function.at("CacheClearFix-Phase1"), 0x80000000, 8, 0x7F2734EC); + } catch (const out_of_range&) { + } + try { + process_code(fci->name_to_function.at("CacheClearFix-Phase2"), 0, 0, 0); } catch (const out_of_range&) { } }); diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index c2494cf3..aa9fa025 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -24,6 +24,7 @@ #include #ifdef HAVE_RESOURCE_FILE #include +#include #include #endif @@ -728,7 +729,8 @@ static HandlerResult S_B2(shared_ptr ses, uint16_t, // TODO: Support SH-4 disassembly too bool is_ppc = ::is_ppc(ses->version()); bool is_x86 = ::is_x86(ses->version()); - if (is_ppc || is_x86) { + bool is_sh4 = ::is_sh4(ses->version()); + if (is_ppc || is_x86 || is_sh4) { try { if (code.size() < sizeof(FooterT)) { throw runtime_error("code section is too small"); @@ -763,6 +765,12 @@ static HandlerResult S_B2(shared_ptr ses, uint16_t, code.size(), 0, &labels); + } else if (is_sh4) { + disassembly = SH4Emulator::disassemble( + &r.pget(0, code.size()), + code.size(), + 0, + &labels); } else { // We shouldn't have entered the outer if statement if this happens throw logic_error("unsupported architecture"); diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index cbe0c786..9b5bcab1 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -122,6 +122,10 @@ void send_first_pre_lobby_commands(shared_ptr c, std::function o // TODO: This function is bad. Ideally we would use coroutines and clean up // all these terrible callbacks. + if (c->login->account->auto_patches_enabled.empty()) { + c->config.set_flag(Client::Flag::HAS_AUTO_PATCHES); + } + if (function_compiler_available() && !c->config.check_flag(Client::Flag::HAS_AUTO_PATCHES) && !c->config.check_flag(Client::Flag::NO_SEND_FUNCTION_CALL)) { @@ -3002,7 +3006,7 @@ static void on_61_98(shared_ptr c, uint16_t command, uint32_t flag, stri const auto* cmd3 = &check_size_t(data); c->ep3_config = make_shared(cmd3->ep3_config); cmd = reinterpret_cast(cmd3); - if (c->config.specific_version == 0x33000000) { + if (c->config.specific_version == 0x00000000) { c->config.specific_version = 0x33534A30; // 3SJ0 } } else { @@ -3010,7 +3014,7 @@ static void on_61_98(shared_ptr c, uint16_t command, uint32_t flag, stri c->channel.version = Version::GC_EP3_NTE; c->log.info("Game version changed to GC_EP3_NTE"); c->config.clear_flag(Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL); - if (c->config.specific_version == 0x33000000) { + if (c->config.specific_version == default_specific_version_for_version(Version::GC_EP3, -1)) { c->config.specific_version = 0x33534A54; // 3SJT } c->convert_account_to_temporary_if_nte(); diff --git a/src/SendCommands.cc b/src/SendCommands.cc index ac08476c..e7f48340 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -338,11 +338,17 @@ void prepare_client_for_patches(shared_ptr c, function on_comple if (!c) { return; } - bool is_gc = ::is_gc(c->version()); - bool is_xb = (c->version() == Version::XB_V3); - if ((is_gc || is_xb) && + const char* version_detect_name = nullptr; + if (c->version() == Version::DC_V2) { + version_detect_name = "VersionDetectDC"; + } else if (is_gc(c->version())) { + version_detect_name = "VersionDetectGC"; + } else if (c->version() == Version::XB_V3) { + version_detect_name = "VersionDetectXB"; + } + if (version_detect_name && c->config.specific_version == default_specific_version_for_version(c->version(), -1)) { - send_function_call(c, s->function_code_index->name_to_function.at(is_xb ? "VersionDetectXB" : "VersionDetectGC")); + send_function_call(c, s->function_code_index->name_to_function.at(version_detect_name)); c->function_call_response_queue.emplace_back([wc = weak_ptr(c), on_complete](uint32_t specific_version, uint32_t) -> void { auto c = wc.lock(); if (!c) { diff --git a/src/Version.cc b/src/Version.cc index 91069400..f0dc15b4 100644 --- a/src/Version.cc +++ b/src/Version.cc @@ -204,8 +204,14 @@ uint32_t default_specific_version_for_version(Version version, int64_t sub_versi // to set the specific_version based on sub_version. Fortunately, all // versions that share sub_version values also support send_function_call, // so for those versions we get the specific_version later by sending the - // VersionDetectGC or VersionDetectXB call. + // VersionDetectDC, VersionDetectGC, or VersionDetectXB call. switch (version) { + case Version::DC_NTE: + return 0x314F4A31; + case Version::DC_V1_11_2000_PROTOTYPE: + return 0x314F4A32; + case Version::DC_V1: + return 0x00000000; // Need to send VersionDetectDC (but can't on V1; rip) case Version::GC_NTE: return 0x334F4A54; // 3OJT case Version::GC_V3: @@ -225,7 +231,7 @@ uint32_t default_specific_version_for_version(Version version, int64_t sub_versi case 0x30: // GC Ep1&2 GameJam demo, GC Ep1&2 Trial Edition, GC Ep1&2 JP v1.2, at least one version of PSO XB case 0x31: // GC Ep1&2 US v1.0, GC US v1.1, XB US default: - return 0x33000000; + return 0x00000000; // Need to send VersionDetectGC } throw logic_error("this should be impossible"); case Version::GC_EP3_NTE: @@ -240,7 +246,7 @@ uint32_t default_specific_version_for_version(Version version, int64_t sub_versi case -1: // Initial check (before sub_version recognition) case 0x40: // GC Ep3 trial and GC Ep3 JP default: - return 0x33000000; + return 0x00000000; // Need to send VersionDetectGC } case Version::XB_V3: return 0x344F0000; diff --git a/system/client-functions/VersionDetectDC.sh4.s b/system/client-functions/VersionDetectDC.sh4.s new file mode 100644 index 00000000..76da9cc6 --- /dev/null +++ b/system/client-functions/VersionDetectDC.sh4.s @@ -0,0 +1,61 @@ +# This function returns the game version, with values more specific than can be +# detected by the sub_version field in the various login commands (e.g. 93/9D). + +# The returned value has the format SSPPRRVV, where: +# S = version (31 = PSOv1, 32 = PSOv2) +# G = game (4F = PSO) +# R = region (45 = E, 4A = J, 50 = P) +# V = minor version (31 = NTE, 32 = 11/2000, 33 = 12/2000, 24 = 01/2001, +# 35 = 08/2001, 46 = not a prototype) +# This results in a 4-character ASCII-printable version code which encodes all +# of the above information. This value is called specific_version in the places +# where it's used by the server. + +entry_ptr: +reloc0: + .offsetof start + +start: + mova r0, [data_start] + mov r1, r0 + mov.l r2, [r1]+ # target value +again: + mov.l r0, [r1]+ # candidate address + cmpeq r0, 0 + bt done # return 0 if no version matched + mov.l r0, [r0] # value from candidate address + cmpeq r0, r2 + mov.l r0, [r1]+ # specific_version from this match + bf again + nop + +done: + rets + nop + + .align 4 +data_start: + .data 0x61657244 + .data 0x8C239D78 # v1 NTE + .data 0x314F4A31 # 1OJ1 + .data 0x8C24CA24 # v1 11/2000 + .data 0x314F4A32 # 1OJ2 + .data 0x8C2873AC # v1 12/2000 + .data 0x314F4A33 # 1OJ3 + .data 0x8C28B04C # v1 01/2001 + .data 0x314F4A34 # 1OJ4 + .data 0x8C291E34 # v1 JP + .data 0x314F4A46 # 1OJF + .data 0x8C28B924 # v1 USA + .data 0x314F4546 # 1OEF + .data 0x8C28B3F4 # v1 EU + .data 0x314F5046 # 1OPF + .data 0x8C2F3748 # v2 08/2001 + .data 0x324F4A35 # 2OJ5 + .data 0x8C2F11D0 # v2 JP + .data 0x324F4A46 # 2OJF + .data 0x8C2F3738 # v2 USA + .data 0x324F4546 # 2OEF + .data 0x8C2E7CE0 # v2 EU + .data 0x324F5046 # 2OPF + .data 0x00000000 # end sentinel diff --git a/tests/GC-Episode2PrivateDrops2P.test.txt b/tests/GC-Episode2PrivateDrops2P.test.txt index 2c67add8..61ff0c34 100644 --- a/tests/GC-Episode2PrivateDrops2P.test.txt +++ b/tests/GC-Episode2PrivateDrops2P.test.txt @@ -467,7 +467,7 @@ I 94381 2023-12-29 15:36:19 - [Commands] Received from C-4 (version=GC_V3 comman 0140 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 40 20 00 00 00 00 00 00 00 | 3 B +0010 | 00 00 00 00 00 00 00 40 20 00 00 00 00 00 00 00 | 3 B 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=D5 flag=00) 0000 | D5 00 2C 00 59 6F 75 20 61 72 65 20 63 6F 6E 6E | , You are conn @@ -477,7 +477,7 @@ I 94381 2023-12-29 15:36:19 - [Commands] Received from C-4 (version=GC_V3 comman 0000 | 96 00 0C 00 7B 9E 17 2C 1D 00 00 00 | { , I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 40 20 00 04 00 00 00 00 00 | 3 B +0010 | 00 00 00 00 00 00 00 40 20 00 04 00 00 00 00 00 | 3 B 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=B1 flag=00) 0000 | B1 00 20 00 32 30 32 33 3A 31 32 3A 32 39 3A 20 | 2023:12:29: @@ -506,7 +506,7 @@ I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=9 0000 | 97 01 04 00 | I 94381 2023-12-29 15:36:19 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +0010 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 94381 2023-12-29 15:36:19 - [Commands] Received from C-4 (version=GC_V3 command=B1 flag=00) 0000 | B1 00 04 00 | @@ -555,11 +555,11 @@ I 94381 2023-12-29 15:36:20 - [Commands] Received from C-5 (version=GC_V3 comman 00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 4A 6F 6E 61 | Jona 00C0 | 68 00 00 00 00 00 00 00 00 00 00 00 32 AC 99 83 | h 2 -00D0 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +00D0 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 00E0 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 94381 2023-12-29 15:36:20 - [Commands] Sending to C-5 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +0010 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 94381 2023-12-29 15:36:20 - [Commands] Sending to C-5 (version=GC_V3 command=83 flag=0F) 0000 | 83 0F B8 00 33 00 00 33 01 00 00 00 00 00 00 00 | 3 3 diff --git a/tests/GC-Episode3BattleWithSpectator.test.txt b/tests/GC-Episode3BattleWithSpectator.test.txt index 1ef509f9..f0cfad4a 100644 --- a/tests/GC-Episode3BattleWithSpectator.test.txt +++ b/tests/GC-Episode3BattleWithSpectator.test.txt @@ -5867,7 +5867,7 @@ I 17097 2023-09-19 21:53:53 - [Commands] Received from C-3 (version=GC command=9 0140 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | I 17097 2023-09-19 21:53:53 - [Commands] Sending to C-3 (version=GC command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 22 22 22 22 32 AC 99 83 | , """"2 -0010 | 00 00 00 33 00 A1 00 40 20 00 00 00 00 00 00 00 | 3@ ` +0010 | 00 00 00 00 00 A1 00 40 20 00 00 00 00 00 00 00 | 3@ ` 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 17097 2023-09-19 21:53:53 - [Commands] Sending to C-3 (version=GC command=B7 flag=00) 0000 | B7 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 | @@ -5882,7 +5882,7 @@ I 17097 2023-09-19 21:53:53 - [Commands] Received from C-3 (version=GC command=9 0000 | 96 00 0C 00 30 AA 74 2C 27 00 00 00 | 0 t,' I 17097 2023-09-19 21:53:53 - [Commands] Sending to C-3 (version=GC command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 22 22 22 22 32 AC 99 83 | , """"2 -0010 | 00 00 00 33 00 A1 00 40 20 00 04 00 00 00 00 00 | 3@ ` +0010 | 00 00 00 00 00 A1 00 40 20 00 04 00 00 00 00 00 | 3@ ` 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 17097 2023-09-19 21:53:53 - [Commands] Sending to C-3 (version=GC command=B1 flag=00) 0000 | B1 00 20 00 32 30 32 33 3A 30 39 3A 32 30 3A 20 | 2023:09:20: diff --git a/tests/GC-Episode3TrialEditionLobbySmokeTest.test.txt b/tests/GC-Episode3TrialEditionLobbySmokeTest.test.txt index 4e67ce7d..da7618d0 100644 --- a/tests/GC-Episode3TrialEditionLobbySmokeTest.test.txt +++ b/tests/GC-Episode3TrialEditionLobbySmokeTest.test.txt @@ -62,7 +62,7 @@ I 25793 2023-11-24 23:03:38 - [Commands] Received from C-4 (version=GC_EP3 comma 0140 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | I 25793 2023-11-24 23:03:38 - [Commands] Sending to C-4 (version=GC_EP3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 11 11 11 11 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 A1 00 40 20 00 00 00 00 00 00 00 | 3 B` +0010 | 00 00 00 00 00 A1 00 40 20 00 00 00 00 00 00 00 | 3 B` 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 25793 2023-11-24 23:03:38 - [Commands] Sending to C-4 (version=GC_EP3 command=B7 flag=00) 0000 | B7 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 | @@ -77,7 +77,7 @@ I 25793 2023-11-24 23:03:38 - [Commands] Received from C-4 (version=GC_EP3 comma 0000 | 96 00 0C 00 5C E6 6B 2C 3B 00 00 00 | \ k,; I 25793 2023-11-24 23:03:38 - [Commands] Sending to C-4 (version=GC_EP3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 11 11 11 11 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 A1 00 40 20 00 04 00 00 00 00 00 | 3 B` +0010 | 00 00 00 00 00 A1 00 40 20 00 04 00 00 00 00 00 | 3 B` 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 25793 2023-11-24 23:03:38 - [Commands] Sending to C-4 (version=GC_EP3 command=B1 flag=00) 0000 | B1 00 20 00 32 30 32 33 3A 31 31 3A 32 35 3A 20 | 2023:11:25: diff --git a/tests/GC-PoisonRoom.test.txt b/tests/GC-PoisonRoom.test.txt index dc8bd149..0be4b0c0 100644 --- a/tests/GC-PoisonRoom.test.txt +++ b/tests/GC-PoisonRoom.test.txt @@ -23206,7 +23206,7 @@ I 56327 2024-03-03 23:56:37 - [Commands] Received from C-4 (version=GC_V3 comman 0140 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | I 56327 2024-03-03 23:56:37 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 40 20 00 00 00 00 00 00 00 | 3 @ +0010 | 00 00 00 00 00 00 00 40 20 00 00 00 00 00 00 00 | 3 @ 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 56327 2024-03-03 23:56:37 - [Commands] Sending to C-4 (version=GC_V3 command=D5 flag=00) 0000 | D5 00 2C 00 59 6F 75 20 61 72 65 20 63 6F 6E 6E | , You are conn @@ -23216,7 +23216,7 @@ I 56327 2024-03-03 23:56:37 - [Commands] Received from C-4 (version=GC_V3 comman 0000 | 96 00 0C 00 28 59 6C 2B 08 01 00 00 | (Yl+ I 56327 2024-03-03 23:56:37 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 40 20 00 04 00 00 00 00 00 | 3 @ +0010 | 00 00 00 00 00 00 00 40 20 00 04 00 00 00 00 00 | 3 @ 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 56327 2024-03-03 23:56:37 - [Commands] Sending to C-4 (version=GC_V3 command=B1 flag=00) 0000 | B1 00 20 00 32 30 32 34 3A 30 33 3A 30 34 3A 20 | 2024:03:04: @@ -23245,7 +23245,7 @@ I 56327 2024-03-03 23:56:38 - [Commands] Sending to C-4 (version=GC_V3 command=9 0000 | 97 01 04 00 | I 56327 2024-03-03 23:56:38 - [Commands] Sending to C-4 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +0010 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 56327 2024-03-03 23:56:38 - [Commands] Received from C-4 (version=GC_V3 command=B1 flag=00) 0000 | B1 00 04 00 | @@ -23294,11 +23294,11 @@ I 56327 2024-03-03 23:56:38 - [Commands] Received from C-5 (version=GC_V3 comman 00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 4E 4F 20 44 | NO D 00C0 | 41 54 41 20 00 00 00 00 00 00 00 00 32 AC 99 83 | ATA 2 -00D0 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +00D0 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 00E0 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 56327 2024-03-03 23:56:38 - [Commands] Sending to C-5 (version=GC_V3 command=04 flag=00) 0000 | 04 00 2C 00 00 00 01 00 1E B1 05 17 32 AC 99 83 | , 2 -0010 | 00 00 00 33 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D +0010 | 00 00 00 00 00 00 00 44 20 00 00 00 00 00 00 00 | 3 D 0020 | 00 00 00 00 00 00 FF FF 80 FF FF FF | I 56327 2024-03-03 23:56:38 - [Commands] Sending to C-5 (version=GC_V3 command=83 flag=0F) 0000 | 83 0F B8 00 33 00 00 33 01 00 00 00 00 00 00 00 | 3 3