input: move copilot code to pad_thread
Some checks failed
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Mac Intel (push) Waiting to run
Build RPCS3 / RPCS3 Mac Apple Silicon (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Generate Translation Template / Generate Translation Template (push) Failing after 40s
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Has been skipped
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Has been skipped

This commit is contained in:
Megamouse 2025-06-02 00:52:05 +02:00
parent 4704c03209
commit d8bc2d5c75
16 changed files with 173 additions and 139 deletions

View file

@ -351,7 +351,7 @@ public:
for (u32 i = 0; i < CELL_GEM_MAX_NUM; i++)
{
const auto& pad = ::at32(handler->GetPads(), pad_num(i));
const bool connected = pad && pad->is_connected() && i < attribute.max_connect;
const bool connected = pad && pad->is_connected() && !pad->is_copilot() && i < attribute.max_connect;
const bool is_real_move = g_cfg.io.move != move_handler::real || pad->m_pad_handler == pad_handler::move;
update_connection(i, connected && is_real_move);
@ -407,7 +407,7 @@ public:
std::lock_guard pad_lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad && pad->m_pad_handler == pad_handler::move)
if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot())
{
if (!pad->move_data.calibration_requested || !pad->move_data.calibration_succeeded)
{
@ -437,7 +437,7 @@ public:
std::lock_guard pad_lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad && pad->m_pad_handler == pad_handler::move)
if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot())
{
pad->move_data.calibration_requested = false;
pad->move_data.calibration_succeeded = false;
@ -469,7 +469,7 @@ public:
for (u32 i = 0; i < std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM); i++)
{
const auto& pad = ::at32(handler->GetPads(), pad_num(i));
if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected())
if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected() && !pad->is_copilot())
{
connected_controllers++;
@ -490,7 +490,7 @@ public:
for (u32 i = 0; i < std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM); i++)
{
const auto& pad = ::at32(handler->GetPads(), pad_num(i));
if (pad && pad->is_connected())
if (pad && pad->is_connected() && !pad->is_copilot())
{
connected_controllers++;
@ -1776,7 +1776,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
return;
}
@ -1864,7 +1864,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& contro
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
return;
}
@ -1895,7 +1895,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected())
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot())
{
return;
}
@ -1940,7 +1940,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
return;
}
@ -1952,7 +1952,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller
ext.status = controller.ext_status;
for (const AnalogStick& stick : pad->m_sticks)
for (const AnalogStick& stick : pad->m_sticks_external)
{
switch (stick.m_offset)
{
@ -1964,7 +1964,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller
}
}
for (const Button& button : pad->m_buttons)
for (const Button& button : pad->m_buttons_external)
{
if (!button.m_pressed)
continue;
@ -2400,7 +2400,7 @@ error_code cellGemEnableMagnetometer(u32 gem_num, u32 enable)
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad && pad->m_pad_handler == pad_handler::move)
if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot())
{
pad->move_data.magnetometer_enabled = controller.enabled_magnetometer;
}
@ -2448,7 +2448,7 @@ error_code cellGemEnableMagnetometer2(u32 gem_num, u32 enable)
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad && pad->m_pad_handler == pad_handler::move)
if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot())
{
pad->move_data.magnetometer_enabled = controller.enabled_magnetometer;
}
@ -2777,7 +2777,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad && pad->is_connected())
if (pad && pad->is_connected() && !pad->is_copilot())
{
inertial_state->temperature = pad->move_data.temperature;
inertial_state->accelerometer[0] = pad->move_data.accelerometer_x;
@ -3392,7 +3392,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr<u32> ext_id, v
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected())
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot())
{
return CELL_GEM_NOT_CONNECTED;
}
@ -3706,7 +3706,7 @@ error_code cellGemWriteExternalPort(u32 gem_num, vm::ptr<u8[CELL_GEM_EXTERNAL_PO
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected())
if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot())
{
return CELL_GEM_NOT_CONNECTED;
}

View file

