controllermap.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any damages
  5. arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it
  8. freely.
  9. */
  10. /* Game controller mapping generator */
  11. /* Gabriel Jacobo <gabomdq@gmail.com> */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "SDL.h"
  16. #ifndef SDL_JOYSTICK_DISABLED
  17. #ifdef __IPHONEOS__
  18. #define SCREEN_WIDTH 320
  19. #define SCREEN_HEIGHT 480
  20. #else
  21. #define SCREEN_WIDTH 512
  22. #define SCREEN_HEIGHT 317
  23. #endif
  24. #define MAP_WIDTH 512
  25. #define MAP_HEIGHT 317
  26. #define MARKER_BUTTON 1
  27. #define MARKER_AXIS 2
  28. typedef struct MappingStep
  29. {
  30. int x, y;
  31. double angle;
  32. int marker;
  33. char *field;
  34. int axis, button, hat, hat_value;
  35. char mapping[4096];
  36. }MappingStep;
  37. SDL_Texture *
  38. LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
  39. {
  40. SDL_Surface *temp;
  41. SDL_Texture *texture;
  42. /* Load the sprite image */
  43. temp = SDL_LoadBMP(file);
  44. if (temp == NULL) {
  45. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
  46. return NULL;
  47. }
  48. /* Set transparent pixel as the pixel at (0,0) */
  49. if (transparent) {
  50. if (temp->format->palette) {
  51. SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
  52. } else {
  53. switch (temp->format->BitsPerPixel) {
  54. case 15:
  55. SDL_SetColorKey(temp, SDL_TRUE,
  56. (*(Uint16 *) temp->pixels) & 0x00007FFF);
  57. break;
  58. case 16:
  59. SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
  60. break;
  61. case 24:
  62. SDL_SetColorKey(temp, SDL_TRUE,
  63. (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
  64. break;
  65. case 32:
  66. SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
  67. break;
  68. }
  69. }
  70. }
  71. /* Create textures from the image */
  72. texture = SDL_CreateTextureFromSurface(renderer, temp);
  73. if (!texture) {
  74. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
  75. SDL_FreeSurface(temp);
  76. return NULL;
  77. }
  78. SDL_FreeSurface(temp);
  79. /* We're ready to roll. :) */
  80. return texture;
  81. }
  82. static SDL_bool
  83. WatchJoystick(SDL_Joystick * joystick)
  84. {
  85. SDL_Window *window = NULL;
  86. SDL_Renderer *screen = NULL;
  87. SDL_Texture *background, *button, *axis, *marker;
  88. const char *name = NULL;
  89. SDL_bool retval = SDL_FALSE;
  90. SDL_bool done = SDL_FALSE, next=SDL_FALSE;
  91. SDL_Event event;
  92. SDL_Rect dst;
  93. int s, _s;
  94. Uint8 alpha=200, alpha_step = -1;
  95. Uint32 alpha_ticks;
  96. char mapping[4096], temp[4096];
  97. MappingStep *step;
  98. MappingStep steps[] = {
  99. {342, 132, 0.0, MARKER_BUTTON, "x", -1, -1, -1, -1, ""},
  100. {387, 167, 0.0, MARKER_BUTTON, "a", -1, -1, -1, -1, ""},
  101. {431, 132, 0.0, MARKER_BUTTON, "b", -1, -1, -1, -1, ""},
  102. {389, 101, 0.0, MARKER_BUTTON, "y", -1, -1, -1, -1, ""},
  103. {174, 132, 0.0, MARKER_BUTTON, "back", -1, -1, -1, -1, ""},
  104. {233, 132, 0.0, MARKER_BUTTON, "guide", -1, -1, -1, -1, ""},
  105. {289, 132, 0.0, MARKER_BUTTON, "start", -1, -1, -1, -1, ""},
  106. {116, 217, 0.0, MARKER_BUTTON, "dpleft", -1, -1, -1, -1, ""},
  107. {154, 249, 0.0, MARKER_BUTTON, "dpdown", -1, -1, -1, -1, ""},
  108. {186, 217, 0.0, MARKER_BUTTON, "dpright", -1, -1, -1, -1, ""},
  109. {154, 188, 0.0, MARKER_BUTTON, "dpup", -1, -1, -1, -1, ""},
  110. {77, 40, 0.0, MARKER_BUTTON, "leftshoulder", -1, -1, -1, -1, ""},
  111. {91, 0, 0.0, MARKER_BUTTON, "lefttrigger", -1, -1, -1, -1, ""},
  112. {396, 36, 0.0, MARKER_BUTTON, "rightshoulder", -1, -1, -1, -1, ""},
  113. {375, 0, 0.0, MARKER_BUTTON, "righttrigger", -1, -1, -1, -1, ""},
  114. {75, 154, 0.0, MARKER_BUTTON, "leftstick", -1, -1, -1, -1, ""},
  115. {305, 230, 0.0, MARKER_BUTTON, "rightstick", -1, -1, -1, -1, ""},
  116. {75, 154, 0.0, MARKER_AXIS, "leftx", -1, -1, -1, -1, ""},
  117. {75, 154, 90.0, MARKER_AXIS, "lefty", -1, -1, -1, -1, ""},
  118. {305, 230, 0.0, MARKER_AXIS, "rightx", -1, -1, -1, -1, ""},
  119. {305, 230, 90.0, MARKER_AXIS, "righty", -1, -1, -1, -1, ""},
  120. };
  121. /* Create a window to display joystick axis position */
  122. window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
  123. SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
  124. SCREEN_HEIGHT, 0);
  125. if (window == NULL) {
  126. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
  127. return SDL_FALSE;
  128. }
  129. screen = SDL_CreateRenderer(window, -1, 0);
  130. if (screen == NULL) {
  131. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
  132. SDL_DestroyWindow(window);
  133. return SDL_FALSE;
  134. }
  135. background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
  136. button = LoadTexture(screen, "button.bmp", SDL_TRUE);
  137. axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
  138. SDL_RaiseWindow(window);
  139. /* scale for platforms that don't give you the window size you asked for. */
  140. SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
  141. /* Print info about the joystick we are watching */
  142. name = SDL_JoystickName(joystick);
  143. SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
  144. name ? name : "Unknown Joystick");
  145. SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
  146. SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
  147. SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
  148. SDL_Log("\n\n\
  149. ====================================================================================\n\
  150. Press the buttons on your controller when indicated\n\
  151. (Your controller may look different than the picture)\n\
  152. If you want to correct a mistake, press backspace or the back button on your device\n\
  153. To skip a button, press SPACE or click/touch the screen\n\
  154. To exit, press ESC\n\
  155. ====================================================================================\n");
  156. /* Initialize mapping with GUID and name */
  157. SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, SDL_arraysize(temp));
  158. SDL_snprintf(mapping, SDL_arraysize(mapping), "%s,%s,platform:%s,",
  159. temp, name ? name : "Unknown Joystick", SDL_GetPlatform());
  160. /* Loop, getting joystick events! */
  161. for(s=0; s<SDL_arraysize(steps) && !done;) {
  162. /* blank screen, set up for drawing this frame. */
  163. step = &steps[s];
  164. SDL_strlcpy(step->mapping, mapping, SDL_arraysize(step->mapping));
  165. step->axis = -1;
  166. step->button = -1;
  167. step->hat = -1;
  168. step->hat_value = -1;
  169. SDL_SetClipboardText("TESTING TESTING 123");
  170. switch(step->marker) {
  171. case MARKER_AXIS:
  172. marker = axis;
  173. break;
  174. case MARKER_BUTTON:
  175. marker = button;
  176. break;
  177. default:
  178. break;
  179. }
  180. dst.x = step->x;
  181. dst.y = step->y;
  182. SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
  183. next=SDL_FALSE;
  184. SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
  185. while (!done && !next) {
  186. if (SDL_GetTicks() - alpha_ticks > 5) {
  187. alpha_ticks = SDL_GetTicks();
  188. alpha += alpha_step;
  189. if (alpha == 255) {
  190. alpha_step = -1;
  191. }
  192. if (alpha < 128) {
  193. alpha_step = 1;
  194. }
  195. }
  196. SDL_RenderClear(screen);
  197. SDL_RenderCopy(screen, background, NULL, NULL);
  198. SDL_SetTextureAlphaMod(marker, alpha);
  199. SDL_SetTextureColorMod(marker, 10, 255, 21);
  200. SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, 0);
  201. SDL_RenderPresent(screen);
  202. if (SDL_PollEvent(&event)) {
  203. switch (event.type) {
  204. case SDL_JOYAXISMOTION:
  205. if (event.jaxis.value > 20000 || event.jaxis.value < -20000) {
  206. for (_s = 0; _s < s; _s++) {
  207. if (steps[_s].axis == event.jaxis.axis) {
  208. break;
  209. }
  210. }
  211. if (_s == s) {
  212. step->axis = event.jaxis.axis;
  213. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  214. SDL_snprintf(temp, SDL_arraysize(temp), ":a%u,", event.jaxis.axis);
  215. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  216. s++;
  217. next=SDL_TRUE;
  218. }
  219. }
  220. break;
  221. case SDL_JOYHATMOTION:
  222. for (_s = 0; _s < s; _s++) {
  223. if (steps[_s].hat == event.jhat.hat && steps[_s].hat_value == event.jhat.value) {
  224. break;
  225. }
  226. }
  227. if (_s == s) {
  228. step->hat = event.jhat.hat;
  229. step->hat_value = event.jhat.value;
  230. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  231. SDL_snprintf(temp, SDL_arraysize(temp), ":h%u.%u,", event.jhat.hat, event.jhat.value );
  232. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  233. s++;
  234. next=SDL_TRUE;
  235. }
  236. break;
  237. case SDL_JOYBALLMOTION:
  238. break;
  239. case SDL_JOYBUTTONUP:
  240. for (_s = 0; _s < s; _s++) {
  241. if (steps[_s].button == event.jbutton.button) {
  242. break;
  243. }
  244. }
  245. if (_s == s) {
  246. step->button = event.jbutton.button;
  247. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  248. SDL_snprintf(temp, SDL_arraysize(temp), ":b%u,", event.jbutton.button);
  249. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  250. s++;
  251. next=SDL_TRUE;
  252. }
  253. break;
  254. case SDL_FINGERDOWN:
  255. case SDL_MOUSEBUTTONDOWN:
  256. /* Skip this step */
  257. s++;
  258. next=SDL_TRUE;
  259. break;
  260. case SDL_KEYDOWN:
  261. if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
  262. /* Undo! */
  263. if (s > 0) {
  264. SDL_strlcpy(mapping, step->mapping, SDL_arraysize(step->mapping));
  265. s--;
  266. next = SDL_TRUE;
  267. }
  268. break;
  269. }
  270. if (event.key.keysym.sym == SDLK_SPACE) {
  271. /* Skip this step */
  272. s++;
  273. next=SDL_TRUE;
  274. break;
  275. }
  276. if ((event.key.keysym.sym != SDLK_ESCAPE)) {
  277. break;
  278. }
  279. /* Fall through to signal quit */
  280. case SDL_QUIT:
  281. done = SDL_TRUE;
  282. break;
  283. default:
  284. break;
  285. }
  286. }
  287. }
  288. }
  289. if (s == SDL_arraysize(steps) ) {
  290. SDL_Log("Mapping:\n\n%s\n\n", mapping);
  291. /* Print to stdout as well so the user can cat the output somewhere */
  292. printf("%s\n", mapping);
  293. }
  294. while(SDL_PollEvent(&event)) {};
  295. SDL_DestroyRenderer(screen);
  296. SDL_DestroyWindow(window);
  297. return retval;
  298. }
  299. int
  300. main(int argc, char *argv[])
  301. {
  302. const char *name;
  303. int i;
  304. SDL_Joystick *joystick;
  305. /* Enable standard application logging */
  306. SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  307. /* Initialize SDL (Note: video is required to start event loop) */
  308. if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
  309. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
  310. exit(1);
  311. }
  312. /* Print information about the joysticks */
  313. SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
  314. for (i = 0; i < SDL_NumJoysticks(); ++i) {
  315. name = SDL_JoystickNameForIndex(i);
  316. SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
  317. joystick = SDL_JoystickOpen(i);
  318. if (joystick == NULL) {
  319. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
  320. SDL_GetError());
  321. } else {
  322. char guid[64];
  323. SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
  324. guid, sizeof (guid));
  325. SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick));
  326. SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick));
  327. SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick));
  328. SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick));
  329. SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
  330. SDL_Log(" guid: %s\n", guid);
  331. SDL_JoystickClose(joystick);
  332. }
  333. }
  334. #ifdef ANDROID
  335. if (SDL_NumJoysticks() > 0) {
  336. #else
  337. if (argv[1]) {
  338. #endif
  339. SDL_bool reportederror = SDL_FALSE;
  340. SDL_bool keepGoing = SDL_TRUE;
  341. SDL_Event event;
  342. int device;
  343. #ifdef ANDROID
  344. device = 0;
  345. #else
  346. device = atoi(argv[1]);
  347. #endif
  348. joystick = SDL_JoystickOpen(device);
  349. while ( keepGoing ) {
  350. if (joystick == NULL) {
  351. if ( !reportederror ) {
  352. SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
  353. keepGoing = SDL_FALSE;
  354. reportederror = SDL_TRUE;
  355. }
  356. } else {
  357. reportederror = SDL_FALSE;
  358. keepGoing = WatchJoystick(joystick);
  359. SDL_JoystickClose(joystick);
  360. }
  361. joystick = NULL;
  362. if (keepGoing) {
  363. SDL_Log("Waiting for attach\n");
  364. }
  365. while (keepGoing) {
  366. SDL_WaitEvent(&event);
  367. if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
  368. || (event.type == SDL_MOUSEBUTTONDOWN)) {
  369. keepGoing = SDL_FALSE;
  370. } else if (event.type == SDL_JOYDEVICEADDED) {
  371. joystick = SDL_JoystickOpen(device);
  372. break;
  373. }
  374. }
  375. }
  376. }
  377. else {
  378. SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
  379. }
  380. SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  381. return 0;
  382. }
  383. #else
  384. int
  385. main(int argc, char *argv[])
  386. {
  387. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
  388. exit(1);
  389. }
  390. #endif