From daf4980fc811876e74528d5e960f9e727572ab63 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 29 Mar 2019 17:19:18 +0100 Subject: [PATCH] input: save assigned maple port of each gamepad --- core/input/gamepad_device.cpp | 36 +++++++++++++++++++ core/input/gamepad_device.h | 23 +++--------- core/linux-dist/evdev_gamepad.h | 26 ++++++++------ core/linux-dist/x11.cpp | 1 + core/linux-dist/x11_keyboard.h | 1 + core/nullDC.cpp | 4 +++ core/sdl/sdl_gamepad.h | 9 +++++ core/windows/xinput_gamepad.h | 5 +++ .../emulator/periph/InputDeviceManager.java | 6 ++-- .../reicast/src/main/jni/src/Android.cpp | 9 ++--- .../src/main/jni/src/android_gamepad.h | 7 ++-- .../emulator-osx/emulator-osx/osx_gamepad.h | 2 ++ 12 files changed, 92 insertions(+), 37 deletions(-) diff --git a/core/input/gamepad_device.cpp b/core/input/gamepad_device.cpp index f8bee9bb7..843f18d62 100644 --- a/core/input/gamepad_device.cpp +++ b/core/input/gamepad_device.cpp @@ -21,6 +21,9 @@ #include "gamepad_device.h" #include "rend/gui.h" #include "oslib/oslib.h" +#include "cfg/cfg.h" + +#define MAPLE_PORT_CFG_PREFIX "maple_" extern void dc_exit(); @@ -253,3 +256,36 @@ void GamepadDevice::detect_axis_input(input_detected_cb axis_moved) _detection_start_time = os_GetSeconds() + 0.2; } +void GamepadDevice::Register(std::shared_ptr gamepad) +{ + int maple_port = cfgLoadInt("input", + (MAPLE_PORT_CFG_PREFIX + gamepad->unique_id()).c_str(), 12345); + if (maple_port != 12345) + gamepad->set_maple_port(maple_port); + + _gamepads_mutex.lock(); + _gamepads.push_back(gamepad); + _gamepads_mutex.unlock(); +} + +void GamepadDevice::Unregister(std::shared_ptr gamepad) +{ + gamepad->save_mapping(); + _gamepads_mutex.lock(); + for (auto it = _gamepads.begin(); it != _gamepads.end(); it++) + if (*it == gamepad) { + _gamepads.erase(it); + break; + } + _gamepads_mutex.unlock(); +} + +void GamepadDevice::SaveMaplePorts() +{ + for (int i = 0; i < GamepadDevice::GetGamepadCount(); i++) + { + std::shared_ptr gamepad = GamepadDevice::GetGamepad(i); + if (gamepad != NULL && !gamepad->unique_id().empty()) + cfgSaveInt("input", (MAPLE_PORT_CFG_PREFIX + gamepad->unique_id()).c_str(), gamepad->maple_port()); + } +} diff --git a/core/input/gamepad_device.h b/core/input/gamepad_device.h index d7cb5d4a5..92a75692d 100644 --- a/core/input/gamepad_device.h +++ b/core/input/gamepad_device.h @@ -31,6 +31,7 @@ public: const std::string& name() { return _name; } int maple_port() { return _maple_port; } void set_maple_port(int port) { _maple_port = port; } + const std::string& unique_id() { return _unique_id; } virtual bool gamepad_btn_input(u32 code, bool pressed); bool gamepad_axis_input(u32 code, int value); virtual ~GamepadDevice() {} @@ -50,28 +51,13 @@ public: virtual void update_rumble() {} bool is_rumble_enabled() { return _rumble_enabled; } - static void Register(std::shared_ptr gamepad) - { - _gamepads_mutex.lock(); - _gamepads.push_back(gamepad); - _gamepads_mutex.unlock(); - } + static void Register(std::shared_ptr gamepad); - static void Unregister(std::shared_ptr gamepad) - { - gamepad->save_mapping(); - _gamepads_mutex.lock(); - for (auto it = _gamepads.begin(); it != _gamepads.end(); it++) - if (*it == gamepad) - { - _gamepads.erase(it); - break; - } - _gamepads_mutex.unlock(); - } + static void Unregister(std::shared_ptr gamepad); static int GetGamepadCount(); static std::shared_ptr GetGamepad(int index); + static void SaveMaplePorts(); protected: GamepadDevice(int maple_port, const char *api_name, bool remappable = true) @@ -83,6 +69,7 @@ protected: virtual void load_axis_min_max(u32 axis) {} std::string _name; + std::string _unique_id = ""; InputMapping *input_mapper; std::map axis_min_values; std::map axis_ranges; diff --git a/core/linux-dist/evdev_gamepad.h b/core/linux-dist/evdev_gamepad.h index f3c5c4bd4..2d06ce4fe 100644 --- a/core/linux-dist/evdev_gamepad.h +++ b/core/linux-dist/evdev_gamepad.h @@ -9,12 +9,18 @@ public: : GamepadDevice(maple_port, "evdev"), _fd(fd), _rumble_effect_id(-1), _devnode(devnode) { fcntl(fd, F_SETFL, O_NONBLOCK); - char name[256] = "Unknown"; - if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) + char buf[256] = "Unknown"; + if (ioctl(fd, EVIOCGNAME(sizeof(buf) - 1), buf) < 0) perror("evdev: ioctl(EVIOCGNAME)"); else - printf("evdev: Opened device '%s' ", name); - _name = name; + printf("evdev: Opened device '%s' ", buf); + _name = buf; + buf[0] = 0; + if (ioctl(fd, EVIOCGUNIQ(sizeof(buf) - 1), buf) == 0) + _unique_id = buf; + if (_unique_id.empty()) + _unique_id = devnode; + if (!find_mapping(mapping_file)) { #if defined(TARGET_PANDORA) @@ -22,18 +28,18 @@ public: #elif defined(TARGET_GCW0) mapping_file = "controller_gcwz.cfg"; #else - if (!strcmp(name, "Microsoft X-Box 360 pad") - || !strcmp(name, "Xbox 360 Wireless Receiver") - || !strcmp(name, "Xbox 360 Wireless Receiver (XBOX)")) + if (_name == "Microsoft X-Box 360 pad" + || _name == "Xbox 360 Wireless Receiver" + || _name == "Xbox 360 Wireless Receiver (XBOX)") { mapping_file = "controller_xpad.cfg"; } - else if (strstr(name, "Xbox Gamepad (userspace driver)") != NULL) + else if (_name.find("Xbox Gamepad (userspace driver)") != std::string::npos) { mapping_file = "controller_xboxdrv.cfg"; } - else if (strstr(name, "keyboard") != NULL || - strstr(name, "Keyboard") != NULL) + else if (_name.find("keyboard") != std::string::npos + || _name.find("Keyboard") != std::string::npos) { mapping_file = "keyboard.cfg"; } diff --git a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp index da977e6b3..85c6fd5f1 100644 --- a/core/linux-dist/x11.cpp +++ b/core/linux-dist/x11.cpp @@ -52,6 +52,7 @@ public: X11MouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "X11") { _name = "Mouse"; + _unique_id = "x11_mouse"; if (!find_mapping()) input_mapper = new MouseInputMapping(); } diff --git a/core/linux-dist/x11_keyboard.h b/core/linux-dist/x11_keyboard.h index e78717e32..70e3edd69 100644 --- a/core/linux-dist/x11_keyboard.h +++ b/core/linux-dist/x11_keyboard.h @@ -181,6 +181,7 @@ public: X11KbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "X11") { _name = "Keyboard"; + _unique_id = "x11_keyboard"; if (!find_mapping()) input_mapper = new KbInputMapping(); } diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 868e6f1b9..00309f0dc 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -22,6 +22,7 @@ #include "imgread/common.h" #include "rend/gui.h" #include "profiler/profiler.h" +#include "input/gamepad_device.h" void FlushCache(); void LoadCustom(); @@ -741,6 +742,9 @@ void SaveSettings() paths += path; } cfgSaveStr("config", "Dreamcast.ContentPath", paths.c_str()); + + GamepadDevice::SaveMaplePorts(); + #ifdef _ANDROID void SaveAndroidSettings(); SaveAndroidSettings(); diff --git a/core/sdl/sdl_gamepad.h b/core/sdl/sdl_gamepad.h index 4d970a700..9f74f578c 100644 --- a/core/sdl/sdl_gamepad.h +++ b/core/sdl/sdl_gamepad.h @@ -50,6 +50,13 @@ public: _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()); + SDL_JoystickGUID guid = SDL_JoystickGetGUID(sdl_joystick); + char buf[33]; + SDL_JoystickGetGUIDString(guid, buf, sizeof(buf)); + _unique_id = buf; + if (_unique_id.empty()) + _unique_id = _name; + if (!find_mapping()) { if (_name == "Microsoft X-Box 360 pad") @@ -175,6 +182,7 @@ public: SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL") { _name = "Keyboard"; + _unique_id = "sdl_keyboard; if (!find_mapping()) input_mapper = new KbInputMapping(); } @@ -201,6 +209,7 @@ public: SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL") { _name = "Mouse"; + _unique_id = "sdl_mouse"; if (!find_mapping()) input_mapper = new MouseInputMapping(); } diff --git a/core/windows/xinput_gamepad.h b/core/windows/xinput_gamepad.h index 5aa9f70e7..26b3e39e7 100644 --- a/core/windows/xinput_gamepad.h +++ b/core/windows/xinput_gamepad.h @@ -36,6 +36,9 @@ public: XInputGamepadDevice(int maple_port, int xinput_port) : GamepadDevice(maple_port, "xinput"), _xinput_port(xinput_port) { + char buf[32]; + sprintf(buf, "xinput-%d", xinput_port + 1); + _unique_id = buf; } void ReadInput() @@ -231,6 +234,7 @@ public: WinKbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "win32") { _name = "Keyboard"; + _unique_id = "win_keyboard; if (!find_mapping()) input_mapper = new KbInputMapping(); } @@ -257,6 +261,7 @@ public: WinMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "win32") { _name = "Mouse"; + _unique_id = "win_mouse; if (!find_mapping()) input_mapper = new MouseInputMapping(); } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java index e8ff499d0..cfe754612 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java @@ -24,7 +24,7 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene { maple_port = 0; if (applicationContext.getPackageManager().hasSystemFeature("android.hardware.touchscreen")) - joystickAdded(VIRTUAL_GAMEPAD_ID, "Virtual Gamepad", maple_port == 3 ? 3 : maple_port++); + joystickAdded(VIRTUAL_GAMEPAD_ID, "Virtual Gamepad", maple_port == 3 ? 3 : maple_port++, "virtual_gamepad_uid"); int[] ids = InputDevice.getDeviceIds(); for (int id : ids) onInputDeviceAdded(id); @@ -49,7 +49,7 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene if ((device.getSources() & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK) { port = this.maple_port == 3 ? 3 : this.maple_port++; } - joystickAdded(i, device.getName(), port); + joystickAdded(i, device.getName(), port, device.getDescriptor()); } } @@ -96,6 +96,6 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene public native boolean joystickButtonEvent(int id, int button, boolean pressed); public native boolean joystickAxisEvent(int id, int button, int value); public native void mouseEvent(int xpos, int ypos, int buttons); - private native void joystickAdded(int id, String name, int maple_port); + private native void joystickAdded(int id, String name, int maple_port, String uniqueId); private native void joystickRemoved(int id); } diff --git a/shell/android-studio/reicast/src/main/jni/src/Android.cpp b/shell/android-studio/reicast/src/main/jni/src/Android.cpp index 3acc179e9..917586e8c 100644 --- a/shell/android-studio/reicast/src/main/jni/src/Android.cpp +++ b/shell/android-studio/reicast/src/main/jni/src/Android.cpp @@ -114,7 +114,7 @@ JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsOpen(JNIEnv JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsContentBrowser(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_init(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port, jstring junique_id) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickRemoved(JNIEnv *env, jobject obj, jint id) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_virtualGamepadEvent(JNIEnv *env, jobject obj, jint kcode, jint joyx, jint joyy, jint lt, jint rt) __attribute__((visibility("default"))); JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickButtonEvent(JNIEnv *env, jobject obj, jint id, jint key, jboolean pressed) __attribute__((visibility("default"))); @@ -622,13 +622,14 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_init( input_device_manager_rumble = env->GetMethodID(env->GetObjectClass(obj), "rumble", "(IFFI)Z"); } -JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port) +JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port, jstring junique_id) { const char* joyname = env->GetStringUTFChars(name,0); - std::shared_ptr gamepad = std::make_shared(maple_port, id, joyname); + const char* unique_id = env->GetStringUTFChars(junique_id, 0); + std::shared_ptr gamepad = std::make_shared(maple_port, id, joyname, unique_id); AndroidGamepadDevice::AddAndroidGamepad(gamepad); env->ReleaseStringUTFChars(name, joyname); - + env->ReleaseStringUTFChars(name, unique_id); } JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickRemoved(JNIEnv *env, jobject obj, jint id) { diff --git a/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h b/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h index 28cb874b4..c1fe2b465 100644 --- a/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h +++ b/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h @@ -87,10 +87,12 @@ public: class AndroidGamepadDevice : public GamepadDevice { public: - AndroidGamepadDevice(int maple_port, int id, const char *name) : GamepadDevice(maple_port, "Android", id != VIRTUAL_GAMEPAD_ID), android_id(id) + AndroidGamepadDevice(int maple_port, int id, const char *name, const char *unique_id) + : GamepadDevice(maple_port, "Android", id != VIRTUAL_GAMEPAD_ID), android_id(id) { _name = name; - printf("Android: Opened joystick %d on port %d: '%s' ", id, maple_port, _name.c_str()); + _unique_id = unique_id; + printf("Android: Opened joystick %d on port %d: '%s' descriptor '%s'", id, maple_port, _name.c_str(), _unique_id.c_str()); if (id == VIRTUAL_GAMEPAD_ID) { input_mapper = new IdentityInputMapping(); @@ -213,6 +215,7 @@ public: AndroidMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "Android") { _name = "Mouse"; + _unique_id = "android_mouse"; if (!find_mapping()) input_mapper = new MouseInputMapping(); } diff --git a/shell/apple/emulator-osx/emulator-osx/osx_gamepad.h b/shell/apple/emulator-osx/emulator-osx/osx_gamepad.h index da3c92773..6b7e0d461 100644 --- a/shell/apple/emulator-osx/emulator-osx/osx_gamepad.h +++ b/shell/apple/emulator-osx/emulator-osx/osx_gamepad.h @@ -36,6 +36,7 @@ public: OSXKbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "OSX") { _name = "Keyboard"; + _unique_id = "osx_keyboard"; if (!find_mapping()) input_mapper = new KbInputMapping(); } @@ -61,6 +62,7 @@ public: OSXMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "OSX") { _name = "Mouse"; + _unique_id = "osx_mouse"; if (!find_mapping()) input_mapper = new MouseInputMapping(); }