Docs / For developers
Architecture
#Data flow for one game
- Source (
sources/quest_dump.py): folder with an APK and optional<package>/orobb/data. - Analysis (
analysis/detect.py): package/label/version (pyaxmlparser), ABIs, engine, XR API, graphics API, direct-VrApi, GLAD/eglGetProcAddress, Unity MSAA levels, Meta permissions, telemetry references. - Recipe (
recommend/engine.py): every patch'sdetect()suggests itself with a reason; a catalog entry (exact known-good recipe) overrides heuristics. The UI shows toggles; the user confirms. - Build (
build.py): overport CLI (OVRPort; defaults + extras) → apk-stage patches inorderon anApkWorkspace→ apksigner (with the package's own keystore) → static validation. Optional alternate build (for example without Unreal ForceQuit). - Install (
install/installer.py+agent/frameport_agent.py):prepare(paths, what's already there) → SFTP uploads with resume →finalize(move into place, settings.conf/framebridge.conf, device files, launch.sh, deployment.json, artwork) →shortcuts(detached systemd unit stops Steam, writes shortcuts.vdf + grid art, restarts Steam). - Test (
validate/device.py): agentlaunch_test(systemd-run launch.sh, wait, stop) → fetch launch.log →triage.py(milestones + signatures → suggested patches) → UI offers "apply suggestions and rebuild".
#Extending
- New patch:
patches/frame/<name>.pywith aPatchsubclass (detect,apply, optionalvalidate), plus a signature incatalog/triage.yamland a PLAYBOOK row. Stages:overport|apk|install. - Upstream fixed a bug we work around: register an
UpstreamFix(patches/upstream.py) in the workaround's module: a probe that finds the fix in OVRPort's output (True / False / None = can't tell). Each build runs the probes on the converted APK and leaves out the workarounds whose fix is there (log "not needed: …",build.superseded, left out of settings.conf at install; game page andframeport showsay so). The recipe keeps asking for the fix, so builds made with an older runtime keep the workaround.FRAMEPORT_KEEP_WORKAROUNDS=1turns it off. - New heuristic: put it in the patch's
detect()(andapplies()for visibility), with the evidence in the reason text; checkscripts/eval_heuristics.pystill reproduces the catalog and add a test intests/test_heuristics.py. - New game recipe:
catalog/games/<package>.yaml(or "Save as known-good" in the GUI, which writes to the user catalog). Publish recipes by serving a folder withindex.jsonand pointingFRAMEPORT_CATALOG_URLat it. - New target: implement
targets/base.Target; the pipeline and UI only use that interface.
#Oculus Rift (PC VR) games
sources/rift_dump finds Windows game folders; analysis/rift (own PE reader) detects exe, bitness, engine, LibOVR vs
OpenXR, D3D version and Oculus Platform SDK use; ids are rift.<slug>. Their only patches are the pcvr category
(patches/pcvr.py: Revive, OpenVR backend, crash reporter, Oculus detection, OpenXR layer, Proton
log/version/env); base.for_game keeps Quest and PC VR patches
apart. "Build" = pipeline.prepare_rift (checks + Revive). Revive is a portable tool (tools/revive.py unpacks
ReviveInstaller.exe in pure Python: NSIS header + deflate blocks). Targets:
targets/pc_revive.PcReviveTarget: Windows/WSL (core/winhost.py), non-Steam shortcut runningReviveInjector.exe /openxr <exe>via the agent's VDF code, grid art, local records in<user data>/pc/.FrameLeptonTarget.install_pcvr→installer.install_pcvr→ agentprepare_pcvr/finalize_pcvr: uploadgame/+revive/(+xrlayer/forpcvr.xr_timefix,helpers/forpcvr.oculus_unreal; size-manifest dedupe, stale files removed),launch.shrunning the ARM64 Proton chain (built from toolmanifest.vdf; withpcvr.oculus_unrealthe injector runs throughhelpers/fp_oculushmd.exe, which provides Unreal'sOculusHMDConnectedevent);proton_status/install_protonmanage Proton from Valve's ARM64 compat list.- Native binaries (
artifacts/): editnative/…, runpython native/build.py, commit the new artifacts + SHA256SUMS, runframeport parityto see which games change.
#Self-update (updates.py, ui/updater.py, cli.py update)
check(): GitHub releases/latest, cached 6 h →Update(version, notes = the release body incl. "What's new" from the annotated tag, the asset for this OS, sums, wheel).install_kind(): bundle = the running exe sits in FramePort.exe's folder / FramePort.app / FramePort/FramePort; source = a git checkout (git pull --ff-only+uv sync); wheel = uv tool / pipx / pip (reinstalls the release's wheel).prepare()(bundle):<data>/updates/<ver>/: download → SHA256SUMS.txt check → extract tostaged/(ditto on macOS) → layout check → on Windows the same Authenticode signer as the running exe →ready.json.apply(): writes<data>/updates/apply.{ps1,sh}and starts it detached; FramePort quits. The script waits for the pid. Windows: backs up the files it replaces (updates/<ver>/previous) and copies over the folder (the zip has no folder of its own). macOS/Linux:mvtarget →.old, staged → target, rollback on failure, clears the quarantine. Then it relaunches FramePort. Log:<data>/logs/update.log. GUI: background check 10 s after start + every 6 h → sidebar card + Library bar → dialog with notes → jobapp-update(waits for other jobs) → restart. "Install updates automatically": prepare in the background, apply inmain()before the window opens. CLI: once-a-day hint from the cached result (a daemon thread refreshes it),frameport update [--check] [--yes]. CI runsscripts/update_smoke.pyon every OS with the archive it just built.
#Dynamic data (fetched live, cached, bundled fallback)
overport CLI release (Android-XR-Bridge/OVRPort, fallback ovrport/app) + patch list + titles, Temurin JRE (Adoptium API), apksigner (Google repository index), store artwork/titles (overport image API), catalog (optional remote), Lepton location/appid (Frame appmanifests), Steam user (Frame userdata).
#Built on
FramePort is a front end for other projects; most of the functionality comes from them:
| Project | Used for |
|---|---|
| OVRPort (overport, originally ovrport/app) | Converts Quest games to OpenXR: its CLI applies the game patches and supplies the OpenXR loader; FramePort also includes its VrApi→OpenXR adapter |
| Valve Lepton, Proton and SteamVR | Run Android games, Windows games and OpenXR on the Frame |
| Revive (LibreVR) | Runs Oculus Rift games on OpenXR / SteamVR |
| Mesa (Zink) | OpenGL ES on Vulkan on the Frame |
| Khronos OpenXR SDK | OpenXR headers for the native layers |
| Eclipse Temurin, Android apksigner, Android NDK | Java runtime, APK signing, building the native layers |
| Flet | The desktop app |
| OculusDB, Steam store | Game descriptions, genres and artwork |
FramePort's own parts: game detection and recipes, the Steam Frame OpenXR adapter (FrameBridge) and the other native
patches in native/, the installer agent that runs on the Frame, and the desktop/command-line app.