@ -411,60 +411,27 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
};
for (const Button& button : pad->m_buttons)
for (const Button& button : pad->m_buttons_external)
{
// here we check btns, and set pad accordingly,
// if something changed, set btnChanged
bool pressed = button.m_pressed;
u16 value = button.m_value;
// Merge copilots
if (!pad->copilots.empty())
{
for (const auto& copilot : pad->copilots)
{
if (!copilot || !copilot->is_connected())
{
continue;
}
for (const Button& other : copilot->m_buttons)
{
if (button.m_offset == other.m_offset && button.m_outKeyCode == other.m_outKeyCode)
{
if (other.m_pressed)
{
pressed = true;
if (value < other.m_value)
{
value = other.m_value;
}
}
break;
}
}
}
}
switch (button.m_offset)
{
case CELL_PAD_BTN_OFFSET_DIGITAL1:
{
if (pressed)
if (button.m_pressed)
pad->m_digital_1 |= button.m_outKeyCode;
else
pad->m_digital_1 &= ~button.m_outKeyCode;
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, value); break;
case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, value); break;
case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, value); break;
case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, value); break;
// These arent pressure btns
case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, button.m_value); break;
case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, button.m_value); break;
case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, button.m_value); break;
case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, button.m_value); break;
// These aren't pressure btns
case CELL_PAD_CTRL_R3:
case CELL_PAD_CTRL_L3:
case CELL_PAD_CTRL_START:
@ -475,21 +442,21 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
case CELL_PAD_BTN_OFFSET_DIGITAL2:
{
if (pressed)
if (button.m_pressed)
pad->m_digital_2 |= button.m_outKeyCode;
else
pad->m_digital_2 &= ~button.m_outKeyCode;
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, value); break;
case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, value); break;
case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, value); break;
case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, value); break;
case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, value); break;
case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, value); break;
case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, value); break;
case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, value); break;
case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, button.m_value); break;
case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, button.m_value); break;
case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, button.m_value); break;
case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, button.m_value); break;
case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, button.m_value); break;
case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, button.m_value); break;
case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, button.m_value); break;
case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break;
default: break;
}
break;
@ -498,18 +465,18 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, value, true); break;
case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, value, true); break;
case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, value, true); break;
case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, value, true); break;
case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, value, true); break;
case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, value, true); break;
case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, value, true); break;
case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, value, true); break;
case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, button.m_value, true); break;
case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, button.m_value, true); break;
default: break;
}
break;
@ -519,46 +486,14 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
}
for (const AnalogStick& stick : pad->m_sticks)
for (const AnalogStick& stick : pad->m_sticks_external)
{
u16 value = stick.m_value;
// Merge copilots
if (!pad->copilots.empty())
{
const auto normalize = [](s32 value)
{
return (value - 128) / 127.0f;
};
f32 accumulated_value = normalize(value);
for (const auto& copilot : pad->copilots)
{
if (!copilot || !copilot->is_connected())
{
continue;
}
for (const AnalogStick& other : copilot->m_sticks)
{
if (stick.m_offset == other.m_offset)
{
accumulated_value += normalize(other.m_value);
break;
}
}
}
value = static_cast<u16>(std::round(std::clamp(accumulated_value * 127.0f + 128.0f, 0.0f, 255.0f)));
}
switch (stick.m_offset)
{
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, stick.m_value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, stick.m_value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, stick.m_value); break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, stick.m_value); break;
default: break;
}
}
@ -1305,7 +1240,7 @@ error_code cellPadLddGetPortNo(s32 handle)
return CELL_PAD_ERROR_UNINITIALIZED;
const auto handler = pad::get_pad_thread();
auto& pads = handler->GetPads();
const auto& pads = handler->GetPads();
if (handle < 0 || static_cast<u32>(handle) >= pads.size())
return CELL_PAD_ERROR_INVALID_PARAMETER;

View file

@ -3,7 +3,6 @@
#include "Emu/Io/pad_types.h"
#include <array>
#include "util/types.hpp"
enum CellPadError : u32
{

View file

@ -173,7 +173,7 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/
{
const auto& pad = pads[i];
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
continue;
}

View file

@ -152,7 +152,7 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), m_controller_index);
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
return;
}

View file

