-
Notifications
You must be signed in to change notification settings - Fork 164
/
pad.h
224 lines (202 loc) · 7.78 KB
/
pad.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/**
* @file pad.h
* @brief Simple wrapper for the HID Npad API.
* @author fincs
* @copyright libnx Authors
*/
#pragma once
#include "../types.h"
#include "../services/hid.h"
/// Mask including all existing controller IDs.
#define PAD_ANY_ID_MASK 0x1000100FFUL
/// Pad state object.
typedef struct {
u8 id_mask;
u8 active_id_mask;
bool read_handheld;
bool active_handheld;
u32 style_set;
u32 attributes;
u64 buttons_cur;
u64 buttons_old;
HidAnalogStickState sticks[2];
u32 gc_triggers[2];
} PadState;
/// Pad button repeater state object.
typedef struct {
u64 button_mask;
s32 counter;
u16 delay;
u16 repeat;
} PadRepeater;
/**
* @brief Configures the input layout supported by the application.
* @param[in] max_players The maximum supported number of players (1 to 8).
* @param[in] style_set Bitfield of supported controller styles (see \ref HidNpadStyleTag).
*/
void padConfigureInput(u32 max_players, u32 style_set);
/**
* @brief Initializes a \ref PadState object to read input from one or more controller input sources.
* @param[in] _pad Pointer to \ref PadState.
* @remarks This is a variadic macro, pass the \ref HidNpadIdType value of each controller to add to the set.
*/
#define padInitialize(_pad, ...) ({ \
const HidNpadIdType _pad_ids[] = { __VA_ARGS__ }; \
u64 _pad_mask = 0; \
for (unsigned _pad_i = 0; _pad_i < (sizeof(_pad_ids)/sizeof(_pad_ids[0])); ++_pad_i) \
_pad_mask |= 1UL << (_pad_ids[_pad_i]); \
padInitializeWithMask((_pad), _pad_mask); \
})
/**
* @brief Same as \ref padInitialize, but taking a bitfield of controller IDs directly.
* @param[in] pad Pointer to \ref PadState.
* @param[in] mask Bitfield of controller IDs (each bit's position indicates a different \ref HidNpadIdType value).
*/
void padInitializeWithMask(PadState* pad, u64 mask);
/**
* @brief Same as \ref padInitialize, but including every single controller input source.
* @param[in] pad Pointer to \ref PadState.
* @remark Use this function if you want to accept input from any controller.
*/
NX_INLINE void padInitializeAny(PadState* pad) {
padInitializeWithMask(pad, PAD_ANY_ID_MASK);
}
/**
* @brief Same as \ref padInitialize, but including \ref HidNpadIdType_No1 and \ref HidNpadIdType_Handheld.
* @param[in] pad Pointer to \ref PadState.
* @remark Use this function if you just want to accept input for a single-player application.
*/
NX_INLINE void padInitializeDefault(PadState* pad) {
padInitialize(pad, HidNpadIdType_No1, HidNpadIdType_Handheld);
}
/**
* @brief Updates pad state by reading from the controller input sources specified during initialization.
* @param[in] pad Pointer to \ref PadState.
*/
void padUpdate(PadState* pad);
/**
* @brief Retrieves whether \ref HidNpadIdType_Handheld is an active input source (i.e. it was possible to read from it).
* @param[in] pad Pointer to \ref PadState.
* @return Boolean value.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR bool padIsHandheld(const PadState* pad) {
return pad->active_handheld;
}
/**
* @brief Retrieves whether the specified controller is an active input source (i.e. it was possible to read from it).
* @param[in] pad Pointer to \ref PadState.
* @param[in] id ID of the controller input source (see \ref HidNpadIdType)
* @return Boolean value.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR bool padIsNpadActive(const PadState* pad, HidNpadIdType id) {
if (id <= HidNpadIdType_No8)
return pad->active_id_mask & BIT(id);
else if (id == HidNpadIdType_Handheld)
return pad->active_handheld;
else
return false;
}
/**
* @brief Retrieves the set of input styles supported by the selected controller input sources.
* @param[in] pad Pointer to \ref PadState.
* @return Bitfield of \ref HidNpadStyleTag.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR u32 padGetStyleSet(const PadState* pad) {
return pad->style_set;
}
/**
* @brief Retrieves the set of attributes reported by the system for the selected controller input sources.
* @param[in] pad Pointer to \ref PadState.
* @return Bitfield of \ref HidNpadAttribute.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR u32 padGetAttributes(const PadState* pad) {
return pad->attributes;
}
/**
* @brief Retrieves whether any of the selected controller input sources is connected.
* @param[in] pad Pointer to \ref PadState.
* @return Boolean value.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR bool padIsConnected(const PadState* pad) {
return pad->attributes & HidNpadAttribute_IsConnected;
}
/**
* @brief Retrieves the current set of pressed buttons across all selected controller input sources.
* @param[in] pad Pointer to \ref PadState.
* @return Bitfield of \ref HidNpadButton.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR u64 padGetButtons(const PadState* pad) {
return pad->buttons_cur;
}
/**
* @brief Retrieves the set of buttons that are newly pressed.
* @param[in] pad Pointer to \ref PadState.
* @return Bitfield of \ref HidNpadButton.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR u64 padGetButtonsDown(const PadState* pad) {
return ~pad->buttons_old & pad->buttons_cur;
}
/**
* @brief Retrieves the set of buttons that are newly released.
* @param[in] pad Pointer to \ref PadState.
* @return Bitfield of \ref HidNpadButton.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR u64 padGetButtonsUp(const PadState* pad) {
return pad->buttons_old & ~pad->buttons_cur;
}
/**
* @brief Retrieves the position of an analog stick in a controller.
* @param[in] pad Pointer to \ref PadState.
* @param[in] i ID of the analog stick to read (0=left, 1=right).
* @return \ref HidAnalogStickState.
* @remark \ref padUpdate must have been previously called.
*/
NX_CONSTEXPR HidAnalogStickState padGetStickPos(const PadState* pad, unsigned i) {
return pad->sticks[i];
}
/**
* @brief Retrieves the position of an analog trigger in a GameCube controller.
* @param[in] pad Pointer to \ref PadState.
* @param[in] i ID of the analog trigger to read (0=left, 1=right).
* @return Analog trigger position (range is 0 to 0x7fff).
* @remark \ref padUpdate must have been previously called.
* @remark \ref HidNpadStyleTag_NpadGc must have been previously configured as a supported style in \ref padConfigureInput for GC trigger data to be readable.
*/
NX_CONSTEXPR u32 padGetGcTriggerPos(const PadState* pad, unsigned i) {
return pad->gc_triggers[i];
}
/**
* @brief Initializes a \ref PadRepeater object with the specified settings.
* @param[in] r Pointer to \ref PadRepeater.
* @param[in] delay Number of input updates between button presses being first detected and them being considered for repeat.
* @param[in] repeat Number of input updates between autogenerated repeat button presses.
*/
NX_CONSTEXPR void padRepeaterInitialize(PadRepeater* r, u16 delay, u16 repeat) {
r->button_mask = 0;
r->counter = 0;
r->delay = delay;
r->repeat = repeat;
}
/**
* @brief Updates pad repeat state.
* @param[in] r Pointer to \ref PadRepeater.
* @param[in] button_mask Bitfield of currently pressed \ref HidNpadButton that will be considered for repeat.
*/
void padRepeaterUpdate(PadRepeater* r, u64 button_mask);
/**
* @brief Retrieves the set of buttons that are being repeated according to the parameters specified in \ref padRepeaterInitialize.
* @param[in] r Pointer to \ref PadRepeater.
* @return Bitfield of \ref HidNpadButton.
* @remark It is suggested to bitwise-OR the return value of this function with that of \ref padGetButtonsDown.
*/
NX_CONSTEXPR u64 padRepeaterGetButtons(const PadRepeater* r) {
return r->counter == 0 ? r->button_mask : 0;
}