pkg: package identity so Dynamic Lighting grants background control

The Settings "Background light control" list only offers apps that have
BOTH package identity and the com.microsoft.windows.lighting
windows.appExtension in their manifest (declaration verified against
Lenovo's LegionLightingController manifest) — without a grant, Windows
hands the LEDs to vRIO only while it is the foreground window, i.e.
never during gameplay.

pkg/AppxManifest.xml is a sparse package (external location) that
grants the existing VRio.App.exe identity as-is: win32App runtime
behavior, runFullTrust + unvirtualizedResources, and the lighting
app-extension. Register-vRIO.ps1 registers/unregisters it against any
exe folder (repo build or an extracted dist zip); unsigned registration
needs Developer Mode. Identity is granted through shell activation
only — launch from the Start menu entry or an AUMID taskbar pin, not by
double-clicking the exe (the script prints this warning).

Verified end-to-end on this machine: process reports the package full
name, vRIO appears in the background-control list, and the wire log
shows the withheld → available transition once granted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-06 15:08:38 -05:00
co-authored by Claude Fable 5
parent 31c3a910f0
commit f77cd55b11
6 changed files with 137 additions and 5 deletions
+16 -5
View File
@@ -23,6 +23,17 @@ controls:
- Cells shade to the **lamp state the host commands** (`LampRequest`: - Cells shade to the **lamp state the host commands** (`LampRequest`:
off / dim / bright, with slow/med/fast flash), so RIOJoy's press-feedback off / dim / bright, with slow/med/fast flash), so RIOJoy's press-feedback
lights the on-screen panel just like the real buttons. lights the on-screen panel just like the real buttons.
- **Lamps can mirror onto an RGB keyboard** (*Mirror lamps on RGB keyboard*,
via Windows 11 Dynamic Lighting): keys bound to lamp-capable buttons glow
with the panel's palette and blink in step with the on-screen flash modes;
per-key keyboards get the full button field, zone-lit keyboards show the
strongest current lamp board-wide, and a picker narrows the mirror to one
keyboard when several are attached. For the LEDs to stay lit while the
*game* has focus, vRIO needs package identity: run `pkg\Register-vRIO.ps1`
once (Developer Mode required; pass the exe folder for a deployed copy),
launch vRIO from its **Start menu entry** (a direct exe launch runs without
identity), then drag vRIO to the top of *Settings → Personalization →
Dynamic Lighting → Background light control*.
- **Keyboard and Xbox (XInput) controller input** drive the same controls - **Keyboard and Xbox (XInput) controller input** drive the same controls
through a bindings file (`%APPDATA%\vRIO\bindings.txt`, created with through a bindings file (`%APPDATA%\vRIO\bindings.txt`, created with
commented defaults on first run — *Edit bindings…* opens it, *Reload commented defaults on first run — *Edit bindings…* opens it, *Reload
@@ -60,11 +71,10 @@ device behavior grounded in the **real v4.2 firmware dump**
- `ResetRequest` re-zeroes the targeted axis (or all). - `ResetRequest` re-zeroes the targeted axis (or all).
- A NAK re-sends the last event up to **4 times**, then gives up with a - A NAK re-sends the last event up to **4 times**, then gives up with a
RESTART byte — the real board's retry budget. RESTART byte — the real board's retry budget.
- Optional **v4.2 reply-wedge emulation**: after retry exhaustion (or the - Optional **v4.2 reply-wedge emulation** (in `VRio.Core`; the UI toggles
"Wedge analog now" button), analog requests are silently dropped — still were removed): after retry exhaustion, analog requests are silently
ACK'd, RX path alive — until a host `ResetRequest`, reproducing the dropped — still ACK'd, RX path alive — until a host `ResetRequest`,
latch-leak fault the firmware analysis documents. Use it to exercise reproducing the latch-leak fault the firmware analysis documents.
RIOJoy's 5-second no-analog recovery watchdog.
## Using it with RIOJoy on one PC ## Using it with RIOJoy on one PC
@@ -86,6 +96,7 @@ a null-modem cable work the same way.
|------|----------| |------|----------|
| `src/VRio.Core` | Protocol framing/builder/parser, the `VRioDevice` state machine, serial pump, panel layout data (class library) | | `src/VRio.Core` | Protocol framing/builder/parser, the `VRioDevice` state machine, serial pump, panel layout data (class library) |
| `src/VRio.App` | WinForms panel UI | | `src/VRio.App` | WinForms panel UI |
| `pkg` | Sparse-package manifest + registration script: grants VRio.App.exe the package identity Dynamic Lighting's background-control list requires |
| `tests/VRio.Core.Tests` | xUnit tests for the protocol + device engine | | `tests/VRio.Core.Tests` | xUnit tests for the protocol + device engine |
## Building ## Building
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Sparse package ("package with external location"): grants the plain win32
VRio.App.exe a package identity without changing how it is built or run.
vRIO needs identity so Windows Dynamic Lighting can list it under
Settings → Personalization → Dynamic Lighting → Background light control —
without it the keyboard lamp mirror only works while vRIO has focus.
Register (Developer Mode, unsigned) with the exe's folder as the external
location: see Register-vRIO.ps1 next to this file.
-->
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap3 uap10 rescap">
<Identity Name="VWE.vRIO"
ProcessorArchitecture="neutral"
Publisher="CN=VWE"
Version="1.0.0.0" />
<Properties>
<DisplayName>vRIO</DisplayName>
<PublisherDisplayName>VWE</PublisherDisplayName>
<Logo>Assets\logo150.png</Logo>
<uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26200.0" />
</Dependencies>
<Resources>
<Resource Language="en-us" />
</Resources>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="unvirtualizedResources" />
</Capabilities>
<Applications>
<Application Id="vRIO"
Executable="VRio.App.exe"
uap10:TrustLevel="mediumIL"
uap10:RuntimeBehavior="win32App">
<uap:VisualElements DisplayName="vRIO"
Description="Virtual RIO cockpit device emulator"
Square150x150Logo="Assets\logo150.png"
Square44x44Logo="Assets\logo44.png"
BackgroundColor="transparent" />
<Extensions>
<!-- Advertise as a lighting-controller app so Dynamic Lighting offers
vRIO in Settings' "Background light control" picker. -->
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.lighting"
Id="vrio"
DisplayName="vRIO"
Description="vRIO cockpit lamp mirror"
PublicFolder="Public" />
</uap3:Extension>
</Extensions>
</Application>
</Applications>
</Package>
Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

+1
View File
@@ -0,0 +1 @@
Public folder for the com.microsoft.windows.lighting app extension (required by the manifest schema).
+53
View File
@@ -0,0 +1,53 @@
<#
.SYNOPSIS
Grants VRio.App.exe package identity by registering the sparse package
(pkg\AppxManifest.xml) with the exe's folder as the external location.
Identity is what lets Windows Dynamic Lighting offer vRIO under
Settings > Personalization > Dynamic Lighting > "Background light control",
so the keyboard lamp mirror keeps working while the game has focus.
Unsigned registration requires Developer Mode
(Settings > System > For developers).
.PARAMETER ExePath
Folder containing VRio.App.exe. Defaults to the repo's Release output;
for a deployed zip, pass the extracted VRio folder.
.PARAMETER Unregister
Remove the registration instead.
#>
param(
[string]$ExePath = (Join-Path $PSScriptRoot '..\src\VRio.App\bin\Release\net48'),
[switch]$Unregister
)
$ErrorActionPreference = 'Stop'
$packageName = 'VWE.vRIO'
$existing = Get-AppxPackage -Name $packageName -ErrorAction SilentlyContinue
if ($existing) {
Write-Host "Removing existing registration $($existing.PackageFullName)..."
Remove-AppxPackage -Package $existing.PackageFullName
}
if ($Unregister) {
Write-Host 'Unregistered.'
return
}
$exe = Join-Path $ExePath 'VRio.App.exe'
if (-not (Test-Path $exe)) { throw "VRio.App.exe not found in '$ExePath'" }
$manifest = Join-Path $PSScriptRoot 'AppxManifest.xml'
Add-AppxPackage -Register $manifest -ExternalLocation (Resolve-Path $ExePath).Path
$family = (Get-AppxPackage -Name $packageName).PackageFamilyName
Write-Host "Registered $packageName with external location '$ExePath'."
Write-Host ''
Write-Host 'IMPORTANT: identity is granted through shell activation only. Launch vRIO'
Write-Host 'from the Start menu entry ("vRIO") or via:'
Write-Host " explorer shell:AppsFolder\$family!vRIO"
Write-Host 'Double-clicking VRio.App.exe runs it WITHOUT identity (lamp mirror then'
Write-Host 'works only while vRIO has focus).'
Write-Host ''
Write-Host 'Then enable the lamp mirror and pick vRIO under Settings > Personalization >'
Write-Host 'Dynamic Lighting > Background light control.'