fix: dual-mode only what ROCKNIX runs both ways

The scraper declared every standalone package launched both ways,
reasoning that RetroArch carries every libretro core. package.mk says
otherwise: it adds ARMSX2 as armsx2-sa only (add_emu_core ps2 armsx2
armsx2-sa true), so the libretro build's pcsx2/resources entries
reached ROCKNIX's list as armsx2-sa files the standalone installs
itself. An emulator is now dual-mode only when package.mk also adds it
as a retroarch core: ten of the 63 standalone names.
This commit is contained in:
Abdessamad Derraz committed 2026-10-20 17:53:57 +02:00
1 parent a5d7a6572d
commit d92291684c
3 files changed
+58 -48

No files matched your search

-43
View File
@@ -135,67 +135,24 @@ standalone_cores:
- yabasanshiro
- yabasanshiro-sa
dual_mode_cores:
- aethersx2
- aethersx2-sa
- amiberry
- ares
- ares-sa
- armsx2
- armsx2-sa
- azahar
- azahar-sa
- bigpemu
- bigpemu-sa
- cemu
- cemu-sa
- daedalusx64
- daedalusx64-sa
- dolphin
- dolphin-sa
- drastic
- drastic-sa
- dsperate
- dsperate-sa
- duckstation
- duckstation-sa
- flycast
- flycast-sa
- gopher64
- gopher64-sa
- gzdoom
- gzdoom-sa
- hatari
- hatarisa
- heroic
- hypseus-singe
- mednafen
- melonds
- melonds-sa
- mupen64plus
- mupen64plus-sa
- nanoboyadvance
- nanoboyadvance-sa
- openbor
- pico-8
- ppsspp
- ppsspp-sa
- rpcs3
- rpcs3-sa
- scummvm
- scummvm-sa
- skyemu
- skyemu-sa
- steam
- supermodel
- supermodel-sa
- touchhle
- touchhle-sa
- vice
- vice-sa
- vita3k
- vita3k-sa
- xemu
- xemu-sa
- yabasanshiro
- yabasanshiro-sa
systems:
+39 -5
View File
@@ -43,6 +43,10 @@ SOURCE_TEMPLATE = (
# The branch a test or a manual run can still name. A scrape reads the tag
# of the release its YAML is labelled with.
SOURCE_URL = SOURCE_TEMPLATE.format(ref="next")
EMULATORS_MK_URL = (
"https://raw.githubusercontent.com/ROCKNIX/distribution/{ref}"
"/projects/ROCKNIX/packages/virtual/emulators/package.mk"
)
STANDALONE_TREE_URL = (
"https://api.github.com/repos/ROCKNIX/distribution/contents/"
"projects/ROCKNIX/packages/emulators/standalone?ref={ref}"
@@ -59,11 +63,26 @@ def standalone_emulators(package_names: list[str]) -> list[str]:
names: set[str] = set()
for package in package_names:
names.add(package)
stripped = re.sub(r"-?sa$", "", package)
if stripped and stripped != package:
stripped = _emulator_of(package)
if stripped != package:
names.add(stripped)
return sorted(names)
def _emulator_of(package: str) -> str:
return re.sub(r"-?sa$", "", package) or package
def dual_mode_emulators(standalone: list[str], package_mk: str) -> list[str]:
"""The standalone emulators RetroArch also runs as a core.
package.mk adds each launch option with `add_emu_core <system> <emulator>
<core> <default>`. Only an emulator also added as `retroarch <core>` is
launched both ways: ARMSX2 is added as armsx2-sa alone.
"""
retroarch = set(re.findall(r"^\s*add_emu_core\s+\S+\s+retroarch\s+(\S+)", package_mk, re.M))
return sorted(name for name in standalone if _emulator_of(name) in retroarch)
# ROCKNIX system key -> retrobios system ID
SYSTEM_SLUG_MAP = {
"xbox": "microsoft-xbox",
@@ -171,6 +190,21 @@ class Scraper(BaseScraper):
raise RuntimeError(f"no standalone emulator package at {url}")
return standalone_emulators(packages)
def _fetch_emulators_mk(self) -> str:
"""The package.mk that adds each emulator and core to es_systems."""
import urllib.error
import urllib.request
url = EMULATORS_MK_URL.format(ref=self.tag or "next")
try:
with urllib.request.urlopen(url, timeout=30) as resp:
text = resp.read().decode("utf-8")
except urllib.error.URLError as e:
raise ConnectionError(f"Failed to fetch {url}: {e}") from e
if "add_emu_core" not in text:
raise RuntimeError(f"no add_emu_core line in {url}")
return text
def validate_format(self, raw_data: str) -> bool:
"""Validate the rocknix-systems format."""
has_dict = re.search(r"^systems\s*=\s*\{", raw_data, re.MULTILINE) is not None
@@ -236,9 +270,9 @@ class Scraper(BaseScraper):
# emulators ROCKNIX packages beside it.
"cores": ["retroarch", *standalone],
"standalone_cores": standalone,
# RetroArch carries every libretro core beside them, so an
# emulator with a libretro build is launched both ways.
"dual_mode_cores": list(standalone),
# Launched both ways only where package.mk also adds the
# emulator as a RetroArch core.
"dual_mode_cores": dual_mode_emulators(standalone, self._fetch_emulators_mk()),
"systems": systems,
}
+19
View File
@@ -414,6 +414,25 @@ class RocknixRunsItsStandaloneEmulators(unittest.TestCase):
["duckstation", "duckstation-sa", "hatari", "hatarisa", "openbor"],
)
def test_only_an_emulator_retroarch_also_runs_is_dual(self):
"""Every standalone package was declared launched both ways, so
ARMSX2's libretro layout reached ROCKNIX, whose package.mk adds it
as armsx2-sa only (add_emu_core ps2 armsx2 armsx2-sa true)."""
from scraper.rocknix_scraper import dual_mode_emulators
package_mk = (
" add_emu_core psx retroarch duckstation false\n"
" add_emu_core psx duckstation duckstation-sa true\n"
" add_emu_core ps2 armsx2 armsx2-sa true\n"
" add_emu_core atarist retroarch hatari false\n"
)
standalone = ["armsx2", "armsx2-sa", "duckstation", "duckstation-sa",
"hatari", "hatarisa"]
self.assertEqual(
dual_mode_emulators(standalone, package_mk),
["duckstation", "duckstation-sa", "hatari", "hatarisa"],
)
def test_the_platform_file_is_read_at_its_release(self):
import yaml