Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input: pad_thread optimizations #10836

Merged
merged 3 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion rpcs3/Emu/system_progress.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ struct progress_dialog_server
void operator()();
~progress_dialog_server();

static auto constexpr thread_name = "Progress Dialog Server"sv;
static constexpr auto thread_name = "Progress Dialog Server"sv;
};
66 changes: 31 additions & 35 deletions rpcs3/Input/pad_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "Emu/Io/Null/NullPadHandler.h"
#include "Emu/Io/PadHandler.h"
#include "Emu/Io/pad_config.h"
#include "Emu/System.h"
#include "Utilities/Thread.h"

LOG_CHANNEL(input_log, "Input");

Expand All @@ -24,7 +26,6 @@ namespace pad
std::string g_title_id;
atomic_t<bool> g_reset{false};
atomic_t<bool> g_enabled{true};
atomic_t<bool> g_active{false};
}

struct pad_setting
Expand All @@ -38,19 +39,12 @@ struct pad_setting
pad_thread::pad_thread(void *_curthread, void *_curwindow, std::string_view title_id) : curthread(_curthread), curwindow(_curwindow)
{
pad::g_title_id = title_id;
Init();

thread = std::make_shared<std::thread>(&pad_thread::ThreadFunc, this);
pad::g_current = this;
}

pad_thread::~pad_thread()
{
pad::g_current = nullptr;
pad::g_active = false;
thread->join();
Megamouse marked this conversation as resolved.
Show resolved Hide resolved

handlers.clear();
}

void pad_thread::Init()
Expand Down Expand Up @@ -214,14 +208,15 @@ void pad_thread::SetIntercepted(bool intercepted)
}
}

void pad_thread::ThreadFunc()
void pad_thread::operator()()
{
pad::g_active = true;
while (pad::g_active)
pad::g_reset = true;

while (thread_ctrl::state() != thread_state::aborting)
{
if (!pad::g_enabled)
if (!pad::g_enabled || Emu.IsPaused())
{
std::this_thread::sleep_for(1ms);
thread_ctrl::wait_for(10000);
continue;
}

Expand All @@ -240,42 +235,43 @@ void pad_thread::ThreadFunc()

m_info.now_connect = connected_devices + num_ldd_pad;

// The input_ignored section is only reached when a dialog was closed and the pads are still intercepted.
// The ignore_input section is only reached when a dialog was closed and the pads are still intercepted.
// As long as any of the listed buttons is pressed, cellPadGetData will ignore all input (needed for Hotline Miami).
// ignore_input was added because if we keep the pads intercepted, then some games will enter the menu due to unexpected system interception (tested with Ninja Gaiden Sigma).
const bool input_ignored = m_info.ignore_input && !(m_info.system_info & CELL_PAD_INFO_INTERCEPTED);
bool any_button_pressed = false;

for (usz i = 0; i < m_pads.size(); i++)
if (m_info.ignore_input && !(m_info.system_info & CELL_PAD_INFO_INTERCEPTED))
{
const auto& pad = m_pads[i];
bool any_button_pressed = false;

if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)
for (usz i = 0; i < m_pads.size() && !any_button_pressed; i++)
{
const auto& pad = m_pads[i];

if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
continue;

for (auto& button : pad->m_buttons)
{
if (button.m_pressed)
if (button.m_pressed && (
button.m_outKeyCode == CELL_PAD_CTRL_CROSS ||
button.m_outKeyCode == CELL_PAD_CTRL_CIRCLE ||
button.m_outKeyCode == CELL_PAD_CTRL_TRIANGLE ||
button.m_outKeyCode == CELL_PAD_CTRL_SQUARE ||
button.m_outKeyCode == CELL_PAD_CTRL_START ||
button.m_outKeyCode == CELL_PAD_CTRL_SELECT))
{
if (button.m_outKeyCode == CELL_PAD_CTRL_CROSS ||
button.m_outKeyCode == CELL_PAD_CTRL_CIRCLE ||
button.m_outKeyCode == CELL_PAD_CTRL_TRIANGLE ||
button.m_outKeyCode == CELL_PAD_CTRL_SQUARE ||
button.m_outKeyCode == CELL_PAD_CTRL_START ||
button.m_outKeyCode == CELL_PAD_CTRL_SELECT)
{
any_button_pressed = true;
}
any_button_pressed = true;
break;
}
}
}
}

if (input_ignored && !any_button_pressed)
{
m_info.ignore_input = false;
if (!any_button_pressed)
{
m_info.ignore_input = false;
}
}

std::this_thread::sleep_for(1ms);
thread_ctrl::wait_for(1000);
}
}

