Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c
9906 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
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_HIDAPI
24
25
#include "../../SDL_hints_c.h"
26
#include "../SDL_sysjoystick.h"
27
#include "SDL_hidapijoystick_c.h"
28
#include "SDL_hidapi_rumble.h"
29
#include "../../hidapi/SDL_hidapi_c.h"
30
31
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
32
33
// Define this if you want to log all packets from the controller
34
// #define DEBUG_GAMECUBE_PROTOCOL
35
36
#define MAX_CONTROLLERS 4
37
38
typedef struct
39
{
40
bool pc_mode;
41
SDL_JoystickID joysticks[MAX_CONTROLLERS];
42
Uint8 wireless[MAX_CONTROLLERS];
43
Uint8 min_axis[MAX_CONTROLLERS * SDL_GAMEPAD_AXIS_COUNT];
44
Uint8 max_axis[MAX_CONTROLLERS * SDL_GAMEPAD_AXIS_COUNT];
45
Uint8 rumbleAllowed[MAX_CONTROLLERS];
46
Uint8 rumble[1 + MAX_CONTROLLERS];
47
// Without this variable, hid_write starts to lag a TON
48
bool rumbleUpdate;
49
bool useRumbleBrake;
50
} SDL_DriverGameCube_Context;
51
52
static void HIDAPI_DriverGameCube_RegisterHints(SDL_HintCallback callback, void *userdata)
53
{
54
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, callback, userdata);
55
}
56
57
static void HIDAPI_DriverGameCube_UnregisterHints(SDL_HintCallback callback, void *userdata)
58
{
59
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, callback, userdata);
60
}
61
62
static bool HIDAPI_DriverGameCube_IsEnabled(void)
63
{
64
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
65
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
66
SDL_HIDAPI_DEFAULT));
67
}
68
69
static bool HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
70
{
71
if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) {
72
// Nintendo Co., Ltd. Wii U GameCube Controller Adapter
73
return true;
74
}
75
if (vendor_id == USB_VENDOR_DRAGONRISE &&
76
(product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 ||
77
product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2)) {
78
// EVORETRO GameCube Controller Adapter
79
return true;
80
}
81
return false;
82
}
83
84
static void ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index)
85
{
86
SDL_memset(&ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT], 128 - 88, SDL_GAMEPAD_AXIS_COUNT);
87
SDL_memset(&ctx->max_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT], 128 + 88, SDL_GAMEPAD_AXIS_COUNT);
88
89
// Trigger axes may have a higher resting value
90
ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT + SDL_GAMEPAD_AXIS_LEFT_TRIGGER] = 40;
91
ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT + SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = 40;
92
}
93
94
static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
95
{
96
if (hint) {
97
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
98
ctx->useRumbleBrake = SDL_GetStringBoolean(hint, false);
99
}
100
}
101
102
static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
103
{
104
SDL_DriverGameCube_Context *ctx;
105
Uint8 packet[37];
106
Uint8 *curSlot;
107
Uint8 i;
108
int size;
109
Uint8 initMagic = 0x13;
110
Uint8 rumbleMagic = 0x11;
111
112
#ifdef HAVE_ENABLE_GAMECUBE_ADAPTORS
113
SDL_EnableGameCubeAdaptors();
114
#endif
115
116
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
117
if (!ctx) {
118
return false;
119
}
120
device->context = ctx;
121
122
ctx->joysticks[0] = 0;
123
ctx->joysticks[1] = 0;
124
ctx->joysticks[2] = 0;
125
ctx->joysticks[3] = 0;
126
ctx->rumble[0] = rumbleMagic;
127
ctx->useRumbleBrake = false;
128
129
if (device->vendor_id != USB_VENDOR_NINTENDO) {
130
ctx->pc_mode = true;
131
}
132
133
if (ctx->pc_mode) {
134
for (i = 0; i < MAX_CONTROLLERS; ++i) {
135
ResetAxisRange(ctx, i);
136
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
137
}
138
} else {
139
// This is all that's needed to initialize the device. Really!
140
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
141
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
142
"HIDAPI_DriverGameCube_InitDevice(): Couldn't initialize WUP-028");
143
return false;
144
}
145
146
// Wait for the adapter to initialize
147
SDL_Delay(10);
148
149
// Add all the applicable joysticks
150
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
151
#ifdef DEBUG_GAMECUBE_PROTOCOL
152
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
153
#endif
154
if (size < 37 || packet[0] != 0x21) {
155
continue; // Nothing to do yet...?
156
}
157
158
// Go through all 4 slots
159
curSlot = packet + 1;
160
for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
161
ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
162
163
// Only allow rumble if the adapter's second USB cable is connected
164
ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) && !ctx->wireless[i];
165
166
if (curSlot[0] & 0x30) { // 0x10 - Wired, 0x20 - Wireless
167
if (ctx->joysticks[i] == 0) {
168
ResetAxisRange(ctx, i);
169
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
170
}
171
} else {
172
if (ctx->joysticks[i] != 0) {
173
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
174
ctx->joysticks[i] = 0;
175
}
176
continue;
177
}
178
}
179
}
180
}
181
182
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE,
183
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
184
185
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
186
187
return true;
188
}
189
190
static int HIDAPI_DriverGameCube_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
191
{
192
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
193
Uint8 i;
194
195
for (i = 0; i < 4; ++i) {
196
if (instance_id == ctx->joysticks[i]) {
197
return i;
198
}
199
}
200
return -1;
201
}
202
203
static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
204
{
205
}
206
207
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size)
208
{
209
SDL_Joystick *joystick;
210
Uint8 i, v;
211
Sint16 axis_value;
212
Uint64 timestamp = SDL_GetTicksNS();
213
214
if (size != 10) {
215
return; // How do we handle this packet?
216
}
217
218
i = packet[0] - 1;
219
if (i >= MAX_CONTROLLERS) {
220
return; // How do we handle this packet?
221
}
222
223
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
224
if (!joystick) {
225
// Hasn't been opened yet, skip
226
return;
227
}
228
229
#define READ_BUTTON(off, flag, button) \
230
SDL_SendJoystickButton( \
231
timestamp, \
232
joystick, \
233
button, \
234
((packet[off] & flag) != 0));
235
READ_BUTTON(1, 0x02, 0) // A
236
READ_BUTTON(1, 0x04, 1) // B
237
READ_BUTTON(1, 0x08, 3) // Y
238
READ_BUTTON(1, 0x01, 2) // X
239
READ_BUTTON(2, 0x80, 4) // DPAD_LEFT
240
READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT
241
READ_BUTTON(2, 0x40, 6) // DPAD_DOWN
242
READ_BUTTON(2, 0x10, 7) // DPAD_UP
243
READ_BUTTON(2, 0x02, 8) // START
244
READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER
245
/* These two buttons are for the bottoms of the analog triggers.
246
* More than likely, you're going to want to read the axes instead!
247
* -flibit
248
*/
249
READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT
250
READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT
251
#undef READ_BUTTON
252
253
#define READ_AXIS(off, axis, invert) \
254
v = invert ? (0xff - packet[off]) : packet[off]; \
255
if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
256
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
257
if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
258
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
259
axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
260
SDL_SendJoystickAxis( \
261
timestamp, \
262
joystick, \
263
axis, axis_value);
264
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0)
265
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1)
266
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0)
267
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1)
268
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
269
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
270
#undef READ_AXIS
271
}
272
273
static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, Uint8 *packet, int size)
274
{
275
SDL_Joystick *joystick;
276
Uint8 *curSlot;
277
Uint8 i;
278
Sint16 axis_value;
279
Uint64 timestamp = SDL_GetTicksNS();
280
281
if (size < 37 || packet[0] != 0x21) {
282
return; // Nothing to do right now...?
283
}
284
285
// Go through all 4 slots
286
curSlot = packet + 1;
287
for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
288
ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
289
290
// Only allow rumble if the adapter's second USB cable is connected
291
ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) && !ctx->wireless[i];
292
293
if (curSlot[0] & 0x30) { // 0x10 - Wired, 0x20 - Wireless
294
if (ctx->joysticks[i] == 0) {
295
ResetAxisRange(ctx, i);
296
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
297
}
298
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
299
300
// Hasn't been opened yet, skip
301
if (!joystick) {
302
continue;
303
}
304
} else {
305
if (ctx->joysticks[i] != 0) {
306
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
307
ctx->joysticks[i] = 0;
308
}
309
continue;
310
}
311
312
#define READ_BUTTON(off, flag, button) \
313
SDL_SendJoystickButton( \
314
timestamp, \
315
joystick, \
316
button, \
317
((curSlot[off] & flag) != 0));
318
READ_BUTTON(1, 0x01, 0) // A
319
READ_BUTTON(1, 0x02, 1) // B
320
READ_BUTTON(1, 0x04, 2) // X
321
READ_BUTTON(1, 0x08, 3) // Y
322
READ_BUTTON(1, 0x10, 4) // DPAD_LEFT
323
READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT
324
READ_BUTTON(1, 0x40, 6) // DPAD_DOWN
325
READ_BUTTON(1, 0x80, 7) // DPAD_UP
326
READ_BUTTON(2, 0x01, 8) // START
327
READ_BUTTON(2, 0x02, 9) // RIGHTSHOULDER
328
/* These two buttons are for the bottoms of the analog triggers.
329
* More than likely, you're going to want to read the axes instead!
330
* -flibit
331
*/
332
READ_BUTTON(2, 0x04, 10) // TRIGGERRIGHT
333
READ_BUTTON(2, 0x08, 11) // TRIGGERLEFT
334
#undef READ_BUTTON
335
336
#define READ_AXIS(off, axis) \
337
if (curSlot[off] < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
338
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = curSlot[off]; \
339
if (curSlot[off] > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
340
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = curSlot[off]; \
341
axis_value = (Sint16)HIDAPI_RemapVal(curSlot[off], ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
342
SDL_SendJoystickAxis( \
343
timestamp, \
344
joystick, \
345
axis, axis_value);
346
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX)
347
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY)
348
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX)
349
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTY)
350
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER)
351
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)
352
#undef READ_AXIS
353
}
354
}
355
356
static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
357
{
358
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
359
Uint8 packet[USB_PACKET_LENGTH];
360
int size;
361
362
// Read input packet
363
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
364
#ifdef DEBUG_GAMECUBE_PROTOCOL
365
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
366
#endif
367
if (ctx->pc_mode) {
368
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size);
369
} else {
370
HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size);
371
}
372
}
373
374
// Write rumble packet
375
if (ctx->rumbleUpdate) {
376
SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
377
ctx->rumbleUpdate = false;
378
}
379
380
// If we got here, nothing bad happened!
381
return true;
382
}
383
384
static bool HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
385
{
386
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
387
Uint8 i;
388
389
SDL_AssertJoysticksLocked();
390
391
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
392
if (joystick->instance_id == ctx->joysticks[i]) {
393
joystick->nbuttons = 12;
394
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
395
if (ctx->wireless[i]) {
396
joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
397
} else {
398
joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED;
399
}
400
return true;
401
}
402
}
403
return false; // Should never get here!
404
}
405
406
static bool HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
407
{
408
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
409
Uint8 i, val;
410
411
SDL_AssertJoysticksLocked();
412
413
if (ctx->pc_mode) {
414
return SDL_Unsupported();
415
}
416
417
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
418
if (joystick->instance_id == ctx->joysticks[i]) {
419
if (ctx->wireless[i]) {
420
return SDL_SetError("Nintendo GameCube WaveBird controllers do not support rumble");
421
}
422
if (!ctx->rumbleAllowed[i]) {
423
return SDL_SetError("Second USB cable for WUP-028 not connected");
424
}
425
if (ctx->useRumbleBrake) {
426
if (low_frequency_rumble == 0 && high_frequency_rumble > 0) {
427
val = 0; // if only low is 0 we want to do a regular stop
428
} else if (low_frequency_rumble == 0 && high_frequency_rumble == 0) {
429
val = 2; // if both frequencies are 0 we want to do a hard stop
430
} else {
431
val = 1; // normal rumble
432
}
433
} else {
434
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
435
}
436
if (val != ctx->rumble[i + 1]) {
437
ctx->rumble[i + 1] = val;
438
ctx->rumbleUpdate = true;
439
}
440
return true;
441
}
442
}
443
444
// Should never get here!
445
return SDL_SetError("Couldn't find joystick");
446
}
447
448
static bool HIDAPI_DriverGameCube_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
449
{
450
return SDL_Unsupported();
451
}
452
453
static Uint32 HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
454
{
455
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
456
Uint32 result = 0;
457
458
SDL_AssertJoysticksLocked();
459
460
if (!ctx->pc_mode) {
461
Uint8 i;
462
463
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
464
if (joystick->instance_id == ctx->joysticks[i]) {
465
if (!ctx->wireless[i] && ctx->rumbleAllowed[i]) {
466
result |= SDL_JOYSTICK_CAP_RUMBLE;
467
break;
468
}
469
}
470
}
471
}
472
473
return result;
474
}
475
476
static bool HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
477
{
478
return SDL_Unsupported();
479
}
480
481
static bool HIDAPI_DriverGameCube_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
482
{
483
return SDL_Unsupported();
484
}
485
486
static bool HIDAPI_DriverGameCube_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
487
{
488
return SDL_Unsupported();
489
}
490
491
static void HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
492
{
493
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
494
495
// Stop rumble activity
496
if (ctx->rumbleUpdate) {
497
SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
498
ctx->rumbleUpdate = false;
499
}
500
}
501
502
static void HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
503
{
504
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
505
506
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE,
507
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
508
}
509
510
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = {
511
SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
512
true,
513
HIDAPI_DriverGameCube_RegisterHints,
514
HIDAPI_DriverGameCube_UnregisterHints,
515
HIDAPI_DriverGameCube_IsEnabled,
516
HIDAPI_DriverGameCube_IsSupportedDevice,
517
HIDAPI_DriverGameCube_InitDevice,
518
HIDAPI_DriverGameCube_GetDevicePlayerIndex,
519
HIDAPI_DriverGameCube_SetDevicePlayerIndex,
520
HIDAPI_DriverGameCube_UpdateDevice,
521
HIDAPI_DriverGameCube_OpenJoystick,
522
HIDAPI_DriverGameCube_RumbleJoystick,
523
HIDAPI_DriverGameCube_RumbleJoystickTriggers,
524
HIDAPI_DriverGameCube_GetJoystickCapabilities,
525
HIDAPI_DriverGameCube_SetJoystickLED,
526
HIDAPI_DriverGameCube_SendJoystickEffect,
527
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
528
HIDAPI_DriverGameCube_CloseJoystick,
529
HIDAPI_DriverGameCube_FreeDevice,
530
};
531
532
#endif // SDL_JOYSTICK_HIDAPI_GAMECUBE
533
534
#endif // SDL_JOYSTICK_HIDAPI
535
536