summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/settings.h11
-rw-r--r--src/input_common/tas/tas_input.cpp3
-rw-r--r--src/input_common/tas/tas_input.h108
-rw-r--r--src/input_common/tas/tas_poller.h4
-rw-r--r--src/yuzu/configuration/config.cpp39
-rw-r--r--src/yuzu/configuration/configure_filesystem.cpp1
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp22
-rw-r--r--src/yuzu/configuration/configure_tas.cpp16
8 files changed, 153 insertions, 51 deletions
diff --git a/src/common/settings.h b/src/common/settings.h
index cf12c325c..c53d5acc3 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -512,17 +512,14 @@ struct Values {
512 "motion_device"}; 512 "motion_device"};
513 BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; 513 BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
514 514
515 BasicSetting<bool> pause_tas_on_load { false, "pause_tas_on_load" }; 515 BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
516 BasicSetting<bool> tas_enable{ false, "tas_enable" }; 516 BasicSetting<bool> tas_enable{false, "tas_enable"};
517 BasicSetting<bool> tas_loop{ false, "tas_loop" }; 517 BasicSetting<bool> tas_loop{false, "tas_loop"};
518 BasicSetting<bool> tas_swap_controllers{ false, "tas_swap_controllers" }; 518 BasicSetting<bool> tas_swap_controllers{true, "tas_swap_controllers"};
519 BasicSetting<bool> is_cpu_boosted{ false, "is_cpu_boosted" };
520" };
521 519
522 BasicSetting<bool> mouse_panning{false, "mouse_panning"}; 520 BasicSetting<bool> mouse_panning{false, "mouse_panning"};
523 BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; 521 BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
524 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; 522 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
525
526 std::string mouse_device; 523 std::string mouse_device;
527 MouseButtonsRaw mouse_buttons; 524 MouseButtonsRaw mouse_buttons;
528 525
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp
index aceb13adc..877d35088 100644
--- a/src/input_common/tas/tas_input.cpp
+++ b/src/input_common/tas/tas_input.cpp
@@ -14,6 +14,7 @@
14 14
15namespace TasInput { 15namespace TasInput {
16 16
17// Supported keywords and buttons from a TAS file
17constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = { 18constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = {
18 std::pair{"KEY_A", TasButton::BUTTON_A}, 19 std::pair{"KEY_A", TasButton::BUTTON_A},
19 {"KEY_B", TasButton::BUTTON_B}, 20 {"KEY_B", TasButton::BUTTON_B},
@@ -214,7 +215,7 @@ void Tas::UpdateThread() {
214 } 215 }
215 } 216 }
216 } else { 217 } else {
217 is_running = Settings::values.tas_loop; 218 is_running = Settings::values.tas_loop.GetValue();
218 current_command = 0; 219 current_command = 0;
219 tas_data.fill({}); 220 tas_data.fill({});
220 if (!is_running) { 221 if (!is_running) {
diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h
index e1f351251..52d000db4 100644
--- a/src/input_common/tas/tas_input.h
+++ b/src/input_common/tas/tas_input.h
@@ -11,6 +11,38 @@
11#include "core/frontend/input.h" 11#include "core/frontend/input.h"
12#include "input_common/main.h" 12#include "input_common/main.h"
13 13
14/*
15To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
16Emulation -> Configure TAS. The file itself has normal text format and has to be called
17script0-1.txt for controller 1, script0-2.txt for controller 2 and so forth (with max. 8 players).
18
19A script file has the same format as TAS-nx uses, so final files will look like this:
20
211 KEY_B 0;0 0;0
226 KEY_ZL 0;0 0;0
2341 KEY_ZL;KEY_Y 0;0 0;0
2443 KEY_X;KEY_A 32767;0 0;0
2544 KEY_A 32767;0 0;0
2645 KEY_A 32767;0 0;0
2746 KEY_A 32767;0 0;0
2847 KEY_A 32767;0 0;0
29
30After placing the file at the correct location, it can be read into Yuzu with the (default) hotkey
31CTRL+F6 (refresh). In the bottom left corner, it will display the amount of frames the script file
32has. Playback can be started or stopped using CTRL+F5.
33
34However, for playback to actually work, the correct input device has to be selected: In the Controls
35menu, select TAS from the device list for the controller that the script should be played on.
36
37Recording a new script file is really simple: Just make sure that the proper device (not TAS) is
38connected on P1, and press CTRL+F7 to start recording. When done, just press the same keystroke
39again (CTRL+F7). The new script will be saved at the location previously selected, as the filename
40record.txt.
41
42For debugging purposes, the common controller debugger can be used (View -> Debugging -> Controller
43P1).
44*/
45
14namespace TasInput { 46namespace TasInput {
15 47
16constexpr size_t PLAYER_NUMBER = 8; 48constexpr size_t PLAYER_NUMBER = 8;
@@ -64,12 +96,26 @@ public:
64 Tas(); 96 Tas();
65 ~Tas(); 97 ~Tas();
66 98
99 // Changes the input status that will be stored in each frame
67 void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes); 100 void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes);
101
102 // Main loop that records or executes input
68 void UpdateThread(); 103 void UpdateThread();
69 104
105 // Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
70 void StartStop(); 106 void StartStop();
107
108 // Sets the flag to reload the file and start from the begining in the next update
71 void Reset(); 109 void Reset();
110
111 /**
112 * Sets the flag to enable or disable recording of inputs
113 * @return Returns true if the current recording status is enabled
114 */
72 bool Record(); 115 bool Record();
116
117 // Saves contents of record_commands on a file if overwrite is enabled player 1 will be
118 // overwritten with the recorded commands
73 void SaveRecording(bool overwrite_file); 119 void SaveRecording(bool overwrite_file);
74 120
75 /** 121 /**
@@ -80,7 +126,11 @@ public:
80 * Total length of script file currently loaded or amount of frames (so far) for Recording 126 * Total length of script file currently loaded or amount of frames (so far) for Recording
81 */ 127 */
82 std::tuple<TasState, size_t, size_t> GetStatus() const; 128 std::tuple<TasState, size_t, size_t> GetStatus() const;
129
130 // Retuns an array of the default button mappings
83 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const; 131 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
132
133 // Retuns an array of the default analog mappings
84 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const; 134 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
85 [[nodiscard]] const TasData& GetTasState(std::size_t pad) const; 135 [[nodiscard]] const TasData& GetTasState(std::size_t pad) const;
86 136
@@ -90,23 +140,81 @@ private:
90 TasAnalog l_axis{}; 140 TasAnalog l_axis{};
91 TasAnalog r_axis{}; 141 TasAnalog r_axis{};
92 }; 142 };
143
144 // Loads TAS files from all players
93 void LoadTasFiles(); 145 void LoadTasFiles();
146
147 // Loads TAS file from the specified player
94 void LoadTasFile(size_t player_index); 148 void LoadTasFile(size_t player_index);
149
150 // Writes a TAS file from the recorded commands
95 void WriteTasFile(std::u8string file_name); 151 void WriteTasFile(std::u8string file_name);
152
153 /**
154 * Parses a string containing the axis values with the following format "x;y"
155 * X and Y have a range from -32767 to 32767
156 * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
157 */
96 TasAnalog ReadCommandAxis(const std::string& line) const; 158 TasAnalog ReadCommandAxis(const std::string& line) const;
159
160 /**
161 * Parses a string containing the button values with the following format "a;b;c;d..."
162 * Each button is represented by it's text format specified in text_to_tas_button array
163 * @return Returns a u32 with each bit representing the status of a button
164 */
97 u32 ReadCommandButtons(const std::string& line) const; 165 u32 ReadCommandButtons(const std::string& line) const;
166
167 /**
168 * Converts an u32 containing the button status into the text equivalent
169 * @return Returns a string with the name of the buttons to be written to the file
170 */
98 std::string WriteCommandButtons(u32 data) const; 171 std::string WriteCommandButtons(u32 data) const;
172
173 /**
174 * Converts an TAS analog object containing the axis status into the text equivalent
175 * @return Returns a string with the value of the axis to be written to the file
176 */
99 std::string WriteCommandAxis(TasAnalog data) const; 177 std::string WriteCommandAxis(TasAnalog data) const;
100 178
179 // Inverts the Y axis polarity
101 std::pair<float, float> FlipAxisY(std::pair<float, float> old); 180 std::pair<float, float> FlipAxisY(std::pair<float, float> old);
102 181
182 /**
183 * Converts an u32 containing the button status into the text equivalent
184 * @return Returns a string with the name of the buttons to be printed on console
185 */
103 std::string DebugButtons(u32 buttons) const; 186 std::string DebugButtons(u32 buttons) const;
187
188 /**
189 * Converts an TAS analog object containing the axis status into the text equivalent
190 * @return Returns a string with the value of the axis to be printed on console
191 */
104 std::string DebugJoystick(float x, float y) const; 192 std::string DebugJoystick(float x, float y) const;
193
194 /**
195 * Converts the given TAS status into the text equivalent
196 * @return Returns a string with the value of the TAS status to be printed on console
197 */
105 std::string DebugInput(const TasData& data) const; 198 std::string DebugInput(const TasData& data) const;
199
200 /**
201 * Converts the given TAS status of multiple players into the text equivalent
202 * @return Returns a string with the value of the status of all TAS players to be printed on
203 * console
204 */
106 std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const; 205 std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const;
206
207 /**
208 * Converts an u32 containing the button status into the text equivalent
209 * @return Returns a string with the name of the buttons
210 */
107 std::string ButtonsToString(u32 button) const; 211 std::string ButtonsToString(u32 button) const;
108 212
213 // Stores current controller configuration and sets a TAS controller for every active controller
214 // to the current config
109 void SwapToTasController(); 215 void SwapToTasController();
216
217 // Sets the stored controller configuration to the current config
110 void SwapToStoredController(); 218 void SwapToStoredController();
111 219
112 size_t script_length{0}; 220 size_t script_length{0};
diff --git a/src/input_common/tas/tas_poller.h b/src/input_common/tas/tas_poller.h
index 1bc0d173b..09e426cef 100644
--- a/src/input_common/tas/tas_poller.h
+++ b/src/input_common/tas/tas_poller.h
@@ -11,7 +11,7 @@
11namespace InputCommon { 11namespace InputCommon {
12 12
13/** 13/**
14 * A button device factory representing a mouse. It receives mouse events and forward them 14 * A button device factory representing a tas bot. It receives tas events and forward them
15 * to all button devices it created. 15 * to all button devices it created.
16 */ 16 */
17class TasButtonFactory final : public Input::Factory<Input::ButtonDevice> { 17class TasButtonFactory final : public Input::Factory<Input::ButtonDevice> {
@@ -29,7 +29,7 @@ private:
29 std::shared_ptr<TasInput::Tas> tas_input; 29 std::shared_ptr<TasInput::Tas> tas_input;
30}; 30};
31 31
32/// An analog device factory that creates analog devices from mouse 32/// An analog device factory that creates analog devices from tas
33class TasAnalogFactory final : public Input::Factory<Input::AnalogDevice> { 33class TasAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
34public: 34public:
35 explicit TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_); 35 explicit TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_);
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index a0dfa06df..27b67fd9e 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -567,8 +567,10 @@ void Config::ReadControlValues() {
567 Settings::values.mouse_panning = false; 567 Settings::values.mouse_panning = false;
568 ReadBasicSetting(Settings::values.mouse_panning_sensitivity); 568 ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
569 569
570 ReadBasicSetting(Settings::values.tas_enable = false); 570 ReadBasicSetting(Settings::values.tas_enable);
571 ReadBasicSetting(Settings::values.tas_reset = false); 571 ReadBasicSetting(Settings::values.tas_loop);
572 ReadBasicSetting(Settings::values.tas_swap_controllers);
573 ReadBasicSetting(Settings::values.pause_tas_on_load);
572 574
573 ReadGlobalSetting(Settings::values.use_docked_mode); 575 ReadGlobalSetting(Settings::values.use_docked_mode);
574 576
@@ -667,20 +669,16 @@ void Config::ReadDataStorageValues() {
667 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))) 669 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)))
668 .toString() 670 .toString()
669 .toStdString()); 671 .toStdString());
670 FS::SetYuzuPath( 672 FS::SetYuzuPath(FS::YuzuPath::TASDir,
671 FS::YuzuPath::TASFile, 673 qt_config
672 qt_config 674 ->value(QStringLiteral("tas_directory"),
673 ->value(QStringLiteral("tas_path"), 675 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)))
674 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile))) 676 .toString()
675 .toString() 677 .toStdString());
676 .toStdString());
677
678 ReadBasicSetting(Settings::values.pauseTasOnLoad);
679 678
680 ReadBasicSetting(Settings::values.gamecard_inserted); 679 ReadBasicSetting(Settings::values.gamecard_inserted);
681 ReadBasicSetting(Settings::values.gamecard_current_game); 680 ReadBasicSetting(Settings::values.gamecard_current_game);
682 ReadBasicSetting(Settings::values.gamecard_path); 681 ReadBasicSetting(Settings::values.gamecard_path);
683
684 682
685 qt_config->endGroup(); 683 qt_config->endGroup();
686} 684}
@@ -1205,11 +1203,11 @@ void Config::SaveControlValues() {
1205 WriteBasicSetting(Settings::values.emulate_analog_keyboard); 1203 WriteBasicSetting(Settings::values.emulate_analog_keyboard);
1206 WriteBasicSetting(Settings::values.mouse_panning_sensitivity); 1204 WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
1207 1205
1208 WriteSetting(QStringLiteral("enable_tas"), Settings::values.tas_enable, false); 1206 WriteBasicSetting(Settings::values.tas_enable);
1209 WriteSetting(QStringLiteral("loop_tas"), Settings::values.tas_loop, false); 1207 WriteBasicSetting(Settings::values.tas_loop);
1210 WriteSetting(QStringLiteral("swap_tas_controllers"), Settings::values.tas_swap_controllers, 1208 WriteBasicSetting(Settings::values.tas_swap_controllers);
1211 true); 1209 WriteBasicSetting(Settings::values.pause_tas_on_load);
1212 WriteSetting(QStringLiteral("tas_pause_on_load"), Settings::values.pause_tas_on_load, true); 1210
1213 qt_config->endGroup(); 1211 qt_config->endGroup();
1214} 1212}
1215 1213
@@ -1237,10 +1235,9 @@ void Config::SaveDataStorageValues() {
1237 WriteSetting(QStringLiteral("dump_directory"), 1235 WriteSetting(QStringLiteral("dump_directory"),
1238 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)), 1236 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)),
1239 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); 1237 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
1240 WriteSetting(QStringLiteral("tas_path"), 1238 WriteSetting(QStringLiteral("tas_directory"),
1241 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile)), 1239 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)),
1242 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile))); 1240 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
1243 WriteSetting(QStringLiteral("tas_pause_on_load"), Settings::values.pauseTasOnLoad, true);
1244 1241
1245 WriteBasicSetting(Settings::values.gamecard_inserted); 1242 WriteBasicSetting(Settings::values.gamecard_inserted);
1246 WriteBasicSetting(Settings::values.gamecard_current_game); 1243 WriteBasicSetting(Settings::values.gamecard_current_game);
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp
index 013de02db..9cb317822 100644
--- a/src/yuzu/configuration/configure_filesystem.cpp
+++ b/src/yuzu/configuration/configure_filesystem.cpp
@@ -52,7 +52,6 @@ void ConfigureFilesystem::setConfiguration() {
52 52
53 ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted.GetValue()); 53 ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted.GetValue());
54 ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game.GetValue()); 54 ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game.GetValue());
55 ui->tas_pause_on_load->setChecked(Settings::values.pauseTasOnLoad);
56 ui->dump_exefs->setChecked(Settings::values.dump_exefs.GetValue()); 55 ui->dump_exefs->setChecked(Settings::values.dump_exefs.GetValue());
57 ui->dump_nso->setChecked(Settings::values.dump_nso.GetValue()); 56 ui->dump_nso->setChecked(Settings::values.dump_nso.GetValue());
58 57
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index ba3720c03..38c59263c 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -222,23 +222,23 @@ void PlayerControlPreview::UpdateInput() {
222 222
223 if (input_changed) { 223 if (input_changed) {
224 update(); 224 update();
225 ControllerInput input{
226 .axis_values =
227 {std::pair<float, float>{axis_values[Settings::NativeAnalog::LStick].value.x(),
228 axis_values[Settings::NativeAnalog::LStick].value.y()},
229 std::pair<float, float>{axis_values[Settings::NativeAnalog::RStick].value.x(),
230 axis_values[Settings::NativeAnalog::RStick].value.y()}},
231 .button_values = button_values,
232 .changed = true,
233 };
234
235 if (controller_callback.input != nullptr) { 225 if (controller_callback.input != nullptr) {
226 ControllerInput input{
227 .axis_values = {std::pair<float, float>{
228 axis_values[Settings::NativeAnalog::LStick].value.x(),
229 axis_values[Settings::NativeAnalog::LStick].value.y()},
230 std::pair<float, float>{
231 axis_values[Settings::NativeAnalog::RStick].value.x(),
232 axis_values[Settings::NativeAnalog::RStick].value.y()}},
233 .button_values = button_values,
234 .changed = true,
235 };
236 controller_callback.input(std::move(input)); 236 controller_callback.input(std::move(input));
237 } 237 }
238 } 238 }
239 239
240 if (controller_callback.update != nullptr) { 240 if (controller_callback.update != nullptr) {
241 controller_callback.update(std::move(true)); 241 controller_callback.update(true);
242 } 242 }
243 243
244 if (mapping_active) { 244 if (mapping_active) {
diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp
index f2f91d84a..00d6c1ba5 100644
--- a/src/yuzu/configuration/configure_tas.cpp
+++ b/src/yuzu/configuration/configure_tas.cpp
@@ -30,18 +30,18 @@ ConfigureTasDialog::~ConfigureTasDialog() = default;
30void ConfigureTasDialog::LoadConfiguration() { 30void ConfigureTasDialog::LoadConfiguration() {
31 ui->tas_path_edit->setText( 31 ui->tas_path_edit->setText(
32 QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir))); 32 QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir)));
33 ui->tas_enable->setChecked(Settings::values.tas_enable); 33 ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue());
34 ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers); 34 ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers.GetValue());
35 ui->tas_loop_script->setChecked(Settings::values.tas_loop); 35 ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue());
36 ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load); 36 ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue());
37} 37}
38 38
39void ConfigureTasDialog::ApplyConfiguration() { 39void ConfigureTasDialog::ApplyConfiguration() {
40 Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString()); 40 Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString());
41 Settings::values.tas_enable = ui->tas_enable->isChecked(); 41 Settings::values.tas_enable.SetValue(ui->tas_enable->isChecked());
42 Settings::values.tas_swap_controllers = ui->tas_control_swap->isChecked(); 42 Settings::values.tas_swap_controllers.SetValue(ui->tas_control_swap->isChecked());
43 Settings::values.tas_loop = ui->tas_loop_script->isChecked(); 43 Settings::values.tas_loop.SetValue(ui->tas_loop_script->isChecked());
44 Settings::values.pause_tas_on_load = ui->tas_pause_on_load->isChecked(); 44 Settings::values.pause_tas_on_load.SetValue(ui->tas_pause_on_load->isChecked());
45} 45}
46 46
47void ConfigureTasDialog::SetDirectory(DirectoryTarget target, QLineEdit* edit) { 47void ConfigureTasDialog::SetDirectory(DirectoryTarget target, QLineEdit* edit) {