1.3.0 linked libVkLayer_fdm_darken.so into every arm64 game's engine library; in libCryRenderVulkan.so CrySystem
initialization then fails right after the renderer lists its Vulkan device extensions, and the shutdown crashes
(SIGSEGV in CSystem::ShutDown). Bisected headless on the dev Frame by swapping libraries between the September
known-good APK and a current build: only the modified renderer breaks it. Climb 2's private VrApi bridge still
loads the layer itself (72 fps headless with this change). frame.adapter package revision 3 for both games;
triage cryengine-init-failed.
With Quest 3 the game switches to a 2592x2256 eye buffer after the intro; by then its UI panels have used up the
runtime's ~15 swapchains per session, so the new eye buffer is refused (XR_ERROR_LIMIT_REACHED) and it stops
drawing. Headless on the dev Frame, same build: Quest 3 frames stop, Quest 2 holds 72 fps.
From issues #409#410#412#418#421#435#441#447#448#453#456#461#462#464#472 via
scripts/catalog_from_issue.py. GoldenEye VR (no sound), JKXR (stutters after minutes) and Umurangi Generation
(freezes when saving a photo) are "issues"; Simpsons and Astro VR Host setup steps point to the Files tab, the
long instructions moved to details.
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.
Verified on the Frame 2026-10-18 with 0.2.1 (room, planes, mesh and anchors through FramePort; with frame.meta_permissions and scene_emul, the MR heuristics' picks).
Halo CE VR's HaloActivity runs in :halo_game; Lepton starts it directly and watches only the main process, which
never exists, so it closed the game about a minute in ('Target app ... did not start'). Analysis field
separate_process (ANALYSIS_VERSION 23), default-on patch, triage app-separate-process, PLAYBOOK row.
Verified on the Frame 2026-10-18 with 0.2.2: controller types, highlighting, vibration and passthrough; switching types restarts the app on the Frame (SteamVR runtime limit).
Transformers Beyond Reality: Redux ended its first frames with Unreal's "Shader compilation failures are
Fatal." With Lepton's Fossilize layer loaded every graphics pipeline failed with
VK_ERROR_OUT_OF_HOST_MEMORY, even a constant-colour one; the pipeline cache, the app's CPU allocator and
Valve's FDM/RPO layers were ruled out on the device. Without Fossilize a few multiview vertex shaders
still fail in Turnip.
- adapter.vk_no_fossilize: the shim removes VK_LAYER_fossilize from GraphicsEnv's debug layer list when
the engine loads it (library constructor, same GraphicsEnv calls as zinkfix)
- adapter.vk_pipeline_fallback: a refused graphics pipeline is created again with a blank fragment
shader, then blank vertex + fragment shaders
- catalog entry (status unknown, headless only), triage vulkan-pipeline-refused, PLAYBOOK, DEVICE_NOTES
Headless on the dev Frame: RUNNING after 78 s at 72 fps (was: exit within 21 s). Headset check pending.
frame.vk_sanitize rewrote "libvulkan.so" in the game's library, but the game builds that name from two pieces, so it
asked for "libfp_vkn.so", Dawn found no Vulkan, fell back to OpenGL ES and left VR. Status stays unknown until it is
checked in the headset.
Summer Sports, Black Hole Pool, The Wizards, Surviving Mars: Pioneer and Survival Nation, all played in the headset.
Foveation choices left out (experimental, per player).
Closes#395Closes#396Closes#397Closes#399Closes#401
Quits at start with the game's own "installed from unknown source" message: Lepton installs the game itself at every
start and the Frame has no Meta store app, so the check can't pass.
Closes#368
Games saw a Quest 2: OVRPort's dispatcher hardcodes the system name "Oculus Quest2" and a Quest 2
headset UUID (XR_META_headset_id), and OVRPlugin decides the headset type from the UUID first, then the
name. device.headset_model (Customize; Quest 3 default for every Quest game, also Quest 3S, Quest Pro,
Quest 2) rewrites both in the dispatcher after checking the original bytes; Quest 2 leaves the build
byte-identical. FrameBridge reports the same name to games that call the runtime directly. A library
migration adds the default to existing recipes (installed games show Update on Frame).
Lepton's ro.product.model ("Lepton") can't be overridden by boot properties, so Build.MODEL is unchanged.
Verified on the Frame: OVRPlugin logs "systemName Meta Quest 3" (was "Oculus Quest2").
OutRun Quest VR quits before its VR session with "Rec.709 color space unavailable": the Frame's runtime
has no XR_FB_color_space. Adapter setting fb_color_space (off by default; triage color-space-missing
suggests it) offers the extension when the runtime lacks it, reports Rec.709 and accepts any colour
space without converting. OVRPort's dispatcher can't forward the new functions, so it isn't on for every
game. Not yet tried on the device.
Transformers Beyond Reality (UE5, FMallocBinned3) reserves 76 GiB with one
mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS) while libUnreal.so's
static constructors run. Quest grants it; the Frame's kernel (overcommit mode 0) refuses a
writable private mapping larger than RAM + swap, and Unreal's out-of-memory handler then
dereferences its not yet created log: SIGSEGV fault addr 0x10 inside System.loadLibrary.
The patch adds MAP_NORESERVE to every anonymous read/write mmap call site of the engine
library (mov w3, #0x22 -> #0x4022 before a bl to mmap's PLT stub, with x0 = 0 and w2 = 3
in the window), suggested from analysis unreal_binned3 (ANALYSIS_VERSION 22 on main). Triage
unreal-reserve-refused, PLAYBOOK row, tests. Headless on the dev Frame the game now gets
past loading to its OpenXR session and first frames.
ELF helpers find .dynsym/.dynstr/.dynamic by section type and link instead of by name: this
game's libOVRPlugin.so has a scrambled section name table, so add_needed raised
"produced NEEDED=[...]" and the build failed in frame.unreal_ovrp_entrypoints, and
dyn_symbols returned nothing (every ovrp_* lookup then counted as missing).
# Conflicts:
# docs/PATCHES.md
# src/frameport/analysis/detect.py
The Frame's runtime has no XR_FB_display_refresh_rate (-7); OVRPort's dispatcher still
offers it and answered 0 Hz. Team Beef's idTech 4 ports run USERCMD_MSEC = 1000 / refresh,
so PreyVR had 0 ms tics: the async thread spun (~1.9M tics/s), com_frameTime stayed 0 and
the main menu's timeline never got past its first step (black backdrop + cursor only).
FrameBridge now always answers with 1 / predictedDisplayPeriod (else the refresh_rate
setting, else 72 Hz). Headless: menu drawn (snapshot mean 68 vs 0.1 before), clocks advance.
- glmv: gl_mv_debug=2 traces draws (state, GL errors per framebuffer), failed texture
uploads/copies/compiles and idTech 4 clocks; how this was found
- triage: a single xrEndFrame -16 is info, not the black-menu error it was blamed for
- PLAYBOOK row, CLAUDE.md fact, host test for the fallback rate
Scared By Squares (Unreal 4.27, OpenXR) creates two actions named "turn"
(an action mapping and an axis mapping called Turn). The Frame's runtime
accepts the duplicate, then vrserver fails to load the input manifest it
builds ("SetXrInputConfig failed. Failed to load manifest"), drops the
app's connection and treats it as exited: black, then the home environment
while the game keeps running with sound. Headless the app reconnected as a
plain OpenXR instance, got throttled to 10 fps and the compositor received
no presents.
- action_dedup (adapter setting, default on): a later duplicate action name
or localized name in a set is created as "<name>_N" / "<Localized> N"
(native/adapter/action_names.h, host-tested). Headless on the dev Frame:
manifest loads, 72 fps, 2808 presents in 45 s (before: 10 fps, none).
- input_diag logs every action set and action (escaped names).
- force_render (hidden diagnostic): xrWaitFrame reports shouldRender=TRUE so
headless runs exercise engines that skip layers when not visible; FrameBridge
logs shouldRender changes.
- Triage: space-warp-used only on the motion-vector swapchain (format 97);
D24S8 (129) eye depth falsely matched. New info finding duplicate-action-renamed.
- Catalog entry (status unknown, min_app 1.2.1), PLAYBOOK row.
- Il2cppReturnPatch (unity_runtime_msaa_off, unity_multipass, unity_text_input, ...): a patch that is turned on
but whose methods Cpp2IL doesn't find in the game now logs it and adds a WARN build check naming the patch
("not applied (<id>): code not found in this game ...") instead of skipping silently. ApkContext.checks =
checks a patch reports while applying; apply_frame_fixes adds them to the build's checks (job/CLI output,
build record). WARN only: the build still succeeds.
- FrameBridge rect_clamp: an empty projection/quad image rect (BattleTalent's first frames: 0,0 0x0 ->
xrEndFrame -25 twice, then OVRPlugin stops submitting) becomes the whole swapchain image when its size is
known; counted as swapped, logged ("rect_clamp: view N empty image rect -> full swapchain WxH"). Adapter
revision unchanged; artifacts rebuilt.
- triage swapchain-rect-invalid, PLAYBOOK row, setting texts, PATCHES.md, i18n template.
Pinball FX2 VR (32-bit, through the a32 bridge) died ~2 s after its loading
screen with "a32: block at 0xf68587a0 overflowed the code buffer" (exit 127):
OpenSSL's sha1_block_data_order_armv8 (reached from RAND_poll) has ~60 SHA-1
crypto instructions in a row, each translated through the interpreter with
its own exit stub, and the block loop only stopped at 96 instructions or half
the code buffer, so the 64-entry stub table overflowed and fatal() ended the
process. The loop now also ends a block while 8 stubs are left.
Headless on the dev Frame the game now runs on past that point (menu-size
swapchains, recenter, its save files written) instead of exiting.
tests/programs/sha1ce.c (72 crypto instructions in a row + an unrolled SHA-1)
failed with the old a32run and passes with the new one, JIT = interpreter.
Triage signature a32-jit-overflow, PLAYBOOK row; frame.a32_bridge marks only
Pinball FX2 VR "Update on Frame" (package_revisions).
Titan Isles (#310) died on GoogleApiHandler with NoSuchMethodError permitUnsafeIntentLaunch(): not the
missing Play services but play-services-basement's PlatformVersion.isAtLeastS()/isAtLeastSv2(), which R8
folded to `return true` in this minSdk 32 build. frame.gms_platform_version makes such constant checks for
Android 12+ return false again (analysis gms_folded_sdk_checks, triage gms-android12-call). Headless on the
dev Frame: runs, 72 fps, no crash.
PianoVision (#297), after frame.unity_appui_vibrator, crashed on MidiDeviceConnectionWatchThread: kshoji's
USB MIDI driver polls UsbManager, and Lepton has no USB service (null). frame.usb_midi_watcher makes
checkConnectedDevices return at once (analysis usb_midi_watcher, triage usb-midi-watcher). Host-tested.
PianoVision quit about a second after start on the Frame: Unity App UI's activity
(com.unity3d.player.appui.AppUIGameActivity) calls getSystemService("vibrator_manager") and casts to
android.os.VibratorManager in onCreate without a version check; Lepton runs Android 11, so
NoClassDefFoundError before Unity starts. The sequence now leaves its registers null (the field store and
the rest of onCreate stay) and the activity's methods that read the vibrator return at once (in-place dex
edit). Suggested by analysis unity_appui_vibrator (ANALYSIS_VERSION 20) and triage unity-appui-vibrator.
Escaping Wonderland's Meta start-up (OculusPlatform.<Initialize>d__13) awaits
Users.GetOrgScopedID after the licence check and the logged-in user, when on
Wi-Fi, only for its analytics id. OVRPort's ovr_User_GetOrgScopedID returns
request id 0, Meta's C# wrapper logs "An unknown error occurred. Request
failed." and never calls back, so the game waits forever. The patch takes the
game's own no-Wi-Fi path for that request (b.ne after cmp w0,#2 on
get_internetReachability -> b, found with Cpp2IL). Analysis flag
cortopia_org_id (ANALYSIS_VERSION 20), triage cortopia-org-id-wait, PLAYBOOK
row, tests. Headless on the dev Frame: past the loading screen into the intro
scene (adventurer spawned), 72 fps.
Photon Voice's AudioInAEC.updateAudioDevice calls getAvailableCommunicationDevices/setCommunicationDevice with no version check; on Lepton's Android 11 the microphone thread dies with NoSuchMethodError (Table Troopers at the tutorial). New patch frame.photon_voice_audio_route (analysis photon_voice_api31, ANALYSIS_VERSION 20) makes it return at once, sharing vivox_audio_route's helper; Vivox's patch is unchanged. Triage vivox-api31 / photon-voice-api31 now look for the SDK in the stack; other libraries fall to audio-api31 (report).
Unity games log 'An unknown error occurred. Request failed.' from
Oculus.Platform.Request.OnComplete when a Meta call gets no usable answer
(Thief Simulator #368, Eleven #346, Spectre #360): warning + report. Games with
their own copy of Meta's platform loader abort with 'DisplayErrorAndExit:
Failed to launch SystemActivities' (Breachers #357): fatal, replaces the
generic native crash. PLAYBOOK rows, tests from the reporters' logs.
The reporter's read-before-write fix for module 16800_8dbab031 (12 int Function
variables loaded before any store, the same bug as Vader Immortal's lightspeed
shaders), headset-verified: past the loading screen, ~28 min at 72 fps.
From working-recipe issues #378, #377, #376, #375, #364, #363 (validated with
scripts/catalog_from_issue.py). The 7th Guest VR: the foveation darkening
diagnostic (foveation_test) left out, title spaced, notes shortened to the
game-specific findings. FGO VR: scale rounded to 1.2.
Closes#378Closes#377Closes#376Closes#375Closes#364Closes#363
Analysis extra.google_vr (ANALYSIS_VERSION 20): manifest DAYDREAM/CARDBOARD
categories, enableVrMode=com.google.vr.vrcore, libgvr.so / Cardboard SDK libs,
GVR Java classes, Unity vr-device-list (not libgvraudio.so, which Quest games
ship too). A build without Oculus support gets a warning (recipe notes, CLI,
game page); never unsupported from the manifest. Triage gvr-not-supported for
Unity's 'Google VR Error', the bridge's missing CardboardViewNativeImpl and
VrCore binds. PLAYBOOK row, tests.