Commit Graph
11 Commits
Author SHA1 Message Date
Dylan DeverillandClaude Fable 5 b80c7b830e Overhaul trackpad haptics: fix firmware lizard revert, click latch, tick gating
The core fix: the SC2026 firmware silently reverts to lizard mode (including
its autonomous click haptics) after a period without host feature reports,
which doubled up with software haptics as a crunchy burst. A keepalive now
re-asserts the lizard-off state every 2 seconds while game mode is active.

Haptics reliability and feel:
- Switch trackpad haptics from OUT_HAPTIC_PULSE (grip LRAs) to
  OUT_HAPTIC_COMMAND (trackpad LRAs) for localized feel
- Click haptic latch: press fires off the debounced firmware click bit,
  release only fires once contact area returns to idle, so force chatter
  and mid-hold easing cannot re-fire
- Movement ticks: distance-based with motion deadzone, post-release and
  first-touch grace windows, pressing/teleport gates (pause, not reset),
  idle decay, and a 50ms send rate limit so firmware waveforms never queue
  into a backlog

Handoff and mouse:
- EnableLizardMode now also sends LOAD_DEFAULT_SETTINGS so firmware mouse
  emulation resumes immediately on disable instead of waiting for the
  firmware revert timeout
- Trackpad mouse: carry sub-pixel movement remainders between frames and
  retune sensitivity (0.015 -> 0.01125)

Also: shared/exclusive HID reopen support, local-only HapticTester tool
(gitignored, conditional CMake target), installer version bump to 1.7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:50:38 -07:00
Dylan DeverillandClaude Sonnet 4.6 ddb91176fe Add distance-based movement haptics and click release haptic for trackpad
Replaces the per-frame movement buzz with a scroll-wheel-style tick that
fires once per 5000 raw units of travel. Adds a matching haptic on click
release to mirror Steam's press/release feel. Reseeds the movement
baseline on click release so stale position delta doesn't bleed into a
spurious movement tick on the same frame.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 00:02:08 -07:00
61ccd6548d Add DS4 gyro/touchpad forwarding, battery status, and enhanced haptics
PlayStation mode now emits DS4_REPORT_EX on every frame:
- Raw gyro and accelerometer forwarded from SC IMU (enabled via
  SETTING_IMU_MODE when PS4 mode is active; disabled on teardown)
- SC right/left trackpads mapped to DS4 touchpad contacts 1/2,
  with correct 12-bit XY packing and per-gesture contact IDs;
  pads claimed for mouse use are suppressed from the touchpad report
- Battery level and charge state forwarded from REPORT_BATTERY_STATUS
  (0x43) reports received in the read loop
- DS4 output moved from deprecated notification callback to a polling
  thread using vigem_target_ds4_await_output_report_timeout()

Enhanced haptics applied to both Xbox and PlayStation modes:
- Power curve (value^0.68) and cross-channel mixing (large motor
  bleeds into both haptic actuators; small motor weighted toward right)
- Short attack boost on rising motor edges to replicate ERM punch
- Trackpad touch and click fire one-shot haptic pulses via new
  OUT_HAPTIC_PULSE (0x81) and OUT_HAPTIC_COMMAND (0x82) output reports

Additional fixes:
- REPORT_SECONDARY = 0x43 renamed to REPORT_BATTERY_STATUS
- ViGEMClient upgraded from 1.16.18.0 to b66d02d snapshot which
  exposes DS4_REPORT_EX, vigem_target_ds4_update_ex(), and
  vigem_target_ds4_await_output_report_timeout()

Co-authored-by: david419kr <david419kr@users.noreply.github.com>

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 21:54:22 -07:00
Dylan DeverillandClaude Sonnet 4.6 a8a9e539ac Add Xbox / PlayStation controller platform selection
Introduces a ControllerPlatform enum (Xbox, PlayStation) and a full
DualShock 4 translation path alongside the existing Xbox 360 one.
Switching platforms live tears down and recreates the virtual device.
The selection persists in the registry and is exposed via a
"Controller Platform" submenu in the tray context menu.