@ -198,9 +198,9 @@ void usb_device_gametablet::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endp
const auto gamepad_handler = pad::get_pad_thread();
const auto& pads = gamepad_handler->GetPads();
const auto& pad = ::at32(pads, m_controller_index);
if (pad->is_connected())
if (pad->is_connected() && !pad->is_copilot())
{
for (Button& button : pad->m_buttons)
for (Button& button : pad->m_buttons_external)
{
if (!button.m_pressed)
{

View file

@ -258,7 +258,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
const auto gamepad_handler = pad::get_pad_thread();
const auto& pads = gamepad_handler->GetPads();
const auto& pad = ::at32(pads, m_controller_index);
if (pad->is_connected())
if (pad->is_connected() && !pad->is_copilot())
{
cfg->handle_input(pad, true, input_callback);
}

View file

@ -318,7 +318,7 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en
const auto gamepad_handler = pad::get_pad_thread();
const auto& pads = gamepad_handler->GetPads();
const auto& pad = ::at32(pads, m_controller_index);
if (pad->is_connected())
if (pad->is_connected() && !pad->is_copilot())
{
cfg->handle_input(pad, true, input_callback);
}

View file

@ -342,7 +342,7 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32
const auto gamepad_handler = pad::get_pad_thread();
const auto& pads = gamepad_handler->GetPads();
const auto& pad = ::at32(pads, m_controller_index);
if (pad->is_connected())
if (pad->is_connected() && !pad->is_copilot())
{
cfg->handle_input(pad, true, input_callback);
}

View file

@ -166,7 +166,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
const auto& pads = handler->GetPads();
const auto& pad = ::at32(pads, m_controller_index);
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
return;
const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index);

View file

@ -90,10 +90,10 @@ public:
void handle_input(std::shared_ptr<Pad> pad, bool press_only, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
{
if (!pad)
if (!pad || pad->is_copilot())
return;
for (const Button& button : pad->m_buttons)
for (const Button& button : pad->m_buttons_external)
{
if (button.m_pressed || !press_only)
{
@ -104,7 +104,7 @@ public:
}
}
for (const AnalogStick& stick : pad->m_sticks)
for (const AnalogStick& stick : pad->m_sticks_external)
{
if (handle_input(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true))
{

View file

@ -543,6 +543,9 @@ struct Pad
std::array<AnalogSensor, 4> m_sensors{};
std::array<VibrateMotor, 2> m_vibrateMotors{};
std::vector<Button> m_buttons_external;
std::array<AnalogStick, 4> m_sticks_external{};
std::vector<std::shared_ptr<Pad>> copilots;
// These hold bits for their respective buttons
@ -612,6 +615,12 @@ struct Pad
return umax;
}
bool is_copilot() const
{
const u32 copilot_player_id = copilot_player();
return copilot_player_id != umax && copilot_player_id != m_player_id;
}
bool is_connected() const
{
return !!(m_port_status & CELL_PAD_STATUS_CONNECTED);

View file

@ -210,7 +210,7 @@ void usb_device_usio::translate_input_taiko()
const usz offset = player * 8ULL;
auto& status = m_io_status[0];
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && is_input_allowed())
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && !pad->is_copilot() && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
@ -295,7 +295,7 @@ void usb_device_usio::translate_input_tekken()
auto& status = m_io_status[player / 2];
auto& input = digital_input[player / 2];
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && is_input_allowed())
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && !pad->is_copilot() && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)

View file

@ -225,7 +225,7 @@ namespace rsx
continue;
}
if (!pad->is_connected())
if (!pad->is_connected() || pad->is_copilot())
{
continue;
}
@ -314,7 +314,7 @@ namespace rsx
continue;
}
for (const Button& button : pad->m_buttons)
for (const Button& button : pad->m_buttons_external)
{
pad_button button_id = pad_button::pad_button_max_enum;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
@ -391,7 +391,7 @@ namespace rsx
break;
}
for (const AnalogStick& stick : pad->m_sticks)
for (const AnalogStick& stick : pad->m_sticks_external)
{
pad_button button_id = pad_button::pad_button_max_enum;
pad_button release_id = pad_button::pad_button_max_enum;

View file

@ -230,16 +230,22 @@ void pad_thread::Init()
// Set copilots
for (usz i = 0; i < m_pads.size(); i++)
{
if (!m_pads[i]) continue;
auto& pad = m_pads[i];
if (!pad)
continue;
m_pads[i]->copilots.clear();
pad->copilots.clear();
if (pad->is_copilot())
continue;
for (usz j = 0; j < m_pads.size(); j++)
{
if (i == j || !m_pads[j] || m_pads[j]->copilot_player() != i)
auto& other = m_pads[j];
if (i == j || !other || other->copilot_player() != i)
continue;
m_pads[i]->copilots.push_back(m_pads[j]);
pad->copilots.push_back(other);
}
}
@ -283,6 +289,87 @@ void pad_thread::SetIntercepted(bool intercepted)
}
}
void pad_thread::apply_copilots()
{
const auto normalize = [](s32 value)
{
return (value - 128) / 127.0f;
};
std::lock_guard lock(pad::g_pad_mutex);
for (auto& pad : m_pads)
{
if (!pad || !pad->is_connected())
{
continue;
}
pad->m_buttons_external = pad->m_buttons;
pad->m_sticks_external = pad->m_sticks;
if (pad->copilots.empty() || pad->is_copilot())
{
continue;
}
// Merge buttons
for (const auto& copilot : pad->copilots)
{
if (!copilot || !copilot->is_connected())
{
continue;
}
for (Button& button : pad->m_buttons_external)
{
for (const Button& other : copilot->m_buttons)
{
if (button.m_offset == other.m_offset && button.m_outKeyCode == other.m_outKeyCode)
{
if (other.m_pressed)
{
button.m_pressed = true;
if (button.m_value < other.m_value)
{
button.m_value = other.m_value;
}
}
break;
}
}
}
}
// Merge sticks
for (AnalogStick& stick : pad->m_sticks_external)
{
f32 accumulated_value = normalize(stick.m_value);
for (const auto& copilot : pad->copilots)
{
if (!copilot || !copilot->is_connected())
{
continue;
}
for (const AnalogStick& other : copilot->m_sticks)
{
if (stick.m_offset == other.m_offset)
{
accumulated_value += normalize(other.m_value);
break;
}
}
}
stick.m_value = static_cast<u16>(std::round(std::clamp(accumulated_value * 127.0f + 128.0f, 0.0f, 255.0f)));
}
}
}
void pad_thread::update_pad_states()
{
for (usz i = 0; i < m_pads.size(); i++)
@ -442,6 +529,8 @@ void pad_thread::operator()()
}
}
apply_copilots();
if (Emu.IsRunning())
{
update_pad_states();
@ -633,8 +722,9 @@ void pad_thread::InitLddPad(u32 handle, const u32* port_status)
static const input::product_info product = input::get_product_info(input::product_type::playstation_3_controller);
m_pads[handle]->ldd = true;
m_pads[handle]->Init
auto& pad = m_pads[handle];
pad->ldd = true;
pad->Init
(
port_status ? *port_status : CELL_PAD_STATUS_CONNECTED | CELL_PAD_STATUS_ASSIGN_CHANGES | CELL_PAD_STATUS_CUSTOM_CONTROLLER,
CELL_PAD_CAPABILITY_PS3_CONFORMITY,
@ -647,7 +737,7 @@ void pad_thread::InitLddPad(u32 handle, const u32* port_status)
);
input_log.notice("Pad %d: LDD, VID=0x%x, PID=0x%x, class_type=0x%x, class_profile=0x%x",
handle, m_pads[handle]->m_vendor_id, m_pads[handle]->m_product_id, m_pads[handle]->m_class_type, m_pads[handle]->m_class_profile);
handle, pad->m_vendor_id, pad->m_product_id, pad->m_class_type, pad->m_class_profile);
num_ldd_pad++;
}

View file

@ -59,6 +59,7 @@ protected:
u32 num_ldd_pad = 0;
private:
void apply_copilots();
void update_pad_states();
u32 m_mask_start_press_to_resume = 0;