Mercurial > repos > blastem
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 } |