diff --git a/.gitignore b/.gitignore index 7007cdae..91ada456 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ Package/AppImage/lib4bin Package/AppImage/sharun # 3rdParty Build Source/3rdParty/mupen64plus-core/src/asm_defines/asm_defines_gas.h -Source/3rdParty/mupen64plus-core/src/asm_defines/asm_defines_nasm.h \ No newline at end of file +Source/3rdParty/mupen64plus-core/src/asm_defines/asm_defines_nasm.h +# IDE +.idea/ \ No newline at end of file diff --git a/Source/RMG-Core/Settings.cpp b/Source/RMG-Core/Settings.cpp index fa530db7..33d6179f 100644 --- a/Source/RMG-Core/Settings.cpp +++ b/Source/RMG-Core/Settings.cpp @@ -654,6 +654,9 @@ static l_Setting get_setting(SettingsID settingId) case SettingsID::Input_DeviceSerial: setting = {"", "DeviceSerial"}; break; + case SettingsID::Input_DeviceGuid: + setting = {"", "DeviceGuid"}; + break; case SettingsID::Input_Deadzone: setting = {"", "Deadzone"}; break; diff --git a/Source/RMG-Core/Settings.hpp b/Source/RMG-Core/Settings.hpp index c9582060..0bfc1589 100644 --- a/Source/RMG-Core/Settings.hpp +++ b/Source/RMG-Core/Settings.hpp @@ -222,6 +222,7 @@ enum class SettingsID Input_DeviceNum, Input_DevicePath, Input_DeviceSerial, + Input_DeviceGuid, Input_Deadzone, Input_Sensitivity, Input_Pak, diff --git a/Source/RMG-Input/CMakeLists.txt b/Source/RMG-Input/CMakeLists.txt index 1490048b..61b82ed4 100644 --- a/Source/RMG-Input/CMakeLists.txt +++ b/Source/RMG-Input/CMakeLists.txt @@ -31,6 +31,7 @@ set(RMG_INPUT_SOURCES UserInterface/UIResources.qrc UserInterface/UICommon.cpp Utilities/Sdl3ButtonLabelToString.cpp + Utilities/Sdl3GuidWithIndex.cpp Utilities/InputProfileDB.cpp Utilities/QtKeyToSdl3Key.cpp Thread/SDLThread.cpp diff --git a/Source/RMG-Input/Thread/SDLThread.cpp b/Source/RMG-Input/Thread/SDLThread.cpp index 37c5a662..de54975e 100644 --- a/Source/RMG-Input/Thread/SDLThread.cpp +++ b/Source/RMG-Input/Thread/SDLThread.cpp @@ -13,6 +13,8 @@ #include #include +#include "../Utilities/Sdl3GuidWithIndex.hpp" + using namespace Thread; SDLThread::SDLThread(QObject *parent) : QThread(parent) @@ -68,8 +70,11 @@ void SDLThread::run(void) QString name; QString path; QString serial; + QString guid; QString errorMessage; + std::vector guidsWithoutIndex; + SDL_Gamepad* controller; SDL_Joystick* joystick; @@ -103,6 +108,7 @@ void SDLThread::run(void) name = SDL_GetGamepadName(controller); path = SDL_GetGamepadPath(controller); serial = SDL_GetGamepadSerial(controller); + guid = QString::fromStdString(Utilities::Sdl3GuidWithIndex(guidsWithoutIndex, joystickId)); SDL_CloseGamepad(controller); } else @@ -118,12 +124,13 @@ void SDLThread::run(void) name = SDL_GetJoystickName(joystick); path = SDL_GetJoystickPath(joystick); serial = SDL_GetJoystickSerial(joystick); + guid = QString::fromStdString(Utilities::Sdl3GuidWithIndex(guidsWithoutIndex, joystickId)); SDL_CloseJoystick(joystick); } if (name != nullptr) { - emit this->OnInputDeviceFound(name, path, serial, joystickId); + emit this->OnInputDeviceFound(name, path, serial, guid, joystickId); } } diff --git a/Source/RMG-Input/Thread/SDLThread.hpp b/Source/RMG-Input/Thread/SDLThread.hpp index 849daa22..370e8c3f 100644 --- a/Source/RMG-Input/Thread/SDLThread.hpp +++ b/Source/RMG-Input/Thread/SDLThread.hpp @@ -41,7 +41,7 @@ private: SDLThreadAction currentAction = SDLThreadAction::None; signals: - void OnInputDeviceFound(QString name, QString path, QString serial, SDL_JoystickID joystickId); + void OnInputDeviceFound(QString name, QString path, QString serial, QString guid, SDL_JoystickID joystickId); void OnDeviceSearchFinished(void); }; } // namespace Thread diff --git a/Source/RMG-Input/UserInterface/MainDialog.cpp b/Source/RMG-Input/UserInterface/MainDialog.cpp index 79dbb6af..025845ef 100644 --- a/Source/RMG-Input/UserInterface/MainDialog.cpp +++ b/Source/RMG-Input/UserInterface/MainDialog.cpp @@ -312,10 +312,10 @@ void MainDialog::on_tabWidget_currentChanged(int index) } } -void MainDialog::on_SDLThread_DeviceFound(QString name, QString path, QString serial, SDL_JoystickID joystickId) +void MainDialog::on_SDLThread_DeviceFound(QString name, QString path, QString serial, QString guid, SDL_JoystickID joystickId) { const InputDevice inputDevice = { InputDeviceType::Joystick, name.toStdString(), - path.toStdString(), serial.toStdString(), joystickId }; + path.toStdString(), serial.toStdString(), guid.toStdString(), joystickId }; this->inputDeviceList.append(inputDevice); } diff --git a/Source/RMG-Input/UserInterface/MainDialog.hpp b/Source/RMG-Input/UserInterface/MainDialog.hpp index 09d591ea..892deb01 100644 --- a/Source/RMG-Input/UserInterface/MainDialog.hpp +++ b/Source/RMG-Input/UserInterface/MainDialog.hpp @@ -69,7 +69,7 @@ public slots: void on_tabWidget_currentChanged(int); - void on_SDLThread_DeviceFound(QString, QString, QString, SDL_JoystickID); + void on_SDLThread_DeviceFound(QString, QString, QString, QString, SDL_JoystickID); void on_SDLThread_DeviceSearchFinished(void); private slots: diff --git a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp index 0cdfba1a..39b2bbea 100644 --- a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp +++ b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp @@ -618,6 +618,7 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString) std::string deviceName = CoreSettingsGetStringValue(SettingsID::Input_DeviceName, section); std::string devicePath = CoreSettingsGetStringValue(SettingsID::Input_DevicePath, section); std::string deviceSerial = CoreSettingsGetStringValue(SettingsID::Input_DeviceSerial, section); + std::string deviceGuid = CoreSettingsGetStringValue(SettingsID::Input_DeviceGuid, section); InputDeviceType deviceType; // keep compatibility with inputDeviceComboBox->count(); i++) { inputDeviceData otherDeviceData = this->inputDeviceComboBox->itemData(i).value(); InputDevice otherDevice = otherDeviceData.device; + if (device.guid == otherDevice.guid) + { + deviceGuidIndex = i; + break; + } if (device.name == otherDevice.name && device.serial == otherDevice.serial) { @@ -687,7 +694,11 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString) } } - if (deviceIndex != -1) + if (deviceGuidIndex != -1) + { // guid match + this->inputDeviceComboBox->setCurrentIndex(deviceGuidIndex); + } + else if (deviceIndex != -1) { // full match this->inputDeviceComboBox->setCurrentIndex(deviceIndex); @@ -1882,6 +1893,7 @@ void ControllerWidget::SaveDefaultSettings() CoreSettingsSetValue(SettingsID::Input_DeviceType, section, static_cast(InputDeviceType::None)); CoreSettingsSetValue(SettingsID::Input_DevicePath, section, std::string("")); CoreSettingsSetValue(SettingsID::Input_DeviceSerial, section, std::string("")); + CoreSettingsSetValue(SettingsID::Input_DeviceGuid, section, std::string("")); CoreSettingsSetValue(SettingsID::Input_Deadzone, section, 9); CoreSettingsSetValue(SettingsID::Input_Sensitivity, section, 100); CoreSettingsSetValue(SettingsID::Input_Pak, section, 0); @@ -1998,6 +2010,7 @@ void ControllerWidget::SaveSettings(QString section) CoreSettingsSetValue(SettingsID::Input_DeviceType, sectionStr, static_cast(device.type)); CoreSettingsSetValue(SettingsID::Input_DevicePath, sectionStr, device.path); CoreSettingsSetValue(SettingsID::Input_DeviceSerial, sectionStr, device.serial); + CoreSettingsSetValue(SettingsID::Input_DeviceGuid, sectionStr, device.guid); CoreSettingsSetValue(SettingsID::Input_Deadzone, sectionStr, this->deadZoneSlider->value()); CoreSettingsSetValue(SettingsID::Input_Sensitivity, sectionStr, this->analogStickSensitivitySlider->value()); CoreSettingsSetValue(SettingsID::Input_Pak, sectionStr, this->optionsDialogSettings.ControllerPak); diff --git a/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.cpp b/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.cpp new file mode 100644 index 00000000..1d965e75 --- /dev/null +++ b/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.cpp @@ -0,0 +1,31 @@ +/* + * Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG + * Copyright (C) 2020-2026 Rosalie Wanders + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "Sdl3GuidWithIndex.hpp" +#include +#include +#include + +using namespace Utilities; + +std::string Utilities::Sdl3GuidWithIndex(std::vector& guidsWithoutIndex, SDL_JoystickID joystickId) +{ + char guidBuffer[33]{}; + SDL_GUIDToString(SDL_GetJoystickGUIDForID(joystickId), guidBuffer, sizeof(guidBuffer)); + std::string guidWithoutIndex = std::string(guidBuffer); + + int guidIndex = 0; + for(auto& otherDeviceGuidWithoutIndex : guidsWithoutIndex) { + if(otherDeviceGuidWithoutIndex == guidWithoutIndex) guidIndex++; + } + guidsWithoutIndex.push_back(guidWithoutIndex); + std::string guidWithIndex = guidWithoutIndex + "/" + std::to_string(guidIndex); + + return guidWithIndex; +} diff --git a/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.hpp b/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.hpp new file mode 100644 index 00000000..2afb9551 --- /dev/null +++ b/Source/RMG-Input/Utilities/Sdl3GuidWithIndex.hpp @@ -0,0 +1,13 @@ +#ifndef RMG_Sdl3GuidWithIndex_HPP +#define RMG_Sdl3GuidWithIndex_HPP + +#include +#include +#include + +namespace Utilities +{ + std::string Sdl3GuidWithIndex(std::vector& guidsWithoutIndex, SDL_JoystickID joystickId); +} // namespace Utilities + +#endif //RMG_Sdl3GuidWithIndex_H diff --git a/Source/RMG-Input/common.hpp b/Source/RMG-Input/common.hpp index 693d3c4b..0c3d9fc2 100644 --- a/Source/RMG-Input/common.hpp +++ b/Source/RMG-Input/common.hpp @@ -80,15 +80,16 @@ struct InputDevice std::string name; std::string path; std::string serial; + std::string guid; SDL_JoystickID id = 0; bool operator== (const InputDevice& other) const { - return other.type == type && + return other.guid == guid || (other.type == type && other.name == name && other.path == path && other.serial == serial && - other.id == id; + other.id == id); } }; diff --git a/Source/RMG-Input/main.cpp b/Source/RMG-Input/main.cpp index 4a874053..dbd51858 100644 --- a/Source/RMG-Input/main.cpp +++ b/Source/RMG-Input/main.cpp @@ -16,6 +16,7 @@ #include "Thread/SDLThread.hpp" #include "common.hpp" #include "main.hpp" +#include "Utilities/Sdl3GuidWithIndex.hpp" #ifdef VRU #include "VRU.hpp" #endif // VRU @@ -88,6 +89,7 @@ struct InputProfile std::string DeviceName; std::string DevicePath; std::string DeviceSerial; + std::string DeviceGuid; InputDeviceType DeviceType = InputDeviceType::Invalid; std::chrono::time_point LastDeviceCheckTime = std::chrono::high_resolution_clock::now(); @@ -313,6 +315,7 @@ static void load_settings(void) profile->DeviceName = CoreSettingsGetStringValue(SettingsID::Input_DeviceName, section); profile->DevicePath = CoreSettingsGetStringValue(SettingsID::Input_DevicePath, section); profile->DeviceSerial = CoreSettingsGetStringValue(SettingsID::Input_DeviceSerial, section); + profile->DeviceGuid = CoreSettingsGetStringValue(SettingsID::Input_DeviceGuid, section); profile->DeviceType = static_cast(CoreSettingsGetIntValue(SettingsID::Input_DeviceType, section)); profile->GameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section); profile->GameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section); @@ -599,6 +602,8 @@ static void open_controller(InputProfile* profile, SDL_JoystickID* joysticks, in std::string deviceName; std::string devicePath; std::string deviceSerial; + std::string deviceGuid; + std::vector deviceGuidsWithoutIndex; for (int i = 0; i < joysticksCount; i++) { @@ -614,7 +619,7 @@ static void open_controller(InputProfile* profile, SDL_JoystickID* joysticks, in PluginDebugMessage(M64MSG_ERROR, errorMessage); continue; } - + joystick = SDL_GetGamepadJoystick(gamepad); if (joystick == nullptr) { @@ -626,6 +631,7 @@ static void open_controller(InputProfile* profile, SDL_JoystickID* joysticks, in deviceName = string_from_const_char(SDL_GetGamepadName(gamepad)); devicePath = string_from_const_char(SDL_GetGamepadPath(gamepad)); deviceSerial = string_from_const_char(SDL_GetGamepadSerial(gamepad)); + deviceGuid = Utilities::Sdl3GuidWithIndex(deviceGuidsWithoutIndex, joystickId); } else { @@ -642,11 +648,13 @@ static void open_controller(InputProfile* profile, SDL_JoystickID* joysticks, in deviceName = string_from_const_char(SDL_GetJoystickName(joystick)); devicePath = string_from_const_char(SDL_GetJoystickPath(joystick)); deviceSerial = string_from_const_char(SDL_GetJoystickSerial(joystick)); + deviceGuid = Utilities::Sdl3GuidWithIndex(deviceGuidsWithoutIndex, joystickId); } - if (deviceName == profile->DeviceName && + if (deviceGuid == profile->DeviceGuid || + (deviceName == profile->DeviceName && devicePath == profile->DevicePath && - deviceSerial == profile->DeviceSerial) + deviceSerial == profile->DeviceSerial)) { profile->SDLJoystick = joystick; profile->SDLGamepad = gamepad;