This commit is contained in:
Megamouse 2025-06-01 14:22:01 -07:00 committed by GitHub
commit 9c7462f2ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 714 additions and 157 deletions

View file

@ -394,6 +394,7 @@ target_sources(rpcs3_emu PRIVATE
Io/Dimensions.cpp
Io/evdev_gun_handler.cpp
Io/GameTablet.cpp
Io/gem_config.cpp
Io/GHLtar.cpp
Io/GunCon3.cpp
Io/Infinity.cpp

View file

@ -27,39 +27,6 @@
LOG_CHANNEL(cellGem);
template <>
void fmt_class_string<gem_btn>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](gem_btn value)
{
switch (value)
{
case gem_btn::start: return "Start";
case gem_btn::select: return "Select";
case gem_btn::triangle: return "Triangle";
case gem_btn::circle: return "Circle";
case gem_btn::cross: return "Cross";
case gem_btn::square: return "Square";
case gem_btn::move: return "Move";
case gem_btn::t: return "T";
case gem_btn::x_axis: return "X-Axis";
case gem_btn::y_axis: return "Y-Axis";
case gem_btn::combo: return "Combo";
case gem_btn::combo_start: return "Combo Start";
case gem_btn::combo_select: return "Combo Select";
case gem_btn::combo_triangle: return "Combo Triangle";
case gem_btn::combo_circle: return "Combo Circle";
case gem_btn::combo_cross: return "Combo Cross";
case gem_btn::combo_square: return "Combo Square";
case gem_btn::combo_move: return "Combo Move";
case gem_btn::combo_t: return "Combo T";
case gem_btn::count: return "Count";
}
return unknown;
});
}
template <>
void fmt_class_string<CellGemError>::format(std::string& out, u64 arg)
{
@ -234,7 +201,7 @@ public:
struct gem_controller
{
u32 status = CELL_GEM_STATUS_DISCONNECTED; // Connection status (CELL_GEM_STATUS_DISCONNECTED or CELL_GEM_STATUS_READY)
u32 ext_status = CELL_GEM_NO_EXTERNAL_PORT_DEVICE; // External port connection status
u32 ext_status = 0; // External port connection status
u32 ext_id = 0; // External device ID (type). For example SHARP_SHOOTER_DEVICE_ID
u32 port = 0; // Assigned port
bool enabled_magnetometer = true; // Whether the magnetometer is enabled (probably used for additional rotational precision)
@ -1918,6 +1885,312 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co
}
}
static const std::unordered_map<gem_btn, u16> ext_btn_map =
{
{ gem_btn::sharpshooter_firing_mode_1, button_flags::ss_firing_mode_1 },
{ gem_btn::sharpshooter_firing_mode_2, button_flags::ss_firing_mode_2 },
{ gem_btn::sharpshooter_firing_mode_3, button_flags::ss_firing_mode_3 },
{ gem_btn::sharpshooter_trigger, button_flags::ss_trigger },
{ gem_btn::sharpshooter_reload, button_flags::ss_reload },
{ gem_btn::racing_wheel_d_pad_up, CELL_PAD_CTRL_UP },
{ gem_btn::racing_wheel_d_pad_right, CELL_PAD_CTRL_RIGHT },
{ gem_btn::racing_wheel_d_pad_down, CELL_PAD_CTRL_DOWN },
{ gem_btn::racing_wheel_d_pad_left, CELL_PAD_CTRL_LEFT },
{ gem_btn::racing_wheel_throttle, 0 },
{ gem_btn::racing_wheel_l1, CELL_PAD_CTRL_L1 },
{ gem_btn::racing_wheel_r1, CELL_PAD_CTRL_R1 },
{ gem_btn::racing_wheel_l2, 0 },
{ gem_btn::racing_wheel_r2, 0 },
{ gem_btn::racing_wheel_paddle_l, button_flags::rw_paddle_l },
{ gem_btn::racing_wheel_paddle_r, button_flags::rw_paddle_r },
{ gem_btn::combo_sharpshooter_firing_mode_1, button_flags::ss_firing_mode_1 },
{ gem_btn::combo_sharpshooter_firing_mode_2, button_flags::ss_firing_mode_2 },
{ gem_btn::combo_sharpshooter_firing_mode_3, button_flags::ss_firing_mode_3 },
{ gem_btn::combo_sharpshooter_trigger, button_flags::ss_trigger },
{ gem_btn::combo_sharpshooter_reload, button_flags::ss_reload },
{ gem_btn::combo_racing_wheel_d_pad_up, CELL_PAD_CTRL_UP },
{ gem_btn::combo_racing_wheel_d_pad_right, CELL_PAD_CTRL_RIGHT },
{ gem_btn::combo_racing_wheel_d_pad_down, CELL_PAD_CTRL_DOWN },
{ gem_btn::combo_racing_wheel_d_pad_left, CELL_PAD_CTRL_LEFT },
{ gem_btn::combo_racing_wheel_throttle, 0 },
{ gem_btn::combo_racing_wheel_l1, CELL_PAD_CTRL_L1 },
{ gem_btn::combo_racing_wheel_r1, CELL_PAD_CTRL_R1 },
{ gem_btn::combo_racing_wheel_l2, 0 },
{ gem_btn::combo_racing_wheel_r2, 0 },
{ gem_btn::combo_racing_wheel_paddle_l, button_flags::rw_paddle_l },
{ gem_btn::combo_racing_wheel_paddle_r, button_flags::rw_paddle_r },
};
static const std::unordered_map<gem_btn, u16> ext_btn_indices =
{
{ gem_btn::racing_wheel_throttle, 0 },
{ gem_btn::racing_wheel_l2, 1 },
{ gem_btn::racing_wheel_r2, 2 },
{ gem_btn::racing_wheel_paddle_l, 3 },
{ gem_btn::racing_wheel_paddle_r, 4 },
{ gem_btn::combo_racing_wheel_throttle, 0 },
{ gem_btn::combo_racing_wheel_l2, 1 },
{ gem_btn::combo_racing_wheel_r2, 2 },
{ gem_btn::combo_racing_wheel_paddle_l, 3 },
{ gem_btn::combo_racing_wheel_paddle_r, 4 },
};
static u32 ext_device_id(gem_ext_id id)
{
switch (id)
{
case gem_ext_id::disconnected: return 0;
case gem_ext_id::sharpshooter: return SHARP_SHOOTER_DEVICE_ID;
case gem_ext_id::racing_wheel: return RACING_WHEEL_DEVICE_ID;
}
fmt::throw_exception("Mo ID found for id = %d", static_cast<s32>(id));
}
template <bool has_combo, bool is_combo>
static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::set<pad_button>& combos, gem_btn btn, pad_button pad_btn, u16 value, bool pressed)
{
if (!pressed)
return;
if constexpr (has_combo && is_combo)
{
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_sharpshooter_firing_mode_1:
case gem_btn::combo_sharpshooter_firing_mode_2:
case gem_btn::combo_sharpshooter_firing_mode_3:
case gem_btn::combo_sharpshooter_trigger:
case gem_btn::combo_sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
default:
break;
}
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
break;
default:
break;
}
}
}
else
{
if constexpr (has_combo)
{
if (combos.contains(pad_btn))
{
return;
}
}
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
{
case gem_btn::sharpshooter_firing_mode_1:
case gem_btn::sharpshooter_firing_mode_2:
case gem_btn::sharpshooter_firing_mode_3:
case gem_btn::sharpshooter_trigger:
case gem_btn::sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
break;
default:
break;
}
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
break;
default:
break;
}
}
}
}
static void real_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
ps_move_data& move_data = pad->move_data;
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
if (!move_data.external_device_connected)
{
return;
}
// TODO:
// ext.analog_left_x
// ext.analog_left_y
// ext.analog_right_x
// ext.analog_right_y
// ext.digital1
// ext.digital2
ext.status = controller.ext_status;
std::memcpy(ext.custom, move_data.external_device_data.data(), 5);
}
static void fake_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
ps_move_data& move_data = pad->move_data;
const auto& cfg = ::at32(g_cfg_gem_fake.players, gem_num);
move_data.external_device_id = ext_device_id(cfg->external_device);
move_data.external_device_connected = move_data.external_device_id != 0;
move_data.external_device_data = {};
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
if (!move_data.external_device_connected)
{
return;
}
cfg->handle_input(pad, true, [&move_data, &ext](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
static std::set<pad_button> s_combos = {};
input_to_ext<false, false>(move_data.external_device_id, ext, s_combos, btn, pad_btn, value, pressed);
});
ext.status = controller.ext_status;
std::memcpy(ext.custom, move_data.external_device_data.data(), 5);
}
static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
auto& handler = g_fxo->get<MouseHandlerBase>();
std::scoped_lock lock(handler.mutex);
// Make sure that the mouse handler is initialized
handler.Init(std::min<u32>(g_fxo->get<gem_config>().attribute.max_connect, CELL_GEM_MAX_NUM));
if (mouse_no >= handler.GetMice().size())
{
controller.ext_status = 0;
controller.ext_id = 0;
return;
}
const Mouse& mouse_data = ::at32(handler.GetMice(), mouse_no);
const auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
const u32 external_device_id = ext_device_id(cfg->external_device);
const bool external_device_connected = external_device_id != 0;
controller.ext_status = external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = external_device_connected ? external_device_id : 0;
if (!external_device_connected)
{
return;
}
bool combo_active = false;
std::set<pad_button> combos;
// Check combo button first
cfg->handle_input(mouse_data, [&combo_active](gem_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& abort)
{
if (pressed && btn == gem_btn::combo)
{
combo_active = true;
abort = true;
}
});
// Check combos
if (combo_active)
{
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
input_to_ext<true, true>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
});
}
// Check normal buttons
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
{
input_to_ext<true, false>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
});
}
/**
* \brief Maps external Move controller data to DS3 input. (This can be input from any physical pad, not just the DS3)
* Implementation detail: CellGemExtPortData's digital/analog fields map the same way as
@ -1926,7 +2199,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co
* \param ext External data to modify
* \return true on success, false if controller is disconnected
*/
static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
static void get_external_device_input(u32 gem_num, gem_config::gem_controller& controller, CellGemExtPortData& ext)
{
ext = {};
@ -1935,53 +2208,6 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller
return;
}
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_pad_thread();
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
if (!pad->is_connected())
{
return;
}
const auto& move_data = pad->move_data;
controller.ext_status = move_data.external_device_connected ? CELL_GEM_EXT_CONNECTED : 0; // TODO: | CELL_GEM_EXT_EXT0 | CELL_GEM_EXT_EXT1
controller.ext_id = move_data.external_device_connected ? move_data.external_device_id : 0;
ext.status = controller.ext_status;
for (const AnalogStick& stick : pad->m_sticks)
{
switch (stick.m_offset)
{
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: ext.analog_left_x = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: ext.analog_left_y = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: ext.analog_right_x = stick.m_value; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: ext.analog_right_y = stick.m_value; break;
default: break;
}
}
for (const Button& button : pad->m_buttons)
{
if (!button.m_pressed)
continue;
switch (button.m_offset)
{
case CELL_PAD_BTN_OFFSET_DIGITAL1: ext.digital1 |= button.m_outKeyCode; break;
case CELL_PAD_BTN_OFFSET_DIGITAL2: ext.digital2 |= button.m_outKeyCode; break;
default: break;
}
}
if (!move_data.external_device_connected)
{
return;
}
// The sharpshooter only sets the custom bytes as follows:
// custom[0] (0x01): Firing mode selector is in position 1.
// custom[0] (0x02): Firing mode selector is in position 2.
@ -1996,7 +2222,21 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller
// custom[3] (0x01): Left paddle
// custom[3] (0x02): Right paddle
std::memcpy(ext.custom, move_data.external_device_data.data(), 5);
switch (g_cfg.io.move)
{
case move_handler::real:
real_input_to_ext(gem_num, controller, ext);
break;
case move_handler::fake:
fake_input_to_ext(gem_num, controller, ext);
break;
case move_handler::mouse:
case move_handler::raw_mouse:
mouse_input_to_ext(gem_num, controller, ext);
break;
default:
break;
}
}
/**
@ -2029,7 +2269,7 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
}
const Mouse& mouse_data = ::at32(handler.GetMice(), mouse_no);
auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
const auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
bool combo_active = false;
std::set<pad_button> combos;
@ -2759,7 +2999,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
if (g_cfg.io.move != move_handler::null)
{
ds3_input_to_ext(gem_num, gem.controllers[gem_num], inertial_state->ext);
get_external_device_input(gem_num, gem.controllers[gem_num], inertial_state->ext);
inertial_state->timestamp = (get_guest_system_time() - gem.start_timestamp_us);
inertial_state->counter = gem.inertial_counter++;
@ -2953,7 +3193,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
if (g_cfg.io.move != move_handler::null)
{
ds3_input_to_ext(gem_num, controller, gem_state->ext);
get_external_device_input(gem_num, controller, gem_state->ext);
if (controller.enabled_tracking)
{
@ -3370,7 +3610,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr<u32> ext_id, v
{
// Get external device status
CellGemExtPortData ext_port_data{};
ds3_input_to_ext(gem_num, controller, ext_port_data);
get_external_device_input(gem_num, controller, ext_port_data);
}
if (!(controller.ext_status & CELL_GEM_EXT_CONNECTED))

View file

@ -278,3 +278,37 @@ struct CellGemVideoConvertAttribute
ENABLE_BITWISE_SERIALIZATION;
};
namespace
{
enum button_flags : u16
{
select = 0x01,
start = 0x08,
triangle = 0x10,
circle = 0x20,
cross = 0x40,
square = 0x80,
ps = 0x0001,
move = 0x4008,
t = 0x8010,
ext_dev = 0x1000,
// Sharpshooter
ss_firing_mode_1 = 0x01,
ss_firing_mode_2 = 0x02,
ss_firing_mode_3 = 0x04,
ss_trigger = 0x40,
ss_reload = 0x80,
// Racing Wheel
rw_d_pad_up = 0x10,
rw_d_pad_right = 0x20,
rw_d_pad_down = 0x40,
rw_d_pad_left = 0x80,
rw_l1 = 0x04,
rw_r1 = 0x08,
rw_paddle_l = 0x01,
rw_paddle_r = 0x02,
};
}

View file

@ -464,7 +464,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
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
// These aren't pressure btns
case CELL_PAD_CTRL_R3:
case CELL_PAD_CTRL_L3:
case CELL_PAD_CTRL_START:

View file

@ -0,0 +1,83 @@
#include "stdafx.h"
#include "gem_config.h"
template <>
void fmt_class_string<gem_ext_id>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](gem_ext_id value)
{
switch (value)
{
case gem_ext_id::disconnected: return "Disconnected";
case gem_ext_id::sharpshooter: return "Sharpshooter";
case gem_ext_id::racing_wheel: return "Racing Wheel";
}
return unknown;
});
}
template <>
void fmt_class_string<gem_btn>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](gem_btn value)
{
switch (value)
{
case gem_btn::start: return "Start";
case gem_btn::select: return "Select";
case gem_btn::triangle: return "Triangle";
case gem_btn::circle: return "Circle";
case gem_btn::cross: return "Cross";
case gem_btn::square: return "Square";
case gem_btn::move: return "Move";
case gem_btn::t: return "T";
case gem_btn::x_axis: return "X-Axis";
case gem_btn::y_axis: return "Y-Axis";
case gem_btn::combo: return "Combo";
case gem_btn::combo_start: return "Combo Start";
case gem_btn::combo_select: return "Combo Select";
case gem_btn::combo_triangle: return "Combo Triangle";
case gem_btn::combo_circle: return "Combo Circle";
case gem_btn::combo_cross: return "Combo Cross";
case gem_btn::combo_square: return "Combo Square";
case gem_btn::combo_move: return "Combo Move";
case gem_btn::combo_t: return "Combo T";
case gem_btn::sharpshooter_firing_mode_1: return "Firing Mode 1";
case gem_btn::sharpshooter_firing_mode_2: return "Firing Mode 2";
case gem_btn::sharpshooter_firing_mode_3: return "Firing Mode 3";
case gem_btn::sharpshooter_trigger: return "Trigger";
case gem_btn::sharpshooter_reload: return "Reload";
case gem_btn::racing_wheel_d_pad_up: return "Up";
case gem_btn::racing_wheel_d_pad_right: return "Right";
case gem_btn::racing_wheel_d_pad_down: return "Down";
case gem_btn::racing_wheel_d_pad_left: return "Left";
case gem_btn::racing_wheel_throttle: return "Throttle";
case gem_btn::racing_wheel_l1: return "L1";
case gem_btn::racing_wheel_r1: return "R1";
case gem_btn::racing_wheel_l2: return "L2";
case gem_btn::racing_wheel_r2: return "R2";
case gem_btn::racing_wheel_paddle_l: return "Paddle L";
case gem_btn::racing_wheel_paddle_r: return "Paddle R";
case gem_btn::combo_sharpshooter_firing_mode_1: return "Combo Firing Mode 1";
case gem_btn::combo_sharpshooter_firing_mode_2: return "Combo Firing Mode 2";
case gem_btn::combo_sharpshooter_firing_mode_3: return "Combo Firing Mode 3";
case gem_btn::combo_sharpshooter_trigger: return "Combo Trigger";
case gem_btn::combo_sharpshooter_reload: return "Combo Reload";
case gem_btn::combo_racing_wheel_d_pad_up: return "Combo Up";
case gem_btn::combo_racing_wheel_d_pad_right: return "Combo Right";
case gem_btn::combo_racing_wheel_d_pad_down: return "Combo Down";
case gem_btn::combo_racing_wheel_d_pad_left: return "Combo Left";
case gem_btn::combo_racing_wheel_throttle: return "Combo Throttle";
case gem_btn::combo_racing_wheel_l1: return "Combo L1";
case gem_btn::combo_racing_wheel_r1: return "Combo R1";
case gem_btn::combo_racing_wheel_l2: return "Combo L2";
case gem_btn::combo_racing_wheel_r2: return "Combo R2";
case gem_btn::combo_racing_wheel_paddle_l: return "Combo Paddle L";
case gem_btn::combo_racing_wheel_paddle_r: return "Combo Paddle R";
case gem_btn::count: return "Count";
}
return unknown;
});
}

View file

@ -2,6 +2,13 @@
#include "emulated_pad_config.h"
enum class gem_ext_id : u32
{
disconnected,
sharpshooter,
racing_wheel
};
enum class gem_btn : u32
{
start,
@ -17,7 +24,9 @@ enum class gem_btn : u32
combo_begin,
combo = combo_begin,
combo_start,
combo_buttons_begin,
combo_start = combo_buttons_begin,
combo_select,
combo_triangle,
combo_circle,
@ -25,7 +34,52 @@ enum class gem_btn : u32
combo_square,
combo_move,
combo_t,
combo_end = combo_t,
combo_buttons_end = combo_t,
combo_end = combo_buttons_end,
sharpshooter_begin,
sharpshooter_firing_mode_1 = sharpshooter_begin,
sharpshooter_firing_mode_2,
sharpshooter_firing_mode_3,
sharpshooter_trigger,
sharpshooter_reload,
sharpshooter_end = sharpshooter_reload,
combo_sharpshooter_begin,
combo_sharpshooter_firing_mode_1 = combo_sharpshooter_begin,
combo_sharpshooter_firing_mode_2,
combo_sharpshooter_firing_mode_3,
combo_sharpshooter_trigger,
combo_sharpshooter_reload,
combo_sharpshooter_end = combo_sharpshooter_reload,
racing_wheel_begin,
racing_wheel_d_pad_up = racing_wheel_begin,
racing_wheel_d_pad_right,
racing_wheel_d_pad_down,
racing_wheel_d_pad_left,
racing_wheel_throttle,
racing_wheel_l1,
racing_wheel_r1,
racing_wheel_l2,
racing_wheel_r2,
racing_wheel_paddle_l,
racing_wheel_paddle_r,
racing_wheel_end = racing_wheel_paddle_r,
combo_racing_wheel_begin,
combo_racing_wheel_d_pad_up = combo_racing_wheel_begin,
combo_racing_wheel_d_pad_right,
combo_racing_wheel_d_pad_down,
combo_racing_wheel_d_pad_left,
combo_racing_wheel_throttle,
combo_racing_wheel_l1,
combo_racing_wheel_r1,
combo_racing_wheel_l2,
combo_racing_wheel_r2,
combo_racing_wheel_paddle_l,
combo_racing_wheel_paddle_r,
combo_racing_wheel_end = combo_racing_wheel_paddle_r,
count
};
@ -44,6 +98,26 @@ struct cfg_fake_gem final : public emulated_pad_config<gem_btn>
cfg_pad_btn<gem_btn> t{ this, "T", gem_btn::t, pad_button::R2 };
cfg_pad_btn<gem_btn> x_axis{ this, "X-Axis", gem_btn::x_axis, pad_button::ls_x };
cfg_pad_btn<gem_btn> y_axis{ this, "Y-Axis", gem_btn::y_axis, pad_button::ls_y };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_1{ this, "Sharpshooter Firing Mode 1", gem_btn::sharpshooter_firing_mode_1, pad_button::dpad_left };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_2{ this, "Sharpshooter Firing Mode 2", gem_btn::sharpshooter_firing_mode_2, pad_button::dpad_up };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_3{ this, "Sharpshooter Firing Mode 3", gem_btn::sharpshooter_firing_mode_3, pad_button::dpad_right };
cfg_pad_btn<gem_btn> sharpshooter_trigger{ this, "Sharpshooter Trigger", gem_btn::sharpshooter_trigger, pad_button::L1 };
cfg_pad_btn<gem_btn> sharpshooter_reload{ this, "Sharpshooter Reload", gem_btn::sharpshooter_reload, pad_button::L2 };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_up{ this, "Racing Wheel D-Pad Up", gem_btn::racing_wheel_d_pad_up, pad_button::dpad_up };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_right{ this, "Racing Wheel D-Pad Right", gem_btn::racing_wheel_d_pad_right, pad_button::dpad_right };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_down{ this, "Racing Wheel D-Pad Down", gem_btn::racing_wheel_d_pad_down, pad_button::dpad_down };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_left{ this, "Racing Wheel D-Pad Left", gem_btn::racing_wheel_d_pad_left, pad_button::dpad_left };
cfg_pad_btn<gem_btn> racing_wheel_throttle{ this, "Racing Wheel Throttle", gem_btn::racing_wheel_throttle, pad_button::rs_up };
cfg_pad_btn<gem_btn> racing_wheel_l1{ this, "Racing Wheel L1", gem_btn::racing_wheel_l1, pad_button::L1 };
cfg_pad_btn<gem_btn> racing_wheel_r1{ this, "Racing Wheel R1", gem_btn::racing_wheel_r1, pad_button::R1 };
cfg_pad_btn<gem_btn> racing_wheel_l2{ this, "Racing Wheel L2", gem_btn::racing_wheel_l2, pad_button::L2 };
cfg_pad_btn<gem_btn> racing_wheel_r2{ this, "Racing Wheel R2", gem_btn::racing_wheel_r2, pad_button::R2 };
cfg_pad_btn<gem_btn> racing_wheel_paddle_l{ this, "Racing Wheel Paddle L", gem_btn::racing_wheel_paddle_l, pad_button::L3 };
cfg_pad_btn<gem_btn> racing_wheel_paddle_r{ this, "Racing Wheel Paddle R", gem_btn::racing_wheel_paddle_r, pad_button::R3 };
cfg::_enum<gem_ext_id> external_device{ this, "External Device", gem_ext_id::disconnected };
};
struct cfg_fake_gems final : public emulated_pads_config<cfg_fake_gem, 4>
@ -72,6 +146,42 @@ struct cfg_mouse_gem final : public emulated_pad_config<gem_btn>
cfg_pad_btn<gem_btn> combo_square{ this, "Combo Square", gem_btn::combo_square, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_move{ this, "Combo Move", gem_btn::combo_move, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_t{ this, "Combo T", gem_btn::combo_t, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_1{ this, "Sharpshooter Firing Mode 1", gem_btn::sharpshooter_firing_mode_1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_2{ this, "Sharpshooter Firing Mode 2", gem_btn::sharpshooter_firing_mode_2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> sharpshooter_firing_mode_3{ this, "Sharpshooter Firing Mode 3", gem_btn::sharpshooter_firing_mode_3, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> sharpshooter_trigger{ this, "Sharpshooter Trigger", gem_btn::sharpshooter_trigger, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> sharpshooter_reload{ this, "Sharpshooter Reload", gem_btn::sharpshooter_reload, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_sharpshooter_firing_mode_1{ this, "Combo Sharpshooter Firing Mode 1", gem_btn::combo_sharpshooter_firing_mode_1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_sharpshooter_firing_mode_2{ this, "Combo Sharpshooter Firing Mode 2", gem_btn::combo_sharpshooter_firing_mode_2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_sharpshooter_firing_mode_3{ this, "Combo Sharpshooter Firing Mode 3", gem_btn::combo_sharpshooter_firing_mode_3, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_sharpshooter_trigger{ this, "Combo Sharpshooter Trigger", gem_btn::combo_sharpshooter_trigger, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_sharpshooter_reload{ this, "Combo Sharpshooter Reload", gem_btn::combo_sharpshooter_reload, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_up{ this, "Racing Wheel D-Pad Up", gem_btn::racing_wheel_d_pad_up, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_right{ this, "Racing Wheel D-Pad Right", gem_btn::racing_wheel_d_pad_right, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_down{ this, "Racing Wheel D-Pad Down", gem_btn::racing_wheel_d_pad_down, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_d_pad_left{ this, "Racing Wheel D-Pad Left", gem_btn::racing_wheel_d_pad_left, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_throttle{ this, "Racing Wheel Throttle", gem_btn::racing_wheel_throttle, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_l1{ this, "Racing Wheel L1", gem_btn::racing_wheel_l1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_r1{ this, "Racing Wheel R1", gem_btn::racing_wheel_r1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_l2{ this, "Racing Wheel L2", gem_btn::racing_wheel_l2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_r2{ this, "Racing Wheel R2", gem_btn::racing_wheel_r2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_paddle_l{ this, "Racing Wheel Paddle L", gem_btn::racing_wheel_paddle_l, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> racing_wheel_paddle_r{ this, "Racing Wheel Paddle R", gem_btn::racing_wheel_paddle_r, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_d_pad_up{ this, "Combo Racing Wheel D-Pad Up", gem_btn::combo_racing_wheel_d_pad_up, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_d_pad_right{ this, "Combo Racing Wheel D-Pad Right", gem_btn::combo_racing_wheel_d_pad_right, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_d_pad_down{ this, "Combo Racing Wheel D-Pad Down", gem_btn::combo_racing_wheel_d_pad_down, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_d_pad_left{ this, "Combo Racing Wheel D-Pad Left", gem_btn::combo_racing_wheel_d_pad_left, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_throttle{ this, "Combo Racing Wheel Throttle", gem_btn::combo_racing_wheel_throttle, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_l1{ this, "Combo Racing Wheel L1", gem_btn::combo_racing_wheel_l1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_r1{ this, "Combo Racing Wheel R1", gem_btn::combo_racing_wheel_r1, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_l2{ this, "Combo Racing Wheel L2", gem_btn::combo_racing_wheel_l2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_r2{ this, "Combo Racing Wheel R2", gem_btn::combo_racing_wheel_r2, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_paddle_l{ this, "Combo Racing Wheel Paddle L", gem_btn::combo_racing_wheel_paddle_l, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_racing_wheel_paddle_r{ this, "Combo Racing Wheel Paddle R", gem_btn::combo_racing_wheel_paddle_r, pad_button::pad_button_max_enum };
cfg::_enum<gem_ext_id> external_device{ this, "External Device", gem_ext_id::disconnected };
};
struct cfg_mouse_gems final : public emulated_pads_config<cfg_mouse_gem, 4>

View file

@ -13,37 +13,6 @@ namespace
constexpr id_pair MOVE_ID_ZCM1 = {0x054C, 0x03D5};
constexpr id_pair MOVE_ID_ZCM2 = {0x054C, 0x0c5e};
enum button_flags : u16
{
select = 0x01,
start = 0x08,
triangle = 0x10,
circle = 0x20,
cross = 0x40,
square = 0x80,
ps = 0x0001,
move = 0x4008,
t = 0x8010,
ext_dev = 0x1000,
// Sharpshooter
ss_firing_mode_1 = 0x01,
ss_firing_mode_2 = 0x02,
ss_firing_mode_3 = 0x04,
ss_trigger = 0x40,
ss_reload = 0x80,
// Racing Wheel
rw_d_pad_up = 0x10,
rw_d_pad_right = 0x20,
rw_d_pad_down = 0x40,
rw_d_pad_left = 0x80,
rw_l1 = 0x04,
rw_r1 = 0x08,
rw_paddle_l = 0x01,
rw_paddle_r = 0x02,
};
enum battery_status : u8
{
charge_empty = 0x00,

View file

@ -86,6 +86,7 @@
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="Emu\Io\GameTablet.cpp" />
<ClCompile Include="Emu\Io\gem_config.cpp" />
<ClCompile Include="Emu\Io\GHLtar.cpp" />
<ClCompile Include="Emu\Io\GunCon3.cpp" />
<ClCompile Include="Emu\Io\midi_config_types.cpp" />

View file

@ -1369,6 +1369,9 @@
<ClCompile Include="Emu\Io\evdev_gun_handler.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
<ClCompile Include="Emu\Io\gem_config.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -2881,4 +2884,4 @@
<Filter>Emu\GPU\RSX\Program\MSAA</Filter>
</None>
</ItemGroup>
</Project>
</Project>

View file

@ -13,11 +13,13 @@
#include "Emu/Io/usio_config.h"
#include "util/asm.hpp"
#include <QButtonGroup>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
enum button_role
@ -123,12 +125,35 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
{
ensure(!!tabs);
const bool show_mouse_legend = m_type == pad_type::mousegem;
const bool show_external_device_selection = m_type == pad_type::mousegem || m_type == pad_type::ds3gem;
if (show_mouse_legend)
{
if (!g_cfg_mouse.load())
{
cfg_log.notice("Could not restore mouse config. Using defaults.");
}
if (!g_cfg_raw_mouse.load())
{
cfg_log.notice("Could not restore raw mouse config. Using defaults.");
}
}
std::set<int> ignored_values;
const auto remove_value = [&ignored_values](int value)
{
ignored_values.insert(static_cast<int>(value));
};
const auto remove_values = [remove_value](int begin, int end)
{
for (int i = begin; i <= end; i++)
{
remove_value(i);
}
};
usz players = 0;
switch (m_type)
@ -148,22 +173,22 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
case pad_type::gem:
players = g_cfg_gem_real.players.size();
// Ignore combo, x and y axis
// Ignore combo, sharpshooter, wheel, x and y axis
remove_value(static_cast<int>(gem_btn::x_axis));
remove_value(static_cast<int>(gem_btn::y_axis));
for (int i = static_cast<int>(gem_btn::combo_begin); i <= static_cast<int>(gem_btn::combo_end); i++)
{
remove_value(i);
}
remove_values(static_cast<int>(gem_btn::sharpshooter_begin), static_cast<int>(gem_btn::sharpshooter_end));
remove_values(static_cast<int>(gem_btn::racing_wheel_begin), static_cast<int>(gem_btn::racing_wheel_end));
remove_values(static_cast<int>(gem_btn::combo_begin), static_cast<int>(gem_btn::combo_end));
remove_values(static_cast<int>(gem_btn::combo_sharpshooter_begin), static_cast<int>(gem_btn::combo_sharpshooter_end));
remove_values(static_cast<int>(gem_btn::combo_racing_wheel_begin), static_cast<int>(gem_btn::combo_racing_wheel_end));
break;
case pad_type::ds3gem:
players = g_cfg_gem_fake.players.size();
// Ignore combo
for (int i = static_cast<int>(gem_btn::combo_begin); i <= static_cast<int>(gem_btn::combo_end); i++)
{
remove_value(i);
}
remove_values(static_cast<int>(gem_btn::combo_begin), static_cast<int>(gem_btn::combo_end));
remove_values(static_cast<int>(gem_btn::combo_sharpshooter_begin), static_cast<int>(gem_btn::combo_sharpshooter_end));
remove_values(static_cast<int>(gem_btn::combo_racing_wheel_begin), static_cast<int>(gem_btn::combo_racing_wheel_end));
break;
case pad_type::mousegem:
players = g_cfg_gem_mouse.players.size();
@ -185,30 +210,18 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
constexpr u32 max_items_per_column = 6;
const int count = static_cast<int>(T::count) - static_cast<int>(ignored_values.size());
int rows = count;
int rows = show_external_device_selection ? max_items_per_column : count;
for (u32 cols = 1; utils::aligned_div(static_cast<u32>(count), cols) > max_items_per_column;)
if (!show_external_device_selection)
{
rows = utils::aligned_div(static_cast<u32>(count), ++cols);
for (u32 cols = 1; utils::aligned_div(static_cast<u32>(count), cols) > max_items_per_column;)
{
rows = utils::aligned_div(static_cast<u32>(count), ++cols);
}
}
m_combos.resize(players);
const bool show_mouse_legend = m_type == pad_type::mousegem;
if (show_mouse_legend)
{
if (!g_cfg_mouse.load())
{
cfg_log.notice("Could not restore mouse config. Using defaults.");
}
if (!g_cfg_raw_mouse.load())
{
cfg_log.notice("Could not restore raw mouse config. Using defaults.");
}
}
for (usz player = 0; player < players; player++)
{
// Create grid with all buttons
@ -228,7 +241,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
if constexpr (std::is_same_v<T, gem_btn>)
{
const gem_btn btn = static_cast<gem_btn>(i);
if (btn >= gem_btn::combo_begin && btn <= gem_btn::combo_end)
if ((btn >= gem_btn::combo_begin && btn <= gem_btn::combo_end) ||
(btn >= gem_btn::combo_sharpshooter_begin && btn <= gem_btn::combo_sharpshooter_end) ||
(btn >= gem_btn::combo_racing_wheel_begin && btn <= gem_btn::combo_racing_wheel_end))
{
gb->setToolTip(tr("Press the \"Combo\" button in combination with any of the other combo buttons to trigger their related PS Move button.\n"
"This can be useful if your device does not have enough regular buttons."));
@ -348,13 +363,19 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
}
});
if (row >= rows)
if (row >= rows ||
(show_external_device_selection &&
(i == static_cast<int>(gem_btn::combo_buttons_begin) ||
i == static_cast<int>(gem_btn::sharpshooter_begin) ||
i == static_cast<int>(gem_btn::racing_wheel_begin) ||
i == static_cast<int>(gem_btn::combo_sharpshooter_begin) ||
i == static_cast<int>(gem_btn::combo_racing_wheel_begin))))
{
row = 0;
col++;
}
::at32(m_combos, player).push_back(combo);
::at32(m_combos, player).push_back(std::make_pair(combo, gb));
h_layout->addWidget(combo);
gb->setLayout(h_layout);
grid_layout->addWidget(gb, row, col);
@ -364,6 +385,100 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
QVBoxLayout* v_layout = new QVBoxLayout(this);
// Allow to select external devices
if (show_external_device_selection)
{
QRadioButton* rb_disconnected = new QRadioButton(tr("Disconnected"), this);
QRadioButton* rb_sharpshooter = new QRadioButton(tr("Sharpshooter"), this);
QRadioButton* rb_racing_wheel = new QRadioButton(tr("Racing Wheel"), this);
QButtonGroup* bg = new QButtonGroup(this);
bg->addButton(rb_disconnected, static_cast<int>(gem_ext_id::disconnected));
bg->addButton(rb_sharpshooter, static_cast<int>(gem_ext_id::sharpshooter));
bg->addButton(rb_racing_wheel, static_cast<int>(gem_ext_id::racing_wheel));
QHBoxLayout* h_layout = new QHBoxLayout(this);
h_layout->addWidget(rb_disconnected);
h_layout->addWidget(rb_sharpshooter);
h_layout->addWidget(rb_racing_wheel);
QGroupBox* gb = new QGroupBox(tr("External Device"), this);
gb->setToolTip(tr("Select an external device to emulate."));
gb->setLayout(h_layout);
v_layout->addWidget(gb);
const auto enable_buttons = [this, player](gem_ext_id id)
{
for (auto& [combo, gb] : m_combos.at(player))
{
if (!combo || !gb)
continue;
const QVariant data = combo->itemData(0, button_role::emulated_button);
if (!data.isValid() || !data.canConvert<int>())
continue;
const int button = data.value<int>();
switch (id)
{
case gem_ext_id::disconnected:
gb->setEnabled(!(
(button >= static_cast<int>(gem_btn::sharpshooter_begin) && button <= static_cast<int>(gem_btn::sharpshooter_end)) ||
(button >= static_cast<int>(gem_btn::racing_wheel_begin) && button <= static_cast<int>(gem_btn::racing_wheel_end)) ||
(button >= static_cast<int>(gem_btn::combo_sharpshooter_begin) && button <= static_cast<int>(gem_btn::combo_sharpshooter_end)) ||
(button >= static_cast<int>(gem_btn::combo_racing_wheel_begin) && button <= static_cast<int>(gem_btn::combo_racing_wheel_end))));
break;
case gem_ext_id::sharpshooter:
gb->setEnabled(!(
(button >= static_cast<int>(gem_btn::racing_wheel_begin) && button <= static_cast<int>(gem_btn::racing_wheel_end)) ||
(button >= static_cast<int>(gem_btn::combo_racing_wheel_begin) && button <= static_cast<int>(gem_btn::combo_racing_wheel_end))));
break;
case gem_ext_id::racing_wheel:
gb->setEnabled(!(
(button >= static_cast<int>(gem_btn::sharpshooter_begin) && button <= static_cast<int>(gem_btn::sharpshooter_end)) ||
(button >= static_cast<int>(gem_btn::combo_sharpshooter_begin) && button <= static_cast<int>(gem_btn::combo_sharpshooter_end))));
break;
default:
break;
}
}
};
gem_ext_id ext_id = gem_ext_id::disconnected;
switch (m_type)
{
case pad_type::ds3gem:
ext_id = ::at32(g_cfg_gem_fake.players, player)->external_device.get();
break;
case pad_type::mousegem:
ext_id = ::at32(g_cfg_gem_mouse.players, player)->external_device.get();
break;
default:
break;
}
bg->button(static_cast<int>(ext_id))->setChecked(true);
enable_buttons(ext_id);
connect(bg, &QButtonGroup::idToggled, [this, player, enable_buttons](int id, bool checked)
{
if (!checked) return;
const gem_ext_id ext_id = static_cast<gem_ext_id>(id);
enable_buttons(ext_id);
switch (m_type)
{
case pad_type::ds3gem:
::at32(g_cfg_gem_fake.players, player)->external_device.set(ext_id);
break;
case pad_type::mousegem:
::at32(g_cfg_gem_mouse.players, player)->external_device.set(ext_id);
break;
default:
break;
}
});
}
// Create a legend of the current mouse settings
if (show_mouse_legend)
{
@ -558,7 +673,7 @@ void emulated_pad_settings_dialog::reset_config()
for (usz player = 0; player < m_combos.size(); player++)
{
for (QComboBox* combo : m_combos.at(player))
for (auto& [combo, gb] : m_combos.at(player))
{
if (!combo)
continue;

View file

@ -2,6 +2,7 @@
#include <QComboBox>
#include <QDialog>
#include <QGroupBox>
#include <QTabWidget>
#include <vector>
@ -37,5 +38,5 @@ private:
pad_type m_type;
std::vector<std::vector<QComboBox*>> m_combos;
std::vector<std::vector<std::pair<QComboBox*, QGroupBox*>>> m_combos;
};

View file

@ -359,7 +359,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
SubscribeTooltip(ui->ppu__static, tooltips.settings.ppu__static);
SubscribeTooltip(ui->ppu_llvm, tooltips.settings.ppu_llvm);
QButtonGroup *ppu_bg = new QButtonGroup(this);
QButtonGroup* ppu_bg = new QButtonGroup(this);
ppu_bg->addButton(ui->ppu__static, static_cast<int>(ppu_decoder_type::_static));
ppu_bg->addButton(ui->ppu_llvm, static_cast<int>(ppu_decoder_type::llvm));
@ -695,7 +695,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
SubscribeTooltip(ui->rb_async_with_shader_interpreter, tooltips.settings.async_with_shader_interpreter);
SubscribeTooltip(ui->rb_shader_interpreter_only, tooltips.settings.shader_interpreter_only);
QButtonGroup *shader_mode_bg = new QButtonGroup(this);
QButtonGroup* shader_mode_bg = new QButtonGroup(this);
shader_mode_bg->addButton(ui->rb_legacy_recompiler, static_cast<int>(shader_mode::recompiler));
shader_mode_bg->addButton(ui->rb_async_recompiler, static_cast<int>(shader_mode::async_recompiler));
shader_mode_bg->addButton(ui->rb_async_with_shader_interpreter, static_cast<int>(shader_mode::async_with_interpreter));
@ -1447,7 +1447,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
// Radio Buttons
// creating this in ui file keeps scrambling the order...
QButtonGroup *enter_button_assignment_bg = new QButtonGroup(this);
QButtonGroup* enter_button_assignment_bg = new QButtonGroup(this);
enter_button_assignment_bg->addButton(ui->enterButtonAssignCircle, 0);
enter_button_assignment_bg->addButton(ui->enterButtonAssignCross, 1);