mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 01:00:14 +02:00
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
144 lines
7.3 KiB
PowerShell
144 lines
7.3 KiB
PowerShell
# Builds the standalone Meta Quest APK on a Windows host.
|
|
#
|
|
# powershell -ExecutionPolicy Bypass -File android/Build-Quest.ps1 [-Generated <dir>]
|
|
# [-Headset modern|quest1|frame] [-Configuration debug|release] [-Install]
|
|
#
|
|
# -Headset frame builds the Steam Frame flavour (steamFrame), which runs under Lepton, SteamOS's
|
|
# Android layer, with SteamVR's OpenXR runtime (docs/quest-port.md, "Steam Frame").
|
|
#
|
|
# One app offers both games: the APK carries a kit for the base game, and for Retro Rewind too
|
|
# when -Generated holds a translation that includes the mod.
|
|
#
|
|
# -Generated names the translator output for the disc you own: the directory
|
|
# holding data_sections_init.cpp, RuntimeConfig.h and build_shards/shards.cmake.
|
|
# It defaults to the installer's build workspace next to this checkout. The
|
|
# Windows-generated tree is used as-is; runtime/cmake/PublicProducts.cmake
|
|
# rewrites its blob assembly for ELF at configure time.
|
|
#
|
|
# Prerequisites (see docs/quest-port.md): JDK 17, the Android SDK with NDK
|
|
# 29.0.14206865 and CMake 3.22.1, and android/Prepare-QuestDependencies.ps1
|
|
# having staged the SDL3 AAR.
|
|
#
|
|
# Dawn is built from source with Aurora's patches (android/Build-QuestDawn.ps1:
|
|
# fragment density maps for foveated rendering) and cached under
|
|
# .scratch/quest-dawn; the first build takes a while. -StockDawn links the
|
|
# stock prebuilt package instead, which leaves foveated rendering unavailable.
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$Generated = '',
|
|
[string]$Dependencies = '',
|
|
[string]$CMakeDir = '',
|
|
[ValidateSet('modern', 'quest1', 'frame')] [string]$Headset = 'modern',
|
|
[ValidateSet('debug', 'release')] [string]$Configuration = 'debug',
|
|
[switch]$Install,
|
|
[switch]$StockDawn
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$repo = (Resolve-Path (Join-Path $root '..')).Path
|
|
|
|
if (-not $Generated) {
|
|
$Generated = Join-Path $repo '.scratch\vr-build-workspace\BuildWorkspace\generated'
|
|
}
|
|
if (-not (Test-Path (Join-Path $Generated 'build_shards\shards.cmake'))) {
|
|
throw "No translated graph at $Generated (expected build_shards\shards.cmake). Run the translator first; see docs/quest-port.md."
|
|
}
|
|
if (-not (Test-Path (Join-Path $root 'app\libs\SDL3-3.4.4.aar'))) {
|
|
throw 'SDL3 AAR missing; run android/Prepare-QuestDependencies.ps1 first.'
|
|
}
|
|
|
|
$javaHome = if ($env:JAVA_HOME) { $env:JAVA_HOME } else { 'C:\Program Files\Java\jdk-17' }
|
|
$sdkRoot = if ($env:ANDROID_HOME) { $env:ANDROID_HOME } elseif ($env:ANDROID_SDK_ROOT) { $env:ANDROID_SDK_ROOT } else { Join-Path $env:LOCALAPPDATA 'Android\Sdk' }
|
|
if (-not (Test-Path (Join-Path $javaHome 'bin\java.exe'))) { throw "JDK 17 not found at $javaHome (set JAVA_HOME)" }
|
|
if (-not (Test-Path $sdkRoot)) { throw "Android SDK not found at $sdkRoot (set ANDROID_HOME)" }
|
|
|
|
$env:JAVA_HOME = $javaHome
|
|
$env:ANDROID_HOME = $sdkRoot
|
|
$env:ANDROID_SDK_ROOT = $sdkRoot
|
|
|
|
# aurora-main requires CMake 3.25+, newer than the SDK's bundled 3.22.1. Point
|
|
# the Android Gradle plugin at a system CMake through local.properties and put
|
|
# the SDK's Ninja on PATH, which a non-bundled CMake needs.
|
|
if (-not $CMakeDir) {
|
|
$cmakeExe = Get-Command cmake.exe -ErrorAction SilentlyContinue
|
|
if ($cmakeExe) { $CMakeDir = Split-Path -Parent (Split-Path -Parent $cmakeExe.Source) }
|
|
}
|
|
if (-not $CMakeDir -or -not (Test-Path (Join-Path $CMakeDir 'bin\cmake.exe'))) {
|
|
throw 'No CMake 3.25+ found; install one or pass -CMakeDir <install root>'
|
|
}
|
|
$sdkCMake = Get-ChildItem -Path (Join-Path $sdkRoot 'cmake') -Directory | Sort-Object Name -Descending | Select-Object -First 1
|
|
if ($sdkCMake) { $env:PATH = (Join-Path $sdkCMake.FullName 'bin') + ';' + $env:PATH }
|
|
# Parenthesised: PowerShell's comma binds tighter than +, which would join both
|
|
# properties into a single line.
|
|
$localProperties = @(
|
|
('sdk.dir=' + $sdkRoot.Replace('\', '\\')),
|
|
('cmake.dir=' + $CMakeDir.Replace('\', '\\'))
|
|
)
|
|
Set-Content -Path (Join-Path $root 'local.properties') -Value $localProperties -Encoding ascii
|
|
|
|
if (-not $Dependencies) {
|
|
$candidate = Join-Path $repo '.scratch\vr-build-workspace\BuildWorkspace\Dependencies'
|
|
if (Test-Path $candidate) { $Dependencies = $candidate }
|
|
}
|
|
|
|
$variant = (Get-Culture).TextInfo.ToTitleCase($Configuration)
|
|
# The Gradle flavour and the -mcpu target its kit must record (headsetCpus in app/build.gradle.kts).
|
|
$flavourDir, $expectedCpu = switch ($Headset) {
|
|
'quest1' { 'quest1', 'kryo' }
|
|
'frame' { 'steamFrame', 'cortex-x4' }
|
|
default { 'modernQuest', 'cortex-a77' }
|
|
}
|
|
$flavour = $flavourDir.Substring(0, 1).ToUpperInvariant() + $flavourDir.Substring(1)
|
|
$task = "app:assemble$flavour$variant"
|
|
$gradleArgs = @(
|
|
'--project-dir', $root,
|
|
"-PmkwGeneratedDir=$Generated"
|
|
)
|
|
if ($Dependencies) { $gradleArgs += "-PmkwDependenciesDir=$Dependencies" }
|
|
if (-not $StockDawn) {
|
|
$dawnWork = Join-Path $repo '.scratch\quest-dawn'
|
|
& (Join-Path $root 'Build-QuestDawn.ps1') -WorkDirectory $dawnWork
|
|
$gradleArgs += "-PmkwQuestDawnDir=$(Join-Path $dawnWork 'package')"
|
|
}
|
|
$gradleArgs += $task
|
|
Write-Host "gradlew $($gradleArgs -join ' ')"
|
|
& (Join-Path $root 'gradlew.bat') @gradleArgs
|
|
if ($LASTEXITCODE -ne 0) { throw "Gradle failed ($LASTEXITCODE)" }
|
|
|
|
$apkDir = Join-Path $root "app\build\outputs\apk\$flavourDir\$Configuration"
|
|
$apk = Get-ChildItem -Path $apkDir -Filter '*.apk' | Select-Object -First 1
|
|
if (-not $apk) { throw "No APK under $apkDir" }
|
|
Write-Host "APK: $($apk.FullName)"
|
|
|
|
# The APK must be distributable: no translated game inside, only the game kit and the toolchain
|
|
# that builds one on the headset.
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$archive = [IO.Compression.ZipFile]::OpenRead($apk.FullName)
|
|
try {
|
|
$gameLibraries = @($archive.Entries | Where-Object { $_.FullName -match '^lib/[^/]+/libmain[^/]*\.so$' })
|
|
$kitEntry = @($archive.Entries | Where-Object { $_.FullName -eq 'assets/game_kit/kit.json' }) | Select-Object -First 1
|
|
$kitCpu = if ($kitEntry) {
|
|
$reader = New-Object IO.StreamReader($kitEntry.Open())
|
|
try { ($reader.ReadToEnd() | ConvertFrom-Json).androidCpu } finally { $reader.Dispose() }
|
|
} else { '' }
|
|
$hasToolchain = @($archive.Entries | Where-Object { $_.FullName -eq 'assets/quest_toolchain/files.zip' }).Count -gt 0
|
|
} finally { $archive.Dispose() }
|
|
if ($gameLibraries.Count -gt 0) { throw "The APK contains a translated game library: $($gameLibraries.FullName -join ', ')" }
|
|
if (-not $kitEntry) { throw 'The APK has no game kit (assets/game_kit/kit.json)' }
|
|
if ($kitCpu -ne $expectedCpu) { throw "The $Headset APK contains a game kit for CPU '$kitCpu', expected '$expectedCpu'" }
|
|
if (-not $hasToolchain) { throw 'The APK has no build toolchain (assets/quest_toolchain/files.zip)' }
|
|
|
|
if ($Install) {
|
|
$adb = Join-Path $sdkRoot 'platform-tools\adb.exe'
|
|
& $adb install -r $apk.FullName
|
|
if ($LASTEXITCODE -ne 0) { throw "adb install failed ($LASTEXITCODE)" }
|
|
if ($Headset -eq 'quest1') {
|
|
Write-Host 'Installed. Use WiiCompiled Settings for setup, then launch WiiCompiled VR directly from the library.'
|
|
} elseif ($Headset -eq 'frame') {
|
|
Write-Host 'Installed. Build a game on this PC with android/Build-QuestGame.ps1 -Headset frame -Install, then start WiiCompiled VR from the Steam library.'
|
|
} else {
|
|
Write-Host 'Installed. Build a game with Build on this Quest in the launcher, or on this PC with android/Build-QuestGame.ps1 -Install.'
|
|
}
|
|
}
|