From b82dd61a0cda6dc0f3b0a14a8a47632c7c135ca5 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 21 May 2023 21:44:55 +0200 Subject: [PATCH] input: add emulated axis configs --- rpcs3/Emu/Cell/Modules/cellGem.cpp | 52 ++++++++++++++++++------ rpcs3/Emu/Io/GHLtar.cpp | 57 ++++++++++++++++---------- rpcs3/Emu/Io/Turntable.cpp | 64 +++++++++++++++++++----------- rpcs3/Emu/Io/gem_config.h | 4 ++ rpcs3/Emu/Io/ghltar_config.h | 4 ++ rpcs3/Emu/Io/pad_types.cpp | 40 +++++++++++++++---- rpcs3/Emu/Io/pad_types.h | 13 ++++++ rpcs3/Emu/Io/turntable_config.h | 6 +++ rpcs3/rpcs3qt/localized_emu.cpp | 4 ++ 9 files changed, 177 insertions(+), 67 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index f0f5fd2416..c1d19b5bb6 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -38,6 +38,8 @@ void fmt_class_string::format(std::string& out, u64 arg) case gem_btn::move: return "Move"; case gem_btn::t: return "T"; case gem_btn::count: return "Count"; + case gem_btn::x_axis: return "X-Axis"; + case gem_btn::y_axis: return "Y-Axis"; } return unknown; @@ -709,6 +711,8 @@ static void ds3_input_to_pad(const u32 port_no, be_t& digital_buttons, be_t digital_buttons |= CELL_GEM_CTRL_T; analog_t = std::max(analog_t, button.m_value); break; + case gem_btn::x_axis: + case gem_btn::y_axis: case gem_btn::count: break; } @@ -719,24 +723,46 @@ static void ds3_input_to_pad(const u32 port_no, be_t& digital_buttons, be_t constexpr u16 ds3_max_x = 255; constexpr u16 ds3_max_y = 255; -static inline void ds3_get_stick_values(const std::shared_ptr& pad, s32& x_pos, s32& y_pos) +static inline void ds3_get_stick_values(u32 port_no, const std::shared_ptr& pad, s32& x_pos, s32& y_pos) { x_pos = 0; y_pos = 0; + const auto& cfg = ::at32(g_cfg_gem.players, port_no); + + std::function handle_input; + handle_input = [&](u32 offset, u32 keycode, u16 value, bool check_axis) + { + if (const auto btn = cfg->find_button(offset, keycode); btn.has_value() && btn.value()) + { + switch (btn.value()->btn_id()) + { + case gem_btn::x_axis: + x_pos = value; + break; + case gem_btn::y_axis: + y_pos = value; + break; + default: + break; + } + } + else if (check_axis) + { + switch (offset) + { + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + default: break; + } + } + }; + for (const AnalogStick& stick : pad->m_sticks) { - switch (stick.m_offset) - { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: - x_pos = stick.m_value; - break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: - y_pos = stick.m_value; - break; - default: - break; - } + handle_input(stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true); } } @@ -759,7 +785,7 @@ static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_contro } s32 ds3_pos_x, ds3_pos_y; - ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y); + ds3_get_stick_values(port_no, pad, ds3_pos_x, ds3_pos_y); if constexpr (std::is_same>::value) { diff --git a/rpcs3/Emu/Io/GHLtar.cpp b/rpcs3/Emu/Io/GHLtar.cpp index b3bc2761ae..026e64655a 100644 --- a/rpcs3/Emu/Io/GHLtar.cpp +++ b/rpcs3/Emu/Io/GHLtar.cpp @@ -28,6 +28,8 @@ void fmt_class_string::format(std::string& out, u64 arg) case ghltar_btn::strum_up: return "Strum Up"; case ghltar_btn::dpad_left: return "D-Pad Left"; case ghltar_btn::dpad_right: return "D-Pad Right"; + case ghltar_btn::whammy: return "Whammy"; + case ghltar_btn::tilt: return "Tilt"; case ghltar_btn::count: return "Count"; } @@ -145,14 +147,10 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint return; } - for (const Button& button : pad->m_buttons) + std::function handle_input; + handle_input = [&](u32 offset, u32 keycode, u16 value, bool check_axis) { - if (!button.m_pressed) - { - continue; - } - - if (const auto btn = cfg->find_button(button.m_offset, button.m_outKeyCode); btn.has_value() && btn.value()) + if (const auto btn = cfg->find_button(offset, keycode); btn.has_value() && btn.value()) { switch (btn.value()->btn_id()) { @@ -195,28 +193,43 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint case ghltar_btn::ghtv: buf[1] += 0x04; // GHTV Button break; + case ghltar_btn::whammy: + buf[6] = ~(value) + 0x01; // Whammy + break; + case ghltar_btn::tilt: + buf[19] = static_cast(value); // Tilt + if (buf[19] >= 0xF0) + buf[5] = 0xFF; + else if (buf[19] <= 0x10) + buf[5] = 0x00; + break; case ghltar_btn::count: break; } } + else if (check_axis) + { + switch (offset) + { + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + default: break; + } + } + }; + + for (const Button& button : pad->m_buttons) + { + if (button.m_pressed) + { + handle_input(button.m_offset, button.m_outKeyCode, button.m_value, true); + } } for (const AnalogStick& stick : pad->m_sticks) { - switch (stick.m_offset) - { - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: - buf[6] = ~(stick.m_value) + 0x01; // Whammy - break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: - buf[19] = static_cast(stick.m_value); // Tilt - if (buf[19] >= 0xF0) - buf[5] = 0xFF; - if (buf[19] <= 0x10) - buf[5] = 0x00; - break; - default: - break; - } + handle_input(stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true); } } diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index 52d88e4ed6..52d4fc4a9e 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -28,6 +28,9 @@ void fmt_class_string::format(std::string& out, u64 arg) case turntable_btn::circle: return "Circle"; case turntable_btn::cross: return "Cross"; case turntable_btn::triangle: return "Triangle"; + case turntable_btn::right_turntable: return "Right Turntable"; + case turntable_btn::crossfader: return "Crossfader"; + case turntable_btn::effects_dial: return "Effects Dial"; case turntable_btn::count: return "Count"; } @@ -156,12 +159,10 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) return; - for (const Button& button : pad->m_buttons) + std::function handle_input; + handle_input = [&](u32 offset, u32 keycode, u16 value, bool check_axis) { - if (!button.m_pressed) - continue; - - if (const auto btn = cfg->find_button(button.m_offset, button.m_outKeyCode); btn.has_value() && btn.value()) + if (const auto btn = cfg->find_button(offset, keycode); btn.has_value() && btn.value()) { switch (btn.value()->btn_id()) { @@ -262,18 +263,8 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo case turntable_btn::select: buf[1] |= 0x01; // Select break; - case turntable_btn::count: - break; - } - } - } - - for (const AnalogStick& stick : pad->m_sticks) - { - switch (stick.m_offset) - { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: - buf[6] = 255 - stick.m_value; // Right Turntable + case turntable_btn::right_turntable: + buf[6] = 255 - value; // Right Turntable // DJ Hero requires turntables to be centered at 128. // If this axis ends up centered at 127, force it to 128. if (buf[6] == 127) @@ -281,16 +272,41 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo buf[6] = 128; } break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: - buf[21] = ((255 - stick.m_value) & 0x3F) << 2; // Crossfader, lower 6 bits - buf[22] = ((255 - stick.m_value) & 0xC0) >> 6; // Crossfader, upper 2 bits + case turntable_btn::crossfader: + buf[21] = ((255 - value) & 0x3F) << 2; // Crossfader, lower 6 bits + buf[22] = ((255 - value) & 0xC0) >> 6; // Crossfader, upper 2 bits break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: - buf[19] = (stick.m_value & 0x3F) << 2; // Effects Dial, lower 6 bits - buf[20] = (stick.m_value & 0xC0) >> 6; // Effects Dial, upper 2 bits + case turntable_btn::effects_dial: + buf[19] = (value & 0x3F) << 2; // Effects Dial, lower 6 bits + buf[20] = (value & 0xC0) >> 6; // Effects Dial, upper 2 bits break; - default: + case turntable_btn::count: break; + } + } + else if (check_axis) + { + switch (offset) + { + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: handle_input(offset, static_cast(axis_direction::both), value, false); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: handle_input(offset, static_cast(axis_direction::both), value, false); break; + default: break; + } + } + }; + + for (const Button& button : pad->m_buttons) + { + if (button.m_pressed) + { + handle_input(button.m_offset, button.m_outKeyCode, button.m_value, true); } } + + for (const AnalogStick& stick : pad->m_sticks) + { + handle_input(stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true); + } } diff --git a/rpcs3/Emu/Io/gem_config.h b/rpcs3/Emu/Io/gem_config.h index c6a99b75a9..4d1a9fb755 100644 --- a/rpcs3/Emu/Io/gem_config.h +++ b/rpcs3/Emu/Io/gem_config.h @@ -14,6 +14,8 @@ enum class gem_btn square, move, t, + x_axis, + y_axis, count }; @@ -30,6 +32,8 @@ struct cfg_gem final : public emulated_pad_config cfg_pad_btn square{ this, "Square", gem_btn::square, pad_button::square }; cfg_pad_btn move{ this, "Move", gem_btn::move, pad_button::R1 }; cfg_pad_btn t{ this, "T", gem_btn::t, pad_button::R2 }; + cfg_pad_btn x_axis{ this, "X-Axis", gem_btn::x_axis, pad_button::ls_x }; + cfg_pad_btn y_axis{ this, "Y-Axis", gem_btn::y_axis, pad_button::ls_y }; }; struct cfg_gems final : public emulated_pads_config diff --git a/rpcs3/Emu/Io/ghltar_config.h b/rpcs3/Emu/Io/ghltar_config.h index 0d97153f5d..72e3afd292 100644 --- a/rpcs3/Emu/Io/ghltar_config.h +++ b/rpcs3/Emu/Io/ghltar_config.h @@ -19,6 +19,8 @@ enum class ghltar_btn strum_up, dpad_left, dpad_right, + whammy, + tilt, count }; @@ -40,6 +42,8 @@ struct cfg_ghltar final : public emulated_pad_config cfg_pad_btn strum_up{ this, "Strum Up", ghltar_btn::strum_up, pad_button::dpad_up }; cfg_pad_btn dpad_left{ this, "D-Pad Left", ghltar_btn::dpad_left, pad_button::dpad_left }; cfg_pad_btn dpad_right{ this, "D-Pad Right", ghltar_btn::dpad_right, pad_button::dpad_right }; + cfg_pad_btn whammy{ this, "Whammy", ghltar_btn::whammy, pad_button::rs_y }; + cfg_pad_btn tilt{ this, "tilt", ghltar_btn::whammy, pad_button::rs_x }; }; struct cfg_ghltars final : public emulated_pads_config diff --git a/rpcs3/Emu/Io/pad_types.cpp b/rpcs3/Emu/Io/pad_types.cpp index 777aca182e..07247c06f7 100644 --- a/rpcs3/Emu/Io/pad_types.cpp +++ b/rpcs3/Emu/Io/pad_types.cpp @@ -29,10 +29,14 @@ void fmt_class_string::format(std::string& out, u64 arg) case pad_button::ls_down: return "Left Stick Down"; case pad_button::ls_left: return "Left Stick Left"; case pad_button::ls_right: return "Left Stick Right"; + case pad_button::ls_x: return "Left Stick X-Axis"; + case pad_button::ls_y: return "Left Stick Y-Axis"; case pad_button::rs_up: return "Right Stick Up"; case pad_button::rs_down: return "Right Stick Down"; case pad_button::rs_left: return "Right Stick Left"; case pad_button::rs_right: return "Right Stick Right"; + case pad_button::rs_x: return "Right Stick X-Axis"; + case pad_button::rs_y: return "Right Stick Y-Axis"; case pad_button::pad_button_max_enum: return unknown; } @@ -65,10 +69,14 @@ u32 pad_button_offset(pad_button button) case pad_button::ls_down: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y; case pad_button::ls_left: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X; case pad_button::ls_right: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X; + case pad_button::ls_x: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X; + case pad_button::ls_y: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y; case pad_button::rs_up: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y; case pad_button::rs_down: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y; case pad_button::rs_left: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X; case pad_button::rs_right: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X; + case pad_button::rs_x: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X; + case pad_button::rs_y: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y; case pad_button::pad_button_max_enum: return 0; } return 0; @@ -95,15 +103,31 @@ u32 pad_button_keycode(pad_button button) case pad_button::R2: return CELL_PAD_CTRL_R2; case pad_button::L3: return CELL_PAD_CTRL_L3; case pad_button::R3: return CELL_PAD_CTRL_R3; - case pad_button::ls_up: return 0; - case pad_button::ls_down: return 0; - case pad_button::ls_left: return 0; - case pad_button::ls_right: return 0; - case pad_button::rs_up: return 0; - case pad_button::rs_down: return 0; - case pad_button::rs_left: return 0; - case pad_button::rs_right: return 0; + case pad_button::ls_up: return static_cast(axis_direction::positive); + case pad_button::ls_down: return static_cast(axis_direction::negative); + case pad_button::ls_left: return static_cast(axis_direction::negative); + case pad_button::ls_right: return static_cast(axis_direction::positive); + case pad_button::ls_x: return static_cast(axis_direction::both); + case pad_button::ls_y: return static_cast(axis_direction::both); + case pad_button::rs_up: return static_cast(axis_direction::positive); + case pad_button::rs_down: return static_cast(axis_direction::negative); + case pad_button::rs_left: return static_cast(axis_direction::negative); + case pad_button::rs_right: return static_cast(axis_direction::positive); + case pad_button::rs_x: return static_cast(axis_direction::both); + case pad_button::rs_y: return static_cast(axis_direction::both); case pad_button::pad_button_max_enum: return 0; } return 0; } + +u32 get_axis_keycode(u32 offset, u16 value) +{ + switch (offset) + { + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: return static_cast(value > 127 ? axis_direction::positive : axis_direction::negative); + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: return static_cast(value > 127 ? axis_direction::positive : axis_direction::negative); + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: return static_cast(value > 127 ? axis_direction::positive : axis_direction::negative); + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: return static_cast(value > 127 ? axis_direction::positive : axis_direction::negative); + default: return static_cast(axis_direction::both); + } +} diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index ef15276040..b49941d365 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -30,10 +30,14 @@ enum class pad_button : u8 ls_down, ls_left, ls_right, + ls_x, + ls_y, rs_up, rs_down, rs_left, rs_right, + rs_x, + rs_y, pad_button_max_enum }; @@ -41,6 +45,15 @@ enum class pad_button : u8 u32 pad_button_offset(pad_button button); u32 pad_button_keycode(pad_button button); +enum class axis_direction : u8 +{ + both = 0, + negative, + positive +}; + +u32 get_axis_keycode(u32 offset, u16 value); + enum SystemInfo { CELL_PAD_INFO_INTERCEPTED = 0x00000001 diff --git a/rpcs3/Emu/Io/turntable_config.h b/rpcs3/Emu/Io/turntable_config.h index 80b4ddb13d..c2291423f5 100644 --- a/rpcs3/Emu/Io/turntable_config.h +++ b/rpcs3/Emu/Io/turntable_config.h @@ -19,6 +19,9 @@ enum class turntable_btn circle, cross, triangle, + right_turntable, + crossfader, + effects_dial, count }; @@ -40,6 +43,9 @@ struct cfg_turntable final : public emulated_pad_config cfg_pad_btn circle{ this, "Circle", turntable_btn::circle, pad_button::L1 }; cfg_pad_btn cross{ this, "Cross", turntable_btn::cross, pad_button::R1 }; cfg_pad_btn triangle{ this, "Triangle", turntable_btn::triangle, pad_button::triangle }; + cfg_pad_btn right_turntable{ this, "Right Turntable", turntable_btn::right_turntable, pad_button::ls_y }; + cfg_pad_btn crossfader{ this, "Crossfader", turntable_btn::crossfader, pad_button::rs_y }; + cfg_pad_btn effects_dial{ this, "Effects Dial", turntable_btn::effects_dial, pad_button::rs_x }; }; struct cfg_turntables final : public emulated_pads_config diff --git a/rpcs3/rpcs3qt/localized_emu.cpp b/rpcs3/rpcs3qt/localized_emu.cpp index 8b5111bf22..003171ba75 100644 --- a/rpcs3/rpcs3qt/localized_emu.cpp +++ b/rpcs3/rpcs3qt/localized_emu.cpp @@ -26,10 +26,14 @@ QString localized_emu::translated_pad_button(pad_button btn) case pad_button::ls_down: return tr("Left Stick Down"); case pad_button::ls_left: return tr("Left Stick Left"); case pad_button::ls_right: return tr("Left Stick Right"); + case pad_button::ls_x: return tr("Left Stick X-Axis"); + case pad_button::ls_y: return tr("Left Stick Y-Axis"); case pad_button::rs_up: return tr("Right Stick Up"); case pad_button::rs_down: return tr("Right Stick Down"); case pad_button::rs_left: return tr("Right Stick Left"); case pad_button::rs_right: return tr("Right Stick Right"); + case pad_button::rs_x: return tr("Right Stick X-Axis"); + case pad_button::rs_y: return tr("Right Stick Y-Axis"); case pad_button::pad_button_max_enum: return ""; } return "";