Files
Daniel LynchandClaude Opus 5 1f3dc40c07 docs+build: hygiene pass — close leak risk, de-drift docs, fix build prereqs
Repo hygiene round following a full review. No shim behaviour changes.

Leak risk:
- .gitignore: ignore CLAUDE.md (personal assistant-lane config, was one
  `git add -A` away from a public commit) and scratch_obj/.

Docs vs. reality:
- shim/README.md: rewritten. It described a pre-implementation skeleton with
  "core fns are TODO stubs returning -1005", three mutually inconsistent stub
  counts, and four completed milestones listed as open. Now carries the verified
  breakdown: 438/438 exports = 371 generated stubs + 46 core + 7 layers + 2
  Vulkan queries + 12 passthru trampolines.
- TESTING.md: dropped the self-contradicting "NOT yet" block (5 of 6 items were
  done or misstated, and contradicted the same file 45 lines above). Path B now
  points at tools/desktop-harness, which exists, instead of the orphaned
  shim/tests/harness.c. Path A prereqs marked as the record they are.
- HOST.md: corrected the runtime assumption. The OpenXR runtime inside Lepton is
  SteamVR (vendor/etc/openxr/1/active_runtime.json -> vrclient.so), not Monado.
  Favourable: SteamVR emulates Oculus Touch by default and advertises the
  XR_FB_foveation family, so the existing input and foveation paths should carry
  over. The old "remaining unknowns" are resolved by Lepton's published source
  and replaced with the items to check before a first Frame boot.
- README.md: same runtime correction.
- docs/research/RECON.md: the four passages prescribing an entitlement
  NOP/stub/bypass are corrected in place rather than merely disclaimed by the
  top banner, which they contradicted.

Build correctness:
- shim/build_android.sh: missing patchelf is now fatal. It warned and exited 0,
  producing a .so that cannot resolve the OpenXR loader at runtime.
- scripts/fetch_deps.sh + packaging/build_openxr_loader.sh: pin the OpenXR and
  Vulkan header versions (were tracking `main`), overridable via OPENXR_TAG /
  VULKAN_HEADERS_TAG; require cmake for the loader build.
- packaging/steamframe_patches.sh: use the apktool.jar that fetch_deps.sh
  downloads. Its prereq check demanded an `apktool` binary on PATH that the
  documented setup never provides, so it could not run after a clean setup.
- shim/gen_stubs.sh: it reads all_exports.txt, not shim_surface.txt; comment and
  emitted banner corrected. stubs.c regenerated (banner line only).
- shim/src/core.c: split seven `if (out) ...; return ...;` one-liners. Host
  build now compiles with zero warnings, down from seven.

Verified: host build 0 warnings; gen_stubs.sh output identical on regeneration;
bash -n clean on all edited scripts; pinned header/tarball URLs return 200 and
the tag tarball extracts to the expected directory name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 02:15:10 -04:00

3.9 KiB

ovrplugin-openxr-shim

A from-scratch reimplementation of Meta's libOVRPlugin.so on top of OpenXR, so legacy VrApi/OVRPlugin-based Meta Quest titles can run on standard OpenXR runtimes — Valve's Steam Frame (SteamVR inside Lepton), Monado, and others.

Status: Resident Evil 4 VR boots and is playable on a Quest 2 through this shim — stereo rendering, head + controller tracking, buttons, grips, haptics, and save loading all work. (Developed as a preservation / interoperability experiment.)

What it is

Quest's libOVRPlugin.so is the C shim Unreal/Unity games call to talk to Meta's VR runtime. Meta deprecated the underlying VrApi in 2022 and the whole modern stack (incl. Steam Frame's SteamVR) is OpenXR-only, so VrApi-era titles have no runtime on non-Meta OpenXR platforms. This project re-exports the ovrp_* C API backed by OpenXR instead, as a drop-in replacement libOVRPlugin.so:

game (libUE4.so) ──ovrp_* C API──> [THIS SHIM] ──OpenXR──> runtime (SteamVR / Meta / Monado / …)

It implements the OpenXR instance/session lifecycle, the Vulkan graphics binding, the frame loop + swapchains, layer compositing, and action-based input — mapping all of it to the ovrp_* ABI the game expects.

  • This repo contains only original code. It does not include or redistribute any game, the Meta runtime, Meta's headers, or Epic's UnrealEngine source. You must build the shim yourself and apply it to a copy of a game you legally own and dump yourself (patch-only, dump-your-own — like ROM-hack patches).
  • Reimplementing an API for interoperability is the goal here; no proprietary binaries or decompiled source are published.
  • Entitlement/ownership checks are out of scope: this project ships no circumvention code and circumvents nothing. On Quest the platform's real entitlement check runs unchanged (you own the title). Running on hardware with no Meta backend requires a valid entitlement by other means — that is the user's responsibility and not provided here.
  • Not affiliated with or endorsed by Meta, Capcom, Epic Games, or Valve. All trademarks belong to their owners.
  • Provided as-is, no warranty. You are responsible for compliance with applicable law and the terms of any software you use it with, in your jurisdiction.

Build

scripts/fetch_deps.sh              # OpenXR + Vulkan headers (Apache-2.0), NDK, JDK, build-tools
shim/build_android.sh              # -> shim/build/arm64/libOVRPlugin.so
packaging/build_openxr_loader.sh   # -> packaging/libs/arm64/libopenxr_loader.so

fetch_deps.sh pins the header versions; override with OPENXR_TAG / VULKAN_HEADERS_TAG.

From your distro you also need patchelf (the Android build fails without it — the shim cannot resolve the OpenXR loader) and cmake (for the loader build). A host x86-64 build is also supported for compile-validation and the desktop harness: shim/build_host.sh.

Use (with your own dumped game)

packaging/repack.sh /path/to/your/base.apk   # swap the shim in, re-sign
adb install -r packaging/out/<game>-shim.apk
# push your own dumped OBB, then launch on a dev-mode Quest

See packaging/README.md and TESTING.md for the full flow.

Layout

  • shim/src/ — the implementation: xr_runtime (session/frame loop/swapchains), vk_session (Vulkan binding + ext), layers, xr_input (action sets), core (the ovrp_* entry points), android_init, generated stubs.
  • shim/include/ovrplugin_shim.h — the ovrp_* C ABI (clean-room from observed ABI).
  • packaging/ — repack/sign tooling.
  • docs/ — research notes + session handoffs (docs/README.md narrates how the frame-pacing "ghost" was solved); TESTING.md/HOST.md at root.

Acknowledgements

Built against the OpenXR and Vulkan specs and the Khronos OpenXR loader.