diff --git a/src/common/assert.cpp b/src/common/assert.cpp index c5329d904..5a4d9c987 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -59,6 +59,7 @@ int DbgExitHandler(const char* file, int line, fmt::text_style style, std::strin } void DbgExit(int status) { + Subsystems::EmergencyShutdownActive(); std::fflush(nullptr); std::_Exit(status); } diff --git a/src/common/assert.h b/src/common/assert.h index 0a05ffeb8..e91899dae 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -29,11 +29,7 @@ void DbgExit(int status); } // namespace Common -#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX #define EXIT_HALT() (Common::DbgExit(321), 1) -#else -#define EXIT_HALT() (std::_Exit(321), 1) -#endif #ifndef KYTY_FINAL #define EXIT_IF(x) \ diff --git a/src/graphics/presentation/window/window.cpp b/src/graphics/presentation/window/window.cpp index dc2eb9a5a..1053d667b 100644 --- a/src/graphics/presentation/window/window.cpp +++ b/src/graphics/presentation/window/window.cpp @@ -814,6 +814,7 @@ static void WindowCreate(WindowContext& context) { int width = static_cast(context.graphic_ctx.screen_width); int height = static_cast(context.graphic_ctx.screen_height); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "0"); @@ -899,6 +900,7 @@ void WindowRun() { void WindowShutdown() { if (g_window != nullptr) { + Controller::EmergencyShutdown(); g_window.reset(); } } diff --git a/src/libs/controller.cpp b/src/libs/controller.cpp index fb1ec6263..ce10b4ab5 100644 --- a/src/libs/controller.cpp +++ b/src/libs/controller.cpp @@ -23,8 +23,8 @@ LIB_NAME("Pad", "Pad"); constexpr int PAD_ERROR_INVALID_ARG = -2137915391; /* 0x80920001 */ constexpr int PAD_ERROR_INVALID_HANDLE = -2137915389; /* 0x80920003 */ -// SDL limits rumble commands to 0xffff ms; zero strengths stop immediately. constexpr uint32_t RUMBLE_DURATION_MS = 0xffff; +constexpr uint32_t RELEASE_FLUSH_MS = 50; struct PadControllerInformation { float touch_pixel_density; @@ -102,6 +102,7 @@ public: void RightStick(int id, int x, int y); void TouchPad(int id, int finger, bool down, float x, float y); void ResetInputState(); + void ReleaseHostPads(); void GetConnectionInfo(bool* flag, int* count); void SetVibration(uint8_t large_motor, uint8_t small_motor); void SetLightBar(uint8_t r, uint8_t g, uint8_t b); @@ -252,10 +253,17 @@ void Initialize() { } void Shutdown() { + EmergencyShutdown(); delete g_controller; g_controller = nullptr; } +void EmergencyShutdown() { + if (g_controller != nullptr) { + g_controller->ReleaseHostPads(); + } +} + void GameController::Connect(int id) { Common::LockGuard lock(m_mutex); @@ -404,6 +412,39 @@ void GameController::ResetInputState() { AddState(); } +void GameController::ReleaseHostPads() { + Common::LockGuard lock(m_mutex); + + std::vector pads; + for (const auto id: m_connected_ids) { + if (id == HOST_INPUT_CONTROLLER_ID) { + continue; + } + if (auto* pad = SDL_GameControllerFromInstanceID(static_cast(id)); + pad != nullptr) { + if (SDL_GameControllerGetType(pad) == SDL_CONTROLLER_TYPE_PS5) { + DualSenseEffects effect {}; + effect.enable_bits = 0x0c; + effect.right_trigger[0] = 0x05; + effect.left_trigger[0] = 0x05; + (void)SDL_GameControllerSendEffect(pad, &effect, sizeof(effect)); + } + (void)SDL_GameControllerRumble(pad, 0, 0, 0); + (void)SDL_GameControllerSetLED(pad, 0, 0, 0); + pads.push_back(pad); + } + } + + if (!pads.empty()) { + SDL_Delay(RELEASE_FLUSH_MS); + for (auto* pad: pads) { + SDL_GameControllerClose(pad); + } + } + + m_connected_ids.clear(); +} + void GameController::SetVibration(uint8_t large_motor, uint8_t small_motor) { Common::LockGuard lock(m_mutex); diff --git a/src/libs/controller.h b/src/libs/controller.h index 8a2edef2a..eca91f275 100644 --- a/src/libs/controller.h +++ b/src/libs/controller.h @@ -7,11 +7,13 @@ namespace Libs::Controller { void Initialize(); void Shutdown(); +void EmergencyShutdown(); struct Lifecycle { - static constexpr const char* name = "Controller"; - static constexpr auto initialize = Libs::Controller::Initialize; - static constexpr auto shutdown = Libs::Controller::Shutdown; + static constexpr const char* name = "Controller"; + static constexpr auto initialize = Libs::Controller::Initialize; + static constexpr auto shutdown = Libs::Controller::Shutdown; + static constexpr auto emergency_shutdown = Libs::Controller::EmergencyShutdown; }; constexpr int HOST_INPUT_CONTROLLER_ID = -1000;