|
31 | 31 | #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
|
32 | 32 |
|
33 | 33 | // Define this if you want to log all packets from the controller
|
34 |
| -// #define DEBUG_GAMECUBE_PROTOCOL |
| 34 | +#if 0 |
| 35 | +#define DEBUG_GAMECUBE_PROTOCOL |
| 36 | +#endif |
35 | 37 |
|
36 | 38 | #define MAX_CONTROLLERS 4
|
37 | 39 |
|
@@ -120,22 +122,15 @@ static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
|
120 | 122 | }
|
121 | 123 | device->context = ctx;
|
122 | 124 |
|
123 |
| - ctx->joysticks[0] = 0; |
124 |
| - ctx->joysticks[1] = 0; |
125 |
| - ctx->joysticks[2] = 0; |
126 |
| - ctx->joysticks[3] = 0; |
127 | 125 | ctx->rumble[0] = rumbleMagic;
|
128 |
| - ctx->useRumbleBrake = false; |
129 | 126 |
|
130 | 127 | if (device->vendor_id != USB_VENDOR_NINTENDO) {
|
131 | 128 | ctx->pc_mode = true;
|
132 | 129 | }
|
133 | 130 |
|
134 | 131 | if (ctx->pc_mode) {
|
135 |
| - for (i = 0; i < MAX_CONTROLLERS; ++i) { |
136 |
| - ResetAxisRange(ctx, i); |
137 |
| - HIDAPI_JoystickConnected(device, &ctx->joysticks[i]); |
138 |
| - } |
| 132 | + ResetAxisRange(ctx, 0); |
| 133 | + HIDAPI_JoystickConnected(device, &ctx->joysticks[0]); |
139 | 134 | } else {
|
140 | 135 | // This is all that's needed to initialize the device. Really!
|
141 | 136 | if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
|
@@ -205,69 +200,61 @@ static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device
|
205 | 200 | {
|
206 | 201 | }
|
207 | 202 |
|
208 |
| -static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size) |
| 203 | +static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick) |
209 | 204 | {
|
210 | 205 | SDL_Joystick *joystick;
|
211 |
| - Uint8 i, v; |
| 206 | + const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index |
| 207 | + Uint8 v; |
212 | 208 | Sint16 axis_value;
|
213 | 209 | Uint64 timestamp = SDL_GetTicksNS();
|
214 | 210 |
|
215 |
| - if (size != 10) { |
216 |
| - return; // How do we handle this packet? |
217 |
| - } |
218 |
| - |
219 |
| - i = packet[0] - 1; |
220 |
| - if (i >= MAX_CONTROLLERS) { |
221 |
| - return; // How do we handle this packet? |
222 |
| - } |
223 |
| - |
224 | 211 | joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
|
225 | 212 | if (!joystick) {
|
226 | 213 | // Hasn't been opened yet, skip
|
227 | 214 | return;
|
228 | 215 | }
|
229 | 216 |
|
230 |
| -#define READ_BUTTON(off, flag, button) \ |
231 |
| - SDL_SendJoystickButton( \ |
232 |
| - timestamp, \ |
233 |
| - joystick, \ |
234 |
| - button, \ |
| 217 | +#define READ_BUTTON(off, flag, button) \ |
| 218 | + SDL_SendJoystickButton( \ |
| 219 | + timestamp, \ |
| 220 | + joystick, \ |
| 221 | + button, \ |
235 | 222 | ((packet[off] & flag) != 0));
|
236 |
| - READ_BUTTON(1, 0x02, 0) // A |
237 |
| - READ_BUTTON(1, 0x04, 1) // B |
238 |
| - READ_BUTTON(1, 0x08, 3) // Y |
239 |
| - READ_BUTTON(1, 0x01, 2) // X |
240 |
| - READ_BUTTON(2, 0x80, 4) // DPAD_LEFT |
241 |
| - READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT |
242 |
| - READ_BUTTON(2, 0x40, 6) // DPAD_DOWN |
243 |
| - READ_BUTTON(2, 0x10, 7) // DPAD_UP |
244 |
| - READ_BUTTON(2, 0x02, 8) // START |
245 |
| - READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER |
| 223 | + READ_BUTTON(0, 0x02, 0) // A |
| 224 | + READ_BUTTON(0, 0x04, 1) // B |
| 225 | + READ_BUTTON(0, 0x08, 3) // Y |
| 226 | + READ_BUTTON(0, 0x01, 2) // X |
| 227 | + READ_BUTTON(1, 0x80, 4) // DPAD_LEFT |
| 228 | + READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT |
| 229 | + READ_BUTTON(1, 0x40, 6) // DPAD_DOWN |
| 230 | + READ_BUTTON(1, 0x10, 7) // DPAD_UP |
| 231 | + READ_BUTTON(1, 0x02, 8) // START |
| 232 | + READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER |
246 | 233 | /* These two buttons are for the bottoms of the analog triggers.
|
247 | 234 | * More than likely, you're going to want to read the axes instead!
|
248 | 235 | * -flibit
|
249 | 236 | */
|
250 |
| - READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT |
251 |
| - READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT |
| 237 | + READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT |
| 238 | + READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT |
252 | 239 | #undef READ_BUTTON
|
253 | 240 |
|
254 |
| -#define READ_AXIS(off, axis, invert) \ |
255 |
| - v = invert ? (0xff - packet[off]) : packet[off]; \ |
256 |
| - if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ |
257 |
| - ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ |
258 |
| - if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ |
259 |
| - ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ |
| 241 | +#define READ_AXIS(off, axis, invert) \ |
| 242 | + v = (invert) ? (0xff - packet[off]) : packet[off]; \ |
| 243 | + if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ |
| 244 | + ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ |
| 245 | + if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ |
| 246 | + ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ |
260 | 247 | 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); \
|
261 |
| - SDL_SendJoystickAxis( \ |
262 |
| - timestamp, \ |
263 |
| - joystick, \ |
| 248 | + SDL_SendJoystickAxis( \ |
| 249 | + timestamp, \ |
| 250 | + joystick, \ |
264 | 251 | axis, axis_value);
|
265 |
| - READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0) |
266 |
| - READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1) |
267 |
| - READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0) |
268 |
| - READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1) |
269 |
| - READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) |
270 |
| - READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) |
| 252 | + READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0) |
| 253 | + READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1) |
| 254 | + READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0) |
| 255 | + READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1) |
| 256 | + READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) |
| 257 | + READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) |
271 | 258 | #undef READ_AXIS
|
272 | 259 | }
|
273 | 260 |
|
@@ -366,7 +353,18 @@ static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
|
366 | 353 | HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
|
367 | 354 | #endif
|
368 | 355 | if (ctx->pc_mode) {
|
369 |
| - HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size); |
| 356 | + if (size == 10) { |
| 357 | + // This is the older firmware |
| 358 | + // The first byte is the index of the connected controller |
| 359 | + // The C stick has an inverted value range compared to the left stick |
| 360 | + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true); |
| 361 | + } else if (size == 9) { |
| 362 | + // This is the newer firmware (version 0x7) |
| 363 | + // The C stick has the same value range compared to the left stick |
| 364 | + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false); |
| 365 | + } else { |
| 366 | + // How do we handle this packet? |
| 367 | + } |
370 | 368 | } else {
|
371 | 369 | HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size);
|
372 | 370 | }
|
|
0 commit comments