fix: keep RomM files where its player reads them

RomM lists a platform's firmware folder without descending (base_handler.py:1002, recursive=False) and EmulatorJS writes the chosen file, or each zip member, under its bare name. 543 files of the RomM pack sat below a folder where no core could read them. The registry now marks RomM's folder flat, and such files are omitted with the reason below_platform_folder in the manifest and the installer.
This commit is contained in:
Abdessamad Derraz committed 2026-10-19 06:57:36 +02:00
1 parent c7f18e84c3
commit 7d1e9f8816
9 files changed
+5665 -7658

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ param(
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "8ca436e66f04f3fa202350f84afa0fc339bf60953022509b9d1e5177830b8636"
$defaultInstallSha256 = "1a10ac215c60706699d267fcfa31c4947d6aa792b46455e078a5861fa8c5e2ea"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+1
View File
@@ -102,6 +102,7 @@ OMISSION_REASONS = {
"external": "external",
"user_provided": "user provided",
"no_platform_slug": "no platform folder",
"below_platform_folder": "below the platform folder",
}
_SHA1_RE = re.compile(r"^[0-9a-fA-F]{40}$")
_SHA256_RE = re.compile(r"^[0-9a-fA-F]{64}$")
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER=""
TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="8ca436e66f04f3fa202350f84afa0fc339bf60953022509b9d1e5177830b8636"
DEFAULT_INSTALL_SHA256="1a10ac215c60706699d267fcfa31c4947d6aa792b46455e078a5861fa8c5e2ea"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+5559 -7651
View File
File diff suppressed because it is too large. Load diff
+6
View File
@@ -450,6 +450,12 @@ platforms:
contribution: platform support
pr: 37
inherits_from: emulatorjs
# RomM lists a firmware folder without descending into it
# (backend/handler/filesystem/base_handler.py:1002, recursive=False), and
# EmulatorJS writes the chosen file, or each member of a zip, under its
# bare name (data/src/emulator.js:713-722). A file below the platform
# folder never reaches a core.
firmware_folder_flat: true
target_scraper: null
target_source: null
install:
+4 -2
View File
@@ -154,7 +154,8 @@
"not_found",
"external",
"user_provided",
"no_platform_slug"
"no_platform_slug",
"below_platform_folder"
]
},
"cores": {
@@ -712,7 +713,8 @@
"not_found",
"external",
"user_provided",
"no_platform_slug"
"no_platform_slug",
"below_platform_folder"
]
},
"cores": {
+1 -1
View File
@@ -3859,7 +3859,7 @@ def _record_unplaceable(unplaceable: list[dict], record_omission: Callable[...,
for u in unplaceable:
record_omission(
u.get("path") or u.get("name", ""), u, u.get("system") or "",
"no_platform_slug", [u.get("emulator", "")],
u.get("unplaceable", "no_platform_slug"), [u.get("emulator", "")],
)
+10 -2
View File
@@ -678,6 +678,7 @@ class ExtraPlacement:
self.slug_based, self.sys_to_slug = _detect_slug_structure(config)
self.platform_systems = set(config.get("systems", {}).keys())
self.native_systems = native_slug_systems(config)
self.flat = bool(config.get("firmware_folder_flat"))
self.norm_map = (
{_norm_system_id(sid): sid for sid in self.platform_systems}
if self.slug_based
@@ -697,11 +698,15 @@ class ExtraPlacement:
entry, self.profiles, self.platform_systems, self.norm_map,
self.sys_to_slug, self.native_systems,
)
if not slug:
if not slug or self.nested(dest):
return None
dest = f"{slug}/{dest}"
return dest, (f"{self.prefix}/{dest}" if self.prefix else dest)
def nested(self, dest: str) -> bool:
"""True when the file would sit below a folder the frontend lists flat."""
return self.slug_based and self.flat and "/" in dest
def _collect_emulator_extras(
config: dict,
@@ -802,7 +807,10 @@ def _collect_emulator_extras(
continue
if placed is None:
if unplaceable is not None:
unplaceable.append(u)
unplaceable.append(
{**u, "unplaceable": "below_platform_folder"}
if placement.nested(dest) else u
)
continue
dest, full_dest = placed
if claimants is not None:
+82
View File
@@ -137,5 +137,87 @@ class RegionKeysForEveryClaimant(unittest.TestCase):
self.assertEqual(claimants, {"one", "two"}, extra_dests)
class FlatFirmwareFolder(unittest.TestCase):
"""RomM lists a platform's firmware folder without descending, and
EmulatorJS writes each file under its bare name. 543 files of the RomM
pack sat below the folder, where no core could ever read them."""
PROFILE = (
"emulator: Psx\ntype: libretro\nsystems: [psx]\ncores: [psx]\nfiles:\n"
" - name: flat.bin\n required: false\n"
" - name: deep.bin\n path: core/bios/deep.bin\n required: false\n"
)
def _manifest(self, flat: bool) -> dict:
with tempfile.TemporaryDirectory() as tmp:
previous = os.getcwd()
os.chdir(tmp)
try:
for d in ("emulators", "platforms", "bios/Sony"):
Path(d).mkdir(parents=True)
files = {}
for name in ("flat.bin", "deep.bin", "scph5501.bin"):
payload = name.encode()
Path(f"bios/Sony/{name}").write_bytes(payload)
sha1 = hashlib.sha1(payload).hexdigest()
files[sha1] = {
"path": f"bios/Sony/{name}", "name": name, "size": len(payload),
"sha1": sha1, "md5": hashlib.md5(payload).hexdigest(),
"sha256": hashlib.sha256(payload).hexdigest(), "crc32": "00000001",
}
db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
config = {
"platform": "Flat", "verification_mode": "md5",
"base_destination": "bios", "cores": ["psx"],
"systems": {
"psx": {"files": [{"name": "scph5501.bin",
"destination": "psx/scph5501.bin",
"md5": hashlib.md5(b"scph5501.bin").hexdigest()}]},
"snes": {"files": [{"name": "s.bin", "destination": "snes/s.bin",
"md5": "1" * 32}]},
},
}
Path("platforms/flat.yml").write_text(yaml.dump(config))
entry = {"status": "active"}
if flat:
entry["firmware_folder_flat"] = True
Path("platforms/_registry.yml").write_text(
yaml.dump({"platforms": {"flat": entry}})
)
Path("emulators/psx.yml").write_text(self.PROFILE)
common._platform_config_cache.clear()
common._emulator_profiles_cache.clear()
profiles = common.load_emulator_profiles("emulators")
return builder.generate_manifest(
"flat", "platforms", db, "bios", "platforms/_registry.yml",
emulators_dir="emulators", emu_profiles=profiles, offline=True,
)
finally:
common._platform_config_cache.clear()
common._emulator_profiles_cache.clear()
os.chdir(previous)
def test_a_nested_file_is_omitted_with_its_reason(self):
manifest = self._manifest(flat=True)
dests = {entry["dest"] for entry in manifest["files"]}
self.assertIn("psx/flat.bin", dests)
self.assertFalse(any("deep.bin" in d for d in dests), dests)
reasons = {o["name"]: o["reason"] for o in manifest["omitted_files"]}
self.assertEqual(reasons.get("deep.bin"), "below_platform_folder")
def test_a_folder_read_recursively_keeps_it(self):
dests = {entry["dest"] for entry in self._manifest(flat=False)["files"]}
self.assertIn("psx/core/bios/deep.bin", dests)
def test_the_romm_pack_holds_nothing_below_a_folder(self):
manifest = REPO_ROOT / "install" / "romm.json"
if not manifest.exists():
self.skipTest("install/romm.json not generated")
import json
files = json.loads(manifest.read_text(encoding="utf-8"))["files"]
self.assertEqual([f["dest"] for f in files if f["dest"].count("/") > 1], [])
if __name__ == "__main__":
unittest.main()