mirror of
https://github.com/daniel-lynch/ovrplugin-openxr-shim.git
synced 2026-10-06 07:00:13 +02:00
Initial public release: OVRPlugin→OpenXR interoperability shim
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
This commit is contained in:
commit
a72a79ad29
57 files changed
+9304
No files matched your search
@@ -0,0 +1,60 @@
|
||||
# Reverse-engineering notes — libOVRPlugin.so
|
||||
|
||||
Pinned version: OVRPlugin **1.51** / pkg `ovrplugin-android-universal:19.0.0.449.531`.
|
||||
Cross-reference header: public **OVRPlugin.cs @ v1.51** (Unity Oculus Integration,
|
||||
many GitHub mirrors) — gives ovrp_ signatures + [StructLayout] struct layouts.
|
||||
|
||||
## RE pipeline (working)
|
||||
Headless Ghidra 12.1.2, driven by `ghidra_scripts/DumpOvrp.java`:
|
||||
```
|
||||
export JAVA_HOME=~/dev/re4vr-port/tools/jdk-21.0.11+10 # portable Temurin JDK
|
||||
tools/ghidra_12.1.2_PUBLIC/support/analyzeHeadless ghidra_proj re4vr \
|
||||
-import dump/apk_libs/lib/arm64-v8a/libOVRPlugin.so \
|
||||
-scriptPath ghidra_scripts -postScript DumpOvrp.java -deleteProject
|
||||
```
|
||||
Gotchas solved: Ghidra needs a JDK (JREs rejected) -> portable Temurin in tools/.
|
||||
Ghidra 12 dropped bundled Jython -> scripts must be Java, not .py.
|
||||
Output: `analysis/ovrp_decomp.txt` (537 ovrp_ sigs, 27 core bodies).
|
||||
|
||||
## Key structural finding
|
||||
Exported ovrp_* are THIN THUNKS: `(*PTR_ovrp_X)()` jumping to the real impl,
|
||||
which calls internal C++ `OVR::Util::Compositor::*` (partially symbolized).
|
||||
=> The game (Java System.loadLibrary + dlsym) calls the EXPORTED symbols. So the
|
||||
SHIM just re-exports the same ovrp_ symbol names backed by OpenXR and replaces
|
||||
libOVRPlugin.so wholesale. We do NOT reverse the internal Compositor C++.
|
||||
Decompilation = reference for semantics + struct sizes only.
|
||||
|
||||
## ABI confirmed (triangulation: Ghidra shape + v1.51 header types = MATCH)
|
||||
ovrp_GetNodePoseState3(ovrpStep, int frameIndex, ovrpNode, ovrpPoseStatef* out):
|
||||
- null out -> returns 0xfffffc17 = -1001 (ovrpFailure_InvalidParameter)
|
||||
- not init -> returns 0xfffffc16 = -1002 (ovrpFailure_NotInitialized)
|
||||
- success -> memcpy(out, ..., 0x58) then return 0
|
||||
- **ovrpPoseStatef = 0x58 = 88 bytes** == public layout:
|
||||
ovrpPosef(28) + 4x ovrpVector3f(48) + double Time(8) -> pad 88. EXACT MATCH.
|
||||
=> Public OVRPlugin.cs v1.51 struct layouts are TRUSTWORTHY for this binary.
|
||||
ovrpResult error-code convention confirmed (-1001 invalid, -1002 not-init).
|
||||
|
||||
## Layer structs reversed (2026-06-23, analysis/struct_layouts.txt)
|
||||
Ghidra recovered C++ type NAMES from demangled symbols but empty layouts (no DWARF);
|
||||
real offsets came from decompiling OVR::Util::Compositor methods.
|
||||
- Two compositor backends: CompositorVRAPI_OpenGL + CompositorVRAPI_Vulkan (RE4=Vulkan).
|
||||
- **ovrpLayerDesc = 0x7c (124B)** [VERIFIED]: ImportLayerDesc memset's 0x7c; switch on
|
||||
+0x00 = ovrpShape (cases 0,1,2,4,5 overlays; case 3 = EyeFov projection). Three
|
||||
historical copy sizes 0x68/0x6c/0x7c = base / +DepthFormat / +MotionVector. Full
|
||||
field layout written to header, offsets confirmed (Fov@0x20, VisibleRect@0x40,
|
||||
DepthFormat@0x68).
|
||||
- **ovrpLayerSubmit = 0x130 (304B)** [VERIFIED]: EndFrame4 allocs count*0x130. Header
|
||||
fields (LayerId, TextureStage, ViewportRect[2], Pose@0x28, Flags) = public layout;
|
||||
per-shape union tail still [TODO] (reserved bytes for now). Stored internally as
|
||||
ovrpLayerSubmitUnion in a std::map<int,pair<union,int>>.
|
||||
Header now has _Static_asserts sizeof(ovrpLayerDesc)==124 && ovrpLayerSubmit==304;
|
||||
both pass, shim rebuilds (239 symbols).
|
||||
|
||||
## Next RE passes (when continuing)
|
||||
- Dedup the export-thunk vs impl entries in the dump (script polish).
|
||||
- For each CORE fn: pair Ghidra arg-shape with v1.51 C# sig -> finalized C header
|
||||
for the shim (ovrp types + struct layouts).
|
||||
- Reverse outliers NOT in the public header (e.g. SpaceWarp/ASW property paths the
|
||||
binary references, any custom Armature behavior).
|
||||
- Entitlement (libovrplatformloader's ovr_* surface) is out of scope for this repo:
|
||||
no replacement ships and nothing is circumvented (see README "Legal / scope").
|
||||
Reference in new issue
Block a user