From 2a646c204f0620c0d9ef69f9035cec315462b22e Mon Sep 17 00:00:00 2001 From: Marc Riera Irigoyen Date: Sat, 29 Oct 2022 20:03:18 +0200 Subject: [PATCH 01/10] Update README --- README.md | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae86274..0440ee4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# ddgo-converter -Converter tool for PC versions of Densha de GO! +# Densha de GO! Controller Converter + +This tool allows using a physical _Densha de GO!_ controller with a game that does not officially support it. It is Linux only (check https://autotraintas.hariko.com/ if you use Windows). + +## How it works + +The program reads input from a real controller, translates it and sends it to an emulated controller, which is picked up by the game. + +## Installation + +The executable is ready to use. However, you will need read AND write permissions on `/dev/uinput` for the program to work. + +**NOTE:** Currently, this fails to launch on the Steam Deck in Gaming Mode. It works fine in Desktop Mode, but you need to disable Steam Input (or close Steam entirely). + +## Supported controllers + +### Physical + +- One-handle controller for Nintendo Switch (ZKNS-001) + +### Emulated + +- Two-handle controller for PC (DGOC-44U) +- Two-handle controller for Sony PlayStation (SLPH-00051) +- Two-handle controller for Nintendo 64 (TCPP-20003) +- Two-handle controller for SEGA Saturn (TC-5175290) + +## Notes + +When emulating console controllers, an emulated Sony PlayStation 3 controller is used for easier mapping. On RetroArch, everything works out of the box. + +_Densha de GO! 64_ requires connecting the controller to Port 3 and enabling **Independent C-button Controls**. From 07dd9abfa249dbbc4e1a8ae86ab1d2cc430b9105 Mon Sep 17 00:00:00 2001 From: Marc Riera Irigoyen Date: Mon, 31 Oct 2022 12:13:01 +0100 Subject: [PATCH 02/10] Improve notch responsiveness --- ddgo-converter/gamepads/physical.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index f45e2e0..4a9fa67 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -106,34 +106,48 @@ class SwitchGamepad(PhysicalGamepad): match event.value: case 0x0: # EMG input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 9)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x5: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 8)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x13: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 7)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x20: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 6)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x2E: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 5)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x3C: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 4)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x49: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 3)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x57: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 2)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x65: input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 1)) + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x80: # N input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) case 0x9F: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 1)) case 0xB7: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 2)) case 0xCE: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 3)) case 0xE6: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 4)) case 0xFF: # P5 + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) return input_events except OSError: From cbfe1d366db48a30365e916da7e9ece06fd70f7e Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Tue, 1 Nov 2022 18:53:48 +0100 Subject: [PATCH 03/10] Error handling for grab/ungrab --- ddgo-converter/gamepads/physical.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index 4a9fa67..5c0ffaf 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -52,10 +52,16 @@ class SwitchGamepad(PhysicalGamepad): self.device = self._get_device() def start(self): - self.device.grab() + try: + self.device.grab() + except: + return def stop(self): - self.device.ungrab() + try: + self.device.ungrab() + except: + return def read_input(self): # time.sleep(5) From 07feffd855efb39756690c69a68fd451199d9cbb Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Tue, 1 Nov 2022 19:16:23 +0100 Subject: [PATCH 04/10] Add support for ZKNS-002 --- ddgo-converter/gamepads/physical.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index 5c0ffaf..61afa99 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -6,7 +6,7 @@ from select import select def create_gamepad(vid, pid, name): match vid, pid: - case 0x0f0d, 0x00c1: + case (0x0f0d, 0x00c1) | (0x33dd, 0x0002): return SwitchGamepad(vid, pid, name) return PhysicalGamepad(vid, pid, name) From 6f1a890895981a792db47c2d617c6db0bee754c8 Mon Sep 17 00:00:00 2001 From: Marc Riera Irigoyen Date: Sat, 5 Nov 2022 18:12:35 +0100 Subject: [PATCH 05/10] v1.1.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0e105b1..1826740 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages setup(name='Densha de GO! Controller Converter', - version='1.0.0', + version='1.1.0', packages=find_packages(), ) From bed298ac9998ffa5defaa7a99d1d910ff56b3281 Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Fri, 18 Nov 2022 19:35:15 +0100 Subject: [PATCH 06/10] Initial support for classic controllers --- ddgo-converter/gamepads/physical.py | 127 +++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 4 deletions(-) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index 61afa99..73b6f7a 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -1,4 +1,4 @@ -from enum import IntEnum +from enum import IntFlag, IntEnum, auto import evdev from hashlib import sha1 from events.input import InputEvent @@ -8,6 +8,8 @@ def create_gamepad(vid, pid, name): match vid, pid: case (0x0f0d, 0x00c1) | (0x33dd, 0x0002): return SwitchGamepad(vid, pid, name) + case 0x054c, 0x0268: + return ClassicGamepad(vid, pid, name) return PhysicalGamepad(vid, pid, name) class PhysicalGamepad: @@ -64,9 +66,6 @@ class SwitchGamepad(PhysicalGamepad): return def read_input(self): - # time.sleep(5) - # print("Read from ZKNS-001 correct") - # return InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_A) select([self.device], [], [], 5) try: event = self.device.read_one() @@ -158,3 +157,123 @@ class SwitchGamepad(PhysicalGamepad): return input_events except OSError: return [InputEvent(InputEvent.EventType.ERROR, None)] + +class ClassicGamepad(PhysicalGamepad): + + class ButtonType(IntEnum): + BUTTON = 0 + POWER = 1 + BRAKE = 2 + + class Buttons(IntFlag): + BUTTON_A = auto() + BUTTON_B = auto() + BUTTON_C = auto() + BUTTON_SELECT = auto() + BUTTON_START = auto() + + class Power(IntFlag): + POWER1 = auto() + POWER2 = auto() + POWER3 = auto() + + class Brake(IntFlag): + BRAKE1 = auto() + BRAKE2 = auto() + BRAKE3 = auto() + BRAKE4 = auto() + + class ButtonConfig(): + def __init__(self, type, code, button): + self.type = type + self.code = code + self.button = button + + def __init__(self, * args): + super().__init__(* args) + self.type = self.GamepadType.CLASSIC + self.config = [ self.ButtonConfig(self.ButtonType.BUTTON, 308, self.Buttons.BUTTON_A), self.ButtonConfig(self.ButtonType.BUTTON, 304, self.Buttons.BUTTON_B), self.ButtonConfig(self.ButtonType.BUTTON, 305, self.Buttons.BUTTON_C), self.ButtonConfig(self.ButtonType.BUTTON, 314, self.Buttons.BUTTON_SELECT), self.ButtonConfig(self.ButtonType.BUTTON, 315, self.Buttons.BUTTON_START), + self.ButtonConfig(self.ButtonType.POWER, 307, self.Power.POWER1), self.ButtonConfig(self.ButtonType.POWER, 546, self.Power.POWER2), self.ButtonConfig(self.ButtonType.POWER, 547, self.Power.POWER3), + self.ButtonConfig(self.ButtonType.BRAKE, 310, self.Brake.BRAKE1), self.ButtonConfig(self.ButtonType.BRAKE, 312, self.Brake.BRAKE2), self.ButtonConfig(self.ButtonType.BRAKE, 311, self.Brake.BRAKE3), self.ButtonConfig(self.ButtonType.BRAKE, 313, self.Brake.BRAKE4) ] + self.device = self._get_device() + self.buttons = IntFlag(0) + self.power = IntFlag(0) + self.brake = IntFlag(0) + + def start(self): + try: + self.device.grab() + except: + return + + def stop(self): + try: + self.device.ungrab() + except: + return + + def read_input(self): + select([self.device], [], [], 5) + try: + event = self.device.read_one() + input_events = [] + if event is not None: + for button in self.config: + match button.type: + case self.ButtonType.POWER: + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 0: + self.power &= ~button.button + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 1: + self.power |= button.button + case self.ButtonType.BRAKE: + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 0: + self.brake &= ~button.button + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 1: + self.brake |= button.button + case self.ButtonType.BUTTON: + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 0: + self.buttons &= ~button.button + if event.type == evdev.ecodes.EV_KEY and event.code == button.code and event.value == 1: + self.buttons |= button.button + input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_A in self.buttons), InputEvent.Button.BUTTON_A)) + input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_B in self.buttons), InputEvent.Button.BUTTON_B)) + input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_C in self.buttons), InputEvent.Button.BUTTON_C)) + input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_SELECT in self.buttons), InputEvent.Button.BUTTON_SELECT)) + input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_START in self.buttons), InputEvent.Button.BUTTON_START)) + match self.power: + case 6: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) + case 5: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 1)) + case 4: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 2)) + case 3: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 3)) + case 2: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 4)) + case 1: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) + match self.brake: + case 14: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) + case 13: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 1)) + case 12: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 2)) + case 11: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 3)) + case 10: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 4)) + case 9: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 5)) + case 8: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 6)) + case 7: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 7)) + case 6: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 8)) + case 0: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 9)) + return input_events + except OSError: + return [InputEvent(InputEvent.EventType.ERROR, None)] From 52a34383cc549327283a61bf1e8d9c49c239e731 Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Fri, 18 Nov 2022 20:09:49 +0100 Subject: [PATCH 07/10] Sync before processing power/brake data --- ddgo-converter/gamepads/physical.py | 69 +++++++++++++++-------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index 73b6f7a..7002f93 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -240,40 +240,41 @@ class ClassicGamepad(PhysicalGamepad): input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_C in self.buttons), InputEvent.Button.BUTTON_C)) input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_SELECT in self.buttons), InputEvent.Button.BUTTON_SELECT)) input_events.append(InputEvent(InputEvent.EventType(self.Buttons.BUTTON_START in self.buttons), InputEvent.Button.BUTTON_START)) - match self.power: - case 6: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) - case 5: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 1)) - case 4: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 2)) - case 3: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 3)) - case 2: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 4)) - case 1: - input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) - match self.brake: - case 14: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) - case 13: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 1)) - case 12: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 2)) - case 11: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 3)) - case 10: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 4)) - case 9: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 5)) - case 8: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 6)) - case 7: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 7)) - case 6: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 8)) - case 0: - input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 9)) + if event.type == evdev.ecodes.EV_SYN: + match self.power: + case 6: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) + case 5: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 1)) + case 4: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 2)) + case 3: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 3)) + case 2: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 4)) + case 1: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) + match self.brake: + case 14: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) + case 13: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 1)) + case 12: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 2)) + case 11: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 3)) + case 10: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 4)) + case 9: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 5)) + case 8: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 6)) + case 7: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 7)) + case 6: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 8)) + case 0: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 9)) return input_events except OSError: return [InputEvent(InputEvent.EventType.ERROR, None)] From 24f41f10feacd224a4dc42fb2eb9d8d6d0cf4d4d Mon Sep 17 00:00:00 2001 From: Marc Riera Irigoyen Date: Sat, 19 Nov 2022 12:02:47 +0100 Subject: [PATCH 08/10] Add run config --- .gitignore | 2 +- .vscode/launch.json | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json diff --git a/.gitignore b/.gitignore index 2f6e956..b75c66b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ __pycache__/ *.db -**/.vscode/ +*/.vscode/ venv/ headers/ diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..404bf77 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Run main program", + "type": "python", + "request": "launch", + "program": "ddgo-converter/ddgo-converter.py", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file From f9ab1ce64f40fb756a53de0663c1885c10277001 Mon Sep 17 00:00:00 2001 From: Marc Riera Irigoyen Date: Sat, 19 Nov 2022 12:26:27 +0100 Subject: [PATCH 09/10] Add support for input DGOC-44U --- README.md | 8 +-- ddgo-converter/gamepads/physical.py | 83 +++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0440ee4..c16790c 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,13 @@ The executable is ready to use. However, you will need read AND write permission ## Supported controllers -### Physical +### Physical (input) +- One-handle controller for PC (DGC-255) +- Two-handle controller for PC (DGOC-44U) - One-handle controller for Nintendo Switch (ZKNS-001) -### Emulated +### Emulated (output) - Two-handle controller for PC (DGOC-44U) - Two-handle controller for Sony PlayStation (SLPH-00051) @@ -27,6 +29,6 @@ The executable is ready to use. However, you will need read AND write permission ## Notes -When emulating console controllers, an emulated Sony PlayStation 3 controller is used for easier mapping. On RetroArch, everything works out of the box. +When emulating console controllers, an emulated Sony PlayStation 3 controller is used for easier mapping. On RetroArch, everything should work out of the box. _Densha de GO! 64_ requires connecting the controller to Port 3 and enabling **Independent C-button Controls**. diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index 7002f93..f68f81d 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -10,6 +10,8 @@ def create_gamepad(vid, pid, name): return SwitchGamepad(vid, pid, name) case 0x054c, 0x0268: return ClassicGamepad(vid, pid, name) + case 0x0ae4, 0x0003: + return PCGamepad(vid, pid, name) return PhysicalGamepad(vid, pid, name) class PhysicalGamepad: @@ -18,6 +20,7 @@ class PhysicalGamepad: UNKNOWN = 0 CLASSIC = 1 SWITCH = 2 + PC = 3 def __init__(self, vid, pid, name): super().__init__() @@ -278,3 +281,83 @@ class ClassicGamepad(PhysicalGamepad): return input_events except OSError: return [InputEvent(InputEvent.EventType.ERROR, None)] + +class PCGamepad(PhysicalGamepad): + + def __init__(self, * args): + super().__init__(* args) + self.type = self.GamepadType.PC + self.config = [] + self.device = self._get_device() + + def start(self): + try: + self.device.grab() + except: + return + + def stop(self): + try: + self.device.ungrab() + except: + return + + def read_input(self): + select([self.device], [], [], 5) + try: + event = self.device.read_one() + input_events = [] + if event is not None: + if event.type == evdev.ecodes.EV_KEY: + match event.code: + case 289: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_A)) + case 288: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_B)) + case 290: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_C)) + case 291: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_D)) + case 292: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_SELECT)) + case 293: + input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_START)) + if event.type == evdev.ecodes.EV_ABS and event.code == evdev.ecodes.ABS_X: + match event.value: + case 0xB9: # EMG + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 9)) + case 0xB5: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 8)) + case 0xB2: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 7)) + case 0xAF: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 6)) + case 0xA8: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 5)) + case 0xA2: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 4)) + case 0x9A: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 3)) + case 0x94: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 2)) + case 0x8A: + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 1)) + case 0x79: # N + input_events.append(InputEvent(InputEvent.EventType.BRAKE_NOTCH, 0)) + if event.type == evdev.ecodes.EV_ABS and event.code == evdev.ecodes.ABS_Y: + match event.value: + case 0x81: # N + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 0)) + case 0x6D: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 1)) + case 0x54: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 2)) + case 0x3F: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 3)) + case 0x21: + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 4)) + case 0x00: # P5 + input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) + return input_events + except OSError: + return [InputEvent(InputEvent.EventType.ERROR, None)] \ No newline at end of file From 4134571ff7ea8dc5d076bb7273171e34429c26f0 Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Tue, 7 Mar 2023 18:33:46 +0100 Subject: [PATCH 10/10] Update Zuiki controller ID --- ddgo-converter/gamepads/physical.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddgo-converter/gamepads/physical.py b/ddgo-converter/gamepads/physical.py index f68f81d..5631a86 100755 --- a/ddgo-converter/gamepads/physical.py +++ b/ddgo-converter/gamepads/physical.py @@ -6,7 +6,7 @@ from select import select def create_gamepad(vid, pid, name): match vid, pid: - case (0x0f0d, 0x00c1) | (0x33dd, 0x0002): + case (0x0f0d, 0x00c1) | (0x33dd, 0x0001) | (0x33dd, 0x0002): return SwitchGamepad(vid, pid, name) case 0x054c, 0x0268: return ClassicGamepad(vid, pid, name) @@ -360,4 +360,4 @@ class PCGamepad(PhysicalGamepad): input_events.append(InputEvent(InputEvent.EventType.POWER_NOTCH, 5)) return input_events except OSError: - return [InputEvent(InputEvent.EventType.ERROR, None)] \ No newline at end of file + return [InputEvent(InputEvent.EventType.ERROR, None)]