duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

analog_controller.h (4086B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> and contributors.
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 
      6 #include "controller.h"
      7 
      8 #include <array>
      9 #include <memory>
     10 #include <optional>
     11 
     12 class AnalogController final : public Controller
     13 {
     14 public:
     15   enum class Axis : u8
     16   {
     17     LeftX,
     18     LeftY,
     19     RightX,
     20     RightY,
     21     Count
     22   };
     23 
     24   enum class Button : u8
     25   {
     26     Select = 0,
     27     L3 = 1,
     28     R3 = 2,
     29     Start = 3,
     30     Up = 4,
     31     Right = 5,
     32     Down = 6,
     33     Left = 7,
     34     L2 = 8,
     35     R2 = 9,
     36     L1 = 10,
     37     R1 = 11,
     38     Triangle = 12,
     39     Circle = 13,
     40     Cross = 14,
     41     Square = 15,
     42     Analog = 16,
     43     Count
     44   };
     45 
     46   enum class HalfAxis : u8
     47   {
     48     LLeft,
     49     LRight,
     50     LDown,
     51     LUp,
     52     RLeft,
     53     RRight,
     54     RDown,
     55     RUp,
     56     Count
     57   };
     58 
     59   static constexpr u8 NUM_MOTORS = 2;
     60 
     61   static const Controller::ControllerInfo INFO;
     62 
     63   AnalogController(u32 index);
     64   ~AnalogController() override;
     65 
     66   static std::unique_ptr<AnalogController> Create(u32 index);
     67 
     68   ControllerType GetType() const override;
     69   bool InAnalogMode() const override;
     70 
     71   void Reset() override;
     72   bool DoState(StateWrapper& sw, bool ignore_input_state) override;
     73 
     74   float GetBindState(u32 index) const override;
     75   void SetBindState(u32 index, float value) override;
     76   u32 GetButtonStateBits() const override;
     77   std::optional<u32> GetAnalogInputBytes() const override;
     78   u32 GetInputOverlayIconColor() const override;
     79 
     80   void ResetTransferState() override;
     81   bool Transfer(const u8 data_in, u8* data_out) override;
     82 
     83   void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
     84 
     85 private:
     86   using MotorState = std::array<u8, NUM_MOTORS>;
     87 
     88   enum class Command : u8
     89   {
     90     Idle,
     91     Ready,
     92     ReadPad,           // 0x42
     93     ConfigModeSetMode, // 0x43
     94     SetAnalogMode,     // 0x44
     95     GetAnalogMode,     // 0x45
     96     Command46,         // 0x46
     97     Command47,         // 0x47
     98     Command4C,         // 0x4C
     99     GetSetRumble       // 0x4D
    100   };
    101 
    102   Command m_command = Command::Idle;
    103   int m_command_step = 0;
    104 
    105   // Transmit and receive buffers, not including the first Hi-Z/ack response byte
    106   static constexpr u32 MAX_RESPONSE_LENGTH = 8;
    107   std::array<u8, MAX_RESPONSE_LENGTH> m_rx_buffer;
    108   std::array<u8, MAX_RESPONSE_LENGTH> m_tx_buffer;
    109   u32 m_response_length = 0;
    110 
    111   // Get number of response halfwords (excluding the initial controller info halfword)
    112   u8 GetResponseNumHalfwords() const;
    113 
    114   u8 GetModeID() const;
    115   u8 GetIDByte() const;
    116 
    117   void SetAnalogMode(bool enabled, bool show_message);
    118   void ProcessAnalogModeToggle();
    119   void SetMotorState(u32 motor, u8 value);
    120   void UpdateHostVibration();
    121   u8 GetExtraButtonMaskLSB() const;
    122   void ResetRumbleConfig();
    123   void SetMotorStateForConfigIndex(int index, u8 value);
    124 
    125   bool m_force_analog_on_reset = false;
    126   bool m_analog_dpad_in_digital_mode = false;
    127   float m_analog_deadzone = 0.0f;
    128   float m_analog_sensitivity = 1.33f;
    129   float m_button_deadzone = 0.0f;
    130   u8 m_rumble_bias = 8;
    131   u8 m_invert_left_stick = 0;
    132   u8 m_invert_right_stick = 0;
    133 
    134   bool m_analog_mode = false;
    135   bool m_analog_locked = false;
    136   bool m_dualshock_enabled = false;
    137   bool m_configuration_mode = false;
    138 
    139   std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
    140 
    141   enum : u8
    142   {
    143     LargeMotor = 0,
    144     SmallMotor = 1
    145   };
    146 
    147   std::array<u8, 6> m_rumble_config{};
    148   int m_rumble_config_large_motor_index = -1;
    149   int m_rumble_config_small_motor_index = -1;
    150 
    151   bool m_analog_toggle_queued = false;
    152   u8 m_status_byte = 0;
    153 
    154   // TODO: Set this with command 0x4D and increase response length in digital mode accordingly
    155   u8 m_digital_mode_extra_halfwords = 0;
    156 
    157   // buttons are active low
    158   u16 m_button_state = UINT16_C(0xFFFF);
    159 
    160   MotorState m_motor_state{};
    161 
    162   // both directions of axis state, merged to m_axis_state
    163   std::array<u8, static_cast<u32>(HalfAxis::Count)> m_half_axis_state{};
    164 
    165   // Member variables that are no longer used, but kept and serialized for compatibility with older save states
    166   u8 m_command_param = 0;
    167   bool m_legacy_rumble_unlocked = false;
    168 };