From d712e5aa1a889959292028e49cd24cf9a701b408 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 18:41:09 +0000 Subject: [PATCH] re: SOLVED -- the mission freeze is a modal sign-in dialog Every Xam UI dialog goes through xeXamDispatchDialog, and the calling guest thread blocks on fence.Wait() until it is dismissed. With kernel logging on the last call before the freeze is XamShowSigninUI(00000001, 00000001): the game asks for a signed-in profile, Xenia opens a modal dialog, and nothing in a scripted run ever dismisses an ImGui dialog. That accounts for every symptom at once -- Main XThread futex-blocked at 0 ms CPU rather than spinning, emulator alive, no guest progress, no faults, and independence from both the GPU backend and the allocation outcome. Fix: run-canary --logged_profile_slot_0_xuid=B13EBABEBABEBABE. Same route, one variable changed: no profile with profile screen id 4, forever 4 -> 5 -> 6 -> 8 -> 9 -> 10 XamShowSigninUI called not called alloc failures 1 0 guest throws 1 0 guest churn 0.000% 1.006% XamShowDeviceSelectorUI is then requested but storage_selection_dialog defaults to false, so it is not shown and does not block. Why it took so long: --log_mask=13, used by every script in this corpus, DISABLES kernel logging -- the one category that names the dialog. Without it the freeze presents as a bare futex block, which is why it was attributed in turn to a heap leak, rounding, MmQueryStatistics, a build regression, the route, the savegame, shader compilation, an infinite guest loop and the software rasterizer, each refuted in its own section. Nearest miss worth recording: challenge-mission-gate.md reported a "Disc Read Error" dialog on this failure. That is XamShowDirtyDiscErrorUI, which calls exit(1) -- "This is death, and should never return" -- so it cannot be our freeze, whose process stays alive. Checking that distinction is what led to the dialog mechanism. Open: no mission reached yet (DEF_VTABLE/INST_VTABLE still 0 at screen 10), so the remaining screens are menus. Ordinary navigation, not a blocker. --- docs/re/BACKLOG.md | 12 +++++ docs/re/mission-freeze-signin-dialog.md | 69 +++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 docs/re/mission-freeze-signin-dialog.md diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 7b555fe5..8b96969c 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -6,6 +6,18 @@ unknown, what evidence exists, and what the first step would be. Move an item in --- +## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26) + +`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the +calling guest thread on `fence.Wait()` until it is dismissed — which nothing in a +scripted run ever does. **Fix: pass `--logged_profile_slot_0_xuid=…`.** Same +route, one variable: screen id goes from stuck at **4 forever** to +**4 → 5 → 6 → 8 → 9 → 10**, allocation failures 1 → **0**, guest throws 1 → **0**, +guest churn 0.000 % → **1.006 %**. +It hid for so long because `--log_mask=13` (used by every script here) +**disables kernel logging**, the one category that names the dialog. +See [`mission-freeze-signin-dialog.md`](mission-freeze-signin-dialog.md). + ## 🔴 ~~BLOCKER — the mission freeze is a software-rendering hang~~ WITHDRAWN (2026-08-26) > **Withdrawn the same day.** Driving the null backend blind to the *same* screen diff --git a/docs/re/mission-freeze-signin-dialog.md b/docs/re/mission-freeze-signin-dialog.md new file mode 100644 index 00000000..32d819bf --- /dev/null +++ b/docs/re/mission-freeze-signin-dialog.md @@ -0,0 +1,69 @@ +# ✅✅ The freeze is `XamShowSigninUI` — a modal dialog nobody can dismiss + +**Root-caused 2026-08-26**, after a long chain of wrong answers recorded in +[`mission-freeze-heap-exhaustion.md`](mission-freeze-heap-exhaustion.md). + +## The mechanism, from Xenia's source + +Every Xam UI dialog goes through `xeXamDispatchDialog` (`xam_ui.cc:60`), and the +calling **guest thread blocks**: + +```cpp +xe::threading::Fence fence; +if (app_context.CallInUIThreadSynchronous( + [&dialog, &fence]() { dialog->Then(&fence); })) { + fence.Wait(); // <- the guest thread stops here until dismissed +``` + +With kernel logging enabled (`--log_mask=0`; note **`log_mask` disables** +categories, so the `--log_mask=13` used throughout this corpus hides exactly +this), the last kernel call before the freeze is: + + d> F8000008 XamShowSigninUI(00000001, 00000001) + +The game asks for a signed-in profile, Xenia opens a modal sign-in dialog, and +the guest waits on the fence **forever** — nothing in a scripted run dismisses an +ImGui dialog. + +That accounts for every symptom at once: `Main XThread` **futex-blocked at 0 ms +CPU** rather than spinning; the emulator alive and healthy; no guest progress; no +faults; and independence from both the GPU backend and the allocation outcome. + +## ✅ The fix, and the before/after + +`run-canary` accepts `--logged_profile_slot_0_xuid=B13EBABEBABEBABE`. Same route, +same inputs, one variable changed: + +| | without a profile | **with `--logged_profile_slot_0_xuid`** | +|---|---|---| +| screen id reached | **4, forever** | **4 → 5 → 6 → 8 → 9 → 10** | +| `XamShowSigninUI` | **called** | not called | +| allocation failures | 1 | **0** | +| guest throws | 1 | **0** | +| guest churn | 0.000 % (19 B of 8 MB) | **1.006 %** (81 KB of 8 MB) | + +The game walks through six further screens where it previously sat at one +forever. `XamShowDeviceSelectorUI` is then requested, but +`storage_selection_dialog` defaults to **false**, so that dialog is not shown and +does not block. + +## 🔴 Why this took so long — and what it invalidates + +The `--log_mask=13` used by every script in this corpus **disables kernel +logging**, which is the one category that names the dialog. Without it the freeze +presents as a bare futex block with no explanation, which is why it was +attributed in turn to a heap leak, allocation rounding, `MmQueryStatistics`, a +build regression, the navigation route, the savegame, shader compilation, an +infinite guest loop, and finally the software rasterizer — each refuted in its +own section. + +⚠️ The nearest miss is worth recording: `challenge-mission-gate.md` reported +Xenia showing a *"Disc Read Error"* on this failure. That is a **different** +dialog (`XamShowDirtyDiscErrorUI`), and it calls `exit(1)` — "This is death, and +should never return" — so it cannot be our freeze, whose process stays alive. +Checking that distinction is what led to the dialog mechanism. + +❔ Still open: a mission has not been reached yet — `DEF_VTABLE` / `INST_VTABLE` +scans are still 0 at screen 10, so the remaining screens are menus (mission +select, briefing, ready room). That is now ordinary navigation work, not a +blocker.