| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- // Copyright 2020 yuzu Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #pragma once
- #include <array>
- #include "common/common_types.h"
- #include "common/settings_input.h"
- #include "input_common/input_engine.h"
- #include "input_common/main.h"
- /*
- To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
- Tools -> 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 InputCommon::TasInput {
- constexpr size_t PLAYER_NUMBER = 10;
- enum class TasButton : u64 {
- BUTTON_A = 1U << 0,
- BUTTON_B = 1U << 1,
- BUTTON_X = 1U << 2,
- BUTTON_Y = 1U << 3,
- STICK_L = 1U << 4,
- STICK_R = 1U << 5,
- TRIGGER_L = 1U << 6,
- TRIGGER_R = 1U << 7,
- TRIGGER_ZL = 1U << 8,
- TRIGGER_ZR = 1U << 9,
- BUTTON_PLUS = 1U << 10,
- BUTTON_MINUS = 1U << 11,
- BUTTON_LEFT = 1U << 12,
- BUTTON_UP = 1U << 13,
- BUTTON_RIGHT = 1U << 14,
- BUTTON_DOWN = 1U << 15,
- BUTTON_SL = 1U << 16,
- BUTTON_SR = 1U << 17,
- BUTTON_HOME = 1U << 18,
- BUTTON_CAPTURE = 1U << 19,
- };
- struct TasAnalog {
- float x{};
- float y{};
- };
- enum class TasState {
- Running,
- Recording,
- Stopped,
- };
- class Tas final : public InputCommon::InputEngine {
- public:
- explicit Tas(const std::string& input_engine_);
- ~Tas();
- /**
- * Changes the input status that will be stored in each frame
- * @param buttons Bitfield with the status of the buttons
- * @param left_axis Value of the left axis
- * @param right_axis Value of the right axis
- */
- void RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis);
- // Main loop that records or executes input
- void UpdateThread();
- // Sets the flag to start or stop the TAS command execution and swaps controllers profiles
- void StartStop();
- // Stop the TAS and reverts any controller profile
- void Stop();
- // Sets the flag to reload the file and start from the beginning in the next update
- void Reset();
- /**
- * Sets the flag to enable or disable recording of inputs
- * @returns true if the current recording status is enabled
- */
- bool Record();
- /**
- * Saves contents of record_commands on a file
- * @param overwrite_file Indicates if player 1 should be overwritten
- */
- void SaveRecording(bool overwrite_file);
- /**
- * Returns the current status values of TAS playback/recording
- * @returns A Tuple of
- * TasState indicating the current state out of Running ;
- * Current playback progress ;
- * Total length of script file currently loaded or being recorded
- */
- std::tuple<TasState, size_t, size_t> GetStatus() const;
- private:
- enum class TasAxis : u8;
- struct TASCommand {
- u64 buttons{};
- TasAnalog l_axis{};
- TasAnalog r_axis{};
- };
- /// Loads TAS files from all players
- void LoadTasFiles();
- /**
- * Loads TAS file from the specified player
- * @param player_index Player number to save the script
- * @param file_index Script number of the file
- */
- void LoadTasFile(size_t player_index, size_t file_index);
- /**
- * Writes a TAS file from the recorded commands
- * @param file_name Name of the file to be written
- */
- void WriteTasFile(std::u8string file_name);
- /**
- * Parses a string containing the axis values. X and Y have a range from -32767 to 32767
- * @param line String containing axis values with the following format "x;y"
- * @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. Each button is represented by it's text format
- * specified in text_to_tas_button array
- * @param line string containing button name with the following format "a;b;c;d..."
- * @returns A u64 with each bit representing the status of a button
- */
- u64 ReadCommandButtons(const std::string& line) const;
- /**
- * Reset state of all players
- */
- void ClearInput();
- /**
- * Converts an u64 containing the button status into the text equivalent
- * @param buttons Bitfield with the status of the buttons
- * @returns A string with the name of the buttons to be written to the file
- */
- std::string WriteCommandButtons(u64 buttons) const;
- /**
- * Converts an TAS analog object containing the axis status into the text equivalent
- * @param analog Value of the axis
- * @returns A string with the value of the axis to be written to the file
- */
- std::string WriteCommandAxis(TasAnalog analog) const;
- /// Sets an axis for a particular pad to the given value.
- void SetTasAxis(const PadIdentifier& identifier, TasAxis axis, f32 value);
- size_t script_length{0};
- bool is_recording{false};
- bool is_running{false};
- bool needs_reset{false};
- std::array<std::vector<TASCommand>, PLAYER_NUMBER> commands{};
- std::vector<TASCommand> record_commands{};
- size_t current_command{0};
- TASCommand last_input{}; // only used for recording
- };
- } // namespace InputCommon::TasInput
|