mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
input: try to add tony hawk RIDE Skateboard
This commit is contained in:
parent
6dcdf6ec76
commit
0bb5974ab6
@ -221,17 +221,24 @@ void fmt_class_string<fmt::buf_to_hexstring>::format(std::string& out, u64 arg)
|
|||||||
const std::vector<u8> buf(_arg.buf, _arg.buf + _arg.len);
|
const std::vector<u8> buf(_arg.buf, _arg.buf + _arg.len);
|
||||||
out.reserve(out.size() + (buf.size() * 3));
|
out.reserve(out.size() + (buf.size() * 3));
|
||||||
static constexpr char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
static constexpr char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
const bool use_linebreak = _arg.line_length > 0;
|
||||||
|
|
||||||
for (usz index = 0; index < buf.size(); index++)
|
for (usz index = 0; index < buf.size(); index++)
|
||||||
{
|
{
|
||||||
out += hex[buf[index] >> 4];
|
if (index > 0)
|
||||||
out += hex[buf[index] & 15];
|
{
|
||||||
|
if (use_linebreak && (index % _arg.line_length) == 0)
|
||||||
if (((index + 1) % 16) == 0)
|
|
||||||
out += '\n';
|
out += '\n';
|
||||||
else
|
else
|
||||||
out += ' ';
|
out += ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_arg.with_prefix)
|
||||||
|
out += "0x";
|
||||||
|
|
||||||
|
out += hex[buf[index] >> 4];
|
||||||
|
out += hex[buf[index] & 15];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void format_byte_array(std::string& out, const uchar* data, usz size)
|
void format_byte_array(std::string& out, const uchar* data, usz size)
|
||||||
|
@ -181,11 +181,13 @@ namespace fmt
|
|||||||
|
|
||||||
struct buf_to_hexstring
|
struct buf_to_hexstring
|
||||||
{
|
{
|
||||||
buf_to_hexstring(const u8* buf, usz len)
|
buf_to_hexstring(const u8* buf, usz len, usz line_length = 16, bool with_prefix = false)
|
||||||
: buf(buf), len(len) {}
|
: buf(buf), len(len), line_length(line_length), with_prefix(with_prefix) {}
|
||||||
|
|
||||||
const u8* buf;
|
const u8* buf;
|
||||||
usz len;
|
usz len;
|
||||||
|
usz line_length;
|
||||||
|
bool with_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string_hash
|
struct string_hash
|
||||||
|
@ -75,6 +75,7 @@ target_sources(rpcs3
|
|||||||
Input/mm_joystick_handler.cpp
|
Input/mm_joystick_handler.cpp
|
||||||
Input/pad_thread.cpp
|
Input/pad_thread.cpp
|
||||||
Input/sdl_pad_handler.cpp
|
Input/sdl_pad_handler.cpp
|
||||||
|
Input/skateboard_pad_handler.cpp
|
||||||
Input/xinput_pad_handler.cpp
|
Input/xinput_pad_handler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,6 +137,9 @@ void cellPad_NotifyStateChange(usz index, u32 /*state*/)
|
|||||||
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
|
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
|
||||||
product = input::get_product_info(input::product_type::ps_move_navigation);
|
product = input::get_product_info(input::product_type::ps_move_navigation);
|
||||||
break;
|
break;
|
||||||
|
case CELL_PAD_PCLASS_TYPE_SKATEBOARD:
|
||||||
|
product = input::get_product_info(input::product_type::ride_skateboard);
|
||||||
|
break;
|
||||||
case CELL_PAD_PCLASS_TYPE_STANDARD:
|
case CELL_PAD_PCLASS_TYPE_STANDARD:
|
||||||
default:
|
default:
|
||||||
product = input::get_product_info(input::product_type::playstation_3_controller);
|
product = input::get_product_info(input::product_type::playstation_3_controller);
|
||||||
@ -301,8 +304,15 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
const u16 d1Initial = pad->m_digital_1;
|
const u16 d1Initial = pad->m_digital_1;
|
||||||
const u16 d2Initial = pad->m_digital_2;
|
const u16 d2Initial = pad->m_digital_2;
|
||||||
|
|
||||||
const auto set_value = [&btnChanged](u16& value, u16 new_value)
|
// Check if this pad is configured as a skateboard which ignores sticks and pressure button values.
|
||||||
|
// Curiously it maps infrared on the press value of the face buttons for some reason.
|
||||||
|
const bool use_piggyback = pad->m_class_type == CELL_PAD_PCLASS_TYPE_SKATEBOARD;
|
||||||
|
|
||||||
|
const auto set_value = [&btnChanged, use_piggyback](u16& value, u16 new_value, bool is_piggyback = false)
|
||||||
{
|
{
|
||||||
|
if (use_piggyback && !is_piggyback)
|
||||||
|
return;
|
||||||
|
|
||||||
if (value != new_value)
|
if (value != new_value)
|
||||||
{
|
{
|
||||||
btnChanged = true;
|
btnChanged = true;
|
||||||
@ -315,7 +325,9 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
// here we check btns, and set pad accordingly,
|
// here we check btns, and set pad accordingly,
|
||||||
// if something changed, set btnChanged
|
// if something changed, set btnChanged
|
||||||
|
|
||||||
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
|
switch (button.m_offset)
|
||||||
|
{
|
||||||
|
case CELL_PAD_BTN_OFFSET_DIGITAL1:
|
||||||
{
|
{
|
||||||
if (button.m_pressed)
|
if (button.m_pressed)
|
||||||
pad->m_digital_1 |= button.m_outKeyCode;
|
pad->m_digital_1 |= button.m_outKeyCode;
|
||||||
@ -335,8 +347,9 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
case CELL_PAD_CTRL_SELECT:
|
case CELL_PAD_CTRL_SELECT:
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
|
case CELL_PAD_BTN_OFFSET_DIGITAL2:
|
||||||
{
|
{
|
||||||
if (button.m_pressed)
|
if (button.m_pressed)
|
||||||
pad->m_digital_2 |= button.m_outKeyCode;
|
pad->m_digital_2 |= button.m_outKeyCode;
|
||||||
@ -355,6 +368,30 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break;
|
case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK:
|
||||||
|
{
|
||||||
|
switch (button.m_outKeyCode)
|
||||||
|
{
|
||||||
|
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); break;
|
||||||
|
case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true); break;
|
||||||
|
case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true); break;
|
||||||
|
case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true); break;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,10 +413,10 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
{
|
{
|
||||||
switch (sensor.m_offset)
|
switch (sensor.m_offset)
|
||||||
{
|
{
|
||||||
case CELL_PAD_BTN_OFFSET_SENSOR_X: set_value(pad->m_sensor_x, sensor.m_value); break;
|
case CELL_PAD_BTN_OFFSET_SENSOR_X: set_value(pad->m_sensor_x, sensor.m_value, true); break;
|
||||||
case CELL_PAD_BTN_OFFSET_SENSOR_Y: set_value(pad->m_sensor_y, sensor.m_value); break;
|
case CELL_PAD_BTN_OFFSET_SENSOR_Y: set_value(pad->m_sensor_y, sensor.m_value, true); break;
|
||||||
case CELL_PAD_BTN_OFFSET_SENSOR_Z: set_value(pad->m_sensor_z, sensor.m_value); break;
|
case CELL_PAD_BTN_OFFSET_SENSOR_Z: set_value(pad->m_sensor_z, sensor.m_value, true); break;
|
||||||
case CELL_PAD_BTN_OFFSET_SENSOR_G: set_value(pad->m_sensor_g, sensor.m_value); break;
|
case CELL_PAD_BTN_OFFSET_SENSOR_G: set_value(pad->m_sensor_g, sensor.m_value, true); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,8 +483,8 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_CROSS] = pad->m_press_cross;
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_CROSS] = pad->m_press_cross;
|
||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE] = pad->m_press_square;
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE] = pad->m_press_square;
|
||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_L1] = pad->m_press_L1;
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_L1] = pad->m_press_L1;
|
||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_L2] = pad->m_press_L2;
|
|
||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_R1] = pad->m_press_R1;
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_R1] = pad->m_press_R1;
|
||||||
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_L2] = pad->m_press_L2;
|
||||||
data->button[CELL_PAD_BTN_OFFSET_PRESS_R2] = pad->m_press_R2;
|
data->button[CELL_PAD_BTN_OFFSET_PRESS_R2] = pad->m_press_R2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -494,6 +531,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
|||||||
default:
|
default:
|
||||||
case CELL_PAD_PCLASS_TYPE_STANDARD:
|
case CELL_PAD_PCLASS_TYPE_STANDARD:
|
||||||
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
|
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
|
||||||
|
case CELL_PAD_PCLASS_TYPE_SKATEBOARD:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,9 @@ usb_handler_thread::usb_handler_thread()
|
|||||||
|
|
||||||
// EA Active 2 dongle for connecting wristbands & legband
|
// EA Active 2 dongle for connecting wristbands & legband
|
||||||
check_device(0x21A4, 0xAC27, 0xAC27, "EA Active 2 Dongle");
|
check_device(0x21A4, 0xAC27, 0xAC27, "EA Active 2 Dongle");
|
||||||
|
|
||||||
|
// Tony Hawk RIDE Skateboard
|
||||||
|
check_device(0x12BA, 0x0400, 0x0400, "Tony Hawk RIDE Skateboard Controller");
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_free_device_list(list, 1);
|
libusb_free_device_list(list, 1);
|
||||||
|
@ -454,19 +454,21 @@ bool PadHandlerBase::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_id)
|
|||||||
std::array<std::set<u32>, button::button_count> mapping = get_mapped_key_codes(pad_device, config);
|
std::array<std::set<u32>, button::button_count> mapping = get_mapped_key_codes(pad_device, config);
|
||||||
|
|
||||||
u32 pclass_profile = 0x0;
|
u32 pclass_profile = 0x0;
|
||||||
|
u32 capabilities = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE;
|
||||||
|
|
||||||
for (const input::product_info& product : input::get_products_by_class(config->device_class_type))
|
for (const input::product_info& product : input::get_products_by_class(config->device_class_type))
|
||||||
{
|
{
|
||||||
if (product.vendor_id == config->vendor_id && product.product_id == config->product_id)
|
if (product.vendor_id == config->vendor_id && product.product_id == config->product_id)
|
||||||
{
|
{
|
||||||
pclass_profile = product.pclass_profile;
|
pclass_profile = product.pclass_profile;
|
||||||
|
capabilities = product.capabilites;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->Init
|
pad->Init
|
||||||
(
|
(
|
||||||
CELL_PAD_STATUS_DISCONNECTED,
|
CELL_PAD_STATUS_DISCONNECTED,
|
||||||
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE,
|
capabilities,
|
||||||
CELL_PAD_DEV_TYPE_STANDARD,
|
CELL_PAD_DEV_TYPE_STANDARD,
|
||||||
config->device_class_type,
|
config->device_class_type,
|
||||||
pclass_profile,
|
pclass_profile,
|
||||||
@ -496,6 +498,16 @@ bool PadHandlerBase::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_id)
|
|||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, mapping[button::select], CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, mapping[button::select], CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, mapping[button::ps], CELL_PAD_CTRL_PS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, mapping[button::ps], CELL_PAD_CTRL_PS);
|
||||||
|
|
||||||
|
if (pad->m_class_type == CELL_PAD_PCLASS_TYPE_SKATEBOARD)
|
||||||
|
{
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_ir_nose], CELL_PAD_CTRL_PRESS_TRIANGLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_ir_tail], CELL_PAD_CTRL_PRESS_CIRCLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_ir_left], CELL_PAD_CTRL_PRESS_CROSS);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_ir_right], CELL_PAD_CTRL_PRESS_SQUARE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_tilt_left], CELL_PAD_CTRL_PRESS_L1);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, mapping[button::skateboard_tilt_right], CELL_PAD_CTRL_PRESS_R1);
|
||||||
|
}
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, mapping[button::ls_left], mapping[button::ls_right]);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, mapping[button::ls_left], mapping[button::ls_right]);
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, mapping[button::ls_down], mapping[button::ls_up]);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, mapping[button::ls_down], mapping[button::ls_up]);
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, mapping[button::rs_left], mapping[button::rs_right]);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, mapping[button::rs_left], mapping[button::rs_right]);
|
||||||
@ -557,6 +569,13 @@ std::array<std::set<u32>, PadHandlerBase::button::button_count> PadHandlerBase::
|
|||||||
mapping[button::rs_up] = narrow_set(device->axis_code_right[3]);
|
mapping[button::rs_up] = narrow_set(device->axis_code_right[3]);
|
||||||
mapping[button::ps] = FindKeyCodes<u32, u32>(button_list, cfg->ps);
|
mapping[button::ps] = FindKeyCodes<u32, u32>(button_list, cfg->ps);
|
||||||
|
|
||||||
|
mapping[button::skateboard_ir_nose] = FindKeyCodes<u32, u32>(button_list, cfg->ir_nose);
|
||||||
|
mapping[button::skateboard_ir_tail] = FindKeyCodes<u32, u32>(button_list, cfg->ir_tail);
|
||||||
|
mapping[button::skateboard_ir_left] = FindKeyCodes<u32, u32>(button_list, cfg->ir_left);
|
||||||
|
mapping[button::skateboard_ir_right] = FindKeyCodes<u32, u32>(button_list, cfg->ir_right);
|
||||||
|
mapping[button::skateboard_tilt_left] = FindKeyCodes<u32, u32>(button_list, cfg->tilt_left);
|
||||||
|
mapping[button::skateboard_tilt_right] = FindKeyCodes<u32, u32>(button_list, cfg->tilt_right);
|
||||||
|
|
||||||
mapping[button::pressure_intensity_button] = FindKeyCodes<u32, u32>(button_list, cfg->pressure_intensity_button);
|
mapping[button::pressure_intensity_button] = FindKeyCodes<u32, u32>(button_list, cfg->pressure_intensity_button);
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
|
@ -98,6 +98,13 @@ protected:
|
|||||||
rs_down,
|
rs_down,
|
||||||
rs_up,
|
rs_up,
|
||||||
|
|
||||||
|
skateboard_ir_nose,
|
||||||
|
skateboard_ir_tail,
|
||||||
|
skateboard_ir_left,
|
||||||
|
skateboard_ir_right,
|
||||||
|
skateboard_tilt_left,
|
||||||
|
skateboard_tilt_right,
|
||||||
|
|
||||||
pressure_intensity_button,
|
pressure_intensity_button,
|
||||||
|
|
||||||
button_count
|
button_count
|
||||||
|
@ -54,6 +54,13 @@ struct cfg_pad final : cfg::node
|
|||||||
cfg::string l2{ this, "L2", "" };
|
cfg::string l2{ this, "L2", "" };
|
||||||
cfg::string l3{ this, "L3", "" };
|
cfg::string l3{ this, "L3", "" };
|
||||||
|
|
||||||
|
cfg::string ir_nose{ this, "IR Nose", "" };
|
||||||
|
cfg::string ir_tail{ this, "IR Tail", "" };
|
||||||
|
cfg::string ir_left{ this, "IR Left", "" };
|
||||||
|
cfg::string ir_right{ this, "IR Right", "" };
|
||||||
|
cfg::string tilt_left{ this, "Tilt Left", "" };
|
||||||
|
cfg::string tilt_right{ this, "Tilt Right", "" };
|
||||||
|
|
||||||
cfg_sensor motion_sensor_x{ this, "Motion Sensor X" };
|
cfg_sensor motion_sensor_x{ this, "Motion Sensor X" };
|
||||||
cfg_sensor motion_sensor_y{ this, "Motion Sensor Y" };
|
cfg_sensor motion_sensor_y{ this, "Motion Sensor Y" };
|
||||||
cfg_sensor motion_sensor_z{ this, "Motion Sensor Z" };
|
cfg_sensor motion_sensor_z{ this, "Motion Sensor Z" };
|
||||||
@ -97,7 +104,7 @@ struct cfg_pad final : cfg::node
|
|||||||
cfg::uint<0, 100> analog_lerp_factor{ this, "Analog Button Lerp Factor", 100 };
|
cfg::uint<0, 100> analog_lerp_factor{ this, "Analog Button Lerp Factor", 100 };
|
||||||
cfg::uint<0, 100> trigger_lerp_factor{ this, "Trigger Lerp Factor", 100 };
|
cfg::uint<0, 100> trigger_lerp_factor{ this, "Trigger Lerp Factor", 100 };
|
||||||
|
|
||||||
cfg::uint<CELL_PAD_PCLASS_TYPE_STANDARD, CELL_PAD_PCLASS_TYPE_NAVIGATION> device_class_type{ this, "Device Class Type", 0 };
|
cfg::uint<CELL_PAD_PCLASS_TYPE_STANDARD, CELL_PAD_PCLASS_TYPE_SKATEBOARD> device_class_type{ this, "Device Class Type", 0 };
|
||||||
cfg::uint<0, 65535> vendor_id{ this, "Vendor ID", 0 };
|
cfg::uint<0, 65535> vendor_id{ this, "Vendor ID", 0 };
|
||||||
cfg::uint<0, 65535> product_id{ this, "Product ID", 0 };
|
cfg::uint<0, 65535> product_id{ this, "Product ID", 0 };
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@ void fmt_class_string<pad_handler>::format(std::string& out, u64 arg)
|
|||||||
case pad_handler::ds3: return "DualShock 3";
|
case pad_handler::ds3: return "DualShock 3";
|
||||||
case pad_handler::ds4: return "DualShock 4";
|
case pad_handler::ds4: return "DualShock 4";
|
||||||
case pad_handler::dualsense: return "DualSense";
|
case pad_handler::dualsense: return "DualSense";
|
||||||
|
case pad_handler::skateboard: return "Skateboard";
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case pad_handler::xinput: return "XInput";
|
case pad_handler::xinput: return "XInput";
|
||||||
case pad_handler::mm: return "MMJoystick";
|
case pad_handler::mm: return "MMJoystick";
|
||||||
|
@ -9,6 +9,7 @@ enum class pad_handler
|
|||||||
ds3,
|
ds3,
|
||||||
ds4,
|
ds4,
|
||||||
dualsense,
|
dualsense,
|
||||||
|
skateboard,
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
xinput,
|
xinput,
|
||||||
mm,
|
mm,
|
||||||
|
@ -133,6 +133,7 @@ enum
|
|||||||
CELL_PAD_PCLASS_TYPE_DJ = 0x03,
|
CELL_PAD_PCLASS_TYPE_DJ = 0x03,
|
||||||
CELL_PAD_PCLASS_TYPE_DANCEMAT = 0x04,
|
CELL_PAD_PCLASS_TYPE_DANCEMAT = 0x04,
|
||||||
CELL_PAD_PCLASS_TYPE_NAVIGATION = 0x05,
|
CELL_PAD_PCLASS_TYPE_NAVIGATION = 0x05,
|
||||||
|
CELL_PAD_PCLASS_TYPE_SKATEBOARD = 0x8001,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Profile of a Standard Type Controller
|
// Profile of a Standard Type Controller
|
||||||
@ -234,6 +235,9 @@ enum ButtonDataOffset
|
|||||||
CELL_PAD_BTN_OFFSET_SENSOR_Y = 21,
|
CELL_PAD_BTN_OFFSET_SENSOR_Y = 21,
|
||||||
CELL_PAD_BTN_OFFSET_SENSOR_Z = 22,
|
CELL_PAD_BTN_OFFSET_SENSOR_Z = 22,
|
||||||
CELL_PAD_BTN_OFFSET_SENSOR_G = 23,
|
CELL_PAD_BTN_OFFSET_SENSOR_G = 23,
|
||||||
|
|
||||||
|
// Fake helpers
|
||||||
|
CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CellPadPeriphGuitarBtnDataOffset
|
enum CellPadPeriphGuitarBtnDataOffset
|
||||||
@ -318,6 +322,23 @@ static constexpr u16 DEFAULT_MOTION_Y = 399;
|
|||||||
static constexpr u16 DEFAULT_MOTION_Z = 512;
|
static constexpr u16 DEFAULT_MOTION_Z = 512;
|
||||||
static constexpr u16 DEFAULT_MOTION_G = 512;
|
static constexpr u16 DEFAULT_MOTION_G = 512;
|
||||||
|
|
||||||
|
// Fake helper enum
|
||||||
|
enum PressurePiggybackFlags : u32
|
||||||
|
{
|
||||||
|
CELL_PAD_CTRL_PRESS_RIGHT = CELL_PAD_BTN_OFFSET_PRESS_RIGHT,
|
||||||
|
CELL_PAD_CTRL_PRESS_LEFT = CELL_PAD_BTN_OFFSET_PRESS_LEFT,
|
||||||
|
CELL_PAD_CTRL_PRESS_UP = CELL_PAD_BTN_OFFSET_PRESS_UP,
|
||||||
|
CELL_PAD_CTRL_PRESS_DOWN = CELL_PAD_BTN_OFFSET_PRESS_DOWN,
|
||||||
|
CELL_PAD_CTRL_PRESS_TRIANGLE = CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE,
|
||||||
|
CELL_PAD_CTRL_PRESS_CIRCLE = CELL_PAD_BTN_OFFSET_PRESS_CIRCLE,
|
||||||
|
CELL_PAD_CTRL_PRESS_CROSS = CELL_PAD_BTN_OFFSET_PRESS_CROSS,
|
||||||
|
CELL_PAD_CTRL_PRESS_SQUARE = CELL_PAD_BTN_OFFSET_PRESS_SQUARE,
|
||||||
|
CELL_PAD_CTRL_PRESS_L1 = CELL_PAD_BTN_OFFSET_PRESS_L1,
|
||||||
|
CELL_PAD_CTRL_PRESS_R1 = CELL_PAD_BTN_OFFSET_PRESS_R1,
|
||||||
|
CELL_PAD_CTRL_PRESS_L2 = CELL_PAD_BTN_OFFSET_PRESS_L2,
|
||||||
|
CELL_PAD_CTRL_PRESS_R2 = CELL_PAD_BTN_OFFSET_PRESS_R2,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr u32 special_button_offset = 666; // Must not conflict with other CELL offsets like ButtonDataOffset
|
constexpr u32 special_button_offset = 666; // Must not conflict with other CELL offsets like ButtonDataOffset
|
||||||
|
|
||||||
enum special_button_value
|
enum special_button_value
|
||||||
|
@ -345,7 +345,7 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
|
|||||||
|
|
||||||
std::array<u8, 128> buf{};
|
std::array<u8, 128> buf{};
|
||||||
|
|
||||||
const int res = hid_read(device->hidDevice, buf.data(), 128);
|
const int res = hid_read(device->hidDevice, buf.data(), buf.size());
|
||||||
|
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
{
|
{
|
||||||
|
@ -1359,6 +1359,16 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
|
|||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->right), CELL_PAD_CTRL_RIGHT);
|
||||||
|
|
||||||
|
if (pad->m_class_type == CELL_PAD_PCLASS_TYPE_SKATEBOARD)
|
||||||
|
{
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->ir_nose), CELL_PAD_CTRL_PRESS_TRIANGLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->ir_tail), CELL_PAD_CTRL_PRESS_CIRCLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->ir_left), CELL_PAD_CTRL_PRESS_CROSS);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->ir_right), CELL_PAD_CTRL_PRESS_SQUARE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->tilt_left), CELL_PAD_CTRL_PRESS_L1);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_buttons(cfg->tilt_right), CELL_PAD_CTRL_PRESS_R1);
|
||||||
|
}
|
||||||
|
|
||||||
m_dev->axis_left[0] = find_buttons(cfg->ls_right);
|
m_dev->axis_left[0] = find_buttons(cfg->ls_right);
|
||||||
m_dev->axis_left[1] = find_buttons(cfg->ls_left);
|
m_dev->axis_left[1] = find_buttons(cfg->ls_left);
|
||||||
m_dev->axis_left[2] = find_buttons(cfg->ls_up);
|
m_dev->axis_left[2] = find_buttons(cfg->ls_up);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "ds3_pad_handler.h"
|
#include "ds3_pad_handler.h"
|
||||||
#include "ds4_pad_handler.h"
|
#include "ds4_pad_handler.h"
|
||||||
#include "dualsense_pad_handler.h"
|
#include "dualsense_pad_handler.h"
|
||||||
|
#include "skateboard_pad_handler.h"
|
||||||
#include "util/logs.hpp"
|
#include "util/logs.hpp"
|
||||||
#include "Utilities/Timer.h"
|
#include "Utilities/Timer.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
@ -267,3 +268,4 @@ u32 hid_pad_handler<Device>::get_battery_color(u8 battery_level, u32 brightness)
|
|||||||
template class hid_pad_handler<ds3_device>;
|
template class hid_pad_handler<ds3_device>;
|
||||||
template class hid_pad_handler<DS4Device>;
|
template class hid_pad_handler<DS4Device>;
|
||||||
template class hid_pad_handler<DualSenseDevice>;
|
template class hid_pad_handler<DualSenseDevice>;
|
||||||
|
template class hid_pad_handler<skateboard_device>;
|
||||||
|
@ -963,6 +963,16 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_i
|
|||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->r2), CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->r2), CELL_PAD_CTRL_R2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->l2), CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->l2), CELL_PAD_CTRL_L2);
|
||||||
|
|
||||||
|
if (pad->m_class_type == CELL_PAD_PCLASS_TYPE_SKATEBOARD)
|
||||||
|
{
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->ir_nose), CELL_PAD_CTRL_PRESS_TRIANGLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->ir_tail), CELL_PAD_CTRL_PRESS_CIRCLE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->ir_left), CELL_PAD_CTRL_PRESS_CROSS);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->ir_right), CELL_PAD_CTRL_PRESS_SQUARE);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->tilt_left), CELL_PAD_CTRL_PRESS_L1);
|
||||||
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK, find_keys(cfg->tilt_right), CELL_PAD_CTRL_PRESS_R1);
|
||||||
|
}
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_keys(cfg->ls_left), find_keys(cfg->ls_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_keys(cfg->ls_left), find_keys(cfg->ls_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_keys(cfg->ls_up), find_keys(cfg->ls_down));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_keys(cfg->ls_up), find_keys(cfg->ls_down));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_keys(cfg->rs_left), find_keys(cfg->rs_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_keys(cfg->rs_left), find_keys(cfg->rs_right));
|
||||||
|
@ -174,6 +174,13 @@ std::array<std::set<u32>, PadHandlerBase::button::button_count> mm_joystick_hand
|
|||||||
mapping[button::rs_down] = narrow_set(joy_device->axis_code_right[2]);
|
mapping[button::rs_down] = narrow_set(joy_device->axis_code_right[2]);
|
||||||
mapping[button::rs_up] = narrow_set(joy_device->axis_code_right[3]);
|
mapping[button::rs_up] = narrow_set(joy_device->axis_code_right[3]);
|
||||||
|
|
||||||
|
mapping[button::skateboard_ir_nose] = find_keys<u32>(cfg->ir_nose);
|
||||||
|
mapping[button::skateboard_ir_tail] = find_keys<u32>(cfg->ir_tail);
|
||||||
|
mapping[button::skateboard_ir_left] = find_keys<u32>(cfg->ir_left);
|
||||||
|
mapping[button::skateboard_ir_right] = find_keys<u32>(cfg->ir_right);
|
||||||
|
mapping[button::skateboard_tilt_left] = find_keys<u32>(cfg->tilt_left);
|
||||||
|
mapping[button::skateboard_tilt_right] = find_keys<u32>(cfg->tilt_right);
|
||||||
|
|
||||||
mapping[button::pressure_intensity_button] = find_keys<u32>(cfg->pressure_intensity_button);
|
mapping[button::pressure_intensity_button] = find_keys<u32>(cfg->pressure_intensity_button);
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "ds3_pad_handler.h"
|
#include "ds3_pad_handler.h"
|
||||||
#include "ds4_pad_handler.h"
|
#include "ds4_pad_handler.h"
|
||||||
#include "dualsense_pad_handler.h"
|
#include "dualsense_pad_handler.h"
|
||||||
|
#include "skateboard_pad_handler.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "xinput_pad_handler.h"
|
#include "xinput_pad_handler.h"
|
||||||
#include "mm_joystick_handler.h"
|
#include "mm_joystick_handler.h"
|
||||||
@ -168,6 +169,9 @@ void pad_thread::Init()
|
|||||||
case pad_handler::dualsense:
|
case pad_handler::dualsense:
|
||||||
cur_pad_handler = std::make_shared<dualsense_pad_handler>();
|
cur_pad_handler = std::make_shared<dualsense_pad_handler>();
|
||||||
break;
|
break;
|
||||||
|
case pad_handler::skateboard:
|
||||||
|
cur_pad_handler = std::make_shared<skateboard_pad_handler>();
|
||||||
|
break;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case pad_handler::xinput:
|
case pad_handler::xinput:
|
||||||
cur_pad_handler = std::make_shared<xinput_pad_handler>();
|
cur_pad_handler = std::make_shared<xinput_pad_handler>();
|
||||||
@ -558,7 +562,7 @@ void pad_thread::InitLddPad(u32 handle, const u32* port_status)
|
|||||||
port_status ? *port_status : CELL_PAD_STATUS_CONNECTED | CELL_PAD_STATUS_ASSIGN_CHANGES | CELL_PAD_STATUS_CUSTOM_CONTROLLER,
|
port_status ? *port_status : CELL_PAD_STATUS_CONNECTED | CELL_PAD_STATUS_ASSIGN_CHANGES | CELL_PAD_STATUS_CUSTOM_CONTROLLER,
|
||||||
CELL_PAD_CAPABILITY_PS3_CONFORMITY,
|
CELL_PAD_CAPABILITY_PS3_CONFORMITY,
|
||||||
CELL_PAD_DEV_TYPE_LDD,
|
CELL_PAD_DEV_TYPE_LDD,
|
||||||
0, // CELL_PAD_PCLASS_TYPE_STANDARD
|
CELL_PAD_PCLASS_TYPE_STANDARD,
|
||||||
product.pclass_profile,
|
product.pclass_profile,
|
||||||
product.vendor_id,
|
product.vendor_id,
|
||||||
product.product_id,
|
product.product_id,
|
||||||
@ -609,6 +613,8 @@ std::shared_ptr<PadHandlerBase> pad_thread::GetHandler(pad_handler type)
|
|||||||
return std::make_unique<ds4_pad_handler>();
|
return std::make_unique<ds4_pad_handler>();
|
||||||
case pad_handler::dualsense:
|
case pad_handler::dualsense:
|
||||||
return std::make_unique<dualsense_pad_handler>();
|
return std::make_unique<dualsense_pad_handler>();
|
||||||
|
case pad_handler::skateboard:
|
||||||
|
return std::make_unique<skateboard_pad_handler>();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case pad_handler::xinput:
|
case pad_handler::xinput:
|
||||||
return std::make_unique<xinput_pad_handler>();
|
return std::make_unique<xinput_pad_handler>();
|
||||||
|
@ -16,7 +16,8 @@ namespace input
|
|||||||
harmonix_rockband_drum_kit,
|
harmonix_rockband_drum_kit,
|
||||||
harmonix_rockband_drum_kit_2,
|
harmonix_rockband_drum_kit_2,
|
||||||
rock_revolution_drum_kit,
|
rock_revolution_drum_kit,
|
||||||
ps_move_navigation
|
ps_move_navigation,
|
||||||
|
ride_skateboard
|
||||||
};
|
};
|
||||||
|
|
||||||
enum vendor_id
|
enum vendor_id
|
||||||
@ -38,6 +39,7 @@ namespace input
|
|||||||
rock_revolution_drum_kit = 0x0300, // Rock Revolution Drum Controller
|
rock_revolution_drum_kit = 0x0300, // Rock Revolution Drum Controller
|
||||||
ps_move_navigation = 0x042F, // PlayStation Move navigation controller
|
ps_move_navigation = 0x042F, // PlayStation Move navigation controller
|
||||||
dance_dance_revolution_mat = 0x1010, // Dance Dance Revolution Dance Mat Controller
|
dance_dance_revolution_mat = 0x1010, // Dance Dance Revolution Dance Mat Controller
|
||||||
|
ride_skateboard = 0x0400, // Tony Hawk RIDE Skateboard Controller
|
||||||
};
|
};
|
||||||
|
|
||||||
struct product_info
|
struct product_info
|
||||||
@ -46,6 +48,7 @@ namespace input
|
|||||||
u16 vendor_id;
|
u16 vendor_id;
|
||||||
u16 product_id;
|
u16 product_id;
|
||||||
u32 pclass_profile; // See CELL_PAD_PCLASS_PROFILE flags
|
u32 pclass_profile; // See CELL_PAD_PCLASS_PROFILE flags
|
||||||
|
u32 capabilites; // See CELL_PAD_CAPABILITY flags
|
||||||
};
|
};
|
||||||
|
|
||||||
inline product_info get_product_info(product_type type)
|
inline product_info get_product_info(product_type type)
|
||||||
@ -67,7 +70,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::konami_de,
|
.vendor_id = vendor_id::konami_de,
|
||||||
.product_id = product_id::dance_dance_revolution_mat,
|
.product_id = product_id::dance_dance_revolution_mat,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::dj_hero_turntable:
|
case product_type::dj_hero_turntable:
|
||||||
@ -88,7 +92,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::dj_hero_turntable,
|
.product_id = product_id::dj_hero_turntable,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::harmonix_rockband_drum_kit:
|
case product_type::harmonix_rockband_drum_kit:
|
||||||
@ -106,7 +111,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::harmonix_rockband_drum_kit,
|
.product_id = product_id::harmonix_rockband_drum_kit,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::harmonix_rockband_drum_kit_2:
|
case product_type::harmonix_rockband_drum_kit_2:
|
||||||
@ -123,7 +129,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::harmonix_rockband_drum_kit_2,
|
.product_id = product_id::harmonix_rockband_drum_kit_2,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::harmonix_rockband_guitar:
|
case product_type::harmonix_rockband_guitar:
|
||||||
@ -148,7 +155,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::harmonix_rockband_guitar,
|
.product_id = product_id::harmonix_rockband_guitar,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::red_octane_gh_drum_kit:
|
case product_type::red_octane_gh_drum_kit:
|
||||||
@ -164,7 +172,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::red_octane_gh_drum_kit,
|
.product_id = product_id::red_octane_gh_drum_kit,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::red_octane_gh_guitar:
|
case product_type::red_octane_gh_guitar:
|
||||||
@ -182,7 +191,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::red_octane_gh_guitar,
|
.product_id = product_id::red_octane_gh_guitar,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::rock_revolution_drum_kit:
|
case product_type::rock_revolution_drum_kit:
|
||||||
@ -199,7 +209,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_cea,
|
.vendor_id = vendor_id::sony_cea,
|
||||||
.product_id = product_id::rock_revolution_drum_kit,
|
.product_id = product_id::rock_revolution_drum_kit,
|
||||||
.pclass_profile = profile
|
.pclass_profile = profile,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::ps_move_navigation:
|
case product_type::ps_move_navigation:
|
||||||
@ -208,7 +219,18 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_corp,
|
.vendor_id = vendor_id::sony_corp,
|
||||||
.product_id = product_id::ps_move_navigation,
|
.product_id = product_id::ps_move_navigation,
|
||||||
.pclass_profile = 0x0
|
.pclass_profile = 0x0,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case product_type::ride_skateboard:
|
||||||
|
{
|
||||||
|
return product_info{
|
||||||
|
.type = type,
|
||||||
|
.vendor_id = vendor_id::sony_cea,
|
||||||
|
.product_id = product_id::ride_skateboard,
|
||||||
|
.pclass_profile = 0x0,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case product_type::playstation_3_controller:
|
case product_type::playstation_3_controller:
|
||||||
@ -218,7 +240,8 @@ namespace input
|
|||||||
.type = type,
|
.type = type,
|
||||||
.vendor_id = vendor_id::sony_corp,
|
.vendor_id = vendor_id::sony_corp,
|
||||||
.product_id = product_id::playstation_3_controller,
|
.product_id = product_id::playstation_3_controller,
|
||||||
.pclass_profile = 0x0
|
.pclass_profile = 0x0,
|
||||||
|
.capabilites = CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,6 +298,13 @@ namespace input
|
|||||||
get_product_info(product_type::ps_move_navigation)
|
get_product_info(product_type::ps_move_navigation)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case CELL_PAD_PCLASS_TYPE_SKATEBOARD:
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
get_product_info(product_type::ride_skateboard)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
379
rpcs3/Input/skateboard_pad_handler.cpp
Normal file
379
rpcs3/Input/skateboard_pad_handler.cpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "skateboard_pad_handler.h"
|
||||||
|
#include "Emu/Io/pad_config.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(skateboard_log, "Skateboard");
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr id_pair SKATEBOARD_ID_0 = {0x12BA, 0x0400}; // Tony Hawk RIDE Skateboard
|
||||||
|
|
||||||
|
enum button_flags : u16
|
||||||
|
{
|
||||||
|
square = 0x0001,
|
||||||
|
cross = 0x0002,
|
||||||
|
circle = 0x0004,
|
||||||
|
triangle = 0x0008,
|
||||||
|
select = 0x0100,
|
||||||
|
start = 0x0200,
|
||||||
|
ps = 0x1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dpad_states : u8
|
||||||
|
{
|
||||||
|
up = 0x00,
|
||||||
|
up_right = 0x01,
|
||||||
|
left = 0x02,
|
||||||
|
down_right = 0x03,
|
||||||
|
down = 0x04,
|
||||||
|
down_left = 0x05,
|
||||||
|
right = 0x06,
|
||||||
|
up_left = 0x07,
|
||||||
|
none = 0x0F,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default data if dongle is connected but the skateboard is turned off:
|
||||||
|
static constexpr std::array<u8, sizeof(skateboard_input_report)> not_connected_state = { 0x00, 0x00, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02 };
|
||||||
|
static constexpr std::array<u8, sizeof(skateboard_input_report)> disconnected_state = { 0x00, 0x00, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
|
}
|
||||||
|
|
||||||
|
skateboard_pad_handler::skateboard_pad_handler()
|
||||||
|
: hid_pad_handler<skateboard_device>(pad_handler::skateboard, {SKATEBOARD_ID_0})
|
||||||
|
{
|
||||||
|
// Unique names for the config files and our pad settings dialog
|
||||||
|
button_list =
|
||||||
|
{
|
||||||
|
{ skateboard_key_codes::none, "" },
|
||||||
|
{ skateboard_key_codes::left, "Left" },
|
||||||
|
{ skateboard_key_codes::right, "Right" },
|
||||||
|
{ skateboard_key_codes::up, "Up" },
|
||||||
|
{ skateboard_key_codes::down, "Down" },
|
||||||
|
{ skateboard_key_codes::cross, "Cross" },
|
||||||
|
{ skateboard_key_codes::square, "Square" },
|
||||||
|
{ skateboard_key_codes::circle, "Circle" },
|
||||||
|
{ skateboard_key_codes::triangle, "Triangle" },
|
||||||
|
{ skateboard_key_codes::start, "Start" },
|
||||||
|
{ skateboard_key_codes::select, "Select" },
|
||||||
|
{ skateboard_key_codes::ps, "PS" },
|
||||||
|
{ skateboard_key_codes::ir_left, "IR Left" },
|
||||||
|
{ skateboard_key_codes::ir_right, "IR Right" },
|
||||||
|
{ skateboard_key_codes::ir_nose, "IR Nose" },
|
||||||
|
{ skateboard_key_codes::ir_tail, "IR Tail" },
|
||||||
|
{ skateboard_key_codes::tilt_left, "Tilt Left" },
|
||||||
|
{ skateboard_key_codes::tilt_right, "Tilt Right" }
|
||||||
|
};
|
||||||
|
|
||||||
|
init_configs();
|
||||||
|
|
||||||
|
// Define border values
|
||||||
|
thumb_max = 255;
|
||||||
|
trigger_min = 0;
|
||||||
|
trigger_max = 255;
|
||||||
|
|
||||||
|
// Set capabilities
|
||||||
|
b_has_config = true;
|
||||||
|
b_has_rumble = false;
|
||||||
|
b_has_motion = true;
|
||||||
|
b_has_deadzones = false;
|
||||||
|
b_has_led = false;
|
||||||
|
b_has_rgb = false;
|
||||||
|
b_has_player_led = false;
|
||||||
|
b_has_battery = false;
|
||||||
|
b_has_pressure_intensity_button = false;
|
||||||
|
|
||||||
|
m_name_string = "Skateboard #";
|
||||||
|
m_max_devices = CELL_PAD_MAX_PORT_NUM;
|
||||||
|
|
||||||
|
m_trigger_threshold = trigger_max / 2;
|
||||||
|
m_thumb_threshold = thumb_max / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
skateboard_pad_handler::~skateboard_pad_handler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void skateboard_pad_handler::init_config(cfg_pad* cfg)
|
||||||
|
{
|
||||||
|
if (!cfg) return;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->ls_down.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->ls_right.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->ls_up.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->rs_left.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->rs_down.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->rs_right.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->rs_up.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->start.def = ::at32(button_list, skateboard_key_codes::start);
|
||||||
|
cfg->select.def = ::at32(button_list, skateboard_key_codes::select);
|
||||||
|
cfg->ps.def = ::at32(button_list, skateboard_key_codes::ps);
|
||||||
|
cfg->square.def = ::at32(button_list, skateboard_key_codes::square);
|
||||||
|
cfg->cross.def = ::at32(button_list, skateboard_key_codes::cross);
|
||||||
|
cfg->circle.def = ::at32(button_list, skateboard_key_codes::circle);
|
||||||
|
cfg->triangle.def = ::at32(button_list, skateboard_key_codes::triangle);
|
||||||
|
cfg->left.def = ::at32(button_list, skateboard_key_codes::left);
|
||||||
|
cfg->down.def = ::at32(button_list, skateboard_key_codes::down);
|
||||||
|
cfg->right.def = ::at32(button_list, skateboard_key_codes::right);
|
||||||
|
cfg->up.def = ::at32(button_list, skateboard_key_codes::up);
|
||||||
|
cfg->r1.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->r2.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->r3.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->l1.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->l2.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
cfg->l3.def = ::at32(button_list, skateboard_key_codes::none);
|
||||||
|
|
||||||
|
cfg->ir_nose.def = ::at32(button_list, skateboard_key_codes::ir_nose);
|
||||||
|
cfg->ir_tail.def = ::at32(button_list, skateboard_key_codes::ir_tail);
|
||||||
|
cfg->ir_left.def = ::at32(button_list, skateboard_key_codes::ir_left);
|
||||||
|
cfg->ir_right.def = ::at32(button_list, skateboard_key_codes::ir_right);
|
||||||
|
cfg->tilt_left.def = ::at32(button_list, skateboard_key_codes::tilt_left);
|
||||||
|
cfg->tilt_right.def = ::at32(button_list, skateboard_key_codes::tilt_right);
|
||||||
|
|
||||||
|
// Set default misc variables
|
||||||
|
cfg->lstickdeadzone.def = 40; // between 0 and 255
|
||||||
|
cfg->rstickdeadzone.def = 40; // between 0 and 255
|
||||||
|
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
void skateboard_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
|
||||||
|
{
|
||||||
|
if (!hidDevice)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
skateboard_device* device = nullptr;
|
||||||
|
|
||||||
|
for (auto& controller : m_controllers)
|
||||||
|
{
|
||||||
|
ensure(controller.second);
|
||||||
|
|
||||||
|
if (!controller.second->hidDevice)
|
||||||
|
{
|
||||||
|
device = controller.second.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hid_set_nonblocking(hidDevice, 1) == -1)
|
||||||
|
{
|
||||||
|
skateboard_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice));
|
||||||
|
hid_close(hidDevice);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->hidDevice = hidDevice;
|
||||||
|
device->path = path;
|
||||||
|
|
||||||
|
// Activate
|
||||||
|
if (send_output_report(device) == -1)
|
||||||
|
{
|
||||||
|
skateboard_log.error("check_add_device: send_output_report failed! Reason: %s", hid_error(hidDevice));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string serial;
|
||||||
|
for (wchar_t ch : wide_serial)
|
||||||
|
serial += static_cast<uchar>(ch);
|
||||||
|
|
||||||
|
skateboard_log.notice("Added device: serial='%s', path='%s'", serial, device->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
skateboard_pad_handler::DataStatus skateboard_pad_handler::get_data(skateboard_device* device)
|
||||||
|
{
|
||||||
|
if (!device)
|
||||||
|
return DataStatus::ReadError;
|
||||||
|
|
||||||
|
std::array<u8, sizeof(skateboard_input_report)> buf{};
|
||||||
|
|
||||||
|
int res = hid_read(device->hidDevice, buf.data(), buf.size());
|
||||||
|
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
// looks like controller disconnected or read error
|
||||||
|
skateboard_log.error("get_data ReadError", device->path);
|
||||||
|
return DataStatus::ReadError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != static_cast<int>(sizeof(skateboard_input_report)))
|
||||||
|
return DataStatus::NoNewData;
|
||||||
|
|
||||||
|
if (std::memcmp(device->padData.data(), buf.data(), sizeof(skateboard_input_report)) == 0)
|
||||||
|
return DataStatus::NoNewData;
|
||||||
|
|
||||||
|
// Get the new data
|
||||||
|
memcpy(device->padData.data(), buf.data(), sizeof(skateboard_input_report));
|
||||||
|
|
||||||
|
// Check the skateboard's power state based on the input report
|
||||||
|
device->skateboard_is_on =
|
||||||
|
(std::memcmp(not_connected_state.data(), buf.data(), not_connected_state.size()) != 0 && // This usually means that the device hasn't been connected to the dongle yet.
|
||||||
|
std::memcmp(disconnected_state.data(), buf.data(), disconnected_state.size()) != 0); // This usually means that the device was disconnected from the dongle.
|
||||||
|
|
||||||
|
return DataStatus::NewData;
|
||||||
|
}
|
||||||
|
|
||||||
|
PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
|
||||||
|
{
|
||||||
|
skateboard_device* skateboard_dev = static_cast<skateboard_device*>(device.get());
|
||||||
|
if (!skateboard_dev || skateboard_dev->path.empty())
|
||||||
|
return connection::disconnected;
|
||||||
|
|
||||||
|
if (skateboard_dev->hidDevice == nullptr)
|
||||||
|
{
|
||||||
|
// try to reconnect
|
||||||
|
hid_device* dev = hid_open_path(skateboard_dev->path.c_str());
|
||||||
|
if (dev)
|
||||||
|
{
|
||||||
|
if (hid_set_nonblocking(dev, 1) == -1)
|
||||||
|
{
|
||||||
|
skateboard_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", skateboard_dev->path, hid_error(dev));
|
||||||
|
}
|
||||||
|
skateboard_dev->hidDevice = dev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// nope, not there
|
||||||
|
skateboard_log.error("Device %s: disconnected", skateboard_dev->path);
|
||||||
|
return connection::disconnected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_data(skateboard_dev) == DataStatus::ReadError)
|
||||||
|
{
|
||||||
|
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
||||||
|
hid_close(skateboard_dev->hidDevice);
|
||||||
|
skateboard_dev->hidDevice = nullptr;
|
||||||
|
|
||||||
|
return connection::no_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skateboard_dev->skateboard_is_on)
|
||||||
|
{
|
||||||
|
// This means that the dongle is still connected, but the skateboard is turned off.
|
||||||
|
// There is no need to reconnect the hid device again, we just have to check the input report for proper data.
|
||||||
|
// The game should get the proper disconnected state anyway.
|
||||||
|
return connection::disconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection::connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<u64, u16> skateboard_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
|
||||||
|
{
|
||||||
|
std::unordered_map<u64, u16> key_buf;
|
||||||
|
skateboard_device* dualsense_dev = static_cast<skateboard_device*>(device.get());
|
||||||
|
if (!dualsense_dev)
|
||||||
|
return key_buf;
|
||||||
|
|
||||||
|
const std::array<u8, 64>& buf = dualsense_dev->padData;
|
||||||
|
const skateboard_input_report* input = reinterpret_cast<const skateboard_input_report*>(buf.data());
|
||||||
|
|
||||||
|
// D-Pad
|
||||||
|
key_buf[skateboard_key_codes::left] = (input->d_pad == dpad_states::left || input->d_pad == dpad_states::up_left || input->d_pad == dpad_states::down_left) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::right] = (input->d_pad == dpad_states::right || input->d_pad == dpad_states::up_right || input->d_pad == dpad_states::down_right) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::up] = (input->d_pad == dpad_states::up || input->d_pad == dpad_states::up_left || input->d_pad == dpad_states::up_right) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::down] = (input->d_pad == dpad_states::down || input->d_pad == dpad_states::down_left || input->d_pad == dpad_states::down_right) ? 255 : 0;
|
||||||
|
|
||||||
|
// Face buttons
|
||||||
|
key_buf[skateboard_key_codes::cross] = (input->buttons & button_flags::cross) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::square] = (input->buttons & button_flags::square) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::circle] = (input->buttons & button_flags::circle) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::triangle] = (input->buttons & button_flags::triangle) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::start] = (input->buttons & button_flags::start) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::select] = (input->buttons & button_flags::select) ? 255 : 0;
|
||||||
|
key_buf[skateboard_key_codes::ps] = (input->buttons & button_flags::ps) ? 255 : 0;
|
||||||
|
|
||||||
|
// Infrared
|
||||||
|
key_buf[skateboard_key_codes::ir_nose] = input->pressure_triangle;
|
||||||
|
key_buf[skateboard_key_codes::ir_tail] = input->pressure_circle;
|
||||||
|
key_buf[skateboard_key_codes::ir_left] = input->pressure_cross;
|
||||||
|
key_buf[skateboard_key_codes::ir_right] = input->pressure_square;
|
||||||
|
key_buf[skateboard_key_codes::tilt_left] = input->pressure_l1;
|
||||||
|
key_buf[skateboard_key_codes::tilt_right] = input->pressure_r1;
|
||||||
|
|
||||||
|
// NOTE: Axes X, Y, Z and RZ are always 128, which is the default anyway, so setting the values is omitted.
|
||||||
|
|
||||||
|
return key_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skateboard_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||||
|
{
|
||||||
|
const auto& device = binding.device;
|
||||||
|
const auto& pad = binding.pad;
|
||||||
|
|
||||||
|
skateboard_device* dev = static_cast<skateboard_device*>(device.get());
|
||||||
|
if (!dev || !pad)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::array<u8, 64>& buf = dev->padData;
|
||||||
|
const skateboard_input_report* input = reinterpret_cast<const skateboard_input_report*>(buf.data());
|
||||||
|
|
||||||
|
pad->m_sensors[0].m_value = Clamp0To1023(input->large_axes[0]);
|
||||||
|
pad->m_sensors[1].m_value = Clamp0To1023(input->large_axes[1]);
|
||||||
|
pad->m_sensors[2].m_value = Clamp0To1023(input->large_axes[2]);
|
||||||
|
pad->m_sensors[3].m_value = Clamp0To1023(input->large_axes[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pad_preview_values skateboard_pad_handler::get_preview_values(const std::unordered_map<u64, u16>& /*data*/)
|
||||||
|
{
|
||||||
|
// There is no proper user interface for skateboard values yet
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int skateboard_pad_handler::send_output_report(skateboard_device* device)
|
||||||
|
{
|
||||||
|
if (!device || !device->hidDevice)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
const cfg_pad* config = device->config;
|
||||||
|
if (config == nullptr)
|
||||||
|
return -2; // hid_write returns -1 on error
|
||||||
|
|
||||||
|
// The output report contents are still unknown
|
||||||
|
skateboard_output_report report{};
|
||||||
|
return hid_write(device->hidDevice, report.data.data(), report.data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void skateboard_pad_handler::apply_pad_data(const pad_ensemble& binding)
|
||||||
|
{
|
||||||
|
const auto& device = binding.device;
|
||||||
|
const auto& pad = binding.pad;
|
||||||
|
|
||||||
|
skateboard_device* dev = static_cast<skateboard_device*>(device.get());
|
||||||
|
if (!dev || !dev->hidDevice || !dev->config || !pad)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->new_output_data = false;
|
||||||
|
|
||||||
|
if (dev->new_output_data)
|
||||||
|
{
|
||||||
|
if (send_output_report(dev) >= 0)
|
||||||
|
{
|
||||||
|
dev->new_output_data = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skateboard_pad_handler::SetPadData(const std::string& padId, u8 player_id, u8 /*large_motor*/, u8 /*small_motor*/, s32 /*r*/, s32 /*g*/, s32 /*b*/, bool /*player_led*/, bool /*battery_led*/, u32 /*battery_led_brightness*/)
|
||||||
|
{
|
||||||
|
std::shared_ptr<skateboard_device> device = get_hid_device(padId);
|
||||||
|
if (device == nullptr || device->hidDevice == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device->player_id = player_id;
|
||||||
|
device->config = get_config(padId);
|
||||||
|
|
||||||
|
ensure(device->config);
|
||||||
|
|
||||||
|
// Disabled until needed
|
||||||
|
//send_output_report(device.get());
|
||||||
|
}
|
189
rpcs3/Input/skateboard_pad_handler.h
Normal file
189
rpcs3/Input/skateboard_pad_handler.h
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hid_pad_handler.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Descriptor
|
||||||
|
// 0x09, 0x05, // Usage (0x05)
|
||||||
|
// 0xA1, 0x01, // Collection (Application)
|
||||||
|
// 0x05, 0x09, // Usage Page (Button)
|
||||||
|
// 0x19, 0x01, // Usage Minimum (0x01)
|
||||||
|
// 0x29, 0x0D, // Usage Maximum (0x0D)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x25, 0x01, // Logical Maximum (1)
|
||||||
|
// 0x75, 0x01, // Report Size (1)
|
||||||
|
// 0x95, 0x0D, // Report Count (13)
|
||||||
|
// 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x75, 0x03, // Report Size (3)
|
||||||
|
// 0x95, 0x01, // Report Count (1)
|
||||||
|
// 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||||
|
// 0x09, 0x39, // Usage (Hat switch)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x25, 0x07, // Logical Maximum (7)
|
||||||
|
// 0x35, 0x00, // Physical Minimum (0)
|
||||||
|
// 0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||||
|
// 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||||
|
// 0x75, 0x04, // Report Size (4)
|
||||||
|
// 0x95, 0x01, // Report Count (1)
|
||||||
|
// 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||||
|
// 0x75, 0x04, // Report Size (4)
|
||||||
|
// 0x95, 0x01, // Report Count (1)
|
||||||
|
// 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x09, 0x30, // Usage (X)
|
||||||
|
// 0x09, 0x31, // Usage (Y)
|
||||||
|
// 0x09, 0x32, // Usage (Z)
|
||||||
|
// 0x09, 0x35, // Usage (Rz)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
// 0x35, 0x00, // Physical Minimum (0)
|
||||||
|
// 0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||||
|
// 0x65, 0x00, // Unit (None)
|
||||||
|
// 0x75, 0x08, // Report Size (8)
|
||||||
|
// 0x95, 0x04, // Report Count (4)
|
||||||
|
// 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||||
|
// 0x09, 0x20, // Usage (0x20)
|
||||||
|
// 0x09, 0x21, // Usage (0x21)
|
||||||
|
// 0x09, 0x22, // Usage (0x22)
|
||||||
|
// 0x09, 0x23, // Usage (0x23)
|
||||||
|
// 0x09, 0x24, // Usage (0x24)
|
||||||
|
// 0x09, 0x25, // Usage (0x25)
|
||||||
|
// 0x09, 0x26, // Usage (0x26)
|
||||||
|
// 0x09, 0x27, // Usage (0x27)
|
||||||
|
// 0x09, 0x28, // Usage (0x28)
|
||||||
|
// 0x09, 0x29, // Usage (0x29)
|
||||||
|
// 0x09, 0x2A, // Usage (0x2A)
|
||||||
|
// 0x09, 0x2B, // Usage (0x2B)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
// 0x75, 0x08, // Report Size (8)
|
||||||
|
// 0x95, 0x0C, // Report Count (12)
|
||||||
|
// 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x09, 0x2C, // Usage (0x2C)
|
||||||
|
// 0x09, 0x2D, // Usage (0x2D)
|
||||||
|
// 0x09, 0x2E, // Usage (0x2E)
|
||||||
|
// 0x09, 0x2F, // Usage (0x2F)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x26, 0xFF, 0x03, // Logical Maximum (1023)
|
||||||
|
// 0x35, 0x00, // Physical Minimum (0)
|
||||||
|
// 0x46, 0xFF, 0x03, // Physical Maximum (1023)
|
||||||
|
// 0x75, 0x10, // Report Size (16)
|
||||||
|
// 0x95, 0x04, // Report Count (4)
|
||||||
|
// 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
// 0x0A, 0x21, 0x26, // Usage (0x2621)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
// 0x35, 0x00, // Physical Minimum (0)
|
||||||
|
// 0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||||
|
// 0x75, 0x08, // Report Size (8)
|
||||||
|
// 0x95, 0x08, // Report Count (8)
|
||||||
|
// 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||||
|
// 0x0A, 0x21, 0x26, // Usage (0x2621)
|
||||||
|
// 0x15, 0x00, // Logical Minimum (0)
|
||||||
|
// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
// 0x75, 0x08, // Report Size (8)
|
||||||
|
// 0x95, 0x08, // Report Count (8)
|
||||||
|
// 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||||
|
// 0xC0, // End Collection
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct skateboard_input_report
|
||||||
|
{
|
||||||
|
// 13 buttons, value range 0 to 1, 13 bits + 3 bits padding (2 bytes total)
|
||||||
|
u16 buttons{};
|
||||||
|
|
||||||
|
// d-pad, value range 0 to 7 (8 directions), 4 bits + 4 bits padding (1 byte total)
|
||||||
|
u8 d_pad{};
|
||||||
|
|
||||||
|
// 4 axis (X, Y, Z, RZ), value range 0 to 255, 1 byte each (4 bytes total)
|
||||||
|
u8 axis_x{};
|
||||||
|
u8 axis_y{};
|
||||||
|
u8 axis_z{};
|
||||||
|
u8 axis_rz{};
|
||||||
|
|
||||||
|
// 12 axis (0x20 - 0x2B), value range 0 to 255, 1 byte each (12 bytes total)
|
||||||
|
// These 12 values match the pressure sensitivity values of the buttons (CELL_PAD_BTN_OFFSET_PRESS)
|
||||||
|
u8 pressure_right{}; // value for CELL_PAD_BTN_OFFSET_PRESS_RIGHT -> always 0 ?
|
||||||
|
u8 pressure_left{}; // value for CELL_PAD_BTN_OFFSET_PRESS_LEFT -> always 0 ?
|
||||||
|
u8 pressure_up{}; // value for CELL_PAD_BTN_OFFSET_PRESS_UP -> always 0 ?
|
||||||
|
u8 pressure_down{}; // value for CELL_PAD_BTN_OFFSET_PRESS_DOWN -> always 0 ?
|
||||||
|
u8 pressure_triangle{}; // value for CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE -> infrared nose
|
||||||
|
u8 pressure_circle{}; // value for CELL_PAD_BTN_OFFSET_PRESS_CIRCLE -> infrared tail
|
||||||
|
u8 pressure_cross{}; // value for CELL_PAD_BTN_OFFSET_PRESS_CROSS -> infrared left
|
||||||
|
u8 pressure_square{}; // value for CELL_PAD_BTN_OFFSET_PRESS_SQUARE -> infrared right
|
||||||
|
u8 pressure_l1{}; // value for CELL_PAD_BTN_OFFSET_PRESS_L1 -> tilt left (probably)
|
||||||
|
u8 pressure_r1{}; // value for CELL_PAD_BTN_OFFSET_PRESS_R1 -> tilt right (probably)
|
||||||
|
u8 pressure_l2{}; // value for CELL_PAD_BTN_OFFSET_PRESS_L2 -> always 0 ?
|
||||||
|
u8 pressure_r2{}; // value for CELL_PAD_BTN_OFFSET_PRESS_R2 -> always 0 ?
|
||||||
|
|
||||||
|
// 4 axis (0x2C - 0x2F), value range 0 to 1023, 2 bytes each (8 bytes total)
|
||||||
|
std::array<u16, 4> large_axes{};
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct skateboard_output_report
|
||||||
|
{
|
||||||
|
// 8 axis (0x2621), value range 0 to 255, 1 byte each (8 bytes total)
|
||||||
|
std::array<u8, 8> data{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skateboard_feature_report
|
||||||
|
{
|
||||||
|
// 8 axis (0x2621), value range 0 to 255, 1 byte each (8 bytes total)
|
||||||
|
std::array<u8, 8> data{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class skateboard_device : public HidDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool skateboard_is_on = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class skateboard_pad_handler final : public hid_pad_handler<skateboard_device>
|
||||||
|
{
|
||||||
|
enum skateboard_key_codes
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
up,
|
||||||
|
down,
|
||||||
|
cross,
|
||||||
|
square,
|
||||||
|
circle,
|
||||||
|
triangle,
|
||||||
|
start,
|
||||||
|
select,
|
||||||
|
ps,
|
||||||
|
ir_nose,
|
||||||
|
ir_tail,
|
||||||
|
ir_left,
|
||||||
|
ir_right,
|
||||||
|
tilt_left,
|
||||||
|
tilt_right,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
skateboard_pad_handler();
|
||||||
|
~skateboard_pad_handler();
|
||||||
|
|
||||||
|
void SetPadData(const std::string& padId, u8 player_id, u8 large_motor, u8 small_motor, s32 r, s32 g, s32 b, bool player_led, bool battery_led, u32 battery_led_brightness) override;
|
||||||
|
void init_config(cfg_pad* cfg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataStatus get_data(skateboard_device* device) override;
|
||||||
|
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;
|
||||||
|
int send_output_report(skateboard_device* device) override;
|
||||||
|
|
||||||
|
PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) override;
|
||||||
|
std::unordered_map<u64, u16> get_button_values(const std::shared_ptr<PadDevice>& device) override;
|
||||||
|
pad_preview_values get_preview_values(const std::unordered_map<u64, u16>& data) override;
|
||||||
|
void get_extended_info(const pad_ensemble& binding) override;
|
||||||
|
void apply_pad_data(const pad_ensemble& binding) override;
|
||||||
|
};
|
@ -180,6 +180,7 @@
|
|||||||
<ClCompile Include="Input\evdev_gun_handler.cpp" />
|
<ClCompile Include="Input\evdev_gun_handler.cpp" />
|
||||||
<ClCompile Include="Input\hid_pad_handler.cpp" />
|
<ClCompile Include="Input\hid_pad_handler.cpp" />
|
||||||
<ClCompile Include="Input\sdl_pad_handler.cpp" />
|
<ClCompile Include="Input\sdl_pad_handler.cpp" />
|
||||||
|
<ClCompile Include="Input\skateboard_pad_handler.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="main_application.cpp" />
|
<ClCompile Include="main_application.cpp" />
|
||||||
<ClCompile Include="Input\basic_keyboard_handler.cpp" />
|
<ClCompile Include="Input\basic_keyboard_handler.cpp" />
|
||||||
@ -923,6 +924,7 @@
|
|||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<ClInclude Include="Input\sdl_pad_handler.h" />
|
<ClInclude Include="Input\sdl_pad_handler.h" />
|
||||||
|
<ClInclude Include="Input\skateboard_pad_handler.h" />
|
||||||
<ClInclude Include="main_application.h" />
|
<ClInclude Include="main_application.h" />
|
||||||
<ClInclude Include="Input/mm_joystick_handler.h" />
|
<ClInclude Include="Input/mm_joystick_handler.h" />
|
||||||
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
|
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
|
||||||
|
@ -166,6 +166,9 @@
|
|||||||
<Filter Include="CI">
|
<Filter Include="CI">
|
||||||
<UniqueIdentifier>{b3bba7ee-4f23-41b6-8ddf-e40f848015de}</UniqueIdentifier>
|
<UniqueIdentifier>{b3bba7ee-4f23-41b6-8ddf-e40f848015de}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Io\Skateboard">
|
||||||
|
<UniqueIdentifier>{bd1fd182-dc0d-45cb-bb9e-f68b2282d7eb}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
@ -1044,6 +1047,9 @@
|
|||||||
<ClCompile Include="rpcs3qt\localized_emu.cpp">
|
<ClCompile Include="rpcs3qt\localized_emu.cpp">
|
||||||
<Filter>Gui\settings</Filter>
|
<Filter>Gui\settings</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Input\skateboard_pad_handler.cpp">
|
||||||
|
<Filter>Io\Skateboard</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||||
@ -1223,6 +1229,9 @@
|
|||||||
<ClInclude Include="rpcs3qt\midi_creator.h">
|
<ClInclude Include="rpcs3qt\midi_creator.h">
|
||||||
<Filter>Gui\settings</Filter>
|
<Filter>Gui\settings</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Input\skateboard_pad_handler.h">
|
||||||
|
<Filter>Io\Skateboard</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||||
|
@ -180,6 +180,7 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr<gui_settings> gui_setti
|
|||||||
ui->chooseClass->addItem(tr("DJ"), u32{CELL_PAD_PCLASS_TYPE_DJ});
|
ui->chooseClass->addItem(tr("DJ"), u32{CELL_PAD_PCLASS_TYPE_DJ});
|
||||||
ui->chooseClass->addItem(tr("Dance Mat"), u32{CELL_PAD_PCLASS_TYPE_DANCEMAT});
|
ui->chooseClass->addItem(tr("Dance Mat"), u32{CELL_PAD_PCLASS_TYPE_DANCEMAT});
|
||||||
ui->chooseClass->addItem(tr("Navigation"), u32{CELL_PAD_PCLASS_TYPE_NAVIGATION});
|
ui->chooseClass->addItem(tr("Navigation"), u32{CELL_PAD_PCLASS_TYPE_NAVIGATION});
|
||||||
|
ui->chooseClass->addItem(tr("Skateboard"), u32{CELL_PAD_PCLASS_TYPE_SKATEBOARD});
|
||||||
|
|
||||||
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
||||||
{
|
{
|
||||||
@ -1382,6 +1383,7 @@ void pad_settings_dialog::ChangeHandler()
|
|||||||
m_description = tooltips.gamepad_settings.null;
|
m_description = tooltips.gamepad_settings.null;
|
||||||
break;
|
break;
|
||||||
case pad_handler::keyboard: m_description = tooltips.gamepad_settings.keyboard; break;
|
case pad_handler::keyboard: m_description = tooltips.gamepad_settings.keyboard; break;
|
||||||
|
case pad_handler::skateboard: m_description = tooltips.gamepad_settings.skateboard; break;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case pad_handler::xinput: m_description = tooltips.gamepad_settings.xinput; break;
|
case pad_handler::xinput: m_description = tooltips.gamepad_settings.xinput; break;
|
||||||
case pad_handler::mm: m_description = tooltips.gamepad_settings.mmjoy; break;
|
case pad_handler::mm: m_description = tooltips.gamepad_settings.mmjoy; break;
|
||||||
@ -1446,6 +1448,7 @@ void pad_settings_dialog::ChangeHandler()
|
|||||||
case pad_handler::ds3:
|
case pad_handler::ds3:
|
||||||
case pad_handler::ds4:
|
case pad_handler::ds4:
|
||||||
case pad_handler::dualsense:
|
case pad_handler::dualsense:
|
||||||
|
case pad_handler::skateboard:
|
||||||
{
|
{
|
||||||
const QString name_string = qstr(m_handler->name_string());
|
const QString name_string = qstr(m_handler->name_string());
|
||||||
for (usz i = 1; i <= m_handler->max_devices(); i++) // Controllers 1-n in GUI
|
for (usz i = 1; i <= m_handler->max_devices(); i++) // Controllers 1-n in GUI
|
||||||
@ -1672,6 +1675,11 @@ void pad_settings_dialog::HandleDeviceClassChange(u32 class_id) const
|
|||||||
ui->chooseProduct->addItem(tr("PS Move Navigation", "PS Move Navigation Controller"), static_cast<int>(product.type));
|
ui->chooseProduct->addItem(tr("PS Move Navigation", "PS Move Navigation Controller"), static_cast<int>(product.type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case input::product_type::ride_skateboard:
|
||||||
|
{
|
||||||
|
ui->chooseProduct->addItem(tr("RIDE Skateboard", "Tony Hawk RIDE Skateboard Controller"), static_cast<int>(product.type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1892,6 +1900,7 @@ QString pad_settings_dialog::GetLocalizedPadHandler(const QString& original, pad
|
|||||||
case pad_handler::ds3: return tr("DualShock 3");
|
case pad_handler::ds3: return tr("DualShock 3");
|
||||||
case pad_handler::ds4: return tr("DualShock 4");
|
case pad_handler::ds4: return tr("DualShock 4");
|
||||||
case pad_handler::dualsense: return tr("DualSense");
|
case pad_handler::dualsense: return tr("DualSense");
|
||||||
|
case pad_handler::skateboard: return tr("Skateboard");
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case pad_handler::xinput: return tr("XInput");
|
case pad_handler::xinput: return tr("XInput");
|
||||||
case pad_handler::mm: return tr("MMJoystick");
|
case pad_handler::mm: return tr("MMJoystick");
|
||||||
|
@ -265,6 +265,7 @@ public:
|
|||||||
const QString dualsense_windows = tr("The DualSense handler is recommended for official DualSense controllers.");
|
const QString dualsense_windows = tr("The DualSense handler is recommended for official DualSense controllers.");
|
||||||
const QString dualsense_linux = tr("The DualSense handler is recommended for official DualSense controllers.");
|
const QString dualsense_linux = tr("The DualSense handler is recommended for official DualSense controllers.");
|
||||||
const QString dualsense_other = tr("The DualSense handler is recommended for official DualSense controllers.");
|
const QString dualsense_other = tr("The DualSense handler is recommended for official DualSense controllers.");
|
||||||
|
const QString skateboard = tr("The Skateboard handler is recommended for official RIDE skateboard controllers.");
|
||||||
const QString xinput = tr("The XInput handler will work with Xbox controllers and many third-party PC-compatible controllers. Pressure sensitive buttons from SCP are supported when SCP's XInput1_3.dll is placed in the main RPCS3 directory. For more details, see the <a %0 href=\"https://wiki.rpcs3.net/index.php?title=Help:Controller_Configuration\">RPCS3 Wiki</a>.").arg(gui::utils::get_link_style());
|
const QString xinput = tr("The XInput handler will work with Xbox controllers and many third-party PC-compatible controllers. Pressure sensitive buttons from SCP are supported when SCP's XInput1_3.dll is placed in the main RPCS3 directory. For more details, see the <a %0 href=\"https://wiki.rpcs3.net/index.php?title=Help:Controller_Configuration\">RPCS3 Wiki</a>.").arg(gui::utils::get_link_style());
|
||||||
const QString evdev = tr("The evdev handler should work with any controller that has Linux support.<br>If your joystick is not being centered properly, read the <a %0 href=\"https://wiki.rpcs3.net/index.php?title=Help:Controller_Configuration\">RPCS3 Wiki</a> for instructions.").arg(gui::utils::get_link_style());
|
const QString evdev = tr("The evdev handler should work with any controller that has Linux support.<br>If your joystick is not being centered properly, read the <a %0 href=\"https://wiki.rpcs3.net/index.php?title=Help:Controller_Configuration\">RPCS3 Wiki</a> for instructions.").arg(gui::utils::get_link_style());
|
||||||
const QString mmjoy = tr("The MMJoystick handler should work with almost any controller recognized by Windows. However, it is recommended that you use the more specific handlers if you have a controller that supports them.");
|
const QString mmjoy = tr("The MMJoystick handler should work with almost any controller recognized by Windows. However, it is recommended that you use the more specific handlers if you have a controller that supports them.");
|
||||||
|
Loading…
Reference in New Issue
Block a user