Doom3Quest-based ports (PreyVR, #306) draw their menu on a curved
cylinder layer submitted once per eye. The Frame's runtime has no
cylinder layers, so FrameBridge shows each as ~7 flat quad strips; a
per-eye pair is ~14 quad layers in one frame, which the runtime rejects
whole (xrEndFrame -> XR_ERROR_LAYER_INVALID, -16). The menu then stays
black while the game runs at 72 fps.
Collapse the pair: drop the right-eye cylinder and show the left eye's
strips to both eyes (the runtime composites a quad to both eyes anyway).
That halves the layer count and drops the per-eye eyeVisibility, and the
runtime accepts the frame. Only frames with per-eye cylinders change --
exactly the ones that were being rejected; mono (BOTH) cylinder games
such as 4XVR are untouched.
Verified on the dev Frame (headless): PreyVR v1.2.4 rebuilt + installed,
the menu frame now submits (one transient -16 on the first frame before
the space is locatable, then clean), 72 fps. Visual confirmation of the
menu needs the headset. Triage signature cylinder-menu-layers-rejected.
No adapter revision bump (installed games are not marked outdated).
Diagnostics only (no behaviour change): the "new layer ... usable=0"
line prints a layer's swapchain pointer, but creation logged only the
result, so a dropped layer couldn't be matched to the xrCreateSwapchain
that made (or failed to make) its swapchain. Needed to pin why a quad
"screen layer" is dropped (#306 PreyVR: menu rendered to a quad whose
swapchain FrameBridge reports as not usable).
Headset-confirmed working configs shared through the issue form:
Tea For God (#295), Ghost Town (#299), Eye of the Temple (#302),
Ocean Rift (#304), Quantum Void (#307), AugmentedEmpire (#311),
Battlemarked (#312), Demeo (#313), Homeworld: Vast Reaches (#314),
Moss (#315), Maestro (#316), Mini Motor Racing X (#317),
Operation Wolf Returns (#318), Ragnarock (#319), Smash Drums (#320),
Vendetta Forever (#321).
Quantum Void, Homeworld: Vast Reaches and Ragnarock go in as status: issues.
Version 1.2.0; catalog min_app 1.1.2 -> 1.2.0 for the entries that need this release (Shadow Point, Medal of Honor, Assassin's Creed Nexus, Journey of the Gods).
Turns on frame.unreal_skip_obb_delivery (and keeps frame.hw_video_decode) so
the fix applies without the user finding the toggle. Not device-verified (the
game is ~41 GB); status unknown, min_app 1.1.2 so only builds that recognise
the obfuscated DownloaderActivity get it.
Medal of Honor (com.Virtuos.R6DLM) keeps Epic's DownloaderActivity and log text but renames the delivery predicates
and OBBData, so expansionFilesDelivered wasn't found and frame.unreal_skip_obb_delivery was never offered. Detection
now also matches a boolean method in the package's DownloaderActivity, called from onCreate, that carries Epic's
"Checking for file : " log and calls the expansion-downloader helpers; the patch rewrites those too. ANALYSIS_VERSION
18 -> 19. Heuristics eval unchanged (10/66); no existing recipe affected.
The GLES-only stand-in left Vulkan games (UNDERDOGS: VkFormat 43, faces=6) with the runtime's refusal, so OVRPlugin
crashed in ovrp_EndFrame4. When there's no GLES context, the adapter now makes a cube-compatible VkImage (6 layers,
the requested format/size/mips, usage from the XR flags) with the app's device/queue and a private transient pool,
transitions it to COLOR_ATTACHMENT_OPTIMAL, and enumerates it as a Vulkan image; its cube layers are still dropped.
GLES behaviour is unchanged. Adapter rebuilt deterministically (both ABIs).
Pre-#263 agents left shortcuts.vdf entries with both appname and AppName; vdf_decode then refused the file
("duplicate VDF key") and Add to Steam library failed. Duplicates are now merged into one key: Steam's capitalized
spelling kept, the last value taken. Clean files still round-trip unchanged.
Only big files (>=8 MiB) used OpenSSH; games made mostly of small files stayed on Paramiko and were slow on a fast
link. native_upload.put_tar streams the same tar batch through system ssh with the paired key and pinned host key;
on any failure the install falls back to Paramiko's put_tar and logs it, and doesn't retry OpenSSH for later batches.
The job log now names the transport for each part. upload_bench gains app-small / paramiko-small comparisons.
- unreal-obb-check-stuck names frame.unreal_skip_obb_check (CRC, needs bVerifyOBBOnStartUp) and
frame.unreal_skip_obb_delivery (the Java name/size gate), and says neither is a guaranteed fix.
- cube-swapchain-refused: the stand-in is GLES-only; a Vulkan game can't use it yet.
- A game that submitted projection frames but then logged no pacing summary for 20 s (process alive) is reported as
frames-stopped (info), so a hang like SKYBOX's signature check isn't a false pass. Headless no-tracking ends are
excluded.
Play on the Steam Frame tab for a game no longer in the library wrote last_played with upsert_game, which created an
entry with only that field: listed under its package name, "Update ready", and Update / Game settings failed with
KeyError 'recipe'. library.set_fields updates existing entries only (last played, test and session results, tags,
toggles); a one-time migration drops entries made of side notes alone.
After "Waiting for app", a failure line or 20 s without a logcat line start FramePort's own reader, from the
launcher's start (logcat -T <epoch>) when the mirror never wrote, else from just before its last line. The reader
restarts from where it ended, stops when Lepton's lines come back, the container's log buffer is 16 MiB, and every
decision goes to logcat-keeper.log.
Merged main (agent 90, ANALYSIS_VERSION 17/18 after main's 15/16) and rebuilt the bridge, foveation and a32
libraries from source (deterministic, no local paths).
Fixes on top:
- a32 loader: apply DT_ANDROID_RELR relocations (Journey of the Gods crashed at start)
- VrApi bridge: vrapi_Get/SetTrackingTransform (floor-level tracking; Shadow Point's player was below the floor)
- a32: never submit an untracked default head pose (hold up to 100 ms, repair or drop); pose consistency per display
time; submit/tracking counters
- VrApi bridge: wait again when xrWaitFrame gives a display time in the refresh just submitted (the runtime rejected
the second frame with AlreadySubmitted; Journey of the Gods ran at ~120 fps on a 90 Hz display and the scene slid
and snapped back); pacing counters
- VrApi bridge: GLES re-entry polls events before reusing the kept session (a lost or exiting session is replaced, a
stopped one waits for READY)
- VrApi bridge: STAGE is the runtime's STAGE space (play-area centre and orientation, unchanged by recentering);
LOCAL_FLOOR keeps the head-based origin
- signer certificate: pick the certificate the SignerInfo names, not the first in the PKCS#7 block
- flat 32-bit apps keep the bridge (it isn't a VR-only fix)
- Frida gadget loads are stripped before translation
- launcher restart test fixed; native/.cache is no longer committed
- catalog: Shadow Point and Journey of the Gods work (headset, 2026-10-14; min_app 1.1.2)
Rebuilt libvrapi.so and libvrapi_foveation.so without the local NDK paths a worktree build left in their debug info; a test checks that no artifact contains a local path.
On Frames whose Steam drops FramePort's shortcuts.vdf entries on every restart
(GitHub #41/#42), "Add to Steam library" restarted Steam twice and then failed
with "Steam removed the new library entry again after restarting". Play's
fallback (the devkit entry, the one Steam keeps) was never reached because
_add_then_play gave up first.
After the second loss the shortcuts worker now adds the devkit entry while
Steam runs, so the game ends up in the library as "Devkit Game: <title>" and
the job succeeds. Agent v89.
- Check the Steam shortcut on every update, also when nothing else changed: a connection lost during
"Add to Steam" or Steam putting its old shortcuts.vdf back left games without a library entry. The
agent restarts Steam only when the entry really changes.
- Artwork updates for installs without a recorded artwork manifest start from a clean folder again
(an old portrait.jpg next to a new portrait.png was picked at random for the Steam grid).
- OpenSSH uploads only rename .part files that are already complete (sftp's reput refuses them, which
sent every resume to the Paramiko fallback).
- frame.tbxr_vendor revision 2: GL4ES ports get "Update on Frame" for the #191 draw fix.
- Configuration-only updates send the library's current Steam tags.
- finalize drops fingerprints and the artwork record an older app didn't send.
- set_settings: malformed numbers are refused before anything is written; int settings keep a
fractional value.
- Display diagnostics use Windows PowerShell 5.1 without pwsh's PSModulePath; window diagnostics and
the instance owner file can't stop the GUI from starting.