[RE] Say so when a guest keystroke is swallowed by IsUIActive

XamInputGetKeystrokeEx returns X_ERROR_SUCCESS with a zeroed keystroke whenever
any Xenia dialog is up, before consulting a driver. That is correct behaviour and
an invisible one: from outside, scripted input simply stops working, the pad
driver logs nothing because it is never asked, and the guest keeps polling. It is
easy to enter that state by accident — F10 is both the RE capture hotkey and the
toolkit's menu-bar key, and a dialog closed by its own [x] rather than by the
menu toggle leaves the counter incremented.

So log it, rate-limited to one line per 600 swallowed calls, with the dialog
counters. On the runs this was written to diagnose it stays silent, which is what
ruled the theory out — a diagnostic that is useful when it does not fire.
This commit is contained in:
Sylpheed RE agent
2026-08-18 22:18:38 +00:00
parent 7dbb24e64f
commit 043002a871

View File

@@ -193,6 +193,21 @@ dword_result_t XamInputGetKeystrokeEx_entry(
keystroke.Zero();
if (kernel_state()->xam_state()->IsUIActive()) {
// RE aid: this early return hands the guest a SUCCESS with an empty
// keystroke without ever asking a driver, so scripted input goes silently
// dead for as long as any Xenia UI is up — including a dialog that was
// closed by its own [x] rather than by the menu toggle that decrements the
// counter. An invisible input blackout is expensive to diagnose from the
// outside; say so, rarely enough not to spam.
static std::atomic<uint32_t> swallowed{0};
const uint32_t n = swallowed.fetch_add(1, std::memory_order_relaxed);
if ((n % 600) == 0) {
XELOGW(
"[RE-INPUT] XamInputGetKeystrokeEx swallowed by IsUIActive "
"(dialogs={} nui={}, {} so far)",
kernel_state()->xam_state()->xam_dialogs_shown_.load(),
kernel_state()->xam_state()->xam_nui_dialogs_shown_.load(), n + 1);
}
return X_ERROR_SUCCESS;
}