From 108e840324f06a01a2791ae25e498f802d09cf03 Mon Sep 17 00:00:00 2001 From: "Christoph \"baka0815\" Schwerdtfeger" Date: Wed, 16 Jan 2019 20:48:32 +0100 Subject: [PATCH] SDL: rumble support This adds support for rumble to the SDL backend. It does not however attach a purupuru/rumble pack --- core/linux-dist/main.cpp | 33 ++++++++------- core/sdl/sdl.cpp | 87 ++++++++++++++++++++++++++++++++++++---- core/sdl/sdl.h | 1 + 3 files changed, 100 insertions(+), 21 deletions(-) diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp index 5394e207f..b8d30ce8b 100644 --- a/core/linux-dist/main.cpp +++ b/core/linux-dist/main.cpp @@ -144,25 +144,30 @@ void UpdateInputState(u32 port) void UpdateVibration(u32 port, u32 value) { + u8 POW_POS = (value >> 8) & 0x3; + u8 POW_NEG = (value >> 12) & 0x3; + u8 FREQ = (value >> 16) & 0xFF; + + double pow = (POW_POS + POW_NEG) / 7.0; + double pow_l = pow * (0x3B - FREQ) / 17.0; + double pow_r = pow * (FREQ - 0x07) / 15.0; + + if (pow_l > 1.0) pow_l = 1.0; + if (pow_r > 1.0) pow_r = 1.0; + + u16 pow_strong = (u16)(65535 * pow_l); + u16 pow_weak = (u16)(65535 * pow_r); + #if defined(USE_EVDEV) - u8 POW_POS = (value >> 8) & 0x3; - u8 POW_NEG = (value >> 12) & 0x3; - u8 FREQ = (value >> 16) & 0xFF; - - double pow = (POW_POS + POW_NEG) / 7.0; - double pow_l = pow * (0x3B - FREQ) / 17.0; - double pow_r = pow * (FREQ - 0x07) / 15.0; - - if (pow_l > 1.0) pow_l = 1.0; - if (pow_r > 1.0) pow_r = 1.0; - - u16 pow_strong = (u16)(65535 * pow_l); - u16 pow_weak = (u16)(65535 * pow_r); - input_evdev_rumble(port, pow_strong, pow_weak); #endif + + #if defined(USE_SDL) + input_sdl_rumble(port, pow_strong, pow_weak); + #endif } + void os_DoEvents() { #if defined(SUPPORT_X11) diff --git a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp index c61fc1dad..15ace1b5f 100644 --- a/core/sdl/sdl.cpp +++ b/core/sdl/sdl.cpp @@ -54,27 +54,39 @@ const u32* sdl_map_axis = sdl_map_axis_usb; u32 JSensitivity[256]; // To have less sensitive value on nubs #endif +bool haptic_init = false; +static SDL_Haptic* haptic = NULL; +int effect_id = 0; + void input_sdl_init() { - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) + u32 subsystem_init = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC); + + if ((subsystem_init & SDL_INIT_JOYSTICK) == 0) { if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) { - die("error initializing SDL Joystick subsystem"); + die("SDL: error initializing Joystick subsystem"); } } + + // Trying to initialize haptic subsystem (rumble) + if ((subsystem_init & SDL_INIT_HAPTIC) == 0) + { + haptic_init = (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0); + } + // Open joystick device int numjoys = SDL_NumJoysticks(); - printf("Number of Joysticks found = %i\n", numjoys); + printf("SDL: Number of Joysticks found = %i\n", numjoys); if (numjoys > 0) { JoySDL = SDL_JoystickOpen(0); } - printf("Joystick opened\n"); - if (JoySDL) { + printf("SDL: Joystick opened\n"); int AxisCount,ButtonCount; const char* Name; @@ -87,14 +99,21 @@ void input_sdl_init() Name = SDL_JoystickName(JoySDL); printf("SDL: Found '%s' joystick with %d axes and %d buttons\n", Name, AxisCount, ButtonCount); + if (haptic_init) + { + if (SDL_JoystickIsHaptic(JoySDL) == SDL_TRUE) + printf("SDL: Rumble support available\n"); + else + printf("SDL: Rumble support NOT available\n"); + } if (Name != NULL && strcmp(Name,"Microsoft X-Box 360 pad")==0) { sdl_map_btn = sdl_map_btn_xbox360; sdl_map_axis = sdl_map_axis_xbox360; - printf("Using Xbox 360 map\n"); + printf("SDL: Using Xbox 360 map\n"); } - + // Create the first controller with two VMUs // (only when evdev is not available as it's already configured via evdev then) // TODO: make this configurable @@ -402,6 +421,60 @@ void input_sdl_handle(u32 port) } } +void input_sdl_rumble(u32 port, u16 pow_strong, u16 pow_weak) +{ + // No haptic supported, no need for rumble + if (!haptic_init) + return; + + // If already open, close it to stop the current rumble effect + if (haptic) + { + if (effect_id != 0) + { + SDL_HapticStopEffect( haptic, effect_id ); + SDL_HapticDestroyEffect( haptic, effect_id ); + effect_id = 0; + } + + SDL_HapticClose(haptic); + haptic = NULL; + } + + // Open the device + if (!haptic) + haptic = SDL_HapticOpenFromJoystick( JoySDL ); + + if (!haptic) + return; + + // Check if the haptic supports the left/right effect + if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_LEFTRIGHT) == 0) + { + SDL_HapticClose(haptic); + haptic = NULL; + + // Disable haptic/rumble + haptic_init = false; + + return; + } + + // Create the effect + SDL_HapticEffect effect; + SDL_memset(&effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default + effect.type = SDL_HAPTIC_LEFTRIGHT; + effect.leftright.large_magnitude = pow_strong; + effect.leftright.small_magnitude = pow_weak; + effect.leftright.length = 0; + + // Upload the effect + effect_id = SDL_HapticNewEffect(haptic, &effect); + + // Let's play the effect + SDL_HapticRunEffect(haptic, effect_id, 1); +} + void sdl_window_set_text(const char* text) { #ifdef TARGET_PANDORA diff --git a/core/sdl/sdl.h b/core/sdl/sdl.h index ce1550718..d85095e59 100644 --- a/core/sdl/sdl.h +++ b/core/sdl/sdl.h @@ -3,5 +3,6 @@ extern void input_sdl_init(); extern void input_sdl_handle(u32 port); +extern void input_sdl_rumble(u32 port, u16 pow_strong, u16 pow_weak); extern void sdl_window_create(); extern void sdl_window_set_text(const char* text);