From e10f70ce8c03f4b781b12e9bfd98f6360080079d Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Tue, 20 Oct 2026 10:35:05 +1000 Subject: [PATCH] hypseus: invert the vertical axis through the keymap in gamepad mode (fixes #13743) --- .../emulators/hypseus_singe.py | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/python-src/batocera-launch/batocera_launch/emulators/hypseus_singe.py b/python-src/batocera-launch/batocera_launch/emulators/hypseus_singe.py index 838ab53aafe..20f89279437 100644 --- a/python-src/batocera-launch/batocera_launch/emulators/hypseus_singe.py +++ b/python-src/batocera-launch/batocera_launch/emulators/hypseus_singe.py @@ -35,6 +35,7 @@ _logger: Final = logging.getLogger(__name__) _CONFIG_NAME: Final = 'hypinput.ini' +_INVERTED_CONFIG_NAME: Final = 'hypinput_inverted.ini' _SHARE_DIR: Final = Path('/usr/share/hypseus-singe') # Bezel images are shared across a family of related ROM variants (regional / @@ -140,6 +141,22 @@ def _get_resolution(video_path: Path) -> tuple[int, int] | None: return width, height +def _write_inverted_keymap(source: Path, destination: Path) -> None: + # -tiphat only inverts hat events, which hypseus ignores in -gamepad mode, so swap the pad bindings instead + lines = source.read_text().splitlines(keepends=True) + entries: dict[str, tuple[int, str, list[str]]] = {} + for index, line in enumerate(lines): + name, sep, value = line.partition('=') + if sep and name.strip() in ('KEY_UP', 'KEY_DOWN'): + entries[name.strip()] = (index, name + sep, value.split()) + if len(entries) == 2: + up_index, up_prefix, up_fields = entries['KEY_UP'] + down_index, down_prefix, down_fields = entries['KEY_DOWN'] + lines[up_index] = f'{up_prefix} {" ".join(up_fields[:2] + down_fields[2:])}\n' + lines[down_index] = f'{down_prefix} {" ".join(down_fields[:2] + up_fields[2:])}\n' + destination.write_text(''.join(lines)) + + def _copy_resources(source_dir: Path, destination_dir: Path) -> None: if not destination_dir.exists(): shutil.copytree(source_dir, destination_dir) @@ -289,12 +306,11 @@ async def configure(self) -> Command: ] # controller config file - args.extend( - [ - '-keymapfile', - self.config.get_bool('hypseus_joy', return_values=('custom.ini', _CONFIG_NAME)), - ] - ) + keymap = self.config.get_bool('hypseus_joy', return_values=('custom.ini', _CONFIG_NAME)) + if self.config.get_bool('hypseus_axis'): + _write_inverted_keymap(self.config_dir / keymap, self.config_dir / _INVERTED_CONFIG_NAME) + keymap = _INVERTED_CONFIG_NAME + args.extend(['-keymapfile', keymap]) # Default -fullscreen behaviour respects game aspect ratio bezel_required = False @@ -391,10 +407,6 @@ async def configure(self) -> Command: else: args.extend(['-bezel', bezel_file]) - # Invert HAT Axis - if self.config.get_bool('hypseus_axis'): - args.append('-tiphat') - # Game rotation options for vertical screens, default is 0. match self.config.get('hypseus_rotate'): case '90' | '270' as rotate: