diff --git a/Makefile b/Makefile index 9d56346158..2186fedcef 100644 --- a/Makefile +++ b/Makefile @@ -214,8 +214,8 @@ ifeq ($(HAVE_SDL), 1) endif ifeq ($(HAVE_SDL2), 1) - OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl2_joypad.o audio/sdl_audio.o - JOYCONFIG_OBJ += input/sdl2_joypad.o + OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o + JOYCONFIG_OBJ += input/sdl_joypad.o JOYCONFIG_LIBS += $(SDL2_LIBS) DEFINES += $(SDL2_CFLAGS) $(BSD_LOCAL_INC) LIBS += $(SDL2_LIBS) diff --git a/Makefile.win b/Makefile.win index 73e84bb8b9..7607c62391 100644 --- a/Makefile.win +++ b/Makefile.win @@ -132,8 +132,8 @@ ifeq ($(HAVE_MENU_COMMON), 1) endif ifeq ($(HAVE_SDL2), 1) - OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl2_joypad.o audio/sdl_audio.o - JOBJ += input/sdl2_joypad.o + OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o + JOBJ += input/sdl_joypad.o LIBS += -lSDL2 JLIBS += -lSDL2 DEFINES += -ISDL2 -DHAVE_SDL2 diff --git a/input/input_common.c b/input/input_common.c index 117e5b6e5d..b975862209 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -74,12 +74,9 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifdef ANDROID &android_joypad, #endif -#ifdef HAVE_SDL +#if defined(HAVE_SDL) || defined(HAVE_SDL2) &sdl_joypad, #endif -#ifdef HAVE_SDL2 - &sdl2_joypad, -#endif #ifdef __MACH__ &apple_joypad, #endif diff --git a/input/input_common.h b/input/input_common.h index 407aa8918b..07aebe1fc3 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -104,7 +104,6 @@ extern const rarch_joypad_driver_t linuxraw_joypad; extern const rarch_joypad_driver_t udev_joypad; extern const rarch_joypad_driver_t winxinput_joypad; // Named as such to avoid confusion with xb1/360 port code extern const rarch_joypad_driver_t sdl_joypad; -extern const rarch_joypad_driver_t sdl2_joypad; extern const rarch_joypad_driver_t ps3_joypad; extern const rarch_joypad_driver_t psp_joypad; extern const rarch_joypad_driver_t xdk_joypad; diff --git a/input/sdl2_joypad.c b/input/sdl2_joypad.c deleted file mode 100644 index f934abccdc..0000000000 --- a/input/sdl2_joypad.c +++ /dev/null @@ -1,315 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include "input_common.h" -#include "SDL.h" -#include "../general.h" - -typedef struct _sdl2_joypad -{ - SDL_Joystick *joypad; - SDL_Haptic *haptic; - int rumble_effect; // -1 = not initialized, -2 = error/unsupported - unsigned num_axes; - unsigned num_buttons; - unsigned num_hats; - unsigned num_balls; -} sdl2_joypad_t; - -static sdl2_joypad_t g_pads[MAX_PLAYERS]; -static bool has_haptic; - -static void sdl2_joypad_destroy(void) -{ - unsigned i; - for (i = 0; i < MAX_PLAYERS; i++) - { - - } - - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - memset(g_pads, 0, sizeof(g_pads)); -} - -static void sdl2_joypad_connect(int id) -{ - sdl2_joypad_t *pad = &g_pads[id]; - pad->joypad = SDL_JoystickOpen(id); - if (!pad->joypad) - { - RARCH_ERR("[SDL]: Couldn't open SDL joystick #%u.\n", id); - return; - } - - RARCH_LOG("[SDL]: Joypad #%u connected: %s.\n", - id, SDL_JoystickName(pad->joypad)); - - pad->haptic = has_haptic ? SDL_HapticOpenFromJoystick(pad->joypad) : NULL; - - if (has_haptic && !pad->haptic) - RARCH_WARN("[SDL]: Couldn't open haptic device of the joypad #%u: %s\n", - id, SDL_GetError()); - - pad->rumble_effect = -1; - - if (pad->haptic) - { - SDL_HapticEffect efx; - efx.type = SDL_HAPTIC_LEFTRIGHT; - efx.leftright.type = SDL_HAPTIC_LEFTRIGHT; - efx.leftright.large_magnitude = efx.leftright.small_magnitude = 0x4000; - efx.leftright.length = 5000; - - if (SDL_HapticEffectSupported(pad->haptic, &efx) == SDL_FALSE) - { - pad->rumble_effect = -2; - RARCH_WARN("[SDL]: Joypad #%u does not support rumble.\n", id); - } - } - - pad->num_axes = SDL_JoystickNumAxes(pad->joypad); - pad->num_buttons = SDL_JoystickNumButtons(pad->joypad); - pad->num_hats = SDL_JoystickNumHats(pad->joypad); - pad->num_balls = SDL_JoystickNumBalls(pad->joypad); - - RARCH_LOG("[SDL]: Joypad #%u has: %u axes, %u buttons, %u hats and %u trackballs.\n", - id, pad->num_axes, pad->num_buttons, pad->num_hats, pad->num_balls); -} - -static void sdl2_joypad_disconnect(int id) -{ - RARCH_LOG("[SDL]: Joypad #%u disconnected.\n", id); - - if (g_pads[id].haptic) - SDL_HapticClose(g_pads[id].haptic); - - if (g_pads[id].joypad) - SDL_JoystickClose(g_pads[id].joypad); - - memset(&g_pads[id], 0, sizeof(g_pads[id])); -} - -static bool sdl2_joypad_init(void) -{ - unsigned i; - - has_haptic = false; - if (SDL_Init(SDL_INIT_JOYSTICK) < 0) - { - RARCH_WARN("[SDL]: Failed to initialize joystick interface: %s\n", - SDL_GetError()); - return false; - } - - SDL_JoystickEventState(SDL_ENABLE); - - // TODO: Add SDL_GameController support. -// if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) -// RARCH_LOG("[SDL]: Failed to initialize game controller interface: %s\n", -// SDL_GetError()); - - if (SDL_Init(SDL_INIT_HAPTIC) < 0) - RARCH_WARN("[SDL]: Failed to initialize haptic device support: %s\n", - SDL_GetError()); - else - has_haptic = true; - - unsigned num_sticks = SDL_NumJoysticks(); - if (num_sticks > MAX_PLAYERS) - num_sticks = MAX_PLAYERS; - - for (i = 0; i < num_sticks; i++) - { - sdl2_joypad_connect(i); - } - - num_sticks = 0; - for (i = 0; i < MAX_PLAYERS; i++) - { - if (g_pads[i].joypad) - num_sticks++; - } - - if (num_sticks == 0) - goto error; - - return true; - -error: - sdl2_joypad_destroy(); - return false; -} - -static bool sdl2_joypad_button(unsigned port, uint16_t joykey) -{ - if (joykey == NO_BTN) - return false; - - const sdl2_joypad_t *pad = &g_pads[port]; - if (!pad->joypad) - return false; - - // Check hat. - if (GET_HAT_DIR(joykey)) - { - uint16_t hat = GET_HAT(joykey); - if (hat >= pad->num_hats) - return false; - - Uint8 dir = SDL_JoystickGetHat(pad->joypad, hat); - switch (GET_HAT_DIR(joykey)) - { - case HAT_UP_MASK: - return dir & SDL_HAT_UP; - case HAT_DOWN_MASK: - return dir & SDL_HAT_DOWN; - case HAT_LEFT_MASK: - return dir & SDL_HAT_LEFT; - case HAT_RIGHT_MASK: - return dir & SDL_HAT_RIGHT; - default: - return false; - } - } - else // Check the button - { - if (joykey < pad->num_buttons && SDL_JoystickGetButton(pad->joypad, joykey)) - return true; - - return false; - } -} - -static int16_t sdl2_joypad_axis(unsigned port, uint32_t joyaxis) -{ - if (joyaxis == AXIS_NONE) - return 0; - - const sdl2_joypad_t *pad = &g_pads[port]; - if (!pad->joypad) - return false; - - Sint16 val = 0; - if (AXIS_NEG_GET(joyaxis) < pad->num_axes) - { - val = SDL_JoystickGetAxis(pad->joypad, AXIS_NEG_GET(joyaxis)); - - if (val > 0) - val = 0; - else if (val < -0x7fff) // -0x8000 can cause trouble if we later abs() it. - val = -0x7fff; - } - else if (AXIS_POS_GET(joyaxis) < pad->num_axes) - { - val = SDL_JoystickGetAxis(pad->joypad, AXIS_POS_GET(joyaxis)); - - if (val < 0) - val = 0; - } - - return val; -} - -static void sdl2_joypad_poll(void) -{ - SDL_Event event; - - SDL_PumpEvents(); - while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) - { - if (event.type == SDL_JOYDEVICEADDED) - { - sdl2_joypad_connect(event.jdevice.which); - } - else if (event.type == SDL_JOYDEVICEREMOVED) - { - sdl2_joypad_disconnect(event.jdevice.which); - } - } -} - -static bool sdl2_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength) -{ - SDL_HapticEffect efx; - memset(&efx, 0, sizeof(efx)); - - sdl2_joypad_t *joypad = &g_pads[pad]; - - if (!joypad->joypad || !joypad->haptic) - return false; - - efx.type = SDL_HAPTIC_LEFTRIGHT; - efx.leftright.type = SDL_HAPTIC_LEFTRIGHT; - efx.leftright.length = 5000; - - switch (effect) - { - case RETRO_RUMBLE_STRONG: efx.leftright.large_magnitude = strength; break; - case RETRO_RUMBLE_WEAK: efx.leftright.small_magnitude = strength; break; - default: return false; - } - - if (joypad->rumble_effect == -1) - { - joypad->rumble_effect = SDL_HapticNewEffect(g_pads[pad].haptic, &efx); - if (joypad->rumble_effect < 0) - { - RARCH_WARN("[SDL]: Failed to create rumble effect for joypad %u: %s\n", - pad, SDL_GetError()); - joypad->rumble_effect = -2; - return false; - } - } - else if (joypad->rumble_effect >= 0) - SDL_HapticUpdateEffect(joypad->haptic, joypad->rumble_effect, &efx); - - if (joypad->rumble_effect < 0) - return false; - - if (SDL_HapticRunEffect(joypad->haptic, joypad->rumble_effect, 1) < 0) - { - RARCH_WARN("[SDL]: Failed to set rumble effect on joypad %u: %s\n", - pad, SDL_GetError()); - return false; - } - - return true; -} - -static bool sdl2_joypad_query_pad(unsigned pad) -{ - return pad < MAX_PLAYERS && g_pads[pad].joypad; -} - -static const char *sdl2_joypad_name(unsigned pad) -{ - if (pad >= MAX_PLAYERS) - return NULL; - - return SDL_JoystickName(g_pads[pad].joypad); -} - -const rarch_joypad_driver_t sdl2_joypad = { - sdl2_joypad_init, - sdl2_joypad_query_pad, - sdl2_joypad_destroy, - sdl2_joypad_button, - sdl2_joypad_axis, - sdl2_joypad_poll, - sdl2_joypad_set_rumble, - sdl2_joypad_name, - "sdl2", -}; - diff --git a/input/sdl_joypad.c b/input/sdl_joypad.c index 89a7480e42..a20de56641 100644 --- a/input/sdl_joypad.c +++ b/input/sdl_joypad.c @@ -17,24 +17,105 @@ #include "SDL.h" #include "../general.h" -struct sdl_joypad +typedef struct _sdl_joypad { SDL_Joystick *joypad; +#ifdef HAVE_SDL2 + SDL_Haptic *haptic; + int rumble_effect; // -1 = not initialized, -2 = error/unsupported +#endif unsigned num_axes; unsigned num_buttons; unsigned num_hats; -}; +#ifdef HAVE_SDL2 + unsigned num_balls; +#endif +} sdl_joypad_t; -static struct sdl_joypad g_pads[MAX_PLAYERS]; +static sdl_joypad_t g_pads[MAX_PLAYERS]; +#ifdef HAVE_SDL2 +static bool has_haptic; +#endif + +static void sdl_joypad_connect(int id) +{ + sdl_joypad_t *pad = &g_pads[id]; + pad->joypad = SDL_JoystickOpen(id); + if (!pad->joypad) + { + RARCH_ERR("[SDL]: Couldn't open SDL joystick #%u.\n", id); + return; + } + + RARCH_LOG("[SDL]: Joypad #%u connected: %s.\n", +#ifdef HAVE_SDL2 + id, SDL_JoystickName(pad->joypad)); +#else + id, SDL_JoystickName(id)); +#endif + + +#ifdef HAVE_SDL2 + pad->haptic = has_haptic ? SDL_HapticOpenFromJoystick(pad->joypad) : NULL; + + if (has_haptic && !pad->haptic) + RARCH_WARN("[SDL]: Couldn't open haptic device of the joypad #%u: %s\n", + id, SDL_GetError()); + + pad->rumble_effect = -1; + + if (pad->haptic) + { + SDL_HapticEffect efx; + efx.type = SDL_HAPTIC_LEFTRIGHT; + efx.leftright.type = SDL_HAPTIC_LEFTRIGHT; + efx.leftright.large_magnitude = efx.leftright.small_magnitude = 0x4000; + efx.leftright.length = 5000; + + if (SDL_HapticEffectSupported(pad->haptic, &efx) == SDL_FALSE) + { + pad->rumble_effect = -2; + RARCH_WARN("[SDL]: Joypad #%u does not support rumble.\n", id); + } + } +#endif + + pad->num_axes = SDL_JoystickNumAxes(pad->joypad); + pad->num_buttons = SDL_JoystickNumButtons(pad->joypad); + pad->num_hats = SDL_JoystickNumHats(pad->joypad); + +#ifdef HAVE_SDL2 + pad->num_balls = SDL_JoystickNumBalls(pad->joypad); + + RARCH_LOG("[SDL]: Joypad #%u has: %u axes, %u buttons, %u hats and %u trackballs.\n", + id, pad->num_axes, pad->num_buttons, pad->num_hats, pad->num_balls); +#else + RARCH_LOG("[SDL]: Joypad #%u has: %u axes, %u buttons, %u hats.\n", + id, pad->num_axes, pad->num_buttons, pad->num_hats); +#endif +} + +static void sdl_joypad_disconnect(int id) +{ +#ifdef HAVE_SDL2 + if (g_pads[id].haptic) + SDL_HapticClose(g_pads[id].haptic); +#endif + + if (g_pads[id].joypad) + { + SDL_JoystickClose(g_pads[id].joypad); + RARCH_LOG("[SDL]: Joypad #%u disconnected.\n", id); + } + + memset(&g_pads[id], 0, sizeof(g_pads[id])); +} static void sdl_joypad_destroy(void) { unsigned i; for (i = 0; i < MAX_PLAYERS; i++) - { - if (g_pads[i].joypad) - SDL_JoystickClose(g_pads[i].joypad); - } + sdl_joypad_disconnect(i); SDL_QuitSubSystem(SDL_INIT_JOYSTICK); memset(g_pads, 0, sizeof(g_pads)); @@ -46,29 +127,18 @@ static bool sdl_joypad_init(void) if (SDL_Init(SDL_INIT_JOYSTICK) < 0) return false; +#if 0 // TODO: Add SDL_GameController support. + if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) + RARCH_LOG("[SDL]: Failed to initialize game controller interface: %s\n", + SDL_GetError()); +#endif + unsigned num_sticks = SDL_NumJoysticks(); if (num_sticks > MAX_PLAYERS) num_sticks = MAX_PLAYERS; for (i = 0; i < num_sticks; i++) - { - struct sdl_joypad *pad = &g_pads[i]; - pad->joypad = SDL_JoystickOpen(i); - if (!pad->joypad) - { - RARCH_ERR("Couldn't open SDL joystick #%u.\n", i); - goto error; - } - - RARCH_LOG("Opened Joystick: %s (#%u).\n", - SDL_JoystickName(i), i); - - pad->num_axes = SDL_JoystickNumAxes(pad->joypad); - pad->num_buttons = SDL_JoystickNumButtons(pad->joypad); - pad->num_hats = SDL_JoystickNumHats(pad->joypad); - RARCH_LOG("Joypad has: %u axes, %u buttons, %u hats.\n", - pad->num_axes, pad->num_buttons, pad->num_hats); - } + sdl_joypad_connect(i); return true; @@ -82,7 +152,7 @@ static bool sdl_joypad_button(unsigned port, uint16_t joykey) if (joykey == NO_BTN) return false; - const struct sdl_joypad *pad = &g_pads[port]; + const sdl_joypad_t *pad = &g_pads[port]; if (!pad->joypad) return false; @@ -122,7 +192,7 @@ static int16_t sdl_joypad_axis(unsigned port, uint32_t joyaxis) if (joyaxis == AXIS_NONE) return 0; - const struct sdl_joypad *pad = &g_pads[port]; + const sdl_joypad_t *pad = &g_pads[port]; if (!pad->joypad) return false; @@ -149,9 +219,76 @@ static int16_t sdl_joypad_axis(unsigned port, uint32_t joyaxis) static void sdl_joypad_poll(void) { +#ifdef HAVE_SDL2 + SDL_Event event; + + SDL_PumpEvents(); + while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) + { + if (event.type == SDL_JOYDEVICEADDED) + { + sdl_joypad_connect(event.jdevice.which); + } + else if (event.type == SDL_JOYDEVICEREMOVED) + { + sdl_joypad_disconnect(event.jdevice.which); + } + } +#else SDL_JoystickUpdate(); +#endif } +#ifdef HAVE_SDL2 +static bool sdl_joypad_set_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength) +{ + SDL_HapticEffect efx; + memset(&efx, 0, sizeof(efx)); + + sdl_joypad_t *joypad = &g_pads[pad]; + + if (!joypad->joypad || !joypad->haptic) + return false; + + efx.type = SDL_HAPTIC_LEFTRIGHT; + efx.leftright.type = SDL_HAPTIC_LEFTRIGHT; + efx.leftright.length = 5000; + + switch (effect) + { + case RETRO_RUMBLE_STRONG: efx.leftright.large_magnitude = strength; break; + case RETRO_RUMBLE_WEAK: efx.leftright.small_magnitude = strength; break; + default: return false; + } + + if (joypad->rumble_effect == -1) + { + joypad->rumble_effect = SDL_HapticNewEffect(g_pads[pad].haptic, &efx); + if (joypad->rumble_effect < 0) + { + RARCH_WARN("[SDL]: Failed to create rumble effect for joypad %u: %s\n", + pad, SDL_GetError()); + joypad->rumble_effect = -2; + return false; + } + } + else if (joypad->rumble_effect >= 0) + SDL_HapticUpdateEffect(joypad->haptic, joypad->rumble_effect, &efx); + + if (joypad->rumble_effect < 0) + return false; + + if (SDL_HapticRunEffect(joypad->haptic, joypad->rumble_effect, 1) < 0) + { + RARCH_WARN("[SDL]: Failed to set rumble effect on joypad %u: %s\n", + pad, SDL_GetError()); + return false; + } + + return true; +} +#endif + static bool sdl_joypad_query_pad(unsigned pad) { return pad < MAX_PLAYERS && g_pads[pad].joypad; @@ -162,7 +299,11 @@ static const char *sdl_joypad_name(unsigned pad) if (pad >= MAX_PLAYERS) return NULL; +#ifdef HAVE_SDL2 + return SDL_JoystickName(g_pads[pad].joypad); +#else return SDL_JoystickName(pad); +#endif } const rarch_joypad_driver_t sdl_joypad = { @@ -172,8 +313,16 @@ const rarch_joypad_driver_t sdl_joypad = { sdl_joypad_button, sdl_joypad_axis, sdl_joypad_poll, +#ifdef HAVE_SDL2 + sdl_joypad_set_rumble, +#else NULL, +#endif sdl_joypad_name, - "sdl", +#ifdef HAVE_SDL2 + "sdl2", +#else + "sdl" +#endif };