Skip to content

Latest commit

 

History

History
790 lines (700 loc) · 30.5 KB

controllermap.c

File metadata and controls

790 lines (700 loc) · 30.5 KB
 
Jan 17, 2020
Jan 17, 2020
2
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/* Game controller mapping generator */
/* Gabriel Jacobo <gabomdq@gmail.com> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
#ifndef SDL_JOYSTICK_DISABLED
Nov 21, 2019
Nov 21, 2019
24
25
26
/* Define this for verbose output while mapping controllers */
#define DEBUG_CONTROLLERMAP
27
28
29
30
31
#ifdef __IPHONEOS__
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
#else
#define SCREEN_WIDTH 512
Oct 13, 2016
Oct 13, 2016
32
#define SCREEN_HEIGHT 320
33
34
35
36
37
#endif
#define MARKER_BUTTON 1
#define MARKER_AXIS 2
Dec 27, 2016
Dec 27, 2016
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
enum
{
SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE,
SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE,
SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE,
SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE,
SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE,
SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE,
SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE,
SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE,
SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT,
SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT,
SDL_CONTROLLER_BINDING_AXIS_MAX,
};
#define BINDING_COUNT (SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_MAX)
Dec 15, 2016
Dec 15, 2016
54
55
static struct
56
57
58
59
60
{
int x, y;
double angle;
int marker;
Dec 15, 2016
Dec 15, 2016
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
} s_arrBindingDisplay[BINDING_COUNT] = {
{ 387, 167, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_A */
{ 431, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_B */
{ 342, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_X */
{ 389, 101, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_Y */
{ 174, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_BACK */
{ 233, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_GUIDE */
{ 289, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_START */
{ 75, 154, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_LEFTSTICK */
{ 305, 230, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_RIGHTSTICK */
{ 77, 40, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_LEFTSHOULDER */
{ 396, 36, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER */
{ 154, 188, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_UP */
{ 154, 249, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_DOWN */
{ 116, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_LEFT */
{ 186, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_RIGHT */
Dec 27, 2016
Dec 27, 2016
77
78
79
80
81
82
83
84
85
86
{ 74, 153, 270.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE */
{ 74, 153, 90.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE */
{ 74, 153, 0.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE */
{ 74, 153, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE */
{ 306, 231, 270.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE */
{ 306, 231, 90.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE */
{ 306, 231, 0.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE */
{ 306, 231, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE */
{ 91, -20, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT */
{ 375, -20, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT */
Dec 15, 2016
Dec 15, 2016
87
88
89
90
91
92
93
};
static int s_arrBindingOrder[BINDING_COUNT] = {
SDL_CONTROLLER_BUTTON_A,
SDL_CONTROLLER_BUTTON_B,
SDL_CONTROLLER_BUTTON_Y,
SDL_CONTROLLER_BUTTON_X,
Dec 27, 2016
Dec 27, 2016
94
95
96
97
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE,
Dec 15, 2016
Dec 15, 2016
98
SDL_CONTROLLER_BUTTON_LEFTSTICK,
Dec 27, 2016
Dec 27, 2016
99
100
101
102
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE,
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE,
Dec 15, 2016
Dec 15, 2016
103
104
SDL_CONTROLLER_BUTTON_RIGHTSTICK,
SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
Dec 27, 2016
Dec 27, 2016
105
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT,
Dec 15, 2016
Dec 15, 2016
106
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
Dec 27, 2016
Dec 27, 2016
107
SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT,
Dec 15, 2016
Dec 15, 2016
108
109
110
111
112
113
114
115
116
SDL_CONTROLLER_BUTTON_DPAD_UP,
SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
SDL_CONTROLLER_BUTTON_DPAD_DOWN,
SDL_CONTROLLER_BUTTON_DPAD_LEFT,
SDL_CONTROLLER_BUTTON_BACK,
SDL_CONTROLLER_BUTTON_GUIDE,
SDL_CONTROLLER_BUTTON_START,
};
Dec 27, 2016
Dec 27, 2016
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
typedef struct
{
SDL_GameControllerBindType bindType;
union
{
int button;
struct {
int axis;
int axis_min;
int axis_max;
} axis;
struct {
int hat;
int hat_mask;
} hat;
} value;
Jan 21, 2017
Jan 21, 2017
137
138
SDL_bool committed;
Dec 27, 2016
Dec 27, 2016
139
140
141
142
143
144
145
} SDL_GameControllerExtendedBind;
static SDL_GameControllerExtendedBind s_arrBindings[BINDING_COUNT];
typedef struct
{
SDL_bool m_bMoving;
Dec 5, 2019
Dec 5, 2019
146
int m_nLastValue;
Dec 27, 2016
Dec 27, 2016
147
148
149
150
151
152
153
int m_nStartingValue;
int m_nFarthestValue;
} AxisState;
static int s_nNumAxes;
static AxisState *s_arrAxisState;
Dec 15, 2016
Dec 15, 2016
154
155
156
static int s_iCurrentBinding;
static Uint32 s_unPendingAdvanceTime;
static SDL_bool s_bBindingComplete;
Sep 21, 2016
Sep 21, 2016
159
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
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
{
SDL_Surface *temp;
SDL_Texture *texture;
/* Load the sprite image */
temp = SDL_LoadBMP(file);
if (temp == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
return NULL;
}
/* Set transparent pixel as the pixel at (0,0) */
if (transparent) {
if (temp->format->palette) {
SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
}
}
/* Create textures from the image */
texture = SDL_CreateTextureFromSurface(renderer, temp);
if (!texture) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
SDL_FreeSurface(temp);
return NULL;
}
SDL_FreeSurface(temp);
/* We're ready to roll. :) */
return texture;
}
Dec 27, 2016
Dec 27, 2016
191
192
static int
StandardizeAxisValue(int nValue)
Dec 15, 2016
Dec 15, 2016
193
{
Dec 27, 2016
Dec 27, 2016
194
195
196
197
198
199
200
201
202
203
204
205
if (nValue > SDL_JOYSTICK_AXIS_MAX/2) {
return SDL_JOYSTICK_AXIS_MAX;
} else if (nValue < SDL_JOYSTICK_AXIS_MIN/2) {
return SDL_JOYSTICK_AXIS_MIN;
} else {
return 0;
}
}
static void
SetCurrentBinding(int iBinding)
{
Jan 4, 2017
Jan 4, 2017
206
int iIndex;
Dec 27, 2016
Dec 27, 2016
207
SDL_GameControllerExtendedBind *pBinding;
Dec 15, 2016
Dec 15, 2016
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
if (iBinding < 0) {
return;
}
if (iBinding == BINDING_COUNT) {
s_bBindingComplete = SDL_TRUE;
return;
}
s_iCurrentBinding = iBinding;
pBinding = &s_arrBindings[s_arrBindingOrder[s_iCurrentBinding]];
SDL_zerop(pBinding);
Jan 4, 2017
Jan 4, 2017
223
224
225
for (iIndex = 0; iIndex < s_nNumAxes; ++iIndex) {
s_arrAxisState[iIndex].m_nFarthestValue = s_arrAxisState[iIndex].m_nStartingValue;
}
Dec 27, 2016
Dec 27, 2016
226
Dec 15, 2016
Dec 15, 2016
227
228
229
s_unPendingAdvanceTime = 0;
}
Jan 4, 2017
Jan 4, 2017
230
231
232
233
234
235
236
237
238
239
240
241
242
static SDL_bool
BBindingContainsBinding(const SDL_GameControllerExtendedBind *pBindingA, const SDL_GameControllerExtendedBind *pBindingB)
{
if (pBindingA->bindType != pBindingB->bindType)
{
return SDL_FALSE;
}
switch (pBindingA->bindType)
{
case SDL_CONTROLLER_BINDTYPE_AXIS:
if (pBindingA->value.axis.axis != pBindingB->value.axis.axis) {
return SDL_FALSE;
}
Jan 21, 2017
Jan 21, 2017
243
244
245
if (!pBindingA->committed) {
return SDL_FALSE;
}
Jan 4, 2017
Jan 4, 2017
246
247
248
249
250
251
252
253
254
255
256
257
258
{
int minA = SDL_min(pBindingA->value.axis.axis_min, pBindingA->value.axis.axis_max);
int maxA = SDL_max(pBindingA->value.axis.axis_min, pBindingA->value.axis.axis_max);
int minB = SDL_min(pBindingB->value.axis.axis_min, pBindingB->value.axis.axis_max);
int maxB = SDL_max(pBindingB->value.axis.axis_min, pBindingB->value.axis.axis_max);
return (minA <= minB && maxA >= maxB);
}
/* Not reached */
default:
return SDL_memcmp(pBindingA, pBindingB, sizeof(*pBindingA)) == 0;
}
}
Dec 15, 2016
Dec 15, 2016
259
static void
Dec 27, 2016
Dec 27, 2016
260
ConfigureBinding(const SDL_GameControllerExtendedBind *pBinding)
Dec 15, 2016
Dec 15, 2016
261
{
Dec 27, 2016
Dec 27, 2016
262
SDL_GameControllerExtendedBind *pCurrent;
Dec 15, 2016
Dec 15, 2016
263
264
265
266
267
int iIndex;
int iCurrentElement = s_arrBindingOrder[s_iCurrentBinding];
/* Do we already have this binding? */
for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) {
Jan 4, 2017
Jan 4, 2017
268
269
pCurrent = &s_arrBindings[iIndex];
if (BBindingContainsBinding(pCurrent, pBinding)) {
Dec 15, 2016
Dec 15, 2016
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
if (iIndex == SDL_CONTROLLER_BUTTON_A && iCurrentElement != SDL_CONTROLLER_BUTTON_B) {
/* Skip to the next binding */
SetCurrentBinding(s_iCurrentBinding + 1);
return;
}
if (iIndex == SDL_CONTROLLER_BUTTON_B) {
/* Go back to the previous binding */
SetCurrentBinding(s_iCurrentBinding - 1);
return;
}
/* Already have this binding, ignore it */
return;
}
}
Jan 21, 2017
Jan 21, 2017
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#ifdef DEBUG_CONTROLLERMAP
switch ( pBinding->bindType )
{
case SDL_CONTROLLER_BINDTYPE_NONE:
break;
case SDL_CONTROLLER_BINDTYPE_BUTTON:
SDL_Log("Configuring button binding for button %d\n", pBinding->value.button);
break;
case SDL_CONTROLLER_BINDTYPE_AXIS:
SDL_Log("Configuring axis binding for axis %d %d/%d committed = %s\n", pBinding->value.axis.axis, pBinding->value.axis.axis_min, pBinding->value.axis.axis_max, pBinding->committed ? "true" : "false");
break;
case SDL_CONTROLLER_BINDTYPE_HAT:
SDL_Log("Configuring hat binding for hat %d %d\n", pBinding->value.hat.hat, pBinding->value.hat.hat_mask);
break;
}
#endif /* DEBUG_CONTROLLERMAP */
Dec 15, 2016
Dec 15, 2016
304
305
306
307
308
309
310
311
312
313
314
/* Should the new binding override the existing one? */
pCurrent = &s_arrBindings[iCurrentElement];
if (pCurrent->bindType != SDL_CONTROLLER_BINDTYPE_NONE) {
SDL_bool bNativeDPad, bCurrentDPad;
SDL_bool bNativeAxis, bCurrentAxis;
bNativeDPad = (iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_UP ||
iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_DOWN ||
iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
bCurrentDPad = (pCurrent->bindType == SDL_CONTROLLER_BINDTYPE_HAT);
Jan 21, 2017
Jan 21, 2017
315
if (bNativeDPad && bCurrentDPad) {
Dec 15, 2016
Dec 15, 2016
316
317
318
319
320
321
/* We already have a binding of the type we want, ignore the new one */
return;
}
bNativeAxis = (iCurrentElement >= SDL_CONTROLLER_BUTTON_MAX);
bCurrentAxis = (pCurrent->bindType == SDL_CONTROLLER_BINDTYPE_AXIS);
Jan 4, 2017
Jan 4, 2017
322
323
324
if (bNativeAxis == bCurrentAxis &&
(pBinding->bindType != SDL_CONTROLLER_BINDTYPE_AXIS ||
pBinding->value.axis.axis != pCurrent->value.axis.axis)) {
Dec 15, 2016
Dec 15, 2016
325
326
327
328
329
330
331
/* We already have a binding of the type we want, ignore the new one */
return;
}
}
*pCurrent = *pBinding;
Jan 21, 2017
Jan 21, 2017
332
333
334
335
336
if (pBinding->committed) {
s_unPendingAdvanceTime = SDL_GetTicks();
} else {
s_unPendingAdvanceTime = 0;
}
Dec 15, 2016
Dec 15, 2016
337
338
}
Dec 27, 2016
Dec 27, 2016
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
static SDL_bool
BMergeAxisBindings(int iIndex)
{
SDL_GameControllerExtendedBind *pBindingA = &s_arrBindings[iIndex];
SDL_GameControllerExtendedBind *pBindingB = &s_arrBindings[iIndex+1];
if (pBindingA->bindType == SDL_CONTROLLER_BINDTYPE_AXIS &&
pBindingB->bindType == SDL_CONTROLLER_BINDTYPE_AXIS &&
pBindingA->value.axis.axis == pBindingB->value.axis.axis) {
if (pBindingA->value.axis.axis_min == pBindingB->value.axis.axis_min) {
pBindingA->value.axis.axis_min = pBindingA->value.axis.axis_max;
pBindingA->value.axis.axis_max = pBindingB->value.axis.axis_max;
pBindingB->bindType = SDL_CONTROLLER_BINDTYPE_NONE;
return SDL_TRUE;
}
}
return SDL_FALSE;
}
Dec 15, 2016
Dec 15, 2016
357
static void
358
359
360
361
362
363
WatchJoystick(SDL_Joystick * joystick)
{
SDL_Window *window = NULL;
SDL_Renderer *screen = NULL;
SDL_Texture *background, *button, *axis, *marker;
const char *name = NULL;
Dec 15, 2016
Dec 15, 2016
364
SDL_bool done = SDL_FALSE;
365
366
367
368
SDL_Event event;
SDL_Rect dst;
Uint8 alpha=200, alpha_step = -1;
Uint32 alpha_ticks = 0;
Dec 15, 2016
Dec 15, 2016
369
SDL_JoystickID nJoystickID;
Jan 4, 2017
Jan 4, 2017
370
int iIndex;
371
372
373
374
375
376
377
/* Create a window to display joystick axis position */
window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
SCREEN_HEIGHT, 0);
if (window == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
Dec 15, 2016
Dec 15, 2016
378
return;
379
380
381
382
383
384
}
screen = SDL_CreateRenderer(window, -1, 0);
if (screen == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
Dec 15, 2016
Dec 15, 2016
385
return;
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
}
background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
button = LoadTexture(screen, "button.bmp", SDL_TRUE);
axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
SDL_RaiseWindow(window);
/* scale for platforms that don't give you the window size you asked for. */
SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
/* Print info about the joystick we are watching */
name = SDL_JoystickName(joystick);
SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
name ? name : "Unknown Joystick");
SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
SDL_Log("\n\n\
====================================================================================\n\
Press the buttons on your controller when indicated\n\
(Your controller may look different than the picture)\n\
If you want to correct a mistake, press backspace or the back button on your device\n\
To skip a button, press SPACE or click/touch the screen\n\
To exit, press ESC\n\
====================================================================================\n");
Dec 15, 2016
Dec 15, 2016
412
413
nJoystickID = SDL_JoystickInstanceID(joystick);
Dec 27, 2016
Dec 27, 2016
415
s_nNumAxes = SDL_JoystickNumAxes(joystick);
Mar 4, 2017
Mar 4, 2017
416
s_arrAxisState = (AxisState *)SDL_calloc(s_nNumAxes, sizeof(*s_arrAxisState));
Dec 27, 2016
Dec 27, 2016
417
Jan 17, 2020
Jan 17, 2020
418
419
420
421
422
/* Skip any spurious events at start */
while (SDL_PollEvent(&event) > 0) {
continue;
}
423
/* Loop, getting joystick events! */
Dec 15, 2016
Dec 15, 2016
424
425
426
427
while (!done && !s_bBindingComplete) {
int iElement = s_arrBindingOrder[s_iCurrentBinding];
switch (s_arrBindingDisplay[iElement].marker) {
428
429
430
431
432
433
434
435
436
437
case MARKER_AXIS:
marker = axis;
break;
case MARKER_BUTTON:
marker = button;
break;
default:
break;
}
Dec 15, 2016
Dec 15, 2016
438
439
dst.x = s_arrBindingDisplay[iElement].x;
dst.y = s_arrBindingDisplay[iElement].y;
440
441
SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
Dec 15, 2016
Dec 15, 2016
442
443
444
445
446
if (SDL_GetTicks() - alpha_ticks > 5) {
alpha_ticks = SDL_GetTicks();
alpha += alpha_step;
if (alpha == 255) {
alpha_step = -1;
Dec 15, 2016
Dec 15, 2016
448
449
450
451
452
453
454
455
456
457
458
459
if (alpha < 128) {
alpha_step = 1;
}
}
SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
SDL_RenderClear(screen);
SDL_RenderCopy(screen, background, NULL, NULL);
SDL_SetTextureAlphaMod(marker, alpha);
SDL_SetTextureColorMod(marker, 10, 255, 21);
SDL_RenderCopyEx(screen, marker, NULL, &dst, s_arrBindingDisplay[iElement].angle, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(screen);
Dec 15, 2016
Dec 15, 2016
461
462
463
464
465
466
467
468
469
while (SDL_PollEvent(&event) > 0) {
switch (event.type) {
case SDL_JOYDEVICEREMOVED:
if (event.jaxis.which == nJoystickID) {
done = SDL_TRUE;
}
break;
case SDL_JOYAXISMOTION:
if (event.jaxis.which == nJoystickID) {
Dec 5, 2019
Dec 5, 2019
470
const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80; /* ShanWan PS3 controller needed 96 */
Dec 27, 2016
Dec 27, 2016
471
472
473
474
AxisState *pAxisState = &s_arrAxisState[event.jaxis.axis];
int nValue = event.jaxis.value;
int nCurrentDistance, nFarthestDistance;
if (!pAxisState->m_bMoving) {
Nov 28, 2019
Nov 28, 2019
475
476
Sint16 nInitialValue;
pAxisState->m_bMoving = SDL_JoystickGetAxisInitialState(joystick, event.jaxis.axis, &nInitialValue);
Dec 5, 2019
Dec 5, 2019
477
pAxisState->m_nLastValue = nInitialValue;
Nov 28, 2019
Nov 28, 2019
478
479
pAxisState->m_nStartingValue = nInitialValue;
pAxisState->m_nFarthestValue = nInitialValue;
Dec 5, 2019
Dec 5, 2019
480
481
482
483
} else if (SDL_abs(nValue - pAxisState->m_nLastValue) <= MAX_ALLOWED_JITTER) {
break;
} else {
pAxisState->m_nLastValue = nValue;
Dec 27, 2016
Dec 27, 2016
484
485
486
487
488
}
nCurrentDistance = SDL_abs(nValue - pAxisState->m_nStartingValue);
nFarthestDistance = SDL_abs(pAxisState->m_nFarthestValue - pAxisState->m_nStartingValue);
if (nCurrentDistance > nFarthestDistance) {
pAxisState->m_nFarthestValue = nValue;
Jan 21, 2017
Jan 21, 2017
489
nFarthestDistance = SDL_abs(pAxisState->m_nFarthestValue - pAxisState->m_nStartingValue);
Dec 27, 2016
Dec 27, 2016
490
}
Jan 21, 2017
Jan 21, 2017
491
492
493
494
495
496
497
#ifdef DEBUG_CONTROLLERMAP
SDL_Log("AXIS %d nValue %d nCurrentDistance %d nFarthestDistance %d\n", event.jaxis.axis, nValue, nCurrentDistance, nFarthestDistance);
#endif
if (nFarthestDistance >= 16000) {
/* If we've gone out far enough and started to come back, let's bind this axis */
SDL_bool bCommitBinding = (nCurrentDistance <= 10000) ? SDL_TRUE : SDL_FALSE;
Dec 27, 2016
Dec 27, 2016
498
SDL_GameControllerExtendedBind binding;
Dec 15, 2016
Dec 15, 2016
499
500
SDL_zero(binding);
binding.bindType = SDL_CONTROLLER_BINDTYPE_AXIS;
Dec 27, 2016
Dec 27, 2016
501
502
503
binding.value.axis.axis = event.jaxis.axis;
binding.value.axis.axis_min = StandardizeAxisValue(pAxisState->m_nStartingValue);
binding.value.axis.axis_max = StandardizeAxisValue(pAxisState->m_nFarthestValue);
Jan 21, 2017
Jan 21, 2017
504
binding.committed = bCommitBinding;
Dec 15, 2016
Dec 15, 2016
505
ConfigureBinding(&binding);
Dec 15, 2016
Dec 15, 2016
507
508
509
510
511
}
break;
case SDL_JOYHATMOTION:
if (event.jhat.which == nJoystickID) {
if (event.jhat.value != SDL_HAT_CENTERED) {
Dec 27, 2016
Dec 27, 2016
512
SDL_GameControllerExtendedBind binding;
Jan 21, 2017
Jan 21, 2017
513
514
515
516
#ifdef DEBUG_CONTROLLERMAP
SDL_Log("HAT %d %d\n", event.jhat.hat, event.jhat.value);
#endif
Dec 15, 2016
Dec 15, 2016
517
518
519
520
SDL_zero(binding);
binding.bindType = SDL_CONTROLLER_BINDTYPE_HAT;
binding.value.hat.hat = event.jhat.hat;
binding.value.hat.hat_mask = event.jhat.value;
Jan 21, 2017
Jan 21, 2017
521
binding.committed = SDL_TRUE;
Dec 15, 2016
Dec 15, 2016
522
ConfigureBinding(&binding);
Dec 15, 2016
Dec 15, 2016
524
525
526
527
528
529
}
break;
case SDL_JOYBALLMOTION:
break;
case SDL_JOYBUTTONDOWN:
if (event.jbutton.which == nJoystickID) {
Dec 27, 2016
Dec 27, 2016
530
SDL_GameControllerExtendedBind binding;
Jan 21, 2017
Jan 21, 2017
531
532
533
534
#ifdef DEBUG_CONTROLLERMAP
SDL_Log("BUTTON %d\n", event.jbutton.button);
#endif
Dec 15, 2016
Dec 15, 2016
535
536
537
SDL_zero(binding);
binding.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
binding.value.button = event.jbutton.button;
Jan 21, 2017
Jan 21, 2017
538
binding.committed = SDL_TRUE;
Dec 15, 2016
Dec 15, 2016
539
540
541
542
543
544
545
546
547
548
549
ConfigureBinding(&binding);
}
break;
case SDL_FINGERDOWN:
case SDL_MOUSEBUTTONDOWN:
/* Skip this step */
SetCurrentBinding(s_iCurrentBinding + 1);
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
SetCurrentBinding(s_iCurrentBinding - 1);
Dec 15, 2016
Dec 15, 2016
551
552
553
}
if (event.key.keysym.sym == SDLK_SPACE) {
SetCurrentBinding(s_iCurrentBinding + 1);
Dec 15, 2016
Dec 15, 2016
555
556
557
}
if ((event.key.keysym.sym != SDLK_ESCAPE)) {
Dec 15, 2016
Dec 15, 2016
560
561
562
563
564
565
/* Fall through to signal quit */
case SDL_QUIT:
done = SDL_TRUE;
break;
default:
break;
Dec 15, 2016
Dec 15, 2016
569
570
571
572
573
574
575
576
SDL_Delay(15);
/* Wait 100 ms for joystick events to stop coming in,
in case a controller sends multiple events for a single control (e.g. axis and button for trigger)
*/
if (s_unPendingAdvanceTime && SDL_GetTicks() - s_unPendingAdvanceTime >= 100) {
SetCurrentBinding(s_iCurrentBinding + 1);
}
Dec 15, 2016
Dec 15, 2016
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
if (s_bBindingComplete) {
char mapping[1024];
char trimmed_name[128];
char *spot;
int iIndex;
char pszElement[12];
SDL_strlcpy(trimmed_name, name, SDL_arraysize(trimmed_name));
while (SDL_isspace(trimmed_name[0])) {
SDL_memmove(&trimmed_name[0], &trimmed_name[1], SDL_strlen(trimmed_name));
}
while (trimmed_name[0] && SDL_isspace(trimmed_name[SDL_strlen(trimmed_name) - 1])) {
trimmed_name[SDL_strlen(trimmed_name) - 1] = '\0';
}
while ((spot = SDL_strchr(trimmed_name, ',')) != NULL) {
SDL_memmove(spot, spot + 1, SDL_strlen(spot));
}
/* Initialize mapping with GUID and name */
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), mapping, SDL_arraysize(mapping));
SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
SDL_strlcat(mapping, trimmed_name, SDL_arraysize(mapping));
SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
SDL_strlcat(mapping, "platform:", SDL_arraysize(mapping));
SDL_strlcat(mapping, SDL_GetPlatform(), SDL_arraysize(mapping));
SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) {
Dec 27, 2016
Dec 27, 2016
607
SDL_GameControllerExtendedBind *pBinding = &s_arrBindings[iIndex];
Dec 15, 2016
Dec 15, 2016
608
609
610
611
612
613
614
615
if (pBinding->bindType == SDL_CONTROLLER_BINDTYPE_NONE) {
continue;
}
if (iIndex < SDL_CONTROLLER_BUTTON_MAX) {
SDL_GameControllerButton eButton = (SDL_GameControllerButton)iIndex;
SDL_strlcat(mapping, SDL_GameControllerGetStringForButton(eButton), SDL_arraysize(mapping));
} else {
Dec 27, 2016
Dec 27, 2016
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
const char *pszAxisName;
switch (iIndex - SDL_CONTROLLER_BUTTON_MAX) {
case SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE:
if (!BMergeAxisBindings(iIndex)) {
SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
}
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTX);
break;
case SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE:
SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTX);
break;
case SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE:
if (!BMergeAxisBindings(iIndex)) {
SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
}
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTY);
break;
case SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE:
SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTY);
break;
case SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE:
if (!BMergeAxisBindings(iIndex)) {
SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
}
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTX);
break;
case SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE:
SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTX);
break;
case SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE:
if (!BMergeAxisBindings(iIndex)) {
SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
}
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTY);
break;
case SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE:
SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTY);
break;
case SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT:
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT);
break;
case SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT:
pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
break;
}
SDL_strlcat(mapping, pszAxisName, SDL_arraysize(mapping));
Dec 15, 2016
Dec 15, 2016
666
667
668
669
670
671
672
673
674
}
SDL_strlcat(mapping, ":", SDL_arraysize(mapping));
pszElement[0] = '\0';
switch (pBinding->bindType) {
case SDL_CONTROLLER_BINDTYPE_BUTTON:
SDL_snprintf(pszElement, sizeof(pszElement), "b%d", pBinding->value.button);
break;
case SDL_CONTROLLER_BINDTYPE_AXIS:
Dec 27, 2016
Dec 27, 2016
675
676
677
678
679
680
681
682
683
684
685
686
687
if (pBinding->value.axis.axis_min == 0 && pBinding->value.axis.axis_max == SDL_JOYSTICK_AXIS_MIN) {
/* The negative half axis */
SDL_snprintf(pszElement, sizeof(pszElement), "-a%d", pBinding->value.axis.axis);
} else if (pBinding->value.axis.axis_min == 0 && pBinding->value.axis.axis_max == SDL_JOYSTICK_AXIS_MAX) {
/* The positive half axis */
SDL_snprintf(pszElement, sizeof(pszElement), "+a%d", pBinding->value.axis.axis);
} else {
SDL_snprintf(pszElement, sizeof(pszElement), "a%d", pBinding->value.axis.axis);
if (pBinding->value.axis.axis_min > pBinding->value.axis.axis_max) {
/* Invert the axis */
SDL_strlcat(pszElement, "~", SDL_arraysize(pszElement));
}
}
Dec 15, 2016
Dec 15, 2016
688
689
690
691
692
693
694
695
696
697
698
699
break;
case SDL_CONTROLLER_BINDTYPE_HAT:
SDL_snprintf(pszElement, sizeof(pszElement), "h%d.%d", pBinding->value.hat.hat, pBinding->value.hat.hat_mask);
break;
default:
SDL_assert(!"Unknown bind type");
break;
}
SDL_strlcat(mapping, pszElement, SDL_arraysize(mapping));
SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
}
700
701
702
703
SDL_Log("Mapping:\n\n%s\n\n", mapping);
/* Print to stdout as well so the user can cat the output somewhere */
printf("%s\n", mapping);
}
Dec 27, 2016
Dec 27, 2016
704
705
706
SDL_free(s_arrAxisState);
s_arrAxisState = NULL;
707
708
709
710
711
712
713
714
715
716
717
718
719
SDL_DestroyRenderer(screen);
SDL_DestroyWindow(window);
}
int
main(int argc, char *argv[])
{
const char *name;
int i;
SDL_Joystick *joystick;
/* Enable standard application logging */
Nov 25, 2015
Nov 25, 2015
720
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
/* Initialize SDL (Note: video is required to start event loop) */
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
/* Print information about the joysticks */
SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
for (i = 0; i < SDL_NumJoysticks(); ++i) {
name = SDL_JoystickNameForIndex(i);
SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
joystick = SDL_JoystickOpen(i);
if (joystick == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
SDL_GetError());
} else {
char guid[64];
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
guid, sizeof (guid));
SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick));
SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick));
SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick));
SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick));
SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
SDL_Log(" guid: %s\n", guid);
Nov 11, 2016
Nov 11, 2016
747
SDL_Log(" VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
SDL_JoystickClose(joystick);
}
}
#ifdef __ANDROID__
if (SDL_NumJoysticks() > 0) {
#else
if (argv[1]) {
#endif
int device;
#ifdef __ANDROID__
device = 0;
#else
device = atoi(argv[1]);
#endif
joystick = SDL_JoystickOpen(device);
Dec 15, 2016
Dec 15, 2016
764
765
766
767
768
if (joystick == NULL) {
SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
} else {
WatchJoystick(joystick);
SDL_JoystickClose(joystick);
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
}
}
else {
SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
}
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
return 0;
}
#else
int
main(int argc, char *argv[])
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
Sep 10, 2019
Sep 10, 2019
785
return 1;
Nov 11, 2016
Nov 11, 2016
789
790
/* vi: set ts=4 sw=4 expandtab: */