netcode-revival: trace the online-path XNet/Xam calls
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
Adds an 'xnet trace' log to the online-path functions (XNetGetTitleXnAddr, XNetGetEthernetLinkStatus, QosListen/QosLookup, CreateKey, Connect, GetConnectStatus, XamUserGetSigninState/Info, XamShowSigninUI, privilege) gated on the xnet_trace cvar (default on during bring-up, rate-limited for the polling signin-state calls). Running the game and clicking the online flow now shows exactly which gate the party/EA path hits, so we can fix the real check instead of guessing at the reverse-engineered globals.
This commit is contained in:
parent
9e300e14bc
commit
7b6322b317
2 changed files with 59 additions and 0 deletions
|
|
@ -15,6 +15,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <rex/chrono/clock.h>
|
#include <rex/chrono/clock.h>
|
||||||
|
#include <rex/cvar.h>
|
||||||
#include <rex/kernel/xam/module.h>
|
#include <rex/kernel/xam/module.h>
|
||||||
#include <rex/kernel/xam/private.h>
|
#include <rex/kernel/xam/private.h>
|
||||||
#include <rex/kernel/xboxkrnl/error.h>
|
#include <rex/kernel/xboxkrnl/error.h>
|
||||||
|
|
@ -48,6 +49,15 @@ namespace xam {
|
||||||
using namespace rex::system;
|
using namespace rex::system;
|
||||||
using namespace rex::system::xam;
|
using namespace rex::system::xam;
|
||||||
|
|
||||||
|
// netcode-revival: trace the online-path calls so a run shows exactly which
|
||||||
|
// XNet/Xam gates the game hits (party/Ea Nation debugging). Default on during
|
||||||
|
// the revival bring-up; disable with xnet_trace=false before any release.
|
||||||
|
REXCVAR_DEFINE_BOOL(xnet_trace, true, "Kernel",
|
||||||
|
"Log online-path XNet/Xam calls (netcode debugging)");
|
||||||
|
bool XnetTrace() {
|
||||||
|
return REXCVAR_GET(xnet_trace);
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/G91/TitanOffLine/blob/1e692d9bb9dfac386d08045ccdadf4ae3227bb5e/xkelib/xam/xamNet.h
|
// https://github.com/G91/TitanOffLine/blob/1e692d9bb9dfac386d08045ccdadf4ae3227bb5e/xkelib/xam/xamNet.h
|
||||||
enum {
|
enum {
|
||||||
XNCALLER_INVALID = 0x0,
|
XNCALLER_INVALID = 0x0,
|
||||||
|
|
@ -498,6 +508,10 @@ u32 NetDll_XNetGetTitleXnAddr_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr) {
|
||||||
std::memset(addr_ptr->abOnline, 0, 20);
|
std::memset(addr_ptr->abOnline, 0, 20);
|
||||||
// 0x60 = the game's "online" status bits (not the standard 0-3 enum; the
|
// 0x60 = the game's "online" status bits (not the standard 0-3 enum; the
|
||||||
// game checks (status & 0x60) everywhere it means "connected to LIVE").
|
// game checks (status & 0x60) everywhere it means "connected to LIVE").
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetGetTitleXnAddr(caller={}) -> status 0x60 (online)",
|
||||||
|
caller);
|
||||||
|
}
|
||||||
return 0x60;
|
return 0x60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -576,6 +590,10 @@ u32 NetDll_XNetGetEthernetLinkStatus_entry(u32 caller) {
|
||||||
// machine only reaches the EA-Nation/online path when the link is up
|
// machine only reaches the EA-Nation/online path when the link is up
|
||||||
// (sub_82A1AAE8 returns the online server IP only if this is non-zero),
|
// (sub_82A1AAE8 returns the online server IP only if this is non-zero),
|
||||||
// so returning 0 left it frozen on "connecting to EA Nation" forever.
|
// so returning 0 left it frozen on "connecting to EA Nation" forever.
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetGetEthernetLinkStatus(caller={}) -> active 100Mbps",
|
||||||
|
caller);
|
||||||
|
}
|
||||||
return XEthernetStatus::XNET_ETHERNET_LINK_ACTIVE |
|
return XEthernetStatus::XNET_ETHERNET_LINK_ACTIVE |
|
||||||
XEthernetStatus::XNET_ETHERNET_LINK_100MBPS;
|
XEthernetStatus::XNET_ETHERNET_LINK_100MBPS;
|
||||||
}
|
}
|
||||||
|
|
@ -639,6 +657,10 @@ u32 NetDll_XNetQosListen_entry(u32 caller, mapped_void id, mapped_void data, u32
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)r7;
|
(void)r7;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetQosListen(caller={}, flags={}) -> ok (advertise)",
|
||||||
|
caller, flags);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -696,6 +718,11 @@ u32 NetDll_XNetQosLookup_entry(u32 caller, u32 cxna, mapped_void apxna, mapped_v
|
||||||
}
|
}
|
||||||
qos->count = qos->count_pending = n;
|
qos->count = qos->count_pending = n;
|
||||||
|
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetQosLookup(caller={}) -> {} session(s) found",
|
||||||
|
caller, n);
|
||||||
|
}
|
||||||
|
|
||||||
if (apxnqosResults) {
|
if (apxnqosResults) {
|
||||||
*apxnqosResults = qos_guest;
|
*apxnqosResults = qos_guest;
|
||||||
}
|
}
|
||||||
|
|
@ -713,6 +740,9 @@ u32 NetDll_XNetCreateKey_entry(u32 caller, mapped_void key) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return X_ERROR_INVALID_PARAMETER;
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetCreateKey(caller={})", caller);
|
||||||
|
}
|
||||||
uint8_t* out = static_cast<uint8_t*>(key);
|
uint8_t* out = static_cast<uint8_t*>(key);
|
||||||
uint64_t r = XnetNextRand();
|
uint64_t r = XnetNextRand();
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
|
@ -726,6 +756,9 @@ u32 NetDll_XNetCreateKey_entry(u32 caller, mapped_void key) {
|
||||||
|
|
||||||
// netcode-revival: accept + (Phase 1) register the session key.
|
// netcode-revival: accept + (Phase 1) register the session key.
|
||||||
u32 NetDll_XNetRegisterKey_entry(u32 caller, mapped_void key) {
|
u32 NetDll_XNetRegisterKey_entry(u32 caller, mapped_void key) {
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetRegisterKey(caller={})", caller);
|
||||||
|
}
|
||||||
(void)key;
|
(void)key;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -737,6 +770,10 @@ u32 NetDll_XNetUnregisterKey_entry(u32 caller, mapped_void key) {
|
||||||
|
|
||||||
// netcode-revival: connecting to a peer is reported as established.
|
// netcode-revival: connecting to a peer is reported as established.
|
||||||
u32 NetDll_XNetConnect_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr) {
|
u32 NetDll_XNetConnect_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr) {
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetConnect(caller={}, peer=10.80.0.{})",
|
||||||
|
caller, xn_addr ? (ntohl(xn_addr->ina.s_addr) & 0xFFu) : 0);
|
||||||
|
}
|
||||||
(void)xn_addr;
|
(void)xn_addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -744,6 +781,9 @@ u32 NetDll_XNetConnect_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr) {
|
||||||
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/xna/xnetgetconnectstatus
|
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/xna/xnetgetconnectstatus
|
||||||
// INT XNetGetConnectStatus(const XNADDR* pxna, INT* pxncs)
|
// INT XNetGetConnectStatus(const XNADDR* pxna, INT* pxncs)
|
||||||
u32 NetDll_XNetGetConnectStatus_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr, mapped_void status_ptr) {
|
u32 NetDll_XNetGetConnectStatus_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr, mapped_void status_ptr) {
|
||||||
|
if (XnetTrace()) {
|
||||||
|
REXLOG_INFO("xnet trace: XNetGetConnectStatus(caller={}) -> CONNECTED", caller);
|
||||||
|
}
|
||||||
(void)xn_addr;
|
(void)xn_addr;
|
||||||
if (status_ptr) {
|
if (status_ptr) {
|
||||||
const uint32_t connected = 2; // XNET_CONNECT_STATUS_CONNECTED
|
const uint32_t connected = 2; // XNET_CONNECT_STATUS_CONNECTED
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ using namespace rex::system::xam;
|
||||||
|
|
||||||
extern std::atomic<int> xam_dialogs_shown_;
|
extern std::atomic<int> xam_dialogs_shown_;
|
||||||
|
|
||||||
|
REXCVAR_DECLARE(bool, xnet_trace);
|
||||||
|
|
||||||
i32 XamUserGetXUID_entry(u32 user_index, u32 type_mask, mapped_u64 xuid_ptr) {
|
i32 XamUserGetXUID_entry(u32 user_index, u32 type_mask, mapped_u64 xuid_ptr) {
|
||||||
assert_true(type_mask == 1 || type_mask == 2 || type_mask == 3 || type_mask == 4 ||
|
assert_true(type_mask == 1 || type_mask == 2 || type_mask == 3 || type_mask == 4 ||
|
||||||
type_mask == 7);
|
type_mask == 7);
|
||||||
|
|
@ -82,6 +84,17 @@ u32 XamUserGetSigninState_entry(u32 user_index) {
|
||||||
signin_state = user_profile->signin_state();
|
signin_state = user_profile->signin_state();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (REXCVAR_GET(xnet_trace)) {
|
||||||
|
// Rate-limited: the frontend polls this frequently.
|
||||||
|
static double last_log = 0.0;
|
||||||
|
const double now =
|
||||||
|
double(std::chrono::steady_clock::now().time_since_epoch().count()) / 1e9;
|
||||||
|
if (now - last_log >= 0.5) {
|
||||||
|
last_log = now;
|
||||||
|
REXLOG_INFO("xam trace: XamUserGetSigninState(user={}) -> {}", user_index,
|
||||||
|
signin_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
return signin_state;
|
return signin_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,6 +126,10 @@ i32 XamUserGetSigninInfo_entry(u32 user_index, u32 flags, ppc_ptr_t<X_USER_SIGNI
|
||||||
info->xuid = user_profile->xuid();
|
info->xuid = user_profile->xuid();
|
||||||
info->signin_state = user_profile->signin_state();
|
info->signin_state = user_profile->signin_state();
|
||||||
rex::string::util_copy_truncating(info->name, user_profile->name(), rex::countof(info->name));
|
rex::string::util_copy_truncating(info->name, user_profile->name(), rex::countof(info->name));
|
||||||
|
if (REXCVAR_GET(xnet_trace)) {
|
||||||
|
REXLOG_INFO("xam trace: XamUserGetSigninInfo(user={}, flags={}) -> signin_state={}",
|
||||||
|
user_index, flags, user_profile->signin_state());
|
||||||
|
}
|
||||||
return X_E_SUCCESS;
|
return X_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,6 +555,8 @@ u32 XamUserAreUsersFriends_entry(u32 user_index, u32 unk1, u32 unk2, mapped_u32
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 XamShowSigninUI_entry(u32 unk, u32 unk_mask) {
|
u32 XamShowSigninUI_entry(u32 unk, u32 unk_mask) {
|
||||||
|
REXLOG_INFO("xam trace: XamShowSigninUI(unk={}, mask={}) - game asked for sign-in",
|
||||||
|
unk, unk_mask);
|
||||||
// Mask values vary. Probably matching user types? Local/remote?
|
// Mask values vary. Probably matching user types? Local/remote?
|
||||||
KernelState* kernel_state = REX_KERNEL_STATE();
|
KernelState* kernel_state = REX_KERNEL_STATE();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue