An independent reimplementation of Meta's libOVRPlugin ABI on top of OpenXR, so VrApi-era Meta Quest VR titles can run on non-Meta OpenXR runtimes (Monado, Steam Frame) instead of being locked to Meta hardware. Original code only — no Meta/Epic/Capcom binaries, headers, or assets. Includes a desktop harness that drives the shim against Monado headless. Scope/legal: interoperability; entitlement handling is out of scope. See README for the legal/scope section and docs/ for the research trail and design notes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6sFYGXZPsq3v7xtcDES6g
3.3 KiB
OVRPlugin -> OpenXR shim — scope
Derived 2026-06-23 from RE4 VR v2.3 (com.Armature.VR4). Method: extracted the
distinct ovrp_* names libUE4.so references (dlsym targets) and intersected
with libOVRPlugin.so's exports. Raw lists in analysis/.
Headline numbers
- OVRPlugin exports 438
ovrp_*entry points. - The game actually references 239 of them. That's the shim surface.
- But ~150 of the 239 are stub-to-constant / no-op for a basic port. Realistically ~85-90 functions need real implementation, of which the genuinely hard core is ~40 (frame loop + layer/swapchain + the display interop).
Render API: VULKAN (confirmed)
libUE4.so has VulkanRHI compiled in and calls ovrp_Get{Instance,Device}ExtensionsVk.
libGLESv2/EGL are NEEDED but that's the standard Android baseline; the active
renderer is Vulkan. => swapchain path is the standard OpenXR XR_KHR_vulkan_enable2
(import the app's VkImages into XrSwapchain). Well-trodden, not exotic.
STUB to no-op/constant (~131 counted, +misc ≈ 150)
| Group | count | how to stub |
|---|---|---|
Mixed Reality Capture (ovrp_Media_*) |
37 | return not-initialized / no-op |
| Camera device (passthrough/depth) | 21 | report unavailable |
| External camera (MRC) | 13 | report 0 cameras |
| Perf/GPU/CPU/ASW/foveation tuning | 31 | accept+ignore, return safe defaults |
| Boundary / Guardian | 7 | "not configured" (or map to XR play bounds later) |
| Hand tracking | 7 | disabled (RE4 VR is controller-only) |
| System-info getters | 15 | return plausible constants (headset type, region…) |
Stubbing these = ~150 functions for near-free. None affect core gameplay.
MUST implement (~88 counted; the project's real work)
| Group | count | notes |
|---|---|---|
| Tracking / poses | 32 | mostly mechanical: map OpenXR xrLocateSpace/views to ovrp pose structs |
| Display / layer / swapchain | 20 | THE HARD PART — projection layers, eye FOV, foveation, swapchain stages |
| Input / controllers | 11 | map Touch controller -> OpenXR action set; mechanical but fiddly |
| Eye / user params | 10 | IPD, eye height, pixels-per-tan-angle -> from XR view config |
| Init / shutdown | 8 | session create/begin/end, instance+system setup |
| Frame loop | 6 | xrWaitFrame/xrBeginFrame/xrEndFrame <-> ovrp_*Frame4, predicted display time |
Verdict
Single-developer-feasible, meaty. The "239 functions" headline collapses to
~40 hard + ~45 mechanical + ~150 stubs. The hard 40 are the standard guts of
any OpenXR app (frame loop, projection layers, Vulkan swapchain, pose/input
mapping). Modern Meta OVRPlugin already ships an OpenXR backend — that's the
reference for exact ovrp_* semantics and struct layouts, which removes most of
the guesswork.
Biggest unknowns / next probes:
- Exact
ovrp_*struct layouts/ABI (need OVR_Plugin.h matching this OVRPlugin version, or RE them in Ghidra). ABI mismatch = crashes. - How the Java side loads libOVRPlugin (System.loadLibrary) — confirms the replacement mechanism (drop-in shim .so with same SONAME).
- Entitlement: out of scope for this project — no
ovr_*replacement ships here; the platform's real check runs unchanged (see README "Legal / scope"). - Whether Steam Frame exposes an Android-app OpenXR runtime at all (the OTHER big external unknown — the shim is moot if the APK can't load there).