Input: Enable In-Game Pad Config Reset

This commit is contained in:
Megamouse 2018-12-17 19:13:35 +01:00
parent 5a40c1802b
commit bc3ab7a9d9
9 changed files with 142 additions and 32 deletions

View File

@ -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<u16>& digital_buttons, be_t<u16>& 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<u16>& 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();

View File

@ -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<pad_t>())
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<pad_t>())
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<pad_t>();
if (!config)
@ -102,6 +108,8 @@ error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> 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<pad_t>();
if (!config)
@ -353,6 +361,8 @@ error_code cellPadPeriphGetInfo(vm::ptr<CellPadPeriphInfo> info)
{
sys_io.trace("cellPadPeriphGetInfo(info=*0x%x)", info);
std::lock_guard lock(pad::g_pad_mutex);
const auto config = fxm::get<pad_t>();
if (!config)
@ -395,6 +405,8 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr<CellPadPeriphData> 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<pad_t>();
if (!config)
@ -427,6 +439,8 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr<CellPadData> 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<pad_t>();
if (!config)
@ -456,6 +470,8 @@ error_code cellPadGetDataExtra(u32 port_no, vm::ptr<u32> device_type, vm::ptr<Ce
{
sys_io.trace("cellPadGetDataExtra(port_no=%d, device_type=*0x%x, data=*0x%x)", port_no, device_type, data);
std::lock_guard lock(pad::g_pad_mutex);
const auto config = fxm::get<pad_t>();
if (!config)
@ -495,6 +511,8 @@ error_code cellPadSetActDirect(u32 port_no, vm::ptr<CellPadActParam> 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<pad_t>();
if (!config)
@ -533,6 +551,8 @@ error_code cellPadGetInfo(vm::ptr<CellPadInfo> info)
{
sys_io.trace("cellPadGetInfo(info=*0x%x)", info);
std::lock_guard lock(pad::g_pad_mutex);
const auto config = fxm::get<pad_t>();
if (!config)
@ -570,6 +590,8 @@ error_code cellPadGetInfo2(vm::ptr<CellPadInfo2> info)
{
sys_io.trace("cellPadGetInfo2(info=*0x%x)", info);
std::lock_guard lock(pad::g_pad_mutex);
const auto config = fxm::get<pad_t>();
if (!config)
@ -608,6 +630,8 @@ error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr<CellPadCapabilityInfo>
{
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<pad_t>();
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<pad_t>();
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<pad_t>();
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<pad_t>();
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<pad_t>();
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<pad_t>();
if (!config)
@ -785,6 +819,8 @@ error_code cellPadLddRegisterController()
{
sys_io.todo("cellPadLddRegisterController()");
std::lock_guard lock(pad::g_pad_mutex);
if (!fxm::check<pad_t>())
return CELL_PAD_ERROR_UNINITIALIZED;
@ -799,6 +835,8 @@ error_code cellPadLddDataInsert(s32 handle, vm::ptr<CellPadData> data)
{
sys_io.todo("cellPadLddDataInsert(handle=%d, data=*0x%x)", handle, data);
std::lock_guard lock(pad::g_pad_mutex);
if (!fxm::check<pad_t>())
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<pad_t>())
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<pad_t>())
return CELL_PAD_ERROR_UNINITIALIZED;

View File

@ -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<std::chrono::steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> 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);

View File

@ -188,6 +188,7 @@ struct EmuCallbacks
std::function<void()> on_stop;
std::function<void()> on_ready;
std::function<void()> exit;
std::function<void()> reset_pads;
std::function<void(s32, s32)> handle_taskbar_progress; // (type, value) type: 0 for reset, 1 for increment, 2 for set_limit
std::function<std::shared_ptr<class KeyboardHandlerBase>()> get_kb_handler;
std::function<std::shared_ptr<class MouseHandlerBase>()> get_mouse_handler;

View File

@ -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<pad_thread*> 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<std::thread>(&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_setting> 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<keyboard_pad_handler> keyptr;
//Always have a Null Pad Handler
// Always have a Null Pad Handler
std::shared_ptr<NullPadHandler> nullpad = std::make_shared<NullPadHandler>();
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<PadHandlerBase> 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<Pad>(
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<Pad>(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<std::thread>(&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)
{

View File

@ -2,6 +2,7 @@
#include <map>
#include <thread>
#include <mutex>
#include "../Utilities/types.h"
#include "Emu/Io/PadHandler.h"
@ -21,6 +22,8 @@ public:
PadInfo& GetInfo() { return m_info; }
std::vector<std::shared_ptr<Pad>>& 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<std::shared_ptr<Pad>> m_pads;
bool active;
atomic_t<bool> active{ false };
atomic_t<bool> reset{ false };
std::shared_ptr<std::thread> thread;
};
namespace pad
{
extern atomic_t<pad_thread*> g_current;
extern std::recursive_mutex g_pad_mutex;
static inline class pad_thread* get_current_handler()
{

View File

@ -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<KeyboardHandlerBase>
{
switch (keyboard_handler type = g_cfg.io.keyboard)

View File

@ -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();
}

View File

@ -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);