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