<# .SYNOPSIS Build the RIOJoy cockpit deployment zip: publish the tray app self-contained, bundle the signed ViGEmBus installer + the post-install scripts, and zip it for TeslaConsole. The zip extracts directly into a single directory (C:\games\RIOJOY). .PARAMETER VigemInstaller Path to the signed ViGEmBus installer to bundle. If omitted, looks in deploy\vendor\ViGEmBus*.exe. .PARAMETER OutDir Where to write the zip (default: dist, relative to the repo root). .PARAMETER Configuration Build configuration (default: Release). #> param( [string]$VigemInstaller, [string]$OutDir = 'dist', [string]$Configuration = 'Release' ) $ErrorActionPreference = 'Stop' $repo = Split-Path $PSScriptRoot -Parent # deploy\ -> repo root $staging = Join-Path ([IO.Path]::GetTempPath()) "riojoy-pkg-$([Guid]::NewGuid().ToString('N'))" Write-Host '== RIOJoy deployment package ==' -ForegroundColor Cyan # --- version stamp -------------------------------------------------------- $sha = (& git -C $repo rev-parse --short HEAD 2>$null) if (-not $sha) { $sha = 'nogit' } $version = "{0}-{1}" -f (Get-Date -Format 'yyyyMMdd'), $sha # --- locate the ViGEmBus installer ---------------------------------------- if (-not $VigemInstaller) { $VigemInstaller = Get-ChildItem -Path (Join-Path $PSScriptRoot 'vendor') -Filter 'ViGEmBus*.exe' ` -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName } if (-not $VigemInstaller -or -not (Test-Path $VigemInstaller)) { throw "ViGEmBus installer not found. Pass -VigemInstaller , or drop ViGEmBus_*.exe into deploy\vendor\. Get it from https://github.com/nefarius/ViGEmBus/releases." } $sig = Get-AuthenticodeSignature $VigemInstaller if ($sig.Status -ne 'Valid') { throw "ViGEmBus installer is not validly signed ($($sig.Status)): $VigemInstaller" } Write-Host "ViGEmBus installer: $(Split-Path $VigemInstaller -Leaf) (signature $($sig.Status))" try { # The payload lives in a 'RIOJoy' folder; postinstall.bat sits beside it at the # zip root (TeslaConsole runs it; it calls RIOJoy\install-rio.ps1). $pkgDir = Join-Path $staging 'RIOJoy' New-Item -ItemType Directory -Force -Path $pkgDir | Out-Null # 1. Publish the tray app into riojoy\app (net48, framework-dependent — relies on # the in-box .NET Framework 4.8 present on every Windows 10/11 machine). $appOut = Join-Path $pkgDir 'app' Write-Host "Publishing RioJoy.Tray ($Configuration, net48 framework-dependent)..." & dotnet publish (Join-Path $repo 'src\RioJoy.Tray\RioJoy.Tray.csproj') ` -c $Configuration -p:DebugType=none ` -o $appOut | Out-Null if ($LASTEXITCODE -ne 0) { throw 'dotnet publish failed.' } # 1b. Trim native SkiaSharp variants the x64 pod never uses. SkiaSharp's net48 # loader finds the native in either the app root or an arch subfolder (both # verified), so we keep only the win-x64 libSkiaSharp.dll at the app root and # drop the x64/x86/arm64 subdir copies and the macOS .dylib (~38 MB). $rootSkia = Join-Path $appOut 'libSkiaSharp.dll' if (-not (Test-Path $rootSkia)) { throw "Expected app\libSkiaSharp.dll (win-x64) before pruning, but it is missing." } foreach ($d in 'x64', 'x86', 'arm64') { $nd = Join-Path $appOut $d if (Test-Path $nd) { Remove-Item $nd -Recurse -Force } } Get-ChildItem $appOut -Filter '*.dylib' -ErrorAction SilentlyContinue | Remove-Item -Force Get-ChildItem $appOut -Filter '*.so' -ErrorAction SilentlyContinue | Remove-Item -Force # 2. Bundle the signed ViGEmBus installer into riojoy\vendor. $vendorOut = Join-Path $pkgDir 'vendor' New-Item -ItemType Directory -Force -Path $vendorOut | Out-Null Copy-Item $VigemInstaller $vendorOut # 3. Install/uninstall scripts + readme + version stamp inside RIOJoy\; # postinstall.bat at root, pre-uninstall.bat inside the payload folder. Copy-Item (Join-Path $PSScriptRoot 'install-rio.ps1') $pkgDir Copy-Item (Join-Path $PSScriptRoot 'uninstall-rio.ps1') $pkgDir Copy-Item (Join-Path $PSScriptRoot 'pre-uninstall.bat') $pkgDir Copy-Item (Join-Path $PSScriptRoot 'README-DEPLOY.txt') $pkgDir Set-Content -Path (Join-Path $pkgDir 'VERSION.txt') -Value "RIOJoy $version" -Encoding utf8 Copy-Item (Join-Path $PSScriptRoot 'postinstall.bat') $staging # 4. Zip the package contents (so it extracts straight into C:\games\RIOJOY). $outDirFull = if ([IO.Path]::IsPathRooted($OutDir)) { $OutDir } else { Join-Path $repo $OutDir } New-Item -ItemType Directory -Force -Path $outDirFull | Out-Null $zip = Join-Path $outDirFull "RIOJoy-$version.zip" if (Test-Path $zip) { Remove-Item $zip -Force } Write-Host "Zipping -> $zip" # Build entries by hand with forward-slash names: both Compress-Archive and # ZipFile.CreateFromDirectory write BACKSLASH separators under Windows PowerShell # (.NET Framework), which some extractors mishandle. Entries are relative to the # staging root, so the zip extracts straight into the target (C:\games\RIOJOY\...). Add-Type -AssemblyName System.IO.Compression Add-Type -AssemblyName System.IO.Compression.FileSystem $base = (Resolve-Path $staging).Path.TrimEnd('\') + '\' $fs = [System.IO.File]::Open($zip, [System.IO.FileMode]::CreateNew) try { $archive = New-Object System.IO.Compression.ZipArchive($fs, [System.IO.Compression.ZipArchiveMode]::Create) try { foreach ($file in Get-ChildItem -Path $staging -Recurse -File) { $entryName = $file.FullName.Substring($base.Length) -replace '\\', '/' [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile( $archive, $file.FullName, $entryName, [System.IO.Compression.CompressionLevel]::Optimal) | Out-Null } } finally { $archive.Dispose() } } finally { $fs.Dispose() } $size = '{0:N1} MB' -f ((Get-Item $zip).Length / 1MB) Write-Host '' Write-Host "Package built: $zip ($size)" -ForegroundColor Green Write-Host 'Deploy: extract (postinstall.bat + riojoy\), then run postinstall.bat (elevated).' } finally { if (Test-Path $staging) { Remove-Item $staging -Recurse -Force } }