summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/tas/tas_input.cpp142
-rw-r--r--src/input_common/tas/tas_input.h58
2 files changed, 107 insertions, 93 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 }
diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h
index 0a152a04f..8ee70bcaf 100644
--- a/src/input_common/tas/tas_input.h
+++ b/src/input_common/tas/tas_input.h
@@ -12,11 +12,17 @@
12#include "core/frontend/input.h" 12#include "core/frontend/input.h"
13#include "input_common/main.h" 13#include "input_common/main.h"
14 14
15#define PLAYER_NUMBER 8
16
17namespace TasInput { 15namespace TasInput {
18 16
19using TasAnalog = std::tuple<float, float>; 17constexpr int PLAYER_NUMBER = 8;
18
19using TasAnalog = std::pair<float, float>;
20
21enum class TasState {
22 RUNNING,
23 RECORDING,
24 STOPPED,
25};
20 26
21enum class TasButton : u32 { 27enum class TasButton : u32 {
22 BUTTON_A = 0x000001, 28 BUTTON_A = 0x000001,
@@ -41,29 +47,6 @@ enum class TasButton : u32 {
41 BUTTON_CAPTURE = 0x080000, 47 BUTTON_CAPTURE = 0x080000,
42}; 48};
43 49
44static const std::array<std::pair<std::string, TasButton>, 20> text_to_tas_button = {
45 std::pair{"KEY_A", TasButton::BUTTON_A},
46 {"KEY_B", TasButton::BUTTON_B},
47 {"KEY_X", TasButton::BUTTON_X},
48 {"KEY_Y", TasButton::BUTTON_Y},
49 {"KEY_LSTICK", TasButton::STICK_L},
50 {"KEY_RSTICK", TasButton::STICK_R},
51 {"KEY_L", TasButton::TRIGGER_L},
52 {"KEY_R", TasButton::TRIGGER_R},
53 {"KEY_PLUS", TasButton::BUTTON_PLUS},
54 {"KEY_MINUS", TasButton::BUTTON_MINUS},
55 {"KEY_DLEFT", TasButton::BUTTON_LEFT},
56 {"KEY_DUP", TasButton::BUTTON_UP},
57 {"KEY_DRIGHT", TasButton::BUTTON_RIGHT},
58 {"KEY_DDOWN", TasButton::BUTTON_DOWN},
59 {"KEY_SL", TasButton::BUTTON_SL},
60 {"KEY_SR", TasButton::BUTTON_SR},
61 {"KEY_CAPTURE", TasButton::BUTTON_CAPTURE},
62 {"KEY_HOME", TasButton::BUTTON_HOME},
63 {"KEY_ZL", TasButton::TRIGGER_ZL},
64 {"KEY_ZR", TasButton::TRIGGER_ZR},
65};
66
67enum class TasAxes : u8 { 50enum class TasAxes : u8 {
68 StickX, 51 StickX,
69 StickY, 52 StickY,
@@ -82,7 +65,7 @@ public:
82 Tas(); 65 Tas();
83 ~Tas(); 66 ~Tas();
84 67
85 static std::string buttonsToString(u32 button) { 68 static std::string ButtonsToString(u32 button) {
86 std::string returns; 69 std::string returns;
87 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_A)) != 0) 70 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_A)) != 0)
88 returns += ", A"; 71 returns += ", A";
@@ -124,14 +107,14 @@ public:
124 returns += ", HOME"; 107 returns += ", HOME";
125 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_CAPTURE)) != 0) 108 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_CAPTURE)) != 0)
126 returns += ", CAPTURE"; 109 returns += ", CAPTURE";
127 return returns.length() != 0 ? returns.substr(2) : ""; 110 return returns.empty() ? "" : returns.substr(2);
128 } 111 }
129 112
130 void RefreshTasFile(); 113 void RefreshTasFile();
131 void LoadTasFiles(); 114 void LoadTasFiles();
132 void RecordInput(u32 buttons, std::array<std::pair<float, float>, 2> axes); 115 void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes);
133 void UpdateThread(); 116 void UpdateThread();
134 std::string GetStatusDescription(); 117 std::tuple<TasState, size_t, size_t> GetStatus();
135 118
136 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const; 119 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
137 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const; 120 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
@@ -143,21 +126,20 @@ private:
143 TasAnalog l_axis{}; 126 TasAnalog l_axis{};
144 TasAnalog r_axis{}; 127 TasAnalog r_axis{};
145 }; 128 };
146 void LoadTasFile(int playerIndex); 129 void LoadTasFile(size_t player_index);
147 void WriteTasFile(); 130 void WriteTasFile();
148 TasAnalog ReadCommandAxis(const std::string line) const; 131 TasAnalog ReadCommandAxis(const std::string& line) const;
149 u32 ReadCommandButtons(const std::string line) const; 132 u32 ReadCommandButtons(const std::string& line) const;
150 std::string WriteCommandButtons(u32 data) const; 133 std::string WriteCommandButtons(u32 data) const;
151 std::string WriteCommandAxis(TasAnalog data) const; 134 std::string WriteCommandAxis(TasAnalog data) const;
152 std::pair<float, float> flipY(std::pair<float, float> old) const;
153 135
154 size_t scriptLength{0}; 136 size_t script_length{0};
155 std::array<TasData, PLAYER_NUMBER> tas_data; 137 std::array<TasData, PLAYER_NUMBER> tas_data;
156 bool update_thread_running{true}; 138 bool update_thread_running{true};
157 bool refresh_tas_fle{false}; 139 bool refresh_tas_fle{false};
158 std::array<std::vector<TASCommand>, PLAYER_NUMBER> newCommands{}; 140 std::array<std::vector<TASCommand>, PLAYER_NUMBER> commands{};
159 std::vector<TASCommand> recordCommands{}; 141 std::vector<TASCommand> record_commands{};
160 std::size_t current_command{0}; 142 std::size_t current_command{0};
161 TASCommand lastInput{}; // only used for recording 143 TASCommand last_input{}; // only used for recording
162}; 144};
163} // namespace TasInput 145} // namespace TasInput