summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/input.h2
-rw-r--r--src/core/hid/emulated_controller.cpp75
-rw-r--r--src/core/hid/emulated_controller.h6
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp3
-rw-r--r--src/input_common/input_poller.cpp30
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp17
6 files changed, 115 insertions, 18 deletions
diff --git a/src/common/input.h b/src/common/input.h
index d61cd7ca8..b5748a6c8 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -130,6 +130,8 @@ struct ButtonStatus {
130 bool inverted{}; 130 bool inverted{};
131 // Press once to activate, press again to release 131 // Press once to activate, press again to release
132 bool toggle{}; 132 bool toggle{};
133 // Spams the button when active
134 bool turbo{};
133 // Internal lock for the toggle status 135 // Internal lock for the toggle status
134 bool locked{}; 136 bool locked{};
135}; 137};
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 0e06468da..631aa6ad2 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -12,6 +12,7 @@
12namespace Core::HID { 12namespace Core::HID {
13constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 13constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
14constexpr s32 HID_TRIGGER_MAX = 0x7fff; 14constexpr s32 HID_TRIGGER_MAX = 0x7fff;
15constexpr u32 TURBO_BUTTON_DELAY = 4;
15// Use a common UUID for TAS and Virtual Gamepad 16// Use a common UUID for TAS and Virtual Gamepad
16constexpr Common::UUID TAS_UUID = 17constexpr Common::UUID TAS_UUID =
17 Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 18 Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
@@ -447,6 +448,7 @@ void EmulatedController::ReloadInput() {
447 }, 448 },
448 }); 449 });
449 } 450 }
451 turbo_button_state = 0;
450} 452}
451 453
452void EmulatedController::UnloadInput() { 454void EmulatedController::UnloadInput() {
@@ -687,6 +689,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
687 } 689 }
688 690
689 current_status.toggle = new_status.toggle; 691 current_status.toggle = new_status.toggle;
692 current_status.turbo = new_status.turbo;
690 current_status.uuid = uuid; 693 current_status.uuid = uuid;
691 694
692 // Update button status with current 695 // Update button status with current
@@ -1548,7 +1551,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const {
1548 if (is_configuring) { 1551 if (is_configuring) {
1549 return {}; 1552 return {};
1550 } 1553 }
1551 return controller.npad_button_state; 1554 return {controller.npad_button_state.raw & GetTurboButtonMask()};
1552} 1555}
1553 1556
1554DebugPadButton EmulatedController::GetDebugPadButtons() const { 1557DebugPadButton EmulatedController::GetDebugPadButtons() const {
@@ -1656,4 +1659,74 @@ void EmulatedController::DeleteCallback(int key) {
1656 } 1659 }
1657 callback_list.erase(iterator); 1660 callback_list.erase(iterator);
1658} 1661}
1662
1663void EmulatedController::TurboButtonUpdate() {
1664 turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2);
1665}
1666
1667NpadButton EmulatedController::GetTurboButtonMask() const {
1668 // Apply no mask when disabled
1669 if (turbo_button_state < TURBO_BUTTON_DELAY) {
1670 return {NpadButton::All};
1671 }
1672
1673 NpadButtonState button_mask{};
1674 for (std::size_t index = 0; index < controller.button_values.size(); ++index) {
1675 if (!controller.button_values[index].turbo) {
1676 continue;
1677 }
1678
1679 switch (index) {
1680 case Settings::NativeButton::A:
1681 button_mask.a.Assign(1);
1682 break;
1683 case Settings::NativeButton::B:
1684 button_mask.b.Assign(1);
1685 break;
1686 case Settings::NativeButton::X:
1687 button_mask.x.Assign(1);
1688 break;
1689 case Settings::NativeButton::Y:
1690 button_mask.y.Assign(1);
1691 break;
1692 case Settings::NativeButton::L:
1693 button_mask.l.Assign(1);
1694 break;
1695 case Settings::NativeButton::R:
1696 button_mask.r.Assign(1);
1697 break;
1698 case Settings::NativeButton::ZL:
1699 button_mask.zl.Assign(1);
1700 break;
1701 case Settings::NativeButton::ZR:
1702 button_mask.zr.Assign(1);
1703 break;
1704 case Settings::NativeButton::DLeft:
1705 button_mask.left.Assign(1);
1706 break;
1707 case Settings::NativeButton::DUp:
1708 button_mask.up.Assign(1);
1709 break;
1710 case Settings::NativeButton::DRight:
1711 button_mask.right.Assign(1);
1712 break;
1713 case Settings::NativeButton::DDown:
1714 button_mask.down.Assign(1);
1715 break;
1716 case Settings::NativeButton::SL:
1717 button_mask.left_sl.Assign(1);
1718 button_mask.right_sl.Assign(1);
1719 break;
1720 case Settings::NativeButton::SR:
1721 button_mask.left_sr.Assign(1);
1722 button_mask.right_sr.Assign(1);
1723 break;
1724 default:
1725 break;
1726 }
1727 }
1728
1729 return static_cast<NpadButton>(~button_mask.raw);
1730}
1731
1659} // namespace Core::HID 1732} // namespace Core::HID
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 3ac77b2b5..b02bf35c4 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -411,6 +411,9 @@ public:
411 */ 411 */
412 void DeleteCallback(int key); 412 void DeleteCallback(int key);
413 413
414 /// Swaps the state of the turbo buttons
415 void TurboButtonUpdate();
416
414private: 417private:
415 /// creates input devices from params 418 /// creates input devices from params
416 void LoadDevices(); 419 void LoadDevices();
@@ -511,6 +514,8 @@ private:
511 */ 514 */
512 void TriggerOnChange(ControllerTriggerType type, bool is_service_update); 515 void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
513 516
517 NpadButton GetTurboButtonMask() const;
518
514 const NpadIdType npad_id_type; 519 const NpadIdType npad_id_type;
515 NpadStyleIndex npad_type{NpadStyleIndex::None}; 520 NpadStyleIndex npad_type{NpadStyleIndex::None};
516 NpadStyleIndex original_npad_type{NpadStyleIndex::None}; 521 NpadStyleIndex original_npad_type{NpadStyleIndex::None};
@@ -520,6 +525,7 @@ private:
520 bool system_buttons_enabled{true}; 525 bool system_buttons_enabled{true};
521 f32 motion_sensitivity{0.01f}; 526 f32 motion_sensitivity{0.01f};
522 bool force_update_motion{false}; 527 bool force_update_motion{false};
528 u32 turbo_button_state{0};
523 529
524 // Temporary values to avoid doing changes while the controller is in configuring mode 530 // Temporary values to avoid doing changes while the controller is in configuring mode
525 NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; 531 NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 5713f1288..3afda9e3f 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -428,6 +428,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
428 return; 428 return;
429 } 429 }
430 430
431 // This function is unique to yuzu for the turbo buttons to work properly
432 controller.device->TurboButtonUpdate();
433
431 auto& pad_entry = controller.npad_pad_state; 434 auto& pad_entry = controller.npad_pad_state;
432 auto& trigger_entry = controller.npad_trigger_state; 435 auto& trigger_entry = controller.npad_trigger_state;
433 const auto button_state = controller.device->GetNpadButtons(); 436 const auto button_state = controller.device->GetNpadButtons();
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 15cbf7e5f..8c6a6521a 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -16,10 +16,10 @@ public:
16 16
17class InputFromButton final : public Common::Input::InputDevice { 17class InputFromButton final : public Common::Input::InputDevice {
18public: 18public:
19 explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, 19 explicit InputFromButton(PadIdentifier identifier_, int button_, bool turbo_, bool toggle_,
20 InputEngine* input_engine_) 20 bool inverted_, InputEngine* input_engine_)
21 : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), 21 : identifier(identifier_), button(button_), turbo(turbo_), toggle(toggle_),
22 input_engine(input_engine_) { 22 inverted(inverted_), input_engine(input_engine_) {
23 UpdateCallback engine_callback{[this]() { OnChange(); }}; 23 UpdateCallback engine_callback{[this]() { OnChange(); }};
24 const InputIdentifier input_identifier{ 24 const InputIdentifier input_identifier{
25 .identifier = identifier, 25 .identifier = identifier,
@@ -40,6 +40,7 @@ public:
40 .value = input_engine->GetButton(identifier, button), 40 .value = input_engine->GetButton(identifier, button),
41 .inverted = inverted, 41 .inverted = inverted,
42 .toggle = toggle, 42 .toggle = toggle,
43 .turbo = turbo,
43 }; 44 };
44 } 45 }
45 46
@@ -68,6 +69,7 @@ public:
68private: 69private:
69 const PadIdentifier identifier; 70 const PadIdentifier identifier;
70 const int button; 71 const int button;
72 const bool turbo;
71 const bool toggle; 73 const bool toggle;
72 const bool inverted; 74 const bool inverted;
73 int callback_key; 75 int callback_key;
@@ -77,10 +79,10 @@ private:
77 79
78class InputFromHatButton final : public Common::Input::InputDevice { 80class InputFromHatButton final : public Common::Input::InputDevice {
79public: 81public:
80 explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, 82 explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool turbo_,
81 bool inverted_, InputEngine* input_engine_) 83 bool toggle_, bool inverted_, InputEngine* input_engine_)
82 : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), 84 : identifier(identifier_), button(button_), direction(direction_), turbo(turbo_),
83 inverted(inverted_), input_engine(input_engine_) { 85 toggle(toggle_), inverted(inverted_), input_engine(input_engine_) {
84 UpdateCallback engine_callback{[this]() { OnChange(); }}; 86 UpdateCallback engine_callback{[this]() { OnChange(); }};
85 const InputIdentifier input_identifier{ 87 const InputIdentifier input_identifier{
86 .identifier = identifier, 88 .identifier = identifier,
@@ -101,6 +103,7 @@ public:
101 .value = input_engine->GetHatButton(identifier, button, direction), 103 .value = input_engine->GetHatButton(identifier, button, direction),
102 .inverted = inverted, 104 .inverted = inverted,
103 .toggle = toggle, 105 .toggle = toggle,
106 .turbo = turbo,
104 }; 107 };
105 } 108 }
106 109
@@ -130,6 +133,7 @@ private:
130 const PadIdentifier identifier; 133 const PadIdentifier identifier;
131 const int button; 134 const int button;
132 const u8 direction; 135 const u8 direction;
136 const bool turbo;
133 const bool toggle; 137 const bool toggle;
134 const bool inverted; 138 const bool inverted;
135 int callback_key; 139 int callback_key;
@@ -853,14 +857,15 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
853 const auto keyboard_key = params.Get("code", 0); 857 const auto keyboard_key = params.Get("code", 0);
854 const auto toggle = params.Get("toggle", false) != 0; 858 const auto toggle = params.Get("toggle", false) != 0;
855 const auto inverted = params.Get("inverted", false) != 0; 859 const auto inverted = params.Get("inverted", false) != 0;
860 const auto turbo = params.Get("turbo", false) != 0;
856 input_engine->PreSetController(identifier); 861 input_engine->PreSetController(identifier);
857 input_engine->PreSetButton(identifier, button_id); 862 input_engine->PreSetButton(identifier, button_id);
858 input_engine->PreSetButton(identifier, keyboard_key); 863 input_engine->PreSetButton(identifier, keyboard_key);
859 if (keyboard_key != 0) { 864 if (keyboard_key != 0) {
860 return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted, 865 return std::make_unique<InputFromButton>(identifier, keyboard_key, turbo, toggle, inverted,
861 input_engine.get()); 866 input_engine.get());
862 } 867 }
863 return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted, 868 return std::make_unique<InputFromButton>(identifier, button_id, turbo, toggle, inverted,
864 input_engine.get()); 869 input_engine.get());
865} 870}
866 871
@@ -876,11 +881,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
876 const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); 881 const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
877 const auto toggle = params.Get("toggle", false) != 0; 882 const auto toggle = params.Get("toggle", false) != 0;
878 const auto inverted = params.Get("inverted", false) != 0; 883 const auto inverted = params.Get("inverted", false) != 0;
884 const auto turbo = params.Get("turbo", false) != 0;
879 885
880 input_engine->PreSetController(identifier); 886 input_engine->PreSetController(identifier);
881 input_engine->PreSetHatButton(identifier, button_id); 887 input_engine->PreSetHatButton(identifier, button_id);
882 return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted, 888 return std::make_unique<InputFromHatButton>(identifier, button_id, direction, turbo, toggle,
883 input_engine.get()); 889 inverted, input_engine.get());
884} 890}
885 891
886std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( 892std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 4b7e3b01b..723690e71 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -182,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
182 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); 182 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
183 const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); 183 const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : "");
184 const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); 184 const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : "");
185 const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : "");
185 const auto common_button_name = input_subsystem->GetButtonName(param); 186 const auto common_button_name = input_subsystem->GetButtonName(param);
186 187
187 // Retrieve the names from Qt 188 // Retrieve the names from Qt
188 if (param.Get("engine", "") == "keyboard") { 189 if (param.Get("engine", "") == "keyboard") {
189 const QString button_str = GetKeyName(param.Get("code", 0)); 190 const QString button_str = GetKeyName(param.Get("code", 0));
190 return QObject::tr("%1%2%3").arg(toggle, inverted, button_str); 191 return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str);
191 } 192 }
192 193
193 if (common_button_name == Common::Input::ButtonNames::Invalid) { 194 if (common_button_name == Common::Input::ButtonNames::Invalid) {
@@ -201,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
201 if (common_button_name == Common::Input::ButtonNames::Value) { 202 if (common_button_name == Common::Input::ButtonNames::Value) {
202 if (param.Has("hat")) { 203 if (param.Has("hat")) {
203 const QString hat = GetDirectionName(param.Get("direction", "")); 204 const QString hat = GetDirectionName(param.Get("direction", ""));
204 return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); 205 return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat);
205 } 206 }
206 if (param.Has("axis")) { 207 if (param.Has("axis")) {
207 const QString axis = QString::fromStdString(param.Get("axis", "")); 208 const QString axis = QString::fromStdString(param.Get("axis", ""));
@@ -219,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
219 } 220 }
220 if (param.Has("button")) { 221 if (param.Has("button")) {
221 const QString button = QString::fromStdString(param.Get("button", "")); 222 const QString button = QString::fromStdString(param.Get("button", ""));
222 return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); 223 return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button);
223 } 224 }
224 } 225 }
225 226
226 QString button_name = GetButtonName(common_button_name); 227 QString button_name = GetButtonName(common_button_name);
227 if (param.Has("hat")) { 228 if (param.Has("hat")) {
228 return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); 229 return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name);
229 } 230 }
230 if (param.Has("axis")) { 231 if (param.Has("axis")) {
231 return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); 232 return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
@@ -234,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
234 return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); 235 return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
235 } 236 }
236 if (param.Has("button")) { 237 if (param.Has("button")) {
237 return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); 238 return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name);
238 } 239 }
239 240
240 return QObject::tr("[unknown]"); 241 return QObject::tr("[unknown]");
@@ -395,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
395 button_map[button_id]->setText(ButtonToText(param)); 396 button_map[button_id]->setText(ButtonToText(param));
396 emulated_controller->SetButtonParam(button_id, param); 397 emulated_controller->SetButtonParam(button_id, param);
397 }); 398 });
399 context_menu.addAction(tr("Turbo button"), [&] {
400 const bool turbo_value = !param.Get("turbo", false);
401 param.Set("turbo", turbo_value);
402 button_map[button_id]->setText(ButtonToText(param));
403 emulated_controller->SetButtonParam(button_id, param);
404 });
398 } 405 }
399 if (param.Has("axis")) { 406 if (param.Has("axis")) {
400 context_menu.addAction(tr("Invert axis"), [&] { 407 context_menu.addAction(tr("Invert axis"), [&] {