Add opt-in swapchain_pool with private GLES images and up to two packed
runtime atlases. Start at eight live app runtime swapchains to reserve
headroom before the session cap. Preserve image ownership, GL state,
source fences, crops and the existing cylinder/equirect layer ordering.
Enable for 4XVR, add count-limit triage without unknown suggestions for
older apps, and document the pending headset menu check. Leave default
recipes and adapter revisions unchanged. Rebuild arm64/arm32 artifacts.
Validation: 132 targeted tests passed (2 skipped), including the native
runtime/GL harness; Ruff and generated docs pass. Full host suite:
2095 passed, 137 skipped, 12 failures and 16 setup errors, all denied
socket creation in this sandbox. No headset validation or push.
Detect and redirect static loader manifests and Android brokers, ship a runtime negotiation shim and the inner loader chain, and maintain per-game manifests on install and launch. Add the PrimedGun recipe, triage and host coverage.
Route OVRPlugin recommendations through the existing extension shim, retain native loader hooks, and log projection rect changes once per second per eye. Enable the fix for Batman, document verification, and rebuild both adapter architectures.
Bionic allows 128 pthread keys per process. Unity 6 takes about 40, and with Gecko, Firebase and the Frame's own
libraries Wander 0.3570 ran out: Firestore aborted at start ("cannot create thread specific key for
__cxa_get_globals()", #198, #202). Opt-in patch, suggested for Unity 6 with Firebase C++ or Gecko: libunity.so's
pthread_key_create/_delete and pthread_get/setspecific imports are renamed in place to fp_tkey_* (new
elf.rename_imports: undefined symbols only, shared names refused, versions set global) and libfp_tkeys.so
(native/tlskeys) is added to its DT_NEEDED; keys without a destructor become generation-tagged slots behind one
real key, everything else keeps real keys. Approach and the first helper by Klownicle (#198), reimplemented here.
Triage signature pthread-keys-exhausted, PLAYBOOK row, Wander's recipe updated to 0.3570.
Mesa enforces OVR_multiview's rule that a draw's program declares as many views as the draw framebuffer has and drops the draw silently; Doom3Quest compiles every vertex shader with layout(num_views=2) and draws its HUD/PDA into 2D-texture FBOs, which stay black on the Frame.
native/glmv (libfpglmv.so, same length as libGLESv3.so): the engine library's dlopen string is rewritten to it and it becomes the first DT_NEEDED. It records stage sources at link time and, when a multiview program draws into a framebuffer without views, draws with a lazily built single-view twin (num_views layout blanked, gl_ViewID_OVR -> 0u; attribute locations, block bindings and uniform values copied), then rebinds the original. Opt-in and experimental (analysis gl_multiview_libs, ANALYSIS_VERSION 6), setting gl_mv_debug, triage gl-multiview-twin-failed.
Host tests: the rewriter on Doom3Quest's 19 shaders (GPL-3.0 fixtures) and glmv.c against a stand-in GL that applies Mesa's rule. Untested on the device.
Klownicle's five fixes for Vader Immortal: Episode I, reimplemented as FramePort patches (found by Klownicle,
GitHub #49; their prebuilt APK is not used):
- frame.unreal_quest_precompile: UVRUtils::GetQuestShaderPrecompilePercent returned 0.0 on its non-Quest branch, so
the menu waited forever on the loading card; that branch now returns 1.0. Located by symbol, every instruction
around it checked (bl IsRunningOnSantaCruz; tbz w0,#0; fmov s0,wzr; ldp; ret); other builds stay untouched.
- frame.unreal_quest_keymap: the RPOC key selector (shared by AddAxisMapping and AddActionMapping, so both mapping
kinds were affected) picked the empty Gear VR key set for an Oculus HMD; the tbz to it becomes a nop. Located as
the common callee of both functions, pattern-checked.
- frame.zink_shader_fix + native/zinkfix (libVkLayer_fp_shaderfix.so): a Vulkan layer under Zink for GLES games
that applies zink_shader_fix entries (vk_shader_fix format) to the SPIR-V Zink generates; it adds itself to
GraphicsEnv's debug layer list from a constructor (the engine library loads it first). zink_shader_dump=1
captures modules. Vader's recipe carries the two lightspeed-shader fixes (12 OpStores each).
- adapter proximity_emul (FrameBridge): OVRPlugin's thumb/index proximity actions get bindings to the capacitive
touch inputs when the runtime lacks XR_FB_touch_controller_proximity (OVRPort offers the extension anyway):
generic replacement for the libUE4 ThumbUp patch.
- Vader's recipe: pose_time_fix + proximity_emul, status unknown (to test in the headset), min_app 0.12.1.
Analysis records unreal_quest_gates (ANALYSIS_VERSION 4). Star Wars: Tales from the Galaxy's Edge (same studio)
has neither gate (different engine build) and gets a catalog entry with pose_time_fix + proximity_emul.
Headless on the dev Frame (Lepton 3.0.5): the layer loads into Zink's instances, the proximity bindings are
accepted, and the game passes the loading card to the "guardian smaller than recommended, press any button" screen.
native/venc/fp_venc: own clean-room driver of the Frame's iris encoder (V4L2 stateful encoder interface, written from
native/venc/SPEC.md = kernel docs + values measured on the Frame). Reads SteamVR's headset-view webcam, box-scales and
converts RGB24 to NV12 (NEON, bit-identical scalar reference), CBR H.264 with SPS/PPS on every IDR, one frame per slot
of an even fraction of the panel rate read through DRM (96 Hz -> 32 fps). stdin "k" = keyframe, EOF = stop;
--probe/--selftest. Static freestanding aarch64 binary in artifacts/linux-arm64-bin (reproducible).
livestream: the script probes fp_venc and pipes it into ffmpeg (-c:v copy + AAC), else the old x264 30 fps path; the
helper is synced to ~/.local/share/frameport/bin by sha256 at stream start (no agent change); a new viewer asks for a
keyframe and waits for it; the status line shows the encoder and fps. Tests: hardware/fallback script branches,
keyframe-on-join, helper sync; tests/test_venc.py compares convert.c with a Python reference (native marker).
Not yet run on the device.
Some Quest games ship voice-over languages as <tag>.lang files and ask the Meta Platform SDK for them; overport's
platform loader answers with nothing, so every language but the built-in one stays greyed out. libfp_langpack.so
answers the language-pack and asset-file calls from the packs already on the device (Metadata = the game's
versionName, the /storage/emulated/0 path spelling Unreal uses). Tested in the headset with Deadpool VR (German
dialogue), AC Nexus and Asgard's Wrath 2.
- The overport CLI now comes from Android-XR-Bridge/OVRPort (fallback ovrport/app); its four new patches are
described and shown only where they apply; parity classifies the 1.2.5 differences (VR metadata, config version,
CLI-added platform compat) as expected: 34/34 at parity.
- README rewritten (purpose, getting started, what works, credits, legal), INSTALL tightened, screenshots in
docs/images (scripts/scrub_library.py + ui_smoke --docs --fake-frame), Quest2Frame references removed.
- Game page: store descriptions without Markdown/[media] markup; themed labels on all switches.
- `frameport install --apk` installs a given build (headset A/B tests).
FrameBridge (all new behaviour per game, off by default; hooks installed only when on):
- equirect_emul (GLES only): 360° equirect/equirect2 layers, which the Frame runtime
lacks, are drawn into one adapter projection layer by a worker thread with a shared
EGL context. Each 360° image becomes a cube map only when it changes; the view is
drawn early (from the app's xrLocateViews) with the frame's exact views. Write-once
360° picture swapchains are served by the adapter (frees runtime swapchain slots).
Learned: the Frame draws quad layers above all projection layers, and doesn't
reproject a projection layer from its own pose.
- session_fixes: layer_debug diagnostics, stable_local, focus_hold, aim correction,
refresh_rate.
- Agent v26: link_media (files sent to shared folders also appear in a player's own
folder), app media folder detection, launcher creates Android/data/<pkg>/{files,cache}.
App: "Add videos" for players, Update all, Rescan folders (only new games), Install
anyway for "Can't run" games, launch-test toggle, triage `unless`, generic source hints.
Catalog: 4XVR, NEX Player, Deadpool VR (working, owner-confirmed).
Games that ask the runtime for controller models (Meta's runtime controller
models) get the Steam Frame controllers instead of Quest Touch ones:
- adapter (render_model.c): emulates XR_FB_render_model when the runtime lacks
it and serves files/framebridge/controller_{left,right}.glb. Off by default;
suggested for games declaring the RENDER_MODEL permission/feature (none of
the 34 catalog games do).
- agent v20: converts the Frame's own SteamVR render models (frame_controller
driver, OBJ+PNG, openxr_grip -> grip space) to glb on the device at install /
set_settings; Valve's models never leave the Frame. `frameport frame
controller-models` lists what it finds.
- xrshim: overport's dispatcher only forwards functions in its own table
("Unknown proc addr"), so OVRPlugin's dlopen("libopenxr_loader.so") string
is pointed at libframe_xrshim.so, which serves the emulated functions and
forwards everything else to overport. Only added with controller_models=1;
other builds differ from known-good only in the adapter binary.
Verified on the device with Toy Master: models converted, adapter emulation on,
all three render-model functions resolved through FrameBridge; launches match
the known-good build. Not yet seen rendering in a game (none requests a model).
Adds Oculus Rift (PC VR) games alongside Quest:
- analysis/rift.py (own PE reader: imports incl. delay-imports, GUI-subsystem
filter, exe ranking, icons), sources/rift_dump.py (recursive scan, one game
per folder, collections), catalog rift fields + Rick and Morty recipe.
- patches/pcvr.py (category "pcvr", shown as patches): Revive (LibOVR->OpenXR,
default on for Oculus games), revive_openvr, no_crash_reporter (Unreal),
oculus_unreal (OculusHMDConnected helper), xr_timefix (Frame OpenXR layer),
proton_*. tools/revive.py (find/install Revive, never replaces the user's).
- targets/pc_revive.py (run on this Windows/WSL PC via Revive + local Steam;
core/winhost.py helpers) and frame_lepton Proton path; agent handles Proton
install, prepare/finalize_pcvr, launch, list_files (AGENT_VERSION 17).
- native/oculushmd (fp_oculushmd.exe) and native/xrlayer (Frame OpenXR 1.1->1.0
+ timespec-time layer); prebuilt artifacts + SHA256SUMS.
Runtime findings (Frame, SteamOS 0.4.2 / Proton 11 arm64): the SteamVR runtime
only accepts OpenXR 1.0, so Proton's vrhelper (1.1) needs the compat layer;
Oculus/LibOVR games need a VR runtime (Revive on PC with SteamVR, or SteamVR-
native builds run directly). Platform-SDK / signature-checked repacks can't run
on the Frame; those are flagged, never bypassed.
GUI overhaul (ui/): streaming persistent Library with tags/filters/sort, a
background job queue + activity panel, per-game page, Frame tab with installed
list + file browser, Settings (incl. agent version), Play + launch-test actions,
resumable/interruptible installs with up-front interventions, dark theme, help
hints, uninstaller (uninstall.py). Faster uploads via a direct link (USB /
Frame hotspot) when reachable. Artwork/details from OculusDB + Steam + ovrp,
composed Steam art sets and tags, thumbnails served by URL.
Docs (PLAYBOOK/FRAME_RUNTIME/ARCHITECTURE/INSTALL/CLAUDE.md), triage signatures,
and unit tests throughout (130 pass).
Python core + Flet GUI + CLI that turns the manual Steam Frame porting work
into a pipeline: scan dumps, analyze, suggest patches (overport + Frame fixes,
catalog of 34 verified recipes), build, static-validate, install over SSH via
a Frame-side agent, add Steam shortcuts with artwork, headless launch test and
log triage. Includes the native sources (FrameBridge adapter, VrApi bridge
patches, GL shim), prebuilt artifacts, docs (playbook, runtime notes) and a
parity harness (34/34 games reproduce the known-good builds).