| @@ -3,27 +3,50 @@ | |||
| #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 || | |||
| 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) { | |||
| SDL_SetEventFilter(filter, NULL); | |||
| reader->data = sdl_find_gamepad(); | |||
| SDL_SetEventFilter(sdl_event_filter, NULL); | |||
| } | |||
| 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_s, | |||
| SDLK_q, | |||
| @@ -36,11 +59,23 @@ static const int keycodes[nes_controller_num_buttons] = { | |||
| static int button_index(int keycode) { | |||
| int index = nes_controller_num_buttons - 1; | |||
| for ( ; index > 0 && keycode != keycodes[index]; --index); | |||
| for ( ; index > 0 && keycode != sdl_keycodes[index]; --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; | |||
| SDL_Event event = {0}; | |||
| @@ -58,6 +93,31 @@ static int sdl_input_update(nes_Input_Reader*, nes_input* input) { | |||
| } else { | |||
| 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); | |||
| } | |||
| } | |||
| } | |||