From b8ed9b735aedc3956e34d2cfee85c8040cfa7373 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 11 Nov 2026 12:06:28 +0100 Subject: [PATCH] feat: profile the retroarch frontend config reads AmberELEC and ROCKNIX install a retroarch.cfg whose system_directory points every core at the BIOS folder. retroarch.yml (type utility, no file, no system) reads that key, and ROCKNIX's systemfiles_in_content_dir, at the RetroArch each one compiles: v1.22.2 and bdba046f. all_libretro never picks a utility profile, and lists naming retroarch gain no file. A libretro core option a frontend record writes stays the core's to read: RetroDECK's pcsx2_bios keeps lrps2 as its reader. --- emulators/retroarch.yml | 58 +++++++++++++++++++++++++++++++++ scripts/launchers.py | 12 +++++-- tests/test_launcher_evidence.py | 28 ++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 emulators/retroarch.yml diff --git a/emulators/retroarch.yml b/emulators/retroarch.yml new file mode 100644 index 000000000..6a04ef897 --- /dev/null +++ b/emulators/retroarch.yml @@ -0,0 +1,58 @@ +emulator: "RetroArch" +type: utility +core_classification: other +source: "https://github.com/libretro/RetroArch" +upstream: "https://github.com/libretro/RetroArch" +profiled_date: "2026-11-11" +source_commit: "69a4f0ea1e8aaf442ae4858f2e7f2b31a1776576" +core_version: "v1.22.2" +version_basis: + kind: tag + tag: "v1.22.2" + distance: 0 +display_name: "RetroArch (libretro frontend)" +cores: + - retroarch +systems: [] + +pin_build: + - platform: amberelec + repo: "https://github.com/AmberELEC/AmberELEC" + revision: "a21975bfb1a3af68f66e07a931b994b523e1e6e2" + path: "packages/games/tools/retroarch/package.mk" + variable: PKG_VERSION + value: "69a4f0ea1e8aaf442ae4858f2e7f2b31a1776576" + - platform: rocknix + repo: "https://github.com/ROCKNIX/distribution" + revision: "20261101" + path: "projects/ROCKNIX/packages/emulators/libretro/retroarch/package.mk" + variable: PKG_VERSION + value: "bdba046fa6766380bc2457532f38e589df769aaf" +config_reads: + - file: "retroarch.cfg" + platforms: [amberelec] + source_ref: "retroarch.c:6968-6969, 7148-7155, 7244, configuration.c:3469, 3779, 3824, 3863-3884, 5014-5018, libretro-common/file/config_file.c:840" + keys: + - key: "system_directory" + source_ref: "configuration.c:1645, 4063-4069, 4110-4115, 4346-4347, libretro-common/file/config_file.c:1180-1189, libretro-common/file/file_path.c:1060-1098, runloop.c:1935-1976" + condition: "systemfiles_in_content_dir false (its default, config.def.h:925); LIBRETRO_SYSTEM_DIRECTORY in the environment replaces the value, an empty value hands the content's folder" + - file: "retroarch.cfg" + platforms: [rocknix] + source_ref: "retroarch.c:7272-7273, 7452-7459, 7548, configuration.c:3565, 3886, 3931, 3970-4010, 5174-5176, libretro-common/file/config_file.c:817" + keys: + - key: "system_directory" + source_ref: "configuration.c:1688, 4193-4199, 4240-4245, 4494-4495, libretro-common/file/config_file.c:1190-1199, libretro-common/file/file_path.c:1066-1100, runloop.c:1949-1990" + condition: "systemfiles_in_content_dir false; LIBRETRO_SYSTEM_DIRECTORY in the environment replaces the value, an empty value hands the content's folder" + - key: "systemfiles_in_content_dir" + source_ref: "configuration.c:1870, runloop.c:1949-1990" + condition: "true hands the content's folder in place of system_directory" + +notes: | + The libretro frontend. It loads each core and answers + RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY with the system_directory of the + config it was started with (-c, else the default path), a leading ~ + expanded to $HOME. The cores read their BIOS files below that folder, so + their profiles hold the files and this one holds none. + ref: retroarch.c:7148-7155, configuration.c:3824, runloop.c:1935-1976 + +files: [] diff --git a/scripts/launchers.py b/scripts/launchers.py index c790af076..138014337 100644 --- a/scripts/launchers.py +++ b/scripts/launchers.py @@ -468,7 +468,12 @@ def config_evidence( readers: list[str] = [] uncovered = list(keys) loaded = False - for key in _named_profiles(record, profiles, platform) or sorted(profiles): + named = _named_profiles(record, profiles, platform) + if file == CORE_OPTIONS: + # A core option is read by the core RetroArch runs, not by the + # frontend a record names (RetroDECK's retroarch component). + named = [k for k in named if "libretro" in str(profiles[k].get("type") or "")] + for key in named or sorted(profiles): profile = profiles[key] handles = _handle_refs(profile) for read in profile.get("config_reads") or []: @@ -1319,7 +1324,10 @@ class LauncherLayer: for key in self._profiles_named(emulator, profiles, relevant) } # RetroDECK names its frontend, retroarch, and the core option it - # writes, pcsx2_bios, names the core. + # writes, pcsx2_bios, names the core: a libretro core option + # belongs to a libretro core. + if place.build == "libretro" and place.kind == "core_option": + owners = {k for k in owners if "libretro" in str(profiles[k].get("type") or "")} if not owners: owners = set(setting_readers(place.passes_to, profiles, relevant)) for key in sorted(owners): diff --git a/tests/test_launcher_evidence.py b/tests/test_launcher_evidence.py index 31d7d549f..bce6fe7e7 100644 --- a/tests/test_launcher_evidence.py +++ b/tests/test_launcher_evidence.py @@ -265,6 +265,34 @@ class Invariants(unittest.TestCase): self.assertEqual(_config_reads_without_build(path, {"config_reads": closed}), []) +class CoreOptions(unittest.TestCase): + def test_a_core_option_is_read_by_the_core_not_the_frontend(self) -> None: + """RetroDECK's retroarch component writes pcsx2_bios: the frontend + names the record, the core RetroArch runs reads the option.""" + profiles = { + "retroarch": {"emulator": "RetroArch", "type": "utility", "cores": ["retroarch"], + "config_reads": [{"file": "retroarch.cfg", "source_ref": "a.c:1", + "keys": [{"key": "system_directory", + "source_ref": "a.c:2"}]}]}, + "lrps2": {"emulator": "LRPS2", "type": "libretro", "cores": ["lrps2"], + "config_reads": [{"file": "core options", "source_ref": "main.cpp:1", + "keys": [{"key": "pcsx2_bios", + "source_ref": "main.cpp:2"}]}]}, + } + option = { + "emulator": "retroarch", "build": "libretro", "kind": "core_option", + "names": ["scph10000.bin"], "passes_to": "core option pcsx2_bios", + "installs": {"path": "$core_options", "source_ref": "prepare.sh:24"}, + "overrides": [], "source_ref": "rd_config/retroarch-core-options.cfg:515", + } + evidence = config_evidence(option, profiles, "retrodeck") + self.assertTrue(evidence.proven, evidence.missing) + self.assertEqual(evidence.readers, ("lrps2",)) + system = {**option, "kind": "passes_path", "passes_to": "retroarch.cfg system_directory", + "source_ref": "rd_config/retroarch.cfg:44"} + self.assertEqual(config_evidence(system, profiles, "retrodeck").readers, ("retroarch",)) + + class BuildRefs(unittest.TestCase): def test_reads_for_a_shipped_build_are_read_at_that_build(self) -> None: document = {