diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/joystick/n3ds/SDL_sysjoystick.c | |
Initial commit
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.c | 298 |
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 | */ | ||
| 39 | static 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 | */ | ||
| 53 | static inline int Correct_Axis_Y(int Y) { | ||
| 54 | return Correct_Axis_X(-Y); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick); | ||
| 58 | static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick); | ||
| 59 | static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick); | ||
| 60 | static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick); | ||
| 61 | |||
| 62 | static bool N3DS_JoystickInit(void) | ||
| 63 | { | ||
| 64 | hidInit(); | ||
| 65 | SDL_PrivateJoystickAdded(1); | ||
| 66 | return true; | ||
| 67 | } | ||
| 68 | |||
| 69 | static const char *N3DS_JoystickGetDeviceName(int device_index) | ||
| 70 | { | ||
| 71 | return "Nintendo 3DS"; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int N3DS_JoystickGetCount(void) | ||
| 75 | { | ||
| 76 | return 1; | ||
| 77 | } | ||
| 78 | |||
| 79 | static SDL_GUID N3DS_JoystickGetDeviceGUID(int device_index) | ||
| 80 | { | ||
| 81 | SDL_GUID guid = SDL_CreateJoystickGUIDForName("Nintendo 3DS"); | ||
| 82 | return guid; | ||
| 83 | } | ||
| 84 | |||
| 85 | static SDL_JoystickID N3DS_JoystickGetDeviceInstanceID(int device_index) | ||
| 86 | { | ||
| 87 | return device_index + 1; | ||
| 88 | } | ||
| 89 | |||
| 90 | static 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 | |||
| 99 | static bool N3DS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) | ||
| 100 | { | ||
| 101 | return SDL_Unsupported(); | ||
| 102 | } | ||
| 103 | |||
| 104 | static 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 | |||
| 114 | static 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 | |||
| 130 | static 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 | |||
| 146 | static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick) | ||
| 147 | { | ||
| 148 | static circlePosition previous_state = { 0, 0 }; | ||
| 149 | circlePosition current_state; | ||
| 150 | hidCircleRead(¤t_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 | |||
| 164 | static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick) | ||
| 165 | { | ||
| 166 | static circlePosition previous_state = { 0, 0 }; | ||
| 167 | circlePosition current_state; | ||
| 168 | hidCstickRead(¤t_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 | |||
| 182 | static void N3DS_JoystickClose(SDL_Joystick *joystick) | ||
| 183 | { | ||
| 184 | } | ||
| 185 | |||
| 186 | static void N3DS_JoystickQuit(void) | ||
| 187 | { | ||
| 188 | hidExit(); | ||
| 189 | } | ||
| 190 | |||
| 191 | static 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 | |||
| 225 | static void N3DS_JoystickDetect(void) | ||
| 226 | { | ||
| 227 | } | ||
| 228 | |||
| 229 | static 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 | |||
| 235 | static const char *N3DS_JoystickGetDevicePath(int device_index) | ||
| 236 | { | ||
| 237 | return NULL; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) | ||
| 241 | { | ||
| 242 | return -1; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int N3DS_JoystickGetDevicePlayerIndex(int device_index) | ||
| 246 | { | ||
| 247 | return -1; | ||
| 248 | } | ||
| 249 | |||
| 250 | static void N3DS_JoystickSetDevicePlayerIndex(int device_index, int player_index) | ||
| 251 | { | ||
| 252 | } | ||
| 253 | |||
| 254 | static bool N3DS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) | ||
| 255 | { | ||
| 256 | return SDL_Unsupported(); | ||
| 257 | } | ||
| 258 | |||
| 259 | static bool N3DS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) | ||
| 260 | { | ||
| 261 | return SDL_Unsupported(); | ||
| 262 | } | ||
| 263 | |||
| 264 | static bool N3DS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) | ||
| 265 | { | ||
| 266 | return SDL_Unsupported(); | ||
| 267 | } | ||
| 268 | |||
| 269 | static bool N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) | ||
| 270 | { | ||
| 271 | return SDL_Unsupported(); | ||
| 272 | } | ||
| 273 | |||
| 274 | SDL_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 | ||
