diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 57bd0518a0..d4ba49674e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -19,6 +19,7 @@ #include "Emu/Io/Infinity.h" #include "Emu/Io/GHLtar.h" #include "Emu/Io/ghltar_config.h" +#include "Emu/Io/guncon3_config.h" #include "Emu/Io/Buzz.h" #include "Emu/Io/buzz_config.h" #include "Emu/Io/GameTablet.h" @@ -41,6 +42,7 @@ cfg_buzz g_cfg_buzz; cfg_ghltars g_cfg_ghltar; cfg_turntables g_cfg_turntable; cfg_usios g_cfg_usio; +cfg_guncon3 g_cfg_guncon3; template <> void fmt_class_string::format(std::string& out, u64 arg) @@ -851,6 +853,11 @@ void connect_usb_controller(u8 index, input::product_type type) if (!already_connected && type == input::product_type::guncon_3) { + if (!g_cfg_guncon3.load()) + { + sys_usbd.notice("Could not load GunCon3 config. Using defaults."); + } + sys_usbd.success("Adding emulated GunCon3 (controller %d)", index); std::shared_ptr dev = std::make_shared(index, usbh.get_new_location()); usbh.connect_usb_device(dev, true); diff --git a/rpcs3/Emu/Io/GunCon3.cpp b/rpcs3/Emu/Io/GunCon3.cpp index 0c29405433..154b6e43e0 100644 --- a/rpcs3/Emu/Io/GunCon3.cpp +++ b/rpcs3/Emu/Io/GunCon3.cpp @@ -2,12 +2,40 @@ #include "GunCon3.h" #include "MouseHandler.h" #include "Emu/IdManager.h" +#include "Emu/Io/guncon3_config.h" #include "Emu/Cell/lv2/sys_usbd.h" #include "Emu/system_config.h" #include "Input/pad_thread.h" LOG_CHANNEL(guncon3_log); +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](guncon3_btn value) + { + switch (value) + { + case guncon3_btn::trigger: return "Trigger"; + case guncon3_btn::a1: return "A1"; + case guncon3_btn::a2: return "A2"; + case guncon3_btn::a3: return "A3"; + case guncon3_btn::b1: return "B1"; + case guncon3_btn::b2: return "B2"; + case guncon3_btn::b3: return "B3"; + case guncon3_btn::c1: return "C1"; + case guncon3_btn::c2: return "C2"; + case guncon3_btn::as_x: return "A-stick X-Axis"; + case guncon3_btn::as_y: return "A-stick Y-Axis"; + case guncon3_btn::bs_x: return "B-stick X-Axis"; + case guncon3_btn::bs_y: return "B-stick Y-Axis"; + case guncon3_btn::count: return "Count"; + } + + return unknown; + }); +} + static const u8 KEY_TABLE[] = { 0x91, 0xFD, 0x4C, 0x8B, 0x20, 0xC1, 0x7C, 0x09, 0x58, 0x14, 0xF6, 0x00, 0x52, 0x55, 0xBF, 0x41, 0x75, 0xC0, 0x13, 0x30, 0xB5, 0xD0, 0x69, 0x85, 0x89, 0xBB, 0xD6, 0x88, 0xBC, 0x73, 0x18, 0x8D, @@ -196,82 +224,33 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, std::lock_guard lock(pad::g_pad_mutex); const auto gamepad_handler = pad::get_current_handler(); const auto& pads = gamepad_handler->GetPads(); - const auto& pad = ::at32(pads, m_controller_index); if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) { - for (const Button& button : pad->m_buttons) + const auto& cfg = ::at32(g_cfg_guncon3.players, m_controller_index); + cfg->handle_input(pad, true, [&](guncon3_btn btn, u16 value, bool pressed) { - if (!button.m_pressed) - { - continue; - } + if (!pressed) + return; - if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) + switch (btn) { - switch (button.m_outKeyCode) - { - case CELL_PAD_CTRL_L3: - gc.btn_a3 |= 1; - break; - case CELL_PAD_CTRL_R3: - gc.btn_b3 |= 1; - break; - case CELL_PAD_CTRL_SELECT: - gc.btn_c1 |= 1; - break; - case CELL_PAD_CTRL_START: - gc.btn_c2 |= 1; - break; - default: - break; - } + case guncon3_btn::trigger: gc.btn_trigger |= 1; break; + case guncon3_btn::a1: gc.btn_a1 |= 1; break; + case guncon3_btn::a2: gc.btn_a2 |= 1; break; + case guncon3_btn::a3: gc.btn_a3 |= 1; break; + case guncon3_btn::b1: gc.btn_b1 |= 1; break; + case guncon3_btn::b2: gc.btn_b2 |= 1; break; + case guncon3_btn::b3: gc.btn_b3 |= 1; break; + case guncon3_btn::c1: gc.btn_c1 |= 1; break; + case guncon3_btn::c2: gc.btn_c2 |= 1; break; + case guncon3_btn::as_x: gc.stick_ax = static_cast(value); break; + case guncon3_btn::as_y: gc.stick_ay = static_cast(value); break; + case guncon3_btn::bs_x: gc.stick_bx = static_cast(value); break; + case guncon3_btn::bs_y: gc.stick_by = static_cast(value); break; + case guncon3_btn::count: break; } - else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2) - { - switch (button.m_outKeyCode) - { - case CELL_PAD_CTRL_CROSS: - gc.btn_trigger |= 1; - break; - case CELL_PAD_CTRL_L1: - gc.btn_a1 |= 1; - break; - case CELL_PAD_CTRL_L2: - gc.btn_a2 |= 1; - break; - case CELL_PAD_CTRL_R1: - gc.btn_b1 |= 1; - break; - case CELL_PAD_CTRL_R2: - gc.btn_b2 |= 1; - break; - default: - break; - } - } - } - - for (const AnalogStick& stick : pad->m_sticks) - { - switch (stick.m_offset) - { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: - gc.stick_ax = static_cast(stick.m_value); - break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: - gc.stick_ay = static_cast(stick.m_value); - break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: - gc.stick_bx = static_cast(stick.m_value); - break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: - gc.stick_by = static_cast(stick.m_value); - break; - default: - break; - } - } + }); } } diff --git a/rpcs3/Emu/Io/guncon3_config.h b/rpcs3/Emu/Io/guncon3_config.h new file mode 100644 index 0000000000..4a385b32f9 --- /dev/null +++ b/rpcs3/Emu/Io/guncon3_config.h @@ -0,0 +1,50 @@ +#pragma once + +#include "emulated_pad_config.h" + +#include + +enum class guncon3_btn +{ + trigger, + a1, + a2, + a3, + b1, + b2, + b3, + c1, + c2, + as_x, + as_y, + bs_x, + bs_y, + + count +}; + +struct cfg_gc3 final : public emulated_pad_config +{ + cfg_gc3(node* owner, const std::string& name) : emulated_pad_config(owner, name) {} + + cfg_pad_btn trigger{this, "Trigger", guncon3_btn::trigger, pad_button::cross}; + cfg_pad_btn a1{this, "A1", guncon3_btn::a1, pad_button::L1}; + cfg_pad_btn a2{this, "A2", guncon3_btn::a2, pad_button::L2}; + cfg_pad_btn a3{this, "A3", guncon3_btn::a3, pad_button::L3}; + cfg_pad_btn b1{this, "B1", guncon3_btn::b1, pad_button::R1}; + cfg_pad_btn b2{this, "B2", guncon3_btn::b2, pad_button::R2}; + cfg_pad_btn b3{this, "B3", guncon3_btn::b3, pad_button::R3}; + cfg_pad_btn c1{this, "C1", guncon3_btn::c1, pad_button::select}; + cfg_pad_btn c2{this, "C2", guncon3_btn::c2, pad_button::start}; + cfg_pad_btn as_x{this, "A-stick X-Axis", guncon3_btn::as_x, pad_button::ls_x}; + cfg_pad_btn as_y{this, "A-stick Y-Axis", guncon3_btn::as_y, pad_button::ls_y}; + cfg_pad_btn bs_x{this, "B-stick X-Axis", guncon3_btn::bs_x, pad_button::rs_x}; + cfg_pad_btn bs_y{this, "B-stick Y-Axis", guncon3_btn::bs_y, pad_button::rs_y}; +}; + +struct cfg_guncon3 final : public emulated_pads_config +{ + cfg_guncon3() : emulated_pads_config("guncon3") {}; +}; + +extern cfg_guncon3 g_cfg_guncon3; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 79e97817cf..405a59a13b 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -539,6 +539,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 5fe6e86034..3ae64c354a 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -2446,6 +2446,9 @@ Emu\Io + + Emu\Io + Emu\Io diff --git a/rpcs3/rpcs3qt/emulated_pad_settings_dialog.cpp b/rpcs3/rpcs3qt/emulated_pad_settings_dialog.cpp index 65c4879dca..a962670c21 100644 --- a/rpcs3/rpcs3qt/emulated_pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/emulated_pad_settings_dialog.cpp @@ -4,6 +4,7 @@ #include "Emu/Io/buzz_config.h" #include "Emu/Io/gem_config.h" #include "Emu/Io/ghltar_config.h" +#include "Emu/Io/guncon3_config.h" #include "Emu/Io/turntable_config.h" #include "Emu/Io/usio_config.h" #include "util/asm.hpp" @@ -83,6 +84,10 @@ emulated_pad_settings_dialog::emulated_pad_settings_dialog(pad_type type, QWidge setWindowTitle(tr("Configure Emulated PS Move (Fake)")); add_tabs(tabs); break; + case emulated_pad_settings_dialog::pad_type::guncon3: + setWindowTitle(tr("Configure Emulated GunCon 3")); + add_tabs(tabs); + break; } v_layout->addWidget(tabs); @@ -121,6 +126,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs) case pad_type::ds3gem: players = g_cfg_gem.players.size(); break; + case pad_type::guncon3: + players = g_cfg_guncon3.players.size(); + break; } m_combos.resize(players); @@ -166,6 +174,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs) case pad_type::ds3gem: saved_btn_id = ::at32(g_cfg_gem.players, player)->get_pad_button(static_cast(id)); break; + case pad_type::guncon3: + saved_btn_id = ::at32(g_cfg_guncon3.players, player)->get_pad_button(static_cast(id)); + break; } combo->setCurrentIndex(combo->findData(static_cast(saved_btn_id))); @@ -198,6 +209,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs) case pad_type::ds3gem: ::at32(g_cfg_gem.players, player)->set_button(static_cast(id), btn_id); break; + case pad_type::guncon3: + ::at32(g_cfg_guncon3.players, player)->set_button(static_cast(id), btn_id); + break; } }); @@ -252,6 +266,12 @@ void emulated_pad_settings_dialog::load_config() cfg_log.notice("Could not load gem config. Using defaults."); } break; + case emulated_pad_settings_dialog::pad_type::guncon3: + if (!g_cfg_guncon3.load()) + { + cfg_log.notice("Could not load guncon3 config. Using defaults."); + } + break; } } @@ -274,6 +294,9 @@ void emulated_pad_settings_dialog::save_config() case emulated_pad_settings_dialog::pad_type::ds3gem: g_cfg_gem.save(); break; + case emulated_pad_settings_dialog::pad_type::guncon3: + g_cfg_guncon3.save(); + break; } } @@ -296,6 +319,9 @@ void emulated_pad_settings_dialog::reset_config() case emulated_pad_settings_dialog::pad_type::ds3gem: g_cfg_gem.from_default(); break; + case emulated_pad_settings_dialog::pad_type::guncon3: + g_cfg_guncon3.from_default(); + break; } for (usz player = 0; player < m_combos.size(); player++) @@ -327,6 +353,9 @@ void emulated_pad_settings_dialog::reset_config() case pad_type::ds3gem: def_btn_id = ::at32(g_cfg_gem.players, player)->default_pad_button(static_cast(data.toInt())); break; + case pad_type::guncon3: + def_btn_id = ::at32(g_cfg_guncon3.players, player)->default_pad_button(static_cast(data.toInt())); + break; } combo->setCurrentIndex(combo->findData(static_cast(def_btn_id))); diff --git a/rpcs3/rpcs3qt/emulated_pad_settings_dialog.h b/rpcs3/rpcs3qt/emulated_pad_settings_dialog.h index cb5bf1b46a..96c16170e6 100644 --- a/rpcs3/rpcs3qt/emulated_pad_settings_dialog.h +++ b/rpcs3/rpcs3qt/emulated_pad_settings_dialog.h @@ -19,7 +19,8 @@ public: turntable, ghltar, usio, - ds3gem + ds3gem, + guncon3 }; emulated_pad_settings_dialog(pad_type type, QWidget* parent = nullptr); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 9bd7acf494..4bccb4abdc 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2751,6 +2751,12 @@ void main_window::CreateConnects() dlg->show(); }); + connect(ui->confGunCon3Act, &QAction::triggered, this, [this] + { + emulated_pad_settings_dialog* dlg = new emulated_pad_settings_dialog(emulated_pad_settings_dialog::pad_type::guncon3, this); + dlg->show(); + }); + connect(ui->confCamerasAct, &QAction::triggered, this, [this]() { camera_settings_dialog dlg(this); diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui index 7c5d338501..6f37b7cee8 100644 --- a/rpcs3/rpcs3qt/main_window.ui +++ b/rpcs3/rpcs3qt/main_window.ui @@ -240,6 +240,7 @@ + @@ -1324,6 +1325,11 @@ PS Move (Fake) + + + GunCon 3 + +