summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c')
-rw-r--r--contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c b/contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c
new file mode 100644
index 0000000..8396ac5
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c
@@ -0,0 +1,298 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_JOYSTICK_N3DS
24
25// This is the N3DS implementation of the SDL joystick API
26
27#include <3ds.h>
28
29#include "../SDL_sysjoystick.h"
30
31#define NB_BUTTONS 23
32
33/*
34 N3DS sticks values are roughly within +/-160
35 which is too small to pass the jitter tolerance.
36 This correction is applied to axis values
37 so they fit better in SDL's value range.
38*/
39static inline int Correct_Axis_X(int X) {
40 if (X > 160) {
41 return SDL_JOYSTICK_AXIS_MAX;
42 }
43 else if (X < -160) {
44 return -SDL_JOYSTICK_AXIS_MAX;
45 }
46 return (X * SDL_JOYSTICK_AXIS_MAX) / 160;
47}
48
49/*
50 The Y axis needs to be flipped because SDL's "up"
51 is reversed compared to libctru's "up"
52*/
53static inline int Correct_Axis_Y(int Y) {
54 return Correct_Axis_X(-Y);
55}
56
57static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick);
58static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick);
59static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick);
60static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick);
61
62static bool N3DS_JoystickInit(void)
63{
64 hidInit();
65 SDL_PrivateJoystickAdded(1);
66 return true;
67}
68
69static const char *N3DS_JoystickGetDeviceName(int device_index)
70{
71 return "Nintendo 3DS";
72}
73
74static int N3DS_JoystickGetCount(void)
75{
76 return 1;
77}
78
79static SDL_GUID N3DS_JoystickGetDeviceGUID(int device_index)
80{
81 SDL_GUID guid = SDL_CreateJoystickGUIDForName("Nintendo 3DS");
82 return guid;
83}
84
85static SDL_JoystickID N3DS_JoystickGetDeviceInstanceID(int device_index)
86{
87 return device_index + 1;
88}
89
90static bool N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index)
91{
92 joystick->nbuttons = NB_BUTTONS;
93 joystick->naxes = 4;
94 joystick->nhats = 0;
95
96 return true;
97}
98
99static bool N3DS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
100{
101 return SDL_Unsupported();
102}
103
104static void N3DS_JoystickUpdate(SDL_Joystick *joystick)
105{
106 Uint64 timestamp = SDL_GetTicksNS();
107
108 UpdateN3DSPressedButtons(timestamp, joystick);
109 UpdateN3DSReleasedButtons(timestamp, joystick);
110 UpdateN3DSCircle(timestamp, joystick);
111 UpdateN3DSCStick(timestamp, joystick);
112}
113
114static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick)
115{
116 static u32 previous_state = 0;
117 u32 updated_down;
118 u32 current_state = hidKeysDown();
119 updated_down = previous_state ^ current_state;
120 if (updated_down) {
121 for (Uint8 i = 0; i < joystick->nbuttons; i++) {
122 if (current_state & BIT(i) & updated_down) {
123 SDL_SendJoystickButton(timestamp, joystick, i, true);
124 }
125 }
126 }
127 previous_state = current_state;
128}
129
130static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick)
131{
132 static u32 previous_state = 0;
133 u32 updated_up;
134 u32 current_state = hidKeysUp();
135 updated_up = previous_state ^ current_state;
136 if (updated_up) {
137 for (Uint8 i = 0; i < joystick->nbuttons; i++) {
138 if (current_state & BIT(i) & updated_up) {
139 SDL_SendJoystickButton(timestamp, joystick, i, false);
140 }
141 }
142 }
143 previous_state = current_state;
144}
145
146static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick)
147{
148 static circlePosition previous_state = { 0, 0 };
149 circlePosition current_state;
150 hidCircleRead(&current_state);
151 if (previous_state.dx != current_state.dx) {
152 SDL_SendJoystickAxis(timestamp, joystick,
153 0,
154 Correct_Axis_X(current_state.dx));
155 }
156 if (previous_state.dy != current_state.dy) {
157 SDL_SendJoystickAxis(timestamp, joystick,
158 1,
159 Correct_Axis_Y(current_state.dy));
160 }
161 previous_state = current_state;
162}
163
164static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick)
165{
166 static circlePosition previous_state = { 0, 0 };
167 circlePosition current_state;
168 hidCstickRead(&current_state);
169 if (previous_state.dx != current_state.dx) {
170 SDL_SendJoystickAxis(timestamp, joystick,
171 2,
172 Correct_Axis_X(current_state.dx));
173 }
174 if (previous_state.dy != current_state.dy) {
175 SDL_SendJoystickAxis(timestamp, joystick,
176 3,
177 Correct_Axis_Y(current_state.dy));
178 }
179 previous_state = current_state;
180}
181
182static void N3DS_JoystickClose(SDL_Joystick *joystick)
183{
184}
185
186static void N3DS_JoystickQuit(void)
187{
188 hidExit();
189}
190
191static bool N3DS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
192{
193 // There is only one possible mapping.
194 *out = (SDL_GamepadMapping){
195 .a = { EMappingKind_Button, 0 },
196 .b = { EMappingKind_Button, 1 },
197 .x = { EMappingKind_Button, 10 },
198 .y = { EMappingKind_Button, 11 },
199 .back = { EMappingKind_Button, 2 },
200 .guide = { EMappingKind_None, 255 },
201 .start = { EMappingKind_Button, 3 },
202 .leftstick = { EMappingKind_None, 255 },
203 .rightstick = { EMappingKind_None, 255 },
204 .leftshoulder = { EMappingKind_Button, 9 },
205 .rightshoulder = { EMappingKind_Button, 8 },
206 .dpup = { EMappingKind_Button, 6 },
207 .dpdown = { EMappingKind_Button, 7 },
208 .dpleft = { EMappingKind_Button, 5 },
209 .dpright = { EMappingKind_Button, 4 },
210 .misc1 = { EMappingKind_None, 255 },
211 .right_paddle1 = { EMappingKind_None, 255 },
212 .left_paddle1 = { EMappingKind_None, 255 },
213 .right_paddle2 = { EMappingKind_None, 255 },
214 .left_paddle2 = { EMappingKind_None, 255 },
215 .leftx = { EMappingKind_Axis, 0 },
216 .lefty = { EMappingKind_Axis, 1 },
217 .rightx = { EMappingKind_Axis, 2 },
218 .righty = { EMappingKind_Axis, 3 },
219 .lefttrigger = { EMappingKind_Button, 14 },
220 .righttrigger = { EMappingKind_Button, 15 },
221 };
222 return true;
223}
224
225static void N3DS_JoystickDetect(void)
226{
227}
228
229static bool N3DS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
230{
231 // We don't override any other drivers
232 return false;
233}
234
235static const char *N3DS_JoystickGetDevicePath(int device_index)
236{
237 return NULL;
238}
239
240static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
241{
242 return -1;
243}
244
245static int N3DS_JoystickGetDevicePlayerIndex(int device_index)
246{
247 return -1;
248}
249
250static void N3DS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
251{
252}
253
254static bool N3DS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
255{
256 return SDL_Unsupported();
257}
258
259static bool N3DS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
260{
261 return SDL_Unsupported();
262}
263
264static bool N3DS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
265{
266 return SDL_Unsupported();
267}
268
269static bool N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
270{
271 return SDL_Unsupported();
272}
273
274SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
275 N3DS_JoystickInit,
276 N3DS_JoystickGetCount,
277 N3DS_JoystickDetect,
278 N3DS_JoystickIsDevicePresent,
279 N3DS_JoystickGetDeviceName,
280 N3DS_JoystickGetDevicePath,
281 N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
282 N3DS_JoystickGetDevicePlayerIndex,
283 N3DS_JoystickSetDevicePlayerIndex,
284 N3DS_JoystickGetDeviceGUID,
285 N3DS_JoystickGetDeviceInstanceID,
286 N3DS_JoystickOpen,
287 N3DS_JoystickRumble,
288 N3DS_JoystickRumbleTriggers,
289 N3DS_JoystickSetLED,
290 N3DS_JoystickSendEffect,
291 N3DS_JoystickSetSensorsEnabled,
292 N3DS_JoystickUpdate,
293 N3DS_JoystickClose,
294 N3DS_JoystickQuit,
295 N3DS_JoystickGetGamepadMapping
296};
297
298#endif // SDL_JOYSTICK_N3DS