// Copyright 2015 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include "input_common/sdl_input/sdl_input.h" #include "common/key_map.h" namespace InputCommon { SDLController::SDLController() { device_name = "SDL2::NONE"; jpad = nullptr; index = 0; controller.circle_pad_x = 0; controller.circle_pad_y = 0; controller.touch_screen_x = 0; controller.touch_screen_y = 0; activated = Init(); } SDLController::~SDLController() { Shutdown(); } bool SDLController::Init() { //Attempt to initialize SDL with joystick only if (SDL_Init(SDL_INIT_JOYSTICK) != 0) { return false; } //Attempt to open joystick with SDL //TODO - Use DiscoverDevice to generate a list of available joysticks, then open the correct index jpad = SDL_JoystickOpen(index); if (jpad == nullptr) { return false; } device_name = SDL_JoystickNameForIndex(index); //If joystick successfully opened, load up keymap from input configuration //TODO - Make it NOT hardcoded joypad_id = KeyMap::NewDeviceId(); SetupKeyMaps(); //TODO - Make it NOT hardcoded SetDeadZone(8000); return true; } void SDLController::DiscoverDevices() {} void SDLController::Shutdown() { //Attempt to close joystick with SDL if (jpad != nullptr) { SDL_JoystickClose(jpad); } } void SDLController::Poll() { if (SDL_PollEvent(&input_event)) { if (input_event.type == SDL_JOYBUTTONDOWN || input_event.type == SDL_JOYBUTTONUP || input_event.type == SDL_JOYAXISMOTION || input_event.type == SDL_JOYHATMOTION) { ProcessInput(); } } } void SDLController::ProcessInput() { //Use a unique id for joystick input int pad_id = 0; int val = 0; //Generate the id based on input from an event switch (input_event.type) { //Joystick button press events case SDL_JOYBUTTONDOWN: pad_id = 100; pad_id += input_event.jbutton.button; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id, joypad_id}).hex; break; //Joystick button release events case SDL_JOYBUTTONUP: pad_id = 100; pad_id += input_event.jbutton.button; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; break; //Joystick axis motion events case SDL_JOYAXISMOTION: pad_id = 200; pad_id += (input_event.jaxis.axis * 2); val = input_event.jaxis.value; if (val > 0) { pad_id += 1; } //If analog input is beyond dead zone, set it if (CheckDeadZone(val)) { controller.pad_state.hex |= KeyMap::GetPadKey({pad_id, joypad_id}).hex; } else { controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; } //Release opposite axis if (pad_id % 2 == 0) { controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; } else { controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id-1, joypad_id}).hex; } break; //Joystick hat motion events case SDL_JOYHATMOTION: pad_id = 300; pad_id += input_event.jhat.hat * 4; switch (input_event.jhat.value) { case SDL_HAT_CENTERED: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_LEFT: controller.pad_state.hex |= KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_LEFTUP: controller.pad_state.hex |= KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_LEFTDOWN: controller.pad_state.hex |= KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_RIGHT: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_RIGHTUP: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_RIGHTDOWN: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_UP: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; case SDL_HAT_DOWN: controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+1, joypad_id}).hex; controller.pad_state.hex &= ~KeyMap::GetPadKey({pad_id+2, joypad_id}).hex; controller.pad_state.hex |= KeyMap::GetPadKey({pad_id+3, joypad_id}).hex; break; } break; } } void SDLController::SetupKeyMaps() { KeyMap::SetKeyMapping({100, joypad_id}, Service::HID::PAD_A); KeyMap::SetKeyMapping({101, joypad_id}, Service::HID::PAD_B); KeyMap::SetKeyMapping({102, joypad_id}, Service::HID::PAD_X); KeyMap::SetKeyMapping({103, joypad_id}, Service::HID::PAD_Y); KeyMap::SetKeyMapping({104, joypad_id}, Service::HID::PAD_R); KeyMap::SetKeyMapping({105, joypad_id}, Service::HID::PAD_L); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_ZL); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_ZR); KeyMap::SetKeyMapping({107, joypad_id}, Service::HID::PAD_START); KeyMap::SetKeyMapping({106, joypad_id}, Service::HID::PAD_SELECT); KeyMap::SetKeyMapping({300, joypad_id}, Service::HID::PAD_LEFT); KeyMap::SetKeyMapping({301, joypad_id}, Service::HID::PAD_RIGHT); KeyMap::SetKeyMapping({302, joypad_id}, Service::HID::PAD_UP); KeyMap::SetKeyMapping({303, joypad_id}, Service::HID::PAD_DOWN); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_C_LEFT); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_C_RIGHT); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_C_UP); KeyMap::SetKeyMapping({0, joypad_id}, Service::HID::PAD_C_DOWN); KeyMap::SetKeyMapping({200, joypad_id}, Service::HID::PAD_CIRCLE_LEFT); KeyMap::SetKeyMapping({201, joypad_id}, Service::HID::PAD_CIRCLE_RIGHT); KeyMap::SetKeyMapping({202, joypad_id}, Service::HID::PAD_CIRCLE_UP); KeyMap::SetKeyMapping({203, joypad_id}, Service::HID::PAD_CIRCLE_DOWN); } void SDLController::SetDeadZone(int range) { dead_zone = range; } bool SDLController::CheckDeadZone(int range) { if ((range < -dead_zone) || (range > dead_zone)) { return true; } else if ((range > -dead_zone) && (range < dead_zone)) { return false; } } }//namespace