diff --git a/src/common/Settings.cpp b/src/common/Settings.cpp index 60bf628b8..cd3082f88 100644 --- a/src/common/Settings.cpp +++ b/src/common/Settings.cpp @@ -783,8 +783,8 @@ void Settings::SyncToEmulator() // register xbox device input settings for (int i = 0; i < 4; i++) { g_EmuShared->SetInputDevTypeSettings(&m_input_port[i].Type, i); - g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].TopSlotType, i, MU_SLOT_TOP); - g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].BottomSlotType, i, MU_SLOT_BOTTOM); + g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].TopSlotType, i, SLOT_TOP); + g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].BottomSlotType, i, SLOT_BOTTOM); if (m_input_port[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) { g_EmuShared->SetInputDevNameSettings(m_input_port[i].DeviceName.c_str(), i); auto it = std::find_if(m_input_profiles[m_input_port[i].Type].begin(), diff --git a/src/common/input/Button.h b/src/common/input/Button.h index ac0658bfe..efd71b959 100644 --- a/src/common/input/Button.h +++ b/src/common/input/Button.h @@ -35,7 +35,7 @@ #define SBC_NUM_BUTTONS 56 #define HIGHEST_NUM_BUTTONS SBC_NUM_BUTTONS -#define MU_NUM_SLOTS 2 +#define XBOX_CTRL_NUM_SLOTS 2 #define XBOX_BUTTON_NAME_LENGTH 30 #define HOST_BUTTON_NAME_LENGTH 30 diff --git a/src/common/input/InputManager.h b/src/common/input/InputManager.h index 15ce595d7..9b288d8ba 100644 --- a/src/common/input/InputManager.h +++ b/src/common/input/InputManager.h @@ -37,8 +37,8 @@ #undef SetPort #endif -#define MU_SLOT_TOP 0 -#define MU_SLOT_BOTTOM 1 +#define SLOT_TOP 0 +#define SLOT_BOTTOM 1 extern int dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)]; @@ -50,6 +50,11 @@ inline XBOX_INPUT_DEVICE input_support_list[] = { XBOX_INPUT_DEVICE::ARCADE_STICK, }; +inline XBOX_INPUT_DEVICE slot_support_list[] = { + XBOX_INPUT_DEVICE::DEVICE_INVALID, + XBOX_INPUT_DEVICE::MEMORY_UNIT, +}; + #pragma pack(1) // xpad in/out buffers stripped of the first two bytes diff --git a/src/common/input/InputWindow.cpp b/src/common/input/InputWindow.cpp index 485265758..05b0bad3f 100644 --- a/src/common/input/InputWindow.cpp +++ b/src/common/input/InputWindow.cpp @@ -43,7 +43,7 @@ InputWindow::~InputWindow() m_DeviceConfig = nullptr; } -bool InputWindow::IsProfileSaved() +int InputWindow::IsProfileSaved() { if (m_bHasChanges) { PopupReturn ret = PopupQuestion(m_hwnd_window, "Current configuration is not saved. Save before closing?"); @@ -53,23 +53,24 @@ bool InputWindow::IsProfileSaved() char name[50]; SendMessage(m_hwnd_profile_list, WM_GETTEXT, sizeof(name), reinterpret_cast(name)); if (SaveProfile(std::string(name))) { - return true; + return EXIT_SAVE; } - return false; + return EXIT_ABORT; } case PopupReturn::No: { - return true; + return EXIT_IGNORE; } case PopupReturn::Cancel: default: { - return false; + return EXIT_ABORT; } } } - return true; + + return EXIT_IGNORE; } void InputWindow::UpdateDeviceList() @@ -259,6 +260,10 @@ bool InputWindow::SaveProfile(const std::string& name) g_Settings->m_input_port[m_port_num].DeviceName = profile.DeviceName; g_Settings->m_input_port[m_port_num].ProfileName = profile.ProfileName; g_Settings->m_input_profiles[m_dev_type].push_back(std::move(profile)); + if (auto duke_wnd = dynamic_cast(this)) { + duke_wnd->SaveSlotConfig(); + } + m_bHasChanges = false; return true; } diff --git a/src/common/input/InputWindow.h b/src/common/input/InputWindow.h index 025c0c8a5..cbad576d4 100644 --- a/src/common/input/InputWindow.h +++ b/src/common/input/InputWindow.h @@ -42,6 +42,10 @@ #define BUTTON_SWAP 9 #define SLOTS_CHANGED 10 +#define EXIT_ABORT 0 +#define EXIT_SAVE 1 +#define EXIT_IGNORE 2 + #define XINPUT_DEFAULT 0 #define DINPUT_DEFAULT 1 @@ -61,7 +65,7 @@ public: virtual void ClearBindings() = 0; virtual void UpdateProfile(const std::string& name, int command); void UpdateCurrentDevice(); - virtual bool IsProfileSaved(); + virtual int IsProfileSaved(); void SwapMoCursorAxis(Button *button); @@ -107,7 +111,8 @@ public: void BindDefault(); void ClearBindings() override; void UpdateProfile(const std::string &name, int command) override; - bool IsProfileSaved() override; + int IsProfileSaved() override; + void SaveSlotConfig(); private: @@ -120,10 +125,8 @@ private: HWND m_hwnd_rumble; // handle of the rumble combobox HWND m_hwnd_rumble_list; - // handle of the top slot combobox - HWND m_hwnd_top_slot_list; - // handle of the bottom slot combobox - HWND m_hwnd_bottom_slot_list; + // handles of the slot combobox + HWND m_hwnd_slot_list[2]; // currently selected rumble control std::string m_rumble; }; diff --git a/src/common/win32/EmuShared.h b/src/common/win32/EmuShared.h index 1b36b352b..aff5a810e 100644 --- a/src/common/win32/EmuShared.h +++ b/src/common/win32/EmuShared.h @@ -368,7 +368,7 @@ class EmuShared : public Mutex bool m_bClipCursor; unsigned int m_dwKrnlProcID; // Only used for kernel mode level. int m_DeviceType[4]; - int m_SlotDeviceType[4][MU_NUM_SLOTS]; + int m_SlotDeviceType[4][XBOX_CTRL_NUM_SLOTS]; char m_DeviceControlNames[4][HIGHEST_NUM_BUTTONS][HOST_BUTTON_NAME_LENGTH]; char m_DeviceName[4][50]; char m_TitleMountPath[xbox::max_path]; diff --git a/src/core/hle/Patches.cpp b/src/core/hle/Patches.cpp index 7fa2bb3f3..9e113068e 100644 --- a/src/core/hle/Patches.cpp +++ b/src/core/hle/Patches.cpp @@ -365,6 +365,7 @@ std::map g_PatchTable = { PATCH_ENTRY("XSetProcessQuantumLength", xbox::EMUPATCH(XSetProcessQuantumLength), PATCH_ALWAYS), PATCH_ENTRY("timeKillEvent", xbox::EMUPATCH(timeKillEvent), PATCH_ALWAYS), PATCH_ENTRY("timeSetEvent", xbox::EMUPATCH(timeSetEvent), PATCH_ALWAYS), + PATCH_ENTRY("XUnmountMU", xbox::EMUPATCH(XUnmountMU), PATCH_ALWAYS), }; std::unordered_map g_FunctionHooks; diff --git a/src/core/hle/XAPI/Xapi.cpp b/src/core/hle/XAPI/Xapi.cpp index 6498d6e51..39d5ca233 100644 --- a/src/core/hle/XAPI/Xapi.cpp +++ b/src/core/hle/XAPI/Xapi.cpp @@ -1238,6 +1238,27 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XMountMURootA) RETURN(ERROR_SUCCESS); } +// ****************************************************************** +// * patch: XUnmountMU +// ****************************************************************** +xbox::dword_xt WINAPI xbox::EMUPATCH(XUnmountMU) +( + dword_xt dwPort, + dword_xt dwSlot +) +{ + + + LOG_FUNC_BEGIN + LOG_FUNC_ARG(dwPort) + LOG_FUNC_ARG(dwSlot) + LOG_FUNC_END; + + LOG_UNIMPLEMENTED(); + + RETURN(ERROR_SUCCESS); +} + // ****************************************************************** // * patch: OutputDebugStringA // ****************************************************************** diff --git a/src/core/hle/XAPI/Xapi.h b/src/core/hle/XAPI/Xapi.h index 6beb91c8a..3902fd71e 100644 --- a/src/core/hle/XAPI/Xapi.h +++ b/src/core/hle/XAPI/Xapi.h @@ -684,6 +684,15 @@ xbox::dword_xt WINAPI EMUPATCH(XMountMURootA) PCHAR pchDrive ); +// ****************************************************************** +// * patch: XUnmountMU +// ****************************************************************** +xbox::dword_xt WINAPI EMUPATCH(XUnmountMU) +( + dword_xt dwPort, + dword_xt dwSlot +); + // ****************************************************************** // * patch: XMountAlternateTitleA // ****************************************************************** diff --git a/src/gui/DlgInputConfig.cpp b/src/gui/DlgInputConfig.cpp index f3a782ec7..744e809ad 100644 --- a/src/gui/DlgInputConfig.cpp +++ b/src/gui/DlgInputConfig.cpp @@ -51,8 +51,8 @@ void SyncInputSettings(int port_num, int dev_type, bool is_opt) if (!is_opt) { // Sync updated input to kernel process to use run-time settings. g_EmuShared->SetInputDevTypeSettings(&g_Settings->m_input_port[port_num].Type, port_num); - g_EmuShared->SetInputSlotTypeSettings(&g_Settings->m_input_port[port_num].TopSlotType, port_num, MU_SLOT_TOP); - g_EmuShared->SetInputSlotTypeSettings(&g_Settings->m_input_port[port_num].BottomSlotType, port_num, MU_SLOT_BOTTOM); + g_EmuShared->SetInputSlotTypeSettings(&g_Settings->m_input_port[port_num].TopSlotType, port_num, SLOT_TOP); + g_EmuShared->SetInputSlotTypeSettings(&g_Settings->m_input_port[port_num].BottomSlotType, port_num, SLOT_BOTTOM); if (dev_type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) { std::string dev_name = g_Settings->m_input_port[port_num].DeviceName; diff --git a/src/gui/controllers/DlgDukeControllerConfig.cpp b/src/gui/controllers/DlgDukeControllerConfig.cpp index 9acbcac51..09576cca4 100644 --- a/src/gui/controllers/DlgDukeControllerConfig.cpp +++ b/src/gui/controllers/DlgDukeControllerConfig.cpp @@ -49,8 +49,8 @@ void DukeInputWindow::Initialize(HWND hwnd, int port_num, int dev_type) m_hwnd_device_list = GetDlgItem(m_hwnd_window, IDC_DEVICE_LIST); m_hwnd_profile_list = GetDlgItem(m_hwnd_window, IDC_PROFILE_NAME); m_hwnd_default = GetDlgItem(m_hwnd_window, IDC_DEFAULT); - m_hwnd_top_slot_list = GetDlgItem(hwnd, IDC_DEVICE_LIST_TOP_SLOT); - m_hwnd_bottom_slot_list = GetDlgItem(hwnd, IDC_DEVICE_LIST_BOTTOM_SLOT); + m_hwnd_slot_list[SLOT_TOP] = GetDlgItem(hwnd, IDC_DEVICE_LIST_TOP_SLOT); + m_hwnd_slot_list[SLOT_BOTTOM] = GetDlgItem(hwnd, IDC_DEVICE_LIST_BOTTOM_SLOT); m_dev_type = dev_type; m_max_num_buttons = dev_num_buttons[dev_type]; m_port_num = port_num; @@ -86,22 +86,27 @@ void DukeInputWindow::Initialize(HWND hwnd, int port_num, int dev_type) // Set the maximum profile name lenght the user can enter in the profile combobox SendMessage(m_hwnd_profile_list, CB_LIMITTEXT, 49, 0); - // Set up the device types we support in the slot ports - SendMessage(m_hwnd_top_slot_list, CB_ADDSTRING, 0, - reinterpret_cast(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)).c_str())); - SendMessage(m_hwnd_bottom_slot_list, CB_ADDSTRING, 0, - reinterpret_cast(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)).c_str())); - - if (m_dev_type != to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK)) { - SendMessage(m_hwnd_top_slot_list, CB_ADDSTRING, 0, - reinterpret_cast(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT)).c_str())); - SendMessage(m_hwnd_bottom_slot_list, CB_ADDSTRING, 0, - reinterpret_cast(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT)).c_str())); + if (m_dev_type == to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK)) { + // The arcade joystick does not have slot ports so we always disable the corresponding options + EnableWindow(m_hwnd_slot_list[SLOT_TOP], FALSE); + EnableWindow(m_hwnd_slot_list[SLOT_BOTTOM], FALSE); } else { - // The arcade joystick does not have slot ports so always disable the corresponding options - EnableWindow(m_hwnd_top_slot_list, FALSE); - EnableWindow(m_hwnd_bottom_slot_list, FALSE); + // Set up the device types we support in the slot ports + for (auto slot_type : slot_support_list) { + LRESULT index_top = SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_ADDSTRING, 0, + reinterpret_cast(GetInputDeviceName(to_underlying(slot_type)).c_str())); + LRESULT index_bottom = SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_ADDSTRING, 0, + reinterpret_cast(GetInputDeviceName(to_underlying(slot_type)).c_str())); + SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_SETITEMDATA, index_top, to_underlying(slot_type)); + SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_SETITEMDATA, index_bottom, to_underlying(slot_type)); + if (g_Settings->m_input_port[m_port_num].TopSlotType == to_underlying(slot_type)) { + SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_SETCURSEL, index_top, 0); + } + if (g_Settings->m_input_port[m_port_num].BottomSlotType == to_underlying(slot_type)) { + SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_SETCURSEL, index_bottom, 0); + } + } } // construct emu device @@ -210,7 +215,7 @@ void DukeInputWindow::UpdateProfile(const std::string &name, int command) break; default: - dynamic_cast(this)->UpdateProfile(name, command); + InputWindow::UpdateProfile(name, command); } } @@ -243,18 +248,30 @@ void DukeInputWindow::DetectOutput(int ms) } } -bool DukeInputWindow::IsProfileSaved() +int DukeInputWindow::IsProfileSaved() { - if (dynamic_cast(this)->IsProfileSaved()) { - int DeviceType = SendMessage(m_hwnd_top_slot_list, CB_GETITEMDATA, SendMessage(m_hwnd_top_slot_list, CB_GETCURSEL, 0, 0), 0); - g_Settings->m_input_port[m_port_num].TopSlotType = DeviceType; - DeviceType = SendMessage(m_hwnd_bottom_slot_list, CB_GETITEMDATA, SendMessage(m_hwnd_bottom_slot_list, CB_GETCURSEL, 0, 0), 0); - g_Settings->m_input_port[m_port_num].BottomSlotType = DeviceType; + if (int ret = InputWindow::IsProfileSaved()) { + if (ret == EXIT_IGNORE) { + return EXIT_IGNORE; + } + else { + if (m_dev_type != to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK)) { + SaveSlotConfig(); + } - return true; + return EXIT_SAVE; + } } - return false; + return EXIT_ABORT; +} + +void DukeInputWindow::SaveSlotConfig() +{ + int DeviceType = SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_GETITEMDATA, SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_GETCURSEL, 0, 0), 0); + g_Settings->m_input_port[m_port_num].TopSlotType = DeviceType; + DeviceType = SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_GETITEMDATA, SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_GETCURSEL, 0, 0), 0); + g_Settings->m_input_port[m_port_num].BottomSlotType = DeviceType; } static INT_PTR CALLBACK DlgRumbleConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -302,7 +319,8 @@ INT_PTR CALLBACK DlgXidControllerConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wPar } break; - case IDC_DEVICE_LIST_TOP_SLOT: { + case IDC_DEVICE_LIST_TOP_SLOT: + case IDC_DEVICE_LIST_BOTTOM_SLOT: { if (HIWORD(wParam) == CBN_SELCHANGE) { g_InputWindow->UpdateProfile(std::string(), SLOTS_CHANGED); }