Files
mitch030504--Wiicompiled_VR…/Launcher/Test-PinnedFacts.ps1
T
iChris4andClaude Opus 5 c8eaa52727 Merge upstream/main into openxr-work (reverse-Z fix adapted for VR)
Brings in patchzyy/Wiicompiled main: os_sleep parked-thread fix (#195),
HTTPS Retro WFC payload (#198), macOS build guide (#177), and the
reverse-Z depth fix (#134).

Conflicts were in aurora-main/lib/gfx/common.cpp and lib/gx/shader.cpp,
both from #134, which lands squarely on the VR stereo replay path.

#134 makes UseReversedZ genuinely reversed: the near/far correction now
applies exactly once, inside effective_projection(), instead of being
applied there AND per-vertex in the shader (the double application had
been cancelling out, so "reversed" Z silently behaved like forward Z).
Three pieces of the VR path were built against that old behaviour and
would have broken silently, so they are adapted here:

- shader.cpp exact-screen-depth parked the virtual screen at -0.5*w
  specifically so the shader's following negation would land it at
  +0.5*w. With that negation gone it now writes +0.5*w directly; keeping
  the minus sign would park the screen at NDC -0.5, outside the clip
  volume, discarding every 2D/HUD draw.

- stereo_replay.hpp backend_ndc_depth_row re-applied the correction to
  the projection it was handed. That projection is effective_projection()
  output, which now already carries it, so the function is a pass-through
  of the Z row and no longer depends on the reversed-Z setting; the dead
  bool parameter is dropped. Re-applying it would invert the virtual
  screen's depth ordering, so 2D layers meant to sit on top would lose
  the depth test to the ones behind them.

- shader_info.cpp stages the host depth window for that exact-depth path.
  It now uses the same reversed-Z remap as upstream's new SetViewport
  code, since frag_depth is written directly and has to reproduce the
  window the fixed viewport transform would have applied. Restricted
  depth windows (how the game forces an element in front of everything)
  are exactly the 2D draws the virtual screen carries.

The SetViewport resolution keeps upstream's remap but retains the
ordering/clamp guard our version had: for any ordered guest range the
result is identical to upstream, and it avoids handing WebGPU
minDepth > maxDepth for the swapped pair MKW is known to emit. The VR eye
replay reuses these recorded values, so the guard covers that path too.

Test updates:
- stereo_replay_test now asserts the composed Z row against the staged
  projection's own Z row rather than against the helper's output, so it
  actually catches a re-introduced double correction (verified: it fails
  when the old negation is put back; the previous self-consistent form
  passed).
- gx_fifo_test's clearDepthValue expectation followed #134's deliberate
  clear_depth_value() inversion, expressed through UseReversedZ rather
  than hardcoded. Upstream changed the behaviour without updating this
  test, so it fails on upstream/main as-is.

Verified: aurora suite 247 passed with the same 2 failures that already
fail on the pre-merge branch (IndexedPaletteHistoryKeepsAbsoluteVertexSlots,
PacksOneUniformWhenBothHalvesNeedInitialValue - both pre-existing, unrelated
to depth); shader.cpp and common.cpp compile clean; translator suite 577
passed. Not yet validated on-device in VR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 04:19:51 +02:00

157 lines
9.0 KiB
PowerShell

# Fails the release build when a fact duplicated across the repo stops agreeing with the copy
# that owns it (recomp.yml). Scripts read pinned facts through Get-MkwProjectPins, but three
# consumers can't read YAML (the C++ runtime header, the C# constants, shell scripts, and hand-written lists on
# both sides of the C#/PowerShell boundary), so those are checked here instead.
[CmdletBinding()]
param([string]$RepositoryRoot)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version 3.0
. (Join-Path $PSScriptRoot 'NativeBuildFlags.ps1')
if ([string]::IsNullOrWhiteSpace($RepositoryRoot)) {
$RepositoryRoot = Join-Path $PSScriptRoot '..'
}
$repoRoot = [IO.Path]::GetFullPath($RepositoryRoot)
$launcher = Join-Path $repoRoot 'Launcher'
$setup = Join-Path $launcher 'WiiCompiled.Setup.Windows'
$common = Join-Path $launcher 'WiiCompiled.Setup.Common'
$failures = [Collections.Generic.List[string]]::new()
function Add-Failure([string]$Message) { $failures.Add($Message) }
function Read-SourceFile([string]$Path, [string]$Description) {
Assert-File $Path $Description
return [IO.File]::ReadAllText($Path)
}
function Get-CapturedValue([string]$Text, [string]$Pattern, [string]$Description) {
$match = [regex]::Match($Text, $Pattern)
if (-not $match.Success) { throw "$Description could not be located; update Test-PinnedFacts.ps1." }
return $match.Groups[1].Value
}
function Get-QuotedList([string]$Text, [string]$BlockPattern, [string]$ItemPattern, [string]$Description) {
$block = Get-CapturedValue $Text $BlockPattern $Description
$items = [regex]::Matches($block, $ItemPattern) | ForEach-Object { $_.Groups[1].Value }
if (@($items).Count -eq 0) { throw "$Description is empty; update Test-PinnedFacts.ps1." }
return [string[]]@($items)
}
function Compare-Set([string[]]$Expected, [string[]]$Actual, [string]$ExpectedName, [string]$ActualName) {
$missing = @($Expected | Where-Object { $Actual -notcontains $_ })
$extra = @($Actual | Where-Object { $Expected -notcontains $_ })
if ($missing.Count -gt 0) { Add-Failure "$ActualName is missing: $($missing -join ', ') (present in $ExpectedName)." }
if ($extra.Count -gt 0) { Add-Failure "$ActualName has entries $ExpectedName does not: $($extra -join ', ')." }
}
$pins = Get-MkwProjectPins (Join-Path $repoRoot 'projects\mkwii\recomp.yml')
# --- The Retro-WFC endpoint: recomp.yml owns it; the installer host pins the same string so a
# --- redirected or rewritten endpoint cannot be fetched from. The literal lives in
# --- WiiCompiled.Setup.Common (shared with WiiCompiled.Setup.Linux) - InputValidation.cs only
# --- re-exports it as `= RetroWfcPayload.CurrentRetroWfcPayloadUri;`, no literal to capture there.
$retroWfcPayload = Read-SourceFile (Join-Path $common 'RetroWfcPayload.cs') 'RetroWfcPayload.cs'
$hostUri = Get-CapturedValue $retroWfcPayload 'CurrentRetroWfcPayloadUri\s*=\s*"([^"]+)"' `
'The host Retro-WFC endpoint constant'
if ($hostUri -cne $pins.RetroWfcPayloadUri) {
Add-Failure "InputValidation.CurrentRetroWfcPayloadUri is '$hostUri' but recomp.yml pins '$($pins.RetroWfcPayloadUri)'."
}
$macosSetup = Read-SourceFile (Join-Path $launcher 'macos\setup.command') 'macOS setup.command'
$macosUri = Get-CapturedValue $macosSetup "'([^']*/api/wfc/payload\?g=RMCPD00)'" `
'The macOS Retro-WFC endpoint'
if ($macosUri -cne $pins.RetroWfcPayloadUri) {
Add-Failure "macOS setup.command downloads '$macosUri' but recomp.yml pins '$($pins.RetroWfcPayloadUri)'."
}
# --- The game identity: the manifest carries it, but the host also compiles a fallback for a
# --- manifest that predates the field, and that fallback decides which disc is accepted.
$models = Read-SourceFile (Join-Path $setup 'Models.cs') 'Models.cs'
$hostGameId = Get-CapturedValue $models 'ExpectedGameId\s*\{\s*get;\s*set;\s*\}\s*=\s*"([^"]+)"' `
'The host expected game id'
if ($hostGameId -cne $pins.GameId) {
Add-Failure "PayloadManifest.ExpectedGameId defaults to '$hostGameId' but recomp.yml pins '$($pins.GameId)'."
}
# --- The translation entry point: the translator is told it by LocalBuild.ps1 (which reads
# --- recomp.yml), while the runtime enters the translated image at its own constant.
$systemBridge = Read-SourceFile (Join-Path $repoRoot 'runtime\include\system_bridge.h') 'system_bridge.h'
$runtimeEntry = (Get-CapturedValue $systemBridge 'kDefaultEntryAddress\s*=\s*(0[xX][0-9a-fA-F]+)' `
'The runtime default entry address').ToLowerInvariant()
if ($runtimeEntry -ne $pins.EntryPoint) {
Add-Failure "system_bridge.h enters at $runtimeEntry but recomp.yml translates from $($pins.EntryPoint)."
}
# --- The pinned dependency set: Build-Installer.ps1 stages it, the installed host requires it,
# --- and Prepare-Dependencies.ps1 must be able to supply every source tree. native_prebuilt is
# --- intentionally produced later by Prepare-NativePrebuilt.ps1; cppwinrt is generated separately
# --- by Prepare-Dependencies.ps1 rather than appearing in its downloaded $packages array.
$installedLayout = Read-SourceFile (Join-Path $setup 'InstalledLayout.cs') 'InstalledLayout.cs'
$buildInstaller = Read-SourceFile (Join-Path $launcher 'Build-Installer.ps1') 'Build-Installer.ps1'
$dependencyNames = Get-QuotedList $installedLayout '(?s)DependencyNames\s*=\s*\[(.*?)\]' `
'"([^"]+)"' 'InstalledLayout.DependencyNames'
$installerDependencies = Get-QuotedList $buildInstaller `
'(?s)\$requiredDependencies\s*=\s*@\((.*?)\)' "'([^']+)'" `
'Build-Installer.ps1 $requiredDependencies'
Compare-Set $dependencyNames $installerDependencies `
'InstalledLayout.DependencyNames' 'Build-Installer.ps1 $requiredDependencies'
$dependencyPreparer = Read-SourceFile (Join-Path $launcher 'Prepare-Dependencies.ps1') `
'Prepare-Dependencies.ps1'
$downloadedDependencies = Get-QuotedList $dependencyPreparer `
'(?sm)\$packages\s*=\s*@\((.*?)^\)' "Name\s*=\s*'([^']+)'" `
'Prepare-Dependencies.ps1 $packages'
$preparedDependencies = @($downloadedDependencies) + @('cppwinrt')
$sourceDependencies = @($dependencyNames | Where-Object { $_ -ne 'native_prebuilt' })
Compare-Set $sourceDependencies $preparedDependencies `
'InstalledLayout.DependencyNames source entries' 'Prepare-Dependencies.ps1 outputs'
# --- The runtime assets copied beside a product: the host hashes exactly these names, so the build
# --- script must publish every one of them or every product reports its support files as stale.
$localBuild = Read-SourceFile (Join-Path $launcher 'LocalBuild.ps1') 'LocalBuild.ps1'
$productAssets = @(Get-CapturedValue $installedLayout 'ProductBootstrapDirectoryName\s*=\s*"([^"]+)"' `
'The product bootstrap directory name') +
@(Get-QuotedList $installedLayout '(?s)ProductFileName\)\[\]\s*Files\s*=\s*\[(.*?)\n\s*\];' `
'\]\s*,\s*"([^"]+)"\s*\)' 'ProductRuntimeAssets.Files')
foreach ($asset in $productAssets) {
if ($localBuild.IndexOf("'$asset'", [StringComparison]::Ordinal) -lt 0) {
Add-Failure "LocalBuild.ps1 never publishes the product runtime asset '$asset'."
}
}
# --- The command-line contract between the host and the build script.
$localBuildService = Read-SourceFile (Join-Path $setup 'LocalBuildService.cs') 'LocalBuildService.cs'
$parameterBlock = Get-CapturedValue $localBuild '(?sm)^param\((.*?)\r?\n\)' 'The LocalBuild.ps1 param block'
$scriptParameters = [regex]::Matches($parameterBlock, '\$(\w+)') | ForEach-Object { $_.Groups[1].Value }
# powershell.exe's own switches travel in the same argument list and are not script parameters.
$hostSwitches = @('NoLogo', 'NoProfile', 'NonInteractive', 'ExecutionPolicy', 'File')
$passedSwitches = [regex]::Matches($localBuildService, '"-([A-Za-z]\w*)"') |
ForEach-Object { $_.Groups[1].Value } | Where-Object { $hostSwitches -notcontains $_ } |
Sort-Object -Unique
foreach ($switch in $passedSwitches) {
if ($scriptParameters -notcontains $switch) {
Add-Failure "LocalBuildService.cs passes -$switch, which LocalBuild.ps1 does not declare."
}
}
foreach ($mandatory in ([regex]::Matches($parameterBlock,
'\[Parameter\(Mandatory\)\][^$]*\$(\w+)') | ForEach-Object { $_.Groups[1].Value })) {
if ($passedSwitches -notcontains $mandatory) {
Add-Failure "LocalBuild.ps1 requires -$mandatory, which LocalBuildService.cs never passes."
}
}
# --- The build steps the installer's progress bar acts on.
$installProgress = Read-SourceFile (Join-Path $setup 'InstallProgress.cs') 'InstallProgress.cs'
$knownSteps = Get-QuotedList $installProgress '(?s)class BuildStepIds\s*\{(.*?)\n\}' `
'const string \w+ = "([^"]+)";' 'BuildStepIds'
$emittedSteps = @([regex]::Matches($localBuild, "(?:-StepId|Write-MkwBuildStep)\s+'([^']+)'") |
ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique)
Compare-Set $knownSteps $emittedSteps 'BuildStepIds' 'the steps LocalBuild.ps1 emits'
if ($failures.Count -gt 0) {
throw "Pinned facts disagree between their copies:`n $($failures -join "`n ")"
}
Write-Host ("Pinned-fact audit passed: game {0}, entry {1}, endpoint {2}; dependency, runtime-asset, " -f
$pins.GameId, $pins.EntryPoint, $pins.RetroWfcPayloadUri) -NoNewline
Write-Host 'build-step, and build-script parameter contracts all agree.'