Skip to content

hid: report vibration device info for startup handles and route iOS haptics on slot attach - #2070

Open
LNPANDY wants to merge 1 commit into
seedds:mainfrom
LNPANDY:fix/hid-vibration-startup-info-and-sessions
Open

LNPANDY wants to merge 1 commit into
seedds:mainfrom
LNPANDY:fix/hid-vibration-startup-info-and-sessions

Conversation

@LNPANDY

@LNPANDY LNPANDY commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Report valid LRA vibration device info for startup handles: Following PR Vibration handles before a controller's haptics are routed (a game that asks once at startup lost every value) #246 (f45d362), GetVibrationDeviceHandles returns non-empty handles at startup before a physical controller's haptics route is registered (dm_haptics_available() == 0). However, GetVibrationDeviceInfo still gated its response on vib_targets (which requires dm_haptics_available()). Games that query GetVibrationDeviceInfo right after GetVibrationDeviceHandles during startup received DeviceType_Unknown (0) and Position_None (0), permanently disabling controller vibration for the session. Split vib_players from vib_targets so GetVibrationDeviceInfo reports LinearResonantActuator (1) and Left/Right (1/2) whenever dm_haptics is initialized and the handle addresses a valid player slot, while SendVibrationValue / SendVibrationValues continue gating actuator output on vib_targets (dm_haptics_available()).
  • Intercept ForcedVibrationSession / PermitVibrationSession in hle_hid.c: Games such as Super Mario Party (010036B0034E4000, main+0x5d503c) call nn::hid::EndForcedVibrationSession() unconditionally during startup after InitializeVibrationDevice. Without HLE interception, execution falls into the SDK's nn::hid::detail::EndPermitVibrationSession(), which attempts to call IHidServer via an uninitialized IPC proxy and crashes with a null pointer dereference (sdk+0x3526bc). Intercept BeginForcedVibrationSession, EndForcedVibrationSession, and the detail/system BeginPermitVibrationSession, EndPermitVibrationSession, and PermitVibration functions with HLE_FORCE.
  • Bind iOS Core Haptics as soon as a controller takes a slot: On iOS (DmGamepad.m), pads_slotted, pads_merged, and DM_PAD_PRESS_TO_JOIN attached motion immediately when a controller claimed a player slot, but deferred dm_haptics_apple_controller until the end of read_pad (after the quit-prompt and controller-applet cp_poll early returns). Bind Core Haptics when the slot is assigned and use dm_gamepad_pads_read when the controller applet returns to idle so haptics routing is never skipped during the transition frame.

Testing

  • make -C dm/host/tests GAME=0100000000010000 build/t_hid build/t_haptics build/t_haptics_apple (t_hid: 210 checks, 0 failed; t_haptics & t_haptics_apple: pass)
  • Verified end-to-end in Super Mario Party (010036B0034E4000) on macOS with a Bluetooth controller: boots cleanly past shader precompilation at 60 FPS with active VibrationNode haptics output (~400 samples/sec).

…aptics on slot attach

GetVibrationDeviceHandles hands out vibration handles at startup before a physical controller's haptics route is registered, while GetVibrationDeviceInfo still gated its answer on vib_targets (which requires dm_haptics_available()). Games that query GetVibrationDeviceInfo right after GetVibrationDeviceHandles during startup received DeviceType_Unknown (0) and Position_None (0), permanently disabling vibration for the session. Split vib_players from vib_targets so GetVibrationDeviceInfo reports LinearResonantActuator (1) and Left/Right (1/2) whenever a haptics sink is initialized and the handle addresses a valid player slot.

Also intercept BeginForcedVibrationSession, EndForcedVibrationSession, and the detail/system PermitVibrationSession / PermitVibration functions in hle_hid.c so games like Super Mario Party (main+0x5d503c) do not enter the SDK's IHidServer proxy and dereference a null pointer on startup.

On iOS, DmGamepad.m attached motion when a controller took a player slot in pads_slotted, pads_merged, or DM_PAD_PRESS_TO_JOIN, but deferred dm_haptics_apple_controller until the end of read_pad after the quit-prompt and controller-applet (cp_poll) guards. Route Core Haptics as soon as the slot is taken and use dm_gamepad_pads_read when the controller prompt returns to idle.
@github-actions github-actions Bot added host The Horizon host: SVCs, services, threads, memory (dm/host) ios The iPhone and iPad app (dm/ios) labels Nov 9, 2026
LNPANDY added a commit to LNPANDY/NX2Apple that referenced this pull request Nov 9, 2026
LNPANDY added a commit to LNPANDY/NX2Apple that referenced this pull request Nov 9, 2026
…aptics on slot attach (#1072)

* hid: report vibration device info for startup handles and route iOS haptics on slot attach

* patches: intercept forced/permit vibration sessions in 0106 (seedds/nxnative#2070)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

host The Horizon host: SVCs, services, threads, memory (dm/host) ios The iPhone and iPad app (dm/ios)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant