foundation-sunshine Agent Skills & AI Rules

GitHub

Sunshine fork: an enhanced sunshine, a self-hosted game streaming host for Moonlight with HDR10/HDR Vivid, virtual displays, advanced audio, optimized...

RAW Rules
4 Discovered Rules • ~5,633 Estimated Tokens
Loading skill content...

sunshine-ds5-sidecar Documentation

tools/sunshine-ds5-sidecar/README.md plugin-manifest ~1,947 tokens
Raw
# Sunshine virtual device host

This optional Windows helper isolates Sunshine from the third-party
HIDMaestro runtime. The shipping executable remains
`Sunshine.Ds5Sidecar.exe` for component-upgrade compatibility, while the
process now uses a `VirtualDeviceHostServer` and `DeviceRegistry` internally.
It owns virtual devices and exposes the versioned `SDS5` named-pipe protocol.
The optional component package includes patched HIDMaestro Core and its notices.

Build the compatible Foundation Core patch and the sidecar:

```powershell
scripts/build-ds5-sidecar.ps1
```

The version 1.4.2 component ZIP includes patched `HIDMaestro.Core.dll`, its
licenses, and the complete .NET runtime. The main Sunshine package contains only
the pinned ZIP download manifest. The Control Panel automatically updates older
installed components when streaming is idle, using the existing administrator
helper, verified staging and whole-component rollback. Optional USB/IP transport
installation remains part of explicit install/repair, not automatic updates.
The sidecar uses normal .NET loading and requires the v1.12.0 runtime and
device-ownership, externally managed USB/IP and `FoundationDualSenseReports=host-clock-v1`
markers even for `--probe`. Sunshine validates the
installed component without replacing DLLs.
The upstream SDK API, assembly version and embedded resources are preserved; see
[`../hidmaestro-core-patch/README.md`](../hidmaestro-core-patch/README.md).

Read-only capability probe:

```powershell
dotnet Sunshine.Ds5Sidecar.dll --probe
```

Deterministic protocol ABI, microphone queue/runtime-contract, four-channel
layout, and channel-isolation checks (no elevation or virtual device required):

```powershell
dotnet Sunshine.Ds5Sidecar.dll --self-check
```

USB/IP installation and repair belong to the shared component manager. Device
creation only checks the approved driver and fails with a shared transport error
when it is missing or incompatible. The ZIP carries `component-compatibility.json`,
the same contract used by the GUI installer. The staged upgrade acceptance test
requires elevation and an idle host, and creates/releases two composite devices:

```powershell
Sunshine.Ds5Sidecar.exe --self-test transport --result transport-acceptance.json
```

