From 574afdf53d5534fdfaf95def252d7667bd08d76a Mon Sep 17 00:00:00 2001 From: "Al. Lopez" <67606569+AL2009man@users.noreply.github.com> Date: Tue, 4 Mar 2025 17:03:02 -0500 Subject: [PATCH 01/22] Experimenting Button Label Experimenting a way to add a hint for Button Labels. It should attempt to fix the Nintendo Layout issue when using a Nintendo Switch controller --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 85e6793a..f76ead5d 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -310,6 +310,7 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); From 07d193e229ddd101af5e5014180530cc3acbcf86 Mon Sep 17 00:00:00 2001 From: "Al. Lopez" <67606569+AL2009man@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:37:09 -0500 Subject: [PATCH 02/22] Create c-cpp.yml --- .github/workflows/c-cpp.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/c-cpp.yml diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml new file mode 100644 index 00000000..6a9c312e --- /dev/null +++ b/.github/workflows/c-cpp.yml @@ -0,0 +1,23 @@ +name: C/C++ CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: configure + run: ./configure + - name: make + run: make + - name: make check + run: make check + - name: make distcheck + run: make distcheck From 176bb625e2ac54b6678f55def6e634fbf09b410a Mon Sep 17 00:00:00 2001 From: "Al. Lopez" <67606569+AL2009man@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:37:24 -0500 Subject: [PATCH 03/22] Create cmake-multi-platform.yml --- .github/workflows/cmake-multi-platform.yml | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 .github/workflows/cmake-multi-platform.yml diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml new file mode 100644 index 00000000..7ab1b4d7 --- /dev/null +++ b/.github/workflows/cmake-multi-platform.yml @@ -0,0 +1,75 @@ +# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. +# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml +name: CMake on multiple platforms + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [ubuntu-latest, windows-latest] + build_type: [Release] + c_compiler: [gcc, clang, cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: ubuntu-latest + c_compiler: clang + cpp_compiler: clang++ + exclude: + - os: windows-latest + c_compiler: gcc + - os: windows-latest + c_compiler: clang + - os: ubuntu-latest + c_compiler: cl + + steps: + - uses: actions/checkout@v4 + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }} + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --build-config ${{ matrix.build_type }} From 9a181e0839d6d81ae2c043d8221598f05c78a5be Mon Sep 17 00:00:00 2001 From: "Al. Lopez" <67606569+AL2009man@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:40:40 -0500 Subject: [PATCH 04/22] Create apply-patch.yml --- .github/workflows/apply-patch.yml | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/apply-patch.yml diff --git a/.github/workflows/apply-patch.yml b/.github/workflows/apply-patch.yml new file mode 100644 index 00000000..45c30ce1 --- /dev/null +++ b/.github/workflows/apply-patch.yml @@ -0,0 +1,40 @@ +name: Apply Patch + +on: [push] + +jobs: + apply_patch: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Apply patch + run: | + git apply < Date: Tue, 4 Mar 2025 22:48:07 -0500 Subject: [PATCH 05/22] removing the workflows --- .github/workflows/apply-patch.yml | 40 ------------ .github/workflows/c-cpp.yml | 23 ------- .github/workflows/cmake-multi-platform.yml | 75 ---------------------- 3 files changed, 138 deletions(-) delete mode 100644 .github/workflows/apply-patch.yml delete mode 100644 .github/workflows/c-cpp.yml delete mode 100644 .github/workflows/cmake-multi-platform.yml diff --git a/.github/workflows/apply-patch.yml b/.github/workflows/apply-patch.yml deleted file mode 100644 index 45c30ce1..00000000 --- a/.github/workflows/apply-patch.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Apply Patch - -on: [push] - -jobs: - apply_patch: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Apply patch - run: | - git apply < - # 2. - # 3. - # - # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. - matrix: - os: [ubuntu-latest, windows-latest] - build_type: [Release] - c_compiler: [gcc, clang, cl] - include: - - os: windows-latest - c_compiler: cl - cpp_compiler: cl - - os: ubuntu-latest - c_compiler: gcc - cpp_compiler: g++ - - os: ubuntu-latest - c_compiler: clang - cpp_compiler: clang++ - exclude: - - os: windows-latest - c_compiler: gcc - - os: windows-latest - c_compiler: clang - - os: ubuntu-latest - c_compiler: cl - - steps: - - uses: actions/checkout@v4 - - - name: Set reusable strings - # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. - id: strings - shell: bash - run: | - echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: > - cmake -B ${{ steps.strings.outputs.build-output-dir }} - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - -S ${{ github.workspace }} - - - name: Build - # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} - - - name: Test - working-directory: ${{ steps.strings.outputs.build-output-dir }} - # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest --build-config ${{ matrix.build_type }} From bec2cf65ba4f06cb50688eb40d83e51af6793e2b Mon Sep 17 00:00:00 2001 From: "Al. Lopez" <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 01:59:35 -0500 Subject: [PATCH 06/22] added experimental Steam Virtual Gamepad support --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 21 ++++++++++++++------- UnleashedRecomp/hid/hid.h | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index f76ead5d..fa09ffe4 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -38,20 +38,23 @@ class Controller SDL_GameControllerType GetControllerType() const { - return SDL_GameControllerTypeForIndex(index); + return SDL_GameControllerGetType(controller); } hid::EInputDevice GetInputDevice() const { switch (GetControllerType()) { - case SDL_CONTROLLER_TYPE_PS3: - case SDL_CONTROLLER_TYPE_PS4: - case SDL_CONTROLLER_TYPE_PS5: - return hid::EInputDevice::PlayStation; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: + case SDL_CONTROLLER_TYPE_PS5: + return hid::EInputDevice::PlayStation; + case SDL_CONTROLLER_TYPE_XBOX360: + case SDL_CONTROLLER_TYPE_XBOXONE: + return hid::EInputDevice::Xbox; + default: + return hid::EInputDevice::Unknown; } - - return hid::EInputDevice::Xbox; } void Close() @@ -134,6 +137,7 @@ class Controller } }; + std::array g_controllers; Controller* g_activeController; @@ -310,6 +314,8 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); SDL_InitSubSystem(SDL_INIT_EVENTS); @@ -318,6 +324,7 @@ void hid::Init() SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } + uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState) { static uint32_t packet; diff --git a/UnleashedRecomp/hid/hid.h b/UnleashedRecomp/hid/hid.h index 730694a9..28736f09 100644 --- a/UnleashedRecomp/hid/hid.h +++ b/UnleashedRecomp/hid/hid.h @@ -7,7 +7,8 @@ namespace hid Keyboard, Mouse, Xbox, - PlayStation + PlayStation, + Unknown }; enum class EInputDeviceExplicit From ef4e37cb417429a2ce7287ba61fd23d13ce3f9fd Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 02:16:09 -0500 Subject: [PATCH 07/22] restoring notes for Button Labels. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index fa09ffe4..5f827204 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -314,9 +314,8 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); // Uses Button Labels. This hint is disabled for Nintendo Controllers. SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); From c9b3a5e03f9e5a33b0f6fcd281b2ead378fbc8ec Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:44:40 -0500 Subject: [PATCH 08/22] Initial Gamepad Hotplug Logic improvements This changes the way how a Controller will be prioritized. By default: it'll always prioritize based on Player 1. It should play nicely with Steam Deck's internal inputs when Steam Input is active --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 152 +++++++++++++++---------- 1 file changed, 89 insertions(+), 63 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 5f827204..4b3ee713 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -197,111 +197,137 @@ static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) auto g = isNight ? 0 : 37; auto b = isNight ? 101 : 184; - controller.SetLED(r, g, b); + // Ensure the lightbar is set correctly + if (SDL_GameControllerHasLED(controller.controller)) + { + SDL_GameControllerSetLED(controller.controller, r, g, b); + } } + int HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) { - case SDL_CONTROLLERDEVICEADDED: + case SDL_CONTROLLERDEVICEADDED: + { + const auto freeIndex = FindFreeController(); + + if (freeIndex != -1) { - const auto freeIndex = FindFreeController(); + auto controller = Controller(event->cdevice.which); - if (freeIndex != -1) - { - auto controller = Controller(event->cdevice.which); + g_controllers[freeIndex] = controller; - g_controllers[freeIndex] = controller; + SetControllerTimeOfDayLED(controller, App::s_isWerehog); - SetControllerTimeOfDayLED(controller, App::s_isWerehog); + // Ensure Player 1's controller is always the active controller + if (freeIndex == 0) + { + SetControllerInputDevice(&g_controllers[0]); } - - break; } - case SDL_CONTROLLERDEVICEREMOVED: - { - auto* controller = FindController(event->cdevice.which); + break; + } - if (controller) - controller->Close(); + case SDL_CONTROLLERDEVICEREMOVED: + { + auto* controller = FindController(event->cdevice.which); - break; - } + if (controller) + controller->Close(); - case SDL_CONTROLLERBUTTONDOWN: - case SDL_CONTROLLERBUTTONUP: - case SDL_CONTROLLERAXISMOTION: - case SDL_CONTROLLERTOUCHPADDOWN: + // If Player 1's controller is removed, set the next available controller as active + if (controller == &g_controllers[0]) { - auto* controller = FindController(event->cdevice.which); - - if (!controller) - break; - - if (event->type == SDL_CONTROLLERAXISMOTION) + for (auto& ctrl : g_controllers) { - if (abs(event->caxis.value) > 8000) + if (ctrl.CanPoll()) { - SDL_ShowCursor(SDL_DISABLE); - SetControllerInputDevice(controller); + SetControllerInputDevice(&ctrl); + break; } - - controller->PollAxis(); } - else + } + + break; + } + + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERAXISMOTION: + case SDL_CONTROLLERTOUCHPADDOWN: + { + auto* controller = FindController(event->cdevice.which); + + if (!controller) + break; + + if (event->type == SDL_CONTROLLERAXISMOTION) + { + if (abs(event->caxis.value) > 8000) { SDL_ShowCursor(SDL_DISABLE); SetControllerInputDevice(controller); - - controller->Poll(); } - break; + controller->PollAxis(); } + else + { + SDL_ShowCursor(SDL_DISABLE); + SetControllerInputDevice(controller); - case SDL_KEYDOWN: - case SDL_KEYUP: - hid::g_inputDevice = hid::EInputDevice::Keyboard; - break; + controller->Poll(); + } - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - { - if (!GameWindow::IsFullscreen() || GameWindow::s_isFullscreenCursorVisible) - SDL_ShowCursor(SDL_ENABLE); + break; + } - hid::g_inputDevice = hid::EInputDevice::Mouse; + case SDL_KEYDOWN: + case SDL_KEYUP: + hid::g_inputDevice = hid::EInputDevice::Keyboard; + break; - break; - } + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + if (!GameWindow::IsFullscreen() || GameWindow::s_isFullscreenCursorVisible) + SDL_ShowCursor(SDL_ENABLE); - case SDL_WINDOWEVENT: - { - if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) - { - // Stop vibrating controllers on focus lost. - for (auto& controller : g_controllers) - controller.SetVibration({ 0, 0 }); - } + hid::g_inputDevice = hid::EInputDevice::Mouse; - break; - } + break; + } - case SDL_USER_EVILSONIC: + case SDL_WINDOWEVENT: + { + if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) { + // Stop vibrating controllers on focus lost. for (auto& controller : g_controllers) - SetControllerTimeOfDayLED(controller, event->user.code); - - break; + controller.SetVibration({ 0, 0 }); } + + break; + } + + case SDL_USER_EVILSONIC: + { + for (auto& controller : g_controllers) + SetControllerTimeOfDayLED(controller, event->user.code); + + break; + } } return 0; } + + void hid::Init() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); From a96fc60dcdfcd705f1d9875758410901e2490b24 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 19:45:13 -0500 Subject: [PATCH 09/22] Lightbar detection when using multiple PlayStation controllers at the same time. An attempt to remedy the Lightbar activation. While Player 2/3/4 will override the in-game lightbar event upon connection: it'll later revert back to the in-game event. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 43 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 4b3ee713..dfb8e379 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -10,6 +10,13 @@ #define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X) #define VIBRATION_TIMEOUT_MS 5000 +struct LEDColor +{ + uint8_t r; + uint8_t g; + uint8_t b; +}; + class Controller { public: @@ -19,6 +26,7 @@ class Controller XAMINPUT_GAMEPAD state{}; XAMINPUT_VIBRATION vibration{ 0, 0 }; int index{}; + LEDColor ledColor{ 0, 0, 0 }; Controller() = default; @@ -131,13 +139,16 @@ class Controller SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS); } - void SetLED(const uint8_t r, const uint8_t g, const uint8_t b) const + void SetLED(const uint8_t r, const uint8_t g, const uint8_t b) { - SDL_GameControllerSetLED(controller, r, g, b); + if (SDL_GameControllerHasLED(controller)) + { + SDL_GameControllerSetLED(controller, r, g, b); + ledColor = { r, g, b }; + } } }; - std::array g_controllers; Controller* g_activeController; @@ -197,14 +208,20 @@ static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) auto g = isNight ? 0 : 37; auto b = isNight ? 101 : 184; - // Ensure the lightbar is set correctly - if (SDL_GameControllerHasLED(controller.controller)) + controller.SetLED(r, g, b); +} + +static void UpdateAllControllerLEDs(bool isNight) +{ + for (auto& controller : g_controllers) { - SDL_GameControllerSetLED(controller.controller, r, g, b); + if (controller.CanPoll()) + { + SetControllerTimeOfDayLED(controller, isNight); + } } } - int HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) @@ -219,7 +236,8 @@ int HID_OnSDLEvent(void*, SDL_Event* event) g_controllers[freeIndex] = controller; - SetControllerTimeOfDayLED(controller, App::s_isWerehog); + // Reapply the stored LED color state + controller.SetLED(controller.ledColor.r, controller.ledColor.g, controller.ledColor.b); // Ensure Player 1's controller is always the active controller if (freeIndex == 0) @@ -316,8 +334,8 @@ int HID_OnSDLEvent(void*, SDL_Event* event) case SDL_USER_EVILSONIC: { - for (auto& controller : g_controllers) - SetControllerTimeOfDayLED(controller, event->user.code); + // Update all controller LEDs to follow Player 1's LED + UpdateAllControllerLEDs(event->user.code); break; } @@ -326,8 +344,6 @@ int HID_OnSDLEvent(void*, SDL_Event* event) return 0; } - - void hid::Init() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); @@ -336,7 +352,7 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "0"); // Disable Player LED for PS5 controllers SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); @@ -349,7 +365,6 @@ void hid::Init() SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } - uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState) { static uint32_t packet; From 458938c2ae1f3154c6919fc6e865fdeeb2232e0f Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:09:24 -0500 Subject: [PATCH 10/22] Attempt to reduce Input leaking To avoid "the Controller is leaking" situation, there's now a Gamepad stat management that should reset Controller state based on connected controller. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index dfb8e379..97df8fb5 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -82,6 +82,11 @@ class Controller return controller; } + void ClearState() + { + memset(&state, 0, sizeof(state)); + } + void PollAxis() { if (!CanPoll()) @@ -184,6 +189,11 @@ inline Controller* FindController(int which) static void SetControllerInputDevice(Controller* controller) { + if (g_activeController && g_activeController != controller) + { + g_activeController->ClearState(); + } + g_activeController = controller; if (App::s_isLoading) @@ -415,3 +425,4 @@ uint32_t hid::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps return ERROR_SUCCESS; } + From 75dacf5578b74f7c6ce7145ba2a43bf8e039dde0 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:44:15 -0500 Subject: [PATCH 11/22] Lightbar active fix when gamepad plugged first prior to game launch Another attempt to fix the lightbar by redoing the controller state mangement. For some reason: the Lightbar gets disabled when a controller is already plugged prior to game launch. It reverts back to normal until the next game event. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 45 +++++++++----------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 97df8fb5..3ca65ac2 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -10,13 +10,6 @@ #define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X) #define VIBRATION_TIMEOUT_MS 5000 -struct LEDColor -{ - uint8_t r; - uint8_t g; - uint8_t b; -}; - class Controller { public: @@ -26,7 +19,6 @@ class Controller XAMINPUT_GAMEPAD state{}; XAMINPUT_VIBRATION vibration{ 0, 0 }; int index{}; - LEDColor ledColor{ 0, 0, 0 }; Controller() = default; @@ -87,6 +79,7 @@ class Controller memset(&state, 0, sizeof(state)); } + void PollAxis() { if (!CanPoll()) @@ -144,16 +137,13 @@ class Controller SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS); } - void SetLED(const uint8_t r, const uint8_t g, const uint8_t b) + void SetLED(const uint8_t r, const uint8_t g, const uint8_t b) const { - if (SDL_GameControllerHasLED(controller)) - { - SDL_GameControllerSetLED(controller, r, g, b); - ledColor = { r, g, b }; - } + SDL_GameControllerSetLED(controller, r, g, b); } }; + std::array g_controllers; Controller* g_activeController; @@ -218,20 +208,14 @@ static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) auto g = isNight ? 0 : 37; auto b = isNight ? 101 : 184; - controller.SetLED(r, g, b); -} - -static void UpdateAllControllerLEDs(bool isNight) -{ - for (auto& controller : g_controllers) + // Ensure the lightbar is set correctly + if (SDL_GameControllerHasLED(controller.controller)) { - if (controller.CanPoll()) - { - SetControllerTimeOfDayLED(controller, isNight); - } + SDL_GameControllerSetLED(controller.controller, r, g, b); } } + int HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) @@ -246,8 +230,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event) g_controllers[freeIndex] = controller; - // Reapply the stored LED color state - controller.SetLED(controller.ledColor.r, controller.ledColor.g, controller.ledColor.b); + SetControllerTimeOfDayLED(controller, App::s_isWerehog); // Ensure Player 1's controller is always the active controller if (freeIndex == 0) @@ -344,8 +327,8 @@ int HID_OnSDLEvent(void*, SDL_Event* event) case SDL_USER_EVILSONIC: { - // Update all controller LEDs to follow Player 1's LED - UpdateAllControllerLEDs(event->user.code); + for (auto& controller : g_controllers) + SetControllerTimeOfDayLED(controller, event->user.code); break; } @@ -354,6 +337,8 @@ int HID_OnSDLEvent(void*, SDL_Event* event) return 0; } + + void hid::Init() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); @@ -362,7 +347,7 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "0"); // Disable Player LED for PS5 controllers + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); @@ -375,6 +360,7 @@ void hid::Init() SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } + uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState) { static uint32_t packet; @@ -425,4 +411,3 @@ uint32_t hid::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps return ERROR_SUCCESS; } - From f3ddd800244339a0ea1abe52e105234b2d41d3e9 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Fri, 7 Mar 2025 13:55:10 -0500 Subject: [PATCH 12/22] Revert "restoring notes for Button Labels." This reverts commit ef4e37cb417429a2ce7287ba61fd23d13ce3f9fd. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 3ca65ac2..7902ee15 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -351,8 +351,9 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); // Uses Button Labels. This hint is disabled for Nintendo Controllers. + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); From bd071015b673ffa613c0cf2431ae83fa25630535 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Fri, 7 Mar 2025 13:55:54 -0500 Subject: [PATCH 13/22] Reapply "restoring notes for Button Labels." This reverts commit f3ddd800244339a0ea1abe52e105234b2d41d3e9. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 7902ee15..3ca65ac2 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -351,9 +351,8 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); // Uses Button Labels. This hint is disabled for Nintendo Controllers. SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); From 7291987ece532b4bd68c8bd00d7c7a3fa0943645 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:34:54 -0500 Subject: [PATCH 14/22] Moving all Gamepad Hotplug changes to separate branch To ensure all Hotplug-related changes don't accidentally get leftover: this commit will revert all the back back to the accidental removal of Button Label's note. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 39 +------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 3ca65ac2..c9515263 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -74,12 +74,6 @@ class Controller return controller; } - void ClearState() - { - memset(&state, 0, sizeof(state)); - } - - void PollAxis() { if (!CanPoll()) @@ -179,11 +173,6 @@ inline Controller* FindController(int which) static void SetControllerInputDevice(Controller* controller) { - if (g_activeController && g_activeController != controller) - { - g_activeController->ClearState(); - } - g_activeController = controller; if (App::s_isLoading) @@ -208,14 +197,9 @@ static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) auto g = isNight ? 0 : 37; auto b = isNight ? 101 : 184; - // Ensure the lightbar is set correctly - if (SDL_GameControllerHasLED(controller.controller)) - { - SDL_GameControllerSetLED(controller.controller, r, g, b); - } + controller.SetLED(r, g, b); } - int HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) @@ -231,12 +215,6 @@ int HID_OnSDLEvent(void*, SDL_Event* event) g_controllers[freeIndex] = controller; SetControllerTimeOfDayLED(controller, App::s_isWerehog); - - // Ensure Player 1's controller is always the active controller - if (freeIndex == 0) - { - SetControllerInputDevice(&g_controllers[0]); - } } break; @@ -249,19 +227,6 @@ int HID_OnSDLEvent(void*, SDL_Event* event) if (controller) controller->Close(); - // If Player 1's controller is removed, set the next available controller as active - if (controller == &g_controllers[0]) - { - for (auto& ctrl : g_controllers) - { - if (ctrl.CanPoll()) - { - SetControllerInputDevice(&ctrl); - break; - } - } - } - break; } @@ -337,8 +302,6 @@ int HID_OnSDLEvent(void*, SDL_Event* event) return 0; } - - void hid::Init() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); From 22b2ba8fe8fc5209c6730e954f23bed307eb613e Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:07:23 -0400 Subject: [PATCH 15/22] added SDL's GameController naming convention as Fallback If EInputDeviceExplicit doesn't recognize a specific Controller Type or Device: it'll fallback to SDL's naming conventions. This helps troubleshooting Controller-related issues when using the debug console. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index c9515263..d5780605 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -183,14 +183,26 @@ static void SetControllerInputDevice(Controller* controller) auto controllerType = (hid::EInputDeviceExplicit)controller->GetControllerType(); + // Only proceed if the controller type changes if (hid::g_inputDeviceExplicit != controllerType) { hid::g_inputDeviceExplicit = controllerType; - LOGFN("Detected controller: {}", hid::GetInputDeviceName()); + // Handle Unknown Type specifically + if (controllerType == hid::EInputDeviceExplicit::Unknown) + { + const char* controllerName = SDL_GameControllerName(controller->controller); + LOGFN("Controller connected: {} (Unknown Controller Type)", controllerName ? controllerName : "Unknown Device"); + } + else + { + // For known types, only use the EInputDeviceExplicit name + LOGFN("Controller connected: {}", hid::GetInputDeviceName()); + } } } + static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) { auto r = isNight ? 22 : 0; From 31b2544d3d41e80eb89320666136444b9bffaae5 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:09:15 -0400 Subject: [PATCH 16/22] Official device naming scheme for EInputDeviceExplicit Changes some of EInputDeviceExplicit's names to match the device's official name (such as Nintendo Switch Pro Controller, Xbox Wireless Controller, Amazon Luna Controller, etc.) --- UnleashedRecomp/hid/hid.cpp | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/UnleashedRecomp/hid/hid.cpp b/UnleashedRecomp/hid/hid.cpp index 0a56224a..029297e8 100644 --- a/UnleashedRecomp/hid/hid.cpp +++ b/UnleashedRecomp/hid/hid.cpp @@ -32,53 +32,53 @@ std::string hid::GetInputDeviceName() { switch (g_inputDevice) { - case EInputDevice::Keyboard: - return "Keyboard"; + case EInputDevice::Keyboard: + return "Keyboard"; - case EInputDevice::Mouse: - return "Mouse"; + case EInputDevice::Mouse: + return "Mouse"; } switch (g_inputDeviceExplicit) { - case EInputDeviceExplicit::Xbox360: - return "Xbox 360"; + case EInputDeviceExplicit::Xbox360: + return "Xbox 360 Controller"; - case EInputDeviceExplicit::XboxOne: - return "Xbox One"; + case EInputDeviceExplicit::XboxOne: + return "Xbox Wireless Controller"; - case EInputDeviceExplicit::DualShock3: - return "DualShock 3"; + case EInputDeviceExplicit::DualShock3: + return "DualShock 3"; - case EInputDeviceExplicit::DualShock4: - return "DualShock 4"; + case EInputDeviceExplicit::DualShock4: + return "DualShock 4"; - case EInputDeviceExplicit::SwitchPro: - return "Nintendo Switch Pro"; + case EInputDeviceExplicit::SwitchPro: + return "Nintendo Switch Pro Controller"; - case EInputDeviceExplicit::Virtual: - return "Virtual"; + case EInputDeviceExplicit::Virtual: + return "Virtual Controller"; - case EInputDeviceExplicit::DualSense: - return "DualSense"; + case EInputDeviceExplicit::DualSense: + return "DualSense"; - case EInputDeviceExplicit::Luna: - return "Amazon Luna"; + case EInputDeviceExplicit::Luna: + return "Amazon Luna Controller"; - case EInputDeviceExplicit::Stadia: - return "Google Stadia"; + case EInputDeviceExplicit::Stadia: + return "Google Stadia Controller"; - case EInputDeviceExplicit::NvShield: - return "NVIDIA Shield"; + case EInputDeviceExplicit::NvShield: + return "NVIDIA SHIELD Controller"; - case EInputDeviceExplicit::SwitchJCLeft: - return "Nintendo Switch Joy-Con (Left)"; + case EInputDeviceExplicit::SwitchJCLeft: + return "Nintendo Switch Joy-Con (Left)"; - case EInputDeviceExplicit::SwitchJCRight: - return "Nintendo Switch Joy-Con (Right)"; + case EInputDeviceExplicit::SwitchJCRight: + return "Nintendo Switch Joy-Con (Right)"; - case EInputDeviceExplicit::SwitchJCPair: - return "Nintendo Switch Joy-Con (Pair)"; + case EInputDeviceExplicit::SwitchJCPair: + return "Nintendo Switch Joy-Con (Pair)"; } return "Unknown"; From df2f95ca8f072e60878429daa7563fdf15c0de85 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:11:22 -0400 Subject: [PATCH 17/22] spacing formatting fix --- UnleashedRecomp/hid/hid.cpp | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/UnleashedRecomp/hid/hid.cpp b/UnleashedRecomp/hid/hid.cpp index 029297e8..64c3b0b7 100644 --- a/UnleashedRecomp/hid/hid.cpp +++ b/UnleashedRecomp/hid/hid.cpp @@ -32,53 +32,53 @@ std::string hid::GetInputDeviceName() { switch (g_inputDevice) { - case EInputDevice::Keyboard: - return "Keyboard"; + case EInputDevice::Keyboard: + return "Keyboard"; - case EInputDevice::Mouse: - return "Mouse"; + case EInputDevice::Mouse: + return "Mouse"; } switch (g_inputDeviceExplicit) { - case EInputDeviceExplicit::Xbox360: - return "Xbox 360 Controller"; + case EInputDeviceExplicit::Xbox360: + return "Xbox 360 Controller"; - case EInputDeviceExplicit::XboxOne: - return "Xbox Wireless Controller"; + case EInputDeviceExplicit::XboxOne: + return "Xbox Wireless Controller"; - case EInputDeviceExplicit::DualShock3: - return "DualShock 3"; + case EInputDeviceExplicit::DualShock3: + return "DualShock 3"; - case EInputDeviceExplicit::DualShock4: - return "DualShock 4"; + case EInputDeviceExplicit::DualShock4: + return "DualShock 4"; - case EInputDeviceExplicit::SwitchPro: - return "Nintendo Switch Pro Controller"; + case EInputDeviceExplicit::SwitchPro: + return "Nintendo Switch Pro Controller"; - case EInputDeviceExplicit::Virtual: - return "Virtual Controller"; + case EInputDeviceExplicit::Virtual: + return "Virtual Controller"; - case EInputDeviceExplicit::DualSense: - return "DualSense"; + case EInputDeviceExplicit::DualSense: + return "DualSense"; - case EInputDeviceExplicit::Luna: - return "Amazon Luna Controller"; + case EInputDeviceExplicit::Luna: + return "Amazon Luna Controller"; - case EInputDeviceExplicit::Stadia: - return "Google Stadia Controller"; + case EInputDeviceExplicit::Stadia: + return "Google Stadia Controller"; - case EInputDeviceExplicit::NvShield: - return "NVIDIA SHIELD Controller"; + case EInputDeviceExplicit::NvShield: + return "NVIDIA SHIELD Controller"; - case EInputDeviceExplicit::SwitchJCLeft: - return "Nintendo Switch Joy-Con (Left)"; + case EInputDeviceExplicit::SwitchJCLeft: + return "Nintendo Switch Joy-Con (Left)"; - case EInputDeviceExplicit::SwitchJCRight: - return "Nintendo Switch Joy-Con (Right)"; + case EInputDeviceExplicit::SwitchJCRight: + return "Nintendo Switch Joy-Con (Right)"; - case EInputDeviceExplicit::SwitchJCPair: - return "Nintendo Switch Joy-Con (Pair)"; + case EInputDeviceExplicit::SwitchJCPair: + return "Nintendo Switch Joy-Con (Pair)"; } return "Unknown"; From 570fab604c907549719a1a5e8cb3f161c0b9b334 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:41:54 -0400 Subject: [PATCH 18/22] remove "SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS" hint since #1045 will include it: we're gonna get rid of it on this code section to avoid conflicts. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index d5780605..3a73577c 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -202,7 +202,6 @@ static void SetControllerInputDevice(Controller* controller) } } - static void SetControllerTimeOfDayLED(Controller& controller, bool isNight) { auto r = isNight ? 22 : 0; @@ -327,8 +326,6 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); // Uses Button Labels. This hint is disabled for Nintendo Controllers. - SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); From 5a57de3ef18030ac57854d32dd15984db41af7d4 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:43:37 -0400 Subject: [PATCH 19/22] moved EInputDevice Unknown class to the top priority --- UnleashedRecomp/hid/hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UnleashedRecomp/hid/hid.h b/UnleashedRecomp/hid/hid.h index 28736f09..f1c5d592 100644 --- a/UnleashedRecomp/hid/hid.h +++ b/UnleashedRecomp/hid/hid.h @@ -4,11 +4,11 @@ namespace hid { enum class EInputDevice { + Unknown, Keyboard, Mouse, Xbox, - PlayStation, - Unknown + PlayStation }; enum class EInputDeviceExplicit From c77ce2b35982de9a7d4d2d779c4d8a79bab106d3 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:01:27 -0400 Subject: [PATCH 20/22] Replacing EInputDeviceExplicit with SDL_GameControllerName Based on @hyperbx's suggestions: It'll look for SDL's Controller Name as opposed to EInputDevice's naming scheme. --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 3a73577c..4c967f21 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -57,6 +57,16 @@ class Controller } } + const char* GetControllerName() const + { + auto result = SDL_GameControllerName(controller); + + if (!result) + return "Unknown Device"; + + return result; + } + void Close() { if (!controller) @@ -137,7 +147,6 @@ class Controller } }; - std::array g_controllers; Controller* g_activeController; @@ -182,22 +191,20 @@ static void SetControllerInputDevice(Controller* controller) hid::g_inputDeviceController = hid::g_inputDevice; auto controllerType = (hid::EInputDeviceExplicit)controller->GetControllerType(); + auto controllerName = controller->GetControllerName(); - // Only proceed if the controller type changes + // Only proceed if the controller type changes. if (hid::g_inputDeviceExplicit != controllerType) { hid::g_inputDeviceExplicit = controllerType; - // Handle Unknown Type specifically if (controllerType == hid::EInputDeviceExplicit::Unknown) { - const char* controllerName = SDL_GameControllerName(controller->controller); - LOGFN("Controller connected: {} (Unknown Controller Type)", controllerName ? controllerName : "Unknown Device"); + LOGFN("Detected controller: {} (Unknown Controller Type)", controllerName); } else { - // For known types, only use the EInputDeviceExplicit name - LOGFN("Controller connected: {}", hid::GetInputDeviceName()); + LOGFN("Detected controller: {}", controllerName); } } } From 95d491762f8f368c6cc8a985cda9509910415211 Mon Sep 17 00:00:00 2001 From: AL2009man <67606569+AL2009man@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:30:10 -0400 Subject: [PATCH 21/22] remove hid::GetInputDeviceName() from hid.ccp Now that SDL_GameControllerName handles Controller naming conventions, the hid.ccp portion of GetInputDeviceName is no longer needed. --- UnleashedRecomp/hid/hid.cpp | 56 ------------------------------------- UnleashedRecomp/hid/hid.h | 1 - 2 files changed, 57 deletions(-) diff --git a/UnleashedRecomp/hid/hid.cpp b/UnleashedRecomp/hid/hid.cpp index 64c3b0b7..900de327 100644 --- a/UnleashedRecomp/hid/hid.cpp +++ b/UnleashedRecomp/hid/hid.cpp @@ -27,59 +27,3 @@ bool hid::IsInputDeviceController() return hid::g_inputDevice != hid::EInputDevice::Keyboard && hid::g_inputDevice != hid::EInputDevice::Mouse; } - -std::string hid::GetInputDeviceName() -{ - switch (g_inputDevice) - { - case EInputDevice::Keyboard: - return "Keyboard"; - - case EInputDevice::Mouse: - return "Mouse"; - } - - switch (g_inputDeviceExplicit) - { - case EInputDeviceExplicit::Xbox360: - return "Xbox 360 Controller"; - - case EInputDeviceExplicit::XboxOne: - return "Xbox Wireless Controller"; - - case EInputDeviceExplicit::DualShock3: - return "DualShock 3"; - - case EInputDeviceExplicit::DualShock4: - return "DualShock 4"; - - case EInputDeviceExplicit::SwitchPro: - return "Nintendo Switch Pro Controller"; - - case EInputDeviceExplicit::Virtual: - return "Virtual Controller"; - - case EInputDeviceExplicit::DualSense: - return "DualSense"; - - case EInputDeviceExplicit::Luna: - return "Amazon Luna Controller"; - - case EInputDeviceExplicit::Stadia: - return "Google Stadia Controller"; - - case EInputDeviceExplicit::NvShield: - return "NVIDIA SHIELD Controller"; - - case EInputDeviceExplicit::SwitchJCLeft: - return "Nintendo Switch Joy-Con (Left)"; - - case EInputDeviceExplicit::SwitchJCRight: - return "Nintendo Switch Joy-Con (Right)"; - - case EInputDeviceExplicit::SwitchJCPair: - return "Nintendo Switch Joy-Con (Pair)"; - } - - return "Unknown"; -} diff --git a/UnleashedRecomp/hid/hid.h b/UnleashedRecomp/hid/hid.h index f1c5d592..d61131fb 100644 --- a/UnleashedRecomp/hid/hid.h +++ b/UnleashedRecomp/hid/hid.h @@ -46,5 +46,4 @@ namespace hid void SetProhibitedInputs(uint16_t wButtons = 0, bool leftStick = false, bool rightStick = false); bool IsInputAllowed(); bool IsInputDeviceController(); - std::string GetInputDeviceName(); } From a404f16333862999e3c8102a4e4e07032741e7fe Mon Sep 17 00:00:00 2001 From: Hyper <34012267+hyperbx@users.noreply.github.com> Date: Thu, 20 Mar 2025 22:20:54 +0000 Subject: [PATCH 22/22] Fix indentation --- UnleashedRecomp/hid/driver/sdl_hid.cpp | 151 ++++++++++++------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 4c967f21..15dee252 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -45,15 +45,15 @@ class Controller { switch (GetControllerType()) { - case SDL_CONTROLLER_TYPE_PS3: - case SDL_CONTROLLER_TYPE_PS4: - case SDL_CONTROLLER_TYPE_PS5: - return hid::EInputDevice::PlayStation; - case SDL_CONTROLLER_TYPE_XBOX360: - case SDL_CONTROLLER_TYPE_XBOXONE: - return hid::EInputDevice::Xbox; - default: - return hid::EInputDevice::Unknown; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: + case SDL_CONTROLLER_TYPE_PS5: + return hid::EInputDevice::PlayStation; + case SDL_CONTROLLER_TYPE_XBOX360: + case SDL_CONTROLLER_TYPE_XBOXONE: + return hid::EInputDevice::Xbox; + default: + return hid::EInputDevice::Unknown; } } @@ -222,99 +222,99 @@ int HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) { - case SDL_CONTROLLERDEVICEADDED: - { - const auto freeIndex = FindFreeController(); - - if (freeIndex != -1) + case SDL_CONTROLLERDEVICEADDED: { - auto controller = Controller(event->cdevice.which); - - g_controllers[freeIndex] = controller; + const auto freeIndex = FindFreeController(); - SetControllerTimeOfDayLED(controller, App::s_isWerehog); - } + if (freeIndex != -1) + { + auto controller = Controller(event->cdevice.which); - break; - } + g_controllers[freeIndex] = controller; - case SDL_CONTROLLERDEVICEREMOVED: - { - auto* controller = FindController(event->cdevice.which); + SetControllerTimeOfDayLED(controller, App::s_isWerehog); + } - if (controller) - controller->Close(); + break; + } - break; - } + case SDL_CONTROLLERDEVICEREMOVED: + { + auto* controller = FindController(event->cdevice.which); - case SDL_CONTROLLERBUTTONDOWN: - case SDL_CONTROLLERBUTTONUP: - case SDL_CONTROLLERAXISMOTION: - case SDL_CONTROLLERTOUCHPADDOWN: - { - auto* controller = FindController(event->cdevice.which); + if (controller) + controller->Close(); - if (!controller) break; + } - if (event->type == SDL_CONTROLLERAXISMOTION) + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERAXISMOTION: + case SDL_CONTROLLERTOUCHPADDOWN: { - if (abs(event->caxis.value) > 8000) + auto* controller = FindController(event->cdevice.which); + + if (!controller) + break; + + if (event->type == SDL_CONTROLLERAXISMOTION) + { + if (abs(event->caxis.value) > 8000) + { + SDL_ShowCursor(SDL_DISABLE); + SetControllerInputDevice(controller); + } + + controller->PollAxis(); + } + else { SDL_ShowCursor(SDL_DISABLE); SetControllerInputDevice(controller); + + controller->Poll(); } - controller->PollAxis(); + break; } - else - { - SDL_ShowCursor(SDL_DISABLE); - SetControllerInputDevice(controller); - controller->Poll(); - } + case SDL_KEYDOWN: + case SDL_KEYUP: + hid::g_inputDevice = hid::EInputDevice::Keyboard; + break; - break; - } + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + if (!GameWindow::IsFullscreen() || GameWindow::s_isFullscreenCursorVisible) + SDL_ShowCursor(SDL_ENABLE); - case SDL_KEYDOWN: - case SDL_KEYUP: - hid::g_inputDevice = hid::EInputDevice::Keyboard; - break; + hid::g_inputDevice = hid::EInputDevice::Mouse; - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - { - if (!GameWindow::IsFullscreen() || GameWindow::s_isFullscreenCursorVisible) - SDL_ShowCursor(SDL_ENABLE); + break; + } - hid::g_inputDevice = hid::EInputDevice::Mouse; + case SDL_WINDOWEVENT: + { + if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) + { + // Stop vibrating controllers on focus lost. + for (auto& controller : g_controllers) + controller.SetVibration({ 0, 0 }); + } - break; - } + break; + } - case SDL_WINDOWEVENT: - { - if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) + case SDL_USER_EVILSONIC: { - // Stop vibrating controllers on focus lost. for (auto& controller : g_controllers) - controller.SetVibration({ 0, 0 }); - } + SetControllerTimeOfDayLED(controller, event->user.code); - break; - } - - case SDL_USER_EVILSONIC: - { - for (auto& controller : g_controllers) - SetControllerTimeOfDayLED(controller, event->user.code); - - break; - } + break; + } } return 0; @@ -339,7 +339,6 @@ void hid::Init() SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } - uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState) { static uint32_t packet;