summaryrefslogtreecommitdiff
path: root/src/input_common/tas/tas_input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/tas/tas_input.cpp')
-rw-r--r--src/input_common/tas/tas_input.cpp142
1 files changed, 87 insertions, 55 deletions
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp
index 343641945..7320a7004 100644
--- a/src/input_common/tas/tas_input.cpp
+++ b/src/input_common/tas/tas_input.cpp
@@ -19,6 +19,29 @@
19 19
20namespace TasInput { 20namespace TasInput {
21 21
22constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = {
23 std::pair{"KEY_A", TasButton::BUTTON_A},
24 {"KEY_B", TasButton::BUTTON_B},
25 {"KEY_X", TasButton::BUTTON_X},
26 {"KEY_Y", TasButton::BUTTON_Y},
27 {"KEY_LSTICK", TasButton::STICK_L},
28 {"KEY_RSTICK", TasButton::STICK_R},
29 {"KEY_L", TasButton::TRIGGER_L},
30 {"KEY_R", TasButton::TRIGGER_R},
31 {"KEY_PLUS", TasButton::BUTTON_PLUS},
32 {"KEY_MINUS", TasButton::BUTTON_MINUS},
33 {"KEY_DLEFT", TasButton::BUTTON_LEFT},
34 {"KEY_DUP", TasButton::BUTTON_UP},
35 {"KEY_DRIGHT", TasButton::BUTTON_RIGHT},
36 {"KEY_DDOWN", TasButton::BUTTON_DOWN},
37 {"KEY_SL", TasButton::BUTTON_SL},
38 {"KEY_SR", TasButton::BUTTON_SR},
39 {"KEY_CAPTURE", TasButton::BUTTON_CAPTURE},
40 {"KEY_HOME", TasButton::BUTTON_HOME},
41 {"KEY_ZL", TasButton::TRIGGER_ZL},
42 {"KEY_ZR", TasButton::TRIGGER_ZR},
43};
44
22Tas::Tas() { 45Tas::Tas() {
23 LoadTasFiles(); 46 LoadTasFiles();
24} 47}
@@ -31,29 +54,31 @@ void Tas::RefreshTasFile() {
31 refresh_tas_fle = true; 54 refresh_tas_fle = true;
32} 55}
33void Tas::LoadTasFiles() { 56void Tas::LoadTasFiles() {
34 scriptLength = 0; 57 script_length = 0;
35 for (int i = 0; i < PLAYER_NUMBER; i++) { 58 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
36 LoadTasFile(i); 59 LoadTasFile(i);
37 if (newCommands[i].size() > scriptLength) 60 if (commands[i].size() > script_length) {
38 scriptLength = newCommands[i].size(); 61 script_length = commands[i].size();
62 }
39 } 63 }
40} 64}
41void Tas::LoadTasFile(int playerIndex) { 65void Tas::LoadTasFile(size_t player_index) {
42 LOG_DEBUG(Input, "LoadTasFile()"); 66 LOG_DEBUG(Input, "LoadTasFile()");
43 if (!newCommands[playerIndex].empty()) { 67 if (!commands[player_index].empty()) {
44 newCommands[playerIndex].clear(); 68 commands[player_index].clear();
45 } 69 }
46 std::string file = Common::FS::ReadStringFromFile( 70 std::string file = Common::FS::ReadStringFromFile(
47 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "script0-" + 71 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "script0-" +
48 std::to_string(playerIndex + 1) + ".txt", 72 std::to_string(player_index + 1) + ".txt",
49 Common::FS::FileType::BinaryFile); 73 Common::FS::FileType::BinaryFile);
50 std::stringstream command_line(file); 74 std::stringstream command_line(file);
51 std::string line; 75 std::string line;
52 int frameNo = 0; 76 int frameNo = 0;
53 TASCommand empty = {.buttons = 0, .l_axis = {0.f, 0.f}, .r_axis = {0.f, 0.f}}; 77 TASCommand empty = {.buttons = 0, .l_axis = {0.f, 0.f}, .r_axis = {0.f, 0.f}};
54 while (std::getline(command_line, line, '\n')) { 78 while (std::getline(command_line, line, '\n')) {
55 if (line.empty()) 79 if (line.empty()) {
56 continue; 80 continue;
81 }
57 LOG_DEBUG(Input, "Loading line: {}", line); 82 LOG_DEBUG(Input, "Loading line: {}", line);
58 std::smatch m; 83 std::smatch m;
59 84
@@ -65,11 +90,12 @@ void Tas::LoadTasFile(int playerIndex) {
65 seglist.push_back(segment); 90 seglist.push_back(segment);
66 } 91 }
67 92
68 if (seglist.size() < 4) 93 if (seglist.size() < 4) {
69 continue; 94 continue;
95 }
70 96
71 while (frameNo < std::stoi(seglist.at(0))) { 97 while (frameNo < std::stoi(seglist.at(0))) {
72 newCommands[playerIndex].push_back(empty); 98 commands[player_index].push_back(empty);
73 frameNo++; 99 frameNo++;
74 } 100 }
75 101
@@ -78,7 +104,7 @@ void Tas::LoadTasFile(int playerIndex) {
78 .l_axis = ReadCommandAxis(seglist.at(2)), 104 .l_axis = ReadCommandAxis(seglist.at(2)),
79 .r_axis = ReadCommandAxis(seglist.at(3)), 105 .r_axis = ReadCommandAxis(seglist.at(3)),
80 }; 106 };
81 newCommands[playerIndex].push_back(command); 107 commands[player_index].push_back(command);
82 frameNo++; 108 frameNo++;
83 } 109 }
84 LOG_INFO(Input, "TAS file loaded! {} frames", frameNo); 110 LOG_INFO(Input, "TAS file loaded! {} frames", frameNo);
@@ -87,84 +113,89 @@ void Tas::LoadTasFile(int playerIndex) {
87void Tas::WriteTasFile() { 113void Tas::WriteTasFile() {
88 LOG_DEBUG(Input, "WriteTasFile()"); 114 LOG_DEBUG(Input, "WriteTasFile()");
89 std::string output_text = ""; 115 std::string output_text = "";
90 for (int frame = 0; frame < (signed)recordCommands.size(); frame++) { 116 for (int frame = 0; frame < (signed)record_commands.size(); frame++) {
91 if (!output_text.empty()) 117 if (!output_text.empty()) {
92 output_text += "\n"; 118 output_text += "\n";
93 TASCommand line = recordCommands.at(frame); 119 }
120 TASCommand line = record_commands.at(frame);
94 output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " + 121 output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " +
95 WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis); 122 WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis);
96 } 123 }
97 size_t bytesWritten = Common::FS::WriteStringToFile( 124 size_t bytesWritten = Common::FS::WriteStringToFile(
98 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "record.txt", 125 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "record.txt",
99 Common::FS::FileType::TextFile, output_text); 126 Common::FS::FileType::TextFile, output_text);
100 if (bytesWritten == output_text.size()) 127 if (bytesWritten == output_text.size()) {
101 LOG_INFO(Input, "TAS file written to file!"); 128 LOG_INFO(Input, "TAS file written to file!");
102 else 129 }
130 else {
103 LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytesWritten, 131 LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytesWritten,
104 output_text.size()); 132 output_text.size());
133 }
105} 134}
106 135
107void Tas::RecordInput(u32 buttons, std::array<std::pair<float, float>, 2> axes) { 136static std::pair<float, float> FlipY(std::pair<float, float> old) {
108 lastInput = {buttons, flipY(axes[0]), flipY(axes[1])};
109}
110
111std::pair<float, float> Tas::flipY(std::pair<float, float> old) const {
112 auto [x, y] = old; 137 auto [x, y] = old;
113 return {x, -y}; 138 return {x, -y};
114} 139}
115 140
116std::string Tas::GetStatusDescription() { 141void Tas::RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes) {
142 last_input = {buttons, FlipY(axes[0]), FlipY(axes[1])};
143}
144
145std::tuple<TasState, size_t, size_t> Tas::GetStatus() {
146 TasState state;
117 if (Settings::values.tas_record) { 147 if (Settings::values.tas_record) {
118 return "Recording TAS: " + std::to_string(recordCommands.size()); 148 return {TasState::RECORDING, record_commands.size(), record_commands.size()};
119 } 149 } else if (Settings::values.tas_enable) {
120 if (Settings::values.tas_enable) { 150 state = TasState::RUNNING;
121 return "Playing TAS: " + std::to_string(current_command) + "/" + 151 } else {
122 std::to_string(scriptLength); 152 state = TasState::STOPPED;
123 } 153 }
124 return "TAS not running: " + std::to_string(current_command) + "/" + 154
125 std::to_string(scriptLength); 155 return {state, current_command, script_length};
126} 156}
127 157
128std::string debugButtons(u32 buttons) { 158static std::string DebugButtons(u32 buttons) {
129 return "{ " + TasInput::Tas::buttonsToString(buttons) + " }"; 159 return "{ " + TasInput::Tas::ButtonsToString(buttons) + " }";
130} 160}
131 161
132std::string debugJoystick(float x, float y) { 162static std::string DebugJoystick(float x, float y) {
133 return "[ " + std::to_string(x) + "," + std::to_string(y) + " ]"; 163 return "[ " + std::to_string(x) + "," + std::to_string(y) + " ]";
134} 164}
135 165
136std::string debugInput(TasData data) { 166static std::string DebugInput(const TasData& data) {
137 return "{ " + debugButtons(data.buttons) + " , " + debugJoystick(data.axis[0], data.axis[1]) + 167 return "{ " + DebugButtons(data.buttons) + " , " + DebugJoystick(data.axis[0], data.axis[1]) +
138 " , " + debugJoystick(data.axis[2], data.axis[3]) + " }"; 168 " , " + DebugJoystick(data.axis[2], data.axis[3]) + " }";
139} 169}
140 170
141std::string debugInputs(std::array<TasData, PLAYER_NUMBER> arr) { 171static std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) {
142 std::string returns = "[ "; 172 std::string returns = "[ ";
143 for (size_t i = 0; i < arr.size(); i++) { 173 for (size_t i = 0; i < arr.size(); i++) {
144 returns += debugInput(arr[i]); 174 returns += DebugInput(arr[i]);
145 if (i != arr.size() - 1) 175 if (i != arr.size() - 1) {
146 returns += " , "; 176 returns += " , ";
177 }
147 } 178 }
148 return returns + "]"; 179 return returns + "]";
149} 180}
150 181
151void Tas::UpdateThread() { 182void Tas::UpdateThread() {
152 if (update_thread_running) { 183 if (update_thread_running) {
153 if (Settings::values.pauseTasOnLoad && Settings::values.cpuBoosted) { 184 if (Settings::values.pause_tas_on_load && Settings::values.is_cpu_boosted) {
154 for (int i = 0; i < PLAYER_NUMBER; i++) { 185 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
155 tas_data[i].buttons = 0; 186 tas_data[i].buttons = 0;
156 tas_data[i].axis = {}; 187 tas_data[i].axis = {};
157 } 188 }
158 } 189 }
159 190
160 if (Settings::values.tas_record) { 191 if (Settings::values.tas_record) {
161 recordCommands.push_back(lastInput); 192 record_commands.push_back(last_input);
162 } 193 }
163 if (!Settings::values.tas_record && !recordCommands.empty()) { 194 if (!Settings::values.tas_record && !record_commands.empty()) {
164 WriteTasFile(); 195 WriteTasFile();
165 Settings::values.tas_reset = true; 196 Settings::values.tas_reset = true;
166 refresh_tas_fle = true; 197 refresh_tas_fle = true;
167 recordCommands.clear(); 198 record_commands.clear();
168 } 199 }
169 if (Settings::values.tas_reset) { 200 if (Settings::values.tas_reset) {
170 current_command = 0; 201 current_command = 0;
@@ -177,12 +208,12 @@ void Tas::UpdateThread() {
177 LOG_DEBUG(Input, "tas_reset done"); 208 LOG_DEBUG(Input, "tas_reset done");
178 } 209 }
179 if (Settings::values.tas_enable) { 210 if (Settings::values.tas_enable) {
180 if ((signed)current_command < scriptLength) { 211 if ((signed)current_command < script_length) {
181 LOG_INFO(Input, "Playing TAS {}/{}", current_command, scriptLength); 212 LOG_INFO(Input, "Playing TAS {}/{}", current_command, script_length);
182 size_t frame = current_command++; 213 size_t frame = current_command++;
183 for (int i = 0; i < PLAYER_NUMBER; i++) { 214 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
184 if (frame < newCommands[i].size()) { 215 if (frame < commands[i].size()) {
185 TASCommand command = newCommands[i][frame]; 216 TASCommand command = commands[i][frame];
186 tas_data[i].buttons = command.buttons; 217 tas_data[i].buttons = command.buttons;
187 auto [l_axis_x, l_axis_y] = command.l_axis; 218 auto [l_axis_x, l_axis_y] = command.l_axis;
188 tas_data[i].axis[0] = l_axis_x; 219 tas_data[i].axis[0] = l_axis_x;
@@ -198,22 +229,22 @@ void Tas::UpdateThread() {
198 } else { 229 } else {
199 Settings::values.tas_enable = false; 230 Settings::values.tas_enable = false;
200 current_command = 0; 231 current_command = 0;
201 for (int i = 0; i < PLAYER_NUMBER; i++) { 232 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
202 tas_data[i].buttons = 0; 233 tas_data[i].buttons = 0;
203 tas_data[i].axis = {}; 234 tas_data[i].axis = {};
204 } 235 }
205 } 236 }
206 } else { 237 } else {
207 for (int i = 0; i < PLAYER_NUMBER; i++) { 238 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
208 tas_data[i].buttons = 0; 239 tas_data[i].buttons = 0;
209 tas_data[i].axis = {}; 240 tas_data[i].axis = {};
210 } 241 }
211 } 242 }
212 } 243 }
213 LOG_DEBUG(Input, "TAS inputs: {}", debugInputs(tas_data)); 244 LOG_DEBUG(Input, "TAS inputs: {}", DebugInputs(tas_data));
214} 245}
215 246
216TasAnalog Tas::ReadCommandAxis(const std::string line) const { 247TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
217 std::stringstream linestream(line); 248 std::stringstream linestream(line);
218 std::string segment; 249 std::string segment;
219 std::vector<std::string> seglist; 250 std::vector<std::string> seglist;
@@ -228,7 +259,7 @@ TasAnalog Tas::ReadCommandAxis(const std::string line) const {
228 return {x, y}; 259 return {x, y};
229} 260}
230 261
231u32 Tas::ReadCommandButtons(const std::string data) const { 262u32 Tas::ReadCommandButtons(const std::string& data) const {
232 std::stringstream button_text(data); 263 std::stringstream button_text(data);
233 std::string line; 264 std::string line;
234 u32 buttons = 0; 265 u32 buttons = 0;
@@ -262,8 +293,9 @@ std::string Tas::WriteCommandButtons(u32 data) const {
262 if ((data & 1) == 1) { 293 if ((data & 1) == 1) {
263 for (auto [text, tas_button] : text_to_tas_button) { 294 for (auto [text, tas_button] : text_to_tas_button) {
264 if (tas_button == static_cast<TasButton>(1 << index)) { 295 if (tas_button == static_cast<TasButton>(1 << index)) {
265 if (line.size() > 0) 296 if (line.size() > 0) {
266 line += ";"; 297 line += ";";
298 }
267 line += text; 299 line += text;
268 break; 300 break;
269 } 301 }