summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/emulated_controller.cpp44
-rw-r--r--src/input_common/drivers/tas_input.cpp23
-rw-r--r--src/input_common/drivers/tas_input.h14
-rw-r--r--src/yuzu/bootmanager.cpp1
-rw-r--r--src/yuzu/debugger/controller.cpp60
-rw-r--r--src/yuzu/debugger/controller.h26
-rw-r--r--src/yuzu/main.cpp2
7 files changed, 122 insertions, 48 deletions
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 3c3fa16d6..69568f4e9 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -127,7 +127,7 @@ void EmulatedController::LoadDevices() {
127 // Initialize TAS devices 127 // Initialize TAS devices
128 std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), 128 std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
129 Input::CreateDevice<Input::InputDevice>); 129 Input::CreateDevice<Input::InputDevice>);
130 std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(), 130 std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(),
131 Input::CreateDevice<Input::InputDevice>); 131 Input::CreateDevice<Input::InputDevice>);
132} 132}
133 133
@@ -135,7 +135,7 @@ void EmulatedController::LoadTASParams() {
135 const auto player_index = NpadIdTypeToIndex(npad_id_type); 135 const auto player_index = NpadIdTypeToIndex(npad_id_type);
136 Common::ParamPackage common_params{}; 136 Common::ParamPackage common_params{};
137 common_params.Set("engine", "tas"); 137 common_params.Set("engine", "tas");
138 common_params.Set("pad", static_cast<int>(player_index)); 138 common_params.Set("port", static_cast<int>(player_index));
139 for (auto& param : tas_button_params) { 139 for (auto& param : tas_button_params) {
140 param = common_params; 140 param = common_params;
141 } 141 }
@@ -144,26 +144,26 @@ void EmulatedController::LoadTASParams() {
144 } 144 }
145 145
146 // TODO(german77): Replace this with an input profile or something better 146 // TODO(german77): Replace this with an input profile or something better
147 tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); 147 tas_button_params[Settings::NativeButton::A].Set("button", 0);
148 tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); 148 tas_button_params[Settings::NativeButton::B].Set("button", 1);
149 tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); 149 tas_button_params[Settings::NativeButton::X].Set("button", 2);
150 tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3); 150 tas_button_params[Settings::NativeButton::Y].Set("button", 3);
151 tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4); 151 tas_button_params[Settings::NativeButton::LStick].Set("button", 4);
152 tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5); 152 tas_button_params[Settings::NativeButton::RStick].Set("button", 5);
153 tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6); 153 tas_button_params[Settings::NativeButton::L].Set("button", 6);
154 tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7); 154 tas_button_params[Settings::NativeButton::R].Set("button", 7);
155 tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8); 155 tas_button_params[Settings::NativeButton::ZL].Set("button", 8);
156 tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9); 156 tas_button_params[Settings::NativeButton::ZR].Set("button", 9);
157 tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10); 157 tas_button_params[Settings::NativeButton::Plus].Set("button", 10);
158 tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11); 158 tas_button_params[Settings::NativeButton::Minus].Set("button", 11);
159 tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12); 159 tas_button_params[Settings::NativeButton::DLeft].Set("button", 12);
160 tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13); 160 tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
161 tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14); 161 tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
162 tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15); 162 tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
163 tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16); 163 tas_button_params[Settings::NativeButton::SL].Set("button", 16);
164 tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17); 164 tas_button_params[Settings::NativeButton::SR].Set("button", 17);
165 tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18); 165 tas_button_params[Settings::NativeButton::Home].Set("button", 18);
166 tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19); 166 tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
167 167
168 tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); 168 tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
169 tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); 169 tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index 7e7a1d58f..d2748b240 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -141,7 +141,7 @@ void Tas::WriteTasFile(std::u8string file_name) {
141 } 141 }
142} 142}
143 143
144void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) { 144void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) {
145 last_input = { 145 last_input = {
146 .buttons = buttons, 146 .buttons = buttons,
147 .l_axis = FlipAxisY(left_axis), 147 .l_axis = FlipAxisY(left_axis),
@@ -195,7 +195,7 @@ void Tas::UpdateThread() {
195 } 195 }
196 if (current_command < script_length) { 196 if (current_command < script_length) {
197 LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length); 197 LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length);
198 size_t frame = current_command++; 198 const size_t frame = current_command++;
199 for (size_t player_index = 0; player_index < commands.size(); player_index++) { 199 for (size_t player_index = 0; player_index < commands.size(); player_index++) {
200 TASCommand command{}; 200 TASCommand command{};
201 if (frame < commands[player_index].size()) { 201 if (frame < commands[player_index].size()) {
@@ -207,8 +207,8 @@ void Tas::UpdateThread() {
207 .port = player_index, 207 .port = player_index,
208 .pad = 0, 208 .pad = 0,
209 }; 209 };
210 for (std::size_t i = 0; i < sizeof(command.buttons); ++i) { 210 for (std::size_t i = 0; i < sizeof(command.buttons) * 8; ++i) {
211 const bool button_status = (command.buttons & (1U << i)) != 0; 211 const bool button_status = (command.buttons & (1LLU << i)) != 0;
212 const int button = static_cast<int>(i); 212 const int button = static_cast<int>(i);
213 SetButton(identifier, button, button_status); 213 SetButton(identifier, button, button_status);
214 } 214 }
@@ -244,14 +244,14 @@ TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
244 return {x, y}; 244 return {x, y};
245} 245}
246 246
247u32 Tas::ReadCommandButtons(const std::string& data) const { 247u64 Tas::ReadCommandButtons(const std::string& data) const {
248 std::stringstream button_text(data); 248 std::stringstream button_text(data);
249 std::string line; 249 std::string line;
250 u32 buttons = 0; 250 u64 buttons = 0;
251 while (std::getline(button_text, line, ';')) { 251 while (std::getline(button_text, line, ';')) {
252 for (auto [text, tas_button] : text_to_tas_button) { 252 for (auto [text, tas_button] : text_to_tas_button) {
253 if (text == line) { 253 if (text == line) {
254 buttons |= static_cast<u32>(tas_button); 254 buttons |= static_cast<u64>(tas_button);
255 break; 255 break;
256 } 256 }
257 } 257 }
@@ -259,13 +259,14 @@ u32 Tas::ReadCommandButtons(const std::string& data) const {
259 return buttons; 259 return buttons;
260} 260}
261 261
262std::string Tas::WriteCommandButtons(u32 buttons) const { 262std::string Tas::WriteCommandButtons(u64 buttons) const {
263 std::string returns = ""; 263 std::string returns = "";
264 for (auto [text_button, tas_button] : text_to_tas_button) { 264 for (auto [text_button, tas_button] : text_to_tas_button) {
265 if ((buttons & static_cast<u32>(tas_button)) != 0) 265 if ((buttons & static_cast<u64>(tas_button)) != 0) {
266 returns += fmt::format("{};", text_button.substr(4)); 266 returns += fmt::format("{};", text_button);
267 }
267 } 268 }
268 return returns.empty() ? "NONE" : returns.substr(2); 269 return returns.empty() ? "NONE" : returns;
269} 270}
270 271
271std::string Tas::WriteCommandAxis(TasAnalog analog) const { 272std::string Tas::WriteCommandAxis(TasAnalog analog) const {
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index 9fadc118b..5f5c3267c 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -47,7 +47,7 @@ namespace InputCommon::TasInput {
47 47
48constexpr size_t PLAYER_NUMBER = 10; 48constexpr size_t PLAYER_NUMBER = 10;
49 49
50enum class TasButton : u32 { 50enum class TasButton : u64 {
51 BUTTON_A = 1U << 0, 51 BUTTON_A = 1U << 0,
52 BUTTON_B = 1U << 1, 52 BUTTON_B = 1U << 1,
53 BUTTON_X = 1U << 2, 53 BUTTON_X = 1U << 2,
@@ -92,7 +92,7 @@ public:
92 * @param left_axis: value of the left axis 92 * @param left_axis: value of the left axis
93 * @param right_axis: value of the right axis 93 * @param right_axis: value of the right axis
94 */ 94 */
95 void RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis); 95 void RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis);
96 96
97 // Main loop that records or executes input 97 // Main loop that records or executes input
98 void UpdateThread(); 98 void UpdateThread();
@@ -129,7 +129,7 @@ public:
129 129
130private: 130private:
131 struct TASCommand { 131 struct TASCommand {
132 u32 buttons{}; 132 u64 buttons{};
133 TasAnalog l_axis{}; 133 TasAnalog l_axis{};
134 TasAnalog r_axis{}; 134 TasAnalog r_axis{};
135 }; 135 };
@@ -164,9 +164,9 @@ private:
164 * Parses a string containing the button values. Each button is represented by it's text format 164 * Parses a string containing the button values. Each button is represented by it's text format
165 * specified in text_to_tas_button array 165 * specified in text_to_tas_button array
166 * @param line: string containing button name with the following format "a;b;c;d..." 166 * @param line: string containing button name with the following format "a;b;c;d..."
167 * @return Returns a u32 with each bit representing the status of a button 167 * @return Returns a u64 with each bit representing the status of a button
168 */ 168 */
169 u32 ReadCommandButtons(const std::string& line) const; 169 u64 ReadCommandButtons(const std::string& line) const;
170 170
171 /** 171 /**
172 * Reset state of all players 172 * Reset state of all players
@@ -174,11 +174,11 @@ private:
174 void ClearInput(); 174 void ClearInput();
175 175
176 /** 176 /**
177 * Converts an u32 containing the button status into the text equivalent 177 * Converts an u64 containing the button status into the text equivalent
178 * @param buttons: bitfield with the status of the buttons 178 * @param buttons: bitfield with the status of the buttons
179 * @return Returns a string with the name of the buttons to be written to the file 179 * @return Returns a string with the name of the buttons to be written to the file
180 */ 180 */
181 std::string WriteCommandButtons(u32 buttons) const; 181 std::string WriteCommandButtons(u64 buttons) const;
182 182
183 /** 183 /**
184 * Converts an TAS analog object containing the axis status into the text equivalent 184 * Converts an TAS analog object containing the axis status into the text equivalent
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 726f789b7..4b3cd9f3e 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -35,6 +35,7 @@
35#include "core/frontend/framebuffer_layout.h" 35#include "core/frontend/framebuffer_layout.h"
36#include "input_common/drivers/keyboard.h" 36#include "input_common/drivers/keyboard.h"
37#include "input_common/drivers/mouse.h" 37#include "input_common/drivers/mouse.h"
38#include "input_common/drivers/tas_input.h"
38#include "input_common/drivers/touch_screen.h" 39#include "input_common/drivers/touch_screen.h"
39#include "input_common/main.h" 40#include "input_common/main.h"
40#include "video_core/renderer_base.h" 41#include "video_core/renderer_base.h"
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index f93a46421..aaca494b8 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -7,11 +7,16 @@
7#include <QString> 7#include <QString>
8#include "common/settings.h" 8#include "common/settings.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hid/emulated_controller.h"
11#include "input_common/drivers/tas_input.h"
12#include "input_common/main.h"
10#include "yuzu/configuration/configure_input_player_widget.h" 13#include "yuzu/configuration/configure_input_player_widget.h"
11#include "yuzu/debugger/controller.h" 14#include "yuzu/debugger/controller.h"
12 15
13ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) 16ControllerDialog::ControllerDialog(Core::System& system_,
14 : QWidget(parent, Qt::Dialog) { 17 std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
18 QWidget* parent)
19 : QWidget(parent, Qt::Dialog), system{system_}, input_subsystem{input_subsystem_} {
15 setObjectName(QStringLiteral("Controller")); 20 setObjectName(QStringLiteral("Controller"));
16 setWindowTitle(tr("Controller P1")); 21 setWindowTitle(tr("Controller P1"));
17 resize(500, 350); 22 resize(500, 350);
@@ -21,7 +26,7 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
21 Qt::WindowMaximizeButtonHint); 26 Qt::WindowMaximizeButtonHint);
22 27
23 widget = new PlayerControlPreview(this); 28 widget = new PlayerControlPreview(this);
24 widget->SetController(system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1)); 29 refreshConfiguration();
25 QLayout* layout = new QVBoxLayout(this); 30 QLayout* layout = new QVBoxLayout(this);
26 layout->setContentsMargins(0, 0, 0, 0); 31 layout->setContentsMargins(0, 0, 0, 0);
27 layout->addWidget(widget); 32 layout->addWidget(widget);
@@ -34,6 +39,22 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
34 widget->setFocus(); 39 widget->setFocus();
35} 40}
36 41
42void ControllerDialog::refreshConfiguration() {
43 UnloadController();
44 auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
45 auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
46 // Display the correct controller
47 controller = handheld->IsConnected() ? handheld : player_1;
48
49 Core::HID::ControllerUpdateCallback engine_callback{
50 .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
51 .is_npad_service = true,
52 };
53 callback_key = controller->SetCallback(engine_callback);
54 widget->SetController(controller);
55 is_controller_set = true;
56}
57
37QAction* ControllerDialog::toggleViewAction() { 58QAction* ControllerDialog::toggleViewAction() {
38 if (toggle_view_action == nullptr) { 59 if (toggle_view_action == nullptr) {
39 toggle_view_action = new QAction(tr("&Controller P1"), this); 60 toggle_view_action = new QAction(tr("&Controller P1"), this);
@@ -47,6 +68,10 @@ QAction* ControllerDialog::toggleViewAction() {
47 68
48void ControllerDialog::UnloadController() { 69void ControllerDialog::UnloadController() {
49 widget->UnloadController(); 70 widget->UnloadController();
71 if (is_controller_set) {
72 controller->DeleteCallback(callback_key);
73 is_controller_set = false;
74 }
50} 75}
51 76
52void ControllerDialog::showEvent(QShowEvent* ev) { 77void ControllerDialog::showEvent(QShowEvent* ev) {
@@ -62,3 +87,32 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
62 } 87 }
63 QWidget::hideEvent(ev); 88 QWidget::hideEvent(ev);
64} 89}
90
91void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) {
92 // TODO(german77): Remove TAS from here
93 switch (type) {
94 case Core::HID::ControllerTriggerType::Button:
95 case Core::HID::ControllerTriggerType::Stick: {
96 const auto buttons_values = controller->GetButtonsValues();
97 const auto stick_values = controller->GetSticksValues();
98 u64 buttons = 0;
99 std::size_t index = 0;
100 for (const auto& button : buttons_values) {
101 buttons |= button.value ? 1LLU << index : 0;
102 index++;
103 }
104 const InputCommon::TasInput::TasAnalog left_axis = {
105 .x = stick_values[Settings::NativeAnalog::LStick].x.value,
106 .y = stick_values[Settings::NativeAnalog::LStick].y.value,
107 };
108 const InputCommon::TasInput::TasAnalog right_axis = {
109 .x = stick_values[Settings::NativeAnalog::RStick].x.value,
110 .y = stick_values[Settings::NativeAnalog::RStick].y.value,
111 };
112 input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis);
113 break;
114 }
115 default:
116 break;
117 }
118}
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index 33f617b9b..ba4185a4b 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -11,24 +11,33 @@ class QHideEvent;
11class QShowEvent; 11class QShowEvent;
12class PlayerControlPreview; 12class PlayerControlPreview;
13 13
14namespace InputCommon {
15class InputSubsystem;
16}
17
14namespace Core { 18namespace Core {
15class System; 19class System;
16} 20}
17 21
18namespace InputCommon { 22namespace Core::HID {
19class InputSubsystem; 23class EmulatedController;
20} 24}
21 25
22class ControllerDialog : public QWidget { 26class ControllerDialog : public QWidget {
23 Q_OBJECT 27 Q_OBJECT
24 28
25public: 29public:
26 explicit ControllerDialog(Core::System& system, QWidget* parent = nullptr); 30 explicit ControllerDialog(Core::System& system_,
31 std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
32 QWidget* parent = nullptr);
27 33
28 /// Returns a QAction that can be used to toggle visibility of this dialog. 34 /// Returns a QAction that can be used to toggle visibility of this dialog.
29 QAction* toggleViewAction(); 35 QAction* toggleViewAction();
30 36
31 // Disables events from the emulated controller 37 /// Reloads the widget to apply any changes in the configuration
38 void refreshConfiguration();
39
40 /// Disables events from the emulated controller
32 void UnloadController(); 41 void UnloadController();
33 42
34protected: 43protected:
@@ -36,6 +45,15 @@ protected:
36 void hideEvent(QHideEvent* ev) override; 45 void hideEvent(QHideEvent* ev) override;
37 46
38private: 47private:
48 /// Redirects input from the widget to the TAS driver
49 void ControllerUpdate(Core::HID::ControllerTriggerType type);
50
51 int callback_key;
52 bool is_controller_set{};
53 Core::HID::EmulatedController* controller;
54
39 QAction* toggle_view_action = nullptr; 55 QAction* toggle_view_action = nullptr;
40 PlayerControlPreview* widget; 56 PlayerControlPreview* widget;
57 Core::System& system;
58 std::shared_ptr<InputCommon::InputSubsystem> input_subsystem;
41}; 59};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 022d11cc4..56db337a4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -925,7 +925,7 @@ void GMainWindow::InitializeDebugWidgets() {
925 waitTreeWidget->hide(); 925 waitTreeWidget->hide();
926 debug_menu->addAction(waitTreeWidget->toggleViewAction()); 926 debug_menu->addAction(waitTreeWidget->toggleViewAction());
927 927
928 controller_dialog = new ControllerDialog(*system, this); 928 controller_dialog = new ControllerDialog(*system, input_subsystem, this);
929 controller_dialog->hide(); 929 controller_dialog->hide();
930 debug_menu->addAction(controller_dialog->toggleViewAction()); 930 debug_menu->addAction(controller_dialog->toggleViewAction());
931 931