Rumble strength in the Insert menu, and HD rumble to the heavy and light motors by frequency #1169
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1169
Loading…
Reference in a new issue
No description provided.
Delete branch "rumble-strength"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds a Rumble strength row to the Insert menu's Controls tab and sends the game's HD rumble to a controller's heavy and light motors by frequency instead of by band.
Rumble strength
Off, 25% to 150% in steps of 25, default 100%. It is saved in
hookshot_options.iniasrumble_strength, like the other rows, and reaches the host as option 9 (rx_option(9, 100)). It stops at its ends like Mouse sensitivity: Left at Off, Right (or Enter) at 150%, a click on either half of the value and the mouse wheel never wrap round from Off to the strongest setting or back. A hand-edited ini value is put on the row's steps when it is loaded (clamped to 0-150, then the nearest 25). Like the other controls rows, changing it does not set the quality preset back to Custom.host/pad_sdl.cscales the motors' 0..65535 values in the poll, just beforerumble_due, so a change applies at once: Off is a change to zero, and the poll sends the stop to a rumble that is already playing. Up to 100% each motor is scaled on its own (100% sends the values unchanged). Above 100%, when the stronger motor would pass 0xFFFF, both are scaled by the same factor so that the stronger just reaches the top, which keeps the heavy/light balance the frequency split chose (heavy 50000 / light 30000 at 150% gives 65535 / 39321, not 65535 / 45000).Frequency-weighted motors
A Switch HD rumble value is two bands, each with an amplitude and a frequency, and the bands overlap (low about 41-626 Hz, high about 82-1253 Hz, 160 Hz and 320 Hz by default). Until now the low band always drove the heavy motor and the high band the light one, with frequency only lowering the strength.
rumble_mapinhost/nn_hid.c(a pure function) keeps each band's strength exactly as before (rumble_motor, the same boost and per-band falloff), then splits it between the motors by its frequency (rumble_heavy_share): all heavy up to 160 Hz, all light from 200 Hz, and a crossfade on a log scale between them (log2(1.25), about a third of an octave), at constant power (square roots of the shares) so a band in the crossfade is not felt weaker. Each motor takes the stronger of the two bands' parts.At the defaults (160/320 Hz) and at what OoT sends in play (low about 100-130 Hz, high about 250-300 Hz, from
hid: vibrationlogs) every band lands on the same motor at the same strength as before, so nothing changes in feel today. The crossfade ends at 200 Hz to leave room below OoT's high band, and the default low band (160 Hz) is still all heavy. What changes: high-band content played below 200 Hz now reaches the heavy motor (all of it at 160 Hz and below), and low-band content played above 160 Hz reaches the light one.Left and right
Not changed. OoT sends the same values to both vibration devices (handles
00000003and00010003log the same numbers), and SDL exposes a gamepad's low and high motors, not left and right devices, so keeping the sides apart would not change what any pad plays. They are still merged by the stronger of the two.Tests
tests/test_rumble_mapping.pycompilesrumble_motor,rumble_heavy_share,rumble_mapandrumble_strengthfrom the sources and checks: at 100% the output matches the old mapping for a grid of amplitudes and default / OoT frequencies, Off gives 0, the strength grows with the percentage and the value, is unchanged per motor up to 100% and above it keeps the motors' ratio with the stronger at 0xFFFF, the share follows the documented curve (1 up to 160 Hz, 0 from 200 Hz, a half at their geometric middle), a band of either kind at 170-199 Hz is split as documented at constant power, OoT's high band range reaches only the light motor, a low-played high band reaches only the heavy motor and a high-played low band only the light one.tests/test_rumble_menu.pycompiles the menu'sset_row, the wheel loop,ini_keyand the ini snap fromgpu/vk/vk_menu.cppwith stubs and checks that the row stops at Off and 150% for the arrows, Enter and clicks and for several wheel notches at once, keeps the quality preset, is saved asrumble_strengthand that ini values are snapped to the steps. It also checks that option 9 isopts.rumbleinvk_replay.cpp's option table, that no id there is used twice or collides with the cheat options or items, and that onlyhost/pad_sdl.creads option 9. Both are picked up bytests/run_all.py.Not tested with a controller: how the crossfade feels on real motors.