Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/core/analog_controller.h
4214 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]> and contributors.
2
// SPDX-License-Identifier: 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
explicit 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
float GetVibrationMotorState(u32 index) const override;
76
void SetBindState(u32 index, float value) override;
77
u32 GetButtonStateBits() const override;
78
std::optional<u32> GetAnalogInputBytes() const override;
79
u32 GetInputOverlayIconColor() const override;
80
81
void ResetTransferState() override;
82
bool Transfer(const u8 data_in, u8* data_out) override;
83
84
void LoadSettings(const SettingsInterface& si, const char* section, bool initial) override;
85
86
private:
87
using MotorState = std::array<u8, NUM_MOTORS>;
88
89
enum class Command : u8
90
{
91
Idle,
92
Ready,
93
ReadPad, // 0x42
94
ConfigModeSetMode, // 0x43
95
SetAnalogMode, // 0x44
96
GetAnalogMode, // 0x45
97
Command46, // 0x46
98
Command47, // 0x47
99
Command4C, // 0x4C
100
GetSetRumble // 0x4D
101
};
102
103
static constexpr s16 DEFAULT_SMALL_MOTOR_VIBRATION_BIAS = 8;
104
static constexpr s16 DEFAULT_LARGE_MOTOR_VIBRATION_BIAS = 8;
105
106
Command m_command = Command::Idle;
107
u8 m_command_step = 0;
108
u8 m_response_length = 0;
109
110
// Transmit and receive buffers, not including the first Hi-Z/ack response byte
111
static constexpr u32 MAX_RESPONSE_LENGTH = 8;
112
std::array<u8, MAX_RESPONSE_LENGTH> m_rx_buffer{};
113
std::array<u8, MAX_RESPONSE_LENGTH> m_tx_buffer{};
114
115
// Get number of response halfwords (excluding the initial controller info halfword)
116
u8 GetResponseNumHalfwords() const;
117
118
u8 GetModeID() const;
119
u8 GetIDByte() const;
120
121
void SetAnalogMode(bool enabled, bool show_message);
122
void ProcessAnalogModeToggle();
123
void SetMotorState(u32 motor, u8 value);
124
void UpdateHostVibration();
125
u16 GetExtraButtonMask() const;
126
void ResetRumbleConfig();
127
void Poll();
128
129
float m_analog_deadzone = 0.0f;
130
float m_analog_sensitivity = 1.33f;
131
float m_button_deadzone = 0.0f;
132
std::array<s16, NUM_MOTORS> m_vibration_bias{DEFAULT_LARGE_MOTOR_VIBRATION_BIAS, DEFAULT_SMALL_MOTOR_VIBRATION_BIAS};
133
u8 m_invert_left_stick = 0;
134
u8 m_invert_right_stick = 0;
135
136
bool m_force_analog_on_reset = false;
137
bool m_analog_dpad_in_digital_mode = false;
138
u8 m_analog_shoulder_buttons = 0;
139
140
bool m_analog_mode = false;
141
bool m_analog_locked = false;
142
bool m_dualshock_enabled = false;
143
bool m_configuration_mode = false;
144
145
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
146
147
enum : u8
148
{
149
SmallMotor = 0,
150
LargeMotor = 1,
151
};
152
153
std::array<u8, 6> m_rumble_config{};
154
155
bool m_analog_toggle_queued = false;
156
u8 m_status_byte = 0;
157
158
// TODO: Set this with command 0x4D and increase response length in digital mode accordingly
159
u8 m_digital_mode_extra_halfwords = 0;
160
161
// buttons are active low
162
u16 m_button_state = UINT16_C(0xFFFF);
163
164
MotorState m_motor_state{};
165
166
// both directions of axis state, merged to m_axis_state
167
std::array<u8, static_cast<u32>(HalfAxis::Count)> m_half_axis_state{};
168
};
169
170