From 395e9a449d338e56ade9ea88ffeed297a7d86b10 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 17:22:07 -0500 Subject: input_common: Rewrite gc_adapter --- src/input_common/drivers/tas_input.cpp | 320 +++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 src/input_common/drivers/tas_input.cpp (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp new file mode 100644 index 000000000..5e2101b27 --- /dev/null +++ b/src/input_common/drivers/tas_input.cpp @@ -0,0 +1,320 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include + +#include "common/fs/file.h" +#include "common/fs/fs_types.h" +#include "common/fs/path_util.h" +#include "common/logging/log.h" +#include "common/settings.h" +#include "input_common/drivers/tas_input.h" + +namespace InputCommon::TasInput { + +enum TasAxes : u8 { + StickX, + StickY, + SubstickX, + SubstickY, + Undefined, +}; + +// Supported keywords and buttons from a TAS file +constexpr std::array, 20> text_to_tas_button = { + std::pair{"KEY_A", TasButton::BUTTON_A}, + {"KEY_B", TasButton::BUTTON_B}, + {"KEY_X", TasButton::BUTTON_X}, + {"KEY_Y", TasButton::BUTTON_Y}, + {"KEY_LSTICK", TasButton::STICK_L}, + {"KEY_RSTICK", TasButton::STICK_R}, + {"KEY_L", TasButton::TRIGGER_L}, + {"KEY_R", TasButton::TRIGGER_R}, + {"KEY_PLUS", TasButton::BUTTON_PLUS}, + {"KEY_MINUS", TasButton::BUTTON_MINUS}, + {"KEY_DLEFT", TasButton::BUTTON_LEFT}, + {"KEY_DUP", TasButton::BUTTON_UP}, + {"KEY_DRIGHT", TasButton::BUTTON_RIGHT}, + {"KEY_DDOWN", TasButton::BUTTON_DOWN}, + {"KEY_SL", TasButton::BUTTON_SL}, + {"KEY_SR", TasButton::BUTTON_SR}, + {"KEY_CAPTURE", TasButton::BUTTON_CAPTURE}, + {"KEY_HOME", TasButton::BUTTON_HOME}, + {"KEY_ZL", TasButton::TRIGGER_ZL}, + {"KEY_ZR", TasButton::TRIGGER_ZR}, +}; + +Tas::Tas(const std::string input_engine_) : InputCommon::InputEngine(input_engine_) { + for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) { + PadIdentifier identifier{ + .guid = Common::UUID{}, + .port = player_index, + .pad = 0, + }; + PreSetController(identifier); + } + ClearInput(); + if (!Settings::values.tas_enable) { + needs_reset = true; + return; + } + LoadTasFiles(); +} + +Tas::~Tas() { + Stop(); +}; + +void Tas::LoadTasFiles() { + script_length = 0; + for (size_t i = 0; i < commands.size(); i++) { + LoadTasFile(i); + if (commands[i].size() > script_length) { + script_length = commands[i].size(); + } + } +} + +void Tas::LoadTasFile(size_t player_index) { + if (!commands[player_index].empty()) { + commands[player_index].clear(); + } + std::string file = + Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / + fmt::format("script0-{}.txt", player_index + 1), + Common::FS::FileType::BinaryFile); + std::stringstream command_line(file); + std::string line; + int frame_no = 0; + while (std::getline(command_line, line, '\n')) { + if (line.empty()) { + continue; + } + std::smatch m; + + std::stringstream linestream(line); + std::string segment; + std::vector seglist; + + while (std::getline(linestream, segment, ' ')) { + seglist.push_back(segment); + } + + if (seglist.size() < 4) { + continue; + } + + while (frame_no < std::stoi(seglist.at(0))) { + commands[player_index].push_back({}); + frame_no++; + } + + TASCommand command = { + .buttons = ReadCommandButtons(seglist.at(1)), + .l_axis = ReadCommandAxis(seglist.at(2)), + .r_axis = ReadCommandAxis(seglist.at(3)), + }; + commands[player_index].push_back(command); + frame_no++; + } + LOG_INFO(Input, "TAS file loaded! {} frames", frame_no); +} + +void Tas::WriteTasFile(std::u8string file_name) { + std::string output_text; + for (size_t frame = 0; frame < record_commands.size(); frame++) { + const TASCommand& line = record_commands[frame]; + output_text += fmt::format("{} {} {} {} {}\n", frame, WriteCommandButtons(line.buttons), + WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis)); + } + const auto bytes_written = Common::FS::WriteStringToFile( + Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name, + Common::FS::FileType::TextFile, output_text); + if (bytes_written == output_text.size()) { + LOG_INFO(Input, "TAS file written to file!"); + } else { + LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytes_written, + output_text.size()); + } +} + +void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) { + last_input = { + .buttons = buttons, + .l_axis = FlipAxisY(left_axis), + .r_axis = FlipAxisY(right_axis), + }; +} + +TasAnalog Tas::FlipAxisY(TasAnalog old) { + return { + .x = old.x, + .y = -old.y, + }; +} + +std::tuple Tas::GetStatus() const { + TasState state; + if (is_recording) { + return {TasState::Recording, 0, record_commands.size()}; + } + + if (is_running) { + state = TasState::Running; + } else { + state = TasState::Stopped; + } + + return {state, current_command, script_length}; +} + +void Tas::UpdateThread() { + if (!Settings::values.tas_enable) { + if (is_running) { + Stop(); + } + return; + } + + if (is_recording) { + record_commands.push_back(last_input); + } + if (needs_reset) { + current_command = 0; + needs_reset = false; + LoadTasFiles(); + LOG_DEBUG(Input, "tas_reset done"); + } + + if (!is_running) { + ClearInput(); + return; + } + if (current_command < script_length) { + LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length); + size_t frame = current_command++; + for (size_t player_index = 0; player_index < commands.size(); player_index++) { + TASCommand command{}; + if (frame < commands[player_index].size()) { + command = commands[player_index][frame]; + } + + PadIdentifier identifier{ + .guid = Common::UUID{}, + .port = player_index, + .pad = 0, + }; + for (std::size_t i = 0; i < sizeof(command.buttons); ++i) { + const bool button_status = (command.buttons & (1U << i)) != 0; + const int button = static_cast(i); + SetButton(identifier, button, button_status); + } + SetAxis(identifier, TasAxes::StickX, command.l_axis.x); + SetAxis(identifier, TasAxes::StickY, command.l_axis.y); + SetAxis(identifier, TasAxes::SubstickX, command.r_axis.x); + SetAxis(identifier, TasAxes::SubstickY, command.r_axis.y); + } + } else { + is_running = Settings::values.tas_loop.GetValue(); + current_command = 0; + ClearInput(); + } +} + +void Tas::ClearInput() { + ResetButtonState(); + ResetAnalogState(); +} + +TasAnalog Tas::ReadCommandAxis(const std::string& line) const { + std::stringstream linestream(line); + std::string segment; + std::vector seglist; + + while (std::getline(linestream, segment, ';')) { + seglist.push_back(segment); + } + + const float x = std::stof(seglist.at(0)) / 32767.0f; + const float y = std::stof(seglist.at(1)) / 32767.0f; + + return {x, y}; +} + +u32 Tas::ReadCommandButtons(const std::string& data) const { + std::stringstream button_text(data); + std::string line; + u32 buttons = 0; + while (std::getline(button_text, line, ';')) { + for (auto [text, tas_button] : text_to_tas_button) { + if (text == line) { + buttons |= static_cast(tas_button); + break; + } + } + } + return buttons; +} + +std::string Tas::WriteCommandButtons(u32 buttons) const { + std::string returns = ""; + for (auto [text_button, tas_button] : text_to_tas_button) { + if ((buttons & static_cast(tas_button)) != 0) + returns += fmt::format("{};", text_button.substr(4)); + } + return returns.empty() ? "NONE" : returns.substr(2); +} + +std::string Tas::WriteCommandAxis(TasAnalog analog) const { + return fmt::format("{};{}", analog.x * 32767, analog.y * 32767); +} + +void Tas::StartStop() { + if (!Settings::values.tas_enable) { + return; + } + if (is_running) { + Stop(); + } else { + is_running = true; + } +} + +void Tas::Stop() { + is_running = false; +} + +void Tas::Reset() { + if (!Settings::values.tas_enable) { + return; + } + needs_reset = true; +} + +bool Tas::Record() { + if (!Settings::values.tas_enable) { + return true; + } + is_recording = !is_recording; + return is_recording; +} + +void Tas::SaveRecording(bool overwrite_file) { + if (is_recording) { + return; + } + if (record_commands.empty()) { + return; + } + WriteTasFile(u8"record.txt"); + if (overwrite_file) { + WriteTasFile(u8"script0-1.txt"); + } + needs_reset = true; + record_commands.clear(); +} + +} // namespace InputCommon::TasInput -- cgit v1.2.3 From 601ac43495904f3f7666d79a800a8b4eda5a8461 Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 19 Oct 2021 00:12:24 -0500 Subject: core/hid: Only signal when needed --- src/input_common/drivers/tas_input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 5e2101b27..7e7a1d58f 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -127,7 +127,7 @@ void Tas::WriteTasFile(std::u8string file_name) { std::string output_text; for (size_t frame = 0; frame < record_commands.size(); frame++) { const TASCommand& line = record_commands[frame]; - output_text += fmt::format("{} {} {} {} {}\n", frame, WriteCommandButtons(line.buttons), + output_text += fmt::format("{} {} {} {}\n", frame, WriteCommandButtons(line.buttons), WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis)); } const auto bytes_written = Common::FS::WriteStringToFile( -- cgit v1.2.3 From 61d9eb9f690d6afe141f24ba75c99b54e122dfa3 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 20:16:10 -0500 Subject: input_common: Revert deleted TAS functions --- src/input_common/drivers/tas_input.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 7e7a1d58f..d2748b240 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -141,7 +141,7 @@ void Tas::WriteTasFile(std::u8string file_name) { } } -void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) { +void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) { last_input = { .buttons = buttons, .l_axis = FlipAxisY(left_axis), @@ -195,7 +195,7 @@ void Tas::UpdateThread() { } if (current_command < script_length) { LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length); - size_t frame = current_command++; + const size_t frame = current_command++; for (size_t player_index = 0; player_index < commands.size(); player_index++) { TASCommand command{}; if (frame < commands[player_index].size()) { @@ -207,8 +207,8 @@ void Tas::UpdateThread() { .port = player_index, .pad = 0, }; - for (std::size_t i = 0; i < sizeof(command.buttons); ++i) { - const bool button_status = (command.buttons & (1U << i)) != 0; + for (std::size_t i = 0; i < sizeof(command.buttons) * 8; ++i) { + const bool button_status = (command.buttons & (1LLU << i)) != 0; const int button = static_cast(i); SetButton(identifier, button, button_status); } @@ -244,14 +244,14 @@ TasAnalog Tas::ReadCommandAxis(const std::string& line) const { return {x, y}; } -u32 Tas::ReadCommandButtons(const std::string& data) const { +u64 Tas::ReadCommandButtons(const std::string& data) const { std::stringstream button_text(data); std::string line; - u32 buttons = 0; + u64 buttons = 0; while (std::getline(button_text, line, ';')) { for (auto [text, tas_button] : text_to_tas_button) { if (text == line) { - buttons |= static_cast(tas_button); + buttons |= static_cast(tas_button); break; } } @@ -259,13 +259,14 @@ u32 Tas::ReadCommandButtons(const std::string& data) const { return buttons; } -std::string Tas::WriteCommandButtons(u32 buttons) const { +std::string Tas::WriteCommandButtons(u64 buttons) const { std::string returns = ""; for (auto [text_button, tas_button] : text_to_tas_button) { - if ((buttons & static_cast(tas_button)) != 0) - returns += fmt::format("{};", text_button.substr(4)); + if ((buttons & static_cast(tas_button)) != 0) { + returns += fmt::format("{};", text_button); + } } - return returns.empty() ? "NONE" : returns.substr(2); + return returns.empty() ? "NONE" : returns; } std::string Tas::WriteCommandAxis(TasAnalog analog) const { -- cgit v1.2.3 From 157e0b85fdd805e02d234dccf1ce578e3159adee Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 2 Nov 2021 22:50:30 -0600 Subject: core/hid: Prevent Emulated controller from flapping with multiple inputs devices --- src/input_common/drivers/tas_input.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index d2748b240..bb9c236ea 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -71,21 +71,21 @@ Tas::~Tas() { void Tas::LoadTasFiles() { script_length = 0; for (size_t i = 0; i < commands.size(); i++) { - LoadTasFile(i); + LoadTasFile(i, 0); if (commands[i].size() > script_length) { script_length = commands[i].size(); } } } -void Tas::LoadTasFile(size_t player_index) { +void Tas::LoadTasFile(size_t player_index, size_t file_index) { if (!commands[player_index].empty()) { commands[player_index].clear(); } - std::string file = - Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / - fmt::format("script0-{}.txt", player_index + 1), - Common::FS::FileType::BinaryFile); + std::string file = Common::FS::ReadStringFromFile( + Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / + fmt::format("script{}-{}.txt", file_index, player_index + 1), + Common::FS::FileType::BinaryFile); std::stringstream command_line(file); std::string line; int frame_no = 0; @@ -144,15 +144,8 @@ void Tas::WriteTasFile(std::u8string file_name) { void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) { last_input = { .buttons = buttons, - .l_axis = FlipAxisY(left_axis), - .r_axis = FlipAxisY(right_axis), - }; -} - -TasAnalog Tas::FlipAxisY(TasAnalog old) { - return { - .x = old.x, - .y = -old.y, + .l_axis = left_axis, + .r_axis = right_axis, }; } @@ -219,6 +212,7 @@ void Tas::UpdateThread() { } } else { is_running = Settings::values.tas_loop.GetValue(); + LoadTasFiles(); current_command = 0; ClearInput(); } -- cgit v1.2.3 From 42949738f2c01a4125a9a385c9100240181153ec Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 14 Nov 2021 21:56:54 -0600 Subject: kraken: Address comments from review Fix compiler bug --- src/input_common/drivers/tas_input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index bb9c236ea..0e01fb0d9 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -47,7 +47,7 @@ constexpr std::array, 20> text_to_tas_but {"KEY_ZR", TasButton::TRIGGER_ZR}, }; -Tas::Tas(const std::string input_engine_) : InputCommon::InputEngine(input_engine_) { +Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engine_) { for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) { PadIdentifier identifier{ .guid = Common::UUID{}, -- cgit v1.2.3 From 2b92d22bda767c7c723935c357bea474f8e2d2f8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 09:05:23 -0500 Subject: input_engine: std::move engine name where applicable We can allow the name to be moved into, allowing allocations to be avoided. --- src/input_common/drivers/tas_input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 0e01fb0d9..a2bedc951 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -47,7 +47,7 @@ constexpr std::array, 20> text_to_tas_but {"KEY_ZR", TasButton::TRIGGER_ZR}, }; -Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engine_) { +Tas::Tas(std::string input_engine_) : InputEngine(std::move(input_engine_)) { for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) { PadIdentifier identifier{ .guid = Common::UUID{}, -- cgit v1.2.3 From c126b0718ca4ffff463c4462ca38f61019df4acf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 10:41:30 -0500 Subject: tas_input: Make TasAxes enum an enum class Prevents these values from potentially clashing with anything in other headers. --- src/input_common/drivers/tas_input.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 0e01fb0d9..1a38616b4 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -15,7 +15,7 @@ namespace InputCommon::TasInput { -enum TasAxes : u8 { +enum class Tas::TasAxis : u8 { StickX, StickY, SubstickX, @@ -205,10 +205,10 @@ void Tas::UpdateThread() { const int button = static_cast(i); SetButton(identifier, button, button_status); } - SetAxis(identifier, TasAxes::StickX, command.l_axis.x); - SetAxis(identifier, TasAxes::StickY, command.l_axis.y); - SetAxis(identifier, TasAxes::SubstickX, command.r_axis.x); - SetAxis(identifier, TasAxes::SubstickY, command.r_axis.y); + SetTasAxis(identifier, TasAxis::StickX, command.l_axis.x); + SetTasAxis(identifier, TasAxis::StickY, command.l_axis.y); + SetTasAxis(identifier, TasAxis::SubstickX, command.r_axis.x); + SetTasAxis(identifier, TasAxis::SubstickY, command.r_axis.y); } } else { is_running = Settings::values.tas_loop.GetValue(); @@ -267,6 +267,10 @@ std::string Tas::WriteCommandAxis(TasAnalog analog) const { return fmt::format("{};{}", analog.x * 32767, analog.y * 32767); } +void Tas::SetTasAxis(const PadIdentifier& identifier, TasAxis axis, f32 value) { + SetAxis(identifier, static_cast(axis), value); +} + void Tas::StartStop() { if (!Settings::values.tas_enable) { return; -- cgit v1.2.3 From d52ad96ce348656b2ea7de8b8a85badfa86d2860 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 10:49:06 -0500 Subject: tas_input: Amend -Wdocumentation warnings Parameters shouldn't have the colon by their name. --- src/input_common/drivers/tas_input.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 1a38616b4..19d8ccae3 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -238,13 +238,13 @@ TasAnalog Tas::ReadCommandAxis(const std::string& line) const { return {x, y}; } -u64 Tas::ReadCommandButtons(const std::string& data) const { - std::stringstream button_text(data); - std::string line; +u64 Tas::ReadCommandButtons(const std::string& line) const { + std::stringstream button_text(line); + std::string button_line; u64 buttons = 0; - while (std::getline(button_text, line, ';')) { + while (std::getline(button_text, button_line, ';')) { for (auto [text, tas_button] : text_to_tas_button) { - if (text == line) { + if (text == button_line) { buttons |= static_cast(tas_button); break; } -- cgit v1.2.3 From 37a8e2a67eae239b13f10ac56bc42932e9a25b25 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 10:50:22 -0500 Subject: tas_input: Remove unused std::smatch variable This also means we can get rid of the dependency on --- src/input_common/drivers/tas_input.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 19d8ccae3..0a504c484 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include #include "common/fs/file.h" @@ -93,7 +92,6 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) { if (line.empty()) { continue; } - std::smatch m; std::stringstream linestream(line); std::string segment; -- cgit v1.2.3 From 6be730bdcdf875655973b1a39576e6933fd93eab Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 10:54:05 -0500 Subject: tas_input: Use u8string_view instead of u8string Same behavior, but without the potential for extra allocations. --- src/input_common/drivers/tas_input.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 0a504c484..3fdd3649b 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -121,16 +121,17 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) { LOG_INFO(Input, "TAS file loaded! {} frames", frame_no); } -void Tas::WriteTasFile(std::u8string file_name) { +void Tas::WriteTasFile(std::u8string_view file_name) { std::string output_text; for (size_t frame = 0; frame < record_commands.size(); frame++) { const TASCommand& line = record_commands[frame]; output_text += fmt::format("{} {} {} {}\n", frame, WriteCommandButtons(line.buttons), WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis)); } - const auto bytes_written = Common::FS::WriteStringToFile( - Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name, - Common::FS::FileType::TextFile, output_text); + + const auto tas_file_name = Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name; + const auto bytes_written = + Common::FS::WriteStringToFile(tas_file_name, Common::FS::FileType::TextFile, output_text); if (bytes_written == output_text.size()) { LOG_INFO(Input, "TAS file written to file!"); } else { @@ -252,7 +253,7 @@ u64 Tas::ReadCommandButtons(const std::string& line) const { } std::string Tas::WriteCommandButtons(u64 buttons) const { - std::string returns = ""; + std::string returns; for (auto [text_button, tas_button] : text_to_tas_button) { if ((buttons & static_cast(tas_button)) != 0) { returns += fmt::format("{};", text_button); -- cgit v1.2.3 From a515ede2af822a337b95ed0b3987a197664d5180 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 10:57:51 -0500 Subject: tas_input: Use istringstream over stringstream This is only using the input facilities, so we don't need to use the fully-fleged stringstream. --- src/input_common/drivers/tas_input.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 3fdd3649b..a7d3d0b47 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -85,7 +85,7 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) { Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / fmt::format("script{}-{}.txt", file_index, player_index + 1), Common::FS::FileType::BinaryFile); - std::stringstream command_line(file); + std::istringstream command_line(file); std::string line; int frame_no = 0; while (std::getline(command_line, line, '\n')) { @@ -93,7 +93,7 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) { continue; } - std::stringstream linestream(line); + std::istringstream linestream(line); std::string segment; std::vector seglist; -- cgit v1.2.3 From 26ef76213c81b6c2dc8eeeae11e9586f22a76011 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 11:07:26 -0500 Subject: tas_input: std::move strings into vector While we're in the same area, we can also avoid performing std::stoi in a loop when it only needs to be performed once. --- src/input_common/drivers/tas_input.cpp | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index a7d3d0b47..d14a43b9e 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -93,27 +93,29 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) { continue; } - std::istringstream linestream(line); - std::string segment; - std::vector seglist; - - while (std::getline(linestream, segment, ' ')) { - seglist.push_back(segment); + std::vector seg_list; + { + std::istringstream line_stream(line); + std::string segment; + while (std::getline(line_stream, segment, ' ')) { + seg_list.push_back(std::move(segment)); + } } - if (seglist.size() < 4) { + if (seg_list.size() < 4) { continue; } - while (frame_no < std::stoi(seglist.at(0))) { - commands[player_index].push_back({}); + const auto num_frames = std::stoi(seg_list[0]); + while (frame_no < num_frames) { + commands[player_index].emplace_back(); frame_no++; } TASCommand command = { - .buttons = ReadCommandButtons(seglist.at(1)), - .l_axis = ReadCommandAxis(seglist.at(2)), - .r_axis = ReadCommandAxis(seglist.at(3)), + .buttons = ReadCommandButtons(seg_list[1]), + .l_axis = ReadCommandAxis(seg_list[2]), + .r_axis = ReadCommandAxis(seg_list[3]), }; commands[player_index].push_back(command); frame_no++; @@ -223,22 +225,23 @@ void Tas::ClearInput() { } TasAnalog Tas::ReadCommandAxis(const std::string& line) const { - std::stringstream linestream(line); - std::string segment; - std::vector seglist; - - while (std::getline(linestream, segment, ';')) { - seglist.push_back(segment); + std::vector seg_list; + { + std::istringstream line_stream(line); + std::string segment; + while (std::getline(line_stream, segment, ';')) { + seg_list.push_back(std::move(segment)); + } } - const float x = std::stof(seglist.at(0)) / 32767.0f; - const float y = std::stof(seglist.at(1)) / 32767.0f; + const float x = std::stof(seg_list.at(0)) / 32767.0f; + const float y = std::stof(seg_list.at(1)) / 32767.0f; return {x, y}; } u64 Tas::ReadCommandButtons(const std::string& line) const { - std::stringstream button_text(line); + std::istringstream button_text(line); std::string button_line; u64 buttons = 0; while (std::getline(button_text, button_line, ';')) { -- cgit v1.2.3 From ddda6ae776e0fab22a3cf70a9f4f5a87df86fda8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 11:19:24 -0500 Subject: tas_input: Execute clear() even if empty clear() when empty is simply a no-op, so we can get rid of the check here and let the stdlib do it for us. --- src/input_common/drivers/tas_input.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index d14a43b9e..bd4e411c9 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -78,9 +78,8 @@ void Tas::LoadTasFiles() { } void Tas::LoadTasFile(size_t player_index, size_t file_index) { - if (!commands[player_index].empty()) { - commands[player_index].clear(); - } + commands[player_index].clear(); + std::string file = Common::FS::ReadStringFromFile( Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / fmt::format("script{}-{}.txt", file_index, player_index + 1), -- cgit v1.2.3 From 734fb180bb42d361f05d1fab02323de5095e2d8d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 11:20:23 -0500 Subject: tas_input: Remove unnecessary semicolon Resolves a -Wextra-semi warning --- src/input_common/drivers/tas_input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index bd4e411c9..1617ba1d4 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -65,7 +65,7 @@ Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engi Tas::~Tas() { Stop(); -}; +} void Tas::LoadTasFiles() { script_length = 0; -- cgit v1.2.3 From 54ca48e8b772453814d2e4d49a4ba29a1b46b32d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 11:36:48 -0500 Subject: tas_input: Avoid minor copies in Read/WriteCommandButtons() We don't need to copy the whole pair --- src/input_common/drivers/tas_input.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/input_common/drivers/tas_input.cpp') diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 1617ba1d4..2094c1feb 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -244,7 +244,7 @@ u64 Tas::ReadCommandButtons(const std::string& line) const { std::string button_line; u64 buttons = 0; while (std::getline(button_text, button_line, ';')) { - for (auto [text, tas_button] : text_to_tas_button) { + for (const auto& [text, tas_button] : text_to_tas_button) { if (text == button_line) { buttons |= static_cast(tas_button); break; @@ -256,7 +256,7 @@ u64 Tas::ReadCommandButtons(const std::string& line) const { std::string Tas::WriteCommandButtons(u64 buttons) const { std::string returns; - for (auto [text_button, tas_button] : text_to_tas_button) { + for (const auto& [text_button, tas_button] : text_to_tas_button) { if ((buttons & static_cast(tas_button)) != 0) { returns += fmt::format("{};", text_button); } -- cgit v1.2.3