1 /*
2  * OpenBOR - http://www.chronocrash.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2019 OpenBOR Team
7  */
8 
9 // Generic control stuff (keyboard+joystick)
10 
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include "globals.h"
15 #include "control.h"
16 #include "openbor.h"
17 #include "List.h"
18 
19 #define AXIS_THRESHOLD 7000
20 
21 typedef enum {
22     DEVICE_TYPE_NONE,
23     DEVICE_TYPE_KEYBOARD,
24     DEVICE_TYPE_CONTROLLER, // XInput compatible controller
25     DEVICE_TYPE_JOYSTICK,   // controller not compatible with XInput
26 } DeviceType;
27 
28 typedef struct {
29     DeviceType deviceType;
30     char name[CONTROL_DEVICE_NAME_SIZE];
31     int mappings[SDID_COUNT];
32     SDL_Haptic *haptic;
33     union {
34         // no extra structure needed for keyboard
35         SDL_GameController *controller;
36         SDL_Joystick *joystick;
37     };
38 } InputDevice;
39 
40 static InputDevice devices[MAX_DEVICES];
41 static bool controlInited = false;
42 static int keyboardDeviceID = -1;
43 static bool altEnterPressed = false;
44 
45 // if non-null, device is being remapped in the input settings menu
46 static InputDevice *remapDevice = NULL;
47 static int remapKeycode = -1;
48 
49 // each list member is an array of SDID_COUNT ints, dynamically allocated
50 static List savedMappings;
51 static bool savedMappingsInited = false;
52 
53 #ifdef ANDROID
54 #define MAX_POINTERS 30
55 typedef enum
56 {
57     TOUCH_STATUS_UP,
58     TOUCH_STATUS_DOWN
59 } touch_status;
60 
61 typedef struct TouchStatus {
62     float px[MAX_POINTERS];
63     float py[MAX_POINTERS];
64     SDL_FingerID pid[MAX_POINTERS];
65     touch_status pstatus[MAX_POINTERS];
66 } TouchStatus;
67 
68 extern int nativeWidth;
69 extern int nativeHeight;
70 static TouchStatus touch_info;
71 
72 static void control_update_android_touch(TouchStatus *touch_info, int maxp);
73 #endif
74 
75 // update the mappings for a device in the save data
update_saved_mapping(int deviceID)76 static void update_saved_mapping(int deviceID)
77 {
78     InputDevice *device = &devices[deviceID];
79     if (device->deviceType == DEVICE_TYPE_NONE) return;
80 
81     if (List_FindByName(&savedMappings, device->name))
82     {
83         memcpy(List_Retrieve(&savedMappings), device->mappings, SDID_COUNT * sizeof(int));
84     }
85     else
86     {
87         int *mappings = malloc(SDID_COUNT * sizeof(int));
88         memcpy(mappings, device->mappings, SDID_COUNT * sizeof(int));
89         List_InsertAfter(&savedMappings, mappings, device->name);
90     }
91 }
92 
93 // set the mappings for a device to the saved settings
load_from_saved_mapping(int deviceID)94 static void load_from_saved_mapping(int deviceID)
95 {
96     InputDevice *device = &devices[deviceID];
97     if (device->deviceType == DEVICE_TYPE_NONE) return;
98 
99     if (List_FindByName(&savedMappings, device->name))
100     {
101         memcpy(device->mappings, List_Retrieve(&savedMappings), SDID_COUNT * sizeof(int));
102     }
103     else
104     {
105         control_resetmappings(deviceID);
106     }
107 }
108 
clear_saved_mappings()109 static void clear_saved_mappings()
110 {
111     if (!savedMappingsInited)
112     {
113         List_Init(&savedMappings);
114         savedMappingsInited = true;
115     }
116 
117     int numMappings = List_GetSize(&savedMappings);
118 	List_Reset(&savedMappings);
119 	for (int i = 0; i < numMappings; i++)
120 	{
121 	    free(List_Retrieve(&savedMappings));
122         List_GotoNext(&savedMappings);
123     }
124     List_Clear(&savedMappings);
125 }
126 
127 /* If 2 or more of the same type of controller are plugged in, we need to disambiguate them so that a player assigning
128    devices in the options menu can tell them apart. Do this by appending "#2", "#3", etc. to the names. */
set_device_name(int deviceID,const char * name)129 static void set_device_name(int deviceID, const char *name)
130 {
131     char fullName[CONTROL_DEVICE_NAME_SIZE];
132 
133     for (int i = 0; i < MAX_DEVICES; i++)
134     {
135         bool nameTaken = false;
136 
137         if (i == 0)
138         {
139             snprintf(fullName, sizeof(fullName), "%s", name);
140         }
141         else
142         {
143             snprintf(fullName, sizeof(fullName), "%s #%i", name, i + 1);
144         }
145 
146         for (int j = 0; j < MAX_DEVICES; j++)
147         {
148             if (j != deviceID && devices[j].deviceType != DEVICE_TYPE_NONE)
149             {
150                 if (0 == strcmp(devices[j].name, fullName))
151                 {
152                     nameTaken = true;
153                     break;
154                 }
155             }
156         }
157 
158         if (!nameTaken) break;
159     }
160 
161     snprintf(devices[deviceID].name, sizeof(devices[deviceID].name), "%s", fullName);
162 }
163 
setup_joystick(int deviceID,int sdlDeviceID)164 static void setup_joystick(int deviceID, int sdlDeviceID)
165 {
166     if (SDL_IsGameController(sdlDeviceID))
167     {
168         devices[deviceID].deviceType = DEVICE_TYPE_CONTROLLER;
169         devices[deviceID].controller = SDL_GameControllerOpen(sdlDeviceID);
170         const char *name = SDL_GameControllerNameForIndex(sdlDeviceID);
171         if (name == NULL)
172         {
173             name = SDL_JoystickNameForIndex(sdlDeviceID);
174             if (name == NULL)
175             {
176                 name = "Unknown Controller";
177             }
178         }
179         //snprintf(devices[deviceID].name, sizeof(devices[deviceID].name), "%s", name);
180         set_device_name(deviceID, name);
181         load_from_saved_mapping(deviceID);
182         printf("%s (device #%i, SDL ID %i) is a game controller.\n", devices[deviceID].name, deviceID, sdlDeviceID);
183     }
184     else
185     {
186         devices[deviceID].deviceType = DEVICE_TYPE_JOYSTICK;
187         devices[deviceID].joystick = SDL_JoystickOpen(sdlDeviceID);
188         const char *name = SDL_JoystickNameForIndex(sdlDeviceID);
189         if (name == NULL)
190         {
191             name = "Unknown Controller";
192         }
193         //snprintf(devices[deviceID].name, sizeof(devices[deviceID].name), "%s", name);
194         set_device_name(deviceID, name);
195         load_from_saved_mapping(deviceID);
196         printf("%s (device #%i, SDL ID %i) is not a game controller.\n", devices[deviceID].name, deviceID, sdlDeviceID);
197     }
198 
199     devices[deviceID].haptic = SDL_HapticOpen(sdlDeviceID);
200     if (devices[deviceID].haptic != NULL)
201     {
202         // initialize rumble
203         if (SDL_HapticRumbleInit(devices[deviceID].haptic) < 0)
204         {
205             printf("Warning: Unable to initialize rumble for %s! %s\n", devices[deviceID].name, SDL_GetError());
206         }
207     }
208 }
209 
control_init()210 void control_init()
211 {
212     if (controlInited) return;
213 
214     if (!savedMappingsInited)
215     {
216         List_Init(&savedMappings);
217         savedMappingsInited = true;
218     }
219 
220     // initialize all devices to DEVICE_TYPE_NONE
221     memset(devices, 0, sizeof(devices));
222 
223     int numJoysticks = SDL_NumJoysticks();
224 
225     if (numJoysticks >= MAX_DEVICES)
226     {
227         // subtract 1 so we have room for the keyboard later
228         numJoysticks = MAX_DEVICES - 1;
229     }
230 
231     int joystickCount = 0;
232     for (int i = 0; i < numJoysticks; i++)
233     {
234         // blacklist the Android accelerometer that SDL counts as a "joystick"
235         if (0 == stricmp("Android Accelerometer", SDL_JoystickNameForIndex(i)))
236         {
237             continue;
238         }
239 
240         setup_joystick(joystickCount, i);
241         joystickCount++;
242     }
243 
244     keyboardDeviceID = joystickCount;
245     devices[joystickCount].deviceType = DEVICE_TYPE_KEYBOARD;
246 #ifdef ANDROID
247     snprintf(devices[joystickCount].name, sizeof(devices[joystickCount].name), "%s", "On-Screen Controller");
248 #else
249     snprintf(devices[joystickCount].name, sizeof(devices[joystickCount].name), "%s", "Keyboard");
250 #endif
251     load_from_saved_mapping(joystickCount);
252 
253 #ifdef ANDROID
254     for (int i = 0; i < MAX_POINTERS; i++)
255     {
256         touch_info.pstatus[i] = TOUCH_STATUS_UP;
257     }
258 #endif
259 
260     controlInited = true;
261 }
262 
control_exit()263 void control_exit()
264 {
265     if (!controlInited) return;
266 
267     clear_saved_mappings();
268 
269     for (int i = 0; i < MAX_DEVICES; i++)
270     {
271         InputDevice *device = &devices[i];
272         if (device->deviceType == DEVICE_TYPE_CONTROLLER)
273         {
274             SDL_GameControllerClose(device->controller);
275             device->controller = NULL;
276         }
277         else if (device->deviceType == DEVICE_TYPE_JOYSTICK)
278         {
279             SDL_JoystickClose(device->joystick);
280             device->joystick = NULL;
281         }
282         if (device->haptic)
283         {
284             SDL_HapticClose(device->haptic);
285             device->haptic = NULL;
286         }
287         device->deviceType = DEVICE_TYPE_NONE;
288     }
289 
290     keyboardDeviceID = -1;
291     remapDevice = NULL;
292     remapKeycode = -1;
293     controlInited = false;
294 }
295 
set_default_keyboard_mappings(InputDevice * device)296 static void set_default_keyboard_mappings(InputDevice *device)
297 {
298     device->mappings[SDID_MOVEUP]     = SDL_SCANCODE_UP;
299     device->mappings[SDID_MOVEDOWN]   = SDL_SCANCODE_DOWN;
300     device->mappings[SDID_MOVELEFT]   = SDL_SCANCODE_LEFT;
301     device->mappings[SDID_MOVERIGHT]  = SDL_SCANCODE_RIGHT;
302     device->mappings[SDID_ATTACK]     = SDL_SCANCODE_A;
303     device->mappings[SDID_ATTACK2]    = SDL_SCANCODE_S;
304     device->mappings[SDID_ATTACK3]    = SDL_SCANCODE_Z;
305     device->mappings[SDID_ATTACK4]    = SDL_SCANCODE_X;
306     device->mappings[SDID_JUMP]       = SDL_SCANCODE_D;
307     device->mappings[SDID_SPECIAL]    = SDL_SCANCODE_F;
308     device->mappings[SDID_START]      = SDL_SCANCODE_RETURN;
309     device->mappings[SDID_SCREENSHOT] = SDL_SCANCODE_F12;
310     device->mappings[SDID_ESC]        = SDL_SCANCODE_ESCAPE;
311 }
312 
set_default_controller_mappings(InputDevice * device)313 static void set_default_controller_mappings(InputDevice *device)
314 {
315     device->mappings[SDID_MOVEUP]     = SDL_CONTROLLER_BUTTON_DPAD_UP;
316     device->mappings[SDID_MOVEDOWN]   = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
317     device->mappings[SDID_MOVELEFT]   = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
318     device->mappings[SDID_MOVERIGHT]  = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
319     device->mappings[SDID_ATTACK]     = SDL_CONTROLLER_BUTTON_A;
320     device->mappings[SDID_ATTACK2]    = SDL_CONTROLLER_BUTTON_X;
321     device->mappings[SDID_ATTACK3]    = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
322     device->mappings[SDID_ATTACK4]    = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
323     device->mappings[SDID_JUMP]       = SDL_CONTROLLER_BUTTON_B;
324     device->mappings[SDID_SPECIAL]    = SDL_CONTROLLER_BUTTON_Y;
325     device->mappings[SDID_START]      = SDL_CONTROLLER_BUTTON_START;
326     device->mappings[SDID_SCREENSHOT] = SDL_CONTROLLER_BUTTON_BACK;
327     device->mappings[SDID_ESC]        = SDL_CONTROLLER_BUTTON_B;
328 }
329 
set_default_joystick_mappings(InputDevice * device)330 static void set_default_joystick_mappings(InputDevice *device)
331 {
332     int numButtons = SDL_JoystickNumButtons(device->joystick);
333 
334     device->mappings[SDID_MOVEUP]     = numButtons;
335     device->mappings[SDID_MOVEDOWN]   = numButtons + 1;
336     device->mappings[SDID_MOVELEFT]   = numButtons + 2;
337     device->mappings[SDID_MOVERIGHT]  = numButtons + 3;
338     device->mappings[SDID_ATTACK]     = 0;
339     device->mappings[SDID_ATTACK2]    = 3;
340     device->mappings[SDID_ATTACK3]    = 4;
341     device->mappings[SDID_ATTACK4]    = 5;
342     device->mappings[SDID_JUMP]       = 1;
343     device->mappings[SDID_SPECIAL]    = 2;
344     device->mappings[SDID_START]      = 6;
345     device->mappings[SDID_SCREENSHOT] = 7;
346     device->mappings[SDID_ESC]        = device->mappings[SDID_SPECIAL];
347 }
348 
control_resetmappings(int deviceID)349 void control_resetmappings(int deviceID)
350 {
351     if (deviceID < 0) return;
352 
353     InputDevice *device = &devices[deviceID];
354     switch (device->deviceType)
355     {
356         case DEVICE_TYPE_KEYBOARD:
357             set_default_keyboard_mappings(device);
358             break;
359         case DEVICE_TYPE_CONTROLLER:
360             set_default_controller_mappings(device);
361             break;
362         case DEVICE_TYPE_JOYSTICK:
363             set_default_joystick_mappings(device);
364             break;
365         default:
366             memset(device->mappings, 0, sizeof(device->mappings));
367             break;
368     }
369 }
370 
handle_events()371 static void handle_events()
372 {
373     SDL_Event ev;
374     while (SDL_PollEvent(&ev))
375     {
376         switch (ev.type)
377         {
378             case SDL_QUIT:
379             {
380                 borShutdown(0, DEFAULT_SHUTDOWN_MESSAGE);
381                 break;
382             }
383 
384             /* There is also a CONTROLLERDEVICEADDED event, but we can ignore it since this one works for
385                both kinds of controllers/joysticks. */
386             case SDL_JOYDEVICEADDED:
387             {
388                 bool already_in_use = false;
389 
390                 /* We get this event for devices that were plugged in at application start, which we already
391                    initialized in control_init(). So look through the device list to avoid duplicates. */
392                 if (SDL_IsGameController(ev.jdevice.which))
393                 {
394                     SDL_GameController *controller = SDL_GameControllerOpen(ev.jdevice.which);
395                     for (int i = 0; i < MAX_DEVICES; i++)
396                     {
397                         if (devices[i].deviceType == DEVICE_TYPE_CONTROLLER &&
398                             devices[i].controller == controller)
399                         {
400                             already_in_use = true;
401                             //printf("Already in use as device %i\n", i);
402                             break;
403                         }
404                     }
405                     SDL_GameControllerClose(controller);
406                 }
407                 else
408                 {
409                     SDL_Joystick *joystick = SDL_JoystickOpen(ev.jdevice.which);
410                     for (int i = 0; i < MAX_DEVICES; i++)
411                     {
412                         if (devices[i].deviceType == DEVICE_TYPE_JOYSTICK &&
413                             devices[i].joystick == joystick)
414                         {
415                             already_in_use = true;
416                             //printf("Already in use as device %i\n", i);
417                             break;
418                         }
419                     }
420                     SDL_JoystickClose(joystick);
421                 }
422 
423                 if (already_in_use)
424                 {
425                     break;
426                 }
427 
428                 // Okay, it's actually a newly inserted device, not a duplicate. Initialize it.
429                 printf("Controller or joystick hotplugged: SDL device ID=%i\n", ev.jdevice.which);
430                 for (int i = 0; i < MAX_DEVICES; i++)
431                 {
432                     if (devices[i].deviceType == DEVICE_TYPE_NONE)
433                     {
434                         setup_joystick(i, ev.jdevice.which);
435                         printf("Hotplugged %s set as device #%i\n",
436                                devices[i].deviceType == DEVICE_TYPE_CONTROLLER ? "controller" : "joystick",
437                                i);
438                         break;
439                     }
440                 }
441                 break;
442             }
443 
444             /* There is also a CONTROLLERDEVICEREMOVED event, but we can ignore it since this one works for
445                both kinds of controllers/joysticks. */
446             case SDL_JOYDEVICEREMOVED:
447             {
448                 for (int i = 0; i < MAX_DEVICES; i++)
449                 {
450                     if (devices[i].deviceType == DEVICE_TYPE_CONTROLLER &&
451                         devices[i].controller == SDL_GameControllerFromInstanceID(ev.jdevice.which))
452                     {
453                         SDL_GameControllerClose(devices[i].controller);
454                         devices[i].deviceType = DEVICE_TYPE_NONE;
455                         printf("Controller removed: device #%i (SDL instance ID=%i)\n", i, ev.jdevice.which);
456                         break;
457                     }
458                     else if (devices[i].deviceType == DEVICE_TYPE_JOYSTICK &&
459                              devices[i].joystick == SDL_JoystickFromInstanceID(ev.jdevice.which))
460                     {
461                         SDL_JoystickClose(devices[i].joystick);
462                         devices[i].deviceType = DEVICE_TYPE_NONE;
463                         printf("Joystick removed: device #%i (SDL instance ID=%i)\n", i, ev.jdevice.which);
464                     }
465                 }
466                 break;
467             }
468 
469             case SDL_KEYDOWN:
470             {
471                 if (remapDevice && remapDevice->deviceType == DEVICE_TYPE_KEYBOARD)
472                 {
473                     remapKeycode = ev.key.keysym.scancode;
474                 }
475 
476 #if 0 // disable Alt+Enter fullscreen toggle for now because it causes problems under X11
477                 // Alt+Enter toggles fullscreen
478                 if (ev.key.keysym.scancode == SDL_SCANCODE_RETURN && (SDL_GetModState() & KMOD_ALT) && !altEnterPressed)
479                 {
480                     fprintf(stderr, "Alt+Enter pressed, repeat=%i\n", ev.key.repeat);
481                     video_fullscreen_flip();
482 
483                     /* Force the Enter key to unpressed in the SDL keyboard state so it won't be read by the
484                        is_key_pressed() function if it's mapped to something in-game. */
485                     //((Uint8*)SDL_GetKeyboardState(NULL))[SDL_SCANCODE_RETURN] = 0;
486                     altEnterPressed = true;
487                 }
488 #endif
489                 break;
490             }
491 
492 #if 0 // disable Alt+Enter fullscreen toggle for now because it causes problems under X11
493             case SDL_KEYUP:
494             {
495                 if (ev.key.keysym.scancode == SDL_SCANCODE_RETURN)
496                 {
497                     altEnterPressed = false;
498                 }
499                 break;
500             }
501 #endif
502 
503             case SDL_CONTROLLERBUTTONDOWN:
504             {
505                 if (remapDevice &&
506                     remapDevice->deviceType == DEVICE_TYPE_CONTROLLER &&
507                     SDL_GameControllerFromInstanceID(ev.cbutton.which) == remapDevice->controller)
508                 {
509                     remapKeycode = ev.cbutton.button;
510                 }
511                 break;
512             }
513             case SDL_CONTROLLERAXISMOTION:
514             {
515                 if (remapDevice &&
516                     remapDevice->deviceType == DEVICE_TYPE_CONTROLLER &&
517                     SDL_GameControllerFromInstanceID(ev.caxis.which) == remapDevice->controller)
518                 {
519                     if (ev.caxis.value > AXIS_THRESHOLD)
520                     {
521                         switch (ev.caxis.axis)
522                         {
523                             case SDL_CONTROLLER_AXIS_LEFTX:
524                             case SDL_CONTROLLER_AXIS_LEFTY:
525                             case SDL_CONTROLLER_AXIS_RIGHTX:
526                             case SDL_CONTROLLER_AXIS_RIGHTY:
527                                 remapKeycode = SDL_CONTROLLER_BUTTON_MAX + (ev.caxis.axis * 2) + 1;
528                                 break;
529                             case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
530                                 remapKeycode = SDL_CONTROLLER_BUTTON_MAX + 8;
531                                 break;
532                             case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
533                                 remapKeycode = SDL_CONTROLLER_BUTTON_MAX + 9;
534                                 break;
535                         }
536                     }
537                     else if (ev.caxis.value < -AXIS_THRESHOLD)
538                     {
539                         // the triggers can't have negative values, so we don't need to handle them here
540                         remapKeycode = SDL_CONTROLLER_BUTTON_MAX + (ev.caxis.axis * 2);
541                     }
542                     break;
543                 }
544                 break;
545             }
546             case SDL_JOYBUTTONDOWN:
547             {
548                 if (remapDevice &&
549                     remapDevice->deviceType == DEVICE_TYPE_JOYSTICK &&
550                     remapDevice->joystick &&
551                     SDL_JoystickFromInstanceID(ev.jbutton.which) == remapDevice->joystick)
552                 {
553                     remapKeycode = ev.jbutton.button;
554                 }
555                 break;
556             }
557             case SDL_JOYHATMOTION:
558             {
559                 if (remapDevice &&
560                     remapDevice->deviceType == DEVICE_TYPE_JOYSTICK &&
561                     remapDevice->joystick &&
562                     SDL_JoystickFromInstanceID(ev.jhat.which) == remapDevice->joystick)
563                 {
564                     // do nothing if the d-pad is pressed diagonally; wait for a cardinal direction
565                     unsigned int base = SDL_JoystickNumButtons(remapDevice->joystick) + (4 * ev.jhat.hat);
566                     switch (ev.jhat.value)
567                     {
568                         case SDL_HAT_UP:
569                             remapKeycode = base;
570                             break;
571                         case SDL_HAT_DOWN:
572                             remapKeycode = base + 1;
573                             break;
574                         case SDL_HAT_LEFT:
575                             remapKeycode = base + 2;
576                             break;
577                         case SDL_HAT_RIGHT:
578                             remapKeycode = base + 3;
579                             break;
580                     }
581                 }
582                 break;
583             }
584             case SDL_JOYAXISMOTION:
585             {
586                 if (remapDevice &&
587                     remapDevice->deviceType == DEVICE_TYPE_JOYSTICK &&
588                     remapDevice->joystick &&
589                     SDL_JoystickFromInstanceID(ev.jaxis.which) == remapDevice->joystick)
590                 {
591                     if (ev.jaxis.value < -AXIS_THRESHOLD || ev.jaxis.value > AXIS_THRESHOLD)
592                     {
593                         remapKeycode = SDL_JoystickNumButtons(remapDevice->joystick) +
594                                        4 * SDL_JoystickNumHats(remapDevice->joystick) +
595                                        2 * ev.jaxis.axis + ((ev.jaxis.value < -AXIS_THRESHOLD) ? 0 : 1);
596                     }
597                 }
598                 break;
599             }
600 
601 #ifdef ANDROID
602             case SDL_FINGERDOWN:
603             {
604                 for (int i = 0; i < MAX_POINTERS; i++)
605                 {
606                     if (touch_info.pstatus[i] == TOUCH_STATUS_UP)
607                     {
608                         touch_info.pid[i] = ev.tfinger.fingerId;
609                         touch_info.px[i] = ev.tfinger.x * nativeWidth;
610                         touch_info.py[i] = ev.tfinger.y * nativeHeight;
611                         touch_info.pstatus[i] = TOUCH_STATUS_DOWN;
612                         break;
613                     }
614                 }
615                 control_update_android_touch(&touch_info, MAX_POINTERS);
616                 break;
617             }
618 
619             case SDL_FINGERUP:
620             {
621                 for (int i = 0; i < MAX_POINTERS; i++)
622                 {
623                     if (touch_info.pid[i] == ev.tfinger.fingerId)
624                     {
625                         touch_info.pstatus[i] = TOUCH_STATUS_UP;
626                         break;
627                     }
628                 }
629                 control_update_android_touch(&touch_info, MAX_POINTERS);
630                 break;
631             }
632 
633             case SDL_FINGERMOTION:
634             {
635                 for (int i = 0; i < MAX_POINTERS; i++)
636                 {
637                     if (touch_info.pid[i] == ev.tfinger.fingerId)
638                     {
639                         touch_info.px[i] = ev.tfinger.x * nativeWidth;
640                         touch_info.py[i] = ev.tfinger.y * nativeHeight;
641                         touch_info.pstatus[i] = TOUCH_STATUS_DOWN;
642                         break;
643                     }
644                 }
645                 control_update_android_touch(&touch_info, MAX_POINTERS);
646                 break;
647             }
648 #endif
649         }
650     }
651 }
652 
653 // Returns 1 if key is pressed, 0 if not
is_key_pressed(InputDevice * device,int keycode)654 static unsigned int is_key_pressed(InputDevice *device, int keycode)
655 {
656     if (device->deviceType == DEVICE_TYPE_KEYBOARD)
657     {
658         // If Enter was pressed as part of an Alt+Enter to toggle fullscreen, don't count it as an in-game button press.
659         if (keycode == SDL_SCANCODE_RETURN && altEnterPressed)
660         {
661             return 0;
662         }
663 
664         return SDL_GetKeyboardState(NULL)[keycode];
665     }
666     else if (device->deviceType == DEVICE_TYPE_CONTROLLER)
667     {
668         SDL_GameController *controller = device->controller;
669         if (keycode < SDL_CONTROLLER_BUTTON_MAX)
670         {
671             return SDL_GameControllerGetButton(controller, keycode);
672         }
673         else
674         {
675             int axisCode = keycode - SDL_CONTROLLER_BUTTON_MAX;
676             switch (axisCode)
677             {
678                 case 0: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) < -AXIS_THRESHOLD);
679                 case 1: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) > AXIS_THRESHOLD);
680                 case 2: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) < -AXIS_THRESHOLD);
681                 case 3: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) > AXIS_THRESHOLD);
682                 case 4: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) < -AXIS_THRESHOLD);
683                 case 5: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) > AXIS_THRESHOLD);
684                 case 6: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) < -AXIS_THRESHOLD);
685                 case 7: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) > AXIS_THRESHOLD);
686                 case 8: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > AXIS_THRESHOLD);
687                 case 9: return (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > AXIS_THRESHOLD);
688             }
689             return 0;
690         }
691     }
692     else if (device->deviceType == DEVICE_TYPE_JOYSTICK)
693     {
694         SDL_Joystick *joystick = device->joystick;
695         if (keycode < SDL_JoystickNumButtons(joystick))
696         {
697             return SDL_JoystickGetButton(joystick, keycode);
698         }
699 
700         keycode -= SDL_JoystickNumButtons(joystick);
701         if (keycode < 4 * SDL_JoystickNumHats(joystick))
702         {
703             const int hatMasks[] = {SDL_HAT_UP, SDL_HAT_DOWN, SDL_HAT_LEFT, SDL_HAT_RIGHT};
704             return !!(SDL_JoystickGetHat(joystick, keycode / 4) & hatMasks[keycode % 4]);
705         }
706 
707         keycode -= 4 * SDL_JoystickNumHats(joystick);
708         if (keycode < 2 * SDL_JoystickNumAxes(joystick))
709         {
710             Sint16 axisPosition = SDL_JoystickGetAxis(joystick, keycode / 2);
711             if (keycode & 1)
712             {
713                 return (axisPosition > AXIS_THRESHOLD);
714             }
715             else
716             {
717                 return (axisPosition < -AXIS_THRESHOLD);
718             }
719         }
720     }
721 
722     return 0;
723 }
724 
control_update_player(s_playercontrols * playerControls)725 void control_update_player(s_playercontrols *playerControls)
726 {
727     uint32_t keyflags = 0;
728     InputDevice *device = &devices[playerControls->deviceID];
729 
730     for (unsigned int i = 0; i < SDID_COUNT; i++)
731     {
732         keyflags |= (is_key_pressed(device, device->mappings[i]) << i);
733     }
734 
735     playerControls->newkeyflags = keyflags & (~playerControls->keyflags);
736     playerControls->keyflags = keyflags;
737 }
738 
control_update(s_playercontrols ** playerControls,int numPlayers)739 void control_update(s_playercontrols **playerControls, int numPlayers)
740 {
741     handle_events();
742 
743     for (int i = 0; i < numPlayers; i++)
744     {
745         control_update_player(playerControls[i]);
746     }
747 }
748 
control_remapdevice(int deviceID)749 void control_remapdevice(int deviceID)
750 {
751     if (deviceID < 0)
752     {
753         // done remapping; reset globals to default values
754         remapDevice = NULL;
755         remapKeycode = -1;
756     }
757     else
758     {
759         assert(devices[deviceID].deviceType != DEVICE_TYPE_NONE);
760         remapDevice = &devices[deviceID];
761         remapKeycode = -1;
762     }
763 }
764 
control_getremappedkey()765 int control_getremappedkey()
766 {
767     return remapKeycode;
768 }
769 
control_getmappings(int deviceID)770 int *control_getmappings(int deviceID)
771 {
772     return devices[deviceID].mappings;
773 }
774 
control_getkeyname(int deviceID,int keycode)775 const char *control_getkeyname(int deviceID, int keycode)
776 {
777     if (deviceID < 0) return "None";
778 
779     if (devices[deviceID].deviceType == DEVICE_TYPE_KEYBOARD)
780     {
781         return SDL_GetKeyName(SDL_GetKeyFromScancode(keycode));
782     }
783     else if (devices[deviceID].deviceType == DEVICE_TYPE_CONTROLLER)
784     {
785         // These are more readable than the button names we get from SDL
786         const char *buttonNames[] = {
787             "A",
788             "B",
789             "X",
790             "Y",
791             "Back",
792             "Guide",
793             "Start",
794             "Left Stick Button",
795             "Right Stick Button",
796             "LB",
797             "RB",
798             "D-Pad Up",
799             "D-Pad Down",
800             "D-Pad Left",
801             "D-Pad Right",
802             "Left Stick Left",
803             "Left Stick Right",
804             "Left Stick Up",
805             "Left Stick Down",
806             "Right Stick Left",
807             "Right Stick Right",
808             "Right Stick Up",
809             "Right Stick Down",
810             "LT",
811             "RT"
812         };
813 
814         if (keycode < sizeof(buttonNames) / sizeof(buttonNames[0]))
815         {
816             return buttonNames[keycode];
817         }
818     }
819     else if (devices[deviceID].deviceType == DEVICE_TYPE_JOYSTICK)
820     {
821         static char buttonName[64];
822         SDL_Joystick *joystick = devices[deviceID].joystick;
823         if (keycode < SDL_JoystickNumButtons(joystick))
824         {
825             snprintf(buttonName, sizeof(buttonName), "Button %u", keycode + 1);
826             return buttonName;
827         }
828 
829         keycode -= SDL_JoystickNumButtons(joystick);
830         if (keycode < 4 * SDL_JoystickNumHats(joystick))
831         {
832             // omit the hat number because no real device is going to have more than one d-pad
833             const char *directions[] = {"Up", "Down", "Left", "Right"};
834             snprintf(buttonName, sizeof(buttonName), "D-Pad %s", directions[keycode % 4]);
835             return buttonName;
836         }
837 
838         keycode -= 4 * SDL_JoystickNumHats(joystick);
839         if (keycode < 2 * SDL_JoystickNumAxes(joystick))
840         {
841             snprintf(buttonName, sizeof(buttonName), "Axis %i %c", (keycode / 2) + 1, (keycode & 1) ? '+' : '-');
842             return buttonName;
843         }
844     }
845 
846     return "None";
847 }
848 
control_isvaliddevice(int deviceID)849 bool control_isvaliddevice(int deviceID)
850 {
851     return deviceID >= 0 && devices[deviceID].deviceType != DEVICE_TYPE_NONE;
852 }
853 
control_getdevicename(int deviceID)854 const char *control_getdevicename(int deviceID)
855 {
856     return devices[deviceID].deviceType == DEVICE_TYPE_NONE ? "None" : devices[deviceID].name;
857 }
858 
control_rumble(int deviceID,int ratio,int msec)859 void control_rumble(int deviceID, int ratio, int msec)
860 {
861     if (msec > 0 && devices[deviceID].haptic)
862     {
863         if (SDL_HapticRumblePlay(devices[deviceID].haptic, ratio, msec) != 0)
864         {
865             printf("Warning: Unable to play rumble! %s\n", SDL_GetError());
866         }
867     }
868 }
869 
870 #ifdef ANDROID
871 /*
872 Get if touchscreen vibration is active
873 */
is_touchpad_vibration_enabled()874 bool is_touchpad_vibration_enabled()
875 {
876     return !!(savedata.is_touchpad_vibration_enabled);
877 }
878 
879 /*
880 Android touch logic, the rest of the code is in android/jni/video.c,
881 maybe they'll be merged someday.
882 */
883 extern float bx[MAXTOUCHB];
884 extern float by[MAXTOUCHB];
885 extern float br[MAXTOUCHB];
886 extern unsigned touchstates[MAXTOUCHB];
887 int hide_t = 5000;
888 
control_update_android_touch(TouchStatus * touch_info,int maxp)889 static void control_update_android_touch(TouchStatus *touch_info, int maxp)
890 {
891     #define pc(x) devices[keyboardDeviceID].mappings[x]
892     int i, j;
893     float tx, ty, tr;
894     float r[MAXTOUCHB];
895     float dirx, diry, circlea, circleb, tan;
896     Uint8* keystate = (Uint8*) SDL_GetKeyboardState(NULL);
897     SDL_Event event;
898 
899     memset(touchstates, 0, sizeof(touchstates));
900 
901     for(j=0; j<MAXTOUCHB; j++)
902     {
903         r[j] = br[j]*br[j]*(1.5*1.5);
904     }
905     dirx = (bx[SDID_MOVERIGHT]+bx[SDID_MOVELEFT])/2.0;
906     diry = (by[SDID_MOVEUP]+by[SDID_MOVEDOWN])/2.0;
907     circlea = bx[SDID_MOVERIGHT]-dirx-br[SDID_MOVEUP];
908     circleb = bx[SDID_MOVERIGHT]-dirx+br[SDID_MOVEUP]*1.5;
909     circlea *= circlea;
910     circleb *= circleb;
911     #define tana 0.577350f
912     #define tanb 1.732051f
913     for (i=0; i<maxp; i++)
914     {
915         if(touch_info->pstatus[i] == TOUCH_STATUS_UP) continue;
916 
917         event.type = SDL_KEYDOWN;
918         event.key.type = SDL_KEYDOWN;
919         event.key.timestamp = SDL_GetTicks();
920         event.key.state = SDL_PRESSED;
921         event.key.repeat = 0;
922 
923         tx = touch_info->px[i]-dirx;
924         ty = touch_info->py[i]-diry;
925         tr = tx*tx + ty*ty;
926 
927         //direction button logic is different, check a ring instead of individual buttons
928         if(tr>circlea && tr<=circleb)
929         {
930             if(tx<0)
931             {
932                 tan = ty/tx;
933                 if(tan>=-tana && tan<=tana)
934                 {
935                     touchstates[SDID_MOVELEFT] = 1;
936                     event.key.keysym.scancode = pc(SDID_MOVELEFT);
937                     SDL_PushEvent(&event);
938                 }
939                 else if(tan<-tanb)
940                 {
941                     touchstates[SDID_MOVEDOWN] = 1;
942                     event.key.keysym.scancode = pc(SDID_MOVEDOWN);
943                     SDL_PushEvent(&event);
944                 }
945                 else if(tan>tanb)
946                 {
947                     touchstates[SDID_MOVEUP] = 1;
948                     event.key.keysym.scancode = pc(SDID_MOVEUP);
949                     SDL_PushEvent(&event);
950                 }
951                 else if(ty<0)
952                 {
953                     touchstates[SDID_MOVEUP] = touchstates[SDID_MOVELEFT] = 1;
954                     event.key.keysym.scancode = pc(SDID_MOVEUP);
955                     SDL_PushEvent(&event);
956                     event.key.keysym.scancode = pc(SDID_MOVELEFT);
957                     SDL_PushEvent(&event);
958                 }
959                 else
960                 {
961                     touchstates[SDID_MOVELEFT] = touchstates[SDID_MOVEDOWN] = 1;
962                     event.key.keysym.scancode = pc(SDID_MOVELEFT);
963                     SDL_PushEvent(&event);
964                     event.key.keysym.scancode = pc(SDID_MOVEDOWN);
965                     SDL_PushEvent(&event);
966                 }
967             }
968             else if(tx>0)
969             {
970                 tan = ty/tx;
971                 if(tan>=-tana && tan<=tana)
972                 {
973                     touchstates[SDID_MOVERIGHT] = 1;
974                     event.key.keysym.scancode = pc(SDID_MOVERIGHT);
975                     SDL_PushEvent(&event);
976                 }
977                 else if(tan<-tanb)
978                 {
979                     touchstates[SDID_MOVEUP] = 1;
980                     event.key.keysym.scancode = pc(SDID_MOVEUP);
981                     SDL_PushEvent(&event);
982                 }
983                 else if(tan>tanb)
984                 {
985                     touchstates[SDID_MOVEDOWN] = 1;
986                     event.key.keysym.scancode = pc(SDID_MOVEDOWN);
987                     SDL_PushEvent(&event);
988                 }
989                 else if(ty<0)
990                 {
991                     touchstates[SDID_MOVEUP] = touchstates[SDID_MOVERIGHT] = 1;
992                     event.key.keysym.scancode = pc(SDID_MOVEUP);
993                     SDL_PushEvent(&event);
994                     event.key.keysym.scancode = pc(SDID_MOVERIGHT);
995                     SDL_PushEvent(&event);
996                 }
997                 else
998                 {
999                     touchstates[SDID_MOVERIGHT] = touchstates[SDID_MOVEDOWN] = 1;
1000                     event.key.keysym.scancode = pc(SDID_MOVERIGHT);
1001                     SDL_PushEvent(&event);
1002                     event.key.keysym.scancode = pc(SDID_MOVEDOWN);
1003                     SDL_PushEvent(&event);
1004                 }
1005             }
1006             else
1007             {
1008                 if(ty>0)
1009                 {
1010                     touchstates[SDID_MOVEDOWN] = 1;
1011                     event.key.keysym.scancode = pc(SDID_MOVEDOWN);
1012                     SDL_PushEvent(&event);
1013                 }
1014                 else
1015                 {
1016                     touchstates[SDID_MOVEUP] = 1;
1017                     event.key.keysym.scancode = pc(SDID_MOVEUP);
1018                     SDL_PushEvent(&event);
1019                 }
1020             }
1021         }
1022 
1023         //rest of the buttons
1024         for(j=0; j<MAXTOUCHB; j++)
1025         {
1026             if(j==SDID_MOVERIGHT || j==SDID_MOVEUP ||
1027                 j==SDID_MOVELEFT || j==SDID_MOVEDOWN)
1028                 continue;
1029             tx = touch_info->px[i]-bx[j];
1030             ty = touch_info->py[i]-by[j];
1031             tr = tx*tx + ty*ty;
1032             if(tr<=r[j])
1033             {
1034                 touchstates[j] = 1;
1035                 event.key.keysym.scancode = pc(j);
1036                 SDL_PushEvent(&event);
1037             }
1038         }
1039     }
1040     #undef tana
1041     #undef tanb
1042 
1043     hide_t = timer_gettick() + 5000;
1044 
1045     //map to current user settings
1046     assert(keyboardDeviceID >= 0);
1047     keystate[pc(SDID_MOVEUP)] = touchstates[SDID_MOVEUP];
1048     keystate[pc(SDID_MOVEDOWN)] = touchstates[SDID_MOVEDOWN];
1049     keystate[pc(SDID_MOVELEFT)] = touchstates[SDID_MOVELEFT];
1050     keystate[pc(SDID_MOVERIGHT)] = touchstates[SDID_MOVERIGHT];
1051     keystate[pc(SDID_ATTACK)] = touchstates[SDID_ATTACK];
1052     keystate[pc(SDID_ATTACK2)] = touchstates[SDID_ATTACK2];
1053     keystate[pc(SDID_ATTACK3)] = touchstates[SDID_ATTACK3];
1054     keystate[pc(SDID_ATTACK4)] = touchstates[SDID_ATTACK4];
1055     keystate[pc(SDID_JUMP)] = touchstates[SDID_JUMP];
1056     keystate[pc(SDID_SPECIAL)] = touchstates[SDID_SPECIAL];
1057     keystate[pc(SDID_START)] = touchstates[SDID_START];
1058     keystate[pc(SDID_SCREENSHOT)] = touchstates[SDID_SCREENSHOT];
1059     keystate[pc(SDID_SCREENSHOT)] = touchstates[SDID_SCREENSHOT];
1060     keystate[pc(SDID_ESC)] = touchstates[SDID_ESC];
1061 
1062     #undef pc
1063 }
1064 
is_touch_area(float x,float y)1065 int is_touch_area(float x, float y)
1066 {
1067     int j;
1068     float tx, ty, tr;
1069     float r[MAXTOUCHB];
1070     float dirx, diry, circlea, circleb, tan;
1071 
1072     for(j=0; j<MAXTOUCHB; j++)
1073     {
1074         r[j] = br[j]*br[j]*(1.5*1.5);
1075     }
1076     dirx = (bx[SDID_MOVERIGHT]+bx[SDID_MOVELEFT])/2.0;
1077     diry = (by[SDID_MOVEUP]+by[SDID_MOVEDOWN])/2.0;
1078     circlea = bx[SDID_MOVERIGHT]-dirx-br[SDID_MOVEUP];
1079     circleb = bx[SDID_MOVERIGHT]-dirx+br[SDID_MOVEUP]*1.5;
1080     circlea *= circlea;
1081     circleb *= circleb;
1082     #define tana 0.577350f
1083     #define tanb 1.732051f
1084     tx = x-dirx;
1085     ty = y-diry;
1086     tr = tx*tx + ty*ty;
1087     //direction button logic is different, check a ring instead of individual buttons
1088     if(tr>circlea && tr<=circleb)
1089     {
1090         if(tx<0)
1091         {
1092             tan = ty/tx;
1093             if(tan>=-tana && tan<=tana)
1094             {
1095                 return 1;
1096             }
1097             else if(tan<-tanb)
1098             {
1099                 return 1;
1100             }
1101             else if(tan>tanb)
1102             {
1103                 return 1;
1104             }
1105             else if(ty<0)
1106             {
1107                 return 1;
1108             }
1109             else
1110             {
1111                 return 1;
1112             }
1113         }
1114         else if(tx>0)
1115         {
1116             tan = ty/tx;
1117             if(tan>=-tana && tan<=tana)
1118             {
1119                 return 1;
1120             }
1121             else if(tan<-tanb)
1122             {
1123                 return 1;
1124             }
1125             else if(tan>tanb)
1126             {
1127                 return 1;
1128             }
1129             else if(ty<0)
1130             {
1131                 return 1;
1132             }
1133             else
1134             {
1135                 return 1;
1136             }
1137         }
1138         else
1139         {
1140             if(ty>0)
1141             {
1142                 return 1;
1143             }
1144             else
1145             {
1146                 return 1;
1147             }
1148         }
1149     }
1150     //rest buttons
1151     for(j=0; j<MAXTOUCHB; j++)
1152     {
1153         if(j==SDID_MOVERIGHT || j==SDID_MOVEUP ||
1154             j==SDID_MOVELEFT || j==SDID_MOVEDOWN)
1155             continue;
1156         tx = x-bx[j];
1157         ty = y-by[j];
1158         tr = tx*tx + ty*ty;
1159         if(tr<=r[j])
1160         {
1161             return 1;
1162         }
1163     }
1164     #undef tana
1165     #undef tanb
1166 
1167     return 0;
1168 }
1169 #endif
1170 
1171 #define MAPPINGS_FILE_SENTINEL 0x9cf232d4
1172 
control_loadmappings(const char * filename)1173 bool control_loadmappings(const char *filename)
1174 {
1175     FILE *fp = fopen(filename, "rb");
1176     if (!fp)
1177     {
1178         return false;
1179     }
1180 
1181     clear_saved_mappings();
1182 
1183     while (!feof(fp) && !ferror(fp))
1184     {
1185         char name[CONTROL_DEVICE_NAME_SIZE];
1186 		int *mapping = malloc(SDID_COUNT * sizeof(int));
1187 		int sentinel;
1188         if (fread(name, 1, sizeof(name), fp) != sizeof(name) ||
1189             fread(mapping, sizeof(int), SDID_COUNT, fp) != SDID_COUNT ||
1190             fread(&sentinel, sizeof(int), 1, fp) != 1)
1191         {
1192             free(mapping);
1193             break;
1194         }
1195         else if (sentinel != MAPPINGS_FILE_SENTINEL)
1196         {
1197             free(mapping);
1198             fclose(fp);
1199             return false;
1200         }
1201 
1202         name[sizeof(name)-1] = '\0'; // just in case
1203         printf("Loaded mapping for %s\n", name);
1204         List_InsertAfter(&savedMappings, mapping, name);
1205     }
1206 
1207     fclose(fp);
1208 
1209     // update all current device mappings with the newly loaded mappings
1210     for (int i = 0; i < MAX_DEVICES; i++)
1211     {
1212         if (devices[i].deviceType != DEVICE_TYPE_NONE)
1213         {
1214             load_from_saved_mapping(i);
1215         }
1216     }
1217 
1218     return true;
1219 }
1220 
control_savemappings(const char * filename)1221 bool control_savemappings(const char *filename)
1222 {
1223     // update savedMappings with all current device mappings
1224     for (int i = 0; i < MAX_DEVICES; i++)
1225     {
1226         if (devices[i].deviceType != DEVICE_TYPE_NONE)
1227         {
1228             update_saved_mapping(i);
1229         }
1230     }
1231 
1232     FILE *fp = fopen(filename, "wb");
1233     if (!fp)
1234     {
1235         return false;
1236     }
1237 
1238     int numMappings = List_GetSize(&savedMappings);
1239 	List_Reset(&savedMappings);
1240 	for (int i = 0; i < numMappings; i++)
1241 	{
1242 		char name[CONTROL_DEVICE_NAME_SIZE];
1243 		snprintf(name, sizeof(name), "%s", List_GetName(&savedMappings));
1244 		int *mapping = List_Retrieve(&savedMappings);
1245 		const int sentinel = MAPPINGS_FILE_SENTINEL;
1246         if (fwrite(name, 1, sizeof(name), fp) != sizeof(name) ||
1247             fwrite(mapping, sizeof(int), SDID_COUNT, fp) != SDID_COUNT ||
1248             fwrite(&sentinel, sizeof(int), 1, fp) != 1)
1249         {
1250             fclose(fp);
1251             return false;
1252         }
1253 
1254         List_GotoNext(&savedMappings);
1255     }
1256 
1257     fclose(fp);
1258     return true;
1259 }
1260 
control_clearmappings()1261 void control_clearmappings()
1262 {
1263     clear_saved_mappings();
1264 
1265     for (int i = 0; i < MAX_DEVICES; i++)
1266     {
1267         if (devices[i].deviceType != DEVICE_TYPE_NONE)
1268         {
1269             control_resetmappings(i);
1270         }
1271     }
1272 }
1273 
1274