diff options
Diffstat (limited to 'src/input_common/tas')
-rw-r--r-- | src/input_common/tas/tas_input.cpp | 3 | ||||
-rw-r--r-- | src/input_common/tas/tas_input.h | 108 | ||||
-rw-r--r-- | src/input_common/tas/tas_poller.h | 4 |
3 files changed, 112 insertions, 3 deletions
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp index aceb13adc..877d35088 100644 --- a/src/input_common/tas/tas_input.cpp +++ b/src/input_common/tas/tas_input.cpp @@ -14,6 +14,7 @@ namespace TasInput { +// Supported keywords and buttons from a TAS file constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = { std::pair{"KEY_A", TasButton::BUTTON_A}, {"KEY_B", TasButton::BUTTON_B}, @@ -214,7 +215,7 @@ void Tas::UpdateThread() { } } } else { - is_running = Settings::values.tas_loop; + is_running = Settings::values.tas_loop.GetValue(); current_command = 0; tas_data.fill({}); if (!is_running) { diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h index e1f351251..52d000db4 100644 --- a/src/input_common/tas/tas_input.h +++ b/src/input_common/tas/tas_input.h @@ -11,6 +11,38 @@ #include "core/frontend/input.h" #include "input_common/main.h" +/* +To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below +Emulation -> Configure TAS. The file itself has normal text format and has to be called +script0-1.txt for controller 1, script0-2.txt for controller 2 and so forth (with max. 8 players). + +A script file has the same format as TAS-nx uses, so final files will look like this: + +1 KEY_B 0;0 0;0 +6 KEY_ZL 0;0 0;0 +41 KEY_ZL;KEY_Y 0;0 0;0 +43 KEY_X;KEY_A 32767;0 0;0 +44 KEY_A 32767;0 0;0 +45 KEY_A 32767;0 0;0 +46 KEY_A 32767;0 0;0 +47 KEY_A 32767;0 0;0 + +After placing the file at the correct location, it can be read into Yuzu with the (default) hotkey +CTRL+F6 (refresh). In the bottom left corner, it will display the amount of frames the script file +has. Playback can be started or stopped using CTRL+F5. + +However, for playback to actually work, the correct input device has to be selected: In the Controls +menu, select TAS from the device list for the controller that the script should be played on. + +Recording a new script file is really simple: Just make sure that the proper device (not TAS) is +connected on P1, and press CTRL+F7 to start recording. When done, just press the same keystroke +again (CTRL+F7). The new script will be saved at the location previously selected, as the filename +record.txt. + +For debugging purposes, the common controller debugger can be used (View -> Debugging -> Controller +P1). +*/ + namespace TasInput { constexpr size_t PLAYER_NUMBER = 8; @@ -64,12 +96,26 @@ public: Tas(); ~Tas(); + // Changes the input status that will be stored in each frame void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes); + + // Main loop that records or executes input void UpdateThread(); + // Sets the flag to start or stop the TAS command excecution and swaps controllers profiles void StartStop(); + + // Sets the flag to reload the file and start from the begining in the next update void Reset(); + + /** + * Sets the flag to enable or disable recording of inputs + * @return Returns true if the current recording status is enabled + */ bool Record(); + + // Saves contents of record_commands on a file if overwrite is enabled player 1 will be + // overwritten with the recorded commands void SaveRecording(bool overwrite_file); /** @@ -80,7 +126,11 @@ public: * Total length of script file currently loaded or amount of frames (so far) for Recording */ std::tuple<TasState, size_t, size_t> GetStatus() const; + + // Retuns an array of the default button mappings InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const; + + // Retuns an array of the default analog mappings InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const; [[nodiscard]] const TasData& GetTasState(std::size_t pad) const; @@ -90,23 +140,81 @@ private: TasAnalog l_axis{}; TasAnalog r_axis{}; }; + + // Loads TAS files from all players void LoadTasFiles(); + + // Loads TAS file from the specified player void LoadTasFile(size_t player_index); + + // Writes a TAS file from the recorded commands void WriteTasFile(std::u8string file_name); + + /** + * Parses a string containing the axis values with the following format "x;y" + * X and Y have a range from -32767 to 32767 + * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0 + */ TasAnalog ReadCommandAxis(const std::string& line) const; + + /** + * Parses a string containing the button values with the following format "a;b;c;d..." + * Each button is represented by it's text format specified in text_to_tas_button array + * @return Returns a u32 with each bit representing the status of a button + */ u32 ReadCommandButtons(const std::string& line) const; + + /** + * Converts an u32 containing the button status into the text equivalent + * @return Returns a string with the name of the buttons to be written to the file + */ std::string WriteCommandButtons(u32 data) const; + + /** + * Converts an TAS analog object containing the axis status into the text equivalent + * @return Returns a string with the value of the axis to be written to the file + */ std::string WriteCommandAxis(TasAnalog data) const; + // Inverts the Y axis polarity std::pair<float, float> FlipAxisY(std::pair<float, float> old); + /** + * Converts an u32 containing the button status into the text equivalent + * @return Returns a string with the name of the buttons to be printed on console + */ std::string DebugButtons(u32 buttons) const; + + /** + * Converts an TAS analog object containing the axis status into the text equivalent + * @return Returns a string with the value of the axis to be printed on console + */ std::string DebugJoystick(float x, float y) const; + + /** + * Converts the given TAS status into the text equivalent + * @return Returns a string with the value of the TAS status to be printed on console + */ std::string DebugInput(const TasData& data) const; + + /** + * Converts the given TAS status of multiple players into the text equivalent + * @return Returns a string with the value of the status of all TAS players to be printed on + * console + */ std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const; + + /** + * Converts an u32 containing the button status into the text equivalent + * @return Returns a string with the name of the buttons + */ std::string ButtonsToString(u32 button) const; + // Stores current controller configuration and sets a TAS controller for every active controller + // to the current config void SwapToTasController(); + + // Sets the stored controller configuration to the current config void SwapToStoredController(); size_t script_length{0}; diff --git a/src/input_common/tas/tas_poller.h b/src/input_common/tas/tas_poller.h index 1bc0d173b..09e426cef 100644 --- a/src/input_common/tas/tas_poller.h +++ b/src/input_common/tas/tas_poller.h @@ -11,7 +11,7 @@ namespace InputCommon { /** - * A button device factory representing a mouse. It receives mouse events and forward them + * A button device factory representing a tas bot. It receives tas events and forward them * to all button devices it created. */ class TasButtonFactory final : public Input::Factory<Input::ButtonDevice> { @@ -29,7 +29,7 @@ private: std::shared_ptr<TasInput::Tas> tas_input; }; -/// An analog device factory that creates analog devices from mouse +/// An analog device factory that creates analog devices from tas class TasAnalogFactory final : public Input::Factory<Input::AnalogDevice> { public: explicit TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_); |