Commit Graph
6 Commits
Author SHA1 Message Date
CydandClaude Opus 4.8 24cdf495e3 Phase 1: RioGamepad virtual HID driver (KMDF + VHF) + C# report packer
Author the custom virtual HID gamepad that replaces vJoy, and pin its wire
format on both sides. Builds clean to RioGamepad.sys against the EWDK
(KMDF 1.15 + VHF, x64, warnings-as-errors).

driver/RioGamepad/:
- ReportDescriptor.h: 6x16-bit axes (X,Y,Z,Rx,Ry,Rz), one 4-direction hat with
  null state, and 96 buttons — the legacy vJoy layout. 25-byte input report.
- Device.c/Driver.c: KMDF root-enumerated device that creates the VHF virtual HID
  device (VhfCreate in DeviceAdd, VhfStart in D0Entry, VhfDelete on cleanup) and
  exposes a device interface + IOCTL_RIO_SUBMIT_REPORT that forwards the caller's
  report bytes to VhfReadReportSubmit. Thin relay: no report logic in the kernel.
- Public.h: device-interface GUID, IOCTL, and the report byte layout shared with
  the C# client. RioGamepad.inf + build.cmd (EWDK build, catalog/sign disabled).

src/RioJoy.Core/Hid/RioHidReport.cs: packs AxisOutputs + hat + 96 buttons into
the exact 25-byte report (LE axes, hat nibble with 0x0F=centered, button bitmap).
13 new xUnit tests (136 total).

Remaining (deploy-side): test-sign + pnputil install + verify in joy.cpl, and
wire the real DeviceIoControl feeder sink (replacing NullJoystickSink). The
EWDK's in-build catalog task (DrvCat) can't load Microsoft.Kits.Logger on this
image, so the .cat is produced with inf2cat/signtool at install time instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:06:16 -05:00
CydandClaude Opus 4.8 1348040e1c Phase 5: tray app + profiles + runtime wiring
Wire the Core pieces into a runnable tray app with per-game profiles and the
three-state serial-yield auto-switch:

- Profiles/: RioProfile + AppConfig model; ConfigStore (System.Text.Json,
  round-tripped); RioIniImporter ports the legacy RIO.ini (button table, invert
  flags, plasma greeting); AutoSwitchResolver + AutoSwitchWatcher resolve the
  foreground executable into Yield (native game) / Activate (profile) / Idle, with
  native always winning and change-only notifications. IForegroundProcessProvider
  abstracts the OS.
- RioRuntime assembles a profile's live pipeline: serial ButtonPressed/Released +
  KeyPressed/Released → InputRouter (via RioAddress); AnalogReply → AxisCalibrator
  → the six joystick axes; RIO commands → calibration resets + version/check
  requests + lamp re-init. SerialLampSink sends lamp feedback over the link;
  NullJoystickSink is a placeholder until the Phase 1 HID feeder exists.
- RioJoy.Tray: NotifyIcon menu mirroring the legacy console menu (axis resets,
  version/status, raw-axes & poll-rate toggles, quit) + profile selection
  (auto vs. manual) + "start with Windows"; RioCoordinator owns the serial
  acquire/release tied to the watcher (native-game COM-port yield). OS adapters:
  ForegroundProcessProvider (Win32 foreground PID→exe) and AutoStartManager (HKCU
  Run key).
- tests: 18 new xUnit tests (123 total) for config round-trip, ini import,
  the three-state resolver + watcher, and RioRuntime end-to-end over the fake
  transport (button→joystick, keypad-offset→keyboard, analog→six axes).

The joystick output stays a no-op until the Phase 1 driver; on-cabinet
verification of the acquire/release lifecycle remains.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 15:36:58 -05:00
CydandClaude Opus 4.8 24a1b64519 Phase 4: axis calibration + plasma display (RioJoy.Core)
Port the analog calibration math and the plasma/VFD command set:

- Calibration/: AxisCalibrator ports UpdateThrottle/UpdatePadal/UpdateJoystick
  (riovjoy2.cpp#L1504+) — throttle deadzone + ratchet field, pedal deadzones,
  joystick X/Y auto-ranging from observed min/max, rudder mixing (enableZR), and
  the per-axis invert flags. Stateful (start positions, last outputs, observed
  extremes) like the legacy globals, with the RIOcmd axis resets. Final outputs
  clamp to the documented 0..32766 range (also guards a legacy compounding quirk).
  AxisOutputs carries the six values; IJoystickSink gains SetAxis(JoyAxis,value)
  so calibrated axes reach the HID feeder.
- Plasma/: PlasmaCommands builds the CPlasma ESC sequences (clear/cursor/font/
  attr/box draw+fill/text) + GetFontSize + the PlasmaPosText auto-fit/centering;
  PlasmaDisplay writes them over the secondary COM transport.
- tests: 21 new xUnit tests (105 total) for throttle proportional/saturation/
  invert, pedal ZR mix vs. direct, joystick centering/direction/invert/reset, the
  output clamp, and plasma byte sequences/font sizes/auto-fit positioning.

Hardware verification of axis feel + plasma output remains; the game-specific
PlasmaScoreDraw layout is deferred to profile content (Phase 5/7).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 15:24:45 -05:00
CydandClaude Opus 4.8 cc64d241c9 Phase 3: input mapping + output routing (RioJoy.Core.Mapping)
Port the iRIO decode and Press_V2/Release_V2 routing into testable C#:

- Mapping/: RioMapEntry decodes the 16-bit map word (lamp/mouse/hat/joy/extended/
  alt/ctrl/shift flags + value) and resolves the routing Kind by the legacy
  precedence (joy+hat+mouse => RIO command; none => keyboard; else joy>hat>mouse).
  RioAddress translates button/keypad events to table addresses (+0x50/+0x60
  keypad offsets); RioInputMap is the 112-entry per-profile table replacing the
  hard-coded iRIO[].
- InputRouter ports Press_V2/Release_V2: modifier press/release ordering,
  scancode keys, joystick buttons, POV hat, mouse move/click (deltas corrected
  per PROTOCOL.md), RIO-command dispatch, and lamp feedback (bright on press, dim
  on release; RIO commands carry none). InitializeLamps() dims all lamp entries.
- Output is split behind sink interfaces (IInputSink/IJoystickSink/ILampSink/
  IRioCommandSink) so routing is pure + unit-tested; Output/SendInputSink is the
  real SendInput keyboard/mouse adapter (scancode injection).
- tests: 30 new xUnit tests (84 total) for entry decode, address translation,
  and router routing/precedence/lamp/modifier ordering via a recording sink.

The joystick sink's real adapter (HID feeder -> RioGamepad via DeviceIoControl)
is blocked on the Phase 1 driver; routing already targets IJoystickSink.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 15:10:06 -05:00
CydandClaude Opus 4.8 b3cb764f4d Phase 2: serial + RIO protocol core (RioJoy.Core) with unit tests
Port the RIO wire protocol from legacy/riovjoy2.cpp into testable C#:

- Protocol/: command + length table, 7-bit checksum, packet builder, and a
  streaming receive-side framing state machine (PacketParser) that mirrors the
  legacy ReadCommBlock framing/resync (high-bit-mid-packet abort). Typed RIO->PC
  decodes: AnalogReport (14-bit sign-extend), VersionInfo, CheckStatus; lamp-state
  composition.
- Serial/: RioSerialLink drives an async receive loop with ACK/NAK reply policy
  (legacy force-accept vs. opt-in VerifyInboundChecksum), the analog poll timer,
  and the >5s reset-recovery watchdog. IRioTransport abstracts the COM port; the
  SerialPort-backed transport does 9600 8N1 + DTR reset pulse, and acquire/release
  is just create/dispose (foundation for native-game serial yield).
- tests/RioJoy.Core.Tests: 54 xUnit tests covering checksum, framing/resync,
  builder round-trips, analog sign-extension + sentinel rejection, lamp combos,
  and the read loop driven against an in-memory fake transport.

Hardware verification (version/check/analog against a cabinet) remains; it can't
be done off-device.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 13:04:03 -05:00
CydandClaude Opus 4.8 39a3dab1fc Phase 0: scaffold modern RIOJoy solution + plan
Modernization of the legacy vJoy-based RIO cockpit interface for Win10/11,
removing the vJoy dependency in favor of a custom VHF/UMDF HID driver,
rewritten in C#/.NET 8 as a background tray app with per-game profiles.

- Reorganize: legacy C++ -> legacy/, cockpit art -> docs/reference/
- RioJoy.sln: src/RioJoy.Core (lib) + src/RioJoy.Tray (tray app), net8.0-windows x64
- driver/ placeholder for the RioGamepad WDK driver
- docs/PLAN.md (7-phase plan; profiles + serial-yield model)
- docs/PROTOCOL.md (RIO wire format + iRIO input-map reference)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 12:43:01 -05:00