mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 20:29:06 -05:00
feat: run retrodeck dual-mode cores as libretro
This commit is contained in:
commit
7a5bc1d2e3
5 files changed
+21916
-11678
No files matched your search
@@ -120,7 +120,7 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
|
||||
| Recalbox | 351/351 | 2,762/2,933 | MD5 hash |
|
||||
| RetroArch | 526/526 | 7,691/7,733 | file presence |
|
||||
| RetroBat | 348/348 | 4,752/9,218 | MD5 hash |
|
||||
| RetroDECK | 2,007/2,008 | 6,287/6,547 | MD5 hash |
|
||||
| RetroDECK | 2,007/2,008 | 6,480/6,741 | MD5 hash |
|
||||
| RetroPie * | 532/532 | 7,858/12,489 | file presence |
|
||||
| RomM | 383/383 | 83/860 | MD5 hash |
|
||||
|
||||
@@ -209,4 +209,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
|
||||
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
|
||||
The reasoning, and where it is weakest, is in [the project's legal position](https://abdess.github.io/retrobios/wiki/legal/).
|
||||
|
||||
*Auto-generated on 2026-10-22T19:15:47Z*
|
||||
*Auto-generated on 2026-10-22T20:58:47Z*
|
||||
+21809
-11671
File diff suppressed because it is too large.
Load diff
@@ -44,6 +44,14 @@ standalone_cores:
|
||||
- vita3k
|
||||
- xemu
|
||||
- xroar
|
||||
dual_mode_cores:
|
||||
- azahar
|
||||
- cemu
|
||||
- dolphin
|
||||
- mame
|
||||
- melonds
|
||||
- pcsx2
|
||||
- ppsspp
|
||||
systems:
|
||||
triforce:
|
||||
files:
|
||||
|
||||
@@ -96,6 +96,25 @@ def es_systems_libretro_systems(text: str) -> dict[str, list[str]]:
|
||||
if match:
|
||||
found.setdefault(match.group(1), set()).add(folder)
|
||||
return {core: sorted(folders) for core, folders in sorted(found.items())}
|
||||
|
||||
|
||||
def component_modes(
|
||||
components: list[str], libretro_systems: dict[str, list[str]]
|
||||
) -> tuple[list[str], list[str]]:
|
||||
"""(standalone_cores, dual_mode_cores) of RetroDECK's emulator components.
|
||||
|
||||
Every component but retroarch is an emulator RetroDECK launches on its
|
||||
own (its component_launcher.sh execs the emulator's binary). One whose name
|
||||
is also a core an ES-DE command loads through RetroArch is offered both
|
||||
ways: es_systems.xml lists "Azahar (Standalone)" and "Azahar"
|
||||
(azahar_libretro.so) for n3ds. The core itself ships, RetroArch's cores
|
||||
coming whole from the buildbot's nightly RetroArch_cores.7z
|
||||
(retroarch/component_recipe.json:250-262 at components fcd0d729).
|
||||
"""
|
||||
standalone = [c for c in components if c != "retroarch"]
|
||||
return standalone, [c for c in standalone if c in libretro_systems]
|
||||
|
||||
|
||||
NON_EMULATOR_COMPONENTS = {
|
||||
"framework",
|
||||
"es-de",
|
||||
@@ -533,6 +552,9 @@ class Scraper(BaseScraper):
|
||||
sys_entry["files"].append(requirement_entry(req))
|
||||
|
||||
version = fetch_github_latest_version("RetroDECK/RetroDECK")
|
||||
# The ROM folders each libretro core runs for: its save folders.
|
||||
libretro_systems = self._fetch_libretro_systems()
|
||||
standalone, dual = component_modes(cores, libretro_systems)
|
||||
|
||||
return {
|
||||
"platform": "RetroDECK",
|
||||
@@ -547,12 +569,10 @@ class Scraper(BaseScraper):
|
||||
"hash_type": "md5",
|
||||
"verification_mode": "md5",
|
||||
"cores": cores,
|
||||
# Each component is one emulator RetroDECK ships and launches on
|
||||
# its own, and retroarch is the one that runs cores.
|
||||
"standalone_cores": [c for c in cores if c != "retroarch"],
|
||||
"standalone_cores": standalone,
|
||||
**({"dual_mode_cores": dual} if dual else {}),
|
||||
"systems": systems,
|
||||
# The ROM folders each libretro core runs for: its save folders.
|
||||
"libretro_systems": self._fetch_libretro_systems(),
|
||||
"libretro_systems": libretro_systems,
|
||||
"launchers": extract_launchers(cores, self.component_file),
|
||||
}
|
||||
|
||||
|
||||
@@ -472,6 +472,78 @@ class RetroDeckCoresAreItsComponents(unittest.TestCase):
|
||||
self.assertNotIn("cores", registry["platforms"]["retrodeck"])
|
||||
|
||||
|
||||
class RetroDeckComponentModes(unittest.TestCase):
|
||||
"""Every RetroDECK component was written standalone only: Azahar, whose
|
||||
ES-DE system also loads azahar_libretro.so, never got its libretro
|
||||
files, which the core reads below its save folder."""
|
||||
|
||||
# Commands as RetroDECK/ES-DE 15e1b236 writes them in
|
||||
# resources/systems/linux/es_systems.xml (n3ds at 1379-1383, psx at
|
||||
# 1843 and 1847). The commented-out DuckStation core is the fixture's own.
|
||||
ES_SYSTEMS = """\
|
||||
<?xml version="1.0"?>
|
||||
<systemList>
|
||||
<system><name>n3ds</name><path>%ROMPATH%/n3ds</path>
|
||||
<command label="Azahar (Standalone)">%EMULATOR_AZAHAR% %ROM%</command>
|
||||
<command label="Azahar">%EMULATOR_RETROARCH% -L %CORE_RETROARCH%/azahar_libretro.so %ROM%</command>
|
||||
<command label="Citra">%EMULATOR_RETROARCH% -L %CORE_RETROARCH%/citra_libretro.so %ROM%</command>
|
||||
</system>
|
||||
<system><name>psx</name><path>%ROMPATH%/psx</path>
|
||||
<command label="SwanStation">%EMULATOR_RETROARCH% -L %CORE_RETROARCH%/swanstation_libretro.so %ROM%</command>
|
||||
<!-- <command label="DuckStation">%EMULATOR_RETROARCH% -L %CORE_RETROARCH%/duckstation_libretro.so %ROM%</command> -->
|
||||
<command label="DuckStation (Legacy) (Standalone)">%EMULATOR_DUCKSTATION% -batch %ROM%</command>
|
||||
</system>
|
||||
</systemList>
|
||||
"""
|
||||
|
||||
def _config(self) -> dict:
|
||||
from scraper import retrodeck_scraper as rd
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
for component in ("azahar", "duckstation", "es-de", "retroarch"):
|
||||
(Path(tmp) / component).mkdir()
|
||||
(Path(tmp) / component / "component_manifest.json").write_text(
|
||||
json.dumps({component: {"system": component}})
|
||||
)
|
||||
scraper = rd.Scraper(manifests_dir=tmp)
|
||||
systems = rd.es_systems_libretro_systems(self.ES_SYSTEMS)
|
||||
with mock.patch.object(rd, "fetch_github_latest_version", return_value="0.10.10b"), \
|
||||
mock.patch.object(rd, "extract_launchers", return_value=[]), \
|
||||
mock.patch.object(rd.Scraper, "_fetch_libretro_systems", return_value=systems):
|
||||
return scraper.generate_platform_yaml()
|
||||
|
||||
def test_a_component_es_de_also_runs_as_a_core_is_dual_mode(self):
|
||||
config = self._config()
|
||||
self.assertEqual(config["cores"], ["azahar", "duckstation", "retroarch"])
|
||||
self.assertEqual(config["standalone_cores"], ["azahar", "duckstation"])
|
||||
self.assertEqual(config["dual_mode_cores"], ["azahar"])
|
||||
|
||||
def test_a_commented_out_core_command_offers_nothing(self):
|
||||
"""duckstation_libretro.so sits in a comment: DuckStation runs standalone only."""
|
||||
config = self._config()
|
||||
self.assertNotIn("duckstation", config["dual_mode_cores"])
|
||||
self.assertNotIn("duckstation", config["libretro_systems"])
|
||||
|
||||
def test_a_core_without_a_component_is_not_a_component(self):
|
||||
"""citra_libretro.so runs through RetroArch, and RetroDECK ships no citra build."""
|
||||
from scraper.retrodeck_scraper import component_modes
|
||||
|
||||
standalone, dual = component_modes(
|
||||
["azahar", "retroarch"], {"azahar": ["n3ds"], "citra": ["n3ds"]}
|
||||
)
|
||||
self.assertEqual((standalone, dual), (["azahar"], ["azahar"]))
|
||||
|
||||
def test_the_platform_file_carries_the_modes(self):
|
||||
import yaml
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
platform = yaml.safe_load((root / "platforms" / "retrodeck.yml").read_text())
|
||||
dual = set(platform.get("dual_mode_cores") or [])
|
||||
self.assertIn("azahar", dual)
|
||||
self.assertLessEqual(dual, set(platform["standalone_cores"]))
|
||||
self.assertLessEqual(dual, set(platform["libretro_systems"]))
|
||||
|
||||
|
||||
class BizHawkRunsAresForN64Only(unittest.TestCase):
|
||||
"""BizHawk embeds ares as Ares64, its N64 core. Mapping it to the ares
|
||||
profile claimed thirty systems and accused FirmwareDatabase.cs of a
|
||||
|
||||
Reference in new issue
Block a user