controllermap.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. Copyright (C) 1997-2013 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 void
  83. DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
  84. {
  85. const SDL_Rect area = { x, y, w, h };
  86. SDL_RenderFillRect(r, &area);
  87. }
  88. static SDL_bool
  89. WatchJoystick(SDL_Joystick * joystick)
  90. {
  91. SDL_Window *window = NULL;
  92. SDL_Renderer *screen = NULL;
  93. SDL_Texture *target, *background, *button, *axis, *marker;
  94. const char *name = NULL;
  95. SDL_bool retval = SDL_FALSE;
  96. SDL_bool done = SDL_FALSE, next=SDL_FALSE;
  97. SDL_Event event;
  98. SDL_Rect dst;
  99. int i, s, _s;
  100. Uint8 alpha=200, alpha_step = -1;
  101. Uint32 alpha_ticks;
  102. char mapping[4096], temp[4096];
  103. MappingStep *step;
  104. MappingStep steps[] = {
  105. {342, 132, 0.0, MARKER_BUTTON, "x", -1, -1, -1, -1, ""},
  106. {387, 167, 0.0, MARKER_BUTTON, "a", -1, -1, -1, -1, ""},
  107. {431, 132, 0.0, MARKER_BUTTON, "b", -1, -1, -1, -1, ""},
  108. {389, 101, 0.0, MARKER_BUTTON, "y", -1, -1, -1, -1, ""},
  109. {174, 132, 0.0, MARKER_BUTTON, "back", -1, -1, -1, -1, ""},
  110. {233, 132, 0.0, MARKER_BUTTON, "guide", -1, -1, -1, -1, ""},
  111. {289, 132, 0.0, MARKER_BUTTON, "start", -1, -1, -1, -1, ""},
  112. {116, 217, 0.0, MARKER_BUTTON, "dpleft", -1, -1, -1, -1, ""},
  113. {154, 249, 0.0, MARKER_BUTTON, "dpdown", -1, -1, -1, -1, ""},
  114. {186, 217, 0.0, MARKER_BUTTON, "dpright", -1, -1, -1, -1, ""},
  115. {154, 188, 0.0, MARKER_BUTTON, "dpup", -1, -1, -1, -1, ""},
  116. {77, 40, 0.0, MARKER_BUTTON, "leftshoulder", -1, -1, -1, -1, ""},
  117. {91, 0, 0.0, MARKER_BUTTON, "lefttrigger", -1, -1, -1, -1, ""},
  118. {396, 36, 0.0, MARKER_BUTTON, "rightshoulder", -1, -1, -1, -1, ""},
  119. {375, 0, 0.0, MARKER_BUTTON, "righttrigger", -1, -1, -1, -1, ""},
  120. {75, 154, 0.0, MARKER_BUTTON, "leftstick", -1, -1, -1, -1, ""},
  121. {305, 230, 0.0, MARKER_BUTTON, "rightstick", -1, -1, -1, -1, ""},
  122. {75, 154, 0.0, MARKER_AXIS, "leftx", -1, -1, -1, -1, ""},
  123. {75, 154, 90.0, MARKER_AXIS, "lefty", -1, -1, -1, -1, ""},
  124. {305, 230, 0.0, MARKER_AXIS, "rightx", -1, -1, -1, -1, ""},
  125. {305, 230, 90.0, MARKER_AXIS, "righty", -1, -1, -1, -1, ""},
  126. };
  127. /* Create a window to display joystick axis position */
  128. window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
  129. SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
  130. SCREEN_HEIGHT, 0);
  131. if (window == NULL) {
  132. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
  133. return SDL_FALSE;
  134. }
  135. screen = SDL_CreateRenderer(window, -1, 0);
  136. if (screen == NULL) {
  137. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
  138. SDL_DestroyWindow(window);
  139. return SDL_FALSE;
  140. }
  141. target = SDL_CreateTexture(screen, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, MAP_WIDTH, MAP_HEIGHT);
  142. background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
  143. button = LoadTexture(screen, "button.bmp", SDL_TRUE);
  144. axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
  145. SDL_RaiseWindow(window);
  146. /* Print info about the joystick we are watching */
  147. name = SDL_JoystickName(joystick);
  148. SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
  149. name ? name : "Unknown Joystick");
  150. SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
  151. SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
  152. SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
  153. SDL_Log("\n\n\
  154. ====================================================================================\n\
  155. Press the buttons on your controller when indicated\n\
  156. (Your controller may look different than the picture)\n\
  157. If you want to correct a mistake, press backspace or the back button on your device\n\
  158. To exit, press ESC\n\
  159. ====================================================================================\n");
  160. /* Initialize mapping with GUID and name */
  161. SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, SDL_arraysize(temp));
  162. SDL_snprintf(mapping, SDL_arraysize(mapping), "%s,%s,platform:%s,",
  163. temp, name ? name : "Unknown Joystick", SDL_GetPlatform());
  164. /* Loop, getting joystick events! */
  165. for(s=0; s<SDL_arraysize(steps) && !done;) {
  166. /* blank screen, set up for drawing this frame. */
  167. step = &steps[s];
  168. SDL_strlcpy(step->mapping, mapping, SDL_arraysize(step->mapping));
  169. step->axis = -1;
  170. step->button = -1;
  171. step->hat = -1;
  172. step->hat_value = -1;
  173. SDL_SetClipboardText("TESTING TESTING 123");
  174. switch(step->marker) {
  175. case MARKER_AXIS:
  176. marker = axis;
  177. break;
  178. case MARKER_BUTTON:
  179. marker = button;
  180. break;
  181. default:
  182. break;
  183. }
  184. dst.x = step->x;
  185. dst.y = step->y;
  186. SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
  187. next=SDL_FALSE;
  188. while (!done && !next) {
  189. if (SDL_GetTicks() - alpha_ticks > 5) {
  190. alpha_ticks = SDL_GetTicks();
  191. alpha += alpha_step;
  192. if (alpha == 255) {
  193. alpha_step = -1;
  194. }
  195. if (alpha < 128) {
  196. alpha_step = 1;
  197. }
  198. }
  199. SDL_SetRenderTarget(screen, target);
  200. SDL_RenderCopy(screen, background, NULL, NULL);
  201. SDL_SetTextureAlphaMod(marker, alpha);
  202. SDL_SetTextureColorMod(marker, 10, 255, 21);
  203. SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, 0);
  204. SDL_SetRenderTarget(screen, NULL);
  205. SDL_RenderCopy(screen, target, NULL, NULL);
  206. SDL_RenderPresent(screen);
  207. if (SDL_PollEvent(&event)) {
  208. switch (event.type) {
  209. case SDL_JOYAXISMOTION:
  210. if (event.jaxis.value > 20000 || event.jaxis.value < -20000) {
  211. for (_s = 0; _s < s; _s++) {
  212. if (steps[_s].axis == event.jaxis.axis) {
  213. break;
  214. }
  215. }
  216. if (_s == s) {
  217. step->axis = event.jaxis.axis;
  218. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  219. SDL_snprintf(temp, SDL_arraysize(temp), ":a%u,", event.jaxis.axis);
  220. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  221. s++;
  222. next=SDL_TRUE;
  223. }
  224. }
  225. break;
  226. case SDL_JOYHATMOTION:
  227. for (_s = 0; _s < s; _s++) {
  228. if (steps[_s].hat == event.jhat.hat && steps[_s].hat_value == event.jhat.value) {
  229. break;
  230. }
  231. }
  232. if (_s == s) {
  233. step->hat = event.jhat.hat;
  234. step->hat_value = event.jhat.value;
  235. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  236. SDL_snprintf(temp, SDL_arraysize(temp), ":h%u.%u,", event.jhat.hat, event.jhat.value );
  237. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  238. s++;
  239. next=SDL_TRUE;
  240. }
  241. break;
  242. case SDL_JOYBALLMOTION:
  243. break;
  244. case SDL_JOYBUTTONUP:
  245. for (_s = 0; _s < s; _s++) {
  246. if (steps[_s].button == event.jbutton.button) {
  247. break;
  248. }
  249. }
  250. if (_s == s) {
  251. step->button = event.jbutton.button;
  252. SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
  253. SDL_snprintf(temp, SDL_arraysize(temp), ":b%u,", event.jbutton.button);
  254. SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
  255. s++;
  256. next=SDL_TRUE;
  257. }
  258. break;
  259. case SDL_KEYDOWN:
  260. if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
  261. /* Undo! */
  262. if (s > 0) {
  263. SDL_strlcpy(mapping, step->mapping, SDL_arraysize(step->mapping));
  264. s--;
  265. next = SDL_TRUE;
  266. }
  267. break;
  268. }
  269. if ((event.key.keysym.sym != SDLK_ESCAPE)) {
  270. break;
  271. }
  272. /* Fall through to signal quit */
  273. case SDL_FINGERDOWN:
  274. case SDL_MOUSEBUTTONDOWN:
  275. case SDL_QUIT:
  276. done = SDL_TRUE;
  277. break;
  278. default:
  279. break;
  280. }
  281. }
  282. }
  283. }
  284. if (s == SDL_arraysize(steps) ) {
  285. SDL_Log("Mapping:\n\n%s\n\n", mapping);
  286. /* Print to stdout as well so the user can cat the output somewhere */
  287. printf("%s\n", mapping);
  288. }
  289. while(SDL_PollEvent(&event)) {};
  290. SDL_DestroyRenderer(screen);
  291. SDL_DestroyWindow(window);
  292. return retval;
  293. }
  294. int
  295. main(int argc, char *argv[])
  296. {
  297. const char *name;
  298. int i;
  299. SDL_Joystick *joystick;
  300. /* Enable standard application logging */
  301. SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  302. /* Initialize SDL (Note: video is required to start event loop) */
  303. if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
  304. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
  305. exit(1);
  306. }
  307. /* Print information about the joysticks */
  308. SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
  309. for (i = 0; i < SDL_NumJoysticks(); ++i) {
  310. name = SDL_JoystickNameForIndex(i);
  311. SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
  312. joystick = SDL_JoystickOpen(i);
  313. if (joystick == NULL) {
  314. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
  315. SDL_GetError());
  316. } else {
  317. char guid[64];
  318. SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
  319. guid, sizeof (guid));
  320. SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick));
  321. SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick));
  322. SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick));
  323. SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick));
  324. SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
  325. SDL_Log(" guid: %s\n", guid);
  326. SDL_JoystickClose(joystick);
  327. }
  328. }
  329. #ifdef ANDROID
  330. if (SDL_NumJoysticks() > 0) {
  331. #else
  332. if (argv[1]) {
  333. #endif
  334. SDL_bool reportederror = SDL_FALSE;
  335. SDL_bool keepGoing = SDL_TRUE;
  336. SDL_Event event;
  337. #ifdef ANDROID
  338. joystick = SDL_JoystickOpen(0);
  339. #else
  340. joystick = SDL_JoystickOpen(atoi(argv[1]));
  341. #endif
  342. while ( keepGoing ) {
  343. if (joystick == NULL) {
  344. if ( !reportederror ) {
  345. SDL_Log("Couldn't open joystick %d: %s\n", atoi(argv[1]), SDL_GetError());
  346. keepGoing = SDL_FALSE;
  347. reportederror = SDL_TRUE;
  348. }
  349. } else {
  350. reportederror = SDL_FALSE;
  351. keepGoing = WatchJoystick(joystick);
  352. SDL_JoystickClose(joystick);
  353. }
  354. joystick = NULL;
  355. if (keepGoing) {
  356. SDL_Log("Waiting for attach\n");
  357. }
  358. while (keepGoing) {
  359. SDL_WaitEvent(&event);
  360. if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
  361. || (event.type == SDL_MOUSEBUTTONDOWN)) {
  362. keepGoing = SDL_FALSE;
  363. } else if (event.type == SDL_JOYDEVICEADDED) {
  364. joystick = SDL_JoystickOpen(atoi(argv[1]));
  365. break;
  366. }
  367. }
  368. }
  369. }
  370. else {
  371. SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
  372. }
  373. SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  374. #ifdef ANDROID
  375. exit(0);
  376. #else
  377. return 0;
  378. #endif
  379. }
  380. #else
  381. int
  382. main(int argc, char *argv[])
  383. {
  384. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
  385. exit(1);
  386. }
  387. #endif