The production process must be launched elevated and placed in the Sunshine
Job Object. The pipe accepts a single elevated client of the creating user;
non-elevated callers are rejected at connect time and dropped without
ending the sidecar.
Input, touch, motion and battery updates submit their combined state directly
on receipt under the session state lock. They do not use a thread-pool timer:
even a 1 ms timer can run at roughly 15.6 ms intervals on Windows and reduce
continuous input to about 64 Hz. The sidecar preserves the incoming update
cadence; it does not synthesize repeated reports to inflate polling-rate tests.
USB reports include rolling 8-bit and 32-bit sequence numbers, device time and
the USB-connected status. Device and motion timestamps use the same host QPC
epoch at 3 MHz. Button, touch and battery reports advance device time while
retaining the latest motion sample timestamp. Network receive time still stands
in for the client's physical sampling time; these metadata corrections have not
been verified to resolve Genshin's camera jumps.
The pipe reader reuses a receive buffer for headers and payloads, dispatching
complete frames as soon as they arrive. This removes separate header/body reads
and per-input payload allocations without adding a batching delay. Microphone
PCM retains its own copy because its queue outlives the receive buffer. The
device-free `--self-check` covers fragmented/packed frames, length validation,
EOF, cancellation and retained PCM ownership.
The reader uses one async state machine per pending frame. Standard axis
bindings are resolved once through the SDK at controller creation and update
the existing state dictionary in place. This avoids rebuilding the SDK's
stick/trigger lists and axis dictionary on every input update. `--self-check`
compares the cached mapping against the SDK's complete bundled profile catalog
and checks that steady-state axis updates allocate no managed objects.
The pinned .NET 10 runtime config sets
`System.Threading.ThreadPool.UnfairSemaphoreSpinLimit` to zero for this process.
Pool workers wait for a signal instead of spinning between short input bursts.
This adds no report-rate limiter or timer. Because it trades spinning for OS
wakeups, CPU and report-interval tests should be repeated when changing the
bundled runtime or enabling additional concurrent input/audio workloads.
Disconnecting the owning pipe disposes every device created by
that connection. Standard `dualsense` uses UMDF2; `dualsense-composite`
enables the USB composite HID/audio profile and authored haptics PCM.
HID-only attaches use `dualsense` with the native 273-byte descriptor and
Game Pad usage (0x05). HIDMaestro v1.12.0 no longer writes the incorrect global
GameInput mapping for JSON profiles and removes exact legacy SDK tables
(issue #1056), so the former Joystick usage override is unnecessary. Input
reports retain `alwaysArmed` for touch and motion data. Windows decides how
to expose the device; native Game Pad usage does not guarantee a WGI Gamepad.
The optional Genshin compatibility attach flag derives a third profile from
`dualsense-composite` at runtime. It preserves the Sony VID/PID, descriptors,
and four-channel layout while changing only the USB product string from
`DualSense Wireless Controller` to the launch-model `Wireless Controller`.
The runtime profile starts the USB speaker control unmuted at its declared
maximum and commits the active endpoint's 4-channel, available-speaker and
full-range masks as quadraphonic (`0x33`) through Core Audio. This matches the
three settings applied by completing Windows' speaker setup wizard as required
by Genshin.
Endpoint enumeration uses the Windows SDK's `IMMDeviceCollection` IID, and
the Windows 10+ policy property calls include the effects-store argument.
`NativeMethods.txt` requests the public audio COM interfaces, structures and
property keys from Microsoft CsWin32. The generator and SDK metadata are pinned
in `packages.lock.json`; publishing restores in locked mode and adds no runtime
library dependency. `CoreAudio` shares endpoint enumeration and reference cleanup
between the default-device monitor and WASAPI probe. Only the undocumented
Windows 10+ policy interface remains hand-declared, inside `AudioPolicyConfig`.
Core Audio references are released per acquisition so configuration readback
cannot invalidate the concurrent default-device monitor. Endpoint detection
also recognizes HIDMaestro's synthetic USB serial under the official USB/IP
host controller, without requiring runtime ownership stamping.
The transport acceptance test creates both the normal composite profile and
the Genshin compatibility profile. It reads back the endpoint format and both
speaker masks for the endpoint created by that attach before passing. It waits
for that endpoint to become inactive before the next round, so a stale endpoint
cannot satisfy another mode's check.
The sidecar advertises this support through a protocol capability bit so an
older runtime cannot silently accept an ineffective setting.
The v1 wire contract reserves capability bits and message numbers for the
virtual microphone. Normal startup intentionally does not advertise them;
only the explicit development prototype can enable those capabilities.

The Phase 2 composite-profile microphone path is development-only and requires
both the exact HIDMaestro 1.12.0.0 runtime and an explicit opt-in. Its elevated
attach/PCM/flush/destroy smoke test is:

```powershell
dotnet Sunshine.Ds5Sidecar.dll --self-test microphone-prototype
```

For an end-to-end developer check, `microphone-capture` snapshots the active
capture endpoints, creates the prototype, opens only its newly added endpoint
through WASAPI, streams a 440 Hz signal for five seconds, and requires observed
host streaming, zero submit errors, captured frames, and non-zero PCM before it
passes:

```powershell
dotnet Sunshine.Ds5Sidecar.dll --self-test microphone-capture
```

This temporary path also enumerates the composite profile's HID and render
interfaces; it is not the final capture-only virtual microphone product.
The composite session monitors every Windows default render and capture role.
If Windows selects a HIDMaestro-backed virtual DualSense endpoint as a default,
the helper reports the policy violation and exits; Sunshine then performs its
single recovery attach in HID-only DS5 mode. This read-only fail-closed guard
avoids undocumented audio-policy writes and never changes a user's defaults.

The trigger effects and lightbar of an output report a game writes to the
virtual pad are read the way the hardware reads them: only when the report's
validity byte for that field is set. A game leaves the fields it is not
programming zero, and reading those zeros as an instruction would cancel an
effect the game just armed and strobe a held color. A validity byte the decoder
does not expose governs nothing, so the fields it would gate are read
unconditionally. The motor bytes are read unconditionally as well, because their
zeros can cancel a rumble that is still playing while gating them can drop a
stop that has no other way to arrive.