diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 6bf69f2c9..b8a98cdcc 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -98,6 +98,9 @@ GameController::GameController(QObject* parent) context->gba->logLevel = GBA_LOG_FATAL; context->gba->luminanceSource = &controller->m_lux; context->gba->rtcSource = &controller->m_rtc; +#ifdef BUILD_SDL + context->gba->rumble = controller->m_inputController->rumble(); +#endif controller->gameStarted(context); }; diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 79b439ce8..c6ba5690c 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -150,6 +150,10 @@ void InputController::setPreferredGamepad(uint32_t type, const QString& device) } GBAInputSetPreferredDevice(m_config->input(), type, m_sdlPlayer.playerId, device.toLocal8Bit().constData()); } + +GBARumble* InputController::rumble() { + return &m_sdlPlayer.rumble.d; +} #endif GBAKey InputController::mapKeyboard(int key) const { diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index 2dd7fe826..b2864d382 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -63,6 +63,7 @@ public: int gamepad(uint32_t type) const { return m_sdlPlayer.joystickIndex; } void setGamepad(uint32_t type, int index) { GBASDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index); } void setPreferredGamepad(uint32_t type, const QString& device); + GBARumble* rumble(); #endif public slots: diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 6e9ac8d49..10ee97b86 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -20,8 +20,14 @@ #define GUI_MOD KMOD_CTRL #endif +static void _GBASDLSetRumble(struct GBARumble* rumble, int enable); + bool GBASDLInitEvents(struct GBASDLEvents* context) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) { + int subsystem = SDL_INIT_JOYSTICK; +#if SDL_VERSION_ATLEAST(2, 0, 0) + subsystem |= SDL_INIT_HAPTIC; +#endif + if (SDL_InitSubSystem(subsystem) < 0) { return false; } @@ -30,9 +36,15 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) { if (nJoysticks > 0) { context->nJoysticks = nJoysticks; context->joysticks = calloc(context->nJoysticks, sizeof(SDL_Joystick*)); +#if SDL_VERSION_ATLEAST(2, 0, 0) + context->haptic = calloc(context->nJoysticks, sizeof(SDL_Haptic*)); +#endif size_t i; for (i = 0; i < context->nJoysticks; ++i) { context->joysticks[i] = SDL_JoystickOpen(i); +#if SDL_VERSION_ATLEAST(2, 0, 0) + context->haptic[i] = SDL_HapticOpenFromJoystick(context->joysticks[i]); +#endif } } else { context->nJoysticks = 0; @@ -56,6 +68,9 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) { void GBASDLDeinitEvents(struct GBASDLEvents* context) { size_t i; for (i = 0; i < context->nJoysticks; ++i) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_HapticClose(context->haptic[i]); +#endif SDL_JoystickClose(context->joysticks[i]); } @@ -126,6 +141,11 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player player->joystick = 0; player->joystickIndex = SIZE_MAX; +#if SDL_VERSION_ATLEAST(2, 0, 0) + player->rumble.d.setRumble = _GBASDLSetRumble; + player->rumble.p = player; +#endif + if (events->playersAttached >= MAX_PLAYERS) { return false; } @@ -171,6 +191,13 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player if (player->joystickIndex != SIZE_MAX) { player->joystick = events->joysticks[player->joystickIndex]; events->joysticksClaimed[player->playerId] = player->joystickIndex; + +#if SDL_VERSION_ATLEAST(2, 0, 0) + player->haptic = events->haptic[player->joystickIndex]; + if (player->haptic) { + SDL_HapticRumbleInit(player->haptic); + } +#endif } ++events->playersAttached; @@ -403,3 +430,17 @@ void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContex break; } } + +#if SDL_VERSION_ATLEAST(2, 0, 0) +static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) { + struct GBASDLRumble* sdlRumble = (struct GBASDLRumble*) rumble; + if (!sdlRumble->p->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->haptic)) { + return; + } + if (enable) { + SDL_HapticRumblePlay(sdlRumble->p->haptic, 1.0f, 20); + } else { + SDL_HapticRumbleStop(sdlRumble->p->haptic); + } +} +#endif diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h index 69e095e9d..81840d39e 100644 --- a/src/platform/sdl/sdl-events.h +++ b/src/platform/sdl/sdl-events.h @@ -26,6 +26,9 @@ struct GBASDLEvents { const char* preferredJoysticks[MAX_PLAYERS]; int playersAttached; size_t joysticksClaimed[MAX_PLAYERS]; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_Haptic** haptic; +#endif }; struct GBASDLPlayer { @@ -37,6 +40,12 @@ struct GBASDLPlayer { SDL_Window* window; int fullscreen; int windowUpdated; + SDL_Haptic* haptic; + + struct GBASDLRumble { + struct GBARumble d; + struct GBASDLPlayer* p; + } rumble; #endif };