feat: read RomM cores from its player maps

RomM merges a nightly core map into the stable one when netplay is on, so it launches azahar, bsnes and genesis_plus_gx_wide, which the inherited EmulatorJS list left out. The scraper now reads both maps from the tagged frontend source and fails if either is missing. The cited mednafen_pce mapping is at index.ts:481-482 in 5.4.0.
This commit is contained in:
Abdessamad Derraz committed 2026-10-19 06:57:32 +02:00
1 parent 6553833a26
commit c7f18e84c3
3 files changed
+137 -1

No files matched your search

+52
View File
@@ -7,6 +7,58 @@ base_destination: bios
hash_type: sha1
verification_mode: md5
hash_rule: size_and_any_hash
cores:
- a5200
- azahar
- beetle_vb
- bsnes
- cap32
- crocods
- desmume
- desmume2015
- dosbox_pure
- fbalpha2012_cps1
- fbalpha2012_cps2
- fbneo
- fceumm
- freeintv
- fuse
- gambatte
- gearcoleco
- genesis_plus_gx
- genesis_plus_gx_wide
- handy
- mame2003
- mame2003_plus
- mednafen_ngp
- mednafen_pce
- mednafen_pcfx
- mednafen_psx_hw
- mednafen_wswan
- melonds
- mgba
- mupen64plus_next
- nestopia
- opera
- parallel_n64
- pcsx_rearmed
- picodrive
- ppsspp
- prboom
- prosystem
- puae
- same_cdi
- smsplus
- snes9x
- stella2014
- vice_x128
- vice_x64
- vice_x64sc
- vice_xpet
- vice_xplus4
- vice_xvic
- virtualjaguar
- yabause
systems:
3do:
files:
+43 -1
View File
@@ -23,12 +23,14 @@ Slugs are IGDB-style platform identifiers.
from __future__ import annotations
import json
import re
import sys
try:
from .base_scraper import (
BaseScraper,
BiosRequirement,
fetch_bytes,
fetch_github_latest_version,
requirement_entry,
)
@@ -36,6 +38,7 @@ except ImportError:
from base_scraper import (
BaseScraper,
BiosRequirement,
fetch_bytes,
fetch_github_latest_version,
requirement_entry,
)
@@ -49,6 +52,42 @@ SOURCE_URL = (
"/backend/models/fixtures/known_bios_files.json"
)
# The player's core table. _EJS_CORES_MAP is what EmulatorJS 4.2.3 runs, and
# _EJS_NIGHTLY_CORES_MAP adds the nightly cores RomM merges in when netplay is
# enabled (getSupportedEJSCores). Both are cores RomM can launch, so the pack
# carries what either needs: azahar, bsnes and genesis_plus_gx_wide exist only
# in the nightly map.
CORES_URL = (
"https://raw.githubusercontent.com/rommapp/romm/{tag}"
"/frontend/src/utils/index.ts"
)
CORE_MAPS = ("_EJS_CORES_MAP", "_EJS_NIGHTLY_CORES_MAP")
def parse_player_cores(source: str) -> list[str]:
"""Every core named by the player's core maps, sorted.
A map missing from the file, or one naming no core, means the source has
changed shape: that raises instead of publishing a shorter list.
"""
cores: set[str] = set()
for name in CORE_MAPS:
match = re.search(
rf"const {name}\b[^=]*=\s*\{{(.*?)^\}}", source, re.S | re.M
)
if match is None:
raise RuntimeError(f"{name} not found in the RomM player source")
found = set(re.findall(r"\[([^\]]*)\]", match.group(1)))
named = {
core
for values in found
for core in re.findall(r'"([A-Za-z0-9_]+)"', values)
}
if not named:
raise RuntimeError(f"{name} names no core")
cores |= named
return sorted(cores)
# IGDB slug -> retrobios system ID
SLUG_MAP: dict[str, str] = {
"3do": "3do",
@@ -112,7 +151,7 @@ SLUG_MAP: dict[str, str] = {
# Slugs whose player runs the same core as another slug and reads firmware
# from its own folder. RomM keys the fixture by tg16 only, but its player maps
# both tg16 and turbografx-cd to mednafen_pce (frontend/src/utils/index.ts:540-541)
# both tg16 and turbografx-cd to mednafen_pce (frontend/src/utils/index.ts:481-482)
# and lists firmware per platform folder (backend/handler/filesystem/
# firmware_handler.py get_firmware_fs_structure), so a CD library without the
# system cards under its own slug cannot boot a disc.
@@ -237,6 +276,9 @@ class Scraper(BaseScraper):
"verification_mode": "md5",
# Firmware.verify_file_hashes: size, then md5, sha1 or crc.
"hash_rule": "size_and_any_hash",
"cores": parse_player_cores(
fetch_bytes(CORES_URL.format(tag=self.tag)).decode("utf-8")
),
"systems": systems,
}
+42
View File
@@ -4876,6 +4876,48 @@ class AHashListIsReadOneWay(unittest.TestCase):
class RommRunsTheCoresItsPlayerNames(unittest.TestCase):
"""RomM's player merges a nightly core map into the stable one when netplay
is on. Inheriting EmulatorJS's list left azahar, bsnes and
genesis_plus_gx_wide out of the RomM pack, though RomM launches them."""
SOURCE = """
const _EJS_CORES_MAP: Record<string, string[]> = {
"3do": ["opera"],
arcade: [
"mame2003_plus",
"fbneo",
],
} as const;
const _EJS_NIGHTLY_CORES_MAP: Record<string, string[]> = {
"3ds": ["azahar"],
snes: ["snes9x", "bsnes"],
};
"""
def test_both_maps_are_read(self):
from scripts.scraper.romm_scraper import parse_player_cores
self.assertEqual(
parse_player_cores(self.SOURCE),
["azahar", "bsnes", "fbneo", "mame2003_plus", "opera", "snes9x"],
)
def test_a_missing_map_raises(self):
from scripts.scraper.romm_scraper import parse_player_cores
source = self.SOURCE.replace("_EJS_NIGHTLY_CORES_MAP", "_RENAMED")
with self.assertRaises(RuntimeError):
parse_player_cores(source)
def test_the_platform_file_carries_the_nightly_cores(self):
from common import load_platform_config
cores = set(load_platform_config("romm", str(ROOT / "platforms"))["cores"])
self.assertTrue({"azahar", "bsnes", "genesis_plus_gx_wide"} <= cores)
class RommNeoGeoFoldersGetTheirBios(unittest.TestCase):
"""RomM runs fbneo for neogeoaes and neogeomvs as for arcade and reads
firmware per platform folder, but the fixture gives neogeo.zip to arcade