diff --git a/core/input/gamepad_device.cpp b/core/input/gamepad_device.cpp index 52c931990..d9734ded5 100644 --- a/core/input/gamepad_device.cpp +++ b/core/input/gamepad_device.cpp @@ -137,7 +137,7 @@ unsigned int GamepadDevice::get_axis_range(u32 axis) { std::string GamepadDevice::make_mapping_filename() { - std::string mapping_file = std::string(api_name()) + "_" + name(); + std::string mapping_file = api_name() + "_" + name(); std::replace(mapping_file.begin(), mapping_file.end(), '/', '-'); std::replace(mapping_file.begin(), mapping_file.end(), '\\', '-'); std::replace(mapping_file.begin(), mapping_file.end(), ':', '-'); diff --git a/core/input/gamepad_device.h b/core/input/gamepad_device.h index 6723b97d2..7768be5d9 100644 --- a/core/input/gamepad_device.h +++ b/core/input/gamepad_device.h @@ -26,8 +26,8 @@ class GamepadDevice { typedef void (*input_detected_cb)(u32 code); public: - virtual const char* api_name() = 0; - virtual const char* name() = 0; + const std::string& api_name() { return _api_name; } + const std::string& name() { return _name; } int maple_port() { return _maple_port; } void set_maple_port(int port) { _maple_port = port; } void gamepad_btn_input(u32 code, bool pressed); @@ -64,7 +64,7 @@ public: static GamepadDevice *GetGamepad(int index); protected: - GamepadDevice(int maple_port) : _maple_port(maple_port), input_mapper(NULL), _input_detected(NULL) { + GamepadDevice(int maple_port, const char *api_name) : _api_name(api_name), _maple_port(maple_port), input_mapper(NULL), _input_detected(NULL) { _gamepads_mutex.lock(); _gamepads.push_back(this); _gamepads_mutex.unlock(); @@ -73,6 +73,7 @@ protected: virtual void load_axis_min_max(u32 axis) {} + std::string _name; InputMapping *input_mapper; std::map axis_min_values; std::map axis_ranges; @@ -82,6 +83,7 @@ private: unsigned int get_axis_range(u32 axis); std::string make_mapping_filename(); + std::string _api_name; int _maple_port; bool _detecting_button = false; input_detected_cb _input_detected; diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index a8bae6279..d262eaf8c 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -616,9 +616,9 @@ static void gui_display_settings() GamepadDevice *gamepad = GamepadDevice::GetGamepad(i); if (gamepad == NULL) continue; - ImGui::Text("%s", gamepad->api_name()); + ImGui::Text("%s", gamepad->api_name().c_str()); ImGui::NextColumn(); - ImGui::Text("%s", gamepad->name()); + ImGui::Text("%s", gamepad->name().c_str()); ImGui::NextColumn(); char port_name[32]; sprintf(port_name, "##mapleport%d", i); diff --git a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp index 76d438818..e69605ecb 100644 --- a/core/sdl/sdl.cpp +++ b/core/sdl/sdl.cpp @@ -10,6 +10,7 @@ #include "khronos/GL3/gl3w.h" #endif #endif +#include "hw/maple/maple_devs.h" #include "sdl_gamepad.h" #include "sdl_keyboard.h" @@ -23,8 +24,6 @@ static SDL_GLContext glcontext; #endif #define WINDOW_HEIGHT 480 -static SDLGamepadDevice* sdl_gamepads[4] = { NULL }; -static SDL_JoystickID joystick_ids[ARRAY_SIZE(sdl_gamepads)] = { 0 }; static SDLMouseGamepadDevice* sdl_mouse_gamepad = NULL; static SDLKbGamepadDevice* sdl_kb_gamepad = NULL; static SDLKeyboardDevice* sdl_keyboard = NULL; @@ -44,6 +43,25 @@ extern s32 mo_y_abs; extern int screen_width, screen_height; +static void sdl_open_joystick(int index) +{ + SDL_Joystick *pJoystick = SDL_JoystickOpen(index); + + if (pJoystick == NULL) + { + printf("SDL: Cannot open joystick %d\n", index + 1); + return; + } + new SDLGamepadDevice(index < MAPLE_PORTS ? index : -1, pJoystick); // TODO save/restore maple port +} + +static void sdl_close_joystick(SDL_JoystickID instance) +{ + SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad(instance); + if (device != NULL) + delete device; +} + void input_sdl_init() { if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) @@ -53,25 +71,10 @@ void input_sdl_init() die("error initializing SDL Joystick subsystem"); } } - // Open joystick device - int numjoys = SDL_NumJoysticks(); - printf("Number of Joysticks found = %i\n", numjoys); - for (int i = 0; i < numjoys && i < ARRAY_SIZE(sdl_gamepads); i++) - { - SDL_Joystick *pJoystick = SDL_JoystickOpen(i); - if (pJoystick == NULL) - { - printf("Cannot open joystick %d\n", i + 1); - continue; - } - joystick_ids[i] = SDL_JoystickInstanceID(pJoystick); - - sdl_gamepads[i] = new SDLGamepadDevice(i, pJoystick); - } SDL_SetRelativeMouseMode(SDL_FALSE); - sdl_keyboard = new SDLKeyboardDevice(0); // FIXME ports! + sdl_keyboard = new SDLKeyboardDevice(0); // FIXME maple ports! sdl_kb_gamepad = new SDLKbGamepadDevice(0); sdl_mouse_gamepad = new SDLMouseGamepadDevice(0); } @@ -113,20 +116,18 @@ void input_sdl_handle(u32 port) break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: - for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++) - if (joystick_ids[i] == event.jbutton.which) - { - sdl_gamepads[i]->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN); - break; - } + { + SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jbutton.which); + if (device != NULL) + device->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN); + } break; case SDL_JOYAXISMOTION: - for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++) - if (joystick_ids[i] == event.jaxis.which) - { - sdl_gamepads[i]->gamepad_axis_input(event.jaxis.axis, event.jaxis.value); - break; - } + { + SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jaxis.which); + if (device != NULL) + device->gamepad_axis_input(event.jaxis.axis, event.jaxis.value); + } break; case SDL_MOUSEMOTION: @@ -153,6 +154,14 @@ void input_sdl_handle(u32 port) } sdl_mouse_gamepad->gamepad_btn_input(event.button.button, event.button.state == SDL_PRESSED); break; + + case SDL_JOYDEVICEADDED: + sdl_open_joystick(event.jdevice.which); + break; + + case SDL_JOYDEVICEREMOVED: + sdl_close_joystick((SDL_JoystickID)event.jdevice.which); + break; } } } diff --git a/core/sdl/sdl_gamepad.h b/core/sdl/sdl_gamepad.h index 49032f018..afca7046b 100644 --- a/core/sdl/sdl_gamepad.h +++ b/core/sdl/sdl_gamepad.h @@ -44,29 +44,47 @@ public: class SDLGamepadDevice : public GamepadDevice { public: - SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port), sdl_joystick(sdl_joystick) + SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port, "SDL"), sdl_joystick(sdl_joystick) { _name = SDL_JoystickName(sdl_joystick); + sdl_joystick_instance = SDL_JoystickInstanceID(sdl_joystick); + printf("SDL: Opened joystick on port %d: '%s' ", maple_port, _name.c_str()); if (!find_mapping()) { if (_name == "Microsoft X-Box 360 pad") { input_mapper = new Xbox360InputMapping(); - printf("Using Xbox 360 mapping\n"); + printf("using Xbox 360 mapping\n"); } else { input_mapper = new DefaultInputMapping(); - printf("Using default mapping\n"); + printf("using default mapping\n"); } save_mapping(); } + else + printf("using custom mapping '%s'\n", input_mapper->name.c_str()); + auto it = sdl_gamepads.find(sdl_joystick_instance); + if (it != sdl_gamepads.end()) + delete it->second; + sdl_gamepads[sdl_joystick_instance] = this; } - virtual const char* api_name() override { return "SDL"; } - virtual const char* name() override { return _name.c_str(); } virtual ~SDLGamepadDevice() override { + printf("SDL: Joystick '%s' on port %d disconnected\n", _name.c_str(), maple_port()); SDL_JoystickClose(sdl_joystick); + sdl_gamepads.erase(sdl_joystick_instance); + } + SDL_JoystickID sdl_instance() { return sdl_joystick_instance; } + + static SDLGamepadDevice *GetSDLGamepad(SDL_JoystickID id) + { + auto it = sdl_gamepads.find(id); + if (it != sdl_gamepads.end()) + return it->second; + else + return NULL; } protected: @@ -77,10 +95,13 @@ protected: } private: - std::string _name; SDL_Joystick* sdl_joystick; + SDL_JoystickID sdl_joystick_instance; + static std::map sdl_gamepads; }; +std::map SDLGamepadDevice::sdl_gamepads; + class KbInputMapping : public InputMapping { public: @@ -107,13 +128,12 @@ public: class SDLKbGamepadDevice : public GamepadDevice { public: - SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port) + SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL") { + _name = "Keyboard"; if (!find_mapping()) input_mapper = new KbInputMapping(); } - virtual const char* api_name() override { return "SDL"; } - virtual const char* name() override { return "Keyboard"; } virtual ~SDLKbGamepadDevice() {} }; @@ -134,13 +154,12 @@ public: class SDLMouseGamepadDevice : public GamepadDevice { public: - SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port) + SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL") { + _name = "Mouse"; if (!find_mapping()) input_mapper = new MouseInputMapping(); } - virtual const char* api_name() override { return "SDL"; } - virtual const char* name() override { return "Mouse"; } virtual ~SDLMouseGamepadDevice() {} };