comparison render_sdl.c @ 1187:6a4503fad67e

Initial support for using SDL2 game controller mapping functionality
author Michael Pavone <pavone@retrodev.com>
date Sun, 22 Jan 2017 16:23:59 -0800
parents b1147418254a
children 1ad0ec7e3939
comparison
equal deleted inserted replaced
1186:110251ea369e 1187:6a4503fad67e
109 SDL_UnlockMutex(audio_mutex); 109 SDL_UnlockMutex(audio_mutex);
110 SDL_CloseAudio(); 110 SDL_CloseAudio();
111 } 111 }
112 112
113 static SDL_Joystick * joysticks[MAX_JOYSTICKS]; 113 static SDL_Joystick * joysticks[MAX_JOYSTICKS];
114 static int joystick_sdl_index[MAX_JOYSTICKS];
114 115
115 int render_width() 116 int render_width()
116 { 117 {
117 return main_width; 118 return main_width;
118 } 119 }
269 static uint32_t overscan_bot[NUM_VID_STD] = {1, 17}; 270 static uint32_t overscan_bot[NUM_VID_STD] = {1, 17};
270 static vid_std video_standard = VID_NTSC; 271 static vid_std video_standard = VID_NTSC;
271 static char *vid_std_names[NUM_VID_STD] = {"ntsc", "pal"}; 272 static char *vid_std_names[NUM_VID_STD] = {"ntsc", "pal"};
272 void render_init(int width, int height, char * title, uint8_t fullscreen) 273 void render_init(int width, int height, char * title, uint8_t fullscreen)
273 { 274 {
274 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { 275 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {
275 fatal_error("Unable to init SDL: %s\n", SDL_GetError()); 276 fatal_error("Unable to init SDL: %s\n", SDL_GetError());
276 } 277 }
277 atexit(SDL_Quit); 278 atexit(SDL_Quit);
278 printf("width: %d, height: %d\n", width, height); 279 printf("width: %d, height: %d\n", width, height);
279 280
622 if (!joysticks[i]) { 623 if (!joysticks[i]) {
623 return i; 624 return i;
624 } 625 }
625 } 626 }
626 return -1; 627 return -1;
628 }
629
630 int32_t render_translate_input_name(int32_t controller, char *name)
631 {
632 static tern_node *button_lookup;
633 if (controller > MAX_JOYSTICKS || !joysticks[controller]) {
634 return RENDER_NOT_PLUGGED_IN;
635 }
636
637 if (!SDL_IsGameController(joystick_sdl_index[controller])) {
638 return RENDER_NOT_MAPPED;
639 }
640
641 if (!button_lookup) {
642 for (int i = SDL_CONTROLLER_BUTTON_A; i < SDL_CONTROLLER_BUTTON_MAX; i++)
643 {
644 button_lookup = tern_insert_int(button_lookup, SDL_GameControllerGetStringForButton(i), i);
645 }
646 //alternative Playstation-style names
647 button_lookup = tern_insert_int(button_lookup, "cross", SDL_CONTROLLER_BUTTON_A);
648 button_lookup = tern_insert_int(button_lookup, "circle", SDL_CONTROLLER_BUTTON_B);
649 button_lookup = tern_insert_int(button_lookup, "square", SDL_CONTROLLER_BUTTON_X);
650 button_lookup = tern_insert_int(button_lookup, "triangle", SDL_CONTROLLER_BUTTON_Y);
651 button_lookup = tern_insert_int(button_lookup, "share", SDL_CONTROLLER_BUTTON_BACK);
652 button_lookup = tern_insert_int(button_lookup, "select", SDL_CONTROLLER_BUTTON_BACK);
653 button_lookup = tern_insert_int(button_lookup, "options", SDL_CONTROLLER_BUTTON_START);
654 button_lookup = tern_insert_int(button_lookup, "l1", SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
655 button_lookup = tern_insert_int(button_lookup, "r1", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
656 }
657 intptr_t sdl_button = tern_find_int(button_lookup, name, SDL_CONTROLLER_BUTTON_INVALID);
658 if (sdl_button == SDL_CONTROLLER_BUTTON_INVALID) {
659 return RENDER_INVALID_NAME;
660 }
661 SDL_GameController *control = SDL_GameControllerOpen(joystick_sdl_index[controller]);
662 if (!control) {
663 warning("Failed to open game controller %d: %s\n", controller, SDL_GetError());
664 return RENDER_NOT_PLUGGED_IN;
665 }
666 SDL_GameControllerButtonBind cbind = SDL_GameControllerGetBindForButton(control, sdl_button);
667 SDL_GameControllerClose(control);
668 switch (cbind.bindType)
669 {
670 case SDL_CONTROLLER_BINDTYPE_BUTTON:
671 return cbind.value.button;
672 case SDL_CONTROLLER_BINDTYPE_AXIS:
673 return RENDER_AXIS_BIT | cbind.value.axis;
674 case SDL_CONTROLLER_BINDTYPE_HAT:
675 return RENDER_DPAD_BIT | (cbind.value.hat.hat << 4) | cbind.value.hat.hat_mask;
676 }
677 return RENDER_NOT_MAPPED;
678 }
679
680 int32_t render_dpad_part(int32_t input)
681 {
682 return input >> 4 & 0x7FFFFF;
683 }
684
685 uint8_t render_direction_part(int32_t input)
686 {
687 return input & 0xF;
627 } 688 }
628 689
629 static uint8_t scancode_map[SDL_NUM_SCANCODES] = { 690 static uint8_t scancode_map[SDL_NUM_SCANCODES] = {
630 [SDL_SCANCODE_A] = 0x1C, 691 [SDL_SCANCODE_A] = 0x1C,
631 [SDL_SCANCODE_B] = 0x32, 692 [SDL_SCANCODE_B] = 0x32,
751 case SDL_JOYDEVICEADDED: 812 case SDL_JOYDEVICEADDED:
752 if (event->jdevice.which < MAX_JOYSTICKS) { 813 if (event->jdevice.which < MAX_JOYSTICKS) {
753 int index = lowest_unused_joystick_index(); 814 int index = lowest_unused_joystick_index();
754 if (index >= 0) { 815 if (index >= 0) {
755 SDL_Joystick * joy = joysticks[index] = SDL_JoystickOpen(event->jdevice.which); 816 SDL_Joystick * joy = joysticks[index] = SDL_JoystickOpen(event->jdevice.which);
817 joystick_sdl_index[index] = event->jdevice.which;
756 if (joy) { 818 if (joy) {
757 printf("Joystick %d added: %s\n", index, SDL_JoystickName(joy)); 819 printf("Joystick %d added: %s\n", index, SDL_JoystickName(joy));
758 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); 820 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
759 } 821 }
760 } 822 }