mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
ee56f79087
Some titles compute vibration for every pad but only send it over SIO to a DualShock (R4 with a presented NeGcon). A trusted mod can now hand the runtime DualShock motor values per seat; the host pad gets the louder of that and the guest's SIO motors. Values lapse 8 VBlanks after the last call and are cleared at every session reset, so nothing can stick on. Opt-in: no title that does not call it changes. PSX_RUMBLE_TRACE now also logs headless. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
1.8 KiB
C
45 lines
1.8 KiB
C
/* psx_host_rumble.h - title-supplied host rumble (psx_mod_set_host_rumble).
|
|
*
|
|
* Some titles compute vibration for every pad but only send it over SIO to a
|
|
* DualShock (R4 with a presented NeGcon keeps running its vibration patterns
|
|
* and writes them nowhere useful). A trusted mod can hand the runtime the
|
|
* DualShock-equivalent motor values instead; the runtime forwards the louder
|
|
* of that and the guest's own SIO motors to the host pad. A value lapses
|
|
* PSX_HOST_RUMBLE_TTL VBlanks after the last call, so a mod that stops
|
|
* calling (menus, unloaded) can never leave a pad vibrating. Pure, so tests
|
|
* link it directly. Nothing changes for a title that never calls it. */
|
|
#ifndef PSX_HOST_RUMBLE_H
|
|
#define PSX_HOST_RUMBLE_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#define PSX_HOST_RUMBLE_TTL 8u
|
|
|
|
typedef struct PsxHostRumbleSlot {
|
|
uint8_t small; /* DualShock small motor: 0 off, nonzero on */
|
|
uint8_t large; /* DualShock large motor strength 0..255 */
|
|
uint8_t valid;
|
|
uint32_t stamp; /* VBlank of the last call */
|
|
} PsxHostRumbleSlot;
|
|
|
|
static inline void psx_host_rumble_set(PsxHostRumbleSlot *slot, uint32_t now,
|
|
uint32_t small, uint32_t large) {
|
|
if (!slot) return;
|
|
slot->small = small ? 1u : 0u;
|
|
slot->large = (uint8_t)(large > 255u ? 255u : large);
|
|
slot->valid = 1u;
|
|
slot->stamp = now;
|
|
}
|
|
|
|
/* Merge into the guest's SIO motor values (in/out). */
|
|
static inline void psx_host_rumble_merge(const PsxHostRumbleSlot *slot,
|
|
uint32_t now, uint8_t *small,
|
|
uint8_t *large) {
|
|
if (!slot || !slot->valid || !small || !large) return;
|
|
if ((uint32_t)(now - slot->stamp) >= PSX_HOST_RUMBLE_TTL) return;
|
|
if (slot->small && !*small) *small = 0xFFu;
|
|
if (slot->large > *large) *large = slot->large;
|
|
}
|
|
|
|
#endif /* PSX_HOST_RUMBLE_H */
|