summaryrefslogtreecommitdiff
path: root/src/input_common/drivers/tas_input.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/drivers/tas_input.h')
-rw-r--r--src/input_common/drivers/tas_input.h200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
new file mode 100644
index 000000000..9fadc118b
--- /dev/null
+++ b/src/input_common/drivers/tas_input.h
@@ -0,0 +1,200 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/common_types.h"
10#include "common/settings_input.h"
11#include "input_common/input_engine.h"
12#include "input_common/main.h"
13
14/*
15To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
16Tools -> Configure TAS. The file itself has normal text format and has to be called script0-1.txt
17for 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
46namespace InputCommon::TasInput {
47
48constexpr size_t PLAYER_NUMBER = 10;
49
50enum class TasButton : u32 {
51 BUTTON_A = 1U << 0,
52 BUTTON_B = 1U << 1,
53 BUTTON_X = 1U << 2,
54 BUTTON_Y = 1U << 3,
55 STICK_L = 1U << 4,
56 STICK_R = 1U << 5,
57 TRIGGER_L = 1U << 6,
58 TRIGGER_R = 1U << 7,
59 TRIGGER_ZL = 1U << 8,
60 TRIGGER_ZR = 1U << 9,
61 BUTTON_PLUS = 1U << 10,
62 BUTTON_MINUS = 1U << 11,
63 BUTTON_LEFT = 1U << 12,
64 BUTTON_UP = 1U << 13,
65 BUTTON_RIGHT = 1U << 14,
66 BUTTON_DOWN = 1U << 15,
67 BUTTON_SL = 1U << 16,
68 BUTTON_SR = 1U << 17,
69 BUTTON_HOME = 1U << 18,
70 BUTTON_CAPTURE = 1U << 19,
71};
72
73struct TasAnalog {
74 float x{};
75 float y{};
76};
77
78enum class TasState {
79 Running,
80 Recording,
81 Stopped,
82};
83
84class Tas final : public InputCommon::InputEngine {
85public:
86 explicit Tas(const std::string input_engine_);
87 ~Tas();
88
89 /**
90 * Changes the input status that will be stored in each frame
91 * @param buttons: bitfield with the status of the buttons
92 * @param left_axis: value of the left axis
93 * @param right_axis: value of the right axis
94 */
95 void RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis);
96
97 // Main loop that records or executes input
98 void UpdateThread();
99
100 // Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
101 void StartStop();
102
103 // Stop the TAS and reverts any controller profile
104 void Stop();
105
106 // Sets the flag to reload the file and start from the begining in the next update
107 void Reset();
108
109 /**
110 * Sets the flag to enable or disable recording of inputs
111 * @return Returns true if the current recording status is enabled
112 */
113 bool Record();
114
115 /**
116 * Saves contents of record_commands on a file
117 * @param overwrite_file: Indicates if player 1 should be overwritten
118 */
119 void SaveRecording(bool overwrite_file);
120
121 /**
122 * Returns the current status values of TAS playback/recording
123 * @return Tuple of
124 * TasState indicating the current state out of Running ;
125 * Current playback progress ;
126 * Total length of script file currently loaded or being recorded
127 */
128 std::tuple<TasState, size_t, size_t> GetStatus() const;
129
130private:
131 struct TASCommand {
132 u32 buttons{};
133 TasAnalog l_axis{};
134 TasAnalog r_axis{};
135 };
136
137 /// Loads TAS files from all players
138 void LoadTasFiles();
139
140 /** Loads TAS file from the specified player
141 * @param player_index: player number where data is going to be stored
142 */
143 void LoadTasFile(size_t player_index);
144
145 /** Writes a TAS file from the recorded commands
146 * @param file_name: name of the file to be written
147 */
148 void WriteTasFile(std::u8string file_name);
149
150 /** Inverts the Y axis polarity
151 * @param old: value of the axis
152 * @return new value of the axis
153 */
154 TasAnalog FlipAxisY(TasAnalog old);
155
156 /**
157 * Parses a string containing the axis values. X and Y have a range from -32767 to 32767
158 * @param line: string containing axis values with the following format "x;y"
159 * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
160 */
161 TasAnalog ReadCommandAxis(const std::string& line) const;
162
163 /**
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
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
168 */
169 u32 ReadCommandButtons(const std::string& line) const;
170
171 /**
172 * Reset state of all players
173 */
174 void ClearInput();
175
176 /**
177 * Converts an u32 containing the button status into the text equivalent
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
180 */
181 std::string WriteCommandButtons(u32 buttons) const;
182
183 /**
184 * Converts an TAS analog object containing the axis status into the text equivalent
185 * @param data: value of the axis
186 * @return A string with the value of the axis to be written to the file
187 */
188 std::string WriteCommandAxis(TasAnalog data) const;
189
190 size_t script_length{0};
191 bool is_old_input_saved{false};
192 bool is_recording{false};
193 bool is_running{false};
194 bool needs_reset{false};
195 std::array<std::vector<TASCommand>, PLAYER_NUMBER> commands{};
196 std::vector<TASCommand> record_commands{};
197 size_t current_command{0};
198 TASCommand last_input{}; // only used for recording
199};
200} // namespace InputCommon::TasInput