DS4 translation maps face buttons to Cross/Circle/Square/Triangle,
encodes the D-pad as a HAT switch (with diagonal support), converts
signed 16-bit axes to uint8 with Y-axis inversion, and routes right
trackpad clicks to the DS4 touchpad button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 01:22:28 -07:00
Dylan Deverill 0ce2b57a36 Merge main into PR branch; wire rumble into multi-slot architecture
Conflicts resolved:
- ControllerManager.cpp: take main's slot-based EnableGameMode/
  DisableGameMode dispatch; wire the rumble callback into
  EnableGameModeSlot and add SetRumble(0,0) to DisableGameModeSlot
  so rumble stops cleanly before vc is torn down.
- VirtualController.h: keep both RumbleCallback/OnRumble (ours) and
  the new Update(backCfg, backMouseEnabled) signature (main's).

Co-Authored-By: Dylan Deverill <ddeverill@gmail.com>
2026-06-20 23:13:24 -07:00
Dylan Deverill f7c4f13c90 Address review feedback on rumble forwarding PR
- Drop Tick()/m_wantsGameMode auto-enable machinery (out of scope for
  this PR — belongs in a separate submission)
- Remove unused CMD_TRIGGER_RUMBLE constant
- Fix WriteOutputReport comment to accurately describe padding behaviour
- Fix CancelIo OVERLAPPED use-after-free: drain with GetOverlappedResult
  before the stack OVERLAPPED goes out of scope
- Strip redundant /wd4819 /wd4828 MSVC flags; /utf-8 already covers them
- Add comment to HeartbeatLoop explaining the 40 ms tick rationale

Co-Authored-By: Dylan Deverill <ddeverill@gmail.com>
2026-06-20 23:04:38 -07:00
Dylan DeverillandClaude Sonnet 4.6 5ca94176b3 Add back button remapping UI with registry persistence
Introduces a WebView2-based remap window (double-click tray icon or
'Remap Back Buttons...' context menu) that lets users assign any of
L4/L5/R4/R5 to a face button, bumper, trigger, d-pad direction, stick
click, Menu/View, mouse button, or 'none' (natural behavior).

- BackButtonConfig: new enum + struct; values stable as registry DWORDs
- RemapWindow: chromeless WebView2 window with a button picker and
  press-to-detect capture mode; settings persist across launches
- ControllerManager: StartButtonCapture/StopButtonCapture API with
  rising-edge HID detection for all mappable targets
- VirtualController: ApplyBackAction injects the mapped XInput button
  each frame; mouse-button actions are edge-detected in the read loop
- TrackpadMouse: back-button mouse-click handling decoupled from remap
- TrayApp: wires up the remap window, saves/loads all back button
  settings to HKCU\Software\SteamlessController

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 22:40:13 -07:00
Dylan DeverillandClaude Sonnet 4.6 9838bed701 Add support for multiple simultaneous Steam Controllers
Each connected controller now gets its own virtual Xbox 360 device via
ViGEmBus, mapping to separate XInput player slots (1, 2, 3...).

Key changes:
- SteamController: add EnumerateAll() to probe and return all live
  device paths across wired (0x1302) and dongle (0x1304) PIDs; add
  Open(path) overload to open a specific already-validated path.
- ControllerManager: replace single-controller state with a vector of
  Slot structs, each owning its own SteamController, VirtualController,
  TrackpadMouse, and read thread. SyncDevices() diffs live paths against
  current slots on every device-change event, adding new controllers and
  removing disconnected ones. Controllers hot-plugged while game mode is
  active are automatically brought into game mode.
- Bump installer version to 1.3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 20:46:48 -07:00
ntspaceowl bc3e9932b1 Auto-enable Steamless mode after startup reconnect 2026-05-30 22:00:00 +09:00
ntspaceowl a660f671b4 Add Steam Controller rumble forwarding 2026-05-28 00:22:50 +09:00
Dylan Deverill 589ed11e4a Initial release 2026-05-10 19:28:03 -07:00