Phase 8D: universal deployment package (XP + Win10/11, two entry points)

One RIOJoy-<ver>.zip now deploys on both OS generations (~75 MB with the
offline XP prerequisites):
- Layout: RIOJoy\app (net48 x64) + RIOJoy\app-xp (net40 x86) +
  RIOJoy\vendor (ViGEmBus; vendor\xp: .NET 4.0 offline installer +
  KB2468871, both signature-verified; RioGamepadXP driver slots in when
  8B lands - build warns/skips until then).
- RIOJoy\install-core.bat: shared OS-detecting install logic (ver ->
  5.1 = XP); pure cmd.exe on the XP path, delegates to install-rio.ps1
  on 10/11. Exports RIOJOY_APPDIR for shortcut creation.
- postinstall.bat (TeslaConsole, unattended): elevates, runs the core,
  then deletes install.bat + README.txt so C:\games stays clean.
- install.bat (standalone computers): same core + Start Menu/desktop
  shortcuts via make-shortcut.vbs (XP-safe); keeps the README.
- README.txt at the zip root explains which entry point to run.
- deploy *.ps1 re-encoded UTF-8-with-BOM: Windows PowerShell read the
  BOM-less files as ANSI, where an em-dash byte parses as a curly quote
  and breaks string parsing (bit install-rio.ps1 in dry-run testing).

