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

negcon_rumble.h (3635B)


      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 NeGconRumble final : public Controller
     13 {
     14 public:
     15   enum class Axis : u8
     16   {
     17     Steering = 0,
     18     I = 1,
     19     II = 2,
     20     L = 3,
     21     Count
     22   };
     23 
     24   enum class Button : u8
     25   {
     26     Start = 0,
     27     Up = 1,
     28     Right = 2,
     29     Down = 3,
     30     Left = 4,
     31     R = 5,
     32     B = 6,
     33     A = 7,
     34     Analog = 8,
     35     Count
     36   };
     37 
     38   enum class HalfAxis : u8
     39   {
     40     SteeringLeft,
     41     SteeringRight,
     42     I,
     43     II,
     44     L,
     45     Count
     46   };
     47 
     48   static constexpr u8 NUM_MOTORS = 2;
     49 
     50   static const Controller::ControllerInfo INFO;
     51 
     52   NeGconRumble(u32 index);
     53   ~NeGconRumble() override;
     54 
     55   static std::unique_ptr<NeGconRumble> Create(u32 index);
     56 
     57   ControllerType GetType() const override;
     58   bool InAnalogMode() const override;
     59 
     60   void Reset() override;
     61   bool DoState(StateWrapper& sw, bool apply_input_state) override;
     62 
     63   float GetBindState(u32 index) const override;
     64   void SetBindState(u32 index, float value) override;
     65 
     66   void ResetTransferState() override;
     67   bool Transfer(const u8 data_in, u8* data_out) override;
     68 
     69   u32 GetButtonStateBits() const override;
     70   std::optional<u32> GetAnalogInputBytes() const override;
     71 
     72   void LoadSettings(SettingsInterface& si, const char* section, bool initial) override;
     73 
     74 private:
     75   using MotorState = std::array<u8, NUM_MOTORS>;
     76 
     77   enum class Command : u8
     78   {
     79     Idle,
     80     Ready,
     81     ReadPad,           // 0x42
     82     ConfigModeSetMode, // 0x43
     83     SetAnalogMode,     // 0x44
     84     GetAnalogMode,     // 0x45
     85     Command46,         // 0x46
     86     Command47,         // 0x47
     87     Command4C,         // 0x4C
     88     GetSetRumble       // 0x4D
     89   };
     90 
     91   bool m_force_analog_on_reset = true;
     92   bool m_analog_dpad_in_digital_mode = false;
     93   float m_analog_deadzone = 0.0f;
     94   float m_analog_sensitivity = 1.33f;
     95   float m_button_deadzone = 0.0f;
     96   u8 m_rumble_bias = 8;
     97   u8 m_invert_left_stick = 0;
     98   u8 m_invert_right_stick = 0;
     99 
    100   bool m_analog_mode = false;
    101   bool m_analog_locked = false;
    102   bool m_dualshock_enabled = false;
    103   bool m_configuration_mode = false;
    104 
    105   std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
    106 
    107   enum : u8
    108   {
    109     LargeMotor = 0,
    110     SmallMotor = 1
    111   };
    112 
    113   // steering, merged to m_axis_state
    114   std::array<u8, 2> m_half_axis_state{};
    115 
    116   // buttons are active low; bits 0-2, 8-10, 14-15 are not used and are always high
    117   u16 m_button_state = UINT16_C(0xFFFF);
    118 
    119   MotorState m_motor_state{};
    120 
    121   Command m_command = Command::Idle;
    122   int m_command_step = 0;
    123 
    124   // Transmit and receive buffers, not including the first Hi-Z/ack response byte
    125   static constexpr u32 MAX_RESPONSE_LENGTH = 8;
    126   std::array<u8, MAX_RESPONSE_LENGTH> m_rx_buffer;
    127   std::array<u8, MAX_RESPONSE_LENGTH> m_tx_buffer;
    128   u32 m_response_length = 0;
    129 
    130   std::array<u8, 6> m_rumble_config{};
    131   int m_rumble_config_large_motor_index = -1;
    132   int m_rumble_config_small_motor_index = -1;
    133 
    134   bool m_analog_toggle_queued = false;
    135   u8 m_status_byte = 0;
    136 
    137   // Get number of response halfwords (excluding the initial controller info halfword)
    138   u8 GetResponseNumHalfwords() const;
    139 
    140   u8 GetModeID() const;
    141   u8 GetIDByte() const;
    142 
    143   void SetAnalogMode(bool enabled, bool show_message);
    144   void ProcessAnalogModeToggle();
    145   void SetMotorState(u32 motor, u8 value);
    146   void UpdateHostVibration();
    147   u8 GetExtraButtonMaskLSB() const;
    148   void ResetRumbleConfig();
    149   void SetMotorStateForConfigIndex(int index, u8 value);
    150 
    151   float m_steering_deadzone = 0.00f;
    152   float m_steering_sensitivity = 1.00f;
    153 };