diff options
Diffstat (limited to 'src/input_common/tas/tas_input.cpp')
| -rw-r--r-- | src/input_common/tas/tas_input.cpp | 189 |
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 | ||
| 113 | void Tas::WriteTasFile() { | 112 | void 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 | ||
| 145 | std::tuple<TasState, size_t, size_t> Tas::GetStatus() { | 143 | std::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 | ||
| 158 | static std::string DebugButtons(u32 buttons) { | 158 | static std::string DebugButtons(u32 buttons) { |
| 159 | return "{ " + TasInput::Tas::ButtonsToString(buttons) + " }"; | 159 | return fmt::format("{{ {} }}", TasInput::Tas::ButtonsToString(buttons)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | static std::string DebugJoystick(float x, float y) { | 162 | static 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 | ||
| 166 | static std::string DebugInput(const TasData& data) { | 166 | static 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 | ||
| 171 | static std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) { | 172 | static 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 | ||
| 182 | void Tas::UpdateThread() { | 183 | void 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 | ||
| 286 | std::string Tas::WriteCommandButtons(u32 data) const { | 275 | std::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 | ||
| 300 | void Tas::StartStop() { | ||
| 301 | is_running = !is_running; | ||
| 302 | } | ||
| 303 | |||
| 304 | void Tas::Reset() { | ||
| 305 | needs_reset = true; | ||
| 306 | } | ||
| 307 | |||
| 308 | void Tas::Record() { | ||
| 309 | is_recording = !is_recording; | ||
| 310 | <<<<<<< HEAD | ||
| 311 | ======= | ||
| 312 | return is_recording; | ||
| 313 | } | ||
| 314 | |||
| 315 | void 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 | |||
| 310 | InputCommon::ButtonMapping Tas::GetButtonMappingForDevice( | 331 | InputCommon::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. |