Verified: zip layout correct; extracted package dispatch-tested on
Win10 non-elevated (OS detect -> modern route -> admin guard, system
untouched).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-11 20:53:43 -05:00
co-authored by Claude Fable 5
parent 63af7bde01
commit 2ecb617c09
9 changed files with 294 additions and 24 deletions
+59
View File
@@ -0,0 +1,59 @@
RIOJoy - cockpit interface for the VWE pods
============================================
This package installs RIOJoy, the program that connects the cockpit's RIO
hardware (joystick, throttle, pedals, 96 lighted buttons, plasma display)
to games that don't know about the cockpit. It works on two kinds of
Windows:
* Windows 10 / 11 (64-bit) - full app, appears to games as an Xbox 360
controller (ViGEmBus driver, included)
* Windows XP SP3 (32-bit) - full runtime + mapping editor; all
prerequisites are included for offline
install (.NET 4.0 + its async update)
The installer detects which Windows it is running on and installs the
right pieces automatically. Everything needed is inside this package -
no internet connection is required.
WHICH FILE DO I RUN?
--------------------
install.bat <-- RUN THIS on a normal, standalone computer.
Right-click -> "Run as administrator" (on XP, log
in as an Administrator user first). It installs
the prerequisites and puts RIOJoy shortcuts in the
Start Menu and on the desktop. RIOJoy does NOT
auto-start with Windows - launch it from the
shortcut when you want the cockpit active.
postinstall.bat -- Used by the arcade cabinet's launcher software
(TeslaConsole). It runs automatically after the
cabinet extracts this package; you do not need to
run it by hand. (It also deletes install.bat and
this README so the cabinet's games folder stays
clean.)
WHAT GETS INSTALLED
-------------------
RIOJoy\app\ the program for Windows 10/11
RIOJoy\app-xp\ the program for Windows XP
RIOJoy\vendor\ third-party prerequisites (ViGEmBus for 10/11;
.NET 4.0 + KB2468871 + the RioGamepadXP joystick
driver for XP)
After installing, start RIOJoy and look for its icon in the system tray
(near the clock). Right-click the icon to pick a profile, edit button
mappings, or send commands to the cockpit hardware. Full deployment
notes for cabinet operators are in RIOJoy\README-DEPLOY.txt.
REMOVING RIOJOY
---------------
Run RIOJoy\pre-uninstall.bat as administrator, then delete the folder
you extracted. On a standalone computer also delete the RIOJoy shortcuts
from the Start Menu and desktop.
+56 -12
View File
@@ -1,8 +1,11 @@
<#
<#
.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).
Build the UNIVERSAL RIOJoy deployment zip (PLAN.md §8D): one archive that
deploys on Windows 10/11 (net48 x64, ViGEmBus) AND Windows XP SP3 (net40
x86, offline prerequisites). Two install entry points sit at the zip root:
postinstall.bat (TeslaConsole, unattended, cleans the root after itself)
and install.bat (standalone computers, adds shortcuts). README.txt at the
root explains it to a human installer.
.PARAMETER VigemInstaller
Path to the signed ViGEmBus installer to bundle. If omitted, looks in
@@ -11,6 +14,12 @@
Where to write the zip (default: dist, relative to the repo root).
.PARAMETER Configuration
Build configuration (default: Release).
.NOTES
XP offline prerequisites are picked up from deploy\vendor\xp\ when present
(dotNetFx40_Full_x86_x64.exe, NDP40-KB2468871-v2-x86.exe, and the
RioGamepadXP driver once Phase 8B lands); missing ones produce warnings,
not failures, so modern-only builds still work.
#>
param(
[string]$VigemInstaller,
@@ -47,14 +56,23 @@ try {
$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).
# 1. Publish the tray app into RIOJoy\app (net48 x64, 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)..."
Write-Host "Publishing RioJoy.Tray ($Configuration, net48 x64 framework-dependent)..."
& dotnet publish (Join-Path $repo 'src\RioJoy.Tray\RioJoy.Tray.csproj') `
-c $Configuration -p:DebugType=none `
-c $Configuration -f net48 -p:DebugType=none `
-o $appOut | Out-Null
if ($LASTEXITCODE -ne 0) { throw 'dotnet publish failed.' }
if ($LASTEXITCODE -ne 0) { throw 'dotnet publish (net48) failed.' }
# 1a. Publish the Windows XP flavor into RIOJoy\app-xp (net40 x86,
# framework-dependent on the bundled .NET 4.0).
$appXpOut = Join-Path $pkgDir 'app-xp'
Write-Host "Publishing RioJoy.Tray ($Configuration, net40 x86 for Windows XP)..."
& dotnet publish (Join-Path $repo 'src\RioJoy.Tray\RioJoy.Tray.csproj') `
-c $Configuration -f net40 -p:DebugType=none `
-o $appXpOut | Out-Null
if ($LASTEXITCODE -ne 0) { throw 'dotnet publish (net40) 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
@@ -71,19 +89,45 @@ try {
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.
# 2. Bundle the signed ViGEmBus installer into RIOJoy\vendor, and the XP
# offline prerequisites into RIOJoy\vendor\xp (warn if absent).
$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.
$vendorXpSrc = Join-Path $PSScriptRoot 'vendor\xp'
$vendorXpOut = Join-Path $vendorOut 'xp'
New-Item -ItemType Directory -Force -Path $vendorXpOut | Out-Null
$xpWanted = @(
@{ Name = 'dotNetFx40_Full_x86_x64.exe'; What = '.NET Framework 4.0 offline installer' },
@{ Name = 'NDP40-KB2468871-v2-x86.exe'; What = '.NET 4.0 update KB2468871 (required by Bcl.Async)' },
@{ Name = 'RioGamepadXP.inf'; What = 'RioGamepadXP driver INF (Phase 8B)' },
@{ Name = 'RioGamepadXP.sys'; What = 'RioGamepadXP driver binary (Phase 8B)' }
)
foreach ($item in $xpWanted) {
$src = Join-Path $vendorXpSrc $item.Name
if (Test-Path $src) {
Copy-Item $src $vendorXpOut
Write-Host "XP vendor: $($item.Name)"
} else {
Write-Warning "XP vendor missing: $($item.Name) - $($item.What). XP installs will warn/skip."
}
}
# 3. Install/uninstall scripts + readmes + version stamp. Payload scripts in
# RIOJoy\; the two entry points (postinstall.bat, install.bat) and the
# human README at the zip root (postinstall.bat deletes install.bat +
# README.txt after a cabinet deploy to keep C:\games clean).
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 'install-core.bat') $pkgDir
Copy-Item (Join-Path $PSScriptRoot 'make-shortcut.vbs') $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
Copy-Item (Join-Path $PSScriptRoot 'install.bat') $staging
Copy-Item (Join-Path $PSScriptRoot 'README.txt') $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 }
+68
View File
@@ -0,0 +1,68 @@
@echo off
rem ===========================================================================
rem RIOJoy shared install core - called by postinstall.bat (cabinet /
rem TeslaConsole) and install.bat (freestanding). NOT run directly.
rem Detects the OS and installs the matching flavor's prerequisites:
rem Windows XP (5.1) -> .NET 4.0 + KB2468871 from RIOJoy\vendor\xp,
rem RioGamepadXP driver INF when bundled;
rem app = RIOJoy\app-xp (net40 x86)
rem Windows 10/11 -> RIOJoy\install-rio.ps1 (ViGEmBus etc.);
rem app = RIOJoy\app (net48 x64)
rem Pure cmd.exe on the XP path (XP has no in-box PowerShell). Idempotent.
rem Sets RIOJOY_APPDIR for the caller (shortcut creation).
rem ===========================================================================
setlocal EnableExtensions
set CORE_RC=0
set PKGROOT=%~dp0
rem PKGROOT = ...\RIOJoy\ (this file lives inside the payload folder)
ver | findstr /C:"Version 5.1" >nul
if %errorlevel% equ 0 goto xp
rem --- Windows 10/11 ---------------------------------------------------------
echo Detected modern Windows - installing the net48 x64 flavor prerequisites.
powershell -NoProfile -ExecutionPolicy Bypass -File "%PKGROOT%install-rio.ps1"
set CORE_RC=%errorlevel%
endlocal & set "RIOJOY_APPDIR=%~dp0app" & exit /b %CORE_RC%
:xp
rem --- Windows XP SP3 ---------------------------------------------------------
echo Detected Windows XP - installing the net40 x86 flavor prerequisites.
rem .NET Framework 4.0 (XP's ceiling; required by the app).
reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v Install 2>nul | findstr /C:"0x1" >nul
if %errorlevel% equ 0 (
echo .NET Framework 4.0 already installed.
) else (
if exist "%PKGROOT%vendor\xp\dotNetFx40_Full_x86_x64.exe" (
echo Installing .NET Framework 4.0 - this takes several minutes...
"%PKGROOT%vendor\xp\dotNetFx40_Full_x86_x64.exe" /q /norestart
if errorlevel 3011 echo .NET install requests a reboot - reboot before first use.
) else (
echo ERROR: vendor\xp\dotNetFx40_Full_x86_x64.exe is missing from the package.
set CORE_RC=1
goto xpdone
)
)
rem KB2468871 - required by the async runtime (Microsoft.Bcl.Async).
rem The update no-ops quickly when already applied, so run unconditionally.
if exist "%PKGROOT%vendor\xp\NDP40-KB2468871-v2-x86.exe" (
echo Applying .NET 4.0 update KB2468871...
"%PKGROOT%vendor\xp\NDP40-KB2468871-v2-x86.exe" /q /norestart
) else (
echo WARNING: vendor\xp\NDP40-KB2468871-v2-x86.exe not bundled - the app
echo will not run without KB2468871. Install it before first use.
)
rem RioGamepadXP virtual-joystick driver (bundled from Phase 8B onward).
if exist "%PKGROOT%vendor\xp\RioGamepadXP.inf" (
echo Installing the RioGamepadXP virtual joystick driver...
rundll32 setupapi.dll,InstallHinfSection DefaultInstall 132 %PKGROOT%vendor\xp\RioGamepadXP.inf
) else (
echo Note: RioGamepadXP driver not bundled yet - joystick output is
echo unavailable on XP; keyboard/mouse, lamps and plasma still work.
)
:xpdone
endlocal & set "RIOJOY_APPDIR=%~dp0app-xp" & exit /b %CORE_RC%
+1 -1
View File
@@ -1,4 +1,4 @@
<#
<#
.SYNOPSIS
RIOJoy cockpit post-install. Installs the signed ViGEmBus virtual-controller
driver (if absent). Must run elevated (postinstall.bat elevates for you).
+54
View File
@@ -0,0 +1,54 @@
@echo off
rem ===========================================================================
rem RIOJoy standalone install entry point - for a computer WITHOUT the
rem TeslaConsole launcher. Extract the whole zip somewhere permanent (e.g.
rem C:\games), then run this as administrator. Installs the prerequisites
rem for this Windows version (XP or 10/11) via the shared install core and
rem creates Start Menu + desktop shortcuts to the right flavor of the app.
rem Nothing auto-starts: launch RIOJoy from the shortcut when you want it.
rem See README.txt for details.
rem ===========================================================================
setlocal
title RIOJoy install
rem --- elevate if we are not already administrator --------------------------
net session >nul 2>&1
if %errorlevel% neq 0 (
rem "if errorlevel" evaluates at run time (a %var% here would be stale).
ver | findstr /C:"Version 5.1" >nul
if not errorlevel 1 (
echo This installer must run as an Administrator user.
pause
exit /b 1
)
echo Requesting administrator privileges...
powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
exit /b 0
)
cd /d "%~dp0"
call "%~dp0RIOJoy\install-core.bat"
set RC=%errorlevel%
if %RC% neq 0 goto done
rem --- shortcuts (Start Menu + desktop) --------------------------------------
rem RIOJOY_APPDIR is set by install-core.bat to app (modern) or app-xp (XP).
set EXE=%RIOJOY_APPDIR%\RioJoy.Tray.exe
if not exist "%EXE%" (
echo ERROR: app executable not found: %EXE%
set RC=1
goto done
)
echo Creating shortcuts...
cscript //nologo "%~dp0RIOJoy\make-shortcut.vbs" "%EXE%" "RIOJoy" "%RIOJOY_APPDIR%"
:done
echo.
if %RC% neq 0 (
echo install FAILED with exit code %RC%.
) else (
echo install completed. Launch RIOJoy from the Start Menu or desktop shortcut.
)
pause
exit /b %RC%
+27
View File
@@ -0,0 +1,27 @@
' make-shortcut.vbs <targetExe> <name> <workingDir>
' Creates Start Menu (all users) and desktop shortcuts. VBScript so the same
' helper works on Windows XP (no PowerShell) and Windows 10/11.
Option Explicit
Dim shell, fso, target, name, workdir, places, place, lnk
If WScript.Arguments.Count < 3 Then
WScript.Echo "usage: make-shortcut.vbs <targetExe> <name> <workingDir>"
WScript.Quit 1
End If
target = WScript.Arguments(0)
name = WScript.Arguments(1)
workdir = WScript.Arguments(2)
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
places = Array(shell.SpecialFolders("AllUsersPrograms"), shell.SpecialFolders("Desktop"))
For Each place In places
If fso.FolderExists(place) Then
Set lnk = shell.CreateShortcut(fso.BuildPath(place, name & ".lnk"))
lnk.TargetPath = target
lnk.WorkingDirectory = workdir
lnk.Description = "RIOJoy cockpit interface"
lnk.Save
WScript.Echo " shortcut: " & fso.BuildPath(place, name & ".lnk")
End If
Next
+17 -4
View File
@@ -1,8 +1,10 @@
@echo off
rem ===========================================================================
rem RIOJoy cockpit post-install entry point (run by TeslaConsole).
rem Sits beside the 'RIOJoy' payload folder; elevates, then runs
rem RIOJoy\install-rio.ps1.
rem RIOJoy cockpit post-install entry point (run by TeslaConsole after the
rem package is extracted into C:\games). Sits beside the 'RIOJoy' payload
rem folder; elevates, runs the shared install core (which picks the XP or
rem modern flavor), then removes the standalone-install files so only
rem launcher-managed files stay at the C:\games root.
rem ===========================================================================
setlocal
title RIOJoy post-install
@@ -10,6 +12,12 @@ title RIOJoy post-install
rem --- elevate if we are not already administrator --------------------------
net session >nul 2>&1
if %errorlevel% neq 0 (
rem "if errorlevel" evaluates at run time (a %var% here would be stale).
ver | findstr /C:"Version 5.1" >nul
if not errorlevel 1 (
echo This installer must run as an Administrator user.
exit /b 1
)
echo Requesting administrator privileges...
powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
exit /b 0
@@ -17,9 +25,14 @@ if %errorlevel% neq 0 (
cd /d "%~dp0"
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0RIOJoy\install-rio.ps1"
call "%~dp0RIOJoy\install-core.bat"
set RC=%errorlevel%
rem --- cleanup: cabinet deploys keep the C:\games root clean ----------------
rem (del tolerates already-missing files, so re-runs stay idempotent)
if exist "%~dp0install.bat" del /q "%~dp0install.bat"
if exist "%~dp0README.txt" del /q "%~dp0README.txt"
echo.
if %RC% neq 0 (
echo postinstall FAILED with exit code %RC%.
+1 -1
View File
@@ -1,4 +1,4 @@
<#
<#
.SYNOPSIS
RIOJoy cockpit pre-uninstall cleanup. Reverses install-rio.ps1: stops the
running tray app, removes the logon entry, optionally uninstalls ViGEmBus,
+11 -6
View File
@@ -294,7 +294,8 @@ Replaces the legacy Google-Sheet → `.data` → GIMP → Script-Fu pipeline
- To confirm at Phase 7: target wallpaper resolution(s); static wallpaper vs.
live overlay (e.g. lit-button highlighting mirroring lamp state).
### Phase 8 — Windows XP compatibility (dual-target) — planned
### Phase 8 — Windows XP compatibility (dual-target) — in progress
(8A/8C/8D done ✅; remaining: 8B driver + 8E XP-VM/cabinet verification)
Bring RIOJoy back to the original XP-era cabinets (x86, XP SP3) **without
regressing Windows 10/11**. Strategy: one codebase, two flavors, **one
universal deployment archive**. The mapping editor ships everywhere
@@ -310,7 +311,7 @@ XP consumes pre-rendered wallpapers.
| JSON | System.Text.Json → **Newtonsoft 13** | Newtonsoft 13 (STJ needs net461+; one serializer for both flavors) |
| Install scripts | PowerShell | **.bat only** (XP has no in-box PowerShell) |
- **8A — Core retarget** (`net48;net40` multi-target): de-Span the
- **8A — Core retarget — done ✅** (`net48;net40` multi-target): de-Span the
protocol/serial layer (≈20 uses / 11 files → `byte[]`/`ArraySegment`;
System.Memory doesn't go below net45, and at 9600 baud Span buys nothing);
swap System.Text.Json → Newtonsoft in `ConfigStore`/`OverlayTemplateStore`
@@ -341,16 +342,20 @@ XP consumes pre-rendered wallpapers.
*Staging:* the XP app is useful before the driver lands — milestone 1
ships keyboard/mouse + lamps + plasma (joystick = Null sink), the driver
follows as milestone 2.
- **8C — Tray on net40/x86:** multi-target `RioJoy.Tray` (net40 drops the
- **8C — Tray on net40/x86 — done ✅:** multi-target `RioJoy.Tray` (net40 drops the
ViGEm + RioJoy.Overlay references); gate `WallpaperMakerForm` + overlay
generation; `WallpaperApplier` converts PNG→BMP via GDI+ before
`SystemParametersInfo` (harmless on 10/11, required on XP); profile editor
stays (Segoe UI falls back to Tahoma). XP cabinets consume wallpapers
pre-rendered on a modern machine (`RioProfile.WallpaperPath` travels with
the config).
- **8D — Packaging (decided: one universal archive, two install entry
points).** `build-package.ps1` produces a single `RIOJoy-<ver>.zip` that
deploys on **both** XP and 10/11:
- **8D — Packaging — done ✅ (one universal archive, two install entry
points).** `build-package.ps1` produces a single `RIOJoy-<ver>.zip` (~75 MB
with the offline XP redistributables) that deploys on **both** XP and 10/11;
the RioGamepadXP driver files bundle automatically once 8B lands
(warn/skip until then). The shared OS-detecting install logic lives in
`RIOJoy\install-core.bat` (pure cmd on the XP path); shortcuts via
`make-shortcut.vbs` (works on XP and 10/11 alike):
- Layout: `RIOJoy\app\` (net48 x64) + `RIOJoy\app-xp\` (net40 x86) +
`RIOJoy\vendor\` (ViGEmBus installer for 10/11; RioGamepadXP.sys + INF
for XP; **.NET 4.0 Full + KB2468871 redistributables** so an offline XP