diff --git a/include/rex/system/xnet_transport.h b/include/rex/system/xnet_transport.h index bb32ab5..982c20d 100644 --- a/include/rex/system/xnet_transport.h +++ b/include/rex/system/xnet_transport.h @@ -116,6 +116,12 @@ class XNetTransport { // The local machine's virtual IP (host order) - mirrors XNetGetTitleXnAddr. static uint32_t LocalVirtualIp(); + // netcode-revival: force the title's internal "live user" static flag + // (Skate 3 build) so its frontend stops refusing "Xbox Live features" + // before it ever calls a rexglue API. Called periodically by the ghost + // client. Fragile: the address is tied to this title's build. + void ForceLiveFlag(); + // --- discovery (used by XNetQosLookup) ------------------------------------ // Send a session query for our room; the reply lands asynchronously and is // surfaced by Sessions() once WaitForReply returns. diff --git a/src/system/xnet_transport.cpp b/src/system/xnet_transport.cpp index a81d24a..bb59cd9 100644 --- a/src/system/xnet_transport.cpp +++ b/src/system/xnet_transport.cpp @@ -153,6 +153,21 @@ bool XNetTransport::Active() const { return active_; } +void XNetTransport::ForceLiveFlag() { + // The Skate 3 frontend gates "Xbox Live features" on an internal static + // byte (the game's own "live user" flag) and refuses WITHOUT calling any + // rexglue API when it is 0. The game sets it from its sign-in manager, but + // with no real Live the flag never becomes non-zero. Force it here. + // Address from the game: sub_8263E788 does lis r11,-32003 -> r11 = + // 0x83030000 (recompiler's -2097348608) then lbz at -30639 => + // 0x83028851. (Fragile: tied to this title's build; revival only.) + uint8_t* flag = REX_KERNEL_MEMORY()->TranslateVirtual(0x83028851); + if (flag != nullptr && *flag == 0) { + REXLOG_INFO("xnet trace: forcing game live flag 0x83028851 = 1"); + *flag = 1; + } +} + void XNetTransport::SetRelay(const char* host, uint16_t port, const char* room) { { std::lock_guard lock(mu_);