From bc3ab7a9d9f60cf9b0e703b21d593bf830caebaa Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 17 Dec 2018 19:13:35 +0100 Subject: [PATCH] Input: Enable In-Game Pad Config Reset --- rpcs3/Emu/Cell/Modules/cellGem.cpp | 4 ++ rpcs3/Emu/Cell/Modules/cellPad.cpp | 42 ++++++++++++++ rpcs3/Emu/RSX/Overlays/overlays.h | 22 ++++---- rpcs3/Emu/System.h | 1 + rpcs3/pad_thread.cpp | 80 ++++++++++++++++++++------- rpcs3/pad_thread.h | 7 ++- rpcs3/rpcs3_app.cpp | 5 ++ rpcs3/rpcs3qt/pad_settings_dialog.cpp | 12 ++++ rpcs3/rpcs3qt/pad_settings_dialog.h | 1 + 9 files changed, 142 insertions(+), 32 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index 295e1ebc67..3995039405 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -140,6 +140,8 @@ static bool check_gem_num(const u32 gem_num) */ static bool map_to_ds3_input(const u32 port_no, be_t& digital_buttons, be_t& analog_t) { + std::lock_guard lock(pad::g_pad_mutex); + const auto handler = pad::get_current_handler(); const PadInfo& rinfo = handler->GetInfo(); @@ -233,6 +235,8 @@ static bool map_to_ds3_input(const u32 port_no, be_t& digital_buttons, be_t */ static bool map_ext_to_ds3_input(const u32 port_no, CellGemExtPortData& ext) { + std::lock_guard lock(pad::g_pad_mutex); + const auto handler = pad::get_current_handler(); auto& pads = handler->GetPads(); diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 0f0b7c33b4..674bb36196 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -35,6 +35,8 @@ error_code cellPadInit(u32 max_connect) { sys_io.warning("cellPadInit(max_connect=%d)", max_connect); + std::lock_guard lock(pad::g_pad_mutex); + if (fxm::check()) return CELL_PAD_ERROR_ALREADY_INITIALIZED; @@ -50,6 +52,8 @@ error_code cellPadEnd() { sys_io.notice("cellPadEnd()"); + std::lock_guard lock(pad::g_pad_mutex); + if (!fxm::remove()) return CELL_PAD_ERROR_UNINITIALIZED; @@ -60,6 +64,8 @@ error_code cellPadClearBuf(u32 port_no) { sys_io.trace("cellPadClearBuf(port_no=%d)", port_no); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -102,6 +108,8 @@ error_code cellPadGetData(u32 port_no, vm::ptr data) { sys_io.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -353,6 +361,8 @@ error_code cellPadPeriphGetInfo(vm::ptr info) { sys_io.trace("cellPadPeriphGetInfo(info=*0x%x)", info); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -395,6 +405,8 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr data) { sys_io.trace("cellPadPeriphGetData(port_no=%d, data=*0x%x)", port_no, data); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -427,6 +439,8 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr data) { sys_io.todo("cellPadGetRawData(port_no=%d, data=*0x%x)", port_no, data); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -456,6 +470,8 @@ error_code cellPadGetDataExtra(u32 port_no, vm::ptr device_type, vm::ptr(); if (!config) @@ -495,6 +511,8 @@ error_code cellPadSetActDirect(u32 port_no, vm::ptr param) { sys_io.trace("cellPadSetActDirect(port_no=%d, param=*0x%x)", port_no, param); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -533,6 +551,8 @@ error_code cellPadGetInfo(vm::ptr info) { sys_io.trace("cellPadGetInfo(info=*0x%x)", info); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -570,6 +590,8 @@ error_code cellPadGetInfo2(vm::ptr info) { sys_io.trace("cellPadGetInfo2(info=*0x%x)", info); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -608,6 +630,8 @@ error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr { sys_io.trace("cellPadGetCapabilityInfo(port_no=%d, data_addr:=0x%x)", port_no, info.addr()); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -638,6 +662,8 @@ error_code cellPadSetPortSetting(u32 port_no, u32 port_setting) { sys_io.trace("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -663,6 +689,8 @@ s32 cellPadInfoPressMode(u32 port_no) { sys_io.trace("cellPadInfoPressMode(port_no=%d)", port_no); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -690,6 +718,8 @@ s32 cellPadInfoSensorMode(u32 port_no) { sys_io.trace("cellPadInfoSensorMode(port_no=%d)", port_no); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -717,6 +747,8 @@ error_code cellPadSetPressMode(u32 port_no, u32 mode) { sys_io.trace("cellPadSetPressMode(port_no=%d, mode=%d)", port_no, mode); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -751,6 +783,8 @@ error_code cellPadSetSensorMode(u32 port_no, u32 mode) { sys_io.trace("cellPadSetSensorMode(port_no=%d, mode=%d)", port_no, mode); + std::lock_guard lock(pad::g_pad_mutex); + const auto config = fxm::get(); if (!config) @@ -785,6 +819,8 @@ error_code cellPadLddRegisterController() { sys_io.todo("cellPadLddRegisterController()"); + std::lock_guard lock(pad::g_pad_mutex); + if (!fxm::check()) return CELL_PAD_ERROR_UNINITIALIZED; @@ -799,6 +835,8 @@ error_code cellPadLddDataInsert(s32 handle, vm::ptr data) { sys_io.todo("cellPadLddDataInsert(handle=%d, data=*0x%x)", handle, data); + std::lock_guard lock(pad::g_pad_mutex); + if (!fxm::check()) return CELL_PAD_ERROR_UNINITIALIZED; @@ -816,6 +854,8 @@ error_code cellPadLddGetPortNo(s32 handle) { sys_io.todo("cellPadLddGetPortNo(handle=%d)", handle); + std::lock_guard lock(pad::g_pad_mutex); + if (!fxm::check()) return CELL_PAD_ERROR_UNINITIALIZED; @@ -831,6 +871,8 @@ error_code cellPadLddUnregisterController(s32 handle) { sys_io.todo("cellPadLddUnregisterController(handle=%d)", handle); + std::lock_guard lock(pad::g_pad_mutex); + if (!fxm::check()) return CELL_PAD_ERROR_UNINITIALIZED; diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 0f801cf1ab..5af2a4c972 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "overlay_controls.h" #include "../../../Utilities/date_time.h" @@ -82,15 +82,6 @@ namespace rsx s32 run_input_loop() { - const auto handler = pad::get_current_handler(); - if (!handler) - { - LOG_ERROR(RSX, "Pad handler expected but none initialized!"); - return selection_code::error; - } - - const PadInfo& rinfo = handler->GetInfo(); - std::array timestamp; timestamp.fill(std::chrono::steady_clock::now()); @@ -107,6 +98,17 @@ namespace rsx if (Emu.IsStopped()) return selection_code::canceled; + std::lock_guard lock(pad::g_pad_mutex); + + const auto handler = pad::get_current_handler(); + if (!handler) + { + LOG_ERROR(RSX, "Pad handler expected but none initialized!"); + return selection_code::error; + } + + const PadInfo& rinfo = handler->GetInfo(); + if (Emu.IsPaused() || !rinfo.now_connect) { std::this_thread::sleep_for(10ms); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index ce15e929c2..778228724f 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -188,6 +188,7 @@ struct EmuCallbacks std::function on_stop; std::function on_ready; std::function exit; + std::function reset_pads; std::function handle_taskbar_progress; // (type, value) type: 0 for reset, 1 for increment, 2 for set_limit std::function()> get_kb_handler; std::function()> get_mouse_handler; diff --git a/rpcs3/pad_thread.cpp b/rpcs3/pad_thread.cpp index fa5655fbc5..7fdea51b9b 100644 --- a/rpcs3/pad_thread.cpp +++ b/rpcs3/pad_thread.cpp @@ -1,4 +1,4 @@ -#include "pad_thread.h" +#include "pad_thread.h" #include "ds4_pad_handler.h" #ifdef _WIN32 #include "xinput_pad_handler.h" @@ -12,27 +12,71 @@ namespace pad { atomic_t g_current = nullptr; + std::recursive_mutex g_pad_mutex; } +struct pad_setting +{ + u32 port_status; + u32 device_capability; + u32 device_type; +}; + pad_thread::pad_thread(void *_curthread, void *_curwindow) : curthread(_curthread), curwindow(_curwindow) { + Init(); + + thread = std::make_shared(&pad_thread::ThreadFunc, this); + pad::g_current = this; +} + +pad_thread::~pad_thread() +{ + pad::g_current = nullptr; + active = false; + thread->join(); + + handlers.clear(); +} + +void pad_thread::Init() +{ + std::lock_guard lock(pad::g_pad_mutex); + + // Cache old settings if possible + std::vector pad_settings; + for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; i++) // max 7 pads + { + if (i >= m_pads.size()) + { + pad_settings.push_back({ CELL_PAD_STATUS_DISCONNECTED, CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_ACTUATOR, CELL_PAD_DEV_TYPE_STANDARD }); + } + else + { + pad_settings.push_back({ m_pads[i]->m_port_status, m_pads[i]->m_device_capability, m_pads[i]->m_device_type }); + } + } + std::memset(&m_info, 0, sizeof(m_info)); m_info.now_connect = 0; + m_pads.clear(); + handlers.clear(); + g_cfg_input.load(); std::shared_ptr keyptr; - //Always have a Null Pad Handler + // Always have a Null Pad Handler std::shared_ptr nullpad = std::make_shared(); handlers.emplace(pad_handler::null, nullpad); - for (u32 i = 0; i < 7 /* Max 7 pads */; i++) + for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; i++) // max 7 pads { std::shared_ptr cur_pad_handler; const auto &handler_type = g_cfg_input.player[i]->handler; - + if (handlers.count(handler_type) != 0) { cur_pad_handler = handlers[handler_type]; @@ -70,30 +114,15 @@ pad_thread::pad_thread(void *_curthread, void *_curwindow) : curthread(_curthrea } cur_pad_handler->Init(); - m_pads.push_back(std::make_shared( - CELL_PAD_STATUS_DISCONNECTED, - CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_ACTUATOR, - CELL_PAD_DEV_TYPE_STANDARD)); + m_pads.push_back(std::make_shared(CELL_PAD_STATUS_DISCONNECTED, pad_settings[i].device_capability, pad_settings[i].device_type)); if (cur_pad_handler->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string()) == false) { - //Failed to bind the device to cur_pad_handler so binds to NullPadHandler + // Failed to bind the device to cur_pad_handler so binds to NullPadHandler LOG_ERROR(GENERAL, "Failed to bind device %s to handler %s", g_cfg_input.player[i]->device.to_string(), handler_type.to_string()); nullpad->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string()); } } - - thread = std::make_shared(&pad_thread::ThreadFunc, this); - pad::g_current = this; -} - -pad_thread::~pad_thread() -{ - pad::g_current = nullptr; - active = false; - thread->join(); - - handlers.clear(); } void pad_thread::SetRumble(const u32 pad, u8 largeMotor, bool smallMotor) @@ -108,11 +137,20 @@ void pad_thread::SetRumble(const u32 pad, u8 largeMotor, bool smallMotor) } } +void pad_thread::Reset() +{ + reset = active.load(); +} + void pad_thread::ThreadFunc() { active = true; while (active) { + if (reset && reset.exchange(false)) + { + Init(); + } u32 connected = 0; for (auto& cur_pad_handler : handlers) { diff --git a/rpcs3/pad_thread.h b/rpcs3/pad_thread.h index e0dae6bffb..e4a2f626a4 100644 --- a/rpcs3/pad_thread.h +++ b/rpcs3/pad_thread.h @@ -2,6 +2,7 @@ #include #include +#include #include "../Utilities/types.h" #include "Emu/Io/PadHandler.h" @@ -21,6 +22,8 @@ public: PadInfo& GetInfo() { return m_info; } std::vector>& GetPads() { return m_pads; } void SetRumble(const u32 pad, u8 largeMotor, bool smallMotor); + void Init(); + void Reset(); protected: void ThreadFunc(); @@ -35,13 +38,15 @@ protected: PadInfo m_info; std::vector> m_pads; - bool active; + atomic_t active{ false }; + atomic_t reset{ false }; std::shared_ptr thread; }; namespace pad { extern atomic_t g_current; + extern std::recursive_mutex g_pad_mutex; static inline class pad_thread* get_current_handler() { diff --git a/rpcs3/rpcs3_app.cpp b/rpcs3/rpcs3_app.cpp index a1c34b4d2e..6743277729 100644 --- a/rpcs3/rpcs3_app.cpp +++ b/rpcs3/rpcs3_app.cpp @@ -142,6 +142,11 @@ void rpcs3_app::InitializeCallbacks() RequestCallAfter(std::move(func)); }; + callbacks.reset_pads = [this]() + { + pad::get_current_handler()->Reset(); + }; + callbacks.get_kb_handler = [=]() -> std::shared_ptr { switch (keyboard_handler type = g_cfg.io.keyboard) diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index 729eee93cc..8ed90f4c58 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -944,6 +944,16 @@ void pad_settings_dialog::SaveProfile() m_handler_cfg.save(); } +void pad_settings_dialog::ResetPadHandler() +{ + if (Emu.IsStopped()) + { + return; + } + + Emu.GetCallbacks().reset_pads(); +} + void pad_settings_dialog::SaveExit() { SaveProfile(); @@ -960,6 +970,8 @@ void pad_settings_dialog::SaveExit() g_cfg_input.save(); + ResetPadHandler(); + QDialog::accept(); } diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.h b/rpcs3/rpcs3qt/pad_settings_dialog.h index d5228430bb..e0506fb7d7 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.h +++ b/rpcs3/rpcs3qt/pad_settings_dialog.h @@ -141,6 +141,7 @@ private: void ReloadButtons(); void ChangeProfile(); + void ResetPadHandler(); /** Repaints a stick deadzone preview label */ void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);