| @@ -3,27 +3,50 @@ | |||||
| #include "input.h" | #include "input.h" | ||||
| static int filter(void*, SDL_Event* event) { | |||||
| static SDL_GameController* sdl_find_gamepad() { | |||||
| int i = SDL_NumJoysticks() - 1; | |||||
| for ( ; i >= 0 && !SDL_IsGameController(i); --i); | |||||
| return (i < 0 ? NULL : SDL_GameControllerOpen(i)); | |||||
| } | |||||
| static void sdl_lose_gamepad(void* data) { | |||||
| SDL_GameController* gamepad = (SDL_GameController*)data; | |||||
| if (NULL != gamepad) SDL_GameControllerClose(gamepad); | |||||
| } | |||||
| static int sdl_match_gamepad(SDL_JoystickID id, void* data) { | |||||
| SDL_GameController* gamepad = (SDL_GameController*)data; | |||||
| return ( SDL_JoystickInstanceID( | |||||
| SDL_GameControllerGetJoystick(gamepad)) | |||||
| == id); | |||||
| } | |||||
| static int sdl_event_filter(void*, SDL_Event* event) { | |||||
| return ( SDL_QUIT == event->type || | return ( SDL_QUIT == event->type || | ||||
| SDL_KEYDOWN == event->type || | SDL_KEYDOWN == event->type || | ||||
| SDL_KEYUP == event->type | |||||
| SDL_KEYUP == event->type || | |||||
| SDL_CONTROLLERDEVICEADDED == event->type || | |||||
| SDL_CONTROLLERDEVICEREMOVED == event->type | |||||
| ); | ); | ||||
| } | } | ||||
| static int sdl_input_init(nes_Input_Reader*) { | |||||
| int status = SDL_Init(SDL_INIT_EVENTS); | |||||
| static int sdl_input_init(nes_Input_Reader* reader) { | |||||
| int status = SDL_Init(SDL_INIT_EVENTS | | |||||
| SDL_INIT_GAMECONTROLLER); | |||||
| if (status == 0) { | if (status == 0) { | ||||
| SDL_SetEventFilter(filter, NULL); | |||||
| reader->data = sdl_find_gamepad(); | |||||
| SDL_SetEventFilter(sdl_event_filter, NULL); | |||||
| } | } | ||||
| return status; | return status; | ||||
| } | } | ||||
| static void sdl_input_done(nes_Input_Reader*) {} | |||||
| static void sdl_input_done(nes_Input_Reader* input) { | |||||
| sdl_lose_gamepad(input->data); | |||||
| } | |||||
| static const int keycodes[nes_controller_num_buttons] = { | |||||
| static const int sdl_keycodes[nes_controller_num_buttons] = { | |||||
| SDLK_a, | SDLK_a, | ||||
| SDLK_s, | SDLK_s, | ||||
| SDLK_q, | SDLK_q, | ||||
| @@ -36,11 +59,23 @@ static const int keycodes[nes_controller_num_buttons] = { | |||||
| static int button_index(int keycode) { | static int button_index(int keycode) { | ||||
| int index = nes_controller_num_buttons - 1; | int index = nes_controller_num_buttons - 1; | ||||
| for ( ; index > 0 && keycode != keycodes[index]; --index); | |||||
| for ( ; index > 0 && keycode != sdl_keycodes[index]; --index); | |||||
| return index; | return index; | ||||
| } | } | ||||
| static int sdl_input_update(nes_Input_Reader*, nes_input* input) { | |||||
| static const int sdl_gamepad_buttons[nes_controller_num_buttons] = { | |||||
| SDL_CONTROLLER_BUTTON_A, | |||||
| SDL_CONTROLLER_BUTTON_B, | |||||
| SDL_CONTROLLER_BUTTON_BACK, | |||||
| SDL_CONTROLLER_BUTTON_START, | |||||
| SDL_CONTROLLER_BUTTON_DPAD_UP, | |||||
| SDL_CONTROLLER_BUTTON_DPAD_DOWN, | |||||
| SDL_CONTROLLER_BUTTON_DPAD_LEFT, | |||||
| SDL_CONTROLLER_BUTTON_DPAD_RIGHT, | |||||
| }; | |||||
| static int sdl_input_update(nes_Input_Reader* reader, | |||||
| nes_input* input) { | |||||
| int status = 0; | int status = 0; | ||||
| SDL_Event event = {0}; | SDL_Event event = {0}; | ||||
| @@ -58,6 +93,31 @@ static int sdl_input_update(nes_Input_Reader*, nes_input* input) { | |||||
| } else { | } else { | ||||
| input->controllers[0].buttons &= ~mask; | input->controllers[0].buttons &= ~mask; | ||||
| } | } | ||||
| } else if (SDL_CONTROLLERDEVICEADDED == event.type) { | |||||
| if (NULL == reader->data) { | |||||
| reader->data = sdl_find_gamepad(); | |||||
| } | |||||
| } else if (SDL_CONTROLLERDEVICEREMOVED == event.type) { | |||||
| if (sdl_match_gamepad(event.cdevice.which, | |||||
| reader->data)) { | |||||
| sdl_lose_gamepad(reader->data); | |||||
| reader->data = sdl_find_gamepad(); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (NULL != reader->data) { | |||||
| SDL_GameController* gamepad = (SDL_GameController*)reader->data; | |||||
| for (int b = 0; b < nes_controller_num_buttons; ++b) { | |||||
| if (SDL_GameControllerGetButton( | |||||
| gamepad, sdl_gamepad_buttons[b])) { | |||||
| input->controllers[0].buttons |= (1 << b); | |||||
| } else { | |||||
| input->controllers[0].buttons &= ~(1 << b); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||