Restructure the README around what a player does: choose where to build
(PC or the Frame), install, update, play, then settings, controls,
known issues and troubleshooting. Building on a server and by hand move
under "Other ways to build", and the upstream and credits notes are
merged into "What comes from where" and a short Credits section that
points at CREDITS.md.
Updating now shows the curl form of --update, which works without a
local copy of the script; the in-game Updates tab; and the one full
install needed when coming from frame-beta-2. Manual steps use the
frame-beta-3 tag, the install options are a table, and the Troubleshooting
section covers in-game update failures. Links to the old "The Android
flavour" section now point at "How it works".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Axv1Y43Lu5a5rSSLUyU5BB
--update reuses the options an install was made with (saved to install.conf in the work dir) and
builds nothing when the Frame already has the newest release and Retro Rewind pack; --check only
reports. The installed release is stamped as .release-tag beside the game on the Frame.
An install built on the Frame itself (--frame local) also gets a systemd user service the game's
new Updates tab starts: the update runs in the background at low priority, writes each step and
the build percentage to a status file the tab shows, and reopens the game at the end if it was
closed. Progress does not go through Steam notifications: on the Frame, Steam receives them from
steam_notif_daemon but does not display them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UyuWx5hNrMpf9R78FZFcbA
Add CREDITS.md, listing the projects the fork is built on and every
change ported from upstream WiiCompiled and other forks, with author and
source commit, taken from the commit messages. Link it from the README,
THIRD-PARTY-NOTICES.md and a new porting note in CONTRIBUTING.md.
Document adaptive_resolution in OPENXR.md, the 4 KiB page constant and
NEON mixing in the README, the Mozilla CA bundle in the notices, and draft
the frame-beta-3 release notes for what PRs #5 to #10 merged.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Axv1Y43Lu5a5rSSLUyU5BB
The second beta brings the one-command installer and the README quick
start; the game and Dawn are unchanged since frame-beta-1. The release
workflow's manual run now defaults to this tag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
docs/steam-frame.md is gone. The README now opens with a quick start that
goes from the disc to playing (emulation setup, disc extraction, the
container build, installing with Frame Control, updating), and carries what
the guide held that a player or contributor needs: recommended settings, the
Frame controller map, known issues, troubleshooting (log lines, the pacing
line, crash backtraces), building on the Frame or with Docker (including
Unraid's qemu registration), how the native build works and why the Android
flavour cannot show a picture. Links to the old guide point at the README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The README and docs/steam-frame.md now describe the Frame build as a beta
that runs on the headset: what works, the recommended settings (render_scale
1.25 is the panels' native 2160x2160), the known issues (doubled images,
right-eye foveation), building with Docker on another machine (including
registering qemu on hosts whose binfmt_misc is per container), and
installing with Frame Control. A frame-* tag now publishes a source-only
pre-release with the notes in docs/releases/<tag>.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The first repeat_frames waited a millisecond for the eyes before spending a
refresh on the retained layer, so nearly every packet also cost a needless
repeat, the next packet missed the game's next frame, and the Steam Frame
showed about 35 new frames a second. The pacing thread now waits until
1.5 ms before the next wake, a period after the last xrWaitFrame returned,
which OpenXRRuntime records.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
SteamVR on the Steam Frame ran the game at half the 120 Hz display rate,
since render-first pacing submits only when a game frame is sealed, and
filled every other refresh itself even with Motion Smoothing off, which
doubled the HUD and the menu screen while the head turned. With the new
[vr] repeat_frames (default on for the Frame, off elsewhere, live), the
pacing thread waits a millisecond for the eyes and otherwise spends the
refresh on a keep-alive cycle that resubmits the retained layer with its
rendered poses, paced by xrWaitFrame.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
On the Steam Frame the full-density region was too small and lagged the
eyes. Gaze-centred maps now widen both of the level's rings by 8 degrees,
covering a saccade until the next frame's map is bound, the tracker's error
and Turnip's per-bin density, and each eye keeps 128 maps instead of 32 so
fewer glances wait for an upload. The fixed, forward maps are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The README now introduces this repository as the Steam Frame fork of
WiiCompiled OpenXR VR: what the fork adds, its untested status, the
requirements and build steps, where to report problems, and what it keeps
from upstream. docs/steam-frame.md gains the emulated ARM64 container route
for building on an x86_64 Linux PC, disc extraction with nodtool and the
copy to the Frame, and clones the default branch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
Launcher/build-dawn-linux.sh builds the pinned Dawn with Aurora's Vulkan hook
and density map patches into a package local-build.sh takes through the new
--dawn-package option, together with --openxr, --headset steam_frame and
--cpu. docs/steam-frame.md now leads with the native SteamOS build (building
in a podman container on the Frame, running it, the log lines to expect);
OPENXR.md's backend table records the Linux Vulkan backend and why the Lepton
flavour cannot present.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
Lepton's Vulkan driver has no external memory or sync fd extensions,
so the Steam Frame gets a native SteamOS build instead. Its backend is
the PC's: OpenXR creates Dawn's own Vulkan instance and device, and the
eyes are copied into the swapchain on Dawn's queue, with nothing shared
between devices.
- openxr_vulkan_win32 and Aurora's vulkan_win32_interop now compile on
desktop Linux. Dawn links statically there, so the bridge calls the
patched package's hooks directly, and exists only when the package's
aurora-dawn.json declares the Vulkan hook ABI (AuroraDawnProvider
turns AuroraVulkanAbi into AURORA_DAWN_VULKAN_HOOKS); a stock Dawn
keeps the stubs and VR falls back to the desktop.
- openxr_integration.cpp gains a Linux branch: XR_KHR_vulkan_enable2,
the timespec clock, refresh rate, performance level, the Frame
controllers and eye gaze; fragment density maps are requested on
Linux as on the Quest (fdm.cpp and gpu.cpp, AURORA_FDM=0/1 overrides).
- Controller motion uses XR_KHR_convert_timespec_time on any Linux.
- CMake: Vulkan headers are fetched for Linux OpenXR builds, the
headset option is MKW_HEADSET on Android and Linux, and Linux aarch64
builds take MKW_LINUX_CPU (cortex-x4 for the Steam Frame, else native).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The Capability Viewer inside Lepton shows no AHardwareBuffer, external
memory fd, semaphore fd or fence fd extension, so the Quest backend's
two-device eye handoff cannot present there; the eyes need to be copied
on Dawn's own device bound to the session, as on Windows Vulkan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
Read from Walkabout Mini Golf's Unity log on the Frame: the Frame
controller profile, display refresh rate, eye gaze and performance
settings are all there; XR_KHR_convert_timespec_time is not, so VR
frame interpolation is unavailable on the Frame.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
Lepton ships /vendor/etc/openxr/1/active_runtime.json and Valve's
implicit fdm_injection layer instead of a runtime broker; the statically
linked Khronos loader falls back to that file, so the app needs no
change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The Frame's kernel reports sve, sve2 and the SVE2 extensions in its
HWCAP, on SteamOS and inside Lepton alike, unlike phones with the same
Snapdragon 8 Gen 3. The steamFrame flavour now builds with
-mcpu=cortex-x4 instead of cortex-x4+nosve.
docs/steam-frame.md records what the headset reported: 4 KB pages,
Android 11 (API 30) in a Waydroid-based Lepton, Mesa's Turnip as its
Vulkan driver, and SteamVR's native linuxarm64 OpenXR runtime on the
host, with the questions still open.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
The adb commands named the device through a PowerShell variable, which
fish and bash do not read; each line now names it, and two grep lines
pull the driver and the relevant extensions out of the vkjson dump.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
docs/steam-frame.md covers the steamFrame flavour: the CPU target and
why it excludes SVE, the Lepton entry activity and manifest, the Frame
controller map, the refresh rate and eye-tracked foveation, building and
installing, the device checklist (what to collect from the headset, the
log lines a first session should show, the open questions), and what a
native SteamOS build would need. OPENXR.md documents refresh_rate and
eye_tracked_foveation and the Frame controller profile; the Quest doc,
the Android README and the README point to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
- Introduced `vrCockpitItemThrow` configuration option to enable throwing items in VR.
- Implemented `ThrowDetector` and `ThrowSequence` classes to manage item throwing mechanics based on hand movements.
- Updated `OpenXRInput` to handle item throwing based on hand swings, integrating with existing VR input systems.
- Enhanced settings overlay to allow users to toggle item throwing functionality.
- Added tests for item throwing mechanics, ensuring correct behavior for various hand movements and conditions.
The headset flavours split the kit export into one task per variant, which
picks the CMake tree by the flavour's MKW_ANDROID_CPU.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the modernQuest and quest1 headset flavours (Kryo CPU target, direct-VR
library entry on Quest 1), records the CPU target in the game kit and checks
it wherever a kit or game package is used, and gates the Quest 1 EFB-copy and
pipeline-scheduling workarounds on the monterey device.
Resolved docs/quest-port.md by keeping both sides: the foveated rendering
section and the Quest 1 renderer compatibility section, and both Build-Quest.ps1
command lines.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Added SetRenderScale method to both D3D12 and Vulkan backends to adjust the render scale dynamically.
- Updated eye size calculations to reflect the new render scale in both backends.
- Implemented ResizeWritablePair method to handle resizing of swapchains based on the requested eye sizes.
- Modified BeginFrame methods to ensure swapchains are resized appropriately before rendering.
- Enhanced error handling to maintain current eye sizes when the requested sizes cannot be allocated.
- Added tests to validate render scale functionality, ensuring correct behavior when scaling up and down, including handling of refused sizes.
- A bare hand already feeds no Wii Remote motion (camera-tracked poses are too noisy to
differentiate twice). In a cockpit race, both hands on the wheel rising together or a free bare
hand rising fast now plays one shake on the remote's accelerometer: 150 ms, so the guest sees it
on at least three frames, one cycle up to +2 g and down to the -3.6 g limit, as Dolphin's
emulated shake does. A turn (one hand up, the other down) never flicks, nor does a lone hand on
the wheel; a rise must last three samples and cover 5 cm within 150 ms, tracking jumps reset it,
and flicks are 0.5 s apart. Wii Remote presentation only.
- debug.wiicompiled.inject <n>:flick plays the same shake, with the controllers or unattended, to
tune it apart from the gesture. Docs: OPENXR.md, docs/quest-port.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New [vr] hand_tracking (default off, Quest only for now): the Quest launcher's Settings > VR and
the headset panel's VR tab, under hand steering. Two XR_EXT_hand_tracking trackers are located
every XR frame: with the controllers held the Quest builds the joints from their touch sensors
(XR_EXT_hand_tracking_data_source's controller source), once they are put down from its
cameras. The trackers exist only while the option and hand steering are on and also serve the
runtime hand mesh; the extensions (plus XR_FB_hand_tracking_aim) are asked for when either is
on at launch.
- Aurora skins the runtime mesh with the joints themselves (tracked pose times inverse bind pose,
no curl, no grip); runtimes with joints but no mesh get a skeleton; non-finite joints put only
that hand back on its grip curl. AuroraCockpitHand carries the 26 seated-frame joints and radii.
- The manifest declares horizonos.permission.HAND_TRACKING (and the deprecated
com.oculus.permission.HAND_TRACKING), both normal permissions with no prompt on a Quest 3, and
oculus.software.handtracking as optional; without it Horizon OS keeps the app controllers-only.
Bare hands then drive khr/simple_controller, so on Android a hand whose squeeze action is
inactive and select active is treated as bare: with the option off it presses nothing but the
menu gesture, is not drawn and feeds no Wii Remote motion.
- Interaction-profile changes and tracker sources are logged. The pure rules (grasp from finger
flexion, bare latch, pinch gate, bare-hand buttons, flick) live in the OpenXR-free
vr/openxr_hand_tracking.h with mkw_vr_hand_tracking_tests; the driving and flick parts are
wired in the next commits. Docs: OPENXR.md, docs/quest-port.md, README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Introduced a new configuration option for immersive window mode in runtime_config.h.
- Updated the parsing and setting functions to handle the immersive window state.
- Modified the OpenXR backend to support rendering with the immersive window, blending the race view with the surrounding environment.
- Enhanced the settings overlay to allow users to select between immersive, immersive window, and flat screen race views.
- Implemented GPU rendering logic for the immersive window mask, ensuring correct visual output in various rendering paths.
- Added tests to validate the immersive window functionality and its interaction with existing race view settings.
- Retro Rewind's SNES Ghost Valley 2 at render_scale 1.0, GPU-bound at about 40 FPS: merging the
eye passes lifts it from 38.9 to 41.5 FPS (app GPU 23.3 to 21.7 ms), and no foveation level
raises the frame rate further.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Luigi Circuit Grand Prix start on a Quest 3, same-session A/B through the debug properties:
one render pass per eye saves 12% of eye GPU time at render_scale 0.8 and 8% at 1.3.
- Foveation is neutral at 0.8 (eyes are geometry and full-resolution tile-store bound) and saves
8/14/22% at Low/Medium/High at 1.3, so it stays off by default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Eyes render under a VK_EXT_fragment_density_map: full rate around each eye's forward direction,
2x2 then 4x4 pixel blocks towards the edges ([vr] foveation = off|low|medium|high, default off).
XR_FB_foveation cannot help here: the runtime's maps only shape passes drawing into its
swapchain, and the eyes reach it through a copy.
- aurora-main/patches/dawn/aurora_fdm.inc: Dawn enables the extension only on request and for
dynamic rendering, flags every render pipeline, and chains an immutable RG8 map into any pass
whose first color attachment is a view bound to one (ABI: include/aurora/dawn_fdm_abi.h).
- android/Build-QuestDawn.ps1 builds the pinned Dawn revision with those patches for arm64
(dawn-build CI flags, protobuf off) into a cached package; Build-Quest.ps1 links it
(-StockDawn opts out) and AuroraDawnProvider.cmake enables the ABI from its manifest.
- lib/gfx/foveation.hpp generates the maps (32 px per texel, densities 255/127/63); an eye is
foveated only when single_pass_eyes draws it in one render pass. Menus never are.
- Live level from the headset panel's VR tab and the launcher; the launch decides whether the
device has maps. debug.wiicompiled.foveation and debug.wiicompiled.fdm for A/B.
- Tests: Foveation cases in gx_fifo_tests, mkw_vr_config_tests. Docs: OPENXR.md, quest-port.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Added eye_pass_plan.hpp: an eye keeps drawing in the render pass it has open across the frame's
GX copies (only the mono render performs them), skips passes a later clear of the whole color and
depth erases, and splits only for a clear of color alone or depth alone.
- render_stereo_eye follows that plan; the cockpit fallback is drawn inside the last pass instead of
a render pass of its own that loaded the eye back.
- The stencil is now cleared where the eye actually starts, so a cockpit mask drawn in an erased pass
can no longer punch holes in the HUD.
- [vr] single_pass_eyes (default on, live from F10) and debug.wiicompiled.eye_passes 0/1 on the Quest
switch back to one render pass per recorded pass for A/B timing.
- Each new plan shape is logged once ("Eye replay plan: ...").
- Tests: EyePassPlan cases in gx_fifo_tests; stereo_multiplayer_smoke and stereo_frame_worker_smoke
pass on D3D12.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Added `ic_question_tip.xml` and `ic_success_tip.xml` vector drawables for UI icons.
- Created layout files for friend-related dialogs: `dialog_add_friend.xml` and `dialog_friend_code.xml`.
- Implemented `item_friend.xml` for displaying individual friend cards in the friends list.
- Developed `page_friends.xml` for the main friends page layout, including empty state handling.
- Added unit tests in `RksysFriendsTest.kt` to validate friend management logic and interactions.
- Introduced `SidebarStatusTest.kt` to ensure proper status reading and SVG path parsing.
- Added PlayerRow.kt to bind player data for leaderboard and rooms.
- Introduced PodiumCard.kt for podium animations and display of player rankings.
- Created drawable resources for podium backgrounds, badges, and particles.
- Developed layout files for leaderboard header and podium cards.
- Implemented LeaderboardTest to validate leaderboard functionality and player ranking logic.
- Created dialog_player_profile.xml for displaying player profiles with loading and error states.
- Added item_player.xml for individual player items in lists, showing Mii, name, friend code, and VR.
- Introduced item_room.xml for room items, displaying game mode, ID, and player count.
- Developed page_room_details.xml for detailed room information, including player actions.
- Implemented page_rooms.xml for the main rooms page layout, featuring search functionality and room listings.
- Added view_vr_history.xml for visualizing player's VR history over time.
- Created LiveRoomsTest.kt to validate room and player functionalities, including leaderboard integration and search capabilities.
- Introduced PlayerMii class to encapsulate Mii data and image.
- Added parseMiiData function to decode Mii data from JSON.
- Updated miiImage function to playerMii for better clarity and functionality.
- Enhanced RksysProfiles to include Mii ID and updated parsing logic.
- Modified SidebarProfileCard to accommodate new Mii handling.
- Redesigned layout for activity_launcher.xml to improve Mii display.
- Adjusted item_mii.xml and page_profiles.xml for better Mii image sizing.
- Updated strings.xml for clarity on Mii parts and bodies.
- Added tests for Mii database and rendering to ensure functionality.
- Created MiiBodies class to handle upper body rendering for Miis.
- Implemented MiiBodiesTest to validate body model parsing and rendering.
- Introduced new layout files for Mii items, Mii editor, and My Miis page.
- Implemented MiiData serialization and deserialization tests to ensure data integrity.
- Created MiiDatabase tests to validate database creation, modification, and error handling.
- Added MiiIds tests to verify ID generation and MAC address derivation.
- Developed MiiRenderer tests to confirm rendering functionality for Mii parts.
- Added vector drawable icons: ic_chart, ic_code, ic_copy, ic_star, ic_translation, ic_user_circle.
- Created layout file for the profiles page, including UI elements for displaying user profiles, history, and statistics.
- Implemented unit tests for Retro WFC functionality, ensuring correct parsing of history, online friend codes, badges, and Mii images.
- Developed tests for Rksys profiles, validating friend code generation, license parsing, and handling of ratings.
- Introduced new drawable resources for user and warning icons.
- Created layout files for mod browser items, loading indicators, and the main mod browser page.
- Implemented IDs for resource referencing in the layout.
- Added unit tests for GameBanana API interactions, ensuring proper parsing of mod data and error handling.
- Developed Rust module for handling mod archives, supporting extraction of 7z and RAR formats with error checking.
The rule and its cost are not obvious from the code: the substitution is per
draw, so the merge test is too, and getting that wrong is worth 6 ms of GPU time
a frame in a race.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Quest launcher's Settings > VR gains a Seat choice (cockpit or
custom, first_person_seat) and a Hand steering switch (hand_steering, off
by default like the runtime), which is only enabled in the first-person
cockpit because the wheel belongs to that seat. About credits heurazy for
the turning steering wheel and hand steering. The runtime side was already
shared with the Quest build.
OPENXR.md records what one Quest 3 race showed: the kart's own wheel
animated (228 draws a frame) with the race camera's view matching the
scene's exactly, but the driver's eye was never calibrated and the
fallback put the wheel centre about 13 cm above eye level. The Quest
declares no hand-tracking permission, so hands are the procedural gloves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>