mirror of
https://github.com/spoopyghosty0/frameport.git
synced 2026-10-06 08:00:35 +02:00
Dashboard at game start (agent v52): watch from the game's first submitted frame instead of the first pacing summary, which came ~8 s after Steam's "Resume game" menu (seen with Into The Radius 2); incremental log reads, 0.5 s checks
This commit is contained in:
1 parent
c3a34ace99
commit
6037b13e88
3 files changed
+42
-10
No files matched your search
@@ -516,7 +516,7 @@ picker at all: a FramePort fix would be an injected picker activity. Generated c
|
||||
Steam placeholder set (no Steam art at all) → fixed in artwork/steam.py.
|
||||
**Steam library failures (GitHub #21/#30):** on some Frames Steam never loads FramePort's shortcuts.vdf entries (same SteamOS build and arm64 beta client as the dev Frame; IDs correct; file written before Steam starts): Play → console_log `GameAction [AppID <id>] … RequestingLicense → UpdatingAppInfo → LaunchApp failed with AppError_9` (= "Game configuration unavailable", Steam treats the id as a store app). Cause unknown; agent v42/43 diagnostics: `launch` returns `steam` (started / error + code / silent from console_log), `collect_diag` adds `steam_library` (real Steam dir, beta, Steam start vs vdf write time, entries per account, devkit games) + `steam-console.txt` (incl. Steam's `logs/shortcuts.previous.txt` if present; steamclient.so has "LoadShortcuts: rejecting attempt to load shortcuts: invalid account ID"). **Fallback (agent v43):** when Play gets AppError_9 the agent registers the game through Steam's devkit interface (what Valve's Devkit Management Tool does, MIT: `devkit-1 steam://devkit-1/<~/.steam/steam.token>/create-shortcut?response=<file>&gameid=<id>&directory=~/devkit-game` written to ~/.steam/steam.pipe; answer file / `.error`; `~/devkit-game/<id>/launch.sh` = link to the game's launch.sh, `<id>-argv.json` ["launch.sh"] (relative to the folder), `<id>-settings.json` {steam_play 0, compat_tool ""}). Steam adds it live (no restart), picks its own appid (read back from shortcuts.vdf by DevkitGameID), shows it as a normal non-Steam game named "Devkit Game: <id>" (OpenVR 0, but VR works: owner-verified 2026-10-04), art copied to grid/<appid>*. Ids: letter first, then letters/digits/_ only (spaces, '-', leading digit → "missing/invalid arguments"). Later Plays use the devkit entry; uninstall (`devkit_unregister`, `delete-shortcut` live) and purge remove it. Verified on the dev Frame: register/launch/unregister; the AppError_9 trigger itself only in unit tests.
|
||||
**Exit game (GitHub #36, 2026-10-04):** `Apps.TerminateApp` (what Exit game calls; reachable for tests through Steam's CEF devtools on 127.0.0.1:8080, SharedJSContext, `Runtime.evaluate` — a stdlib websocket client is enough) closed both a normal shortcut and a devkit entry on the dev Frame within 1-3 s. SIGTERM to Steam's `reaper` alone left launch.sh + Lepton (setsid) + the container running (an earlier headset launch ran on for 87 min); SIGTERM to launch.sh cleans up in ~4 s. Agent v44: launch.sh's 2 s loop ends the game when its parent (the reaper) is gone; `upgrade_launchers` (from ensure_host_fixes) adds that to existing launchers in place. Which in-headset exit path fails is still unknown. Screenshots on the Frame: all under SteamVR's appid 250820 (`760/remote/250820/screenshots`, screenshots.vdf has creation time, no game).
|
||||
**SteamVR dashboard at game start (2026-10-04):** the dashboard (Resume game / controller / VR options) was open whenever a FramePort game started (also over Lepton's 2D launcher). Steam's UI exposes `SteamClient.OpenVR.VROverlay.{IsDashboardVisible,HideDashboard,ShowDashboard}` (CEF devtools, `steam_js` in the agent). Agent v44: launch.sh starts `_dashboard_worker` (waits for FrameBridge's first `pacing:` line in launch.log, then hides a visible dashboard for 25 s, at most 3 times; log `<base>/dashboard.log`; opt out with env FRAMEPORT_KEEP_DASHBOARD=1). Verified on the dev Frame (dashboard shown → 4XVR launched via Steam → hidden ~5 s after the first frames); not yet seen in the headset.
|
||||
**SteamVR dashboard at game start (2026-10-04):** the dashboard (Resume game / controller / VR options) was open whenever a FramePort game started (also over Lepton's 2D launcher). Steam's UI exposes `SteamClient.OpenVR.VROverlay.{IsDashboardVisible,HideDashboard,ShowDashboard}` (CEF devtools, `steam_js` in the agent). Agent v44: launch.sh starts `_dashboard_worker` (waits for FrameBridge's first `pacing:` line in launch.log, then hides a visible dashboard for 25 s, at most 3 times; log `<base>/dashboard.log`; opt out with env FRAMEPORT_KEEP_DASHBOARD=1). Verified on the dev Frame (dashboard shown → 4XVR launched via Steam → hidden ~5 s after the first frames); not yet seen in the headset. **Headset (ITR2, 2026-10-05): too late** — Steam shows its frame menu (`valve.steam.gamepadui.frame.menu`, vrwebhelper_systemui.txt `[PooledPopups] Showing`) ~0.3 s after the game's first submitted frame (FrameBridge `new layer:`), but the first `pacing:` summary comes ~8 s later; the owner had pressed Resume (`[HideDashboard] return_to_game`) before the worker looked. Agent v52: watches from the first `new layer:` line (incremental log reads, 0.5 s polls, 30 s window).
|
||||
**Space warp / ITR2 (2026-10-04):** Into The Radius 2 (UE5, `libUnreal.so` + OVRPlugin, Vulkan) uses Application SpaceWarp (extra swapchains `376x376 format=97` motion vectors + `format=129` depth); #35 reports flickering textures. OVRPort's `patch_disable_space_warp` has no effect on UE5, and hiding XR_FB_space_warp in FrameBridge's enumerate doesn't reach the game either: **OVRPort's dispatcher offers/enables XR_FB_space_warp itself**. FrameBridge `hide_space_warp` (per game, off) hides it and strips `XrCompositionLayerSpaceWarpInfoFB` (1000171000) from the projection views (log `hide_space_warp: removed space warp info`); the game still renders its MV swapchains. Test build installed on the dev Frame; flicker not yet checked in a headset. Heuristic: UE5 + OVRPlugin shows it as an option (off). `equirect_emul` is suggested for Unreal games whose graphics API isn't detected ("GLES or unknown"); on Vulkan it switches itself off (Myst/Riven/ITR2): harmless, but Unreal Vulkan detection is a known gap.
|
||||
**PR #34 (merged 2026-10-04, Lucas-Mathieu):** `native/adapter/audio_metadata.h` patches Meta XR Audio Wwise (only build ID e1619e7f…, Batman: Arkham Shadow 1.4.1) so queued audio metadata isn't freed while the current audio frame references it (smoke-bomb crash). Verified headless: installs ("metadata reclamation follows …"), 72 fps; we added a once-per-second scan limit. Outside PRs: review source, rebuild `artifacts/` ourselves, merge locally (contributor's commit kept), push main.
|
||||
**Heuristics eval (2026-10-04):** `scripts/eval_heuristics.py "<VR CyberDeck Portable>"` → 19/44 recipes exact, 322/352 fields (most diffs: `frame.unity_text_input` suggested where older catalog recipes lack it; the rest are runtime-only findings: use_alt, vk_shader_fix, focus_hold, sync_guard, multipass). `PATCHED/` copies aren't scored (already converted).
|
||||
|
||||
@@ -36,7 +36,7 @@ import time
|
||||
import zlib
|
||||
from types import SimpleNamespace
|
||||
|
||||
AGENT_VERSION = 51
|
||||
AGENT_VERSION = 52
|
||||
HOME = os.path.expanduser("~")
|
||||
STEAM = os.path.join(HOME, ".local/share/Steam")
|
||||
ANCHORS = os.path.join(HOME, "Applications/quest-frame")
|
||||
@@ -3627,27 +3627,38 @@ def steam_js(expression, timeout=5):
|
||||
return res.get("value")
|
||||
|
||||
|
||||
def dashboard_worker(log, parent, wait_start=240, window=25):
|
||||
"""Close SteamVR's dashboard once the game's first VR frames are logged (FrameBridge's "pacing:" line), checking
|
||||
for `window` seconds after that (Steam can open it a moment later; at most 3 times). Ends with the launcher."""
|
||||
FIRST_FRAME_MARKERS = (b"FrameBridge: new layer:", b"FrameBridge: pacing:")
|
||||
|
||||
|
||||
def dashboard_worker(log, parent, wait_start=240, window=30, poll=0.5):
|
||||
"""Close SteamVR's dashboard (Steam's "Resume game" frame menu) that opens when the game submits its first VR
|
||||
frame: watch from FrameBridge's first "new layer:" line (the first submitted frame; Steam showed the menu ~0.3 s
|
||||
later with ITR2), checking every `poll` s for `window` s after it (at most 3 hides). Waiting for the first
|
||||
"pacing:" summary (agent 44-51) was ~8 s too late: the owner had pressed Resume by then. Ends with the launcher."""
|
||||
def alive():
|
||||
try:
|
||||
os.kill(int(parent), 0)
|
||||
return True
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
deadline = time.time() + wait_start
|
||||
deadline, pos, tail = time.time() + wait_start, 0, b""
|
||||
while time.time() < deadline and alive():
|
||||
try:
|
||||
with open(log, "rb") as f:
|
||||
if b"FrameBridge: pacing:" in f.read():
|
||||
break
|
||||
f.seek(pos)
|
||||
chunk = f.read()
|
||||
pos += len(chunk)
|
||||
text = tail + chunk
|
||||
if any(m in text for m in FIRST_FRAME_MARKERS):
|
||||
break
|
||||
tail = text[-64:] # a marker split across two reads
|
||||
except OSError:
|
||||
pass
|
||||
time.sleep(1)
|
||||
time.sleep(poll)
|
||||
else:
|
||||
print("no VR frames logged; dashboard left as it is")
|
||||
return
|
||||
print(f"{time.strftime('%H:%M:%S')} first VR frame")
|
||||
hidden, end = 0, time.time() + window
|
||||
while time.time() < end and hidden < 3 and alive():
|
||||
try:
|
||||
@@ -3658,7 +3669,7 @@ def dashboard_worker(log, parent, wait_start=240, window=25):
|
||||
except Exception as exc: # noqa: BLE001 (no devtools port, Steam restarting: leave it)
|
||||
print(f"steam ui: {exc}")
|
||||
return
|
||||
time.sleep(1)
|
||||
time.sleep(poll)
|
||||
|
||||
|
||||
COMMANDS = {n[4:]: f for n, f in globals().items() if n.startswith("cmd_")}
|
||||
|
||||
@@ -1153,6 +1153,27 @@ def test_dashboard_worker_hides_dashboard_after_first_frames(monkeypatch, tmp_pa
|
||||
assert calls.count("SteamClient.OpenVR.VROverlay.HideDashboard()") == 3 # at most three times
|
||||
|
||||
|
||||
def test_dashboard_worker_starts_at_the_first_submitted_frame(monkeypatch, tmp_path):
|
||||
"""Steam's "Resume game" menu opens at the game's first frame (ITR2: 0.3 s after FrameBridge's "new layer:"); the
|
||||
first "pacing:" summary comes ~8 s later, after the player had pressed Resume. The log grows while it waits."""
|
||||
a = load_agent(monkeypatch, tmp_path)
|
||||
log = tmp_path / "launch.log"
|
||||
log.write_text("Lepton starting\nI FrameBridge: xrCreateSwapchain 2016x1728\nI FrameBridge: new la")
|
||||
pieces = ["yer: type=35 swapchain=0x0\n"] # the marker split across two reads
|
||||
|
||||
def sleep(s):
|
||||
if pieces:
|
||||
with open(log, "a") as f:
|
||||
f.write(pieces.pop(0))
|
||||
monkeypatch.setattr(a.time, "sleep", sleep)
|
||||
clock = iter(range(0, 10000))
|
||||
monkeypatch.setattr(a.time, "time", lambda: next(clock))
|
||||
calls = []
|
||||
monkeypatch.setattr(a, "steam_js", lambda expr, timeout=5: calls.append(expr) or expr.endswith("Visible()"))
|
||||
a.dashboard_worker(str(log), os.getpid(), wait_start=10, window=4)
|
||||
assert "SteamClient.OpenVR.VROverlay.HideDashboard()" in calls
|
||||
|
||||
|
||||
def test_dashboard_worker_waits_for_vr_frames(monkeypatch, tmp_path):
|
||||
a = load_agent(monkeypatch, tmp_path)
|
||||
monkeypatch.setattr(a.time, "sleep", lambda s: None)
|
||||
|
||||
Reference in new issue
Block a user