summaryrefslogtreecommitdiff
path: root/src/input_common/tas/tas_input.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/tas/tas_input.h')
-rw-r--r--src/input_common/tas/tas_input.h163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h
new file mode 100644
index 000000000..0a152a04f
--- /dev/null
+++ b/src/input_common/tas/tas_input.h
@@ -0,0 +1,163 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <mutex>
9#include <thread>
10
11#include "common/common_types.h"
12#include "core/frontend/input.h"
13#include "input_common/main.h"
14
15#define PLAYER_NUMBER 8
16
17namespace TasInput {
18
19using TasAnalog = std::tuple<float, float>;
20
21enum class TasButton : u32 {
22 BUTTON_A = 0x000001,
23 BUTTON_B = 0x000002,
24 BUTTON_X = 0x000004,
25 BUTTON_Y = 0x000008,
26 STICK_L = 0x000010,
27 STICK_R = 0x000020,
28 TRIGGER_L = 0x000040,
29 TRIGGER_R = 0x000080,
30 TRIGGER_ZL = 0x000100,
31 TRIGGER_ZR = 0x000200,
32 BUTTON_PLUS = 0x000400,
33 BUTTON_MINUS = 0x000800,
34 BUTTON_LEFT = 0x001000,
35 BUTTON_UP = 0x002000,
36 BUTTON_RIGHT = 0x004000,
37 BUTTON_DOWN = 0x008000,
38 BUTTON_SL = 0x010000,
39 BUTTON_SR = 0x020000,
40 BUTTON_HOME = 0x040000,
41 BUTTON_CAPTURE = 0x080000,
42};
43
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 {
68 StickX,
69 StickY,
70 SubstickX,
71 SubstickY,
72 Undefined,
73};
74
75struct TasData {
76 u32 buttons{};
77 std::array<float, 4> axis{};
78};
79
80class Tas {
81public:
82 Tas();
83 ~Tas();
84
85 static std::string buttonsToString(u32 button) {
86 std::string returns;
87 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_A)) != 0)
88 returns += ", A";
89 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_B)) != 0)
90 returns += ", B";
91 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_X)) != 0)
92 returns += ", X";
93 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_Y)) != 0)
94 returns += ", Y";
95 if ((button & static_cast<u32>(TasInput::TasButton::STICK_L)) != 0)
96 returns += ", STICK_L";
97 if ((button & static_cast<u32>(TasInput::TasButton::STICK_R)) != 0)
98 returns += ", STICK_R";
99 if ((button & static_cast<u32>(TasInput::TasButton::TRIGGER_L)) != 0)
100 returns += ", TRIGGER_L";
101 if ((button & static_cast<u32>(TasInput::TasButton::TRIGGER_R)) != 0)
102 returns += ", TRIGGER_R";
103 if ((button & static_cast<u32>(TasInput::TasButton::TRIGGER_ZL)) != 0)
104 returns += ", TRIGGER_ZL";
105 if ((button & static_cast<u32>(TasInput::TasButton::TRIGGER_ZR)) != 0)
106 returns += ", TRIGGER_ZR";
107 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_PLUS)) != 0)
108 returns += ", PLUS";
109 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_MINUS)) != 0)
110 returns += ", MINUS";
111 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_LEFT)) != 0)
112 returns += ", LEFT";
113 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_UP)) != 0)
114 returns += ", UP";
115 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_RIGHT)) != 0)
116 returns += ", RIGHT";
117 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_DOWN)) != 0)
118 returns += ", DOWN";
119 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_SL)) != 0)
120 returns += ", SL";
121 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_SR)) != 0)
122 returns += ", SR";
123 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_HOME)) != 0)
124 returns += ", HOME";
125 if ((button & static_cast<u32>(TasInput::TasButton::BUTTON_CAPTURE)) != 0)
126 returns += ", CAPTURE";
127 return returns.length() != 0 ? returns.substr(2) : "";
128 }
129
130 void RefreshTasFile();
131 void LoadTasFiles();
132 void RecordInput(u32 buttons, std::array<std::pair<float, float>, 2> axes);
133 void UpdateThread();
134 std::string GetStatusDescription();
135
136 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
137 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
138 [[nodiscard]] const TasData& GetTasState(std::size_t pad) const;
139
140private:
141 struct TASCommand {
142 u32 buttons{};
143 TasAnalog l_axis{};
144 TasAnalog r_axis{};
145 };
146 void LoadTasFile(int playerIndex);
147 void WriteTasFile();
148 TasAnalog ReadCommandAxis(const std::string line) const;
149 u32 ReadCommandButtons(const std::string line) const;
150 std::string WriteCommandButtons(u32 data) const;
151 std::string WriteCommandAxis(TasAnalog data) const;
152 std::pair<float, float> flipY(std::pair<float, float> old) const;
153
154 size_t scriptLength{0};
155 std::array<TasData, PLAYER_NUMBER> tas_data;
156 bool update_thread_running{true};
157 bool refresh_tas_fle{false};
158 std::array<std::vector<TASCommand>, PLAYER_NUMBER> newCommands{};
159 std::vector<TASCommand> recordCommands{};
160 std::size_t current_command{0};
161 TASCommand lastInput{}; // only used for recording
162};
163} // namespace TasInput