.changelog/3130.md
RumblePattern (shortTransient / mediumBurst / longSustained / rapidPulse)GCControllerHapticsManager — tracks burst timing, counts on/off pulses, and applies profile-derived motor scaling and sharpnesssetSystemProfile(_:) and setSystemProfile(forSystemIdentifier:) public API on GCControllerHapticsManagerresetSystemProfile() on GCControllerHapticsManager — resets to generic tuning when emulation ends so the next core isn't affected by the previous system's profilePVLibRetroRumbleHelper.setCurrentSystem(identifier:) — wires system profiles from libretro core loadPVCoreBridgeTestsPVLibRetroRumbleHelper.rumble() now uses duration: 10.0 (continuous until stopRumble()) instead of hardcoded 0.15s/0.08sGCControllerHapticsManager.stopRumble() classifies burst duration and picks UIImpactFeedbackGenerator style (.heavy/.medium/.light/.rigid) based on pattern; device-fallback haptic is emitted only on stop (not on start) to avoid double-firingProcessInfo.systemUptime instead of Date() to avoid misclassification from NTP or DST clock adjustmentsPVMupen64Plus-NXCore+Rumble) updated to use N64-specific motor params (lowFreq: 1.0, highFreq: 0.2, duration: 10.0) and registers N64 profile on emulation startstartEmulation and resets it on stopEmulation via MupenGameCore+Rumbleapple_gamecontroller_joypad_set_rumble in PVRetroArchCore+Controls.m now tries PVLibRetroRumbleHelper first (timing-based classifier + per-system profile scaling + tvOS support), falling back to the legacy PVMFIRumbleController path only if the helper is unavailable