Expand Down
13 changes: 6 additions & 7 deletions rpcs3/Input/pad_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "Utilities/mutex.h"

#include <map>
#include <thread>
#include <mutex>
#include <string_view>
#include <string>
Expand All @@ -23,10 +22,11 @@ class pad_thread
pad_thread& operator=(const pad_thread&) = delete;
~pad_thread();

void operator()();

PadInfo& GetInfo() { return m_info; }
auto& GetPads() { return m_pads; }
void SetRumble(const u32 pad, u8 largeMotor, bool smallMotor);
void Init();
void SetIntercepted(bool intercepted);

s32 AddLddPad();
Expand All @@ -35,9 +35,11 @@ class pad_thread
static std::shared_ptr<PadHandlerBase> GetHandler(pad_handler type);
static void InitPadConfig(cfg_pad& cfg, pad_handler type, std::shared_ptr<PadHandlerBase>& handler);

static auto constexpr thread_name = "Pad Thread"sv;

protected:
void Init();
void InitLddPad(u32 handle);
void ThreadFunc();

// List of all handlers
std::map<pad_handler, std::shared_ptr<PadHandlerBase>> handlers;
Expand All @@ -49,8 +51,6 @@ class pad_thread
PadInfo m_info{ 0, 0, false };
std::array<std::shared_ptr<Pad>, CELL_PAD_MAX_PORT_NUM> m_pads;

std::shared_ptr<std::thread> thread;

u32 num_ldd_pad = 0;
};

Expand All @@ -61,7 +61,6 @@ namespace pad
extern std::string g_title_id;
extern atomic_t<bool> g_enabled;
extern atomic_t<bool> g_reset;
extern atomic_t<bool> g_active;

static inline class pad_thread* get_current_handler(bool relaxed = false)
{
Expand All @@ -81,7 +80,7 @@ namespace pad
static inline void reset(std::string_view title_id)
{
g_title_id = title_id;
g_reset = g_active.load();
g_reset = true;
}

static inline void SetIntercepted(bool intercepted)
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/main_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "util/logs.hpp"
#include "util/sysinfo.hpp"

#include "Utilities/Thread.h"
#include "Input/pad_thread.h"
#include "Emu/System.h"
#include "Emu/system_config.h"
Expand Down Expand Up @@ -99,7 +100,7 @@ EmuCallbacks main_application::CreateCallbacks()

callbacks.init_pad_handler = [this](std::string_view title_id)
{
g_fxo->init<pad_thread>(get_thread(), m_game_window, title_id);
g_fxo->init<named_thread<pad_thread>>(get_thread(), m_game_window, title_id);
};

callbacks.get_audio = []() -> std::shared_ptr<AudioBackend>
Expand Down
11 changes: 11 additions & 0 deletions rpcs3/rpcs3qt/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1938,6 +1938,11 @@ void main_window::CreateConnects()

connect(ui->addGamesAct, &QAction::triggered, this, [this]()
{
if (!m_gui_settings->GetBootConfirmation(this))
{
return;
}

QStringList paths;

// Only select one folder for now
Expand Down Expand Up @@ -2661,6 +2666,8 @@ void main_window::CreateFirmwareCache()
return;
}

Emu.SetForceBoot(true);
Emu.Stop();
Emu.SetForceBoot(true);

if (const game_boot_result error = Emu.BootGame(g_cfg.vfs.get_dev_flash() + "sys", "", true);
Expand Down Expand Up @@ -2888,6 +2895,10 @@ void main_window::dropEvent(QDropEvent* event)
{
return;
}

Emu.SetForceBoot(true);
Emu.Stop();

if (const auto error = Emu.BootGame(sstr(drop_paths.first()), "", true); error != game_boot_result::no_errors)
{
gui_log.error("Boot failed: reason: %s, path: %s", error, sstr(drop_paths.first()));
Expand Down