summaryrefslogtreecommitdiff
path: root/src/input_common/tas/tas_input.cpp
diff options
context:
space:
mode:
authorGravatar german772021-06-19 14:38:49 -0500
committerGravatar MonsterDruide12021-09-18 23:22:30 +0200
commitc01a872c8efa90065b6ba1a74079ddf6ec12058f (patch)
treed441117b0d133bff32b39f5060b31db57bc0413f /src/input_common/tas/tas_input.cpp
parentcore: Hacky TAS syncing & load pausing (diff)
downloadyuzu-c01a872c8efa90065b6ba1a74079ddf6ec12058f.tar.gz
yuzu-c01a872c8efa90065b6ba1a74079ddf6ec12058f.tar.xz
yuzu-c01a872c8efa90065b6ba1a74079ddf6ec12058f.zip
config: Move TAS options to it's own menu
Diffstat (limited to 'src/input_common/tas/tas_input.cpp')
-rw-r--r--src/input_common/tas/tas_input.cpp189
1 files changed, 105 insertions, 84 deletions
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp
index 7320a7004..6efa1234a 100644
--- a/src/input_common/tas/tas_input.cpp
+++ b/src/input_common/tas/tas_input.cpp
@@ -67,14 +67,13 @@ void Tas::LoadTasFile(size_t player_index) {
67 if (!commands[player_index].empty()) { 67 if (!commands[player_index].empty()) {
68 commands[player_index].clear(); 68 commands[player_index].clear();
69 } 69 }
70 std::string file = Common::FS::ReadStringFromFile( 70 std::string file =
71 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "script0-" + 71 Common::FS::ReadStringFromFile(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir) +
72 std::to_string(player_index + 1) + ".txt", 72 "script0-" + std::to_string(player_index + 1) + ".txt",
73 Common::FS::FileType::BinaryFile); 73 Common::FS::FileType::BinaryFile);
74 std::stringstream command_line(file); 74 std::stringstream command_line(file);
75 std::string line; 75 std::string line;
76 int frameNo = 0; 76 int frame_no = 0;
77 TASCommand empty = {.buttons = 0, .l_axis = {0.f, 0.f}, .r_axis = {0.f, 0.f}};
78 while (std::getline(command_line, line, '\n')) { 77 while (std::getline(command_line, line, '\n')) {
79 if (line.empty()) { 78 if (line.empty()) {
80 continue; 79 continue;
@@ -94,9 +93,9 @@ void Tas::LoadTasFile(size_t player_index) {
94 continue; 93 continue;
95 } 94 }
96 95
97 while (frameNo < std::stoi(seglist.at(0))) { 96 while (frame_no < std::stoi(seglist.at(0))) {
98 commands[player_index].push_back(empty); 97 commands[player_index].push_back({});
99 frameNo++; 98 frame_no++;
100 } 99 }
101 100
102 TASCommand command = { 101 TASCommand command = {
@@ -105,30 +104,29 @@ void Tas::LoadTasFile(size_t player_index) {
105 .r_axis = ReadCommandAxis(seglist.at(3)), 104 .r_axis = ReadCommandAxis(seglist.at(3)),
106 }; 105 };
107 commands[player_index].push_back(command); 106 commands[player_index].push_back(command);
108 frameNo++; 107 frame_no++;
109 } 108 }
110 LOG_INFO(Input, "TAS file loaded! {} frames", frameNo); 109 LOG_INFO(Input, "TAS file loaded! {} frames", frame_no);
111} 110}
112 111
113void Tas::WriteTasFile() { 112void Tas::WriteTasFile() {
114 LOG_DEBUG(Input, "WriteTasFile()"); 113 LOG_DEBUG(Input, "WriteTasFile()");
115 std::string output_text = ""; 114 std::string output_text;
116 for (int frame = 0; frame < (signed)record_commands.size(); frame++) { 115 for (size_t frame = 0; frame < record_commands.size(); frame++) {
117 if (!output_text.empty()) { 116 if (!output_text.empty()) {
118 output_text += "\n"; 117 output_text += "\n";
119 } 118 }
120 TASCommand line = record_commands.at(frame); 119 const TASCommand& line = record_commands[frame];
121 output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " + 120 output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " +
122 WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis); 121 WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis);
123 } 122 }
124 size_t bytesWritten = Common::FS::WriteStringToFile( 123 const size_t bytes_written = Common::FS::WriteStringToFile(
125 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASFile) + "record.txt", 124 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir) + "record.txt",
126 Common::FS::FileType::TextFile, output_text); 125 Common::FS::FileType::TextFile, output_text);
127 if (bytesWritten == output_text.size()) { 126 if (bytes_written == output_text.size()) {
128 LOG_INFO(Input, "TAS file written to file!"); 127 LOG_INFO(Input, "TAS file written to file!");
129 } 128 } else {
130 else { 129 LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytes_written,
131 LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytesWritten,
132 output_text.size()); 130 output_text.size());
133 } 131 }
134} 132}
@@ -142,30 +140,33 @@ void Tas::RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>&
142 last_input = {buttons, FlipY(axes[0]), FlipY(axes[1])}; 140 last_input = {buttons, FlipY(axes[0]), FlipY(axes[1])};
143} 141}
144 142
145std::tuple<TasState, size_t, size_t> Tas::GetStatus() { 143std::tuple<TasState, size_t, size_t> Tas::GetStatus() const {
146 TasState state; 144 TasState state;
147 if (Settings::values.tas_record) { 145 if (is_recording) {
148 return {TasState::RECORDING, record_commands.size(), record_commands.size()}; 146 return {TasState::Recording, 0, record_commands.size()};
149 } else if (Settings::values.tas_enable) { 147 }
150 state = TasState::RUNNING; 148
149 if (is_running) {
150 state = TasState::Running;
151 } else { 151 } else {
152 state = TasState::STOPPED; 152 state = TasState::Stopped;
153 } 153 }
154 154
155 return {state, current_command, script_length}; 155 return {state, current_command, script_length};
156} 156}
157 157
158static std::string DebugButtons(u32 buttons) { 158static std::string DebugButtons(u32 buttons) {
159 return "{ " + TasInput::Tas::ButtonsToString(buttons) + " }"; 159 return fmt::format("{{ {} }}", TasInput::Tas::ButtonsToString(buttons));
160} 160}
161 161
162static std::string DebugJoystick(float x, float y) { 162static std::string DebugJoystick(float x, float y) {
163 return "[ " + std::to_string(x) + "," + std::to_string(y) + " ]"; 163 return fmt::format("[ {} , {} ]", std::to_string(x), std::to_string(y));
164} 164}
165 165
166static std::string DebugInput(const TasData& data) { 166static std::string DebugInput(const TasData& data) {
167 return "{ " + DebugButtons(data.buttons) + " , " + DebugJoystick(data.axis[0], data.axis[1]) + 167 return fmt::format("{{ {} , {} , {} }}", DebugButtons(data.buttons),
168 " , " + DebugJoystick(data.axis[2], data.axis[3]) + " }"; 168 DebugJoystick(data.axis[0], data.axis[1]),
169 DebugJoystick(data.axis[2], data.axis[3]));
169} 170}
170 171
171static std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) { 172static std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) {
@@ -180,66 +181,54 @@ static std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) {
180} 181}
181 182
182void Tas::UpdateThread() { 183void Tas::UpdateThread() {
183 if (update_thread_running) { 184 if (!update_thread_running) {
184 if (Settings::values.pause_tas_on_load && Settings::values.is_cpu_boosted) { 185 return;
185 for (size_t i = 0; i < PLAYER_NUMBER; i++) { 186 }
186 tas_data[i].buttons = 0;
187 tas_data[i].axis = {};
188 }
189 }
190 187
191 if (Settings::values.tas_record) { 188 if (is_recording) {
192 record_commands.push_back(last_input); 189 record_commands.push_back(last_input);
193 } 190 }
194 if (!Settings::values.tas_record && !record_commands.empty()) { 191 if (!is_recording && !record_commands.empty()) {
195 WriteTasFile(); 192 WriteTasFile();
196 Settings::values.tas_reset = true; 193 needs_reset = true;
197 refresh_tas_fle = true; 194 refresh_tas_fle = true;
198 record_commands.clear(); 195 record_commands.clear();
199 } 196 }
200 if (Settings::values.tas_reset) { 197 if (needs_reset) {
201 current_command = 0; 198 current_command = 0;
202 if (refresh_tas_fle) { 199 if (refresh_tas_fle) {
203 LoadTasFiles();
204 refresh_tas_fle = false;
205 }
206 Settings::values.tas_reset = false;
207 LoadTasFiles(); 200 LoadTasFiles();
208 LOG_DEBUG(Input, "tas_reset done"); 201 refresh_tas_fle = false;
209 } 202 }
210 if (Settings::values.tas_enable) { 203 needs_reset = false;
211 if ((signed)current_command < script_length) { 204 LoadTasFiles();
212 LOG_INFO(Input, "Playing TAS {}/{}", current_command, script_length); 205 LOG_DEBUG(Input, "tas_reset done");
213 size_t frame = current_command++; 206 }
214 for (size_t i = 0; i < PLAYER_NUMBER; i++) { 207 if (is_running) {
215 if (frame < commands[i].size()) { 208 if (current_command < script_length) {
216 TASCommand command = commands[i][frame]; 209 LOG_INFO(Input, "Playing TAS {}/{}", current_command, script_length);
217 tas_data[i].buttons = command.buttons; 210 size_t frame = current_command++;
218 auto [l_axis_x, l_axis_y] = command.l_axis; 211 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
219 tas_data[i].axis[0] = l_axis_x; 212 if (frame < commands[i].size()) {
220 tas_data[i].axis[1] = l_axis_y; 213 TASCommand command = commands[i][frame];
221 auto [r_axis_x, r_axis_y] = command.r_axis; 214 tas_data[i].buttons = command.buttons;
222 tas_data[i].axis[2] = r_axis_x; 215 auto [l_axis_x, l_axis_y] = command.l_axis;
223 tas_data[i].axis[3] = r_axis_y; 216 tas_data[i].axis[0] = l_axis_x;
224 } else { 217 tas_data[i].axis[1] = l_axis_y;
225 tas_data[i].buttons = 0; 218 auto [r_axis_x, r_axis_y] = command.r_axis;
226 tas_data[i].axis = {}; 219 tas_data[i].axis[2] = r_axis_x;
227 } 220 tas_data[i].axis[3] = r_axis_y;
228 } 221 } else {
229 } else { 222 tas_data[i] = {};
230 Settings::values.tas_enable = false;
231 current_command = 0;
232 for (size_t i = 0; i < PLAYER_NUMBER; i++) {
233 tas_data[i].buttons = 0;
234 tas_data[i].axis = {};
235 } 223 }
236 } 224 }
237 } else { 225 } else {
238 for (size_t i = 0; i < PLAYER_NUMBER; i++) { 226 is_running = Settings::values.tas_loop;
239 tas_data[i].buttons = 0; 227 current_command = 0;
240 tas_data[i].axis = {}; 228 tas_data.fill({});
241 }
242 } 229 }
230 } else {
231 tas_data.fill({});
243 } 232 }
244 LOG_DEBUG(Input, "TAS inputs: {}", DebugInputs(tas_data)); 233 LOG_DEBUG(Input, "TAS inputs: {}", DebugInputs(tas_data));
245} 234}
@@ -284,8 +273,9 @@ std::string Tas::WriteCommandAxis(TasAnalog data) const {
284} 273}
285 274
286std::string Tas::WriteCommandButtons(u32 data) const { 275std::string Tas::WriteCommandButtons(u32 data) const {
287 if (data == 0) 276 if (data == 0) {
288 return "NONE"; 277 return "NONE";
278 }
289 279
290 std::string line; 280 std::string line;
291 u32 index = 0; 281 u32 index = 0;
@@ -307,6 +297,37 @@ std::string Tas::WriteCommandButtons(u32 data) const {
307 return line; 297 return line;
308} 298}
309 299
300void Tas::StartStop() {
301 is_running = !is_running;
302}
303
304void Tas::Reset() {
305 needs_reset = true;
306}
307
308void Tas::Record() {
309 is_recording = !is_recording;
310<<<<<<< HEAD
311=======
312 return is_recording;
313}
314
315void Tas::SaveRecording(bool overwrite_file) {
316 if (is_recording) {
317 return;
318 }
319 if (record_commands.empty()) {
320 return;
321 }
322 WriteTasFile("record.txt");
323 if (overwrite_file) {
324 WriteTasFile("script0-1.txt");
325 }
326 needs_reset = true;
327 record_commands.clear();
328>>>>>>> 773d268db (config: disable pause on load)
329}
330
310InputCommon::ButtonMapping Tas::GetButtonMappingForDevice( 331InputCommon::ButtonMapping Tas::GetButtonMappingForDevice(
311 const Common::ParamPackage& params) const { 332 const Common::ParamPackage& params) const {
312 // This list is missing ZL/ZR since those are not considered buttons. 333 // This list is missing ZL/ZR since those are not considered buttons.