From 5883df80af35f3e2ba02b38633d2786e82807edf Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:10:24 +0100
Subject: [PATCH 01/83] fix: verify --emulator counts release assets
generate_emulator_pack resolves with offline=offline and fetches a release asset the cache lacks, while verify_emulator resolved offline and called it missing. verify --emulator now applies pending_release_asset as verify --platform does, accepts --offline, and the pipeline compares emulator packs offline on both sides.
---
scripts/pipeline.py | 28 +++++++++-----
scripts/verify.py | 40 ++++++++++++++++----
tests/test_verify_release_asset.py | 61 +++++++++++++++++++++++++++++-
wiki/tools.md | 2 +-
4 files changed, 111 insertions(+), 20 deletions(-)
diff --git a/scripts/pipeline.py b/scripts/pipeline.py
index 2c2f23ede..244c19aa5 100644
--- a/scripts/pipeline.py
+++ b/scripts/pipeline.py
@@ -562,6 +562,7 @@ def check_emulator_packs(
comparison holds them together. No archive is written and no file read.
"""
import generate_pack # noqa: PLC0415
+ import packresolve # noqa: PLC0415
import verify # noqa: PLC0415
from common import ( # noqa: PLC0415
ProfileSelectionError,
@@ -580,16 +581,23 @@ def check_emulator_packs(
def compare(names: list[str], standalone: bool, label: str, **narrowing: object) -> bool:
record = generate_pack.PackRecord()
- with contextlib.redirect_stdout(io.StringIO()), \
- contextlib.redirect_stderr(io.StringIO()):
- generate_pack.generate_emulator_pack(
- names, emulators_dir, db, "bios", "", standalone, zip_contents,
- offline=True, platforms_dir=platforms_dir, record=record, **narrowing,
- )
- report = verify.verify_emulator(
- names, emulators_dir, db, standalone, platforms_dir=platforms_dir,
- **narrowing,
- )
+ was_offline = packresolve._OFFLINE
+ # The pack is built offline: verify counts a release asset the cache
+ # lacks the same way, missing, as the narrowed-pack step does.
+ packresolve.set_offline(True)
+ try:
+ with contextlib.redirect_stdout(io.StringIO()), \
+ contextlib.redirect_stderr(io.StringIO()):
+ generate_pack.generate_emulator_pack(
+ names, emulators_dir, db, "bios", "", standalone, zip_contents,
+ offline=True, platforms_dir=platforms_dir, record=record, **narrowing,
+ )
+ report = verify.verify_emulator(
+ names, emulators_dir, db, standalone, platforms_dir=platforms_dir,
+ **narrowing,
+ )
+ finally:
+ packresolve.set_offline(was_offline)
lines = _set_difference_lines(
label, set(report["pack_destinations"]), set(record.files)
)
diff --git a/scripts/verify.py b/scripts/verify.py
index f47c7f011..9fbdfa9a3 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -2058,7 +2058,7 @@ def verify_emulator(
it and every member it carries are optional, as the builder leaves them.
"""
from packextras import expand_agnostic_entries
- from packresolve import resolve_file
+ from packresolve import pending_release_asset, resolve_file, run_is_offline
from packpaths import (
_archive_destination,
_register_path,
@@ -2084,6 +2084,16 @@ def verify_emulator(
validation_index = _build_validation_index(selected_profiles)
data_registry = load_data_dir_registry(platforms_dir)
+ def pending(entry: dict, local_path: str | None, status: str) -> tuple[str | None, str]:
+ # Read from disk and the cache, as _resolve_for_platform does: a
+ # release asset the cache lacks is fetched by an online build
+ # (generate_emulator_pack resolves with offline=offline).
+ if status in ("not_found", "hash_mismatch") and not run_is_offline():
+ asset = pending_release_asset(entry, db)
+ if asset:
+ return asset, RELEASE_ASSET_PENDING
+ return local_path, status
+
details = []
file_status: dict[str, str] = {}
file_severity: dict[str, str] = {}
@@ -2223,14 +2233,15 @@ def verify_emulator(
archive = file_entry.get("archive")
if archive and archive not in seen_archives:
seen_archives.add(archive)
- local_path, resolve_status = resolve_file(
- archive_entry(archive, files),
+ own_entry = archive_entry(archive, files)
+ local_path, resolve_status = pending(own_entry, *resolve_file(
+ own_entry,
db,
DEFAULT_BIOS_DIR,
zip_contents,
data_dir_registry=data_registry,
offline=True,
- )
+ ))
required = any(
f.get("archive") == archive and f.get("required", True)
for f in files
@@ -2254,6 +2265,8 @@ def verify_emulator(
"required": required,
"path": local_path,
}
+ if resolve_status == RELEASE_ASSET_PENDING:
+ result["release_asset"] = local_path
else:
result = {
"name": archive,
@@ -2314,7 +2327,7 @@ def verify_emulator(
dest_hint = file_entry.get("path", "")
# The emulator pack's resolution, release assets included.
- local_path, resolve_status = resolve_file(
+ local_path, resolve_status = pending(file_entry, *resolve_file(
{**with_archive_members(file_entry, files), "source_profile": emu_name},
db,
DEFAULT_BIOS_DIR,
@@ -2322,7 +2335,7 @@ def verify_emulator(
dest_hint=dest_hint,
data_dir_registry=data_registry,
offline=True,
- )
+ ))
if resolve_status in ("not_found", "user_provided", "external"):
local_path = None
name = file_entry.get("name", "")
@@ -2332,6 +2345,15 @@ def verify_emulator(
stored = _storage_verdict(file_entry, emulator_pack=True)
if stored is not None:
result = stored
+ elif resolve_status == RELEASE_ASSET_PENDING:
+ result = {
+ "name": name,
+ "status": Status.OK,
+ "required": required,
+ "path": local_path,
+ "release_asset": local_path,
+ "reason": "release asset, fetched when the pack is built",
+ }
elif not local_path:
result = {"name": name, "status": Status.MISSING, "required": required}
# An entry the profile documents as unsourceable is absent by
@@ -2582,6 +2604,10 @@ def print_emulator_result(result: dict, verbose: bool = False) -> None:
if unsourceable:
parts.append(f"{unsourceable} unsourceable")
print(f"{label}: {', '.join(parts)} [{mode}]")
+ fetched = sorted({d["name"] for d in result["details"] if d.get("release_asset")})
+ if fetched:
+ shown = ", ".join(fetched[:10]) + (f" (+{len(fetched) - 10})" if len(fetched) > 10 else "")
+ print(f" Release assets fetched when the pack is built ({len(fetched)}): {shown}")
seen = set()
for d in result["details"]:
@@ -2712,8 +2738,6 @@ def _refuse_mode_flags(args: argparse.Namespace, parser: argparse.ArgumentParser
"--destinations describes the full pack and is incompatible with --system"),
(args.destinations and not (args.platform or args.all),
"--destinations requires --platform or --all"),
- (args.offline and not (args.platform or args.all),
- "--offline requires --platform or --all"),
# Game data is categorized against a platform's list and its cores.
(getattr(args, "no_game_data", False) and not (args.platform or args.all),
"--no-game-data requires --platform or --all"),
diff --git a/tests/test_verify_release_asset.py b/tests/test_verify_release_asset.py
index 58150b375..55afa91f0 100644
--- a/tests/test_verify_release_asset.py
+++ b/tests/test_verify_release_asset.py
@@ -29,7 +29,7 @@ import common # noqa: E402
import generate_db # noqa: E402
import generate_pack as builder # noqa: E402
import packresolve # noqa: E402
-from verify import Status, verify_platform # noqa: E402
+from verify import Status, verify_emulator, verify_platform # noqa: E402
PAYLOAD = b"a firmware image the repository does not commit"
SHA1 = hashlib.sha1(PAYLOAD).hexdigest()
@@ -176,6 +176,65 @@ class CoreExtraReleaseAssetNotCached(ReleaseAssetNotCached):
test_the_online_build_packs_it = None
+class EmulatorReleaseAssetNotCached(ReleaseAssetNotCached):
+ """verify --emulator against generate_emulator_pack: the emulator pack
+ resolves with offline=offline and fetched the asset online, while verify
+ forced offline resolution and called it missing."""
+
+ def setUp(self):
+ super().setUp()
+ self.profile = {
+ "emulator": "Big Core", "type": "libretro", "systems": ["sys"],
+ "files": [{"name": "big.bin", "required": True, "sha1": SHA1}],
+ }
+ Path("emulators/bigcore.yml").write_text(yaml.dump(self.profile))
+ common._emulator_profiles_cache.clear()
+
+ def _report(self) -> dict:
+ common._emulator_profiles_cache.clear()
+ return verify_emulator(["bigcore"], "emulators", self.db, platforms_dir="platforms")
+
+ def _entry(self) -> dict:
+ return next(d for d in self._report()["details"] if d["name"] == "big.bin")
+
+ def test_counted_as_fetched_when_the_pack_is_built(self):
+ entry = self._entry()
+ self.assertEqual(entry["status"], Status.OK)
+ self.assertEqual(entry["release_asset"], REGISTERED[0])
+
+ def test_its_path_is_a_pack_destination(self):
+ self.assertIn("big.bin", self._report()["pack_destinations"])
+
+ def test_offline_counts_it_missing(self):
+ packresolve.set_offline(True)
+ self.assertEqual(self._entry()["status"], Status.MISSING)
+ self.assertNotIn("big.bin", self._report()["pack_destinations"])
+
+ def test_an_asset_with_other_content_is_not_counted(self):
+ self.profile["files"][0]["sha1"] = "0" * 40
+ Path("emulators/bigcore.yml").write_text(yaml.dump(self.profile))
+ self.assertEqual(self._entry()["status"], Status.MISSING)
+
+ def test_an_archive_asset_is_counted_too(self):
+ self.profile["files"] = [{"name": "inner.rom", "archive": "big.bin"}]
+ Path("emulators/bigcore.yml").write_text(yaml.dump(self.profile))
+ self.assertIn("big.bin", self._report()["pack_destinations"])
+
+ def test_the_online_build_packs_it(self):
+ cache = Path("cache/big.bin")
+ cache.parent.mkdir()
+ cache.write_bytes(PAYLOAD)
+ record = builder.PackRecord()
+ with mock.patch.object(
+ packresolve, "fetch_large_file", return_value=str(cache)
+ ):
+ builder.generate_emulator_pack(
+ ["bigcore"], "emulators", self.db, "bios", "out",
+ offline=False, platforms_dir="platforms", record=record,
+ )
+ self.assertEqual(set(record.files), set(self._report()["pack_destinations"]))
+
+
class OfflinePipelineVerifiesOffline(unittest.TestCase):
"""The offline pipeline builds packs without release assets: its verify
step has to count them the same way, or step 5 compares two answers."""
diff --git a/wiki/tools.md b/wiki/tools.md
index dab60e5b0..78dfb21b1 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -154,7 +154,7 @@ python scripts/verify.py --platform recalbox --region us # regional priority l
python scripts/verify.py --platform emuelec --no-game-data # the firmware-only pack, game data named
python scripts/verify.py --emulator mame --required-only # the pack built with --required-only
python scripts/verify.py --all --destinations tmp/paths.json # also write the paths each pack holds
-python scripts/verify.py --all --offline # a release asset the cache lacks counts missing, as in an offline build
+python scripts/verify.py --all --offline # a release asset the cache lacks counts missing, as in an offline build (any mode, --emulator included)
python scripts/verify.py --list-platforms # list all platforms
python scripts/verify.py --list-emulators # list all emulators
python scripts/verify.py --list-systems # list all systems
From c634a282d821fc4d0335f06f74da0c3259ba1ae3 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:11:28 +0100
Subject: [PATCH 02/83] fix: a shipped twin path is untested, not excluded
A path declared twice, once unpinned and once with a pin the copy misses: the builder wrote excluded over the file it shipped, in either order of the two systems. It now counts the path untested, as verify does, and lists no exclusion.
---
scripts/generate_pack.py | 8 ++-
tests/test_twin_declaration_status.py | 98 +++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 1 deletion(-)
create mode 100644 tests/test_twin_declaration_status.py
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index 354964481..458fa968b 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -1135,7 +1135,10 @@ def generate_pack(
config.get("hash_rule", ""),
)
if refusal:
- file_status[dedup_key] = "excluded"
+ # An earlier declaration of this path shipped a file this
+ # one refuses: it is in the pack, untested as verify
+ # counts it, not excluded.
+ file_status[dedup_key] = "untested" if already_packed else "excluded"
file_reasons[dedup_key] = refusal
continue
if not hash_mismatch_excludes_file(verification_mode) and (
@@ -1171,6 +1174,9 @@ def generate_pack(
if already_packed:
continue
+ if file_status.get(dedup_key) == "excluded":
+ # An earlier declaration refused the file this one ships.
+ file_status[dedup_key] = "untested"
seen_destinations.add(dedup_key)
_register_path(dedup_key, seen_destinations, seen_parents)
if case_insensitive:
diff --git a/tests/test_twin_declaration_status.py b/tests/test_twin_declaration_status.py
new file mode 100644
index 000000000..d9967a2b8
--- /dev/null
+++ b/tests/test_twin_declaration_status.py
@@ -0,0 +1,98 @@
+"""A path declared twice, once unpinned and once with a pin the copy misses.
+
+The unpinned declaration ships the file and the pinned one refuses it. The
+builder wrote "excluded" over the shipped path, so its summary said "1 unsafe
+excluded" for a file inside the archive, while verify counted it untested
+and listed no exclusion. Both orders of the two systems are checked: the
+refusal read first left "excluded" behind the file the second one ships.
+"""
+
+from __future__ import annotations
+
+import contextlib
+import hashlib
+import io
+import os
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+import yaml
+
+REPO_ROOT = Path(__file__).resolve().parent.parent
+sys.path.insert(0, str(REPO_ROOT / "scripts"))
+
+import common # noqa: E402
+import generate_db # noqa: E402
+import generate_pack as builder # noqa: E402
+from verify import Status, verify_platform # noqa: E402
+
+PAYLOAD = b"a console firmware"
+SHA1 = hashlib.sha1(PAYLOAD).hexdigest()
+
+
+class TwinDeclarationStatus(unittest.TestCase):
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
+ self._cwd = os.getcwd()
+ os.chdir(self._tmp.name)
+ for d in ("emulators", "platforms", "bios/Twin"):
+ Path(d).mkdir(parents=True)
+ Path("bios/Twin/fw.bin").write_bytes(PAYLOAD)
+ files = {SHA1: {
+ "path": "bios/Twin/fw.bin", "name": "fw.bin", "size": len(PAYLOAD),
+ "sha1": SHA1, "md5": hashlib.md5(PAYLOAD).hexdigest(),
+ "sha256": hashlib.sha256(PAYLOAD).hexdigest(), "crc32": "00000001",
+ }}
+ self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
+ Path("platforms/_registry.yml").write_text(
+ yaml.dump({"platforms": {"twin": {"status": "active"}}})
+ )
+ self.addCleanup(common._platform_config_cache.clear)
+
+ def tearDown(self):
+ os.chdir(self._cwd)
+ self._tmp.cleanup()
+
+ def _config(self, unpinned: str, pinned: str) -> dict:
+ config = {
+ "platform": "Twin", "verification_mode": "md5",
+ "systems": {
+ unpinned: {"files": [{"name": "fw.bin", "destination": "fw.bin"}]},
+ pinned: {"files": [{
+ "name": "fw.bin", "destination": "fw.bin", "md5": "0" * 32,
+ }]},
+ },
+ }
+ Path("platforms/twin.yml").write_text(yaml.dump(config))
+ common._platform_config_cache.clear()
+ return config
+
+ def _check(self, config: dict) -> None:
+ record = builder.PackRecord()
+ out = io.StringIO()
+ with contextlib.redirect_stdout(out):
+ builder.generate_pack(
+ "twin", "platforms", self.db, "bios", "out",
+ emulators_dir="emulators", emu_profiles={}, record=record,
+ offline=True,
+ )
+ self.assertIn("fw.bin", record.members)
+ summary = out.getvalue()
+ self.assertNotIn("excluded", summary.lower())
+ self.assertIn("0/1 files OK, 1 untested", summary)
+ self.assertIn("UNTESTED: fw.bin", summary)
+ report = verify_platform(config, self.db, "emulators", {})
+ self.assertEqual(report["status_counts"], {Status.UNTESTED: 1})
+ self.assertEqual(report["excluded_files"], [])
+
+ def test_unpinned_declaration_read_first(self):
+ self._check(self._config("aaa", "bbb"))
+
+ def test_pinned_declaration_read_first(self):
+ self._check(self._config("zzz", "bbb"))
+
+
+if __name__ == "__main__":
+ unittest.main()
From 5c93c6dc6b2826f22cacd0dbe6b5808e75f2b192 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:12:19 +0100
Subject: [PATCH 03/83] refactor: one emudeck script-to-profile rule
The target scraper kept its own copy of the EmuScripts table and took
.ps1 files the platform scraper never read, so emudeck-we's template
skeleton was published as a core and removed afterwards by an override.
Both scrapers now read emulator_of_script, and the platform scraper
lists the installers at the pinned revision, as launchers: and the
SteamOS target already did. Targets rescraped, override dropped.
---
install/targets/emudeck.json | 2 +
platforms/targets/_overrides.yml | 7 ---
platforms/targets/emudeck.yml | 7 +--
scripts/scraper/emudeck_launchers.py | 13 +++--
scripts/scraper/emudeck_scraper.py | 15 +++---
.../targets/emudeck_targets_scraper.py | 46 +++-------------
tests/test_launchers_emudeck.py | 2 +
tests/test_scraper_contract.py | 2 +-
tests/test_target_scrapers.py | 53 +++++++++++++++++++
9 files changed, 86 insertions(+), 61 deletions(-)
diff --git a/install/targets/emudeck.json b/install/targets/emudeck.json
index 36f30d211..4ef016714 100644
--- a/install/targets/emudeck.json
+++ b/install/targets/emudeck.json
@@ -83,6 +83,7 @@
"galaksija",
"gam4980",
"gambatte",
+ "gametank",
"gearboy",
"gearcoleco",
"geargrafx",
@@ -346,6 +347,7 @@
"galaksija",
"gam4980",
"gambatte",
+ "gametank",
"gearboy",
"gearcoleco",
"geargrafx",
diff --git a/platforms/targets/_overrides.yml b/platforms/targets/_overrides.yml
index 1080067b0..d07226f89 100644
--- a/platforms/targets/_overrides.yml
+++ b/platforms/targets/_overrides.yml
@@ -121,13 +121,6 @@ retrodeck:
# includes the frontend name alongside the actual cores.
remove_cores: [retroarch]
-emudeck:
- targets:
- _default:
- # EmuDeck's EmuScripts tree carries a template.sh placeholder used
- # to scaffold new installers. It is not an emulator.
- remove_cores: [template]
-
lakka:
targets:
generic:
diff --git a/platforms/targets/emudeck.yml b/platforms/targets/emudeck.yml
index 49ac73621..c445457fb 100644
--- a/platforms/targets/emudeck.yml
+++ b/platforms/targets/emudeck.yml
@@ -1,6 +1,6 @@
platform: emudeck
-source: https://github.com/dragoonDorise/EmuDeck
-scraped_at: '2026-10-17T18:43:57Z'
+source: https://github.com/dragoonDorise/EmuDeck/tree/dddb30229adbbd54d5ff7283cfd70e11c4322c26
+scraped_at: '2026-11-06T07:10:22Z'
targets:
steamos:
architecture: x86_64
@@ -88,6 +88,7 @@ targets:
- galaksija
- gam4980
- gambatte
+ - gametank
- gearboy
- gearcoleco
- geargrafx
@@ -352,6 +353,7 @@ targets:
- galaksija
- gam4980
- gambatte
+ - gametank
- gearboy
- gearcoleco
- geargrafx
@@ -487,7 +489,6 @@ targets:
- supermodel
- swanstation
- tamalibretro
- - template
- tgbdual
- theodore
- thepowdertoy
diff --git a/scripts/scraper/emudeck_launchers.py b/scripts/scraper/emudeck_launchers.py
index cbb7252ba..2723d62d8 100644
--- a/scripts/scraper/emudeck_launchers.py
+++ b/scripts/scraper/emudeck_launchers.py
@@ -46,14 +46,18 @@ STORAGE = "${storagePath}"
FLATPAK_DATA = "${HOME}/.var/app/"
# EmuScripts file names that differ from the emulator profile they set up.
+# The platform and target scrapers both read them here.
SCRIPT_EMULATORS = {
"pcsx2qt": "pcsx2",
"rpcs3legacy": "rpcs3",
"cemuproton": "cemu",
"rmg": "mupen64plus_next",
}
-# The main RetroArch config script installs no emulator.
-NOT_EMULATORS = {"retroarch_maincfg"}
+# The main RetroArch config script installs no emulator, and emudeck-we's
+# emuDeckTemplate.ps1 is the skeleton new installers are copied from.
+NOT_EMULATORS = {"retroarch_maincfg", "template"}
+# EmuDeck's SteamOS installers are shell scripts, emudeck-we's PowerShell.
+SCRIPT_SUFFIXES = (".sh", ".ps1")
# What the emulator does with a directory written into each key.
DIRECTORY_KINDS = {
@@ -66,9 +70,10 @@ DIRECTORY_KINDS = {
def emulator_of_script(file_name: str) -> str | None:
"""The emulator an EmuScripts file sets up, None for a helper script."""
- if not file_name.endswith(".sh"):
+ stem, dot, suffix = file_name.rpartition(".")
+ if not dot or f".{suffix}" not in SCRIPT_SUFFIXES:
return None
- key = re.sub(r"^emuDeck", "", file_name[: -len(".sh")], flags=re.IGNORECASE).lower()
+ key = re.sub(r"^emuDeck", "", stem, flags=re.IGNORECASE).lower()
if not key or key in NOT_EMULATORS:
return None
return SCRIPT_EMULATORS.get(key, key)
diff --git a/scripts/scraper/emudeck_scraper.py b/scripts/scraper/emudeck_scraper.py
index 4f72adefb..d4fadacf0 100644
--- a/scripts/scraper/emudeck_scraper.py
+++ b/scripts/scraper/emudeck_scraper.py
@@ -469,9 +469,10 @@ class Scraper(BaseScraper):
version = fetch_github_latest_version("dragoonDorise/EmuDeck")
- cores = self._fetch_installed_emulators()
+ revision = launcher_revision(self.checkbios_url)
+ cores = self._fetch_installed_emulators(revision)
standalone = [core for core in cores if core != "retroarch"]
- tree = RepoTree.github(EMUDECK_REPO, launcher_revision(self.checkbios_url))
+ tree = RepoTree.github(EMUDECK_REPO, revision)
libretro = set(installed_libretro_cores(tree.read(RETROARCH_SCRIPT)))
return {
@@ -501,16 +502,16 @@ class Scraper(BaseScraper):
"launchers": extract_launchers(tree),
}
- def _fetch_installed_emulators(self) -> list[str]:
- """Fetch the list of emulators installed by EmuDeck from EmuScripts.
-
- Returns core names normalized to match emulator profile keys.
+ def _fetch_installed_emulators(self, revision: str) -> list[str]:
+ """The emulators EmuDeck's EmuScripts install at the pinned revision,
+ named as their profiles are: the launcher layer and the SteamOS
+ target are read at that revision too.
"""
import json
api_url = (
"https://api.github.com/repos/dragoonDorise/EmuDeck/"
- "contents/functions/EmuScripts"
+ f"contents/functions/EmuScripts?ref={revision}"
)
try:
req = urllib.request.Request(api_url, headers=github_headers())
diff --git a/scripts/scraper/targets/emudeck_targets_scraper.py b/scripts/scraper/targets/emudeck_targets_scraper.py
index 0e69d055e..fa8fa75b2 100644
--- a/scripts/scraper/targets/emudeck_targets_scraper.py
+++ b/scripts/scraper/targets/emudeck_targets_scraper.py
@@ -12,7 +12,6 @@ from __future__ import annotations
import argparse
import json
-import re
import sys
import urllib.error
import urllib.request
@@ -22,6 +21,7 @@ import yaml
from common import github_token, yaml_load
+from ..emudeck_launchers import SCRIPT_SUFFIXES, emulator_of_script
from . import BaseTargetScraper
PLATFORM_NAME = "emudeck"
@@ -33,24 +33,6 @@ WINDOWS_API = (
"https://api.github.com/repos/EmuDeck/emudeck-we/contents/functions/EmuScripts"
)
-# Map EmuDeck script names to emulator profile keys
-# Script naming: emuDeckDolphin.sh -> dolphin
-# Some need explicit mapping when names differ
-_NAME_OVERRIDES: dict[str, str] = {
- "pcsx2qt": "pcsx2",
- "rpcs3legacy": "rpcs3",
- "cemuproton": "cemu",
- "rmg": "mupen64plus_next",
- "bigpemu": "bigpemu",
- "eden": "eden",
- "suyu": "suyu",
- "ares": "ares",
-}
-
-# Scripts that are not emulators (config helpers, etc.)
-_SKIP = {"retroarch_maincfg", "retroarch"}
-
-
def _fetch(url: str) -> str:
headers = {"User-Agent": "retrobios-scraper/1.0"}
token = github_token()
@@ -69,26 +51,13 @@ def _list_emuscripts(api_url: str) -> list[str]:
"""List emulator script filenames from GitHub API."""
entries = json.loads(_fetch(api_url))
names = [
- e["name"] for e in entries if e.get("name", "").endswith((".sh", ".ps1"))
+ e["name"] for e in entries if e.get("name", "").endswith(SCRIPT_SUFFIXES)
]
if not names:
raise RuntimeError(f"no emulator scripts listed at {api_url}")
return names
-def _script_to_core(filename: str) -> str | None:
- """Convert EmuScripts filename to core profile key."""
- # Strip extension and emuDeck prefix
- name = re.sub(r"\.(sh|ps1)$", "", filename, flags=re.IGNORECASE)
- name = re.sub(r"^emuDeck", "", name, flags=re.IGNORECASE)
- if not name:
- return None
- key = name.lower()
- if key in _SKIP:
- return None
- return _NAME_OVERRIDES.get(key, key)
-
-
class Scraper(BaseTargetScraper):
"""Fetches emulator lists for EmuDeck SteamOS and Windows targets."""
@@ -114,14 +83,13 @@ class Scraper(BaseTargetScraper):
seen: set[str] = set()
has_retroarch = False
for script in scripts:
- core = _script_to_core(script)
- if core and core not in seen:
+ core = emulator_of_script(script)
+ # RetroArch stands for its libretro cores, added below.
+ if core == "retroarch":
+ has_retroarch = True
+ elif core and core not in seen:
seen.add(core)
cores.append(core)
- # Detect RetroArch presence (provides all libretro cores)
- name = re.sub(r"\.(sh|ps1)$", "", script, flags=re.IGNORECASE)
- if name.lower() in ("emudeckretroarch", "retroarch_maincfg"):
- has_retroarch = True
standalone_count = len(cores)
# EmuDeck ships RetroArch = all its libretro cores are available
diff --git a/tests/test_launchers_emudeck.py b/tests/test_launchers_emudeck.py
index 314994972..33d7596fe 100644
--- a/tests/test_launchers_emudeck.py
+++ b/tests/test_launchers_emudeck.py
@@ -373,6 +373,8 @@ class Helpers(unittest.TestCase):
self.assertEqual(el.emulator_of_script("emuDeckXemu.sh"), "xemu")
self.assertIsNone(el.emulator_of_script("RetroArch_maincfg.sh"))
self.assertIsNone(el.emulator_of_script("README.md"))
+ self.assertEqual(el.emulator_of_script("emuDeckPCSX2QT.ps1"), "pcsx2")
+ self.assertIsNone(el.emulator_of_script("emuDeckTemplate.ps1"))
def test_the_revision_comes_from_the_pinned_url(self):
url = (
diff --git a/tests/test_scraper_contract.py b/tests/test_scraper_contract.py
index bfe7f1553..cf9e04c20 100644
--- a/tests/test_scraper_contract.py
+++ b/tests/test_scraper_contract.py
@@ -724,7 +724,7 @@ class UnreadableReleaseStopsTheScrape(unittest.TestCase):
with mock.patch("urllib.request.urlopen", self._refuse), self.assertRaises(
RuntimeError
):
- emudeck_scraper.Scraper()._fetch_installed_emulators()
+ emudeck_scraper.Scraper(checkbios_url="pinned")._fetch_installed_emulators("0" * 40)
def test_libretro_core_metadata_raises(self):
"""libretro dropped every system name and manufacturer when the
diff --git a/tests/test_target_scrapers.py b/tests/test_target_scrapers.py
index c2c6626fb..6b05e356c 100644
--- a/tests/test_target_scrapers.py
+++ b/tests/test_target_scrapers.py
@@ -541,6 +541,59 @@ class TargetsReadThePlatformRevision(unittest.TestCase):
self.assertTrue(steamos)
self.assertTrue(all(u.endswith(f"?ref={pin}") for u in steamos), steamos)
+ def test_emudeck_platform_lists_its_installers_at_the_pin(self):
+ """cores: was read on master while launchers: and the SteamOS target
+ were read at the pin: the YAML described two revisions."""
+ from scripts.scraper import emudeck_scraper
+
+ pin = "d" * 40
+ seen: list[str] = []
+
+ class _Body:
+ def __init__(self, url):
+ seen.append(url)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *_exc):
+ return False
+
+ def read(self):
+ return json.dumps([{"name": "emuDeckRMG.sh"}]).encode()
+
+ with mock.patch("urllib.request.urlopen", lambda req, **_kw: _Body(req.full_url)):
+ cores = emudeck_scraper.Scraper(checkbios_url="pinned")._fetch_installed_emulators(pin)
+ self.assertEqual(cores, ["mupen64plus_next"])
+ self.assertEqual(len(seen), 1)
+ self.assertTrue(seen[0].endswith(f"?ref={pin}"), seen)
+
+
+class EmuDeckScriptNamesHaveOneRule(unittest.TestCase):
+ """The target scraper kept its own copy of the EmuScripts-to-profile
+ table: it published emudeck-we's template skeleton as a core, and a
+ rename added to one copy only made --target filter that core out."""
+
+ def test_the_target_scraper_names_scripts_as_the_platform_does(self):
+ from scripts.scraper.emudeck_launchers import emulator_of_script
+
+ listing = [
+ "emuDeckRMG.sh",
+ "emuDeckPCSX2QT.ps1",
+ "emuDeckTemplate.ps1",
+ "emuDeckRetroArch.ps1",
+ "RetroArch_maincfg.sh",
+ "emuDeckXemu.ps1",
+ ]
+ scraper = emudeck_targets_scraper.Scraper(revision="0" * 40)
+ with mock.patch.object(
+ emudeck_targets_scraper, "_list_emuscripts", return_value=listing
+ ), mock.patch.object(scraper, "_load_retroarch_cores", return_value=["mgba"]):
+ cores = scraper._fetch_cores_for_target("unused", "Windows")
+ standalone = {emulator_of_script(name) for name in listing} - {None, "retroarch"}
+ self.assertEqual(standalone, {"mupen64plus_next", "pcsx2", "xemu"})
+ self.assertEqual(cores, sorted(standalone | {"mgba"}))
+
class HashScrapersRefuseAnUnknownVersion(unittest.TestCase):
"""mame_hash_scraper wrote core_version "unknown" after a failed API call
From b550b9780c8c0424655fda3eaedd93b61b476f80 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:12:25 +0100
Subject: [PATCH 04/83] fix: judge content-found cores by any dump
A core with found_by: content reads no file by the destination's name. Any dump its profile accepts for the system settles the slot: Batocera, KNULLI and ROCKNIX ship scph1001.bin v2.0, which DuckStation and rustation accept under scph1001_v20.bin.
---
scripts/slots.py | 32 +++++++++++++++++++++++++++++++-
tests/test_slots.py | 19 +++++++++++++++++++
2 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/scripts/slots.py b/scripts/slots.py
index 8e7f826cd..f3908a631 100644
--- a/scripts/slots.py
+++ b/scripts/slots.py
@@ -43,7 +43,12 @@ from common import (
variant_base_name,
)
from packresolve import preferred_entries
-from validation import outside_gap_scope, read_from_save_dir, with_archive_members
+from validation import (
+ opens_by_name,
+ outside_gap_scope,
+ read_from_save_dir,
+ with_archive_members,
+)
if TYPE_CHECKING:
from packextras import ExtraPlacement
@@ -85,6 +90,9 @@ class Claim:
entry: dict = field(default_factory=dict)
local_path: str | None = None
status: str = ""
+ # A core that identifies its firmware by content reads no file by this
+ # name: any dump it accepts for the system answers for it.
+ accepts: tuple[dict, ...] = ()
@property
def is_proven(self) -> bool:
@@ -210,6 +218,12 @@ def profile_claims(
zip_contents, data_dir_registry,
)
)
+ labels = [
+ f for f in profile.get("files") or []
+ if isinstance(f, dict)
+ and not opens_by_name(f, profile, is_standalone)
+ and _lists_hashes(f)
+ ]
for entry in profile.get("files") or []:
if not isinstance(entry, dict):
continue
@@ -260,6 +274,13 @@ def profile_claims(
)
if status == "name_exact" and _size_the_code_reads(entry, local):
status = SIZE_EXACT
+ accepts: tuple[dict, ...] = ()
+ if not opens_by_name(entry, profile, is_standalone):
+ systems = set(entry_system_ids(entry, profile))
+ accepts = tuple(
+ f for f in labels
+ if not systems or systems & set(entry_system_ids(f, profile))
+ )
claims.append(
Claim(
origin="profile",
@@ -269,6 +290,7 @@ def profile_claims(
entry=entry,
local_path=local,
status=status,
+ accepts=accepts,
)
)
return claims
@@ -746,6 +768,10 @@ def _satisfies(profile: Claim, platform: Claim, db: dict) -> bool:
They agree when they resolve to the same bytes, when the platform's own
hash list accepts the profile's file, or when the profile's accepts the
platform's. A contradiction needs both lists to reject the other side.
+ A core found by content (found_by: content) reads no file by the
+ destination's name, so any dump it accepts for the system settles the
+ slot: DuckStation takes Batocera's scph1001.bin v2.0, which its profile
+ labels scph1001_v20.bin.
"""
if profile.local_path == platform.local_path:
return True
@@ -764,6 +790,10 @@ def _satisfies(profile: Claim, platform: Claim, db: dict) -> bool:
and _accepted_by_all(profile.local_path, [platform.entry], db)
):
return True
+ if platform.local_path and any(
+ _accepted_by_all(platform.local_path, [label], db) for label in profile.accepts
+ ):
+ return True
return bool(
platform.local_path
and _lists_hashes(profile.entry)
diff --git a/tests/test_slots.py b/tests/test_slots.py
index 44afbe8e0..0acf3c653 100644
--- a/tests/test_slots.py
+++ b/tests/test_slots.py
@@ -111,6 +111,25 @@ class TestConflicts(unittest.TestCase):
conflicts = slots.find_conflicts(config, self._profile("GC/JAP/IPL.bin"), REGIONS_DB)
self.assertEqual([c.destination for c in conflicts], ["bios/GC/JAP/IPL.bin"])
+ def test_a_core_found_by_content_takes_any_dump_it_accepts(self):
+ """DuckStation identifies its BIOS by content, so the name of its
+ scph1001.bin entry is a label. Batocera ships the v2.0 dump there,
+ which the profile accepts under scph1001_v20.bin: no conflict."""
+ files = [
+ {"name": "IPL.bin", "path": "GC/JAP/IPL.bin", "md5": "n" * 32},
+ {"name": "IPL_usa.bin", "md5": "m" * 32},
+ ]
+ by_name = slots.find_conflicts(
+ self._config("m" * 32), {"dolphin": {"files": files}}, REGIONS_DB
+ )
+ self.assertEqual(len(by_name), 1)
+ by_content = slots.find_conflicts(
+ self._config("m" * 32),
+ {"dolphin": {"found_by": "content", "files": files}},
+ REGIONS_DB,
+ )
+ self.assertEqual(by_content, [])
+
def test_wrong_region_under_a_region_slot_is_reported(self):
conflicts = slots.find_conflicts(
self._config("m" * 32), self._profile("GC/JAP/IPL.bin"), REGIONS_DB
From 895a520afdcfac61b6d59e79c2cb998e4490484c Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:12:37 +0100
Subject: [PATCH 05/83] fix: verify --platform names uncached data dirs
A platform entry that resolves only through a data directory tree read as missing with no cause on a checkout where data/ was never refreshed, while an online pack build refreshes the trees and packs it. verify_platform now reports the uncached trees and prints them when files are missing.
---
scripts/verify.py | 14 ++++++
tests/test_verify_data_dir_notice.py | 74 ++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
create mode 100644 tests/test_verify_data_dir_notice.py
diff --git a/scripts/verify.py b/scripts/verify.py
index 9fbdfa9a3..8689a4dcf 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -1575,6 +1575,13 @@ def verify_platform(
"exclusion_notes": exclusions,
"region_fallbacks": sorted(region_fallbacks),
**({"left_out": left_out} if no_game_data else {}),
+ # Every tree of the registry answers a declaration by its tail, so
+ # one that was never refreshed leaves its files missing here while
+ # an online pack build refreshes it and packs them.
+ "data_dir_notices": sorted(
+ key for key, entry in (data_dir_registry or {}).items()
+ if not os.path.isdir(entry.get("local_cache", ""))
+ ),
"details": details,
"ground_truth_coverage": {
"with_validation": with_validation,
@@ -1952,6 +1959,13 @@ def print_platform_result(
# them missing, as an offline build leaves them out.
shown = ", ".join(fetched[:10]) + (f" (+{len(fetched) - 10})" if len(fetched) > 10 else "")
print(f" Release assets fetched when the pack is built ({len(fetched)}): {shown}")
+ uncached = result.get("data_dir_notices") or []
+ if uncached and result.get("status_counts", {}).get(Status.MISSING):
+ shown = ", ".join(uncached[:10]) + (f" (+{len(uncached) - 10})" if len(uncached) > 10 else "")
+ print(
+ f" Data directories not cached ({len(uncached)}), their files count missing "
+ f"until refresh_data_dirs.py runs (an online pack build refreshes them): {shown}"
+ )
for line in result.get("left_out") or []:
print(f" {line}")
fallbacks = result.get("region_fallbacks") or []
diff --git a/tests/test_verify_data_dir_notice.py b/tests/test_verify_data_dir_notice.py
new file mode 100644
index 000000000..b9e4a71f9
--- /dev/null
+++ b/tests/test_verify_data_dir_notice.py
@@ -0,0 +1,74 @@
+"""verify --platform names the data directories that were never refreshed.
+
+A platform entry can resolve only through a data directory tree (AmberELEC's
+Machines/*/config.ini in the blueMSX tree). On a checkout where data/ was
+never refreshed, verify counted 200 such entries missing with no word on the
+cause, while an online pack build refreshes the trees and packs them.
+verify --emulator already named its uncached trees.
+"""
+
+from __future__ import annotations
+
+import contextlib
+import io
+import os
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parent.parent
+sys.path.insert(0, str(REPO_ROOT / "scripts"))
+
+import generate_db # noqa: E402
+from verify import print_platform_result, verify_platform # noqa: E402
+
+
+class UncachedDataDirectoryNotice(unittest.TestCase):
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
+ self._cwd = os.getcwd()
+ os.chdir(self._tmp.name)
+ Path("emulators").mkdir()
+ Path("data/present").mkdir(parents=True)
+ self.db = {"files": {}, "indexes": generate_db.build_indexes({}, {})}
+ self.config = {
+ "platform": "Tree", "verification_mode": "md5",
+ "systems": {"msx": {"files": [{
+ "name": "config.ini", "destination": "Machines/MSX/config.ini",
+ }]}},
+ }
+ self.registry = {
+ "absent": {"local_cache": "data/absent"},
+ "present": {"local_cache": "data/present"},
+ }
+
+ def tearDown(self):
+ os.chdir(self._cwd)
+ self._tmp.cleanup()
+
+ def _run(self) -> tuple[dict, str]:
+ result = verify_platform(
+ self.config, self.db, "emulators", {}, data_dir_registry=self.registry,
+ )
+ out = io.StringIO()
+ with contextlib.redirect_stdout(out):
+ print_platform_result(result, ["Tree"])
+ return result, out.getvalue()
+
+ def test_an_uncached_tree_is_named(self):
+ result, printed = self._run()
+ self.assertEqual(result["data_dir_notices"], ["absent"])
+ self.assertIn("Data directories not cached (1)", printed)
+ self.assertIn("refresh_data_dirs.py", printed)
+ self.assertIn(": absent", printed)
+
+ def test_no_note_when_every_tree_is_cached(self):
+ Path("data/absent").mkdir()
+ result, printed = self._run()
+ self.assertEqual(result["data_dir_notices"], [])
+ self.assertNotIn("refresh_data_dirs", printed)
+
+
+if __name__ == "__main__":
+ unittest.main()
From 8022ef4cb31c9140d195863c7e6299773f73e04b Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:12:43 +0100
Subject: [PATCH 06/83] fix: read the given database on every page
The page-finishing pass reloaded the repository's database.json whatever
--db said, so a card held only by the given collection raised KeyError.
siteinputs holds the inputs generate_site was given.
---
scripts/generate_site.py | 25 +++++++++++-----
scripts/siteinputs.py | 32 +++++++++++++++++++++
tests/test_site_inputs.py | 60 +++++++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 7 deletions(-)
create mode 100644 scripts/siteinputs.py
create mode 100644 tests/test_site_inputs.py
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 32f926da0..9b83ff328 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -89,6 +89,7 @@ from generate_readme import (
from provenance_report import build_report, distinct_missing
import sitemarkup as markup
import siteentries
+import siteinputs
import retired_files
import sitestarlight
from siteexports import generate_exports_page, load_export_reports
@@ -3174,7 +3175,9 @@ def _front_matter(markdown: str) -> dict:
return data if isinstance(data, dict) else {}
-_SHA1_BY_PREFIX: dict[str, str] = {}
+@functools.lru_cache(maxsize=None)
+def _sha1_by_prefix(db_path: str) -> dict[str, str]:
+ return {sha1[:12]: sha1 for sha1 in load_database(db_path)["files"]}
def _cards_elsewhere(markdown: str) -> str:
@@ -3185,11 +3188,9 @@ def _cards_elsewhere(markdown: str) -> str:
away = {ident for ident in links if f'id="{ident}"' not in markdown}
if not away:
return markdown
- if not _SHA1_BY_PREFIX:
- db = load_database(str(_REPO_ROOT / "database.json"))
- _SHA1_BY_PREFIX.update({sha1[:12]: sha1 for sha1 in db["files"]})
+ by_prefix = _sha1_by_prefix(str(siteinputs.current().db))
for ident in away:
- full = _SHA1_BY_PREFIX[ident.removeprefix("sha1-")]
+ full = by_prefix[ident.removeprefix("sha1-")]
markdown = markdown.replace(f"](#{ident})", f"]({markup.site_href(f'files/?sha1={full}')})")
return markdown
@@ -3500,10 +3501,14 @@ def _list_pages(
f"[part {i}]({other}.md)" for i, other in enumerate(stems, 1))
-@functools.lru_cache(maxsize=1)
def _collection_sha1_by_path() -> dict[str, str]:
"""The sha1 of each file the collection holds, by its path."""
- with open(_REPO_ROOT / "database.json", encoding="utf-8") as handle:
+ return _sha1_by_path_in(str(siteinputs.current().db))
+
+
+@functools.lru_cache(maxsize=None)
+def _sha1_by_path_in(db_path: str) -> dict[str, str]:
+ with open(db_path, encoding="utf-8") as handle:
files = json.load(handle).get("files", {})
return {str(entry.get("path", "")): sha1 for sha1, entry in files.items()}
@@ -12260,6 +12265,12 @@ def main() -> None:
def _generate(args: argparse.Namespace) -> None:
+ # Every page reads these, never the repository's own files.
+ siteinputs.use(siteinputs.SiteInputs(
+ db=Path(args.db).resolve(),
+ emulators=Path(args.emulators_dir).resolve(),
+ platforms=Path(args.platforms_dir).resolve(),
+ ))
db = load_database(args.db)
docs = Path(args.docs_dir)
# Files the site serves as they are (data, downloads, images), in the
diff --git a/scripts/siteinputs.py b/scripts/siteinputs.py
new file mode 100644
index 000000000..7aa3326ff
--- /dev/null
+++ b/scripts/siteinputs.py
@@ -0,0 +1,32 @@
+"""The collection, profiles and platform files the site describes.
+
+generate_site.py takes them as --db, --emulators-dir and --platforms-dir and
+installs them here before writing a page. Every page module reads its inputs
+from current(), so a run on another collection describes that collection on
+every page. A module used on its own reads the repository's files.
+"""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+
+
+@dataclass(frozen=True)
+class SiteInputs:
+ db: Path = ROOT / "database.json"
+ emulators: Path = ROOT / "emulators"
+ platforms: Path = ROOT / "platforms"
+
+
+_current = [SiteInputs()]
+
+
+def current() -> SiteInputs:
+ return _current[0]
+
+
+def use(inputs: SiteInputs) -> None:
+ _current[0] = inputs
diff --git a/tests/test_site_inputs.py b/tests/test_site_inputs.py
new file mode 100644
index 000000000..ab75d4be7
--- /dev/null
+++ b/tests/test_site_inputs.py
@@ -0,0 +1,60 @@
+"""generate_site --db reaches every page.
+
+The run loaded the given database, but the page-finishing pass reloaded the
+repository's database.json: a card held only by the given collection stopped
+the whole run on a KeyError.
+"""
+
+from __future__ import annotations
+
+import ast
+import json
+import shutil
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(REPO_ROOT / "scripts"))
+
+import generate_site # noqa: E402
+import siteinputs # noqa: E402
+
+SHA1 = "0123456789ab" + "c" * 28
+
+
+class _Inputs(unittest.TestCase):
+ def use(self, **paths: Path) -> None:
+ siteinputs.use(siteinputs.SiteInputs(**paths))
+ self.addCleanup(siteinputs.use, siteinputs.SiteInputs())
+
+
+class TheGivenDatabase(_Inputs):
+ def setUp(self) -> None:
+ tmp = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp" if (REPO_ROOT / "tmp").is_dir() else None))
+ self.addCleanup(shutil.rmtree, tmp)
+ self.db = tmp / "database.json"
+ self.db.write_text(json.dumps({"files": {SHA1: {"path": "bios/X/only-here.bin"}}}))
+
+ def test_a_card_held_elsewhere_resolves_in_the_given_collection(self) -> None:
+ self.use(db=self.db)
+ page = generate_site._cards_elsewhere("[x](#sha1-0123456789ab) ")
+ self.assertIn(f"files/?sha1={SHA1}", page)
+
+ def test_paths_are_read_from_the_given_collection(self) -> None:
+ self.use(db=self.db)
+ self.assertEqual(generate_site._collection_sha1_by_path(), {"bios/X/only-here.bin": SHA1})
+
+
+class GenerateInstallsTheInputs(unittest.TestCase):
+ def test_generate_installs_the_inputs_first(self) -> None:
+ source = ast.get_source_segment(
+ (REPO_ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8"),
+ next(n for n in ast.parse((REPO_ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8")).body
+ if isinstance(n, ast.FunctionDef) and n.name == "_generate"))
+ self.assertLess(source.index("siteinputs.use("), source.index("load_database("))
+
+
+if __name__ == "__main__":
+ unittest.main()
From 57ccca640a353bdbfe4550d8d9792a16652d5fd3 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:13:32 +0100
Subject: [PATCH 07/83] refactor: importers write through write_if_changed
game_dat_importer and arcade_parent_importer each kept an exact-text
copy of write_if_changed, so a redump refresh rewrote every catalog for
its fetched date alone. Both now use artifacts.write_if_changed, which
treats fetched as a timestamp. A No-Intro rebuild still rewrites its
catalogs, since asset_updated_at moves with it, so check_freshness keeps
reading a fetched date no older than the pack.
---
scripts/artifacts.py | 1 +
scripts/scraper/arcade_parent_importer.py | 13 +++----------
scripts/scraper/game_dat_importer.py | 14 ++++----------
tests/test_game_catalogs.py | 11 +++++++++++
4 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/scripts/artifacts.py b/scripts/artifacts.py
index 66b752837..ef6818657 100644
--- a/scripts/artifacts.py
+++ b/scripts/artifacts.py
@@ -19,6 +19,7 @@ import re
_TIMESTAMP_PATTERNS = [
re.compile(r'"generated_at":\s*"[^"]*"'), # database.json
re.compile(r'"imported_at":\s*"[^"]*"'), # provenance snapshots
+ re.compile(r'"fetched":\s*"[^"]*"'), # games/catalogs/
re.compile(r"\*Auto-generated on [^*]*\*"), # README.md
re.compile(r"\*Generated on [^*]*\*"), # docs site pages
# The decorated pages carry the same stamp again as a rendered element,
diff --git a/scripts/scraper/arcade_parent_importer.py b/scripts/scraper/arcade_parent_importer.py
index ee1eca55a..a884b3188 100644
--- a/scripts/scraper/arcade_parent_importer.py
+++ b/scripts/scraper/arcade_parent_importer.py
@@ -49,7 +49,7 @@ from collections.abc import Callable, Iterator
from dataclasses import dataclass, field
from pathlib import Path
-from ..artifacts import write_text_atomic
+from ..artifacts import write_if_changed
from ..common import load_emulator_profiles, run_cli
from .romset_dat_importer import (
LISTXML_CHUNK,
@@ -1114,14 +1114,6 @@ def dump(doc: dict) -> str:
return json.dumps(doc, sort_keys=True, separators=(",", ":"), ensure_ascii=False) + "\n"
-def write_if_changed(path: Path, text: str) -> bool:
- if path.is_file() and path.read_text(encoding="utf-8") == text:
- return False
- path.parent.mkdir(parents=True, exist_ok=True)
- write_text_atomic(str(path), text)
- return True
-
-
def main() -> int:
parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.splitlines()[0])
which = parser.add_mutually_exclusive_group(required=True)
@@ -1197,7 +1189,8 @@ def main() -> int:
continue
if not args.dry_run:
target = args.output_dir / f"{profile}.json"
- if write_if_changed(target, dump(doc)):
+ target.parent.mkdir(parents=True, exist_ok=True)
+ if write_if_changed(str(target), dump(doc)):
print(f" wrote {target}")
return 1 if failed else 0
diff --git a/scripts/scraper/game_dat_importer.py b/scripts/scraper/game_dat_importer.py
index e15a57fda..0968008bf 100644
--- a/scripts/scraper/game_dat_importer.py
+++ b/scripts/scraper/game_dat_importer.py
@@ -38,7 +38,7 @@ _SCRIPTS_DIR = str(Path(__file__).resolve().parents[1])
if _SCRIPTS_DIR not in sys.path:
sys.path.insert(0, _SCRIPTS_DIR)
-from artifacts import copy_stream_atomic, write_text_atomic # noqa: E402
+from artifacts import copy_stream_atomic, write_if_changed, write_text_atomic # noqa: E402
from common import parse_untrusted_xml # noqa: E402
from region import REGIONS, WORLD # noqa: E402
from region_audit import NOINTRO # noqa: E402
@@ -275,14 +275,6 @@ def dump_catalog(doc: dict) -> str:
return f'{text},"games":[\n{games}\n]}}\n'
-def write_if_changed(path: Path, text: str) -> bool:
- if path.is_file() and path.read_text(encoding="utf-8") == text:
- return False
- path.parent.mkdir(parents=True, exist_ok=True)
- write_text_atomic(str(path), text)
- return True
-
-
# Fetching ---------------------------------------------------------------
@@ -503,7 +495,9 @@ def main() -> int:
failures.append(f"{doc['source']}/{doc['system']}: {cov['games']} games, "
f"floor {floor_of(doc)}")
if not args.dry_run:
- write_if_changed(args.output_dir / doc["source"] / f"{doc['system']}.json", text)
+ target = args.output_dir / doc["source"] / f"{doc['system']}.json"
+ target.parent.mkdir(parents=True, exist_ok=True)
+ write_if_changed(str(target), text)
print(f"{len(docs)} catalogs, {raw_total} bytes raw, {gz_total} bytes gzip")
for failure in failures:
print(f"FAIL {failure}", file=sys.stderr)
diff --git a/tests/test_game_catalogs.py b/tests/test_game_catalogs.py
index 61ca33b63..306d78844 100644
--- a/tests/test_game_catalogs.py
+++ b/tests/test_game_catalogs.py
@@ -102,6 +102,17 @@ class FixtureImport(unittest.TestCase):
twin = second / path.relative_to(first)
self.assertEqual(path.read_bytes(), twin.read_bytes(), path.name)
+ def test_a_new_fetch_date_alone_rewrites_nothing(self) -> None:
+ """A refresh rewrote every catalog for the day it ran, and the diff
+ read before commit no longer showed which DAT had moved."""
+ self.assertEqual(run_import("redump", self.out).returncode, 0)
+ path = self.out / "redump" / "sega-megacd.json"
+ doc = json.loads(path.read_text())
+ doc["fetched"] = "2000-01-01"
+ path.write_text(importer.dump_catalog(doc))
+ self.assertEqual(run_import("redump", self.out).returncode, 0)
+ self.assertEqual(json.loads(path.read_text())["fetched"], "2000-01-01")
+
def test_floor_refuses_a_short_dat(self) -> None:
result = run_import("no-intro", self.out, "--floor", "--dry-run")
self.assertEqual(result.returncode, 1)
From afceabaf3c35e83f45602711fe31fd1d39a31623 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:14:17 +0100
Subject: [PATCH 08/83] fix: bios_integrity stops when git fails
modified_for_git read the stdout of git status without its exit code:
a corrupt index printed nothing, the working change read as unmodified,
and --apply wrote HEAD's blob over it. Every git call now raises on a
non-zero status, and the command exits 2 naming the git error.
---
scripts/bios_integrity.py | 19 +++++++++++++++++--
tests/test_autorun.py | 10 ++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/scripts/bios_integrity.py b/scripts/bios_integrity.py
index 72d1caf71..1b0a69b17 100644
--- a/scripts/bios_integrity.py
+++ b/scripts/bios_integrity.py
@@ -91,8 +91,19 @@ def sha1_of(path: Path) -> str:
return digest.hexdigest()
+class GitFailed(RuntimeError):
+ """A git command failed: its empty output says nothing about the file."""
+
+
def git(root: Path, *args: str) -> subprocess.CompletedProcess:
- return subprocess.run(["git", "-C", str(root), *args], capture_output=True, check=False)
+ """Run git in root. A failure raises: an unreadable index read as an empty
+ status made a session's working change look unmodified, and --apply wrote
+ HEAD's bytes over it."""
+ done = subprocess.run(["git", "-C", str(root), *args], capture_output=True, check=False)
+ if done.returncode:
+ message = done.stderr.decode(errors="replace").strip()
+ raise GitFailed(f"git {' '.join(args)} exited {done.returncode}: {message}")
+ return done
def head_blob(root: Path, path: str) -> str:
@@ -197,7 +208,11 @@ def main() -> int:
from common import load_database
root = Path.cwd()
- report = check(root, load_database(args.db), args.apply)
+ try:
+ report = check(root, load_database(args.db), args.apply)
+ except GitFailed as exc:
+ print(f"ERROR: {exc}. Nothing was restored past this point.", file=sys.stderr)
+ return 2
if args.json:
print(json.dumps(report.as_dict(), indent=2))
else:
diff --git a/tests/test_autorun.py b/tests/test_autorun.py
index c8c04e0ad..ad15f7421 100644
--- a/tests/test_autorun.py
+++ b/tests/test_autorun.py
@@ -891,6 +891,16 @@ class BiosIntegrity(Scratch):
self.assertEqual([(f.path, f.verdict) for f in report.findings], [(rel, bib.SKIPPED)])
self.assertEqual((self.repo / rel).read_bytes(), b"\x02" * 80)
+ def test_an_unreadable_index_stops_before_any_restore(self):
+ """git status failed on a corrupt index, its empty stdout read as
+ "unmodified", and --apply wrote HEAD's bytes over the session's."""
+ rel = "bios/Sony/edited.bin"
+ (self.repo / rel).write_bytes(b"\x02" * 80)
+ (self.repo / ".git" / "index").write_bytes(b"garbage\n")
+ with self.assertRaises(bib.GitFailed):
+ bib.check(self.repo, self.db, apply=True)
+ self.assertEqual((self.repo / rel).read_bytes(), b"\x02" * 80)
+
def test_a_mismatch_the_second_read_does_not_confirm_is_a_misread(self):
reads = {}
expected = {e["path"]: e["sha1"] for e in self.db["files"].values()}
From 9b871db83aad31b060758e4825a685a723801927 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:12:50 +0100
Subject: [PATCH 09/83] fix: read the given profiles and platform files
Five generate_site helpers read ./emulators or ./platforms, and
has_release_pack read platforms relative to the working directory: run
from scripts/, a released setup's get page showed the No ZIP line.
siterender's fallbacks and sitediagrams read the repository too. All of
them now read siteinputs. platforms/_guides.yml stays the repository's:
siteguides loads it at import, before any flag is parsed.
---
scripts/generate_site.py | 76 ++++++++++++++++++++++-----------------
scripts/sitediagrams.py | 37 +++++++++++++------
scripts/siterender.py | 13 ++++---
tests/test_site_inputs.py | 68 +++++++++++++++++++++++++++++++++--
wiki/testing-guide.md | 2 +-
5 files changed, 145 insertions(+), 51 deletions(-)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 9b83ff328..62f400543 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -663,7 +663,7 @@ def release_line(platform_name: str, record: dict) -> list[str]:
f"[SHA256SUMS.txt]({base}/SHA256SUMS.txt) and its "
f"[signature]({base}/SHA256SUMS.txt.sig).",
]
- config = load_platform_config(platform_name, "platforms")
+ config = load_platform_config(platform_name, str(siteinputs.current().platforms))
page_version = str(config.get("version") or "")
pack_version = _pack_version(pack_name)
if page_version and pack_version and page_version.lstrip("v") != pack_version.lstrip("v"):
@@ -688,7 +688,7 @@ def setup_version(platform_name: str, record: dict | None = None) -> str:
platform YAML was read at. Empty when neither says, or when the
platform has no YAML to read a version from."""
try:
- config = load_platform_config(platform_name, "platforms")
+ config = load_platform_config(platform_name, str(siteinputs.current().platforms))
except FileNotFoundError:
return ""
pack_name = release_record.pack_name_for(platform_name, record or {})
@@ -715,8 +715,7 @@ NO_ZIP_FAQ = "wiki/faq.md#why-is-there-no-zip-for-my-setup"
def has_release_pack(platform_name: str) -> bool:
"""Whether a release publishes a ZIP for the platform (`release_pack`)."""
- entry = load_platform_registry("platforms").get(platform_name) or {}
- return entry.get("release_pack") is True
+ return platform_name in _release_pack_platforms()
def no_zip_line(display: str) -> str:
@@ -735,7 +734,7 @@ def get_page_title(platform_name: str, display: str) -> str:
the system's own download. A setup that is also an emulator (BizHawk)
names it last: "BizHawk BIOS files" is the title of its emulator page."""
kind = "BIOS pack" if has_release_pack(platform_name) else "BIOS files"
- if (_REPO_ROOT / "emulators" / f"{platform_name}.yml").is_file():
+ if (siteinputs.current().emulators / f"{platform_name}.yml").is_file():
return f"{kind} for {display}"
return f"{display} {kind}"
@@ -780,7 +779,7 @@ def _pack_buttons(platform_name: str, label: str = "Pack", prefix: str = "../",
frontend user asks. A setup with no release pack gets the line that
says so, and why."""
if not has_release_pack(platform_name):
- display = display or load_platform_config(platform_name, "platforms").get(
+ display = display or load_platform_config(platform_name, str(siteinputs.current().platforms)).get(
"platform", platform_name)
return f"{no_zip_line(display)} [Why no ZIP?]({prefix}{NO_ZIP_FAQ})"
record = release_record.load_advertised()
@@ -805,7 +804,7 @@ def generate_get_page(platform_name: str) -> str:
the files of the pack the current release holds, read from release.json,
or the command when no release publishes one. The release process
never touches it: committing release.json rebuilds it."""
- config = load_platform_config(platform_name, "platforms")
+ config = load_platform_config(platform_name, str(siteinputs.current().platforms))
display = config.get("platform", platform_name)
record = release_record.load_advertised()
pack = release_record.pack_for(platform_name, record)
@@ -824,7 +823,7 @@ def generate_get_page(platform_name: str) -> str:
if released and pack and pack.get("assets"):
parts = len(pack["assets"])
release = release_line(platform_name, record)
- extract_to = (load_platform_registry("platforms").get(platform_name) or {}).get("extract_to")
+ extract_to = (load_platform_registry(str(siteinputs.current().platforms)).get(platform_name) or {}).get("extract_to")
lines += [
"This address stays the same. It always gives the latest ZIP.",
"",
@@ -873,7 +872,7 @@ def generate_get_page(platform_name: str) -> str:
def generate_get_index() -> str:
"""get/: the permanent page of every setup, grouped as the home tiles
are. A link trimmed to /get/ answered 404."""
- registry = load_platform_registry("platforms")
+ registry = load_platform_registry(str(siteinputs.current().platforms))
lines = [
"---", "search: exclude",
'description: "The BIOS files of every setup, one page each. Each address stays the same."',
@@ -887,7 +886,7 @@ def generate_get_index() -> str:
continue
lines += [f"## {label}", ""]
for name in names:
- display = load_platform_config(name, "platforms").get("platform", name)
+ display = load_platform_config(name, str(siteinputs.current().platforms)).get("platform", name)
lines.append(f"- [{get_page_title(name, display)}]({name}.md)")
lines.append("")
return "\n".join(lines)
@@ -1068,10 +1067,13 @@ def _split_contract(config: dict) -> tuple[dict, dict]:
return contract, registry
-@functools.lru_cache(maxsize=1)
def _release_pack_platforms() -> frozenset[str]:
- return frozenset(list_release_pack_platforms(
- str(_REPO_ROOT / "platforms"), include_archived=True))
+ return _release_packs_in(str(siteinputs.current().platforms))
+
+
+@functools.lru_cache(maxsize=None)
+def _release_packs_in(platforms_dir: str) -> frozenset[str]:
+ return frozenset(list_release_pack_platforms(platforms_dir, include_archived=True))
# Per-entry fields a folder check needs beyond the hashes: an md5 is a ZIP
@@ -2105,7 +2107,7 @@ def _short_sha256(item: dict, catalog: str) -> str:
def _platforms_without_a_list(platforms_dir: Path | None = None) -> list[str]:
"""The names of the platforms whose registry says they keep no list."""
- platforms_dir = platforms_dir or _REPO_ROOT / "platforms"
+ platforms_dir = platforms_dir or siteinputs.current().platforms
names = []
for key, entry in sorted(load_platform_registry(str(platforms_dir)).items()):
if entry.get("native_list") != "none":
@@ -3538,7 +3540,7 @@ def _system_named_link(sys_id: str, prefix: str = "") -> str:
def _emulator_named_link(key: str, prefix: str = "") -> str:
"""An emulator by the name its page carries, linked to that page. A
profile with no page (an alias, a test) is named only."""
- profile = load_emulator_profiles(str(_REPO_ROOT / "emulators"), skip_aliases=False).get(key, {})
+ profile = _profiles_on_disk().get(key, {})
label = _escape_tags(str(profile.get("emulator") or key))
if profile.get("type") in ("alias", "test"):
return label
@@ -3928,10 +3930,9 @@ def _platform_data_links(name: str) -> str:
return ", ".join(links)
-@functools.lru_cache(maxsize=1)
def _site_profiles() -> dict[str, dict]:
"""Every emulator profile, read once for the citations of a page."""
- return load_emulator_profiles(str(_REPO_ROOT / "emulators"))
+ return _profiles_in(str(siteinputs.current().emulators), skip_aliases=True)
# Whose code a source reference cites, in one word: a platform page names
@@ -4015,13 +4016,17 @@ def _category_evidence_md(evidence: dict, launched: list[str] | None = None) ->
return f"No reader found ({cores})"
-@functools.lru_cache(maxsize=1)
def _profiles_by_core_name() -> dict[str, list[str]]:
"""Core name as a platform writes it -> the profiles with a page for it.
MinUI writes `mednafen_vb`, the profile and its page are `beetle_vb`.
"""
- profiles = load_emulator_profiles(str(_REPO_ROOT / "emulators"))
+ return _core_names_in(str(siteinputs.current().emulators))
+
+
+@functools.lru_cache(maxsize=None)
+def _core_names_in(emulators_dir: str) -> dict[str, list[str]]:
+ profiles = _profiles_in(emulators_dir, skip_aliases=True)
with_page = {k for k, v in profiles.items() if v.get("type") not in ("alias", "test")}
return {
core: sorted(k for k in keys if k in with_page)
@@ -4191,7 +4196,7 @@ def _card_route(name: str, display: str, guide: Guide) -> list[str]:
sees it is the reader's to name: no guide cites it."""
if guide.on_card or _offline_line(name):
return []
- extract_to = (load_platform_registry("platforms").get(name) or {}).get("extract_to")
+ extract_to = (load_platform_registry(str(siteinputs.current().platforms)).get(name) or {}).get("extract_to")
leaf = (extract_to or "bios").rstrip("/").rsplit("/", 1)[-1].lstrip("~") or "bios"
tabs = guide.card_run or ("windows", "macos", "linux")
args = {key: f"--platform {name} --dest "
@@ -4392,7 +4397,7 @@ def generate_handheld_guide(guide: HandheldGuide) -> str:
A handheld owner starts from the device name. The systems were named
only in a closed note, with a path seen from inside the device."""
uses = GUIDES[guide.uses]
- display = load_platform_config(guide.uses, "platforms").get("platform", guide.uses)
+ display = load_platform_config(guide.uses, str(siteinputs.current().platforms)).get("platform", guide.uses)
args = {"windows": f"--platform {guide.uses} --dest E:\\BIOS",
"macos": f"--platform {guide.uses} --dest /path/to/card/BIOS",
"linux": f"--platform {guide.uses} --dest /path/to/card/BIOS"}
@@ -4447,7 +4452,7 @@ def _platform_guide(name: str, display: str, cov: dict, registry: dict, no_list:
lines.append("")
for note in guide.notes:
lines += [note, ""]
- lines += [line for note in extract_notes("platforms", released_only=True)
+ lines += [line for note in extract_notes(str(siteinputs.current().platforms), released_only=True)
if f"The {display} pack " in note
for line in (note, "")]
if guide.more_folders:
@@ -4922,7 +4927,7 @@ def _data_member_digests(
from hashing import compute_hashes # noqa: PLC0415
if data_registry is None:
- data_registry = load_data_dir_registry(str(root / "platforms"))
+ data_registry = load_data_dir_registry(str(siteinputs.current().platforms))
found: dict[str, dict[str, str]] = {}
for ref, tree in sorted(members.items()):
cache = (data_registry.get(ref) or {}).get("local_cache")
@@ -5810,7 +5815,7 @@ def _platform_display(name: str) -> str:
display = _platform_names.get(name)
if display is None:
try:
- config = load_platform_config(name, str(_REPO_ROOT / "platforms"))
+ config = load_platform_config(name, str(siteinputs.current().platforms))
except FileNotFoundError:
config = {}
display = _platform_names[name] = str(config.get("platform") or name)
@@ -6607,11 +6612,13 @@ def _reading_pairs(sha1: str, consumers: FileConsumers) -> list[tuple[str, dict]
return pairs
-@functools.lru_cache(maxsize=1)
def _profiles_on_disk() -> dict[str, dict]:
- from common import load_emulator_profiles # noqa: PLC0415
+ return _profiles_in(str(siteinputs.current().emulators), skip_aliases=False)
- return load_emulator_profiles(str(_REPO_ROOT / "emulators"), skip_aliases=False)
+
+@functools.lru_cache(maxsize=None)
+def _profiles_in(emulators_dir: str, skip_aliases: bool) -> dict[str, dict]:
+ return load_emulator_profiles(emulators_dir, skip_aliases=skip_aliases)
def _entry_systems(emulator: str, entry: dict) -> list[str]:
@@ -8931,10 +8938,14 @@ def emulator_install_route(name: str, profile: dict) -> tuple[str, list[str], tu
return command, setups, oses
-@functools.cache
def _standalone_cores(platform: str) -> frozenset[str]:
"""The emulators a setup launches as apps, by its platform file."""
- config = load_platform_config(platform, str(_REPO_ROOT / "platforms"))
+ return _standalone_cores_in(str(siteinputs.current().platforms), platform)
+
+
+@functools.cache
+def _standalone_cores_in(platforms_dir: str, platform: str) -> frozenset[str]:
+ config = load_platform_config(platform, platforms_dir)
return frozenset(str(c) for c in config.get("standalone_cores") or [])
@@ -11787,7 +11798,7 @@ def _own_root_folders(registry: dict) -> dict[str, str]:
destination carries its root in every path."""
folders = {}
for key, entry in registry.items():
- config = load_platform_config(key, "platforms")
+ config = load_platform_config(key, str(siteinputs.current().platforms))
if config.get("base_destination") == "" and entry.get("extract_to"):
folders[key] = entry["extract_to"]
return folders
@@ -11887,9 +11898,10 @@ def generate_which_pack() -> str:
The tiles are the choice. Open tables under them listed every setup a
second time and made the page 11,800 px tall on a phone."""
- registry = load_platform_registry("platforms")
+ registry = load_platform_registry(str(siteinputs.current().platforms))
record = release_record.load_advertised()
- display = {key: load_platform_config(key, "platforms").get("platform", key) for key in registry}
+ display = {key: load_platform_config(key, str(siteinputs.current().platforms)).get("platform", key)
+ for key in registry}
all_tabs = ("windows", "macos", "linux", "steamdeck", "android")
lines = [
"---",
diff --git a/scripts/sitediagrams.py b/scripts/sitediagrams.py
index 285d2bdea..2171bb371 100644
--- a/scripts/sitediagrams.py
+++ b/scripts/sitediagrams.py
@@ -36,6 +36,7 @@ from xml.sax.saxutils import escape
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "scripts"))
+import siteinputs # noqa: E402
import sitemarkup as markup # noqa: E402
PLACEHOLDER = re.compile(r"(?m)^([ \t]*)[ \t]*$")
@@ -314,21 +315,29 @@ def svg(figure: Figure, layout: str, suffix: str) -> str:
# Data
-@lru_cache(maxsize=None)
def registry() -> dict:
+ return _registry_in(str(siteinputs.current().platforms))
+
+
+@lru_cache(maxsize=None)
+def _registry_in(platforms_dir: str) -> dict:
import yaml
- with open(ROOT / "platforms" / "_registry.yml", encoding="utf-8") as handle:
+ with open(Path(platforms_dir) / "_registry.yml", encoding="utf-8") as handle:
return yaml.safe_load(handle).get("platforms", {})
-@lru_cache(maxsize=None)
def setups() -> tuple[str, ...]:
"""The registered setups, archived ones included: each has its own page,
pack and file list, so every count of setups on the site is this one."""
+ return _setups_in(str(siteinputs.current().platforms))
+
+
+@lru_cache(maxsize=None)
+def _setups_in(platforms_dir: str) -> tuple[str, ...]:
from common import list_registered_platforms
- return tuple(sorted(list_registered_platforms(str(ROOT / "platforms"), include_archived=True)))
+ return tuple(sorted(list_registered_platforms(platforms_dir, include_archived=True)))
def setups_named(named: list[str]) -> str:
@@ -339,15 +348,19 @@ def setups_named(named: list[str]) -> str:
return ", ".join(named) + (f" and {others} more" if others else "")
-@lru_cache(maxsize=None)
def platform_modes() -> dict[str, tuple[str, str, str | None]]:
"""name -> (display name, verification mode, hash rule) for every platform."""
+ return _platform_modes_in(str(siteinputs.current().platforms))
+
+
+@lru_cache(maxsize=None)
+def _platform_modes_in(platforms_dir: str) -> dict[str, tuple[str, str, str | None]]:
from common import load_platform_config
out: dict[str, tuple[str, str, str | None]] = {}
- for name in setups():
- config = load_platform_config(name, str(ROOT / "platforms"))
- rule = registry().get(name, {}).get("hash_rule") or config.get("hash_rule")
+ for name in _setups_in(platforms_dir):
+ config = load_platform_config(name, platforms_dir)
+ rule = _registry_in(platforms_dir).get(name, {}).get("hash_rule") or config.get("hash_rule")
out[name] = (config.get("platform", name), config.get("verification_mode", ""), rule)
return out
@@ -365,13 +378,17 @@ def _folder(name: str) -> str:
CHAIN_EXAMPLES = (("batocera", "duckstation"), ("emudeck", "pcsx2"), ("retroarch", "beetle_psx"))
-@lru_cache(maxsize=None)
def emulator_names() -> dict[str, str]:
+ return _emulator_names_in(str(siteinputs.current().emulators))
+
+
+@lru_cache(maxsize=None)
+def _emulator_names_in(emulators_dir: str) -> dict[str, str]:
import yaml
names: dict[str, str] = {}
for _, emulator in CHAIN_EXAMPLES:
- with open(ROOT / "emulators" / f"{emulator}.yml", encoding="utf-8") as handle:
+ with open(Path(emulators_dir) / f"{emulator}.yml", encoding="utf-8") as handle:
label = str(yaml.safe_load(handle).get("emulator", emulator))
names[emulator] = re.sub(r"\s*\(.*\)$", "", label)
return names
diff --git a/scripts/siterender.py b/scripts/siterender.py
index 9f19a9d02..bca6e60b5 100644
--- a/scripts/siterender.py
+++ b/scripts/siterender.py
@@ -7,6 +7,7 @@ import urllib.parse
from collections.abc import Callable
from pathlib import Path
+import siteinputs
import sitemarkup as markup
@@ -401,7 +402,8 @@ def _build_boards() -> None:
from common import load_emulator_profiles
- database = _REPO_ROOT / "database.json"
+ inputs = siteinputs.current()
+ database = inputs.db
if not database.exists():
_archive_boards.clear()
_board_names.clear()
@@ -409,7 +411,7 @@ def _build_boards() -> None:
return
with open(database, encoding="utf-8") as handle:
db = json.load(handle)
- profiles = load_emulator_profiles(str(_REPO_ROOT / "emulators"), skip_aliases=False)
+ profiles = load_emulator_profiles(str(inputs.emulators), skip_aliases=False)
_arcade_source[0] = (profiles, db)
profiles, db = _arcade_source[0]
files = db.get("files", {})
@@ -780,9 +782,10 @@ def _ensure_console_sections() -> None:
from common import load_emulator_profiles
from generate_site import _group_by_manufacturer
- with open(_REPO_ROOT / "database.json", encoding="utf-8") as handle:
+ inputs = siteinputs.current()
+ with open(inputs.db, encoding="utf-8") as handle:
db = json.load(handle)
- profiles = load_emulator_profiles(str(_REPO_ROOT / "emulators"), skip_aliases=False)
+ profiles = load_emulator_profiles(str(inputs.emulators), skip_aliases=False)
set_console_sections(_group_by_manufacturer(db), program_names(profiles))
@@ -1431,7 +1434,7 @@ def system_search_aliases(sys_id: str) -> list[str]:
platform_system_names,
)
- platforms_dir = str(_REPO_ROOT / "platforms")
+ platforms_dir = str(siteinputs.current().platforms)
index: dict[str, set[str]] = {}
for platform in list_registered_platforms(platforms_dir, include_archived=True):
config = load_platform_config(platform, platforms_dir)
diff --git a/tests/test_site_inputs.py b/tests/test_site_inputs.py
index ab75d4be7..57ee16fa4 100644
--- a/tests/test_site_inputs.py
+++ b/tests/test_site_inputs.py
@@ -1,14 +1,17 @@
-"""generate_site --db reaches every page.
+"""generate_site --db, --emulators-dir and --platforms-dir reach every page.
The run loaded the given database, but the page-finishing pass reloaded the
repository's database.json: a card held only by the given collection stopped
-the whole run on a KeyError.
+the whole run on a KeyError. The emulator names and engine sections came from
+./emulators, and has_release_pack read `platforms` relative to the working
+directory, so a get/ page said "No ZIP" for a setup the API marked as released.
"""
from __future__ import annotations
import ast
import json
+import os
import shutil
import sys
import tempfile
@@ -19,6 +22,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import generate_site # noqa: E402
+import sitediagrams # noqa: E402
import siteinputs # noqa: E402
SHA1 = "0123456789ab" + "c" * 28
@@ -47,7 +51,65 @@ class TheGivenDatabase(_Inputs):
self.assertEqual(generate_site._collection_sha1_by_path(), {"bios/X/only-here.bin": SHA1})
-class GenerateInstallsTheInputs(unittest.TestCase):
+class TheGivenProfilesAndPlatforms(_Inputs):
+ def setUp(self) -> None:
+ tmp = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp" if (REPO_ROOT / "tmp").is_dir() else None))
+ self.addCleanup(shutil.rmtree, tmp)
+ self.emulators = tmp / "emulators"
+ self.emulators.mkdir()
+ (self.emulators / "fixturecore.yml").write_text(
+ "emulator: Fixture Core\ntype: libretro\nsystems: [fixture-system]\nfiles: []\n")
+ self.platforms = tmp / "platforms"
+ shutil.copytree(REPO_ROOT / "platforms", self.platforms)
+
+ def test_emulator_names_come_from_the_given_profiles(self) -> None:
+ self.use(emulators=self.emulators)
+ self.assertEqual(set(generate_site._profiles_on_disk()), {"fixturecore"})
+ self.assertEqual(generate_site._emulator_named_link("fixturecore"),
+ "[Fixture Core](emulators/fixturecore.md)")
+
+ def test_release_pack_does_not_depend_on_the_working_directory(self) -> None:
+ released = generate_site._release_pack_platforms()
+ self.assertIn("retroarch", released)
+ here = os.getcwd()
+ os.chdir(REPO_ROOT / "scripts")
+ self.addCleanup(os.chdir, here)
+ self.assertTrue(generate_site.has_release_pack("retroarch"))
+ self.assertEqual(generate_site.get_page_title("retroarch", "RetroArch"), "RetroArch BIOS pack")
+
+ def test_the_registry_comes_from_the_given_platforms(self) -> None:
+ registry = self.platforms / "_registry.yml"
+ registry.write_text(registry.read_text().replace("release_pack: true", "release_pack: false"))
+ self.use(platforms=self.platforms)
+ self.assertFalse(generate_site.has_release_pack("retroarch"))
+ self.assertEqual(sitediagrams.registry()["retroarch"].get("release_pack"), False)
+
+
+class NoPageModuleReadsTheRepositoryInputs(unittest.TestCase):
+ """A helper that opens the repository's database, profiles or platform
+ files itself bypasses the flags. siteinputs.current() is the one source."""
+
+ MODULES = ("generate_site.py", "siterender.py", "sitediagrams.py")
+ INPUTS = {"database.json", "emulators", "platforms"}
+
+ def test_no_literal_input_path(self) -> None:
+ found = []
+ for module in self.MODULES:
+ tree = ast.parse((REPO_ROOT / "scripts" / module).read_text(encoding="utf-8"))
+ for node in ast.walk(tree):
+ if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Div) \
+ and getattr(node.left, "id", "") in ("_REPO_ROOT", "ROOT") \
+ and isinstance(node.right, ast.Constant) and node.right.value in self.INPUTS:
+ found.append(f"{module}:{node.lineno}")
+ if isinstance(node, ast.Call) and getattr(node.func, "id", getattr(node.func, "attr", "")) in (
+ "load_platform_config", "load_platform_registry", "load_emulator_profiles",
+ "list_registered_platforms", "load_database", "extract_notes",
+ "load_data_dir_registry"):
+ for arg in node.args:
+ if isinstance(arg, ast.Constant) and arg.value in self.INPUTS:
+ found.append(f"{module}:{node.lineno}")
+ self.assertEqual(found, [])
+
def test_generate_installs_the_inputs_first(self) -> None:
source = ast.get_source_segment(
(REPO_ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8"),
diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md
index 3ef512d15..3a106e55c 100644
--- a/wiki/testing-guide.md
+++ b/wiki/testing-guide.md
@@ -65,7 +65,7 @@ Every module in `tests/`, by the area it guards.
| Pack probe | the cores a platform runs for a system, staging grown to a fixed point, runs mapped to pack and manifest entries, the line and its schema, the probe lock per run, that no page shows its lines. One class builds a real pack narrowed to PlayStation and lays it out both ways, from the archive and with `install.py --dest`, and skips without the collection | `test_pack_probe` |
| Automation runner, disk cleanup, asset sync and bit-flip repair | fake jobs, git repositories with a bare origin and session worktrees, a committed file with one bit flipped, canned CI runs in place of `gh` | `test_autorun` |
| Truth and native export | synthetic + cached originals | `test_export_counts`, `test_export_native_layer`, `test_export_report`, `test_exporters`, `test_truth_data_dir_readers`, `test_truth_diff`, `test_truth_layout` |
-| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_cited_lines`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_pin_build`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_retired_files`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_arcade_boards`, `test_site_availability`, `test_site_bootstrap`, `test_site_built_gate`, `test_site_components`, `test_site_console_folders`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_css`, `test_site_density_cards`, `test_site_emulator_page`, `test_site_emulators`, `test_site_entry`, `test_site_entry_tables`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_integration`, `test_site_nav`, `test_site_picker`, `test_site_platform_density`, `test_site_platform_hashes`, `test_site_reference`, `test_site_render`, `test_site_search`, `test_site_system_links`, `test_site_system_names`, `test_site_system_sections`, `test_site_systems`, `test_site_validation`, `test_site_weight`, `test_site_wiki`, `test_site_write`, `test_source_ref_targets`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_version_basis`, `test_workflow_paths` |
+| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_cited_lines`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_pin_build`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_retired_files`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_arcade_boards`, `test_site_availability`, `test_site_bootstrap`, `test_site_built_gate`, `test_site_components`, `test_site_console_folders`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_css`, `test_site_density_cards`, `test_site_emulator_page`, `test_site_emulators`, `test_site_entry`, `test_site_entry_tables`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_inputs`, `test_site_integration`, `test_site_nav`, `test_site_picker`, `test_site_platform_density`, `test_site_platform_hashes`, `test_site_reference`, `test_site_render`, `test_site_search`, `test_site_system_links`, `test_site_system_names`, `test_site_system_sections`, `test_site_systems`, `test_site_validation`, `test_site_weight`, `test_site_wiki`, `test_site_write`, `test_source_ref_targets`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_version_basis`, `test_workflow_paths` |
| Games on the card | small DATs, listxml and setup sources, a fake fetcher, fixture install lists, and the committed data against its schemas | `test_arcade_parents`, `test_game_catalogs`, `test_game_headers`, `test_game_regions`, `test_games_index`, `test_romfolders_card`, `test_romfolders_es` |
## Test architecture
From 6a79281e07729d3550f9d706d197920f63ec32f2 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:14:45 +0100
Subject: [PATCH 10/83] chore: read every site module in the text guards
Three guards named generate_site.py or a fixed list of four modules, while
page text now lives in twelve site modules and packreadme.py. The list
is a glob. Read that way, the pack README said "all of theirs" twice.
---
scripts/packreadme.py | 6 +++---
tests/sitepages.py | 9 +++++++++
tests/test_site_render.py | 9 +++++----
tests/test_site_validation.py | 18 +++++++++++++-----
4 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/scripts/packreadme.py b/scripts/packreadme.py
index 06ee483a3..ee5e5e26f 100644
--- a/scripts/packreadme.py
+++ b/scripts/packreadme.py
@@ -300,8 +300,8 @@ def _build_readme(
if fallback_systems:
listed = "\n".join(f" {_group_label(s)}" for s in fallback_systems)
region_info += (
- "\n These systems have no BIOS in those regions, so all\n"
- " of theirs were kept:\n"
+ "\n These systems have no BIOS in those regions, so every\n"
+ " BIOS file for them was kept:\n"
f"{listed}\n"
)
region_info += (
@@ -316,7 +316,7 @@ def _build_readme(
slot_info = (
" Where a core declares which BIOS it prefers, only that one was\n"
" kept for each system and region. Systems whose cores declare no\n"
- " order keep all of theirs.\n"
+ " order keep every BIOS file.\n"
)
if undecidable_slots:
slot_info += (
diff --git a/tests/sitepages.py b/tests/sitepages.py
index ee8897a55..f11300dd8 100644
--- a/tests/sitepages.py
+++ b/tests/sitepages.py
@@ -44,3 +44,12 @@ def pages() -> list[Path]:
def name(path: Path) -> str:
"""A page file's docs path, the name tests use for it."""
return path.relative_to(CONTENT).with_suffix(".md").as_posix()
+
+
+def generator_sources() -> list[Path]:
+ """Every module whose strings reach a page: generate_site.py, each
+ scripts/site*.py and the pack README writer. Listed by glob, so text
+ moved out of generate_site.py stays under the guards that read it."""
+ scripts = REPO_ROOT / "scripts"
+ return sorted({*scripts.glob("site*.py"), scripts / "generate_site.py",
+ scripts / "packreadme.py"})
diff --git a/tests/test_site_render.py b/tests/test_site_render.py
index f4b11a4ac..9628bd5ed 100644
--- a/tests/test_site_render.py
+++ b/tests/test_site_render.py
@@ -50,15 +50,16 @@ class EveryPageAddressesPlatformsAsPeers(unittest.TestCase):
text every site generator writes, docstrings and bare identifiers aside."""
WORDS = ("their file", "theirs", "of ours", "corrected", "left out", "drift")
- SOURCES = ("generate_site.py", "siterender.py", "sitesources.py", "siteexports.py")
-
def test_no_page_text_judges_another_project(self):
import ast
import re
+ from tests.sitepages import generator_sources
+
found = []
- for name in self.SOURCES:
- tree = ast.parse((REPO_ROOT / "scripts" / name).read_text(encoding="utf-8"))
+ for source in generator_sources():
+ name = source.name
+ tree = ast.parse(source.read_text(encoding="utf-8"))
docstrings = {
id(node.body[0].value) for node in ast.walk(tree)
if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef,
diff --git a/tests/test_site_validation.py b/tests/test_site_validation.py
index feac2d14a..e7ec40fb4 100644
--- a/tests/test_site_validation.py
+++ b/tests/test_site_validation.py
@@ -349,9 +349,13 @@ class TheSitemapIsAnnouncedWhereCrawlersLook(unittest.TestCase):
config = (root / "website" / "astro.config.mjs").read_text()
self.assertIn("site: SITE", config)
self.assertIn("sitemap.xml", config)
- source = (root / "scripts" / "generate_site.py").read_text()
- self.assertNotIn('"robots.txt"),\n "User-agent', source)
- self.assertNotIn("Sitemap: https://", source)
+ from tests.sitepages import generator_sources
+
+ for path in generator_sources():
+ source = path.read_text(encoding="utf-8")
+ with self.subTest(module=path.name):
+ self.assertNotIn('"robots.txt"),\n "User-agent', source)
+ self.assertNotIn("Sitemap: https://", source)
@@ -409,8 +413,12 @@ class PlainHouseStyle(unittest.TestCase):
def test_headings_do_not_repeat_the_site_name(self):
# The header bar already names the site, and the browser title gets
# it from the theme: "# DuckStation - RetroBIOS" said it twice.
- source = (ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8")
- self.assertNotRegex(source, r'"# [^"]* - (?:\{SITE_NAME\}|RetroBIOS)')
+ from tests.sitepages import generator_sources
+
+ for path in generator_sources():
+ with self.subTest(module=path.name):
+ self.assertNotRegex(path.read_text(encoding="utf-8"),
+ r'"# [^"]* - (?:\{SITE_NAME\}|RetroBIOS)')
for page in sorted((ROOT / "wiki").glob("*.md")):
first = page.read_text(encoding="utf-8").splitlines()[0]
with self.subTest(page=page.name):
From 25b9c85208addfbea10e184434a3cc3388f6a53e Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:15:15 +0100
Subject: [PATCH 11/83] fix: refuse an unreadable native sources index
_load_sources read a truncated .sources.json as empty: fetch served
the cached original of an older pin as current, the next download
rewrote the index with one entry, and check_freshness said no URL was
recorded. It now raises SourcesIndexUnreadable naming the remedy, and
check_freshness reports one ERROR row for the index.
---
scripts/check_freshness.py | 5 ++++-
scripts/export_native.py | 19 +++++++++++++++++--
tests/test_check_freshness.py | 8 ++++++++
tests/test_exporters.py | 16 ++++++++++++++++
4 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py
index b8e03f28b..3f703d768 100644
--- a/scripts/check_freshness.py
+++ b/scripts/check_freshness.py
@@ -509,7 +509,10 @@ def check_native(
) -> list[Finding]:
exporters = discover_exporters()
index = cache_dir / export_native.SOURCES_INDEX
- recorded = export_native.load_sources(cache_dir)
+ try:
+ recorded = export_native.load_sources(cache_dir)
+ except export_native.SourcesIndexUnreadable as exc:
+ return [Finding("native", index.name, ERROR, detail=str(exc))]
findings: list[Finding] = []
for name in list_registered_platforms(str(platforms_dir), include_archived=True):
exporter_class = exporters.get(name)
diff --git a/scripts/export_native.py b/scripts/export_native.py
index 42d529eba..d91e9e783 100644
--- a/scripts/export_native.py
+++ b/scripts/export_native.py
@@ -36,6 +36,7 @@ from artifacts import file_lock, write_bytes_atomic, write_if_changed, write_tex
import yaml
from common import (
+ InputMissing,
build_zip_contents_index,
platform_arg,
list_registered_platforms,
@@ -62,13 +63,27 @@ _USER_AGENT = "retrobios-exporter/1.0"
_MAX_BYTES = 64 * 1024 * 1024
+class SourcesIndexUnreadable(InputMissing):
+ """The cache's URL index exists and does not read as JSON."""
+
+
def _load_sources(index: Path | None) -> dict[str, str]:
+ """The URL each cached file was fetched from.
+
+ An absent index records nothing. An index that does not read raises:
+ read as empty it let every cached original pass for current, and the
+ next download rewrote it with that one entry.
+ """
if index is None or not index.is_file():
return {}
try:
return json.loads(index.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError):
- return {}
+ except (OSError, json.JSONDecodeError) as exc:
+ raise SourcesIndexUnreadable(
+ f"{index} does not read ({exc}): remove it, then"
+ " python scripts/export_native.py --all --refresh-cache"
+ " downloads every original again and records its URL"
+ ) from exc
def source_key(destination: Path, index: Path | None) -> str:
diff --git a/tests/test_check_freshness.py b/tests/test_check_freshness.py
index 72846872f..9fedcc590 100644
--- a/tests/test_check_freshness.py
+++ b/tests/test_check_freshness.py
@@ -35,6 +35,14 @@ class NativeCacheTests(unittest.TestCase):
self.root.mkdir()
self.wanted = {"list.txt": "https://example.invalid/tag-2/list.txt"}
+ def test_an_unreadable_index_is_an_error_not_unrecorded(self):
+ """Read as empty, it named "no URL recorded" for every original."""
+ self.index.write_text("{", encoding="utf-8")
+ findings = cf.check_native(REPO_ROOT / "platforms", self.cache, self.cache)
+ self.assertEqual([(f.subject, f.status) for f in findings],
+ [(self.index.name, cf.ERROR)])
+ self.assertIn("--refresh-cache", findings[0].detail)
+
def _cached(self, mtime: float) -> None:
path = self.root / "list.txt"
path.write_text("x", encoding="utf-8")
diff --git a/tests/test_exporters.py b/tests/test_exporters.py
index f84b4e624..391171064 100644
--- a/tests/test_exporters.py
+++ b/tests/test_exporters.py
@@ -1005,6 +1005,22 @@ class CachedOriginal(unittest.TestCase):
self._upstream("v1.txt", "moved")
self.assertEqual(fetch(url, target, self.index), b"one")
+ def test_an_unreadable_index_serves_nothing(self):
+ """A truncated index read as empty: the cached batocera-41 file was
+ served for a 43.1 URL, and the next download erased every other
+ platform's recorded URL."""
+ import export_native
+
+ old = self._upstream("batocera-41.txt", "old")
+ target = self.cache / "plat" / "list.txt"
+ fetch(old, target, self.index)
+ self.index.write_text('{"plat/list.txt": "' + old + '",', encoding="utf-8")
+ new = self._upstream("batocera-43.txt", "new")
+ with self.assertRaises(export_native.SourcesIndexUnreadable) as caught:
+ fetch(new, target, self.index)
+ self.assertIn("--refresh-cache", str(caught.exception))
+ self.assertTrue(self.index.read_text(encoding="utf-8").endswith(","))
+
def test_refresh_reads_a_branch_url_again(self):
"""A branch URL keeps its name while the platform moves."""
url = self._upstream("branch.txt", "one")
From 807ffa0ca98d9808e19d220afa6208bcd132772f Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:16:08 +0100
Subject: [PATCH 12/83] fix: let content labels accept their region slot
verify judged a found_by: content entry by its label alone and called ROCKNIX's scph1001.bin (v2.0) a rustation sha256 mismatch, though rustation declares and boots that dump. A label now accepts the dumps its core takes for the same system and declared region.
---
scripts/validation.py | 69 +++++++++++++++++++++++++++++++++-
tests/test_validation_scope.py | 39 +++++++++++++++++++
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/scripts/validation.py b/scripts/validation.py
index 544451f90..5a4272dd5 100644
--- a/scripts/validation.py
+++ b/scripts/validation.py
@@ -16,6 +16,7 @@ from common import (
adler32_of,
archive_members,
compute_hashes,
+ entry_system_ids,
name_match_size_ok,
sanitize_pack_path,
size_fits,
@@ -145,6 +146,72 @@ def _rule_failure(
return None
+def _found_by_content(entry: dict, profile: dict) -> bool:
+ """Whether every build of the core identifies this entry by content."""
+ return not opens_by_name(entry, profile) and not opens_by_name(
+ entry, profile, standalone=True
+ )
+
+
+def _regions(entry: dict) -> set[str]:
+ value = entry.get("region")
+ return set(value) if isinstance(value, list) else {value} if value else set()
+
+
+def content_alternatives(entry: dict, profile: dict) -> list[dict]:
+ """The labels a content-found core takes in place of this one.
+
+ rustation scans its folder by sha256 (found_by: content): its
+ scph1001.bin is a label for v2.2, and the v2.0 dump ROCKNIX ships under
+ that name boots the same North American console, labelled
+ scph1001_v20.bin. Alternatives share the entry's system and declared
+ region, the slot slot.py groups by: openMSX also finds its ROMs by
+ sha1, but each one serves its own machine and declares no region.
+ """
+ if not _found_by_content(entry, profile):
+ return []
+ regions = _regions(entry)
+ if not regions:
+ return []
+ systems = set(entry_system_ids(entry, profile))
+ return [
+ other for other in profile.get("files") or []
+ if isinstance(other, dict)
+ and _found_by_content(other, profile)
+ and regions & _regions(other)
+ and systems == set(entry_system_ids(other, profile))
+ ]
+
+
+def _labels_widened(profile: dict) -> list[dict]:
+ """The profile's entries, each content-found label accepting the dumps
+ of its alternatives (content_alternatives)."""
+ widened = []
+ for f in profile.get("files") or []:
+ if not isinstance(f, dict):
+ continue
+ siblings = content_alternatives(f, profile)
+ if len(siblings) < 2:
+ widened.append(f)
+ continue
+ merged = dict(f)
+ for field_name in ("crc32", "md5", "sha1", "sha256"):
+ if f.get(field_name):
+ merged[field_name] = list(dict.fromkeys(
+ value for other in siblings
+ for value in parse_hash_list(other.get(field_name))
+ ))
+ if f.get("size") is not None:
+ merged["size"] = sorted({
+ size for other in siblings
+ for size in (other["size"] if isinstance(other.get("size"), list)
+ else [other.get("size")])
+ if size is not None
+ })
+ widened.append(merged)
+ return widened
+
+
def _build_validation_index(profiles: dict) -> dict[str, dict]:
"""Build per-filename validation rules from emulator profiles.
@@ -170,7 +237,7 @@ def _build_validation_index(profiles: dict) -> dict[str, dict]:
for emu_name, profile in profiles.items():
if profile.get("type") in ("launcher", "alias"):
continue
- for f in profile.get("files", []):
+ for f in _labels_widened(profile):
fname = f.get("name", "")
if not fname:
continue
diff --git a/tests/test_validation_scope.py b/tests/test_validation_scope.py
index 87399f979..30c8946b4 100644
--- a/tests/test_validation_scope.py
+++ b/tests/test_validation_scope.py
@@ -47,5 +47,44 @@ class HleIndexScope(unittest.TestCase):
self.assertIn("for profile in platform_profiles.values()", block)
self.assertNotIn("profiles.values()", block.replace("platform_profiles.values()", ""))
+
+class ContentFoundLabelsTakeTheirRegionSlot(unittest.TestCase):
+ """rustation scans its folder by sha256, so its scph1001.bin entry is a
+ label. ROCKNIX ships the v2.0 dump under that name, which rustation
+ boots (labelled scph1001_v20.bin), and verify called it a mismatch."""
+
+ def test_an_alternative_dump_passes_under_the_label(self):
+ import hashlib
+ import sys
+ import tempfile
+
+ sys.path.insert(0, str(REPO_ROOT / "scripts"))
+ from validation import _build_validation_index, check_file_validation
+
+ with tempfile.TemporaryDirectory() as tmp:
+ path = Path(tmp) / "scph1001.bin"
+ path.write_bytes(b"v2.0")
+ v20 = hashlib.sha256(b"v2.0").hexdigest()
+ profile = {
+ "found_by": "content",
+ "systems": ["sony-playstation"],
+ "files": [
+ {"name": "scph1001.bin", "region": ["north-america"],
+ "validation": ["sha256"], "sha256": "a" * 64},
+ {"name": "scph1001_v20.bin", "region": ["north-america"],
+ "validation": ["sha256"], "sha256": v20},
+ {"name": "scph5500.bin", "region": ["japan"],
+ "validation": ["sha256"], "sha256": "b" * 64},
+ ],
+ }
+ index = _build_validation_index({"rustation": profile})
+ self.assertIsNone(check_file_validation(str(path), "scph1001.bin", index))
+ # Another region is another slot.
+ self.assertIsNotNone(check_file_validation(str(path), "scph5500.bin", index))
+ # A core that opens the file by name rejects it.
+ index = _build_validation_index({"rustation": {**profile, "found_by": "name"}})
+ self.assertIsNotNone(check_file_validation(str(path), "scph1001.bin", index))
+
+
if __name__ == "__main__":
unittest.main()
From 6695efeebeab687e41cc9f7d2ad92ce3377e230a Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:16:08 +0100
Subject: [PATCH 13/83] fix: scope slot labels to system and region
slots reads content_alternatives too, so a content-found label is settled only by a dump of its own system and region slot.
---
scripts/slots.py | 25 +++++++------------------
tests/test_slots.py | 14 ++++++++++++--
2 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/scripts/slots.py b/scripts/slots.py
index f3908a631..cb69660c1 100644
--- a/scripts/slots.py
+++ b/scripts/slots.py
@@ -44,7 +44,7 @@ from common import (
)
from packresolve import preferred_entries
from validation import (
- opens_by_name,
+ content_alternatives,
outside_gap_scope,
read_from_save_dir,
with_archive_members,
@@ -91,7 +91,7 @@ class Claim:
local_path: str | None = None
status: str = ""
# A core that identifies its firmware by content reads no file by this
- # name: any dump it accepts for the system answers for it.
+ # name: any dump it takes for the same system and region answers for it.
accepts: tuple[dict, ...] = ()
@property
@@ -218,12 +218,6 @@ def profile_claims(
zip_contents, data_dir_registry,
)
)
- labels = [
- f for f in profile.get("files") or []
- if isinstance(f, dict)
- and not opens_by_name(f, profile, is_standalone)
- and _lists_hashes(f)
- ]
for entry in profile.get("files") or []:
if not isinstance(entry, dict):
continue
@@ -274,13 +268,7 @@ def profile_claims(
)
if status == "name_exact" and _size_the_code_reads(entry, local):
status = SIZE_EXACT
- accepts: tuple[dict, ...] = ()
- if not opens_by_name(entry, profile, is_standalone):
- systems = set(entry_system_ids(entry, profile))
- accepts = tuple(
- f for f in labels
- if not systems or systems & set(entry_system_ids(f, profile))
- )
+ accepts = tuple(content_alternatives(entry, profile))
claims.append(
Claim(
origin="profile",
@@ -769,8 +757,8 @@ def _satisfies(profile: Claim, platform: Claim, db: dict) -> bool:
hash list accepts the profile's file, or when the profile's accepts the
platform's. A contradiction needs both lists to reject the other side.
A core found by content (found_by: content) reads no file by the
- destination's name, so any dump it accepts for the system settles the
- slot: DuckStation takes Batocera's scph1001.bin v2.0, which its profile
+ destination's name, so any dump it takes for the same system and region
+ settles the slot: DuckStation takes Batocera's scph1001.bin v2.0, which its profile
labels scph1001_v20.bin.
"""
if profile.local_path == platform.local_path:
@@ -791,7 +779,8 @@ def _satisfies(profile: Claim, platform: Claim, db: dict) -> bool:
):
return True
if platform.local_path and any(
- _accepted_by_all(platform.local_path, [label], db) for label in profile.accepts
+ _lists_hashes(label) and _accepted_by_all(platform.local_path, [label], db)
+ for label in profile.accepts
):
return True
return bool(
diff --git a/tests/test_slots.py b/tests/test_slots.py
index 0acf3c653..f5c7eafbc 100644
--- a/tests/test_slots.py
+++ b/tests/test_slots.py
@@ -116,8 +116,9 @@ class TestConflicts(unittest.TestCase):
scph1001.bin entry is a label. Batocera ships the v2.0 dump there,
which the profile accepts under scph1001_v20.bin: no conflict."""
files = [
- {"name": "IPL.bin", "path": "GC/JAP/IPL.bin", "md5": "n" * 32},
- {"name": "IPL_usa.bin", "md5": "m" * 32},
+ {"name": "IPL.bin", "path": "GC/JAP/IPL.bin", "md5": "n" * 32,
+ "region": ["japan"]},
+ {"name": "IPL_alt.bin", "md5": "m" * 32, "region": ["japan"]},
]
by_name = slots.find_conflicts(
self._config("m" * 32), {"dolphin": {"files": files}}, REGIONS_DB
@@ -129,6 +130,15 @@ class TestConflicts(unittest.TestCase):
REGIONS_DB,
)
self.assertEqual(by_content, [])
+ # Another region is another slot: openMSX finds each ROM by sha1 too,
+ # and one machine's ROM never stands for another's.
+ files[1]["region"] = ["north-america"]
+ other_slot = slots.find_conflicts(
+ self._config("m" * 32),
+ {"dolphin": {"found_by": "content", "files": files}},
+ REGIONS_DB,
+ )
+ self.assertEqual(len(other_slot), 1)
def test_wrong_region_under_a_region_slot_is_reported(self):
conflicts = slots.find_conflicts(
From dfa1cc31d380a55806974daeed5944d717ebec7b Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:16:18 +0100
Subject: [PATCH 14/83] fix: generate_truth refuses a target it lacks
--platform bizhawk --target switch printed skipped, then Done., and
exited 0 with no model written. generate_truth now resolves targets
through build_target_cores_cache, as verify and generate_pack do: a
named platform without the target is refused with exit 1, --all
leaves such platforms out and says so.
---
scripts/generate_truth.py | 27 +++++++++++++++------------
tests/test_truth_diff.py | 16 ++++++++++++++++
2 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/scripts/generate_truth.py b/scripts/generate_truth.py
index ac5856667..472ae3ea7 100644
--- a/scripts/generate_truth.py
+++ b/scripts/generate_truth.py
@@ -14,13 +14,13 @@ import sys
sys.path.insert(0, os.path.dirname(__file__))
from common import (
+ build_target_cores_cache,
platform_arg,
list_registered_platforms,
load_data_dir_registry,
load_database,
load_emulator_profiles,
load_platform_config,
- load_target_config,
require_directory,
require_platform,
require_yaml,
@@ -97,6 +97,19 @@ def main(argv: list[str] | None = None) -> None:
require_platform(args.platform, args.platforms_dir)
platforms = [args.platform]
+ # A named platform without that target is refused, as verify and
+ # generate_pack refuse it: skipped, it printed Done. and exited 0 with
+ # no model written. --all leaves such platforms out and says so.
+ target_cores_cache: dict[str, set[str] | None] = {}
+ if args.target:
+ try:
+ target_cores_cache, platforms = build_target_cores_cache(
+ platforms, args.target, args.platforms_dir, is_all=args.all
+ )
+ except (FileNotFoundError, ValueError) as exc:
+ print(f"ERROR: {exc}", file=sys.stderr)
+ sys.exit(1)
+
# A target-narrowed model is a different artifact: written under the
# platform's own name it overwrote the full one, and diff_truth then
# compared a narrowed model against the whole scrape. Its directory is
@@ -109,17 +122,7 @@ def main(argv: list[str] | None = None) -> None:
output_dir, [name], args.target, args.platforms_dir
)
os.makedirs(output_dir, exist_ok=True)
- target_cores: set[str] | None = None
- if args.target:
- try:
- target_cores = load_target_config(
- name,
- args.target,
- args.platforms_dir,
- )
- except FileNotFoundError:
- print(f" {name}: no target config, skipped")
- continue
+ target_cores = target_cores_cache.get(name)
# Load platform config (with inheritance) and registry entry
try:
diff --git a/tests/test_truth_diff.py b/tests/test_truth_diff.py
index fa48edf6e..949be7c7d 100644
--- a/tests/test_truth_diff.py
+++ b/tests/test_truth_diff.py
@@ -60,6 +60,22 @@ class ATargetedModelIsItsOwnArtifact(unittest.TestCase):
)
+ def test_a_named_platform_without_the_target_is_refused(self):
+ """bizhawk --target switch printed "skipped", then Done., exit 0,
+ and wrote no model: the diff after it failed instead."""
+ repo = pathlib.Path(__file__).resolve().parent.parent
+ with tempfile.TemporaryDirectory(dir=str(repo / "tmp")) as directory:
+ proc = subprocess.run(
+ [sys.executable, "scripts/generate_truth.py", "--platform", "bizhawk",
+ "--target", "switch", "--output-dir", directory],
+ capture_output=True, check=False, text=True, cwd=str(repo), timeout=400,
+ )
+ self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
+ self.assertIn("bizhawk has no hardware targets", proc.stderr)
+ self.assertNotIn("Done.", proc.stdout)
+ self.assertEqual(list(pathlib.Path(directory).iterdir()), [])
+
+
class ADiffThatComparedNothingFails(unittest.TestCase):
"""diff_truth --all skipped every platform without a model and exited 0."""
From 2f721bc640d3ea7425c4dffd4d0e697dea379f17 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:16:44 +0100
Subject: [PATCH 15/83] fix: list unsourceable files as not collected yet
Every card read "Not collectable" and the gaps page listed 259 entries as
acknowledged gaps verified from source code. unsourceable: only keeps a
same-named file from being served in the entry's place, and each entry
stays an acquisition target (wiki/profiling.md). The section now names
the catalog or romset that lists each file, from the provenance report
built with the profiles' needs: XM7's KANJI2.ROM is in No-Intro and in
MAME's fm7740sx.zip. The old anchor still leads to the section.
---
scripts/generate_site.py | 74 +++++++++++++++++++++++----------
tests/test_audit_regressions.py | 28 ++++++++++++-
2 files changed, 79 insertions(+), 23 deletions(-)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 62f400543..0eece3cfc 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -86,7 +86,7 @@ from generate_readme import (
extract_targets,
release_totals,
)
-from provenance_report import build_report, distinct_missing
+from provenance_report import build_report, distinct_missing, profile_needs
import sitemarkup as markup
import siteentries
import siteinputs
@@ -8433,12 +8433,7 @@ def _render_emulator_file(
if fnote:
lines.append(f"- {data_root_words(_escape_tags(link_prose_citations(profile, str(fnote))), data_href)}")
if not in_repo and f.get("unsourceable"):
- # The badge alone sent readers after a dump that cannot exist, and the
- # reason was only on the gaps page, which the card did not link.
- lines.append(
- f"- Not collectable: {_escape_tags(str(f['unsourceable']))} "
- "([acknowledged gaps](../gaps.md#acknowledged-gaps))"
- )
+ lines.append(f"- {_unsourceable_line(f)}")
lines.extend(_contents_lines(contents))
lines[body_start:] = _search_skipped_apart(lines[body_start:])
lines.append("")
@@ -8550,12 +8545,7 @@ def _emulator_card_folds(
open_lines.append(data_root_words(
_escape_tags(link_prose_citations(profile, str(fnote))), data_href))
if not in_repo and f.get("unsourceable"):
- # The badge alone sent readers after a dump that cannot exist, and the
- # reason was only on the gaps page, which the card did not link.
- open_lines.append(
- f"Not collectable: {_escape_tags(str(f['unsourceable']))} "
- "([acknowledged gaps](../gaps.md#acknowledged-gaps))"
- )
+ open_lines.append(_unsourceable_line(f))
lines = [f"- {d}" for d in open_lines]
shut_fold = [f"- {d}" for d in hashes + [m for m in more if skipped(m)]]
read_fold = [f"- {m}" for m in more if not skipped(m)]
@@ -10459,6 +10449,33 @@ def _hash_cell(hashes: dict[str, list[str]]) -> str:
)
+def _unsourceable_line(f: dict) -> str:
+ """Why the collection holds no copy of a file a profile marks
+ `unsourceable:`, linked to the list of them. The flag only keeps a
+ same-named file from being served in its place: the file is still
+ wanted, and "Not collectable" sent readers away from KANJI2.ROM, which
+ MAME's fm7740sx.zip carries."""
+ return (f"Not collected yet: {_escape_tags(str(f['unsourceable']))} "
+ "([files not collected yet](../gaps.md#not-collected-yet))")
+
+
+def _catalogued_needs(report: dict | None) -> dict[tuple[str, str], list[str]]:
+ """(profile, file name casefolded) -> where a dump catalog or an
+ imported romset lists that file, from a provenance report built with
+ the profiles' needs."""
+ out: dict[tuple[str, str], list[str]] = {}
+ for source, data in sorted((report or {}).items()):
+ label = _PROVENANCE_LABELS.get(source, source)
+ for entry in data.get("missing", []):
+ where = [f"{label} `{_escape_tags(str(entry.get('name', '')))}`"]
+ where += [f"{_escape_tags(str(hit['source']))} `{_escape_tags(str(hit['archive']))}`"
+ for hit in entry.get("romsets", [])]
+ for need in entry.get("needed_by", []):
+ held = out.setdefault((need["emulator"], str(need["name"]).casefold()), [])
+ held += [w for w in where if w not in held]
+ return out
+
+
def _reason_cell(text: str) -> str:
"""A reason in a gaps table, in the class that keeps its column readable."""
return f'{text}' if text else "-"
@@ -10753,9 +10770,14 @@ def generate_gap_analysis(
registry: dict | None = None,
gap_report: dict | None = None,
moved: dict[str, str] | None = None,
+ catalogued: dict | None = None,
) -> str:
"""Generate a unified gap analysis page.
+ ``catalogued`` is a provenance report built with the profiles' needs:
+ a file the collection does not hold yet names the catalog or romset
+ that lists it.
+
With ``moved``, the list of files to source goes to pages of its own,
keyed by stem: on the page it made 662 KB of HTML.
@@ -11186,7 +11208,7 @@ def generate_gap_analysis(
"",
])
- # ---- Section 4: Acknowledged gaps (unsourceable files) ----
+ # ---- Section 4: files the collection does not hold yet (unsourceable) ----
all_unsourceable: list[dict] = []
for emu_name, data in sorted(report_all.items()):
@@ -11200,19 +11222,26 @@ def generate_gap_analysis(
})
if all_unsourceable:
+ listed = _catalogued_needs(catalogued)
+ # The old heading's address still leads here.
lines.extend([
- "## Acknowledged gaps",
+ '',
"",
- f"{len(all_unsourceable)} files documented as unsourceable "
- "(verified from source code).",
+ "## Not collected yet",
"",
- "| File | Emulator | Reason | Source ref |",
- "|------|----------|--------|-----------|",
+ f"{len(all_unsourceable)} files the collection does not hold. A file "
+ "with the same name is never served in their place. Each is still "
+ "wanted, and the last column names a catalog or romset that lists it.",
+ "",
+ "| File | Emulator | Reason | Source ref | Listed in |",
+ "|------|----------|--------|-----------|-----------|",
])
for u in sorted(all_unsourceable, key=lambda x: x["name"]):
+ where = listed.get((u["emu_key"], str(u["name"]).casefold()), [])
lines.append(
f"| `{u['name']}` | {u['emulator']} | {_reason_cell(u['reason'])} "
- f"| {_source_ref_markdown(profiles[u['emu_key']], u['source_ref'])} |"
+ f"| {_source_ref_markdown(profiles[u['emu_key']], u['source_ref'])} "
+ f"| {', '.join(where) or '-'} |"
)
lines.append("")
@@ -12563,12 +12592,16 @@ def _generate(args: argparse.Namespace) -> None:
sitestarlight.MOVED_PAGES.setdefault(
f"cross-reference-{pname}.md", f"platforms/{pname}.md")
+ provenance_report = build_report(
+ db, load_provenance_snapshots(), needs=profile_needs(profiles, db))
+
print("Generating gap analysis page...")
gap_pages: dict[str, str] = {}
write_if_changed(
str(docs / "gaps.md"),
tables_out_of_search(generate_gap_analysis(
profiles, coverages, db, suppl_names, registry, gap_report, gap_pages,
+ catalogued=provenance_report,
)) + reference_next(),
)
for stem, page in gap_pages.items():
@@ -12584,7 +12617,6 @@ def _generate(args: argparse.Namespace) -> None:
)
print("Generating dump provenance page...")
- provenance_report = build_report(db, load_provenance_snapshots())
provenance_pages: dict[str, str] = {}
write_if_changed(
str(docs / "provenance.md"),
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 3df8850fe..91110a2d5 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -5143,8 +5143,32 @@ class UnsourceableCardSaysWhy(unittest.TestCase):
text = "\n".join(_render_emulator_file(
entry, {"files": [entry]}, None, [entry], lambda f: False, "file-x",
))
- self.assertIn("Not collectable: written by the firmware editor", text)
- self.assertIn("../gaps.md#acknowledged-gaps", text)
+ self.assertIn("Not collected yet: written by the firmware editor", text)
+ self.assertIn("../gaps.md#not-collected-yet", text)
+ self.assertNotIn("collectable", text)
+
+ def test_the_gaps_page_names_where_a_wanted_file_is_listed(self):
+ """The section read "Acknowledged gaps ... (verified from source
+ code)" while No-Intro lists XM7's KANJI2.ROM and MAME's fm7740sx.zip
+ carries it: the flag only keeps a homonym out, the file is wanted."""
+ from scripts.generate_site import generate_gap_analysis
+
+ unsourced = {"name": "KANJI2.ROM", "reason": "no dump distributed", "source_ref": ""}
+ report = {"xm7": {"emulator": "XM7", "gaps": 0, "gap_missing": 0, "gap_bios": 0,
+ "unsourceable": [unsourced], "gap_details": []}}
+ catalogued = {"no-intro": {"missing": [{
+ "name": "KANJI2.rom",
+ "romsets": [{"source": "mame", "archive": "fm7740sx.zip"}],
+ "needed_by": [{"emulator": "xm7", "name": "KANJI2.ROM", "required": True}],
+ }]}}
+ page = generate_gap_analysis(
+ {"xm7": {"emulator": "XM7", "files": []}}, {}, {"files": {}, "indexes": {}},
+ gap_report=report, catalogued=catalogued)
+ self.assertIn("## Not collected yet", page)
+ self.assertIn('', page)
+ self.assertIn("| No-Intro `KANJI2.rom`, mame `fm7740sx.zip` |", page)
+ self.assertNotIn("Acknowledged", page)
+ self.assertNotIn("verified from source code", page)
From 2a0088a0fc03bbe598702aba08da45784a0456c9 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:17:11 +0100
Subject: [PATCH 16/83] docs: name the launcher index in installer changes
install/launchers/index.json records the SHA-256 of install.py that
--add-app checks, and the page listed only the pins of install.sh and
install.ps1 as what a change to install.py rewrites.
---
tests/test_port.py | 7 +++++++
wiki/installer.md | 5 ++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/tests/test_port.py b/tests/test_port.py
index 269d4023e..5c873e84b 100644
--- a/tests/test_port.py
+++ b/tests/test_port.py
@@ -124,6 +124,13 @@ class LauncherIndex(unittest.TestCase):
"install/launchers/index.json is stale: run "
"python scripts/generate_launcher_index.py")
+ def test_the_installer_page_says_when_to_rewrite_it(self):
+ """The list records install.py's SHA-256, and the page that says
+ what a change to install.py rewrites named only the two pins."""
+ page = (REPO_ROOT / "wiki" / "installer.md").read_text(encoding="utf-8")
+ section = page.split("## Changing the installer", 1)[1].split("\n## ", 1)[0]
+ self.assertIn("scripts/generate_launcher_index.py", section)
+
def test_every_member_of_the_archives_is_listed(self):
import generate_launcher_index # noqa: PLC0415
diff --git a/wiki/installer.md b/wiki/installer.md
index 73719bf16..afcacf4ef 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -1702,7 +1702,10 @@ a real 3.8 interpreter, which CI installs beside 3.12 so the check cannot skip.
The build scripts need 3.9 and are not bound by this.
Every change to `install.py` recomputes the SHA-256 pinned in `install.sh` and
-`install.ps1` in the same commit. The tests compare the pins with the file.
+`install.ps1` in the same commit, and runs `scripts/generate_launcher_index.py`:
+`install/launchers/index.json` records the hash of `install.py` that
+`--add-app` checks before it writes a launcher on a card. The tests compare
+the pins and the list with the file.
The tables of options, events, exit codes, keys and card markers, the line
menu and the run samples on this page sit between `generated` markers and are
From 97d0a478d2fd3a1d62cdbee62ed911c372df5712 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:18:59 +0100
Subject: [PATCH 17/83] fix: read RetroArch's config under XDG_CONFIG_HOME
Native RetroArch on Linux keeps retroarch.cfg under $XDG_CONFIG_HOME/retroarch when the variable is set, and falls back to ~/.retroarch.cfg (file_path_special.c fill_pathname_application_data, configuration.c open_default_config_file at e98e1da0). Detection read ~/.config/retroarch only.
---
install.ps1 | 2 +-
install.py | 31 +++++++++++++++++-------
install.sh | 2 +-
install/launchers/index.json | 16 ++++++-------
install/retroarch.json | 12 ++++++++++
platforms/_registry.yml | 13 ++++++++++
tests/test_install.py | 46 ++++++++++++++++++++++++++++++++++++
7 files changed, 104 insertions(+), 18 deletions(-)
diff --git a/install.ps1 b/install.ps1
index 896cdaf76..e41f7f32d 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858"
+ $defaultInstallSha256 = "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index 01c0b9425..05a057480 100644
--- a/install.py
+++ b/install.py
@@ -291,7 +291,6 @@ def _os_default_dests(os_type: str) -> dict[str, Path]:
the command line but not found must not land in ~/bios, which none of
them reads.
"""
- home = Path.home()
if os_type == "windows":
return {
# RetroArch's system directory defaults to \system
@@ -307,13 +306,13 @@ def _os_default_dests(os_type: str) -> dict[str, Path]:
# RetroArch may be the Linux one inside the distribution, while RetroBat
# only exists on the Windows side, reached through /mnt/c.
return {
- "retroarch": home / ".config" / "retroarch" / "system",
+ "retroarch": _unix_retroarch_base() / "system",
"retrobat": _host_path("C:/RetroBat/bios"),
}
if os_type == "darwin":
return {"retroarch": _macos_retroarch_base() / "system"}
return {
- "retroarch": home / ".config" / "retroarch" / "system",
+ "retroarch": _unix_retroarch_base() / "system",
}
@@ -1385,6 +1384,17 @@ def _macos_retroarch_base() -> Path:
return Path.home() / "Documents" / "RetroArch"
+def _unix_retroarch_base() -> Path:
+ """RetroArch's base folder on Linux: $XDG_CONFIG_HOME/retroarch when the
+ variable is set, else ~/.config/retroarch (fill_pathname_application_data
+ in file_path_special.c, frontend_unix_get_env in platform_unix.c). The
+ code tests only that the variable exists, so an empty one counts."""
+ xdg = os.environ.get("XDG_CONFIG_HOME")
+ if xdg is not None:
+ return Path(xdg) / "retroarch"
+ return Path.home() / ".config" / "retroarch"
+
+
# System directory -> the retroarch.cfg it was read from and the directory
# ':' expands to there, for finding the cores of the same installation.
_RETROARCH_CONFIGS: dict[Path, tuple[Path, Path]] = {}
@@ -2773,11 +2783,16 @@ def detect_platforms(os_type: str) -> list[tuple[str, Path]]:
if ra_dir:
found.append(("retroarch", ra_dir))
- # RetroArch native
- native_cfg = home / ".config" / "retroarch" / "retroarch.cfg"
- ra_dir = _parse_retroarch_system_dir(native_cfg)
- if ra_dir:
- found.append(("retroarch", ra_dir))
+ # RetroArch native: the config under its base folder, then
+ # ~/.retroarch.cfg when that one is missing (open_default_config_file
+ # in configuration.c). Either way the system folder defaults to the
+ # base folder's.
+ native_base = _unix_retroarch_base()
+ for native_cfg in (native_base / "retroarch.cfg", home / ".retroarch.cfg"):
+ ra_dir = _parse_retroarch_system_dir(native_cfg, native_base)
+ if ra_dir:
+ found.append(("retroarch", ra_dir))
+ break
if os_type == "darwin":
# open_default_config_file reads /RetroArch/config
diff --git a/install.sh b/install.sh
index b085a4cbb..26c45e4c6 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858"
+DEFAULT_INSTALL_SHA256="f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 358ee41c9..5ee293708 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103894,
+ "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1156738,
- "sha256": "35c0920008baadca997d0f778e99ce46d702bbe3d3f0d33104d7158422b292aa"
+ "size": 1157521,
+ "sha256": "0f9b070334a530a0ed5a6b6b773928d92f5a08aa0d0af18fde7b6cb4a16e731d"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103894,
+ "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103894,
+ "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
"executable": false
},
{
diff --git a/install/retroarch.json b/install/retroarch.json
index 024fb6396..166d197d3 100644
--- a/install/retroarch.json
+++ b/install/retroarch.json
@@ -21,12 +21,24 @@
"config": "$HOME/snap/retroarch/current/.config/retroarch/retroarch.cfg",
"parse_key": "system_directory"
},
+ {
+ "os": "linux",
+ "method": "config_file",
+ "config": "$XDG_CONFIG_HOME/retroarch/retroarch.cfg",
+ "parse_key": "system_directory"
+ },
{
"os": "linux",
"method": "config_file",
"config": "$HOME/.config/retroarch/retroarch.cfg",
"parse_key": "system_directory"
},
+ {
+ "os": "linux",
+ "method": "config_file",
+ "config": "$HOME/.retroarch.cfg",
+ "parse_key": "system_directory"
+ },
{
"os": "darwin",
"method": "config_file",
diff --git a/platforms/_registry.yml b/platforms/_registry.yml
index 891b01a95..a2da8d55c 100644
--- a/platforms/_registry.yml
+++ b/platforms/_registry.yml
@@ -219,10 +219,23 @@ platforms:
method: config_file
config: $HOME/snap/retroarch/current/.config/retroarch/retroarch.cfg
parse_key: system_directory
+ # Native: $XDG_CONFIG_HOME/retroarch when the variable is set, else
+ # $HOME/.config/retroarch, then $HOME/.retroarch.cfg when that file is
+ # missing (file_path_special.c fill_pathname_application_data,
+ # configuration.c open_default_config_file). A value left at default
+ # is the system folder of the first of the two folders.
+ - os: linux
+ method: config_file
+ config: $XDG_CONFIG_HOME/retroarch/retroarch.cfg
+ parse_key: system_directory
- os: linux
method: config_file
config: $HOME/.config/retroarch/retroarch.cfg
parse_key: system_directory
+ - os: linux
+ method: config_file
+ config: $HOME/.retroarch.cfg
+ parse_key: system_directory
# configuration.c reads /RetroArch/config, and a value
# left at default is ~/Documents/RetroArch/system (platform_darwin.m).
# Older builds kept the file one level up.
diff --git a/tests/test_install.py b/tests/test_install.py
index f36389a1e..dbef10dd9 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -2646,6 +2646,52 @@ class RetroArchWhereItReallyLives(unittest.TestCase):
self.assertIn(("retroarch", support / "system"), found)
+class LinuxRetroArchFollowsXdgConfigHome(unittest.TestCase):
+ """RetroArch on Linux keeps its config under $XDG_CONFIG_HOME/retroarch
+ when the variable is set, then falls back to ~/.retroarch.cfg
+ (file_path_special.c fill_pathname_application_data, configuration.c
+ open_default_config_file). Only ~/.config/retroarch was read: a home
+ with its own XDG layout detected nothing."""
+
+ def _env(self) -> tuple[Path, Path]:
+ home = Path(_tempdir(self))
+ xdg = Path(_tempdir(self))
+ patcher = unittest.mock.patch.dict(os.environ, {"HOME": str(home)}, clear=True)
+ patcher.start()
+ self.addCleanup(patcher.stop)
+ return home, xdg
+
+ def test_the_config_under_xdg_config_home_is_read(self):
+ home, xdg = self._env()
+ (xdg / "retroarch").mkdir()
+ (xdg / "retroarch" / "retroarch.cfg").write_text('system_directory = "/srv/bios"\n')
+ # A config under ~/.config is not the one this RetroArch opens.
+ (home / ".config" / "retroarch").mkdir(parents=True)
+ (home / ".config" / "retroarch" / "retroarch.cfg").write_text(
+ 'system_directory = "/elsewhere"\n')
+ os.environ["XDG_CONFIG_HOME"] = str(xdg)
+ found = install.detect_platforms("linux")
+ self.assertIn(("retroarch", Path("/srv/bios")), found)
+ self.assertNotIn(("retroarch", Path("/elsewhere")), found)
+ self.assertEqual(install._os_default_dests("linux")["retroarch"],
+ xdg / "retroarch" / "system")
+
+ def test_home_retroarch_cfg_is_the_fallback(self):
+ home, xdg = self._env()
+ os.environ["XDG_CONFIG_HOME"] = str(xdg)
+ (home / ".retroarch.cfg").write_text('system_directory = "default"\n')
+ found = install.detect_platforms("linux")
+ self.assertIn(("retroarch", xdg / "retroarch" / "system"), found)
+
+ def test_without_the_variable_the_folder_is_under_dot_config(self):
+ home, _ = self._env()
+ (home / ".config" / "retroarch").mkdir(parents=True)
+ (home / ".config" / "retroarch" / "retroarch.cfg").write_text(
+ 'system_directory = "default"\n')
+ found = install.detect_platforms("linux")
+ self.assertIn(("retroarch", home / ".config" / "retroarch" / "system"), found)
+
+
class NoPythonNamesThisSystemsCommand(unittest.TestCase):
"""Without Python the bootstrap said `sudo apt install python3` on every
system: Termux has no sudo and installs with `pkg install python`, and
From 54eac3b2df1bdb41b9b0badfea35035138653332 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:19:00 +0100
Subject: [PATCH 18/83] refactor: verify keeps its lock stack name
The --destinations branch of _main rebound held, the ExitStack that
holds the data directory locks, to the dict it writes. It is now
named destinations, and a test refuses a rebinding of the stack.
---
scripts/verify.py | 6 +++---
tests/test_verify_listing.py | 17 +++++++++++++++++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/scripts/verify.py b/scripts/verify.py
index f47c7f011..efbfda178 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -2988,13 +2988,13 @@ def _main(held: contextlib.ExitStack) -> None:
print(_overall_summary(group_results))
if args.destinations:
- held = {}
+ destinations = {}
for (result, names), (group, _rep) in zip(group_results, groups):
for name, key in zip(names, group):
- held[name] = {
+ destinations[name] = {
"platform": key, "pack_destinations": result["pack_destinations"],
}
- Path(args.destinations).write_text(json.dumps(held, indent=1, sort_keys=True))
+ Path(args.destinations).write_text(json.dumps(destinations, indent=1, sort_keys=True))
if args.json:
for r in all_results.values():
diff --git a/tests/test_verify_listing.py b/tests/test_verify_listing.py
index c825b52a5..11d05d6ce 100644
--- a/tests/test_verify_listing.py
+++ b/tests/test_verify_listing.py
@@ -173,6 +173,23 @@ class TheDestinationsFlagNeedsAPack(unittest.TestCase):
self.assertEqual(result.returncode, 2, result.stdout[-300:])
self.assertIn("--destinations", result.stderr)
+ def test_the_lock_stack_is_not_rebound(self):
+ """The --destinations branch reused `held`, the ExitStack that holds
+ the data directory locks, for its dict: a later enter_context in
+ that mode raised AttributeError."""
+ import ast
+
+ tree = ast.parse((REPO_ROOT / "scripts" / "verify.py").read_text(encoding="utf-8"))
+ body = next(n for n in tree.body if isinstance(n, ast.FunctionDef) and n.name == "_main")
+ stack = body.args.args[0].arg
+ rebound = [
+ node.lineno for node in ast.walk(body)
+ if isinstance(node, (ast.Assign, ast.AnnAssign, ast.AugAssign))
+ for target in (node.targets if isinstance(node, ast.Assign) else [node.target])
+ if isinstance(target, ast.Name) and target.id == stack
+ ]
+ self.assertEqual(rebound, [])
+
class EveryGapCountedIsNamed(unittest.TestCase):
"""verify --platform batocera --verbose counted 3 optional core files and
From 4f930b5573c905880910bc360337460fee20f3b0 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:19:08 +0100
Subject: [PATCH 19/83] feat: find wanted dumps by hash on the files page
files/?hash= read the collection, platforms, emulators and retired files,
never the Wanted list: the SHA1 of Redump's ps2-dvd-212k.bin answered
that nothing the site knows has it. The lookup now carries a wanted
layer from the rows of provenance-wanted.csv, computed once for both,
and the page names the catalog that lists the dump.
---
schemas/site-api-envelope.schema.json | 6 +++--
scripts/generate_site.py | 27 ++++++++++++++++++---
tests/test_site_exports.py | 34 +++++++++++++++++++++++++++
website/src/scripts/site.ts | 17 +++++++++++++-
4 files changed, 78 insertions(+), 6 deletions(-)
diff --git a/schemas/site-api-envelope.schema.json b/schemas/site-api-envelope.schema.json
index adbda67c5..4b9e765fd 100644
--- a/schemas/site-api-envelope.schema.json
+++ b/schemas/site-api-envelope.schema.json
@@ -393,7 +393,8 @@
"retired",
"data-directory",
"platform",
- "emulator"
+ "emulator",
+ "wanted"
]
},
"left": {
@@ -433,7 +434,8 @@
"description": "On a platform or emulator record: the algorithm of the value its owner wrote, filed under that value and under the file's other hashes. name: the emulator reads the file by its name and declares no hash that matches it."
},
"owner": {
- "type": "string"
+ "type": "string",
+ "description": "On a platform or emulator record: the platform or profile key. On a wanted record: the dump catalog that lists the value (Redump, No-Intro, TOSEC), the collection holding no file with it."
},
"system_name": {
"type": "string",
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 0eece3cfc..53e2c875f 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -1620,6 +1620,7 @@ def generate_data_exports(
members = data_directory_members()
locations = file_location_items(db, profiles, members)
+ wanted = _provenance_wanted_rows(db)
envelopes = {
"platforms.json": ("platforms", platform_items),
"emulators.json": ("emulators", emulator_items),
@@ -1628,7 +1629,7 @@ def generate_data_exports(
}
write_lookup_shards(
api, file_lookup_records(db, coverages, profiles, locations, members, consumers,
- retired_files.load(_REPO_ROOT / "retired.json")),
+ retired_files.load(_REPO_ROOT / "retired.json"), wanted),
generated_at, commit,
)
for filename, (kind, items) in envelopes.items():
@@ -1747,7 +1748,7 @@ def generate_data_exports(
_record(downloads / "retrobios.sqlite")
write_if_changed(
str(downloads / "provenance-wanted.csv"),
- _csv_document(list(WANTED_FIELDS), _provenance_wanted_rows(db)),
+ _csv_document(list(WANTED_FIELDS), wanted),
)
assets = [
@@ -5010,12 +5011,14 @@ def file_lookup_records(
members: dict | None = None,
consumers: FileConsumers | None = None,
retired: dict | None = None,
+ wanted: list[dict] | None = None,
) -> list[dict]:
"""Every hash the site knows, one record per value, for files/?hash=.
The collection's own files lead to their card, a platform's declared
value to the system section of its page, a profile's to the entry's
- card. The site search indexed these values as text, 4 MB of the 21 MB
+ card, a wanted dump (``wanted``, the provenance-wanted.csv rows) to
+ its catalog on the provenance page. The site search indexed these values as text, 4 MB of the 21 MB
it made every visitor download: the lookup reads one shard instead.
"""
files = db.get("files", {})
@@ -5088,6 +5091,7 @@ def file_lookup_records(
**({"system_name": entry_label} if entry_label else {}),
})
records += retired_records(retired or {}, files, locations)
+ records += wanted_records(wanted or [])
records += _held_under_every_hash(records, files, db.get("indexes") or {})
for record in records:
if record["layer"] in ("platform", "emulator"):
@@ -5099,6 +5103,23 @@ def file_lookup_records(
r["value"], r["layer"], r.get("owner", ""), r["name"], r["url"]))
+def wanted_records(rows: list[dict]) -> list[dict]:
+ """A record under each hash of a dump a catalog lists and the collection
+ lacks, from the rows of provenance-wanted.csv. A pasted hash of a
+ wanted dump (Redump's ps2-dvd-212k.bin) answered that nothing the site
+ knows has it, and never said the dump is wanted."""
+ records = []
+ for row in rows:
+ label = _PROVENANCE_LABELS.get(row["catalog"], row["catalog"])
+ url = _site_path(f"provenance.md#{_slugify_anchor(label)}")
+ for algorithm in ("sha1", "md5", "crc32"):
+ value = str(row.get(algorithm) or "").lower()
+ if value:
+ records.append({"value": value, "algorithm": algorithm, "layer": "wanted",
+ "owner": label, "name": row["name"], "url": url})
+ return records
+
+
def _read_by_name(records: list[dict], files: dict, consumers: FileConsumers) -> list[dict]:
"""The emulators the file's card names that no declared hash reached.
diff --git a/tests/test_site_exports.py b/tests/test_site_exports.py
index 1d96d3f0a..5455a422b 100644
--- a/tests/test_site_exports.py
+++ b/tests/test_site_exports.py
@@ -832,6 +832,40 @@ class AnArchiveMemberIsFoundByItsCrc(unittest.TestCase):
self.assertIn("byLayer('archive-member')", script)
+class AWantedDumpIsFoundByItsHash(unittest.TestCase):
+ """The SHA1 of a PS2 SCPH-30005R BIOS, which Redump lists as
+ ps2-dvd-212k.bin and the Wanted page asks for, answered that no file
+ the site knows has it."""
+
+ def test_each_hash_of_a_wanted_row_is_a_record(self):
+ import generate_site # noqa: PLC0415
+
+ row = {"catalog": "redump", "dat": "Sony - PlayStation 2 - BIOS Images",
+ "name": "ps2-dvd-212k.bin", "description": "", "size": "4194304",
+ "crc32": "1A2B3C4D", "md5": "", "sha1": "5b346eb9258d710609a9855befd35cab8f3a334a"}
+ records = generate_site.file_lookup_records(
+ {"files": {}, "indexes": {}}, {}, {}, [], wanted=[row, {**row, "dat": "other"}])
+ self.assertEqual(records, [
+ {"value": "1a2b3c4d", "algorithm": "crc32", "layer": "wanted", "owner": "Redump",
+ "name": "ps2-dvd-212k.bin", "url": "/retrobios/provenance/#redump"},
+ {"value": "5b346eb9258d710609a9855befd35cab8f3a334a", "algorithm": "sha1",
+ "layer": "wanted", "owner": "Redump", "name": "ps2-dvd-212k.bin",
+ "url": "/retrobios/provenance/#redump"},
+ ])
+
+ def test_the_schema_and_the_page_carry_the_layer(self):
+ import json as _json # noqa: PLC0415
+
+ import generate_site # noqa: PLC0415
+
+ root = Path(__file__).resolve().parents[1]
+ schema = _json.loads((root / "schemas" / "site-api-envelope.schema.json").read_text())
+ self.assertIn('"wanted"', _json.dumps(schema))
+ self.assertIn("byLayer('wanted')", (root / "website" / "src" / "scripts" / "site.ts").read_text())
+ source = Path(generate_site.__file__).read_text(encoding="utf-8")
+ self.assertIn('retired_files.load(_REPO_ROOT / "retired.json"), wanted)', source)
+
+
class AFileHasAnAddressByContent(unittest.TestCase):
"""mt32_control.rom moved from the Commodore page to the Roland page and
every link to its card broke: the anchor was content-based, the page
diff --git a/website/src/scripts/site.ts b/website/src/scripts/site.ts
index 09d20902f..263309d34 100644
--- a/website/src/scripts/site.ts
+++ b/website/src/scripts/site.ts
@@ -558,9 +558,12 @@ const renderMatches = async (status: HTMLElement, result: HTMLElement, matched:
const setups = new Set(platforms.map((item) => item.owner));
const members = distinct(byLayer('archive-member'), (item) => `${item.sha1}|${item.name}`);
+ // A dump a catalog lists and the collection lacks: the Wanted list.
+ const wanted = held.length || members.length ? [] : distinct(byLayer('wanted'), (item) => `${item.owner}|${item.name}`);
const counted = [
held.length ? count(held.length, 'file in the collection', 'files in the collection')
: members.length ? count(members.length, 'member of a collection archive', 'members of collection archives')
+ : wanted.length ? 'a wanted dump, not in the collection yet'
: 'not in the collection',
...(platforms.length ? [`${count(platforms.length, 'declaration', 'declarations')} by ${count(setups.size, 'setup', 'setups')}`] : []),
...(owners.length ? [count(owners.length, 'emulator that reads it', 'emulators that read it')] : []),
@@ -617,8 +620,20 @@ const renderMatches = async (status: HTMLElement, result: HTMLElement, matched:
);
});
const retired = held.length ? [] : distinct(byLayer('retired'), (item) => item.sha1 ?? item.value);
- if (!held.length && !members.length && !retired.length) blocks.push(paragraph('No file in the collection has this hash.'));
+ if (!held.length && !members.length && !retired.length && !wanted.length) blocks.push(paragraph('No file in the collection has this hash.'));
blocks.push(...retired.map(retiredParagraph));
+ if (wanted.length) {
+ const list = document.createElement('ul');
+ for (const item of wanted) {
+ const row = document.createElement('li');
+ row.append(link(item.url, item.owner ?? ''), ' lists it as ', code(item.name ?? item.value));
+ list.append(row);
+ }
+ blocks.push(
+ paragraph(strong('Wanted.'), ' The collection does not hold this dump yet. If you dumped it yourself, ', link('contributing/', 'add it'), '.'),
+ list,
+ );
+ }
if (members.length) {
// A ROM the collection holds inside a set: the set's card, by its name.
const list = document.createElement('ul');
From 9f3f1cec3be5dddbefd505fa2b60dfb75c0d46b1 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:19:36 +0100
Subject: [PATCH 20/83] fix: validate_schemas names its jsonschema install
Without jsonschema the documented command stopped on an ImportError
traceback. Run as a command it now prints the install pipeline.py names
for the same step, with the format-nongpl extra, and exits 1. An import
from the tests still raises ImportError, which they skip on.
---
scripts/validate_schemas.py | 10 +++++++++-
tests/test_schema_semantic_gate.py | 26 ++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/scripts/validate_schemas.py b/scripts/validate_schemas.py
index 5380f64c6..6bb3167c0 100644
--- a/scripts/validate_schemas.py
+++ b/scripts/validate_schemas.py
@@ -14,7 +14,15 @@ from pathlib import Path, PurePosixPath
import yaml
from common import source_yaml_paths, yaml_load
-from jsonschema import Draft202012Validator, FormatChecker
+
+try:
+ from jsonschema import Draft202012Validator, FormatChecker
+except ImportError:
+ # Tests import this module and skip on the ImportError, the command
+ # names the install pipeline.py names for the same step.
+ if __name__ != "__main__":
+ raise
+ sys.exit('Error: jsonschema required (pip install "jsonschema[format-nongpl]")')
ROOT = Path(__file__).resolve().parent.parent
SCHEMAS = ROOT / "schemas"
diff --git a/tests/test_schema_semantic_gate.py b/tests/test_schema_semantic_gate.py
index 2710455ac..9ccc9692c 100644
--- a/tests/test_schema_semantic_gate.py
+++ b/tests/test_schema_semantic_gate.py
@@ -120,5 +120,31 @@ class DataRootIsKeyedBySystem(unittest.TestCase):
self.assertTrue(self._errors({}))
+class WithoutJsonschema(unittest.TestCase):
+ """The documented command stopped on a bare ImportError traceback that
+ named neither the install nor the format-nongpl extra."""
+
+ def test_the_command_names_the_install(self):
+ import os
+ import subprocess
+
+ scratch = REPO_ROOT / "tmp" / "tests"
+ scratch.mkdir(parents=True, exist_ok=True)
+ with tempfile.TemporaryDirectory(dir=scratch) as directory:
+ stub = Path(directory) / "jsonschema"
+ stub.mkdir()
+ (stub / "__init__.py").write_text(
+ 'raise ImportError("No module named jsonschema")\n', encoding="utf-8"
+ )
+ env = {**os.environ, "PYTHONPATH": directory}
+ proc = subprocess.run(
+ [sys.executable, "scripts/validate_schemas.py", "--source-only"],
+ capture_output=True, text=True, check=False, cwd=REPO_ROOT, env=env,
+ )
+ self.assertEqual(proc.returncode, 1)
+ self.assertNotIn("Traceback", proc.stderr)
+ self.assertIn('pip install "jsonschema[format-nongpl]"', proc.stderr)
+
+
if __name__ == "__main__":
unittest.main()
From d1535d0787a458caa31c902d7aeba3da15d9ed26 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:20:03 +0100
Subject: [PATCH 21/83] fix: name the file a variant download is saved as
A .variants/ copy downloads as advision.zip.1c086064, its storage name:
raw.githubusercontent.com sends no Content-Disposition and the download
attribute is ignored across origins. A card whose download name differs
from the file name now says what to save it as, at a glance.
---
scripts/generate_site.py | 15 ++++++++++++++-
tests/test_audit_regressions.py | 17 +++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 53e2c875f..aaae2d7ad 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -5805,6 +5805,13 @@ def _wanted_list(source: str, label: str, data: dict, by_dat: dict[str, list],
_RELEASE_ASSET_NAMES: dict[str, str] | None = None
+def _download_name(path: str) -> str:
+ """The name a browser saves a collection file under: the last segment
+ of its download URL. Neither host sends a Content-Disposition, and the
+ download attribute is ignored on another origin."""
+ return urllib.parse.unquote(_fetch_url(path).rsplit("/", 1)[-1])
+
+
def _fetch_url(path: str) -> str:
"""Where a collection file downloads from: its raw URL, or the
large-files release asset when .gitignore keeps it out of git."""
@@ -6179,6 +6186,12 @@ def _system_file_card(
# Each fact: its label, its values, whether the search reads it. What a
# setup does with the file comes first, the fingerprints last.
facts: list[tuple[str, list[str], bool]] = []
+ saved = _download_name(f["path"]) if f.get("path") else name
+ if saved != name:
+ # A .variants/ copy is stored as advision.zip.1c086064, and the
+ # browser names the download after the URL: copied as it came, the
+ # file a platform pins was not found under its name.
+ facts.append(("Save as", [f"{_code(name)}, the download is named {_code(saved)}"], False))
if plats:
# Each link lands on the platform's system section, and says where
# that platform puts the file. Out of the search: the card's title
@@ -6237,7 +6250,7 @@ def _system_file_card(
# What a system card shows at a glance: who lists the file and who reads it.
# Its fingerprints and the rest open on demand, so a page of 250 cards reads
# as a list of files, not a wall of hashes.
-_CARD_KEY_FACTS = ("On the setup's list", "Packed for its emulators by", "Emulators")
+_CARD_KEY_FACTS = ("Save as", "On the setup's list", "Packed for its emulators by", "Emulators")
_CARD_HASHES = ("SHA1", "MD5", "CRC32", "SHA256")
# The words a card's fold names its other facts by.
_CARD_MORE_WORDS = {"Romset": "romset", "Collection path": "collection path",
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 91110a2d5..577b0cfff 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -5207,6 +5207,23 @@ class CollectionCardsCarryFullHashes(unittest.TestCase):
self.assertIn(f'{value}', text)
+class AVariantCardSaysWhatToSaveItAs(unittest.TestCase):
+ """The Download button of a .variants/ card saved advision.zip.1c086064,
+ the storage name, and nothing said RetroBat looks for advision.zip."""
+
+ def test_the_name_to_save_it_under(self):
+ from scripts.generate_site import FileConsumers, _system_file_card
+
+ entry = {"name": "advision.zip", "size": 10, "sha1": "a" * 40,
+ "path": "bios/Entex/Adventure Vision/.variants/advision.zip.1c086064"}
+ text = "\n".join(_system_file_card(entry, FileConsumers({}, {})))
+ self.assertIn("Save as", text)
+ self.assertIn("advision.zip.1c086064", text)
+ plain = "\n".join(_system_file_card(
+ {**entry, "path": "bios/Entex/Adventure Vision/advision.zip"}, FileConsumers({}, {})))
+ self.assertNotIn("Save as", plain)
+
+
class NullReadsAsNone(unittest.TestCase):
"""`upstream: ~` printed `| Upstream | None |` and `bios_filename: null`
From c7a30856b0ee20e7f3cd18693bf214f6828a6a39 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:20:46 +0100
Subject: [PATCH 22/83] feat: link the build file that holds a revision
pin_build, in 36 profiles, names the platform repository, revision, file
and variable that hold a pin_frozen revision, and the site read none of
it: the Revision held row printed the file as plain text. A Build file
row links each one at the revision it was read at.
---
scripts/generate_site.py | 20 ++++++++++++++++++++
tests/test_audit_regressions.py | 19 +++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index aaae2d7ad..fe43620af 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -8196,6 +8196,23 @@ def _exact_size(size: int) -> str:
return _fmt_size(size) if size < 1024 else f"{_fmt_size(size)} ({size:,} bytes)"
+def _build_file_links(pin_build: list[dict]) -> list[str]:
+ """Each platform build file that holds the revision, linked at the
+ revision it was read at. The prose of pin_frozen named the file as
+ plain text, while pin_build carries all a pinned link needs."""
+ from sitesources import _browse_repo, _source_permalink # noqa: PLC0415
+
+ links = []
+ for build in pin_build:
+ repo = _browse_repo(str(build["repo"]))
+ path = str(build["path"])
+ text = f"{_escape_tags(_platform_display(str(build['platform'])))} {_code(path)}"
+ if repo is not None:
+ text = f"[{text}]({_source_permalink(repo, str(build['revision']), path, None, None)})"
+ links.append(f"{text} at {_code(str(build['revision']))} sets {_code(str(build['variable']))}")
+ return links
+
+
def _build_rows(profile: dict) -> list[str]:
"""Meta card rows for who ships the build, how its files are found, why
its revision is held and where its releases are announced."""
@@ -8216,6 +8233,9 @@ def _build_rows(profile: dict) -> list[str]:
if frozen:
held = _escape_tags(' '.join(str(frozen).split())).replace('|', r'\|')
rows.append(f"| {label} | {held} |")
+ builds = _build_file_links(profile.get("pin_build") or [])
+ if builds:
+ rows.append(f"| Build file | {'
'.join(builds)} |")
announced = profile.get("version_source")
if isinstance(announced, dict) and announced.get("url"):
url = str(announced["url"])
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 577b0cfff..5263d0c54 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -5207,6 +5207,25 @@ class CollectionCardsCarryFullHashes(unittest.TestCase):
self.assertIn(f'{value}', text)
+class AHeldRevisionLinksItsBuildFile(unittest.TestCase):
+ """advanced_drastic's page printed the KNULLI build file that holds its
+ revision as plain text, while pin_build carries the repository, the tag
+ and the path a pinned link needs. 36 profiles carry one."""
+
+ def test_the_build_file_row(self):
+ from scripts.generate_site import _build_rows
+
+ rows = _build_rows({"pin_frozen": "KNULLI builds this revision.", "pin_build": [{
+ "platform": "knulli", "repo": "https://github.com/knulli-cfw/knulli-linux",
+ "revision": "20260511", "path": "package/emulators/advanced_drastic/advanced_drastic.mk",
+ "variable": "ADVANCED_DRASTIC_VERSION", "value": "eaf41ab9"}]})
+ self.assertIn(
+ "| Build file | [KNULLI `package/emulators/advanced_drastic/advanced_drastic.mk`]"
+ "(https://github.com/knulli-cfw/knulli-linux/blob/20260511/package/emulators/"
+ "advanced_drastic/advanced_drastic.mk) at `20260511` sets `ADVANCED_DRASTIC_VERSION` |",
+ rows)
+
+
class AVariantCardSaysWhatToSaveItAs(unittest.TestCase):
"""The Download button of a .variants/ card saved advision.zip.1c086064,
the storage name, and nothing said RetroBat looks for advision.zip."""
From 7876dc09e95b8bdde10d9174556878e3a7db3fdc Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:21:30 +0100
Subject: [PATCH 23/83] fix: send moved part cards to the emulator index
Adding one entry to mame.yml moves 938 cards from one part page to the
next, and a published emulators/mame-files-1/#file-... address landed
on a page without the card. A part page now sends a file- id it does
not hold to the emulator page, whose card index row opens the part that
holds it.
---
tests/test_site_exports.py | 25 +++++++++++++++++++++++++
website/src/scripts/site.ts | 13 +++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tests/test_site_exports.py b/tests/test_site_exports.py
index 5455a422b..4d230afc9 100644
--- a/tests/test_site_exports.py
+++ b/tests/test_site_exports.py
@@ -866,6 +866,31 @@ class AWantedDumpIsFoundByItsHash(unittest.TestCase):
self.assertIn('retired_files.load(_REPO_ROOT / "retired.json"), wanted)', source)
+class AMovedPartCardReachesItsPage(unittest.TestCase):
+ """One entry added to mame.yml moved 938 of its 1,585 cards from one
+ part page to another, and emulators/mame-files-1/#file-mackbd-m0110a-zip
+ led to a page without the card: part pages have no card index, and
+ site.js redirected only sha1- ids."""
+
+ def test_a_part_page_sends_a_missing_card_to_the_emulator_page(self):
+ import re as _re # noqa: PLC0415
+
+ import generate_site # noqa: PLC0415
+
+ script = (Path(__file__).resolve().parents[1] / "website" / "src" / "scripts"
+ / "site.ts").read_text(encoding="utf-8")
+ body = script.split("const followMovedCard = () => {", 1)[1].split("\n};", 1)[0]
+ pattern = _re.search(r"const part = /(.+?)/\.exec\(location\.pathname\)", body).group(1)
+ files = [{"name": f"f{i}.bin", "path": f"f{i}.bin", "required": True} for i in range(600)]
+ stem = generate_site.emulator_parts("mame", files)[1][0]
+ found = _re.search(pattern.replace("\\/", "/"), f"/retrobios/emulators/{stem}/")
+ self.assertEqual(found.group(1), "mame")
+ self.assertIn("emulators/${part[1]}/#", body)
+ self.assertIn("id.startsWith('file-')", body)
+ # The emulator page holds the index whose row leads to the card.
+ self.assertIn("closest('.rb-card-index tr')", body)
+
+
class AFileHasAnAddressByContent(unittest.TestCase):
"""mt32_control.rom moved from the Commodore page to the Roland page and
every link to its card broke: the anchor was content-based, the page
diff --git a/website/src/scripts/site.ts b/website/src/scripts/site.ts
index 263309d34..daeb78f28 100644
--- a/website/src/scripts/site.ts
+++ b/website/src/scripts/site.ts
@@ -814,7 +814,10 @@ const resolveFileAddress = () => {
// A file card moved to another page keeps its address: an id of the form
// sha1-<12 hex> that this page does not hold is looked up by content, and
-// an emulator card listed in the table of a split page opens its page.
+// an emulator card listed in the table of a split page opens its page. A
+// part of a split emulator page (emulators/mame-files-1/) sends a card id
+// it no longer holds to that table: an entry added to the profile moves
+// hundreds of cards from one part to the next.
const followMovedCard = () => {
const id = decodeURIComponent(location.hash.slice(1));
if (!id) return;
@@ -824,8 +827,14 @@ const followMovedCard = () => {
location.replace(link.href);
return;
}
+ if (target) return;
const match = /^sha1-([0-9a-f]{12})$/.exec(id);
- if (match && !target) location.replace(new URL(`files/?sha1=${match[1]}`, siteRoot()));
+ if (match) {
+ location.replace(new URL(`files/?sha1=${match[1]}`, siteRoot()));
+ return;
+ }
+ const part = /\/emulators\/(.+)-files-\d+\/?$/.exec(location.pathname);
+ if (part && id.startsWith('file-')) location.replace(new URL(`emulators/${part[1]}/#${encodeURIComponent(id)}`, siteRoot()));
};
// A link to a card folded in a table row (emulators with many entries)
From 7a03578dd96efa8a55fa3ee6fbb9931fa48e6b4a Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:21:47 +0100
Subject: [PATCH 24/83] fix: count name holders with case folded
A hashless profile entry adopted the only exact holder of its name as the file its aliases designate. dosbox's SC-55 ROM2.BIN found Galaksija's ROM2.BIN, and ROM2_ST.BIN was indexed against a 4 KiB BASIC ROM while SC-55's rom2.bin sat under the same folded name. The name now has to designate one file once case is folded, a primary and its own variants counted as one.
---
database.json | 5 +----
scripts/generate_db.py | 27 +++++++++++++++++++++++----
tests/test_db_aliases.py | 19 +++++++++++++++++++
3 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/database.json b/database.json
index bc7d27139..375671581 100644
--- a/database.json
+++ b/database.json
@@ -1,6 +1,6 @@
{
"schema_version": 1,
- "generated_at": "2026-11-05T23:59:37Z",
+ "generated_at": "2026-11-06T07:21:27Z",
"total_files": 19947,
"total_size": 16926035621,
"bios_dir": "bios",
@@ -281813,9 +281813,6 @@
"TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin": [
"a308b15f93da34961c0141ec95b98c211557e2d5"
],
- "ROM2_ST.BIN": [
- "5d5ab4313a2d0effe7572bb129193b64cab002c1"
- ],
"mt32_ctrl_1_04.rom": [
"5a5cb5a77d7d55ee69657c2f870416daed52dea7"
],
diff --git a/scripts/generate_db.py b/scripts/generate_db.py
index ade383713..32c956171 100644
--- a/scripts/generate_db.py
+++ b/scripts/generate_db.py
@@ -576,12 +576,26 @@ def _collect_all_aliases(
# naming its content once 64DD_IPL.bin sorted first, and its aliases
# 64dd_ipl_J.bin and 64DD_IPL_JP.n64 went with it.
holders: dict[str, set[str]] = {}
+ # The files a name designates once case is folded, as the resolver's
+ # name step folds it, a primary and its own .variants/ counted as one
+ # file. dosbox's SC-55 ROM2.BIN found Galaksija's ROM2.BIN the only
+ # exact holder, and its alias ROM2_ST.BIN went to a 4 KiB BASIC ROM,
+ # while SC-55's rom2.bin sat under the same folded name.
+ families: dict[str, set[str]] = {}
+
+ def _hold(name: str, path: str, sha1: str) -> None:
+ holders.setdefault(name, set()).add(sha1)
+ directory = path.rpartition("/")[0].removesuffix("/.variants")
+ families.setdefault(name.casefold(), set()).add(
+ f"{directory}/{variant_base_name(name)}".casefold()
+ )
+
for sha1, entry in files.items():
- holders.setdefault(entry["name"], set()).add(sha1)
+ _hold(entry["name"], entry["path"], sha1)
for sha1, copy_list in (copies or {}).items():
if sha1 in files:
for copy in copy_list:
- holders.setdefault(copy["name"], set()).add(sha1)
+ _hold(copy["name"], copy["path"], sha1)
aliases = {}
@@ -691,11 +705,16 @@ def _collect_all_aliases(
]
if taken:
shadowed.append((entry_name, set(matched), taken))
- if not matched and len(holders.get(entry_name, ())) == 1:
+ held = holders.get(entry_name, set())
+ if (
+ not matched
+ and len(held) == 1
+ and len(families[entry_name.casefold()]) == 1
+ ):
# A name carried by several contents names none of them:
# quasi88's disk.rom aliases went to whichever
# disk.rom the scan met last, a Tandy CoCo ROM.
- matched = set(holders[entry_name])
+ matched = set(held)
for sha in sorted(matched):
for alias_name in entry_aliases:
_add_alias(alias_name, sha)
diff --git a/tests/test_db_aliases.py b/tests/test_db_aliases.py
index 91bfd56fa..eff324b5f 100644
--- a/tests/test_db_aliases.py
+++ b/tests/test_db_aliases.py
@@ -56,6 +56,25 @@ class AliasesNeedAnUnambiguousName(unittest.TestCase):
named = {a["name"] for entries in aliases.values() for a in entries}
self.assertNotIn("n88sub.rom", named)
+ def test_homonyms_differing_in_case_take_no_alias(self):
+ """dosbox's SC-55 ROM2.BIN: Galaksija's ROM2.BIN was the only exact
+ holder, and ROM2_ST.BIN went to it beside SC-55's rom2.bin."""
+ files = {
+ "a": self._file("DISK.ROM", "bios/NEC/PC-98/DISK.ROM", "m1"),
+ "b": self._file("disk.rom", "bios/Tandy/CoCo/disk.rom", "m2"),
+ }
+ aliases = self._aliases(files)
+ named = {a["name"] for entries in aliases.values() for a in entries}
+ self.assertNotIn("n88sub.rom", named)
+
+ def test_a_primary_and_its_variant_are_one_file(self):
+ files = {
+ "a": self._file("disk.rom", "bios/NEC/PC-88/disk.rom", "m1"),
+ "b": self._file("DISK.ROM", "bios/NEC/PC-88/.variants/DISK.ROM.0123abcd", "m2"),
+ }
+ aliases = self._aliases(files)
+ self.assertEqual([a["name"] for a in aliases.get("a", [])], ["n88sub.rom"])
+
def test_a_unique_name_still_carries_its_aliases(self):
files = {"a": self._file("disk.rom", "bios/NEC/PC-88/disk.rom", "m1")}
aliases = self._aliases(files)
From 3e2a5279a150cfead6da9d7795784f99e952dfeb Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:21:52 +0100
Subject: [PATCH 25/83] fix: split parts hold what the full pack holds
Each part was built alone: the Other_Cores part never saw the platform's destinations and each part had its own case fold. RetroDECK's parts wrote bios/SGB1.sfc/ members beside the file bios/SGB1.sfc, RetroBat's wrote 21 openmsx/ twins of openMSX/ files, and a path two systems declare got each system's file. The full pack is now built in memory first and a part writes a declared file or core extra only where the full pack writes the same bytes.
---
scripts/generate_pack.py | 93 +++++++++++++++++----------
tests/test_split_extras.py | 127 ++++++++++++++++++++++++++++++++++++-
2 files changed, 187 insertions(+), 33 deletions(-)
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index 458fa968b..907f0bb8f 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -26,6 +26,7 @@ import argparse
import contextlib
import functools
import hashlib
+import io
import json
import os
import re
@@ -158,6 +159,9 @@ class PackRecord:
self.members: list[str] = []
self.files: list[str] = []
self.trees: list[str] = []
+ # The collection file each copied member comes from: a split part
+ # writes a file only where the full pack writes the same bytes.
+ self.sources: dict[str, str] = {}
def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> None:
@@ -173,6 +177,7 @@ def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> Non
"""
if isinstance(zf, PackRecord):
zf.members.append(arcname)
+ zf.sources[arcname] = source_path
return
info = zipfile.ZipInfo(filename=arcname, date_time=_FIXED_DATE_TIME)
info.compress_type = _member_compression(arcname)
@@ -806,6 +811,7 @@ def generate_pack(
pack_name: str | None = None,
no_game_data: bool = False,
record: PackRecord | None = None,
+ within: dict[str, str] | None = None,
) -> str | None:
"""Generate a ZIP pack for a platform.
@@ -819,6 +825,12 @@ def generate_pack(
``record`` builds the pack in memory (PackRecord): no archive is written,
no external file fetched, and the paths are kept on it.
+ ``within`` is the full pack's PackRecord.sources, given to a split part:
+ a declared file or core extra is written only where the full pack writes
+ the same bytes. A part sees neither the other systems' declarations nor
+ their extras, so a path the full pack settles (a file/directory conflict,
+ a case twin, a path another system's file takes) was written again.
+
Returns the path to the generated ZIP, or None on failure.
"""
config = load_platform_config(platform_name, platforms_dir)
@@ -1174,6 +1186,11 @@ def generate_pack(
if already_packed:
continue
+ if within is not None and not _same_bytes(
+ local_path, within.get(_flat(full_dest, base_dest, flatten))
+ ):
+ # The full pack holds another system's file here.
+ continue
if file_status.get(dedup_key) == "excluded":
# An earlier declaration refused the file this one ships.
file_status[dedup_key] = "untested"
@@ -1281,6 +1298,8 @@ def generate_pack(
)
flat_dest = _flat(full_dest, base_dest, flatten)
+ if within is not None and not _same_bytes(local_path, within.get(flat_dest)):
+ continue
if local_path.endswith(".zip"):
_add_zip_to_pack(local_path, flat_dest, zf, fe)
else:
@@ -1414,6 +1433,7 @@ def _extract_zip_to_archive(
for name in map(sanitize_pack_path, src.namelist())
if name and not name.endswith("/")
)
+ target_zf.sources[dest_prefix] = source_zip
return
for info in src.infolist():
if info.is_dir():
@@ -1447,6 +1467,7 @@ def _add_zip_to_pack(
"""
if isinstance(target_zf, PackRecord):
target_zf.members.append(dest_path)
+ target_zf.sources[dest_path] = source_zip
return
_check_zip_members(source_zip)
_add_pack_member(target_zf, source_zip, dest_path)
@@ -2075,8 +2096,14 @@ def generate_split_packs(
one_per_slot: bool = False,
offline: bool | None = None,
no_game_data: bool = False,
+ records: dict[str, PackRecord] | None = None,
) -> list[str]:
- """Generate split packs (one ZIP per system or manufacturer)."""
+ """Generate split packs (one ZIP per system or manufacturer).
+
+ The parts add up to the full pack: each is built against the full pack's
+ own placement (``within``). ``records`` builds the parts in memory, keyed
+ by part name, with no archive written.
+ """
config = load_platform_config(platform_name, platforms_dir)
# The split directory carries the same tags as the packs inside it, or two
# differently narrowed runs write into one another.
@@ -2099,10 +2126,36 @@ def generate_split_packs(
f"{_platform_pack_stem([platform_name], platform_name, platforms_dir)}{split_tags}"
)
split_dir = os.path.join(output_dir, f"{part_prefix}{group_tag}_Split")
- os.makedirs(split_dir, exist_ok=True)
+ if records is None:
+ os.makedirs(split_dir, exist_ok=True)
if emu_profiles is None:
emu_profiles = load_emulator_profiles(emulators_dir)
+ narrowing = {
+ "emulators_dir": emulators_dir, "zip_contents": zip_contents,
+ "data_registry": data_registry, "emu_profiles": emu_profiles,
+ "target_cores": target_cores, "required_only": required_only,
+ "source": source, "regions": regions, "target_name": target_name,
+ "one_per_slot": one_per_slot, "offline": offline,
+ "no_game_data": no_game_data,
+ }
+ full = PackRecord()
+ with contextlib.redirect_stdout(io.StringIO()):
+ generate_pack(
+ platform_name, platforms_dir, db, bios_dir, split_dir,
+ record=full, **narrowing,
+ )
+
+ def part(pack_name: str, **scope: object) -> str | None:
+ record = PackRecord() if records is not None else None
+ zip_path = generate_pack(
+ platform_name, platforms_dir, db, bios_dir, split_dir,
+ pack_name=pack_name, record=record, within=full.sources,
+ **scope, **narrowing,
+ )
+ if record is not None and zip_path:
+ records[pack_name] = record
+ return zip_path
# The systems a core of the target runs: a part per declared system sent
# each one the target drops to a refusal naming it as unknown.
systems = platform_scope_systems(config, emu_profiles, target_cores)
@@ -2136,27 +2189,9 @@ def generate_split_packs(
results = []
for group_name, group_system_ids in sorted(groups.items()):
group_extras = _extras_for_systems(all_extras, group_system_ids)
- zip_path = generate_pack(
- platform_name,
- platforms_dir,
- db,
- bios_dir,
- split_dir,
- emulators_dir=emulators_dir,
- zip_contents=zip_contents,
- data_registry=data_registry,
- emu_profiles=emu_profiles,
- target_cores=target_cores,
- required_only=required_only,
- system_filter=group_system_ids,
- precomputed_extras=group_extras,
- source=source,
- regions=regions,
- target_name=target_name,
- one_per_slot=one_per_slot,
- offline=offline,
- pack_name=f"{part_prefix}_{_name_part(group_name, '_')}_BIOS_Pack.zip",
- no_game_data=no_game_data,
+ zip_path = part(
+ f"{part_prefix}_{_name_part(group_name, '_')}_BIOS_Pack.zip",
+ system_filter=group_system_ids, precomputed_extras=group_extras,
)
if zip_path:
results.append(zip_path)
@@ -2172,15 +2207,9 @@ def generate_split_packs(
}
undistributed = [fe for fe in all_extras if id(fe) not in distributed]
if undistributed:
- zip_path = generate_pack(
- platform_name, platforms_dir, db, bios_dir, split_dir,
- emulators_dir=emulators_dir, zip_contents=zip_contents,
- data_registry=data_registry, emu_profiles=emu_profiles,
- target_cores=target_cores, required_only=required_only,
- precomputed_extras=undistributed, extras_only=True, source=source,
- regions=regions, target_name=target_name, one_per_slot=one_per_slot,
- offline=offline, pack_name=f"{part_prefix}_Other_Cores_BIOS_Pack.zip",
- no_game_data=no_game_data,
+ zip_path = part(
+ f"{part_prefix}_Other_Cores_BIOS_Pack.zip",
+ precomputed_extras=undistributed, extras_only=True,
)
if zip_path:
results.append(zip_path)
diff --git a/tests/test_split_extras.py b/tests/test_split_extras.py
index 568cd34be..e64fff4a3 100644
--- a/tests/test_split_extras.py
+++ b/tests/test_split_extras.py
@@ -7,6 +7,7 @@ and in no part (4507 of RetroArch's 5430).
from __future__ import annotations
+import hashlib
import sys
import tempfile
import unittest
@@ -19,7 +20,7 @@ REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import build_zip_contents_index, compute_hashes, load_emulator_profiles # noqa: E402
-from generate_pack import generate_split_packs # noqa: E402
+from generate_pack import PackRecord, generate_pack, generate_split_packs # noqa: E402
class SplitPartsCoverTheExtras(unittest.TestCase):
@@ -70,5 +71,129 @@ class SplitPartsCoverTheExtras(unittest.TestCase):
self.assertIn("core_c.bin", members)
+class SplitPartsHoldWhatTheFullPackHolds(unittest.TestCase):
+ """A part sees neither the other systems' declarations nor their extras.
+
+ RetroDECK's Other_Cores part wrote bios/SGB1.sfc/program.rom beside the
+ SNES part's file bios/SGB1.sfc, a file/directory clash the full pack
+ refuses. RetroBat's ColecoVision part wrote openmsx/... beside the MSX
+ part's openMSX/..., case twins the full pack folds. A path two systems
+ declare got each system's file, one per part.
+ """
+
+ def _build(self, platform: dict, profiles: dict[str, dict], blobs: dict[str, bytes]):
+ tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
+ self.addCleanup(tmp.cleanup)
+ root = Path(tmp.name)
+ (root / "platforms").mkdir()
+ (root / "emulators").mkdir()
+ files = {}
+ for rel, payload in blobs.items():
+ path = root / "bios" / rel
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_bytes(payload)
+ files[rel] = (str(path), compute_hashes(str(path)))
+ by_name: dict[str, list[str]] = {}
+ for rel, (_p, h) in files.items():
+ by_name.setdefault(Path(rel).name, []).append(h["sha1"])
+ db = {
+ "files": {
+ h["sha1"]: {"name": Path(rel).name, "md5": h["md5"], "sha1": h["sha1"],
+ "sha256": h["sha256"], "path": p, "size": 1}
+ for rel, (p, h) in files.items()
+ },
+ "indexes": {
+ "by_md5": {h["md5"]: h["sha1"] for _p, h in files.values()},
+ "by_name": by_name, "by_crc32": {}, "by_path_suffix": {},
+ },
+ }
+ (root / "platforms" / "_registry.yml").write_text(
+ yaml.dump({"platforms": {"plat": {"status": "active"}}})
+ )
+ (root / "platforms" / "plat.yml").write_text(yaml.dump(platform))
+ for name, profile in profiles.items():
+ (root / "emulators" / f"{name}.yml").write_text(yaml.dump(profile))
+ args = dict(
+ emulators_dir=str(root / "emulators"),
+ zip_contents=build_zip_contents_index(db),
+ emu_profiles=load_emulator_profiles(str(root / "emulators")),
+ offline=True,
+ )
+ full = PackRecord()
+ generate_pack(
+ "plat", str(root / "platforms"), db, str(root / "bios"), "", record=full, **args
+ )
+ parts: dict[str, PackRecord] = {}
+ generate_split_packs(
+ "plat", str(root / "platforms"), db, str(root / "bios"), str(root / "dist"),
+ records=parts, **args,
+ )
+ self.assertFalse((root / "dist").exists())
+ return full, parts
+
+ def _assert_parts_add_up(self, full: PackRecord, parts: dict[str, PackRecord]) -> None:
+ notes = {"README.txt"}
+ union = {m for r in parts.values() for m in r.members} - notes
+ self.assertEqual(union, set(full.members) - notes)
+ for record in parts.values():
+ for member, source in record.sources.items():
+ self.assertEqual(
+ compute_hashes(source)["sha1"],
+ compute_hashes(full.sources[member])["sha1"], member,
+ )
+
+ def test_a_file_directory_conflict_stays_out_of_every_part(self):
+ full, parts = self._build(
+ {
+ "platform": "Plat", "verification_mode": "existence", "cores": ["sgb"],
+ "systems": {"snes": {"files": [{"name": "SGB1.sfc"}]}},
+ },
+ {"sgb": {
+ "emulator": "SGB", "type": "libretro", "systems": ["sgb-other"],
+ "files": [{"name": "program.rom", "path": "SGB1.sfc/program.rom"}],
+ }},
+ {"SGB1.sfc": b"cartridge", "sgb/program.rom": b"program"},
+ )
+ self.assertNotIn("SGB1.sfc/program.rom", full.members)
+ self._assert_parts_add_up(full, parts)
+
+ def test_a_case_twin_is_written_once(self):
+ full, parts = self._build(
+ {
+ "platform": "Plat", "verification_mode": "existence",
+ "case_insensitive_fs": True, "cores": ["msxcore"],
+ "systems": {
+ "msx": {"files": [{"name": "disk.rom", "destination": "openMSX/disk.rom"}]},
+ "coleco": {"files": []},
+ },
+ },
+ {"msxcore": {
+ "emulator": "MSX Core", "type": "libretro", "systems": ["msx", "coleco"],
+ "files": [{"name": "disk.rom", "path": "openmsx/disk.rom"}],
+ }},
+ {"MSX/disk.rom": b"disk"},
+ )
+ self.assertNotIn("openmsx/disk.rom", full.members)
+ self._assert_parts_add_up(full, parts)
+
+ def test_a_path_two_systems_declare_holds_one_file(self):
+ full, parts = self._build(
+ {
+ "platform": "Plat", "verification_mode": "existence",
+ "systems": {
+ "coco": {"files": [{
+ "name": "disk.rom", "sha1": hashlib.sha1(b"coco disk").hexdigest(),
+ }]},
+ "pc88": {"files": [{
+ "name": "disk.rom", "sha1": hashlib.sha1(b"pc-88 disk").hexdigest(),
+ }]},
+ },
+ },
+ {},
+ {"CoCo/disk.rom": b"coco disk", "PC88/disk.rom": b"pc-88 disk"},
+ )
+ self._assert_parts_add_up(full, parts)
+
+
if __name__ == "__main__":
unittest.main()
From e871e01abfe0b5ecdb45e41ed5edfc0c7751fcfa Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:22:06 +0100
Subject: [PATCH 26/83] docs: list the community tool's fields
Author, Repository and License sat on three lines of one paragraph, which
renders as one line. They are a list, and a guard refuses two bold
labels on consecutive lines of a paragraph.
---
tests/test_prose_style.py | 12 ++++++++++++
wiki/community-tools.md | 6 +++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/tests/test_prose_style.py b/tests/test_prose_style.py
index cf439800d..d089e9f45 100644
--- a/tests/test_prose_style.py
+++ b/tests/test_prose_style.py
@@ -386,6 +386,18 @@ class NoClauseSemicolons(unittest.TestCase):
]
self.assertEqual(offenders, [], "\n".join(offenders[:20]))
+ def test_bold_labels_do_not_run_together(self):
+ """community-tools.md wrote Author, Repository and License on three
+ lines of one paragraph: rendered, the three ran on one line."""
+ label = r"\*\*[^*\n]+:\*\*"
+ run = re.compile(rf"^{label}.*\n{label}", re.M)
+ offenders = [
+ f"{p.relative_to(ROOT)}: {m.group(0).splitlines()[0]}"
+ for p in _tracked() if p.suffix == ".md"
+ for m in run.finditer(FENCED.sub("", p.read_text(encoding="utf-8")))
+ ]
+ self.assertEqual(offenders, [], "\n".join(offenders[:20]))
+
def test_wiki_headings_use_sentence_case(self):
"""The gaps page and two wiki pages titled in Title Case ("What Each
Pack Contains") beside sentence-case pages ("Quick install")."""
diff --git a/wiki/community-tools.md b/wiki/community-tools.md
index bf0384e59..f5a56b04c 100644
--- a/wiki/community-tools.md
+++ b/wiki/community-tools.md
@@ -12,9 +12,9 @@ Projects built on RetroBIOS data.
## BIOS preservation tool
-**Author:** [monster-penguin](https://github.com/monster-penguin)
-**Repository:** [github.com/monster-penguin/BIOS-Preservation-Tool](https://github.com/monster-penguin/BIOS-Preservation-Tool)
-**License:** MIT
+- **Author:** [monster-penguin](https://github.com/monster-penguin)
+- **Repository:** [github.com/monster-penguin/BIOS-Preservation-Tool](https://github.com/monster-penguin/BIOS-Preservation-Tool)
+- **License:** MIT
A local tool for managing your own BIOS collection. Point it at your files, it verifies them against RetroBIOS platform YAMLs, stores them in a deduplicated database, and produces ready-to-use directories for each platform. Supports scanning directories, archives, and URLs.
From f696d4974fb4a545afc98fef323ca15593b1a987 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:22:18 +0100
Subject: [PATCH 27/83] fix: name a --dest that is a file
A BIOS folder that is a file, or lies under one, failed at mkdir with EEXIST or ENOTDIR, and the run blamed permissions and offered sudo. It is now refused before anything is checked, with an error event whose reason is not_a_folder.
---
install.ps1 | 2 +-
install.py | 28 ++++++++++++++++++++++++++--
install.sh | 2 +-
install/launchers/index.json | 16 ++++++++--------
tests/test_install.py | 34 ++++++++++++++++++++++++++++++++++
wiki/installer.md | 4 ++--
6 files changed, 72 insertions(+), 14 deletions(-)
diff --git a/install.ps1 b/install.ps1
index e41f7f32d..57aca4f16 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0"
+ $defaultInstallSha256 = "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index 05a057480..baa21de99 100644
--- a/install.py
+++ b/install.py
@@ -680,8 +680,9 @@ EVENT_KEYS: dict[str, tuple[str, ...]] = {
# found nowhere and no folder to assume) or from (a folder named with --from,
# reason: not_found, not_a_folder, unreadable, or system for the root
# of the system and /proc, /sys, /dev) or dest (reason: unreadable, a
- # folder above it this user cannot open, or not_writable, the BIOS
- # folder cannot be created, a summary following) or option (reason:
+ # folder above it this user cannot open, not_a_folder, the BIOS folder
+ # is a file or lies under one, or not_writable, the BIOS folder cannot
+ # be created, a summary following) or option (reason:
# unknown, a platform, target, system, core or emulator the run cannot
# use, refused before any download).
"error": ("stage", "reason", "platform", "message"),
@@ -13773,6 +13774,27 @@ def _refuse_closed(dest: Path, named: str) -> None:
sys.exit(1)
+def _refuse_file(dest: Path, named: str) -> None:
+ """End the run on a BIOS folder that is a file, or lies under one.
+
+ mkdir then failed on EEXIST or ENOTDIR, and the run blamed permissions
+ and offered sudo, which fails the same way.
+ """
+ for folder in (dest, *dest.parents):
+ if _exists(folder):
+ break
+ else:
+ return
+ if _is_dir(folder):
+ return
+ where = (f"{shown_path(dest)} is a file, not a folder" if folder == dest
+ else f"{shown_path(dest)} cannot be a folder: {shown_path(folder)} is a file")
+ EVENTS.emit("error", stage="dest", reason="not_a_folder", platform="", message=where)
+ print(f"Error: {screen_text(where)}. Name the folder the BIOS files go in, not "
+ f"the file {named}.", file=sys.stderr)
+ sys.exit(1)
+
+
def _missing_dest(dest: Path, ask: bool, named: str = "named with --dest",
again: bool = False) -> bool:
"""Say that a --dest folder does not exist before anything goes there.
@@ -13787,6 +13809,7 @@ def _missing_dest(dest: Path, ask: bool, named: str = "named with --dest",
a card's folder ended the run where it meant "not that card".
"""
_refuse_closed(dest, named)
+ _refuse_file(dest, named)
if dest.exists():
return True
nearest = dest.absolute()
@@ -15114,6 +15137,7 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
else f"{found_in[0]} names" if found_in else "detected here")
# One setup by now: two found without questions stopped above.
_refuse_closed(path, f"{named} (name another with --dest)")
+ _refuse_file(path, f"{named} (name another with --dest)")
total_downloaded = 0
total_up_to_date = 0
diff --git a/install.sh b/install.sh
index 26c45e4c6..4f1d02bbf 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0"
+DEFAULT_INSTALL_SHA256="482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 5ee293708..6f8f8ff49 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103894,
- "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
+ "size": 1104874,
+ "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1157521,
- "sha256": "0f9b070334a530a0ed5a6b6b773928d92f5a08aa0d0af18fde7b6cb4a16e731d"
+ "size": 1158501,
+ "sha256": "0ecf443039c136286322a57b33f1374dd52de0b5f2a772fbae93c1f98c19b62d"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1103894,
- "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
+ "size": 1104874,
+ "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103894,
- "sha256": "f48287847612b616bcaf607bd50207353bef5648e650a732c2d9595a64726ab0",
+ "size": 1104874,
+ "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
"executable": false
},
{
diff --git a/tests/test_install.py b/tests/test_install.py
index dbef10dd9..7efea9660 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -448,6 +448,40 @@ class AMissingDestIsSaid(unittest.TestCase):
self.assertIn("does not exist", out)
+class ADestThatIsAFileIsNamed(unittest.TestCase):
+ """--dest naming a file, or a path under one, failed at mkdir with
+ EEXIST or ENOTDIR, and the run said this user cannot write there and
+ offered a sudo command that fails the same way."""
+
+ def _run(self, dest: Path) -> subprocess.CompletedProcess:
+ env = dict(os.environ, RETROBIOS_OS="linux")
+ return subprocess.run(
+ [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "retroarch",
+ "--dest", str(dest), "--manifest", str(REPO_ROOT / "install" / "retroarch.json"),
+ "--system", "nintendo-gba", "--yes", "--events", "--offline"],
+ env=env, capture_output=True, text=True, timeout=120, check=False,
+ stdin=subprocess.DEVNULL)
+
+ def test_the_file_is_named_and_sudo_is_not_offered(self):
+ root = Path(_tempdir(self))
+ (root / "scph5501.bin").write_bytes(b"x")
+ for dest, words in (
+ (root / "scph5501.bin", f"{root / 'scph5501.bin'} is a file, not a folder"),
+ (root / "scph5501.bin" / "sub",
+ f"cannot be a folder: {root / 'scph5501.bin'} is a file"),
+ ):
+ with self.subTest(dest=dest):
+ proc = self._run(dest)
+ self.assertEqual(proc.returncode, 1, proc.stderr)
+ self.assertIn(words, proc.stderr)
+ self.assertNotIn("sudo", proc.stderr)
+ errors = [json.loads(line) for line in proc.stdout.splitlines()
+ if line.startswith("{") and '"error"' in line]
+ self.assertEqual([(e["stage"], e["reason"]) for e in errors],
+ [("dest", "not_a_folder")])
+ self.assertEqual((root / "scph5501.bin").read_bytes(), b"x")
+
+
class AFolderThatRefusesWritesIsNamed(unittest.TestCase):
"""A read-only BIOS folder ended the run on a traceback (a subfolder to
create), or on three retries per file and "once that is resolved", and a
diff --git a/wiki/installer.md b/wiki/installer.md
index 73719bf16..88da4c7b0 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -1738,7 +1738,7 @@ fields, the installer refuses to narrow rather than install everything.
| Code | Meaning |
|------|---------|
| `0` | everything asked for is installed or already in place |
-| `1` | a failure: the one-liner could not download or verify `install.py`, or found no Python 3.8 with its ssl, unicodedata and zlib modules (nothing was run), an unusable base URL, `--installed-cores` with no core found, a manifest that fails validation, a fetch that never succeeded, no platform to install for in a non-interactive run, some files failed or were left out by `--offline` while others installed, `--check` found files to fetch, a `--from-pack` pack that cannot be read, lacks a part or is for another platform, a `--from` folder that does not exist or cannot be read, a `--dest` that is not the card of the system named (another system's card, a folder inside one, a drive with none of its files where its card always has them, or a folder that does not exist), `--restore` could not put a file back, or `--add-app` could not put every file of the app on the card |
+| `1` | a failure: the one-liner could not download or verify `install.py`, or found no Python 3.8 with its ssl, unicodedata and zlib modules (nothing was run), an unusable base URL, `--installed-cores` with no core found, a manifest that fails validation, a fetch that never succeeded, no platform to install for in a non-interactive run, some files failed or were left out by `--offline` while others installed, `--check` found files to fetch, a `--from-pack` pack that cannot be read, lacks a part or is for another platform, a `--from` folder that does not exist or cannot be read, a BIOS folder that is a file or lies under one, a `--dest` that is not the card of the system named (another system's card, a folder inside one, a drive with none of its files where its card always has them, or a folder that does not exist), `--restore` could not put a file back, or `--add-app` could not put every file of the app on the card |
| `2` | nothing was installed: every file the run tried failed (a BIOS folder that cannot be written, for one), or `--offline` left every file out, the drive has too little free space for the download (checked before any folder is created), or the question about a folder that does not exist, named with `--dest` or typed at the folder question, was answered no. Also an option the installer refused before any download: an unknown option, `--jobs` outside 1 to 32, `--target` with `--every-board`, `--target` with `--from-pack` or `--offline` (or `RETROBIOS_INSTALL_OFFLINE` set) when no core list per board is at hand (the pack carries none and none is beside `--manifest` as `targets/.json`), or for a platform that publishes none, which is said to have no hardware targets, `--list-targets` with `--offline` and neither, `--add-app` with `--check`, `--dry-run`, a listing, `--from-pack` or `--offline`. The message then starts with `install.py: error:`. Also an unknown platform, target, system, core or emulator, said in an `Error:` or `Unknown platform` line and an `error` event whose `stage` is `option`. Also `--add-app` for a folder on no card that takes the app, said in an `Error:` line and an `app` event before anything is written. With `--restore`, a folder that is not a dated folder inside `retrobios-backup`. Also a quit chosen before the install, as `gh` ends a cancelled prompt: `q` at a question, `q` or **Quit** on the full screen, which then keeps `RetroBIOS: quit. Nothing was installed.`, and the full screen closed with no button pressed (`RETROBIOS_IDLE_EXIT`). No code but `0` closes a Windows Terminal tab started on the installer itself, so such a tab stays open on a quit |
| `130` | stopped with Ctrl+C, or with Ctrl+C or Ctrl+D at a question, the terminal keeping `RetroBIOS: stopped. Nothing was installed.` before an install. Run the same command again to carry on |
| `141` | the output was piped to a reader that closed early (`--list-platforms \| head`) |
@@ -1785,7 +1785,7 @@ other schemas under `api/v1/schemas/`.
| `start` | `schema`, `installer`, `mode` | First line. `schema` is 1, `installer` the identity `--version` prints, `mode` one of `install`, `check`, `dry-run`, `list` |
| `unsearched` | `folder`, `reason`, `message` | Before `detect`, once for each folder the search for setups could not look in, this user being refused it or a read failing there (a failing card, a link that loops). What it would hold counts as absent, and the other places are still searched: `detect` then lists what they hold, and an empty `platforms` after an `unsearched` line means nothing was found where the installer could look. `reason` says why in words (`Permission denied`), `message` says it in a sentence |
| `detect` | `os`, `os_name`, `platforms` | Once the platforms are known. `os_name` comes from `/etc/os-release`. `platforms` lists `{platform, name, bios_dir}`, and is empty when nothing supported was found |
-| `error` | `stage`, `reason`, `platform`, `message` | The file list could not be read (`stage` is `manifest`): `reason` is `network`, `not_found` or `invalid`, `clock` when the server's certificate was refused and the system clock reads a date before the installer was written, `no_ca` when the machine holds no list of trusted certificates (`SSL_CERT_FILE` names one), `no_ssl` when this Python was built without its `ssl` module and cannot use HTTPS, or `offline` when `--offline` forbids the request. A folder named with `--from` cannot be read (`stage` is `from`, `reason` `not_found`, `not_a_folder` for a file that is no ZIP, `unreadable`, or `system` for the root of the system, `/proc`, `/sys` or `/dev`). The BIOS folder sits under a folder this user cannot open (`stage` is `dest`, `reason` `unreadable`), and the run ends with code 1 before anything is written. A platform, target, system, core or emulator named on the command line is unknown or cannot be used here (`stage` is `option`, `reason` `unknown`, `platform` the platform it was checked against or the name typed), refused before any download with code 2. The BIOS folder cannot be created (`stage` is `dest`, `reason` `not_writable`): a `summary` follows with what the run installed before it. Two systems are detected on one machine and no `--dest` names the folder (`stage` is `detect`, `reason` `conflict`). The platform named with `--platform` is found nowhere and no folder can be assumed for it: a card system with no card named, a portable emulator, Batocera or Recalbox named on a computer (their folder is the `bios` folder of their SHARE drive), or no usual folder on this system or one set aside behind a folder this user cannot open (`stage` is `detect`, `reason` `not_found`). So is a platform named by a file list or a pack, in a run without questions where it is found nowhere here. A `--dest` refused as the card of the system named carries the same `stage` and `reason`: another system's card, a folder inside a card, a drive with none of the files its card always has, or a folder that does not exist. `message` says it in words, and is the only thing that tells these cases apart |
+| `error` | `stage`, `reason`, `platform`, `message` | The file list could not be read (`stage` is `manifest`): `reason` is `network`, `not_found` or `invalid`, `clock` when the server's certificate was refused and the system clock reads a date before the installer was written, `no_ca` when the machine holds no list of trusted certificates (`SSL_CERT_FILE` names one), `no_ssl` when this Python was built without its `ssl` module and cannot use HTTPS, or `offline` when `--offline` forbids the request. A folder named with `--from` cannot be read (`stage` is `from`, `reason` `not_found`, `not_a_folder` for a file that is no ZIP, `unreadable`, or `system` for the root of the system, `/proc`, `/sys` or `/dev`). The BIOS folder sits under a folder this user cannot open (`stage` is `dest`, `reason` `unreadable`), or is a file or lies under one (`reason` `not_a_folder`), and the run ends with code 1 before anything is written. A platform, target, system, core or emulator named on the command line is unknown or cannot be used here (`stage` is `option`, `reason` `unknown`, `platform` the platform it was checked against or the name typed), refused before any download with code 2. The BIOS folder cannot be created (`stage` is `dest`, `reason` `not_writable`): a `summary` follows with what the run installed before it. Two systems are detected on one machine and no `--dest` names the folder (`stage` is `detect`, `reason` `conflict`). The platform named with `--platform` is found nowhere and no folder can be assumed for it: a card system with no card named, a portable emulator, Batocera or Recalbox named on a computer (their folder is the `bios` folder of their SHARE drive), or no usual folder on this system or one set aside behind a folder this user cannot open (`stage` is `detect`, `reason` `not_found`). So is a platform named by a file list or a pack, in a run without questions where it is found nowhere here. A `--dest` refused as the card of the system named carries the same `stage` and `reason`: another system's card, a folder inside a card, a drive with none of the files its card always has, or a folder that does not exist. `message` says it in words, and is the only thing that tells these cases apart |
| `scanned` | `folder`, `files`, `truncated`, `other_drives` | Each folder named with `--from`, once read and before `detect`. `files` counts the files found, `truncated` is true when the search stopped at 200,000 of them, and `other_drives` lists the folders below it on another drive, which were not entered |
| `version` | `platform`, `list_version`, `installed_version`, `message` | Before `choices`, when the system here runs another version than the one the list was built for: `list_version` is the list's, `installed_version` the one the system's version file states, and `message` says it and what it means. Not written when either version is unknown. The run goes on |
| `board` | `platform`, `board`, `applied`, `message` | Before `choices`, with no `--target` and no `--every-board`, when the system names its board or a Batocera or KNULLI card mounted here does (`boot/batocera.board` or `boot/knulli.board` on its boot partition, `board` then being the board its image maps to): `applied` is true when the run keeps that board's files only, false for a board the platform's list does not name, which keeps every board's files. `message` says it |
From 1518ca53adb936773e350c539c72345ad8f1b9d4 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:22:27 +0100
Subject: [PATCH 28/83] docs: say the legal answer once
A closing Summary restated the opening lines on the strongest and weakest
ground, and the not-legal-advice line came three times. The disclaimer
stays at the top, and the one sentence the summary added, the risk the
project accepts, moves to the encryption keys section.
---
tests/test_site_wiki.py | 7 +++++++
wiki/legal.md | 10 ++--------
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/tests/test_site_wiki.py b/tests/test_site_wiki.py
index 8ea952643..bf9873856 100644
--- a/tests/test_site_wiki.py
+++ b/tests/test_site_wiki.py
@@ -455,6 +455,13 @@ class LegalOpensInPlainWords(unittest.TestCase):
self.assertEqual(re.findall(r"(?m)^## ", detail), [])
self.assertIn("### Emulation and BIOS redistribution", detail)
+ def test_said_once(self):
+ """A closing Summary restated the opening lines, and "not legal
+ advice" came three times."""
+ self.assertEqual(self.text.count("legal advice"), 1)
+ self.assertNotIn("### Summary", self.text)
+ self.assertIn("The project accepts that risk deliberately", self.text)
+
def test_a_contact_section_names_only_a_channel_that_exists(self):
section = _section(self.text, "Contact")
self.assertIn("https://github.com/Abdess/retrobios/issues", section)
diff --git a/wiki/legal.md b/wiki/legal.md
index 9c0f9c10e..44cd9585a 100644
--- a/wiki/legal.md
+++ b/wiki/legal.md
@@ -18,7 +18,7 @@ It depends on your country. Nothing here is legal advice.
## The reasoning in detail
-Redistributing firmware is not settled law. Below is the reasoning the project acts on, with the strength of each argument, so anyone can weigh it. None of it is legal advice, and none of it has been tested in court.
+Redistributing firmware is not settled law. Below is the reasoning the project acts on, with the strength of each argument, so anyone can weigh it. None of it has been tested in court.
### Emulation and BIOS redistribution
@@ -29,7 +29,7 @@ Redistributing firmware is not settled law. Below is the reasoning the project a
### Encryption keys (Switch prod.keys, 3DS AES keys, Wii U keys)
-This is the most contested area, and the weakest part of the project's position.
+This is the most contested area, and the weakest part of the project's position. The project accepts that risk deliberately, in the belief that these files are worth preserving while they can still be obtained.
- **Keys are unlikely to be copyrightable.** A bare numeric value has no author's creative expression, so copyright is a poor fit. This says nothing about the DMCA, which is the provision that actually applies.
- **DMCA 1201(f) is narrow.** Section 1201(f) allows a person who has lawfully obtained the right to use a copy to circumvent for the sole purpose of achieving interoperability with an independently created program, and 1201(f)(3) allows the means to be made available to others only for that same purpose. Publishing keys openly is not obviously within that allowance, and the trafficking prohibitions in 1201(a)(2) and 1201(b) remain in play. This is the clearest legal risk the project carries.
@@ -43,12 +43,6 @@ This is the most contested area, and the weakest part of the project's position.
- **Functional necessity.** Emulators cannot run the software these systems were built for without this firmware. That is why the files are collected. It is a statement of purpose, not a legal defence in itself.
- **Yuzu context.** The Yuzu settlement (2024) concerned the emulator and its alleged facilitation of piracy. Yuzu settled without admitting liability, so it set no precedent either way on firmware or key redistribution. It does show that rights holders in this space litigate.
-### Summary
-
-This project preserves BIOS files, firmware and keys for personal use, archival and interoperability. The strongest ground is the older, discontinued firmware, where fair use and the absence of a market both point the same way. The weakest is the encryption keys, where DMCA 1201 applies and the interoperability exemption is narrower than the use made of it here. The project accepts that risk deliberately, in the belief that these files are worth preserving while they can still be obtained.
-
-This reflects the project's good-faith understanding, not legal advice.
-
## Asking for a file to be removed
A rights holder, or anyone acting for one, can [open an issue](https://github.com/Abdess/retrobios/issues) identifying the file by path or hash. A file whose removal is requested by its rights holder is removed from the repository and from the next release. No formal notice is required and none will be demanded. State the file and the basis of the claim. The same channel is open to anyone else with a concern about a specific file.
From fd3733fcaa7b87771b6be2266484ba1f58274ec6 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:23:29 +0100
Subject: [PATCH 29/83] docs: give the FAQ console answer a command
The answer said --region us keeps only your region's BIOS, with nothing
to run. On the PlayStation it keeps 44 files, Japanese PS2 images among
them (install.py --system sony-playstation --region us --dry-run). The
answer now gives the --core command the installer itself suggests, in
the tabs of each system, and says what --region drops.
---
tests/test_site_wiki.py | 13 +++++++++++++
wiki/faq.md | 9 ++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/tests/test_site_wiki.py b/tests/test_site_wiki.py
index bf9873856..563628d88 100644
--- a/tests/test_site_wiki.py
+++ b/tests/test_site_wiki.py
@@ -426,6 +426,19 @@ def _entry(profile: dict, name: str) -> dict:
raise AssertionError(f"{name} not in the profile")
+class TheFaqAnswersWithACommand(unittest.TestCase):
+ """"Do I need every file of a console?" answered `--region us keeps only
+ your region's BIOS`, with no command to run, and that run kept 44 files
+ of the PlayStation set, Japanese PS2 images among them. `--core pcsx1`
+ is the lever the installer itself names."""
+
+ def test_every_file_of_a_console(self):
+ section = _section(_wiki("faq.md"), "Do I need every file of a console?")
+ self.assertIn("", section)
+ self.assertIn("--system sony-playstation --core pcsx1", section)
+ self.assertNotIn("only your region", section)
+
+
class LegalOpensInPlainWords(unittest.TestCase):
"""C5: Is it legal? is a Start here page and opened on case law."""
diff --git a/wiki/faq.md b/wiki/faq.md
index ff0781a70..70548bfc3 100644
--- a/wiki/faq.md
+++ b/wiki/faq.md
@@ -25,7 +25,14 @@ curl -fsSL https://abdess.github.io/retrobios/i | sh -s -- --dry-run
## Do I need every file of a console?
-No. `--region us` keeps only your region's BIOS.
+No. `--core` keeps what your emulator reads, here PCSX for PlayStation:
+
+
+```sh
+curl -fsSL https://abdess.github.io/retrobios/i | sh -s -- --system sony-playstation --core pcsx1
+```
+
+`--region us` drops another region's BIOS where a US one exists.
## Does the BIOS set the game's language?
From 8dc3ac82c71e2c366921e1d16ff61e63d00791b6 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:24:49 +0100
Subject: [PATCH 30/83] fix: date each prose citation on its own
realign_prose dated a whole field from the last commit that changed any of its citations. idtech4a++ corrected two notes citations by hand in the commit that advanced its pin, so the untouched Game.java:69-72 and GameResourceUrl.java:14-118 read as written under the current pin and were never offered again. Each citation is now followed through the history on its own. The two idtech4a++ ranges move to 72-75 and 15-121, read at ce49510f.
---
emulators/idtech4a++.yml | 4 +-
scripts/profile_sync.py | 92 ++++++++++++++------------------------
tests/test_profile_sync.py | 18 ++++++++
3 files changed, 54 insertions(+), 60 deletions(-)
diff --git a/emulators/idtech4a++.yml b/emulators/idtech4a++.yml
index 6e329f943..3f3096a71 100644
--- a/emulators/idtech4a++.yml
+++ b/emulators/idtech4a++.yml
@@ -110,7 +110,7 @@ notes: |
Q3E/src/main/jni/quake2/yquake2/src/common/filesystem.c:1801-1850,
Q3E/src/main/jni/zdoom/src/d_iwad.cpp:738,
Q3E/src/main/jni/ecwolf/src/wl_iwad.cpp:766,
- idTech4Amm/src/main/java/com/karin/idTech4Amm/sys/GameResourceUrl.java:14-118
+ idTech4Amm/src/main/java/com/karin/idTech4Amm/sys/GameResourceUrl.java:15-121
The Quake III lineage keeps id's release checksums for `baseq3` pak0 through
pak8 and `missionpack` pak0 through pak3, and an archive whose value disagrees
@@ -130,7 +130,7 @@ notes: |
two games whose data is a file rather than a folder.
ref: Q3E/src/main/jni/zdoom/src/d_iwad.cpp:287-297, 321-342,
Q3E/src/main/jni/zdoom/src/version.h:100-102,
- idTech4Amm/src/main/java/com/karin/idTech4Amm/sys/Game.java:69-72,
+ idTech4Amm/src/main/java/com/karin/idTech4Amm/sys/Game.java:72-75,
Q3E/src/main/java/com/n0n3m4/q3e/Q3EInterface.java:710-713
Starting a game extracts that game's bundled resources first. A text file named
diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py
index 795fbd62d..76bfdb95a 100644
--- a/scripts/profile_sync.py
+++ b/scripts/profile_sync.py
@@ -3742,15 +3742,6 @@ def _git_file_at(path: Path, sha: str) -> dict | None:
return document if isinstance(document, dict) else None
-def _scalar_values(document: dict) -> dict[str, str]:
- """String scalars of the document, keyed by field path."""
- return {
- field: value
- for kind, field, _, _, value in _walk_document(document)
- if kind == "str"
- }
-
-
def _pin_of(
document: dict, field: str, mode: str = "",
repo: upstream.Repo | None = None,
@@ -3788,26 +3779,6 @@ def _pin_of(
return value
-_CITATION_RUN_RE = re.compile(
- PROSE_CITE_RE.pattern + r"(?:, *\d+(?:-\d+)?)*"
-)
-
-
-def _scalar_citations(text: str | None) -> tuple[str, ...] | None:
- """The citations a scalar carries, in order, without the prose around them.
-
- A note reworded around unchanged citations was still written under the
- pin those citations describe: comparing whole texts moved the writing
- revision to the rewording commit, whose pin is current, and the stale
- citations were never offered for realignment again.
- """
- if text is None:
- return None
- return tuple(
- _citation_key(m.group(0)) for m in _CITATION_RUN_RE.finditer(text)
- )
-
-
def _writing_pins(
revisions: list[tuple[str, dict]], intro_sha: str, field: str, mode: str = "",
repo: upstream.Repo | None = None,
@@ -4066,68 +4037,73 @@ def realign_prose(
if not history:
return []
- current_values = _scalar_values(document)
- fields = {citation.field for citation in citations}
- alive = dict.fromkeys(fields, True)
- intro: dict[str, str | None] = dict.fromkeys(fields)
+ # Each citation is followed on its own: a field's text changes whenever
+ # one of its citations is corrected by hand, and dating the whole field
+ # from that commit put idtech4a++'s untouched Game.java:69-72 under the
+ # current pin, so the stale range was never offered again.
+ keys = [(c.field, _citation_key(c.ref)) for c in citations]
+ alive = [True] * len(citations)
+ intro: list[str | None] = [None] * len(citations)
revisions: list[tuple[str, dict]] = []
- # Fields whose writing pin lies past a revision that cannot be read:
+ # Citations whose writing pin lies past a revision that cannot be read:
# where their text came in is unknown, so they are not moved.
- unknown: dict[str, str] = {}
+ unknown: dict[int, str] = {}
# A revision that does not parse is passed over unless the pins differ
- # on its two sides while the field's citations changed across it: then
- # the text may have come in there under either pin. Otherwise nothing
+ # on its two sides while the citation is absent across it: then the
+ # text may have come in there under either pin. Otherwise nothing
# it could hold changes the reading. lindbergh-loader
# committed invalid YAML once (df7346b3), fixed the same day, and every
# note older than that commit stayed blocked for good.
gap: str | None = None
+
+ def carried_by(past: dict) -> set[tuple[str, str]]:
+ return {
+ (c.field, _citation_key(c.ref))
+ for c in collect_citations(past) if c.kind == "prose"
+ }
+
for sha in history:
- if not any(alive.values()):
+ if not any(alive):
break
past = _git_file_at(path, sha)
if past is None:
gap = gap or sha
continue
+ held = carried_by(past)
if gap:
newer = revisions[-1][1] if revisions else document
moved = any(
newer.get(pin) != past.get(pin)
for pin in ("source_commit", "upstream_commit")
)
- values = _scalar_values(past)
- for field, live in alive.items():
- if live and moved and _scalar_citations(values.get(field)) != (
- _scalar_citations(current_values.get(field))
- ):
- unknown[field] = gap
- alive[field] = False
+ for index, live in enumerate(alive):
+ if live and moved and keys[index] not in held:
+ unknown[index] = gap
+ alive[index] = False
gap = None
revisions.append((sha, past))
- values = _scalar_values(past)
- for field in fields:
- if not alive[field]:
+ for index, live in enumerate(alive):
+ if not live:
continue
- if _scalar_citations(values.get(field)) == _scalar_citations(
- current_values.get(field)
- ):
- intro[field] = sha
+ if keys[index] in held:
+ intro[index] = sha
else:
- alive[field] = False
+ alive[index] = False
if gap:
# The oldest revisions do not parse: where the text came in is past
# what can be read.
- unknown.update({field: gap for field, live in alive.items() if live})
+ unknown.update({index: gap for index, live in enumerate(alive) if live})
messages: list[str] = []
jobs: list[tuple[Citation, dict]] = []
- for citation in citations:
- if citation.field in unknown:
+ for index, citation in enumerate(citations):
+ if index in unknown:
messages.append(
f"read again: {citation.field}: {citation.ref} "
- f"(revision {unknown[citation.field][:8]} unreadable)"
+ f"(revision {unknown[index][:8]} unreadable)"
)
continue
- intro_sha = intro.get(citation.field)
+ intro_sha = intro[index]
if intro_sha is None:
# The scalar is not committed yet: written now, under this pin.
continue
diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py
index d9574bfc9..2521591b2 100644
--- a/tests/test_profile_sync.py
+++ b/tests/test_profile_sync.py
@@ -4766,6 +4766,24 @@ class TestRealignProse(unittest.TestCase):
any("pin moved under this text" in m for m in messages), messages
)
+ def test_a_citation_corrected_beside_another_dates_only_itself(self):
+ """idtech4a++ advanced its pin in the commit that corrected two
+ citations of its notes by hand. Dated per field, the untouched
+ Game.java:69-72 took that commit's current pin and was never
+ offered again, though its lines had moved."""
+ self._repo_with_advanced_pin()
+ self._commit(
+ PROSE_SAMPLE.replace("(b.c:2,8-9)", "(b.c:3,9-10)"),
+ "advance the pin, b.c corrected by hand",
+ )
+ self.files[("oldpin", "a.c")] = ["x"] * 9 + ["subject"]
+ self.files[("pin", "a.c")] = ["x"] * 13 + ["subject"]
+ self.files[("pin", "b.c")] = list("pqrstuvwxyz")
+ messages = profile_sync.realign_prose(self.path, self.tmp.name, dry_run=True)
+ flagged = [m for m in messages if "a.c:10" in m]
+ self.assertTrue(flagged, messages)
+ self.assertFalse([m for m in messages if "b.c:" in m], messages)
+
def test_a_citation_in_an_unmoved_upstream_needs_no_reading(self):
"""nethersx2 cites AetherSX2 files that only its upstream carries,
at an upstream pin that never moved. The port's pin did move under
From 556855421aec70eda38a41ea3914b25599fdbd5e Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:25:25 +0100
Subject: [PATCH 31/83] fix: keep release notes to checked claims
The v2026.10.10 notes said a pack holds every file its emulators open, so
a game never stops on a missing file, and that hashes never come from a
forum list: the gap analysis lists files no pack carries, and in md5
mode a pack keeps the platform's own md5 (verification-modes.md). The
generated text and the README now point to the gap analysis, and
release_notes.py refuses a whats-new text holding a judging or
contradicted phrase.
---
README.md | 4 ++--
scripts/generate_readme.py | 2 +-
scripts/release_notes.py | 26 ++++++++++++++++++++++++--
tests/test_pack_counts.py | 31 +++++++++++++++++++++++++++++++
wiki/release-process.md | 5 ++++-
5 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index ed1f62cc9..3b4d52cbd 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ First time? Follow the [first install, step by step](https://abdess.github.io/re
## Download BIOS packs
-A pack holds everything its platform runs: its own BIOS list plus every file its emulator cores load. Pick your platform, download the ZIP, extract to the BIOS path. Each Download link is a page that keeps its address from one release to the next. The installer above does the same file by file: its screen installs everything, or fewer under **Choose systems**, and `--system`, `--core`, `--region` and `--target` make the same choice without questions. For a bare minimum, build your own pack below.
+A pack holds its platform's own BIOS list plus the files its emulator cores load. What no pack carries yet is in the [gap analysis](https://abdess.github.io/retrobios/gaps/). Pick your platform, download the ZIP, extract to the BIOS path. Each Download link is a page that keeps its address from one release to the next. The installer above does the same file by file: its screen installs everything, or fewer under **Choose systems**, and `--system`, `--core`, `--region` and `--target` make the same choice without questions. For a bare minimum, build your own pack below.
A pack over 2 GB comes in several parts (`Pack.part1of2.zip`, `Pack.part2of2.zip`), and every part is needed. Each part is an ordinary ZIP: extract them all into the same folder.
@@ -208,4 +208,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-11-06T05:38:30Z*
+*Auto-generated on 2026-11-06T07:24:52Z*
diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py
index 5418e4889..85b5a9ad1 100644
--- a/scripts/generate_readme.py
+++ b/scripts/generate_readme.py
@@ -608,7 +608,7 @@ def generate_readme(db: dict, platforms_dir: str, db_path: str = "database.json"
"",
"## Download BIOS packs",
"",
- "A pack holds everything its platform runs: its own BIOS list plus every file its emulator cores load. Pick your platform, download the ZIP, extract to the BIOS path. Each Download link is a page that keeps its address from one release to the next. The installer above does the same file by file: its screen installs everything, or fewer under **" + _installer_words().TUI_SYSTEMS_ROW + "**, and `--system`, `--core`, `--region` and `--target` make the same choice without questions. For a bare minimum, build your own pack below.",
+ f"A pack holds its platform's own BIOS list plus the files its emulator cores load. What no pack carries yet is in the [gap analysis]({SITE_URL}gaps/). Pick your platform, download the ZIP, extract to the BIOS path. Each Download link is a page that keeps its address from one release to the next. The installer above does the same file by file: its screen installs everything, or fewer under **" + _installer_words().TUI_SYSTEMS_ROW + "**, and `--system`, `--core`, `--region` and `--target` make the same choice without questions. For a bare minimum, build your own pack below.",
"",
"A pack over 2 GB comes in several parts (`Pack.part1of2.zip`,"
" `Pack.part2of2.zip`), and every part is needed. Each part is an"
diff --git a/scripts/release_notes.py b/scripts/release_notes.py
index cf3903cae..dcf3613f9 100644
--- a/scripts/release_notes.py
+++ b/scripts/release_notes.py
@@ -7,7 +7,8 @@ issue 81 happened. Install commands, the parts sentence and the table come
from the record and the registry. Each row links the platform's page under
get/ on the site, which outlives the release, and the setups the registry
does not mark release_pack are named with the command. The maintainer writes
-what changed, and that text is appended as given.
+what changed, and that text is appended as given once it holds none of the
+REFUSED phrases.
Usage:
python scripts/release_notes.py --whats-new tmp/whats-new.md --output notes.md
@@ -102,6 +103,20 @@ def _link(name: str, pack: dict) -> str:
return f"[{label}]({release_record.get_page(_owner(name, pack), SITE)})"
+# Words the published notes of v2026.10.10 carried by hand: "never from a
+# forum list" judged lists other people keep, and "a game never stops on a
+# missing file" was a claim the gap analysis contradicts. Text about other
+# projects says what changed, not who erred (wiki/release-process.md).
+REFUSED = ("their file", "theirs", "of ours", "corrected", "wrong", "drift",
+ "left out", "never seen", "forum", "never stops", "never fails")
+
+
+def refused_words(text: str) -> list[str]:
+ """The refused phrases the text holds, case ignored."""
+ lowered = text.lower()
+ return [phrase for phrase in REFUSED if phrase in lowered]
+
+
def render(record: dict, platforms_dir: str, whats_new: str) -> str:
packs = record.get("packs", {})
folders = _extract_folders(record, platforms_dir)
@@ -124,7 +139,8 @@ def render(record: dict, platforms_dir: str, whats_new: str) -> str:
"### Download a pack",
"",
("One complete pack for each platform below: the BIOS list the platform"
- " publishes plus every file its emulators open. Each link is a page"
+ " publishes plus the files its emulators open. Files no pack carries yet"
+ f" are listed in the [gap analysis]({SITE}gaps/). Each link is a page"
" that keeps its address from one release to the next. Files is what the pack"
" holds once extracted, the count a file manager shows. Extracted size"
" is the space those files take, and the download is smaller."),
@@ -173,6 +189,12 @@ def main() -> int:
if not whats_new.strip():
print(f"Error: {args.whats_new} is empty", file=sys.stderr)
return 1
+ refused = refused_words(whats_new)
+ if refused:
+ print(f"Error: {args.whats_new} says {', '.join(repr(w) for w in refused)}. State what"
+ " changed and how it was checked, not a verdict on other projects or a"
+ " promise the gap analysis contradicts", file=sys.stderr)
+ return 1
write_text_atomic(str(args.output), render(record, args.platforms_dir, whats_new))
print(f"Wrote {args.output} for {record['tag']}, {len(record['packs'])} packs")
return 0
diff --git a/tests/test_pack_counts.py b/tests/test_pack_counts.py
index 461ed4942..e74ae2d14 100644
--- a/tests/test_pack_counts.py
+++ b/tests/test_pack_counts.py
@@ -11,12 +11,14 @@ installer fetches and leaves out the data directories a pack also carries.
from __future__ import annotations
import hashlib
+import io
import json
import sys
import tempfile
import unittest
import zipfile
from pathlib import Path
+from unittest import mock
import yaml
@@ -552,6 +554,35 @@ class TheReleaseNotesReadTheRecord(unittest.TestCase):
def test_the_notes_never_open_on_the_collection(self):
self.assertNotIn("collection", self.render().split("### What changed")[0])
+ def test_the_notes_claim_only_what_the_gaps_allow(self):
+ """v2026.10.10 said a pack holds every file its emulators open, "so a
+ game never stops on a missing file", and that hashes never come
+ "from a forum list". The gap analysis lists what no pack carries."""
+ text = self.render().split("### What changed")[0]
+ self.assertNotIn("every file its emulators", text)
+ self.assertIn("https://abdess.github.io/retrobios/gaps/", text)
+ self.assertEqual(release_notes.refused_words(text), [])
+
+ def test_a_judging_whats_new_is_refused(self):
+ self.assertEqual(
+ release_notes.refused_words(
+ "- Every hash comes from the emulator's source, never from a forum list.\n"
+ "- So a game never stops on a missing file."),
+ ["forum", "never stops"])
+ with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
+ whats_new = Path(tmp) / "whats-new.md"
+ whats_new.write_text("- Hashes never from a forum list\n", encoding="utf-8")
+ record = Path(tmp) / "release.json"
+ record.write_text(json.dumps(self.RECORD), encoding="utf-8")
+ argv = ["release_notes.py", "--record", str(record), "--whats-new", str(whats_new),
+ "--platforms-dir", str(REPO_ROOT / "platforms"),
+ "--output", str(Path(tmp) / "notes.md")]
+ with mock.patch.object(sys, "argv", argv), \
+ mock.patch("sys.stderr", new_callable=io.StringIO) as err:
+ self.assertEqual(release_notes.main(), 1)
+ self.assertIn("'forum'", err.getvalue())
+ self.assertFalse((Path(tmp) / "notes.md").exists())
+
def test_the_release_process_runs_it(self):
page = (REPO_ROOT / "wiki" / "release-process.md").read_text(encoding="utf-8")
self.assertIn("scripts/release_notes.py", page)
diff --git a/wiki/release-process.md b/wiki/release-process.md
index 250ad6ad7..3c031fab7 100644
--- a/wiki/release-process.md
+++ b/wiki/release-process.md
@@ -276,7 +276,10 @@ python scripts/generate_site.py
# 5. Write the notes: install commands, the parts sentence and the pack table
# come from release.json, and what changed since the previous tag is the
-# maintainer's own text in tmp/whats-new.md, appended as written.
+# maintainer's own text in tmp/whats-new.md, appended as written. The
+# script refuses a text that judges another project ("forum list") or
+# promises what the gap analysis contradicts ("never stops"): it says
+# what changed and how it was checked.
python scripts/release_notes.py --whats-new tmp/whats-new.md --output tmp/notes.md
# Create the release as a DRAFT, upload every asset, and only then publish it.
From 5f8205b36b39c46c4806dbef814125f455509c36 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:26:22 +0100
Subject: [PATCH 32/83] docs: date the Redump DATs instead of judging them
The catalog table called redump.org's DATs stale and said Dat-o-Matic
blocks automation. redump.org serves BIOS DATs dated 2010 to 2022
(Content-Disposition of /datfile/{psx,ps2,gc,xbox}-bios/, read
2026-11-06), and the Redump row named /static/bios links the scraper
replaced with one /bios/ route per system.
---
tests/test_doc_pages.py | 17 +++++++++++++++++
wiki/tools.md | 4 ++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/tests/test_doc_pages.py b/tests/test_doc_pages.py
index c29301dde..bb0d0d3eb 100644
--- a/tests/test_doc_pages.py
+++ b/tests/test_doc_pages.py
@@ -1986,3 +1986,20 @@ class ArchivedIsWhatTheToolsDo(unittest.TestCase):
if __name__ == "__main__":
unittest.main()
+
+
+class TheCatalogRowsStateFacts(unittest.TestCase):
+ """tools.md said "redump.org serves stale DATs" and "Dat-o-Matic blocks
+ automation", verdicts on two preservation projects, and gave Redump's
+ /static/bios links, which the scraper no longer reads."""
+
+ def test_dates_and_routes_not_verdicts(self):
+ text = (WIKI / "tools.md").read_text(encoding="utf-8")
+ rows = [line for line in text.splitlines()
+ if line.startswith(("| Redump |", "| No-Intro |"))]
+ self.assertEqual(len(rows), 2)
+ for word in ("stale", "blocks"):
+ self.assertNotIn(word, " ".join(rows))
+ scraper = (ROOT / "scripts" / "scraper" / "redump_dat_scraper.py").read_text(encoding="utf-8")
+ self.assertIn("/bios/", scraper)
+ self.assertIn("`/bios/`", rows[0])
diff --git a/wiki/tools.md b/wiki/tools.md
index dab60e5b0..c7dfae1dc 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -1643,8 +1643,8 @@ names the profiles read.
| Catalog | Acquisition | Notes |
|---------|------------|-------|
-| Redump | direct fetch from redump.info `/static/bios` | 4 BIOS DATs. redump.org serves stale DATs |
-| No-Intro | local pack, imported with `dat_pack_importer` | Dat-o-Matic blocks automation, and the `hugo19941994/auto-datfile-generator` mirror rebuilds daily |
+| Redump | direct fetch from redump.info, one `/bios/` route per system | 4 BIOS DATs. redump.org serves BIOS DATs dated 2010 to 2022, redump.info the current ones |
+| No-Intro | local pack, imported with `dat_pack_importer` | Dat-o-Matic serves its DATs through a browser session, and the `hugo19941994/auto-datfile-generator` mirror rebuilds daily |
| TOSEC | local pack, imported with `dat_pack_importer` | annual pack from tosecdev.org, 138 Firmware DATs |
The join is by SHA1, then by MD5 + size. A match sets the `provenance` field
From da9e1f568cc0aa0cece1da6ee67e88536edfd153 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:27:32 +0100
Subject: [PATCH 33/83] fix: refuse an offline export with no originals
pipeline.py --offline --with-export, listed as a standard command, passes
no --fetch to step 2e: on a fresh clone the database, verify and truth
were built before the export failed on every platform whose own file it
patches. The run is refused before step 0 when .cache/upstream-native/
holds nothing for such a platform, and tools.md says how to fill it.
---
scripts/pipeline.py | 27 ++++++++++++++++++++++++++
tests/test_tool_messages.py | 38 +++++++++++++++++++++++++++++++++++++
wiki/advanced-usage.md | 3 ++-
wiki/tools.md | 7 +++++++
4 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/scripts/pipeline.py b/scripts/pipeline.py
index 2c2f23ede..90976b050 100644
--- a/scripts/pipeline.py
+++ b/scripts/pipeline.py
@@ -883,6 +883,32 @@ def _refuse_offline_without_caches(
)
+def _refuse_offline_export_without_originals(
+ parser: argparse.ArgumentParser, args: argparse.Namespace,
+ cache: str = ".cache/upstream-native",
+) -> None:
+ """An offline run with --with-export needs each patched file cached.
+
+ Seven formats carry code, so step 2e patches the platform's own file,
+ which --offline does not fetch. On a fresh clone the database, verify
+ and the truth model were built before step 2e failed on every one.
+ """
+ if not (args.offline and args.with_export):
+ return
+ from exporter import discover_exporters # noqa: PLC0415
+
+ lacking = sorted(
+ name for name, exporter in discover_exporters().items()
+ if exporter.needs_original() and not any(Path(cache, name).glob("*"))
+ )
+ if lacking:
+ parser.error(
+ f"--with-export patches each platform's own file, and {cache}/ holds none "
+ f"for {', '.join(lacking)}: run python scripts/export_native.py --all "
+ "--refresh-cache once, or drop --offline"
+ )
+
+
def _truth_steps(args: argparse.Namespace, results: dict) -> bool:
"""Steps 2c to 2e: truth model, its diff, the native export."""
all_ok = True
@@ -1010,6 +1036,7 @@ def main() -> None:
args = parser.parse_args()
_refuse_unapplied_flags(parser, args)
_refuse_offline_without_caches(parser, args)
+ _refuse_offline_export_without_originals(parser, args)
if not args.offline:
# Read once and put in the environment every step inherits: the
# scrapers and refresh_data_dirs went anonymous unless the user had
diff --git a/tests/test_tool_messages.py b/tests/test_tool_messages.py
index 7f043a22b..3f1a8abbd 100644
--- a/tests/test_tool_messages.py
+++ b/tests/test_tool_messages.py
@@ -175,6 +175,44 @@ class AnOfflineRunWithNoCacheStopsFirst(unittest.TestCase):
parser.error.assert_not_called()
+class AnOfflineExportWithNoOriginalsStopsFirst(unittest.TestCase):
+ """pipeline.py --offline --with-export, which tools.md listed as a
+ standard command, built the database, verify and the truth model on a
+ fresh clone, then failed step 2e on every platform whose own file it
+ patches: --offline never passes --fetch."""
+
+ def _args(self, **flags):
+ import argparse
+
+ return argparse.Namespace(**{"offline": True, "with_export": True, **flags})
+
+ def test_refused_before_any_step(self):
+ from exporter import discover_exporters
+
+ patched = sorted(n for n, e in discover_exporters().items() if e.needs_original())
+ self.assertIn("batocera", patched)
+ with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
+ parser = mock.Mock()
+ pipeline._refuse_offline_export_without_originals(parser, self._args(), tmp)
+ message = parser.error.call_args.args[0]
+ self.assertIn("export_native.py --all --refresh-cache", message)
+ self.assertIn("batocera", message)
+ for args in (self._args(offline=False), self._args(with_export=False)):
+ parser = mock.Mock()
+ pipeline._refuse_offline_export_without_originals(parser, args, tmp)
+ parser.error.assert_not_called()
+ for name in patched:
+ (Path(tmp) / name).mkdir()
+ (Path(tmp) / name / "original").write_text("x")
+ parser = mock.Mock()
+ pipeline._refuse_offline_export_without_originals(parser, self._args(), tmp)
+ parser.error.assert_not_called()
+
+ def test_the_tools_page_says_so(self):
+ text = (REPO_ROOT / "wiki" / "tools.md").read_text(encoding="utf-8")
+ self.assertIn("export_native.py --all --refresh-cache", text)
+
+
class TheTruthDiffShowsWhereAndAsksNothing(unittest.TestCase):
"""The markdown wrote `**Remove** hiscore.dat (phantom)` beside six
`**Add** hiscore.dat`, none with a path, for files profiled cores read."""
diff --git a/wiki/advanced-usage.md b/wiki/advanced-usage.md
index c17cc07ac..d54969839 100644
--- a/wiki/advanced-usage.md
+++ b/wiki/advanced-usage.md
@@ -534,7 +534,8 @@ Include truth generation and diffing in the pipeline:
python scripts/pipeline.py --offline --with-truth
```
-Include truth + native format export:
+Include truth + native format export. Offline, the platforms' own files
+must already be cached ([tools](tools.md#pipeline)):
```bash
python scripts/pipeline.py --offline --with-export
diff --git a/wiki/tools.md b/wiki/tools.md
index c7dfae1dc..2c4b4290a 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -28,6 +28,13 @@ python scripts/pipeline.py --check-buildbot # online run + buildbot fresh
`python scripts/refresh_data_dirs.py` once first. A run that builds packs with no
data directory cached is refused before step 0.
+`--with-export` online passes `--fetch` to step 2e, which downloads each
+platform's own file and patches it. Offline that file must already be in
+`.cache/upstream-native/`: on a fresh clone run
+`python scripts/export_native.py --all --refresh-cache` once first. An offline
+run with `--with-export` and an empty cache for any platform it patches is
+refused before step 0.
+
Pipeline steps:
| Step | Description | Skipped by |
From 04aad256833c0b6fe375b2be55f44e9092704487 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:27:48 +0100
Subject: [PATCH 34/83] feat: pipeline compares split parts to the pack
Step 5 compared every narrowed pack with verify and never the --split parts with the full pack, so a part writing a path the full pack settles passed every check. check_split_packs builds each platform's parts in memory and compares their union with the full pack, path for path and byte for byte.
---
scripts/pipeline.py | 88 ++++++++++++++++++++++++++++++++++++++
tests/test_split_extras.py | 43 +++++++++++++++++++
wiki/advanced-usage.md | 4 ++
wiki/tools.md | 8 +++-
4 files changed, 142 insertions(+), 1 deletion(-)
diff --git a/scripts/pipeline.py b/scripts/pipeline.py
index 244c19aa5..cfb63107b 100644
--- a/scripts/pipeline.py
+++ b/scripts/pipeline.py
@@ -55,6 +55,7 @@ import subprocess
import sys
import tempfile
import time
+from collections.abc import Callable
from pathlib import Path
# The build scripts need CPython 3.9, which builds the same database,
@@ -810,6 +811,92 @@ def check_narrowed_packs(
return all_ok
+def split_differences(
+ full: object, parts: dict[str, object], same_bytes: Callable[[str, str], bool],
+) -> list[str]:
+ """Where the --split parts of a pack, together, are not the full pack.
+
+ A path in a part and not in the full pack, a path of the full pack in no
+ part, and a path a part fills with other bytes than the full pack.
+ """
+ full_members = {m for m in full.members if not _PACK_NOTES.search(m)}
+ union = {
+ m for record in parts.values() for m in record.members
+ if not _PACK_NOTES.search(m)
+ }
+ lines = [f"in a part, not in the full pack: {m}" for m in sorted(union - full_members)]
+ lines += [f"in the full pack, in no part: {m}" for m in sorted(full_members - union)]
+ lines += sorted({
+ f"other bytes in {name}: {member}"
+ for name, record in parts.items()
+ for member, source in record.sources.items()
+ if member in full.sources and not same_bytes(source, full.sources[member])
+ })
+ return lines
+
+
+def check_split_packs(
+ emulators_dir: str = "emulators", platforms_dir: str = "platforms",
+ db_path: str = "database.json", include_archived: bool = False,
+) -> bool:
+ """Build each platform's --split parts in memory and compare them with
+ the full pack: the parts must add up to it, path for path and byte for
+ byte. Each part is a pack of its own and used to settle its paths alone:
+ RetroDECK's parts carried bios/SGB1.sfc as a file and as a directory,
+ RetroBat's 21 openmsx/ twins of openMSX/ files. Offline, as every
+ comparison of this step.
+ """
+ import generate_pack # noqa: PLC0415
+ import packresolve # noqa: PLC0415
+ from common import ( # noqa: PLC0415
+ build_zip_contents_index,
+ group_identical_platforms,
+ list_registered_platforms,
+ load_data_dir_registry,
+ load_database,
+ load_emulator_profiles,
+ )
+
+ print(f"\n--- {step_title(STEP_LABELS['consistency'])}, split packs ---")
+ db = load_database(db_path)
+ zip_contents = build_zip_contents_index(db)
+ profiles = load_emulator_profiles(emulators_dir)
+ registry = load_data_dir_registry(platforms_dir)
+ groups = group_identical_platforms(
+ list_registered_platforms(platforms_dir, include_archived=include_archived),
+ platforms_dir,
+ )
+ was_offline = packresolve._OFFLINE
+ packresolve.set_offline(True)
+ all_ok = True
+ try:
+ for _members, platform in groups:
+ args = dict(
+ emulators_dir=emulators_dir, zip_contents=zip_contents,
+ data_registry=registry, emu_profiles=profiles, offline=True,
+ )
+ full = generate_pack.PackRecord()
+ parts: dict[str, generate_pack.PackRecord] = {}
+ with contextlib.redirect_stdout(io.StringIO()), \
+ contextlib.redirect_stderr(io.StringIO()):
+ generate_pack.generate_pack(
+ platform, platforms_dir, db, "bios", "", record=full, **args,
+ )
+ generate_pack.generate_split_packs(
+ platform, platforms_dir, db, "bios", "", records=parts, **args,
+ )
+ lines = split_differences(full, parts, generate_pack._same_bytes)
+ if lines:
+ all_ok = False
+ print(f" {platform} --split: {len(lines)} differences")
+ print("\n".join(f" {line}" for line in lines[:20]))
+ finally:
+ packresolve.set_offline(was_offline)
+ print(f" {len(groups)} split platform packs compared, "
+ f"{'all equal' if all_ok else 'differences above'}")
+ return all_ok
+
+
class _Skipped:
"""A step that did not run. Truthy, so it never fails the pipeline, and
distinct, so the summary does not report it as work that was done."""
@@ -1373,6 +1460,7 @@ def main() -> None:
ok = check_narrowed_packs(
include_archived=args.include_archived, full=args.full_narrowings,
) and ok
+ ok = check_split_packs(include_archived=args.include_archived) and ok
print(
f"--- {step_title(STEP_LABELS['consistency'])}, counts and paths: "
f"{'OK' if ok else 'FAILED'} ---"
diff --git a/tests/test_split_extras.py b/tests/test_split_extras.py
index e64fff4a3..9fa7c4d1a 100644
--- a/tests/test_split_extras.py
+++ b/tests/test_split_extras.py
@@ -195,5 +195,48 @@ class SplitPartsHoldWhatTheFullPackHolds(unittest.TestCase):
self._assert_parts_add_up(full, parts)
+class PipelineComparesTheSplitParts(unittest.TestCase):
+ """Step 5 compared the --region, --target, --system, --required-only and
+ --no-game-data packs with verify, and nothing compared the --split parts
+ with the full pack: RetroDECK's SGB1.sfc file/directory clash and
+ RetroBat's 21 openmsx/openMSX twins passed every check."""
+
+ def setUp(self):
+ import pipeline
+
+ self.pipeline = pipeline
+
+ def _record(self, sources: dict[str, str]) -> PackRecord:
+ record = PackRecord()
+ record.members = [*sources, "README.txt"]
+ record.sources = dict(sources)
+ return record
+
+ def test_equal_parts_report_nothing(self):
+ full = self._record({"a.bin": "x", "b.bin": "y"})
+ parts = {"A": self._record({"a.bin": "x"}), "B": self._record({"b.bin": "y"})}
+ self.assertEqual(self.pipeline.split_differences(full, parts, str.__eq__), [])
+
+ def test_each_difference_is_named(self):
+ full = self._record({"SGB1.sfc": "x", "kept.bin": "k", "lost.bin": "l"})
+ parts = {
+ "Snes": self._record({"SGB1.sfc": "x", "kept.bin": "other"}),
+ "Other": self._record({"SGB1.sfc/program.rom": "p"}),
+ }
+ self.assertEqual(
+ self.pipeline.split_differences(full, parts, str.__eq__),
+ [
+ "in a part, not in the full pack: SGB1.sfc/program.rom",
+ "in the full pack, in no part: lost.bin",
+ "other bytes in Snes: kept.bin",
+ ],
+ )
+
+ def test_step_five_runs_the_comparison(self):
+ source = (REPO_ROOT / "scripts" / "pipeline.py").read_text()
+ step = source[source.index("# Step 5: Consistency check"):source.index("# Step 6:")]
+ self.assertIn("check_split_packs(", step)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/wiki/advanced-usage.md b/wiki/advanced-usage.md
index c17cc07ac..78c3fe16a 100644
--- a/wiki/advanced-usage.md
+++ b/wiki/advanced-usage.md
@@ -63,6 +63,10 @@ Group the split ZIPs by manufacturer (Sony, Nintendo, Sega, etc.):
python scripts/generate_pack.py --platform retroarch --split --group-by manufacturer
```
+The parts together hold exactly the files of the full pack, so every part
+can be extracted into the same folder. Core files of a system the platform
+does not list go in an `Other_Cores` part.
+
### System-specific packs
Extract only the files for a single system within a platform:
diff --git a/wiki/tools.md b/wiki/tools.md
index 78dfb21b1..8dbf84bae 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -52,7 +52,7 @@ Pipeline steps:
| 4c | Generate target manifests | `--skip-packs` |
| 4d | Collected copies only an emulator install provides (`bundled_only.py --strict`, gates the run) | - |
| 4e | Games index: what the installer reads for the games on a card (`generate_games_index.py`, fails under its coverage floor) | - (reads the committed install lists) |
-| 5 | Consistency check: counts, paths per archive, every emulator and system pack, the narrowed platform packs | `--skip-packs`, or no full pack built (`--source platform` or `truth`) |
+| 5 | Consistency check: counts, paths per archive, every emulator and system pack, the narrowed platform packs, the `--split` parts | `--skip-packs`, or no full pack built (`--source platform` or `truth`) |
| 6 | Pack integrity (extract + hash) | `--skip-packs`, or no full pack built |
| 7 | Generate README and CONTRIBUTING, then the installer page's tables and run samples (`generate_installer_doc.py`) | `--skip-docs` |
| 8 | Generate site | `--skip-docs` |
@@ -110,6 +110,12 @@ alone, run `python scripts/check_buildbot_system.py`.
`--source` and `--one-per-slot` are not compared: verify has no report of
a platform-only, truth-only or one-per-slot pack. A test fails when a new
narrowing reaches the pack name without being compared or exempted.
+- **The `--split` parts add up to the full pack.** Step 5 builds the parts of
+ every platform in memory and compares their union with the full pack, path
+ for path and byte for byte: a part is built against the full pack's own
+ placement, so a path the full pack settles (a file/directory clash, a case
+ twin, a path two systems declare) is not written again in a part. The 17
+ platform packs took about four and a half minutes on 2026-11-06.
- **Generators write through `write_if_changed()`.** A new timestamp alone
rewrites nothing, so a diff on a generated file always means content.
- **One run per output directory.** Pack generation takes a lock on
From f255efca0ffc726dfa371c342595b9ef524fb4db Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:27:59 +0100
Subject: [PATCH 35/83] docs: list pipeline flag refusals in one table
tools.md said --full-narrowings is refused with --skip-packs only, while
pipeline.py also refuses it with --source platform or truth, and
advanced-usage.md kept a second, shorter list. The tools table now
carries every pair, checked against _refuse_unapplied_flags, and
advanced-usage links to it.
---
tests/test_tool_messages.py | 39 +++++++++++++++++++++++++++++++++++++
wiki/advanced-usage.md | 2 +-
wiki/tools.md | 2 +-
3 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/tests/test_tool_messages.py b/tests/test_tool_messages.py
index 3f1a8abbd..1ba332604 100644
--- a/tests/test_tool_messages.py
+++ b/tests/test_tool_messages.py
@@ -213,6 +213,45 @@ class AnOfflineExportWithNoOriginalsStopsFirst(unittest.TestCase):
self.assertIn("export_native.py --all --refresh-cache", text)
+class ThePipelineFlagTableSaysEveryRefusal(unittest.TestCase):
+ """tools.md said --full-narrowings is refused with --skip-packs only, and
+ advanced-usage.md kept its own shorter list: `--source truth
+ --full-narrowings` failed with nothing on either page saying so."""
+
+ PAIRS = {"--source": "platform", "--all-variants": True, "--full-narrowings": True,
+ "--skip-packs": True}
+
+ def _refused(self, flags: dict) -> bool:
+ import argparse
+
+ args = argparse.Namespace(source=None, all_variants=False, full_narrowings=False,
+ skip_packs=False)
+ for flag, value in flags.items():
+ setattr(args, flag.lstrip("-").replace("-", "_"), value)
+ parser = mock.Mock()
+ pipeline._refuse_unapplied_flags(parser, args)
+ return parser.error.called
+
+ def test_each_refused_pair_is_in_the_row_of_a_flag(self):
+ import itertools
+
+ text = (REPO_ROOT / "wiki" / "tools.md").read_text(encoding="utf-8")
+ rows = {line.split("`")[1].split()[0]: line for line in text.splitlines()
+ if line.startswith("| `--")}
+ for (a, va), (b, vb) in itertools.combinations(self.PAIRS.items(), 2):
+ if not self._refused({a: va, b: vb}):
+ continue
+ with self.subTest(pair=(a, b)):
+ self.assertTrue(f"`{b}" in rows.get(a, "") or f"`{a}" in rows.get(b, ""),
+ f"{a} with {b} is refused, and neither row says so")
+ self.assertIn("`--source truth`", rows["--full-narrowings"])
+
+ def test_one_list_of_refusals(self):
+ text = (REPO_ROOT / "wiki" / "advanced-usage.md").read_text(encoding="utf-8")
+ self.assertNotIn("are refused with", text)
+ self.assertIn("tools.md#pipeline", text)
+
+
class TheTruthDiffShowsWhereAndAsksNothing(unittest.TestCase):
"""The markdown wrote `**Remove** hiscore.dat (phantom)` beside six
`**Add** hiscore.dat`, none with a path, for files profiled cores read."""
diff --git a/wiki/advanced-usage.md b/wiki/advanced-usage.md
index d54969839..9f230fe2e 100644
--- a/wiki/advanced-usage.md
+++ b/wiki/advanced-usage.md
@@ -543,7 +543,7 @@ python scripts/pipeline.py --offline --with-export
### Combining flags
-These flags compose (`--source` and `--all-variants` are refused with `--skip-packs`):
+These flags compose, except the pairs the [pipeline flags](tools.md#pipeline) table marks as refused:
```bash
python scripts/pipeline.py --offline --skip-packs --skip-docs --with-truth --target switch
diff --git a/wiki/tools.md b/wiki/tools.md
index 2c4b4290a..0e62fec66 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -76,7 +76,7 @@ Pipeline flags:
| `--target TARGET` | filter verify, packs and truth by hardware target |
| `--source {platform,truth,full}` | pack file source, passed through to `generate_pack.py`. Refused with `--skip-packs` |
| `--all-variants` | build the 6 source x required combinations. Refused with `--skip-packs` and with `--source` |
-| `--full-narrowings` | step 5 compares every region, target and system of each platform instead of three of each. Refused with `--skip-packs` |
+| `--full-narrowings` | step 5 compares every region, target and system of each platform instead of three of each. Refused with `--skip-packs` and with `--source platform` or `--source truth` |
| `--check-buildbot` | run step 2b. Additive, and ignored under `--offline` |
| `--with-truth` | run steps 2c and 2d |
| `--with-export` | run steps 2c, 2d and 2e |
From 21dd14c851b38e122d762815c8480eea5b1f9ec5 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:30:55 +0100
Subject: [PATCH 36/83] fix: a verified large file keeps its bytes
fetch_large_file verified a cached copy and returned its name, which another run replaces when the release serves a re-upload: the caller then packed bytes it never verified. The returned path is now a hard link under .cache/large/.by-sha1//, kept only if it holds the inode that was hashed. Revisions no name holds are dropped a day later. restore_large_files hashes each copy before moving it into place.
---
scripts/largefiles.py | 84 ++++++++++++++++++++++++++++-----
scripts/restore_large_files.py | 39 +++++++++++++--
tests/test_audit_regressions.py | 38 +++++++++++++++
tests/test_large_file_cache.py | 64 +++++++++++++++++++++----
wiki/release-process.md | 7 ++-
5 files changed, 208 insertions(+), 24 deletions(-)
diff --git a/scripts/largefiles.py b/scripts/largefiles.py
index 13b09b1ad..367ba2e28 100644
--- a/scripts/largefiles.py
+++ b/scripts/largefiles.py
@@ -12,6 +12,7 @@ import os
import sys
import re
import tempfile
+import time
import urllib.error
import urllib.parse
import urllib.request
@@ -26,6 +27,13 @@ from hashing import compute_hashes
LARGE_FILES_RELEASE = "large-files"
LARGE_FILES_REPO = "Abdess/retrobios"
LARGE_FILES_CACHE = ".cache/large"
+# Verified revisions, hard-linked as / beside the cache. A name
+# in the cache is replaced when the release serves new bytes under it, so a
+# path handed out by name could hold other bytes by the time the caller read
+# them. Nothing ever writes other bytes under a sha1. The asset name stays
+# last: callers read the extension (an archive is packed as one).
+VERIFIED_STORE = ".by-sha1"
+ORPHAN_GRACE = 24 * 3600
GITIGNORE = Path(__file__).resolve().parent.parent / ".gitignore"
_UNSAFE_ASSET_CHARS = re.compile(r"[^A-Za-z0-9._-]+")
@@ -169,14 +177,14 @@ def _fetch_asset(
if os.path.isdir(cached):
return None
- if os.path.exists(cached) and not (expected_sha1 or expected_md5):
- return cached
if os.path.exists(cached):
snapshot = _read_once(cached)
if snapshot is None:
pass
elif _matches(snapshot[0], expected_sha1, expected_md5):
- return cached
+ pinned = _pin_verified(cached, snapshot, dest_dir, name)
+ if pinned:
+ return pinned
elif not _replaced_on_release(name, snapshot[0]["sha256"], snapshot[1], offline):
# A copy of this asset that answers another hash: the caller
# wants a different revision under the same name, and the
@@ -220,17 +228,71 @@ def _fetch_asset(
print(f" large file {candidate}: {exc}", file=sys.stderr)
if not downloaded:
return None
- if (expected_sha1 or expected_md5) and not _matches(
- compute_hashes(tmp_path), expected_sha1, expected_md5
- ):
+ snapshot = _read_once(tmp_path)
+ if snapshot is None or not _matches(snapshot[0], expected_sha1, expected_md5):
return None
set_plain_mode(tmp_path)
+ pinned = _pin_verified(tmp_path, snapshot, dest_dir, name)
os.replace(tmp_path, cached)
- return cached
+ _prune_verified(dest_dir)
+ return pinned
finally:
_drop(tmp_path)
+def _pin_verified(
+ path: str, snapshot: tuple[dict[str, str], int, int], dest_dir: str, name: str,
+) -> str | None:
+ """The verified revision at *path*, as / in VERIFIED_STORE.
+
+ *snapshot* is what _read_once read: the link is kept only if it holds
+ that inode, so a copy another run promoted after the hash is never
+ passed off as the one verified. None when the name moved in between.
+ """
+ revision = os.path.join(dest_dir, VERIFIED_STORE, snapshot[0]["sha1"])
+ os.makedirs(revision, exist_ok=True)
+ final = os.path.join(revision, name)
+ if os.path.isfile(final):
+ return final
+ scratch = os.path.join(revision, f".{os.getpid()}.{os.urandom(4).hex()}.tmp")
+ try:
+ os.link(path, scratch)
+ except FileNotFoundError:
+ return None
+ try:
+ if os.stat(scratch).st_ino != snapshot[2]:
+ return None
+ os.replace(scratch, final)
+ return final
+ finally:
+ with contextlib.suppress(FileNotFoundError):
+ os.unlink(scratch)
+
+
+def _prune_verified(dest_dir: str) -> None:
+ """Drop the revisions no cache name has held for ORPHAN_GRACE seconds.
+
+ Losing its cache name changes the inode's ctime, so a revision another
+ run pinned just before the release replaced it stays readable while that
+ run packs it.
+ """
+ store = os.path.join(dest_dir, VERIFIED_STORE)
+ now = time.time()
+ for revision in os.scandir(store):
+ if not revision.is_dir():
+ continue
+ for entry in os.scandir(revision.path):
+ if entry.name.endswith(".tmp"):
+ continue
+ with contextlib.suppress(FileNotFoundError):
+ stat = entry.stat()
+ if stat.st_nlink == 1 and now - stat.st_ctime > ORPHAN_GRACE:
+ os.unlink(entry.path)
+ # Another run may be linking a copy into it: left for the next prune.
+ with contextlib.suppress(FileNotFoundError, OSError):
+ os.rmdir(revision.path)
+
+
def _asset_urls(name: str) -> list[tuple[str, str]]:
"""Release URLs an asset may be published under, with their names.
@@ -252,9 +314,9 @@ def _asset_urls(name: str) -> list[tuple[str, str]]:
]
-def _read_once(path: str) -> tuple[dict[str, str], int] | None:
- """Digests and size of the file at *path*, all read from one file, or
- None when it is gone.
+def _read_once(path: str) -> tuple[dict[str, str], int, int] | None:
+ """Digests, size and inode of the file at *path*, all read from one
+ file, or None when it is gone.
Every judgement on a cache copy reads this one snapshot. Hashed, then
hashed again by path for the release check, a copy another run promoted
@@ -271,7 +333,7 @@ def _read_once(path: str) -> tuple[dict[str, str], int] | None:
except FileNotFoundError:
return None
if (before.st_ino, before.st_mtime_ns) == (after.st_ino, after.st_mtime_ns):
- return hashes, after.st_size
+ return hashes, after.st_size, after.st_ino
return None
diff --git a/scripts/restore_large_files.py b/scripts/restore_large_files.py
index 96a7a5010..973872fa3 100644
--- a/scripts/restore_large_files.py
+++ b/scripts/restore_large_files.py
@@ -17,11 +17,14 @@ Usage:
from __future__ import annotations
import argparse
+import contextlib
import hashlib
import os
import sys
+import tempfile
sys.path.insert(0, os.path.dirname(__file__))
+from artifacts import set_plain_mode
from common import copy_file_atomic, load_database
@@ -56,6 +59,36 @@ def index_cache(cache_dir: str) -> dict[str, str]:
return index
+def _copy_verified(source: str, path: str, sha1: str) -> bool:
+ """Copy *source* to *path* only if the copy hashes to *sha1*.
+
+ The cache was hashed before the copy, and another run can replace a
+ cached name in between (a re-uploaded asset): the copy is what counts.
+ Whole or absent: a scan running beside a plain copy hashed the truncated
+ file and published that in the database.
+ """
+ handle, scratch = tempfile.mkstemp(
+ dir=os.path.dirname(os.path.abspath(path)),
+ prefix=f".{os.path.basename(path)}.", suffix=".tmp",
+ )
+ os.close(handle)
+ try:
+ copy_file_atomic(source, scratch)
+ digest = hashlib.sha1()
+ with open(scratch, "rb") as f:
+ for chunk in iter(lambda: f.read(1 << 20), b""):
+ digest.update(chunk)
+ if digest.hexdigest() != sha1:
+ print(f"Changed in the cache while restoring: {source}", file=sys.stderr)
+ return False
+ set_plain_mode(scratch)
+ os.replace(scratch, path)
+ return True
+ finally:
+ with contextlib.suppress(FileNotFoundError):
+ os.unlink(scratch)
+
+
def restore(
cache_dir: str, db_path: str, gitignore: str
) -> tuple[int, list[str]]:
@@ -79,9 +112,9 @@ def restore(
unsatisfied.append(path)
continue
os.makedirs(os.path.dirname(path), exist_ok=True)
- # Whole or absent: a scan running beside a plain copy hashed the
- # truncated file and published that in the database.
- copy_file_atomic(source, path)
+ if not _copy_verified(source, path, sha1):
+ unsatisfied.append(path)
+ continue
print(f"Restored: {path}")
restored += 1
print(f"Total: {restored} files restored")
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 3df8850fe..6bfa03c80 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -2054,6 +2054,44 @@ class CheckoutCompletenessRegressions(unittest.TestCase):
finally:
os.chdir(cwd)
+ def test_restore_refuses_a_copy_replaced_after_the_index(self):
+ """The cache is hashed first and copied later: another run that
+ replaced the cached name in between put its bytes at a path the
+ database pins to the old ones."""
+ from scripts import restore_large_files
+
+ with tempfile.TemporaryDirectory(dir=TMP_ROOT) as directory:
+ root = Path(directory)
+ cache = root / "cache"
+ cache.mkdir()
+ payload = b"firmware bytes"
+ (cache / "asset.bin").write_bytes(payload)
+ sha1 = hashlib.sha1(payload).hexdigest()
+ (root / ".gitignore").write_text("bios/Sony/big.pup\n", encoding="utf-8")
+ (root / "database.json").write_text(
+ json.dumps({"files": {sha1: {"path": "bios/Sony/big.pup"}}}),
+ encoding="utf-8",
+ )
+ real_index = restore_large_files.index_cache
+
+ def index_then_replace(cache_dir: str) -> dict[str, str]:
+ index = real_index(cache_dir)
+ (cache / "asset.bin").write_bytes(b"re-uploaded bytes")
+ return index
+
+ cwd = os.getcwd()
+ os.chdir(root)
+ try:
+ with mock.patch.object(restore_large_files, "index_cache", index_then_replace):
+ restored, unsatisfied = restore_large_files.restore(
+ str(cache), "database.json", ".gitignore"
+ )
+ self.assertEqual((restored, unsatisfied), (0, ["bios/Sony/big.pup"]))
+ self.assertFalse((root / "bios/Sony/big.pup").exists())
+ self.assertEqual(os.listdir(root / "bios/Sony"), [])
+ finally:
+ os.chdir(cwd)
+
def test_restore_leaves_tracked_paths_alone(self):
from scripts.restore_large_files import restore
diff --git a/tests/test_large_file_cache.py b/tests/test_large_file_cache.py
index ed6b9d16e..783c5541b 100644
--- a/tests/test_large_file_cache.py
+++ b/tests/test_large_file_cache.py
@@ -158,9 +158,9 @@ class LargeFileCacheTest(unittest.TestCase):
raise AssertionError("must not download when the cache is valid")
largefiles.urllib.request.urlopen = fail
- self.assertEqual(
- common.fetch_large_file("asset.bin", dest_dir=self.dir), str(cached)
- )
+ self.assertTrue(os.path.samefile(
+ common.fetch_large_file("asset.bin", dest_dir=self.dir), cached
+ ))
def test_offline_cache_miss_never_opens_the_network(self):
def fail(req, timeout=None):
@@ -182,15 +182,15 @@ class LargeFileCacheTest(unittest.TestCase):
raise AssertionError("offline cache hit must not open the network")
largefiles.urllib.request.urlopen = fail
- self.assertEqual(
+ self.assertTrue(os.path.samefile(
common.fetch_large_file(
"asset.bin",
dest_dir=self.dir,
expected_sha1=hashlib.sha1(PAYLOAD_A).hexdigest(),
offline=True,
),
- str(cached),
- )
+ cached,
+ ))
def _serve(self, payload: bytes, gets: list):
class _Head(io.BytesIO):
@@ -222,7 +222,7 @@ class LargeFileCacheTest(unittest.TestCase):
"asset.bin", dest_dir=self.dir,
expected_sha1=hashlib.sha1(rebuilt).hexdigest(),
)
- self.assertEqual(result, str(cached))
+ self.assertTrue(os.path.samefile(result, cached))
self.assertEqual(cached.read_bytes(), rebuilt)
self.assertEqual(len(gets), 1)
@@ -582,7 +582,7 @@ class ReleaseAssetNames(unittest.TestCase):
offline=True,
registered=self.REGISTERED,
)
- self.assertEqual(got, os.path.join(cache, names[self.RTCW]))
+ self.assertTrue(os.path.samefile(got, os.path.join(cache, names[self.RTCW])))
# The cache entry of the other asset is a valid file, not stale.
self.assertTrue(Path(cache, names[self.ET]).exists())
@@ -762,7 +762,7 @@ class ASameSizeReuploadIsSeen(unittest.TestCase):
"dsi_nand.bin", str(self.dir), hashlib.sha1(new).hexdigest(), "",
offline=False,
)
- self.assertEqual(found, str(self.cached))
+ self.assertTrue(os.path.samefile(found, self.cached))
def test_the_release_check_compares_digests_at_equal_size(self):
expected = {"bios/Nintendo/DSi/dsi_nand.bin": 8}
@@ -792,3 +792,49 @@ class ASameSizeReuploadIsSeen(unittest.TestCase):
if __name__ == "__main__":
unittest.main()
+
+
+class AVerifiedPathKeepsItsBytes(unittest.TestCase):
+ """fetch_large_file verified a cached copy and returned its name. Another
+ run that found the release re-uploaded then replaced that name with the
+ new revision, and the first run packed bytes it never verified, under a
+ manifest sha1 that describes the old ones."""
+
+ def setUp(self):
+ _test_registry(self)
+ self.dir = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp"))
+ self.addCleanup(shutil.rmtree, self.dir, True)
+ (self.dir / "asset.bin").write_bytes(PAYLOAD_A)
+ self.served = {"asset.bin": hashlib.sha256(PAYLOAD_B).hexdigest()}
+
+ def _fetch(self, payload: bytes, offline: bool) -> str | None:
+ def urlopen(req, timeout=None):
+ return _SlowResponse(PAYLOAD_B)
+
+ with mock.patch.object(largefiles, "_served_digests", lambda: self.served), \
+ mock.patch.object(largefiles.urllib.request, "urlopen", urlopen):
+ return largefiles.fetch_large_file(
+ "asset.bin", dest_dir=str(self.dir),
+ expected_sha1=hashlib.sha1(payload).hexdigest(), offline=offline,
+ )
+
+ def test_a_revision_promoted_after_the_check_is_not_read(self):
+ first = self._fetch(PAYLOAD_A, offline=True)
+ second = self._fetch(PAYLOAD_B, offline=False)
+ self.assertEqual((self.dir / "asset.bin").read_bytes(), PAYLOAD_B)
+ self.assertEqual(Path(second).read_bytes(), PAYLOAD_B)
+ self.assertEqual(Path(first).read_bytes(), PAYLOAD_A)
+ self.assertEqual(Path(first).name, "asset.bin")
+
+ def test_an_orphaned_revision_is_dropped_after_the_grace(self):
+ first = self._fetch(PAYLOAD_A, offline=True)
+ self._fetch(PAYLOAD_B, offline=False)
+ self.assertTrue(Path(first).exists())
+ with mock.patch.object(largefiles, "ORPHAN_GRACE", -1):
+ largefiles._prune_verified(str(self.dir))
+ self.assertFalse(Path(first).exists())
+ self.assertEqual((self.dir / "asset.bin").read_bytes(), PAYLOAD_B)
+ self.assertEqual(
+ [p.name for p in (self.dir / largefiles.VERIFIED_STORE).iterdir()],
+ [hashlib.sha1(PAYLOAD_B).hexdigest()],
+ )
diff --git a/wiki/release-process.md b/wiki/release-process.md
index 250ad6ad7..eb0f1ecd6 100644
--- a/wiki/release-process.md
+++ b/wiki/release-process.md
@@ -206,7 +206,12 @@ file's own name. A path whose asset name differs from its file name is
uploaded from a copy carrying the asset name.
**Local cache.** `generate_pack.py` calls `fetch_large_file()` which downloads
-from the release and caches in `.cache/large/` for subsequent runs.
+from the release and caches in `.cache/large/` for subsequent runs. The path it
+returns is a hard link under `.cache/large/.by-sha1//`, never the cached
+name: another run that finds the asset re-uploaded replaces the name, and the
+first run still reads the bytes it verified. A revision no name holds is
+dropped a day later, at the next download. `restore_large_files.py` hashes
+each copy before it moves it into place.
**Check.** The installer refuses a download whose `Content-Length` differs
from the manifest size, and the manifest size is that of the local file. A
From b3f8f64395654073fc8e588aee064d736a546494 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:33:01 +0100
Subject: [PATCH 37/83] fix: refuse options a listing does not read
Two listing options printed one list, and --list-platforms, --list-targets and --list-emulators printed the same output with --system, --region or --core as without, code 0. A run now prints one list, and an option a listing ignores is refused.
---
install.ps1 | 2 +-
install.py | 25 +++++++++++++++++++-
install.sh | 2 +-
install/launchers/index.json | 16 ++++++-------
tests/test_install.py | 44 +++++++++++++++++++++++++++++++++++
tests/test_install_offline.py | 7 +++++-
wiki/installer.md | 10 ++++----
7 files changed, 89 insertions(+), 17 deletions(-)
diff --git a/install.ps1 b/install.ps1
index 57aca4f16..dab7b3426 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610"
+ $defaultInstallSha256 = "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index baa21de99..429dffa35 100644
--- a/install.py
+++ b/install.py
@@ -13429,6 +13429,29 @@ def main() -> None:
if (args.list_platforms or args.list_targets or args.list_systems
or args.list_cores or args.list_emulators):
parser.error("--for-games narrows an install, not a listing")
+ # Applied or refused, never ignored: a run prints one list, and the
+ # narrowing options apply to --list-systems and --list-cores only, past
+ # --target and --installed-cores, which --list-emulators also reads.
+ listings = [flag for flag, given in (
+ ("--list-platforms", args.list_platforms), ("--list-targets", args.list_targets),
+ ("--list-systems", args.list_systems), ("--list-cores", args.list_cores),
+ ("--list-emulators", args.list_emulators)) if given]
+ if len(listings) > 1:
+ parser.error(f"{listings[0]} and {listings[1]} each print a list: run them "
+ "one at a time")
+ if listings and listings[0] in ("--list-platforms", "--list-targets",
+ "--list-emulators"):
+ unread = (("--system", args.system), ("--core", args.core),
+ ("--region", args.region), ("--emulator", args.emulator))
+ if listings[0] != "--list-emulators":
+ unread += (("--target", args.target), ("--every-board", args.every_board),
+ ("--installed-cores", args.installed_cores))
+ if listings[0] == "--list-platforms":
+ unread += (("--platform", args.platform),)
+ given = next((flag for flag, value in unread if value), "")
+ if given:
+ parser.error(f"{listings[0]} prints the whole list, which {given} "
+ "does not narrow")
if args.declared_only:
# Applied or refused, never ignored.
for given, reason in (
@@ -15176,7 +15199,7 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
# --installed-cores is below: EmuDeck installed 3.2 GB and only then was
# steamos refused for RetroArch, with no summary of what had landed.
target_lists: dict[str, dict] = {}
- if args.target and not args.list_targets:
+ if args.target:
for plat_name, _bios_path in platforms:
targets = fetch_targets(plat_name)
if targets is None:
diff --git a/install.sh b/install.sh
index 4f1d02bbf..cbdaed395 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610"
+DEFAULT_INSTALL_SHA256="7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 6f8f8ff49..2be9a4f89 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1104874,
- "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
+ "size": 1106280,
+ "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1158501,
- "sha256": "0ecf443039c136286322a57b33f1374dd52de0b5f2a772fbae93c1f98c19b62d"
+ "size": 1159907,
+ "sha256": "6460af3bc1a9d27c7373b42cf45f19bf8619b8e55daac9892af9f57df21b258e"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1104874,
- "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
+ "size": 1106280,
+ "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1104874,
- "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610",
+ "size": 1106280,
+ "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
"executable": false
},
{
diff --git a/tests/test_install.py b/tests/test_install.py
index 7efea9660..658385670 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -4475,6 +4475,50 @@ def _install_run(env: dict, *argv: str, **kwargs) -> subprocess.CompletedProcess
)
+class AListingAppliesItsOptionsOrRefusesThem(unittest.TestCase):
+ """--list-systems --list-cores printed the systems alone, and
+ --list-platforms, --list-targets and --list-emulators printed the same
+ list with --system, --region or --core as without, code 0."""
+
+ def test_two_listings_or_an_option_a_listing_ignores_are_refused(self):
+ env = dict(os.environ, RETROBIOS_OS="linux")
+ given = ["--platform", "retroarch", "--offline", "--no-input",
+ "--manifest", "install/retroarch.json"]
+ for argv, words in (
+ ([*given, "--list-systems", "--list-cores"],
+ "--list-systems and --list-cores each print a list"),
+ ([*given, "--list-cores", "--list-emulators"],
+ "--list-cores and --list-emulators each print a list"),
+ (["--list-platforms", "--list-systems", "--platform", "retroarch"],
+ "--list-platforms and --list-systems each print a list"),
+ (["--list-platforms", "--region", "us"],
+ "--list-platforms prints the whole list, which --region does not narrow"),
+ (["--list-platforms", "--platform", "retroarch"],
+ "--list-platforms prints the whole list, which --platform does not narrow"),
+ ([*given, "--list-targets", "--system", "sony-playstation"],
+ "--list-targets prints the whole list, which --system does not narrow"),
+ ([*given, "--list-targets", "--target", "switch"],
+ "--list-targets prints the whole list, which --target does not narrow"),
+ ([*given, "--list-emulators", "--system", "sony-playstation"],
+ "--list-emulators prints the whole list, which --system does not narrow"),
+ ([*given, "--list-emulators", "--core", "beetle_psx"],
+ "--list-emulators prints the whole list, which --core does not narrow"),
+ ):
+ with self.subTest(argv=argv):
+ proc = _install_run(env, *argv)
+ self.assertEqual(proc.returncode, 2, proc.stdout + proc.stderr)
+ self.assertIn(words, proc.stderr)
+
+ def test_the_options_a_listing_reads_still_apply(self):
+ env = dict(os.environ, RETROBIOS_OS="linux")
+ given = ["--platform", "retroarch", "--offline", "--no-input",
+ "--manifest", "install/retroarch.json"]
+ whole = _install_run(env, *given, "--list-cores")
+ narrowed = _install_run(env, *given, "--list-cores", "--system", "nintendo-gba")
+ self.assertEqual((whole.returncode, narrowed.returncode), (0, 0), narrowed.stderr)
+ self.assertLess(len(narrowed.stdout), len(whole.stdout))
+
+
class AMissingPackNamesTheOptionAndThePacksBeside(unittest.TestCase):
"""A typo in --from-pack said "Error: X does not exist": not the option,
not the pack sitting next to the name typed."""
diff --git a/tests/test_install_offline.py b/tests/test_install_offline.py
index b46ea29be..08d9194d2 100644
--- a/tests/test_install_offline.py
+++ b/tests/test_install_offline.py
@@ -778,7 +778,12 @@ class OfflineMakesNoRequest(Scratch):
self.assertIn("--offline", proc.stderr)
def test_a_listing_and_a_pack_need_no_network_anyway(self):
- proc = self.run_installer("--offline", "--list-platforms")
+ # --platform alone with it is refused: the listing names every one.
+ proc = subprocess.run(
+ [sys.executable, str(REPO_ROOT / "install.py"), "--offline", "--list-platforms"],
+ env=_offline_env(), capture_output=True, text=True, timeout=120,
+ check=False, stdin=subprocess.DEVNULL,
+ )
self.assertEqual(proc.returncode, 0, proc.stderr)
diff --git a/wiki/installer.md b/wiki/installer.md
index 88da4c7b0..f66a8eb54 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -976,9 +976,9 @@ what the options name, everything by default.
| `--required-only` | With `--for-games`, only the files the games cannot start without |
| `--no-game-data` | Leave out game data (a game's own files, not firmware) and install the firmware only. What it leaves out is named. See [Firmware without game data](#firmware-without-game-data) |
| `--declared-only` | Keep only the files the platform's own list names (`cores: null` in the manifest), not the extra files cores load. With `--check`, the answer is about the list the platform itself checks. Refused with `--core`, the listings it does not change, `--standalone-copies` and `--tui` |
-| `--list-systems` | Print a platform's systems with the files and size each holds, the files other systems share too counted apart |
-| `--list-cores` | Print the cores whose extra files a platform installs |
-| `--list-emulators` | Print every name `--emulator` accepts, each buildbot name beside the emulator it stands for |
+| `--list-systems` | Print a platform's systems with the files and size each holds, the files other systems share too counted apart. `--system`, `--core`, `--region`, `--target` and `--installed-cores` narrow it, as they narrow an install. A run prints one list: two listing options are refused |
+| `--list-cores` | Print the cores whose extra files a platform installs. The options that narrow `--list-systems` narrow it too |
+| `--list-emulators` | Print every name `--emulator` accepts, each buildbot name beside the emulator it stands for. `--target` and `--installed-cores` narrow it, and `--system`, `--core`, `--region` and `--emulator` are refused |
| `--romm-firmware TEMPLATE` | RomM: where each platform's firmware goes in the library, as `filesystem.structure.firmware` in RomM's `config.yml` says (`{platform}/bios` for a library laid out as `{platform}/roms`). Read from `config.yml` beside the library when it is there. See [RomM firmware layout](#romm-firmware-layout) |
| `--no-input` | Never ask a question, even at a terminal. A run whose output goes to a file or a pipe asks nothing either, and says so on stderr. It finds the setups and the mounted cards the screen finds: one is taken, as Enter takes it, two stop the run with an `error` event (`stage` `detect`, `reason` `conflict`) naming each with its `--platform` and `--dest`, and none stops it too, with `reason` `not_found` when a file list or a pack names the platform |
| `--check` | Report and exit without writing |
@@ -994,8 +994,8 @@ what the options name, everything by default.
| `--tui` | Open the full-screen interface, or stop with the reason it cannot open here (code 2) instead of falling back to the questions. Wins over `RETROBIOS_PLAIN` and `ACCESSIBLE`. See [The full-screen interface](#the-full-screen-interface) |
| `--plain` | Ask the questions line by line instead of the full-screen interface, the mode for a screen reader. See [The full-screen interface](#the-full-screen-interface) |
| `--version` | Print the installer's identity, the first 12 hex digits of the SHA-256 the bootstraps pin |
-| `--list-platforms` | Print the supported platforms and what was detected here |
-| `--list-targets` | Print the hardware targets a platform publishes, with the core count each carries |
+| `--list-platforms` | Print the supported platforms and what was detected here. An option that narrows a list (`--platform`, `--system`, `--core`, `--region`, `--emulator`, `--target`, `--every-board`, `--installed-cores`) is refused |
+| `--list-targets` | Print the hardware targets a platform publishes, with the core count each carries. `--system`, `--core`, `--region`, `--emulator`, `--target`, `--every-board` and `--installed-cores` are refused |
| `--jobs N`, `-j N` | Parallel downloads, 1 to 32, default 8 |
| `--verbose`, `-v` | Print per-attempt failures and hash mismatches |
| `--standalone-copies` | Also copy into detected standalone emulator directories |
From a0ecca002448268fdd9a3810489345b953cffaa3 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:33:16 +0100
Subject: [PATCH 38/83] fix: collect abbreviated prose citations
A location written without its file, (:507), reads in the file named last in the scalar, either cited or named as 'path:' before a list. A dotless file cited with its directory (tools/errorgen:20) is a citation too. devilutionx, corsixth, starship, plastic, eden-nightly, theforceengine, lightspark and higan_sfc gain 33 citations that bump and realign now follow. Two read that way pointed at another file and now name theirs: devilutionx assets.cpp:511-518, corsixth app.lua:1591.
---
emulators/corsixth.yml | 2 +-
emulators/devilutionx.yml | 2 +-
scripts/sourceref.py | 126 ++++++++++++++++++++++++++-----------
tests/test_profile_sync.py | 33 ++++++++++
4 files changed, 123 insertions(+), 40 deletions(-)
diff --git a/emulators/corsixth.yml b/emulators/corsixth.yml
index 019755a9d..dc366dd4f 100644
--- a/emulators/corsixth.yml
+++ b/emulators/corsixth.yml
@@ -54,7 +54,7 @@ notes: |
upper-case names the DOS release ships and the lookup normalises to.
The sound/music path uses the game's XMI tracks when a SoundFont is
- available (App:findSoundFont at :1591 probes GeneralUser-GS.sf2,
+ available (App:findSoundFont at CorsixTH/Lua/app.lua:1591 probes GeneralUser-GS.sf2,
FluidR3_GM.sf2, FluidR3.sf3 and three Linux system paths), and the
SoundFont is a user preference, not game data.
diff --git a/emulators/devilutionx.yml b/emulators/devilutionx.yml
index 0c7dfcb13..97825919c 100644
--- a/emulators/devilutionx.yml
+++ b/emulators/devilutionx.yml
@@ -54,7 +54,7 @@ notes: |
the mods/hf file list under the BUILD_MOD_MPQS option
(CMake/Mods.cmake:11-36, 61-71). The compiled
binary expects devilutionx.mpq next to the executable on every
- platform except Android, Apple and 3DS/Switch (:511-518), where its
+ platform except Android, Apple and 3DS/Switch (Source/engine/assets.cpp:511-518), where its
contents are shipped loose. After loading the core archives the engine
reads the asset ASSETS_VERSION and aborts with "Failed to load UI
resources" unless its content is "1\n" (Source/init.cpp:54, 79-85,
diff --git a/scripts/sourceref.py b/scripts/sourceref.py
index c0bf3fcd1..ec980b6e2 100644
--- a/scripts/sourceref.py
+++ b/scripts/sourceref.py
@@ -220,10 +220,21 @@ PROSE_EXTENSIONLESS = (
"COPYING",
"CHANGELOG",
)
-PROSE_CITE_RE = re.compile(
+# Any other dotless file is cited with its directory, which a constant or a
+# hex address never carries: lightspark's tools/errorgen:20.
+_PROSE_PATH = (
r"(?P[A-Za-z0-9_][\w./+-]*\.[A-Za-z]\w*"
- r"|(?:[\w./+-]*/)?(?:" + "|".join(PROSE_EXTENSIONLESS) + r"))"
- r":(?P\d+(?:-\d+)?)"
+ r"|(?:[\w./+-]*/)?(?:" + "|".join(PROSE_EXTENSIONLESS) + r")"
+ r"|(?:[\w.+-]+/)+[A-Za-z_][\w+-]*)"
+)
+PROSE_CITE_RE = re.compile(_PROSE_PATH + r":(?P\d+(?:-\d+)?)")
+# A file named before its locations, `Source/engine/assets.cpp:` then a
+# list, and a location that leaves the file out, `(:507)`, which reads in
+# the file named last: devilutionx, corsixth and starship cite their load
+# order this way. Neither was collected, so no bump or guard followed them.
+_PROSE_FILE_NAMED_RE = re.compile(_PROSE_PATH + r":(?=\s|$)")
+_PROSE_ABBREVIATED_RE = re.compile(
+ r"(?:(?<=[(\s])|^):(?P\d+(?:-\d+)?)(?![\w:-])(?!\.\d)"
)
PROSE_LIST_ITEM_RE = re.compile(r"\d+[.)](?:\s|$)")
PROSE_WRAPPED_RANGE_RE = re.compile(r":\d+(?:-\d+)?(?:[,)\s]|$)")
@@ -344,6 +355,12 @@ def _prose_runs(
joined line, so a writer can put each span back on its own line.
"""
lines = text.splitlines()
+ # The file an abbreviated location reads in, and the role it was named
+ # under, carried from line to line within the scalar.
+ named: tuple[str, str] | None = None
+ # Where the run wrapped from the line before ends in this one: its
+ # ranges are that run's, not abbreviated locations of their own.
+ carried = 0
for number, own in enumerate(lines):
# A literal block keeps its line breaks, so a citation wrapped after
# `file:` or after a range's comma lost the ranges on the next line
@@ -369,46 +386,35 @@ def _prose_runs(
elif following and line.endswith(","):
joined_at = len(line) + 1
line += " " + following
- consumed = 0
- for match in PROSE_CITE_RE.finditer(line):
+ consumed, carried = carried, 0
+ events = sorted(
+ [(m.start(), 0, m) for m in PROSE_CITE_RE.finditer(line)]
+ + [(m.start(), 1, m) for m in _PROSE_FILE_NAMED_RE.finditer(line)]
+ + [(m.start(), 2, m) for m in _PROSE_ABBREVIATED_RE.finditer(line)],
+ key=lambda event: (event[0], event[1]),
+ )
+ for _start, kind, match in events:
if match.start() >= boundary:
break
if match.start() < consumed:
continue
- token_start = max(line.rfind(" ", 0, match.start()),
- line.rfind("\t", 0, match.start())) + 1
- token = line[token_start:].split()[0] if line[token_start:] else ""
- if "://" in token:
+ if kind == 1:
+ if "://" not in line[max(0, match.start() - 3):match.end()]:
+ named = (match.group("path"), "")
continue
- path = match.group("path")
- path_start = match.start("path")
- # A dotfile citation opens its token with the dot: `.gitlab-ci.yml`
- # after a delimiter is the filename, while the dot of `boot.cfg`
- # inside a word belongs to the word before it.
- if (
- path_start > 0
- and line[path_start - 1] == "."
- and (path_start == 1 or line[path_start - 2] in " \t(")
- ):
- path_start -= 1
- path = "." + path
- # A path opening its line reads its role or project word at the
- # end of the line before: genesis_plus_gx_expanded wrapped
- # `(Batocera` and `package/batocera/...mk:7` one line apart.
- lead = line[:path_start]
- if number and not lead.strip():
- lead = lines[number - 1].rstrip() + " "
- role = _prose_role(lead, len(lead))
- if not role and _prose_external(lead, len(lead), known):
- # Kept with its project word, the source_ref convention: the
- # report looks for the project inside the declared trees
- # (mupen64plus-ae vendors `rice Config.cpp`) and calls the
- # citation EXTERNAL only when none carries it.
- before = lead.rstrip()
- word = before[max(before.rfind(" "), before.rfind("\t"),
- before.rfind("(")) + 1:]
- path = f"{word} {path}"
- path_span = (path_start, match.end("path"))
+ if kind == 2:
+ if named is None:
+ continue
+ path, role = named
+ path_start = match.start()
+ path_span = (path_start, path_start)
+ else:
+ path, role, path_start, path_span = _prose_path(
+ line, lines, number, match, known
+ )
+ if path is None:
+ continue
+ named = (path, role)
spans = [(match.start("range"), match.end("range"))]
end = match.end()
while True:
@@ -429,6 +435,9 @@ def _prose_runs(
spans.append((cont.start("range"), cont.end("range")))
end = cont.end()
consumed = end
+ if end > boundary:
+ indent = len(lines[number + 1]) - len(lines[number + 1].lstrip())
+ carried = indent + end - joined_at
parts = []
for lo, hi in spans:
rng = line[lo:hi]
@@ -438,3 +447,44 @@ def _prose_runs(
number, path_span, tuple(spans), tuple(parts),
line[path_start:end], joined_at if end > boundary else 0,
)
+
+
+def _prose_path(
+ line: str, lines: list[str], number: int, match: re.Match,
+ known: frozenset[str] | set[str],
+) -> tuple[str | None, str, int, tuple[int, int]]:
+ """(path, role, start, span) of one written citation, None for a URL."""
+ token_start = max(line.rfind(" ", 0, match.start()),
+ line.rfind("\t", 0, match.start())) + 1
+ token = line[token_start:].split()[0] if line[token_start:] else ""
+ if "://" in token:
+ return None, "", 0, (0, 0)
+ path = match.group("path")
+ path_start = match.start("path")
+ # A dotfile citation opens its token with the dot: `.gitlab-ci.yml`
+ # after a delimiter is the filename, while the dot of `boot.cfg`
+ # inside a word belongs to the word before it.
+ if (
+ path_start > 0
+ and line[path_start - 1] == "."
+ and (path_start == 1 or line[path_start - 2] in " \t(")
+ ):
+ path_start -= 1
+ path = "." + path
+ # A path opening its line reads its role or project word at the
+ # end of the line before: genesis_plus_gx_expanded wrapped
+ # `(Batocera` and `package/batocera/...mk:7` one line apart.
+ lead = line[:path_start]
+ if number and not lead.strip():
+ lead = lines[number - 1].rstrip() + " "
+ role = _prose_role(lead, len(lead))
+ if not role and _prose_external(lead, len(lead), known):
+ # Kept with its project word, the source_ref convention: the
+ # report looks for the project inside the declared trees
+ # (mupen64plus-ae vendors `rice Config.cpp`) and calls the
+ # citation EXTERNAL only when none carries it.
+ before = lead.rstrip()
+ word = before[max(before.rfind(" "), before.rfind("\t"),
+ before.rfind("(")) + 1:]
+ path = f"{word} {path}"
+ return path, role, path_start, (path_start, match.end("path"))
diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py
index 2521591b2..8bee4ba3d 100644
--- a/tests/test_profile_sync.py
+++ b/tests/test_profile_sync.py
@@ -5919,6 +5919,39 @@ class ARoleIsReadPerPart(unittest.TestCase):
("src/a.cpp", "source"), ("src/a.cpp", "source"), ("b.c", "upstream"),
])
+ def test_an_abbreviated_location_reads_in_the_file_named_last(self):
+ """devilutionx writes `Source/engine/assets.cpp:` then `(:507)` for
+ each loader, and its pin moved under five uncollected numbers."""
+ from sourceref import _prose_runs
+
+ text = (
+ "Load order is defined in Source/engine/assets.cpp:\n"
+ " LoadCoreArchives() (:507) - devilutionx.mpq, fonts.mpq\n"
+ " LoadLanguageArchive() (:523) - .mpq\n"
+ "Startup (src/port/Engine.cpp:65-127) loads sf64.o2r (:72, :88-89),\n"
+ "falls back at :90-106. Wrapped (code/q_shared.h\n"
+ ":44,65) and lightspark's (tools/errorgen:20).\n"
+ )
+ cited = [
+ (p.path, p.start, p.end) for run in _prose_runs(text) for p in run[3]
+ ]
+ self.assertEqual(cited, [
+ ("Source/engine/assets.cpp", 507, 507),
+ ("Source/engine/assets.cpp", 523, 523),
+ ("src/port/Engine.cpp", 65, 127),
+ ("src/port/Engine.cpp", 72, 72),
+ ("src/port/Engine.cpp", 88, 89),
+ ("src/port/Engine.cpp", 90, 106),
+ ("code/q_shared.h", 44, 44),
+ ("code/q_shared.h", 65, 65),
+ ("tools/errorgen", 20, 20),
+ ])
+
+ def test_an_abbreviated_location_needs_a_file_before_it(self):
+ from sourceref import _prose_runs
+
+ self.assertEqual(list(_prose_runs("read at boot (:507), devilutionx.mpq")), [])
+
class TheTriageCountsWhatBlocksThePin(unittest.TestCase):
"""Prose written under an older pin refuses the recale and the bump, yet
From 4377cbb2af0d3159202761214305b3d79ffaca13 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:36:42 +0100
Subject: [PATCH 39/83] fix: another tree's casing does not hold a file
dosbox-x's et4000.bin matched only pcem's et4000.BIN. resolve_local_file, asked as dosbox-x, refuses another emulator's tree in its case-insensitive step, so the pack and installer leave it out, while the gap report and verify's core files resolved without the asker and counted it held. Both now resolve as the profile, and the manifests of Batocera and KNULLI no longer flag it held.
---
install/batocera.json | 3 +-
install/knulli.json | 3 +-
scripts/cross_reference.py | 26 ++++++++++++++---
scripts/generate_site.py | 6 ++--
scripts/verify.py | 15 ++++++----
tests/test_foreign_tree_names.py | 48 ++++++++++++++++++++++++++++++++
6 files changed, 85 insertions(+), 16 deletions(-)
diff --git a/install/batocera.json b/install/batocera.json
index 8c24297c0..114a811ab 100644
--- a/install/batocera.json
+++ b/install/batocera.json
@@ -1841,8 +1841,7 @@
"reason": "not_found",
"cores": [
"dosbox-x"
- ],
- "held": true
+ ]
},
{
"dest": "extras.wad",
diff --git a/install/knulli.json b/install/knulli.json
index 25b3ccce4..f06163712 100644
--- a/install/knulli.json
+++ b/install/knulli.json
@@ -1598,8 +1598,7 @@
"reason": "not_found",
"cores": [
"dosbox-x"
- ],
- "held": true
+ ]
},
{
"dest": "extras.wad",
diff --git a/scripts/cross_reference.py b/scripts/cross_reference.py
index 71ac29ed9..08e1b74be 100644
--- a/scripts/cross_reference.py
+++ b/scripts/cross_reference.py
@@ -26,7 +26,9 @@ sys.path.insert(0, os.path.dirname(__file__))
from common import (
platform_arg,
ProfileSelectionError,
+ _foreign_tree,
_norm_system_id,
+ _owner_tokens,
archive_entry,
directory_members,
expand_directory_entries,
@@ -215,8 +217,14 @@ def _resolve_source(
none of the hashes the entry declares: a name never wins over a declared
hash, and zquestclassic's ending.mid read as held because Hydra Castle
Labyrinth has another file of that name.
+
+ Another casing of the name in another emulator's tree proves nothing, as
+ in resolve_local_file's case-insensitive step: dosbox-x's et4000.bin read
+ as held through pcem's et4000.BIN, which the pack and the installer
+ refuse it.
"""
declared = _declared_content(file_entry or {})
+ owners = _owner_tokens(file_entry or {})
def _can_be(sha1s: list | str) -> bool:
if not file_entry or db_files is None:
@@ -233,6 +241,14 @@ def _resolve_source(
"""Whether the files indexed under *name* can be this entry."""
return _can_be(by_name.get(name) or [])
+ def _folded_hit(name: str) -> bool:
+ """_name_hit for a name matched in another casing."""
+ return _can_be([
+ sha1 for sha1 in by_name.get(name) or []
+ if db_files is None
+ or not _foreign_tree(db_files.get(sha1, {}).get("path", ""), owners)
+ ])
+
# bios/ via database.json by_name
if fname in by_name and _name_hit(fname):
return "bios"
@@ -241,10 +257,10 @@ def _resolve_source(
if basename and basename in by_name and _name_hit(basename):
return "bios"
key = fname.lower()
- if key in by_name_lower and _name_hit(by_name_lower[key]):
+ if key in by_name_lower and _folded_hit(by_name_lower[key]):
return "bios"
if basename:
- if basename.lower() in by_name_lower and _name_hit(
+ if basename.lower() in by_name_lower and _folded_hit(
by_name_lower[basename.lower()]
):
return "bios"
@@ -257,7 +273,7 @@ def _resolve_source(
if canonical and canonical != fname:
if canonical in by_name and _name_hit(canonical):
return "bios"
- if canonical.lower() in by_name_lower and _name_hit(
+ if canonical.lower() in by_name_lower and _folded_hit(
by_name_lower[canonical.lower()]
):
return "bios"
@@ -901,7 +917,9 @@ def _cross_reference_profile(
source = next(
(
found for version in versions[slot]
- if (found := entry_source(version, index)) is not None
+ if (found := entry_source(
+ {**version, "source_profile": emu_name}, index,
+ )) is not None
),
"missing",
)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 32f926da0..4e206261e 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -9416,7 +9416,7 @@ def _hash_spans(value: str | list, copy: bool = False) -> str:
def _availability_check(
- db: dict, data_names: set[str] | None
+ db: dict, data_names: set[str] | None, owner: str = "",
) -> Callable[[dict], bool]:
"""A predicate answering whether the collection holds a file.
@@ -9447,7 +9447,7 @@ def _availability_check(
# under the name belongs to another game or release.
if not f.get("name") or f.get("unsourceable"):
return False
- return entry_source(f, index) is not None
+ return entry_source({**f, "source_profile": owner} if owner else f, index) is not None
return _file_available
@@ -10180,7 +10180,7 @@ def emulator_pages(
lines.append("")
lines.extend(markup.aside("info", "Why no files", [_escape_tags(str(exclusion))])[:-1])
else:
- _file_available = _availability_check(db, data_names)
+ _file_available = _availability_check(db, data_names, name)
lines.extend(["## Files", ""])
lines.extend(_emulator_file_summary(files))
diff --git a/scripts/verify.py b/scripts/verify.py
index 8689a4dcf..b465ab4bc 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -667,13 +667,18 @@ def find_undeclared_files(
# Resolution: name, then path basename
# storage: release names where the bytes are served from, not
# that the collection holds them: resolved like any file.
+ # Resolved as the asker, as the builder's ExtraResolver does:
+ # another casing of the name in another emulator's tree is
+ # not this emulator's file (dosbox-x's et4000.bin and pcem's
+ # et4000.BIN).
+ owned = {**f, "source_profile": emu_name}
if shipped_on_mismatch and (f.get("md5") or f.get("sha1")):
# The entry states what its content should be and the builder
# drops a copy that contradicts it, so content decides here
# too. A name match would not do: generic names collide across
# systems, and answering yes on one describes a pack that will
# not contain the file.
- _lp, _st = resolve_local_file(f, db, dest_hint=dest)
+ _lp, _st = resolve_local_file(owned, db, dest_hint=dest)
in_repo = _lp is not None and _st != "hash_mismatch"
else:
in_repo = _name_in_index(
@@ -693,8 +698,8 @@ def find_undeclared_files(
# rejects them all. NanoBoyAdvance's 16 KB bios.bin met
# only PCem's and QEMU's PC BIOS images of that name.
# The fallback below then decides as for any mismatch.
- _lp, _st = resolve_local_file(f, db, dest_hint=dest)
- if _st == "hash_mismatch":
+ _lp, _st = resolve_local_file(owned, db, dest_hint=dest)
+ if _st == "hash_mismatch" or _lp is None:
in_repo = False
if not in_repo:
# Hash fallback: the repo may hold the content under a
@@ -707,7 +712,7 @@ def find_undeclared_files(
# frontend would reject it, the builder leaves it out, and
# calling it available here would describe a pack that
# does not contain it.
- _lp, _st = resolve_local_file(f, db, dest_hint=dest)
+ _lp, _st = resolve_local_file(owned, db, dest_hint=dest)
in_repo = _st != "not_found" and _lp is not None
if in_repo and _st == "hash_mismatch" and shipped_on_mismatch:
in_repo = False
@@ -717,7 +722,7 @@ def find_undeclared_files(
# held for it, the rule the builder's lookup applies
# (packextras.ExtraResolver). The Apple IIGS' 128 KB
# ROM is not Basilisk II's ROM.
- _lp, _st = resolve_local_file(f, db, dest_hint=dest)
+ _lp, _st = resolve_local_file(owned, db, dest_hint=dest)
if core_size_refusal(
f, _lp, same_slot_entries(profile.get("files"), fname, dest)
):
diff --git a/tests/test_foreign_tree_names.py b/tests/test_foreign_tree_names.py
index 2be75d71b..360060add 100644
--- a/tests/test_foreign_tree_names.py
+++ b/tests/test_foreign_tree_names.py
@@ -185,5 +185,53 @@ class RetailDashboardTree(unittest.TestCase):
self.assertEqual(status, "path_exact", path)
+class TheGapReportAsksAsTheEmulator(unittest.TestCase):
+ """dosbox-x's et4000.bin, no hash: pcem's et4000.BIN was its only
+ casing. The resolver, asked as dosbox-x, refuses it and the pack and the
+ installer leave the file out, while the gap report, verify's core files
+ and the manifest's held flag counted it available."""
+
+ _hold = ForeignTreeNames._hold
+
+ def setUp(self):
+ ForeignTreeNames.setUp(self)
+ self._hold("bios/Other/pcem/roms/et4000.BIN", b"E" * 64)
+ self.entry = {"name": "et4000.bin", "required": True}
+
+ def _source(self, owner: str) -> str | None:
+ from cross_reference import entry_source
+
+ by_name = self.db["indexes"]["by_name"]
+ index = {
+ "by_name": by_name, "by_name_lower": {k.lower(): k for k in by_name},
+ "by_path_suffix": {}, "by_md5": {}, "by_sha256": {}, "by_crc32": {},
+ "db_files": self.db["files"], "data_names": None,
+ }
+ return entry_source({**self.entry, "source_profile": owner}, index)
+
+ def test_another_tree_casing_is_not_held(self):
+ self.assertIsNone(self._source("dosbox-x"))
+ entry = {**self.entry, "source_profile": "dosbox-x"}
+ self.assertEqual(resolve_local_file(entry, self.db), (None, "not_found"))
+
+ def test_the_tree_owner_holds_it(self):
+ self.assertEqual(self._source("pcem"), "bios")
+
+ def test_core_files_follow_the_resolver(self):
+ from verify import find_undeclared_files
+
+ profiles = {"dosbox-x": {
+ "emulator": "DOSBox-X", "type": "libretro", "systems": ["dos"],
+ "files": [self.entry],
+ }}
+ config = {"platform": "P", "verification_mode": "md5", "cores": ["dosbox-x"],
+ "systems": {"dos": {"files": []}}}
+ (found,) = [
+ u for u in find_undeclared_files(config, "emulators", self.db, profiles)
+ if u["name"] == "et4000.bin"
+ ]
+ self.assertFalse(found["in_repo"])
+
+
if __name__ == "__main__":
unittest.main()
From 63fafaf0f9e02171a02e7a20f41cd0c760b69262 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:37:12 +0100
Subject: [PATCH 40/83] fix: read teknoparrot and simple64 from mirrors
teknogods/TeknoParrotUI and simple64/simple64 answer 404 on the API and the web, and neither organisation lists them now. simple64's README at the pin archives the project for gopher64. Each profile declares upstream_gone and a fork that keeps its default branch at the analysed commit: thecrixux/TeknoParrotUI master is b75872ad, simple64-vault/simple64 main is d8c969c7. realign_prose reads a source declared gone through that mirror, which unblocks five teknoparrot notes citations that anchor unchanged.
---
emulators/simple64.yml | 2 ++
emulators/teknoparrot.yml | 2 ++
scripts/profile_sync.py | 24 ++++++++++++++++++++----
tests/test_profile_sync.py | 28 ++++++++++++++++++++++++++++
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/emulators/simple64.yml b/emulators/simple64.yml
index f09be5b1d..9df8dfdad 100644
--- a/emulators/simple64.yml
+++ b/emulators/simple64.yml
@@ -5,6 +5,8 @@ source: "https://github.com/simple64/simple64"
upstream: "https://github.com/simple64/simple64"
profiled_date: "2026-08-08"
source_commit: "d8c969c7b932e3d76e6a25549d76348839dbaefd"
+upstream_gone: "simple64/simple64 answers 404 on the API and the web, and the simple64 organisation lists no repository. The README at the pin archives the project in favour of gopher64. Observed 2026-11-06. simple64-vault/simple64 keeps main at the analysed commit."
+source_mirror: "https://github.com/simple64-vault/simple64"
core_version: "v2024.12.1-5-gd8c969c"
version_basis:
kind: tag
diff --git a/emulators/teknoparrot.yml b/emulators/teknoparrot.yml
index 59a2a4a5f..8b6ed2cf4 100644
--- a/emulators/teknoparrot.yml
+++ b/emulators/teknoparrot.yml
@@ -6,6 +6,8 @@ upstream: closed-source
author: "TeknoGods"
profiled_date: "2026-10-20"
source_commit: "b75872addc1d5cce81a62f4c1468eab59e2d3cbe"
+upstream_gone: "teknogods/TeknoParrotUI answers 404 on the API and the web, and the teknogods organisation no longer lists it. Observed 2026-11-06. thecrixux/TeknoParrotUI keeps master at the analysed commit."
+source_mirror: "https://github.com/thecrixux/TeknoParrotUI"
core_version: "TeknoParrotUI 7ffcdf1"
version_basis:
kind: unverified
diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py
index 76bfdb95a..9c4471dfd 100644
--- a/scripts/profile_sync.py
+++ b/scripts/profile_sync.py
@@ -3914,7 +3914,8 @@ def _realign_part(
def _writing_pairs(
- document: dict, repos: list, revisions: list[tuple[str, dict]], intro_sha: str
+ document: dict, repos: list, revisions: list[tuple[str, dict]], intro_sha: str,
+ served: dict | None = None,
) -> tuple[list[list], list[str]]:
"""Every reading of where the text was written, and the ambiguities.
@@ -3944,8 +3945,9 @@ def _writing_pairs(
ambiguous.append(f"{pin_field}_commit {' -> '.join(written)}")
# The current pin among the candidates reads as "no move" (None) for
# that repository, which the other candidates must then agree with.
+ reader = (served or {}).get(repo, repo)
options.append([
- (repo, pin, current) if pin != current else None for pin in written
+ (reader, pin, current) if pin != current else None for pin in written
])
readings = [
[pair for pair in combo if pair is not None]
@@ -4026,8 +4028,20 @@ def realign_prose(
]
if not repos:
return []
+ # A source declared gone is read through its mirror, which carries the
+ # same commits: teknoparrot's notes stayed blocked once
+ # teknogods/TeknoParrotUI answered 404, every reading of the old pin
+ # calling the files absent.
+ mirror = (
+ upstream.parse_repo(str(document.get("source_mirror") or ""))
+ if document.get("upstream_gone") else None
+ )
+ served = {
+ repo: mirror for field, _mode, repo in repos
+ if mirror is not None and field == "source"
+ }
pinned = [
- (repo, pin)
+ (served.get(repo, repo), pin)
for field, mode, repo in repos
if (pin := _pin_of(document, f"{field}_commit", mode))
]
@@ -4107,7 +4121,9 @@ def realign_prose(
if intro_sha is None:
# The scalar is not committed yet: written now, under this pin.
continue
- readings, ambiguous = _writing_pairs(document, repos, revisions, intro_sha)
+ readings, ambiguous = _writing_pairs(
+ document, repos, revisions, intro_sha, served
+ )
if not any(readings):
continue
moves, blocked = _realign_citation(
diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py
index 8bee4ba3d..9a0fb5241 100644
--- a/tests/test_profile_sync.py
+++ b/tests/test_profile_sync.py
@@ -4784,6 +4784,34 @@ class TestRealignProse(unittest.TestCase):
self.assertTrue(flagged, messages)
self.assertFalse([m for m in messages if "b.c:" in m], messages)
+ def test_a_source_declared_gone_is_read_through_its_mirror(self):
+ """teknogods/TeknoParrotUI answers 404. Read there, every citation
+ written under the old pin was absent and blocked the profile."""
+ self._repo_with_advanced_pin()
+ self._commit(
+ PROSE_SAMPLE.replace(
+ 'source_commit: "pin"\n',
+ 'source_commit: "pin"\n'
+ 'upstream_gone: "o/n answers 404."\n'
+ 'source_mirror: "https://github.com/m/n"\n',
+ ),
+ "advance the pin, declare the forge gone",
+ )
+ self.files[("oldpin", "a.c")] = ["x"] * 9 + ["subject"]
+ self.files[("pin", "a.c")] = ["x"] * 13 + ["subject"]
+ self.files[("oldpin", "b.c")] = list("pqrstuvwx")
+ self.files[("pin", "b.c")] = list("pqrstuvwx")
+ served = profile_sync.upstream.fetch_file
+ profile_sync.upstream.fetch_file = (
+ lambda repo, sha, path, cache_dir, offline=False: (
+ served(repo, sha, path, cache_dir, offline)
+ if repo.slug == "m/n" else None
+ )
+ )
+ messages = profile_sync.realign_prose(self.path, self.tmp.name, dry_run=True)
+ # b.c did not move between the two pins: nothing to read again.
+ self.assertFalse([m for m in messages if "b.c:" in m], messages)
+
def test_a_citation_in_an_unmoved_upstream_needs_no_reading(self):
"""nethersx2 cites AetherSX2 files that only its upstream carries,
at an upstream pin that never moved. The port's pin did move under
From 328bfbe53b505a5227a71afc574805f6e629b09d Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:37:16 +0100
Subject: [PATCH 41/83] chore: run the catalog row test from its file
The class sat after unittest.main(), so running test_doc_pages.py on its
own skipped it.
---
tests/test_doc_pages.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tests/test_doc_pages.py b/tests/test_doc_pages.py
index bb0d0d3eb..5e6eb2c96 100644
--- a/tests/test_doc_pages.py
+++ b/tests/test_doc_pages.py
@@ -1984,9 +1984,6 @@ class ArchivedIsWhatTheToolsDo(unittest.TestCase):
self.assertNotIn("list_platforms", workflow.read_text(encoding="utf-8"))
-if __name__ == "__main__":
- unittest.main()
-
class TheCatalogRowsStateFacts(unittest.TestCase):
"""tools.md said "redump.org serves stale DATs" and "Dat-o-Matic blocks
@@ -2003,3 +2000,8 @@ class TheCatalogRowsStateFacts(unittest.TestCase):
scraper = (ROOT / "scripts" / "scraper" / "redump_dat_scraper.py").read_text(encoding="utf-8")
self.assertIn("/bios/", scraper)
self.assertIn("`/bios/`", rows[0])
+
+
+if __name__ == "__main__":
+ unittest.main()
+
From 23d878c52673eb9080320b2596117cca0919cd82 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:37:19 +0100
Subject: [PATCH 42/83] chore: stub the export cache check in a test
test_a_targeted_export_reads_a_full_model runs pipeline.py --offline
--with-export, which is now refused when .cache/upstream-native/ is
empty, as in any fresh checkout. The test is about the truth directory
the export reads.
---
tests/test_audit_regressions.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 5263d0c54..6776263b8 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -1140,9 +1140,12 @@ class PipelineRegressions(unittest.TestCase):
argv = ["pipeline.py", "--offline", "--skip-packs", "--skip-docs",
"--with-export", "--target", "switch"]
+ # The originals the offline export patches are not cached in a
+ # checkout: the run would be refused before any step.
with mock.patch.object(sys, "argv", argv), mock.patch.object(
pipeline, "run", side_effect=fake_run
- ), contextlib.redirect_stdout(io.StringIO()), contextlib.suppress(SystemExit):
+ ), mock.patch.object(pipeline, "_refuse_offline_export_without_originals"), \
+ contextlib.redirect_stdout(io.StringIO()), contextlib.suppress(SystemExit):
pipeline.main()
truth_runs = [c for c in commands if "scripts/generate_truth.py" in c]
export = next(c for c in commands if "scripts/export_native.py" in c)
From 420162c79b78ae698f25d0d6cd9aea47bb07ff4b Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:37:36 +0100
Subject: [PATCH 43/83] fix: rank uncheckable profiles first in triage
--strict fails on a profile no declared repository answers for, yet --triage scored it 0 under the clean profiles and left it out of the count to review. It now weighs as a pin to set again and is counted.
---
scripts/profile_sync.py | 5 ++++-
tests/test_profile_sync.py | 19 +++++++++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py
index 9c4471dfd..5a90476ae 100644
--- a/scripts/profile_sync.py
+++ b/scripts/profile_sync.py
@@ -2665,6 +2665,9 @@ def drift_score(
# set again before any ref can be read, so each outranks a GONE ref:
# pcem ranked last at 0 with an orphaned upstream_commit.
score += PIN_WEIGHT * (len(report.orphaned) + len(report.moved_repos))
+ # A profile no repository answers for cannot be read at all, and
+ # --strict fails on it: it ranked at 0 under the clean profiles.
+ score += PIN_WEIGHT * report.uncheckable()
score += min(commits, 20) // 4
return score
@@ -5034,7 +5037,7 @@ def _print_triage(
state = triage_state(report)
if refused:
state += f", {refused}"
- pending += bool(report.needs_review())
+ pending += bool(report.needs_review() or report.uncheckable())
print(f"{score:5d} {report.name:30s} {state}")
print(f"{len(ranked)} profiles, {pending} with something to review")
diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py
index 9a0fb5241..95879c00a 100644
--- a/tests/test_profile_sync.py
+++ b/tests/test_profile_sync.py
@@ -6027,6 +6027,25 @@ class TheTriageCountsWhatBlocksThePin(unittest.TestCase):
self.assertEqual(lines[-1], "2 profiles, 1 with something to review")
self.assertEqual(len(err.getvalue().splitlines()), 1, err.getvalue())
+ def test_an_uncheckable_profile_ranks_first_and_counts(self):
+ """simple64 and teknoparrot answered 404 and --strict failed on them,
+ while the triage put them at 0 under the clean profiles."""
+ gone = ProfileReport(
+ name="gone", pin="p", skipped="no declared repository answers (o/n)",
+ )
+ reports = [self._report("clean", 1), gone]
+ selected = {r.name: {"source": "https://github.com/o/n"} for r in reports}
+ args = argparse.Namespace(cache_dir="unused", offline=True)
+ out = io.StringIO()
+ with mock.patch.object(profile_sync, "check_version", return_value=None), \
+ mock.patch.object(profile_sync.upstream, "commits_touching",
+ return_value=0), \
+ contextlib.redirect_stdout(out), contextlib.redirect_stderr(io.StringIO()):
+ profile_sync._print_triage(args, selected, reports)
+ lines = out.getvalue().splitlines()
+ self.assertIn("gone", lines[1])
+ self.assertEqual(lines[-1], "2 profiles, 1 with something to review")
+
class TestBranchProfiles(unittest.TestCase):
"""--changed and --added name the profiles a branch brings, not by hand."""
From 63be8cc3bccfbb9d2a5ac8d942cdfc29a4f76cf6 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:39:40 +0100
Subject: [PATCH 44/83] fix: find tab-indented batocera-systems entries
The entry pattern required four spaces of indent. EmuELEC indents 23 systems with one tab, so render appended each again whole and the published export carried 21 duplicated keys, the md5 fills only in the second copy. Any indent opens an entry now, and an entry written again keeps its own. The EmuELEC export is regenerated: one copy of each system, the amiga entry also gaining the eight WHDLoad Kickstarts the profiles added since 2026-10-22.
---
exports/emuelec.json | 98 +++++++++++++++++-
exports/emuelec/batocera-systems | 138 +++++++++++++-------------
scripts/exporter/batocera_exporter.py | 18 ++--
tests/test_exporters.py | 18 ++++
4 files changed, 191 insertions(+), 81 deletions(-)
diff --git a/exports/emuelec.json b/exports/emuelec.json
index 25e4cdf5f..36da198f3 100644
--- a/exports/emuelec.json
+++ b/exports/emuelec.json
@@ -6,14 +6,102 @@
"files": [
"batocera-systems"
],
- "summary": "590 kept, 39 files added, 47 hashes added to an existing entry",
+ "summary": "590 kept, 47 files added, 47 hashes added to an existing entry",
"counts": {
"kept": 590,
- "added": 39,
- "not_added": 1117,
+ "added": 47,
+ "not_added": 1712,
"not_kept": 0
},
"changes": [
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick33180.A500.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick33180.A500.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "c993feb1eeddec1d2e687aa514231028"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick34005.A500.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick34005.A500.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "7eb13d974af0992d672b67c317a7e0a1"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick37175.A500.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick37175.A500.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "e057054449b5e21591ce27d2eb9ac720"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick36143.A3000.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick36143.A3000.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "2a2652daba6be3ef1d0bdf5ddd4347c6"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick39106.A1200.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick39106.A1200.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "af8b2e2227f01a142e20c8ab463f14ed"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick40063.A600.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick40063.A600.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "3f97c1963d82c808ef29e7c984c4c688"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick40068.A1200.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick40068.A1200.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "547b42b7b070c7f227ea45e0986d57a1"
+ }
+ },
+ {
+ "kind": "added",
+ "system": "amiga",
+ "name": "kick40068.A4000.RTB",
+ "destination": "whdboot/save-data/Kickstarts/kick40068.A4000.RTB",
+ "field": null,
+ "old": null,
+ "new": {
+ "md5": "f89f19b858ea6b1a04327c6f71ee1600"
+ }
+ },
{
"kind": "added",
"system": "amiga",
@@ -922,7 +1010,8 @@
"hashes_cleared": [],
"requirements_corrected": 0,
"withheld": [],
- "found_by_content": 107,
+ "found_by_content": 312,
+ "unattributed": [],
"removal_candidates": [
{
"system": "colecovision",
@@ -4421,5 +4510,6 @@
"unresolved_cores": []
}
],
+ "doubled": [],
"invalid": []
}
diff --git a/exports/emuelec/batocera-systems b/exports/emuelec/batocera-systems
index 8d5bbb68f..06688a758 100755
--- a/exports/emuelec/batocera-systems
+++ b/exports/emuelec/batocera-systems
@@ -51,7 +51,25 @@ systems = {
{ "md5": "e40a5dfb3d017ba8779faba30cbd1c8e", "file": "bios/kick40063.A600" },
{ "md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/kick40068.A1200" },
{ "md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/kick40068.A4000" },
- { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom" } ] },
+ { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom" },
+ { "md5": "c993feb1eeddec1d2e687aa514231028", "file": "whdboot/save-data/Kickstarts/kick33180.A500.RTB" },
+ { "md5": "7eb13d974af0992d672b67c317a7e0a1", "file": "whdboot/save-data/Kickstarts/kick34005.A500.RTB" },
+ { "md5": "e057054449b5e21591ce27d2eb9ac720", "file": "whdboot/save-data/Kickstarts/kick37175.A500.RTB" },
+ { "md5": "2a2652daba6be3ef1d0bdf5ddd4347c6", "file": "whdboot/save-data/Kickstarts/kick36143.A3000.RTB" },
+ { "md5": "af8b2e2227f01a142e20c8ab463f14ed", "file": "whdboot/save-data/Kickstarts/kick39106.A1200.RTB" },
+ { "md5": "3f97c1963d82c808ef29e7c984c4c688", "file": "whdboot/save-data/Kickstarts/kick40063.A600.RTB" },
+ { "md5": "547b42b7b070c7f227ea45e0986d57a1", "file": "whdboot/save-data/Kickstarts/kick40068.A1200.RTB" },
+ { "md5": "f89f19b858ea6b1a04327c6f71ee1600", "file": "whdboot/save-data/Kickstarts/kick40068.A4000.RTB" },
+ { "md5": "6c5b44c1a2bcee664129f850bfe4ed8a", "file": "uae_data/drive_click_A500.wav" },
+ { "md5": "7401f854a75f9ede18769168ab896a2a", "file": "uae_data/drive_spin_A500.wav" },
+ { "md5": "f9d954879fee8e96baa93d6139077cdb", "file": "uae_data/drive_spinnd_A500.wav" },
+ { "md5": "aebeacc7e7bc52ef890785c835bec3d0", "file": "uae_data/drive_startup_A500.wav" },
+ { "md5": "1a4b2d6254918ff769f26beeede75655", "file": "uae_data/drive_snatch_A500.wav" },
+ { "md5": "b64bee23f356635f67fb08b543df9797", "file": "uae_data/drive_click_LOUD.wav" },
+ { "md5": "56d8e36a2f04b5e8c5a1f1530cfc886c", "file": "uae_data/drive_spin_LOUD.wav" },
+ { "md5": "43ab05c6d969cb40805970a5b2352875", "file": "uae_data/drive_spinnd_LOUD.wav" },
+ { "md5": "743b4b9f0ca645c4c2a34953b5e01e45", "file": "uae_data/drive_startup_LOUD.wav" },
+ { "md5": "40cdf89f35b68cfefd4df5fb0256e02f", "file": "uae_data/drive_snatch_LOUD.wav" } ] },
# ---------- Fujistu FM-Towns ---------- #
# https://github.com/captainys/TOWNSEMU
@@ -492,7 +510,9 @@ systems = {
# SNK
"neogeo": { "name": "NeoGeo", "biosFiles": [ { "md5": "", "file": "neogeo/neogeo.zip" } ] },
"neogeocd": { "name": "NeoGeo CD", "biosFiles": [ { "md5": "", "file": "neogeo/neogeo.zip" },
- { "md5": "f39572af7584cb5b3f70ae8cc848aba2", "file": "bios/neocd/neocd_z.rom"} ] },
+ { "md5": "f39572af7584cb5b3f70ae8cc848aba2", "file": "bios/neocd/neocd_z.rom"},
+ { "md5": "b31a246b69493c35194fe0bac120dc37", "file": "neocdz.zip"},
+ { "md5": "006a881532f2caffc3fe9fb5593f2ed5", "file": "neocd.zip"} ] },
# Sony Computer Entertainment
@@ -656,7 +676,7 @@ systems = {
{ "md5": "", "file": "ports/dinothawr/xbr-lv2-a.glslp" },
{ "md5": "", "file": "ports/dinothawr/xbr-lv2-pass1.glsl" } ] },
- "DOOM1": { "name": "DOOM1 (PrBoom)", "biosFiles": [ { "md5": "", "file": "ports/doom/doom1.wad" } ] },
+ "DOOM1": { "name": "DOOM1 (PrBoom)", "biosFiles": [ { "md5": "", "file": "ports/doom/doom1.wad" }, { "md5": "5772f907fdee4284f6332d89c0c5609c", "file": "gzdoom.pk3" }, { "md5": "094baa608b85fbe636933b4098e7e1f1", "file": "game_widescreen_gfx.pk3" } ] },
"DOOM2": { "name": "DOOM2 (PrBoom)", "biosFiles": [ { "md5": "", "file": "ports/doom2/doom2.wad" } ] },
@@ -749,59 +769,60 @@ systems = {
{ "md5": "", "file": "ports/opentyrian/newshi.shp" },
{ "md5": "", "file": "ports/opentyrian/shapes).dat" } ] },
- "Cannonball": { "name": "Cannonball", "biosFiles": [ { "md5": "", "file": "ports/cannonball/epr-10187.88" },
- { "md5": "", "file": "ports/cannonball/epr-10327.76" },
- { "md5": "", "file": "ports/cannonball/epr-10327a.76" },
- { "md5": "", "file": "ports/cannonball/epr-10328.75" },
- { "md5": "", "file": "ports/cannonball/epr-10328a.75" },
- { "md5": "", "file": "ports/cannonball/epr-10329.58" },
- { "md5": "", "file": "ports/cannonball/epr-10329a.58" },
- { "md5": "", "file": "ports/cannonball/epr-10330.57" },
- { "md5": "", "file": "ports/cannonball/epr-10330a.57" },
- { "md5": "", "file": "ports/cannonball/epr-10380.133" },
- { "md5": "", "file": "ports/cannonball/epr-10380b.133" },
- { "md5": "", "file": "ports/cannonball/epr-10381.132" },
- { "md5": "", "file": "ports/cannonball/epr-10381b.132" },
- { "md5": "", "file": "ports/cannonball/epr-10382.118" },
- { "md5": "", "file": "ports/cannonball/epr-10382b.118" },
- { "md5": "", "file": "ports/cannonball/epr-10383.117" },
- { "md5": "", "file": "ports/cannonball/epr-10383b.117" },
- { "md5": "", "file": "ports/cannonball/mpr-10371.9" },
- { "md5": "", "file": "ports/cannonball/mpr-10372.13" },
- { "md5": "", "file": "ports/cannonball/mpr-10373.10" },
- { "md5": "", "file": "ports/cannonball/mpr-10374.14" },
- { "md5": "", "file": "ports/cannonball/mpr-10375.11" },
- { "md5": "", "file": "ports/cannonball/mpr-10376.15" },
- { "md5": "", "file": "ports/cannonball/mpr-10377.12" },
- { "md5": "", "file": "ports/cannonball/mpr-10378.16" },
- { "md5": "", "file": "ports/cannonball/opr-10185.11" },
- { "md5": "", "file": "ports/cannonball/opr-10186.47" },
- { "md5": "", "file": "ports/cannonball/opr-10188.71" },
- { "md5": "", "file": "ports/cannonball/opr-10189.70" },
- { "md5": "", "file": "ports/cannonball/opr-10190.69" },
- { "md5": "", "file": "ports/cannonball/opr-10191.68" },
- { "md5": "", "file": "ports/cannonball/opr-10192.67" },
- { "md5": "", "file": "ports/cannonball/opr-10193.66" },
- { "md5": "", "file": "ports/cannonball/opr-10230.104" },
- { "md5": "", "file": "ports/cannonball/opr-10231.103" },
- { "md5": "", "file": "ports/cannonball/opr-10232.102" },
- { "md5": "", "file": "ports/cannonball/opr-10266.101" },
- { "md5": "", "file": "ports/cannonball/opr-10267.100" },
- { "md5": "", "file": "ports/cannonball/opr-10268.99" } ] },
+ "Cannonball": { "name": "Cannonball", "biosFiles": [ { "md5": "0cc087bbf1d5ad46319756b5b17ab9be", "file": "ports/cannonball/epr-10187.88" },
+ { "md5": "eddae6f176ad5a3438e4dae1b8c4d4fb", "file": "ports/cannonball/epr-10327.76" },
+ { "md5": "35bdcb3d8eaae6505af896a55f26dda1", "file": "ports/cannonball/epr-10327a.76" },
+ { "md5": "73486b2da791109e322c71cbaf51338b", "file": "ports/cannonball/epr-10328.75" },
+ { "md5": "5c82ed7dd7450f5c037b4dcaa0103218", "file": "ports/cannonball/epr-10328a.75" },
+ { "md5": "7197dfbdf83029abd56e72b98b274c63", "file": "ports/cannonball/epr-10329.58" },
+ { "md5": "f8729ace245eb8fc4854819f783f6042", "file": "ports/cannonball/epr-10329a.58" },
+ { "md5": "9556c737b5506241a5a58635e58bdbad", "file": "ports/cannonball/epr-10330.57" },
+ { "md5": "f0f9e2cce2d64dbb28650b11679f745b", "file": "ports/cannonball/epr-10330a.57" },
+ { "md5": "591daabf7c4b9005171f9af83068f3a1", "file": "ports/cannonball/epr-10380.133" },
+ { "md5": "94bb116334e7076aeeee5fcdcb536f87", "file": "ports/cannonball/epr-10380b.133" },
+ { "md5": "ab1a9fe4feb5d5bd867552e3740bdc07", "file": "ports/cannonball/epr-10381.132" },
+ { "md5": "ab1a9fe4feb5d5bd867552e3740bdc07", "file": "ports/cannonball/epr-10381b.132" },
+ { "md5": "bcf3cae054791aa0c2c9d3c144bb1682", "file": "ports/cannonball/epr-10382.118" },
+ { "md5": "8ff3212b3a2e37a37ba73a998bbc424f", "file": "ports/cannonball/epr-10382b.118" },
+ { "md5": "161ceb196fcc9825bc981f933f305b5e", "file": "ports/cannonball/epr-10383.117" },
+ { "md5": "2d2b6149f1bccaaebf9c792f292e36d0", "file": "ports/cannonball/epr-10383b.117" },
+ { "md5": "9bc7fcfda9dea3a6d1c527b3146a4a95", "file": "ports/cannonball/mpr-10371.9" },
+ { "md5": "7da2895e20d2152ebddbdd2df29f3bd4", "file": "ports/cannonball/mpr-10372.13" },
+ { "md5": "5ed55433e64a4daecb9a0dbfc8771131", "file": "ports/cannonball/mpr-10373.10" },
+ { "md5": "5d09103268ac520609fb10ba186374b1", "file": "ports/cannonball/mpr-10374.14" },
+ { "md5": "187a6496e67c95e119ce97600902d178", "file": "ports/cannonball/mpr-10375.11" },
+ { "md5": "107a513ce97fb3b88d97425f19054471", "file": "ports/cannonball/mpr-10376.15" },
+ { "md5": "4a41f5ad01d78f52e8b6187c971c7270", "file": "ports/cannonball/mpr-10377.12" },
+ { "md5": "f6b7defe9860aa8a2f2e2915f1d9b94d", "file": "ports/cannonball/mpr-10378.16" },
+ { "md5": "866f1a596cc943bc5a416ff3e63cc9b0", "file": "ports/cannonball/opr-10185.11" },
+ { "md5": "866f1a596cc943bc5a416ff3e63cc9b0", "file": "ports/cannonball/opr-10186.47" },
+ { "md5": "ce4c62deb59049edb9972a5214ab39a1", "file": "ports/cannonball/opr-10188.71" },
+ { "md5": "c23c9998ed1b32918cdb3b0a80547aac", "file": "ports/cannonball/opr-10189.70" },
+ { "md5": "e555e967fcbb98d01c2da5730e9f6a28", "file": "ports/cannonball/opr-10190.69" },
+ { "md5": "edfdde9f0a1f2ea98139c9823a190e13", "file": "ports/cannonball/opr-10191.68" },
+ { "md5": "e36e9675a128d78acb191781e2271ae5", "file": "ports/cannonball/opr-10192.67" },
+ { "md5": "4980cb65d6ef5d4c4910d28fc200d369", "file": "ports/cannonball/opr-10193.66" },
+ { "md5": "e58109f14a0a4891afed803580577833", "file": "ports/cannonball/opr-10230.104" },
+ { "md5": "faf3f323326434cebbe3536359724985", "file": "ports/cannonball/opr-10231.103" },
+ { "md5": "7d6cae678c6a36bf0712958ee0e7711a", "file": "ports/cannonball/opr-10232.102" },
+ { "md5": "786da8c971d530bd51400da1904d5a3d", "file": "ports/cannonball/opr-10266.101" },
+ { "md5": "7ca240eb19818825f9d59d26b3037f69", "file": "ports/cannonball/opr-10267.100" },
+ { "md5": "080b53f5d3952a8a07981f9f66997887", "file": "ports/cannonball/opr-10268.99" },
+ { "md5": "7300090310ef7dc5cf4b7ebe06a38e66", "file": "cannonball/opr-10188.71f" } ] },
- "CaveStory": { "name": "Cave Story (nxengine)", "biosFiles": [ { "md5": "", "file": "ports/CaveStory/Doukutsu.exe" } ] },
+ "CaveStory": { "name": "Cave Story (nxengine)", "biosFiles": [ { "md5": "", "file": "ports/CaveStory/Doukutsu.exe" }, { "md5": "38695d3d69d7a0ada8178072dad4c58b", "file": "nxengine/Doukutsu.exe" } ] },
"Dinothawr": { "name": "Dinothawr", "biosFiles": [ { "md5": "", "file": "ports/dinothawr/dinothawr.game" } ] },
- "Quake": { "name": "Quake (tryquake)", "biosFiles": [ { "md5": "", "file": "ports/quake/id1/pak0.pak" } ] },
+ "Quake": { "name": "Quake (tryquake)", "biosFiles": [ { "md5": "", "file": "ports/quake/id1/pak0.pak" }, { "md5": "00480ea1008b9fe2e134896a015a31fd", "file": "quoth/pak0.pak" }, { "md5": "7e67039da2527d95f61c215ef6f879cd", "file": "quoth/pak1.pak" }, { "md5": "ae0a13119175f9b26b039d9bae508591", "file": "quoth/pak2.pak" } ] },
"REminiscence": { "name": "Flashback (REminiscence)", "biosFiles": [ { "md5": "", "file": "ports/reminiscence/level1.map" } ] },
- "RickDangerous": { "name": "Rick Dangerous (xrick)", "biosFiles": [ { "md5": "", "file": "ports/xrick/data.zip" } ] },
+ "RickDangerous": { "name": "Rick Dangerous (xrick)", "biosFiles": [ { "md5": "a471e64e9f69afbe59c10cc94ed1b184", "file": "ports/xrick/data.zip" } ] },
"VVVVVV": { "name": "VVVVVV", "biosFiles": [ { "md5": "", "file": "ports/VVVVVV/data.zip" } ] },
- "eduke32": { "name": "Duke Nukem 3D", "biosFiles": [ { "md5": "", "file": "ports/eduke/duke3d.grp" } ] },
+ "eduke32": { "name": "Duke Nukem 3D", "biosFiles": [ { "md5": "", "file": "ports/eduke/duke3d.grp" }, { "md5": "f8a7f96a84fc0f401abe2b1d617d1c76", "file": "penthous.zip" } ] },
"sonic1": { "name": "Sonic 1", "biosFiles": [ { "md5": "", "file": "ports/sonic1/Data.rsdk" } ] },
"sonic2": { "name": "Sonic 2", "biosFiles": [ { "md5": "", "file": "ports/sonic2/Data.rsdk" } ] },
"soniccd": { "name": "Sonic CD", "biosFiles": [ { "md5": "", "file": "ports/soniccd/Data.rsdk" } ] },
@@ -818,30 +839,7 @@ systems = {
"cdi": { "name": "Phillips CDI", "biosFiles": [ { "md5": "", "file": "bios/same_cdi/bios/cdimono1.zip" },
{ "md5": "", "file": "bios/same_cdi/bios/cdimono2.zip" },
{ "md5": "", "file": "bios/same_cdi/bios/cdibios.zip" } ] },
-
- "Cannonball": { "name": "Cannonball", "biosFiles": [ { "md5": "0cc087bbf1d5ad46319756b5b17ab9be", "file": "ports/cannonball/epr-10187.88" }, { "md5": "eddae6f176ad5a3438e4dae1b8c4d4fb", "file": "ports/cannonball/epr-10327.76" }, { "md5": "35bdcb3d8eaae6505af896a55f26dda1", "file": "ports/cannonball/epr-10327a.76" }, { "md5": "73486b2da791109e322c71cbaf51338b", "file": "ports/cannonball/epr-10328.75" }, { "md5": "5c82ed7dd7450f5c037b4dcaa0103218", "file": "ports/cannonball/epr-10328a.75" }, { "md5": "7197dfbdf83029abd56e72b98b274c63", "file": "ports/cannonball/epr-10329.58" }, { "md5": "f8729ace245eb8fc4854819f783f6042", "file": "ports/cannonball/epr-10329a.58" }, { "md5": "9556c737b5506241a5a58635e58bdbad", "file": "ports/cannonball/epr-10330.57" }, { "md5": "f0f9e2cce2d64dbb28650b11679f745b", "file": "ports/cannonball/epr-10330a.57" }, { "md5": "591daabf7c4b9005171f9af83068f3a1", "file": "ports/cannonball/epr-10380.133" }, { "md5": "94bb116334e7076aeeee5fcdcb536f87", "file": "ports/cannonball/epr-10380b.133" }, { "md5": "ab1a9fe4feb5d5bd867552e3740bdc07", "file": "ports/cannonball/epr-10381.132" }, { "md5": "ab1a9fe4feb5d5bd867552e3740bdc07", "file": "ports/cannonball/epr-10381b.132" }, { "md5": "bcf3cae054791aa0c2c9d3c144bb1682", "file": "ports/cannonball/epr-10382.118" }, { "md5": "8ff3212b3a2e37a37ba73a998bbc424f", "file": "ports/cannonball/epr-10382b.118" }, { "md5": "161ceb196fcc9825bc981f933f305b5e", "file": "ports/cannonball/epr-10383.117" }, { "md5": "2d2b6149f1bccaaebf9c792f292e36d0", "file": "ports/cannonball/epr-10383b.117" }, { "md5": "9bc7fcfda9dea3a6d1c527b3146a4a95", "file": "ports/cannonball/mpr-10371.9" }, { "md5": "7da2895e20d2152ebddbdd2df29f3bd4", "file": "ports/cannonball/mpr-10372.13" }, { "md5": "5ed55433e64a4daecb9a0dbfc8771131", "file": "ports/cannonball/mpr-10373.10" }, { "md5": "5d09103268ac520609fb10ba186374b1", "file": "ports/cannonball/mpr-10374.14" }, { "md5": "187a6496e67c95e119ce97600902d178", "file": "ports/cannonball/mpr-10375.11" }, { "md5": "107a513ce97fb3b88d97425f19054471", "file": "ports/cannonball/mpr-10376.15" }, { "md5": "4a41f5ad01d78f52e8b6187c971c7270", "file": "ports/cannonball/mpr-10377.12" }, { "md5": "f6b7defe9860aa8a2f2e2915f1d9b94d", "file": "ports/cannonball/mpr-10378.16" }, { "md5": "866f1a596cc943bc5a416ff3e63cc9b0", "file": "ports/cannonball/opr-10185.11" }, { "md5": "866f1a596cc943bc5a416ff3e63cc9b0", "file": "ports/cannonball/opr-10186.47" }, { "md5": "ce4c62deb59049edb9972a5214ab39a1", "file": "ports/cannonball/opr-10188.71" }, { "md5": "c23c9998ed1b32918cdb3b0a80547aac", "file": "ports/cannonball/opr-10189.70" }, { "md5": "e555e967fcbb98d01c2da5730e9f6a28", "file": "ports/cannonball/opr-10190.69" }, { "md5": "edfdde9f0a1f2ea98139c9823a190e13", "file": "ports/cannonball/opr-10191.68" }, { "md5": "e36e9675a128d78acb191781e2271ae5", "file": "ports/cannonball/opr-10192.67" }, { "md5": "4980cb65d6ef5d4c4910d28fc200d369", "file": "ports/cannonball/opr-10193.66" }, { "md5": "e58109f14a0a4891afed803580577833", "file": "ports/cannonball/opr-10230.104" }, { "md5": "faf3f323326434cebbe3536359724985", "file": "ports/cannonball/opr-10231.103" }, { "md5": "7d6cae678c6a36bf0712958ee0e7711a", "file": "ports/cannonball/opr-10232.102" }, { "md5": "786da8c971d530bd51400da1904d5a3d", "file": "ports/cannonball/opr-10266.101" }, { "md5": "7ca240eb19818825f9d59d26b3037f69", "file": "ports/cannonball/opr-10267.100" }, { "md5": "080b53f5d3952a8a07981f9f66997887", "file": "ports/cannonball/opr-10268.99" }, { "md5": "7300090310ef7dc5cf4b7ebe06a38e66", "file": "cannonball/opr-10188.71f" } ] },
- "CaveStory": { "name": "Cave Story (nxengine)", "biosFiles": [ { "md5": "", "file": "ports/CaveStory/Doukutsu.exe" }, { "md5": "38695d3d69d7a0ada8178072dad4c58b", "file": "nxengine/Doukutsu.exe" } ] },
- "DOOM1": { "name": "DOOM1 (PrBoom)", "biosFiles": [ { "md5": "", "file": "ports/doom/doom1.wad" }, { "md5": "5772f907fdee4284f6332d89c0c5609c", "file": "gzdoom.pk3" }, { "md5": "094baa608b85fbe636933b4098e7e1f1", "file": "game_widescreen_gfx.pk3" } ] },
- "DOOM2": { "name": "DOOM2 (PrBoom)", "biosFiles": [ { "md5": "", "file": "ports/doom2/doom2.wad" } ] },
- "Diablo": { "name": "Diablo 1 (devilutionx) ", "biosFiles": [ { "md5": "68f049866b44688a7af65ba766bef75a", "file": "ports/diablo/diabdat.mpq" } ] },
- "Dinothawr": { "name": "Dinothawr", "biosFiles": [ { "md5": "", "file": "ports/dinothawr/dinothawr.game" } ] },
- "OpenTyrian": { "name": "OpenTyrian", "biosFiles": [ { "md5": "", "file": "ports/opentyrian/cubetxt1.dat" }, { "md5": "", "file": "ports/opentyrian/cubetxt2.dat" }, { "md5": "", "file": "ports/opentyrian/cubetxt3.dat" }, { "md5": "", "file": "ports/opentyrian/cubetxt4.dat" }, { "md5": "", "file": "ports/opentyrian/demo.1" }, { "md5": "", "file": "ports/opentyrian/demo.2" }, { "md5": "", "file": "ports/opentyrian/demo.3" }, { "md5": "", "file": "ports/opentyrian/demo.4" }, { "md5": "", "file": "ports/opentyrian/demo.5" }, { "md5": "", "file": "ports/opentyrian/dpmi16bi.ovl" }, { "md5": "", "file": "ports/opentyrian/estsc.shp" }, { "md5": "", "file": "ports/opentyrian/exitmsg.bin" }, { "md5": "", "file": "ports/opentyrian/levels1.dat" }, { "md5": "", "file": "ports/opentyrian/levels2.dat" }, { "md5": "", "file": "ports/opentyrian/levels3.dat" }, { "md5": "", "file": "ports/opentyrian/levels4.dat" }, { "md5": "", "file": "ports/opentyrian/loudness.awe" }, { "md5": "", "file": "ports/opentyrian/modems.txt" }, { "md5": "", "file": "ports/opentyrian/music.mus" }, { "md5": "", "file": "ports/opentyrian/netarena.pcx" }, { "md5": "", "file": "ports/opentyrian/netfont1.pcx" }, { "md5": "", "file": "ports/opentyrian/netfont2.pcx" }, { "md5": "", "file": "ports/opentyrian/netmega.pcx" }, { "md5": "", "file": "ports/opentyrian/netset.pcx" }, { "md5": "", "file": "ports/opentyrian/newsh#.shp" }, { "md5": "", "file": "ports/opentyrian/newsh0.shp" }, { "md5": "", "file": "ports/opentyrian/newsh1.shp" }, { "md5": "", "file": "ports/opentyrian/newsh2.shp" }, { "md5": "", "file": "ports/opentyrian/newsh3.shp" }, { "md5": "", "file": "ports/opentyrian/newsh4.shp" }, { "md5": "", "file": "ports/opentyrian/newsh5.shp" }, { "md5": "", "file": "ports/opentyrian/newsh6.shp" }, { "md5": "", "file": "ports/opentyrian/newsh7.shp" }, { "md5": "", "file": "ports/opentyrian/newsh8.shp" }, { "md5": "", "file": "ports/opentyrian/newsh9.shp" }, { "md5": "", "file": "ports/opentyrian/newsha.shp" }, { "md5": "", "file": "ports/opentyrian/newshb.shp" }, { "md5": "", "file": "ports/opentyrian/newshc.shp" }, { "md5": "", "file": "ports/opentyrian/newshd.shp" }, { "md5": "", "file": "ports/opentyrian/newshe.shp" }, { "md5": "", "file": "ports/opentyrian/newshf.shp" }, { "md5": "", "file": "ports/opentyrian/newshg.shp" }, { "md5": "", "file": "ports/opentyrian/newshh.shp" }, { "md5": "", "file": "ports/opentyrian/newshj.shp" }, { "md5": "", "file": "ports/opentyrian/newshk.shp" }, { "md5": "", "file": "ports/opentyrian/newshl.shp" }, { "md5": "", "file": "ports/opentyrian/newshm.shp" }, { "md5": "", "file": "ports/opentyrian/newshn.shp" }, { "md5": "", "file": "ports/opentyrian/newsho.shp" }, { "md5": "", "file": "ports/opentyrian/newshp.shp" }, { "md5": "", "file": "ports/opentyrian/newshr.shp" }, { "md5": "", "file": "ports/opentyrian/newshs.shp" }, { "md5": "", "file": "ports/opentyrian/newsht.shp" }, { "md5": "", "file": "ports/opentyrian/newshu.shp" }, { "md5": "", "file": "ports/opentyrian/newshv.shp" }, { "md5": "", "file": "ports/opentyrian/newsh^.shp" }, { "md5": "", "file": "ports/opentyrian/newsh~.shp" }, { "md5": "", "file": "ports/opentyrian/order.tfp" }, { "md5": "", "file": "ports/opentyrian/palette.dat" }, { "md5": "", "file": "ports/opentyrian/setup.box" }, { "md5": "", "file": "ports/opentyrian/setup.ini" }, { "md5": "", "file": "ports/opentyrian/setup.int" }, { "md5": "", "file": "ports/opentyrian/shapesw.dat" }, { "md5": "", "file": "ports/opentyrian/shapesx.dat" }, { "md5": "", "file": "ports/opentyrian/shapesy.dat" }, { "md5": "", "file": "ports/opentyrian/shapesz.dat" }, { "md5": "", "file": "ports/opentyrian/shipedit.pcx" }, { "md5": "", "file": "ports/opentyrian/tshp2.pcx" }, { "md5": "", "file": "ports/opentyrian/tyrend.anm" }, { "md5": "", "file": "ports/opentyrian/tyrian.cdt" }, { "md5": "", "file": "ports/opentyrian/tyrian.hdt" }, { "md5": "", "file": "ports/opentyrian/tyrian.ico" }, { "md5": "", "file": "ports/opentyrian/tyrian.pic" }, { "md5": "", "file": "ports/opentyrian/tyrian.shp" }, { "md5": "", "file": "ports/opentyrian/tyrian.snd" }, { "md5": "", "file": "ports/opentyrian/tyrian1.lvl" }, { "md5": "", "file": "ports/opentyrian/tyrian2.lvl" }, { "md5": "", "file": "ports/opentyrian/tyrian3.lvl" }, { "md5": "", "file": "ports/opentyrian/tyrian4.lvl" }, { "md5": "", "file": "ports/opentyrian/tyrianc.shp" }, { "md5": "", "file": "ports/opentyrian/tyrset.pcx" }, { "md5": "", "file": "ports/opentyrian/user1.shp" }, { "md5": "", "file": "ports/opentyrian/user2.shp" }, { "md5": "", "file": "ports/opentyrian/voices.snd" }, { "md5": "", "file": "ports/opentyrian/voicesc.snd" }, { "md5": "", "file": "ports/opentyrian/netterm.int" }, { "md5": "", "file": "ports/opentyrian/newshi.shp" }, { "md5": "", "file": "ports/opentyrian/shapes).dat" } ] },
- "Quake": { "name": "Quake (tryquake)", "biosFiles": [ { "md5": "", "file": "ports/quake/id1/pak0.pak" }, { "md5": "00480ea1008b9fe2e134896a015a31fd", "file": "quoth/pak0.pak" }, { "md5": "7e67039da2527d95f61c215ef6f879cd", "file": "quoth/pak1.pak" }, { "md5": "ae0a13119175f9b26b039d9bae508591", "file": "quoth/pak2.pak" } ] },
- "REminiscence": { "name": "Flashback (REminiscence)", "biosFiles": [ { "md5": "", "file": "ports/reminiscence/level1.map" } ] },
- "RickDangerous": { "name": "Rick Dangerous (xrick)", "biosFiles": [ { "md5": "a471e64e9f69afbe59c10cc94ed1b184", "file": "ports/xrick/data.zip" } ] },
- "VVVVVV": { "name": "VVVVVV", "biosFiles": [ { "md5": "", "file": "ports/VVVVVV/data.zip" } ] },
- "amiga": { "name": "Amiga/CD32", "biosFiles": [ { "md5": "89da1838a24460e4b93f4f0c5d92d48d", "file": "bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom" }, { "md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom" }, { "md5": "68c9c0826f6c0ca20546d588ee77391c", "file": "bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom" }, { "md5": "192d6d950d0ed3df8040b788502831c2", "file": "bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom" }, { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom" }, { "md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom" }, { "md5": "465646c9b6729f77eea5314d1f057951", "file": "bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom" }, { "md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom" }, { "md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom" }, { "md5": "413590e50098a056cfec418d3df0212d", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom" }, { "md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom" }, { "md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/kick33180.A500" }, { "md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/kick34005.A500" }, { "md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/kick37175.A500" }, { "md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/kick40060.CD32" }, { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/kick40060.CD32.ext" }, { "md5": "e40a5dfb3d017ba8779faba30cbd1c8e", "file": "bios/kick40063.A600" }, { "md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/kick40068.A1200" }, { "md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/kick40068.A4000" }, { "md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom" }, { "md5": "6c5b44c1a2bcee664129f850bfe4ed8a", "file": "uae_data/drive_click_A500.wav" }, { "md5": "7401f854a75f9ede18769168ab896a2a", "file": "uae_data/drive_spin_A500.wav" }, { "md5": "f9d954879fee8e96baa93d6139077cdb", "file": "uae_data/drive_spinnd_A500.wav" }, { "md5": "aebeacc7e7bc52ef890785c835bec3d0", "file": "uae_data/drive_startup_A500.wav" }, { "md5": "1a4b2d6254918ff769f26beeede75655", "file": "uae_data/drive_snatch_A500.wav" }, { "md5": "b64bee23f356635f67fb08b543df9797", "file": "uae_data/drive_click_LOUD.wav" }, { "md5": "56d8e36a2f04b5e8c5a1f1530cfc886c", "file": "uae_data/drive_spin_LOUD.wav" }, { "md5": "43ab05c6d969cb40805970a5b2352875", "file": "uae_data/drive_spinnd_LOUD.wav" }, { "md5": "743b4b9f0ca645c4c2a34953b5e01e45", "file": "uae_data/drive_startup_LOUD.wav" }, { "md5": "40cdf89f35b68cfefd4df5fb0256e02f", "file": "uae_data/drive_snatch_LOUD.wav" } ] },
- "atari7800": { "name": "Atari 7800", "biosFiles": [ { "md5": "0763f1ffb006ddbe32e52d497ee848ae", "file": "bios/7800 BIOS (U).rom" } ] },
- "atari800": { "name": "Atari 800", "biosFiles": [ { "md5": "06daac977823773a3eea3422fd26a703", "file": "bios/ATARIXL.ROM" }, { "md5": "0bac0c6a50104045d902df4503a4c30b", "file": "bios/ATARIBAS.ROM" }, { "md5": "eb1f32f5d9f382db1bbfb8d7f9cb343a", "file": "bios/ATARIOSA.ROM" }, { "md5": "a3e8d617c95d08031fe1b20d541434b2", "file": "bios/ATARIOSB.ROM" } ] },
- "colecovision": { "name": "Colecovision", "biosFiles": [ { "md5": "", "file": "bios/Machines/COL - Bit Corporation Dina/config.ini" }, { "md5": "1de922acdd742d31349c2801e9768c35", "file": "bios/Machines/COL - Bit Corporation Dina/czz50-1.rom" }, { "md5": "72b089dc55b7fe7ffb5028f365e8c045", "file": "bios/Machines/COL - Bit Corporation Dina/czz50-2.rom" }, { "md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/Machines/COL - ColecoVision/coleco.rom" }, { "md5": "", "file": "bios/Machines/COL - ColecoVision/config.ini" }, { "md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom" }, { "md5": "", "file": "bios/Machines/COL - ColecoVision with Opcode Memory Extension/config.ini" }, { "md5": "", "file": "bios/Machines/COL - Spectravideo SVI-603 Coleco/config.ini" }, { "md5": "c60a2e85572c0ccb69505a7646d5c1b6", "file": "bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM" }, { "md5": "", "file": "bios/Databases/colecodb.xml" } ] },
- "eduke32": { "name": "Duke Nukem 3D", "biosFiles": [ { "md5": "", "file": "ports/eduke/duke3d.grp" }, { "md5": "f8a7f96a84fc0f401abe2b1d617d1c76", "file": "penthous.zip" } ] },
- "fds": { "name": "Nintendo Family Computer Disk System", "biosFiles": [ { "md5": "7bfe8c0540ed4bd6a0f1e2a0f0118ced", "file": "bios/NstDatabase.xml" }, { "md5": "ca30b50f880eb660a320674ed365ef7a", "file": "bios/disksys.rom" } ] },
- "gbc": { "name": "Game Boy Color", "biosFiles": [ { "md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin" }, { "md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin" } ] },
- "neogeo": { "name": "NeoGeo", "biosFiles": [ { "md5": "", "file": "neogeo/neogeo.zip" } ] },
- "neogeocd": { "name": "NeoGeo CD", "biosFiles": [ { "md5": "", "file": "neogeo/neogeo.zip" }, { "md5": "f39572af7584cb5b3f70ae8cc848aba2", "file": "bios/neocd/neocd_z.rom" }, { "md5": "b31a246b69493c35194fe0bac120dc37", "file": "neocdz.zip" }, { "md5": "006a881532f2caffc3fe9fb5593f2ed5", "file": "neocd.zip" } ] },
- "o2em": { "name": "Odyssey 2", "biosFiles": [ { "md5": "562d5ebf9e030a40d6fabfc2f33139fd", "file": "bios/o2rom.bin" }, { "md5": "f1071cdb0b6b10dde94d3bc8a6146387", "file": "bios/c52.bin" }, { "md5": "c500ff71236068e0dc0d0603d265ae76", "file": "bios/g7400.bin" }, { "md5": "279008e4a0db2dc5f1c048853b033828", "file": "bios/jopac.bin" } ] },
- "pcengine": { "name": "PC Engine", "biosFiles": [ { "md5": "ff1a674273fe3540ccef576376407d1d", "file": "bios/syscard3.pce" } ] },
-
+
}
class BiosStatus:
diff --git a/scripts/exporter/batocera_exporter.py b/scripts/exporter/batocera_exporter.py
index 6d877263f..bbf9e9de2 100644
--- a/scripts/exporter/batocera_exporter.py
+++ b/scripts/exporter/batocera_exporter.py
@@ -19,7 +19,9 @@ SOURCE_URL = (
"/package/batocera/core/batocera-scripts/scripts/batocera-systems"
)
-_ENTRY_START = re.compile(r'^(\s{4})"([^"]+)":\s*\{')
+# Any indent: Batocera writes four spaces, EmuELEC one tab for 23 systems,
+# and an entry the pattern missed was appended again whole.
+_ENTRY_START = re.compile(r'^(\s+)"([^"]+)":\s*\{')
_INDENT = " " * 4
# One BIOS item: a dict literal with no nested braces.
_ITEM = re.compile(r"\{[^{}\n]*\}")
@@ -382,12 +384,13 @@ class Exporter(BaseExporter):
return inner if isinstance(inner, dict) else {}
def _entry_line(
- self, system: NativeSystem, files: list[NativeFile], before: dict | None = None
+ self, system: NativeSystem, files: list[NativeFile], before: dict | None = None,
+ indent: str = _INDENT,
) -> str:
own = self._own_entry(system, before)
runner = "".join(f"{key}, " for key in self._runner_keys(own))
return (
- f'{_INDENT}"{system.native_id}": '
+ f'{indent}"{system.native_id}": '
f'{{ "name": "{self.display_name(system)}", {runner}'
f'"biosFiles": [ {self._bios_files(files, own)} ] }},'
)
@@ -440,16 +443,17 @@ class Exporter(BaseExporter):
before = self._parse_entry(original)
own = self._own_entry(system, before)
items = self._bios_items(files, own)
+ indent = _ENTRY_START.match(original[0]).group(1)
one_line = len(original) == 1 and not trailing and not leading
if one_line:
- return [self._entry_line(system, files, before)]
+ return [self._entry_line(system, files, before, indent)]
runner = "".join(f"{key}, " for key in self._runner_keys(own))
head = (
- f'{_INDENT}"{system.native_id}": '
+ f'{indent}"{system.native_id}": '
f'{{ "name": "{self.display_name(system)}", {runner}"biosFiles": ['
)
- pad = " " * (len(_INDENT) + 4)
+ pad = indent + " " * 4
lines = [head]
for index, item in enumerate(items):
key = _note_key(item)
@@ -458,7 +462,7 @@ class Exporter(BaseExporter):
note = trailing.get(key, "")
suffix = f" {note}" if note else ""
lines.append(f"{pad}{item}{separator}{suffix}")
- lines.append(f"{_INDENT}] }},")
+ lines.append(f"{indent}] }},")
return lines
def _patched_entry(
diff --git a/tests/test_exporters.py b/tests/test_exporters.py
index f84b4e624..9f7f9565b 100644
--- a/tests/test_exporters.py
+++ b/tests/test_exporters.py
@@ -2909,6 +2909,24 @@ class BatoceraNotesStayWithTheirItem(unittest.TestCase):
self.assertEqual(trailing, {("bios/bk0010.zip", "two.rom"): "# tail"})
+class BatoceraEntriesAtAnyIndent(unittest.TestCase):
+ """EmuELEC indents 23 of its systems with one tab. The entry pattern
+ required four spaces, so each was appended again whole and the export
+ carried 21 duplicated keys that ast.literal_eval kept silently."""
+
+ def test_a_tab_indented_entry_is_located(self):
+ from exporter.batocera_exporter import Exporter
+
+ body = [
+ ' "atari5200": { "name": "5200", "biosFiles": [ { "md5": "a", "file": "bios/5200.rom" } ] },',
+ '\t"amiga": { "name": "Amiga", "biosFiles": [ { "md5": "b", "file": "bios/kick.rom" },',
+ '\t\t{ "md5": "c", "file": "bios/kick2.rom" } ] },',
+ ]
+ self.assertEqual(
+ Exporter._entry_spans(body), {"atari5200": (0, 0), "amiga": (1, 2)}
+ )
+
+
class RecalboxKeepsUnchangedText(unittest.TestCase):
"""Every element the model held was re-rendered: attribute order,
alignment, line breaks inside md5 and digest case changed in 222
From 8aa1a5fdad290b0db92eccbff0b90902f1a6309a Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:42:53 +0100
Subject: [PATCH 45/83] fix: a release asset absent on disk stays held
The previous commit counted a name with no resolved copy as not held, which also dropped release assets the builder holds while no copy is on disk (test_install_selection AHeldFileTheInstallerCannotFetch). Only the case-insensitive name match now leaves out copies in another emulator's tree, as resolve_local_file does.
---
scripts/verify.py | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/scripts/verify.py b/scripts/verify.py
index b465ab4bc..8d2614a87 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -26,11 +26,12 @@ from __future__ import annotations
import argparse
import contextlib
+import functools
import json
import os
import sys
from collections import Counter
-from collections.abc import Mapping
+from collections.abc import Callable, Mapping
from pathlib import Path
import slots
@@ -38,6 +39,8 @@ import slots
sys.path.insert(0, os.path.dirname(__file__))
from hashing import parse_md5_list
from common import (
+ _foreign_tree,
+ _owner_tokens,
platform_arg,
target_listing_line,
suggest_names,
@@ -419,14 +422,25 @@ def _build_expected(file_entry: dict, checks: list[str]) -> dict:
return expected
+def _in_foreign_tree(db: dict, owners: set[str], sha1: str) -> bool:
+ """Whether the collection keeps this sha1 in another emulator's tree."""
+ return _foreign_tree(db.get("files", {}).get(sha1, {}).get("path", ""), owners)
+
+
def _name_in_index(
name: str,
by_name: dict,
by_path_suffix: dict | None = None,
data_names: set[str] | None = None,
by_name_lower: dict[str, str] | None = None,
+ foreign: Callable[[str], bool] | None = None,
) -> bool:
- """Check if a name is resolvable in the database indexes or data directories."""
+ """Check if a name is resolvable in the database indexes or data directories.
+
+ *foreign* tells a copy in another emulator's tree from the sha1 of a
+ name: matched in another casing, such a copy is not the asker's, as in
+ resolve_local_file's case-insensitive step.
+ """
# Strip trailing slash for directory-type entries (e.g. nestopia/samples/foo/)
name = name.rstrip("/")
if name in by_name:
@@ -435,11 +449,11 @@ def _name_in_index(
if basename != name and basename in by_name:
return True
if by_name_lower:
- key = name.lower()
- if key in by_name_lower:
- return True
- if basename != name and basename.lower() in by_name_lower:
- return True
+ for key in {name.lower(), basename.lower()}:
+ if key in by_name_lower and not (
+ foreign and all(foreign(s) for s in by_name[by_name_lower[key]])
+ ):
+ return True
if by_path_suffix and name in by_path_suffix:
return True
if data_names:
@@ -672,6 +686,7 @@ def find_undeclared_files(
# not this emulator's file (dosbox-x's et4000.bin and pcem's
# et4000.BIN).
owned = {**f, "source_profile": emu_name}
+ foreign = functools.partial(_in_foreign_tree, db, _owner_tokens(owned))
if shipped_on_mismatch and (f.get("md5") or f.get("sha1")):
# The entry states what its content should be and the builder
# drops a copy that contradicts it, so content decides here
@@ -683,12 +698,13 @@ def find_undeclared_files(
else:
in_repo = _name_in_index(
fname, by_name, by_path_suffix, data_names, by_name_lower,
+ foreign,
)
if not in_repo and dest != fname:
path_base = dest.rsplit("/", 1)[-1]
in_repo = _name_in_index(
path_base, by_name, by_path_suffix, data_names,
- by_name_lower,
+ by_name_lower, foreign,
)
if in_repo and not any(
f.get(h) for h in ("sha1", "md5", "crc32", "sha256")
@@ -699,7 +715,7 @@ def find_undeclared_files(
# only PCem's and QEMU's PC BIOS images of that name.
# The fallback below then decides as for any mismatch.
_lp, _st = resolve_local_file(owned, db, dest_hint=dest)
- if _st == "hash_mismatch" or _lp is None:
+ if _st == "hash_mismatch":
in_repo = False
if not in_repo:
# Hash fallback: the repo may hold the content under a
From d1d94f597910abb73baa5a5c551070f91abf9c08 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:44:22 +0100
Subject: [PATCH 46/83] fix: keep card and closed-folder tests apart
The --dest refusal for a path under a file stopped two fixtures: muOS's MUOS marker was written as a file with the BIOS folder below it, and the folder that cannot be created was a path under a file. The marker is now a folder and that case uses a folder this user cannot write.
---
tests/test_install_tui.py | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/tests/test_install_tui.py b/tests/test_install_tui.py
index 24bbd3485..7e0b2e0b2 100644
--- a/tests/test_install_tui.py
+++ b/tests/test_install_tui.py
@@ -5898,7 +5898,10 @@ def _card_from_rules(root: Path, setup: install.CardSetup) -> Path:
(root / "bios").mkdir(exist_ok=True)
for value in rule.values:
(root / value).parent.mkdir(parents=True, exist_ok=True)
- if rule.method == "games_part" and "." not in PurePosixPath(value).name:
+ # A marker the BIOS folder sits under is a folder on the card
+ # (muOS's MUOS/bios): written as a file, no folder fits below it.
+ if (rule.method == "games_part" and "." not in PurePosixPath(value).name
+ or str(setup.below).startswith(f"{value}/")):
(root / value).mkdir(exist_ok=True)
else:
(root / value).write_text("", encoding="utf-8")
@@ -9763,14 +9766,21 @@ class ScreenRowsAndFilters(unittest.TestCase):
from test_install_offline import PAYLOAD, _offline_env, _pack
- blocker = self.root / "file"
- blocker.write_text("not a folder")
+ if os.name == "nt" or os.geteuid() == 0:
+ self.skipTest("a folder that refuses writes is POSIX, and root writes anyway")
+ # A file in the way is refused before the plan, as not_a_folder.
+ blocker = self.root / "closed"
+ blocker.mkdir()
pack = _pack(self.root, "RetroArch_v1_BIOS_Pack.zip", PAYLOAD)
- proc = subprocess.run(
- [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "retroarch",
- "--dest", str(blocker / "system"), "--from-pack", str(pack), "--events"],
- env=_offline_env(), capture_output=True, text=True, timeout=120, check=False,
- stdin=subprocess.DEVNULL)
+ os.chmod(blocker, 0o500)
+ try:
+ proc = subprocess.run(
+ [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "retroarch",
+ "--dest", str(blocker / "system"), "--from-pack", str(pack), "--events"],
+ env=_offline_env(), capture_output=True, text=True, timeout=120,
+ check=False, stdin=subprocess.DEVNULL)
+ finally:
+ os.chmod(blocker, 0o700)
events = [json.loads(line) for line in proc.stdout.splitlines()]
kinds = [event["event"] for event in events]
self.assertEqual(kinds[-3:], ["error", "summary", "end"], proc.stderr)
From eb99131a6efa9419049393c75fbf52b15e6f116f Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:45:03 +0100
Subject: [PATCH 47/83] fix: stop advising --save-dir a list cannot serve
RetroPie, ROCKNIX, AmberELEC, EmuELEC and RomM keep their save directory in no fixed place, and their lists leave those files out with no hash or address. The run said to name the folder with --save-dir, and said it again when --save-dir was given. It now says the list holds none of them.
---
install.ps1 | 2 +-
install.py | 20 +++++++++++++++++--
install.sh | 2 +-
install/launchers/index.json | 16 +++++++--------
tests/test_install.py | 24 +++++++++++++++++++++++
tests/test_install_tui.py | 38 +++++++++++++++++++++++++++++++++++-
wiki/installer.md | 5 ++++-
7 files changed, 93 insertions(+), 14 deletions(-)
diff --git a/install.ps1 b/install.ps1
index dab7b3426..412a6456e 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300"
+ $defaultInstallSha256 = "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index 429dffa35..feabcc09e 100644
--- a/install.py
+++ b/install.py
@@ -6456,7 +6456,8 @@ def _report_outcome(
kept = _kept_lines() + ([
f"{_plural(len(unplaced), 'file')} read from "
f"{unplaced[0].get('frontend') or 'the frontend'}'s save directory left out: "
- f"its place is not known. {LINE_SAVE_REMEDY}"] if unplaced else [])
+ + (f"{unplaced[0]['save_why']}." if unplaced[0].get("save_why")
+ else f"its place is not known. {LINE_SAVE_REMEDY}")] if unplaced else [])
kept += list(notes or [])
if interrupted:
say(f"\nStopped. {_plural(downloaded, 'file')} installed.")
@@ -8636,6 +8637,13 @@ def saves_line(display: str, count: int, where: str) -> str:
f"{shown_path(folder)}")
+def unlisted_saves_words(display: str) -> str:
+ """Why a file list holds none of the files read from the save
+ directory: the platform keeps it in no fixed place, and the list leaves
+ them out with no hash or address, which --save-dir cannot change."""
+ return f"{display} keeps it in no fixed place, and its file list holds none of them"
+
+
def unplaced_line(display: str, count: int, remedy: str) -> str:
"""The files read from an unknown save directory, left out."""
return (f"{_plural(count, 'file')} read from {display}'s save directory left out: "
@@ -15395,6 +15403,10 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
display = display_name(plat_name, manifest)
files, unplaced = place_save_entries(
files, bios_path, manifest, args.save_dir, display, say=False)
+ if not manifest.get("save_directory"):
+ # Its own list leaves these files out: naming the folder with
+ # --save-dir installs none of them, and was advised in a loop.
+ _SAVE_WHY[bios_path] = unlisted_saves_words(display)
# The games of the card, read before the choices: where it holds
# some, what they need is the menu's first choice, and --for-games
# narrows the list here, before the systems are counted.
@@ -15597,7 +15609,8 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
total_omitted += len(omitted_files)
# Named for the end of the run: ROCKNIX's own list leaves them out,
# and the end said "the frontend's save directory".
- omitted_seen.extend({**entry, "frontend": display}
+ omitted_seen.extend({**entry, "frontend": display,
+ "save_why": unlisted_saves_words(display)}
if entry.get("reason") == "no_save_directory"
and not entry.get("frontend") else entry
for entry in omitted_files)
@@ -21212,6 +21225,9 @@ def _unplaced_lines(summary: dict | None, state: TuiState,
if not count:
return []
name = display_name(state.platform) if state.platform else "the frontend"
+ if state.manifest and not state.manifest.get("save_directory"):
+ return [f"{_plural(count, 'file')} read from {name}'s save directory left out: "
+ f"{unlisted_saves_words(name)}."]
return [f"{_plural(count, 'file')} read from {name}'s save directory left out: "
f"its place is not known. {remedy or TUI_SAVE_REMEDY}"]
diff --git a/install.sh b/install.sh
index cbdaed395..c8cba304a 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300"
+DEFAULT_INSTALL_SHA256="3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 2be9a4f89..cd32da514 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1106280,
- "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
+ "size": 1107258,
+ "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1159907,
- "sha256": "6460af3bc1a9d27c7373b42cf45f19bf8619b8e55daac9892af9f57df21b258e"
+ "size": 1160885,
+ "sha256": "5ccc4ec3df34a1fef96caea9e84218de1fb92331664047c36d6863c11973dc3d"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1106280,
- "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
+ "size": 1107258,
+ "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1106280,
- "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300",
+ "size": 1107258,
+ "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
"executable": false
},
{
diff --git a/tests/test_install.py b/tests/test_install.py
index 658385670..b8c72ae82 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -482,6 +482,30 @@ class ADestThatIsAFileIsNamed(unittest.TestCase):
self.assertEqual((root / "scph5501.bin").read_bytes(), b"x")
+class SaveFilesAListHoldsNoneOfAreNotPromised(unittest.TestCase):
+ """RetroPie, ROCKNIX, AmberELEC, EmuELEC and RomM keep their save
+ directory in no fixed place: their lists leave those files out with no
+ hash or address. The run said "Name it with --save-dir", and said it
+ again with --save-dir given, which installs none of them."""
+
+ def test_the_reason_is_said_and_no_option_is_offered(self):
+ manifest = json.loads((REPO_ROOT / "install" / "retropie.json").read_text())
+ self.assertIsNone(manifest.get("save_directory"))
+ root = Path(_tempdir(self))
+ env = dict(os.environ, RETROBIOS_OS="linux")
+ for extra in ([], ["--save-dir", str(root / "saves")]):
+ with self.subTest(extra=extra):
+ proc = _install_run(
+ env, "--platform", "retropie", "--dest", str(root / "bios"),
+ "--manifest", "install/retropie.json", "--offline", "--no-input",
+ "--yes", "--emulator", "azahar", *extra)
+ out = proc.stdout + proc.stderr
+ self.assertIn("read from RetroPie's save directory left out: RetroPie "
+ "keeps it in no fixed place, and its file list holds none "
+ "of them.", out)
+ self.assertNotIn("Name it with --save-dir", out)
+
+
class AFolderThatRefusesWritesIsNamed(unittest.TestCase):
"""A read-only BIOS folder ended the run on a traceback (a subfolder to
create), or on three retries per file and "once that is resolved", and a
diff --git a/tests/test_install_tui.py b/tests/test_install_tui.py
index 7e0b2e0b2..988b7234e 100644
--- a/tests/test_install_tui.py
+++ b/tests/test_install_tui.py
@@ -2967,12 +2967,44 @@ class SaveDirectoryLeftOut(unittest.TestCase):
UNPLACED = {"reason": "no_save_directory", "label": "no save directory", "files": 2,
"required": 0}
+ def _ended(self, manifest: dict) -> tuple:
+ state = fresh_state()
+ state.stack = ["setup"]
+ with mock.patch.object(install.Path, "exists", return_value=True):
+ install.tui_update(state, Key("enter"))
+ install.tui_receive(state, ("manifest", "retroarch", manifest))
+ summary = {"event": "summary", "mode": "check", "installed": 0, "up_to_date": 0,
+ "pending": 5, "failed": [], "skipped": [self.UNPLACED], "left_out": [],
+ "kept": [], "interrupted": False}
+ for event in [*FILES, *SYSTEMS, CHECK, summary]:
+ install.tui_receive(state, ("event", state.run_id, event))
+ with mock.patch.object(install, "_tui_folder_facts", return_value={
+ "free": 50 * 1024 ** 3, "writable": True, "cores": []}):
+ install.tui_receive(state, ("ended", state.run_id, 1, []))
+ return state, summary
+
+ def test_a_list_that_holds_none_of_them_offers_no_folder(self):
+ """RetroPie's list leaves its save files out with no hash or address:
+ --save-dir installs none of them, and was advised again each run."""
+ state, summary = self._ended(MANIFEST)
+ line = ("2 files read from RetroArch's save directory left out: RetroArch keeps "
+ "it in no fixed place, and its file list holds none of them.")
+ plan = " ".join(" ".join(install.tui_view(state, 120, 40)).split())
+ self.assertIn(line, plan)
+ self.assertNotIn("--save-dir", plan)
+ state.stack.append("result")
+ state.code = 0
+ state.summary = {**summary, "mode": "install", "installed": 5}
+ self.assertEqual([text for text in install.tui_outcome(state)[1] if "save" in text],
+ [line])
+
def test_files_left_out_of_the_save_directory_are_said(self):
state = fresh_state()
state.stack = ["setup"]
with mock.patch.object(install.Path, "exists", return_value=True):
install.tui_update(state, Key("enter"))
- install.tui_receive(state, ("manifest", "retroarch", MANIFEST))
+ install.tui_receive(state, ("manifest", "retroarch", {
+ **MANIFEST, "save_directory": {"folder": "saves", "by_core": True}}))
summary = {"event": "summary", "mode": "check", "installed": 0, "up_to_date": 0,
"pending": 5, "failed": [], "skipped": [self.UNPLACED], "left_out": [],
"kept": [], "interrupted": False}
@@ -3834,6 +3866,8 @@ class BackTicksAndSaveFolder(unittest.TestCase):
def test_the_save_folder_remedy_is_the_same_on_both_screens(self):
summary = {"skipped": [{"reason": "no_save_directory", "files": 1}]}
state = checked_state()
+ state.manifest = {**state.manifest, "save_directory": {"folder": "saves",
+ "by_core": True}}
lines = install._unplaced_lines(summary, state)
self.assertIn("Options, Save folder (--save-dir)", lines[0])
@@ -11846,6 +11880,8 @@ class OneChoicePerRun(unittest.TestCase):
def test_the_farewell_names_the_option_not_the_screen(self):
state = _installed_state(SYSTEM_DIR)
+ state.manifest = {**state.manifest, "save_directory": {"folder": "saves",
+ "by_core": True}}
state.summary = {**state.summary, "skipped": [
{"reason": "no_save_directory", "label": "", "files": 1, "required": False}]}
farewell = " ".join(install.tui_farewell(state))
diff --git a/wiki/installer.md b/wiki/installer.md
index f66a8eb54..0d6e5141b 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -386,7 +386,10 @@ the save directory beside it (`saves`, `/storage/savefiles` on Lakka).
applies, or when `savefiles_in_content_dir` or
`sort_savefiles_by_content_enable` keeps saves beside each game, those files
are left out and the run says why, like the other entries the list cannot
-install. The full screen says so on its plan and its result.
+install. The full screen says so on its plan and its result. RetroPie, ROCKNIX,
+AmberELEC, EmuELEC and RomM keep the save directory in no fixed place: their
+lists hold none of these files, so `--save-dir` installs none, and the run says
+that instead of naming the option.
Batocera, KNULLI, Recalbox, RetroBat and RetroDECK write the save directory at
each launch, one folder per system (`by_system` in the file list). Their lists
From 9a805fd2401b7ff0ff322de1c27701e305aebbd4 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:50:29 +0100
Subject: [PATCH 48/83] docs: name the methods that count an export
adding-a-platform listed what a format can hold and none of what counts the written file. lands, states, fills, clears, names_anew and withheld are what seven exporters override so the summary matches the diff; a test reads the page for every one an exporter overrides.
---
tests/test_exporters.py | 20 ++++++++++++++++++++
wiki/adding-a-platform.md | 22 ++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/tests/test_exporters.py b/tests/test_exporters.py
index 9f7f9565b..251b31966 100644
--- a/tests/test_exporters.py
+++ b/tests/test_exporters.py
@@ -2909,6 +2909,26 @@ class BatoceraNotesStayWithTheirItem(unittest.TestCase):
self.assertEqual(trailing, {("bios/bk0010.zip", "two.rom"): "# tail"})
+class TheWikiNamesWhatCountsAnExport(unittest.TestCase):
+ """adding-a-platform listed the methods that say what a format can hold
+ and none of those that count what render wrote, which seven exporters
+ override so the report matches the diff."""
+
+ def test_every_overridden_contract_method_is_documented(self):
+ documented = ("carries", "requires", "can_add", "keys_by_system",
+ "lands", "states", "fills", "clears", "names_anew", "withheld")
+ overridden = {
+ name
+ for cls in discover_exporters().values()
+ for name in documented
+ if name in vars(cls)
+ }
+ wiki = (REPO_ROOT / "wiki" / "adding-a-platform.md").read_text(encoding="utf-8")
+ for name in sorted(overridden):
+ with self.subTest(method=name):
+ self.assertIn(f"`{name}(", wiki)
+
+
class BatoceraEntriesAtAnyIndent(unittest.TestCase):
"""EmuELEC indents 23 of its systems with one tab. The entry pattern
required four spaces, so each was appended again whole and the export
diff --git a/wiki/adding-a-platform.md b/wiki/adding-a-platform.md
index 8da75e437..add851786 100644
--- a/wiki/adding-a-platform.md
+++ b/wiki/adding-a-platform.md
@@ -606,6 +606,28 @@ of files:
own system, so an entry filed under one of our system ids is never written.
- `needs_original()` - `True` as soon as `native_sources()` names a file.
+Those methods say what the format could hold. The report counts what `render()`
+actually wrote, through a second set, read entry by entry:
+
+- `lands(fe)` - whether the entry is in the written file. Defaults to
+ `writable()`. Override it when `render()` drops an entry the format could
+ hold: RetroBat merges an addition into a path it already declares, and
+ System.dat leaves out a file with no section name.
+- `states(fe, field)` - whether the written entry carries the corrected field.
+ Defaults to `field in carries()`.
+- `fills(fe, field)` and `clears(fe, field)` - whether a hash only the truth
+ names is written, and whether a hash the truth contradicts leaves the entry.
+ Both default to `states()`.
+- `names_anew(fe)` - whether the render wrote, for the first time, a file the
+ platform already declares. Only a format whose unit is not the entry needs it
+ (a RetroPie help sentence).
+- `withheld()` - corrections the render proved and still did not write, named
+ so the run does not read as nothing to do.
+
+An exporter whose `render()` skips anything the defaults count must override
+the matching method. Otherwise the summary announces a change the maintainer
+will not find in the diff.
+
### Round-trip validation
The scraper and the exporter are checked against each other as
From 46a4a26a546259c07c69532458f83ac711a5ddfc Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:50:29 +0100
Subject: [PATCH 49/83] fix: keep bundled game data out of missing
verify counted game data installed with its emulator as missing, which cross_reference files as bundled: 24 of Batocera's 427. Bundled firmware already left the lists, and the line naming it never printed. Every bundled entry is now counted on that line, required firmware named and the rest under --verbose.
---
scripts/verify.py | 26 ++++++++++++++++++--------
tests/test_verify_listing.py | 27 +++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/scripts/verify.py b/scripts/verify.py
index f47c7f011..b12991d90 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -1845,6 +1845,13 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
game_data, bios_files, unplaced = _split_undeclared(undeclared)
+ # A file installed with its emulator is never collected, firmware or
+ # game data, required or not: cross_reference counts it apart. The
+ # firmware already left the pack lists (_mark_unplaced), the game data
+ # did not, and Abuse's three bundled data files read as missing.
+ bundled = [u for u in undeclared if not u["in_repo"] and u.get("bundled")]
+ game_data = [u for u in game_data if u["in_repo"] or not u.get("bundled")]
+
req_not_in_repo = _core_required_missing(bios_files)
req_hle_not_in_repo = [
u
@@ -1854,12 +1861,6 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
req_in_repo = [u for u in bios_files if u["required"] and u["in_repo"]]
opt_in_repo = [u for u in bios_files if not u["required"] and u["in_repo"]]
opt_not_in_repo = [u for u in bios_files if not u["required"] and not u["in_repo"]]
-
- bundled = [
- u for u in bios_files
- if u["required"] and not u["in_repo"] and u.get("bundled")
- and not u.get("hle_fallback")
- ]
# The builder's count, one file per pack path, when the platform pass
# replayed it. Counting entries said 1130 for RetroArch, 48 more than the
# pack holds: rom.key alone was claimed by three Amiga cores.
@@ -1886,8 +1887,17 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
for u in opt_not_in_repo:
_print_undeclared_entry(u, "MISSING (optional)", verbose, repeated)
if bundled:
- names = ", ".join(sorted({u["name"] for u in bundled}))
- print(f" Bundled with their emulator, not collected: {names}")
+ # The required firmware is named, as a missing one would be; the
+ # rest (shaders, runtime libraries, engine data) on request.
+ shown = bundled if verbose else [
+ u for u in bundled
+ if u["required"] and u.get("category", "bios") != "game_data"
+ ]
+ names = ", ".join(sorted({u["name"] for u in shown}))
+ print(
+ f" Bundled with their emulator, not collected: {len(bundled)}"
+ + (f" ({names})" if names else "")
+ )
if unplaced:
print(f" Core files held but not packed: {len(unplaced)} "
f"({_omission_reasons(unplaced)})")
diff --git a/tests/test_verify_listing.py b/tests/test_verify_listing.py
index c825b52a5..209a8dae1 100644
--- a/tests/test_verify_listing.py
+++ b/tests/test_verify_listing.py
@@ -200,6 +200,33 @@ class EveryGapCountedIsNamed(unittest.TestCase):
self.assertIn("MISSING (game data): engine needs level.dat", verbose.getvalue())
+class BundledGameDataIsNotMissing(unittest.TestCase):
+ """cross_reference put Abuse's abuse.lsp, defaults.prp and english.lsp
+ under bundled while verify called them missing game data: 24 of the 427
+ Batocera counted."""
+
+ def test_bundled_game_data_is_counted_apart(self):
+ import contextlib
+ import io
+
+ sys.path.insert(0, str(REPO_ROOT / "scripts"))
+ import verify # noqa: PLC0415
+
+ result = {"undeclared_files": [
+ {"name": "abuse.lsp", "emulator": "Abuse", "required": True,
+ "in_repo": False, "category": "game_data", "bundled": True,
+ "in_pack": False},
+ {"name": "level.dat", "emulator": "engine", "required": True,
+ "in_repo": False, "category": "game_data"},
+ ]}
+ with contextlib.redirect_stdout(io.StringIO()) as out:
+ verify._print_undeclared_section(result, verbose=True)
+ self.assertIn("Game data: 0 in pack, 1 missing", out.getvalue())
+ self.assertNotIn("needs abuse.lsp", out.getvalue())
+ self.assertIn("Bundled with their emulator, not collected: 1 (abuse.lsp)",
+ out.getvalue())
+
+
class CoreCopiesWithoutAGapEntryAreCounted(unittest.TestCase):
"""verify --platform recalbox --system nec-pc-engine printed no Core
files line while the pack held six geargrafx syscard copies: the gap
From 1b7ea4212f17196ba5d333de8ccb51800b6cd540 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:52:31 +0100
Subject: [PATCH 50/83] fix: tests write temporary files under tmp/
264 TemporaryDirectory() and mkdtemp() calls without dir= wrote to the
/tmp tmpfs, and a full tmpfs failed modules no change touched. The test
package now points tempfile and TMPDIR at tmp/tests, and sets
GIT_CEILING_DIRECTORIES there so git run in a scratch directory does
not find the checkout above it. The package test asserts both.
---
tests/__init__.py | 14 +++++++++++---
tests/test_audit_regressions.py | 7 ++++++-
wiki/testing-guide.md | 8 +++++---
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/tests/__init__.py b/tests/__init__.py
index bbe42a6ec..1540b4305 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -13,6 +13,7 @@ temporary directory instead of naming the missing parent.
from __future__ import annotations
import os
+import tempfile
from pathlib import Path
os.environ.setdefault("RETROBIOS_OFFLINE", "1")
@@ -22,9 +23,16 @@ os.environ.setdefault(
str(Path(__file__).resolve().parent.parent / "tmp" / "tests" / "probe.lock"),
)
-(Path(__file__).resolve().parent.parent / "tmp" / "tests").mkdir(
- parents=True, exist_ok=True
-)
+_SCRATCH = Path(__file__).resolve().parent.parent / "tmp" / "tests"
+_SCRATCH.mkdir(parents=True, exist_ok=True)
+# A TemporaryDirectory() without dir= landed in /tmp, a 4 GB tmpfs here: once
+# another run filled it, modules unrelated to any change failed with ENOSPC.
+# The default is the repository's tmp/, for this process and its children.
+os.environ["TMPDIR"] = str(_SCRATCH)
+tempfile.tempdir = str(_SCRATCH)
+# A scratch directory is not part of this checkout: git run inside one must
+# not walk up to the repository, as it could not from /tmp.
+os.environ["GIT_CEILING_DIRECTORIES"] = str(_SCRATCH)
# The installer's cache (the games index, what reading a card found) is the
# suite's own: a run never reads nor fills the one of the person running it.
os.environ.setdefault(
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 3df8850fe..388a7cd0c 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -206,11 +206,16 @@ class AModuleRunAloneHasItsScratchDirectory(unittest.TestCase):
)
proc = subprocess.run(
[sys.executable, "-I", "-c",
- "import sys; sys.path.insert(0, '.'); import tests"],
+ "import sys; sys.path.insert(0, '.'); import tests, tempfile, os;"
+ " print(tempfile.gettempdir()); print(os.environ['TMPDIR'])"],
cwd=clone, capture_output=True, text=True, timeout=60, check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr)
self.assertTrue((clone / "tmp" / "tests").is_dir())
+ # 264 TemporaryDirectory() calls without dir= wrote to the /tmp
+ # tmpfs, and a full tmpfs failed modules no change touched.
+ scratch = str((clone / "tmp" / "tests").resolve())
+ self.assertEqual(proc.stdout.split(), [scratch, scratch])
class ReleaseSigningRegressions(unittest.TestCase):
diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md
index 3ef512d15..1a9f64b74 100644
--- a/wiki/testing-guide.md
+++ b/wiki/testing-guide.md
@@ -9,9 +9,11 @@ The tests hold what users and platforms rely on: a pack holds what its
platform checks, the site states what the code does, the installer writes only
where it should.
-No test needs network access. Most build synthetic fixtures under the
-repository's `tmp/`, and modules that read real artifacts skip when those are
-absent. The test runner prints the count.
+No test needs network access. Most build synthetic fixtures, and every
+temporary directory lands under the repository's `tmp/tests/`:
+`tests/__init__.py` points `tempfile` and `TMPDIR` there, never at the `/tmp`
+tmpfs. Modules that read real artifacts skip when those are absent. The test
+runner prints the count.
## Running tests
From 47e0e8d120f8d091d36b3439729e73d8aff69bba Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:52:58 +0100
Subject: [PATCH 51/83] fix: database paths must be committed or ignored
The manifest guard compared repo_path with database.json only, so a
git mv under bios/ committed without regenerating either left both
naming the old path and every test passed. A new test requires each
database path to be tracked or gitignored, and a manifest entry whose
repo_path git neither holds nor ignores now fails as untracked.
---
tests/test_audit_regressions.py | 34 ++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 388a7cd0c..35e200ba0 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -2296,7 +2296,9 @@ class EveryManifestEntryIsFetchable(unittest.TestCase):
else "gitignored" if repo_path in ignored
else "untracked, never committed"
)
- if bool(entry.get("release_asset")) != (state == "gitignored"):
+ if state == "untracked, never committed" or (
+ bool(entry.get("release_asset")) != (state == "gitignored")
+ ):
wrong.append((entry["dest"], repo_path, state))
self.assertEqual(wrong, [], f"{name} picks the wrong source: {wrong[:3]}")
@@ -2310,6 +2312,36 @@ class EveryManifestEntryIsFetchable(unittest.TestCase):
self.skipTest("not a git checkout")
self.assertEqual(sorted(untracked)[:20], [], f"{len(untracked)} untracked files under bios/")
+ def test_every_database_path_is_committed_or_a_release_asset(self):
+ """A git mv under bios/ committed without regenerating anything left
+ database.json and the manifests agreeing on the old path: the tests
+ above compare them with each other, so all passed, and the installer
+ got a 404 (issue 78, with the database stale too)."""
+ database = ROOT / "database.json"
+ if not database.is_file():
+ self.skipTest("database.json not generated")
+ files = json.loads(database.read_text(encoding="utf-8"))["files"]
+ paths = {
+ path
+ for entry in files.values()
+ for path in [entry.get("path"), *(entry.get("paths") or [])]
+ if path
+ }
+ tracked = _git_paths("ls-files", "-z")
+ if tracked is None:
+ self.skipTest("not a git checkout")
+ outside = sorted(paths - tracked)
+ ignored = _git_paths("check-ignore", "-z", "--no-index", "--stdin", stdin=outside)
+ if ignored is None:
+ self.skipTest("not a git checkout")
+ stale = [path for path in outside if path not in ignored]
+ self.assertEqual(
+ stale[:20], [],
+ f"{len(stale)} database paths git neither holds nor ignores: "
+ "python scripts/generate_db.py --force --bios-dir bios --output database.json, "
+ "then the manifests",
+ )
+
class ReleaseAssetCriterion(unittest.TestCase):
"""What decides whether the installer fetches from the release is git, not size.
From 19dddedff6d6b1b986b606fdcd939dc9f59fb83f Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:53:26 +0100
Subject: [PATCH 52/83] fix: a data lock wait names its holder
A refresh blocked on a data directory lock printed only that another
run held it, then waited with no limit. The line now names the lock
file and the lsof command that shows its holder, and for a refresh,
the generate_pack --no-refresh-data and --offline runs that read the
cache without waiting.
---
scripts/refresh_data_dirs.py | 20 +++++++++++++++++++-
tests/test_refresh_data_dirs.py | 29 +++++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/scripts/refresh_data_dirs.py b/scripts/refresh_data_dirs.py
index 7b74f7be1..31def57cc 100644
--- a/scripts/refresh_data_dirs.py
+++ b/scripts/refresh_data_dirs.py
@@ -71,6 +71,24 @@ def cache_lock(
return _announced_lock(cache_dir.with_name(f".{cache_dir.name}.lock"), shared, cache_dir)
+def _wait_message(lock_path: Path, shared: bool, cache_dir: Path) -> str:
+ """Who to wait for, and, for a refresh, how not to.
+
+ The bare "another run holds it" named neither the lock nor its holder,
+ and the build waited with no limit.
+ """
+ message = (
+ f"waiting for {cache_dir}: another run holds {lock_path} "
+ f"(lsof {lock_path} names it)"
+ )
+ if not shared:
+ message += (
+ ". generate_pack.py --no-refresh-data, or --offline there and in"
+ " pipeline.py, builds from the cache as it is without waiting"
+ )
+ return message
+
+
@contextlib.contextmanager
def _announced_lock(lock_path: Path, shared: bool, cache_dir: Path) -> Iterator[None]:
"""file_lock, saying so when it has to wait.
@@ -90,7 +108,7 @@ def _announced_lock(lock_path: Path, shared: bool, cache_dir: Path) -> Iterator[
try:
fcntl.flock(handle, mode | fcntl.LOCK_NB)
except BlockingIOError:
- log.warning("waiting for %s: another run holds it", cache_dir)
+ log.warning(_wait_message(lock_path, shared, cache_dir))
fcntl.flock(handle, mode)
try:
yield
diff --git a/tests/test_refresh_data_dirs.py b/tests/test_refresh_data_dirs.py
index 42f21d122..dc38143ac 100644
--- a/tests/test_refresh_data_dirs.py
+++ b/tests/test_refresh_data_dirs.py
@@ -118,6 +118,35 @@ class RefreshConcurrency(unittest.TestCase):
self.assertTrue(finished, "the refresh waited for a reader")
self.assertEqual(result, [False])
+ def test_a_waiting_refresh_names_the_lock_and_the_way_around(self):
+ """"waiting for data/dolphin-sys: another run holds it" named
+ neither the lock nor its holder, and the build waited unbounded."""
+ import fcntl # noqa: PLC0415
+
+ self.cache.mkdir(parents=True)
+ lock_path = self.cache.with_name(".pak.lock")
+ entered = threading.Event()
+
+ def refresh() -> None:
+ with rdd.cache_lock(self.cache):
+ entered.set()
+
+ with open(lock_path, "a") as reader, self.assertLogs(rdd.log, "WARNING") as logs:
+ fcntl.flock(reader, fcntl.LOCK_SH)
+ worker = threading.Thread(target=refresh, daemon=True)
+ worker.start()
+ for _ in range(200):
+ if logs.records:
+ break
+ worker.join(timeout=0.05)
+ self.assertFalse(entered.is_set())
+ fcntl.flock(reader, fcntl.LOCK_UN)
+ worker.join(timeout=20)
+ self.assertTrue(entered.is_set())
+ message = logs.records[0].getMessage()
+ self.assertIn(f"lsof {lock_path}", message)
+ self.assertIn("--no-refresh-data", message)
+
def test_version_file_is_never_left_truncated(self):
Path(self.versions).parent.mkdir(parents=True)
Path(self.versions).write_text(json.dumps({"keep": {"sha": "1"}}))
From a1ddee8e5e395b6c472ff9d985f64a12519c8046 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:54:06 +0100
Subject: [PATCH 53/83] fix: a lock reader refuses a missing directory
artifact_lock created its directory even for a shared reader, so a
mistyped path given to --verify-packs or release_record was left as a
directory holding a .lock, and split_pack created the parent before
printing a bare errno. A reader now raises ArtifactDirectoryMissing,
which run_cli prints on one line, and split_pack checks its target
before taking the lock.
---
scripts/artifacts.py | 12 ++++++++++++
scripts/common.py | 3 ++-
scripts/split_pack.py | 4 ++++
tests/test_artifact_lock.py | 22 ++++++++++++++++++++++
4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/scripts/artifacts.py b/scripts/artifacts.py
index ef6818657..79643ae39 100644
--- a/scripts/artifacts.py
+++ b/scripts/artifacts.py
@@ -209,6 +209,10 @@ def _strip_timestamps(text: str) -> str:
class ArtifactLockBusy(RuntimeError):
"""Raised when another process already holds the artifact directory."""
+
+class ArtifactDirectoryMissing(FileNotFoundError):
+ """A reader named a directory that does not exist."""
+
# A run that holds artifact directories for its whole duration names them
# here, os.pathsep apart, for the steps it spawns: they would otherwise be
# refused by it. A pipeline holds the repository root and its --output-dir.
@@ -228,6 +232,14 @@ def artifact_lock(directory: str, exclusive: bool = True) -> Iterator[None]:
Writers take the lock exclusively, readers share it. On platforms
without flock the lock is a no-op.
"""
+ # A reader creating the directory it was pointed at left a typo behind
+ # as a directory holding a .lock, and the next run with the same typo
+ # no longer said the path did not exist.
+ if not exclusive and not os.path.isdir(directory):
+ raise ArtifactDirectoryMissing(
+ f"{directory}: no such directory, pass the --output-dir the packs "
+ "were written to (default dist/)"
+ )
try:
import fcntl
except ImportError:
diff --git a/scripts/common.py b/scripts/common.py
index 50c90874d..f1890d55c 100644
--- a/scripts/common.py
+++ b/scripts/common.py
@@ -3587,6 +3587,7 @@ from artifacts import ( # noqa: E402,F401
copy_file_atomic,
plain_file_mode,
set_plain_mode,
+ ArtifactDirectoryMissing,
ArtifactLockBusy,
artifact_lock,
hold_artifact_lock,
@@ -3634,7 +3635,7 @@ def run_cli(main: Callable[[], int | None]) -> None:
try:
code = main()
sys.stdout.flush()
- except (InputMissing, ArtifactLockBusy) as exc:
+ except (InputMissing, ArtifactLockBusy, ArtifactDirectoryMissing) as exc:
print(f"ERROR: {exc}", file=sys.stderr)
sys.exit(1)
except BrokenPipeError:
diff --git a/scripts/split_pack.py b/scripts/split_pack.py
index 9e830ff72..3df3fe866 100644
--- a/scripts/split_pack.py
+++ b/scripts/split_pack.py
@@ -338,6 +338,10 @@ def main() -> int:
# The packs are rewritten in place by generate_pack under this lock: a
# build running beside the split mixes its bytes into the pack being
# read, or writes a pack that the split then deletes.
+ if not args.target.exists():
+ print(f"Error: {args.target}: no such pack or directory, pass a pack or the "
+ "--output-dir generate_pack wrote (default dist/)", file=sys.stderr)
+ return 1
directory = args.target if args.target.is_dir() else args.target.parent
try:
with artifact_lock(str(directory)):
diff --git a/tests/test_artifact_lock.py b/tests/test_artifact_lock.py
index 612bd87d8..72804b1cb 100644
--- a/tests/test_artifact_lock.py
+++ b/tests/test_artifact_lock.py
@@ -61,6 +61,28 @@ class ArtifactLockTest(unittest.TestCase):
with artifact_lock(self.dir, exclusive=False):
pass
+ def test_a_reader_never_creates_the_directory(self):
+ """A mistyped --output-dir given to --verify-packs or release_record
+ was created holding a .lock, and the next run with the same typo no
+ longer said the path did not exist."""
+ from common import ArtifactDirectoryMissing # noqa: PLC0415
+
+ missing = os.path.join(self.dir, "sub", "dsit")
+ with self.assertRaises(ArtifactDirectoryMissing):
+ with artifact_lock(missing, exclusive=False):
+ pass
+ self.assertFalse(os.path.exists(os.path.join(self.dir, "sub")))
+
+ def test_split_refuses_a_missing_target_before_locking(self):
+ missing = Path(self.dir) / "sub" / "dsit"
+ proc = subprocess.run(
+ [sys.executable, "scripts/split_pack.py", str(missing)],
+ cwd=REPO_ROOT, capture_output=True, text=True, check=False, timeout=60,
+ )
+ self.assertEqual(proc.returncode, 1)
+ self.assertIn("no such pack or directory", proc.stderr)
+ self.assertFalse(missing.parent.exists())
+
def test_lock_is_released_on_exit(self):
with artifact_lock(self.dir):
pass
From a343be0da15df6e03f21966ea460db05a597e0ab Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:54:23 +0100
Subject: [PATCH 54/83] fix: validate_pr json says failed, not new
The JSON report put "outcome": "new" on every file without another
outcome, so a path that does not exist, or a file that failed a check,
was listed as a new contribution. A failed file now reads "failed".
---
scripts/validate_pr.py | 3 ++-
tests/test_validate_pr.py | 9 +++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/scripts/validate_pr.py b/scripts/validate_pr.py
index e3050f83c..59bd1c45a 100644
--- a/scripts/validate_pr.py
+++ b/scripts/validate_pr.py
@@ -847,7 +847,8 @@ def main() -> None:
{
"file": r.filepath,
"passed": r.passed,
- "outcome": r.outcome or "new",
+ # A file that failed, unread or refused, is not a new one.
+ "outcome": r.outcome or ("new" if r.passed else "failed"),
"destination": r.destination,
"sha1": r.sha1,
"md5": r.md5,
diff --git a/tests/test_validate_pr.py b/tests/test_validate_pr.py
index 642420795..5f631cd1b 100644
--- a/tests/test_validate_pr.py
+++ b/tests/test_validate_pr.py
@@ -522,6 +522,15 @@ class FlagsAreAppliedOrRefused(unittest.TestCase):
self.assertEqual(result.returncode, 2)
self.assertIn("not allowed with", result.stderr)
+ def test_a_failed_file_is_not_reported_new(self):
+ """A path that does not exist came out as "outcome": "new", and a
+ reader listing new contributions announced a BIOS nobody sent."""
+ import json # noqa: PLC0415
+
+ result = self._run("--json", "bios/nope.bin")
+ report = json.loads(result.stdout)
+ self.assertEqual([(r["passed"], r["outcome"]) for r in report], [(False, "failed")])
+
class AFileOutsideBiosIsToldWhereToGo(unittest.TestCase):
From bf206d5b42fab62ed1a820382c28472ff0fae120 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:55:26 +0100
Subject: [PATCH 55/83] feat: slots names who declares a collided path
A collision line named two files and neither the system declaring each
nor the one the pack ships, so the reader went back to the platform
file. find_collisions walks the systems in the builder's sorted order,
takes the builder's preferred declaration, and the line and the JSON
now name each system and the file packed. RetroDECK's bios/disk.rom
reads as the CoCo ROM packed, the PC-88 one left out, as its manifest
holds.
---
scripts/slots.py | 58 +++++++++++++++++++++++++++++++++++----------
tests/test_slots.py | 17 +++++++++++++
2 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/scripts/slots.py b/scripts/slots.py
index 8e7f826cd..0b69507d3 100644
--- a/scripts/slots.py
+++ b/scripts/slots.py
@@ -675,14 +675,23 @@ class Collision:
destination: str
resolved: list[str]
- # Each declaration with the file it resolved to, in the platform's order.
+ # Each declaration with the file it resolved to, in the builder's order.
declarations: list[tuple[dict, str | None]] = field(default_factory=list)
+ # The system of each declaration, in the same order.
+ systems: list[str] = field(default_factory=list)
+ # The file the pack ships at the destination, as the builder decides it.
+ shipped: str | None = None
def _collision_json(collision: Collision) -> dict:
return {
"destination": collision.destination,
"resolved": list(collision.resolved),
+ "shipped": collision.shipped,
+ "declarations": [
+ {"system": system, "name": entry.get("name", ""), "file": local}
+ for system, (entry, local) in zip(collision.systems, collision.declarations)
+ ],
}
@@ -702,19 +711,27 @@ def find_collisions(
CoCo disk ROM at one bios/disk.rom.
"""
fold = bool(config.get("case_insensitive_fs", False))
- by_dest: dict[str, list[dict]] = {}
- for system in (config.get("systems") or {}).values():
+ systems = config.get("systems") or {}
+ # The builder walks the systems sorted and lets a hash-constrained
+ # declaration that resolves by content take the path: the same order
+ # and the same choice say which file ships.
+ preferred = set(
+ preferred_entries(systems, db, "bios", "", False, zip_contents, True).values()
+ )
+ by_dest: dict[str, list[tuple[str, dict]]] = {}
+ for sys_id, system in sorted(systems.items()):
for entry in system.get("files") or []:
if not isinstance(entry, dict):
continue
dest = entry.get("destination") or entry.get("name") or ""
if dest:
- by_dest.setdefault(_normalize(dest, fold), []).append(entry)
+ by_dest.setdefault(_normalize(dest, fold), []).append((sys_id, entry))
collisions = []
- for key, entries in sorted(by_dest.items()):
- if len(entries) < 2:
+ for key, claims in sorted(by_dest.items()):
+ if len(claims) < 2:
continue
+ entries = [entry for _sys_id, entry in claims]
resolved = []
declarations = []
for entry in entries:
@@ -734,8 +751,18 @@ def find_collisions(
# also names the first one's file.
if any(_accepted_by_all(path, entries, db) for path in resolved):
continue
+ shipped = next(
+ (local for entry, local in declarations if local and id(entry) in preferred),
+ resolved[0],
+ )
collisions.append(
- Collision(destination=key, resolved=resolved, declarations=declarations)
+ Collision(
+ destination=key,
+ resolved=resolved,
+ declarations=declarations,
+ systems=[sys_id for sys_id, _entry in claims],
+ shipped=shipped,
+ )
)
return collisions
@@ -863,11 +890,18 @@ def _same_file_family(paths: list[str]) -> bool:
def format_collision(collision: Collision) -> str:
- """One line naming the destination and the files fighting for it."""
- return (
- f"{collision.destination}: declared for "
- + " and for ".join(collision.resolved)
- )
+ """One line naming the destination, which system declares which file,
+ and the one the pack ships there."""
+ owners: dict[str, list[str]] = {}
+ for system, (_entry, local) in zip(collision.systems, collision.declarations):
+ if local and system not in owners.setdefault(local, []):
+ owners[local].append(system)
+ parts = [
+ f"{path} ({', '.join(owners[path])}) "
+ + ("packed" if path == collision.shipped else "left out")
+ for path in collision.resolved
+ ]
+ return f"{collision.destination}: " + ", ".join(parts)
def format_conflict(conflict: Conflict) -> str:
diff --git a/tests/test_slots.py b/tests/test_slots.py
index 44afbe8e0..64dd87669 100644
--- a/tests/test_slots.py
+++ b/tests/test_slots.py
@@ -509,6 +509,23 @@ class TestSelfContradictingDestinations(unittest.TestCase):
self.assertEqual(len(collisions), 1)
self.assertEqual(len(collisions[0].resolved), 2)
+ def test_the_line_names_each_system_and_the_file_packed(self):
+ """The line named two files and neither the system that declares
+ each nor the one the pack ships: the reader went to the YAML."""
+ config = {"systems": {
+ "zeta": {"files": [{"name": "IPL.bin", "destination": "disk.rom",
+ "md5": "m" * 32}]},
+ "alpha": {"files": [{"name": "IPL.bin", "destination": "disk.rom",
+ "md5": "n" * 32}]},
+ }}
+ collision = slots.find_collisions(config, REGIONS_DB)[0]
+ line = slots.format_collision(collision)
+ packed, left = collision.resolved
+ # The builder walks the systems sorted: alpha's declaration ships.
+ self.assertIn(f"{packed} (alpha) packed", line)
+ self.assertIn(f"{left} (zeta) left out", line)
+ self.assertEqual(collision.shipped, packed)
+
def test_one_archive_named_by_its_inner_roms_is_not_a_collision(self):
# The documented zipped_file pattern: several md5s, one archive.
config = self._config(
From ea58f6f5cecd53e3303e255d44a80a55bff600d0 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:55:51 +0100
Subject: [PATCH 56/83] fix: refresh_stale --dry-run honours --json
--dry-run printed its text plan and returned before --json was read,
so a caller parsing the output as JSON failed. With both flags the plan
is printed as JSON: planned jobs with their commands and follow-ups,
the rows left to a human, and the count ignored.
---
scripts/refresh_stale.py | 18 +++++++++++++++++-
tests/test_refresh_stale.py | 22 ++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/scripts/refresh_stale.py b/scripts/refresh_stale.py
index 4e79e70a5..8e1221ec2 100755
--- a/scripts/refresh_stale.py
+++ b/scripts/refresh_stale.py
@@ -579,7 +579,7 @@ def main() -> int:
parser.add_argument(
"--json",
action="store_true",
- help="machine-readable summary (jobs, surfaced, ignored)",
+ help="machine-readable summary (jobs, surfaced, ignored), the plan with --dry-run",
)
parser.add_argument(
"--findings",
@@ -618,6 +618,22 @@ def main() -> int:
registry = _load_platform_registry()
jobs, surfaced, ignored = plan_jobs(findings, registry)
+ if args.dry_run and args.json:
+ print(json.dumps({
+ "planned": [
+ {
+ "area": job.area,
+ "subject": job.subject,
+ "command": job.command,
+ "after": sorted(job.after),
+ "then": [list(command) for command in job.then],
+ }
+ for job in sorted(jobs, key=lambda j: (j.area, j.subject))
+ ],
+ "surfaced": surfaced,
+ "ignored_count": len(ignored),
+ }, indent=2))
+ return 0
if args.dry_run:
print(f"\n[plan] {len(jobs)} refreshable, {len(surfaced)} manual, "
f"{len(ignored)} already clean/skipped")
diff --git a/tests/test_refresh_stale.py b/tests/test_refresh_stale.py
index 3310d068e..dedd6629b 100644
--- a/tests/test_refresh_stale.py
+++ b/tests/test_refresh_stale.py
@@ -234,6 +234,28 @@ class SavedFindings(unittest.TestCase):
findings = rs.load_findings(path, ("data", "catalogs"))
self.assertEqual([f["subject"] for f in findings], ["dolphin-sys"])
+ def test_dry_run_json_prints_the_plan_as_json(self):
+ """--dry-run --json printed the text plan, and a caller parsing it
+ as JSON failed on the first line."""
+ import json # noqa: PLC0415
+ import subprocess # noqa: PLC0415
+
+ with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp" / "tests") as directory:
+ path = Path(directory) / "freshness.json"
+ path.write_text(json.dumps([
+ finding("catalogs", "mame recipes"), finding("coreinfo", "anybor"),
+ ]), encoding="utf-8")
+ proc = subprocess.run(
+ [sys.executable, "scripts/refresh_stale.py", "--findings", str(path),
+ "--dry-run", "--json"],
+ cwd=REPO_ROOT, capture_output=True, text=True, check=False, timeout=120,
+ )
+ self.assertEqual(proc.returncode, 0, proc.stderr)
+ plan = json.loads(proc.stdout)
+ self.assertEqual([(j["area"], j["subject"]) for j in plan["planned"]],
+ [("catalogs", "mame recipes")])
+ self.assertEqual([f["subject"] for f in plan["surfaced"]], ["anybor"])
+
def test_a_report_that_is_not_a_list_is_refused(self):
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp" / "tests") as directory:
path = Path(directory) / "freshness.json"
From 8b7e5ceef4a14900e26d260f73bcff9398a91f46 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:56:14 +0100
Subject: [PATCH 57/83] fix: refresh_stale knows the romfolders area
check_freshness gained a romfolders area and refresh_stale did not:
its rows were dropped from a saved report without a word, and --only
romfolders was refused. A rom-folder pin is moved by hand, so the area
is listed for a human, a test holds the two area lists equal, and the
--only help names every area.
---
scripts/refresh_stale.py | 11 ++++++++---
tests/test_refresh_stale.py | 10 ++++++++++
wiki/tools.md | 5 ++++-
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/scripts/refresh_stale.py b/scripts/refresh_stale.py
index 8e1221ec2..960b2c3da 100755
--- a/scripts/refresh_stale.py
+++ b/scripts/refresh_stale.py
@@ -34,7 +34,9 @@ has ended, and its export is rewritten even when no row named it.
Surfaced only (no refresh): data rows that are not a _data_dirs.yml key
(the registry itself, buildbot assets it does not track), coreinfo gaps, redump/no-intro/tosec packs,
-CI pins (install.py SHA-256, PyPI, pinned actions), profile_sync. Each needs
+CI pins (install.py SHA-256, PyPI, pinned actions), profile_sync, rom-folder
+pins (moved by hand, then python -m scripts.scraper.romfolders --setup NAME
+reads them again). Each needs
a human read (new .info file, manual DAT download, PyPI version bump).
Usage:
@@ -65,7 +67,9 @@ PLATFORMS_REGISTRY = REPO_ROOT / "platforms" / "_registry.yml"
DATA_DIRS_REGISTRY = REPO_ROOT / "platforms" / "_data_dirs.yml"
AUTO_AREAS = ("platforms", "native", "targets", "data", "catalogs")
-MANUAL_AREAS = ("coreinfo", "ci", "profiles")
+# A rom-folder pin is moved by hand in platforms/romfolders/_sources/,
+# then `python -m scripts.scraper.romfolders --setup NAME` reads it again.
+MANUAL_AREAS = ("romfolders", "coreinfo", "ci", "profiles")
JOB_TIMEOUT = 1800 # 30 minutes per refresher, scrapers rarely exceed 10
@@ -563,7 +567,8 @@ def main() -> int:
parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.split("\n\n")[0])
parser.add_argument(
"--only",
- help="comma-separated areas to check: " + ",".join(AUTO_AREAS),
+ help="comma-separated areas to check: " + ",".join(AUTO_AREAS)
+ + " (refreshed), " + ",".join(MANUAL_AREAS) + " (listed for a human)",
)
parser.add_argument(
"--dry-run",
diff --git a/tests/test_refresh_stale.py b/tests/test_refresh_stale.py
index dedd6629b..a1c463b0c 100644
--- a/tests/test_refresh_stale.py
+++ b/tests/test_refresh_stale.py
@@ -256,6 +256,16 @@ class SavedFindings(unittest.TestCase):
[("catalogs", "mame recipes")])
self.assertEqual([f["subject"] for f in plan["surfaced"]], ["anybor"])
+ def test_every_area_check_freshness_reports_is_known(self):
+ """romfolders was added to check_freshness and not here: its rows
+ were dropped from a saved report without a word, and --only
+ romfolders was refused."""
+ import check_freshness # noqa: PLC0415
+
+ self.assertEqual(set(check_freshness.AREAS), set(rs.AUTO_AREAS + rs.MANUAL_AREAS))
+ jobs, surfaced, _ = rs.plan_jobs([finding("romfolders", "muos")], REGISTRY, {})
+ self.assertEqual((jobs, [f["subject"] for f in surfaced]), ([], ["muos"]))
+
def test_a_report_that_is_not_a_list_is_refused(self):
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp" / "tests") as directory:
path = Path(directory) / "freshness.json"
diff --git a/wiki/tools.md b/wiki/tools.md
index dab60e5b0..f566efe53 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -760,7 +760,10 @@ committed.
Rows that need a decision are listed and never run: a buildbot core with no
profile, a new `.info` file, the Redump, No-Intro and TOSEC packs, the CI
-pins, and `profile_sync`. A failed scraper leaves its cached original
+pins, `profile_sync`, and a rom-folder pin (moved by hand in
+`platforms/romfolders/_sources/`, then `python -m scripts.scraper.romfolders
+--setup NAME` reads it again). `--dry-run --json` prints the plan as JSON.
+A failed scraper leaves its cached original
untouched. Each job writes its output to `tmp/refresh_stale/`, and a GitHub
token is taken from `GITHUB_TOKEN` or from `gh auth token`.
From 320db754901b4b5cd39ddb4a674f54f754ad8292 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:56:32 +0100
Subject: [PATCH 58/83] fix: check_freshness aligns details after remotes
render padded the local value but not the remote one, so in an area
where some rows carry a remote value their detail started fifteen
columns later than the rows without one. The remote value is padded to
its column, and a row without one leaves the same blank span.
---
scripts/check_freshness.py | 15 +++++++++------
tests/test_check_freshness.py | 13 +++++++++++++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py
index 3f703d768..2fbee0d48 100644
--- a/scripts/check_freshness.py
+++ b/scripts/check_freshness.py
@@ -1760,15 +1760,18 @@ def render(findings: list[Finding]) -> str:
# Columns are padded, never cut: the profile_sync row says in its
# local and remote values what to re-read, and lost the end of it.
local_width = min(max((len(f.local) for f in rows), default=0), 44)
+ remote_width = min(max((len(f.remote) for f in rows), default=0), 44)
+ # The arrow and the remote value, or as many blanks where a row has none.
+ remote_span = 4 + remote_width if remote_width else 0
for f in rows:
cols = f" {f.status:7} {f.subject:{width}}"
if f.remote:
- cols += f" {f.local:{local_width}} -> {f.remote}"
- elif f.local or (f.detail and local_width):
- # An arrow pointing at nothing read as a lost value. An empty
- # local value still takes its column, or the detail starts
- # where the other rows show theirs.
- cols += f" {f.local:{local_width}}"
+ cols += f" {f.local:{local_width}} -> {f.remote:{remote_width}}"
+ elif f.local or (f.detail and (local_width or remote_span)):
+ # An arrow pointing at nothing read as a lost value. Empty
+ # local and remote values still take their columns, or the
+ # detail starts where the other rows show theirs.
+ cols += f" {f.local:{local_width}}" + " " * remote_span
if f.detail:
cols += f" {f.detail}"
lines.append(cols.rstrip())
diff --git a/tests/test_check_freshness.py b/tests/test_check_freshness.py
index 9fedcc590..829062f66 100644
--- a/tests/test_check_freshness.py
+++ b/tests/test_check_freshness.py
@@ -742,6 +742,19 @@ class RowsSayAllTheyStandFor(unittest.TestCase):
rows = [line for line in text.splitlines() if line.startswith(" STALE")]
self.assertEqual(rows[0].index("no longer"), rows[1].index("is not what"))
+ def test_a_remote_value_keeps_the_detail_column(self):
+ """A row with a remote value pushed its detail past the column the
+ rows without one used, in [coreinfo] by some fifteen characters."""
+ text = cf.render([
+ cf.Finding("coreinfo", "anybor", cf.STALE, detail="no profile claims"),
+ cf.Finding("coreinfo", "amiberry", cf.STALE, local="e5d1f0f9a143",
+ remote="ae545d85c06f", detail=".info changed"),
+ cf.Finding("coreinfo", "x", cf.STALE, local="abc", remote="d", detail="third"),
+ ])
+ rows = [line for line in text.splitlines() if line.startswith(" STALE")]
+ columns = {row.index(word) for row, word in zip(rows, ("no profile", ".info", "third"))}
+ self.assertEqual(len(columns), 1, rows)
+
def test_json_carries_every_unresolved_name(self):
missing = {f"core{i:02d}": [] for i in range(50)}
(row,) = cf._unresolved_findings("retropie", missing)
From 5407eafe5b3fb34ebd8dc0e1cfb14f1d588c1360 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:57:15 +0100
Subject: [PATCH 59/83] feat: validate_pr reads an undeclared ZIP's files
A card's BIOS folder zipped to upload it was hashed as one file and
reported not recognised, its contributor asked where the dump came from
and told to place it under bios/. A ZIP no list or profile declares as a
whole is now read member by member: each is named held, declared and not
held, or not recognised, and the contributor is asked for the files
unzipped. A declared archive (a MAME or FBNeo set) is never opened.
---
scripts/validate_pr.py | 77 ++++++++++++++++++++++++++++++++++++---
tests/test_validate_pr.py | 23 ++++++++++++
2 files changed, 95 insertions(+), 5 deletions(-)
diff --git a/scripts/validate_pr.py b/scripts/validate_pr.py
index 59bd1c45a..a07140fb6 100644
--- a/scripts/validate_pr.py
+++ b/scripts/validate_pr.py
@@ -18,6 +18,7 @@ Outputs a structured report suitable for PR comments.
from __future__ import annotations
import argparse
+import hashlib
import json
import os
import re
@@ -25,6 +26,7 @@ import shutil
import subprocess
import sys
import urllib.parse
+import zipfile
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
@@ -335,6 +337,53 @@ def load_profile_hashes(
return known
+def _archive_members(
+ filepath: str, db: dict | None, platform_hashes: dict, profile_hashes: dict
+) -> list[str] | None:
+ """What each file of a ZIP is, None when filepath is not a ZIP.
+
+ Read only for an archive no list declares as a whole: MAME and FBNeo
+ sets are ZIP BIOS files in their own right.
+ """
+ if not zipfile.is_zipfile(filepath):
+ return None
+ held = (db or {}).get("files", {})
+ described = []
+ try:
+ with zipfile.ZipFile(filepath) as archive:
+ for info in archive.infolist():
+ if info.is_dir():
+ continue
+ if info.file_size > MAX_FILE_SIZE:
+ described.append(f"`{info.filename}` too large to read here")
+ continue
+ sha1, md5 = hashlib.sha1(), hashlib.md5()
+ with archive.open(info) as handle:
+ for chunk in iter(lambda: handle.read(1 << 20), b""):
+ sha1.update(chunk)
+ md5.update(chunk)
+ sha1_hex, md5_hex = sha1.hexdigest(), md5.hexdigest()
+ crc = f"{info.CRC:08x}"
+ if sha1_hex in held:
+ state = f"already held at `{held[sha1_hex]['path']}`"
+ elif (
+ sha1_hex in platform_hashes.get("sha1", set())
+ or md5_hex in platform_hashes.get("md5", set())
+ or (crc, info.file_size) in platform_hashes.get("crc32", set())
+ or profile_hashes.get("sha1", {}).get(sha1_hex)
+ or profile_hashes.get("md5", {}).get(md5_hex)
+ or profile_hashes.get("crc32", {}).get((crc, info.file_size))
+ ):
+ state = "declared and not held"
+ else:
+ state = "not recognised"
+ described.append(f"`{info.filename}` {state}")
+ except (zipfile.BadZipFile, RuntimeError, OSError) as exc:
+ # An encrypted member raises RuntimeError.
+ described.append(f"unreadable ({exc})")
+ return described
+
+
def validate_file(
filepath: str,
db: dict | None,
@@ -446,6 +495,8 @@ def validate_file(
or profile_hashes.get("crc32", {}).get((result.crc32, None))
)
+ # The files of a ZIP no list declares whole, when the upload is one.
+ members: list[str] | None = None
if sha1_known:
result.add_check(True, "SHA1 matches known platform requirement")
elif md5_known:
@@ -466,11 +517,26 @@ def validate_file(
)
else:
result.outcome = "unknown"
- result.add_warning(
- "Not recognised: no platform list or emulator profile declares this "
- f"file. Say in the {'issue' if too_large else 'pull request'} which "
- "emulator reads it, for which system, and where the dump comes from"
+ members = None if too_large else _archive_members(
+ filepath, db, platform_hashes, profile_hashes
)
+ if members is not None:
+ # A folder zipped to upload many files at once was hashed as one
+ # file and its contributor asked where that dump came from.
+ shown = "; ".join(members[:10]) + (
+ f"; and {len(members) - 10} more" if len(members) > 10 else ""
+ )
+ result.add_warning(
+ "A ZIP no platform list or emulator profile declares as a whole: "
+ "add the files it holds, unzipped, not the archive. Inside: "
+ + (shown or "nothing")
+ )
+ else:
+ result.add_warning(
+ "Not recognised: no platform list or emulator profile declares this "
+ f"file. Say in the {'issue' if too_large else 'pull request'} which "
+ "emulator reads it, for which system, and where the dump comes from"
+ )
normalized = os.path.normpath(relative)
# A platform's declaration first, then a profile's: most files the gaps
@@ -503,7 +569,8 @@ def validate_file(
result.add_check(True, f"Correct placement: bios/{parts[1]}/{parts[2]}/")
else:
result.add_warning("File should be in bios/Manufacturer/Console/ structure")
- elif result.outcome == "held":
+ elif result.outcome == "held" or members is not None:
+ # Nothing to place: a copy, or an archive whose files go in unzipped.
pass
elif expected_folders:
# The contributor asks before forking: say where it goes.
diff --git a/tests/test_validate_pr.py b/tests/test_validate_pr.py
index 5f631cd1b..68e4f5d3b 100644
--- a/tests/test_validate_pr.py
+++ b/tests/test_validate_pr.py
@@ -269,6 +269,29 @@ class HashRecognition(_Fixture):
self.assertIn("no platform list or emulator profile declares this file", markdown)
self.assertIn("which emulator reads it", markdown)
+ def test_a_zip_of_bios_files_is_read_member_by_member(self):
+ """A card's BIOS folder zipped to upload it was hashed as one file,
+ and its contributor was asked where that dump came from."""
+ import hashlib # noqa: PLC0415
+ import zipfile # noqa: PLC0415
+
+ held, declared = b"HELD BIOS", b"DECLARED BIOS"
+ with zipfile.ZipFile(self.tmp / "mybios.zip", "w") as archive:
+ archive.writestr("scph5501.bin", held)
+ archive.writestr("sub/declared.bin", declared)
+ archive.writestr("other.bin", b"noise")
+ db = {"files": {hashlib.sha1(held).hexdigest(): {"path": "bios/Sony/PS/scph5501.bin"}}}
+ known = {**EMPTY_HASHES, "md5": {hashlib.md5(declared).hexdigest()}}
+ result = validate_pr.validate_file("mybios.zip", db, known)
+ markdown = result.to_markdown()
+ self.assertEqual(result.outcome, "unknown")
+ self.assertIn("unzipped, not the archive", markdown)
+ self.assertIn("`scph5501.bin` already held at `bios/Sony/PS/scph5501.bin`", markdown)
+ self.assertIn("`sub/declared.bin` declared and not held", markdown)
+ self.assertIn("`other.bin` not recognised", markdown)
+ self.assertNotIn("where the dump comes from", markdown)
+ self.assertNotIn("Place it in", markdown)
+
def test_a_duplicate_of_a_known_file_is_reported(self):
"""A copy of a held file passed, and was sent to the folder that
already holds it."""
From 01ce92232d3aa673881f52db55f51b332c4644b2 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:58:40 +0100
Subject: [PATCH 60/83] docs: say how an uploaded ZIP is read
CONTRIBUTING and the site's contributing page now say that a ZIP no
list declares as a whole is read file by file, and that the files go in
unzipped.
---
CONTRIBUTING.md | 4 ++++
scripts/generate_readme.py | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 928bd71f4..965d1a80a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -22,6 +22,10 @@ the most useful contribution.
hash differs from the one already held under its name goes to that folder's
`.variants/`.
+A ZIP that no list declares as a whole is read file by file, and the report
+says which of them the collection already holds: upload the files
+themselves, unzipped.
+
From a clone, the file goes to `bios/Manufacturer/Console/filename`, and
`python scripts/validate_pr.py path/to/file` names that folder for a file still
outside `bios/`, and `--place` copies it there under its declared name. Given a
diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py
index 5418e4889..0a9d8e6d8 100644
--- a/scripts/generate_readme.py
+++ b/scripts/generate_readme.py
@@ -941,6 +941,10 @@ the most useful contribution.
hash differs from the one already held under its name goes to that folder's
`.variants/`.
+A ZIP that no list declares as a whole is read file by file, and the report
+says which of them the collection already holds: upload the files
+themselves, unzipped.
+
From a clone, the file goes to `bios/Manufacturer/Console/filename`, and
`python scripts/validate_pr.py path/to/file` names that folder for a file still
outside `bios/`, and `--place` copies it there under its declared name. Given a
From 725325f0a159a39a7dea64102edb8c37659814ac Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:59:10 +0100
Subject: [PATCH 61/83] fix: announce a data tree at its archive size
A tarball tree was announced at its extracted size: yaps2 at 6.5 MB for a 21.2 MB download, Cemu's game profiles at 9.9 KB for 21.4 MB. refresh_data_dirs records the size of each archive it downloads (a tree current from before is measured, not refetched), the install lists carry it as archive_size, and the plan, the menu and the data event count it.
---
install.ps1 | 2 +-
install.py | 32 ++++++++++---
install.sh | 2 +-
install/amberelec.json | 12 +++--
install/batocera.json | 6 ++-
install/emudeck.json | 27 +++++++----
install/emuelec.json | 15 ++++---
install/knulli.json | 12 +++--
install/lakka.json | 21 ++++++---
install/launchers/index.json | 16 +++----
install/myminui.json | 14 +++---
install/nextui.json | 11 +++--
install/recalbox.json | 6 ++-
install/retroarch.json | 30 ++++++++-----
install/retrobat.json | 9 ++--
install/retrodeck.json | 15 ++++---
install/retropie.json | 18 +++++---
install/rocknix.json | 30 ++++++++-----
schemas/install-manifest.schema.json | 5 +++
scripts/generate_pack.py | 16 ++++++-
scripts/refresh_data_dirs.py | 67 +++++++++++++++++++++++++---
tests/test_install.py | 31 +++++++++++++
tests/test_refresh_data_dirs.py | 49 +++++++++++++++++++-
wiki/installer.md | 9 ++--
24 files changed, 352 insertions(+), 103 deletions(-)
diff --git a/install.ps1 b/install.ps1
index 412a6456e..7225221c0 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51"
+ $defaultInstallSha256 = "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index feabcc09e..8a4f6cb3c 100644
--- a/install.py
+++ b/install.py
@@ -3708,6 +3708,9 @@ def _check_data_directory(entry: object, where: str) -> None:
strip = entry.get("strip_components", 0)
if not isinstance(strip, int) or isinstance(strip, bool) or not 0 <= strip <= 16:
raise ValueError(f"{where}.strip_components is invalid")
+ size = entry.get("archive_size", 1)
+ if not isinstance(size, int) or isinstance(size, bool) or size < 1:
+ raise ValueError(f"{where}.archive_size is invalid")
if kind == "tarball" and (
not isinstance(entry.get("source_path"), str) or not entry["source_path"]
):
@@ -6873,11 +6876,12 @@ def _print_plan(
# files, and 2636 data files" read as two kinds of one thing. The kinds
# follow, adding up to it.
total = counts.files + tree_files
- parts = ([f"{_plural(total, 'file')} ({format_size(counts.size + tree_counts.size)})"]
+ tree_bytes = sum(data_fetch_bytes(entry, needed) for entry, needed in trees)
+ parts = ([f"{_plural(total, 'file')} ({format_size(counts.size + tree_bytes)})"]
if total else [])
split = parts_words(counts if (manifest or {}).get("categorized")
else tally({"size": e.get("size")} for e in to_download),
- tree_files, tree_counts.size)
+ tree_files, tree_bytes)
if split and trees:
split += f", the data files extracted from {_plural(len(trees), 'archive')}"
# A pack is copied from, not downloaded: "Would download 23 files" was
@@ -6952,8 +6956,11 @@ def _print_plan(
"every system and its files.")
for entry, needed in trees:
source = LOCAL.pack.name if LOCAL.pack is not None else entry["url"]
+ fetched = data_fetch_bytes(entry, needed)
+ archive = ("" if fetched == sum(meta.get("size", 0) for meta in needed.values())
+ else f" (a {format_size(fetched)} archive)")
print(f" {term.bold(entry['ref'] + ' data')} {_sized(list(needed.values()))}, "
- f"from {source}")
+ f"from {source}{archive}")
for folder, (count, size) in sorted((kept or {}).items()):
print(f"\n Would keep {_plural(count, 'file')} you have ({format_size(size)}), "
f"whose contents differ, in {folder}")
@@ -7184,6 +7191,19 @@ def data_directory_state(entry: dict, bios_path: Path,
return root, needed, present
+def data_fetch_bytes(entry: dict, needed: dict[str, dict]) -> int:
+ """What getting a tree's missing files costs: its source archive, which
+ comes whole for one file, or from a pack the files themselves. A list
+ that records no archive size gives the files' own sizes: a tarball whose
+ tree is 10 KB was announced as 10 KB and was a download of 21 MB."""
+ if not needed:
+ return 0
+ size = entry.get("archive_size")
+ if LOCAL.pack is None and isinstance(size, int) and size > 0:
+ return size
+ return sum(meta.get("size", 0) for meta in needed.values())
+
+
def install_data_directory(entry: dict, bios_path: Path,
state: tuple[Path, dict[str, dict], int] | None = None,
progress: Progress | None = None) -> dict:
@@ -8963,7 +8983,7 @@ def found_head(files: list[dict], trees: list[dict], bios_path: Path) -> str:
for tree in trees:
_root, wanted, _present = data_directory_state(tree, bios_path, remember=True)
data += len(wanted)
- data_bytes += sum(meta.get("size", 0) for meta in wanted.values())
+ data_bytes += data_fetch_bytes(tree, wanted)
left = [entry for entry in needed if id(entry) not in copies]
rest = len(left) + data
where = ", ".join(f"{count} found in {_last_name(label)}"
@@ -15683,8 +15703,8 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
plat_name, manifest, bios_path, files, up_to_date, mismatched,
sum(len(state[1]) for _entry, state in data_states), len(omitted_files),
chosen=selection[0] if selection else None,
- data_bytes=sum(meta.get("size", 0) for _entry, state in data_states
- for meta in state[1].values()),
+ data_bytes=sum(data_fetch_bytes(entry, state[1])
+ for entry, state in data_states),
)
emit_copies(plat_name, to_download, copies, bios_index, bios_path, files)
emit_unreadable(plat_name, unread)
diff --git a/install.sh b/install.sh
index c8cba304a..fe3d4fd6e 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51"
+DEFAULT_INSTALL_SHA256="567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/amberelec.json b/install/amberelec.json
index 745e5792b..51f5a9028 100644
--- a/install/amberelec.json
+++ b/install/amberelec.json
@@ -63489,7 +63489,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "fbneo-cheats",
@@ -77218,7 +77219,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -77451,7 +77453,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -77823,7 +77826,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
}
]
}
\ No newline at end of file
diff --git a/install/batocera.json b/install/batocera.json
index 8c24297c0..a5ecfcb19 100644
--- a/install/batocera.json
+++ b/install/batocera.json
@@ -225291,7 +225291,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -225524,7 +225525,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
}
],
"save_directory": {
diff --git a/install/emudeck.json b/install/emudeck.json
index c1d09d585..32f4ed6a2 100644
--- a/install/emudeck.json
+++ b/install/emudeck.json
@@ -100486,7 +100486,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "dinothawr",
@@ -100934,7 +100935,8 @@
"size": 105
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 5752250
},
{
"ref": "dirksimple",
@@ -100990,7 +100992,8 @@
"size": 12988
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 175384
},
{
"ref": "dolphin-sys",
@@ -109666,7 +109669,8 @@
"strip_components": 2,
"exclude": [
"Themes"
- ]
+ ],
+ "archive_size": 3197914
},
{
"ref": "fbneo-cheats",
@@ -123395,7 +123399,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -123628,7 +123633,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -124000,7 +124006,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "lrps2",
@@ -124016,7 +124023,8 @@
"size": 1814032
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 318896
},
{
"ref": "yaps2-resources",
@@ -124476,7 +124484,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
],
"save_directory": {
diff --git a/install/emuelec.json b/install/emuelec.json
index 8135201bd..e9709f639 100644
--- a/install/emuelec.json
+++ b/install/emuelec.json
@@ -69309,7 +69309,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "dinothawr",
@@ -69757,7 +69758,8 @@
"size": 105
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 5752250
},
{
"ref": "fbneo-cheats",
@@ -83486,7 +83488,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -83719,7 +83722,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -84091,7 +84095,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
}
]
}
\ No newline at end of file
diff --git a/install/knulli.json b/install/knulli.json
index 25b3ccce4..4e70dab7f 100644
--- a/install/knulli.json
+++ b/install/knulli.json
@@ -157933,7 +157933,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -158166,7 +158167,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "lrps2",
@@ -158182,7 +158184,8 @@
"size": 1814032
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 318896
},
{
"ref": "ppsspp-assets",
@@ -158870,7 +158873,8 @@
"size": 15005
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 9844388
}
],
"save_directory": {
diff --git a/install/lakka.json b/install/lakka.json
index 093e07996..5866fe5db 100644
--- a/install/lakka.json
+++ b/install/lakka.json
@@ -115932,7 +115932,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "cemu-gameprofiles",
@@ -116888,7 +116889,8 @@
"size": 36
}
},
- "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default"
+ "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default",
+ "archive_size": 21360579
},
{
"ref": "dirksimple",
@@ -116944,7 +116946,8 @@
"size": 12988
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 175384
},
{
"ref": "fbneo-cheats",
@@ -130673,7 +130676,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -130906,7 +130910,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -131278,7 +131283,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "yaps2-resources",
@@ -131738,7 +131744,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
],
"save_directory": {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index cd32da514..acfb61130 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1107258,
- "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
+ "size": 1108265,
+ "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1160885,
- "sha256": "5ccc4ec3df34a1fef96caea9e84218de1fb92331664047c36d6863c11973dc3d"
+ "size": 1161892,
+ "sha256": "1031750dcd599e0c4dd2e6c39296b3bcada68494a4837ad442150da64b67a55c"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1107258,
- "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
+ "size": 1108265,
+ "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1107258,
- "sha256": "3aa392c9c4fd50ab2a8474bb71ef11be45945964fb147b2ade45296461c87f51",
+ "size": 1108265,
+ "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
"executable": false
},
{
diff --git a/install/myminui.json b/install/myminui.json
index 919ecf4b1..85de7b9bc 100644
--- a/install/myminui.json
+++ b/install/myminui.json
@@ -6,7 +6,7 @@
"platform": "myminui",
"display_name": "MyMinUI",
"version": "2026-08-09",
- "generated": "2026-11-05T18:33:47Z",
+ "generated": "2026-11-05T23:59:37Z",
"base_destination": "",
"detect": [
{
@@ -18957,7 +18957,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-cheats",
@@ -32686,7 +32687,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -32919,7 +32921,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "fbneo-samples",
@@ -33152,7 +33155,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
}
]
}
\ No newline at end of file
diff --git a/install/nextui.json b/install/nextui.json
index d38175219..4518d3d5c 100644
--- a/install/nextui.json
+++ b/install/nextui.json
@@ -6,7 +6,7 @@
"platform": "nextui",
"display_name": "NextUI",
"version": "2026-10-20",
- "generated": "2026-11-05T18:33:47Z",
+ "generated": "2026-11-05T23:59:37Z",
"base_destination": "",
"detect": [
{
@@ -5635,7 +5635,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "fbneo-cheats",
@@ -19364,7 +19365,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -19597,7 +19599,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
}
]
}
\ No newline at end of file
diff --git a/install/recalbox.json b/install/recalbox.json
index b947571f5..9b97c9d50 100644
--- a/install/recalbox.json
+++ b/install/recalbox.json
@@ -62833,7 +62833,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -63066,7 +63067,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
}
],
"save_directory": {
diff --git a/install/retroarch.json b/install/retroarch.json
index 166d197d3..11b60b965 100644
--- a/install/retroarch.json
+++ b/install/retroarch.json
@@ -116923,7 +116923,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "cemu-gameprofiles",
@@ -117879,7 +117880,8 @@
"size": 36
}
},
- "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default"
+ "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default",
+ "archive_size": 21360579
},
{
"ref": "dinothawr",
@@ -118327,7 +118329,8 @@
"size": 105
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 5752250
},
{
"ref": "dirksimple",
@@ -118383,7 +118386,8 @@
"size": 12988
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 175384
},
{
"ref": "dolphin-sys",
@@ -127054,7 +127058,8 @@
"strip_components": 2,
"exclude": [
"Themes"
- ]
+ ],
+ "archive_size": 3197914
},
{
"ref": "fbneo-cheats",
@@ -140783,7 +140788,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -141016,7 +141022,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -141388,7 +141395,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "ppsspp-assets",
@@ -142076,7 +142084,8 @@
"size": 15005
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 9844388
},
{
"ref": "yaps2-resources",
@@ -142536,7 +142545,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
],
"save_directory": {
diff --git a/install/retrobat.json b/install/retrobat.json
index 3a2e41f89..ca7459771 100644
--- a/install/retrobat.json
+++ b/install/retrobat.json
@@ -89075,7 +89075,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -89308,7 +89309,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -89680,7 +89682,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
}
],
"save_directory": {
diff --git a/install/retrodeck.json b/install/retrodeck.json
index b70189e03..e94e2c442 100644
--- a/install/retrodeck.json
+++ b/install/retrodeck.json
@@ -137751,7 +137751,8 @@
"size": 36
}
},
- "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default"
+ "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default",
+ "archive_size": 21360579
},
{
"ref": "fbneo-cheats",
@@ -151480,7 +151481,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -151713,7 +151715,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -152085,7 +152088,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "yaps2-resources",
@@ -152549,7 +152553,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
],
"save_directory": {
diff --git a/install/retropie.json b/install/retropie.json
index c255b9d1f..3db3da56e 100644
--- a/install/retropie.json
+++ b/install/retropie.json
@@ -124071,7 +124071,8 @@
"size": 36
}
},
- "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default"
+ "source_path": "Cemu-3310f3b8b184d64a62b89fd59088c799432badf5/bin/gameProfiles/default",
+ "archive_size": 21360579
},
{
"ref": "dolphin-sys",
@@ -132742,7 +132743,8 @@
"strip_components": 2,
"exclude": [
"Themes"
- ]
+ ],
+ "archive_size": 3197914
},
{
"ref": "fbneo-cheats",
@@ -146471,7 +146473,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -146704,7 +146707,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -147076,7 +147080,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "yaps2-resources",
@@ -147536,7 +147541,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
]
}
\ No newline at end of file
diff --git a/install/rocknix.json b/install/rocknix.json
index 793ca6670..f06bd3144 100644
--- a/install/rocknix.json
+++ b/install/rocknix.json
@@ -86538,7 +86538,8 @@
"size": 344
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 4465709
},
{
"ref": "dinothawr",
@@ -86986,7 +86987,8 @@
"size": 105
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 5752250
},
{
"ref": "dirksimple",
@@ -87042,7 +87044,8 @@
"size": 12988
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 175384
},
{
"ref": "dolphin-sys",
@@ -95719,7 +95722,8 @@
"strip_components": 2,
"exclude": [
"Themes"
- ]
+ ],
+ "archive_size": 3197914
},
{
"ref": "fbneo-cheats",
@@ -109448,7 +109452,8 @@
"size": 10054
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 5083767
},
{
"ref": "fbneo-samples",
@@ -109681,7 +109686,8 @@
"size": 551776
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 53006540
},
{
"ref": "freeintv-overlays",
@@ -110053,7 +110059,8 @@
"size": 248636
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 21311170
},
{
"ref": "lrps2",
@@ -110069,7 +110076,8 @@
"size": 1814032
}
},
- "strip_components": 0
+ "strip_components": 0,
+ "archive_size": 318896
},
{
"ref": "ppsspp-assets",
@@ -110757,7 +110765,8 @@
"size": 15005
}
},
- "strip_components": 1
+ "strip_components": 1,
+ "archive_size": 9844388
},
{
"ref": "yaps2-resources",
@@ -111217,7 +111226,8 @@
"size": 637
}
},
- "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources"
+ "source_path": "yaps2-57ea93c0ce8306063b31fe6658dab6b492bbedfe/bin/resources",
+ "archive_size": 21181421
}
]
}
\ No newline at end of file
diff --git a/schemas/install-manifest.schema.json b/schemas/install-manifest.schema.json
index 4e7d1ec20..264c08558 100644
--- a/schemas/install-manifest.schema.json
+++ b/schemas/install-manifest.schema.json
@@ -429,6 +429,11 @@
"minimum": 0,
"description": "With type zip: leading path parts dropped from each member."
},
+ "archive_size": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Bytes of the source archive when it was last downloaded: what fetching the tree costs. Absent when not recorded."
+ },
"source_path": {
"type": "string",
"description": "With type tarball: only members below this path are kept, relative to it."
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index 354964481..8a62186a3 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -4949,9 +4949,12 @@ def _manifest_data_directories(
(strip_components for a ZIP, source_path for a tarball, exclude) come
from _data_dirs.yml, the same refresh_data_dirs applies. Every file
carries the sha1 and size the cache holds, so a member the source
- changed since is refused rather than installed.
+ changed since is refused rather than installed. archive_size is the
+ size of the archive refresh_data_dirs last downloaded, what fetching
+ the tree costs: a tarball whose tree is 10 KB is a download of 21 MB.
"""
grouped: dict[tuple[str, str], dict] = {}
+ versions: dict[str, dict[str, dict]] = {}
for src, full in members:
ref, systems, prefix = refs[full]
entry = registry.get(ref, {})
@@ -4976,6 +4979,17 @@ def _manifest_data_directories(
group["source_path"] = str(entry.get("source_path", "")).format(version=version)
if entry.get("exclude"):
group["exclude"] = [str(e) for e in entry["exclude"]]
+ cache = entry.get("local_cache")
+ if cache:
+ recorded = Path(cache).parent / ".versions.json"
+ if str(recorded) not in versions:
+ try:
+ versions[str(recorded)] = json.loads(recorded.read_text())
+ except FileNotFoundError:
+ versions[str(recorded)] = {}
+ size = versions[str(recorded)].get(ref, {}).get("archive_size")
+ if isinstance(size, int) and size > 0:
+ group["archive_size"] = size
group["systems"].extend(s for s in systems if s not in group["systems"])
rel = full[len(prefix):].lstrip("/") if prefix else full
hashes = compute_hashes(src, frozenset({"sha1"}))
diff --git a/scripts/refresh_data_dirs.py b/scripts/refresh_data_dirs.py
index 7b74f7be1..7c3d63562 100644
--- a/scripts/refresh_data_dirs.py
+++ b/scripts/refresh_data_dirs.py
@@ -24,7 +24,7 @@ import time
import urllib.error
import urllib.request
import zipfile
-from collections.abc import Iterator
+from collections.abc import Callable, Iterator
from pathlib import Path
from artifacts import file_lock as _file_lock, set_plain_mode
from common import InputMissing, github_token, platform_arg, require_platform, suggest_names, yaml_load
@@ -270,10 +270,12 @@ def _download_and_extract(
source_path: str,
local_cache: str,
exclude: list[str] | None = None,
+ measured: Callable[[int], None] | None = None,
) -> int:
"""Download tarball, extract source_path subtree to local_cache.
- Returns the number of files extracted.
+ Returns the number of files extracted. measured receives the size of
+ the archive downloaded.
"""
exclude = exclude or []
cache_dir = Path(local_cache)
@@ -290,6 +292,8 @@ def _download_and_extract(
if not chunk:
break
f.write(chunk)
+ if measured is not None:
+ measured(tarball_path.stat().st_size)
log.info("extracting %s -> %s", source_path, local_cache)
@@ -347,6 +351,7 @@ def _download_and_extract_zip(
local_cache: str,
exclude: list[str] | None = None,
strip_components: int = 0,
+ measured: Callable[[int], None] | None = None,
) -> int:
"""Download ZIP, extract to local_cache. Returns file count.
@@ -369,6 +374,8 @@ def _download_and_extract_zip(
if not chunk:
break
f.write(chunk)
+ if measured is not None:
+ measured(zip_path.stat().st_size)
extract_dir = Path(tmpdir) / "extract"
extract_dir.mkdir()
@@ -408,6 +415,46 @@ def _download_and_extract_zip(
return file_count
+def _measure_archive(source_url: str) -> int | None:
+ """The size of the archive at source_url, read by streaming it: a
+ tarball GitHub builds on request is sent without a Content-Length."""
+ req = urllib.request.Request(source_url, headers={"User-Agent": USER_AGENT})
+ size = 0
+ try:
+ with urllib.request.urlopen(req, timeout=DOWNLOAD_TIMEOUT) as resp:
+ while chunk := resp.read(65536):
+ size += len(chunk)
+ except _TRANSIENT as exc:
+ log.warning("could not measure %s: %s", source_url, exc)
+ return None
+ return size or None
+
+
+def _record_archive_size(key: str, entry: dict, versions_path: str) -> None:
+ """Record the archive size of a tree current since before it was kept.
+
+ The installer announces a tree's download as that size: a tarball
+ whose tree is 10 KB is a download of 21 MB. Measured, not refetched,
+ so the tree the packs carry stays the one recorded.
+ """
+ path = Path(versions_path)
+ with _file_lock(path.with_name(f".{path.name}.lock")):
+ versions = _load_versions(versions_path)
+ record = versions.get(key)
+ if record is None or "archive_size" in record:
+ return
+ version = entry.get("version", "master")
+ size = _measure_archive(entry["source_url"].format(version=version))
+ if size is None:
+ return
+ with _file_lock(path.with_name(f".{path.name}.lock")):
+ versions = _load_versions(versions_path)
+ if key in versions and "archive_size" not in versions[key]:
+ versions[key]["archive_size"] = size
+ _save_versions(versions, versions_path)
+ log.info("[%s] archive size recorded: %d bytes", key, size)
+
+
def _get_remote_etag(source_url: str) -> str | None:
"""HEAD request to get ETag or Last-Modified for freshness check."""
try:
@@ -456,6 +503,7 @@ def refresh_entry(
return None
if not needs:
log.info("[%s] up to date (tag: %s)", key, _short_tag(cached_tag))
+ _record_archive_size(key, entry, versions_path)
return False
with cache_lock(entry["local_cache"]):
return _refresh_entry(key, entry, force, dry_run, versions_path)
@@ -516,13 +564,19 @@ def _refresh_entry(
else:
remote_tag = get_remote_sha(entry["source_url"], version)
+ archive_sizes: list[int] = []
+
def fetch() -> int:
+ archive_sizes.clear()
if source_type == "zip":
return _download_and_extract_zip(
- source_url, local_cache, exclude, entry.get("strip_components", 0)
+ source_url, local_cache, exclude, entry.get("strip_components", 0),
+ measured=archive_sizes.append,
)
source_path = entry["source_path"].format(version=version)
- return _download_and_extract(source_url, source_path, local_cache, exclude)
+ return _download_and_extract(
+ source_url, source_path, local_cache, exclude, measured=archive_sizes.append
+ )
# An archive that reads but holds nothing under the path is the same on
# every try: only a failed or unreadable download is tried again.
@@ -540,7 +594,10 @@ def _refresh_entry(
log.warning("[%s] download failed (%s), trying again in %d s", key, exc, wait)
time.sleep(wait)
- _record_version(key, {"sha": remote_tag or "", "version": version}, versions_path)
+ record = {"sha": remote_tag or "", "version": version}
+ if archive_sizes:
+ record["archive_size"] = archive_sizes[-1]
+ _record_version(key, record, versions_path)
log.info("[%s] refreshed: %d files extracted to %s", key, file_count, local_cache)
return True
diff --git a/tests/test_install.py b/tests/test_install.py
index b8c72ae82..a918d7d06 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -3888,6 +3888,37 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
self.assertIn(f"{install.format_size(bios + archive)} downloaded in", proc.stdout)
+ def test_the_plan_announces_the_archive_not_the_tree(self):
+ """yaps2's tarball is 21.2 MB for a 6.5 MB tree, Cemu's 21.4 MB for
+ 9.9 KB: the plan announced the tree, and the run downloaded far more."""
+ from test_install_selection import FakeRepository # noqa: PLC0415
+
+ member = b"profile"
+ archive_size = 21_360_579
+ with FakeRepository() as repo:
+ listed = json.loads((repo.root / "install" / "retroarch.json").read_text())
+ listed["data_directories"] = [{
+ "ref": "cemu-gameprofiles", "dest": "cemu", "type": "tarball",
+ "url": "https://example.invalid/Cemu.tar.gz", "source_path": "Cemu-1/bin",
+ "systems": ["nintendo-gba"], "archive_size": archive_size,
+ "files": {"gameProfiles/a.ini": {"sha1": hashlib.sha1(member).hexdigest(),
+ "size": len(member)}}}]
+ (repo.root / "install" / "retroarch.json").write_text(json.dumps(listed))
+ proc = repo.run("--no-input", "--dry-run")
+ bios = sum(len(payload) for payload, *_ in FakeRepository.PAYLOADS.values())
+ self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
+ self.assertIn(f"({install.format_size(bios + archive_size)})", proc.stdout)
+ self.assertIn(f"(a {install.format_size(archive_size)} archive)", proc.stdout)
+
+ def test_a_pack_or_an_old_list_counts_the_files_themselves(self):
+ needed = {"a": {"size": 7}}
+ entry = {"archive_size": 21_360_579}
+ self.assertEqual(install.data_fetch_bytes(entry, needed), 21_360_579)
+ self.assertEqual(install.data_fetch_bytes({}, needed), 7)
+ self.assertEqual(install.data_fetch_bytes(entry, {}), 0)
+ with unittest.mock.patch.object(install.LOCAL, "pack", object()):
+ self.assertEqual(install.data_fetch_bytes(entry, needed), 7)
+
def test_verified_members_land_the_rest_are_said(self):
work = Path(_tempdir(self))
archive = self._zip(work)
diff --git a/tests/test_refresh_data_dirs.py b/tests/test_refresh_data_dirs.py
index 42f21d122..0a4af04fd 100644
--- a/tests/test_refresh_data_dirs.py
+++ b/tests/test_refresh_data_dirs.py
@@ -93,6 +93,26 @@ class RefreshConcurrency(unittest.TestCase):
)
self.assertEqual(seen, [True])
+ def test_the_archive_size_is_recorded_without_replacing_the_tree(self):
+ """The installer announces a tree's download as the archive's size:
+ a tarball extracted to 10 KB is a download of 21 MB. A tree current
+ before the size was kept is measured, its files left as they are."""
+ payload = _zip_bytes({"a.bin": b"x" * 100})
+ entry = {"source_type": "zip", "source_url": "https://x/pak.zip",
+ "local_cache": str(self.cache)}
+ with mock.patch.object(rdd.urllib.request, "urlopen",
+ lambda *a, **k: _Response(payload)), \
+ mock.patch.object(rdd, "_get_remote_etag", return_value="e1"):
+ self.assertTrue(rdd.refresh_entry("pak", entry, versions_path=self.versions))
+ self.assertEqual(rdd._load_versions(self.versions)["pak"]["archive_size"],
+ len(payload))
+ rdd._record_version("pak", {"sha": "e1"}, self.versions)
+ (self.cache / "a.bin").write_bytes(b"kept")
+ self.assertFalse(rdd.refresh_entry("pak", entry, versions_path=self.versions))
+ self.assertEqual(rdd._load_versions(self.versions)["pak"],
+ {"sha": "e1", "archive_size": len(payload)})
+ self.assertEqual((self.cache / "a.bin").read_bytes(), b"kept")
+
def test_a_current_tree_is_not_waited_for(self):
"""A pipeline reads every tree for its whole run. A build beside it
waited on the exclusive lock before asking the remote, which would
@@ -100,7 +120,7 @@ class RefreshConcurrency(unittest.TestCase):
import fcntl # noqa: PLC0415
self.cache.mkdir(parents=True)
- rdd._record_version("pak", {"sha": "e1"}, self.versions)
+ rdd._record_version("pak", {"sha": "e1", "archive_size": 1}, self.versions)
entry = {"source_type": "zip", "source_url": "https://x/pak.zip",
"local_cache": str(self.cache)}
result: list = []
@@ -229,7 +249,7 @@ class DryRunReport(unittest.TestCase):
def test_the_remote_tag_is_shown_beside_the_cached_one(self):
with tempfile.TemporaryDirectory() as tmp:
versions = Path(tmp) / "versions.json"
- versions.write_text(json.dumps({"k": {"etag": '"2725165595"'}}))
+ versions.write_text(json.dumps({"k": {"etag": '"2725165595"', "archive_size": 1}}))
entry = {"source_type": "zip", "source_url": "https://x.invalid/a.zip",
"local_cache": tmp}
with mock.patch.object(rdd, "_get_remote_etag", return_value='"2685251384"'), \
@@ -249,5 +269,30 @@ class DryRunReport(unittest.TestCase):
)
+class TheManifestCarriesTheArchiveSize(unittest.TestCase):
+ """The size refresh_data_dirs recorded reaches the install list, which
+ the installer announces as the tree's download."""
+
+ def test_recorded_size_is_written_and_an_unrecorded_one_left_out(self):
+ from generate_pack import _manifest_data_directories # noqa: PLC0415
+
+ (REPO_ROOT / "tmp").mkdir(exist_ok=True)
+ with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
+ data = Path(tmp) / "data"
+ for ref in ("pak", "old"):
+ (data / ref).mkdir(parents=True)
+ (data / ref / "a.bin").write_bytes(b"abc")
+ (data / ".versions.json").write_text(json.dumps(
+ {"pak": {"sha": "e1", "archive_size": 21_360_579}, "old": {"sha": "e2"}}))
+ registry = {ref: {"source_type": "zip", "source_url": f"https://x/{ref}.zip",
+ "local_cache": str(data / ref)} for ref in ("pak", "old")}
+ members = [(str(data / ref / "a.bin"), f"{ref}/a.bin") for ref in ("pak", "old")]
+ refs = {f"{ref}/a.bin": (ref, ("s",), ref) for ref in ("pak", "old")}
+ listed = {entry["ref"]: entry for entry in
+ _manifest_data_directories(members, refs, registry, "")}
+ self.assertEqual(listed["pak"]["archive_size"], 21_360_579)
+ self.assertNotIn("archive_size", listed["old"])
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/wiki/installer.md b/wiki/installer.md
index 0d6e5141b..796938117 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -1620,8 +1620,11 @@ built (`strip_components` for a ZIP, `source_path` for a tarball, `exclude`),
and writes a file only when its hash matches the list. A file the source has
changed since is left out and counted, and the pack still holds it. `--check`
counts the data files missing, `--dry-run` names each tree it would fetch, and
-narrowing with `--system`, `--core` or `--target` keeps only the trees of the
-systems that stay.
+the size announced for a tree is its archive's (`archive_size`, recorded when
+`refresh_data_dirs.py` last downloaded it): one missing file fetches the whole
+archive, and a tarball can be a thousand times its tree. Narrowing with
+`--system`, `--core` or `--target` keeps only the trees of the systems that
+stay.
## What the bootstrap does
@@ -1802,7 +1805,7 @@ other schemas under `api/v1/schemas/`.
| `games_unavailable` | `platform`, `reason`, `message` | With `--for-games`, what the games need could not be read (`offline`, `network`, `invalid`, `stale`, `no_sets`, `no_folder`): the run keeps every file of the list, except for a `FOLDER` that does not exist, where it stops |
| `check` | `platform`, `name`, `bios_dir`, `files`, `present`, `missing`, `wrong_hash`, `bytes_needed`, `data_missing`, `not_installable` | The platform's totals. `data_missing` counts data-tree files to fetch, `not_installable` the files the collection cannot supply |
| `declared` | `platform`, `files`, `present`, `missing`, `wrong_hash`, `bytes_needed`, `dests` | Right after `check`, the same counts over the files the platform's own list names (`cores: null`), and their `dests` in the order of the `file` events. A setup that checks its own list reads its answer here, with or without `--declared-only` |
-| `data` | `platform`, `files`, `bytes` | Right after `declared`: the data-tree files to fetch (the `data_missing` of `check`) and the bytes they write once in place |
+| `data` | `platform`, `files`, `bytes` | Right after `declared`: the data-tree files to fetch (the `data_missing` of `check`) and the bytes fetching them costs: each tree's archive, or the files themselves from a pack or a list that records no archive size |
| `found` | `platform`, `dest`, `folder`, `path`, `member`, `reason` | Each file to install that this machine already holds, after `check` and before anything is written, in `--check` and `--dry-run` too. `folder` is the `--from` folder as given, or the `bios_dir` of the check when the BIOS folder holds the file at another place, and then `reason` says where in words (`nested folder: ...` for a misplaced file, `the same file is at ...` for one the list installs there too). `path` is the file, and `member` the ZIP member holding the bytes when `path` is an archive, an empty string otherwise. Its copy is reported by a `downloaded` event |
| `unreadable` | `platform`, `folder`, `path`, `member`, `reason` | Each file in a `--from` folder that could not be read and may be one the run still needs, right after the `found` events: its size is that of a file no copy was found for, or unknown (a folder that could not be listed, a ZIP that would not open). `member` names the ZIP member, or is empty. `reason` says why in words (`Permission denied`, `it is encrypted, a password is needed`) |
| `saves` | `platform`, `files`, `folder` | After `choices` and before `checking`, when the files the run installs (once `--system` and the other choices narrowed the list) hold some read from the frontend's save directory and that directory is known: how many, and the `folder` they go to, where `` and `` stand for one folder per system or per core (the screen and `--plain` say it in words: "a folder per core under /sdcard/RetroArch/saves"). When it is not known, the files are counted in the summary's `skipped` instead (`no_save_directory`) |
From 810756463171990723f91878227d1e317780c989 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 08:59:15 +0100
Subject: [PATCH 62/83] fix: gearcoleco warns on an unknown CRC32
At be1a3716 find_firmware rejects a candidate by size alone (platforms/libretro/libretro.cpp:811-816), and an OS-7, EOS or SmartWriter image whose CRC32 differs is logged and loaded (lines 875-876, 928-935). The three entries keep crc32 in validation with on_mismatch warn, so another 8 KiB OS-7 revision such as colecoa.rom no longer reads as rejected.
---
emulators/gearcoleco.yml | 3 +++
tests/test_validation_scope.py | 30 ++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/emulators/gearcoleco.yml b/emulators/gearcoleco.yml
index 72dd6fc61..c48ae5414 100644
--- a/emulators/gearcoleco.yml
+++ b/emulators/gearcoleco.yml
@@ -67,6 +67,7 @@ files:
size: 8192
crc32: "3aa93ef3"
validation: [size, crc32]
+ on_mismatch: {crc32: warn}
source_ref: "platforms/libretro/libretro.cpp:779-840 (find_firmware), platforms/libretro/libretro.cpp:858-885 (load_colecovision_firmware), platforms/libretro/libretro.cpp:2453-2457, platforms/libretro/libretro.cpp:2258-2259, src/Adam.cpp:28-31, src/Adam.h:52, src/Memory.cpp:310-319, src/Memory.cpp:246-249"
note: >
Loaded for both machines. Any 8192-byte image is accepted, and a CRC32
@@ -80,6 +81,7 @@ files:
size: 8192
crc32: "05a37a34"
validation: [size, crc32]
+ on_mismatch: {crc32: warn}
source_ref: "platforms/libretro/libretro.cpp:887-948 (load_adam_firmware), platforms/libretro/libretro.cpp:2426-2427, platforms/libretro/libretro.cpp:2483-2487, platforms/libretro/libretro.cpp:2500-2501, platforms/libretro/libretro.cpp:2584-2588, src/Adam.cpp:32-35, src/Adam.h:53, src/Adam.cpp:137-146, src/Adam.cpp:166-188, src/GearcolecoCore.cpp:414-419, src/Adam.cpp:519-522"
note: >
The 8 KiB EOS bank, the first half of the 16 KiB u22 chip. A CRC32
@@ -94,6 +96,7 @@ files:
size: 32768
crc32: "58d86a2a"
validation: [size, crc32]
+ on_mismatch: {crc32: warn}
source_ref: "platforms/libretro/libretro.cpp:887-948 (load_adam_firmware), platforms/libretro/libretro.cpp:2426-2427, platforms/libretro/libretro.cpp:2483-2487, platforms/libretro/libretro.cpp:2500-2501, platforms/libretro/libretro.cpp:2584-2588, src/Adam.cpp:36-39, src/Adam.h:54, src/Adam.cpp:137-146, src/Adam.cpp:166-188, src/GearcolecoCore.cpp:414-419, src/Adam.cpp:513-522"
note: >
A CRC32 other than 58d86a2a logs "Unknown SmartWriter revision" and
diff --git a/tests/test_validation_scope.py b/tests/test_validation_scope.py
index 30c8946b4..423f7b81b 100644
--- a/tests/test_validation_scope.py
+++ b/tests/test_validation_scope.py
@@ -86,5 +86,35 @@ class ContentFoundLabelsTakeTheirRegionSlot(unittest.TestCase):
self.assertIsNotNone(check_file_validation(str(path), "scph1001.bin", index))
+class GearcolecoWarnsOnAnUnknownRevision(unittest.TestCase):
+ """Gearcoleco rejects a firmware by size only and logs an unknown CRC32
+ before loading it (platforms/libretro/libretro.cpp:811-816, 875-876,
+ 928-935 at be1a3716): another OS-7 revision of 8 KiB runs."""
+
+ def test_another_revision_passes(self):
+ import sys
+ import tempfile
+
+ import yaml
+
+ sys.path.insert(0, str(REPO_ROOT / "scripts"))
+ from validation import _build_validation_index, check_file_validation
+
+ profile = yaml.safe_load(
+ (REPO_ROOT / "emulators" / "gearcoleco.yml").read_text(encoding="utf-8")
+ )
+ index = _build_validation_index({"gearcoleco": profile})
+ with tempfile.TemporaryDirectory() as tmp:
+ for name, size in (("colecovision.rom", 8192), ("eos.rom", 8192),
+ ("writer.rom", 32768)):
+ path = Path(tmp) / name
+ path.write_bytes(b"\x01" * size)
+ with self.subTest(name=name):
+ self.assertIsNone(check_file_validation(str(path), name, index))
+ path.write_bytes(b"\x01" * (size - 1))
+ with self.subTest(name=name, size="short"):
+ self.assertIsNotNone(check_file_validation(str(path), name, index))
+
+
if __name__ == "__main__":
unittest.main()
From 4efcb3da64fd6efa44d6b01805506280bbd9a20c Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:00:06 +0100
Subject: [PATCH 63/83] fix: group core files under their pack path
On a platform that writes bios/ in front of its destinations (RetroDECK, AmberELEC, EmuELEC), a core extra was grouped, dropped and held under its bare destination while the platform's declaration of the same file used bios/. Beetle PSX's scph5501.bin was kept by the --region japan pack while the declaration was dropped and the installer dropped the path. extra_region_key keys every extra with the platform's declared root, in the builder, the manifest selection, verify's replay and the omissions. The same key gives the declared entries the systems of the core files at their path: every --system case of RetroDECK differed between pack and installer before, none does now.
---
install/amberelec.json | 165 ++-
install/emuelec.json | 150 +++
install/games/fallback/amberelec.json | 2 +-
install/games/fallback/emuelec.json | 2 +-
install/games/fallback/retrodeck.json | 2 +-
install/games/index.json | 2 +-
install/retrodeck.json | 1663 ++++++++++++++++++++++++-
scripts/generate_pack.py | 21 +-
scripts/manifestselect.py | 12 +-
scripts/packextras.py | 20 +-
tests/test_install_selection.py | 93 ++
11 files changed, 2113 insertions(+), 19 deletions(-)
diff --git a/install/amberelec.json b/install/amberelec.json
index 745e5792b..80fe07cb8 100644
--- a/install/amberelec.json
+++ b/install/amberelec.json
@@ -2106,6 +2106,10 @@
"repo_path": "bios/Atari/400-800/ATARIXL.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -2128,6 +2132,10 @@
"repo_path": "bios/Atari/400-800/ATARIBAS.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -2150,6 +2158,10 @@
"repo_path": "bios/Atari/400-800/ATARIOSA.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -2172,6 +2184,10 @@
"repo_path": "bios/Atari/400-800/ATARIOSB.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -2194,6 +2210,10 @@
"repo_path": "bios/Atari/5200/5200.rom",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-5200"
],
"alternatives": [
@@ -2361,6 +2381,11 @@
"repo_path": "bios/Microsoft/MSX/Databases/.variants/colecodb.xml.78113162",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"coleco-colecovision"
],
"alternatives": [
@@ -3432,6 +3457,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/ARAB1.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3454,6 +3484,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/ARABIC.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3476,6 +3511,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/BEERIDE.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3498,6 +3538,11 @@
"repo_path": "bios/Microsoft/MSX/FMPAC.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3520,6 +3565,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/GCVMX80.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3542,6 +3592,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/HANGUL.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3564,6 +3619,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_kanjifont.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3586,6 +3646,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/MICROSOLDISK.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -3608,6 +3673,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/yrw801.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4301,6 +4371,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_kanjibasic.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4510,6 +4585,11 @@
"repo_path": "bios/Microsoft/MSX/share/systemroms/fs-5500_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4532,6 +4612,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/NOVAXIS.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4554,6 +4639,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/nowindDos1.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4576,6 +4666,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/nowindDos2.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4598,6 +4693,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/PAINT.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4620,6 +4720,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4642,6 +4747,11 @@
"repo_path": "bios/Microsoft/MSX/nms8250_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4664,6 +4774,11 @@
"repo_path": "bios/Other/msx-emu/Machines/Shared Roms/RS232.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4697,6 +4812,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/SUNRISEIDE.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4719,6 +4839,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/SWP.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4741,6 +4866,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/XBASIC2.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5316,6 +5446,11 @@
"repo_path": "bios/Nintendo/SNES/BS-X.bin",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-satellaview"
+ ],
+ "declared_in": [
"nintendo-satellaview"
],
"alternatives": [
@@ -5512,6 +5647,9 @@
"north-america",
"oceania"
],
+ "region_groups": [
+ "sega-master-system"
+ ],
"region_system_groups": [
"sega-master-system"
],
@@ -5541,6 +5679,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-master-system"
+ ],
"region_system_groups": [
"sega-master-system"
],
@@ -5571,6 +5712,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -5602,6 +5746,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -5632,6 +5779,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -6104,6 +6254,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -6136,6 +6289,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -6168,6 +6324,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -8987,7 +9146,8 @@
],
"region_groups": [
"sony-playstation"
- ]
+ ],
+ "priority": 10
},
{
"dest": "bios/scph1002a.bin",
@@ -9233,7 +9393,8 @@
],
"region_groups": [
"sony-playstation"
- ]
+ ],
+ "priority": 10
},
{
"dest": "bios/scph7002.bin",
diff --git a/install/emuelec.json b/install/emuelec.json
index 8135201bd..e331497bb 100644
--- a/install/emuelec.json
+++ b/install/emuelec.json
@@ -3363,6 +3363,10 @@
"repo_path": "bios/Atari/400-800/ATARIXL.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -3385,6 +3389,10 @@
"repo_path": "bios/Atari/400-800/ATARIBAS.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -3407,6 +3415,10 @@
"repo_path": "bios/Atari/400-800/ATARIOSA.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -3429,6 +3441,10 @@
"repo_path": "bios/Atari/400-800/ATARIOSB.ROM",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -3451,6 +3467,10 @@
"repo_path": "bios/Atari/5200/5200.rom",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-5200"
],
"alternatives": [
@@ -3686,6 +3706,11 @@
"repo_path": "bios/Microsoft/MSX/Databases/.variants/colecodb.xml.78113162",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"coleco-colecovision"
],
"alternatives": [
@@ -4923,6 +4948,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/ARAB1.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4945,6 +4975,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/ARABIC.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4967,6 +5002,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/BEERIDE.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -4989,6 +5029,11 @@
"repo_path": "bios/Microsoft/MSX/FMPAC.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5011,6 +5056,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/GCVMX80.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5033,6 +5083,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/HANGUL.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5055,6 +5110,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_kanjifont.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5077,6 +5137,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/MICROSOLDISK.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5099,6 +5164,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/yrw801.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -5792,6 +5862,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_kanjibasic.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6001,6 +6076,11 @@
"repo_path": "bios/Microsoft/MSX/share/systemroms/fs-5500_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6023,6 +6103,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/NOVAXIS.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6045,6 +6130,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/nowindDos1.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6067,6 +6157,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/nowindDos2.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6089,6 +6184,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/PAINT.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6111,6 +6211,11 @@
"repo_path": "bios/Microsoft/MSX/openmsx/fs-a1wsx_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6133,6 +6238,11 @@
"repo_path": "bios/Microsoft/MSX/nms8250_disk.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6155,6 +6265,11 @@
"repo_path": "bios/Other/msx-emu/Machines/Shared Roms/RS232.ROM",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6188,6 +6303,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/SUNRISEIDE.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6210,6 +6330,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/SWP.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6232,6 +6357,11 @@
"repo_path": "bios/Microsoft/MSX/Shared Roms/XBASIC2.rom",
"cores": null,
"systems": [
+ "coleco-colecovision",
+ "microsoft-msx",
+ "sc-3000"
+ ],
+ "declared_in": [
"microsoft-msx"
],
"alternatives": [
@@ -6694,6 +6824,11 @@
"repo_path": "bios/Nintendo/SNES/Satellaview_BS-X.sfc",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-satellaview"
+ ],
+ "declared_in": [
"nintendo-satellaview"
],
"alternatives": [
@@ -6895,6 +7030,9 @@
"north-america",
"oceania"
],
+ "region_groups": [
+ "sega-master-system"
+ ],
"region_system_groups": [
"sega-master-system"
],
@@ -6924,6 +7062,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-master-system"
+ ],
"region_system_groups": [
"sega-master-system"
],
@@ -6954,6 +7095,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -6985,6 +7129,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -7015,6 +7162,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
diff --git a/install/games/fallback/amberelec.json b/install/games/fallback/amberelec.json
index 9833d42b1..6450d12d2 100644
--- a/install/games/fallback/amberelec.json
+++ b/install/games/fallback/amberelec.json
@@ -1 +1 @@
-{"files":[["bios/128p-0.rom",16384,"bios"],["bios/128p-1.rom",16384,"bios"],["bios/256s-0.rom",16384,"bios"],["bios/256s-1.rom",16384,"bios"],["bios/256s-2.rom",16384,"bios"],["bios/256s-3.rom",16384,"bios"],["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BIOS.col",8192,"bios"],["bios/BLOOD.RFF",3536782,"game_data"],["bios/BS-X.bin",1048576,"bios"],["bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom",262144,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/DUKE3D.GRP",11035779,"game_data"],["bios/Databases/colecodb.xml",164848,"bios"],["bios/Databases/msxcaswavdb.xml",819679,"bios"],["bios/Databases/msxromdb.xml",930986,"bios"],["bios/Databases/msxsysromdb.xml",157542,"bios"],["bios/Databases/segadb.xml",82318,"bios"],["bios/Databases/svidb.xml",261070,"bios"],["bios/ECS.bin",24576,"bios"],["bios/GUI.RFF",7145,"game_data"],["bios/IVOICE.bin",2048,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C128.bin",16384,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom",262144,"bios"],["bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom",524288,"bios"],["bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom",524288,"bios"],["bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom",524288,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-1.rom",8192,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-2.rom",8192,"bios"],["bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/config.ini",347,"bios"],["bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM",8192,"bios"],["bios/Machines/Forte II Games - Pesadelo/pesadelo.rom",65536,"bios"],["bios/Machines/MSX - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom",16384,"bios"],["bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom",32768,"bios"],["bios/Machines/MSX/MSX.ROM",32768,"bios"],["bios/Machines/MSX/MSX2.ROM",32768,"bios"],["bios/Machines/MSX/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX/config.ini",408,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom",16384,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom",32768,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_logo_msx2+.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_main_msx2+.rom",32768,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_music.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+/MSX.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2+/config.ini",773,"bios"],["bios/Machines/MSX2/MSX.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2/config.ini",649,"bios"],["bios/Machines/MSXturboR/config.ini",941,"bios"],["bios/Machines/SVI - Spectravideo SVI-318/svi318.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi806se.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328/svi328.rom",32768,"bios"],["bios/Machines/Shared Roms/ARAB1.ROM",32768,"bios"],["bios/Machines/Shared Roms/ARABIC.rom",32768,"bios"],["bios/Machines/Shared Roms/BEERIDE.ROM",16384,"bios"],["bios/Machines/Shared Roms/FMPAC.rom",65536,"bios"],["bios/Machines/Shared Roms/GCVMX80.ROM",8192,"bios"],["bios/Machines/Shared Roms/HANGUL.rom",131072,"bios"],["bios/Machines/Shared Roms/KANJI.rom",262144,"bios"],["bios/Machines/Shared Roms/MICROSOLDISK.ROM",16384,"bios"],["bios/Machines/Shared Roms/MOONSOUND.rom",2097152,"bios"],["bios/Machines/Shared Roms/MSX.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2AR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2AREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSX2BR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2BREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2EXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2FR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2FREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2G.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2GEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2HAN.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2J.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2JEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2KR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2KREXT.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2P.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2PEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2PMUS.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2R.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2R2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2REXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2SE.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SPEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSXAR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXBR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXDOS2.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXDOS23.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXFR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXG.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXHAN.rom",8192,"bios"],["bios/Machines/Shared Roms/MSXJ.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKANJI.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXSE.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXSP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXTR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXTREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTRMUS.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTROPT.ROM",16384,"bios"],["bios/Machines/Shared Roms/NATIONALDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/NOVAXIS.rom",16384,"bios"],["bios/Machines/Shared Roms/PAINT.rom",65536,"bios"],["bios/Machines/Shared Roms/PANASONICDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/PHILIPSDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/RS232.ROM",8192,"bios"],["bios/Machines/Shared Roms/SUNRISEIDE.rom",65536,"bios"],["bios/Machines/Shared Roms/SWP.rom",32768,"bios"],["bios/Machines/Shared Roms/Shared.txt",41,"bios"],["bios/Machines/Shared Roms/XBASIC2.rom",16384,"bios"],["bios/Machines/Shared Roms/nowindDos1.rom",524288,"bios"],["bios/Machines/Shared Roms/nowindDos2.rom",524288,"bios"],["bios/Mupen64plus/IPL.n64",4194304,"bios"],["bios/Mupen64plus/font.ttf",65932,"bios"],["bios/NWINTER.GRP",10965909,"game_data"],["bios/NstDatabase.xml",1022369,"bios"],["bios/PPSSPP/ppge_atlas.meta",1119232,"bios"],["bios/PPSSPP/ppge_atlas.zim",666530,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/SOUNDS.RFF",12830764,"game_data"],["bios/STBIOS.bin",262144,"bios"],["bios/SURFACE.DAT",4096,"game_data"],["bios/SW.GRP",26056769,"game_data"],["bios/VOXEL.DAT",8192,"game_data"],["bios/Vircon32Bios.v32",1073060,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/[BIOS] Atari Jaguar CD (World).j64",262144,"bios"],["bios/[BIOS] Atari Jaguar Developer CD (World).j64",262144,"bios"],["bios/ace.zip",21283,"bios"],["bios/ace91.zip",27636,"bios"],["bios/ace91_euro.zip",27381,"bios"],["bios/ace_a.zip",3752,"bios"],["bios/ace_a2.zip",3760,"bios"],["bios/aceeuro.zip",23853,"bios"],["bios/action2.wad",209908382,"game_data"],["bios/all.bin",516096,"bios"],["bios/areplay.bin",32768,"bios"],["bios/astron.zip",57886,"bios"],["bios/astronp.zip",23339,"bios"],["bios/atari-1200xl-os-rev-10.rom",16384,"bios"],["bios/atari-1200xl-os-rev-11.rom",16384,"bios"],["bios/atari-5200-os-2port.rom",2048,"bios"],["bios/atari-800-os-a-ntsc.rom",10240,"bios"],["bios/atari-basic-rev-a.rom",8192,"bios"],["bios/atari-basic-rev-b.rom",8192,"bios"],["bios/atari-xl-os-ver-1.rom",16384,"bios"],["bios/atari-xl-os-ver-3.rom",16384,"bios"],["bios/badlandp.zip",8789,"bios"],["bios/badlands.zip",12872,"bios"],["bios/bega.zip",48777,"bios"],["bios/begar1.zip",19993,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/blazer.zip",19999,"bios"],["bios/c52.bin",1024,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/cliff.zip",16725,"bios"],["bios/cliff_ox.zip",16879,"bios"],["bios/cliffalt.zip",15087,"bios"],["bios/cliffalt2.zip",14504,"bios"],["bios/cobra.zip",29388,"bios"],["bios/cobraab.zip",20648,"bios"],["bios/cobraconv.zip",27623,"bios"],["bios/cobram3.zip",23520,"bios"],["bios/colecovision.rom",8192,"bios"],["bios/cputest.zip",11874,"bios"],["bios/custom.pal",192,"bios"],["bios/dc/awbios.zip",34620,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/font.bin",519984,"bios"],["bios/dc/naomi.zip",6134785,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/delaweare.wad",83219726,"game_data"],["bios/disksys.rom",8192,"bios"],["bios/dle11.zip",28296,"bios"],["bios/dle20.zip",25955,"bios"],["bios/dle21.zip",24883,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/ep128emu/roms/tvc22_ext.rom",8192,"bios"],["bios/ep128emu/roms/tvc22_sys.rom",16384,"bios"],["bios/ep128emu/roms/tvc_dos12d.rom",16384,"bios"],["bios/ep128emu/roms/tvcfileio.rom",8192,"bios"],["bios/esh.zip",16764,"bios"],["bios/eshalt.zip",5660,"bios"],["bios/eshalt2.zip",5277,"bios"],["bios/eshfix7.zip",5669,"bios"],["bios/eshfix7alt.zip",5678,"bios"],["bios/eshfix7alt2.zip",5669,"bios"],["bios/exec.bin",8192,"bios"],["bios/fbneo/hiscore.dat",328397,"bios"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/firefox.zip",53410,"bios"],["bios/firefoxa.zip",51026,"bios"],["bios/firmware.bin",262144,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me_plus-lr.jar",1219093,"bios"],["bios/fuse/128-0.rom",16384,"bios"],["bios/fuse/128-1.rom",16384,"bios"],["bios/fuse/128p-0.rom",16384,"bios"],["bios/fuse/128p-1.rom",16384,"bios"],["bios/fuse/256s-0.rom",16384,"bios"],["bios/fuse/256s-1.rom",16384,"bios"],["bios/fuse/256s-2.rom",16384,"bios"],["bios/fuse/256s-3.rom",16384,"bios"],["bios/fuse/48.rom",16384,"bios"],["bios/fuse/didaktik80.rom",14336,"bios"],["bios/fuse/disciple.rom",8192,"bios"],["bios/fuse/gluck.rom",16384,"bios"],["bios/fuse/if1-2.rom",8192,"bios"],["bios/fuse/mf1.rom",8192,"bios"],["bios/fuse/mf128.rom",8192,"bios"],["bios/fuse/mf3.rom",8192,"bios"],["bios/fuse/opus.rom",8192,"bios"],["bios/fuse/plus2-0.rom",16384,"bios"],["bios/fuse/plus2-1.rom",16384,"bios"],["bios/fuse/plus3-0.rom",16384,"bios"],["bios/fuse/plus3-1.rom",16384,"bios"],["bios/fuse/plus3-2.rom",16384,"bios"],["bios/fuse/plus3-3.rom",16384,"bios"],["bios/fuse/plus3e-0.rom",16384,"bios"],["bios/fuse/plus3e-1.rom",16384,"bios"],["bios/fuse/plus3e-2.rom",16384,"bios"],["bios/fuse/plus3e-3.rom",16384,"bios"],["bios/fuse/plusd.rom",8192,"bios"],["bios/fuse/se-0.rom",16384,"bios"],["bios/fuse/se-1.rom",16384,"bios"],["bios/fuse/speccyboot-1.4.rom",8192,"bios"],["bios/fuse/tc2048.rom",16384,"bios"],["bios/fuse/tc2068-0.rom",16384,"bios"],["bios/fuse/tc2068-1.rom",8192,"bios"],["bios/fuse/trdos.rom",16384,"bios"],["bios/fuse/ttx2000s.rom",8192,"bios"],["bios/fuse/usource.rom",8192,"bios"],["bios/g7400.bin",1024,"bios"],["bios/galaxy.zip",48574,"bios"],["bios/galaxyp.zip",20042,"bios"],["bios/gamecontrollerdb.txt",609830,"game_data"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gluck.rom",16384,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gpworld.zip",86990,"bios"],["bios/grom.bin",2048,"bios"],["bios/gtg.zip",19748,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hacx2.wad",20504847,"game_data"],["bios/harm1.wad",58396393,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/howard.o",513,"bios"],["bios/interstellar.zip",39757,"bios"],["bios/jagboot.rom",131072,"bios"],["bios/jagboot_m.rom",131072,"bios"],["bios/jopac.bin",1024,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/lair.zip",17906,"bios"],["bios/lair2.zip",25809,"bios"],["bios/lair2_211.zip",23278,"bios"],["bios/lair2_300.zip",24540,"bios"],["bios/lair2_314.zip",25195,"bios"],["bios/lair2_315.zip",25271,"bios"],["bios/lair2_316_euro.zip",25175,"bios"],["bios/lair2_318.zip",25592,"bios"],["bios/lair2_319_euro.zip",25493,"bios"],["bios/lair2_319_span.zip",25828,"bios"],["bios/lair_a.zip",21377,"bios"],["bios/lair_b.zip",4293,"bios"],["bios/lair_c.zip",968,"bios"],["bios/lair_d.zip",27677,"bios"],["bios/lair_d2.zip",4056,"bios"],["bios/lair_e.zip",20802,"bios"],["bios/lair_f.zip",6027,"bios"],["bios/lair_ita.zip",6408,"bios"],["bios/lair_n1.zip",26477,"bios"],["bios/lair_x.zip",24316,"bios"],["bios/laireuro.zip",10771,"bios"],["bios/lgp.zip",37609,"bios"],["bios/lynxboot.img",512,"bios"],["bios/mach3.zip",441761,"bios"],["bios/mame2003-plus/artwork/blueshrk.zip",925914,"game_data"],["bios/mame2003-plus/artwork/dotron.zip",2010009,"game_data"],["bios/mame2003-plus/artwork/frogs.zip",2832731,"game_data"],["bios/mame2003-plus/artwork/invaders.zip",4324198,"game_data"],["bios/mame2003-plus/artwork/omegrace.zip",1754523,"game_data"],["bios/mame2003-plus/artwork/skydiver.zip",117241,"game_data"],["bios/mame2003-plus/artwork/solarq.zip",1342645,"game_data"],["bios/mame2003-plus/artwork/warrior.zip",1125335,"game_data"],["bios/mame2003-plus/cheat.dat",7971360,"game_data"],["bios/mame2003-plus/hiscore.dat",131926,"game_data"],["bios/mame2003-plus/history.dat",38635890,"game_data"],["bios/mame2003-plus/mameinfo.dat",24837237,"game_data"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/ng-lo.rom",65536,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/neocdz.zip",1181333,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/penthous.zip",2112419,"game_data"],["bios/plutonia.wad",17420824,"game_data"],["bios/psxonpsp660.bin",524288,"bios"],["bios/quasi88/DISK.ROM",2048,"bios"],["bios/quasi88/N88.ROM",32768,"bios"],["bios/quasi88/N88N.ROM",32768,"bios"],["bios/quasi88/N88_0.ROM",8192,"bios"],["bios/quasi88/N88_1.ROM",8192,"bios"],["bios/quasi88/N88_2.ROM",8192,"bios"],["bios/quasi88/N88_3.ROM",8192,"bios"],["bios/quasi88/font.rom",2048,"bios"],["bios/quasi88/font2.rom",2048,"bios"],["bios/quasi88/font3.rom",2048,"bios"],["bios/quasi88/n88jisho.rom",524288,"bios"],["bios/quasi88/n88knj1.rom",131072,"bios"],["bios/quasi88/n88knj2.rom",131072,"bios"],["bios/roadblaster.zip",20664,"bios"],["bios/rom.key",2069,"bios"],["bios/rotwb.wad",20592999,"game_data"],["bios/sae.zip",27734,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sanyotry.bin",1048576,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/sdq.zip",11467,"bios"],["bios/sdqshort.zip",10147,"bios"],["bios/sdqshortalt.zip",10161,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/sl31253.bin",1024,"bios"],["bios/sl31254.bin",1024,"bios"],["bios/sl90025.bin",1024,"bios"],["bios/square1.pk3",45202919,"game_data"],["bios/stvbios.zip",2955630,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262144,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/system/nds_bios_arm7.bin",16384,"bios"],["bios/system/nds_bios_arm9.bin",4096,"bios"],["bios/system/nds_firmware.bin",262144,"bios"],["bios/timetrav.zip",53103,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/tos.img",196608,"bios"],["bios/tq.zip",24144,"bios"],["bios/tq_alt.zip",3831,"bios"],["bios/tq_swear.zip",19758,"bios"],["bios/trdos.rom",16384,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/upd7801g.s01",4096,"bios"],["bios/uvt.zip",62052,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/wildmidi.cfg",192,"game_data"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",2048,"bios"],["neogeo/aes.zip",850311,"bios"],["neogeo/neogeo.zip",1952551,"bios"]],"format_version":1,"platform":"amberelec","sets":{"amstrad-cpc|cap32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"amstrad-cpc|crocods":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"aquaplus-piece|piemu":{"bytes":516096,"files":[207],"optional":[],"required_bytes":516096},"arcade-laserdisc|hypseus-singe":{"bytes":2648486,"files":[200,201,202,203,204,205,209,210,219,220,221,222,235,240,241,242,243,244,245,246,247,249,259,260,261,270,271,272,273,274,275,280,281,325,326,327,335,337,343,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,468,471,484,485,486,504,507,508,509,522],"optional":[327],"required_bytes":2038656},"arcade|fbneo":{"bytes":309895027,"files":[277,278,279],"optional":[277,278,279],"required_bytes":0},"arcade|mame2003_plus":{"bytes":86009009,"files":[392,393,394,395,396,397,398,399,400,401,402,403],"optional":[392,393,394,395,396,397,398,399,400,401,402,403],"required_bytes":0},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella2014":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-400-800|atari800":{"bytes":229376,"files":[14,15,16,17,18,176,177,178,179,197,211,212,213,214,215,216,217,218],"optional":[18,176,177,178,179,197,211,212,213,214,215,216,217,218],"required_bytes":45056},"atari-5200|a5200":{"bytes":2048,"files":[10],"optional":[],"required_bytes":2048},"atari-7800|prosystem":{"bytes":20480,"files":[12,13],"optional":[12],"required_bytes":4096},"atari-jaguar|virtualjaguar":{"bytes":786432,"files":[198,199,344,345],"optional":[198,199,344,345],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[342,390],"optional":[342],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[341,506],"optional":[341],"required_bytes":196608},"blood|raze":{"bytes":16386979,"files":[20,36,190,192,194],"optional":[20,36,190,192,194],"required_bytes":0},"capcom-cps1|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"casio-pv1000|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"chip8|jaxe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"colecovision|bluemsx":{"bytes":2474134,"files":[19,29,30,31,32,33,34,56,57,58,59,60,61,248],"optional":[30,31,32,33,34],"required_bytes":222539},"commodore-amiga-cd32|puae2021":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae2021":{"bytes":18823838,"files":[22,23,44,45,46,47,48,49,50,51,52,53,196,237,238,355,356,357,358,359,360,361,362,363,364,365,366,367,469,511,512,513,514,515,516,517,518,519,520],"optional":[196,237,238,355,356,360,361,362,469,511,512,513,514,515,516,517,518,519,520],"required_bytes":8912896},"commodore-c128|vice_x128":{"bytes":106496,"files":[38,39,40,41,42],"optional":[38,39,40,41,42],"required_bytes":0},"commodore-c64|vice_x64":{"bytes":114688,"files":[38,39,40,42,43,347,348],"optional":[38,39,40,42,43,347,348],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":12288,"files":[239,349],"optional":[239,349],"required_bytes":0},"doom|gzdoom":{"bytes":613275828,"files":[206,257,262,263,264,283,284,285,338,339,340,453,470,494,505],"optional":[206,257,262,263,264,283,284,285,338,339,340,453,470,494,505],"required_bytes":0},"dos|dosbox_pure":{"bytes":41236388,"files":[24,25,26,27,54,55,180,181,182,183,184,185,186,187,188,189],"optional":[24,25,26,27,54,55,180,181,182,183,184,185,186,187,188,189],"required_bytes":0},"duke3d|raze":{"bytes":24114107,"files":[28,172,452],"optional":[28,172,452],"required_bytes":0},"enterprise-64-128|ep128emu_core":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"entex-advision|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"exhumed|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":3072,"files":[491,492,493],"optional":[491,492,493],"required_bytes":0},"famicom|nestopia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamate|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gameking|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamepock|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"handheld-electronic|gw":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"hartung-game-master|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"intellivision|freeintv":{"bytes":36864,"files":[35,37,276,336],"optional":[],"required_bytes":36864},"j2me|freej2me_plus":{"bytes":1219093,"files":[286],"optional":[],"required_bytes":1219093},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|bluemsx":{"bytes":8543963,"files":[30,31,32,33,34,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169],"optional":[30,31,32,33,34,150],"required_bytes":6259600},"nam|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-88|quasi88":{"bytes":892928,"files":[455,456,457,458,459,460,461,462,463,464,465,466,467],"optional":[462,463,464,465,466,467],"required_bytes":100352},"nec-pc-engine-cd|mednafen_pce_fast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|mednafen_pce_fast":{"bytes":1343488,"files":[331,496,497,498,499,500],"optional":[498,500],"required_bytes":819200},"nec-pcfx|beetle_pcfx":{"bytes":1048576,"files":[451],"optional":[],"required_bytes":1048576},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":2802862,"files":[799,800],"optional":[],"required_bytes":2802862},"nintendo-64|":{"bytes":8454540,"files":[11,170,171],"optional":[],"required_bytes":8454540},"nintendo-ds|drastic":{"bytes":565248,"files":[226,227,282,501,502,503],"optional":[501,502,503],"required_bytes":282624},"nintendo-fds|nestopia":{"bytes":1030561,"files":[173,258],"optional":[],"required_bytes":1030561},"nintendo-gba|mgba":{"bytes":19200,"files":[328,329,330,488],"optional":[],"required_bytes":19200},"nintendo-gbc|gambatte":{"bytes":2560,"files":[328,330],"optional":[],"required_bytes":2560},"nintendo-gb|gambatte":{"bytes":2560,"files":[328,330],"optional":[],"required_bytes":2560},"nintendo-nes|nestopia":{"bytes":192,"files":[250],"optional":[250],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[224],"optional":[224],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":1048576,"files":[21],"optional":[],"required_bytes":1048576},"nintendo-snes|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sufami-turbo|snes9x":{"bytes":262144,"files":[191],"optional":[],"required_bytes":262144},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[236,324,346,439,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792],"optional":[],"required_bytes":1606321},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"panasonic-3do|opera":{"bytes":13123332,"files":[9,334,440,441,442,443,444,445,446,447,448,449,450,476],"optional":[440,441,443,445,446,447,448,449,450],"required_bytes":4718592},"pc-98|np2kai":{"bytes":1294790,"files":[419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438],"optional":[419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438],"required_bytes":0},"philips-cdi|same_cdi":{"bytes":1857124,"files":[472,473,474,475],"optional":[472,473,475],"required_bytes":745703},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|fake08":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"powerslave|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"redneck|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"rpgmaker|easyrpg":{"bytes":148398498,"files":[265,793],"optional":[265,793],"required_bytes":0},"scummvm|scummvm-standalone":{"bytes":1703936,"files":[25,26,54,55],"optional":[25,26,54,55],"required_bytes":0},"scv|emuscv":{"bytes":4096,"files":[521],"optional":[],"required_bytes":4096},"sega-32x|picodrive":{"bytes":3328,"files":[6,7,8],"optional":[6,7,8],"required_bytes":0},"sega-dreamcast-arcade|flycast2021":{"bytes":8266557,"files":[251,255,256],"optional":[],"required_bytes":8266557},"sega-dreamcast-arcade|flycast2021le":{"bytes":8266557,"files":[251,255,256],"optional":[],"required_bytes":8266557},"sega-dreamcast|flycast2021":{"bytes":2748208,"files":[252,253,254],"optional":[254],"required_bytes":2228224},"sega-dreamcast|flycast2021le":{"bytes":2748208,"files":[252,253,254],"optional":[254],"required_bytes":2228224},"sega-gamegear|gearsystem":{"bytes":1024,"files":[223],"optional":[],"required_bytes":1024},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":32768,"files":[225,231,232,234],"optional":[225],"required_bytes":24576},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[228,229,230],"optional":[],"required_bytes":393216},"sega-megadrive|genesis_plus_gx":{"bytes":2426880,"files":[208,233,332,489,490],"optional":[208,233,332,489,490],"required_bytes":0},"sega-saturn|yabasanshiro":{"bytes":8722798,"files":[404,405,406,477,487,495],"optional":[],"required_bytes":8722798},"sega-sc3000|bluemsx":{"bytes":2251595,"files":[30,31,32,33,34],"optional":[30,31,32,33,34],"required_bytes":0},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"shadow-warrior|raze":{"bytes":26056769,"files":[193],"optional":[193],"required_bytes":0},"sharp-x1|x1":{"bytes":318464,"files":[794,795,796,797,798],"optional":[794,795,796],"required_bytes":6144},"sharp-x68000|px68k":{"bytes":1310720,"files":[350,351,352,353,354],"optional":[],"required_bytes":1310720},"sinclair-zx-spectrum|fuse":{"bytes":645120,"files":[0,1,2,3,4,5,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,333,510],"optional":[],"required_bytes":645120},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":8442300,"files":[407,408,409,410,411,412,413,414,415,416,417,418,800],"optional":[407,408,409,410,411,412,413,416,417],"required_bytes":3723708},"snk-ngpc|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"solarus|solarus":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation|pcsx_rearmed":{"bytes":3670016,"files":[454,478,479,480,481,482,483],"optional":[454,478,479,483],"required_bytes":1572864},"sony-psp|ppsspp":{"bytes":1785762,"files":[174,175],"optional":[174,175],"required_bytes":0},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"videoton-tvc|ep128emu_core":{"bytes":49152,"files":[266,267,268,269],"optional":[266,267,268,269],"required_bytes":0},"vircon32|vircon32":{"bytes":1073060,"files":[195],"optional":[195],"required_bytes":0},"vtech-vsmile|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ww2gi|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
+{"files":[["bios/128p-0.rom",16384,"bios"],["bios/128p-1.rom",16384,"bios"],["bios/256s-0.rom",16384,"bios"],["bios/256s-1.rom",16384,"bios"],["bios/256s-2.rom",16384,"bios"],["bios/256s-3.rom",16384,"bios"],["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BIOS.col",8192,"bios"],["bios/BLOOD.RFF",3536782,"game_data"],["bios/BS-X.bin",1048576,"bios"],["bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom",262144,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/DUKE3D.GRP",11035779,"game_data"],["bios/Databases/colecodb.xml",164848,"bios"],["bios/Databases/msxcaswavdb.xml",819679,"bios"],["bios/Databases/msxromdb.xml",930986,"bios"],["bios/Databases/msxsysromdb.xml",157542,"bios"],["bios/Databases/segadb.xml",82318,"bios"],["bios/Databases/svidb.xml",261070,"bios"],["bios/ECS.bin",24576,"bios"],["bios/GUI.RFF",7145,"game_data"],["bios/IVOICE.bin",2048,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C128.bin",16384,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom",262144,"bios"],["bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom",524288,"bios"],["bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom",524288,"bios"],["bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom",524288,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-1.rom",8192,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-2.rom",8192,"bios"],["bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/config.ini",347,"bios"],["bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM",8192,"bios"],["bios/Machines/Forte II Games - Pesadelo/pesadelo.rom",65536,"bios"],["bios/Machines/MSX - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom",16384,"bios"],["bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom",32768,"bios"],["bios/Machines/MSX/MSX.ROM",32768,"bios"],["bios/Machines/MSX/MSX2.ROM",32768,"bios"],["bios/Machines/MSX/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX/config.ini",408,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom",16384,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom",32768,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_logo_msx2+.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_main_msx2+.rom",32768,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_music.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+/MSX.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2+/config.ini",773,"bios"],["bios/Machines/MSX2/MSX.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2/config.ini",649,"bios"],["bios/Machines/MSXturboR/config.ini",941,"bios"],["bios/Machines/SVI - Spectravideo SVI-318/svi318.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi806se.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328/svi328.rom",32768,"bios"],["bios/Machines/Shared Roms/ARAB1.ROM",32768,"bios"],["bios/Machines/Shared Roms/ARABIC.rom",32768,"bios"],["bios/Machines/Shared Roms/BEERIDE.ROM",16384,"bios"],["bios/Machines/Shared Roms/FMPAC.rom",65536,"bios"],["bios/Machines/Shared Roms/GCVMX80.ROM",8192,"bios"],["bios/Machines/Shared Roms/HANGUL.rom",131072,"bios"],["bios/Machines/Shared Roms/KANJI.rom",262144,"bios"],["bios/Machines/Shared Roms/MICROSOLDISK.ROM",16384,"bios"],["bios/Machines/Shared Roms/MOONSOUND.rom",2097152,"bios"],["bios/Machines/Shared Roms/MSX.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2AR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2AREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSX2BR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2BREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2EXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2FR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2FREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2G.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2GEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2HAN.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2J.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2JEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2KR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2KREXT.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2P.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2PEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2PMUS.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2R.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2R2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2REXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2SE.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SPEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSXAR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXBR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXDOS2.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXDOS23.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXFR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXG.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXHAN.rom",8192,"bios"],["bios/Machines/Shared Roms/MSXJ.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKANJI.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXSE.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXSP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXTR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXTREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTRMUS.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTROPT.ROM",16384,"bios"],["bios/Machines/Shared Roms/NATIONALDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/NOVAXIS.rom",16384,"bios"],["bios/Machines/Shared Roms/PAINT.rom",65536,"bios"],["bios/Machines/Shared Roms/PANASONICDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/PHILIPSDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/RS232.ROM",8192,"bios"],["bios/Machines/Shared Roms/SUNRISEIDE.rom",65536,"bios"],["bios/Machines/Shared Roms/SWP.rom",32768,"bios"],["bios/Machines/Shared Roms/Shared.txt",41,"bios"],["bios/Machines/Shared Roms/XBASIC2.rom",16384,"bios"],["bios/Machines/Shared Roms/nowindDos1.rom",524288,"bios"],["bios/Machines/Shared Roms/nowindDos2.rom",524288,"bios"],["bios/Mupen64plus/IPL.n64",4194304,"bios"],["bios/Mupen64plus/font.ttf",65932,"bios"],["bios/NWINTER.GRP",10965909,"game_data"],["bios/NstDatabase.xml",1022369,"bios"],["bios/PPSSPP/ppge_atlas.meta",1119232,"bios"],["bios/PPSSPP/ppge_atlas.zim",666530,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/SOUNDS.RFF",12830764,"game_data"],["bios/STBIOS.bin",262144,"bios"],["bios/SURFACE.DAT",4096,"game_data"],["bios/SW.GRP",26056769,"game_data"],["bios/VOXEL.DAT",8192,"game_data"],["bios/Vircon32Bios.v32",1073060,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/[BIOS] Atari Jaguar CD (World).j64",262144,"bios"],["bios/[BIOS] Atari Jaguar Developer CD (World).j64",262144,"bios"],["bios/ace.zip",21283,"bios"],["bios/ace91.zip",27636,"bios"],["bios/ace91_euro.zip",27381,"bios"],["bios/ace_a.zip",3752,"bios"],["bios/ace_a2.zip",3760,"bios"],["bios/aceeuro.zip",23853,"bios"],["bios/action2.wad",209908382,"game_data"],["bios/all.bin",516096,"bios"],["bios/areplay.bin",32768,"bios"],["bios/astron.zip",57886,"bios"],["bios/astronp.zip",23339,"bios"],["bios/atari-1200xl-os-rev-10.rom",16384,"bios"],["bios/atari-1200xl-os-rev-11.rom",16384,"bios"],["bios/atari-5200-os-2port.rom",2048,"bios"],["bios/atari-800-os-a-ntsc.rom",10240,"bios"],["bios/atari-basic-rev-a.rom",8192,"bios"],["bios/atari-basic-rev-b.rom",8192,"bios"],["bios/atari-xl-os-ver-1.rom",16384,"bios"],["bios/atari-xl-os-ver-3.rom",16384,"bios"],["bios/badlandp.zip",8789,"bios"],["bios/badlands.zip",12872,"bios"],["bios/bega.zip",48777,"bios"],["bios/begar1.zip",19993,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/blazer.zip",19999,"bios"],["bios/c52.bin",1024,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/cliff.zip",16725,"bios"],["bios/cliff_ox.zip",16879,"bios"],["bios/cliffalt.zip",15087,"bios"],["bios/cliffalt2.zip",14504,"bios"],["bios/cobra.zip",29388,"bios"],["bios/cobraab.zip",20648,"bios"],["bios/cobraconv.zip",27623,"bios"],["bios/cobram3.zip",23520,"bios"],["bios/colecovision.rom",8192,"bios"],["bios/cputest.zip",11874,"bios"],["bios/custom.pal",192,"bios"],["bios/dc/awbios.zip",34620,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/font.bin",519984,"bios"],["bios/dc/naomi.zip",6134785,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/delaweare.wad",83219726,"game_data"],["bios/disksys.rom",8192,"bios"],["bios/dle11.zip",28296,"bios"],["bios/dle20.zip",25955,"bios"],["bios/dle21.zip",24883,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/ep128emu/roms/tvc22_ext.rom",8192,"bios"],["bios/ep128emu/roms/tvc22_sys.rom",16384,"bios"],["bios/ep128emu/roms/tvc_dos12d.rom",16384,"bios"],["bios/ep128emu/roms/tvcfileio.rom",8192,"bios"],["bios/esh.zip",16764,"bios"],["bios/eshalt.zip",5660,"bios"],["bios/eshalt2.zip",5277,"bios"],["bios/eshfix7.zip",5669,"bios"],["bios/eshfix7alt.zip",5678,"bios"],["bios/eshfix7alt2.zip",5669,"bios"],["bios/exec.bin",8192,"bios"],["bios/fbneo/hiscore.dat",328397,"bios"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/firefox.zip",53410,"bios"],["bios/firefoxa.zip",51026,"bios"],["bios/firmware.bin",262144,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me_plus-lr.jar",1219093,"bios"],["bios/fuse/128-0.rom",16384,"bios"],["bios/fuse/128-1.rom",16384,"bios"],["bios/fuse/128p-0.rom",16384,"bios"],["bios/fuse/128p-1.rom",16384,"bios"],["bios/fuse/256s-0.rom",16384,"bios"],["bios/fuse/256s-1.rom",16384,"bios"],["bios/fuse/256s-2.rom",16384,"bios"],["bios/fuse/256s-3.rom",16384,"bios"],["bios/fuse/48.rom",16384,"bios"],["bios/fuse/didaktik80.rom",14336,"bios"],["bios/fuse/disciple.rom",8192,"bios"],["bios/fuse/gluck.rom",16384,"bios"],["bios/fuse/if1-2.rom",8192,"bios"],["bios/fuse/mf1.rom",8192,"bios"],["bios/fuse/mf128.rom",8192,"bios"],["bios/fuse/mf3.rom",8192,"bios"],["bios/fuse/opus.rom",8192,"bios"],["bios/fuse/plus2-0.rom",16384,"bios"],["bios/fuse/plus2-1.rom",16384,"bios"],["bios/fuse/plus3-0.rom",16384,"bios"],["bios/fuse/plus3-1.rom",16384,"bios"],["bios/fuse/plus3-2.rom",16384,"bios"],["bios/fuse/plus3-3.rom",16384,"bios"],["bios/fuse/plus3e-0.rom",16384,"bios"],["bios/fuse/plus3e-1.rom",16384,"bios"],["bios/fuse/plus3e-2.rom",16384,"bios"],["bios/fuse/plus3e-3.rom",16384,"bios"],["bios/fuse/plusd.rom",8192,"bios"],["bios/fuse/se-0.rom",16384,"bios"],["bios/fuse/se-1.rom",16384,"bios"],["bios/fuse/speccyboot-1.4.rom",8192,"bios"],["bios/fuse/tc2048.rom",16384,"bios"],["bios/fuse/tc2068-0.rom",16384,"bios"],["bios/fuse/tc2068-1.rom",8192,"bios"],["bios/fuse/trdos.rom",16384,"bios"],["bios/fuse/ttx2000s.rom",8192,"bios"],["bios/fuse/usource.rom",8192,"bios"],["bios/g7400.bin",1024,"bios"],["bios/galaxy.zip",48574,"bios"],["bios/galaxyp.zip",20042,"bios"],["bios/gamecontrollerdb.txt",609830,"game_data"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gluck.rom",16384,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gpworld.zip",86990,"bios"],["bios/grom.bin",2048,"bios"],["bios/gtg.zip",19748,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hacx2.wad",20504847,"game_data"],["bios/harm1.wad",58396393,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/howard.o",513,"bios"],["bios/interstellar.zip",39757,"bios"],["bios/jagboot.rom",131072,"bios"],["bios/jagboot_m.rom",131072,"bios"],["bios/jopac.bin",1024,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/lair.zip",17906,"bios"],["bios/lair2.zip",25809,"bios"],["bios/lair2_211.zip",23278,"bios"],["bios/lair2_300.zip",24540,"bios"],["bios/lair2_314.zip",25195,"bios"],["bios/lair2_315.zip",25271,"bios"],["bios/lair2_316_euro.zip",25175,"bios"],["bios/lair2_318.zip",25592,"bios"],["bios/lair2_319_euro.zip",25493,"bios"],["bios/lair2_319_span.zip",25828,"bios"],["bios/lair_a.zip",21377,"bios"],["bios/lair_b.zip",4293,"bios"],["bios/lair_c.zip",968,"bios"],["bios/lair_d.zip",27677,"bios"],["bios/lair_d2.zip",4056,"bios"],["bios/lair_e.zip",20802,"bios"],["bios/lair_f.zip",6027,"bios"],["bios/lair_ita.zip",6408,"bios"],["bios/lair_n1.zip",26477,"bios"],["bios/lair_x.zip",24316,"bios"],["bios/laireuro.zip",10771,"bios"],["bios/lgp.zip",37609,"bios"],["bios/lynxboot.img",512,"bios"],["bios/mach3.zip",441761,"bios"],["bios/mame2003-plus/artwork/blueshrk.zip",925914,"game_data"],["bios/mame2003-plus/artwork/dotron.zip",2010009,"game_data"],["bios/mame2003-plus/artwork/frogs.zip",2832731,"game_data"],["bios/mame2003-plus/artwork/invaders.zip",4324198,"game_data"],["bios/mame2003-plus/artwork/omegrace.zip",1754523,"game_data"],["bios/mame2003-plus/artwork/skydiver.zip",117241,"game_data"],["bios/mame2003-plus/artwork/solarq.zip",1342645,"game_data"],["bios/mame2003-plus/artwork/warrior.zip",1125335,"game_data"],["bios/mame2003-plus/cheat.dat",7971360,"game_data"],["bios/mame2003-plus/hiscore.dat",131926,"game_data"],["bios/mame2003-plus/history.dat",38635890,"game_data"],["bios/mame2003-plus/mameinfo.dat",24837237,"game_data"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/ng-lo.rom",65536,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/neocdz.zip",1181333,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/penthous.zip",2112419,"game_data"],["bios/plutonia.wad",17420824,"game_data"],["bios/psxonpsp660.bin",524288,"bios"],["bios/quasi88/DISK.ROM",2048,"bios"],["bios/quasi88/N88.ROM",32768,"bios"],["bios/quasi88/N88N.ROM",32768,"bios"],["bios/quasi88/N88_0.ROM",8192,"bios"],["bios/quasi88/N88_1.ROM",8192,"bios"],["bios/quasi88/N88_2.ROM",8192,"bios"],["bios/quasi88/N88_3.ROM",8192,"bios"],["bios/quasi88/font.rom",2048,"bios"],["bios/quasi88/font2.rom",2048,"bios"],["bios/quasi88/font3.rom",2048,"bios"],["bios/quasi88/n88jisho.rom",524288,"bios"],["bios/quasi88/n88knj1.rom",131072,"bios"],["bios/quasi88/n88knj2.rom",131072,"bios"],["bios/roadblaster.zip",20664,"bios"],["bios/rom.key",2069,"bios"],["bios/rotwb.wad",20592999,"game_data"],["bios/sae.zip",27734,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sanyotry.bin",1048576,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/sdq.zip",11467,"bios"],["bios/sdqshort.zip",10147,"bios"],["bios/sdqshortalt.zip",10161,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/sl31253.bin",1024,"bios"],["bios/sl31254.bin",1024,"bios"],["bios/sl90025.bin",1024,"bios"],["bios/square1.pk3",45202919,"game_data"],["bios/stvbios.zip",2955630,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262144,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/system/nds_bios_arm7.bin",16384,"bios"],["bios/system/nds_bios_arm9.bin",4096,"bios"],["bios/system/nds_firmware.bin",262144,"bios"],["bios/timetrav.zip",53103,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/tos.img",196608,"bios"],["bios/tq.zip",24144,"bios"],["bios/tq_alt.zip",3831,"bios"],["bios/tq_swear.zip",19758,"bios"],["bios/trdos.rom",16384,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/upd7801g.s01",4096,"bios"],["bios/uvt.zip",62052,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/wildmidi.cfg",192,"game_data"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",2048,"bios"],["neogeo/aes.zip",850311,"bios"],["neogeo/neogeo.zip",1952551,"bios"]],"format_version":1,"platform":"amberelec","sets":{"amstrad-cpc|cap32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"amstrad-cpc|crocods":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"aquaplus-piece|piemu":{"bytes":516096,"files":[207],"optional":[],"required_bytes":516096},"arcade-laserdisc|hypseus-singe":{"bytes":2648486,"files":[200,201,202,203,204,205,209,210,219,220,221,222,235,240,241,242,243,244,245,246,247,249,259,260,261,270,271,272,273,274,275,280,281,325,326,327,335,337,343,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,468,471,484,485,486,504,507,508,509,522],"optional":[327],"required_bytes":2038656},"arcade|fbneo":{"bytes":309895027,"files":[277,278,279],"optional":[277,278,279],"required_bytes":0},"arcade|mame2003_plus":{"bytes":86009009,"files":[392,393,394,395,396,397,398,399,400,401,402,403],"optional":[392,393,394,395,396,397,398,399,400,401,402,403],"required_bytes":0},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella2014":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-400-800|atari800":{"bytes":231424,"files":[10,14,15,16,17,18,176,177,178,179,197,211,212,213,214,215,216,217,218],"optional":[18,176,177,178,179,197,211,212,213,214,215,216,217,218],"required_bytes":47104},"atari-5200|a5200":{"bytes":47104,"files":[10,14,15,16,17],"optional":[],"required_bytes":47104},"atari-7800|prosystem":{"bytes":20480,"files":[12,13],"optional":[12],"required_bytes":4096},"atari-jaguar|virtualjaguar":{"bytes":786432,"files":[198,199,344,345],"optional":[198,199,344,345],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[342,390],"optional":[342],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[341,506],"optional":[341],"required_bytes":196608},"blood|raze":{"bytes":16386979,"files":[20,36,190,192,194],"optional":[20,36,190,192,194],"required_bytes":0},"capcom-cps1|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|fbalpha2012":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"casio-pv1000|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"chip8|jaxe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"colecovision|bluemsx":{"bytes":6471830,"files":[19,29,30,31,32,33,34,56,57,58,59,60,61,105,106,107,108,109,110,111,112,113,147,158,159,160,161,162,163,164,165,167,168,169,248],"optional":[30,31,32,33,34],"required_bytes":4220235},"commodore-amiga-cd32|puae2021":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae2021":{"bytes":18823838,"files":[22,23,44,45,46,47,48,49,50,51,52,53,196,237,238,355,356,357,358,359,360,361,362,363,364,365,366,367,469,511,512,513,514,515,516,517,518,519,520],"optional":[196,237,238,355,356,360,361,362,469,511,512,513,514,515,516,517,518,519,520],"required_bytes":8912896},"commodore-c128|vice_x128":{"bytes":106496,"files":[38,39,40,41,42],"optional":[38,39,40,41,42],"required_bytes":0},"commodore-c64|vice_x64":{"bytes":114688,"files":[38,39,40,42,43,347,348],"optional":[38,39,40,42,43,347,348],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":12288,"files":[239,349],"optional":[239,349],"required_bytes":0},"doom|gzdoom":{"bytes":613275828,"files":[206,257,262,263,264,283,284,285,338,339,340,453,470,494,505],"optional":[206,257,262,263,264,283,284,285,338,339,340,453,470,494,505],"required_bytes":0},"dos|dosbox_pure":{"bytes":41236388,"files":[24,25,26,27,54,55,180,181,182,183,184,185,186,187,188,189],"optional":[24,25,26,27,54,55,180,181,182,183,184,185,186,187,188,189],"required_bytes":0},"duke3d|raze":{"bytes":24114107,"files":[28,172,452],"optional":[28,172,452],"required_bytes":0},"enterprise-64-128|ep128emu_core":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"entex-advision|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"exhumed|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":3072,"files":[491,492,493],"optional":[491,492,493],"required_bytes":0},"famicom|nestopia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamate|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gameking|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamepock|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"handheld-electronic|gw":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"hartung-game-master|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"intellivision|freeintv":{"bytes":36864,"files":[35,37,276,336],"optional":[],"required_bytes":36864},"j2me|freej2me_plus":{"bytes":1219093,"files":[286],"optional":[],"required_bytes":1219093},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|bluemsx":{"bytes":8708811,"files":[29,30,31,32,33,34,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169],"optional":[30,31,32,33,34,150],"required_bytes":6424448},"nam|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-88|quasi88":{"bytes":892928,"files":[455,456,457,458,459,460,461,462,463,464,465,466,467],"optional":[462,463,464,465,466,467],"required_bytes":100352},"nec-pc-engine-cd|mednafen_pce_fast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|mednafen_pce_fast":{"bytes":1343488,"files":[331,496,497,498,499,500],"optional":[498,500],"required_bytes":819200},"nec-pcfx|beetle_pcfx":{"bytes":1048576,"files":[451],"optional":[],"required_bytes":1048576},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":2802862,"files":[799,800],"optional":[],"required_bytes":2802862},"nintendo-64|":{"bytes":8454540,"files":[11,170,171],"optional":[],"required_bytes":8454540},"nintendo-ds|drastic":{"bytes":565248,"files":[226,227,282,501,502,503],"optional":[501,502,503],"required_bytes":282624},"nintendo-fds|nestopia":{"bytes":1030561,"files":[173,258],"optional":[],"required_bytes":1030561},"nintendo-gba|mgba":{"bytes":19200,"files":[328,329,330,488],"optional":[],"required_bytes":19200},"nintendo-gbc|gambatte":{"bytes":1051136,"files":[21,328,330],"optional":[],"required_bytes":1051136},"nintendo-gb|gambatte":{"bytes":1051136,"files":[21,328,330],"optional":[],"required_bytes":1051136},"nintendo-nes|nestopia":{"bytes":192,"files":[250],"optional":[250],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[224],"optional":[224],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":1048576,"files":[21],"optional":[],"required_bytes":1048576},"nintendo-snes|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sufami-turbo|snes9x":{"bytes":262144,"files":[191],"optional":[],"required_bytes":262144},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[236,324,346,439,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792],"optional":[],"required_bytes":1606321},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"panasonic-3do|opera":{"bytes":13123332,"files":[9,334,440,441,442,443,444,445,446,447,448,449,450,476],"optional":[440,441,443,445,446,447,448,449,450],"required_bytes":4718592},"pc-98|np2kai":{"bytes":1294790,"files":[419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438],"optional":[419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438],"required_bytes":0},"philips-cdi|same_cdi":{"bytes":1857124,"files":[472,473,474,475],"optional":[472,473,475],"required_bytes":745703},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|fake08":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"powerslave|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"redneck|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"rpgmaker|easyrpg":{"bytes":148398498,"files":[265,793],"optional":[265,793],"required_bytes":0},"scummvm|scummvm-standalone":{"bytes":1703936,"files":[25,26,54,55],"optional":[25,26,54,55],"required_bytes":0},"scv|emuscv":{"bytes":4096,"files":[521],"optional":[],"required_bytes":4096},"sega-32x|picodrive":{"bytes":3328,"files":[6,7,8],"optional":[6,7,8],"required_bytes":0},"sega-dreamcast-arcade|flycast2021":{"bytes":8266557,"files":[251,255,256],"optional":[],"required_bytes":8266557},"sega-dreamcast-arcade|flycast2021le":{"bytes":8266557,"files":[251,255,256],"optional":[],"required_bytes":8266557},"sega-dreamcast|flycast2021":{"bytes":2748208,"files":[252,253,254],"optional":[254],"required_bytes":2228224},"sega-dreamcast|flycast2021le":{"bytes":2748208,"files":[252,253,254],"optional":[254],"required_bytes":2228224},"sega-gamegear|gearsystem":{"bytes":1024,"files":[223],"optional":[],"required_bytes":1024},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":32768,"files":[225,231,232,234],"optional":[225],"required_bytes":24576},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[228,229,230],"optional":[],"required_bytes":393216},"sega-megadrive|genesis_plus_gx":{"bytes":2426880,"files":[208,233,332,489,490],"optional":[208,233,332,489,490],"required_bytes":0},"sega-saturn|yabasanshiro":{"bytes":8722798,"files":[404,405,406,477,487,495],"optional":[],"required_bytes":8722798},"sega-sc3000|bluemsx":{"bytes":6414139,"files":[29,30,31,32,33,34,105,106,107,108,109,110,111,112,113,147,158,159,160,161,162,163,164,165,167,168,169],"optional":[30,31,32,33,34],"required_bytes":4162544},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"shadow-warrior|raze":{"bytes":26056769,"files":[193],"optional":[193],"required_bytes":0},"sharp-x1|x1":{"bytes":318464,"files":[794,795,796,797,798],"optional":[794,795,796],"required_bytes":6144},"sharp-x68000|px68k":{"bytes":1310720,"files":[350,351,352,353,354],"optional":[],"required_bytes":1310720},"sinclair-zx-spectrum|fuse":{"bytes":645120,"files":[0,1,2,3,4,5,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,333,510],"optional":[],"required_bytes":645120},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":8442300,"files":[407,408,409,410,411,412,413,414,415,416,417,418,800],"optional":[407,408,409,410,411,412,413,416,417],"required_bytes":3723708},"snk-ngpc|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"solarus|solarus":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation|pcsx_rearmed":{"bytes":3670016,"files":[454,478,479,480,481,482,483],"optional":[454,478,479,483],"required_bytes":1572864},"sony-psp|ppsspp":{"bytes":1785762,"files":[174,175],"optional":[174,175],"required_bytes":0},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"videoton-tvc|ep128emu_core":{"bytes":49152,"files":[266,267,268,269],"optional":[266,267,268,269],"required_bytes":0},"vircon32|vircon32":{"bytes":1073060,"files":[195],"optional":[195],"required_bytes":0},"vtech-vsmile|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ww2gi|raze":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
diff --git a/install/games/fallback/emuelec.json b/install/games/fallback/emuelec.json
index 2641e9b42..889d7e601 100644
--- a/install/games/fallback/emuelec.json
+++ b/install/games/fallback/emuelec.json
@@ -1 +1 @@
-{"files":[["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BS-X.bin",1048576,"bios"],["bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom",262144,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/Databases/colecodb.xml",164848,"bios"],["bios/Databases/msxcaswavdb.xml",819679,"bios"],["bios/Databases/msxromdb.xml",930986,"bios"],["bios/Databases/msxsysromdb.xml",157542,"bios"],["bios/Databases/segadb.xml",82318,"bios"],["bios/Databases/svidb.xml",261070,"bios"],["bios/ECS.bin",24576,"bios"],["bios/GBA/gba_bios.bin",16384,"bios"],["bios/GC/EUR/IPL.bin",2097152,"bios"],["bios/GC/JAP/IPL.bin",2097152,"bios"],["bios/GC/USA/IPL.bin",2097152,"bios"],["bios/GC/dsp_coef.bin",4096,"bios"],["bios/GC/dsp_rom.bin",8192,"bios"],["bios/GC/font_japanese.bin",259626,"bios"],["bios/GC/font_western.bin",6478,"bios"],["bios/IVOICE.bin",2048,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C128.bin",16384,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom",262144,"bios"],["bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom",524288,"bios"],["bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom",524288,"bios"],["bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom",524288,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723a_fw.bin",24548,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723b_fw.bin",45048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723d_fw.bin",52080,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761a_fw.bin",74488,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761bu_fw.bin",44484,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821a_fw.bin",37420,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821c_fw.bin",54636,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822b_fw.bin",51176,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822cu_fw.bin",38207,"bios"],["bios/Load/Firmware/rtl_bt/rtl8851bu_fw.bin",49760,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852au_fw.bin",67188,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852btu_fw.bin",128140,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852bu_fw.bin",129733,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852cu_fw.bin",113336,"bios"],["bios/Load/Firmware/rtl_bt/rtl8922au_fw.bin",71360,"bios"],["bios/Load/WiiSD.raw",134217728,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-1.rom",8192,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-2.rom",8192,"bios"],["bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/config.ini",347,"bios"],["bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM",8192,"bios"],["bios/Machines/Forte II Games - Pesadelo/pesadelo.rom",65536,"bios"],["bios/Machines/MSX - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom",16384,"bios"],["bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom",32768,"bios"],["bios/Machines/MSX/MSX.ROM",32768,"bios"],["bios/Machines/MSX/MSX2.ROM",32768,"bios"],["bios/Machines/MSX/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX/config.ini",408,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom",16384,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom",32768,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_logo_msx2+.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_main_msx2+.rom",32768,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_music.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+/MSX.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2+/config.ini",773,"bios"],["bios/Machines/MSX2/MSX.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2/config.ini",649,"bios"],["bios/Machines/MSXturboR/config.ini",941,"bios"],["bios/Machines/SVI - Spectravideo SVI-318/svi318.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi806se.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328/svi328.rom",32768,"bios"],["bios/Machines/Shared Roms/ARAB1.ROM",32768,"bios"],["bios/Machines/Shared Roms/ARABIC.rom",32768,"bios"],["bios/Machines/Shared Roms/BEERIDE.ROM",16384,"bios"],["bios/Machines/Shared Roms/FMPAC.rom",65536,"bios"],["bios/Machines/Shared Roms/GCVMX80.ROM",8192,"bios"],["bios/Machines/Shared Roms/HANGUL.rom",131072,"bios"],["bios/Machines/Shared Roms/KANJI.rom",262144,"bios"],["bios/Machines/Shared Roms/MICROSOLDISK.ROM",16384,"bios"],["bios/Machines/Shared Roms/MOONSOUND.rom",2097152,"bios"],["bios/Machines/Shared Roms/MSX.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2AR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2AREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSX2BR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2BREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2EXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2FR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2FREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2G.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2GEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2HAN.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2J.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2JEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2KR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2KREXT.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2P.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2PEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2PMUS.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2R.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2R2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2REXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2SE.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SPEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSXAR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXBR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXDOS2.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXDOS23.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXFR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXG.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXHAN.rom",8192,"bios"],["bios/Machines/Shared Roms/MSXJ.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKANJI.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXSE.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXSP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXTR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXTREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTRMUS.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTROPT.ROM",16384,"bios"],["bios/Machines/Shared Roms/NATIONALDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/NOVAXIS.rom",16384,"bios"],["bios/Machines/Shared Roms/PAINT.rom",65536,"bios"],["bios/Machines/Shared Roms/PANASONICDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/PHILIPSDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/RS232.ROM",8192,"bios"],["bios/Machines/Shared Roms/SUNRISEIDE.rom",65536,"bios"],["bios/Machines/Shared Roms/SWP.rom",32768,"bios"],["bios/Machines/Shared Roms/Shared.txt",41,"bios"],["bios/Machines/Shared Roms/XBASIC2.rom",16384,"bios"],["bios/Machines/Shared Roms/nowindDos1.rom",524288,"bios"],["bios/Machines/Shared Roms/nowindDos2.rom",524288,"bios"],["bios/Mupen64plus/IPL.n64",4194304,"bios"],["bios/Mupen64plus/font.ttf",65932,"bios"],["bios/NstDatabase.xml",1009534,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/STBIOS.bin",262144,"bios"],["bios/SegaCDBIOS9303.bin",131072,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/Wii/clientca.pem",1005,"bios"],["bios/Wii/clientcakey.pem",609,"bios"],["bios/Wii/rootca.pem",897,"bios"],["bios/Wii/shared2/sys/SYSCONF",16384,"bios"],["bios/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/aa310.zip",6536273,"bios"],["bios/ace.zip",21283,"bios"],["bios/ace91.zip",27636,"bios"],["bios/ace91_euro.zip",27381,"bios"],["bios/ace_a.zip",3752,"bios"],["bios/ace_a2.zip",3760,"bios"],["bios/aceeuro.zip",23853,"bios"],["bios/advision.zip",1546,"bios"],["bios/ap2000.zip",21618,"bios"],["bios/apfm1000.zip",6896,"bios"],["bios/aplcd150.zip",9137,"bios"],["bios/arc_a448.zip",602,"bios"],["bios/arc_a448b.zip",836,"bios"],["bios/arc_acejoy.zip",1311,"bios"],["bios/arc_armadeus.zip",1014,"bios"],["bios/arc_bbcio_aga30.zip",1329,"bios"],["bios/arc_bbcio_aka10.zip",3792,"bios"],["bios/arc_bbcio_we.zip",1273,"bios"],["bios/arc_eaglem2.zip",47500,"bios"],["bios/arc_ether1_aka25.zip",163,"bios"],["bios/arc_ether2_aeh50.zip",378,"bios"],["bios/arc_ether3_aeh54.zip",50047,"bios"],["bios/arc_ethera.zip",149278,"bios"],["bios/arc_etherd.zip",105641,"bios"],["bios/arc_etherr.zip",49753,"bios"],["bios/arc_faxpack.zip",5826,"bios"],["bios/arc_greyhawk.zip",5265,"bios"],["bios/arc_hdisc_akd52.zip",421,"bios"],["bios/arc_hdisc_cw.zip",565,"bios"],["bios/arc_hdisc_morley.zip",1333,"bios"],["bios/arc_hdisc_we.zip",462,"bios"],["bios/arc_ide_be.zip",24321,"bios"],["bios/arc_ide_rdev.zip",7001,"bios"],["bios/arc_iomidi_aka15.zip",5309,"bios"],["bios/arc_lark.zip",33629,"bios"],["bios/arc_lbp4.zip",14292,"bios"],["bios/arc_midi2.zip",12743,"bios"],["bios/arc_midi_aka16.zip",21857,"bios"],["bios/arc_midimax.zip",36846,"bios"],["bios/arc_midimax2.zip",21595,"bios"],["bios/arc_nexus_a500.zip",15560,"bios"],["bios/arc_rom_aka05.zip",4909,"bios"],["bios/arc_rom_r225.zip",107080,"bios"],["bios/arc_rs423.zip",285,"bios"],["bios/arc_scan256.zip",9805,"bios"],["bios/arc_scanjunior.zip",6379,"bios"],["bios/arc_scanjunior3.zip",6965,"bios"],["bios/arc_scanlight.zip",7019,"bios"],["bios/arc_scanvideo.zip",25778,"bios"],["bios/arc_scsi_aka30.zip",11747,"bios"],["bios/arc_scsi_aka31.zip",11851,"bios"],["bios/arc_scsi_aka32.zip",96376,"bios"],["bios/arc_scsi_cumana.zip",43880,"bios"],["bios/arc_scsi_ling.zip",51477,"bios"],["bios/arc_scsi_morley.zip",196852,"bios"],["bios/arc_scsi_oak.zip",85368,"bios"],["bios/arc_scsi_vti.zip",34230,"bios"],["bios/arc_serial.zip",3063,"bios"],["bios/arc_spectra.zip",2421,"bios"],["bios/arc_ua_morley.zip",1410,"bios"],["bios/arc_uma_morley.zip",9527,"bios"],["bios/arc_upa_hccs.zip",1172,"bios"],["bios/arc_upmidi_aka12.zip",9038,"bios"],["bios/archimedes_keyboard.zip",1323,"bios"],["bios/areplay.bin",32768,"bios"],["bios/astrocde.zip",6800,"bios"],["bios/astrocdl.zip",6805,"bios"],["bios/astrocdw.zip",6807,"bios"],["bios/astron.zip",57886,"bios"],["bios/astronp.zip",23339,"bios"],["bios/atari-1200xl-os-rev-10.rom",16384,"bios"],["bios/atari-1200xl-os-rev-11.rom",16384,"bios"],["bios/atari-5200-os-2port.rom",2048,"bios"],["bios/atari-800-os-a-ntsc.rom",10240,"bios"],["bios/atari-basic-rev-a.rom",8192,"bios"],["bios/atari-basic-rev-b.rom",8192,"bios"],["bios/atari-xl-os-ver-1.rom",16384,"bios"],["bios/atari-xl-os-ver-3.rom",16384,"bios"],["bios/badlandp.zip",8789,"bios"],["bios/badlands.zip",12872,"bios"],["bios/bbc_24bbc.zip",2844684,"bios"],["bios/bbc_2ndserial.zip",2844684,"bios"],["bios/bbc_acorn1770.zip",60692,"bios"],["bios/bbc_acorn8271.zip",97195,"bios"],["bios/bbc_ams3.zip",8252,"bios"],["bios/bbc_ariesb20.zip",2525,"bios"],["bios/bbc_ariesb32.zip",8935,"bios"],["bios/bbc_autoprom.zip",2737,"bios"],["bios/bbc_beebspch.zip",6564,"bios"],["bios/bbc_bitstik1.zip",5798,"bios"],["bios/bbc_bitstik2.zip",5798,"bios"],["bios/bbc_cc500.zip",2844684,"bios"],["bios/bbc_chameleon.zip",654,"bios"],["bios/bbc_cisco.zip",13978,"bios"],["bios/bbc_cms6502.zip",17969,"bios"],["bios/bbc_cumana1.zip",10212,"bios"],["bios/bbc_cumana2.zip",11242,"bios"],["bios/bbc_cumana68k.zip",3790,"bios"],["bios/bbc_cv1797.zip",6453,"bios"],["bios/bbc_datacentre.zip",40386,"bios"],["bios/bbc_ieee488.zip",2844684,"bios"],["bios/bbc_integrab.zip",34749,"bios"],["bios/bbc_kenda.zip",6558,"bios"],["bios/bbc_magazzino.zip",11695,"bios"],["bios/bbc_memexb20.zip",1305,"bios"],["bios/bbc_mertec.zip",13212,"bios"],["bios/bbc_morleyaa.zip",5048,"bios"],["bios/bbc_multiform.zip",11635,"bios"],["bios/bbc_opus1770.zip",24620,"bios"],["bios/bbc_opus2791.zip",47054,"bios"],["bios/bbc_opus2793.zip",24583,"bios"],["bios/bbc_opus3.zip",36996,"bios"],["bios/bbc_opus8272.zip",23119,"bios"],["bios/bbc_opusa.zip",23792,"bios"],["bios/bbc_pdram.zip",2195,"bios"],["bios/bbc_pms64k.zip",8361,"bios"],["bios/bbc_ramdisc.zip",2844684,"bios"],["bios/bbc_raven20.zip",4486,"bios"],["bios/bbc_stl1770_1.zip",12775,"bios"],["bios/bbc_stl1770_2.zip",12822,"bios"],["bios/bbc_stl2m128.zip",3298,"bios"],["bios/bbc_stl4m32.zip",11382,"bios"],["bios/bbc_stldfdc_1.zip",12504,"bios"],["bios/bbc_stlswr128.zip",11806,"bios"],["bios/bbc_stlswr16.zip",11806,"bios"],["bios/bbc_stlswr32.zip",11806,"bios"],["bios/bbc_stlswr64.zip",11806,"bios"],["bios/bbc_sweetalker.zip",2019,"bios"],["bios/bbc_tube_16032.zip",17960,"bios"],["bios/bbc_tube_32016.zip",31067,"bios"],["bios/bbc_tube_32016l.zip",3585,"bios"],["bios/bbc_tube_6502.zip",4337,"bios"],["bios/bbc_tube_6502e.zip",1515,"bios"],["bios/bbc_tube_6502p.zip",6023,"bios"],["bios/bbc_tube_65c102.zip",4375,"bios"],["bios/bbc_tube_80186.zip",6643,"bios"],["bios/bbc_tube_80286.zip",6649,"bios"],["bios/bbc_tube_a500.zip",12117,"bios"],["bios/bbc_tube_a500d.zip",12312,"bios"],["bios/bbc_tube_arm.zip",38022,"bios"],["bios/bbc_tube_arm7.zip",109910,"bios"],["bios/bbc_tube_casper.zip",18005,"bios"],["bios/bbc_tube_cms6809.zip",9090,"bios"],["bios/bbc_tube_matchbox.zip",48928,"bios"],["bios/bbc_tube_pcplus.zip",6662,"bios"],["bios/bbc_tube_rc6502.zip",31532,"bios"],["bios/bbc_tube_rc65816.zip",31259,"bios"],["bios/bbc_tube_x25.zip",17863,"bios"],["bios/bbc_tube_z80.zip",3197,"bios"],["bios/bbc_tube_z80w.zip",3145,"bios"],["bios/bbc_tube_zep100.zip",40985,"bios"],["bios/bbc_tube_zep100l.zip",18020,"bios"],["bios/bbc_tube_zep100m.zip",29188,"bios"],["bios/bbc_tube_zep100w.zip",29266,"bios"],["bios/bbc_udm.zip",44349,"bios"],["bios/bbc_voicebox.zip",2019,"bios"],["bios/bbc_we32kram.zip",22610,"bios"],["bios/bbc_weddb2.zip",35836,"bios"],["bios/bbc_weddb3.zip",11202,"bios"],["bios/bbcm.zip",400592,"bios"],["bios/bbcmc.zip",100096,"bios"],["bios/bega.zip",48777,"bios"],["bios/begar1.zip",19993,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/bk/B11M_BOS.ROM",8192,"bios"],["bios/bk/B11M_EXT.ROM",8192,"bios"],["bios/bk/BAS11M_0.ROM",16384,"bios"],["bios/bk/BAS11M_1.ROM",8192,"bios"],["bios/bk/BASIC10.ROM",24576,"bios"],["bios/bk/DISK_327.ROM",4096,"bios"],["bios/bk/FOCAL10.ROM",24576,"bios"],["bios/bk/MONIT10.ROM",8192,"bios"],["bios/bk/TERAK.ROM",128,"bios"],["bios/blazer.zip",19999,"bios"],["bios/c2031.zip",12163,"bios"],["bios/c2040.zip",7844,"bios"],["bios/c2040_fdc.zip",426,"bios"],["bios/c3040.zip",7844,"bios"],["bios/c4023.zip",4285,"bios"],["bios/c4040.zip",20926,"bios"],["bios/c52.bin",1024,"bios"],["bios/c8050.zip",39422,"bios"],["bios/c8050fdc.zip",426,"bios"],["bios/c8250.zip",39422,"bios"],["bios/c8280.zip",23702,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/carthw.cfg",16367,"bios"],["bios/cdd2000.zip",195999,"bios"],["bios/cdr4210.zip",82902,"bios"],["bios/cdrn820s.zip",66313,"bios"],["bios/cdu415.zip",31828,"bios"],["bios/cdu561_25.zip",141631,"bios"],["bios/cdu75s.zip",31456,"bios"],["bios/cfp1080s.zip",67669,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/chessmachine.zip",542,"bios"],["bios/chex.deh",20367,"game_data"],["bios/chex.wad",12361532,"game_data"],["bios/cliff.zip",16725,"bios"],["bios/cliff_ox.zip",16879,"bios"],["bios/cliffalt.zip",15087,"bios"],["bios/cliffalt2.zip",14504,"bios"],["bios/cms_4080term.zip",576010,"bios"],["bios/cobra.zip",29388,"bios"],["bios/cobraab.zip",20648,"bios"],["bios/cobraconv.zip",27623,"bios"],["bios/cobram3.zip",23520,"bios"],["bios/comx_pl80.zip",8379,"bios"],["bios/cp2024.zip",23160,"bios"],["bios/cputest.zip",11874,"bios"],["bios/crd254sh.zip",31383,"bios"],["bios/crvision.zip",1810,"bios"],["bios/custom.pal",192,"bios"],["bios/cw7501.zip",83060,"bios"],["bios/d9060.zip",32197,"bios"],["bios/d9090.zip",32197,"bios"],["bios/dc/awbios.zip",34620,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/dc_nvmem.bin",131072,"bios"],["bios/dc/naomi.zip",6134785,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/dc_boot.bin",2097152,"bios"],["bios/dc_nvmem.bin",131072,"bios"],["bios/disksys.rom",8192,"bios"],["bios/dle11.zip",28296,"bios"],["bios/dle20.zip",25955,"bios"],["bios/dle21.zip",24883,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/econet_e01.zip",26965,"bios"],["bios/econet_e01s.zip",54134,"bios"],["bios/ef9365.zip",590,"bios"],["bios/electron.zip",25571,"bios"],["bios/electron64.zip",25089,"bios"],["bios/electron_ap1.zip",13514,"bios"],["bios/electron_ap6.zip",17045,"bios"],["bios/electron_elksd128.zip",37465,"bios"],["bios/electron_elksd64.zip",21261,"bios"],["bios/electron_m2105.zip",149867,"bios"],["bios/electron_mc68k.zip",35027,"bios"],["bios/electron_mode7.zip",7850,"bios"],["bios/electron_plus1.zip",1344,"bios"],["bios/electron_plus3.zip",57712,"bios"],["bios/electron_pwrjoy.zip",1437,"bios"],["bios/electron_romboxp.zip",25157,"bios"],["bios/electron_sidewndr.zip",958848,"bios"],["bios/electron_voxbox.zip",2019,"bios"],["bios/epson_fx80.zip",12887,"bios"],["bios/epson_jx80.zip",11210,"bios"],["bios/epson_rx80.zip",6311,"bios"],["bios/esh.zip",16764,"bios"],["bios/eshalt.zip",5660,"bios"],["bios/eshalt2.zip",5277,"bios"],["bios/eshfix7.zip",5669,"bios"],["bios/eshfix7alt.zip",5678,"bios"],["bios/eshfix7alt2.zip",5669,"bios"],["bios/eu_mcd1_9210.bin",131072,"bios"],["bios/eu_mcd2_9303.bin",131072,"bios"],["bios/eu_mcd2_9306.bin",131072,"bios"],["bios/ex800.zip",21628,"bios"],["bios/exec.bin",8192,"bios"],["bios/fbneo/hiscore.dat",328397,"bios"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/firefox.zip",53410,"bios"],["bios/firefoxa.zip",51026,"bios"],["bios/firmware.bin",262144,"bios"],["bios/fm7.zip",104276,"bios"],["bios/fm77av.zip",46921,"bios"],["bios/fmnew7.zip",26815,"bios"],["bios/fmtmarty.zip",1524715,"bios"],["bios/fmtowns.zip",655778,"bios"],["bios/fmtowns/FMT_DIC.ROM",524288,"bios"],["bios/fmtowns/FMT_DOS.ROM",524288,"bios"],["bios/fmtowns/FMT_F20.ROM",524288,"bios"],["bios/fmtowns/FMT_FNT.ROM",262144,"bios"],["bios/fmtowns/FMT_SYS.ROM",262144,"bios"],["bios/fmtownsux.zip",838046,"bios"],["bios/fnvision.zip",1798,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me-lr.jar",552042,"bios"],["bios/french.deh",20764,"game_data"],["bios/g7400.bin",1024,"bios"],["bios/galaxy.zip",48574,"bios"],["bios/galaxyp.zip",20042,"bios"],["bios/gamecom.zip",145138,"bios"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gmaster.zip",1686,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gpib_hardbox.zip",18236,"bios"],["bios/gpib_mshark.zip",13934,"bios"],["bios/gpib_softbox.zip",9859,"bios"],["bios/gpworld.zip",86990,"bios"],["bios/grom.bin",2048,"bios"],["bios/gtg.zip",19748,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/hd44780.zip",965,"bios"],["bios/heath_gp19_tlb.zip",13491,"bios"],["bios/heath_imaginator_tlb.zip",9135,"bios"],["bios/heath_super19_tlb.zip",5615,"bios"],["bios/heath_superset_tlb.zip",14186,"bios"],["bios/heath_tlb.zip",5021,"bios"],["bios/heath_ultra_tlb.zip",4818,"bios"],["bios/heath_watz_tlb.zip",7609,"bios"],["bios/heretic.wad",14189976,"game_data"],["bios/heretic1.wad",5120920,"game_data"],["bios/hexen.wad",20083672,"game_data"],["bios/howard.o",513,"bios"],["bios/ie15_device.zip",5520,"bios"],["bios/ie15kbd.zip",352,"bios"],["bios/interstellar.zip",39757,"bios"],["bios/jopac.bin",1024,"bios"],["bios/jp_mcd1_9111.bin",131072,"bios"],["bios/jp_mcd1_9112.bin",131072,"bios"],["bios/jp_mcd2_921222.bin",131072,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/lair.zip",17906,"bios"],["bios/lair2.zip",25809,"bios"],["bios/lair2_211.zip",23278,"bios"],["bios/lair2_300.zip",24540,"bios"],["bios/lair2_314.zip",25195,"bios"],["bios/lair2_315.zip",25271,"bios"],["bios/lair2_316_euro.zip",25175,"bios"],["bios/lair2_318.zip",25592,"bios"],["bios/lair2_319_euro.zip",25493,"bios"],["bios/lair2_319_span.zip",25828,"bios"],["bios/lair_a.zip",21377,"bios"],["bios/lair_b.zip",4293,"bios"],["bios/lair_c.zip",968,"bios"],["bios/lair_d.zip",27677,"bios"],["bios/lair_d2.zip",4056,"bios"],["bios/lair_e.zip",20802,"bios"],["bios/lair_f.zip",6027,"bios"],["bios/lair_ita.zip",6408,"bios"],["bios/lair_n1.zip",26477,"bios"],["bios/lair_x.zip",24316,"bios"],["bios/laireuro.zip",10771,"bios"],["bios/lasr2001.zip",12613,"bios"],["bios/lgp.zip",37609,"bios"],["bios/lx800.zip",15176,"bios"],["bios/lx810l.zip",22103,"bios"],["bios/lynxboot.img",512,"bios"],["bios/mach3.zip",441761,"bios"],["bios/mame/hash/advision.xml",2281,"game_data"],["bios/mame/hash/apfimag_cass.xml",43143,"game_data"],["bios/mame/hash/apfm1000.xml",9759,"game_data"],["bios/mame/hash/archimedes.xml",271056,"game_data"],["bios/mame/hash/archimedes_hdd.xml",549,"game_data"],["bios/mame/hash/archimedes_rom.xml",2409,"game_data"],["bios/mame/hash/astrocde.xml",56504,"game_data"],["bios/mame/hash/bbc_cass.xml",736181,"game_data"],["bios/mame/hash/bbc_flop_32016.xml",8282,"game_data"],["bios/mame/hash/bbc_flop_6502.xml",6281,"game_data"],["bios/mame/hash/bbc_flop_68000.xml",1770,"game_data"],["bios/mame/hash/bbc_flop_80186.xml",7946,"game_data"],["bios/mame/hash/bbc_flop_arm.xml",11609,"game_data"],["bios/mame/hash/bbc_flop_hybrid.xml",40742,"game_data"],["bios/mame/hash/bbc_flop_torch.xml",19139,"game_data"],["bios/mame/hash/bbc_flop_z80.xml",7743,"game_data"],["bios/mame/hash/bbc_hdd.xml",2639,"game_data"],["bios/mame/hash/bbc_rom.xml",502371,"game_data"],["bios/mame/hash/bbc_vsm.xml",2571,"game_data"],["bios/mame/hash/bbcb_flop.xml",124846,"game_data"],["bios/mame/hash/bbcb_flop_orig.xml",158528,"game_data"],["bios/mame/hash/bbcb_flop_us.xml",743,"game_data"],["bios/mame/hash/bbcm_cart.xml",11115,"game_data"],["bios/mame/hash/bbcm_flop.xml",5301,"game_data"],["bios/mame/hash/bbcmc_flop.xml",17528,"game_data"],["bios/mame/hash/crvision.xml",29061,"game_data"],["bios/mame/hash/e01_flop.xml",972,"game_data"],["bios/mame/hash/electron_cart.xml",22690,"game_data"],["bios/mame/hash/electron_cass.xml",270749,"game_data"],["bios/mame/hash/electron_flop.xml",105636,"game_data"],["bios/mame/hash/electron_rom.xml",36576,"game_data"],["bios/mame/hash/fm77av.xml",56002,"game_data"],["bios/mame/hash/fm7_cass.xml",84996,"game_data"],["bios/mame/hash/fm7_disk.xml",94601,"game_data"],["bios/mame/hash/fm8_cass.xml",13963,"game_data"],["bios/mame/hash/gamecom.xml",10648,"game_data"],["bios/mame/hash/gmaster.xml",7077,"game_data"],["bios/mame/hash/ibm5150.xml",824234,"game_data"],["bios/mame/hash/laser2001_cart.xml",729,"game_data"],["bios/mame/hash/laser2001_flop.xml",587,"game_data"],["bios/mame/hash/pro128s_flop.xml",14348,"game_data"],["bios/mame/hash/socrates.xml",4963,"game_data"],["bios/mame/hash/ti99_cart.xml",229953,"game_data"],["bios/mame/hash/tutor.xml",17761,"game_data"],["bios/mame/hash/vsmile_cart.xml",284343,"game_data"],["bios/mame/hash/vsmilem_cart.xml",84670,"game_data"],["bios/mame/samples/bbc.zip",8469,"game_data"],["bios/mame/samples/floppy/35_seek_12ms.wav",26540,"game_data"],["bios/mame/samples/floppy/35_seek_20ms.wav",44144,"game_data"],["bios/mame/samples/floppy/35_seek_2ms.wav",7450,"game_data"],["bios/mame/samples/floppy/35_seek_6ms.wav",22230,"game_data"],["bios/mame/samples/floppy/35_spin_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_end.wav",17684,"game_data"],["bios/mame/samples/floppy/35_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_loaded.wav",35308,"game_data"],["bios/mame/samples/floppy/35_step_1_1.wav",6878,"game_data"],["bios/mame/samples/floppy/525_seek_12ms.wav",22764,"game_data"],["bios/mame/samples/floppy/525_seek_20ms.wav",30060,"game_data"],["bios/mame/samples/floppy/525_seek_6ms.wav",14860,"game_data"],["bios/mame/samples/floppy/525_spin_empty.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_end.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_spin_start_empty.wav",11180,"game_data"],["bios/mame/samples/floppy/525_spin_start_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_step_1_1.wav",6628,"game_data"],["bios/mame2003-plus/artwork/blueshrk.zip",925914,"game_data"],["bios/mame2003-plus/artwork/dotron.zip",2010009,"game_data"],["bios/mame2003-plus/artwork/frogs.zip",2832731,"game_data"],["bios/mame2003-plus/artwork/invaders.zip",4324198,"game_data"],["bios/mame2003-plus/artwork/omegrace.zip",1754523,"game_data"],["bios/mame2003-plus/artwork/skydiver.zip",117241,"game_data"],["bios/mame2003-plus/artwork/solarq.zip",1342645,"game_data"],["bios/mame2003-plus/artwork/warrior.zip",1125335,"game_data"],["bios/mame2003-plus/cheat.dat",7971360,"game_data"],["bios/mame2003-plus/hiscore.dat",131926,"game_data"],["bios/mame2003-plus/history.dat",38635890,"game_data"],["bios/mame2003-plus/mameinfo.dat",24837237,"game_data"],["bios/manager.zip",12713,"bios"],["bios/mm5740.zip",212,"bios"],["bios/mockingboardd.zip",1861,"bios"],["bios/mpeg_card.bin",524288,"bios"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/mz1p16.zip",3679,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/nlq401.zip",7554,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/nss_tvinterface.zip",17125,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/p72.zip",351169,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/pc6022.zip",3694,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/pico-8/pico8",9377000,"bios"],["bios/pico-8/pico8.dat",17721245,"bios"],["bios/pico-8/pico8_dyn",1761480,"bios"],["bios/plutonia.wad",17420824,"game_data"],["bios/psxonpsp660.bin",524288,"bios"],["bios/px320a.zip",1092458,"bios"],["bios/roadblaster.zip",20664,"bios"],["bios/rom.key",2069,"bios"],["bios/s97801_device.zip",8720,"bios"],["bios/s97801_kbd.zip",1772,"bios"],["bios/saa5050.zip",536,"bios"],["bios/sae.zip",27734,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdibios.zip",472798,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sanyotry.bin",1048576,"bios"],["bios/satar4mp.bin",262144,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/scorpion_ic.zip",18332,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/sdq.zip",11467,"bios"],["bios/sdqshort.zip",10147,"bios"],["bios/sdqshortalt.zip",10161,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sfd1001.zip",13984,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/smoc501.zip",37103,"bios"],["bios/socrates.zip",218299,"bios"],["bios/strife1.wad",28377364,"game_data"],["bios/stvbios.zip",2955630,"bios"],["bios/swtpc8212_device.zip",5070,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262656,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/ti99_4a.zip",21377,"bios"],["bios/ti99_arcturus.zip",11432,"bios"],["bios/ti99_bwg.zip",7452,"bios"],["bios/ti99_ccdcc.zip",9611,"bios"],["bios/ti99_ccfdc.zip",9712,"bios"],["bios/ti99_ddcc1.zip",6231,"bios"],["bios/ti99_evpc.zip",17207,"bios"],["bios/ti99_fdc.zip",4969,"bios"],["bios/ti99_gkracker.zip",5998,"bios"],["bios/ti99_hfdc.zip",11813,"bios"],["bios/ti99_myarcmem.zip",6085,"bios"],["bios/ti99_pcode.zip",41460,"bios"],["bios/ti99_rs232.zip",1782,"bios"],["bios/ti99_speech.zip",31206,"bios"],["bios/ti99_thermal.zip",1544,"bios"],["bios/ti99_tipi.zip",5838,"bios"],["bios/ti99_whtscsi.zip",12367,"bios"],["bios/timetrav.zip",53103,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/tos.img",196608,"bios"],["bios/tq.zip",24144,"bios"],["bios/tq_alt.zip",3831,"bios"],["bios/tq_swear.zip",19758,"bios"],["bios/tutor.zip",34653,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/us_scd1_9210.bin",131072,"bios"],["bios/us_scd2_9306.bin",131072,"bios"],["bios/uvt.zip",62052,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/voices.wad",27319149,"game_data"],["bios/votraxtnt.zip",3922,"bios"],["bios/votrsc01a.zip",590,"bios"],["bios/vsmile.zip",3078731,"bios"],["bios/wildmidi.cfg",192,"game_data"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",32768,"bios"],["bios/zip100_ide.zip",36071,"bios"],["neogeo/neogeo.zip",1952551,"bios"],["ports/doom/doom1.wad",4196020,"game_data"],["ports/doom2/doom2.wad",14943400,"game_data"]],"format_version":1,"platform":"emuelec","sets":{"acorn-archimedes|mame":{"bytes":26295965,"files":[209,217,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,289,290,296,297,300,301,308,309,316,320,323,324,325,364,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,597,598,599,607,609,611,620,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"optional":[217,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,289,290,296,297,300,301,308,309,316,320,323,324,325,364,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,597,598,599,607,609,611,620,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"required_bytes":6537596},"acorn-bbc-micro|mame":{"bytes":22407281,"files":[217,219,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,423,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,620,631,634,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,737,747,758,762,766,1080,1081,1089],"optional":[217,219,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,423,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,620,631,634,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"required_bytes":501224},"amstrad-cpc|cap32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apf-m1000|mame":{"bytes":198434,"files":[218,595,596,651,652,653,654,655,656,657,658,659],"optional":[595,596,651,652,653,654,655,656,657,658,659],"required_bytes":6896},"apple-ios|touchhle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple-macintosh|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple2|applewin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade-laserdisc|hypseus-singe":{"bytes":2038656,"files":[210,211,212,213,214,215,277,278,287,288,370,371,393,419,420,421,422,424,425,426,427,430,446,447,448,474,475,476,477,478,479,488,489,509,510,522,524,541,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,589,593,733,738,754,755,756,789,792,793,794,808],"optional":[],"required_bytes":2038656},"arcade|advancemame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade|fbneo":{"bytes":309895027,"files":[485,486,487],"optional":[485,486,487],"required_bytes":0},"arcade|mame2003_plus":{"bytes":86009009,"files":[660,661,662,663,664,665,666,667,668,669,670,671],"optional":[660,661,662,663,664,665,666,667,668,669,670,671],"required_bytes":0},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-400-800|atari800":{"bytes":229376,"files":[8,9,10,11,12,186,187,188,189,208,279,280,281,282,283,284,285,286],"optional":[12,186,187,188,189,208,279,280,281,282,283,284,285,286],"required_bytes":45056},"atari-5200|a5200":{"bytes":2048,"files":[4],"optional":[],"required_bytes":2048},"atari-7800|prosystem":{"bytes":20480,"files":[6,7],"optional":[6],"required_bytes":4096},"atari-jaguarcd|bigpemu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-jaguar|bigpemu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[538,592],"optional":[538],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[526,791],"optional":[526],"required_bytes":196608},"bally-astrocade|mame":{"bytes":76916,"files":[274,275,276,600],"optional":[275,276,600],"required_bytes":6800},"capcom-cps1|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"chex|chocolate-doom":{"bytes":12381899,"files":[417,418],"optional":[418],"required_bytes":20367},"chip8|jaxe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco3|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"colecovision|bluemsx":{"bytes":2457750,"files":[20,21,22,23,24,25,70,71,72,73,74,75],"optional":[21,22,23,24,25],"required_bytes":206155},"commanderx16|x16emu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga-cd32|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae":{"bytes":18823838,"files":[14,15,42,43,44,45,46,47,48,49,50,51,202,405,406,554,555,556,557,558,559,560,561,562,563,564,565,566,734,796,797,798,799,800,801,802,803,804,805],"optional":[202,405,406,554,555,559,560,561,734,796,797,798,799,800,801,802,803,804,805],"required_bytes":8912896},"commodore-c128|vice_x128":{"bytes":106496,"files":[36,37,38,39,40],"optional":[36,37,38,39,40],"required_bytes":0},"commodore-c64|vice_x64":{"bytes":114688,"files":[36,37,38,40,41,546,547],"optional":[36,37,38,40,41,546,547],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":12288,"files":[415,548],"optional":[415,548],"required_bytes":0},"crvision|mame":{"bytes":545261,"files":[217,416,428,432,471,472,473,483,502,588,590,591,619,632,633,672,679,690,714,725],"optional":[217,416,428,471,472,473,483,502,588,590,591,619,632,633,672,679,690,714,725],"required_bytes":1810},"discrete-arcade|dice":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"doom|chocolate-doom":{"bytes":194610746,"files":[449,450,451,503,504,505,507,525,730,790,1091,1092],"optional":[449,450,451,503,504,505,525,730,790],"required_bytes":19160184},"dos|dosbox_pure":{"bytes":41236388,"files":[16,17,18,19,68,69,190,191,192,193,194,195,196,197,198,199],"optional":[16,17,18,19,68,69,190,191,192,193,194,195,196,197,198,199],"required_bytes":0},"dos|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon32|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon64|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"electron|mame":{"bytes":3522535,"files":[217,297,301,364,416,428,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,483,527,528,529,530,531,532,533,534,539,540,590,591,601,621,622,623,624,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,735,736,747,766,1080,1081],"optional":[217,297,301,364,416,428,457,458,459,460,461,462,463,464,467,468,469,470,471,472,473,483,527,528,529,530,531,532,533,534,539,540,590,591,601,621,622,623,624,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,735,736,747,766,1080,1081],"required_bytes":84627},"elektor-tv-games-computer|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"elektronika-bk|bk":{"bytes":102528,"files":[384,385,386,387,388,389,390,391,392],"optional":[384,385,386,387,388,389,390,392],"required_bytes":8192},"emerson-arcadia-2001|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"entex-advision|mame":{"bytes":3827,"files":[216,594],"optional":[594],"required_bytes":1546},"epochcv|pd777":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"famicom|nestopia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"flash|ruffle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fm7|mame":{"bytes":1052160,"files":[217,416,428,471,472,473,483,491,492,493,590,591,625,626,627,628,651,652,653,654,655,656,657,658,659,679,690,714,725],"optional":[217,416,428,471,472,473,483,493,590,591,625,626,627,628,651,652,653,654,655,656,657,658,659,679,690,714,725],"required_bytes":151197},"fmtowns|dreamm":{"bytes":5115691,"files":[494,495,496,497,498,499,500,501],"optional":[],"required_bytes":5115691},"fmtowns|tsugaru":{"bytes":5115691,"files":[494,495,496,497,498,499,500,501],"optional":[],"required_bytes":5115691},"gamepark-gp32|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"handheld-electronic|gw":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"hartung-game-master|mame":{"bytes":8763,"files":[517,630],"optional":[630],"required_bytes":1686},"heretic|chocolate-doom":{"bytes":19310896,"files":[535,536],"optional":[535,536],"required_bytes":0},"hexen|chocolate-doom":{"bytes":20083672,"files":[537],"optional":[537],"required_bytes":0},"ibm-pc|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"intellivision|freeintv":{"bytes":36864,"files":[26,35,484,523],"optional":[],"required_bytes":36864},"interton-vc4000|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"j2me|freej2me":{"bytes":552042,"files":[506],"optional":[],"required_bytes":552042},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mc10|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2+|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msxturbor|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|openmsx":{"bytes":6259600,"files":[76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182],"optional":[],"required_bytes":6259600},"nec-pc-88|quasi88":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine-cd|mednafen_pce_fast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|mednafen_pce_fast":{"bytes":1344000,"files":[515,767,768,769,770,771],"optional":[769,771],"required_bytes":819712},"nec-pcfx|beetle_pcfx":{"bytes":1048576,"files":[726],"optional":[],"required_bytes":1048576},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":1952551,"files":[1090],"optional":[],"required_bytes":1952551},"ngage|eka2l1":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-3ds|azahar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-64|mupen64plus_next":{"bytes":8454540,"files":[5,183,184],"optional":[183,184],"required_bytes":4194304},"nintendo-ds|melonds":{"bytes":282624,"files":[375,376,490],"optional":[],"required_bytes":282624},"nintendo-fds|nestopia":{"bytes":1017726,"files":[185,445],"optional":[],"required_bytes":1017726},"nintendo-gamecube|dolphin":{"bytes":141804715,"files":[27,28,29,30,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"optional":[27,28,29,30,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"required_bytes":0},"nintendo-gba|mgba":{"bytes":19200,"files":[512,513,514,759],"optional":[],"required_bytes":19200},"nintendo-gbc|gambatte":{"bytes":2560,"files":[512,514],"optional":[],"required_bytes":2560},"nintendo-gb|gambatte":{"bytes":2560,"files":[512,514],"optional":[],"required_bytes":2560},"nintendo-nes|nestopia":{"bytes":192,"files":[433],"optional":[433],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[373],"optional":[373],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":1048576,"files":[13],"optional":[],"required_bytes":1048576},"nintendo-snes|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sufami-turbo|snes9x":{"bytes":262144,"files":[200],"optional":[],"required_bytes":262144},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wii|dolphin":{"bytes":135513259,"files":[27,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"optional":[27,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[400,508,542,712,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078],"optional":[],"required_bytes":1606321},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"oricatmos|oricutron":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"palm-os|mu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"panasonic-3do|opera":{"bytes":13123332,"files":[3,518,713,715,716,717,718,719,720,721,722,723,724,744],"optional":[713,715,717,719,720,721,722,723,724],"required_bytes":4718592},"pc-98|np2kai":{"bytes":1294790,"files":[691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710],"optional":[691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710],"required_bytes":0},"philips-cdi|same_cdi":{"bytes":2329922,"files":[739,740,741,742,743],"optional":[739,740],"required_bytes":1462792},"philips-p2000t|m2000":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|lexaloffle":{"bytes":28859725,"files":[727,728,729],"optional":[729],"required_bytes":27098245},"rpgmaker|easyrpg":{"bytes":148398498,"files":[452,1083],"optional":[452,1083],"required_bytes":0},"sam-coupe|samcoupe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"scummvm|scummvm-standalone":{"bytes":1703936,"files":[17,18,68,69],"optional":[17,18,68,69],"required_bytes":0},"scv|emuscv":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-32x|picodrive":{"bytes":3328,"files":[0,1,2],"optional":[0,1,2],"required_bytes":0},"sega-dreamcast-arcade|flycast":{"bytes":8266557,"files":[437,441,442],"optional":[],"required_bytes":8266557},"sega-dreamcast|flycast":{"bytes":4587520,"files":[438,439,440,443,444],"optional":[440,443,444],"required_bytes":2228224},"sega-gamegear|gearsystem":{"bytes":1024,"files":[372],"optional":[],"required_bytes":1024},"sega-gamegear|picodrive":{"bytes":17391,"files":[372,407],"optional":[407],"required_bytes":1024},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-genesis|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":32768,"files":[374,380,381,383],"optional":[374],"required_bytes":24576},"sega-mastersystem|picodrive":{"bytes":40943,"files":[380,381,383,407],"optional":[407],"required_bytes":24576},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[377,378,379],"optional":[],"required_bytes":393216},"sega-megacd|picodrive":{"bytes":1589231,"files":[201,377,378,379,407,480,481,482,543,544,545,806,807],"optional":[201,407,480,481,543,544,806],"required_bytes":786432},"sega-megadrive|genesis_plus_gx":{"bytes":2426880,"files":[273,382,516,760,761],"optional":[273,382,516,760,761],"required_bytes":0},"sega-megadrive|genesis_plus_gx_wide":{"bytes":2426880,"files":[273,382,516,760,761],"optional":[273,382,516,760,761],"required_bytes":0},"sega-megadrive|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-pico|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-pico|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-saturn|":{"bytes":9509230,"files":[675,676,677,678,745,746,757,765],"optional":[],"required_bytes":9509230},"sega-sc3000|bluemsx":{"bytes":2251595,"files":[21,22,23,24,25],"optional":[21,22,23,24,25],"required_bytes":0},"sega-sc3000|picodrive":{"bytes":16367,"files":[407],"optional":[407],"required_bytes":0},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-sg1000|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sharp-x1|x1":{"bytes":349184,"files":[1084,1085,1086,1087,1088],"optional":[1084,1085,1086,1087,1088],"required_bytes":0},"sharp-x68000|px68k":{"bytes":1310720,"files":[549,550,551,552,553],"optional":[],"required_bytes":1310720},"sinclair-zx-spectrum|fuse":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":7195431,"files":[680,681,682,683,684,685,686,687,688,689,1090],"optional":[680,681,682,683,684,685,686,688,689],"required_bytes":2476839},"snk-ngpc|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"solarus|solarus":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation|pcsx_rearmed":{"bytes":3670016,"files":[731,748,749,750,751,752,753],"optional":[731,748,749,753],"required_bytes":1572864},"sony-psp|ppsspp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"strife|chocolate-doom":{"bytes":55696513,"files":[764,1079],"optional":[764,1079],"required_bytes":0},"sunplus-native32|native32emu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tandy-1000|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"texas-instruments-ti-83|numero":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ti99|mame":{"bytes":2718201,"files":[219,408,409,410,411,412,413,414,429,431,434,636,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,732,762,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,1089],"optional":[219,408,409,410,411,412,413,414,429,431,434,636,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,732,762,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,1089],"required_bytes":21377},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tiger-game-com|mame":{"bytes":155786,"files":[511,629],"optional":[629],"required_bytes":145138},"tutor|mame":{"bytes":538364,"files":[217,416,428,471,472,473,483,590,591,637,679,690,714,725,795],"optional":[217,416,428,471,472,473,483,590,591,637,679,690,714,725],"required_bytes":34653},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vircon32|vircon32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vtech-socrates|mame":{"bytes":223262,"files":[635,763],"optional":[635],"required_bytes":218299},"vtech-vsmile|mame":{"bytes":3447744,"files":[638,639,1082],"optional":[638,639],"required_bytes":3078731},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
+{"files":[["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BS-X.bin",1048576,"bios"],["bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom",262144,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/Databases/colecodb.xml",164848,"bios"],["bios/Databases/msxcaswavdb.xml",819679,"bios"],["bios/Databases/msxromdb.xml",930986,"bios"],["bios/Databases/msxsysromdb.xml",157542,"bios"],["bios/Databases/segadb.xml",82318,"bios"],["bios/Databases/svidb.xml",261070,"bios"],["bios/ECS.bin",24576,"bios"],["bios/GBA/gba_bios.bin",16384,"bios"],["bios/GC/EUR/IPL.bin",2097152,"bios"],["bios/GC/JAP/IPL.bin",2097152,"bios"],["bios/GC/USA/IPL.bin",2097152,"bios"],["bios/GC/dsp_coef.bin",4096,"bios"],["bios/GC/dsp_rom.bin",8192,"bios"],["bios/GC/font_japanese.bin",259626,"bios"],["bios/GC/font_western.bin",6478,"bios"],["bios/IVOICE.bin",2048,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C128.bin",16384,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom",262144,"bios"],["bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom",262144,"bios"],["bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom",524288,"bios"],["bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom",524288,"bios"],["bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom",524288,"bios"],["bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom",524288,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723a_fw.bin",24548,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723b_fw.bin",45048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723d_fw.bin",52080,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761a_fw.bin",74488,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761bu_fw.bin",44484,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821a_fw.bin",37420,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821c_fw.bin",54636,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822b_fw.bin",51176,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822cu_fw.bin",38207,"bios"],["bios/Load/Firmware/rtl_bt/rtl8851bu_fw.bin",49760,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852au_fw.bin",67188,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852btu_fw.bin",128140,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852bu_fw.bin",129733,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852cu_fw.bin",113336,"bios"],["bios/Load/Firmware/rtl_bt/rtl8922au_fw.bin",71360,"bios"],["bios/Load/WiiSD.raw",134217728,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-1.rom",8192,"bios"],["bios/Machines/COL - Bit Corporation Dina/czz50-2.rom",8192,"bios"],["bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/coleco.rom",8192,"bios"],["bios/Machines/COL - ColecoVision/config.ini",347,"bios"],["bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM",8192,"bios"],["bios/Machines/Forte II Games - Pesadelo/pesadelo.rom",65536,"bios"],["bios/Machines/MSX - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom",16384,"bios"],["bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom",32768,"bios"],["bios/Machines/MSX/MSX.ROM",32768,"bios"],["bios/Machines/MSX/MSX2.ROM",32768,"bios"],["bios/Machines/MSX/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX/config.ini",408,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom",16384,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom",32768,"bios"],["bios/Machines/MSX2 - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios.txt",8924,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_logo_msx2+.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_main_msx2+.rom",32768,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_music.rom",16384,"bios"],["bios/Machines/MSX2+ - C-BIOS/cbios_sub.rom",16384,"bios"],["bios/Machines/MSX2+/MSX.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2+/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2+/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2+/config.ini",773,"bios"],["bios/Machines/MSX2/MSX.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2EXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSX2P.ROM",32768,"bios"],["bios/Machines/MSX2/MSX2PEXT.ROM",16384,"bios"],["bios/Machines/MSX2/MSXDOS2.ROM",65536,"bios"],["bios/Machines/MSX2/config.ini",649,"bios"],["bios/Machines/MSXturboR/config.ini",941,"bios"],["bios/Machines/SVI - Spectravideo SVI-318/svi318.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi806se.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi328a.rom",32768,"bios"],["bios/Machines/SVI - Spectravideo SVI-328 MK2/svi806.rom",4096,"bios"],["bios/Machines/SVI - Spectravideo SVI-328/svi328.rom",32768,"bios"],["bios/Machines/Shared Roms/ARAB1.ROM",32768,"bios"],["bios/Machines/Shared Roms/ARABIC.rom",32768,"bios"],["bios/Machines/Shared Roms/BEERIDE.ROM",16384,"bios"],["bios/Machines/Shared Roms/FMPAC.rom",65536,"bios"],["bios/Machines/Shared Roms/GCVMX80.ROM",8192,"bios"],["bios/Machines/Shared Roms/HANGUL.rom",131072,"bios"],["bios/Machines/Shared Roms/KANJI.rom",262144,"bios"],["bios/Machines/Shared Roms/MICROSOLDISK.ROM",16384,"bios"],["bios/Machines/Shared Roms/MOONSOUND.rom",2097152,"bios"],["bios/Machines/Shared Roms/MSX.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2AR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2AREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSX2BR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2BREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2EXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2FR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2FREXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2G.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2GEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2HAN.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2J.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2JEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2KR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2KREXT.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2P.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2PEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2PMUS.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2R.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2R2.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSX2REXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSX2SE.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSX2SPEXT.rom",16384,"bios"],["bios/Machines/Shared Roms/MSXAR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXBR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXDOS2.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXDOS23.ROM",65536,"bios"],["bios/Machines/Shared Roms/MSXFR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXG.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXHAN.rom",8192,"bios"],["bios/Machines/Shared Roms/MSXJ.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKANJI.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXKR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXR2.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXSE.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXSP.rom",32768,"bios"],["bios/Machines/Shared Roms/MSXTR.ROM",32768,"bios"],["bios/Machines/Shared Roms/MSXTREXT.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTRMUS.ROM",16384,"bios"],["bios/Machines/Shared Roms/MSXTROPT.ROM",16384,"bios"],["bios/Machines/Shared Roms/NATIONALDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/NOVAXIS.rom",16384,"bios"],["bios/Machines/Shared Roms/PAINT.rom",65536,"bios"],["bios/Machines/Shared Roms/PANASONICDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/PHILIPSDISK.rom",16384,"bios"],["bios/Machines/Shared Roms/RS232.ROM",8192,"bios"],["bios/Machines/Shared Roms/SUNRISEIDE.rom",65536,"bios"],["bios/Machines/Shared Roms/SWP.rom",32768,"bios"],["bios/Machines/Shared Roms/Shared.txt",41,"bios"],["bios/Machines/Shared Roms/XBASIC2.rom",16384,"bios"],["bios/Machines/Shared Roms/nowindDos1.rom",524288,"bios"],["bios/Machines/Shared Roms/nowindDos2.rom",524288,"bios"],["bios/Mupen64plus/IPL.n64",4194304,"bios"],["bios/Mupen64plus/font.ttf",65932,"bios"],["bios/NstDatabase.xml",1009534,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/STBIOS.bin",262144,"bios"],["bios/SegaCDBIOS9303.bin",131072,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/Wii/clientca.pem",1005,"bios"],["bios/Wii/clientcakey.pem",609,"bios"],["bios/Wii/rootca.pem",897,"bios"],["bios/Wii/shared2/sys/SYSCONF",16384,"bios"],["bios/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/aa310.zip",6536273,"bios"],["bios/ace.zip",21283,"bios"],["bios/ace91.zip",27636,"bios"],["bios/ace91_euro.zip",27381,"bios"],["bios/ace_a.zip",3752,"bios"],["bios/ace_a2.zip",3760,"bios"],["bios/aceeuro.zip",23853,"bios"],["bios/advision.zip",1546,"bios"],["bios/ap2000.zip",21618,"bios"],["bios/apfm1000.zip",6896,"bios"],["bios/aplcd150.zip",9137,"bios"],["bios/arc_a448.zip",602,"bios"],["bios/arc_a448b.zip",836,"bios"],["bios/arc_acejoy.zip",1311,"bios"],["bios/arc_armadeus.zip",1014,"bios"],["bios/arc_bbcio_aga30.zip",1329,"bios"],["bios/arc_bbcio_aka10.zip",3792,"bios"],["bios/arc_bbcio_we.zip",1273,"bios"],["bios/arc_eaglem2.zip",47500,"bios"],["bios/arc_ether1_aka25.zip",163,"bios"],["bios/arc_ether2_aeh50.zip",378,"bios"],["bios/arc_ether3_aeh54.zip",50047,"bios"],["bios/arc_ethera.zip",149278,"bios"],["bios/arc_etherd.zip",105641,"bios"],["bios/arc_etherr.zip",49753,"bios"],["bios/arc_faxpack.zip",5826,"bios"],["bios/arc_greyhawk.zip",5265,"bios"],["bios/arc_hdisc_akd52.zip",421,"bios"],["bios/arc_hdisc_cw.zip",565,"bios"],["bios/arc_hdisc_morley.zip",1333,"bios"],["bios/arc_hdisc_we.zip",462,"bios"],["bios/arc_ide_be.zip",24321,"bios"],["bios/arc_ide_rdev.zip",7001,"bios"],["bios/arc_iomidi_aka15.zip",5309,"bios"],["bios/arc_lark.zip",33629,"bios"],["bios/arc_lbp4.zip",14292,"bios"],["bios/arc_midi2.zip",12743,"bios"],["bios/arc_midi_aka16.zip",21857,"bios"],["bios/arc_midimax.zip",36846,"bios"],["bios/arc_midimax2.zip",21595,"bios"],["bios/arc_nexus_a500.zip",15560,"bios"],["bios/arc_rom_aka05.zip",4909,"bios"],["bios/arc_rom_r225.zip",107080,"bios"],["bios/arc_rs423.zip",285,"bios"],["bios/arc_scan256.zip",9805,"bios"],["bios/arc_scanjunior.zip",6379,"bios"],["bios/arc_scanjunior3.zip",6965,"bios"],["bios/arc_scanlight.zip",7019,"bios"],["bios/arc_scanvideo.zip",25778,"bios"],["bios/arc_scsi_aka30.zip",11747,"bios"],["bios/arc_scsi_aka31.zip",11851,"bios"],["bios/arc_scsi_aka32.zip",96376,"bios"],["bios/arc_scsi_cumana.zip",43880,"bios"],["bios/arc_scsi_ling.zip",51477,"bios"],["bios/arc_scsi_morley.zip",196852,"bios"],["bios/arc_scsi_oak.zip",85368,"bios"],["bios/arc_scsi_vti.zip",34230,"bios"],["bios/arc_serial.zip",3063,"bios"],["bios/arc_spectra.zip",2421,"bios"],["bios/arc_ua_morley.zip",1410,"bios"],["bios/arc_uma_morley.zip",9527,"bios"],["bios/arc_upa_hccs.zip",1172,"bios"],["bios/arc_upmidi_aka12.zip",9038,"bios"],["bios/archimedes_keyboard.zip",1323,"bios"],["bios/areplay.bin",32768,"bios"],["bios/astrocde.zip",6800,"bios"],["bios/astrocdl.zip",6805,"bios"],["bios/astrocdw.zip",6807,"bios"],["bios/astron.zip",57886,"bios"],["bios/astronp.zip",23339,"bios"],["bios/atari-1200xl-os-rev-10.rom",16384,"bios"],["bios/atari-1200xl-os-rev-11.rom",16384,"bios"],["bios/atari-5200-os-2port.rom",2048,"bios"],["bios/atari-800-os-a-ntsc.rom",10240,"bios"],["bios/atari-basic-rev-a.rom",8192,"bios"],["bios/atari-basic-rev-b.rom",8192,"bios"],["bios/atari-xl-os-ver-1.rom",16384,"bios"],["bios/atari-xl-os-ver-3.rom",16384,"bios"],["bios/badlandp.zip",8789,"bios"],["bios/badlands.zip",12872,"bios"],["bios/bbc_24bbc.zip",2844684,"bios"],["bios/bbc_2ndserial.zip",2844684,"bios"],["bios/bbc_acorn1770.zip",60692,"bios"],["bios/bbc_acorn8271.zip",97195,"bios"],["bios/bbc_ams3.zip",8252,"bios"],["bios/bbc_ariesb20.zip",2525,"bios"],["bios/bbc_ariesb32.zip",8935,"bios"],["bios/bbc_autoprom.zip",2737,"bios"],["bios/bbc_beebspch.zip",6564,"bios"],["bios/bbc_bitstik1.zip",5798,"bios"],["bios/bbc_bitstik2.zip",5798,"bios"],["bios/bbc_cc500.zip",2844684,"bios"],["bios/bbc_chameleon.zip",654,"bios"],["bios/bbc_cisco.zip",13978,"bios"],["bios/bbc_cms6502.zip",17969,"bios"],["bios/bbc_cumana1.zip",10212,"bios"],["bios/bbc_cumana2.zip",11242,"bios"],["bios/bbc_cumana68k.zip",3790,"bios"],["bios/bbc_cv1797.zip",6453,"bios"],["bios/bbc_datacentre.zip",40386,"bios"],["bios/bbc_ieee488.zip",2844684,"bios"],["bios/bbc_integrab.zip",34749,"bios"],["bios/bbc_kenda.zip",6558,"bios"],["bios/bbc_magazzino.zip",11695,"bios"],["bios/bbc_memexb20.zip",1305,"bios"],["bios/bbc_mertec.zip",13212,"bios"],["bios/bbc_morleyaa.zip",5048,"bios"],["bios/bbc_multiform.zip",11635,"bios"],["bios/bbc_opus1770.zip",24620,"bios"],["bios/bbc_opus2791.zip",47054,"bios"],["bios/bbc_opus2793.zip",24583,"bios"],["bios/bbc_opus3.zip",36996,"bios"],["bios/bbc_opus8272.zip",23119,"bios"],["bios/bbc_opusa.zip",23792,"bios"],["bios/bbc_pdram.zip",2195,"bios"],["bios/bbc_pms64k.zip",8361,"bios"],["bios/bbc_ramdisc.zip",2844684,"bios"],["bios/bbc_raven20.zip",4486,"bios"],["bios/bbc_stl1770_1.zip",12775,"bios"],["bios/bbc_stl1770_2.zip",12822,"bios"],["bios/bbc_stl2m128.zip",3298,"bios"],["bios/bbc_stl4m32.zip",11382,"bios"],["bios/bbc_stldfdc_1.zip",12504,"bios"],["bios/bbc_stlswr128.zip",11806,"bios"],["bios/bbc_stlswr16.zip",11806,"bios"],["bios/bbc_stlswr32.zip",11806,"bios"],["bios/bbc_stlswr64.zip",11806,"bios"],["bios/bbc_sweetalker.zip",2019,"bios"],["bios/bbc_tube_16032.zip",17960,"bios"],["bios/bbc_tube_32016.zip",31067,"bios"],["bios/bbc_tube_32016l.zip",3585,"bios"],["bios/bbc_tube_6502.zip",4337,"bios"],["bios/bbc_tube_6502e.zip",1515,"bios"],["bios/bbc_tube_6502p.zip",6023,"bios"],["bios/bbc_tube_65c102.zip",4375,"bios"],["bios/bbc_tube_80186.zip",6643,"bios"],["bios/bbc_tube_80286.zip",6649,"bios"],["bios/bbc_tube_a500.zip",12117,"bios"],["bios/bbc_tube_a500d.zip",12312,"bios"],["bios/bbc_tube_arm.zip",38022,"bios"],["bios/bbc_tube_arm7.zip",109910,"bios"],["bios/bbc_tube_casper.zip",18005,"bios"],["bios/bbc_tube_cms6809.zip",9090,"bios"],["bios/bbc_tube_matchbox.zip",48928,"bios"],["bios/bbc_tube_pcplus.zip",6662,"bios"],["bios/bbc_tube_rc6502.zip",31532,"bios"],["bios/bbc_tube_rc65816.zip",31259,"bios"],["bios/bbc_tube_x25.zip",17863,"bios"],["bios/bbc_tube_z80.zip",3197,"bios"],["bios/bbc_tube_z80w.zip",3145,"bios"],["bios/bbc_tube_zep100.zip",40985,"bios"],["bios/bbc_tube_zep100l.zip",18020,"bios"],["bios/bbc_tube_zep100m.zip",29188,"bios"],["bios/bbc_tube_zep100w.zip",29266,"bios"],["bios/bbc_udm.zip",44349,"bios"],["bios/bbc_voicebox.zip",2019,"bios"],["bios/bbc_we32kram.zip",22610,"bios"],["bios/bbc_weddb2.zip",35836,"bios"],["bios/bbc_weddb3.zip",11202,"bios"],["bios/bbcm.zip",400592,"bios"],["bios/bbcmc.zip",100096,"bios"],["bios/bega.zip",48777,"bios"],["bios/begar1.zip",19993,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/bk/B11M_BOS.ROM",8192,"bios"],["bios/bk/B11M_EXT.ROM",8192,"bios"],["bios/bk/BAS11M_0.ROM",16384,"bios"],["bios/bk/BAS11M_1.ROM",8192,"bios"],["bios/bk/BASIC10.ROM",24576,"bios"],["bios/bk/DISK_327.ROM",4096,"bios"],["bios/bk/FOCAL10.ROM",24576,"bios"],["bios/bk/MONIT10.ROM",8192,"bios"],["bios/bk/TERAK.ROM",128,"bios"],["bios/blazer.zip",19999,"bios"],["bios/c2031.zip",12163,"bios"],["bios/c2040.zip",7844,"bios"],["bios/c2040_fdc.zip",426,"bios"],["bios/c3040.zip",7844,"bios"],["bios/c4023.zip",4285,"bios"],["bios/c4040.zip",20926,"bios"],["bios/c52.bin",1024,"bios"],["bios/c8050.zip",39422,"bios"],["bios/c8050fdc.zip",426,"bios"],["bios/c8250.zip",39422,"bios"],["bios/c8280.zip",23702,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/carthw.cfg",16367,"bios"],["bios/cdd2000.zip",195999,"bios"],["bios/cdr4210.zip",82902,"bios"],["bios/cdrn820s.zip",66313,"bios"],["bios/cdu415.zip",31828,"bios"],["bios/cdu561_25.zip",141631,"bios"],["bios/cdu75s.zip",31456,"bios"],["bios/cfp1080s.zip",67669,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/chessmachine.zip",542,"bios"],["bios/chex.deh",20367,"game_data"],["bios/chex.wad",12361532,"game_data"],["bios/cliff.zip",16725,"bios"],["bios/cliff_ox.zip",16879,"bios"],["bios/cliffalt.zip",15087,"bios"],["bios/cliffalt2.zip",14504,"bios"],["bios/cms_4080term.zip",576010,"bios"],["bios/cobra.zip",29388,"bios"],["bios/cobraab.zip",20648,"bios"],["bios/cobraconv.zip",27623,"bios"],["bios/cobram3.zip",23520,"bios"],["bios/comx_pl80.zip",8379,"bios"],["bios/cp2024.zip",23160,"bios"],["bios/cputest.zip",11874,"bios"],["bios/crd254sh.zip",31383,"bios"],["bios/crvision.zip",1810,"bios"],["bios/custom.pal",192,"bios"],["bios/cw7501.zip",83060,"bios"],["bios/d9060.zip",32197,"bios"],["bios/d9090.zip",32197,"bios"],["bios/dc/awbios.zip",34620,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/dc_nvmem.bin",131072,"bios"],["bios/dc/naomi.zip",6134785,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/dc_boot.bin",2097152,"bios"],["bios/dc_nvmem.bin",131072,"bios"],["bios/disksys.rom",8192,"bios"],["bios/dle11.zip",28296,"bios"],["bios/dle20.zip",25955,"bios"],["bios/dle21.zip",24883,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/econet_e01.zip",26965,"bios"],["bios/econet_e01s.zip",54134,"bios"],["bios/ef9365.zip",590,"bios"],["bios/electron.zip",25571,"bios"],["bios/electron64.zip",25089,"bios"],["bios/electron_ap1.zip",13514,"bios"],["bios/electron_ap6.zip",17045,"bios"],["bios/electron_elksd128.zip",37465,"bios"],["bios/electron_elksd64.zip",21261,"bios"],["bios/electron_m2105.zip",149867,"bios"],["bios/electron_mc68k.zip",35027,"bios"],["bios/electron_mode7.zip",7850,"bios"],["bios/electron_plus1.zip",1344,"bios"],["bios/electron_plus3.zip",57712,"bios"],["bios/electron_pwrjoy.zip",1437,"bios"],["bios/electron_romboxp.zip",25157,"bios"],["bios/electron_sidewndr.zip",958848,"bios"],["bios/electron_voxbox.zip",2019,"bios"],["bios/epson_fx80.zip",12887,"bios"],["bios/epson_jx80.zip",11210,"bios"],["bios/epson_rx80.zip",6311,"bios"],["bios/esh.zip",16764,"bios"],["bios/eshalt.zip",5660,"bios"],["bios/eshalt2.zip",5277,"bios"],["bios/eshfix7.zip",5669,"bios"],["bios/eshfix7alt.zip",5678,"bios"],["bios/eshfix7alt2.zip",5669,"bios"],["bios/eu_mcd1_9210.bin",131072,"bios"],["bios/eu_mcd2_9303.bin",131072,"bios"],["bios/eu_mcd2_9306.bin",131072,"bios"],["bios/ex800.zip",21628,"bios"],["bios/exec.bin",8192,"bios"],["bios/fbneo/hiscore.dat",328397,"bios"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/firefox.zip",53410,"bios"],["bios/firefoxa.zip",51026,"bios"],["bios/firmware.bin",262144,"bios"],["bios/fm7.zip",104276,"bios"],["bios/fm77av.zip",46921,"bios"],["bios/fmnew7.zip",26815,"bios"],["bios/fmtmarty.zip",1524715,"bios"],["bios/fmtowns.zip",655778,"bios"],["bios/fmtowns/FMT_DIC.ROM",524288,"bios"],["bios/fmtowns/FMT_DOS.ROM",524288,"bios"],["bios/fmtowns/FMT_F20.ROM",524288,"bios"],["bios/fmtowns/FMT_FNT.ROM",262144,"bios"],["bios/fmtowns/FMT_SYS.ROM",262144,"bios"],["bios/fmtownsux.zip",838046,"bios"],["bios/fnvision.zip",1798,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me-lr.jar",552042,"bios"],["bios/french.deh",20764,"game_data"],["bios/g7400.bin",1024,"bios"],["bios/galaxy.zip",48574,"bios"],["bios/galaxyp.zip",20042,"bios"],["bios/gamecom.zip",145138,"bios"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gmaster.zip",1686,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gpib_hardbox.zip",18236,"bios"],["bios/gpib_mshark.zip",13934,"bios"],["bios/gpib_softbox.zip",9859,"bios"],["bios/gpworld.zip",86990,"bios"],["bios/grom.bin",2048,"bios"],["bios/gtg.zip",19748,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/hd44780.zip",965,"bios"],["bios/heath_gp19_tlb.zip",13491,"bios"],["bios/heath_imaginator_tlb.zip",9135,"bios"],["bios/heath_super19_tlb.zip",5615,"bios"],["bios/heath_superset_tlb.zip",14186,"bios"],["bios/heath_tlb.zip",5021,"bios"],["bios/heath_ultra_tlb.zip",4818,"bios"],["bios/heath_watz_tlb.zip",7609,"bios"],["bios/heretic.wad",14189976,"game_data"],["bios/heretic1.wad",5120920,"game_data"],["bios/hexen.wad",20083672,"game_data"],["bios/howard.o",513,"bios"],["bios/ie15_device.zip",5520,"bios"],["bios/ie15kbd.zip",352,"bios"],["bios/interstellar.zip",39757,"bios"],["bios/jopac.bin",1024,"bios"],["bios/jp_mcd1_9111.bin",131072,"bios"],["bios/jp_mcd1_9112.bin",131072,"bios"],["bios/jp_mcd2_921222.bin",131072,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/lair.zip",17906,"bios"],["bios/lair2.zip",25809,"bios"],["bios/lair2_211.zip",23278,"bios"],["bios/lair2_300.zip",24540,"bios"],["bios/lair2_314.zip",25195,"bios"],["bios/lair2_315.zip",25271,"bios"],["bios/lair2_316_euro.zip",25175,"bios"],["bios/lair2_318.zip",25592,"bios"],["bios/lair2_319_euro.zip",25493,"bios"],["bios/lair2_319_span.zip",25828,"bios"],["bios/lair_a.zip",21377,"bios"],["bios/lair_b.zip",4293,"bios"],["bios/lair_c.zip",968,"bios"],["bios/lair_d.zip",27677,"bios"],["bios/lair_d2.zip",4056,"bios"],["bios/lair_e.zip",20802,"bios"],["bios/lair_f.zip",6027,"bios"],["bios/lair_ita.zip",6408,"bios"],["bios/lair_n1.zip",26477,"bios"],["bios/lair_x.zip",24316,"bios"],["bios/laireuro.zip",10771,"bios"],["bios/lasr2001.zip",12613,"bios"],["bios/lgp.zip",37609,"bios"],["bios/lx800.zip",15176,"bios"],["bios/lx810l.zip",22103,"bios"],["bios/lynxboot.img",512,"bios"],["bios/mach3.zip",441761,"bios"],["bios/mame/hash/advision.xml",2281,"game_data"],["bios/mame/hash/apfimag_cass.xml",43143,"game_data"],["bios/mame/hash/apfm1000.xml",9759,"game_data"],["bios/mame/hash/archimedes.xml",271056,"game_data"],["bios/mame/hash/archimedes_hdd.xml",549,"game_data"],["bios/mame/hash/archimedes_rom.xml",2409,"game_data"],["bios/mame/hash/astrocde.xml",56504,"game_data"],["bios/mame/hash/bbc_cass.xml",736181,"game_data"],["bios/mame/hash/bbc_flop_32016.xml",8282,"game_data"],["bios/mame/hash/bbc_flop_6502.xml",6281,"game_data"],["bios/mame/hash/bbc_flop_68000.xml",1770,"game_data"],["bios/mame/hash/bbc_flop_80186.xml",7946,"game_data"],["bios/mame/hash/bbc_flop_arm.xml",11609,"game_data"],["bios/mame/hash/bbc_flop_hybrid.xml",40742,"game_data"],["bios/mame/hash/bbc_flop_torch.xml",19139,"game_data"],["bios/mame/hash/bbc_flop_z80.xml",7743,"game_data"],["bios/mame/hash/bbc_hdd.xml",2639,"game_data"],["bios/mame/hash/bbc_rom.xml",502371,"game_data"],["bios/mame/hash/bbc_vsm.xml",2571,"game_data"],["bios/mame/hash/bbcb_flop.xml",124846,"game_data"],["bios/mame/hash/bbcb_flop_orig.xml",158528,"game_data"],["bios/mame/hash/bbcb_flop_us.xml",743,"game_data"],["bios/mame/hash/bbcm_cart.xml",11115,"game_data"],["bios/mame/hash/bbcm_flop.xml",5301,"game_data"],["bios/mame/hash/bbcmc_flop.xml",17528,"game_data"],["bios/mame/hash/crvision.xml",29061,"game_data"],["bios/mame/hash/e01_flop.xml",972,"game_data"],["bios/mame/hash/electron_cart.xml",22690,"game_data"],["bios/mame/hash/electron_cass.xml",270749,"game_data"],["bios/mame/hash/electron_flop.xml",105636,"game_data"],["bios/mame/hash/electron_rom.xml",36576,"game_data"],["bios/mame/hash/fm77av.xml",56002,"game_data"],["bios/mame/hash/fm7_cass.xml",84996,"game_data"],["bios/mame/hash/fm7_disk.xml",94601,"game_data"],["bios/mame/hash/fm8_cass.xml",13963,"game_data"],["bios/mame/hash/gamecom.xml",10648,"game_data"],["bios/mame/hash/gmaster.xml",7077,"game_data"],["bios/mame/hash/ibm5150.xml",824234,"game_data"],["bios/mame/hash/laser2001_cart.xml",729,"game_data"],["bios/mame/hash/laser2001_flop.xml",587,"game_data"],["bios/mame/hash/pro128s_flop.xml",14348,"game_data"],["bios/mame/hash/socrates.xml",4963,"game_data"],["bios/mame/hash/ti99_cart.xml",229953,"game_data"],["bios/mame/hash/tutor.xml",17761,"game_data"],["bios/mame/hash/vsmile_cart.xml",284343,"game_data"],["bios/mame/hash/vsmilem_cart.xml",84670,"game_data"],["bios/mame/samples/bbc.zip",8469,"game_data"],["bios/mame/samples/floppy/35_seek_12ms.wav",26540,"game_data"],["bios/mame/samples/floppy/35_seek_20ms.wav",44144,"game_data"],["bios/mame/samples/floppy/35_seek_2ms.wav",7450,"game_data"],["bios/mame/samples/floppy/35_seek_6ms.wav",22230,"game_data"],["bios/mame/samples/floppy/35_spin_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_end.wav",17684,"game_data"],["bios/mame/samples/floppy/35_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_loaded.wav",35308,"game_data"],["bios/mame/samples/floppy/35_step_1_1.wav",6878,"game_data"],["bios/mame/samples/floppy/525_seek_12ms.wav",22764,"game_data"],["bios/mame/samples/floppy/525_seek_20ms.wav",30060,"game_data"],["bios/mame/samples/floppy/525_seek_6ms.wav",14860,"game_data"],["bios/mame/samples/floppy/525_spin_empty.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_end.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_spin_start_empty.wav",11180,"game_data"],["bios/mame/samples/floppy/525_spin_start_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_step_1_1.wav",6628,"game_data"],["bios/mame2003-plus/artwork/blueshrk.zip",925914,"game_data"],["bios/mame2003-plus/artwork/dotron.zip",2010009,"game_data"],["bios/mame2003-plus/artwork/frogs.zip",2832731,"game_data"],["bios/mame2003-plus/artwork/invaders.zip",4324198,"game_data"],["bios/mame2003-plus/artwork/omegrace.zip",1754523,"game_data"],["bios/mame2003-plus/artwork/skydiver.zip",117241,"game_data"],["bios/mame2003-plus/artwork/solarq.zip",1342645,"game_data"],["bios/mame2003-plus/artwork/warrior.zip",1125335,"game_data"],["bios/mame2003-plus/cheat.dat",7971360,"game_data"],["bios/mame2003-plus/hiscore.dat",131926,"game_data"],["bios/mame2003-plus/history.dat",38635890,"game_data"],["bios/mame2003-plus/mameinfo.dat",24837237,"game_data"],["bios/manager.zip",12713,"bios"],["bios/mm5740.zip",212,"bios"],["bios/mockingboardd.zip",1861,"bios"],["bios/mpeg_card.bin",524288,"bios"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/mz1p16.zip",3679,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/nlq401.zip",7554,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/nss_tvinterface.zip",17125,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/p72.zip",351169,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/pc6022.zip",3694,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/pico-8/pico8",9377000,"bios"],["bios/pico-8/pico8.dat",17721245,"bios"],["bios/pico-8/pico8_dyn",1761480,"bios"],["bios/plutonia.wad",17420824,"game_data"],["bios/psxonpsp660.bin",524288,"bios"],["bios/px320a.zip",1092458,"bios"],["bios/roadblaster.zip",20664,"bios"],["bios/rom.key",2069,"bios"],["bios/s97801_device.zip",8720,"bios"],["bios/s97801_kbd.zip",1772,"bios"],["bios/saa5050.zip",536,"bios"],["bios/sae.zip",27734,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdibios.zip",472798,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sanyotry.bin",1048576,"bios"],["bios/satar4mp.bin",262144,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/scorpion_ic.zip",18332,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/sdq.zip",11467,"bios"],["bios/sdqshort.zip",10147,"bios"],["bios/sdqshortalt.zip",10161,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sfd1001.zip",13984,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/smoc501.zip",37103,"bios"],["bios/socrates.zip",218299,"bios"],["bios/strife1.wad",28377364,"game_data"],["bios/stvbios.zip",2955630,"bios"],["bios/swtpc8212_device.zip",5070,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262656,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/ti99_4a.zip",21377,"bios"],["bios/ti99_arcturus.zip",11432,"bios"],["bios/ti99_bwg.zip",7452,"bios"],["bios/ti99_ccdcc.zip",9611,"bios"],["bios/ti99_ccfdc.zip",9712,"bios"],["bios/ti99_ddcc1.zip",6231,"bios"],["bios/ti99_evpc.zip",17207,"bios"],["bios/ti99_fdc.zip",4969,"bios"],["bios/ti99_gkracker.zip",5998,"bios"],["bios/ti99_hfdc.zip",11813,"bios"],["bios/ti99_myarcmem.zip",6085,"bios"],["bios/ti99_pcode.zip",41460,"bios"],["bios/ti99_rs232.zip",1782,"bios"],["bios/ti99_speech.zip",31206,"bios"],["bios/ti99_thermal.zip",1544,"bios"],["bios/ti99_tipi.zip",5838,"bios"],["bios/ti99_whtscsi.zip",12367,"bios"],["bios/timetrav.zip",53103,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/tos.img",196608,"bios"],["bios/tq.zip",24144,"bios"],["bios/tq_alt.zip",3831,"bios"],["bios/tq_swear.zip",19758,"bios"],["bios/tutor.zip",34653,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/us_scd1_9210.bin",131072,"bios"],["bios/us_scd2_9306.bin",131072,"bios"],["bios/uvt.zip",62052,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/voices.wad",27319149,"game_data"],["bios/votraxtnt.zip",3922,"bios"],["bios/votrsc01a.zip",590,"bios"],["bios/vsmile.zip",3078731,"bios"],["bios/wildmidi.cfg",192,"game_data"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",32768,"bios"],["bios/zip100_ide.zip",36071,"bios"],["neogeo/neogeo.zip",1952551,"bios"],["ports/doom/doom1.wad",4196020,"game_data"],["ports/doom2/doom2.wad",14943400,"game_data"]],"format_version":1,"platform":"emuelec","sets":{"acorn-archimedes|mame":{"bytes":26295965,"files":[209,217,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,289,290,296,297,300,301,308,309,316,320,323,324,325,364,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,597,598,599,607,609,611,620,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"optional":[217,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,289,290,296,297,300,301,308,309,316,320,323,324,325,364,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,597,598,599,607,609,611,620,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"required_bytes":6537596},"acorn-bbc-micro|mame":{"bytes":22407281,"files":[217,219,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,423,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,620,631,634,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,737,747,758,762,766,1080,1081,1089],"optional":[217,219,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,394,395,396,397,398,399,401,402,403,404,408,409,410,411,412,413,414,416,423,428,429,431,434,435,436,453,454,455,471,472,473,483,519,520,521,527,528,529,530,531,532,533,534,539,540,590,591,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,620,631,634,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,732,735,736,747,758,762,766,1080,1081,1089],"required_bytes":501224},"amstrad-cpc|cap32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apf-m1000|mame":{"bytes":198434,"files":[218,595,596,651,652,653,654,655,656,657,658,659],"optional":[595,596,651,652,653,654,655,656,657,658,659],"required_bytes":6896},"apple-ios|touchhle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple-macintosh|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple2|applewin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade-laserdisc|hypseus-singe":{"bytes":2038656,"files":[210,211,212,213,214,215,277,278,287,288,370,371,393,419,420,421,422,424,425,426,427,430,446,447,448,474,475,476,477,478,479,488,489,509,510,522,524,541,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,589,593,733,738,754,755,756,789,792,793,794,808],"optional":[],"required_bytes":2038656},"arcade|advancemame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade|fbneo":{"bytes":309895027,"files":[485,486,487],"optional":[485,486,487],"required_bytes":0},"arcade|mame2003_plus":{"bytes":86009009,"files":[660,661,662,663,664,665,666,667,668,669,670,671],"optional":[660,661,662,663,664,665,666,667,668,669,670,671],"required_bytes":0},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-400-800|atari800":{"bytes":231424,"files":[4,8,9,10,11,12,186,187,188,189,208,279,280,281,282,283,284,285,286],"optional":[12,186,187,188,189,208,279,280,281,282,283,284,285,286],"required_bytes":47104},"atari-5200|a5200":{"bytes":47104,"files":[4,8,9,10,11],"optional":[],"required_bytes":47104},"atari-7800|prosystem":{"bytes":20480,"files":[6,7],"optional":[6],"required_bytes":4096},"atari-jaguarcd|bigpemu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-jaguar|bigpemu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[538,592],"optional":[538],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[526,791],"optional":[526],"required_bytes":196608},"bally-astrocade|mame":{"bytes":76916,"files":[274,275,276,600],"optional":[275,276,600],"required_bytes":6800},"capcom-cps1|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|fbneo":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"chex|chocolate-doom":{"bytes":12381899,"files":[417,418],"optional":[418],"required_bytes":20367},"chip8|jaxe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco3|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"colecovision|bluemsx":{"bytes":6455446,"files":[20,21,22,23,24,25,70,71,72,73,74,75,119,120,121,122,123,124,125,126,127,161,171,172,173,174,175,176,177,178,180,181,182],"optional":[21,22,23,24,25],"required_bytes":4203851},"commanderx16|x16emu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga-cd32|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae":{"bytes":18823838,"files":[14,15,42,43,44,45,46,47,48,49,50,51,202,405,406,554,555,556,557,558,559,560,561,562,563,564,565,566,734,796,797,798,799,800,801,802,803,804,805],"optional":[202,405,406,554,555,559,560,561,734,796,797,798,799,800,801,802,803,804,805],"required_bytes":8912896},"commodore-c128|vice_x128":{"bytes":106496,"files":[36,37,38,39,40],"optional":[36,37,38,39,40],"required_bytes":0},"commodore-c64|vice_x64":{"bytes":114688,"files":[36,37,38,40,41,546,547],"optional":[36,37,38,40,41,546,547],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":12288,"files":[415,548],"optional":[415,548],"required_bytes":0},"crvision|mame":{"bytes":545261,"files":[217,416,428,432,471,472,473,483,502,588,590,591,619,632,633,672,679,690,714,725],"optional":[217,416,428,471,472,473,483,502,588,590,591,619,632,633,672,679,690,714,725],"required_bytes":1810},"discrete-arcade|dice":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"doom|chocolate-doom":{"bytes":194610746,"files":[449,450,451,503,504,505,507,525,730,790,1091,1092],"optional":[449,450,451,503,504,505,525,730,790],"required_bytes":19160184},"dos|dosbox_pure":{"bytes":41236388,"files":[16,17,18,19,68,69,190,191,192,193,194,195,196,197,198,199],"optional":[16,17,18,19,68,69,190,191,192,193,194,195,196,197,198,199],"required_bytes":0},"dos|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon32|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon64|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"electron|mame":{"bytes":3522535,"files":[217,297,301,364,416,428,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,483,527,528,529,530,531,532,533,534,539,540,590,591,601,621,622,623,624,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,735,736,747,766,1080,1081],"optional":[217,297,301,364,416,428,457,458,459,460,461,462,463,464,467,468,469,470,471,472,473,483,527,528,529,530,531,532,533,534,539,540,590,591,601,621,622,623,624,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,673,674,679,690,711,714,725,735,736,747,766,1080,1081],"required_bytes":84627},"elektor-tv-games-computer|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"elektronika-bk|bk":{"bytes":102528,"files":[384,385,386,387,388,389,390,391,392],"optional":[384,385,386,387,388,389,390,392],"required_bytes":8192},"emerson-arcadia-2001|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"entex-advision|mame":{"bytes":3827,"files":[216,594],"optional":[594],"required_bytes":1546},"epochcv|pd777":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"famicom|nestopia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"flash|ruffle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fm7|mame":{"bytes":1052160,"files":[217,416,428,471,472,473,483,491,492,493,590,591,625,626,627,628,651,652,653,654,655,656,657,658,659,679,690,714,725],"optional":[217,416,428,471,472,473,483,493,590,591,625,626,627,628,651,652,653,654,655,656,657,658,659,679,690,714,725],"required_bytes":151197},"fmtowns|dreamm":{"bytes":5115691,"files":[494,495,496,497,498,499,500,501],"optional":[],"required_bytes":5115691},"fmtowns|tsugaru":{"bytes":5115691,"files":[494,495,496,497,498,499,500,501],"optional":[],"required_bytes":5115691},"gamepark-gp32|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"handheld-electronic|gw":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"hartung-game-master|mame":{"bytes":8763,"files":[517,630],"optional":[630],"required_bytes":1686},"heretic|chocolate-doom":{"bytes":19310896,"files":[535,536],"optional":[535,536],"required_bytes":0},"hexen|chocolate-doom":{"bytes":20083672,"files":[537],"optional":[537],"required_bytes":0},"ibm-pc|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"intellivision|freeintv":{"bytes":36864,"files":[26,35,484,523],"optional":[],"required_bytes":36864},"interton-vc4000|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"j2me|freej2me":{"bytes":552042,"files":[506],"optional":[],"required_bytes":552042},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mc10|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2+|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msxturbor|openmsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|openmsx":{"bytes":6424448,"files":[20,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182],"optional":[],"required_bytes":6424448},"nec-pc-88|quasi88":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine-cd|mednafen_pce_fast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|mednafen_pce_fast":{"bytes":1344000,"files":[515,767,768,769,770,771],"optional":[769,771],"required_bytes":819712},"nec-pcfx|beetle_pcfx":{"bytes":1048576,"files":[726],"optional":[],"required_bytes":1048576},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":1952551,"files":[1090],"optional":[],"required_bytes":1952551},"ngage|eka2l1":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-3ds|azahar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-64|mupen64plus_next":{"bytes":8454540,"files":[5,183,184],"optional":[183,184],"required_bytes":4194304},"nintendo-ds|melonds":{"bytes":282624,"files":[375,376,490],"optional":[],"required_bytes":282624},"nintendo-fds|nestopia":{"bytes":1017726,"files":[185,445],"optional":[],"required_bytes":1017726},"nintendo-gamecube|dolphin":{"bytes":141804715,"files":[27,28,29,30,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"optional":[27,28,29,30,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"required_bytes":0},"nintendo-gba|mgba":{"bytes":19200,"files":[512,513,514,759],"optional":[],"required_bytes":19200},"nintendo-gbc|gambatte":{"bytes":1051136,"files":[13,512,514],"optional":[],"required_bytes":1051136},"nintendo-gb|gambatte":{"bytes":1051136,"files":[13,512,514],"optional":[],"required_bytes":1051136},"nintendo-nes|nestopia":{"bytes":192,"files":[433],"optional":[433],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[373],"optional":[373],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":1048576,"files":[13],"optional":[],"required_bytes":1048576},"nintendo-snes|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sufami-turbo|snes9x":{"bytes":262144,"files":[200],"optional":[],"required_bytes":262144},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wii|dolphin":{"bytes":135513259,"files":[27,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"optional":[27,31,32,33,34,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,203,204,205,206,207],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[400,508,542,712,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078],"optional":[],"required_bytes":1606321},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"oricatmos|oricutron":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"palm-os|mu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"panasonic-3do|opera":{"bytes":13123332,"files":[3,518,713,715,716,717,718,719,720,721,722,723,724,744],"optional":[713,715,717,719,720,721,722,723,724],"required_bytes":4718592},"pc-98|np2kai":{"bytes":1294790,"files":[691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710],"optional":[691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710],"required_bytes":0},"philips-cdi|same_cdi":{"bytes":2329922,"files":[739,740,741,742,743],"optional":[739,740],"required_bytes":1462792},"philips-p2000t|m2000":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|lexaloffle":{"bytes":28859725,"files":[727,728,729],"optional":[729],"required_bytes":27098245},"rpgmaker|easyrpg":{"bytes":148398498,"files":[452,1083],"optional":[452,1083],"required_bytes":0},"sam-coupe|samcoupe":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"scummvm|scummvm-standalone":{"bytes":1703936,"files":[17,18,68,69],"optional":[17,18,68,69],"required_bytes":0},"scv|emuscv":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-32x|picodrive":{"bytes":3328,"files":[0,1,2],"optional":[0,1,2],"required_bytes":0},"sega-dreamcast-arcade|flycast":{"bytes":8266557,"files":[437,441,442],"optional":[],"required_bytes":8266557},"sega-dreamcast|flycast":{"bytes":4587520,"files":[438,439,440,443,444],"optional":[440,443,444],"required_bytes":2228224},"sega-gamegear|gearsystem":{"bytes":1024,"files":[372],"optional":[],"required_bytes":1024},"sega-gamegear|picodrive":{"bytes":17391,"files":[372,407],"optional":[407],"required_bytes":1024},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-genesis|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":32768,"files":[374,380,381,383],"optional":[374],"required_bytes":24576},"sega-mastersystem|picodrive":{"bytes":40943,"files":[380,381,383,407],"optional":[407],"required_bytes":24576},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[377,378,379],"optional":[],"required_bytes":393216},"sega-megacd|picodrive":{"bytes":1589231,"files":[201,377,378,379,407,480,481,482,543,544,545,806,807],"optional":[201,407,480,481,543,544,806],"required_bytes":786432},"sega-megadrive|genesis_plus_gx":{"bytes":2426880,"files":[273,382,516,760,761],"optional":[273,382,516,760,761],"required_bytes":0},"sega-megadrive|genesis_plus_gx_wide":{"bytes":2426880,"files":[273,382,516,760,761],"optional":[273,382,516,760,761],"required_bytes":0},"sega-megadrive|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-pico|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-pico|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-saturn|":{"bytes":9509230,"files":[675,676,677,678,745,746,757,765],"optional":[],"required_bytes":9509230},"sega-sc3000|bluemsx":{"bytes":6414139,"files":[20,21,22,23,24,25,119,120,121,122,123,124,125,126,127,161,171,172,173,174,175,176,177,178,180,181,182],"optional":[21,22,23,24,25],"required_bytes":4162544},"sega-sc3000|picodrive":{"bytes":4178911,"files":[20,119,120,121,122,123,124,125,126,127,161,171,172,173,174,175,176,177,178,180,181,182,407],"optional":[407],"required_bytes":4162544},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-sg1000|picodrive":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sharp-x1|x1":{"bytes":349184,"files":[1084,1085,1086,1087,1088],"optional":[1084,1085,1086,1087,1088],"required_bytes":0},"sharp-x68000|px68k":{"bytes":1310720,"files":[549,550,551,552,553],"optional":[],"required_bytes":1310720},"sinclair-zx-spectrum|fuse":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":7195431,"files":[680,681,682,683,684,685,686,687,688,689,1090],"optional":[680,681,682,683,684,685,686,688,689],"required_bytes":2476839},"snk-ngpc|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"solarus|solarus":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation|pcsx_rearmed":{"bytes":3670016,"files":[731,748,749,750,751,752,753],"optional":[731,748,749,753],"required_bytes":1572864},"sony-psp|ppsspp":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"strife|chocolate-doom":{"bytes":55696513,"files":[764,1079],"optional":[764,1079],"required_bytes":0},"sunplus-native32|native32emu":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tandy-1000|dreamm":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"texas-instruments-ti-83|numero":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ti99|mame":{"bytes":2718201,"files":[219,408,409,410,411,412,413,414,429,431,434,636,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,732,762,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,1089],"optional":[219,408,409,410,411,412,413,414,429,431,434,636,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,732,762,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,1089],"required_bytes":21377},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tiger-game-com|mame":{"bytes":155786,"files":[511,629],"optional":[629],"required_bytes":145138},"tutor|mame":{"bytes":538364,"files":[217,416,428,471,472,473,483,590,591,637,679,690,714,725,795],"optional":[217,416,428,471,472,473,483,590,591,637,679,690,714,725],"required_bytes":34653},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vircon32|vircon32":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vtech-socrates|mame":{"bytes":223262,"files":[635,763],"optional":[635],"required_bytes":218299},"vtech-vsmile|mame":{"bytes":3447744,"files":[638,639,1082],"optional":[638,639],"required_bytes":3078731},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
diff --git a/install/games/fallback/retrodeck.json b/install/games/fallback/retrodeck.json
index 3f58a9bf3..8bd600501 100644
--- a/install/games/fallback/retrodeck.json
+++ b/install/games/fallback/retrodeck.json
@@ -1 +1 @@
-{"files":[["arcade/hiscore.dat",322458,"bios"],["atari2600/stella/KVB1.WAV",4219542,"game_data"],["atari2600/stella/KVB2.WAV",9593878,"game_data"],["atari2600/stella/KVB3.WAV",7676992,"game_data"],["atari2600/stella/KVS1.WAV",3436329,"game_data"],["atari2600/stella/KVS2.WAV",2086275,"game_data"],["atari2600/stella/KVS3.WAV",3720920,"game_data"],["atari2600/stella/KVSHARED.WAV",3059116,"game_data"],["bios/000-lo.lo",131072,"bios"],["bios/128-spanish-0.rom",16384,"bios"],["bios/128-spanish-1.rom",16384,"bios"],["bios/128p-0.rom",16384,"bios"],["bios/128p-1.rom",16384,"bios"],["bios/22vp931.zip",1405,"bios"],["bios/256s-0.rom",16384,"bios"],["bios/256s-1.rom",16384,"bios"],["bios/256s-2.rom",16384,"bios"],["bios/256s-3.rom",16384,"bios"],["bios/2608_BD.WAV",19192,"bios"],["bios/2608_HH.WAV",36722,"bios"],["bios/2608_RIM.WAV",5288,"bios"],["bios/2608_SD.WAV",15558,"bios"],["bios/2608_TOM.WAV",23092,"bios"],["bios/2608_TOP.WAV",57016,"bios"],["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3c505.zip",10896,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/3dobios.zip",2351546,"bios"],["bios/3xtwin.zip",1417,"bios"],["bios/4dparprn.zip",480212,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/64_cspeech.zip",2011,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/82c606.zip",479847,"bios"],["bios/A78_highscore.bin",16364,"bios"],["bios/APPLE2GS.ROM",131072,"bios"],["bios/ARAB1.ROM",32768,"bios"],["bios/ARABIC.rom",32768,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/AmigaVision.rom",524288,"bios"],["bios/Atari Jaguar (World).j64",131072,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BEERIDE.ROM",16384,"bios"],["bios/BIOS.col",8192,"bios"],["bios/BS-X (En) (DRM-Free).bin",1048576,"bios"],["bios/BS-X (En).bin",1048576,"bios"],["bios/BS-X.bin",1048576,"bios"],["bios/CARTS.SHA",33152,"bios"],["bios/CCNPATCH.cas",1481,"bios"],["bios/CCNPATCH.wav",71748,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/CYRILLIC.FNT",2048,"bios"],["bios/Cemu/cafeLibs/erreula.rpl",790080,"bios"],["bios/Cemu/cafeLibs/snd_user.rpl",84032,"bios"],["bios/Cemu/cafeLibs/snduser2.rpl",111360,"bios"],["bios/Cemu/cafeLibs/swkbd.rpl",1116288,"bios"],["bios/Cemu/keys.txt",449507,"bios"],["bios/Cemu/otp.bin",1024,"bios"],["bios/Cemu/resources/sharedFonts/CafeCn.ttf",9664448,"bios"],["bios/Cemu/resources/sharedFonts/CafeKr.ttf",5626464,"bios"],["bios/Cemu/resources/sharedFonts/CafeStd.ttf",5363768,"bios"],["bios/Cemu/resources/sharedFonts/CafeTw.ttf",6593548,"bios"],["bios/Cemu/seeprom.bin",512,"bios"],["bios/Cemu/shareddata.bin",33554432,"bios"],["bios/Complex.bin",1048576,"bios"],["bios/Complex_4627.bin",1048576,"bios"],["bios/Complex_4627v1.03.bin",1048576,"bios"],["bios/DBPATCH.cas",1481,"bios"],["bios/DBPATCH.wav",71900,"bios"],["bios/DEFAULT.FNT",2048,"bios"],["bios/DISK.ROM",16384,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/FMPAC.ROM",65536,"bios"],["bios/FMPAC16.ROM",33152,"bios"],["bios/FONT.ROM",288768,"bios"],["bios/GBA/gba_bios.bin",16384,"bios"],["bios/GC/EUR/IPL.bin",2097152,"bios"],["bios/GC/JAP/IPL.bin",2097152,"bios"],["bios/GC/USA/IPL.bin",2097152,"bios"],["bios/GC/dsp_coef.bin",4096,"bios"],["bios/GC/dsp_rom.bin",8192,"bios"],["bios/GC/font_japanese.bin",259626,"bios"],["bios/GC/font_western.bin",6478,"bios"],["bios/GCVMX80.ROM",8192,"bios"],["bios/HANGUL.rom",131072,"bios"],["bios/INTERNAT.FNT",2048,"bios"],["bios/ITALIC.FNT",2048,"bios"],["bios/JAPANESE.FNT",2048,"bios"],["bios/JISYO.ROM",524288,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/KANJI.ROM",131072,"bios"],["bios/KANJI1.ROM",131072,"bios"],["bios/KOREAN.FNT",2048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723a_fw.bin",24548,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723b_fw.bin",45048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723d_fw.bin",52080,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761a_fw.bin",74488,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761bu_fw.bin",44484,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821a_fw.bin",37420,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821c_fw.bin",54636,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822b_fw.bin",51176,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822cu_fw.bin",38207,"bios"],["bios/Load/Firmware/rtl_bt/rtl8851bu_fw.bin",49760,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852au_fw.bin",67188,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852btu_fw.bin",128140,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852bu_fw.bin",129733,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852cu_fw.bin",113336,"bios"],["bios/Load/Firmware/rtl_bt/rtl8922au_fw.bin",71360,"bios"],["bios/Load/WiiSD.raw",134217728,"bios"],["bios/MICROSOLDISK.ROM",16384,"bios"],["bios/MOONSOUND.rom",2097152,"bios"],["bios/MSX.ROM",32768,"bios"],["bios/MSX2.ROM",32768,"bios"],["bios/MSX2AR.ROM",32768,"bios"],["bios/MSX2AREXT.ROM",16384,"bios"],["bios/MSX2BR.rom",32768,"bios"],["bios/MSX2BREXT.rom",16384,"bios"],["bios/MSX2EXT.ROM",16384,"bios"],["bios/MSX2FR.rom",32768,"bios"],["bios/MSX2FREXT.rom",16384,"bios"],["bios/MSX2G.rom",32768,"bios"],["bios/MSX2GEXT.rom",16384,"bios"],["bios/MSX2HAN.rom",32768,"bios"],["bios/MSX2J.rom",32768,"bios"],["bios/MSX2JEXT.rom",16384,"bios"],["bios/MSX2KR.rom",32768,"bios"],["bios/MSX2KREXT.rom",32768,"bios"],["bios/MSX2P.ROM",32768,"bios"],["bios/MSX2PEXT.ROM",16384,"bios"],["bios/MSX2PMUS.rom",16384,"bios"],["bios/MSX2R.rom",32768,"bios"],["bios/MSX2R2.ROM",32768,"bios"],["bios/MSX2REXT.rom",16384,"bios"],["bios/MSX2SE.rom",32768,"bios"],["bios/MSX2SP.rom",32768,"bios"],["bios/MSX2SPEXT.rom",16384,"bios"],["bios/MSXAR.ROM",32768,"bios"],["bios/MSXBR.rom",32768,"bios"],["bios/MSXDOS2.ROM",65536,"bios"],["bios/MSXDOS23.ROM",65536,"bios"],["bios/MSXFR.rom",32768,"bios"],["bios/MSXG.rom",32768,"bios"],["bios/MSXHAN.rom",8192,"bios"],["bios/MSXJ.rom",32768,"bios"],["bios/MSXKANJI.rom",32768,"bios"],["bios/MSXKR.rom",32768,"bios"],["bios/MSXR.rom",32768,"bios"],["bios/MSXR2.rom",32768,"bios"],["bios/MSXSE.ROM",32768,"bios"],["bios/MSXSP.ROM",32768,"bios"],["bios/MSXTR.ROM",32768,"bios"],["bios/MSXTREXT.ROM",16384,"bios"],["bios/MSXTRMUS.ROM",16384,"bios"],["bios/MSXTROPT.ROM",16384,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/MesenPalette.pal",192,"bios"],["bios/N80.ROM",32768,"bios"],["bios/N88EXT0.ROM",8192,"bios"],["bios/N88EXT1.ROM",8192,"bios"],["bios/N88EXT2.ROM",8192,"bios"],["bios/N88EXT3.ROM",8192,"bios"],["bios/N88JISHO.ROM",524288,"bios"],["bios/N88KNJ2.ROM",131072,"bios"],["bios/N88SUB.ROM",2048,"bios"],["bios/NATIONALDISK.rom",16384,"bios"],["bios/NOVAXIS.rom",16384,"bios"],["bios/NstDatabase.xml",1009534,"bios"],["bios/PAINT.rom",65536,"bios"],["bios/PAINTER.ROM",65536,"bios"],["bios/PANASONICDISK.rom",16384,"bios"],["bios/PHILIPSDISK.rom",16384,"bios"],["bios/ProSystem.dat",16364,"bios"],["bios/ROM.ROM",262144,"bios"],["bios/ROM03.ROM",262144,"bios"],["bios/ROM_400/800_CUSTOM",10240,"bios"],["bios/ROM_5200",2048,"bios"],["bios/ROM_5200_A",2048,"bios"],["bios/ROM_BASIC_A",8192,"bios"],["bios/ROM_BASIC_B",8192,"bios"],["bios/ROM_BASIC_C",8192,"bios"],["bios/ROM_OS_AA00R10",16384,"bios"],["bios/ROM_OS_AA00R11",16384,"bios"],["bios/ROM_OS_A_NTSC",10240,"bios"],["bios/ROM_OS_A_PAL",10240,"bios"],["bios/ROM_OS_BB00R1",16384,"bios"],["bios/ROM_OS_BB01R2",16384,"bios"],["bios/ROM_OS_BB01R3",16384,"bios"],["bios/ROM_OS_BB01R4",16384,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_B_NTSC",10240,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/ROM_XEGAME",8192,"bios"],["bios/RS232.ROM",16640,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/SCPH-10000.bin",4194304,"bios"],["bios/SCPH-10000.mec",4,"bios"],["bios/SCPH-30004R.bin",4194304,"bios"],["bios/SCPH-39001.bin",4194304,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.BIN",4194304,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.nvm",1024,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.rom1",524288,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.rom2",524288,"bios"],["bios/SCPH-70004.BIN",4194304,"bios"],["bios/SCPH-70004.rom1",524288,"bios"],["bios/SCPH-70004_BIOS_V12_EUR_200.rom2",8192,"bios"],["bios/SCPH-70006_BIOS_V12_HK_200.nvm",1024,"bios"],["bios/SCPH-70008_BIOS_V12_RUS_200.BIN",4194304,"bios"],["bios/SCPH-70008_BIOS_V12_RUS_200.nvm",1024,"bios"],["bios/SCPH-75008_BIOS_V14_RUS_220.nvm",1024,"bios"],["bios/SCPH-77008_BIOS_V15_RUS_220.nvm",1024,"bios"],["bios/SCPH-90006_BIOS_VX_HK _230.nvm",1024,"bios"],["bios/SCPH-90006_BIOS_VX_HK _230.rom1",524288,"bios"],["bios/SCPH30004R.nvm",1024,"bios"],["bios/SGB1.sfc",262144,"bios"],["bios/SGB2.sfc",524288,"bios"],["bios/STBIOS.bin",262144,"bios"],["bios/SUNRISEIDE.rom",65536,"bios"],["bios/SWP.rom",32768,"bios"],["bios/StudyBox.bin",262144,"bios"],["bios/Triforce/segaboot.gcm",2097152,"bios"],["bios/VEC_MineStorm.vec",8192,"bios"],["bios/Vectrex_Bios.bin",4096,"bios"],["bios/Vircon32Bios.v32",1073060,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/Wii/clientca.pem",1005,"bios"],["bios/Wii/clientcakey.pem",609,"bios"],["bios/Wii/rootca.pem",897,"bios"],["bios/Wii/shared2/sys/SYSCONF",16384,"bios"],["bios/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["bios/XBASIC2.rom",16384,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/[BIOS] Atari Jaguar CD (World).j64",262144,"bios"],["bios/[BIOS] Atari Jaguar Developer CD (World).j64",262144,"bios"],["bios/a1000kbd_de.zip",1331,"bios"],["bios/a1000kbd_dk.zip",1331,"bios"],["bios/a1000kbd_fr.zip",1331,"bios"],["bios/a1000kbd_gb.zip",1331,"bios"],["bios/a1000kbd_it.zip",1331,"bios"],["bios/a1000kbd_se.zip",1331,"bios"],["bios/a1000kbd_us.zip",1331,"bios"],["bios/a1200kbd_rb.zip",1476,"bios"],["bios/a1cass.zip",509,"bios"],["bios/a2000kbd_ch.zip",1335,"bios"],["bios/a2000kbd_de.zip",1335,"bios"],["bios/a2000kbd_dk.zip",1335,"bios"],["bios/a2000kbd_es.zip",1335,"bios"],["bios/a2000kbd_fr.zip",1335,"bios"],["bios/a2000kbd_g80_de.zip",1151,"bios"],["bios/a2000kbd_g80_dk.zip",1151,"bios"],["bios/a2000kbd_g80_gb.zip",1151,"bios"],["bios/a2000kbd_g80_se.zip",1151,"bios"],["bios/a2000kbd_g80_us.zip",1151,"bios"],["bios/a2000kbd_gb.zip",1335,"bios"],["bios/a2000kbd_it.zip",1335,"bios"],["bios/a2000kbd_no.zip",1335,"bios"],["bios/a2000kbd_se.zip",1335,"bios"],["bios/a2000kbd_us.zip",1335,"bios"],["bios/a2aevm80.zip",2540,"bios"],["bios/a2ap16.zip",2649,"bios"],["bios/a2ap16a.zip",2549,"bios"],["bios/a2aplcrd.zip",1188,"bios"],["bios/a2autokbd.zip",1363,"bios"],["bios/a2booti.zip",3578,"bios"],["bios/a2bufgrapplerplus.zip",483416,"bios"],["bios/a2bufgrapplerplusa.zip",483416,"bios"],["bios/a2bus_byte8251.zip",95177,"bios"],["bios/a2cffa02.zip",2371,"bios"],["bios/a2cffa2.zip",1153946,"bios"],["bios/a2corvus.zip",1590,"bios"],["bios/a2diskiing.zip",371,"bios"],["bios/a2excel9.zip",7157,"bios"],["bios/a2focdrv.zip",1651,"bios"],["bios/a2grafex.zip",367,"bios"],["bios/a2grappler.zip",481339,"bios"],["bios/a2grapplerplus.zip",485390,"bios"],["bios/a2hsscsi.zip",11374,"bios"],["bios/a2ieee488.zip",39523,"bios"],["bios/a2iwm.zip",371,"bios"],["bios/a2kb200.zip",1144,"bios"],["bios/a2memexp.zip",2174,"bios"],["bios/a2mouse.zip",2836,"bios"],["bios/a2parprn.zip",354,"bios"],["bios/a2pdromdr.zip",666891,"bios"],["bios/a2pic.zip",519,"bios"],["bios/a2q68.zip",5474,"bios"],["bios/a2q68plus.zip",5474,"bios"],["bios/a2ramfac.zip",16155,"bios"],["bios/a2romfp.zip",11102,"bios"],["bios/a2romint.zip",12783,"bios"],["bios/a2scsi.zip",786942,"bios"],["bios/a2sd.zip",1282,"bios"],["bios/a2sic.zip",1867,"bios"],["bios/a2sider1.zip",779735,"bios"],["bios/a2sider2.zip",778704,"bios"],["bios/a2ssc.zip",96978,"bios"],["bios/a2superdrive.zip",10883,"bios"],["bios/a2suprterm.zip",1864,"bios"],["bios/a2surance.zip",3321,"bios"],["bios/a2swyft.zip",11515,"bios"],["bios/a2thunpl.zip",998,"bios"],["bios/a2tk10.zip",1541,"bios"],["bios/a2tmstho.zip",1217,"bios"],["bios/a2twarp.zip",2309,"bios"],["bios/a2ultrme.zip",3652,"bios"],["bios/a2ulttrm.zip",3746,"bios"],["bios/a2uniprint.zip",481948,"bios"],["bios/a2vidtrm.zip",10620,"bios"],["bios/a2vistaa800.zip",790,"bios"],["bios/a2vtc1.zip",2062,"bios"],["bios/a2vulcan.zip",1155306,"bios"],["bios/a2vulgld.zip",1157284,"bios"],["bios/a2vuliie.zip",1155276,"bios"],["bios/a2zipdrv.zip",1154563,"bios"],["bios/a3fdc.zip",262,"bios"],["bios/a500kbd_ch.zip",1335,"bios"],["bios/a500kbd_de.zip",1335,"bios"],["bios/a500kbd_dk.zip",1335,"bios"],["bios/a500kbd_es.zip",1335,"bios"],["bios/a500kbd_fr.zip",1335,"bios"],["bios/a500kbd_gb.zip",1335,"bios"],["bios/a500kbd_it.zip",1335,"bios"],["bios/a500kbd_no.zip",1335,"bios"],["bios/a500kbd_se.zip",1335,"bios"],["bios/a500kbd_us.zip",1335,"bios"],["bios/a600kbd_ch.zip",1335,"bios"],["bios/a600kbd_de.zip",1335,"bios"],["bios/a600kbd_dk.zip",1335,"bios"],["bios/a600kbd_es.zip",1335,"bios"],["bios/a600kbd_fr.zip",1335,"bios"],["bios/a600kbd_gb.zip",1335,"bios"],["bios/a600kbd_it.zip",1335,"bios"],["bios/a600kbd_no.zip",1335,"bios"],["bios/a600kbd_se.zip",1335,"bios"],["bios/a600kbd_us.zip",1335,"bios"],["bios/a7ports.zip",479847,"bios"],["bios/aa310.zip",6536273,"bios"],["bios/abc1600mac.zip",7345,"bios"],["bios/abc1600mover.zip",1347,"bios"],["bios/abc55.zip",1546,"bios"],["bios/abc77.zip",1546,"bios"],["bios/abc800kb.zip",1087,"bios"],["bios/abc80kb.zip",389,"bios"],["bios/abc830.zip",24177,"bios"],["bios/abc832.zip",24177,"bios"],["bios/abc834.zip",24177,"bios"],["bios/abc838.zip",24177,"bios"],["bios/abc850.zip",98610,"bios"],["bios/abc850flop.zip",24177,"bios"],["bios/abc852.zip",98610,"bios"],["bios/abc856.zip",98610,"bios"],["bios/abc890.zip",98610,"bios"],["bios/abc894.zip",98610,"bios"],["bios/abc99.zip",5285,"bios"],["bios/abc_db4106.zip",1696,"bios"],["bios/abc_db4107.zip",23643,"bios"],["bios/abc_db4112.zip",9945,"bios"],["bios/abc_fd2.zip",6129,"bios"],["bios/abc_slutprov.zip",509,"bios"],["bios/abc_ssa.zip",101707,"bios"],["bios/abc_uni800.zip",163,"bios"],["bios/abc_unidisk.zip",9386,"bios"],["bios/abcexp.zip",101707,"bios"],["bios/abcsio.zip",3201,"bios"],["bios/acb2072.zip",11517,"bios"],["bios/ace80.zip",1177,"bios"],["bios/ace_sp_reelctrl.zip",1966,"bios"],["bios/ace_sp_reelctrl_pcp.zip",1148,"bios"],["bios/acorn_vdu40.zip",536,"bios"],["bios/acorn_vdu80.zip",704,"bios"],["bios/acorn_vib.zip",574980,"bios"],["bios/acs8600_ics.zip",98064,"bios"],["bios/action2.wad",209908382,"game_data"],["bios/adam.zip",52891,"bios"],["bios/adam_ddp.zip",1595,"bios"],["bios/adam_fdc.zip",1609,"bios"],["bios/adam_fdc_320kb.zip",4716,"bios"],["bios/adam_fdc_a720dipi.zip",1671,"bios"],["bios/adam_fdc_fp720at.zip",1614,"bios"],["bios/adam_fdc_mihddd.zip",1807,"bios"],["bios/adam_ide.zip",1631404,"bios"],["bios/adam_kb.zip",1758,"bios"],["bios/adam_prn.zip",1644,"bios"],["bios/adam_spi.zip",576494,"bios"],["bios/adbmodem.zip",763,"bios"],["bios/adv071_u24.rom",8192,"bios"],["bios/adv072_u24.rom",8192,"bios"],["bios/adv073-2_u24.rom",8192,"bios"],["bios/aes.zip",850311,"bios"],["bios/aes_keys.txt",7357,"bios"],["bios/agat7_flop.zip",588,"bios"],["bios/agat840k_hle.zip",322,"bios"],["bios/agat9_flop.zip",589,"bios"],["bios/agat_fdc.zip",609,"bios"],["bios/aha1542a.zip",793450,"bios"],["bios/aha1542b.zip",862291,"bios"],["bios/aha1542c.zip",52938,"bios"],["bios/aha1542cf.zip",92027,"bios"],["bios/aha1542cp.zip",36978,"bios"],["bios/aha1740.zip",806698,"bios"],["bios/aha1742a.zip",835784,"bios"],["bios/aha2940.zip",38616,"bios"],["bios/aha2940au.zip",31135,"bios"],["bios/airlbios.zip",715730,"bios"],["bios/aleck64.zip",1804,"bios"],["bios/alg3do.zip",84346,"bios"],["bios/alg_bios.zip",143125,"bios"],["bios/allied.zip",2926,"bios"],["bios/alpha-basic.rom",16384,"bios"],["bios/alpha-boot-v0.4.rom",8192,"bios"],["bios/alpha-boot-v1.0.rom",8192,"bios"],["bios/alto2_cpu.zip",15499,"bios"],["bios/altos2_kbd.zip",695,"bios"],["bios/am100kbd.zip",2016,"bios"],["bios/amiga_a2091.zip",832812,"bios"],["bios/amiga_a2232.zip",95177,"bios"],["bios/amiga_a570.zip",171907,"bios"],["bios/amiga_a590.zip",847830,"bios"],["bios/amiga_ar1.zip",61074,"bios"],["bios/amiga_ar2.zip",193315,"bios"],["bios/amiga_ar3.zip",263916,"bios"],["bios/amiga_buddha.zip",1179140,"bios"],["bios/amiga_oktagon2008.zip",791783,"bios"],["bios/amiga_ripple.zip",1166737,"bios"],["bios/ampex230_kbd.zip",976,"bios"],["bios/ap2000.zip",21618,"bios"],["bios/aplcd150.zip",9137,"bios"],["bios/aprissi.zip",100147,"bios"],["bios/aquarius_c1541.zip",1494391,"bios"],["bios/ar_bios.zip",681333,"bios"],["bios/arc_a448.zip",602,"bios"],["bios/arc_a448b.zip",836,"bios"],["bios/arc_acejoy.zip",1311,"bios"],["bios/arc_armadeus.zip",1014,"bios"],["bios/arc_bbcio_aga30.zip",20932,"bios"],["bios/arc_bbcio_aka10.zip",2859984,"bios"],["bios/arc_bbcio_we.zip",20876,"bios"],["bios/arc_eaglem2.zip",47500,"bios"],["bios/arc_econet.zip",560858,"bios"],["bios/arc_ether1_aka25.zip",163,"bios"],["bios/arc_ether2_aeh50.zip",378,"bios"],["bios/arc_ether3_aeh54.zip",50047,"bios"],["bios/arc_ethera.zip",149278,"bios"],["bios/arc_etherd.zip",105641,"bios"],["bios/arc_etherr.zip",49753,"bios"],["bios/arc_faxpack.zip",5826,"bios"],["bios/arc_greyhawk.zip",5265,"bios"],["bios/arc_hdisc_akd52.zip",421,"bios"],["bios/arc_hdisc_cw.zip",565,"bios"],["bios/arc_hdisc_morley.zip",1333,"bios"],["bios/arc_hdisc_we.zip",462,"bios"],["bios/arc_ide_be.zip",1175878,"bios"],["bios/arc_ide_rdev.zip",1158558,"bios"],["bios/arc_iomidi_aka15.zip",2861501,"bios"],["bios/arc_lark.zip",33629,"bios"],["bios/arc_lbp4.zip",494095,"bios"],["bios/arc_midi2.zip",12743,"bios"],["bios/arc_midi_aka16.zip",21857,"bios"],["bios/arc_midimax.zip",36846,"bios"],["bios/arc_midimax2.zip",21595,"bios"],["bios/arc_nexus_a500.zip",15560,"bios"],["bios/arc_rom_aka05.zip",4909,"bios"],["bios/arc_rom_r225.zip",107080,"bios"],["bios/arc_rs423.zip",95418,"bios"],["bios/arc_scan256.zip",9805,"bios"],["bios/arc_scanjunior.zip",6379,"bios"],["bios/arc_scanjunior3.zip",6965,"bios"],["bios/arc_scanlight.zip",7019,"bios"],["bios/arc_scanvideo.zip",25778,"bios"],["bios/arc_scsi_a500.zip",778041,"bios"],["bios/arc_scsi_aka30.zip",789744,"bios"],["bios/arc_scsi_aka31.zip",789848,"bios"],["bios/arc_scsi_aka32.zip",874373,"bios"],["bios/arc_scsi_cumana.zip",821877,"bios"],["bios/arc_scsi_ling.zip",829474,"bios"],["bios/arc_scsi_morley.zip",974849,"bios"],["bios/arc_scsi_oak.zip",863365,"bios"],["bios/arc_scsi_vti.zip",820278,"bios"],["bios/arc_serial.zip",98196,"bios"],["bios/arc_spectra.zip",2421,"bios"],["bios/arc_ua_morley.zip",21013,"bios"],["bios/arc_uma_morley.zip",29130,"bios"],["bios/arc_upa_hccs.zip",20775,"bios"],["bios/arc_upmidi_aka12.zip",17089,"bios"],["bios/archimedes_keyboard.zip",1323,"bios"],["bios/areplay.bin",32768,"bios"],["bios/aristmk5.zip",261435,"bios"],["bios/aristmk6.zip",22239668,"bios"],["bios/aristmk7.zip",524288,"bios"],["bios/arkanoid68705p3.zip",266,"bios"],["bios/arkanoid68705p5.zip",266,"bios"],["bios/asc88.zip",783706,"bios"],["bios/ascsasi.zip",779354,"bios"],["bios/astrocde.zip",6800,"bios"],["bios/astrocdl.zip",6805,"bios"],["bios/astrocdw.zip",6807,"bios"],["bios/at_keybc.zip",3655,"bios"],["bios/at_mb.zip",3655,"bios"],["bios/atari1050.zip",13755,"bios"],["bios/atari810.zip",3303,"bios"],["bios/atari_cage.zip",573,"bios"],["bios/atari_cage_seattle.zip",573,"bios"],["bios/atarisy1.zip",49385,"bios"],["bios/atom_discpack.zip",3459,"bios"],["bios/atom_econet.zip",560858,"bios"],["bios/atom_gdos.zip",3145,"bios"],["bios/atom_gdos2015.zip",6985,"bios"],["bios/atom_speech.zip",2019,"bios"],["bios/atom_tube.zip",314472,"bios"],["bios/atom_vdu80.zip",1074,"bios"],["bios/awbios.zip",42296,"bios"],["bios/ax208.zip",5590,"bios"],["bios/ax208p.zip",5598,"bios"],["bios/banshee_x86.zip",35460,"bios"],["bios/bas10.rom",8192,"bios"],["bios/bas11.rom",8192,"bios"],["bios/bas12.rom",8192,"bios"],["bios/bas13.rom",8192,"bios"],["bios/bas14.rom",8192,"bios"],["bios/basf7100_kbd.zip",456,"bios"],["bios/bbc_24bbc.zip",2844684,"bios"],["bios/bbc_2ndserial.zip",2844684,"bios"],["bios/bbc_acorn1770.zip",60692,"bios"],["bios/bbc_acorn8271.zip",164713,"bios"],["bios/bbc_ams3.zip",8252,"bios"],["bios/bbc_ariesb20.zip",2525,"bios"],["bios/bbc_ariesb32.zip",8935,"bios"],["bios/bbc_autoprom.zip",2737,"bios"],["bios/bbc_awhd.zip",2844684,"bios"],["bios/bbc_b488.zip",291066,"bios"],["bios/bbc_beebex.zip",480885,"bios"],["bios/bbc_beebide.zip",2844684,"bios"],["bios/bbc_beebspch.zip",6564,"bios"],["bios/bbc_bitstik1.zip",5798,"bios"],["bios/bbc_bitstik2.zip",5798,"bios"],["bios/bbc_cc500.zip",2844684,"bios"],["bios/bbc_chameleon.zip",654,"bios"],["bios/bbc_cisco.zip",13978,"bios"],["bios/bbc_cms6502.zip",17969,"bios"],["bios/bbc_cumana1.zip",10212,"bios"],["bios/bbc_cumana2.zip",11242,"bios"],["bios/bbc_cumana68k.zip",781787,"bios"],["bios/bbc_cv1797.zip",6453,"bios"],["bios/bbc_datacentre.zip",1191943,"bios"],["bios/bbc_detalker.zip",2019,"bios"],["bios/bbc_ide8.zip",1151601,"bios"],["bios/bbc_ieee488.zip",2844684,"bios"],["bios/bbc_integrab.zip",34749,"bios"],["bios/bbc_kenda.zip",6558,"bios"],["bios/bbc_lcd.zip",965,"bios"],["bios/bbc_m2000.zip",2844684,"bios"],["bios/bbc_m3000.zip",2844684,"bios"],["bios/bbc_m500.zip",2844684,"bios"],["bios/bbc_m5000.zip",2844684,"bios"],["bios/bbc_m87.zip",2844684,"bios"],["bios/bbc_magazzino.zip",11695,"bios"],["bios/bbc_memexb20.zip",1305,"bios"],["bios/bbc_mertec.zip",2869404,"bios"],["bios/bbc_meup.zip",8095,"bios"],["bios/bbc_morleyaa.zip",5048,"bios"],["bios/bbc_multiform.zip",11635,"bios"],["bios/bbc_opus1770.zip",24620,"bios"],["bios/bbc_opus2791.zip",47054,"bios"],["bios/bbc_opus2793.zip",24583,"bios"],["bios/bbc_opus3.zip",36996,"bios"],["bios/bbc_opus8272.zip",23119,"bios"],["bios/bbc_opusa.zip",23792,"bios"],["bios/bbc_pdram.zip",2195,"bios"],["bios/bbc_pms64k.zip",8361,"bios"],["bios/bbc_ramdisc.zip",2844684,"bios"],["bios/bbc_raven20.zip",4486,"bios"],["bios/bbc_sasi.zip",778041,"bios"],["bios/bbc_scsi.zip",778041,"bios"],["bios/bbc_scsiaiv.zip",778041,"bios"],["bios/bbc_stl1770_1.zip",12775,"bios"],["bios/bbc_stl1770_2.zip",12822,"bios"],["bios/bbc_stl2m128.zip",3298,"bios"],["bios/bbc_stl4m32.zip",11382,"bios"],["bios/bbc_stldfdc_1.zip",12504,"bios"],["bios/bbc_stlswr128.zip",11806,"bios"],["bios/bbc_stlswr16.zip",11806,"bios"],["bios/bbc_stlswr32.zip",11806,"bios"],["bios/bbc_stlswr64.zip",11806,"bios"],["bios/bbc_sweetalker.zip",2019,"bios"],["bios/bbc_tube_16032.zip",17960,"bios"],["bios/bbc_tube_32016.zip",31067,"bios"],["bios/bbc_tube_32016l.zip",3585,"bios"],["bios/bbc_tube_6502.zip",4337,"bios"],["bios/bbc_tube_6502e.zip",1515,"bios"],["bios/bbc_tube_6502p.zip",6023,"bios"],["bios/bbc_tube_65c102.zip",4375,"bios"],["bios/bbc_tube_80186.zip",6643,"bios"],["bios/bbc_tube_80286.zip",6649,"bios"],["bios/bbc_tube_a500.zip",12117,"bios"],["bios/bbc_tube_a500d.zip",12312,"bios"],["bios/bbc_tube_arm.zip",38022,"bios"],["bios/bbc_tube_arm7.zip",109910,"bios"],["bios/bbc_tube_casper.zip",18005,"bios"],["bios/bbc_tube_cms6809.zip",9090,"bios"],["bios/bbc_tube_matchbox.zip",48928,"bios"],["bios/bbc_tube_pcplus.zip",6662,"bios"],["bios/bbc_tube_rc6502.zip",31532,"bios"],["bios/bbc_tube_rc65816.zip",31259,"bios"],["bios/bbc_tube_x25.zip",17863,"bios"],["bios/bbc_tube_z80.zip",3197,"bios"],["bios/bbc_tube_z80w.zip",3145,"bios"],["bios/bbc_tube_zep100.zip",40985,"bios"],["bios/bbc_tube_zep100l.zip",18020,"bios"],["bios/bbc_tube_zep100m.zip",29188,"bios"],["bios/bbc_tube_zep100w.zip",29266,"bios"],["bios/bbc_udm.zip",44349,"bios"],["bios/bbc_usersplit.zip",8095,"bios"],["bios/bbc_voicebox.zip",2019,"bios"],["bios/bbc_we32kram.zip",22610,"bios"],["bios/bbc_weddb2.zip",35836,"bios"],["bios/bbc_weddb3.zip",11202,"bios"],["bios/bbcm.zip",400592,"bios"],["bios/bbcmc.zip",100096,"bios"],["bios/beebopl.zip",2844684,"bios"],["bios/beebsid.zip",2844684,"bios"],["bios/betadisk.zip",563424,"bios"],["bios/bingoct.zip",173688,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.rom",98304,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios9821.rom",8192,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/bioscv.rom",2048,"bios"],["bios/biosdsi7.bin",65536,"bios"],["bios/biosdsi9.bin",65536,"bios"],["bios/bk_altpro.zip",1160579,"bios"],["bios/bk_ay.zip",479847,"bios"],["bios/bk_covox.zip",479847,"bios"],["bios/bk_irps.zip",95177,"bios"],["bios/bk_kmd.zip",6973,"bios"],["bios/bk_printer.zip",479847,"bios"],["bios/bk_samara.zip",1154606,"bios"],["bios/bluechip.zip",23865,"bios"],["bios/bml3kanji.zip",69657,"bios"],["bios/bml3mp1802.zip",1841,"bios"],["bios/bml3mp1805.zip",1874,"bios"],["bios/bootloader-dbvz.rom",512,"bios"],["bios/bsmt2000.zip",2646,"bios"],["bios/bt542b.zip",796611,"bios"],["bios/bt542bh.zip",800147,"bios"],["bios/bt545s.zip",799349,"bios"],["bios/bubsys.zip",12021,"bios"],["bios/bw2_ramcard.zip",8925,"bios"],["bios/bwtwo.zip",2396,"bios"],["bios/c101687.rom",32768,"bios"],["bios/c1526.zip",18797,"bios"],["bios/c1540.zip",12139,"bios"],["bios/c1541.zip",85282,"bios"],["bios/c1541c.zip",23897,"bios"],["bios/c1541dd.zip",15970,"bios"],["bios/c1541ii.zip",35933,"bios"],["bios/c1541pd.zip",14855,"bios"],["bios/c1541pdc.zip",502900,"bios"],["bios/c1551.zip",11640,"bios"],["bios/c1563.zip",12632,"bios"],["bios/c1570.zip",17870,"bios"],["bios/c1571.zip",55420,"bios"],["bios/c1571cr.zip",38062,"bios"],["bios/c1581.zip",58254,"bios"],["bios/c2031.zip",12163,"bios"],["bios/c2040.zip",7844,"bios"],["bios/c2040_fdc.zip",426,"bios"],["bios/c3040.zip",7844,"bios"],["bios/c4023.zip",4285,"bios"],["bios/c4040.zip",20926,"bios"],["bios/c52.bin",1024,"bios"],["bios/c64_ar4x.zip",190,"bios"],["bios/c64_buscard.zip",2010118,"bios"],["bios/c64_buscard2.zip",2010118,"bios"],["bios/c64_cspeech.zip",2011,"bios"],["bios/c64_geocable.zip",479847,"bios"],["bios/c64_ide64.zip",1151601,"bios"],["bios/c64_ieee488.zip",2010118,"bios"],["bios/c64_magic_voice.zip",2010118,"bios"],["bios/c64_mscr.zip",2311,"bios"],["bios/c64_music64.zip",2010118,"bios"],["bios/c64_nl10.zip",16716,"bios"],["bios/c64_sfxse.zip",2010118,"bios"],["bios/c64_speakeasy.zip",590,"bios"],["bios/c64_supercpu.zip",2010118,"bios"],["bios/c64_swiftlink.zip",95177,"bios"],["bios/c64_tdos.zip",2010118,"bios"],["bios/c64_turbo232.zip",95177,"bios"],["bios/c64_xl80.zip",830,"bios"],["bios/c64_z80videopak.zip",858,"bios"],["bios/c8050.zip",39422,"bios"],["bios/c8050fdc.zip",426,"bios"],["bios/c8250.zip",39422,"bios"],["bios/c8250lp.zip",29852,"bios"],["bios/c8280.zip",23702,"bios"],["bios/cadabc.zip",9823,"bios"],["bios/cafeLibs/erreula.rpl",790080,"bios"],["bios/cafeLibs/snd_user.rpl",84032,"bios"],["bios/cafeLibs/snduser2.rpl",111360,"bios"],["bios/cafeLibs/swkbd.rpl",1116288,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/carthw.cfg",16367,"bios"],["bios/cbm2_hrga.zip",3343,"bios"],["bios/cbm2_hrgb.zip",3343,"bios"],["bios/cbm8000_hsg_a.zip",3615,"bios"],["bios/cbm8000_hsg_b.zip",3615,"bios"],["bios/cbm_interpod.zip",294472,"bios"],["bios/cbm_serbox.zip",2245,"bios"],["bios/cc90_232.zip",574980,"bios"],["bios/cchip.zip",2700,"bios"],["bios/ccs7710.zip",96606,"bios"],["bios/cd6809_fdc.zip",7241,"bios"],["bios/cd90_015.zip",1871,"bios"],["bios/cd90_351.zip",4831,"bios"],["bios/cd90_640.zip",1744,"bios"],["bios/cdd2000.zip",195999,"bios"],["bios/cdi200.rom",524288,"bios"],["bios/cdi220.rom",524288,"bios"],["bios/cdi220b.rom",524288,"bios"],["bios/cdibios.zip",468660,"bios"],["bios/cdimono1.zip",745703,"bios"],["bios/cdimono2.zip",244291,"bios"],["bios/cdos20.rom",16384,"bios"],["bios/cdr4210.zip",82902,"bios"],["bios/cdrn820s.zip",66313,"bios"],["bios/cdu415.zip",31828,"bios"],["bios/cdu561_25.zip",141631,"bios"],["bios/cdu75s.zip",31456,"bios"],["bios/cedmag.zip",1242,"bios"],["bios/cemu/keys.txt",449507,"bios"],["bios/centennial_sl01m_15_11194.zip",301,"bios"],["bios/centennial_sl02m_15_11194.zip",301,"bios"],["bios/centennial_sl04m_15_11194.zip",313,"bios"],["bios/centronics_chessmec.zip",542,"bios"],["bios/cffa1.zip",1156283,"bios"],["bios/cfp1080s.zip",67669,"bios"],["bios/cga.zip",3710,"bios"],["bios/cga_iskr1030m.zip",1588,"bios"],["bios/cga_iskr1031.zip",1665,"bios"],["bios/cga_m24.zip",2283,"bios"],["bios/cga_mc1502.zip",1235,"bios"],["bios/cga_poisk2.zip",3177,"bios"],["bios/cga_superimpose.zip",3710,"bios"],["bios/cgenie_fdc.zip",20834,"bios"],["bios/cgenie_printer.zip",479847,"bios"],["bios/cgrom.dat",786432,"bios"],["bios/cgthree.zip",1224,"bios"],["bios/channelf.zip",2705,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/chessmachine.zip",542,"bios"],["bios/chihiro.zip",2104141,"bios"],["bios/cit101_kbd.zip",930,"bios"],["bios/cit101e_kbd.zip",921,"bios"],["bios/cit220p_kbd.zip",773,"bios"],["bios/clgd5401.zip",36135,"bios"],["bios/clgd542x.zip",329437,"bios"],["bios/clgd5434_pci.zip",78023,"bios"],["bios/clgd5446_pci.zip",40471,"bios"],["bios/clgd5465_laguna.zip",21300,"bios"],["bios/cmdhd.zip",8968,"bios"],["bios/cmdrc2.zip",12317,"bios"],["bios/cmi_ankbd.zip",836,"bios"],["bios/cmi_mkbd.zip",1391,"bios"],["bios/cms_4080term.zip",576010,"bios"],["bios/cms_hires.zip",590,"bios"],["bios/cms_ieee.zip",291066,"bios"],["bios/cmsscsi.zip",783178,"bios"],["bios/coco3.rom",32768,"bios"],["bios/coco3p.rom",32768,"bios"],["bios/coco_dcmodem.zip",99130,"bios"],["bios/coco_fdc.zip",71429,"bios"],["bios/coco_ide.zip",1859954,"bios"],["bios/coco_multipack.zip",1859954,"bios"],["bios/coco_orch90.zip",6977,"bios"],["bios/coco_psg.zip",9965,"bios"],["bios/coco_rs232.zip",98780,"bios"],["bios/coco_scii.zip",496580,"bios"],["bios/coco_ssc.zip",5511,"bios"],["bios/coco_t4426.zip",127813,"bios"],["bios/coco_wpk.zip",857,"bios"],["bios/coco_wpk2.zip",857,"bios"],["bios/coco_wpkrs.zip",857,"bios"],["bios/cocopakram.zip",479847,"bios"],["bios/coh1000a.zip",126281,"bios"],["bios/coh1000c.zip",278470,"bios"],["bios/coh1000t.zip",126274,"bios"],["bios/coh1000w.zip",126147,"bios"],["bios/coh1001l.zip",126185,"bios"],["bios/coh1002e.zip",128626,"bios"],["bios/coh1002m.zip",138588,"bios"],["bios/coh1002t.zip",216727,"bios"],["bios/coh1002v.zip",126314,"bios"],["bios/coh3002c.zip",137941,"bios"],["bios/coh3002t.zip",504337,"bios"],["bios/coleco.rom",8192,"bios"],["bios/coleco.zip",28014,"bios"],["bios/colecovision.rom",8192,"bios"],["bios/color64extbas.rom",8192,"bios"],["bios/compis_hrg.zip",367,"bios"],["bios/compis_uhrg.zip",367,"bios"],["bios/compiskb.zip",480,"bios"],["bios/comx_clm.zip",4009,"bios"],["bios/comx_eb.zip",523172,"bios"],["bios/comx_epr.zip",15391,"bios"],["bios/comx_fd.zip",6238,"bios"],["bios/comx_pl80.zip",8379,"bios"],["bios/comx_prn.zip",485242,"bios"],["bios/comx_thm.zip",2913,"bios"],["bios/concept_kbd.zip",336,"bios"],["bios/cp2024.zip",23160,"bios"],["bios/cp31.zip",223978,"bios"],["bios/cp400bas.rom",8192,"bios"],["bios/cp400dsk.rom",8192,"bios"],["bios/cp400ext.rom",8192,"bios"],["bios/cp400extbas.rom",8192,"bios"],["bios/cp450_fdc.zip",7187,"bios"],["bios/cp450dsk.rom",8192,"bios"],["bios/cpc464.rom",32768,"bios"],["bios/cpc6128.rom",32768,"bios"],["bios/cpc664.rom",32768,"bios"],["bios/cpc_amsdos.rom",16384,"bios"],["bios/cpc_brunword4.zip",139453,"bios"],["bios/cpc_ddi1.zip",1471881,"bios"],["bios/cpc_dkspeech.zip",1460991,"bios"],["bios/cpc_hd20.zip",19579,"bios"],["bios/cpc_mface2.zip",1460991,"bios"],["bios/cpc_playcity.zip",1460991,"bios"],["bios/cpc_rom.zip",1460991,"bios"],["bios/cpc_ser.zip",1460991,"bios"],["bios/cpc_serams.zip",1460991,"bios"],["bios/cpc_smartwatch.zip",5640,"bios"],["bios/cpc_ssa1.zip",1460991,"bios"],["bios/cpc_symf2.zip",1151601,"bios"],["bios/cpc_transtape.zip",4021,"bios"],["bios/cpuap.zip",26613,"bios"],["bios/cq90_028.zip",1744,"bios"],["bios/crd254sh.zip",31383,"bios"],["bios/crvfdc01.zip",149,"bios"],["bios/crvfdc02.zip",151,"bios"],["bios/crysbios.zip",43480,"bios"],["bios/csd1.zip",12487,"bios"],["bios/ct1741.zip",8003,"bios"],["bios/cu_graphc.zip",590,"bios"],["bios/cu_graphm.zip",590,"bios"],["bios/cu_teletext.zip",480339,"bios"],["bios/cubo.zip",673549,"bios"],["bios/cuda.zip",12814,"bios"],["bios/cuda302.zip",3720,"bios"],["bios/cudalite.zip",4037,"bios"],["bios/cv8lc.zip",7423,"bios"],["bios/cw7501.zip",83060,"bios"],["bios/cx4.data.rom",3072,"bios"],["bios/d200e_1.rom",16384,"bios"],["bios/d200e_2.rom",16384,"bios"],["bios/d200e_26.rom",4096,"bios"],["bios/d200rom1.rom",16384,"bios"],["bios/d200rom2.rom",16384,"bios"],["bios/d2fdc.zip",262,"bios"],["bios/d32.rom",16384,"bios"],["bios/d64_2.rom",16384,"bios"],["bios/d64rom1.rom",16384,"bios"],["bios/d64tano.rom",16384,"bios"],["bios/d64tano2.rom",16384,"bios"],["bios/d78c11agf_e19.u1",4096,"bios"],["bios/d8000.rom",32768,"bios"],["bios/d9060.zip",32197,"bios"],["bios/d9090.zip",32197,"bios"],["bios/db50xg.zip",3666695,"bios"],["bios/db60xg.zip",3669859,"bios"],["bios/dc/airlbios.zip",715730,"bios"],["bios/dc/awbios.zip",42296,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/dc_nvmem.bin",131072,"bios"],["bios/dc/f355bios.zip",1394278,"bios"],["bios/dc/f355dlx.zip",2328436,"bios"],["bios/dc/flash.bin",131072,"bios"],["bios/dc/hod2bios.zip",1874145,"bios"],["bios/dc/naomi.zip",9321533,"bios"],["bios/dc/naomi2.zip",7022501,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/dc320b.zip",793791,"bios"],["bios/dc320e.zip",809942,"bios"],["bios/dc820.zip",804028,"bios"],["bios/dc820b.zip",810042,"bios"],["bios/ddos10.rom",8192,"bios"],["bios/ddos11c.rom",8192,"bios"],["bios/ddos12a.rom",8192,"bios"],["bios/ddos40.rom",8192,"bios"],["bios/ddos42.rom",8192,"bios"],["bios/ddrfammt.zip",883352,"bios"],["bios/decobsmt.zip",2646,"bios"],["bios/decocass.zip",13225,"bios"],["bios/dectalk_isa.zip",3823,"bios"],["bios/delaweare.wad",83219726,"game_data"],["bios/delta2.rom",8192,"bios"],["bios/deltados.rom",8192,"bios"],["bios/deluxe.rom",32768,"bios"],["bios/dg640.zip",855,"bios"],["bios/digilog_kbd.zip",1067,"bios"],["bios/dim68k_kbd.zip",1550,"bios"],["bios/dio98543.zip",2010,"bios"],["bios/dio98544.zip",2034,"bios"],["bios/dio98550.zip",3081,"bios"],["bios/dio98603a.zip",291168,"bios"],["bios/dio98603b.zip",377453,"bios"],["bios/dio98624.zip",37948,"bios"],["bios/dio98628.zip",101051,"bios"],["bios/dio98629.zip",5266,"bios"],["bios/dio98644.zip",95177,"bios"],["bios/disciple.rom",8192,"bios"],["bios/disk.rom",8194,"bios"],["bios/disk10.rom",8192,"bios"],["bios/disk11.rom",8192,"bios"],["bios/disk_plus3.szx",1568,"bios"],["bios/diskii13.zip",590,"bios"],["bios/disksys.rom",8192,"bios"],["bios/distomeb_rtime.zip",479847,"bios"],["bios/dm_clgd5430.zip",20166,"bios"],["bios/dmv_k210.zip",479847,"bios"],["bios/dmv_k211.zip",95177,"bios"],["bios/dmv_k212.zip",95177,"bios"],["bios/dmv_k213.zip",95177,"bios"],["bios/dmv_k220.zip",15572,"bios"],["bios/dmv_k230.zip",2880,"bios"],["bios/dmv_k231.zip",2880,"bios"],["bios/dmv_k235.zip",2430,"bios"],["bios/dmv_k801.zip",95177,"bios"],["bios/dmv_k806.zip",642,"bios"],["bios/dmv_keyboard.zip",1135,"bios"],["bios/dolphin-emu/Sys/GC/EUR/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/JAP/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/USA/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/dsp_coef.bin",4096,"bios"],["bios/dolphin-emu/Sys/GC/dsp_rom.bin",8192,"bios"],["bios/dolphin-emu/Sys/GC/font_japanese.bin",259626,"bios"],["bios/dolphin-emu/Sys/GC/font_western.bin",6478,"bios"],["bios/dolphin-emu/Sys/Triforce/segaboot.gcm",2097152,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/dplus48.rom",8192,"bios"],["bios/dplus49b.rom",8192,"bios"],["bios/dplus50.rom",8192,"bios"],["bios/dragon_claw.zip",640119,"bios"],["bios/dragon_fdc.zip",7074,"bios"],["bios/dragon_jcbsnd.zip",1735,"bios"],["bios/dragon_jcbspch.zip",5510,"bios"],["bios/dragon_msx2.zip",313,"bios"],["bios/dragon_multipack.zip",640119,"bios"],["bios/dragon_serial.zip",100100,"bios"],["bios/dragon_sprites.zip",3619,"bios"],["bios/dragonfly-1.3.rom",4096,"bios"],["bios/dragonfly-2.3.rom",4096,"bios"],["bios/ds1001.zip",313,"bios"],["bios/dsd4432.zip",1119,"bios"],["bios/dsd5217.zip",21312,"bios"],["bios/dsp1.data.rom",2048,"bios"],["bios/dsp1b.data.rom",2048,"bios"],["bios/dsp1b.program.rom",6144,"bios"],["bios/dsp2.data.rom",2048,"bios"],["bios/dsp2.program.rom",6144,"bios"],["bios/dsp3.data.rom",2048,"bios"],["bios/dsp3.program.rom",6144,"bios"],["bios/dsp4.data.rom",2048,"bios"],["bios/dsp4.program.rom",6144,"bios"],["bios/dsp56303.zip",568,"bios"],["bios/dsp56311.zip",568,"bios"],["bios/dsp56362.zip",629,"bios"],["bios/duodock.zip",1149126,"bios"],["bios/dvk_kmd.zip",6186,"bios"],["bios/dvk_ktlk.zip",95177,"bios"],["bios/dw_kbd.zip",722,"bios"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/ec1841_0002.zip",3710,"bios"],["bios/ecb_grip21.zip",490120,"bios"],["bios/econet_e01.zip",506768,"bios"],["bios/econet_e01s.zip",533937,"bios"],["bios/ecwolf.pk3",178755,"bios"],["bios/eeprom.bin",256,"bios"],["bios/eeprom.dat",64,"bios"],["bios/ef9340_1.zip",1022,"bios"],["bios/ef9365.zip",590,"bios"],["bios/ega.zip",18988,"bios"],["bios/egret.zip",8834,"bios"],["bios/eidemax.zip",46469,"bios"],["bios/einstein_sd.zip",1105,"bios"],["bios/einstein_speech.zip",2019,"bios"],["bios/eispc_kb.zip",848,"bios"],["bios/ekara.zip",630644,"bios"],["bios/ekaraa.zip",629642,"bios"],["bios/ekarag.zip",795612,"bios"],["bios/ekaraj.zip",629853,"bios"],["bios/ekaramix.zip",663402,"bios"],["bios/ekaraphs.zip",798457,"bios"],["bios/ekaras.zip",813756,"bios"],["bios/electron.zip",25571,"bios"],["bios/electron64.zip",25089,"bios"],["bios/electron_ap1.zip",504869,"bios"],["bios/electron_ap5.zip",3159112,"bios"],["bios/electron_ap6.zip",508400,"bios"],["bios/electron_elksd128.zip",37465,"bios"],["bios/electron_elksd64.zip",21261,"bios"],["bios/electron_fbprint.zip",479847,"bios"],["bios/electron_m2105.zip",724803,"bios"],["bios/electron_mc68k.zip",35027,"bios"],["bios/electron_mode7.zip",958848,"bios"],["bios/electron_plus1.zip",1344,"bios"],["bios/electron_plus2.zip",958848,"bios"],["bios/electron_plus3.zip",57712,"bios"],["bios/electron_pwrjoy.zip",1437,"bios"],["bios/electron_rombox.zip",958848,"bios"],["bios/electron_romboxp.zip",504960,"bios"],["bios/electron_rs423.zip",95177,"bios"],["bios/electron_sidewndr.zip",958848,"bios"],["bios/electron_stlefs.zip",2844684,"bios"],["bios/electron_tube.zip",314472,"bios"],["bios/electron_voxbox.zip",2019,"bios"],["bios/enetlc.zip",8935,"bios"],["bios/enetlctp.zip",471,"bios"],["bios/enetnbtp.zip",472,"bios"],["bios/enh2000.zip",12453,"bios"],["bios/enp10.zip",35461,"bios"],["bios/ep64_exdos.zip",14521,"bios"],["bios/epitch.zip",629853,"bios"],["bios/epson_fx80.zip",12887,"bios"],["bios/epson_jx80.zip",11210,"bios"],["bios/epson_pf10.zip",3426,"bios"],["bios/epson_qx_option_multifont.zip",42543,"bios"],["bios/epson_qx_option_sound_card.zip",3573,"bios"],["bios/epson_rx80.zip",6311,"bios"],["bios/epson_tf20.zip",3426,"bios"],["bios/ergoline_kbd.zip",1847,"bios"],["bios/esq2x40_vfx.zip",288,"bios"],["bios/esqpanel240_vfx.zip",288,"bios"],["bios/et4000.zip",31117,"bios"],["bios/et4000_kasan16.zip",206680,"bios"],["bios/et4kw32i.zip",18756,"bios"],["bios/et532_board.zip",1252,"bios"],["bios/ethudock.zip",692,"bios"],["bios/europc_kbd.zip",1138,"bios"],["bios/ev346.zip",3881,"bios"],["bios/everdrive_md.zip",37759,"bios"],["bios/evio.zip",1292911,"bios"],["bios/ex1280.zip",3538,"bios"],["bios/ex800.zip",21628,"bios"],["bios/exec.bin",8192,"bios"],["bios/executive10_102_kbd.zip",1778,"bios"],["bios/exorterm155_device.zip",8999,"bios"],["bios/exorterm155_terminal.zip",8999,"bios"],["bios/exos201.zip",19800,"bios"],["bios/extbas10.rom",8192,"bios"],["bios/extbas11.rom",8192,"bios"],["bios/external.bin",262144,"bios"],["bios/f355bios.zip",1394278,"bios"],["bios/f355dlx.zip",2328436,"bios"],["bios/f4431_kbd.zip",1807,"bios"],["bios/fba2012/samples/dkong.zip",29270,"game_data"],["bios/fba2012/samples/dkongjr.zip",300220,"game_data"],["bios/fba2012/samples/fireshrk.zip",180371945,"game_data"],["bios/fba2012/samples/galaga.zip",243090,"game_data"],["bios/fba2012/samples/ghox.zip",149028023,"game_data"],["bios/fba2012/samples/rallyx.zip",72511,"game_data"],["bios/fba2012/samples/tekipaki.zip",207969846,"game_data"],["bios/fba2012/samples/vimana.zip",278695628,"game_data"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/fc_disksys.zip",11579,"bios"],["bios/fd148.zip",11962,"bios"],["bios/fd2000.zip",45358,"bios"],["bios/fd4000.zip",45409,"bios"],["bios/fd502.rom",8192,"bios"],["bios/fd502ds.rom",8192,"bios"],["bios/fdc344.zip",2298,"bios"],["bios/fdc37c665gt.zip",479847,"bios"],["bios/fdc37c93x.zip",479847,"bios"],["bios/fdc37m707.zip",479847,"bios"],["bios/fdcmag.zip",2158,"bios"],["bios/fdsbios.zip",8312,"bios"],["bios/fga4he.zip",17002,"bios"],["bios/filetto_cga.zip",3713,"bios"],["bios/firmware.bin",262144,"bios"],["bios/fm7.zip",104276,"bios"],["bios/fm77av.zip",46921,"bios"],["bios/fmnew7.zip",26815,"bios"],["bios/font.bmp",524350,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedom220_kbd.zip",1353,"bios"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me-lr.jar",552042,"bios"],["bios/freej2me-sdl.jar",552043,"bios"],["bios/freej2me.jar",552039,"bios"],["bios/front-sp1.bin",524288,"bios"],["bios/fs-a1gt_firmware.rom",4194304,"bios"],["bios/fs-a1gt_kanjifont.rom",262144,"bios"],["bios/fs-a1wsx_basic-bios2p.rom",32768,"bios"],["bios/fs-a1wsx_disk.rom",16384,"bios"],["bios/fs-a1wsx_firmware.rom",2097152,"bios"],["bios/fs-a1wsx_fmbasic.rom",16384,"bios"],["bios/fs-a1wsx_kanjibasic.rom",32768,"bios"],["bios/fs-a1wsx_kanjifont.rom",262144,"bios"],["bios/fs-a1wsx_msx2psub.rom",16384,"bios"],["bios/fsd1.zip",11799,"bios"],["bios/fsd2.zip",48020,"bios"],["bios/fuse/128-0.rom",16384,"bios"],["bios/fuse/128-1.rom",16384,"bios"],["bios/fuse/128p-0.rom",16384,"bios"],["bios/fuse/128p-1.rom",16384,"bios"],["bios/fuse/256s-0.rom",16384,"bios"],["bios/fuse/256s-1.rom",16384,"bios"],["bios/fuse/256s-2.rom",16384,"bios"],["bios/fuse/256s-3.rom",16384,"bios"],["bios/fuse/48.rom",16384,"bios"],["bios/fuse/didaktik80.rom",14336,"bios"],["bios/fuse/disciple.rom",8192,"bios"],["bios/fuse/gluck.rom",16384,"bios"],["bios/fuse/if1-2.rom",8192,"bios"],["bios/fuse/mf1.rom",8192,"bios"],["bios/fuse/mf128.rom",8192,"bios"],["bios/fuse/mf3.rom",8192,"bios"],["bios/fuse/opus.rom",8192,"bios"],["bios/fuse/plus2-0.rom",16384,"bios"],["bios/fuse/plus2-1.rom",16384,"bios"],["bios/fuse/plus3-0.rom",16384,"bios"],["bios/fuse/plus3-1.rom",16384,"bios"],["bios/fuse/plus3-2.rom",16384,"bios"],["bios/fuse/plus3-3.rom",16384,"bios"],["bios/fuse/plus3e-0.rom",16384,"bios"],["bios/fuse/plus3e-1.rom",16384,"bios"],["bios/fuse/plus3e-2.rom",16384,"bios"],["bios/fuse/plus3e-3.rom",16384,"bios"],["bios/fuse/plusd.rom",8192,"bios"],["bios/fuse/se-0.rom",16384,"bios"],["bios/fuse/se-1.rom",16384,"bios"],["bios/fuse/speccyboot-1.4.rom",8192,"bios"],["bios/fuse/tc2048.rom",16384,"bios"],["bios/fuse/tc2068-0.rom",16384,"bios"],["bios/fuse/tc2068-1.rom",8192,"bios"],["bios/fuse/trdos.rom",16384,"bios"],["bios/fuse/ttx2000s.rom",8192,"bios"],["bios/fuse/usource.rom",8192,"bios"],["bios/fx-scsi.rom",524288,"bios"],["bios/g7400.bin",1024,"bios"],["bios/g80_1500.zip",5636,"bios"],["bios/galgbios.zip",1345333,"bios"],["bios/gamate.zip",5072,"bios"],["bios/gamecom.zip",145138,"bios"],["bios/gamecontrollerdb.txt",600521,"game_data"],["bios/gamtor_vga.zip",208,"bios"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gcslottv.zip",737452,"bios"],["bios/geforce256.zip",25685,"bios"],["bios/geforce256ddr.zip",21811,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/gfxultra.zip",19347,"bios"],["bios/gfxultrap.zip",38094,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gic.zip",373,"bios"],["bios/gluck.rom",16384,"bios"],["bios/gmaster.zip",1686,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gotsndspr1.zip",588,"bios"],["bios/gotsndspr1a.zip",590,"bios"],["bios/gp_110.zip",3140,"bios"],["bios/gpib_hardbox.zip",18236,"bios"],["bios/gpib_mshark.zip",13934,"bios"],["bios/gpib_softbox.zip",9859,"bios"],["bios/gpl16250va.zip",155340,"bios"],["bios/gpl951xx.zip",3396,"bios"],["bios/gq863.zip",74462,"bios"],["bios/grndctrl.zip",95177,"bios"],["bios/grom.bin",2048,"bios"],["bios/gts1.zip",3734,"bios"],["bios/gunsense.zip",5062,"bios"],["bios/h89bus_io_decoder_444_43.zip",175,"bios"],["bios/h89bus_io_decoder_444_61.zip",176,"bios"],["bios/h89bus_io_decoder_cdr86.zip",177,"bios"],["bios/h89bus_io_decoder_mms_61c.zip",193,"bios"],["bios/h89h_88_3.zip",95177,"bios"],["bios/h89ha_88_3.zip",95177,"bios"],["bios/h8_cpu_8080.zip",7111,"bios"],["bios/h8_h_8_5.zip",95177,"bios"],["bios/h8_ha_8_6.zip",6415,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hacx2.wad",20504847,"game_data"],["bios/hardbox.zip",18236,"bios"],["bios/harddriv_board.zip",95177,"bios"],["bios/harddrivc_board.zip",95177,"bios"],["bios/harm1.wad",58396393,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/hcpu30.zip",590392,"bios"],["bios/hd44780.zip",965,"bios"],["bios/hd44780u.zip",2082,"bios"],["bios/hd61830.zip",839,"bios"],["bios/hdae5000.zip",823668,"bios"],["bios/hdbdw3bck.rom",8192,"bios"],["bios/hdrivair0_board.zip",95177,"bios"],["bios/hdrivair_board.zip",95177,"bios"],["bios/he191_3425.zip",983,"bios"],["bios/heath_gp19_tlb.zip",13491,"bios"],["bios/heath_igc_super19_tlb_device.zip",5615,"bios"],["bios/heath_igc_tlb_device.zip",5021,"bios"],["bios/heath_igc_ultra_tlb_device.zip",4818,"bios"],["bios/heath_igc_watz_tlb_device.zip",7609,"bios"],["bios/heath_imaginator_tlb.zip",9135,"bios"],["bios/heath_super19_tlb.zip",5615,"bios"],["bios/heath_superset_tlb.zip",14186,"bios"],["bios/heath_tlb.zip",5021,"bios"],["bios/heath_ultra_tlb.zip",4818,"bios"],["bios/heath_watz_tlb.zip",7609,"bios"],["bios/heathrow.zip",95177,"bios"],["bios/hikara.zip",636237,"bios"],["bios/hikaru.zip",1049493,"bios"],["bios/hisaturn.bin",524288,"bios"],["bios/hk68v10.zip",103216,"bios"],["bios/hng64.zip",41592,"bios"],["bios/hod2bios.zip",1479106,"bios"],["bios/howard.o",513,"bios"],["bios/hp82900.zip",691,"bios"],["bios/hp82919.zip",95177,"bios"],["bios/hp82937.zip",39932,"bios"],["bios/hp82939.zip",97002,"bios"],["bios/hp9122c.zip",10761,"bios"],["bios/hp9133.zip",21140,"bios"],["bios/hp98034.zip",38621,"bios"],["bios/hp98035.zip",1993,"bios"],["bios/hp98036.zip",95177,"bios"],["bios/hp98046.zip",96236,"bios"],["bios/hp98265a.zip",778041,"bios"],["bios/hp9845_prt.zip",1241,"bios"],["bios/hp9895.zip",6135,"bios"],["bios/hpblp.zip",842209,"bios"],["bios/human_interface.zip",39948,"bios"],["bios/i82371ab.zip",1171917,"bios"],["bios/i82371eb_ide.zip",1151601,"bios"],["bios/i82371sb.zip",1151601,"bios"],["bios/i82371sb_ide.zip",1151601,"bios"],["bios/i8244.zip",456,"bios"],["bios/i8245.zip",456,"bios"],["bios/ibm_mfc.zip",17863,"bios"],["bios/ibm_vga.zip",13184,"bios"],["bios/ibsap2.zip",1061,"bios"],["bios/id1/pak0.pak",18689235,"game_data"],["bios/idpart_video.zip",97756,"bios"],["bios/ie15_device.zip",5520,"bios"],["bios/ie15_terminal.zip",5520,"bios"],["bios/ie15kbd.zip",352,"bios"],["bios/if1-1.rom",8192,"bios"],["bios/imds2ioc.zip",499607,"bios"],["bios/imi5000h.zip",3337,"bios"],["bios/imi7000.zip",3337,"bios"],["bios/in207100kbd.zip",1074,"bios"],["bios/in213kbd.zip",658,"bios"],["bios/indusgt.zip",15707,"bios"],["bios/internal.bin",4096,"bios"],["bios/intv_ecs.zip",13890,"bios"],["bios/intv_voice.zip",2025,"bios"],["bios/ioc2f.zip",595178,"bios"],["bios/ioc2g.zip",595178,"bios"],["bios/iplrom.dat",131072,"bios"],["bios/iplrom30.dat",131072,"bios"],["bios/iplromcdc_flash.bino.dat",131072,"bios"],["bios/iplromco.dat",131072,"bios"],["bios/iplromxv.dat",131072,"bios"],["bios/iq151_disc2.zip",1872,"bios"],["bios/iq151_minigraf.zip",3404,"bios"],["bios/iq151_ms15a.zip",1938,"bios"],["bios/iq151_video32.zip",709,"bios"],["bios/iq151_video64.zip",1120,"bios"],["bios/iris_kbd.zip",939,"bios"],["bios/isa_aga.zip",2673,"bios"],["bios/isa_aga_pc200.zip",3722,"bios"],["bios/isa_bblue2.zip",479847,"bios"],["bios/isa_chessmdr.zip",542,"bios"],["bios/isa_epc_mda.zip",1714,"bios"],["bios/isa_finalchs.zip",39370,"bios"],["bios/isa_hdc.zip",5558,"bios"],["bios/isa_hercules.zip",483007,"bios"],["bios/isa_ibm_mda.zip",483513,"bios"],["bios/isa_ibm_pgc.zip",69664,"bios"],["bios/isa_ibm_speech.zip",22584,"bios"],["bios/isa_ide.zip",1151601,"bios"],["bios/isa_lpt.zip",479847,"bios"],["bios/isa_mpu401.zip",3573,"bios"],["bios/isa_pcmidi.zip",6300,"bios"],["bios/isa_prose4001.zip",96246,"bios"],["bios/isbc202.zip",2023,"bios"],["bios/isbc8024.zip",98001,"bios"],["bios/isbc_215g.zip",11746,"bios"],["bios/isgsm.zip",10207,"bios"],["bios/isinger.zip",556765,"bios"],["bios/it8703f_device.zip",479847,"bios"],["bios/it8705f.zip",479847,"bios"],["bios/iteagle.zip",3614545,"bios"],["bios/iteagle_fpga.zip",95177,"bios"],["bios/itf.rom",32768,"bios"],["bios/ivelultrkb.zip",841,"bios"],["bios/jagboot.rom",131072,"bios"],["bios/jagboot_m.rom",131072,"bios"],["bios/jaleco_vj_pc.zip",1268315,"bios"],["bios/jc1310.zip",3574,"bios"],["bios/jopac.bin",1024,"bios"],["bios/jpopira.zip",1116085,"bios"],["bios/jvs13551.zip",15088,"bios"],["bios/k573_dio.zip",158,"bios"],["bios/k573kara.zip",95291,"bios"],["bios/k573mcr.zip",3927,"bios"],["bios/k573msu.zip",136526,"bios"],["bios/k7659_keyboard.zip",384,"bios"],["bios/kaypro10kbd.zip",1307,"bios"],["bios/kayproiikbd.zip",1101,"bios"],["bios/kb_3270pc.zip",1115,"bios"],["bios/kb_ec1841.zip",788,"bios"],["bios/kb_iskr1030.zip",1022,"bios"],["bios/kb_ms_natural.zip",3029,"bios"],["bios/kb_pcat101.zip",2989,"bios"],["bios/kb_pcat84.zip",1032,"bios"],["bios/kb_pcxt83.zip",726,"bios"],["bios/kbd_lle_en_us.zip",3038,"bios"],["bios/kc_d002.zip",1185978,"bios"],["bios/kc_d004.zip",4285,"bios"],["bios/kc_d004_gide.zip",1181737,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/keys.txt",449507,"bios"],["bios/keytronic_l2207.zip",2325,"bios"],["bios/keytronic_pc3270.zip",3168,"bios"],["bios/keytronic_pc3270_at.zip",3168,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick34005.CDTV",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40060.CD32.full",1048576,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/km035.zip",1035,"bios"],["bios/konamigv.zip",81391,"bios"],["bios/konamigx.zip",8734,"bios"],["bios/konendev.zip",25691,"bios"],["bios/kpython.zip",24831,"bios"],["bios/kpython2.zip",2638808,"bios"],["bios/kronos/stvbios.zip",3455065,"bios"],["bios/ks0066.zip",2011,"bios"],["bios/kviper.zip",33864,"bios"],["bios/labtam_3232.zip",73648,"bios"],["bios/labtam_8086cpu.zip",98364,"bios"],["bios/labtam_vducom.zip",170873,"bios"],["bios/labtam_z80sbc.zip",16546,"bios"],["bios/lba_enhancer.zip",2746,"bios"],["bios/lc7985.zip",957,"bios"],["bios/ldv1000.zip",4816,"bios"],["bios/lha201.zip",6661,"bios"],["bios/lindbios.zip",1462941,"bios"],["bios/lisa2fdc.zip",3159,"bios"],["bios/lisafdc.zip",3328,"bios"],["bios/lisavideo.zip",260,"bios"],["bios/lk201.zip",6069,"bios"],["bios/lm24014h.zip",629,"bios"],["bios/lrk331.zip",18121,"bios"],["bios/luna_68k_cmc.zip",13767,"bios"],["bios/luna_68k_gpu.zip",84000,"bios"],["bios/luna_68k_ioc.zip",28610,"bios"],["bios/lux10828.zip",9352,"bios"],["bios/lux21046.zip",24177,"bios"],["bios/lux21056.zip",18460,"bios"],["bios/lux4105.zip",778041,"bios"],["bios/lx800.zip",15176,"bios"],["bios/lx810l.zip",22103,"bios"],["bios/lynxboot.img",512,"bios"],["bios/m1comm.zip",3832,"bios"],["bios/m20_8086.zip",6611,"bios"],["bios/m24_kbd.zip",1483,"bios"],["bios/m24_z8000.zip",9638,"bios"],["bios/m50458.zip",2448,"bios"],["bios/m50dass.zip",5021,"bios"],["bios/m68705p3.zip",266,"bios"],["bios/m68705p5.zip",266,"bios"],["bios/m68705r3.zip",271,"bios"],["bios/m68705u3.zip",271,"bios"],["bios/m68hc05pge.zip",607,"bios"],["bios/macf108.zip",2024731,"bios"],["bios/mach64isa.zip",121273,"bios"],["bios/mackbd_m0110.zip",1021,"bios"],["bios/mackbd_m0110a.zip",866,"bios"],["bios/mackbd_m0110a_f.zip",866,"bios"],["bios/mackbd_m0110a_j.zip",866,"bios"],["bios/mackbd_m0110b.zip",1021,"bios"],["bios/mackbd_m0110f.zip",1021,"bios"],["bios/mackbd_m0110j.zip",1021,"bios"],["bios/mackbd_m0110t.zip",1021,"bios"],["bios/mackbd_m0120.zip",1051,"bios"],["bios/mackbd_m0120p.zip",1843,"bios"],["bios/macsbios.zip",305290,"bios"],["bios/macxlfdc.zip",5757,"bios"],["bios/macxlvideo.zip",212,"bios"],["bios/mame/hash/32x.xml",128073,"game_data"],["bios/mame/hash/3do.xml",3729,"game_data"],["bios/mame/hash/3do_m2.xml",1791,"game_data"],["bios/mame/hash/README.md",354,"game_data"],["bios/mame/hash/a2600.xml",737892,"game_data"],["bios/mame/hash/a2600_cass.xml",32898,"game_data"],["bios/mame/hash/a5200.hsi",32063,"game_data"],["bios/mame/hash/a5200.xml",58114,"game_data"],["bios/mame/hash/a7800.xml",127364,"game_data"],["bios/mame/hash/a800.xml",269515,"game_data"],["bios/mame/hash/a800_cass.xml",1717,"game_data"],["bios/mame/hash/a800_flop.xml",38722,"game_data"],["bios/mame/hash/abc1600_flop.xml",7222,"game_data"],["bios/mame/hash/abc1600_hdd.xml",547,"game_data"],["bios/mame/hash/abc800_hdd.xml",1362,"game_data"],["bios/mame/hash/abc806_flop.xml",4664,"game_data"],["bios/mame/hash/abc80_cass.xml",1063,"game_data"],["bios/mame/hash/abc80_flop.xml",4875,"game_data"],["bios/mame/hash/abc80_rom.xml",2440,"game_data"],["bios/mame/hash/abc830_flop.xml",7246,"game_data"],["bios/mame/hash/abc832_flop.xml",14768,"game_data"],["bios/mame/hash/abc838_flop.xml",1979,"game_data"],["bios/mame/hash/acrnsys_flop.xml",1659,"game_data"],["bios/mame/hash/acrnsys_rom.xml",2174,"game_data"],["bios/mame/hash/adam_cart.xml",6596,"game_data"],["bios/mame/hash/adam_cass.xml",33914,"game_data"],["bios/mame/hash/adam_flop.xml",625845,"game_data"],["bios/mame/hash/advantage.xml",5914,"game_data"],["bios/mame/hash/advision.xml",2281,"game_data"],["bios/mame/hash/aim65_cart.xml",9060,"game_data"],["bios/mame/hash/aleste.xml",1366,"game_data"],["bios/mame/hash/alice32.xml",27026,"game_data"],["bios/mame/hash/alice90.xml",3996,"game_data"],["bios/mame/hash/alphasmart_kapps.xml",16025,"game_data"],["bios/mame/hash/alphatro_cart.xml",1129,"game_data"],["bios/mame/hash/alphatro_flop.xml",1342,"game_data"],["bios/mame/hash/altos5.xml",1323,"game_data"],["bios/mame/hash/altos586.xml",574,"game_data"],["bios/mame/hash/altos8600.xml",1043,"game_data"],["bios/mame/hash/amiga_amix.xml",4460,"game_data"],["bios/mame/hash/amiga_apps.xml",7434,"game_data"],["bios/mame/hash/amiga_cd.xml",15524,"game_data"],["bios/mame/hash/amiga_demos.xml",3217,"game_data"],["bios/mame/hash/amiga_flop.xml",410553,"game_data"],["bios/mame/hash/amiga_hardware.xml",9287,"game_data"],["bios/mame/hash/amiga_hdd.xml",1617,"game_data"],["bios/mame/hash/amiga_workbench.xml",61616,"game_data"],["bios/mame/hash/amigaaga_flop.xml",215186,"game_data"],["bios/mame/hash/amigaecs_flop.xml",35873,"game_data"],["bios/mame/hash/amigaocs_flop.xml",2095329,"game_data"],["bios/mame/hash/ampro.xml",2178,"game_data"],["bios/mame/hash/apc.xml",14254,"game_data"],["bios/mame/hash/apexc_cyl.xml",1523,"game_data"],["bios/mame/hash/apfimag_cass.xml",43143,"game_data"],["bios/mame/hash/apfm1000.xml",9759,"game_data"],["bios/mame/hash/apogee.xml",41066,"game_data"],["bios/mame/hash/apollo_ctape.xml",2075,"game_data"],["bios/mame/hash/apple1.xml",20026,"game_data"],["bios/mame/hash/apple2_cass.xml",138008,"game_data"],["bios/mame/hash/apple2_flop_clcracked.xml",2899755,"game_data"],["bios/mame/hash/apple2_flop_misc.xml",308001,"game_data"],["bios/mame/hash/apple2_flop_orig.xml",2077439,"game_data"],["bios/mame/hash/apple2_rom.xml",1709,"game_data"],["bios/mame/hash/apple2gs_flop_clcracked.xml",162549,"game_data"],["bios/mame/hash/apple2gs_flop_misc.xml",296955,"game_data"],["bios/mame/hash/apple2gs_flop_orig.xml",234778,"game_data"],["bios/mame/hash/apple3.xml",10270,"game_data"],["bios/mame/hash/applix_flop.xml",541,"game_data"],["bios/mame/hash/apricot_flop.xml",33034,"game_data"],["bios/mame/hash/apxen_flop.xml",1562,"game_data"],["bios/mame/hash/aquarius_cart.xml",14960,"game_data"],["bios/mame/hash/aquarius_cass.xml",34155,"game_data"],["bios/mame/hash/arb.xml",3568,"game_data"],["bios/mame/hash/arcadia.xml",57566,"game_data"],["bios/mame/hash/archimedes.xml",271056,"game_data"],["bios/mame/hash/archimedes_hdd.xml",549,"game_data"],["bios/mame/hash/archimedes_rom.xml",2409,"game_data"],["bios/mame/hash/astrocde.xml",56504,"game_data"],["bios/mame/hash/atom_cass.xml",19518,"game_data"],["bios/mame/hash/atom_flop.xml",7657,"game_data"],["bios/mame/hash/atom_rom.xml",16011,"game_data"],["bios/mame/hash/attache.xml",555,"game_data"],["bios/mame/hash/aussiebyte.xml",545,"game_data"],["bios/mame/hash/b2m.xml",1244,"game_data"],["bios/mame/hash/basf7100.xml",881,"game_data"],["bios/mame/hash/bbc_cass.xml",736181,"game_data"],["bios/mame/hash/bbc_flop_32016.xml",8282,"game_data"],["bios/mame/hash/bbc_flop_6502.xml",6281,"game_data"],["bios/mame/hash/bbc_flop_68000.xml",1770,"game_data"],["bios/mame/hash/bbc_flop_80186.xml",7946,"game_data"],["bios/mame/hash/bbc_flop_arm.xml",11609,"game_data"],["bios/mame/hash/bbc_flop_hybrid.xml",40742,"game_data"],["bios/mame/hash/bbc_flop_torch.xml",19139,"game_data"],["bios/mame/hash/bbc_flop_z80.xml",7743,"game_data"],["bios/mame/hash/bbc_hdd.xml",2639,"game_data"],["bios/mame/hash/bbc_rom.xml",502371,"game_data"],["bios/mame/hash/bbc_vsm.xml",2571,"game_data"],["bios/mame/hash/bbcb_flop.xml",124846,"game_data"],["bios/mame/hash/bbcb_flop_orig.xml",158528,"game_data"],["bios/mame/hash/bbcb_flop_us.xml",743,"game_data"],["bios/mame/hash/bbcbc.xml",5189,"game_data"],["bios/mame/hash/bbcm_cart.xml",11115,"game_data"],["bios/mame/hash/bbcm_flop.xml",5301,"game_data"],["bios/mame/hash/bbcmc_flop.xml",17528,"game_data"],["bios/mame/hash/bdesignm_design_cart.xml",3983,"game_data"],["bios/mame/hash/bdesignm_game_cart.xml",3809,"game_data"],["bios/mame/hash/bingobear.xml",1244,"game_data"],["bios/mame/hash/bk0010.xml",49493,"game_data"],["bios/mame/hash/bkrankp_cart.xml",9615,"game_data"],["bios/mame/hash/bmjr_cass.xml",790,"game_data"],["bios/mame/hash/bml3_cass.xml",1359,"game_data"],["bios/mame/hash/bml3_flop.xml",4172,"game_data"],["bios/mame/hash/brother_pn.xml",1902,"game_data"],["bios/mame/hash/bungo_flop.xml",2355,"game_data"],["bios/mame/hash/buzztime_cart.xml",1855,"game_data"],["bios/mame/hash/bw12.xml",869,"game_data"],["bios/mame/hash/bw14.xml",4116,"game_data"],["bios/mame/hash/bw2.xml",2574,"game_data"],["bios/mame/hash/bx256hp_flop.xml",4979,"game_data"],["bios/mame/hash/c128_cart.xml",7667,"game_data"],["bios/mame/hash/c128_flop.xml",29219,"game_data"],["bios/mame/hash/c128_rom.xml",3843,"game_data"],["bios/mame/hash/c2color_cart.xml",4498,"game_data"],["bios/mame/hash/c64_cart.xml",258956,"game_data"],["bios/mame/hash/c64_cass.xml",578831,"game_data"],["bios/mame/hash/c64_flop_misc.xml",34001,"game_data"],["bios/mame/hash/c64_flop_orig.xml",30419,"game_data"],["bios/mame/hash/c64_quik.xml",585,"game_data"],["bios/mame/hash/c65_flop.xml",616,"game_data"],["bios/mame/hash/camplynx_cass.xml",37656,"game_data"],["bios/mame/hash/camplynx_flop.xml",13892,"game_data"],["bios/mame/hash/carbeena.xml",811,"game_data"],["bios/mame/hash/casio_rompack.xml",72987,"game_data"],["bios/mame/hash/casloopy.xml",7085,"game_data"],["bios/mame/hash/cassvisn_cart.xml",8242,"game_data"],["bios/mame/hash/cbm2_cart.xml",2432,"game_data"],["bios/mame/hash/cbm2_flop.xml",55851,"game_data"],["bios/mame/hash/cbm8096_flop.xml",976,"game_data"],["bios/mame/hash/cbm8296_flop.xml",1344,"game_data"],["bios/mame/hash/cc40_cart.xml",4533,"game_data"],["bios/mame/hash/cd32.xml",73479,"game_data"],["bios/mame/hash/cdi.xml",541705,"game_data"],["bios/mame/hash/cdtv.xml",128903,"game_data"],["bios/mame/hash/cecflop.xml",9584,"game_data"],["bios/mame/hash/cgenie_cass.xml",135849,"game_data"],["bios/mame/hash/cgenie_flop_rom.xml",1068,"game_data"],["bios/mame/hash/challenge_gear_cart.xml",1798,"game_data"],["bios/mame/hash/channelf.xml",20040,"game_data"],["bios/mame/hash/chessking_cart.xml",641,"game_data"],["bios/mame/hash/chessmstdm.xml",1095,"game_data"],["bios/mame/hash/chip8_quik.xml",32203,"game_data"],["bios/mame/hash/clickstart_cart.xml",10218,"game_data"],["bios/mame/hash/clipper_flop.xml",1190,"game_data"],["bios/mame/hash/coco_cart.xml",57803,"game_data"],["bios/mame/hash/coco_flop.xml",81301,"game_data"],["bios/mame/hash/coleco.xml",153128,"game_data"],["bios/mame/hash/coleco_homebrew.xml",89593,"game_data"],["bios/mame/hash/compclr2_flop.xml",94972,"game_data"],["bios/mame/hash/compis.xml",40308,"game_data"],["bios/mame/hash/comx35_flop.xml",543,"game_data"],["bios/mame/hash/conchess.xml",1245,"game_data"],["bios/mame/hash/copera.xml",5754,"game_data"],["bios/mame/hash/cpc_cass.xml",1991951,"game_data"],["bios/mame/hash/cpc_flop.xml",12700511,"game_data"],["bios/mame/hash/crvision.xml",29061,"game_data"],["bios/mame/hash/ctvboy.xml",3078,"game_data"],["bios/mame/hash/cubieboard4.xml",3873,"game_data"],["bios/mame/hash/cx3000tc.xml",2044,"game_data"],["bios/mame/hash/cz1_cart.xml",1477,"game_data"],["bios/mame/hash/dai_cass.xml",4412,"game_data"],["bios/mame/hash/database.xml",8810,"game_data"],["bios/mame/hash/dc.xml",1547464,"game_data"],["bios/mame/hash/dgnalpha_flop.xml",6812,"game_data"],["bios/mame/hash/dgnbeta_flop.xml",1891,"game_data"],["bios/mame/hash/digiblast_cart.xml",10923,"game_data"],["bios/mame/hash/digilog320.xml",1545,"game_data"],["bios/mame/hash/dim68k.xml",7070,"game_data"],["bios/mame/hash/dmv.xml",54867,"game_data"],["bios/mame/hash/dps1.xml",596,"game_data"],["bios/mame/hash/dragon_cart.xml",19887,"game_data"],["bios/mame/hash/dragon_cass.xml",452453,"game_data"],["bios/mame/hash/dragon_flex.xml",11710,"game_data"],["bios/mame/hash/dragon_flop.xml",78876,"game_data"],["bios/mame/hash/dragon_os9.xml",7566,"game_data"],["bios/mame/hash/duelmast_cart.xml",1148,"game_data"],["bios/mame/hash/e01_flop.xml",972,"game_data"],["bios/mame/hash/easy_karaoke_cart.xml",16341,"game_data"],["bios/mame/hash/ec1841.xml",4295,"game_data"],["bios/mame/hash/einstein.xml",53792,"game_data"],["bios/mame/hash/einstein_rom.xml",547,"game_data"],["bios/mame/hash/ekara_cart.xml",193645,"game_data"],["bios/mame/hash/electron_cart.xml",22690,"game_data"],["bios/mame/hash/electron_cass.xml",270749,"game_data"],["bios/mame/hash/electron_flop.xml",105636,"game_data"],["bios/mame/hash/electron_rom.xml",36576,"game_data"],["bios/mame/hash/entex_sag.xml",3620,"game_data"],["bios/mame/hash/ep64_cart.xml",6240,"game_data"],["bios/mame/hash/ep64_cass.xml",1272,"game_data"],["bios/mame/hash/ep64_flop.xml",73009,"game_data"],["bios/mame/hash/epson_cpm.xml",5880,"game_data"],["bios/mame/hash/eti660_quik.xml",2480,"game_data"],["bios/mame/hash/evio.xml",10523,"game_data"],["bios/mame/hash/ews286_flop.xml",1384,"game_data"],["bios/mame/hash/excalibur64.xml",551,"game_data"],["bios/mame/hash/exl100.xml",6011,"game_data"],["bios/mame/hash/famibox.xml",31176,"game_data"],["bios/mame/hash/famicom_cass.xml",21948,"game_data"],["bios/mame/hash/famicom_flop.xml",168824,"game_data"],["bios/mame/hash/fidel_msc.xml",1132,"game_data"],["bios/mame/hash/fidel_sc6.xml",565,"game_data"],["bios/mame/hash/fidel_scc.xml",4897,"game_data"],["bios/mame/hash/fm77av.xml",56002,"game_data"],["bios/mame/hash/fm7_cass.xml",84996,"game_data"],["bios/mame/hash/fm7_disk.xml",94601,"game_data"],["bios/mame/hash/fm8_cass.xml",13963,"game_data"],["bios/mame/hash/fmtowns_cd.xml",2734453,"game_data"],["bios/mame/hash/fmtowns_flop_cracked.xml",3606,"game_data"],["bios/mame/hash/fmtowns_flop_misc.xml",63683,"game_data"],["bios/mame/hash/fmtowns_flop_orig.xml",150372,"game_data"],["bios/mame/hash/fp1100_cass.xml",4676,"game_data"],["bios/mame/hash/gaelco_ds5002fp_rom.xml",4164,"game_data"],["bios/mame/hash/galaxy.xml",24068,"game_data"],["bios/mame/hash/gamate.xml",27468,"game_data"],["bios/mame/hash/gameboy.xml",1136450,"game_data"],["bios/mame/hash/gamecom.xml",10648,"game_data"],["bios/mame/hash/gamegear.xml",414475,"game_data"],["bios/mame/hash/gameking.xml",21981,"game_data"],["bios/mame/hash/gameking3.xml",4399,"game_data"],["bios/mame/hash/gamepock.xml",2708,"game_data"],["bios/mame/hash/gba.xml",1727109,"game_data"],["bios/mame/hash/gba_ereader.xml",286933,"game_data"],["bios/mame/hash/gbcolor.xml",1161729,"game_data"],["bios/mame/hash/gcslottv.xml",2531,"game_data"],["bios/mame/hash/generic_cdrom.xml",52075,"game_data"],["bios/mame/hash/generic_flop_525.xml",4909,"game_data"],["bios/mame/hash/genie3_flop.xml",4849,"game_data"],["bios/mame/hash/ggm.xml",8019,"game_data"],["bios/mame/hash/gimix.xml",2241,"game_data"],["bios/mame/hash/gj4000.xml",681,"game_data"],["bios/mame/hash/gjmovie.xml",760,"game_data"],["bios/mame/hash/gjrstar.xml",2795,"game_data"],["bios/mame/hash/gl2000.xml",4022,"game_data"],["bios/mame/hash/gl6000sl.xml",1205,"game_data"],["bios/mame/hash/glcolor.xml",2575,"game_data"],["bios/mame/hash/glcx.xml",4447,"game_data"],["bios/mame/hash/gln.xml",1724,"game_data"],["bios/mame/hash/gls.xml",609,"game_data"],["bios/mame/hash/gmaster.xml",7077,"game_data"],["bios/mame/hash/gp32.xml",20073,"game_data"],["bios/mame/hash/gtfore.xml",2385,"game_data"],["bios/mame/hash/guab.xml",4131,"game_data"],["bios/mame/hash/gx4000.xml",12933,"game_data"],["bios/mame/hash/h21.xml",1358,"game_data"],["bios/mame/hash/h88_cass.xml",6198,"game_data"],["bios/mame/hash/hikara.xml",23854,"game_data"],["bios/mame/hash/horizon.xml",110171,"game_data"],["bios/mame/hash/hp85_rom.xml",2800,"game_data"],["bios/mame/hash/hp86_rom.xml",5029,"game_data"],["bios/mame/hash/hp9825_rom.xml",6691,"game_data"],["bios/mame/hash/hp9831_rom.xml",1188,"game_data"],["bios/mame/hash/hp9835a_rom.xml",2757,"game_data"],["bios/mame/hash/hp9845a_rom.xml",4328,"game_data"],["bios/mame/hash/hp9845b_rom.xml",19426,"game_data"],["bios/mame/hash/hp98x6_rom.xml",1486,"game_data"],["bios/mame/hash/hp9k3xx_cdrom.xml",7323,"game_data"],["bios/mame/hash/hp9k3xx_flop.xml",30834,"game_data"],["bios/mame/hash/hp9k3xx_hdd.xml",691,"game_data"],["bios/mame/hash/hp_ipc.xml",23990,"game_data"],["bios/mame/hash/hp_ipc_rom.xml",672,"game_data"],["bios/mame/hash/ht68k.xml",923,"game_data"],["bios/mame/hash/hx20_rom.xml",904,"game_data"],["bios/mame/hash/hyperscan.xml",2390,"game_data"],["bios/mame/hash/hyperscan_card.xml",193115,"game_data"],["bios/mame/hash/i7000_card.xml",7455,"game_data"],["bios/mame/hash/ibm5140.xml",1967,"game_data"],["bios/mame/hash/ibm5150.xml",824234,"game_data"],["bios/mame/hash/ibm5150_cass.xml",736,"game_data"],["bios/mame/hash/ibm5150_hdd.xml",5316,"game_data"],["bios/mame/hash/ibm5170.xml",1162208,"game_data"],["bios/mame/hash/ibm5170_cdrom.xml",454762,"game_data"],["bios/mame/hash/ibm5170_hdd.xml",12253,"game_data"],["bios/mame/hash/ibm6580.xml",4972,"game_data"],["bios/mame/hash/ibmpc110.xml",1581,"game_data"],["bios/mame/hash/ibmpcjr_cart.xml",9823,"game_data"],["bios/mame/hash/ibmpcjr_flop.xml",6253,"game_data"],["bios/mame/hash/ibmpcjx.xml",2034,"game_data"],["bios/mame/hash/icanguit.xml",4013,"game_data"],["bios/mame/hash/icanpian.xml",7041,"game_data"],["bios/mame/hash/intellect02.xml",1026,"game_data"],["bios/mame/hash/interact.xml",14054,"game_data"],["bios/mame/hash/interpro.xml",15826,"game_data"],["bios/mame/hash/intv.hsi",21652,"game_data"],["bios/mame/hash/intv.xml",100100,"game_data"],["bios/mame/hash/intvecs.xml",7161,"game_data"],["bios/mame/hash/iq128.xml",1656,"game_data"],["bios/mame/hash/iq151_cart.xml",2180,"game_data"],["bios/mame/hash/iq151_flop.xml",1019,"game_data"],["bios/mame/hash/ique.xml",18576,"game_data"],["bios/mame/hash/iqunlim_cart.xml",1166,"game_data"],["bios/mame/hash/itt3030.xml",1428,"game_data"],["bios/mame/hash/jaguar.xml",78281,"game_data"],["bios/mame/hash/jakks_gamekey_dp.xml",761,"game_data"],["bios/mame/hash/jakks_gamekey_dy.xml",2768,"game_data"],["bios/mame/hash/jakks_gamekey_mv.xml",756,"game_data"],["bios/mame/hash/jakks_gamekey_nk.xml",1934,"game_data"],["bios/mame/hash/jakks_gamekey_nm.xml",2051,"game_data"],["bios/mame/hash/jakks_gamekey_sw.xml",2931,"game_data"],["bios/mame/hash/jakks_gamekey_wp.xml",1064,"game_data"],["bios/mame/hash/jaminator.xml",6011,"game_data"],["bios/mame/hash/jazz.xml",1564,"game_data"],["bios/mame/hash/jb3000_flop.xml",660,"game_data"],["bios/mame/hash/juicebox.xml",18075,"game_data"],["bios/mame/hash/juku.xml",6267,"game_data"],["bios/mame/hash/jupace_cass.xml",81423,"game_data"],["bios/mame/hash/jupace_snap.xml",2564,"game_data"],["bios/mame/hash/k28.xml",3157,"game_data"],["bios/mame/hash/k28o.xml",827,"game_data"],["bios/mame/hash/kaypro.xml",8389,"game_data"],["bios/mame/hash/kc_cart.xml",2336,"game_data"],["bios/mame/hash/kc_cass.xml",70753,"game_data"],["bios/mame/hash/kc_flop.xml",2125,"game_data"],["bios/mame/hash/kim1_cass.xml",4296,"game_data"],["bios/mame/hash/kisssite_cd.xml",13436,"game_data"],["bios/mame/hash/korvet_flop.xml",8743,"game_data"],["bios/mame/hash/kpython2.xml",3610,"game_data"],["bios/mame/hash/lanteach.xml",561,"game_data"],["bios/mame/hash/lantrans.xml",4167,"game_data"],["bios/mame/hash/laser2001_cart.xml",729,"game_data"],["bios/mame/hash/laser2001_flop.xml",587,"game_data"],["bios/mame/hash/leapfrog_didj_cart.xml",3419,"game_data"],["bios/mame/hash/leapfrog_iquest_cart.xml",996,"game_data"],["bios/mame/hash/leapfrog_leappad_cart.xml",91522,"game_data"],["bios/mame/hash/leapfrog_ltleappad_cart.xml",9206,"game_data"],["bios/mame/hash/leapfrog_mfleappad_cart.xml",11748,"game_data"],["bios/mame/hash/leapfrog_zippity_cart.xml",1903,"game_data"],["bios/mame/hash/leapster.xml",79859,"game_data"],["bios/mame/hash/leapster_explorer_cart.xml",2082,"game_data"],["bios/mame/hash/lisa.xml",35666,"game_data"],["bios/mame/hash/lisa2.xml",5305,"game_data"],["bios/mame/hash/lk3000.xml",2341,"game_data"],["bios/mame/hash/lnux4004.xml",551,"game_data"],["bios/mame/hash/lviv.xml",117889,"game_data"],["bios/mame/hash/lynx.xml",57321,"game_data"],["bios/mame/hash/m20.xml",24233,"game_data"],["bios/mame/hash/m24.xml",585,"game_data"],["bios/mame/hash/m3.xml",567,"game_data"],["bios/mame/hash/m5_cart.xml",24121,"game_data"],["bios/mame/hash/m5_cass.xml",16984,"game_data"],["bios/mame/hash/m5_flop.xml",1025,"game_data"],["bios/mame/hash/mac_cdrom.xml",9773,"game_data"],["bios/mame/hash/mac_flop.xml",9064,"game_data"],["bios/mame/hash/mac_flop_clcracked.xml",131047,"game_data"],["bios/mame/hash/mac_flop_orig.xml",199535,"game_data"],["bios/mame/hash/mac_hdd.xml",3737,"game_data"],["bios/mame/hash/mac_hdflop.xml",329807,"game_data"],["bios/mame/hash/mbc200.xml",906,"game_data"],["bios/mame/hash/mbc55x.xml",6393,"game_data"],["bios/mame/hash/mbee_cart.xml",23641,"game_data"],["bios/mame/hash/mbee_cass.xml",1994,"game_data"],["bios/mame/hash/mbee_flop.xml",218405,"game_data"],["bios/mame/hash/mbee_quik.xml",64816,"game_data"],["bios/mame/hash/mc10.xml",52188,"game_data"],["bios/mame/hash/mc1000_cass.xml",53448,"game_data"],["bios/mame/hash/mc1502_flop.xml",949,"game_data"],["bios/mame/hash/md2_flop.xml",2723,"game_data"],["bios/mame/hash/megacd.xml",1291438,"game_data"],["bios/mame/hash/megadriv.xml",1656213,"game_data"],["bios/mame/hash/megaduck.xml",19227,"game_data"],["bios/mame/hash/megapc.xml",1756,"game_data"],["bios/mame/hash/megatech.xml",31502,"game_data"],["bios/mame/hash/mephisto_mm1.xml",613,"game_data"],["bios/mame/hash/mephisto_mm2.xml",650,"game_data"],["bios/mame/hash/mephisto_mm4.xml",618,"game_data"],["bios/mame/hash/mephisto_mm5.xml",616,"game_data"],["bios/mame/hash/mephisto_smondial2.xml",681,"game_data"],["bios/mame/hash/microbox2_flop.xml",955,"game_data"],["bios/mame/hash/microvision.xml",12187,"game_data"],["bios/mame/hash/midi_flop.xml",1102,"game_data"],["bios/mame/hash/mikro80.xml",2155,"game_data"],["bios/mame/hash/mikrosha_cart.xml",564,"game_data"],["bios/mame/hash/mikrosha_cass.xml",19640,"game_data"],["bios/mame/hash/mindset_flop.xml",889,"game_data"],["bios/mame/hash/misterx.xml",1485,"game_data"],["bios/mame/hash/mk14_quik.xml",1607,"game_data"],["bios/mame/hash/mm1_flop.xml",3737,"game_data"],["bios/mame/hash/mm2_flop.xml",1145,"game_data"],["bios/mame/hash/mm2_hdd.xml",564,"game_data"],["bios/mame/hash/mo5_cart.xml",21269,"game_data"],["bios/mame/hash/mo5_cass.xml",706525,"game_data"],["bios/mame/hash/mo5_flop.xml",32837,"game_data"],["bios/mame/hash/mo5_qd.xml",12350,"game_data"],["bios/mame/hash/mo6_cass.xml",70027,"game_data"],["bios/mame/hash/mo6_flop.xml",23106,"game_data"],["bios/mame/hash/mobigo_cart.xml",23750,"game_data"],["bios/mame/hash/monon_color.xml",15292,"game_data"],["bios/mame/hash/mpc3000_flop.xml",3350,"game_data"],["bios/mame/hash/mpc60_flop.xml",15063,"game_data"],["bios/mame/hash/mpf1_rom.xml",2881,"game_data"],["bios/mame/hash/mpu1000.xml",614,"game_data"],["bios/mame/hash/mpz80.xml",21352,"game_data"],["bios/mame/hash/msx.hsi",130435,"game_data"],["bios/mame/hash/msx1_bee_card.xml",5450,"game_data"],["bios/mame/hash/msx1_cart.xml",1069721,"game_data"],["bios/mame/hash/msx1_cass.xml",815967,"game_data"],["bios/mame/hash/msx1_flop.xml",243313,"game_data"],["bios/mame/hash/msx1_flop_525.xml",8311,"game_data"],["bios/mame/hash/msx2.hsi",290917,"game_data"],["bios/mame/hash/msx2_cart.xml",191807,"game_data"],["bios/mame/hash/msx2_cass.xml",2308,"game_data"],["bios/mame/hash/msx2_flop.xml",1138601,"game_data"],["bios/mame/hash/msx2p_cart.xml",2243,"game_data"],["bios/mame/hash/msx2p_flop.xml",35351,"game_data"],["bios/mame/hash/msx_softcard.xml",2406,"game_data"],["bios/mame/hash/msx_yamaha_minicart.xml",913,"game_data"],["bios/mame/hash/msxr_cart.xml",4556,"game_data"],["bios/mame/hash/msxr_flop.xml",58312,"game_data"],["bios/mame/hash/mt65_cass.xml",3972,"game_data"],["bios/mame/hash/mt65_rom.xml",7665,"game_data"],["bios/mame/hash/mt65_snap.xml",6125,"game_data"],["bios/mame/hash/mtu130_flop.xml",2682,"game_data"],["bios/mame/hash/mtx_cart.xml",3484,"game_data"],["bios/mame/hash/mtx_cass.xml",23223,"game_data"],["bios/mame/hash/mtx_flop.xml",3849,"game_data"],["bios/mame/hash/mtx_hdd.xml",1479,"game_data"],["bios/mame/hash/mtx_rom.xml",2033,"game_data"],["bios/mame/hash/mylife_cart.xml",3029,"game_data"],["bios/mame/hash/myvision.xml",10822,"game_data"],["bios/mame/hash/mz2000_cass.xml",18487,"game_data"],["bios/mame/hash/mz2000_flop.xml",6827,"game_data"],["bios/mame/hash/mz2000_snap.xml",6357,"game_data"],["bios/mame/hash/mz2500_flop.xml",41591,"game_data"],["bios/mame/hash/mz5500_flop.xml",3298,"game_data"],["bios/mame/hash/mz700_cass.xml",101940,"game_data"],["bios/mame/hash/mz800_cass.xml",6416,"game_data"],["bios/mame/hash/mz800_rom.xml",1699,"game_data"],["bios/mame/hash/mz80b_cass.xml",3476,"game_data"],["bios/mame/hash/mz80b_flop.xml",1334,"game_data"],["bios/mame/hash/mz80k_cass.xml",17674,"game_data"],["bios/mame/hash/n64.xml",634504,"game_data"],["bios/mame/hash/n64_lodgenet.xml",18886,"game_data"],["bios/mame/hash/n64dd.xml",7365,"game_data"],["bios/mame/hash/nascom_flop.xml",4009,"game_data"],["bios/mame/hash/nascom_snap.xml",32837,"game_data"],["bios/mame/hash/nascom_socket.xml",2918,"game_data"],["bios/mame/hash/neocd.xml",69767,"game_data"],["bios/mame/hash/neogeo.xml",861636,"game_data"],["bios/mame/hash/nes.hsi",2901163,"game_data"],["bios/mame/hash/nes.xml",3760989,"game_data"],["bios/mame/hash/nes_ade.xml",3683,"game_data"],["bios/mame/hash/nes_datach.xml",5512,"game_data"],["bios/mame/hash/nes_kstudio.xml",1679,"game_data"],["bios/mame/hash/nes_ntbrom.xml",1534,"game_data"],["bios/mame/hash/nes_vt_cart.xml",1225,"game_data"],["bios/mame/hash/next.xml",4495,"game_data"],["bios/mame/hash/next_cdrom.xml",2473,"game_data"],["bios/mame/hash/next_hdd.xml",5837,"game_data"],["bios/mame/hash/ngp.xml",6692,"game_data"],["bios/mame/hash/ngpc.xml",69520,"game_data"],["bios/mame/hash/nimbus.xml",14651,"game_data"],["bios/mame/hash/novag_ssensor4.xml",690,"game_data"],["bios/mame/hash/nuon.xml",3452,"game_data"],["bios/mame/hash/octopus.xml",3416,"game_data"],["bios/mame/hash/ondra.xml",4936,"game_data"],["bios/mame/hash/orao.xml",25307,"game_data"],["bios/mame/hash/oric1_cass.xml",201867,"game_data"],["bios/mame/hash/orina_stylish_plus_cart.xml",694,"game_data"],["bios/mame/hash/orion_cart.xml",898,"game_data"],["bios/mame/hash/orion_cass.xml",28871,"game_data"],["bios/mame/hash/orion_flop.xml",42898,"game_data"],["bios/mame/hash/orionpro_flop.xml",12350,"game_data"],["bios/mame/hash/osborne1.xml",10325,"game_data"],["bios/mame/hash/osborne2.xml",2130,"game_data"],["bios/mame/hash/p2000_cart.xml",19726,"game_data"],["bios/mame/hash/p2000_cass.xml",80619,"game_data"],["bios/mame/hash/p500_flop.xml",925,"game_data"],["bios/mame/hash/partner_cass.xml",27737,"game_data"],["bios/mame/hash/partner_flop.xml",890,"game_data"],["bios/mame/hash/pasogo.xml",4088,"game_data"],["bios/mame/hash/pasopia7_cass.xml",1740,"game_data"],["bios/mame/hash/pasopia_cass.xml",3381,"game_data"],["bios/mame/hash/pb2000c.xml",994,"game_data"],["bios/mame/hash/pc1000.xml",5519,"game_data"],["bios/mame/hash/pc100_flop.xml",3563,"game_data"],["bios/mame/hash/pc1512_flop.xml",6358,"game_data"],["bios/mame/hash/pc1512_hdd.xml",511,"game_data"],["bios/mame/hash/pc1640_flop.xml",2796,"game_data"],["bios/mame/hash/pc1640_hdd.xml",572,"game_data"],["bios/mame/hash/pc200.xml",1683,"game_data"],["bios/mame/hash/pc6001_cart.xml",6880,"game_data"],["bios/mame/hash/pc6001_cass.xml",52713,"game_data"],["bios/mame/hash/pc6001mk2_cass.xml",42402,"game_data"],["bios/mame/hash/pc6001mk2_flop.xml",5521,"game_data"],["bios/mame/hash/pc6001mk2sr_cass.xml",8673,"game_data"],["bios/mame/hash/pc6001mk2sr_flop.xml",1876,"game_data"],["bios/mame/hash/pc8001_flop.xml",131233,"game_data"],["bios/mame/hash/pc8001mk2_flop.xml",10373,"game_data"],["bios/mame/hash/pc8001mk2sr_flop.xml",7003,"game_data"],["bios/mame/hash/pc8201.xml",1733,"game_data"],["bios/mame/hash/pc8801_cass.xml",56042,"game_data"],["bios/mame/hash/pc8801_cdrom.xml",6105,"game_data"],["bios/mame/hash/pc8801_flop.xml",2323906,"game_data"],["bios/mame/hash/pc8801_flop_orig.xml",840,"game_data"],["bios/mame/hash/pc88va.xml",66115,"game_data"],["bios/mame/hash/pc88va_flop_orig.xml",5665,"game_data"],["bios/mame/hash/pc98.xml",3156503,"game_data"],["bios/mame/hash/pc98_cd.xml",496918,"game_data"],["bios/mame/hash/pc98_flop_orig.xml",10051,"game_data"],["bios/mame/hash/pc98_hdd.xml",939,"game_data"],["bios/mame/hash/pcd_flop.xml",2088,"game_data"],["bios/mame/hash/pce.xml",168484,"game_data"],["bios/mame/hash/pce_tourvision.xml",64224,"game_data"],["bios/mame/hash/pcecd.xml",359086,"game_data"],["bios/mame/hash/pcfx.xml",6670,"game_data"],["bios/mame/hash/pcw.xml",74002,"game_data"],["bios/mame/hash/pcw16.xml",2116,"game_data"],["bios/mame/hash/pcx_flop.xml",7886,"game_data"],["bios/mame/hash/pda600.xml",1050,"game_data"],["bios/mame/hash/pdp1_ptp.xml",2537,"game_data"],["bios/mame/hash/pecom_cass.xml",3816,"game_data"],["bios/mame/hash/pegasus_cart.xml",8532,"game_data"],["bios/mame/hash/pencil2.xml",4876,"game_data"],["bios/mame/hash/pencil2_cass.xml",7881,"game_data"],["bios/mame/hash/pentagon_cass.xml",1246,"game_data"],["bios/mame/hash/pet_cass.xml",106400,"game_data"],["bios/mame/hash/pet_flop.xml",33750,"game_data"],["bios/mame/hash/pet_hdd.xml",1283,"game_data"],["bios/mame/hash/pet_quik.xml",1032,"game_data"],["bios/mame/hash/pet_rom.xml",14809,"game_data"],["bios/mame/hash/phc25_cass.xml",12548,"game_data"],["bios/mame/hash/photo_cd.xml",1400,"game_data"],["bios/mame/hash/pi_storyreader_cart.xml",22422,"game_data"],["bios/mame/hash/pi_storyreader_v2_cart.xml",658,"game_data"],["bios/mame/hash/picno.xml",12147,"game_data"],["bios/mame/hash/pico.xml",288031,"game_data"],["bios/mame/hash/pippin.xml",45021,"game_data"],["bios/mame/hash/pippin_flop.xml",750,"game_data"],["bios/mame/hash/pixter_cart.xml",2630,"game_data"],["bios/mame/hash/playmaker.xml",1242,"game_data"],["bios/mame/hash/pls1000_cart.xml",2938,"game_data"],["bios/mame/hash/plus4_cart.xml",10278,"game_data"],["bios/mame/hash/plus4_cass.xml",1191,"game_data"],["bios/mame/hash/plus4_flop.xml",2108,"game_data"],["bios/mame/hash/plus4_quik.xml",951,"game_data"],["bios/mame/hash/pmd85_cass.xml",45145,"game_data"],["bios/mame/hash/pockchalv2.xml",18615,"game_data"],["bios/mame/hash/pockchalw.xml",30826,"game_data"],["bios/mame/hash/pofo.xml",2062,"game_data"],["bios/mame/hash/poisk1_flop.xml",961,"game_data"],["bios/mame/hash/pokemini.xml",19575,"game_data"],["bios/mame/hash/poly_flop.xml",1085,"game_data"],["bios/mame/hash/polysix.xml",889,"game_data"],["bios/mame/hash/popstar_cart.xml",1581,"game_data"],["bios/mame/hash/precur2w_cart.xml",782,"game_data"],["bios/mame/hash/princ.xml",3746,"game_data"],["bios/mame/hash/pro128_cart.xml",1868,"game_data"],["bios/mame/hash/pro128_cass.xml",81276,"game_data"],["bios/mame/hash/pro128_flop.xml",1233,"game_data"],["bios/mame/hash/pro128s_flop.xml",14348,"game_data"],["bios/mame/hash/prof180.xml",1181,"game_data"],["bios/mame/hash/prof80.xml",865,"game_data"],["bios/mame/hash/psi98.xml",1275,"game_data"],["bios/mame/hash/psion1.xml",3874,"game_data"],["bios/mame/hash/psion2.xml",79959,"game_data"],["bios/mame/hash/psion_flop.xml",1096,"game_data"],["bios/mame/hash/psion_quik.xml",5838,"game_data"],["bios/mame/hash/psion_ssd.xml",21905,"game_data"],["bios/mame/hash/psx.xml",3919227,"game_data"],["bios/mame/hash/pt68k2.xml",555,"game_data"],["bios/mame/hash/pv1000.xml",12768,"game_data"],["bios/mame/hash/pv2000.xml",11468,"game_data"],["bios/mame/hash/px4_cart.xml",3064,"game_data"],["bios/mame/hash/px8_cart.xml",7208,"game_data"],["bios/mame/hash/pyl601.xml",5562,"game_data"],["bios/mame/hash/ql_cart.xml",1279,"game_data"],["bios/mame/hash/ql_cass.xml",1897,"game_data"],["bios/mame/hash/ql_flop.xml",2234,"game_data"],["bios/mame/hash/quizwiz.xml",3091,"game_data"],["bios/mame/hash/qx10_flop.xml",3250,"game_data"],["bios/mame/hash/r8_card.xml",4710,"game_data"],["bios/mame/hash/r9751.xml",10712,"game_data"],["bios/mame/hash/radio86_cart.xml",539,"game_data"],["bios/mame/hash/radio86_cass.xml",36046,"game_data"],["bios/mame/hash/rainbow.xml",10136,"game_data"],["bios/mame/hash/ramstar.xml",6165,"game_data"],["bios/mame/hash/roland_tnsc1.xml",4197,"game_data"],["bios/mame/hash/roland_tnsc2.xml",3332,"game_data"],["bios/mame/hash/rwtrntcs.xml",1090,"game_data"],["bios/mame/hash/rx78_cart.xml",20435,"game_data"],["bios/mame/hash/rx78_cass.xml",1469,"game_data"],["bios/mame/hash/rz1_cass.xml",2687,"game_data"],["bios/mame/hash/s2000_flop.xml",603,"game_data"],["bios/mame/hash/s3000_cdrom.xml",3926,"game_data"],["bios/mame/hash/sagafox.xml",531,"game_data"],["bios/mame/hash/sage2.xml",4188,"game_data"],["bios/mame/hash/saitek_egr.xml",2069,"game_data"],["bios/mame/hash/saitek_kso.xml",1105,"game_data"],["bios/mame/hash/saitek_schess.xml",1334,"game_data"],["bios/mame/hash/samcoupe_cass.xml",1614,"game_data"],["bios/mame/hash/samcoupe_flop.xml",21118,"game_data"],["bios/mame/hash/sat_cart.xml",6332,"game_data"],["bios/mame/hash/sat_vccart.xml",8717,"game_data"],["bios/mame/hash/saturn.xml",1716943,"game_data"],["bios/mame/hash/sawatte.xml",10312,"game_data"],["bios/mame/hash/sb80_flop.xml",2853,"game_data"],["bios/mame/hash/sbrain.xml",525,"game_data"],["bios/mame/hash/sc3000_cart.xml",16483,"game_data"],["bios/mame/hash/sc3000_cass.xml",19145,"game_data"],["bios/mame/hash/scv.xml",15177,"game_data"],["bios/mame/hash/sd132_flop.xml",2596,"game_data"],["bios/mame/hash/sd1_flop.xml",568,"game_data"],["bios/mame/hash/sdk85.xml",1175,"game_data"],["bios/mame/hash/sega_beena_cart.xml",210730,"game_data"],["bios/mame/hash/segaai.xml",34327,"game_data"],["bios/mame/hash/sf7000.xml",10494,"game_data"],["bios/mame/hash/sg1000.xml",118348,"game_data"],["bios/mame/hash/sgi_mips.xml",242357,"game_data"],["bios/mame/hash/sgi_mips_hdd.xml",2337,"game_data"],["bios/mame/hash/sgx.xml",2705,"game_data"],["bios/mame/hash/singingstarkaraoke_cart.xml",1479,"game_data"],["bios/mame/hash/sitcom.xml",6387,"game_data"],["bios/mame/hash/smartcycle_cart.xml",6112,"game_data"],["bios/mame/hash/smarttv_cart.xml",6900,"game_data"],["bios/mame/hash/smc777.xml",71270,"game_data"],["bios/mame/hash/sms.xml",350397,"game_data"],["bios/mame/hash/snes.xml",2841229,"game_data"],["bios/mame/hash/snes_bspack.xml",213194,"game_data"],["bios/mame/hash/snes_strom.xml",8678,"game_data"],["bios/mame/hash/snes_vkun.xml",1383,"game_data"],["bios/mame/hash/snotec.xml",8033,"game_data"],["bios/mame/hash/snread.xml",3415,"game_data"],["bios/mame/hash/snspell.xml",5704,"game_data"],["bios/mame/hash/socrates.xml",4963,"game_data"],["bios/mame/hash/softbox.xml",996,"game_data"],["bios/mame/hash/softwarelist.dtd",2483,"game_data"],["bios/mame/hash/sol20_cass.xml",35251,"game_data"],["bios/mame/hash/sony_news.xml",4134,"game_data"],["bios/mame/hash/sorcerer_cart.xml",7212,"game_data"],["bios/mame/hash/sorcerer_cass.xml",58610,"game_data"],["bios/mame/hash/sorcerer_flop.xml",2033,"game_data"],["bios/mame/hash/spc1000_cass.xml",44923,"game_data"],["bios/mame/hash/spc1500_cass.xml",1620,"game_data"],["bios/mame/hash/special_cass.xml",56426,"game_data"],["bios/mame/hash/special_flop.xml",903,"game_data"],["bios/mame/hash/specnext_sd.xml",1136,"game_data"],["bios/mame/hash/specpls3_flop.xml",813283,"game_data"],["bios/mame/hash/spectrum_betadisc_flop.xml",51683,"game_data"],["bios/mame/hash/spectrum_cart.xml",9023,"game_data"],["bios/mame/hash/spectrum_cass.xml",6897158,"game_data"],["bios/mame/hash/spectrum_flop_opus.xml",30500,"game_data"],["bios/mame/hash/spectrum_mgt_flop.xml",4836,"game_data"],["bios/mame/hash/spectrum_microdrive.xml",28256,"game_data"],["bios/mame/hash/spectrum_wafadrive.xml",701,"game_data"],["bios/mame/hash/sprachmg.xml",4905,"game_data"],["bios/mame/hash/squale_cart.xml",2249,"game_data"],["bios/mame/hash/ssem_quik.xml",4598,"game_data"],["bios/mame/hash/st_cart.xml",3348,"game_data"],["bios/mame/hash/st_flop.xml",210727,"game_data"],["bios/mame/hash/st_flop_demos.xml",3744,"game_data"],["bios/mame/hash/stepone_flop.xml",4628,"game_data"],["bios/mame/hash/studio2.xml",32602,"game_data"],["bios/mame/hash/stv.xml",89130,"game_data"],["bios/mame/hash/sun_sparc.xml",4191,"game_data"],["bios/mame/hash/super6.xml",6296,"game_data"],["bios/mame/hash/super80_cass.xml",102426,"game_data"],["bios/mame/hash/super80_flop.xml",1706,"game_data"],["bios/mame/hash/super_tv_pc_cart.xml",3902,"game_data"],["bios/mame/hash/superpet_flop.xml",13019,"game_data"],["bios/mame/hash/supracan.xml",10722,"game_data"],["bios/mame/hash/sv8000.xml",3267,"game_data"],["bios/mame/hash/svi318_cart.xml",4379,"game_data"],["bios/mame/hash/svi318_cass.xml",86966,"game_data"],["bios/mame/hash/svi318_flop.xml",2959,"game_data"],["bios/mame/hash/svision.xml",29557,"game_data"],["bios/mame/hash/svmu.xml",29673,"game_data"],["bios/mame/hash/t1000.xml",7944,"game_data"],["bios/mame/hash/takara_daigunder_dx_cart.xml",1843,"game_data"],["bios/mame/hash/tandy200.xml",1727,"game_data"],["bios/mame/hash/tandy2k.xml",4874,"game_data"],["bios/mame/hash/tandy6k.xml",4732,"game_data"],["bios/mame/hash/tc4.xml",1582,"game_data"],["bios/mame/hash/tdv2324.xml",3160,"game_data"],["bios/mame/hash/tek4052_cart.xml",2734,"game_data"],["bios/mame/hash/telestory_cart.xml",9328,"game_data"],["bios/mame/hash/teradrive_flop.xml",4861,"game_data"],["bios/mame/hash/teradrive_hdd.xml",954,"game_data"],["bios/mame/hash/tg16.xml",37822,"game_data"],["bios/mame/hash/thinkpad8xx.xml",6558,"game_data"],["bios/mame/hash/ti74_cart.xml",1611,"game_data"],["bios/mame/hash/ti95_cart.xml",1071,"game_data"],["bios/mame/hash/ti99_cart.xml",229953,"game_data"],["bios/mame/hash/tiki100.xml",33003,"game_data"],["bios/mame/hash/timex_cass.xml",53889,"game_data"],["bios/mame/hash/timex_dock.xml",17721,"game_data"],["bios/mame/hash/tmc600_quik.xml",1369,"game_data"],["bios/mame/hash/tntell.xml",2942,"game_data"],["bios/mame/hash/to770_cart.xml",772,"game_data"],["bios/mame/hash/to770a_cart.xml",758,"game_data"],["bios/mame/hash/to7_cart.xml",25832,"game_data"],["bios/mame/hash/to7_cass.xml",305755,"game_data"],["bios/mame/hash/to7_qd.xml",9433,"game_data"],["bios/mame/hash/to8_cass.xml",6669,"game_data"],["bios/mame/hash/to8_qd.xml",3289,"game_data"],["bios/mame/hash/to_flop.xml",545143,"game_data"],["bios/mame/hash/triton_rom.xml",532,"game_data"],["bios/mame/hash/trs80_cass.xml",32516,"game_data"],["bios/mame/hash/trs80_flop.xml",2661,"game_data"],["bios/mame/hash/trs80_quik.xml",40444,"game_data"],["bios/mame/hash/trs80m2.xml",9352,"game_data"],["bios/mame/hash/trsm100.xml",5175,"game_data"],["bios/mame/hash/tsconf.xml",16553,"game_data"],["bios/mame/hash/ttwist_brainquest_cart.xml",682,"game_data"],["bios/mame/hash/turboextreme_cart.xml",607,"game_data"],["bios/mame/hash/tutor.xml",17761,"game_data"],["bios/mame/hash/tvc_cart.xml",5156,"game_data"],["bios/mame/hash/tvc_cass.xml",97888,"game_data"],["bios/mame/hash/tvc_flop.xml",326997,"game_data"],["bios/mame/hash/tvdear.xml",1842,"game_data"],["bios/mame/hash/tvgogo.xml",5603,"game_data"],["bios/mame/hash/tvochken.xml",16440,"game_data"],["bios/mame/hash/tx0_ptp.xml",6329,"game_data"],["bios/mame/hash/u110_card.xml",8800,"game_data"],["bios/mame/hash/unichamp.xml",1778,"game_data"],["bios/mame/hash/ut88.xml",2584,"game_data"],["bios/mame/hash/uzebox.xml",50778,"game_data"],["bios/mame/hash/v1050_flop.xml",4387,"game_data"],["bios/mame/hash/v1050_hdd.xml",1054,"game_data"],["bios/mame/hash/vbaby_cart.xml",4246,"game_data"],["bios/mame/hash/vboy.xml",23269,"game_data"],["bios/mame/hash/vc4000.xml",17828,"game_data"],["bios/mame/hash/vector06_cart.xml",679,"game_data"],["bios/mame/hash/vector06_flop.xml",7730,"game_data"],["bios/mame/hash/vectrex.xml",34697,"game_data"],["bios/mame/hash/vfxsd_flop.xml",994,"game_data"],["bios/mame/hash/vg5k.xml",30437,"game_data"],["bios/mame/hash/vgmplay.xml",19970196,"game_data"],["bios/mame/hash/vic10.xml",13030,"game_data"],["bios/mame/hash/vic1001_cart.xml",159400,"game_data"],["bios/mame/hash/vic1001_cass.xml",1136,"game_data"],["bios/mame/hash/vic1001_flop.xml",3222,"game_data"],["bios/mame/hash/victor9k_flop.xml",1056,"game_data"],["bios/mame/hash/vidbrain.xml",9944,"game_data"],["bios/mame/hash/videoart.xml",3840,"game_data"],["bios/mame/hash/videopac.xml",107901,"game_data"],["bios/mame/hash/vii.xml",903,"game_data"],["bios/mame/hash/vip.xml",981,"game_data"],["bios/mame/hash/vis.xml",61330,"game_data"],["bios/mame/hash/visicom.xml",3074,"game_data"],["bios/mame/hash/vixen.xml",7617,"game_data"],["bios/mame/hash/vsmile_cart.xml",284343,"game_data"],["bios/mame/hash/vsmile_cd.xml",28424,"game_data"],["bios/mame/hash/vsmileb_cart.xml",20217,"game_data"],["bios/mame/hash/vsmilem_cart.xml",84670,"game_data"],["bios/mame/hash/vtech2_cass.xml",2383,"game_data"],["bios/mame/hash/vtech_innotab_cart.xml",10101,"game_data"],["bios/mame/hash/vtech_innotv_cart.xml",2019,"game_data"],["bios/mame/hash/vtech_storio_cart.xml",13859,"game_data"],["bios/mame/hash/vz_cass.xml",8941,"game_data"],["bios/mame/hash/vz_snap.xml",63700,"game_data"],["bios/mame/hash/wangpc.xml",2810,"game_data"],["bios/mame/hash/waveterm.xml",2024,"game_data"],["bios/mame/hash/wicat.xml",10200,"game_data"],["bios/mame/hash/wizard_cart.xml",6438,"game_data"],["bios/mame/hash/wmbullet.xml",1680,"game_data"],["bios/mame/hash/wren_flop.xml",2590,"game_data"],["bios/mame/hash/wscolor.xml",103090,"game_data"],["bios/mame/hash/wswan.xml",145839,"game_data"],["bios/mame/hash/x07_card.xml",698,"game_data"],["bios/mame/hash/x07_cass.xml",51019,"game_data"],["bios/mame/hash/x1_cass.xml",76089,"game_data"],["bios/mame/hash/x1_flop.xml",249940,"game_data"],["bios/mame/hash/x37_flop.xml",6292,"game_data"],["bios/mame/hash/x37_hdd.xml",530,"game_data"],["bios/mame/hash/x68k_flop.xml",1441600,"game_data"],["bios/mame/hash/xegs.xml",23925,"game_data"],["bios/mame/hash/xerox820.xml",5473,"game_data"],["bios/mame/hash/xerox820ii.xml",4778,"game_data"],["bios/mame/hash/yeno_laptop_cart.xml",1742,"game_data"],["bios/mame/hash/z80clock.xml",9043,"game_data"],["bios/mame/hash/z80ne_cass.xml",42440,"game_data"],["bios/mame/hash/z80ne_flop.xml",30301,"game_data"],["bios/mame/hash/z88_cart.xml",24642,"game_data"],["bios/mame/hash/zorba.xml",33048,"game_data"],["bios/mame/hash/zx80_cass.xml",3169,"game_data"],["bios/mame/hash/zx81_cass.xml",474158,"game_data"],["bios/mame/plugins/README.md",88,"game_data"],["bios/mame/plugins/autofire/autofire_menu.lua",11558,"game_data"],["bios/mame/plugins/autofire/autofire_save.lua",2817,"game_data"],["bios/mame/plugins/autofire/init.lua",3223,"game_data"],["bios/mame/plugins/autofire/plugin.json",162,"game_data"],["bios/mame/plugins/boot.lua",990,"game_data"],["bios/mame/plugins/cheat/cheat_json.lua",198,"game_data"],["bios/mame/plugins/cheat/cheat_simple.lua",10784,"game_data"],["bios/mame/plugins/cheat/cheat_xml.lua",7419,"game_data"],["bios/mame/plugins/cheat/init.lua",26494,"game_data"],["bios/mame/plugins/cheat/plugin.json",149,"game_data"],["bios/mame/plugins/cheat/xml_to_json.lua",252,"game_data"],["bios/mame/plugins/cheatfind/init.lua",35221,"game_data"],["bios/mame/plugins/cheatfind/plugin.json",168,"game_data"],["bios/mame/plugins/commonui/init.lua",5312,"game_data"],["bios/mame/plugins/commonui/plugin.json",154,"game_data"],["bios/mame/plugins/console/init.lua",8744,"game_data"],["bios/mame/plugins/console/plugin.json",153,"game_data"],["bios/mame/plugins/data/button_char.lua",7593,"game_data"],["bios/mame/plugins/data/data_command.lua",635,"game_data"],["bios/mame/plugins/data/data_gameinit.lua",466,"game_data"],["bios/mame/plugins/data/data_hiscore.lua",41388,"game_data"],["bios/mame/plugins/data/data_history.lua",5235,"game_data"],["bios/mame/plugins/data/data_mameinfo.lua",908,"game_data"],["bios/mame/plugins/data/data_marp.lua",3763,"game_data"],["bios/mame/plugins/data/data_messinfo.lua",912,"game_data"],["bios/mame/plugins/data/data_story.lua",792,"game_data"],["bios/mame/plugins/data/data_sysinfo.lua",475,"game_data"],["bios/mame/plugins/data/database.lua",3853,"game_data"],["bios/mame/plugins/data/init.lua",1938,"game_data"],["bios/mame/plugins/data/load_dat.lua",6420,"game_data"],["bios/mame/plugins/data/plugin.json",146,"game_data"],["bios/mame/plugins/discord/init.lua",2881,"game_data"],["bios/mame/plugins/discord/plugin.json",155,"game_data"],["bios/mame/plugins/dummy/init.lua",881,"game_data"],["bios/mame/plugins/dummy/plugin.json",167,"game_data"],["bios/mame/plugins/gdbstub/init.lua",7838,"game_data"],["bios/mame/plugins/gdbstub/plugin.json",154,"game_data"],["bios/mame/plugins/hiscore/hiscore.dat",314161,"game_data"],["bios/mame/plugins/hiscore/init.lua",10287,"game_data"],["bios/mame/plugins/hiscore/plugin.json",167,"game_data"],["bios/mame/plugins/hiscore/sort_hiscore.lua",4447,"game_data"],["bios/mame/plugins/inputmacro/init.lua",3797,"game_data"],["bios/mame/plugins/inputmacro/inputmacro_menu.lua",20962,"game_data"],["bios/mame/plugins/inputmacro/inputmacro_persist.lua",3719,"game_data"],["bios/mame/plugins/inputmacro/plugin.json",171,"game_data"],["bios/mame/plugins/json/LICENSE",1079,"game_data"],["bios/mame/plugins/json/README.md",45,"game_data"],["bios/mame/plugins/json/init.lua",21505,"game_data"],["bios/mame/plugins/json/plugin.json",136,"game_data"],["bios/mame/plugins/keypress/init.lua",1162,"game_data"],["bios/mame/plugins/keypress/plugin.json",195,"game_data"],["bios/mame/plugins/layout/init.lua",2376,"game_data"],["bios/mame/plugins/layout/plugin.json",157,"game_data"],["bios/mame/plugins/offscreenreload/init.lua",2415,"game_data"],["bios/mame/plugins/offscreenreload/offscreenreload_menu.lua",11498,"game_data"],["bios/mame/plugins/offscreenreload/offscreenreload_persist.lua",3471,"game_data"],["bios/mame/plugins/offscreenreload/plugin.json",189,"game_data"],["bios/mame/plugins/plugin.schema",655,"game_data"],["bios/mame/plugins/portname/init.lua",5173,"game_data"],["bios/mame/plugins/portname/plugin.json",170,"game_data"],["bios/mame/plugins/timecode/init.lua",11542,"game_data"],["bios/mame/plugins/timecode/plugin.json",175,"game_data"],["bios/mame/plugins/timer/init.lua",2359,"game_data"],["bios/mame/plugins/timer/plugin.json",161,"game_data"],["bios/mame/plugins/timer/timer_persist.lua",7109,"game_data"],["bios/mame/plugins/vector/init.lua",1443,"game_data"],["bios/mame/plugins/vector/plugin.json",182,"game_data"],["bios/mame/plugins/xml/LICENSE.txt",1061,"game_data"],["bios/mame/plugins/xml/init.lua",12842,"game_data"],["bios/mame/plugins/xml/plugin.json",146,"game_data"],["bios/mame/samples/bbc.zip",8469,"game_data"],["bios/mame/samples/floppy/35_seek_12ms.wav",26540,"game_data"],["bios/mame/samples/floppy/35_seek_20ms.wav",44144,"game_data"],["bios/mame/samples/floppy/35_seek_2ms.wav",7450,"game_data"],["bios/mame/samples/floppy/35_seek_6ms.wav",22230,"game_data"],["bios/mame/samples/floppy/35_spin_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_end.wav",17684,"game_data"],["bios/mame/samples/floppy/35_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_loaded.wav",35308,"game_data"],["bios/mame/samples/floppy/35_step_1_1.wav",6878,"game_data"],["bios/mame/samples/floppy/525_seek_12ms.wav",22764,"game_data"],["bios/mame/samples/floppy/525_seek_20ms.wav",30060,"game_data"],["bios/mame/samples/floppy/525_seek_6ms.wav",14860,"game_data"],["bios/mame/samples/floppy/525_spin_empty.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_end.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_spin_start_empty.wav",11180,"game_data"],["bios/mame/samples/floppy/525_spin_start_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_step_1_1.wav",6628,"game_data"],["bios/maxaflex.zip",13673,"bios"],["bios/mc1502_rom.zip",25819,"bios"],["bios/mc_mk4_hopper.zip",791,"bios"],["bios/mcpx_1.0.bin",512,"bios"],["bios/mcpx_apu.zip",629,"bios"],["bios/mcx128.zip",28343,"bios"],["bios/md_jcart.zip",95467,"bios"],["bios/md_kbd.zip",1044,"bios"],["bios/md_rom_svp.zip",1263,"bios"],["bios/md_seprom_codemast.zip",95467,"bios"],["bios/md_seprom_mm96.zip",95467,"bios"],["bios/mdisplay2.zip",965,"bios"],["bios/mdisplay3.zip",14234,"bios"],["bios/mediagx_cs5530_ide.zip",1151601,"bios"],["bios/megadrive_ar.zip",37759,"bios"],["bios/megadrive_rom_jcart_micromac2.zip",95467,"bios"],["bios/megadrive_rom_jcart_micromac96.zip",95467,"bios"],["bios/megadrive_rom_jcart_sampras.zip",95467,"bios"],["bios/megadrive_rom_jcart_sskid.zip",95467,"bios"],["bios/megaplay.zip",49978,"bios"],["bios/megatech.zip",24831,"bios"],["bios/mg1_kbd_device.zip",740,"bios"],["bios/mga2064w.zip",86678,"bios"],["bios/microtan_kbd_mt009.zip",376,"bios"],["bios/microtouch.zip",41890,"bios"],["bios/midcsd.zip",222,"bios"],["bios/midssio.zip",163,"bios"],["bios/mie.zip",725,"bios"],["bios/mindset_rs232_module.zip",95177,"bios"],["bios/mindset_sound_module.zip",1102,"bios"],["bios/minichif.zip",22917,"bios"],["bios/miuchiz.zip",7286,"bios"],["bios/mks3.zip",2351,"bios"],["bios/mm1kb.zip",499,"bios"],["bios/mm5740.zip",212,"bios"],["bios/mockingboardd.zip",1861,"bios"],["bios/model1io.zip",4700,"bios"],["bios/model1io2.zip",113112,"bios"],["bios/mpcb828.zip",3690,"bios"],["bios/mpcb849.zip",3567,"bios"],["bios/mpcb896.zip",168,"bios"],["bios/mpcb963.zip",164,"bios"],["bios/mpcba79.zip",168,"bios"],["bios/mpcbb68.zip",3163,"bios"],["bios/mpcbb92.zip",3163,"bios"],["bios/mpeg_card.bin",524288,"bios"],["bios/mpf1_epb.zip",1497,"bios"],["bios/mpf1_epb_ibp.zip",2667,"bios"],["bios/mpf1_iom_ip.zip",96299,"bios"],["bios/mpf1_prt.zip",2971,"bios"],["bios/mpf1_prt_ip.zip",2760,"bios"],["bios/mpf1_sgb.zip",2402,"bios"],["bios/mpf1_ssb.zip",3448,"bios"],["bios/mpf1_ssb_ip.zip",4164,"bios"],["bios/mpf1_tva_ip.zip",1790,"bios"],["bios/mpf1_vid.zip",2320,"bios"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18100.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/mps1200.zip",21255,"bios"],["bios/mps1250.zip",26948,"bios"],["bios/mpu401.zip",3573,"bios"],["bios/mpu_pc98.zip",3573,"bios"],["bios/mr9735_002.zip",542,"bios"],["bios/ms7004.zip",1446,"bios"],["bios/msdsd1.zip",11813,"bios"],["bios/msdsd2.zip",12220,"bios"],["bios/mshark.zip",109067,"bios"],["bios/msm6222b01.zip",972,"bios"],["bios/msmt070.zip",202,"bios"],["bios/msmt071.zip",170,"bios"],["bios/msmt081.zip",170,"bios"],["bios/msmt094.zip",113806,"bios"],["bios/msx_cart_bm_012.zip",5300,"bios"],["bios/msx_cart_easispeech.zip",2011,"bios"],["bios/msx_cart_fmpac.zip",313,"bios"],["bios/msx_cart_gouda_scsi.zip",778041,"bios"],["bios/msx_cart_mega_scsi.zip",778041,"bios"],["bios/msx_cart_sfg01.zip",10912,"bios"],["bios/msx_cart_sfg05.zip",69473,"bios"],["bios/msx_cart_skw01.zip",591507,"bios"],["bios/msx_cart_slotexpander.zip",3909365,"bios"],["bios/msx_cart_sunrise_ataide.zip",1309918,"bios"],["bios/msx_cart_ucn01.zip",671804,"bios"],["bios/msx_moonsound.zip",1922475,"bios"],["bios/msx_segactrl.zip",95467,"bios"],["bios/msx_slot_rs232.zip",95177,"bios"],["bios/msx_slot_rs232_mitsubishi.zip",95177,"bios"],["bios/msx_slot_rs232_sony.zip",95177,"bios"],["bios/msx_slot_rs232_svi738.zip",95177,"bios"],["bios/msx_slot_rs232_toshiba.zip",95177,"bios"],["bios/msx_slot_rs232_toshiba_hx3x.zip",95177,"bios"],["bios/mtx_cfx.zip",1206105,"bios"],["bios/mtx_sdxbas.zip",10404,"bios"],["bios/mtx_sdxcpm.zip",4710,"bios"],["bios/mu5lcd.zip",12098,"bios"],["bios/mulcd.zip",40392,"bios"],["bios/mvme120.zip",142638,"bios"],["bios/mvme121.zip",142638,"bios"],["bios/mvme122.zip",142638,"bios"],["bios/mvme123.zip",142638,"bios"],["bios/mvme147.zip",347124,"bios"],["bios/mvme180.zip",191443,"bios"],["bios/mvme181.zip",222873,"bios"],["bios/mvme187.zip",317218,"bios"],["bios/mvme327a.zip",39770,"bios"],["bios/mvme328.zip",47299,"bios"],["bios/mvme350.zip",8228,"bios"],["bios/mx1600bas.rom",8192,"bios"],["bios/mx1600extbas.rom",8192,"bios"],["bios/mz1e30.zip",13614,"bios"],["bios/mz1p16.zip",3679,"bios"],["bios/mzr8105.zip",10272,"bios"],["bios/mzr8300.zip",95177,"bios"],["bios/n88.rom",32768,"bios"],["bios/n88_0.rom",8192,"bios"],["bios/n88_1.rom",8192,"bios"],["bios/n88_2.rom",8192,"bios"],["bios/n88_3.rom",8192,"bios"],["bios/n88knj1.rom",131072,"bios"],["bios/n88n.rom",32768,"bios"],["bios/nabupc_keyboard.zip",1348,"bios"],["bios/nabupc_option_rs232.zip",95177,"bios"],["bios/namco50.zip",898,"bios"],["bios/namco51.zip",716,"bios"],["bios/namco52.zip",389,"bios"],["bios/namco53.zip",675,"bios"],["bios/namco54.zip",592,"bios"],["bios/namco62.zip",645,"bios"],["bios/namco_amc.zip",130552,"bios"],["bios/namco_asca1.zip",130552,"bios"],["bios/namco_asca3.zip",130552,"bios"],["bios/namco_asca3a.zip",130552,"bios"],["bios/namco_asca5.zip",130552,"bios"],["bios/namco_csz1.zip",130599,"bios"],["bios/namco_cyberlead.zip",130552,"bios"],["bios/namco_cyberlead_led.zip",80055,"bios"],["bios/namco_cyberleada.zip",130552,"bios"],["bios/namco_de_pcb.zip",1721,"bios"],["bios/namco_emio102.zip",130552,"bios"],["bios/namco_empri101.zip",130552,"bios"],["bios/namco_fca10.zip",130552,"bios"],["bios/namco_fca11.zip",130552,"bios"],["bios/namco_fcb.zip",130552,"bios"],["bios/namco_tssio.zip",130552,"bios"],["bios/namco_xmiu1.zip",130552,"bios"],["bios/namcoc65.zip",2163,"bios"],["bios/namcoc67.zip",6552,"bios"],["bios/namcoc68.zip",1721,"bios"],["bios/namcoc69.zip",7771,"bios"],["bios/namcoc70.zip",7822,"bios"],["bios/namcoc71.zip",2756,"bios"],["bios/namcoc74.zip",6936,"bios"],["bios/namcoc75.zip",8709,"bios"],["bios/namcoc76.zip",9579,"bios"],["bios/namcos21_dsp_c67_device.zip",6552,"bios"],["bios/nand/private/movable.sed",320,"bios"],["bios/nand/rw/sys/LocalFriendCodeSeed_B",272,"bios"],["bios/nand/rw/sys/SecureInfo_A",273,"bios"],["bios/nanoreseau_mo.zip",1937,"bios"],["bios/nanoreseau_to.zip",1970,"bios"],["bios/naomi.zip",9321533,"bios"],["bios/naomi2.zip",7022501,"bios"],["bios/naomigd.zip",3371765,"bios"],["bios/nb_aenet.zip",400,"bios"],["bios/nb_amc3b.zip",417,"bios"],["bios/nb_btbug.zip",91614,"bios"],["bios/nb_c264.zip",6489,"bios"],["bios/nb_image.zip",1832,"bios"],["bios/nb_laserview.zip",4885,"bios"],["bios/nb_m2hr.zip",3538,"bios"],["bios/nb_m2vc.zip",2106,"bios"],["bios/nb_mdc48.zip",6576,"bios"],["bios/nb_mdc824.zip",7883,"bios"],["bios/nb_pcs8.zip",9570,"bios"],["bios/nb_qdlink.zip",3316,"bios"],["bios/nb_rtpd.zip",1828,"bios"],["bios/nb_sp8s3.zip",23241,"bios"],["bios/nb_spdq.zip",39282,"bios"],["bios/nb_thungx.zip",18290,"bios"],["bios/nb_thungx16.zip",18318,"bios"],["bios/nb_vikbw.zip",2162,"bios"],["bios/nb_wkstn.zip",2715,"bios"],["bios/nb_wspt.zip",2646,"bios"],["bios/ncr53c825_pci.zip",10043,"bios"],["bios/neocd.bin",524288,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/neocd_f.rom",524288,"bios"],["bios/neocd_sf.rom",524288,"bios"],["bios/neocd_st.rom",524288,"bios"],["bios/neocd_sz.rom",524288,"bios"],["bios/neocd_t.rom",524288,"bios"],["bios/neocd_z.rom",524288,"bios"],["bios/neocdz.zip",598775,"bios"],["bios/neogeo.zip",1859335,"bios"],["bios/neon250.zip",20999,"bios"],["bios/nes_rob.zip",637,"bios"],["bios/nes_vrc7.zip",313,"bios"],["bios/newbrain_eim.zip",128088,"bios"],["bios/newbrain_fdc.zip",128088,"bios"],["bios/ngp.zip",65536,"bios"],["bios/ngpc.zip",65536,"bios"],["bios/nichidvd.zip",49667,"bios"],["bios/nlq401.zip",7554,"bios"],["bios/nmk004.zip",3556,"bios"],["bios/nms8250_basic-bios2.rom",32768,"bios"],["bios/nms8250_disk.rom",16384,"bios"],["bios/nms8250_msx2sub.rom",16384,"bios"],["bios/nokia_crtc186.zip",5203,"bios"],["bios/novell_dcb.zip",3425,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/np600a3.zip",8089,"bios"],["bios/nss.zip",50536,"bios"],["bios/nss_tvinterface.zip",11169,"bios"],["bios/number_9_rev.zip",367,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/ohare.zip",95177,"bios"],["bios/omniwave.zip",880710,"bios"],["bios/omti8621isa.zip",13582,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/orch90.rom",8192,"bios"],["bios/oric_jasmin.zip",471,"bios"],["bios/oric_microdisc.zip",3254,"bios"],["bios/osa_analyst.zip",348004,"bios"],["bios/osa_bforce.zip",26799,"bios"],["bios/osa_maestro.zip",324479,"bios"],["bios/osa_maestroa.zip",47396,"bios"],["bios/osa_sparc.zip",348745,"bios"],["bios/oti64111_pci.zip",19135,"bios"],["bios/otp.bin",1024,"bios"],["bios/p1_fdc.zip",6158,"bios"],["bios/p1_hdc.zip",6372,"bios"],["bios/p1_rom.zip",5821,"bios"],["bios/p72.zip",351169,"bios"],["bios/pa7234.zip",63947,"bios"],["bios/pa7246.zip",63947,"bios"],["bios/paddington.zip",95177,"bios"],["bios/palmos40-en-m500.rom",2359296,"bios"],["bios/palmos41-en-m515.rom",4194304,"bios"],["bios/palmos52-en-t3.rom",16777216,"bios"],["bios/palmos60-en-t3.rom",16777216,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/partner_gdp.zip",1917,"bios"],["bios/pc1512kb.zip",733,"bios"],["bios/pc1640_iga.zip",8824,"bios"],["bios/pc6022.zip",3694,"bios"],["bios/pc80s31.zip",3242,"bios"],["bios/pc80s31k.zip",7153,"bios"],["bios/pc87306.zip",479847,"bios"],["bios/pc8801_23.zip",7609,"bios"],["bios/pc88va2_fd_if.zip",3891,"bios"],["bios/pc97338.zip",479847,"bios"],["bios/pc9801_118.zip",7609,"bios"],["bios/pc9801_14.zip",5571,"bios"],["bios/pc9801_26.zip",132073,"bios"],["bios/pc9801_27.zip",2700,"bios"],["bios/pc9801_55l.zip",4654,"bios"],["bios/pc9801_55u.zip",4653,"bios"],["bios/pc9801_86.zip",125153,"bios"],["bios/pc98_fdd_2dd.zip",1959,"bios"],["bios/pc98_fdd_2hd.zip",2702,"bios"],["bios/pc98_otomichan_kai.zip",116066,"bios"],["bios/pc_lpt.zip",479847,"bios"],["bios/pcd_kbd.zip",2572,"bios"],["bios/pcd_video.zip",612,"bios"],["bios/pce_multitap.zip",95467,"bios"],["bios/pce_xhe3.zip",95467,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/pcfxbios.bin",1048576,"bios"],["bios/pcfxga.rom",1048576,"bios"],["bios/pcfxv101.bin",1048576,"bios"],["bios/pcx_video.zip",8874,"bios"],["bios/pd32.zip",998,"bios"],["bios/pd3_30hr.zip",4685,"bios"],["bios/pd3_30hrint.zip",4685,"bios"],["bios/pd3_c264.zip",5773,"bios"],["bios/pd3_lviw.zip",4760,"bios"],["bios/pd3_mclr.zip",4568,"bios"],["bios/pd3_mclrint.zip",4568,"bios"],["bios/pd3_pc16.zip",8246,"bios"],["bios/pd3_pcs8.zip",9552,"bios"],["bios/pdc20262.zip",1165916,"bios"],["bios/pdc20268.zip",9340,"bios"],["bios/pds30_emac.zip",346,"bios"],["bios/pds_hyper.zip",3836,"bios"],["bios/pds_sefp.zip",14387,"bios"],["bios/pdslc_macconlc.zip",419,"bios"],["bios/pencil2_coleco.zip",5795,"bios"],["bios/peribox.zip",2106147,"bios"],["bios/peribox_ev.zip",2106147,"bios"],["bios/peribox_ev1.zip",2106147,"bios"],["bios/peribox_gen.zip",2106147,"bios"],["bios/peribox_genmod.zip",2106147,"bios"],["bios/peribox_sg.zip",2106147,"bios"],["bios/permedia2.zip",138948,"bios"],["bios/pet_softbox.zip",104992,"bios"],["bios/pet_superpet.zip",110907,"bios"],["bios/pg200.zip",549,"bios"],["bios/pgm.zip",2094614,"bios"],["bios/phc-70fd2_basickun.rom",16384,"bios"],["bios/philips__cdi-220_ph3_r1.2__mb834200b-15__02f_aa__9402_z04.tc574200-le._1.7211",524288,"bios"],["bios/pico-8/pico8",9377000,"bios"],["bios/pico-8/pico8.dat",17721245,"bios"],["bios/pico-8/pico8_dyn",1761480,"bios"],["bios/pl6_fpga.zip",95177,"bios"],["bios/playch10.zip",23388,"bios"],["bios/plg100_vl.zip",333318,"bios"],["bios/plg150_ap.zip",11733949,"bios"],["bios/plus2-0.rom",16384,"bios"],["bios/plus2-1.rom",16384,"bios"],["bios/plus3-0.rom",16384,"bios"],["bios/plus3-1.rom",16384,"bios"],["bios/plus3-2.rom",16384,"bios"],["bios/plus3-3.rom",16384,"bios"],["bios/plus3e-0.rom",16384,"bios"],["bios/plus3e-1.rom",16384,"bios"],["bios/plus3e-2.rom",16384,"bios"],["bios/plus3e-3.rom",16384,"bios"],["bios/plusd.rom",8192,"bios"],["bios/plutonia.wad",17420824,"game_data"],["bios/pofo_hpc101.zip",479847,"bios"],["bios/pofo_hpc102.zip",95177,"bios"],["bios/pofo_hpc104.zip",574980,"bios"],["bios/pofo_hpc104_2.zip",574980,"bios"],["bios/polyvti.zip",859,"bios"],["bios/popira.zip",654918,"bios"],["bios/popira2.zip",1124630,"bios"],["bios/popirak.zip",639838,"bios"],["bios/ppge_atlas.zim",666530,"bios"],["bios/pr8210.zip",2012,"bios"],["bios/prav8ckb.zip",1204,"bios"],["bios/prboom.wad",143312,"bios"],["bios/premier_fdc.zip",6765,"bios"],["bios/profighterq.zip",62808,"bios"],["bios/profighterqa.zip",62747,"bios"],["bios/profighterqb.zip",62747,"bios"],["bios/profighterx.zip",62764,"bios"],["bios/promotion3210.zip",18077,"bios"],["bios/ps1_rom.bin",524288,"bios"],["bios/ps2-0100j-20000117.bin",4194304,"bios"],["bios/ps2-0100jd-20000117.bin",4194304,"bios"],["bios/ps2-0101j-20000217.bin",4194304,"bios"],["bios/ps2-0101jd-20000217.bin",4194304,"bios"],["bios/ps2-0101xd-20000224.bin",4194304,"bios"],["bios/ps2-0110a-20000727.bin",4194304,"bios"],["bios/ps2-0110ad-20000727.bin",4194304,"bios"],["bios/ps2-0120a-20000902.bin",4194304,"bios"],["bios/ps2-0120e-20000902.bin",4194304,"bios"],["bios/ps2-0120ed-20000902-20030110.bin",4194304,"bios"],["bios/ps2-0120ed-20000902.bin",4194304,"bios"],["bios/ps2-0120j-20001027-185015.bin",4194304,"bios"],["bios/ps2-0120j-20001027-191435.bin",4194304,"bios"],["bios/ps2-0150a-20001228.bin",4194304,"bios"],["bios/ps2-0150ad-20001228-20030520.bin",4194304,"bios"],["bios/ps2-0150e-20001228.bin",4194304,"bios"],["bios/ps2-0150ed-20001228-20030520.bin",4194304,"bios"],["bios/ps2-0150j-20010118.bin",4194304,"bios"],["bios/ps2-0150jd-20010118.bin",4194304,"bios"],["bios/ps2-0160a-20010427.bin",4194304,"bios"],["bios/ps2-0160a-20010704.bin",4194304,"bios"],["bios/ps2-0160a-20011004.bin",4194304,"bios"],["bios/ps2-0160a-20020207.bin",4194304,"bios"],["bios/ps2-0160e-20010704.bin",4194304,"bios"],["bios/ps2-0160e-20011004.bin",4194304,"bios"],["bios/ps2-0160e-20020319.bin",4194304,"bios"],["bios/ps2-0160e-20020426.bin",4194304,"bios"],["bios/ps2-0160h-20010730.bin",4194304,"bios"],["bios/ps2-0160h-20020426.bin",4194304,"bios"],["bios/ps2-0160h-20030602.bin",4194304,"bios"],["bios/ps2-0160j-20010427.bin",4194304,"bios"],["bios/ps2-0160j-20011004.bin",4194304,"bios"],["bios/ps2-0160j-20020426.bin",4194304,"bios"],["bios/ps2-0170a-20030325.bin",4194304,"bios"],["bios/ps2-0170ad-20030325.bin",4194304,"bios"],["bios/ps2-0170e-20030227.bin",4194304,"bios"],["bios/ps2-0170ed-20030227.bin",4194304,"bios"],["bios/ps2-0170j-20030206.bin",4194304,"bios"],["bios/ps2-0170jd-20030206.bin",4194304,"bios"],["bios/ps2-0180cd-20030224.bin",4194304,"bios"],["bios/ps2-0180j-20031028.bin",4194304,"bios"],["bios/ps2-0190a-20030623.bin",4194304,"bios"],["bios/ps2-0190a-20040329.bin",4194304,"bios"],["bios/ps2-0190ad-20030623.bin",4194304,"bios"],["bios/ps2-0190c-20030623.bin",4194304,"bios"],["bios/ps2-0190cd-20030623.bin",4194304,"bios"],["bios/ps2-0190e-20030623.bin",4194304,"bios"],["bios/ps2-0190e-20030822.bin",4194304,"bios"],["bios/ps2-0190h-20030623.bin",4194304,"bios"],["bios/ps2-0190j-20030623.bin",4194304,"bios"],["bios/ps2-0190j-20030822.bin",4194304,"bios"],["bios/ps2-0190k-20030623.bin",4194304,"bios"],["bios/ps2-0190r-20030623.bin",4194304,"bios"],["bios/ps2-0200a-20040614.bin",4194304,"bios"],["bios/ps2-0200ad-20040614.bin",4194304,"bios"],["bios/ps2-0200e-20040614.bin",4194304,"bios"],["bios/ps2-0200ed-20040614.bin",4194304,"bios"],["bios/ps2-0200h-20040614.bin",4194304,"bios"],["bios/ps2-0200j-20040614.bin",4194304,"bios"],["bios/ps2-0210j-20040917.bin",4194304,"bios"],["bios/ps2-0220a-20050620.bin",4194304,"bios"],["bios/ps2-0220a-20060210.bin",4194304,"bios"],["bios/ps2-0220a-20060905.bin",4194304,"bios"],["bios/ps2-0220ad-20050620.bin",4194304,"bios"],["bios/ps2-0220ad-20060905.bin",4194304,"bios"],["bios/ps2-0220e-20050620.bin",4194304,"bios"],["bios/ps2-0220e-20060210.bin",4194304,"bios"],["bios/ps2-0220e-20060905.bin",4194304,"bios"],["bios/ps2-0220h-20050620.bin",4194304,"bios"],["bios/ps2-0220h-20060210.bin",4194304,"bios"],["bios/ps2-0220h-20060905.bin",4194304,"bios"],["bios/ps2-0220j-20050620.bin",4194304,"bios"],["bios/ps2-0220j-20060210.bin",4194304,"bios"],["bios/ps2-0220j-20060905.bin",4194304,"bios"],["bios/ps2-0220jd-20050620.bin",4194304,"bios"],["bios/ps2-0220jd-20060905.bin",4194304,"bios"],["bios/ps2-0230a-20080220.bin",4194304,"bios"],["bios/ps2-0230a-20080220.nvm",1024,"bios"],["bios/ps2-0230e-20080220.bin",4194304,"bios"],["bios/ps2-0230h-20080220.bin",4194304,"bios"],["bios/ps2-0230j-20080220.bin",4194304,"bios"],["bios/ps2-0250e-20100415.bin",4194304,"bios"],["bios/ps2-0250j-20100415.bin",4194304,"bios"],["bios/ps2-dvd-300e.bin",4194304,"bios"],["bios/ps2-dvd-300u.bin",4194304,"bios"],["bios/ps2-dvd-302c.bin",4194304,"bios"],["bios/ps2-dvd-302e.bin",4194304,"bios"],["bios/ps2-dvd-302u.bin",4194304,"bios"],["bios/ps2-dvd-310.bin",4194304,"bios"],["bios/ps2-dvd-311.bin",4194304,"bios"],["bios/ps2_keybc.zip",3537,"bios"],["bios/ps2_scph50006.bin",4194304,"bios"],["bios/ps2_scph50008.bin",4194304,"bios"],["bios/psion_3fax.zip",394842,"bios"],["bios/psion_3link_par.zip",479847,"bios"],["bios/psion_3link_ser.zip",145742,"bios"],["bios/psion_parallel.zip",479847,"bios"],["bios/psion_pclink.zip",95177,"bios"],["bios/psion_serpar.zip",574980,"bios"],["bios/psion_siena_ssd.zip",574980,"bios"],["bios/psvita/PSP2UPDAT.PUP",56778752,"bios"],["bios/psvita/PSVUPDAT.PUP",133834240,"bios"],["bios/psx_cd.zip",222667,"bios"],["bios/psxgboost.zip",179516,"bios"],["bios/psxonpsp660.bin",524288,"bios"],["bios/pumpitup.zip",7985810,"bios"],["bios/pvga1a.zip",65692,"bios"],["bios/pvga1a_jk.zip",103539,"bios"],["bios/px320a.zip",1092458,"bios"],["bios/qg640.zip",75366,"bios"],["bios/ql_cumanafdi.zip",16173,"bios"],["bios/ql_gold.zip",66339,"bios"],["bios/ql_kdi.zip",6387,"bios"],["bios/ql_mhd.zip",5988,"bios"],["bios/ql_mpfdi.zip",5067,"bios"],["bios/ql_opdbm.zip",27486,"bios"],["bios/ql_pcmlqdi.zip",10237,"bios"],["bios/ql_qldisc.zip",13083,"bios"],["bios/ql_qplus4.zip",1997923,"bios"],["bios/ql_qubide.zip",1182071,"bios"],["bios/ql_sdisk.zip",488706,"bios"],["bios/ql_sqboard256.zip",541045,"bios"],["bios/ql_sqboard512.zip",541045,"bios"],["bios/ql_sqmouse.zip",541045,"bios"],["bios/ql_sqmouse512.zip",541045,"bios"],["bios/ql_trump.zip",121019,"bios"],["bios/ql_trump256.zip",121019,"bios"],["bios/ql_trump512.zip",121019,"bios"],["bios/ql_trump768.zip",121019,"bios"],["bios/qsound.zip",2654,"bios"],["bios/qsound_hle.zip",2676,"bios"],["bios/qts1.zip",898304,"bios"],["bios/quadro.zip",51307,"bios"],["bios/quasi88/font.rom",2048,"bios"],["bios/quasi88/font2.rom",2048,"bios"],["bios/quasi88/font3.rom",2048,"bios"],["bios/quasi88/n88.rom",32768,"bios"],["bios/quasi88/n88_0.rom",8192,"bios"],["bios/quasi88/n88_1.rom",8192,"bios"],["bios/quasi88/n88_2.rom",8192,"bios"],["bios/quasi88/n88_3.rom",8192,"bios"],["bios/quasi88/n88jisho.rom",524288,"bios"],["bios/quasi88/n88knj1.rom",131072,"bios"],["bios/quasi88/n88knj2.rom",131072,"bios"],["bios/quasi88/n88n.rom",32768,"bios"],["bios/quasi88/n88sub.rom",2048,"bios"],["bios/quoth/pak0.pak",48226771,"game_data"],["bios/quoth/pak1.pak",84961704,"game_data"],["bios/quoth/pak2.pak",8021749,"game_data"],["bios/qvision_wavestar.zip",4834,"bios"],["bios/qx10_keyboard_ascii.zip",963,"bios"],["bios/qx10_keyboard_hasci.zip",963,"bios"],["bios/racedriv_board.zip",95177,"bios"],["bios/racedrivb1_board.zip",95177,"bios"],["bios/racedrivc1_board.zip",95177,"bios"],["bios/racedrivc_board.zip",95177,"bios"],["bios/racedrivc_panorama_side_board.zip",95177,"bios"],["bios/rageiidvd.zip",74874,"bios"],["bios/rc2014_82c55_ide.zip",1151601,"bios"],["bios/rc2014_dual_serial.zip",95177,"bios"],["bios/rc2014_dual_serial_40p.zip",95177,"bios"],["bios/rc2014_ide_hdd.zip",1151601,"bios"],["bios/rc2014_micro.zip",107725,"bios"],["bios/rc2014_mini_cpm.zip",3885695,"bios"],["bios/rc2014_pagable_rom.zip",34021,"bios"],["bios/rc2014_rom_ram_512k.zip",2572870,"bios"],["bios/rc2014_sc106.zip",4617504,"bios"],["bios/rc2014_sc107.zip",4617504,"bios"],["bios/rc2014_sc111.zip",95177,"bios"],["bios/rc2014_sc113.zip",4617504,"bios"],["bios/rc2014_sc141.zip",3861903,"bios"],["bios/rc2014_sc147.zip",3861903,"bios"],["bios/rc2014_serial_io.zip",95177,"bios"],["bios/rc2014_switchable_rom.zip",42387,"bios"],["bios/recel.zip",2156,"bios"],["bios/resources/sharedFonts/CafeCn.ttf",9664448,"bios"],["bios/resources/sharedFonts/CafeKr.ttf",5626464,"bios"],["bios/resources/sharedFonts/CafeStd.ttf",5363768,"bios"],["bios/resources/sharedFonts/CafeTw.ttf",6593548,"bios"],["bios/rf57_932.zip",95177,"bios"],["bios/riva128.zip",60632,"bios"],["bios/riva128zx.zip",59311,"bios"],["bios/rivatnt.zip",82626,"bios"],["bios/rivatnt2.zip",46394,"bios"],["bios/rivatnt2_m64.zip",272160,"bios"],["bios/rivatnt2_ultra.zip",24007,"bios"],["bios/rm_mq2.zip",6064,"bios"],["bios/robotron_k7070.zip",110597,"bios"],["bios/robotron_k7071.zip",4152,"bios"],["bios/rolm_pdc.zip",8595,"bios"],["bios/rolm_smioc.zip",101325,"bios"],["bios/rom.db",17742,"bios"],["bios/rom.key",2069,"bios"],["bios/rotwb.wad",20592999,"game_data"],["bios/rs232_patch_box.zip",95177,"bios"],["bios/rt1000b.zip",5852,"bios"],["bios/rtpc_kbd.zip",1918,"bios"],["bios/rtpc_kls.zip",5044,"bios"],["bios/rx01.zip",2846,"bios"],["bios/s100_am310.zip",96441,"bios"],["bios/s100_djdma.zip",3777,"bios"],["bios/s100_nsmdsa.zip",396,"bios"],["bios/s100_nsmdsad.zip",334,"bios"],["bios/s100_sj2db.zip",1012,"bios"],["bios/s100_wunderbus.zip",95177,"bios"],["bios/s1410.zip",11050,"bios"],["bios/s3_764.zip",18299,"bios"],["bios/s8k_cpu.zip",31998,"bios"],["bios/s8k_cpu10.zip",6294,"bios"],["bios/s8k_hpcpu.zip",11518,"bios"],["bios/s97269pb.zip",566,"bios"],["bios/s97801_device.zip",8720,"bios"],["bios/s97801_kbd.zip",1772,"bios"],["bios/s_smp.zip",209,"bios"],["bios/saa5050.zip",536,"bios"],["bios/saa5051.zip",522,"bios"],["bios/saa5052.zip",514,"bios"],["bios/saa5053.zip",519,"bios"],["bios/saa5054.zip",511,"bios"],["bios/saa5055.zip",525,"bios"],["bios/saa5056.zip",535,"bios"],["bios/saa5057.zip",523,"bios"],["bios/saa5240a.zip",1015,"bios"],["bios/saa5240b.zip",978,"bios"],["bios/saa5243e.zip",1297,"bios"],["bios/sad8852.zip",4434,"bios"],["bios/sam_atom_hdd.zip",1151601,"bios"],["bios/sam_sdide.zip",1151601,"bios"],["bios/sambus.zip",1633379,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sammymdl.zip",24090,"bios"],["bios/samples/bbc.zip",8469,"game_data"],["bios/sanyotry.bin",1048576,"bios"],["bios/satar4mp.bin",262144,"bios"],["bios/satcdb.zip",101309,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/sb16.zip",8003,"bios"],["bios/sb300p.zip",1591,"bios"],["bios/sbus_hme.zip",17450,"bios"],["bios/sbus_sunpc.zip",536,"bios"],["bios/sc119.zip",721668,"bios"],["bios/scorpion_ic.zip",18332,"bios"],["bios/scph100.bin",524288,"bios"],["bios/scph1000.bin",524288,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph1002.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph102A.bin",524288,"bios"],["bios/scph102B.bin",524288,"bios"],["bios/scph102C.bin",524288,"bios"],["bios/scph3000.bin",524288,"bios"],["bios/scph30004fr.nvm",1024,"bios"],["bios/scph3500.bin",524288,"bios"],["bios/scph39001.nvm",1024,"bios"],["bios/scph5000.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/scph7002.bin",524288,"bios"],["bios/scph7003.bin",524288,"bios"],["bios/scph7502.bin",524288,"bios"],["bios/scph9002(7502).bin",524288,"bios"],["bios/scsidma.zip",778041,"bios"],["bios/scummvm.zip",79379908,"bios"],["bios/scummvm/extra/CM32L_CONTROL.ROM",65536,"bios"],["bios/scummvm/extra/CM32L_PCM.ROM",1048576,"bios"],["bios/scummvm/extra/MT32_CONTROL.ROM",65536,"bios"],["bios/scummvm/extra/MT32_PCM.ROM",524288,"bios"],["bios/scv.zip",4073,"bios"],["bios/sdbdos.rom",65536,"bios"],["bios/sdose6.rom",8192,"bios"],["bios/sdose8.rom",8192,"bios"],["bios/sdtandy_fdc.zip",7109,"bios"],["bios/se-0.rom",16384,"bios"],["bios/se-1.rom",16384,"bios"],["bios/sed1200da.zip",749,"bios"],["bios/sed1200db.zip",775,"bios"],["bios/sed1200fa.zip",749,"bios"],["bios/sed1200fb.zip",775,"bios"],["bios/sed1278.zip",2096,"bios"],["bios/seeprom.bin",512,"bios"],["bios/sega1003.bin",524288,"bios"],["bios/sega837_14438.zip",201331,"bios"],["bios/sega_100.bin",524288,"bios"],["bios/sega_100a.bin",524288,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sega_fm_unit.zip",313,"bios"],["bios/sega_sk1100.zip",3461,"bios"],["bios/sega_sk1100e.zip",3461,"bios"],["bios/sega_sp400.zip",3461,"bios"],["bios/segaai_soundbox.zip",47380,"bios"],["bios/segabill.zip",3117,"bios"],["bios/segadimm.zip",5632733,"bios"],["bios/seganetw.zip",734284,"bios"],["bios/segasp.zip",1281424,"bios"],["bios/sente6vb.zip",4778,"bios"],["bios/serad.zip",99508,"bios"],["bios/serial_heath_h19.zip",49567,"bios"],["bios/serial_votraxtnt.zip",3922,"bios"],["bios/sfcbox.zip",194344,"bios"],["bios/sfd1001.zip",13984,"bios"],["bios/sgb1.boot.rom",256,"bios"],["bios/sgb1.program.rom",262144,"bios"],["bios/sgb2.boot.rom",524288,"bios"],["bios/sgb2_boot.bin",256,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sgi_gm1.zip",120530,"bios"],["bios/sgi_ip2.zip",39192,"bios"],["bios/sgi_ip4.zip",307898,"bios"],["bios/sgi_kbd.zip",1233,"bios"],["bios/sgi_pm1.zip",18125,"bios"],["bios/sgi_pm2.zip",35149,"bios"],["bios/shareddata.bin",33554432,"bios"],["bios/shtzone.zip",3332,"bios"],["bios/side116.zip",1155085,"bios"],["bios/simutrek.zip",2912,"bios"],["bios/sis5513_ide.zip",1151601,"bios"],["bios/sis630_gui.zip",49059,"bios"],["bios/sis6326_agp.zip",101579,"bios"],["bios/sis6326_dvd.zip",23245,"bios"],["bios/sis6326_pci.zip",64665,"bios"],["bios/sis85c496_host.zip",1171917,"bios"],["bios/sis900_eth.zip",24831,"bios"],["bios/sis950_lpc.zip",20242,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/skns.zip",783788,"bios"],["bios/sl31253.bin",1024,"bios"],["bios/sl31254.bin",1024,"bios"],["bios/sl90025.bin",1024,"bios"],["bios/smoc501.zip",37103,"bios"],["bios/sms_diypaddle.zip",334,"bios"],["bios/sms_rapid_fire.zip",95467,"bios"],["bios/sms_rs232.zip",95177,"bios"],["bios/sms_teamplayer.zip",95467,"bios"],["bios/smvme2000.zip",124406,"bios"],["bios/sn74s262.zip",675,"bios"],["bios/sn74s263.zip",705,"bios"],["bios/snes:st018.data.rom",32768,"bios"],["bios/sns_dsp1bleg.zip",4140,"bios"],["bios/sns_dsp1leg.zip",4135,"bios"],["bios/sns_dsp1leg_hi.zip",4135,"bios"],["bios/sns_dsp2leg.zip",2987,"bios"],["bios/sns_dsp3leg.zip",3522,"bios"],["bios/sns_dsp4leg.zip",3417,"bios"],["bios/sns_rom_sgb.zip",390,"bios"],["bios/sns_rom_sgb2.zip",392,"bios"],["bios/sns_seta10leg.zip",2712,"bios"],["bios/sns_seta11leg.zip",17424,"bios"],["bios/softcard3.zip",407,"bios"],["bios/sound.rom",16384,"bios"],["bios/sound_orchestra.zip",13041,"bios"],["bios/sound_pc9821ce.zip",103032,"bios"],["bios/sound_pc9821cx3.zip",7609,"bios"],["bios/spc1000_fdd_exp.zip",1839,"bios"],["bios/speakboard.zip",116066,"bios"],["bios/spec128.zip",32986,"bios"],["bios/spec1282a.zip",41646,"bios"],["bios/speccyboot-1.4.rom",8192,"bios"],["bios/spectred_kbd.zip",911,"bios"],["bios/spectrum.zip",16506,"bios"],["bios/spectrum_beta128.zip",2046403,"bios"],["bios/spectrum_betacbi.zip",2046403,"bios"],["bios/spectrum_betaclone.zip",2046403,"bios"],["bios/spectrum_betaplus.zip",2046403,"bios"],["bios/spectrum_betav2.zip",2046403,"bios"],["bios/spectrum_betav3.zip",2046403,"bios"],["bios/spectrum_d40.zip",14616,"bios"],["bios/spectrum_d80.zip",14616,"bios"],["bios/spectrum_d80v2.zip",7460,"bios"],["bios/spectrum_disciple.zip",2046403,"bios"],["bios/spectrum_flpone.zip",2046403,"bios"],["bios/spectrum_fuller.zip",2046403,"bios"],["bios/spectrum_gamma.zip",2046403,"bios"],["bios/spectrum_intf1.zip",2046403,"bios"],["bios/spectrum_kempcentref.zip",481571,"bios"],["bios/spectrum_kempcentreu.zip",481760,"bios"],["bios/spectrum_kempcentrs.zip",479847,"bios"],["bios/spectrum_kempdisc.zip",2046403,"bios"],["bios/spectrum_lprint.zip",481681,"bios"],["bios/spectrum_lprint3.zip",2046403,"bios"],["bios/spectrum_melodik.zip",2046403,"bios"],["bios/spectrum_mface1.zip",2046403,"bios"],["bios/spectrum_mface128.zip",2046403,"bios"],["bios/spectrum_mface128v1.zip",2046403,"bios"],["bios/spectrum_mface1v1.zip",2046403,"bios"],["bios/spectrum_mface1v2.zip",2046403,"bios"],["bios/spectrum_mface1v3.zip",2046403,"bios"],["bios/spectrum_mface3.zip",19134,"bios"],["bios/spectrum_mikroplus.zip",12536,"bios"],["bios/spectrum_mpoker.zip",2573,"bios"],["bios/spectrum_mprint.zip",2046403,"bios"],["bios/spectrum_opus.zip",2046403,"bios"],["bios/spectrum_plus2test.zip",3413,"bios"],["bios/spectrum_plusd.zip",497390,"bios"],["bios/spectrum_proceed.zip",1500724,"bios"],["bios/spectrum_sdi.zip",1496950,"bios"],["bios/spectrum_spdos.zip",2046403,"bios"],["bios/spectrum_speccydos.zip",2046403,"bios"],["bios/spectrum_specmate.zip",2046403,"bios"],["bios/spectrum_swiftdisc.zip",2046403,"bios"],["bios/spectrum_swiftdisc2.zip",2046403,"bios"],["bios/spectrum_uslot.zip",2046403,"bios"],["bios/spectrum_usource.zip",7261,"bios"],["bios/spectrum_uspeech.zip",3944,"bios"],["bios/spectrum_vtx5000.zip",2046403,"bios"],["bios/spectrum_wafa.zip",2046403,"bios"],["bios/spi.zip",479847,"bios"],["bios/square1.pk3",45202919,"game_data"],["bios/squirreljme-0.3.0-fast.jar",2367241,"bios"],["bios/squirreljme-0.3.0-slow-test.jar",3772058,"bios"],["bios/squirreljme-0.3.0-slow.jar",3129653,"bios"],["bios/squirreljme-0.3.0-test.jar",3396757,"bios"],["bios/squirreljme-0.3.0.jar",15181774,"bios"],["bios/squirreljme-fast.jar",15181774,"bios"],["bios/squirreljme-slow-test.jar",15181774,"bios"],["bios/squirreljme-slow.jar",15181774,"bios"],["bios/squirreljme-test.jar",3396757,"bios"],["bios/squirreljme.jar",4700395,"bios"],["bios/ss50_mpc.zip",95177,"bios"],["bios/ss50_mps.zip",95177,"bios"],["bios/ss50_mps2.zip",95177,"bios"],["bios/ss50_piaide.zip",1151601,"bios"],["bios/ssi263hle.zip",588,"bios"],["bios/st010.data.rom",4096,"bios"],["bios/st010.program.rom",49152,"bios"],["bios/st011.data.rom",4096,"bios"],["bios/st011.program.rom",49152,"bios"],["bios/st018.program.rom",131072,"bios"],["bios/st_kbd.zip",3344,"bios"],["bios/steeltal1_board.zip",95177,"bios"],["bios/steeltal_board.zip",95177,"bios"],["bios/steeltalp_board.zip",95177,"bios"],["bios/stereo_fx.zip",3977,"bios"],["bios/stic.zip",1296,"bios"],["bios/strtdriv_board.zip",95177,"bios"],["bios/stunrun_board.zip",95177,"bios"],["bios/stvbios.zip",2699375,"bios"],["bios/su2000.zip",90729,"bios"],["bios/sun1_cpu.zip",57393,"bios"],["bios/sun1cpu.zip",57393,"bios"],["bios/sun_gem.zip",9773,"bios"],["bios/supracan.zip",1849,"bios"],["bios/sv601.zip",577653,"bios"],["bios/sv602.zip",577653,"bios"],["bios/sv603.zip",5695,"bios"],["bios/sv802.zip",479847,"bios"],["bios/sv805.zip",95177,"bios"],["bios/sv806.zip",2717,"bios"],["bios/sw1000xg.zip",20518162,"bios"],["bios/swp30.zip",47545,"bios"],["bios/swtpc8212_device.zip",5070,"bios"],["bios/swtpc8212_terminal.zip",5070,"bios"],["bios/sx1541.zip",30913,"bios"],["bios/sys246.zip",580122,"bios"],["bios/sys256.zip",582110,"bios"],["bios/sys68k_cpu1.zip",605422,"bios"],["bios/sys68k_cpu20.zip",129580,"bios"],["bios/sys68k_cpu21.zip",34447,"bios"],["bios/sys68k_cpu21a.zip",34447,"bios"],["bios/sys68k_cpu21b.zip",34447,"bios"],["bios/sys68k_cpu21s.zip",34447,"bios"],["bios/sys68k_cpu21ya.zip",34447,"bios"],["bios/sys68k_cpu21yb.zip",34447,"bios"],["bios/sys68k_cpu30.zip",291856,"bios"],["bios/sys68k_cpu30be.zip",291856,"bios"],["bios/sys68k_cpu30x.zip",291856,"bios"],["bios/sys68k_cpu30xa.zip",291856,"bios"],["bios/sys68k_cpu30za.zip",291856,"bios"],["bios/sys68k_cpu33.zip",218296,"bios"],["bios/sys68k_iscsi1.zip",17599,"bios"],["bios/sys68k_isio1.zip",7302,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262144,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/sysdata/keys.txt",7424,"bios"],["bios/sysdata/otp.bin",256,"bios"],["bios/sysdata/seeddb.bin",53264,"bios"],["bios/sysdata/shared_font.bin",3145728,"bios"],["bios/t5182.zip",2681,"bios"],["bios/taikodp.zip",1141771,"bios"],["bios/taito68705tiger.zip",266,"bios"],["bios/taitosjsecmcu.zip",266,"bios"],["bios/taitotz.zip",77002,"bios"],["bios/tak_daig.zip",951997,"bios"],["bios/tanbus_mpvdu.zip",536,"bios"],["bios/tanbus_ra32krom.zip",4189,"bios"],["bios/tanbus_ravdu.zip",525,"bios"],["bios/tanbus_tandos.zip",297319,"bios"],["bios/tanbus_tanex.zip",121959,"bios"],["bios/tanbus_vid8082.zip",5374,"bios"],["bios/tandberg_tdv2100_disp_logic.zip",96432,"bios"],["bios/tandberg_tdv2100_keyboard.zip",572,"bios"],["bios/tandy_1000_graphics.zip",3739,"bios"],["bios/tandy_1000x_graphics.zip",3731,"bios"],["bios/tape_128.sz",1464,"bios"],["bios/tape_16.szx",591,"bios"],["bios/tape_2048.szx",720,"bios"],["bios/tape_2068.szx",1799,"bios"],["bios/tape_48.szx",1799,"bios"],["bios/tape_pentagon.szx",1479,"bios"],["bios/tape_plus2.szx",1571,"bios"],["bios/tape_plus2a.szx",1617,"bios"],["bios/tape_plus3.szx",1856,"bios"],["bios/tape_plus3e.szx",1970,"bios"],["bios/tape_scorpion.szx",3500,"bios"],["bios/tape_se.szx",2146,"bios"],["bios/tape_ts2068.szx",1840,"bios"],["bios/tc2048.rom",16384,"bios"],["bios/tc2068-0.rom",16384,"bios"],["bios/tc2068-1.rom",8192,"bios"],["bios/tdl12.zip",786047,"bios"],["bios/technica.zip",12198,"bios"],["bios/tek410x_kbd.zip",936,"bios"],["bios/tek_msu_fdc.zip",2453,"bios"],["bios/teletex800.zip",1260,"bios"],["bios/tetriskr_cga.zip",160878,"bios"],["bios/tgui9680.zip",22311,"bios"],["bios/ti8x_glinkhle.zip",95177,"bios"],["bios/ti8x_tconn.zip",95177,"bios"],["bios/ti99_4a.zip",21377,"bios"],["bios/ti99_arcturus.zip",11432,"bios"],["bios/ti99_bwg.zip",7452,"bios"],["bios/ti99_ccdcc.zip",9611,"bios"],["bios/ti99_ccfdc.zip",9712,"bios"],["bios/ti99_ddcc1.zip",6231,"bios"],["bios/ti99_evpc.zip",17207,"bios"],["bios/ti99_fdc.zip",4969,"bios"],["bios/ti99_gkracker.zip",5998,"bios"],["bios/ti99_hfdc.zip",11813,"bios"],["bios/ti99_ide.zip",1151601,"bios"],["bios/ti99_iosplit.zip",2106147,"bios"],["bios/ti99_myarcmem.zip",6085,"bios"],["bios/ti99_pcode.zip",41460,"bios"],["bios/ti99_rs232.zip",1782,"bios"],["bios/ti99_speech.zip",31291,"bios"],["bios/ti99_speechconn.zip",2106147,"bios"],["bios/ti99_thermal.zip",1544,"bios"],["bios/ti99_tipi.zip",5838,"bios"],["bios/ti99_whtscsi.zip",790364,"bios"],["bios/ti_hx5102.zip",9758,"bios"],["bios/tiki100_8088.zip",1246,"bios"],["bios/tim011_kbd.zip",1862,"bios"],["bios/tk02.zip",2839,"bios"],["bios/tms32030.zip",573,"bios"],["bios/tms32031.zip",573,"bios"],["bios/tms32032.zip",620,"bios"],["bios/tms32033.zip",573,"bios"],["bios/tms320c30.zip",573,"bios"],["bios/tms320c31.zip",573,"bios"],["bios/tms320c32.zip",620,"bios"],["bios/tms320vc33.zip",573,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/top-sp1.bin",524288,"bios"],["bios/tos.img",196608,"bios"],["bios/tourvis.zip",29492,"bios"],["bios/tp880v.zip",150415,"bios"],["bios/tp881v.zip",167178,"bios"],["bios/trdos.rom",16384,"bios"],["bios/triforce.zip",2046778,"bios"],["bios/trio64dx_pci.zip",73424,"bios"],["bios/trs80m2kb.zip",920,"bios"],["bios/tsvme104.zip",120366,"bios"],["bios/turbogx.zip",11121,"bios"],["bios/turbogxp.zip",11215,"bios"],["bios/tv950kb.zip",1046,"bios"],["bios/tv955kb.zip",1417,"bios"],["bios/tvc_hbf.zip",36960,"bios"],["bios/tvga9000.zip",37841,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/ubpnic.zip",171,"bios"],["bios/ultra12f.zip",44397,"bios"],["bios/ultra12f32.zip",20138,"bios"],["bios/ultra14f.zip",794627,"bios"],["bios/ultra24f.zip",797445,"bios"],["bios/umc6650.zip",160,"bios"],["bios/uni-bioscd.rom",524288,"bios"],["bios/uniap2ti.zip",1716,"bios"],["bios/upc82c710.zip",479847,"bios"],["bios/upc82c711.zip",479847,"bios"],["bios/upd7220.zip",367,"bios"],["bios/upd7801g.s01",4096,"bios"],["bios/uts_400kbd.zip",853,"bios"],["bios/uts_extw.zip",1046,"bios"],["bios/v102_kbd.zip",1329,"bios"],["bios/v4bios.zip",3753,"bios"],["bios/v50_kbd.zip",1066,"bios"],["bios/v550_kbd.zip",1184,"bios"],["bios/vanta.zip",72613,"bios"],["bios/vector4_kbd.zip",1267,"bios"],["bios/vic1010.zip",10861,"bios"],["bios/vic1011.zip",95177,"bios"],["bios/vic1112.zip",291066,"bios"],["bios/vic1515.zip",2699,"bios"],["bios/vic1520.zip",3695,"bios"],["bios/vic20_fe3.zip",9529,"bios"],["bios/vic20_speakeasy.zip",590,"bios"],["bios/vic20_videopak.zip",830,"bios"],["bios/vice/C64/basic-901226-01.bin",8192,"bios"],["bios/vice/C64/chargen-901225-01.bin",4096,"bios"],["bios/vice/C64/chargen-906143-02.bin",4096,"bios"],["bios/vice/C64/kernal-251104-04.bin",8192,"bios"],["bios/vice/C64/kernal-390852-01.bin",8192,"bios"],["bios/vice/C64/kernal-901227-01.bin",8192,"bios"],["bios/vice/C64/kernal-901227-02.bin",8192,"bios"],["bios/vice/C64/kernal-901227-03.bin",8192,"bios"],["bios/vice/C64/kernal-901246-01.bin",8192,"bios"],["bios/vice/C64/kernal-906145-02.bin",8192,"bios"],["bios/vice/DRIVES/dos1540-325302+3-01.bin",16384,"bios"],["bios/vice/DRIVES/dos1541-325302-01+901229-05.bin",16384,"bios"],["bios/vice/DRIVES/dos1541ii-251968-03.bin",16384,"bios"],["bios/vice/DRIVES/dos1570-315090-01.bin",32768,"bios"],["bios/vice/DRIVES/dos1571-310654-05.bin",32768,"bios"],["bios/vice/DRIVES/dos1581-318045-02.bin",32768,"bios"],["bios/vice/JiffyDOS_1541-II.bin",16384,"bios"],["bios/vice/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/vice/JiffyDOS_1581.bin",32768,"bios"],["bios/vice/JiffyDOS_C64.bin",8192,"bios"],["bios/vice/JiffyDOS_SX-64.bin",8192,"bios"],["bios/vice/SCPU64/chargen-901225-01.bin",4096,"bios"],["bios/vice/SCPU64/chargen-906143-02.bin",4096,"bios"],["bios/vice/SCPU64/scpu-dos-1.4.bin",131072,"bios"],["bios/vice/SCPU64/scpu-dos-2.04.bin",131072,"bios"],["bios/vice/SCPU64/scpu64",65536,"bios"],["bios/vice/VIC20/chargen-901460-02.bin",4096,"bios"],["bios/vice/VIC20/kernal.901486-02.bin",8192,"bios"],["bios/victor9k_fdc.zip",1152,"bios"],["bios/victor9k_kb.zip",669,"bios"],["bios/videnh2.zip",1713,"bios"],["bios/virge_pci.zip",35167,"bios"],["bios/virgedx_pci.zip",56560,"bios"],["bios/virgevx_pci.zip",19358,"bios"],["bios/vision864.zip",18539,"bios"],["bios/vision964.zip",18202,"bios"],["bios/vision968.zip",55852,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/voicebox.zip",2019,"bios"],["bios/voodoo_3000_x86.zip",40056,"bios"],["bios/votraxtnt.zip",3922,"bios"],["bios/votrsc01.zip",588,"bios"],["bios/votrsc01a.zip",590,"bios"],["bios/vp575.zip",3613,"bios"],["bios/vp700.zip",3613,"bios"],["bios/vrc5074.zip",95177,"bios"],["bios/vsaturn.bin",524288,"bios"],["bios/vsmile.zip",5065220,"bios"],["bios/vsmile_v100.bin",2097152,"bios"],["bios/vsmile_v102.bin",2097152,"bios"],["bios/vsmile_v103.bin",2097152,"bios"],["bios/vtech_fdc.zip",123619,"bios"],["bios/vtech_printer.zip",479847,"bios"],["bios/vtech_rs232.zip",97591,"bios"],["bios/vtech_rtty.zip",2488,"bios"],["bios/vtech_sdloader.zip",11160,"bios"],["bios/vtech_wordpro.zip",8125,"bios"],["bios/w83787f.zip",479847,"bios"],["bios/w83977tf.zip",479847,"bios"],["bios/wangpc_lic.zip",2810,"bios"],["bios/wangpc_rtc.zip",3197,"bios"],["bios/wangpc_tig.zip",367,"bios"],["bios/wangpc_wdc.zip",3193,"bios"],["bios/wangpckb.zip",1228,"bios"],["bios/wd1002a_wx1.zip",1868,"bios"],["bios/wd1007a.zip",3971,"bios"],["bios/wd90c00_jk.zip",58499,"bios"],["bios/wd90c11_lr.zip",18343,"bios"],["bios/wd90c30_lr.zip",41732,"bios"],["bios/wd90c31_lr.zip",22513,"bios"],["bios/wd90c31a_lr.zip",38568,"bios"],["bios/wd90c31a_zs.zip",18777,"bios"],["bios/wd90c33_zz.zip",19105,"bios"],["bios/wd90c90_jk.zip",15497,"bios"],["bios/wd9710_pci.zip",18718,"bios"],["bios/wdxt_gen.zip",4266,"bios"],["bios/wg130.zip",1861561,"bios"],["bios/wildmidi.cfg",192,"game_data"],["bios/wpcap.dll",499128,"bios"],["bios/wyse700.zip",4164,"bios"],["bios/x68k_cz6bs1.zip",3156,"bios"],["bios/x820iikb.zip",1128,"bios"],["bios/x820kb.zip",1128,"bios"],["bios/xegs.zip",23089,"bios"],["bios/xerox820_16_8.zip",1338,"bios"],["bios/xerox820_emii_flpy5.zip",2303,"bios"],["bios/xerox820_emii_rgd5.zip",2303,"bios"],["bios/xetec_c5181.zip",3192,"bios"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",32768,"bios"],["bios/xroarbios.rom",8192,"bios"],["bios/xt446.zip",18613894,"bios"],["bios/xtide.zip",1300467,"bios"],["bios/yados.rom",16384,"bios"],["bios/ym2413.zip",286,"bios"],["bios/ym2423.zip",313,"bios"],["bios/ym2608.zip",7587,"bios"],["bios/ymf281.zip",313,"bios"],["bios/yrw801.rom",2097152,"bios"],["bios/z8671.zip",2028,"bios"],["bios/z8682.zip",201,"bios"],["bios/z_89_11.zip",95177,"bios"],["bios/zc405351p__servo_cdi_4.1__0d67p__lluk9404.mc68hc705c8a.7490",8192,"bios"],["bios/zc405352p__slave_cdi_4.1__0d67p__lltr9403.mc68hc705c8a.7206",8192,"bios"],["bios/zip100_ide.zip",36071,"bios"],["bios/zorba_kbd.zip",1406,"bios"],["bios/zx405037p__cdi_servo_2.1__b43t__llek9215.mc68hc705c8a_withtestrom.7201",8192,"bios"],["bios/zx405042p__cdi_slave_2.0__b43t__zzmk9213.mc68hc705c8a_withtestrom.7206",8192,"bios"],["bios/zxbus_adapter.zip",297163,"bios"],["bios/zxbus_neogs.zip",297163,"bios"],["bios/zxs:48.rom",16384,"bios"],["bios/zxs:if1-2.rom",8192,"bios"],["cps/hiscore.dat",322458,"bios"],["cps1/hiscore.dat",322458,"bios"],["cps2/hiscore.dat",322458,"bios"],["cps3/hiscore.dat",322458,"bios"],["fba/hiscore.dat",322458,"bios"],["gc/User/GBA/gba_bios.bin",16384,"bios"],["gc/User/Load/WiiSD.raw",134217728,"bios"],["gc/User/Wii/clientca.pem",1005,"bios"],["gc/User/Wii/clientcakey.pem",609,"bios"],["gc/User/Wii/rootca.pem",897,"bios"],["gc/User/Wii/shared2/sys/SYSCONF",16384,"bios"],["gc/User/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["mame/hiscore.dat",322458,"bios"],["n3ds/Azahar/nand/private/movable.sed",320,"bios"],["n3ds/Azahar/nand/rw/sys/LocalFriendCodeSeed_B",272,"bios"],["n3ds/Azahar/nand/rw/sys/SecureInfo_A",273,"bios"],["n3ds/Azahar/sysdata/keys.txt",7424,"bios"],["n3ds/Azahar/sysdata/otp.bin",256,"bios"],["n3ds/Azahar/sysdata/seeddb.bin",53264,"bios"],["n3ds/Azahar/sysdata/shared_font.bin",3145728,"bios"],["roms/neogeo/neogeo.zip",1859335,"bios"],["wii/User/GBA/gba_bios.bin",16384,"bios"],["wii/User/Load/WiiSD.raw",134217728,"bios"],["wii/User/Wii/clientca.pem",1005,"bios"],["wii/User/Wii/clientcakey.pem",609,"bios"],["wii/User/Wii/rootca.pem",897,"bios"],["wii/User/Wii/shared2/sys/SYSCONF",16384,"bios"],["wii/User/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeCn.ttf",13110604,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeKr.ttf",2260660,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeStd.ttf",2442464,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeTw.ttf",8229724,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/1004f000/content/00/swkbd/swkbd.pack",1907900,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10051000/content/00/erreula/erreula.pack",1252759,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_ACCOUNT_1_CERT.der",1226,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_ACCOUNT_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_COMMON_1_CERT.der",1224,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_COMMON_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_OLIVE_1_CERT.der",1224,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_OLIVE_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_VINO_1_CERT.der",1223,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_VINO_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_WOOD_1_CERT.der",1223,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_WOOD_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ADDTRUST_EXT_CA_ROOT.der",1082,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/BALTIMORE_CYBERTRUST_ROOT_CA.der",891,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA.der",897,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA_G2.der",1173,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA_G3.der",1060,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA.der",924,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA_G2.der",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA_G3.der",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/COMODO_CA.der",980,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CYBERTRUST_GLOBAL_ROOT_CA.der",933,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_ASSURED_ID_ROOT_CA.der",955,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_ASSURED_ID_ROOT_CA_G2.der",922,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_GLOBAL_ROOT_CA.der",947,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_GLOBAL_ROOT_CA_G2.der",914,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_HIGH_ASSURANCE_EV_ROOT_CA.der",969,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_CA_2048.der",1070,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_ROOT_CA.der",1173,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_ROOT_CA_G2.der",1090,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_SECURE_SERVER_CA.der",1244,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/EQUIFAX_SECURE_CA.der",804,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_GLOBAL_CA.der",856,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_GLOBAL_CA2.der",874,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_PRIMARY_CA.der",896,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_PRIMARY_CA_G3.der",1026,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA.der",889,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA_R2.der",958,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA_R3.der",867,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GTE_CYBERTRUST_GLOBAL_ROOT.der",606,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PREMIUM_SERVER_CA.der",811,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PRIMARY_ROOT_CA.der",1060,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PRIMARY_ROOT_CA_G3.der",1070,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/UTN_DATACORP_SGC_CA.der",1122,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/UTN_USERFIRST_HARDWARE_CA.der",1144,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA.der",576,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G2.der",774,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G3.der",1054,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G5.der",1239,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_UNIVERSAL_ROOT_CA.der",1213,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERIZON_GLOBAL_ROOT_CA.der",889,"bios"]],"format_version":1,"platform":"retrodeck","sets":{"acorn-archimedes|mame":{"bytes":6536273,"files":[361],"optional":[],"required_bytes":6536273},"acorn-bbc-micro|mame":{"bytes":623105,"files":[616,633,638,639,640,641,642,2302,2933],"optional":[616,633,638,639,640,2302,2933],"required_bytes":500688},"amstrad-cpc|cap32":{"bytes":114688,"files":[852,853,854,855],"optional":[852,853,854,855],"required_bytes":0},"apple-iigs|mame":{"bytes":134915450,"files":[39,186,187,297,301,305,306,307,308,309,390,569,705,708,925,1024,1025,1026,1027,1028,1029,1030,1059,1078,1188,1249,1279,1328,1340,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2605,2685,2686,2687,2910,2911,3013,3185,3189,3256,3620],"optional":[297,301,305,306,307,308,309,390,569,705,708,1279,1448,1456,1457,1458,1471,1472,1473,1475,1500,1501,1506,1507,1508,1510,1511,1512,1521,1522,1523,1524,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1548,1549,1550,1554,1576,1577,1580,1588,1594,1600,1601,1602,1603,1611,1619,1626,1627,1628,1629,1630,1632,1637,1638,1639,1640,1641,1643,1644,1645,1648,1658,1659,1660,1661,1669,1671,1675,1679,1694,1695,1701,1722,1771,1774,1775,1796,1797,1798,1799,1800,1801,1808,1816,1891,1892,1903,1904,1941,1942,1943,1957,1960,1966,1969,1976,2004,2016,2034,2035,2054,2058,2059,2070,2078,2092,2093,2094,2095,2096,2097,2098,2107,2122,2136,2138,2139,2151,2152,2153,2159,2178,2180,2192,2195,2198,2203,2204,2220,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2605,2910,2911,3013,3256,3620],"required_bytes":110399541},"apple-macintosh|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple2|applewin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade|fbalpha2012":{"bytes":1335159885,"files":[0,13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,288,289,290,291,292,293,294,295,296,298,299,300,302,310,311,312,313,314,315,316,318,319,320,321,322,323,324,325,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,427,428,429,430,431,432,436,437,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,511,512,513,514,515,516,517,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,564,565,566,567,568,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,634,635,636,643,644,645,646,664,665,666,667,668,669,670,671,672,673,674,676,677,678,679,680,681,682,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,706,707,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,737,738,739,740,741,742,743,744,745,746,747,748,749,750,754,758,759,760,761,762,763,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,781,782,784,785,786,787,788,790,792,793,794,795,796,797,798,799,800,801,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,830,833,834,835,836,837,838,839,840,841,842,843,844,845,850,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,877,878,879,880,881,882,883,884,885,892,900,901,902,903,916,917,918,919,926,927,928,933,934,935,936,937,938,939,940,941,942,943,944,950,952,953,954,955,956,957,958,959,960,961,962,963,964,979,980,981,982,983,984,985,986,989,990,1001,1002,1003,1004,1005,1006,1007,1009,1010,1011,1012,1016,1017,1018,1019,1021,1022,1023,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1074,1075,1076,1077,1079,1080,1082,1083,1084,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1102,1103,1104,1105,1108,1109,1110,1111,1112,1113,1115,1122,1138,1139,1179,1180,1189,1190,1192,1193,1195,1199,1200,1201,1207,1208,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1223,1224,1225,1228,1229,1230,1231,1232,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1250,1252,1253,1254,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1281,1282,1283,1284,1286,1287,1288,1289,1290,1291,1293,1294,1295,1296,1302,1303,1304,1305,1306,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1329,1330,1331,1332,1337,1338,1341,1342,1343,1344,1345,1346,1347,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1369,1370,1371,1387,1388,1389,1390,1391,1392,1394,1395,1396,1397,1398,1399,1400,1401,1402,1404,1408,1409,1410,1414,1415,1416,1417,1418,1419,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,2322,2323,2326,2327,2328,2329,2330,2331,2332,2333,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2368,2369,2370,2371,2372,2373,2374,2376,2377,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2433,2434,2435,2436,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2525,2526,2527,2528,2529,2530,2531,2534,2535,2536,2541,2562,2563,2564,2565,2567,2568,2569,2572,2573,2574,2576,2577,2578,2579,2581,2582,2583,2584,2585,2586,2587,2602,2603,2604,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2631,2633,2634,2635,2636,2637,2638,2639,2640,2641,2643,2644,2645,2646,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2664,2665,2666,2667,2680,2681,2682,2683,2684,2689,2692,2693,2694,2695,2696,2697,2789,2792,2793,2794,2795,2796,2797,2798,2801,2802,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2893,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2909,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2932,2936,2938,2939,2940,2941,2942,2943,2965,2975,2978,2979,2980,2981,2982,2985,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3009,3011,3012,3016,3017,3018,3019,3020,3021,3024,3025,3026,3029,3033,3034,3035,3036,3037,3038,3039,3040,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3055,3056,3057,3058,3059,3060,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3122,3123,3124,3125,3126,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3143,3144,3146,3147,3148,3149,3150,3151,3153,3154,3155,3156,3157,3158,3159,3160,3184,3186,3187,3188,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3216,3217,3218,3219,3220,3221,3222,3223,3224,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3260,3261,3262,3264,3266,3267,3268,3269,3270,3271,3272,3273,3284,3285,3286,3287,3288,3289,3292,3293,3294,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3340,3341,3343,3344,3345,3346,3347,3348,3619,3621,3622,3623,3624,3625,3626,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3660,3661,3663,3675,3676,3678,3679,3680,3681,3683,3684,3685,3688,3689,3692,3693,3696,3697,3698,3699,3700,3708],"optional":[0,1092,1093,1094,1095,1096,1097,1098,1099,3696,3697,3698,3699,3700,3708],"required_bytes":516192146},"arcade|fbneo":{"bytes":825758776,"files":[13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,288,289,290,291,292,293,294,295,296,298,299,300,302,310,311,312,313,314,315,316,318,319,320,321,322,323,324,325,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,427,428,429,430,431,432,436,437,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,511,512,513,514,515,516,517,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,564,565,566,567,568,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,634,635,636,643,644,645,646,664,665,666,667,668,669,670,671,672,673,674,676,677,678,679,680,681,682,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,706,707,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,737,738,739,740,741,742,743,744,745,746,747,748,749,750,754,758,759,760,761,762,763,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,781,782,784,785,786,787,788,790,792,793,794,795,796,797,798,799,800,801,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,830,833,834,835,836,837,838,839,840,841,842,843,844,845,850,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,877,878,879,880,881,882,883,884,885,892,900,901,902,903,916,917,918,919,926,927,928,933,934,935,936,937,938,939,940,941,942,943,944,950,952,953,954,955,956,957,958,959,960,961,962,963,964,979,980,981,982,983,984,985,986,989,990,1001,1002,1003,1004,1005,1006,1007,1009,1010,1011,1012,1016,1017,1018,1019,1021,1022,1023,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1074,1075,1076,1077,1079,1080,1082,1083,1084,1089,1090,1091,1100,1101,1102,1103,1104,1105,1108,1109,1110,1111,1112,1113,1115,1122,1138,1139,1179,1180,1189,1190,1192,1193,1195,1199,1200,1201,1207,1208,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1223,1224,1225,1228,1229,1230,1231,1232,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1250,1252,1253,1254,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1281,1282,1283,1284,1286,1287,1288,1289,1290,1291,1293,1294,1295,1296,1302,1303,1304,1305,1306,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1329,1330,1331,1332,1337,1338,1341,1342,1343,1344,1345,1346,1347,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1369,1370,1371,1387,1388,1389,1390,1391,1392,1394,1395,1396,1397,1398,1399,1400,1401,1402,1404,1408,1409,1410,1414,1415,1416,1417,1418,1419,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,2322,2323,2326,2327,2328,2329,2330,2331,2332,2333,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2368,2369,2370,2371,2372,2373,2374,2376,2377,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2433,2434,2435,2436,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2525,2526,2527,2528,2529,2530,2531,2534,2535,2536,2541,2562,2563,2564,2565,2567,2568,2569,2572,2573,2574,2576,2577,2578,2579,2581,2582,2583,2584,2585,2586,2587,2602,2603,2604,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2631,2633,2634,2635,2636,2637,2638,2639,2640,2641,2643,2644,2645,2646,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2664,2665,2666,2667,2680,2681,2682,2683,2684,2689,2692,2693,2694,2695,2696,2697,2789,2792,2793,2794,2795,2796,2797,2798,2801,2802,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2893,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2909,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2932,2936,2938,2939,2940,2941,2942,2943,2965,2975,2978,2979,2980,2981,2982,2985,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3009,3011,3012,3016,3017,3018,3019,3020,3021,3024,3025,3026,3029,3033,3034,3035,3036,3037,3038,3039,3040,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3055,3056,3057,3058,3059,3060,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3122,3123,3124,3125,3126,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3143,3144,3146,3147,3148,3149,3150,3151,3153,3154,3155,3156,3157,3158,3159,3160,3184,3186,3187,3188,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3216,3217,3218,3219,3220,3221,3222,3223,3224,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3260,3261,3262,3264,3266,3267,3268,3269,3270,3271,3272,3273,3284,3285,3286,3287,3288,3289,3292,3293,3294,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3340,3341,3343,3344,3345,3346,3347,3348,3619,3621,3622,3623,3624,3625,3626,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3660,3661,3663,3675,3676,3678,3679,3680,3681,3683,3684,3685,3688,3689,3692,3693],"optional":[1100,1101],"required_bytes":516192146},"arcade|mame":{"bytes":644070374,"files":[13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,511,512,513,514,515,516,517,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,634,635,636,637,643,644,645,646,664,665,666,667,668,669,670,671,672,673,674,676,677,678,679,680,681,682,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,737,738,739,740,741,742,743,744,745,746,747,748,749,750,754,758,759,760,761,762,763,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,781,782,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,830,833,834,835,836,837,838,839,840,841,842,843,844,845,850,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,892,900,901,902,903,916,917,918,919,926,927,928,933,934,935,936,937,938,939,940,941,942,943,944,950,952,953,954,955,956,957,958,959,960,961,962,963,964,979,980,981,982,983,984,985,986,989,990,991,1001,1002,1003,1004,1005,1006,1007,1009,1010,1011,1012,1016,1017,1018,1019,1020,1021,1022,1023,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1079,1080,1082,1083,1084,1085,1089,1090,1091,1102,1103,1104,1105,1108,1109,1110,1111,1112,1113,1114,1115,1122,1138,1139,1179,1180,1184,1189,1190,1192,1193,1195,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1223,1224,1225,1228,1229,1230,1231,1232,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1250,1252,1253,1254,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1281,1282,1283,1284,1286,1287,1288,1289,1290,1291,1293,1294,1295,1296,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1329,1330,1331,1332,1334,1337,1338,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1369,1370,1371,1387,1388,1389,1390,1391,1392,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1449,1450,1451,1452,1453,1454,1455,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1474,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1502,1503,1504,1505,1509,1513,1514,1515,1516,1517,1518,1519,1520,1525,1526,1527,1528,1529,1530,1531,1547,1551,1552,1553,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1578,1579,1581,1582,1583,1584,1585,1586,1587,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1602,1603,1604,1605,1606,1607,1608,1609,1610,1612,1613,1614,1615,1616,1617,1618,1620,1621,1622,1623,1624,1625,1631,1633,1634,1635,1636,1642,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1662,1663,1664,1665,1666,1667,1668,1670,1672,1673,1674,1676,1677,1678,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1696,1697,1698,1699,1700,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1772,1773,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1802,1803,1804,1805,1806,1807,1809,1810,1811,1812,1813,1814,1815,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1958,1959,1961,1962,1963,1964,1965,1967,1968,1969,1970,1971,1972,1973,1974,1975,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2055,2056,2057,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2071,2072,2073,2074,2075,2076,2077,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2154,2155,2156,2157,2158,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2179,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2193,2194,2196,2197,2199,2200,2201,2202,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2433,2434,2435,2436,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2525,2526,2527,2528,2529,2530,2531,2534,2535,2536,2540,2541,2562,2563,2564,2565,2567,2568,2569,2572,2573,2574,2575,2576,2577,2578,2579,2581,2582,2583,2584,2585,2586,2587,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2664,2665,2666,2667,2680,2681,2682,2683,2684,2689,2690,2692,2693,2694,2695,2696,2697,2789,2792,2793,2794,2795,2796,2797,2798,2801,2802,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2932,2936,2938,2939,2940,2941,2942,2943,2965,2975,2978,2979,2980,2981,2982,2985,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3009,3010,3011,3012,3013,3014,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3029,3033,3034,3035,3036,3037,3038,3039,3040,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3054,3055,3056,3057,3058,3059,3060,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3122,3123,3124,3125,3126,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3184,3186,3187,3188,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3216,3217,3218,3219,3220,3221,3222,3223,3224,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3260,3261,3262,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3284,3285,3286,3287,3288,3289,3291,3292,3293,3294,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3340,3341,3342,3343,3344,3345,3346,3347,3348,3619,3620,3621,3622,3623,3624,3625,3626,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3660,3661,3662,3663,3665,3666,3667,3668,3675,3676,3678,3679,3680,3681,3683,3684,3685,3688,3689,3692,3693],"optional":[287,297,301,303,304,305,306,307,308,309,317,326,390,426,438,563,569,610,611,612,613,614,615,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,637,705,708,789,791,876,991,1020,1073,1085,1114,1184,1202,1203,1204,1205,1206,1279,1307,1334,1348,1403,1405,1406,1407,1411,1412,1413,1445,1446,1594,1602,1603,1891,1892,1903,1904,1969,2092,2093,2094,2095,2096,2097,2098,2138,2139,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2324,2334,2375,2540,2575,2605,2632,2642,2647,2690,2894,2906,2907,2908,2910,2911,3010,3013,3014,3022,3023,3054,3062,3142,3152,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3242,3253,3254,3255,3256,3265,3291,3342,3620,3662,3665,3666,3667,3668],"required_bytes":610609152},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella":{"bytes":33793052,"files":[1,2,3,4,5,6,7],"optional":[1,2,3,4,5,6,7],"required_bytes":0},"atari-400-800|atari800":{"bytes":371249,"files":[42,43,44,45,48,188,191,192,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,256,683,3664],"optional":[42,43,44,45,48,188,191,192,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,256,683,3664],"required_bytes":0},"atari-5200|a5200":{"bytes":59392,"files":[32,42,43,44,45,189,190,193],"optional":[32,189,190,193],"required_bytes":45056},"atari-7800|prosystem":{"bytes":53208,"files":[35,36,38,185],"optional":[35,36,38,185],"required_bytes":0},"atari-jaguar|virtualjaguar":{"bytes":917504,"files":[47,257,258,1335,1336],"optional":[47,257,258,1335,1336],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[1255,1420],"optional":[1255],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[1227,3259],"optional":[1227],"required_bytes":196608},"bally-astrocade|mame":{"bytes":20412,"files":[518,519,520],"optional":[519,520],"required_bytes":6800},"capcom-cps1|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"casio-pv1000|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco|xroar":{"bytes":466100,"files":[55,56,76,77,410,411,412,539,540,541,542,543,802,803,832,847,848,849,851,932,946,947,948,1086,1087,1106,1107,1233,2431,2432,2571,3674,3677],"optional":[55,56,76,77,410,411,412,539,540,541,543,802,803,832,847,849,851,946,947,1086,1087,1106,1107,1233,2571,3674,3677],"required_bytes":73728},"coleco-adam|mame":{"bytes":52891,"files":[398],"optional":[],"required_bytes":52891},"colecovision|bluemsx":{"bytes":24576,"files":[50,829,831],"optional":[829,831],"required_bytes":8192},"commodore-amiga-cd32|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae":{"bytes":15415966,"files":[46,249,734,735,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,2891,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283],"optional":[249,734,735,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,2891,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283],"required_bytes":524288},"commodore-c64|vice_x64sc":{"bytes":770048,"files":[98,99,100,101,102,1360,1361,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337],"optional":[98,99,100,101,102,1360,1361,3317,3318,3328,3329,3330,3331,3332],"required_bytes":540672},"commodore-cdtv|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":24576,"files":[783,1362,3338,3339],"optional":[783,1362,3338,3339],"required_bytes":0},"crvision|jollycv":{"bytes":2048,"files":[661],"optional":[],"required_bytes":2048},"doom|gzdoom":{"bytes":613419140,"files":[397,929,973,974,975,1121,1123,1124,1221,1222,1226,2679,2691,2892,3111,3257],"optional":[397,929,973,974,975,1121,1123,1124,1221,1222,1226,2679,2892,3111,3257],"required_bytes":143312},"dos|dosbox_pure":{"bytes":41236388,"files":[57,58,59,80,167,168,210,211,212,213,214,215,216,217,218,219],"optional":[57,58,59,80,167,168,210,211,212,213,214,215,216,217,218,219],"required_bytes":0},"dragon32|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon64|xroar":{"bytes":380928,"files":[433,434,435,757,846,887,888,889,890,891,893,894,895,896,897,920,921,922,923,924,930,931,976,977,978,987,988,2972,2973,2974],"optional":[434,757,846,888,889,890,891,894,896,897,921,922,923,924,930,931,976,977,978,987,988,2972,2973,2974],"required_bytes":81920},"electron|mame":{"bytes":50660,"files":[1031,1032],"optional":[1032],"required_bytes":25571},"emerson-arcadia-2001|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":5777,"files":[782,3030,3031,3032],"optional":[],"required_bytes":5777},"famicom|mesen":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"flash|ruffle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fm7|mame":{"bytes":178012,"files":[1117,1118,1119],"optional":[1119],"required_bytes":151197},"fmtowns|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamate|mame":{"bytes":5072,"files":[1181],"optional":[],"required_bytes":5072},"hartung-game-master|mame":{"bytes":133563649,"files":[569,705,708,898,925,1024,1025,1026,1027,1028,1029,1030,1059,1078,1188,1197,1249,1328,1340,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2685,2686,2687,3013,3185,3189,3256,3620],"optional":[569,705,708,898,1197,1448,1456,1457,1458,1471,1472,1473,1475,1500,1501,1506,1507,1508,1510,1511,1512,1521,1522,1523,1524,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1548,1549,1550,1554,1576,1577,1580,1588,1594,1600,1601,1602,1603,1611,1619,1626,1627,1628,1629,1630,1632,1637,1638,1639,1640,1641,1643,1644,1645,1648,1658,1659,1660,1661,1669,1671,1675,1679,1694,1695,1701,1722,1771,1774,1775,1796,1797,1798,1799,1800,1801,1808,1816,1891,1892,1903,1904,1941,1942,1943,1957,1960,1966,1969,1976,2004,2016,2034,2035,2054,2058,2059,2070,2078,2092,2093,2094,2095,2096,2097,2098,2107,2122,2136,2138,2139,2151,2152,2153,2159,2178,2180,2192,2195,2198,2203,2204,2220,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,3013,3256,3620],"required_bytes":109744181},"intellivision|freeintv":{"bytes":10240,"files":[1081,1209],"optional":[],"required_bytes":10240},"j2me|squirreljme":{"bytes":83146081,"files":[1125,1126,1127,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121],"optional":[3112,3113,3114,3115,3116,3117,3118,3119,3120,3121],"required_bytes":1656124},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"microsoft-xbox|xemu":{"bytes":3645624,"files":[73,74,75,1014,2325,3659],"optional":[73,74,75,1014,2325,3659],"required_bytes":0},"msx1|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msxturbor|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|bluemsx":{"bytes":13300736,"files":[40,41,49,54,60,78,79,81,82,92,93,94,95,96,103,105,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,178,179,181,182,183,184,209,242,243,255,1129,1130,1131,1132,1133,1134,1135,1136,1137,2537,2538,2539,2659,3682],"optional":[49,60,78,81,92,94,95,122,123,127,128,129,134,138,139,142,143,144,145,146,147,148,149,150,152,153,154,155,158,159,160,161,162,163,164,165,166,178,179,181,182,183,184,242,243,255,1129,1130,1131,1132,1133,1134,1135,1137,2537,2538,2539,2659,3682],"required_bytes":1152000},"nec-pc-88|quasi88":{"bytes":2508802,"files":[97,104,170,171,172,173,174,175,176,177,946,2437,2438,2439,2440,2441,2442,2443,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844],"optional":[97,104,170,171,172,173,174,175,176,177,946,2439,2440,2441,2832,2833,2834,2837,2838,2839,2840,2841,2842,2843,2844],"required_bytes":245760},"nec-pc-engine-cd|beetle_pce":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|beetle_pce":{"bytes":1343488,"files":[1191,3175,3176,3177,3178,3179],"optional":[1191,3175,3176,3177,3179],"required_bytes":262144},"nec-pcfx|beetle_pcfx":{"bytes":4718592,"files":[1177,2627,2628,2629,2630],"optional":[],"required_bytes":4718592},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":2709646,"files":[413,3716],"optional":[413],"required_bytes":1859335},"nintendo-3ds|azahar":{"bytes":6422431,"files":[414,2479,2480,2481,3180,3181,3182,3183,3709,3710,3711,3712,3713,3714,3715],"optional":[2479,2480,2481,3180,3181,3182,3183,3709,3710,3711,3712,3713,3714,3715],"required_bytes":7357},"nintendo-64dd|parallel_n64":{"bytes":4194304,"files":[33],"optional":[],"required_bytes":4194304},"nintendo-64|mupen64plus_next":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-ds|desmume":{"bytes":413696,"files":[651,652,662,663,1116],"optional":[],"required_bytes":413696},"nintendo-fds|mesen":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-gamecube|dolphin":{"bytes":12582912,"files":[85,86,87,965,966,967],"optional":[85,86,87,965,966,967],"required_bytes":0},"nintendo-gamecube|primehack":{"bytes":6291456,"files":[85,86,87],"optional":[85,86,87],"required_bytes":0},"nintendo-gba|mgba":{"bytes":16384,"files":[1186],"optional":[],"required_bytes":16384},"nintendo-gbc|gambatte":{"bytes":2304,"files":[1187],"optional":[],"required_bytes":2304},"nintendo-gb|gambatte":{"bytes":256,"files":[1185],"optional":[],"required_bytes":256},"nintendo-nes|mesen":{"bytes":1280062,"files":[169,180,244,951],"optional":[169,180,244,951],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[648],"optional":[648],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sgb|mesen-s":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-snes|snes9x":{"bytes":5289728,"files":[51,52,53,239,240,241,886,992,993,994,995,996,997,998,999,1000,3004,3005,3006,3007,3008,3041,3127,3128,3129,3130,3131],"optional":[51,52,53,241],"required_bytes":1881856},"nintendo-sufami-turbo|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-switch|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wiiu|cemu":{"bytes":156415016,"files":[61,62,63,64,65,66,67,68,69,70,71,72,730,731,732,733,764,1368,2580,2874,2875,2876,2877,2983,3015,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778],"optional":[61,62,63,64,66,67,68,69,70,71,72,730,731,732,733,2580,2874,2875,2876,2877,2983,3015,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778],"required_bytes":1348521},"nintendo-wii|dolphin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wii|primehack":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[704,1178,1339,2566,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618],"optional":[1178,1339],"required_bytes":1604273},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"oric|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"palm-os|mu":{"bytes":40108544,"files":[675,2588,2589,2590,2591],"optional":[675,2588,2590,2591],"required_bytes":4194304},"panasonic-3do|opera":{"bytes":13123332,"files":[28,1198,2570,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2934],"optional":[28,1198,2570,2593,2594,2595,2596,2597,2600,2601,2934],"required_bytes":3030788},"pc-98|np2kai":{"bytes":2453192,"files":[18,19,20,21,22,23,83,649,653,899,1120,1333,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,3053],"optional":[18,19,20,21,22,23,653,899,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561],"required_bytes":960574},"philips-cdi|same_cdi":{"bytes":5445698,"files":[751,752,753,754,755,756,2660,2928,2929,2930,2931,3686,3687,3690,3691],"optional":[751,752,753,754,755,756,2660,2928,2929,2931,3686,3687,3690,3691],"required_bytes":745703},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|lexaloffle":{"bytes":28859725,"files":[2661,2662,2663],"optional":[],"required_bytes":28859725},"quake|tyrquake":{"bytes":159899459,"files":[1280,2845,2846,2847],"optional":[2846,2847],"required_bytes":66916006},"rpgmaker|easyrpg":{"bytes":148398498,"files":[1008,3658],"optional":[1008,3658],"required_bytes":0},"sammy-atomiswave|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"scummvm|scummvm":{"bytes":81083844,"files":[2966,2967,2968,2969,2970],"optional":[2967,2968,2969,2970],"required_bytes":79379908},"scv|mame":{"bytes":94503326,"files":[569,705,708,1447,1449,1450,1451,1452,1453,1454,1455,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1474,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1502,1503,1504,1505,1509,1513,1514,1515,1516,1517,1518,1519,1520,1525,1526,1527,1528,1529,1530,1531,1547,1551,1552,1553,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1578,1579,1581,1582,1583,1584,1585,1586,1587,1589,1590,1591,1592,1593,1595,1596,1597,1598,1599,1604,1605,1606,1607,1608,1609,1610,1612,1613,1614,1615,1616,1617,1618,1620,1621,1622,1623,1624,1625,1631,1633,1634,1635,1636,1642,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1662,1663,1664,1665,1666,1667,1668,1670,1672,1673,1674,1676,1677,1678,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1696,1697,1698,1699,1700,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1772,1773,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1802,1803,1804,1805,1806,1807,1809,1810,1811,1812,1813,1814,1815,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1958,1959,1961,1962,1963,1964,1965,1967,1968,1970,1971,1972,1973,1974,1975,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2071,2072,2073,2074,2075,2076,2077,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2099,2100,2101,2102,2103,2104,2105,2106,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2137,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2154,2155,2156,2157,2158,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2179,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2193,2194,2196,2197,2199,2200,2201,2202,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2971,3013,3256,3295,3620],"optional":[569,705,708,2054,2971,3013,3256,3295,3620],"required_bytes":94417006},"sega-32x|picodrive":{"bytes":19695,"files":[24,25,26,736],"optional":[24,25,26,736],"required_bytes":0},"sega-dreamcast|flycast":{"bytes":27286439,"files":[904,905,906,907,908,909,910,911,912,913,914,915],"optional":[908,914],"required_bytes":20132866},"sega-gamegear|gearsystem":{"bytes":1024,"files":[647],"optional":[647],"required_bytes":0},"sega-gamegear|genesis_plus_gx":{"bytes":1024,"files":[647],"optional":[647],"required_bytes":0},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":16384,"files":[650,658],"optional":[],"required_bytes":16384},"sega-mastersystem|genesis_plus_gx":{"bytes":32768,"files":[650,657,658,660],"optional":[657,660],"required_bytes":16384},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[654,655,656],"optional":[],"required_bytes":393216},"sega-megadrive|genesis_plus_gx":{"bytes":2444622,"files":[510,659,1194,2890,3027,3028],"optional":[],"required_bytes":2444622},"sega-model2|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomi2|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomigd|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomi|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-saturn|beetle_saturn":{"bytes":12398703,"files":[1251,2367,2378,2379,2380,2381,2935,2937,2984,2986,2987,2988,3140,3627],"optional":[1251,2367,2379,2935,2986,2987,3627],"required_bytes":8990831},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-sg1000|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-stv|kronos":{"bytes":3455065,"files":[1393],"optional":[],"required_bytes":3455065},"sega-triforce|dolphin":{"bytes":408492481,"files":[84,88,89,90,91,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,245,250,251,252,253,254,968,969,970,971,972,3701,3702,3703,3704,3705,3706,3707,3717,3718,3719,3720,3721,3722,3723],"optional":[84,88,89,90,91,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,250,251,252,253,254,968,969,970,971,3701,3702,3703,3704,3705,3706,3707,3717,3718,3719,3720,3721,3722,3723],"required_bytes":4194304},"sharp-x1|x1":{"bytes":349184,"files":[3669,3670,3671,3672,3673],"optional":[3669,3670,3671,3672,3673],"required_bytes":0},"sharp-x68000|px68k":{"bytes":2752512,"files":[780,1297,1298,1299,1300,1301,1363,1364,1365,1366,1367],"optional":[1298,1299,1300,1301,1365,1366,1367],"required_bytes":1835008},"sinclair-zx-spectrum|fuse":{"bytes":996720,"files":[9,10,11,12,14,15,16,17,945,949,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1196,1285,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2976,2977,3061,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3263,3694,3695],"optional":[9,10,11,12,14,15,16,17,945,949,1196,1285,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2976,2977,3061,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3263,3694,3695],"required_bytes":514048},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":10616832,"files":[8,1128,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,3258,3290],"optional":[8,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,3290],"required_bytes":4718592},"snk-ngpc|beetle_ngp":{"bytes":65536,"files":[2533],"optional":[2533],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":65536,"files":[2532],"optional":[2532],"required_bytes":0},"solarus|solarus":{"bytes":600521,"files":[1183],"optional":[1183],"required_bytes":0},"sony-playstation-2|pcsx2":{"bytes":408963140,"files":[220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,1015,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2790,2791,2953,2955],"optional":[230,1015,2776],"required_bytes":408953860},"sony-playstation-3|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation-vita|vita3k":{"bytes":190612992,"files":[2799,2800],"optional":[2799],"required_bytes":133834240},"sony-playstation|swanstation":{"bytes":11010048,"files":[2698,2803,2944,2945,2946,2947,2948,2949,2950,2951,2952,2954,2956,2957,2958,2959,2960,2961,2962,2963,2964],"optional":[],"required_bytes":11010048},"sony-psp|ppsspp":{"bytes":666530,"files":[2688],"optional":[2688],"required_bytes":0},"spectravideo|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"supracan|mame":{"bytes":133496902,"files":[925,1024,1025,1026,1027,1028,1029,1030,1059,1078,1188,1249,1328,1340,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2685,2686,2687,3145,3185,3189,3289],"optional":[1448,1456,1457,1458,1471,1472,1473,1475,1500,1501,1506,1507,1508,1510,1511,1512,1521,1522,1523,1524,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1548,1549,1550,1554,1576,1577,1580,1588,1594,1600,1601,1602,1603,1611,1619,1626,1627,1628,1629,1630,1632,1637,1638,1639,1640,1641,1643,1644,1645,1648,1658,1659,1660,1661,1669,1671,1675,1679,1694,1695,1701,1722,1771,1774,1775,1796,1797,1798,1799,1800,1801,1808,1816,1891,1892,1903,1904,1941,1942,1943,1957,1960,1966,1969,1976,2004,2016,2034,2035,2054,2058,2059,2070,2078,2092,2093,2094,2095,2096,2097,2098,2107,2122,2136,2138,2139,2151,2152,2153,2159,2178,2180,2192,2195,2198,2203,2204,2220,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,3145,3289],"required_bytes":109744181},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ti99|mame":{"bytes":21377,"files":[3225],"optional":[],"required_bytes":21377},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tiger-game-com|mame":{"bytes":133969245,"files":[569,705,708,925,1024,1025,1026,1027,1028,1029,1030,1059,1078,1088,1182,1188,1249,1292,1328,1340,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2685,2686,2687,3013,3185,3189,3256,3620],"optional":[569,705,708,1088,1182,1292,1448,1456,1457,1458,1471,1472,1473,1475,1500,1501,1506,1507,1508,1510,1511,1512,1521,1522,1523,1524,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1548,1549,1550,1554,1576,1577,1580,1588,1594,1600,1601,1602,1603,1611,1619,1626,1627,1628,1629,1630,1632,1637,1638,1639,1640,1641,1643,1644,1645,1648,1658,1659,1660,1661,1669,1671,1675,1679,1694,1695,1701,1722,1771,1774,1775,1796,1797,1798,1799,1800,1801,1808,1816,1891,1892,1903,1904,1941,1942,1943,1957,1960,1966,1969,1976,2004,2016,2034,2035,2054,2058,2059,2070,2078,2092,2093,2094,2095,2096,2097,2098,2107,2122,2136,2138,2139,2151,2152,2153,2159,2178,2180,2192,2195,2198,2203,2204,2220,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,3013,3256,3620],"required_bytes":109744181},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":12288,"files":[246,247],"optional":[246,247],"required_bytes":0},"vircon32|vircon32":{"bytes":1073060,"files":[248],"optional":[248],"required_bytes":0},"vtech-vsmile|mame":{"bytes":106205669,"files":[569,705,708,1447,1449,1450,1451,1452,1453,1454,1455,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1474,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1502,1503,1504,1505,1509,1513,1514,1515,1516,1517,1518,1519,1520,1525,1526,1527,1528,1529,1530,1531,1547,1551,1552,1553,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1578,1579,1581,1582,1583,1584,1585,1586,1587,1589,1590,1591,1592,1593,1595,1596,1597,1598,1599,1604,1605,1606,1607,1608,1609,1610,1612,1613,1614,1615,1616,1617,1618,1620,1621,1622,1623,1624,1625,1631,1633,1634,1635,1636,1642,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1662,1663,1664,1665,1666,1667,1668,1670,1672,1673,1674,1676,1677,1678,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1696,1697,1698,1699,1700,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1772,1773,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1802,1803,1804,1805,1806,1807,1809,1810,1811,1812,1813,1814,1815,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1958,1959,1961,1962,1963,1964,1965,1967,1968,1970,1971,1972,1973,1974,1975,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2055,2056,2057,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2071,2072,2073,2074,2075,2076,2077,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2099,2100,2101,2102,2103,2104,2105,2106,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2137,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2154,2155,2156,2157,2158,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2179,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,3013,3256,3620,3628,3629,3630,3631],"optional":[569,705,708,2195,2198,3013,3256,3620,3628,3629,3630,3631],"required_bytes":94417006},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":178755,"files":[1013],"optional":[],"required_bytes":178755},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
+{"files":[["arcade/hiscore.dat",322458,"bios"],["atari2600/stella/KVB1.WAV",4219542,"game_data"],["atari2600/stella/KVB2.WAV",9593878,"game_data"],["atari2600/stella/KVB3.WAV",7676992,"game_data"],["atari2600/stella/KVS1.WAV",3436329,"game_data"],["atari2600/stella/KVS2.WAV",2086275,"game_data"],["atari2600/stella/KVS3.WAV",3720920,"game_data"],["atari2600/stella/KVSHARED.WAV",3059116,"game_data"],["bios/000-lo.lo",131072,"bios"],["bios/128-spanish-0.rom",16384,"bios"],["bios/128-spanish-1.rom",16384,"bios"],["bios/128p-0.rom",16384,"bios"],["bios/128p-1.rom",16384,"bios"],["bios/22vp931.zip",1405,"bios"],["bios/256s-0.rom",16384,"bios"],["bios/256s-1.rom",16384,"bios"],["bios/256s-2.rom",16384,"bios"],["bios/256s-3.rom",16384,"bios"],["bios/2608_BD.WAV",19192,"bios"],["bios/2608_HH.WAV",36722,"bios"],["bios/2608_RIM.WAV",5288,"bios"],["bios/2608_SD.WAV",15558,"bios"],["bios/2608_TOM.WAV",23092,"bios"],["bios/2608_TOP.WAV",57016,"bios"],["bios/32X_G_BIOS.BIN",256,"bios"],["bios/32X_M_BIOS.BIN",2048,"bios"],["bios/32X_S_BIOS.BIN",1024,"bios"],["bios/3c505.zip",10896,"bios"],["bios/3do_arcade_saot.bin",524288,"bios"],["bios/3dobios.zip",2351546,"bios"],["bios/3xtwin.zip",1417,"bios"],["bios/4dparprn.zip",480212,"bios"],["bios/5200.rom",2048,"bios"],["bios/64DD_IPL.bin",4194304,"bios"],["bios/64_cspeech.zip",2011,"bios"],["bios/7800 BIOS (E).rom",16384,"bios"],["bios/7800 BIOS (U).rom",4096,"bios"],["bios/82c606.zip",479847,"bios"],["bios/A78_highscore.bin",16364,"bios"],["bios/APPLE2GS.ROM",131072,"bios"],["bios/ARAB1.ROM",32768,"bios"],["bios/ARABIC.rom",32768,"bios"],["bios/ATARIBAS.ROM",8192,"bios"],["bios/ATARIOSA.ROM",10240,"bios"],["bios/ATARIOSB.ROM",10240,"bios"],["bios/ATARIXL.ROM",16384,"bios"],["bios/AmigaVision.rom",524288,"bios"],["bios/Atari Jaguar (World).j64",131072,"bios"],["bios/BB01R4_OS.ROM",16384,"bios"],["bios/BEERIDE.ROM",16384,"bios"],["bios/BIOS.col",8192,"bios"],["bios/BS-X (En) (DRM-Free).bin",1048576,"bios"],["bios/BS-X (En).bin",1048576,"bios"],["bios/BS-X.bin",1048576,"bios"],["bios/CARTS.SHA",33152,"bios"],["bios/CCNPATCH.cas",1481,"bios"],["bios/CCNPATCH.wav",71748,"bios"],["bios/CM32LN_CONTROL.ROM",65536,"bios"],["bios/CM32L_CONTROL.ROM",65536,"bios"],["bios/CM32L_PCM.ROM",1048576,"bios"],["bios/CYRILLIC.FNT",2048,"bios"],["bios/Cemu/cafeLibs/erreula.rpl",790080,"bios"],["bios/Cemu/cafeLibs/snd_user.rpl",84032,"bios"],["bios/Cemu/cafeLibs/snduser2.rpl",111360,"bios"],["bios/Cemu/cafeLibs/swkbd.rpl",1116288,"bios"],["bios/Cemu/keys.txt",449507,"bios"],["bios/Cemu/otp.bin",1024,"bios"],["bios/Cemu/resources/sharedFonts/CafeCn.ttf",9664448,"bios"],["bios/Cemu/resources/sharedFonts/CafeKr.ttf",5626464,"bios"],["bios/Cemu/resources/sharedFonts/CafeStd.ttf",5363768,"bios"],["bios/Cemu/resources/sharedFonts/CafeTw.ttf",6593548,"bios"],["bios/Cemu/seeprom.bin",512,"bios"],["bios/Cemu/shareddata.bin",33554432,"bios"],["bios/Complex.bin",1048576,"bios"],["bios/Complex_4627.bin",1048576,"bios"],["bios/Complex_4627v1.03.bin",1048576,"bios"],["bios/DBPATCH.cas",1481,"bios"],["bios/DBPATCH.wav",71900,"bios"],["bios/DEFAULT.FNT",2048,"bios"],["bios/DISK.ROM",16384,"bios"],["bios/DOSBOX.SF2",32319396,"bios"],["bios/FMPAC.ROM",65536,"bios"],["bios/FMPAC16.ROM",33152,"bios"],["bios/FONT.ROM",288768,"bios"],["bios/GBA/gba_bios.bin",16384,"bios"],["bios/GC/EUR/IPL.bin",2097152,"bios"],["bios/GC/JAP/IPL.bin",2097152,"bios"],["bios/GC/USA/IPL.bin",2097152,"bios"],["bios/GC/dsp_coef.bin",4096,"bios"],["bios/GC/dsp_rom.bin",8192,"bios"],["bios/GC/font_japanese.bin",259626,"bios"],["bios/GC/font_western.bin",6478,"bios"],["bios/GCVMX80.ROM",8192,"bios"],["bios/HANGUL.rom",131072,"bios"],["bios/INTERNAT.FNT",2048,"bios"],["bios/ITALIC.FNT",2048,"bios"],["bios/JAPANESE.FNT",2048,"bios"],["bios/JISYO.ROM",524288,"bios"],["bios/JiffyDOS_1541-II.bin",16384,"bios"],["bios/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/JiffyDOS_1581.bin",32768,"bios"],["bios/JiffyDOS_C64.bin",8192,"bios"],["bios/JiffyDOS_SX-64.bin",8192,"bios"],["bios/KANJI.ROM",131072,"bios"],["bios/KANJI1.ROM",131072,"bios"],["bios/KOREAN.FNT",2048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723a_fw.bin",24548,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723b_fw.bin",45048,"bios"],["bios/Load/Firmware/rtl_bt/rtl8723d_fw.bin",52080,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761a_fw.bin",74488,"bios"],["bios/Load/Firmware/rtl_bt/rtl8761bu_fw.bin",44484,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821a_fw.bin",37420,"bios"],["bios/Load/Firmware/rtl_bt/rtl8821c_fw.bin",54636,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822b_fw.bin",51176,"bios"],["bios/Load/Firmware/rtl_bt/rtl8822cu_fw.bin",38207,"bios"],["bios/Load/Firmware/rtl_bt/rtl8851bu_fw.bin",49760,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852au_fw.bin",67188,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852btu_fw.bin",128140,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852bu_fw.bin",129733,"bios"],["bios/Load/Firmware/rtl_bt/rtl8852cu_fw.bin",113336,"bios"],["bios/Load/Firmware/rtl_bt/rtl8922au_fw.bin",71360,"bios"],["bios/Load/WiiSD.raw",134217728,"bios"],["bios/MICROSOLDISK.ROM",16384,"bios"],["bios/MOONSOUND.rom",2097152,"bios"],["bios/MSX.ROM",32768,"bios"],["bios/MSX2.ROM",32768,"bios"],["bios/MSX2AR.ROM",32768,"bios"],["bios/MSX2AREXT.ROM",16384,"bios"],["bios/MSX2BR.rom",32768,"bios"],["bios/MSX2BREXT.rom",16384,"bios"],["bios/MSX2EXT.ROM",16384,"bios"],["bios/MSX2FR.rom",32768,"bios"],["bios/MSX2FREXT.rom",16384,"bios"],["bios/MSX2G.rom",32768,"bios"],["bios/MSX2GEXT.rom",16384,"bios"],["bios/MSX2HAN.rom",32768,"bios"],["bios/MSX2J.rom",32768,"bios"],["bios/MSX2JEXT.rom",16384,"bios"],["bios/MSX2KR.rom",32768,"bios"],["bios/MSX2KREXT.rom",32768,"bios"],["bios/MSX2P.ROM",32768,"bios"],["bios/MSX2PEXT.ROM",16384,"bios"],["bios/MSX2PMUS.rom",16384,"bios"],["bios/MSX2R.rom",32768,"bios"],["bios/MSX2R2.ROM",32768,"bios"],["bios/MSX2REXT.rom",16384,"bios"],["bios/MSX2SE.rom",32768,"bios"],["bios/MSX2SP.rom",32768,"bios"],["bios/MSX2SPEXT.rom",16384,"bios"],["bios/MSXAR.ROM",32768,"bios"],["bios/MSXBR.rom",32768,"bios"],["bios/MSXDOS2.ROM",65536,"bios"],["bios/MSXDOS23.ROM",65536,"bios"],["bios/MSXFR.rom",32768,"bios"],["bios/MSXG.rom",32768,"bios"],["bios/MSXHAN.rom",8192,"bios"],["bios/MSXJ.rom",32768,"bios"],["bios/MSXKANJI.rom",32768,"bios"],["bios/MSXKR.rom",32768,"bios"],["bios/MSXR.rom",32768,"bios"],["bios/MSXR2.rom",32768,"bios"],["bios/MSXSE.ROM",32768,"bios"],["bios/MSXSP.ROM",32768,"bios"],["bios/MSXTR.ROM",32768,"bios"],["bios/MSXTREXT.ROM",16384,"bios"],["bios/MSXTRMUS.ROM",16384,"bios"],["bios/MSXTROPT.ROM",16384,"bios"],["bios/MT32_CONTROL.ROM",65536,"bios"],["bios/MT32_PCM.ROM",524288,"bios"],["bios/MesenPalette.pal",192,"bios"],["bios/N80.ROM",32768,"bios"],["bios/N88EXT0.ROM",8192,"bios"],["bios/N88EXT1.ROM",8192,"bios"],["bios/N88EXT2.ROM",8192,"bios"],["bios/N88EXT3.ROM",8192,"bios"],["bios/N88JISHO.ROM",524288,"bios"],["bios/N88KNJ2.ROM",131072,"bios"],["bios/N88SUB.ROM",2048,"bios"],["bios/NATIONALDISK.rom",16384,"bios"],["bios/NOVAXIS.rom",16384,"bios"],["bios/NstDatabase.xml",1009534,"bios"],["bios/PAINT.rom",65536,"bios"],["bios/PAINTER.ROM",65536,"bios"],["bios/PANASONICDISK.rom",16384,"bios"],["bios/PHILIPSDISK.rom",16384,"bios"],["bios/ProSystem.dat",16364,"bios"],["bios/ROM.ROM",262144,"bios"],["bios/ROM03.ROM",262144,"bios"],["bios/ROM_400/800_CUSTOM",10240,"bios"],["bios/ROM_5200",2048,"bios"],["bios/ROM_5200_A",2048,"bios"],["bios/ROM_BASIC_A",8192,"bios"],["bios/ROM_BASIC_B",8192,"bios"],["bios/ROM_BASIC_C",8192,"bios"],["bios/ROM_OS_AA00R10",16384,"bios"],["bios/ROM_OS_AA00R11",16384,"bios"],["bios/ROM_OS_A_NTSC",10240,"bios"],["bios/ROM_OS_A_PAL",10240,"bios"],["bios/ROM_OS_BB00R1",16384,"bios"],["bios/ROM_OS_BB01R2",16384,"bios"],["bios/ROM_OS_BB01R3",16384,"bios"],["bios/ROM_OS_BB01R4",16384,"bios"],["bios/ROM_OS_BB01R59",16384,"bios"],["bios/ROM_OS_BB01R59A",16384,"bios"],["bios/ROM_OS_BB02R3",16384,"bios"],["bios/ROM_OS_BB02R3V4",16384,"bios"],["bios/ROM_OS_B_NTSC",10240,"bios"],["bios/ROM_OS_CC01R4",16384,"bios"],["bios/ROM_XEGAME",8192,"bios"],["bios/RS232.ROM",16640,"bios"],["bios/SC-55-v1.00/sc55_rom1.bin",32768,"bios"],["bios/SC-55-v1.00/sc55_rom2.bin",262144,"bios"],["bios/SC-55-v1.00/sc55_waverom1.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom2.bin",1048576,"bios"],["bios/SC-55-v1.00/sc55_waverom3.bin",1048576,"bios"],["bios/SC-55/ROM1.BIN",32768,"bios"],["bios/SC-55/ROM2.BIN",524288,"bios"],["bios/SC-55/ROM_SM.BIN",4096,"bios"],["bios/SC-55/WAVEROM1.BIN",2097152,"bios"],["bios/SC-55/WAVEROM2.BIN",1048576,"bios"],["bios/SCPH-10000.bin",4194304,"bios"],["bios/SCPH-10000.mec",4,"bios"],["bios/SCPH-30004R.bin",4194304,"bios"],["bios/SCPH-39001.bin",4194304,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.BIN",4194304,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.nvm",1024,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.rom1",524288,"bios"],["bios/SCPH-50009_BIOS_V10_CHN_190.rom2",524288,"bios"],["bios/SCPH-70004.BIN",4194304,"bios"],["bios/SCPH-70004.rom1",524288,"bios"],["bios/SCPH-70004_BIOS_V12_EUR_200.rom2",8192,"bios"],["bios/SCPH-70006_BIOS_V12_HK_200.nvm",1024,"bios"],["bios/SCPH-70008_BIOS_V12_RUS_200.BIN",4194304,"bios"],["bios/SCPH-70008_BIOS_V12_RUS_200.nvm",1024,"bios"],["bios/SCPH-75008_BIOS_V14_RUS_220.nvm",1024,"bios"],["bios/SCPH-77008_BIOS_V15_RUS_220.nvm",1024,"bios"],["bios/SCPH-90006_BIOS_VX_HK _230.nvm",1024,"bios"],["bios/SCPH-90006_BIOS_VX_HK _230.rom1",524288,"bios"],["bios/SCPH30004R.nvm",1024,"bios"],["bios/SGB1.sfc",262144,"bios"],["bios/SGB2.sfc",524288,"bios"],["bios/STBIOS.bin",262144,"bios"],["bios/SUNRISEIDE.rom",65536,"bios"],["bios/SWP.rom",32768,"bios"],["bios/StudyBox.bin",262144,"bios"],["bios/Triforce/segaboot.gcm",2097152,"bios"],["bios/VEC_MineStorm.vec",8192,"bios"],["bios/Vectrex_Bios.bin",4096,"bios"],["bios/Vircon32Bios.v32",1073060,"bios"],["bios/WHDLoad.prefs",1935,"bios"],["bios/Wii/clientca.pem",1005,"bios"],["bios/Wii/clientcakey.pem",609,"bios"],["bios/Wii/rootca.pem",897,"bios"],["bios/Wii/shared2/sys/SYSCONF",16384,"bios"],["bios/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["bios/XBASIC2.rom",16384,"bios"],["bios/XEGAME.ROM",8192,"bios"],["bios/[BIOS] Atari Jaguar CD (World).j64",262144,"bios"],["bios/[BIOS] Atari Jaguar Developer CD (World).j64",262144,"bios"],["bios/a1000kbd_de.zip",1331,"bios"],["bios/a1000kbd_dk.zip",1331,"bios"],["bios/a1000kbd_fr.zip",1331,"bios"],["bios/a1000kbd_gb.zip",1331,"bios"],["bios/a1000kbd_it.zip",1331,"bios"],["bios/a1000kbd_se.zip",1331,"bios"],["bios/a1000kbd_us.zip",1331,"bios"],["bios/a1200kbd_rb.zip",1476,"bios"],["bios/a1cass.zip",509,"bios"],["bios/a2000kbd_ch.zip",1335,"bios"],["bios/a2000kbd_de.zip",1335,"bios"],["bios/a2000kbd_dk.zip",1335,"bios"],["bios/a2000kbd_es.zip",1335,"bios"],["bios/a2000kbd_fr.zip",1335,"bios"],["bios/a2000kbd_g80_de.zip",1151,"bios"],["bios/a2000kbd_g80_dk.zip",1151,"bios"],["bios/a2000kbd_g80_gb.zip",1151,"bios"],["bios/a2000kbd_g80_se.zip",1151,"bios"],["bios/a2000kbd_g80_us.zip",1151,"bios"],["bios/a2000kbd_gb.zip",1335,"bios"],["bios/a2000kbd_it.zip",1335,"bios"],["bios/a2000kbd_no.zip",1335,"bios"],["bios/a2000kbd_se.zip",1335,"bios"],["bios/a2000kbd_us.zip",1335,"bios"],["bios/a2aevm80.zip",2540,"bios"],["bios/a2ap16.zip",2649,"bios"],["bios/a2ap16a.zip",2549,"bios"],["bios/a2aplcrd.zip",1188,"bios"],["bios/a2autokbd.zip",1363,"bios"],["bios/a2booti.zip",3578,"bios"],["bios/a2bufgrapplerplus.zip",483416,"bios"],["bios/a2bufgrapplerplusa.zip",483416,"bios"],["bios/a2bus_byte8251.zip",95177,"bios"],["bios/a2cffa02.zip",2371,"bios"],["bios/a2cffa2.zip",1153946,"bios"],["bios/a2corvus.zip",1590,"bios"],["bios/a2diskiing.zip",371,"bios"],["bios/a2excel9.zip",7157,"bios"],["bios/a2focdrv.zip",1651,"bios"],["bios/a2grafex.zip",367,"bios"],["bios/a2grappler.zip",481339,"bios"],["bios/a2grapplerplus.zip",485390,"bios"],["bios/a2hsscsi.zip",11374,"bios"],["bios/a2ieee488.zip",39523,"bios"],["bios/a2iwm.zip",371,"bios"],["bios/a2kb200.zip",1144,"bios"],["bios/a2memexp.zip",2174,"bios"],["bios/a2mouse.zip",2836,"bios"],["bios/a2parprn.zip",354,"bios"],["bios/a2pdromdr.zip",666891,"bios"],["bios/a2pic.zip",519,"bios"],["bios/a2q68.zip",5474,"bios"],["bios/a2q68plus.zip",5474,"bios"],["bios/a2ramfac.zip",16155,"bios"],["bios/a2romfp.zip",11102,"bios"],["bios/a2romint.zip",12783,"bios"],["bios/a2scsi.zip",786942,"bios"],["bios/a2sd.zip",1282,"bios"],["bios/a2sic.zip",1867,"bios"],["bios/a2sider1.zip",779735,"bios"],["bios/a2sider2.zip",778704,"bios"],["bios/a2ssc.zip",96978,"bios"],["bios/a2superdrive.zip",10883,"bios"],["bios/a2suprterm.zip",1864,"bios"],["bios/a2surance.zip",3321,"bios"],["bios/a2swyft.zip",11515,"bios"],["bios/a2thunpl.zip",998,"bios"],["bios/a2tk10.zip",1541,"bios"],["bios/a2tmstho.zip",1217,"bios"],["bios/a2twarp.zip",2309,"bios"],["bios/a2ultrme.zip",3652,"bios"],["bios/a2ulttrm.zip",3746,"bios"],["bios/a2uniprint.zip",481948,"bios"],["bios/a2vidtrm.zip",10620,"bios"],["bios/a2vistaa800.zip",790,"bios"],["bios/a2vtc1.zip",2062,"bios"],["bios/a2vulcan.zip",1155306,"bios"],["bios/a2vulgld.zip",1157284,"bios"],["bios/a2vuliie.zip",1155276,"bios"],["bios/a2zipdrv.zip",1154563,"bios"],["bios/a3fdc.zip",262,"bios"],["bios/a500kbd_ch.zip",1335,"bios"],["bios/a500kbd_de.zip",1335,"bios"],["bios/a500kbd_dk.zip",1335,"bios"],["bios/a500kbd_es.zip",1335,"bios"],["bios/a500kbd_fr.zip",1335,"bios"],["bios/a500kbd_gb.zip",1335,"bios"],["bios/a500kbd_it.zip",1335,"bios"],["bios/a500kbd_no.zip",1335,"bios"],["bios/a500kbd_se.zip",1335,"bios"],["bios/a500kbd_us.zip",1335,"bios"],["bios/a600kbd_ch.zip",1335,"bios"],["bios/a600kbd_de.zip",1335,"bios"],["bios/a600kbd_dk.zip",1335,"bios"],["bios/a600kbd_es.zip",1335,"bios"],["bios/a600kbd_fr.zip",1335,"bios"],["bios/a600kbd_gb.zip",1335,"bios"],["bios/a600kbd_it.zip",1335,"bios"],["bios/a600kbd_no.zip",1335,"bios"],["bios/a600kbd_se.zip",1335,"bios"],["bios/a600kbd_us.zip",1335,"bios"],["bios/a7ports.zip",479847,"bios"],["bios/aa310.zip",6536273,"bios"],["bios/abc1600mac.zip",7345,"bios"],["bios/abc1600mover.zip",1347,"bios"],["bios/abc55.zip",1546,"bios"],["bios/abc77.zip",1546,"bios"],["bios/abc800kb.zip",1087,"bios"],["bios/abc80kb.zip",389,"bios"],["bios/abc830.zip",24177,"bios"],["bios/abc832.zip",24177,"bios"],["bios/abc834.zip",24177,"bios"],["bios/abc838.zip",24177,"bios"],["bios/abc850.zip",98610,"bios"],["bios/abc850flop.zip",24177,"bios"],["bios/abc852.zip",98610,"bios"],["bios/abc856.zip",98610,"bios"],["bios/abc890.zip",98610,"bios"],["bios/abc894.zip",98610,"bios"],["bios/abc99.zip",5285,"bios"],["bios/abc_db4106.zip",1696,"bios"],["bios/abc_db4107.zip",23643,"bios"],["bios/abc_db4112.zip",9945,"bios"],["bios/abc_fd2.zip",6129,"bios"],["bios/abc_slutprov.zip",509,"bios"],["bios/abc_ssa.zip",101707,"bios"],["bios/abc_uni800.zip",163,"bios"],["bios/abc_unidisk.zip",9386,"bios"],["bios/abcexp.zip",101707,"bios"],["bios/abcsio.zip",3201,"bios"],["bios/acb2072.zip",11517,"bios"],["bios/ace80.zip",1177,"bios"],["bios/ace_sp_reelctrl.zip",1966,"bios"],["bios/ace_sp_reelctrl_pcp.zip",1148,"bios"],["bios/acorn_vdu40.zip",536,"bios"],["bios/acorn_vdu80.zip",704,"bios"],["bios/acorn_vib.zip",574980,"bios"],["bios/acs8600_ics.zip",98064,"bios"],["bios/action2.wad",209908382,"game_data"],["bios/adam.zip",52891,"bios"],["bios/adam_ddp.zip",1595,"bios"],["bios/adam_fdc.zip",1609,"bios"],["bios/adam_fdc_320kb.zip",4716,"bios"],["bios/adam_fdc_a720dipi.zip",1671,"bios"],["bios/adam_fdc_fp720at.zip",1614,"bios"],["bios/adam_fdc_mihddd.zip",1807,"bios"],["bios/adam_ide.zip",1631404,"bios"],["bios/adam_kb.zip",1758,"bios"],["bios/adam_prn.zip",1644,"bios"],["bios/adam_spi.zip",576494,"bios"],["bios/adbmodem.zip",763,"bios"],["bios/adv071_u24.rom",8192,"bios"],["bios/adv072_u24.rom",8192,"bios"],["bios/adv073-2_u24.rom",8192,"bios"],["bios/aes.zip",850311,"bios"],["bios/aes_keys.txt",7357,"bios"],["bios/agat7_flop.zip",588,"bios"],["bios/agat840k_hle.zip",322,"bios"],["bios/agat9_flop.zip",589,"bios"],["bios/agat_fdc.zip",609,"bios"],["bios/aha1542a.zip",793450,"bios"],["bios/aha1542b.zip",862291,"bios"],["bios/aha1542c.zip",52938,"bios"],["bios/aha1542cf.zip",92027,"bios"],["bios/aha1542cp.zip",36978,"bios"],["bios/aha1740.zip",806698,"bios"],["bios/aha1742a.zip",835784,"bios"],["bios/aha2940.zip",38616,"bios"],["bios/aha2940au.zip",31135,"bios"],["bios/airlbios.zip",715730,"bios"],["bios/aleck64.zip",1804,"bios"],["bios/alg3do.zip",84346,"bios"],["bios/alg_bios.zip",143125,"bios"],["bios/allied.zip",2926,"bios"],["bios/alpha-basic.rom",16384,"bios"],["bios/alpha-boot-v0.4.rom",8192,"bios"],["bios/alpha-boot-v1.0.rom",8192,"bios"],["bios/alto2_cpu.zip",15499,"bios"],["bios/altos2_kbd.zip",695,"bios"],["bios/am100kbd.zip",2016,"bios"],["bios/amiga_a2091.zip",832812,"bios"],["bios/amiga_a2232.zip",95177,"bios"],["bios/amiga_a570.zip",171907,"bios"],["bios/amiga_a590.zip",847830,"bios"],["bios/amiga_ar1.zip",61074,"bios"],["bios/amiga_ar2.zip",193315,"bios"],["bios/amiga_ar3.zip",263916,"bios"],["bios/amiga_buddha.zip",1179140,"bios"],["bios/amiga_oktagon2008.zip",791783,"bios"],["bios/amiga_ripple.zip",1166737,"bios"],["bios/ampex230_kbd.zip",976,"bios"],["bios/ap2000.zip",21618,"bios"],["bios/aplcd150.zip",9137,"bios"],["bios/apple2gs.zip",174124,"bios"],["bios/aprissi.zip",100147,"bios"],["bios/aquarius_c1541.zip",1494391,"bios"],["bios/ar_bios.zip",681333,"bios"],["bios/arc_a448.zip",602,"bios"],["bios/arc_a448b.zip",836,"bios"],["bios/arc_acejoy.zip",1311,"bios"],["bios/arc_armadeus.zip",1014,"bios"],["bios/arc_bbcio_aga30.zip",20932,"bios"],["bios/arc_bbcio_aka10.zip",2859984,"bios"],["bios/arc_bbcio_we.zip",20876,"bios"],["bios/arc_eaglem2.zip",47500,"bios"],["bios/arc_econet.zip",560858,"bios"],["bios/arc_ether1_aka25.zip",163,"bios"],["bios/arc_ether2_aeh50.zip",378,"bios"],["bios/arc_ether3_aeh54.zip",50047,"bios"],["bios/arc_ethera.zip",149278,"bios"],["bios/arc_etherd.zip",105641,"bios"],["bios/arc_etherr.zip",49753,"bios"],["bios/arc_faxpack.zip",5826,"bios"],["bios/arc_greyhawk.zip",5265,"bios"],["bios/arc_hdisc_akd52.zip",421,"bios"],["bios/arc_hdisc_cw.zip",565,"bios"],["bios/arc_hdisc_morley.zip",1333,"bios"],["bios/arc_hdisc_we.zip",462,"bios"],["bios/arc_ide_be.zip",1175878,"bios"],["bios/arc_ide_rdev.zip",1158558,"bios"],["bios/arc_iomidi_aka15.zip",2861501,"bios"],["bios/arc_lark.zip",33629,"bios"],["bios/arc_lbp4.zip",494095,"bios"],["bios/arc_midi2.zip",12743,"bios"],["bios/arc_midi_aka16.zip",21857,"bios"],["bios/arc_midimax.zip",36846,"bios"],["bios/arc_midimax2.zip",21595,"bios"],["bios/arc_nexus_a500.zip",15560,"bios"],["bios/arc_rom_aka05.zip",4909,"bios"],["bios/arc_rom_r225.zip",107080,"bios"],["bios/arc_rs423.zip",95418,"bios"],["bios/arc_scan256.zip",9805,"bios"],["bios/arc_scanjunior.zip",6379,"bios"],["bios/arc_scanjunior3.zip",6965,"bios"],["bios/arc_scanlight.zip",7019,"bios"],["bios/arc_scanvideo.zip",25778,"bios"],["bios/arc_scsi_a500.zip",778041,"bios"],["bios/arc_scsi_aka30.zip",789744,"bios"],["bios/arc_scsi_aka31.zip",789848,"bios"],["bios/arc_scsi_aka32.zip",874373,"bios"],["bios/arc_scsi_cumana.zip",821877,"bios"],["bios/arc_scsi_ling.zip",829474,"bios"],["bios/arc_scsi_morley.zip",974849,"bios"],["bios/arc_scsi_oak.zip",863365,"bios"],["bios/arc_scsi_vti.zip",820278,"bios"],["bios/arc_serial.zip",98196,"bios"],["bios/arc_spectra.zip",2421,"bios"],["bios/arc_ua_morley.zip",21013,"bios"],["bios/arc_uma_morley.zip",29130,"bios"],["bios/arc_upa_hccs.zip",20775,"bios"],["bios/arc_upmidi_aka12.zip",17089,"bios"],["bios/archimedes_keyboard.zip",1323,"bios"],["bios/areplay.bin",32768,"bios"],["bios/aristmk5.zip",261435,"bios"],["bios/aristmk6.zip",22239668,"bios"],["bios/aristmk7.zip",524288,"bios"],["bios/arkanoid68705p3.zip",266,"bios"],["bios/arkanoid68705p5.zip",266,"bios"],["bios/asc88.zip",783706,"bios"],["bios/ascsasi.zip",779354,"bios"],["bios/astrocde.zip",6800,"bios"],["bios/astrocdl.zip",6805,"bios"],["bios/astrocdw.zip",6807,"bios"],["bios/at_keybc.zip",3655,"bios"],["bios/at_mb.zip",3655,"bios"],["bios/atari1050.zip",13755,"bios"],["bios/atari810.zip",3303,"bios"],["bios/atari_cage.zip",573,"bios"],["bios/atari_cage_seattle.zip",573,"bios"],["bios/atarisy1.zip",49385,"bios"],["bios/atom_discpack.zip",3459,"bios"],["bios/atom_econet.zip",560858,"bios"],["bios/atom_gdos.zip",3145,"bios"],["bios/atom_gdos2015.zip",6985,"bios"],["bios/atom_speech.zip",2019,"bios"],["bios/atom_tube.zip",314472,"bios"],["bios/atom_vdu80.zip",1074,"bios"],["bios/awbios.zip",42296,"bios"],["bios/ax208.zip",5590,"bios"],["bios/ax208p.zip",5598,"bios"],["bios/banshee_x86.zip",35460,"bios"],["bios/bas10.rom",8192,"bios"],["bios/bas11.rom",8192,"bios"],["bios/bas12.rom",8192,"bios"],["bios/bas13.rom",8192,"bios"],["bios/bas14.rom",8192,"bios"],["bios/basf7100_kbd.zip",456,"bios"],["bios/bbc_24bbc.zip",2844684,"bios"],["bios/bbc_2ndserial.zip",2844684,"bios"],["bios/bbc_acorn1770.zip",60692,"bios"],["bios/bbc_acorn8271.zip",164713,"bios"],["bios/bbc_ams3.zip",8252,"bios"],["bios/bbc_ariesb20.zip",2525,"bios"],["bios/bbc_ariesb32.zip",8935,"bios"],["bios/bbc_autoprom.zip",2737,"bios"],["bios/bbc_awhd.zip",2844684,"bios"],["bios/bbc_b488.zip",291066,"bios"],["bios/bbc_beebex.zip",480885,"bios"],["bios/bbc_beebide.zip",2844684,"bios"],["bios/bbc_beebspch.zip",6564,"bios"],["bios/bbc_bitstik1.zip",5798,"bios"],["bios/bbc_bitstik2.zip",5798,"bios"],["bios/bbc_cc500.zip",2844684,"bios"],["bios/bbc_chameleon.zip",654,"bios"],["bios/bbc_cisco.zip",13978,"bios"],["bios/bbc_cms6502.zip",17969,"bios"],["bios/bbc_cumana1.zip",10212,"bios"],["bios/bbc_cumana2.zip",11242,"bios"],["bios/bbc_cumana68k.zip",781787,"bios"],["bios/bbc_cv1797.zip",6453,"bios"],["bios/bbc_datacentre.zip",1191943,"bios"],["bios/bbc_detalker.zip",2019,"bios"],["bios/bbc_ide8.zip",1151601,"bios"],["bios/bbc_ieee488.zip",2844684,"bios"],["bios/bbc_integrab.zip",34749,"bios"],["bios/bbc_kenda.zip",6558,"bios"],["bios/bbc_lcd.zip",965,"bios"],["bios/bbc_m2000.zip",2844684,"bios"],["bios/bbc_m3000.zip",2844684,"bios"],["bios/bbc_m500.zip",2844684,"bios"],["bios/bbc_m5000.zip",2844684,"bios"],["bios/bbc_m87.zip",2844684,"bios"],["bios/bbc_magazzino.zip",11695,"bios"],["bios/bbc_memexb20.zip",1305,"bios"],["bios/bbc_mertec.zip",2869404,"bios"],["bios/bbc_meup.zip",8095,"bios"],["bios/bbc_morleyaa.zip",5048,"bios"],["bios/bbc_multiform.zip",11635,"bios"],["bios/bbc_opus1770.zip",24620,"bios"],["bios/bbc_opus2791.zip",47054,"bios"],["bios/bbc_opus2793.zip",24583,"bios"],["bios/bbc_opus3.zip",36996,"bios"],["bios/bbc_opus8272.zip",23119,"bios"],["bios/bbc_opusa.zip",23792,"bios"],["bios/bbc_pdram.zip",2195,"bios"],["bios/bbc_pms64k.zip",8361,"bios"],["bios/bbc_ramdisc.zip",2844684,"bios"],["bios/bbc_raven20.zip",4486,"bios"],["bios/bbc_sasi.zip",778041,"bios"],["bios/bbc_scsi.zip",778041,"bios"],["bios/bbc_scsiaiv.zip",778041,"bios"],["bios/bbc_stl1770_1.zip",12775,"bios"],["bios/bbc_stl1770_2.zip",12822,"bios"],["bios/bbc_stl2m128.zip",3298,"bios"],["bios/bbc_stl4m32.zip",11382,"bios"],["bios/bbc_stldfdc_1.zip",12504,"bios"],["bios/bbc_stlswr128.zip",11806,"bios"],["bios/bbc_stlswr16.zip",11806,"bios"],["bios/bbc_stlswr32.zip",11806,"bios"],["bios/bbc_stlswr64.zip",11806,"bios"],["bios/bbc_sweetalker.zip",2019,"bios"],["bios/bbc_tube_16032.zip",17960,"bios"],["bios/bbc_tube_32016.zip",31067,"bios"],["bios/bbc_tube_32016l.zip",3585,"bios"],["bios/bbc_tube_6502.zip",4337,"bios"],["bios/bbc_tube_6502e.zip",1515,"bios"],["bios/bbc_tube_6502p.zip",6023,"bios"],["bios/bbc_tube_65c102.zip",4375,"bios"],["bios/bbc_tube_80186.zip",6643,"bios"],["bios/bbc_tube_80286.zip",6649,"bios"],["bios/bbc_tube_a500.zip",12117,"bios"],["bios/bbc_tube_a500d.zip",12312,"bios"],["bios/bbc_tube_arm.zip",38022,"bios"],["bios/bbc_tube_arm7.zip",109910,"bios"],["bios/bbc_tube_casper.zip",18005,"bios"],["bios/bbc_tube_cms6809.zip",9090,"bios"],["bios/bbc_tube_matchbox.zip",48928,"bios"],["bios/bbc_tube_pcplus.zip",6662,"bios"],["bios/bbc_tube_rc6502.zip",31532,"bios"],["bios/bbc_tube_rc65816.zip",31259,"bios"],["bios/bbc_tube_x25.zip",17863,"bios"],["bios/bbc_tube_z80.zip",3197,"bios"],["bios/bbc_tube_z80w.zip",3145,"bios"],["bios/bbc_tube_zep100.zip",40985,"bios"],["bios/bbc_tube_zep100l.zip",18020,"bios"],["bios/bbc_tube_zep100m.zip",29188,"bios"],["bios/bbc_tube_zep100w.zip",29266,"bios"],["bios/bbc_udm.zip",44349,"bios"],["bios/bbc_usersplit.zip",8095,"bios"],["bios/bbc_voicebox.zip",2019,"bios"],["bios/bbc_we32kram.zip",22610,"bios"],["bios/bbc_weddb2.zip",35836,"bios"],["bios/bbc_weddb3.zip",11202,"bios"],["bios/bbcm.zip",400592,"bios"],["bios/bbcmc.zip",100096,"bios"],["bios/beebopl.zip",2844684,"bios"],["bios/beebsid.zip",2844684,"bios"],["bios/betadisk.zip",563424,"bios"],["bios/bingoct.zip",173688,"bios"],["bios/bios.gg",1024,"bios"],["bios/bios.min",4096,"bios"],["bios/bios.rom",98304,"bios"],["bios/bios.sms",8192,"bios"],["bios/bios7.bin",16384,"bios"],["bios/bios9.bin",4096,"bios"],["bios/bios9821.rom",8192,"bios"],["bios/bios_CD_E.bin",131072,"bios"],["bios/bios_CD_J.bin",131072,"bios"],["bios/bios_CD_U.bin",131072,"bios"],["bios/bios_E.sms",8192,"bios"],["bios/bios_J.sms",8192,"bios"],["bios/bios_MD.bin",2048,"bios"],["bios/bios_U.sms",8192,"bios"],["bios/bioscv.rom",2048,"bios"],["bios/biosdsi7.bin",65536,"bios"],["bios/biosdsi9.bin",65536,"bios"],["bios/bk_altpro.zip",1160579,"bios"],["bios/bk_ay.zip",479847,"bios"],["bios/bk_covox.zip",479847,"bios"],["bios/bk_irps.zip",95177,"bios"],["bios/bk_kmd.zip",6973,"bios"],["bios/bk_printer.zip",479847,"bios"],["bios/bk_samara.zip",1154606,"bios"],["bios/bluechip.zip",23865,"bios"],["bios/bml3kanji.zip",69657,"bios"],["bios/bml3mp1802.zip",1841,"bios"],["bios/bml3mp1805.zip",1874,"bios"],["bios/bootloader-dbvz.rom",512,"bios"],["bios/bsmt2000.zip",2646,"bios"],["bios/bt542b.zip",796611,"bios"],["bios/bt542bh.zip",800147,"bios"],["bios/bt545s.zip",799349,"bios"],["bios/bubsys.zip",12021,"bios"],["bios/bw2_ramcard.zip",8925,"bios"],["bios/bwtwo.zip",2396,"bios"],["bios/c101687.rom",32768,"bios"],["bios/c1526.zip",18797,"bios"],["bios/c1540.zip",12139,"bios"],["bios/c1541.zip",85282,"bios"],["bios/c1541c.zip",23897,"bios"],["bios/c1541dd.zip",15970,"bios"],["bios/c1541ii.zip",35933,"bios"],["bios/c1541pd.zip",14855,"bios"],["bios/c1541pdc.zip",502900,"bios"],["bios/c1551.zip",11640,"bios"],["bios/c1563.zip",12632,"bios"],["bios/c1570.zip",17870,"bios"],["bios/c1571.zip",55420,"bios"],["bios/c1571cr.zip",38062,"bios"],["bios/c1581.zip",58254,"bios"],["bios/c2031.zip",12163,"bios"],["bios/c2040.zip",7844,"bios"],["bios/c2040_fdc.zip",426,"bios"],["bios/c3040.zip",7844,"bios"],["bios/c4023.zip",4285,"bios"],["bios/c4040.zip",20926,"bios"],["bios/c52.bin",1024,"bios"],["bios/c64_ar4x.zip",190,"bios"],["bios/c64_buscard.zip",2010118,"bios"],["bios/c64_buscard2.zip",2010118,"bios"],["bios/c64_cspeech.zip",2011,"bios"],["bios/c64_geocable.zip",479847,"bios"],["bios/c64_ide64.zip",1151601,"bios"],["bios/c64_ieee488.zip",2010118,"bios"],["bios/c64_magic_voice.zip",2010118,"bios"],["bios/c64_mscr.zip",2311,"bios"],["bios/c64_music64.zip",2010118,"bios"],["bios/c64_nl10.zip",16716,"bios"],["bios/c64_sfxse.zip",2010118,"bios"],["bios/c64_speakeasy.zip",590,"bios"],["bios/c64_supercpu.zip",2010118,"bios"],["bios/c64_swiftlink.zip",95177,"bios"],["bios/c64_tdos.zip",2010118,"bios"],["bios/c64_turbo232.zip",95177,"bios"],["bios/c64_xl80.zip",830,"bios"],["bios/c64_z80videopak.zip",858,"bios"],["bios/c8050.zip",39422,"bios"],["bios/c8050fdc.zip",426,"bios"],["bios/c8250.zip",39422,"bios"],["bios/c8250lp.zip",29852,"bios"],["bios/c8280.zip",23702,"bios"],["bios/cadabc.zip",9823,"bios"],["bios/cafeLibs/erreula.rpl",790080,"bios"],["bios/cafeLibs/snd_user.rpl",84032,"bios"],["bios/cafeLibs/snduser2.rpl",111360,"bios"],["bios/cafeLibs/swkbd.rpl",1116288,"bios"],["bios/capsimg.dll",191488,"bios"],["bios/capsimg.so",95460,"bios"],["bios/carthw.cfg",16367,"bios"],["bios/cbm2_hrga.zip",3343,"bios"],["bios/cbm2_hrgb.zip",3343,"bios"],["bios/cbm8000_hsg_a.zip",3615,"bios"],["bios/cbm8000_hsg_b.zip",3615,"bios"],["bios/cbm_interpod.zip",294472,"bios"],["bios/cbm_serbox.zip",2245,"bios"],["bios/cc90_232.zip",574980,"bios"],["bios/cchip.zip",2700,"bios"],["bios/ccs7710.zip",96606,"bios"],["bios/cd6809_fdc.zip",7241,"bios"],["bios/cd90_015.zip",1871,"bios"],["bios/cd90_351.zip",4831,"bios"],["bios/cd90_640.zip",1744,"bios"],["bios/cdd2000.zip",195999,"bios"],["bios/cdi200.rom",524288,"bios"],["bios/cdi220.rom",524288,"bios"],["bios/cdi220b.rom",524288,"bios"],["bios/cdibios.zip",468660,"bios"],["bios/cdimono1.zip",745703,"bios"],["bios/cdimono2.zip",244291,"bios"],["bios/cdos20.rom",16384,"bios"],["bios/cdr4210.zip",82902,"bios"],["bios/cdrn820s.zip",66313,"bios"],["bios/cdu415.zip",31828,"bios"],["bios/cdu561_25.zip",141631,"bios"],["bios/cdu75s.zip",31456,"bios"],["bios/cedmag.zip",1242,"bios"],["bios/cemu/keys.txt",449507,"bios"],["bios/centennial_sl01m_15_11194.zip",301,"bios"],["bios/centennial_sl02m_15_11194.zip",301,"bios"],["bios/centennial_sl04m_15_11194.zip",313,"bios"],["bios/centronics_chessmec.zip",542,"bios"],["bios/cffa1.zip",1156283,"bios"],["bios/cfp1080s.zip",67669,"bios"],["bios/cga.zip",3710,"bios"],["bios/cga_iskr1030m.zip",1588,"bios"],["bios/cga_iskr1031.zip",1665,"bios"],["bios/cga_m24.zip",2283,"bios"],["bios/cga_mc1502.zip",1235,"bios"],["bios/cga_poisk2.zip",3177,"bios"],["bios/cga_superimpose.zip",3710,"bios"],["bios/cgenie_fdc.zip",20834,"bios"],["bios/cgenie_printer.zip",479847,"bios"],["bios/cgrom.dat",786432,"bios"],["bios/cgthree.zip",1224,"bios"],["bios/channelf.zip",2705,"bios"],["bios/chargen-901460-02.bin",4096,"bios"],["bios/chessmachine.zip",542,"bios"],["bios/chihiro.zip",2104141,"bios"],["bios/cit101_kbd.zip",930,"bios"],["bios/cit101e_kbd.zip",921,"bios"],["bios/cit220p_kbd.zip",773,"bios"],["bios/clgd5401.zip",36135,"bios"],["bios/clgd542x.zip",329437,"bios"],["bios/clgd5434_pci.zip",78023,"bios"],["bios/clgd5446_pci.zip",40471,"bios"],["bios/clgd5465_laguna.zip",21300,"bios"],["bios/cmdhd.zip",8968,"bios"],["bios/cmdrc2.zip",12317,"bios"],["bios/cmi_ankbd.zip",836,"bios"],["bios/cmi_mkbd.zip",1391,"bios"],["bios/cms_4080term.zip",576010,"bios"],["bios/cms_hires.zip",590,"bios"],["bios/cms_ieee.zip",291066,"bios"],["bios/cmsscsi.zip",783178,"bios"],["bios/coco3.rom",32768,"bios"],["bios/coco3p.rom",32768,"bios"],["bios/coco_dcmodem.zip",99130,"bios"],["bios/coco_fdc.zip",71429,"bios"],["bios/coco_ide.zip",1859954,"bios"],["bios/coco_multipack.zip",1859954,"bios"],["bios/coco_orch90.zip",6977,"bios"],["bios/coco_psg.zip",9965,"bios"],["bios/coco_rs232.zip",98780,"bios"],["bios/coco_scii.zip",496580,"bios"],["bios/coco_ssc.zip",5511,"bios"],["bios/coco_t4426.zip",127813,"bios"],["bios/coco_wpk.zip",857,"bios"],["bios/coco_wpk2.zip",857,"bios"],["bios/coco_wpkrs.zip",857,"bios"],["bios/cocopakram.zip",479847,"bios"],["bios/coh1000a.zip",126281,"bios"],["bios/coh1000c.zip",278470,"bios"],["bios/coh1000t.zip",126274,"bios"],["bios/coh1000w.zip",126147,"bios"],["bios/coh1001l.zip",126185,"bios"],["bios/coh1002e.zip",128626,"bios"],["bios/coh1002m.zip",138588,"bios"],["bios/coh1002t.zip",216727,"bios"],["bios/coh1002v.zip",126314,"bios"],["bios/coh3002c.zip",137941,"bios"],["bios/coh3002t.zip",504337,"bios"],["bios/coleco.rom",8192,"bios"],["bios/coleco.zip",28014,"bios"],["bios/colecovision.rom",8192,"bios"],["bios/color64extbas.rom",8192,"bios"],["bios/compis_hrg.zip",367,"bios"],["bios/compis_uhrg.zip",367,"bios"],["bios/compiskb.zip",480,"bios"],["bios/comx_clm.zip",4009,"bios"],["bios/comx_eb.zip",523172,"bios"],["bios/comx_epr.zip",15391,"bios"],["bios/comx_fd.zip",6238,"bios"],["bios/comx_pl80.zip",8379,"bios"],["bios/comx_prn.zip",485242,"bios"],["bios/comx_thm.zip",2913,"bios"],["bios/concept_kbd.zip",336,"bios"],["bios/cp2024.zip",23160,"bios"],["bios/cp31.zip",223978,"bios"],["bios/cp400bas.rom",8192,"bios"],["bios/cp400dsk.rom",8192,"bios"],["bios/cp400ext.rom",8192,"bios"],["bios/cp400extbas.rom",8192,"bios"],["bios/cp450_fdc.zip",7187,"bios"],["bios/cp450dsk.rom",8192,"bios"],["bios/cpc464.rom",32768,"bios"],["bios/cpc6128.rom",32768,"bios"],["bios/cpc664.rom",32768,"bios"],["bios/cpc_amsdos.rom",16384,"bios"],["bios/cpc_brunword4.zip",139453,"bios"],["bios/cpc_ddi1.zip",1471881,"bios"],["bios/cpc_dkspeech.zip",1460991,"bios"],["bios/cpc_hd20.zip",19579,"bios"],["bios/cpc_mface2.zip",1460991,"bios"],["bios/cpc_playcity.zip",1460991,"bios"],["bios/cpc_rom.zip",1460991,"bios"],["bios/cpc_ser.zip",1460991,"bios"],["bios/cpc_serams.zip",1460991,"bios"],["bios/cpc_smartwatch.zip",5640,"bios"],["bios/cpc_ssa1.zip",1460991,"bios"],["bios/cpc_symf2.zip",1151601,"bios"],["bios/cpc_transtape.zip",4021,"bios"],["bios/cpuap.zip",26613,"bios"],["bios/cq90_028.zip",1744,"bios"],["bios/crd254sh.zip",31383,"bios"],["bios/crvfdc01.zip",149,"bios"],["bios/crvfdc02.zip",151,"bios"],["bios/crysbios.zip",43480,"bios"],["bios/csd1.zip",12487,"bios"],["bios/ct1741.zip",8003,"bios"],["bios/cu_graphc.zip",590,"bios"],["bios/cu_graphm.zip",590,"bios"],["bios/cu_teletext.zip",480339,"bios"],["bios/cubo.zip",673549,"bios"],["bios/cuda.zip",12814,"bios"],["bios/cuda302.zip",3720,"bios"],["bios/cudalite.zip",4037,"bios"],["bios/cv8lc.zip",7423,"bios"],["bios/cw7501.zip",83060,"bios"],["bios/cx4.data.rom",3072,"bios"],["bios/d200e_1.rom",16384,"bios"],["bios/d200e_2.rom",16384,"bios"],["bios/d200e_26.rom",4096,"bios"],["bios/d200rom1.rom",16384,"bios"],["bios/d200rom2.rom",16384,"bios"],["bios/d2fdc.zip",262,"bios"],["bios/d32.rom",16384,"bios"],["bios/d64_2.rom",16384,"bios"],["bios/d64rom1.rom",16384,"bios"],["bios/d64tano.rom",16384,"bios"],["bios/d64tano2.rom",16384,"bios"],["bios/d78c11agf_e19.u1",4096,"bios"],["bios/d8000.rom",32768,"bios"],["bios/d9060.zip",32197,"bios"],["bios/d9090.zip",32197,"bios"],["bios/db50xg.zip",3666695,"bios"],["bios/db60xg.zip",3669859,"bios"],["bios/dc/airlbios.zip",715730,"bios"],["bios/dc/awbios.zip",42296,"bios"],["bios/dc/dc_boot.bin",2097152,"bios"],["bios/dc/dc_flash.bin",131072,"bios"],["bios/dc/dc_nvmem.bin",131072,"bios"],["bios/dc/f355bios.zip",1394278,"bios"],["bios/dc/f355dlx.zip",2328436,"bios"],["bios/dc/flash.bin",131072,"bios"],["bios/dc/hod2bios.zip",1874145,"bios"],["bios/dc/naomi.zip",9321533,"bios"],["bios/dc/naomi2.zip",7022501,"bios"],["bios/dc/naomi_boot.bin",2097152,"bios"],["bios/dc320b.zip",793791,"bios"],["bios/dc320e.zip",809942,"bios"],["bios/dc820.zip",804028,"bios"],["bios/dc820b.zip",810042,"bios"],["bios/ddos10.rom",8192,"bios"],["bios/ddos11c.rom",8192,"bios"],["bios/ddos12a.rom",8192,"bios"],["bios/ddos40.rom",8192,"bios"],["bios/ddos42.rom",8192,"bios"],["bios/ddrfammt.zip",883352,"bios"],["bios/decobsmt.zip",2646,"bios"],["bios/decocass.zip",13225,"bios"],["bios/dectalk_isa.zip",3823,"bios"],["bios/delaweare.wad",83219726,"game_data"],["bios/delta2.rom",8192,"bios"],["bios/deltados.rom",8192,"bios"],["bios/deluxe.rom",32768,"bios"],["bios/dg640.zip",855,"bios"],["bios/digilog_kbd.zip",1067,"bios"],["bios/dim68k_kbd.zip",1550,"bios"],["bios/dio98543.zip",2010,"bios"],["bios/dio98544.zip",2034,"bios"],["bios/dio98550.zip",3081,"bios"],["bios/dio98603a.zip",291168,"bios"],["bios/dio98603b.zip",377453,"bios"],["bios/dio98624.zip",37948,"bios"],["bios/dio98628.zip",101051,"bios"],["bios/dio98629.zip",5266,"bios"],["bios/dio98644.zip",95177,"bios"],["bios/disciple.rom",8192,"bios"],["bios/disk.rom",8194,"bios"],["bios/disk10.rom",8192,"bios"],["bios/disk11.rom",8192,"bios"],["bios/disk_plus3.szx",1568,"bios"],["bios/diskii13.zip",590,"bios"],["bios/disksys.rom",8192,"bios"],["bios/distomeb_rtime.zip",479847,"bios"],["bios/dm_clgd5430.zip",20166,"bios"],["bios/dmv_k210.zip",479847,"bios"],["bios/dmv_k211.zip",95177,"bios"],["bios/dmv_k212.zip",95177,"bios"],["bios/dmv_k213.zip",95177,"bios"],["bios/dmv_k220.zip",15572,"bios"],["bios/dmv_k230.zip",2880,"bios"],["bios/dmv_k231.zip",2880,"bios"],["bios/dmv_k235.zip",2430,"bios"],["bios/dmv_k801.zip",95177,"bios"],["bios/dmv_k806.zip",642,"bios"],["bios/dmv_keyboard.zip",1135,"bios"],["bios/dolphin-emu/Sys/GC/EUR/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/JAP/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/USA/IPL.bin",2097152,"bios"],["bios/dolphin-emu/Sys/GC/dsp_coef.bin",4096,"bios"],["bios/dolphin-emu/Sys/GC/dsp_rom.bin",8192,"bios"],["bios/dolphin-emu/Sys/GC/font_japanese.bin",259626,"bios"],["bios/dolphin-emu/Sys/GC/font_western.bin",6478,"bios"],["bios/dolphin-emu/Sys/Triforce/segaboot.gcm",2097152,"bios"],["bios/doom.wad",11159840,"game_data"],["bios/doom2.wad",14943400,"game_data"],["bios/doom2f.wad",14607420,"game_data"],["bios/dplus48.rom",8192,"bios"],["bios/dplus49b.rom",8192,"bios"],["bios/dplus50.rom",8192,"bios"],["bios/dragon_claw.zip",640119,"bios"],["bios/dragon_fdc.zip",7074,"bios"],["bios/dragon_jcbsnd.zip",1735,"bios"],["bios/dragon_jcbspch.zip",5510,"bios"],["bios/dragon_msx2.zip",313,"bios"],["bios/dragon_multipack.zip",640119,"bios"],["bios/dragon_serial.zip",100100,"bios"],["bios/dragon_sprites.zip",3619,"bios"],["bios/dragonfly-1.3.rom",4096,"bios"],["bios/dragonfly-2.3.rom",4096,"bios"],["bios/ds1001.zip",313,"bios"],["bios/dsd4432.zip",1119,"bios"],["bios/dsd5217.zip",21312,"bios"],["bios/dsp1.data.rom",2048,"bios"],["bios/dsp1b.data.rom",2048,"bios"],["bios/dsp1b.program.rom",6144,"bios"],["bios/dsp2.data.rom",2048,"bios"],["bios/dsp2.program.rom",6144,"bios"],["bios/dsp3.data.rom",2048,"bios"],["bios/dsp3.program.rom",6144,"bios"],["bios/dsp4.data.rom",2048,"bios"],["bios/dsp4.program.rom",6144,"bios"],["bios/dsp56303.zip",568,"bios"],["bios/dsp56311.zip",568,"bios"],["bios/dsp56362.zip",629,"bios"],["bios/duodock.zip",1149126,"bios"],["bios/dvk_kmd.zip",6186,"bios"],["bios/dvk_ktlk.zip",95177,"bios"],["bios/dw_kbd.zip",722,"bios"],["bios/easyrpg.soundfont",148398306,"game_data"],["bios/ec1841_0002.zip",3710,"bios"],["bios/ecb_grip21.zip",490120,"bios"],["bios/econet_e01.zip",506768,"bios"],["bios/econet_e01s.zip",533937,"bios"],["bios/ecwolf.pk3",178755,"bios"],["bios/eeprom.bin",256,"bios"],["bios/eeprom.dat",64,"bios"],["bios/ef9340_1.zip",1022,"bios"],["bios/ef9365.zip",590,"bios"],["bios/ega.zip",18988,"bios"],["bios/egret.zip",8834,"bios"],["bios/eidemax.zip",46469,"bios"],["bios/einstein_sd.zip",1105,"bios"],["bios/einstein_speech.zip",2019,"bios"],["bios/eispc_kb.zip",848,"bios"],["bios/ekara.zip",630644,"bios"],["bios/ekaraa.zip",629642,"bios"],["bios/ekarag.zip",795612,"bios"],["bios/ekaraj.zip",629853,"bios"],["bios/ekaramix.zip",663402,"bios"],["bios/ekaraphs.zip",798457,"bios"],["bios/ekaras.zip",813756,"bios"],["bios/electron.zip",25571,"bios"],["bios/electron64.zip",25089,"bios"],["bios/electron_ap1.zip",504869,"bios"],["bios/electron_ap5.zip",3159112,"bios"],["bios/electron_ap6.zip",508400,"bios"],["bios/electron_elksd128.zip",37465,"bios"],["bios/electron_elksd64.zip",21261,"bios"],["bios/electron_fbprint.zip",479847,"bios"],["bios/electron_m2105.zip",724803,"bios"],["bios/electron_mc68k.zip",35027,"bios"],["bios/electron_mode7.zip",958848,"bios"],["bios/electron_plus1.zip",1344,"bios"],["bios/electron_plus2.zip",958848,"bios"],["bios/electron_plus3.zip",57712,"bios"],["bios/electron_pwrjoy.zip",1437,"bios"],["bios/electron_rombox.zip",958848,"bios"],["bios/electron_romboxp.zip",504960,"bios"],["bios/electron_rs423.zip",95177,"bios"],["bios/electron_sidewndr.zip",958848,"bios"],["bios/electron_stlefs.zip",2844684,"bios"],["bios/electron_tube.zip",314472,"bios"],["bios/electron_voxbox.zip",2019,"bios"],["bios/enetlc.zip",8935,"bios"],["bios/enetlctp.zip",471,"bios"],["bios/enetnbtp.zip",472,"bios"],["bios/enh2000.zip",12453,"bios"],["bios/enp10.zip",35461,"bios"],["bios/ep64_exdos.zip",14521,"bios"],["bios/epitch.zip",629853,"bios"],["bios/epson_fx80.zip",12887,"bios"],["bios/epson_jx80.zip",11210,"bios"],["bios/epson_pf10.zip",3426,"bios"],["bios/epson_qx_option_multifont.zip",42543,"bios"],["bios/epson_qx_option_sound_card.zip",3573,"bios"],["bios/epson_rx80.zip",6311,"bios"],["bios/epson_tf20.zip",3426,"bios"],["bios/ergoline_kbd.zip",1847,"bios"],["bios/esq2x40_vfx.zip",288,"bios"],["bios/esqpanel240_vfx.zip",288,"bios"],["bios/et4000.zip",31117,"bios"],["bios/et4000_kasan16.zip",206680,"bios"],["bios/et4kw32i.zip",18756,"bios"],["bios/et532_board.zip",1252,"bios"],["bios/ethudock.zip",692,"bios"],["bios/europc_kbd.zip",1138,"bios"],["bios/ev346.zip",3881,"bios"],["bios/everdrive_md.zip",37759,"bios"],["bios/evio.zip",1292911,"bios"],["bios/ex1280.zip",3538,"bios"],["bios/ex800.zip",21628,"bios"],["bios/exec.bin",8192,"bios"],["bios/executive10_102_kbd.zip",1778,"bios"],["bios/exorterm155_device.zip",8999,"bios"],["bios/exorterm155_terminal.zip",8999,"bios"],["bios/exos201.zip",19800,"bios"],["bios/extbas10.rom",8192,"bios"],["bios/extbas11.rom",8192,"bios"],["bios/external.bin",262144,"bios"],["bios/f355bios.zip",1394278,"bios"],["bios/f355dlx.zip",2328436,"bios"],["bios/f4431_kbd.zip",1807,"bios"],["bios/fba2012/samples/dkong.zip",29270,"game_data"],["bios/fba2012/samples/dkongjr.zip",300220,"game_data"],["bios/fba2012/samples/fireshrk.zip",180371945,"game_data"],["bios/fba2012/samples/galaga.zip",243090,"game_data"],["bios/fba2012/samples/ghox.zip",149028023,"game_data"],["bios/fba2012/samples/rallyx.zip",72511,"game_data"],["bios/fba2012/samples/tekipaki.zip",207969846,"game_data"],["bios/fba2012/samples/vimana.zip",278695628,"game_data"],["bios/fbneo/samples/donpachi.zip",208549253,"game_data"],["bios/fbneo/samples/sfz3mix.zip",101017377,"game_data"],["bios/fc_disksys.zip",11579,"bios"],["bios/fd148.zip",11962,"bios"],["bios/fd2000.zip",45358,"bios"],["bios/fd4000.zip",45409,"bios"],["bios/fd502.rom",8192,"bios"],["bios/fd502ds.rom",8192,"bios"],["bios/fdc344.zip",2298,"bios"],["bios/fdc37c665gt.zip",479847,"bios"],["bios/fdc37c93x.zip",479847,"bios"],["bios/fdc37m707.zip",479847,"bios"],["bios/fdcmag.zip",2158,"bios"],["bios/fdsbios.zip",8312,"bios"],["bios/fga4he.zip",17002,"bios"],["bios/filetto_cga.zip",3713,"bios"],["bios/firmware.bin",262144,"bios"],["bios/fm7.zip",104276,"bios"],["bios/fm77av.zip",46921,"bios"],["bios/fmnew7.zip",26815,"bios"],["bios/font.bmp",524350,"bios"],["bios/freedm.wad",22218796,"game_data"],["bios/freedom220_kbd.zip",1353,"bios"],["bios/freedoom1.wad",28795076,"game_data"],["bios/freedoom2.wad",28787748,"game_data"],["bios/freej2me-lr.jar",552042,"bios"],["bios/freej2me-sdl.jar",552043,"bios"],["bios/freej2me.jar",552039,"bios"],["bios/front-sp1.bin",524288,"bios"],["bios/fs-a1gt_firmware.rom",4194304,"bios"],["bios/fs-a1gt_kanjifont.rom",262144,"bios"],["bios/fs-a1wsx_basic-bios2p.rom",32768,"bios"],["bios/fs-a1wsx_disk.rom",16384,"bios"],["bios/fs-a1wsx_firmware.rom",2097152,"bios"],["bios/fs-a1wsx_fmbasic.rom",16384,"bios"],["bios/fs-a1wsx_kanjibasic.rom",32768,"bios"],["bios/fs-a1wsx_kanjifont.rom",262144,"bios"],["bios/fs-a1wsx_msx2psub.rom",16384,"bios"],["bios/fsd1.zip",11799,"bios"],["bios/fsd2.zip",48020,"bios"],["bios/fuse/128-0.rom",16384,"bios"],["bios/fuse/128-1.rom",16384,"bios"],["bios/fuse/128p-0.rom",16384,"bios"],["bios/fuse/128p-1.rom",16384,"bios"],["bios/fuse/256s-0.rom",16384,"bios"],["bios/fuse/256s-1.rom",16384,"bios"],["bios/fuse/256s-2.rom",16384,"bios"],["bios/fuse/256s-3.rom",16384,"bios"],["bios/fuse/48.rom",16384,"bios"],["bios/fuse/didaktik80.rom",14336,"bios"],["bios/fuse/disciple.rom",8192,"bios"],["bios/fuse/gluck.rom",16384,"bios"],["bios/fuse/if1-2.rom",8192,"bios"],["bios/fuse/mf1.rom",8192,"bios"],["bios/fuse/mf128.rom",8192,"bios"],["bios/fuse/mf3.rom",8192,"bios"],["bios/fuse/opus.rom",8192,"bios"],["bios/fuse/plus2-0.rom",16384,"bios"],["bios/fuse/plus2-1.rom",16384,"bios"],["bios/fuse/plus3-0.rom",16384,"bios"],["bios/fuse/plus3-1.rom",16384,"bios"],["bios/fuse/plus3-2.rom",16384,"bios"],["bios/fuse/plus3-3.rom",16384,"bios"],["bios/fuse/plus3e-0.rom",16384,"bios"],["bios/fuse/plus3e-1.rom",16384,"bios"],["bios/fuse/plus3e-2.rom",16384,"bios"],["bios/fuse/plus3e-3.rom",16384,"bios"],["bios/fuse/plusd.rom",8192,"bios"],["bios/fuse/se-0.rom",16384,"bios"],["bios/fuse/se-1.rom",16384,"bios"],["bios/fuse/speccyboot-1.4.rom",8192,"bios"],["bios/fuse/tc2048.rom",16384,"bios"],["bios/fuse/tc2068-0.rom",16384,"bios"],["bios/fuse/tc2068-1.rom",8192,"bios"],["bios/fuse/trdos.rom",16384,"bios"],["bios/fuse/ttx2000s.rom",8192,"bios"],["bios/fuse/usource.rom",8192,"bios"],["bios/fx-scsi.rom",524288,"bios"],["bios/g7400.bin",1024,"bios"],["bios/g80_1500.zip",5636,"bios"],["bios/galgbios.zip",1345333,"bios"],["bios/gamate.zip",5072,"bios"],["bios/gamecom.zip",145138,"bios"],["bios/gamecontrollerdb.txt",600521,"game_data"],["bios/gamtor_vga.zip",208,"bios"],["bios/gb_bios.bin",256,"bios"],["bios/gba_bios.bin",16384,"bios"],["bios/gbc_bios.bin",2304,"bios"],["bios/gcslottv.zip",737452,"bios"],["bios/geforce256.zip",25685,"bios"],["bios/geforce256ddr.zip",21811,"bios"],["bios/gexpress.pce",32768,"bios"],["bios/gfxultra.zip",19347,"bios"],["bios/gfxultrap.zip",38094,"bios"],["bios/ggenie.bin",32768,"bios"],["bios/gic.zip",373,"bios"],["bios/gluck.rom",16384,"bios"],["bios/gmaster.zip",1686,"bios"],["bios/goldstar.bin",1048576,"bios"],["bios/gotsndspr1.zip",588,"bios"],["bios/gotsndspr1a.zip",590,"bios"],["bios/gp_110.zip",3140,"bios"],["bios/gpib_hardbox.zip",18236,"bios"],["bios/gpib_mshark.zip",13934,"bios"],["bios/gpib_softbox.zip",9859,"bios"],["bios/gpl16250va.zip",155340,"bios"],["bios/gpl951xx.zip",3396,"bios"],["bios/gq863.zip",74462,"bios"],["bios/grndctrl.zip",95177,"bios"],["bios/grom.bin",2048,"bios"],["bios/gts1.zip",3734,"bios"],["bios/gunsense.zip",5062,"bios"],["bios/h89bus_io_decoder_444_43.zip",175,"bios"],["bios/h89bus_io_decoder_444_61.zip",176,"bios"],["bios/h89bus_io_decoder_cdr86.zip",177,"bios"],["bios/h89bus_io_decoder_mms_61c.zip",193,"bios"],["bios/h89h_88_3.zip",95177,"bios"],["bios/h89ha_88_3.zip",95177,"bios"],["bios/h8_cpu_8080.zip",7111,"bios"],["bios/h8_h_8_5.zip",95177,"bios"],["bios/h8_ha_8_6.zip",6415,"bios"],["bios/hacx.wad",19321722,"game_data"],["bios/hacx2.wad",20504847,"game_data"],["bios/hardbox.zip",18236,"bios"],["bios/harddriv_board.zip",95177,"bios"],["bios/harddrivc_board.zip",95177,"bios"],["bios/harm1.wad",58396393,"game_data"],["bios/hatari/BOOT.ST",737280,"bios"],["bios/hcpu30.zip",590392,"bios"],["bios/hd44780.zip",965,"bios"],["bios/hd44780u.zip",2082,"bios"],["bios/hd61830.zip",839,"bios"],["bios/hdae5000.zip",823668,"bios"],["bios/hdbdw3bck.rom",8192,"bios"],["bios/hdrivair0_board.zip",95177,"bios"],["bios/hdrivair_board.zip",95177,"bios"],["bios/he191_3425.zip",983,"bios"],["bios/heath_gp19_tlb.zip",13491,"bios"],["bios/heath_igc_super19_tlb_device.zip",5615,"bios"],["bios/heath_igc_tlb_device.zip",5021,"bios"],["bios/heath_igc_ultra_tlb_device.zip",4818,"bios"],["bios/heath_igc_watz_tlb_device.zip",7609,"bios"],["bios/heath_imaginator_tlb.zip",9135,"bios"],["bios/heath_super19_tlb.zip",5615,"bios"],["bios/heath_superset_tlb.zip",14186,"bios"],["bios/heath_tlb.zip",5021,"bios"],["bios/heath_ultra_tlb.zip",4818,"bios"],["bios/heath_watz_tlb.zip",7609,"bios"],["bios/heathrow.zip",95177,"bios"],["bios/hikara.zip",636237,"bios"],["bios/hikaru.zip",1049493,"bios"],["bios/hisaturn.bin",524288,"bios"],["bios/hk68v10.zip",103216,"bios"],["bios/hng64.zip",41592,"bios"],["bios/hod2bios.zip",1479106,"bios"],["bios/howard.o",513,"bios"],["bios/hp82900.zip",691,"bios"],["bios/hp82919.zip",95177,"bios"],["bios/hp82937.zip",39932,"bios"],["bios/hp82939.zip",97002,"bios"],["bios/hp9122c.zip",10761,"bios"],["bios/hp9133.zip",21140,"bios"],["bios/hp98034.zip",38621,"bios"],["bios/hp98035.zip",1993,"bios"],["bios/hp98036.zip",95177,"bios"],["bios/hp98046.zip",96236,"bios"],["bios/hp98265a.zip",778041,"bios"],["bios/hp9845_prt.zip",1241,"bios"],["bios/hp9895.zip",6135,"bios"],["bios/hpblp.zip",842209,"bios"],["bios/human_interface.zip",39948,"bios"],["bios/i82371ab.zip",1171917,"bios"],["bios/i82371eb_ide.zip",1151601,"bios"],["bios/i82371sb.zip",1151601,"bios"],["bios/i82371sb_ide.zip",1151601,"bios"],["bios/i8244.zip",456,"bios"],["bios/i8245.zip",456,"bios"],["bios/ibm_mfc.zip",17863,"bios"],["bios/ibm_vga.zip",13184,"bios"],["bios/ibsap2.zip",1061,"bios"],["bios/id1/pak0.pak",18689235,"game_data"],["bios/idpart_video.zip",97756,"bios"],["bios/ie15_device.zip",5520,"bios"],["bios/ie15_terminal.zip",5520,"bios"],["bios/ie15kbd.zip",352,"bios"],["bios/if1-1.rom",8192,"bios"],["bios/imds2ioc.zip",499607,"bios"],["bios/imi5000h.zip",3337,"bios"],["bios/imi7000.zip",3337,"bios"],["bios/in207100kbd.zip",1074,"bios"],["bios/in213kbd.zip",658,"bios"],["bios/indusgt.zip",15707,"bios"],["bios/internal.bin",4096,"bios"],["bios/intv_ecs.zip",13890,"bios"],["bios/intv_voice.zip",2025,"bios"],["bios/ioc2f.zip",595178,"bios"],["bios/ioc2g.zip",595178,"bios"],["bios/iplrom.dat",131072,"bios"],["bios/iplrom30.dat",131072,"bios"],["bios/iplromcdc_flash.bino.dat",131072,"bios"],["bios/iplromco.dat",131072,"bios"],["bios/iplromxv.dat",131072,"bios"],["bios/iq151_disc2.zip",1872,"bios"],["bios/iq151_minigraf.zip",3404,"bios"],["bios/iq151_ms15a.zip",1938,"bios"],["bios/iq151_video32.zip",709,"bios"],["bios/iq151_video64.zip",1120,"bios"],["bios/iris_kbd.zip",939,"bios"],["bios/isa_aga.zip",2673,"bios"],["bios/isa_aga_pc200.zip",3722,"bios"],["bios/isa_bblue2.zip",479847,"bios"],["bios/isa_chessmdr.zip",542,"bios"],["bios/isa_epc_mda.zip",1714,"bios"],["bios/isa_finalchs.zip",39370,"bios"],["bios/isa_hdc.zip",5558,"bios"],["bios/isa_hercules.zip",483007,"bios"],["bios/isa_ibm_mda.zip",483513,"bios"],["bios/isa_ibm_pgc.zip",69664,"bios"],["bios/isa_ibm_speech.zip",22584,"bios"],["bios/isa_ide.zip",1151601,"bios"],["bios/isa_lpt.zip",479847,"bios"],["bios/isa_mpu401.zip",3573,"bios"],["bios/isa_pcmidi.zip",6300,"bios"],["bios/isa_prose4001.zip",96246,"bios"],["bios/isbc202.zip",2023,"bios"],["bios/isbc8024.zip",98001,"bios"],["bios/isbc_215g.zip",11746,"bios"],["bios/isgsm.zip",10207,"bios"],["bios/isinger.zip",556765,"bios"],["bios/it8703f_device.zip",479847,"bios"],["bios/it8705f.zip",479847,"bios"],["bios/iteagle.zip",3614545,"bios"],["bios/iteagle_fpga.zip",95177,"bios"],["bios/itf.rom",32768,"bios"],["bios/ivelultrkb.zip",841,"bios"],["bios/jagboot.rom",131072,"bios"],["bios/jagboot_m.rom",131072,"bios"],["bios/jaleco_vj_pc.zip",1268315,"bios"],["bios/jc1310.zip",3574,"bios"],["bios/jopac.bin",1024,"bios"],["bios/jpopira.zip",1116085,"bios"],["bios/jvs13551.zip",15088,"bios"],["bios/k573_dio.zip",158,"bios"],["bios/k573kara.zip",95291,"bios"],["bios/k573mcr.zip",3927,"bios"],["bios/k573msu.zip",136526,"bios"],["bios/k7659_keyboard.zip",384,"bios"],["bios/kaypro10kbd.zip",1307,"bios"],["bios/kayproiikbd.zip",1101,"bios"],["bios/kb_3270pc.zip",1115,"bios"],["bios/kb_ec1841.zip",788,"bios"],["bios/kb_iskr1030.zip",1022,"bios"],["bios/kb_ms_natural.zip",3029,"bios"],["bios/kb_pcat101.zip",2989,"bios"],["bios/kb_pcat84.zip",1032,"bios"],["bios/kb_pcxt83.zip",726,"bios"],["bios/kbd_lle_en_us.zip",3038,"bios"],["bios/kc_d002.zip",1185978,"bios"],["bios/kc_d004.zip",4285,"bios"],["bios/kc_d004_gide.zip",1181737,"bios"],["bios/kernal-901227-01.bin",8192,"bios"],["bios/kernal-901227-02.bin",8192,"bios"],["bios/kernal.901486-02.bin",8192,"bios"],["bios/keropi/cgrom.dat",786432,"bios"],["bios/keropi/iplrom.dat",131072,"bios"],["bios/keropi/iplrom30.dat",131072,"bios"],["bios/keropi/iplromco.dat",131072,"bios"],["bios/keropi/iplromxv.dat",131072,"bios"],["bios/keys.txt",449507,"bios"],["bios/keytronic_l2207.zip",2325,"bios"],["bios/keytronic_pc3270.zip",3168,"bios"],["bios/keytronic_pc3270_at.zip",3168,"bios"],["bios/kick31034.A1000",262144,"bios"],["bios/kick32034.A1000",262144,"bios"],["bios/kick33180.A500",262144,"bios"],["bios/kick34005.A500",262144,"bios"],["bios/kick34005.CDTV",262144,"bios"],["bios/kick37175.A500",524288,"bios"],["bios/kick37350.A600",524288,"bios"],["bios/kick39106.A1200",524288,"bios"],["bios/kick39106.A4000",524288,"bios"],["bios/kick40060.CD32",524288,"bios"],["bios/kick40060.CD32.ext",524288,"bios"],["bios/kick40060.CD32.full",1048576,"bios"],["bios/kick40063.A600",524288,"bios"],["bios/kick40068.A1200",524288,"bios"],["bios/kick40068.A4000",524288,"bios"],["bios/km035.zip",1035,"bios"],["bios/konamigv.zip",81391,"bios"],["bios/konamigx.zip",8734,"bios"],["bios/konendev.zip",25691,"bios"],["bios/kpython.zip",24831,"bios"],["bios/kpython2.zip",2638808,"bios"],["bios/kronos/stvbios.zip",3455065,"bios"],["bios/ks0066.zip",2011,"bios"],["bios/kviper.zip",33864,"bios"],["bios/labtam_3232.zip",73648,"bios"],["bios/labtam_8086cpu.zip",98364,"bios"],["bios/labtam_vducom.zip",170873,"bios"],["bios/labtam_z80sbc.zip",16546,"bios"],["bios/lba_enhancer.zip",2746,"bios"],["bios/lc7985.zip",957,"bios"],["bios/ldv1000.zip",4816,"bios"],["bios/lha201.zip",6661,"bios"],["bios/lindbios.zip",1462941,"bios"],["bios/lisa2fdc.zip",3159,"bios"],["bios/lisafdc.zip",3328,"bios"],["bios/lisavideo.zip",260,"bios"],["bios/lk201.zip",6069,"bios"],["bios/lm24014h.zip",629,"bios"],["bios/lrk331.zip",18121,"bios"],["bios/luna_68k_cmc.zip",13767,"bios"],["bios/luna_68k_gpu.zip",84000,"bios"],["bios/luna_68k_ioc.zip",28610,"bios"],["bios/lux10828.zip",9352,"bios"],["bios/lux21046.zip",24177,"bios"],["bios/lux21056.zip",18460,"bios"],["bios/lux4105.zip",778041,"bios"],["bios/lx800.zip",15176,"bios"],["bios/lx810l.zip",22103,"bios"],["bios/lynxboot.img",512,"bios"],["bios/m1comm.zip",3832,"bios"],["bios/m20_8086.zip",6611,"bios"],["bios/m24_kbd.zip",1483,"bios"],["bios/m24_z8000.zip",9638,"bios"],["bios/m50458.zip",2448,"bios"],["bios/m50dass.zip",5021,"bios"],["bios/m68705p3.zip",266,"bios"],["bios/m68705p5.zip",266,"bios"],["bios/m68705r3.zip",271,"bios"],["bios/m68705u3.zip",271,"bios"],["bios/m68hc05pge.zip",607,"bios"],["bios/macf108.zip",2024731,"bios"],["bios/mach64isa.zip",121273,"bios"],["bios/mackbd_m0110.zip",1021,"bios"],["bios/mackbd_m0110a.zip",866,"bios"],["bios/mackbd_m0110a_f.zip",866,"bios"],["bios/mackbd_m0110a_j.zip",866,"bios"],["bios/mackbd_m0110b.zip",1021,"bios"],["bios/mackbd_m0110f.zip",1021,"bios"],["bios/mackbd_m0110j.zip",1021,"bios"],["bios/mackbd_m0110t.zip",1021,"bios"],["bios/mackbd_m0120.zip",1051,"bios"],["bios/mackbd_m0120p.zip",1843,"bios"],["bios/macsbios.zip",305290,"bios"],["bios/macxlfdc.zip",5757,"bios"],["bios/macxlvideo.zip",212,"bios"],["bios/mame/hash/32x.xml",128073,"game_data"],["bios/mame/hash/3do.xml",3729,"game_data"],["bios/mame/hash/3do_m2.xml",1791,"game_data"],["bios/mame/hash/README.md",354,"game_data"],["bios/mame/hash/a2600.xml",737892,"game_data"],["bios/mame/hash/a2600_cass.xml",32898,"game_data"],["bios/mame/hash/a5200.hsi",32063,"game_data"],["bios/mame/hash/a5200.xml",58114,"game_data"],["bios/mame/hash/a7800.xml",127364,"game_data"],["bios/mame/hash/a800.xml",269515,"game_data"],["bios/mame/hash/a800_cass.xml",1717,"game_data"],["bios/mame/hash/a800_flop.xml",38722,"game_data"],["bios/mame/hash/abc1600_flop.xml",7222,"game_data"],["bios/mame/hash/abc1600_hdd.xml",547,"game_data"],["bios/mame/hash/abc800_hdd.xml",1362,"game_data"],["bios/mame/hash/abc806_flop.xml",4664,"game_data"],["bios/mame/hash/abc80_cass.xml",1063,"game_data"],["bios/mame/hash/abc80_flop.xml",4875,"game_data"],["bios/mame/hash/abc80_rom.xml",2440,"game_data"],["bios/mame/hash/abc830_flop.xml",7246,"game_data"],["bios/mame/hash/abc832_flop.xml",14768,"game_data"],["bios/mame/hash/abc838_flop.xml",1979,"game_data"],["bios/mame/hash/acrnsys_flop.xml",1659,"game_data"],["bios/mame/hash/acrnsys_rom.xml",2174,"game_data"],["bios/mame/hash/adam_cart.xml",6596,"game_data"],["bios/mame/hash/adam_cass.xml",33914,"game_data"],["bios/mame/hash/adam_flop.xml",625845,"game_data"],["bios/mame/hash/advantage.xml",5914,"game_data"],["bios/mame/hash/advision.xml",2281,"game_data"],["bios/mame/hash/aim65_cart.xml",9060,"game_data"],["bios/mame/hash/aleste.xml",1366,"game_data"],["bios/mame/hash/alice32.xml",27026,"game_data"],["bios/mame/hash/alice90.xml",3996,"game_data"],["bios/mame/hash/alphasmart_kapps.xml",16025,"game_data"],["bios/mame/hash/alphatro_cart.xml",1129,"game_data"],["bios/mame/hash/alphatro_flop.xml",1342,"game_data"],["bios/mame/hash/altos5.xml",1323,"game_data"],["bios/mame/hash/altos586.xml",574,"game_data"],["bios/mame/hash/altos8600.xml",1043,"game_data"],["bios/mame/hash/amiga_amix.xml",4460,"game_data"],["bios/mame/hash/amiga_apps.xml",7434,"game_data"],["bios/mame/hash/amiga_cd.xml",15524,"game_data"],["bios/mame/hash/amiga_demos.xml",3217,"game_data"],["bios/mame/hash/amiga_flop.xml",410553,"game_data"],["bios/mame/hash/amiga_hardware.xml",9287,"game_data"],["bios/mame/hash/amiga_hdd.xml",1617,"game_data"],["bios/mame/hash/amiga_workbench.xml",61616,"game_data"],["bios/mame/hash/amigaaga_flop.xml",215186,"game_data"],["bios/mame/hash/amigaecs_flop.xml",35873,"game_data"],["bios/mame/hash/amigaocs_flop.xml",2095329,"game_data"],["bios/mame/hash/ampro.xml",2178,"game_data"],["bios/mame/hash/apc.xml",14254,"game_data"],["bios/mame/hash/apexc_cyl.xml",1523,"game_data"],["bios/mame/hash/apfimag_cass.xml",43143,"game_data"],["bios/mame/hash/apfm1000.xml",9759,"game_data"],["bios/mame/hash/apogee.xml",41066,"game_data"],["bios/mame/hash/apollo_ctape.xml",2075,"game_data"],["bios/mame/hash/apple1.xml",20026,"game_data"],["bios/mame/hash/apple2_cass.xml",138008,"game_data"],["bios/mame/hash/apple2_flop_clcracked.xml",2899755,"game_data"],["bios/mame/hash/apple2_flop_misc.xml",308001,"game_data"],["bios/mame/hash/apple2_flop_orig.xml",2077439,"game_data"],["bios/mame/hash/apple2_rom.xml",1709,"game_data"],["bios/mame/hash/apple2gs_flop_clcracked.xml",162549,"game_data"],["bios/mame/hash/apple2gs_flop_misc.xml",296955,"game_data"],["bios/mame/hash/apple2gs_flop_orig.xml",234778,"game_data"],["bios/mame/hash/apple3.xml",10270,"game_data"],["bios/mame/hash/applix_flop.xml",541,"game_data"],["bios/mame/hash/apricot_flop.xml",33034,"game_data"],["bios/mame/hash/apxen_flop.xml",1562,"game_data"],["bios/mame/hash/aquarius_cart.xml",14960,"game_data"],["bios/mame/hash/aquarius_cass.xml",34155,"game_data"],["bios/mame/hash/arb.xml",3568,"game_data"],["bios/mame/hash/arcadia.xml",57566,"game_data"],["bios/mame/hash/archimedes.xml",271056,"game_data"],["bios/mame/hash/archimedes_hdd.xml",549,"game_data"],["bios/mame/hash/archimedes_rom.xml",2409,"game_data"],["bios/mame/hash/astrocde.xml",56504,"game_data"],["bios/mame/hash/atom_cass.xml",19518,"game_data"],["bios/mame/hash/atom_flop.xml",7657,"game_data"],["bios/mame/hash/atom_rom.xml",16011,"game_data"],["bios/mame/hash/attache.xml",555,"game_data"],["bios/mame/hash/aussiebyte.xml",545,"game_data"],["bios/mame/hash/b2m.xml",1244,"game_data"],["bios/mame/hash/basf7100.xml",881,"game_data"],["bios/mame/hash/bbc_cass.xml",736181,"game_data"],["bios/mame/hash/bbc_flop_32016.xml",8282,"game_data"],["bios/mame/hash/bbc_flop_6502.xml",6281,"game_data"],["bios/mame/hash/bbc_flop_68000.xml",1770,"game_data"],["bios/mame/hash/bbc_flop_80186.xml",7946,"game_data"],["bios/mame/hash/bbc_flop_arm.xml",11609,"game_data"],["bios/mame/hash/bbc_flop_hybrid.xml",40742,"game_data"],["bios/mame/hash/bbc_flop_torch.xml",19139,"game_data"],["bios/mame/hash/bbc_flop_z80.xml",7743,"game_data"],["bios/mame/hash/bbc_hdd.xml",2639,"game_data"],["bios/mame/hash/bbc_rom.xml",502371,"game_data"],["bios/mame/hash/bbc_vsm.xml",2571,"game_data"],["bios/mame/hash/bbcb_flop.xml",124846,"game_data"],["bios/mame/hash/bbcb_flop_orig.xml",158528,"game_data"],["bios/mame/hash/bbcb_flop_us.xml",743,"game_data"],["bios/mame/hash/bbcbc.xml",5189,"game_data"],["bios/mame/hash/bbcm_cart.xml",11115,"game_data"],["bios/mame/hash/bbcm_flop.xml",5301,"game_data"],["bios/mame/hash/bbcmc_flop.xml",17528,"game_data"],["bios/mame/hash/bdesignm_design_cart.xml",3983,"game_data"],["bios/mame/hash/bdesignm_game_cart.xml",3809,"game_data"],["bios/mame/hash/bingobear.xml",1244,"game_data"],["bios/mame/hash/bk0010.xml",49493,"game_data"],["bios/mame/hash/bkrankp_cart.xml",9615,"game_data"],["bios/mame/hash/bmjr_cass.xml",790,"game_data"],["bios/mame/hash/bml3_cass.xml",1359,"game_data"],["bios/mame/hash/bml3_flop.xml",4172,"game_data"],["bios/mame/hash/brother_pn.xml",1902,"game_data"],["bios/mame/hash/bungo_flop.xml",2355,"game_data"],["bios/mame/hash/buzztime_cart.xml",1855,"game_data"],["bios/mame/hash/bw12.xml",869,"game_data"],["bios/mame/hash/bw14.xml",4116,"game_data"],["bios/mame/hash/bw2.xml",2574,"game_data"],["bios/mame/hash/bx256hp_flop.xml",4979,"game_data"],["bios/mame/hash/c128_cart.xml",7667,"game_data"],["bios/mame/hash/c128_flop.xml",29219,"game_data"],["bios/mame/hash/c128_rom.xml",3843,"game_data"],["bios/mame/hash/c2color_cart.xml",4498,"game_data"],["bios/mame/hash/c64_cart.xml",258956,"game_data"],["bios/mame/hash/c64_cass.xml",578831,"game_data"],["bios/mame/hash/c64_flop_misc.xml",34001,"game_data"],["bios/mame/hash/c64_flop_orig.xml",30419,"game_data"],["bios/mame/hash/c64_quik.xml",585,"game_data"],["bios/mame/hash/c65_flop.xml",616,"game_data"],["bios/mame/hash/camplynx_cass.xml",37656,"game_data"],["bios/mame/hash/camplynx_flop.xml",13892,"game_data"],["bios/mame/hash/carbeena.xml",811,"game_data"],["bios/mame/hash/casio_rompack.xml",72987,"game_data"],["bios/mame/hash/casloopy.xml",7085,"game_data"],["bios/mame/hash/cassvisn_cart.xml",8242,"game_data"],["bios/mame/hash/cbm2_cart.xml",2432,"game_data"],["bios/mame/hash/cbm2_flop.xml",55851,"game_data"],["bios/mame/hash/cbm8096_flop.xml",976,"game_data"],["bios/mame/hash/cbm8296_flop.xml",1344,"game_data"],["bios/mame/hash/cc40_cart.xml",4533,"game_data"],["bios/mame/hash/cd32.xml",73479,"game_data"],["bios/mame/hash/cdi.xml",541705,"game_data"],["bios/mame/hash/cdtv.xml",128903,"game_data"],["bios/mame/hash/cecflop.xml",9584,"game_data"],["bios/mame/hash/cgenie_cass.xml",135849,"game_data"],["bios/mame/hash/cgenie_flop_rom.xml",1068,"game_data"],["bios/mame/hash/challenge_gear_cart.xml",1798,"game_data"],["bios/mame/hash/channelf.xml",20040,"game_data"],["bios/mame/hash/chessking_cart.xml",641,"game_data"],["bios/mame/hash/chessmstdm.xml",1095,"game_data"],["bios/mame/hash/chip8_quik.xml",32203,"game_data"],["bios/mame/hash/clickstart_cart.xml",10218,"game_data"],["bios/mame/hash/clipper_flop.xml",1190,"game_data"],["bios/mame/hash/coco_cart.xml",57803,"game_data"],["bios/mame/hash/coco_flop.xml",81301,"game_data"],["bios/mame/hash/coleco.xml",153128,"game_data"],["bios/mame/hash/coleco_homebrew.xml",89593,"game_data"],["bios/mame/hash/compclr2_flop.xml",94972,"game_data"],["bios/mame/hash/compis.xml",40308,"game_data"],["bios/mame/hash/comx35_flop.xml",543,"game_data"],["bios/mame/hash/conchess.xml",1245,"game_data"],["bios/mame/hash/copera.xml",5754,"game_data"],["bios/mame/hash/cpc_cass.xml",1991951,"game_data"],["bios/mame/hash/cpc_flop.xml",12700511,"game_data"],["bios/mame/hash/crvision.xml",29061,"game_data"],["bios/mame/hash/ctvboy.xml",3078,"game_data"],["bios/mame/hash/cubieboard4.xml",3873,"game_data"],["bios/mame/hash/cx3000tc.xml",2044,"game_data"],["bios/mame/hash/cz1_cart.xml",1477,"game_data"],["bios/mame/hash/dai_cass.xml",4412,"game_data"],["bios/mame/hash/database.xml",8810,"game_data"],["bios/mame/hash/dc.xml",1547464,"game_data"],["bios/mame/hash/dgnalpha_flop.xml",6812,"game_data"],["bios/mame/hash/dgnbeta_flop.xml",1891,"game_data"],["bios/mame/hash/digiblast_cart.xml",10923,"game_data"],["bios/mame/hash/digilog320.xml",1545,"game_data"],["bios/mame/hash/dim68k.xml",7070,"game_data"],["bios/mame/hash/dmv.xml",54867,"game_data"],["bios/mame/hash/dps1.xml",596,"game_data"],["bios/mame/hash/dragon_cart.xml",19887,"game_data"],["bios/mame/hash/dragon_cass.xml",452453,"game_data"],["bios/mame/hash/dragon_flex.xml",11710,"game_data"],["bios/mame/hash/dragon_flop.xml",78876,"game_data"],["bios/mame/hash/dragon_os9.xml",7566,"game_data"],["bios/mame/hash/duelmast_cart.xml",1148,"game_data"],["bios/mame/hash/e01_flop.xml",972,"game_data"],["bios/mame/hash/easy_karaoke_cart.xml",16341,"game_data"],["bios/mame/hash/ec1841.xml",4295,"game_data"],["bios/mame/hash/einstein.xml",53792,"game_data"],["bios/mame/hash/einstein_rom.xml",547,"game_data"],["bios/mame/hash/ekara_cart.xml",193645,"game_data"],["bios/mame/hash/electron_cart.xml",22690,"game_data"],["bios/mame/hash/electron_cass.xml",270749,"game_data"],["bios/mame/hash/electron_flop.xml",105636,"game_data"],["bios/mame/hash/electron_rom.xml",36576,"game_data"],["bios/mame/hash/entex_sag.xml",3620,"game_data"],["bios/mame/hash/ep64_cart.xml",6240,"game_data"],["bios/mame/hash/ep64_cass.xml",1272,"game_data"],["bios/mame/hash/ep64_flop.xml",73009,"game_data"],["bios/mame/hash/epson_cpm.xml",5880,"game_data"],["bios/mame/hash/eti660_quik.xml",2480,"game_data"],["bios/mame/hash/evio.xml",10523,"game_data"],["bios/mame/hash/ews286_flop.xml",1384,"game_data"],["bios/mame/hash/excalibur64.xml",551,"game_data"],["bios/mame/hash/exl100.xml",6011,"game_data"],["bios/mame/hash/famibox.xml",31176,"game_data"],["bios/mame/hash/famicom_cass.xml",21948,"game_data"],["bios/mame/hash/famicom_flop.xml",168824,"game_data"],["bios/mame/hash/fidel_msc.xml",1132,"game_data"],["bios/mame/hash/fidel_sc6.xml",565,"game_data"],["bios/mame/hash/fidel_scc.xml",4897,"game_data"],["bios/mame/hash/fm77av.xml",56002,"game_data"],["bios/mame/hash/fm7_cass.xml",84996,"game_data"],["bios/mame/hash/fm7_disk.xml",94601,"game_data"],["bios/mame/hash/fm8_cass.xml",13963,"game_data"],["bios/mame/hash/fmtowns_cd.xml",2734453,"game_data"],["bios/mame/hash/fmtowns_flop_cracked.xml",3606,"game_data"],["bios/mame/hash/fmtowns_flop_misc.xml",63683,"game_data"],["bios/mame/hash/fmtowns_flop_orig.xml",150372,"game_data"],["bios/mame/hash/fp1100_cass.xml",4676,"game_data"],["bios/mame/hash/gaelco_ds5002fp_rom.xml",4164,"game_data"],["bios/mame/hash/galaxy.xml",24068,"game_data"],["bios/mame/hash/gamate.xml",27468,"game_data"],["bios/mame/hash/gameboy.xml",1136450,"game_data"],["bios/mame/hash/gamecom.xml",10648,"game_data"],["bios/mame/hash/gamegear.xml",414475,"game_data"],["bios/mame/hash/gameking.xml",21981,"game_data"],["bios/mame/hash/gameking3.xml",4399,"game_data"],["bios/mame/hash/gamepock.xml",2708,"game_data"],["bios/mame/hash/gba.xml",1727109,"game_data"],["bios/mame/hash/gba_ereader.xml",286933,"game_data"],["bios/mame/hash/gbcolor.xml",1161729,"game_data"],["bios/mame/hash/gcslottv.xml",2531,"game_data"],["bios/mame/hash/generic_cdrom.xml",52075,"game_data"],["bios/mame/hash/generic_flop_525.xml",4909,"game_data"],["bios/mame/hash/genie3_flop.xml",4849,"game_data"],["bios/mame/hash/ggm.xml",8019,"game_data"],["bios/mame/hash/gimix.xml",2241,"game_data"],["bios/mame/hash/gj4000.xml",681,"game_data"],["bios/mame/hash/gjmovie.xml",760,"game_data"],["bios/mame/hash/gjrstar.xml",2795,"game_data"],["bios/mame/hash/gl2000.xml",4022,"game_data"],["bios/mame/hash/gl6000sl.xml",1205,"game_data"],["bios/mame/hash/glcolor.xml",2575,"game_data"],["bios/mame/hash/glcx.xml",4447,"game_data"],["bios/mame/hash/gln.xml",1724,"game_data"],["bios/mame/hash/gls.xml",609,"game_data"],["bios/mame/hash/gmaster.xml",7077,"game_data"],["bios/mame/hash/gp32.xml",20073,"game_data"],["bios/mame/hash/gtfore.xml",2385,"game_data"],["bios/mame/hash/guab.xml",4131,"game_data"],["bios/mame/hash/gx4000.xml",12933,"game_data"],["bios/mame/hash/h21.xml",1358,"game_data"],["bios/mame/hash/h88_cass.xml",6198,"game_data"],["bios/mame/hash/hikara.xml",23854,"game_data"],["bios/mame/hash/horizon.xml",110171,"game_data"],["bios/mame/hash/hp85_rom.xml",2800,"game_data"],["bios/mame/hash/hp86_rom.xml",5029,"game_data"],["bios/mame/hash/hp9825_rom.xml",6691,"game_data"],["bios/mame/hash/hp9831_rom.xml",1188,"game_data"],["bios/mame/hash/hp9835a_rom.xml",2757,"game_data"],["bios/mame/hash/hp9845a_rom.xml",4328,"game_data"],["bios/mame/hash/hp9845b_rom.xml",19426,"game_data"],["bios/mame/hash/hp98x6_rom.xml",1486,"game_data"],["bios/mame/hash/hp9k3xx_cdrom.xml",7323,"game_data"],["bios/mame/hash/hp9k3xx_flop.xml",30834,"game_data"],["bios/mame/hash/hp9k3xx_hdd.xml",691,"game_data"],["bios/mame/hash/hp_ipc.xml",23990,"game_data"],["bios/mame/hash/hp_ipc_rom.xml",672,"game_data"],["bios/mame/hash/ht68k.xml",923,"game_data"],["bios/mame/hash/hx20_rom.xml",904,"game_data"],["bios/mame/hash/hyperscan.xml",2390,"game_data"],["bios/mame/hash/hyperscan_card.xml",193115,"game_data"],["bios/mame/hash/i7000_card.xml",7455,"game_data"],["bios/mame/hash/ibm5140.xml",1967,"game_data"],["bios/mame/hash/ibm5150.xml",824234,"game_data"],["bios/mame/hash/ibm5150_cass.xml",736,"game_data"],["bios/mame/hash/ibm5150_hdd.xml",5316,"game_data"],["bios/mame/hash/ibm5170.xml",1162208,"game_data"],["bios/mame/hash/ibm5170_cdrom.xml",454762,"game_data"],["bios/mame/hash/ibm5170_hdd.xml",12253,"game_data"],["bios/mame/hash/ibm6580.xml",4972,"game_data"],["bios/mame/hash/ibmpc110.xml",1581,"game_data"],["bios/mame/hash/ibmpcjr_cart.xml",9823,"game_data"],["bios/mame/hash/ibmpcjr_flop.xml",6253,"game_data"],["bios/mame/hash/ibmpcjx.xml",2034,"game_data"],["bios/mame/hash/icanguit.xml",4013,"game_data"],["bios/mame/hash/icanpian.xml",7041,"game_data"],["bios/mame/hash/intellect02.xml",1026,"game_data"],["bios/mame/hash/interact.xml",14054,"game_data"],["bios/mame/hash/interpro.xml",15826,"game_data"],["bios/mame/hash/intv.hsi",21652,"game_data"],["bios/mame/hash/intv.xml",100100,"game_data"],["bios/mame/hash/intvecs.xml",7161,"game_data"],["bios/mame/hash/iq128.xml",1656,"game_data"],["bios/mame/hash/iq151_cart.xml",2180,"game_data"],["bios/mame/hash/iq151_flop.xml",1019,"game_data"],["bios/mame/hash/ique.xml",18576,"game_data"],["bios/mame/hash/iqunlim_cart.xml",1166,"game_data"],["bios/mame/hash/itt3030.xml",1428,"game_data"],["bios/mame/hash/jaguar.xml",78281,"game_data"],["bios/mame/hash/jakks_gamekey_dp.xml",761,"game_data"],["bios/mame/hash/jakks_gamekey_dy.xml",2768,"game_data"],["bios/mame/hash/jakks_gamekey_mv.xml",756,"game_data"],["bios/mame/hash/jakks_gamekey_nk.xml",1934,"game_data"],["bios/mame/hash/jakks_gamekey_nm.xml",2051,"game_data"],["bios/mame/hash/jakks_gamekey_sw.xml",2931,"game_data"],["bios/mame/hash/jakks_gamekey_wp.xml",1064,"game_data"],["bios/mame/hash/jaminator.xml",6011,"game_data"],["bios/mame/hash/jazz.xml",1564,"game_data"],["bios/mame/hash/jb3000_flop.xml",660,"game_data"],["bios/mame/hash/juicebox.xml",18075,"game_data"],["bios/mame/hash/juku.xml",6267,"game_data"],["bios/mame/hash/jupace_cass.xml",81423,"game_data"],["bios/mame/hash/jupace_snap.xml",2564,"game_data"],["bios/mame/hash/k28.xml",3157,"game_data"],["bios/mame/hash/k28o.xml",827,"game_data"],["bios/mame/hash/kaypro.xml",8389,"game_data"],["bios/mame/hash/kc_cart.xml",2336,"game_data"],["bios/mame/hash/kc_cass.xml",70753,"game_data"],["bios/mame/hash/kc_flop.xml",2125,"game_data"],["bios/mame/hash/kim1_cass.xml",4296,"game_data"],["bios/mame/hash/kisssite_cd.xml",13436,"game_data"],["bios/mame/hash/korvet_flop.xml",8743,"game_data"],["bios/mame/hash/kpython2.xml",3610,"game_data"],["bios/mame/hash/lanteach.xml",561,"game_data"],["bios/mame/hash/lantrans.xml",4167,"game_data"],["bios/mame/hash/laser2001_cart.xml",729,"game_data"],["bios/mame/hash/laser2001_flop.xml",587,"game_data"],["bios/mame/hash/leapfrog_didj_cart.xml",3419,"game_data"],["bios/mame/hash/leapfrog_iquest_cart.xml",996,"game_data"],["bios/mame/hash/leapfrog_leappad_cart.xml",91522,"game_data"],["bios/mame/hash/leapfrog_ltleappad_cart.xml",9206,"game_data"],["bios/mame/hash/leapfrog_mfleappad_cart.xml",11748,"game_data"],["bios/mame/hash/leapfrog_zippity_cart.xml",1903,"game_data"],["bios/mame/hash/leapster.xml",79859,"game_data"],["bios/mame/hash/leapster_explorer_cart.xml",2082,"game_data"],["bios/mame/hash/lisa.xml",35666,"game_data"],["bios/mame/hash/lisa2.xml",5305,"game_data"],["bios/mame/hash/lk3000.xml",2341,"game_data"],["bios/mame/hash/lnux4004.xml",551,"game_data"],["bios/mame/hash/lviv.xml",117889,"game_data"],["bios/mame/hash/lynx.xml",57321,"game_data"],["bios/mame/hash/m20.xml",24233,"game_data"],["bios/mame/hash/m24.xml",585,"game_data"],["bios/mame/hash/m3.xml",567,"game_data"],["bios/mame/hash/m5_cart.xml",24121,"game_data"],["bios/mame/hash/m5_cass.xml",16984,"game_data"],["bios/mame/hash/m5_flop.xml",1025,"game_data"],["bios/mame/hash/mac_cdrom.xml",9773,"game_data"],["bios/mame/hash/mac_flop.xml",9064,"game_data"],["bios/mame/hash/mac_flop_clcracked.xml",131047,"game_data"],["bios/mame/hash/mac_flop_orig.xml",199535,"game_data"],["bios/mame/hash/mac_hdd.xml",3737,"game_data"],["bios/mame/hash/mac_hdflop.xml",329807,"game_data"],["bios/mame/hash/mbc200.xml",906,"game_data"],["bios/mame/hash/mbc55x.xml",6393,"game_data"],["bios/mame/hash/mbee_cart.xml",23641,"game_data"],["bios/mame/hash/mbee_cass.xml",1994,"game_data"],["bios/mame/hash/mbee_flop.xml",218405,"game_data"],["bios/mame/hash/mbee_quik.xml",64816,"game_data"],["bios/mame/hash/mc10.xml",52188,"game_data"],["bios/mame/hash/mc1000_cass.xml",53448,"game_data"],["bios/mame/hash/mc1502_flop.xml",949,"game_data"],["bios/mame/hash/md2_flop.xml",2723,"game_data"],["bios/mame/hash/megacd.xml",1291438,"game_data"],["bios/mame/hash/megadriv.xml",1656213,"game_data"],["bios/mame/hash/megaduck.xml",19227,"game_data"],["bios/mame/hash/megapc.xml",1756,"game_data"],["bios/mame/hash/megatech.xml",31502,"game_data"],["bios/mame/hash/mephisto_mm1.xml",613,"game_data"],["bios/mame/hash/mephisto_mm2.xml",650,"game_data"],["bios/mame/hash/mephisto_mm4.xml",618,"game_data"],["bios/mame/hash/mephisto_mm5.xml",616,"game_data"],["bios/mame/hash/mephisto_smondial2.xml",681,"game_data"],["bios/mame/hash/microbox2_flop.xml",955,"game_data"],["bios/mame/hash/microvision.xml",12187,"game_data"],["bios/mame/hash/midi_flop.xml",1102,"game_data"],["bios/mame/hash/mikro80.xml",2155,"game_data"],["bios/mame/hash/mikrosha_cart.xml",564,"game_data"],["bios/mame/hash/mikrosha_cass.xml",19640,"game_data"],["bios/mame/hash/mindset_flop.xml",889,"game_data"],["bios/mame/hash/misterx.xml",1485,"game_data"],["bios/mame/hash/mk14_quik.xml",1607,"game_data"],["bios/mame/hash/mm1_flop.xml",3737,"game_data"],["bios/mame/hash/mm2_flop.xml",1145,"game_data"],["bios/mame/hash/mm2_hdd.xml",564,"game_data"],["bios/mame/hash/mo5_cart.xml",21269,"game_data"],["bios/mame/hash/mo5_cass.xml",706525,"game_data"],["bios/mame/hash/mo5_flop.xml",32837,"game_data"],["bios/mame/hash/mo5_qd.xml",12350,"game_data"],["bios/mame/hash/mo6_cass.xml",70027,"game_data"],["bios/mame/hash/mo6_flop.xml",23106,"game_data"],["bios/mame/hash/mobigo_cart.xml",23750,"game_data"],["bios/mame/hash/monon_color.xml",15292,"game_data"],["bios/mame/hash/mpc3000_flop.xml",3350,"game_data"],["bios/mame/hash/mpc60_flop.xml",15063,"game_data"],["bios/mame/hash/mpf1_rom.xml",2881,"game_data"],["bios/mame/hash/mpu1000.xml",614,"game_data"],["bios/mame/hash/mpz80.xml",21352,"game_data"],["bios/mame/hash/msx.hsi",130435,"game_data"],["bios/mame/hash/msx1_bee_card.xml",5450,"game_data"],["bios/mame/hash/msx1_cart.xml",1069721,"game_data"],["bios/mame/hash/msx1_cass.xml",815967,"game_data"],["bios/mame/hash/msx1_flop.xml",243313,"game_data"],["bios/mame/hash/msx1_flop_525.xml",8311,"game_data"],["bios/mame/hash/msx2.hsi",290917,"game_data"],["bios/mame/hash/msx2_cart.xml",191807,"game_data"],["bios/mame/hash/msx2_cass.xml",2308,"game_data"],["bios/mame/hash/msx2_flop.xml",1138601,"game_data"],["bios/mame/hash/msx2p_cart.xml",2243,"game_data"],["bios/mame/hash/msx2p_flop.xml",35351,"game_data"],["bios/mame/hash/msx_softcard.xml",2406,"game_data"],["bios/mame/hash/msx_yamaha_minicart.xml",913,"game_data"],["bios/mame/hash/msxr_cart.xml",4556,"game_data"],["bios/mame/hash/msxr_flop.xml",58312,"game_data"],["bios/mame/hash/mt65_cass.xml",3972,"game_data"],["bios/mame/hash/mt65_rom.xml",7665,"game_data"],["bios/mame/hash/mt65_snap.xml",6125,"game_data"],["bios/mame/hash/mtu130_flop.xml",2682,"game_data"],["bios/mame/hash/mtx_cart.xml",3484,"game_data"],["bios/mame/hash/mtx_cass.xml",23223,"game_data"],["bios/mame/hash/mtx_flop.xml",3849,"game_data"],["bios/mame/hash/mtx_hdd.xml",1479,"game_data"],["bios/mame/hash/mtx_rom.xml",2033,"game_data"],["bios/mame/hash/mylife_cart.xml",3029,"game_data"],["bios/mame/hash/myvision.xml",10822,"game_data"],["bios/mame/hash/mz2000_cass.xml",18487,"game_data"],["bios/mame/hash/mz2000_flop.xml",6827,"game_data"],["bios/mame/hash/mz2000_snap.xml",6357,"game_data"],["bios/mame/hash/mz2500_flop.xml",41591,"game_data"],["bios/mame/hash/mz5500_flop.xml",3298,"game_data"],["bios/mame/hash/mz700_cass.xml",101940,"game_data"],["bios/mame/hash/mz800_cass.xml",6416,"game_data"],["bios/mame/hash/mz800_rom.xml",1699,"game_data"],["bios/mame/hash/mz80b_cass.xml",3476,"game_data"],["bios/mame/hash/mz80b_flop.xml",1334,"game_data"],["bios/mame/hash/mz80k_cass.xml",17674,"game_data"],["bios/mame/hash/n64.xml",634504,"game_data"],["bios/mame/hash/n64_lodgenet.xml",18886,"game_data"],["bios/mame/hash/n64dd.xml",7365,"game_data"],["bios/mame/hash/nascom_flop.xml",4009,"game_data"],["bios/mame/hash/nascom_snap.xml",32837,"game_data"],["bios/mame/hash/nascom_socket.xml",2918,"game_data"],["bios/mame/hash/neocd.xml",69767,"game_data"],["bios/mame/hash/neogeo.xml",861636,"game_data"],["bios/mame/hash/nes.hsi",2901163,"game_data"],["bios/mame/hash/nes.xml",3760989,"game_data"],["bios/mame/hash/nes_ade.xml",3683,"game_data"],["bios/mame/hash/nes_datach.xml",5512,"game_data"],["bios/mame/hash/nes_kstudio.xml",1679,"game_data"],["bios/mame/hash/nes_ntbrom.xml",1534,"game_data"],["bios/mame/hash/nes_vt_cart.xml",1225,"game_data"],["bios/mame/hash/next.xml",4495,"game_data"],["bios/mame/hash/next_cdrom.xml",2473,"game_data"],["bios/mame/hash/next_hdd.xml",5837,"game_data"],["bios/mame/hash/ngp.xml",6692,"game_data"],["bios/mame/hash/ngpc.xml",69520,"game_data"],["bios/mame/hash/nimbus.xml",14651,"game_data"],["bios/mame/hash/novag_ssensor4.xml",690,"game_data"],["bios/mame/hash/nuon.xml",3452,"game_data"],["bios/mame/hash/octopus.xml",3416,"game_data"],["bios/mame/hash/ondra.xml",4936,"game_data"],["bios/mame/hash/orao.xml",25307,"game_data"],["bios/mame/hash/oric1_cass.xml",201867,"game_data"],["bios/mame/hash/orina_stylish_plus_cart.xml",694,"game_data"],["bios/mame/hash/orion_cart.xml",898,"game_data"],["bios/mame/hash/orion_cass.xml",28871,"game_data"],["bios/mame/hash/orion_flop.xml",42898,"game_data"],["bios/mame/hash/orionpro_flop.xml",12350,"game_data"],["bios/mame/hash/osborne1.xml",10325,"game_data"],["bios/mame/hash/osborne2.xml",2130,"game_data"],["bios/mame/hash/p2000_cart.xml",19726,"game_data"],["bios/mame/hash/p2000_cass.xml",80619,"game_data"],["bios/mame/hash/p500_flop.xml",925,"game_data"],["bios/mame/hash/partner_cass.xml",27737,"game_data"],["bios/mame/hash/partner_flop.xml",890,"game_data"],["bios/mame/hash/pasogo.xml",4088,"game_data"],["bios/mame/hash/pasopia7_cass.xml",1740,"game_data"],["bios/mame/hash/pasopia_cass.xml",3381,"game_data"],["bios/mame/hash/pb2000c.xml",994,"game_data"],["bios/mame/hash/pc1000.xml",5519,"game_data"],["bios/mame/hash/pc100_flop.xml",3563,"game_data"],["bios/mame/hash/pc1512_flop.xml",6358,"game_data"],["bios/mame/hash/pc1512_hdd.xml",511,"game_data"],["bios/mame/hash/pc1640_flop.xml",2796,"game_data"],["bios/mame/hash/pc1640_hdd.xml",572,"game_data"],["bios/mame/hash/pc200.xml",1683,"game_data"],["bios/mame/hash/pc6001_cart.xml",6880,"game_data"],["bios/mame/hash/pc6001_cass.xml",52713,"game_data"],["bios/mame/hash/pc6001mk2_cass.xml",42402,"game_data"],["bios/mame/hash/pc6001mk2_flop.xml",5521,"game_data"],["bios/mame/hash/pc6001mk2sr_cass.xml",8673,"game_data"],["bios/mame/hash/pc6001mk2sr_flop.xml",1876,"game_data"],["bios/mame/hash/pc8001_flop.xml",131233,"game_data"],["bios/mame/hash/pc8001mk2_flop.xml",10373,"game_data"],["bios/mame/hash/pc8001mk2sr_flop.xml",7003,"game_data"],["bios/mame/hash/pc8201.xml",1733,"game_data"],["bios/mame/hash/pc8801_cass.xml",56042,"game_data"],["bios/mame/hash/pc8801_cdrom.xml",6105,"game_data"],["bios/mame/hash/pc8801_flop.xml",2323906,"game_data"],["bios/mame/hash/pc8801_flop_orig.xml",840,"game_data"],["bios/mame/hash/pc88va.xml",66115,"game_data"],["bios/mame/hash/pc88va_flop_orig.xml",5665,"game_data"],["bios/mame/hash/pc98.xml",3156503,"game_data"],["bios/mame/hash/pc98_cd.xml",496918,"game_data"],["bios/mame/hash/pc98_flop_orig.xml",10051,"game_data"],["bios/mame/hash/pc98_hdd.xml",939,"game_data"],["bios/mame/hash/pcd_flop.xml",2088,"game_data"],["bios/mame/hash/pce.xml",168484,"game_data"],["bios/mame/hash/pce_tourvision.xml",64224,"game_data"],["bios/mame/hash/pcecd.xml",359086,"game_data"],["bios/mame/hash/pcfx.xml",6670,"game_data"],["bios/mame/hash/pcw.xml",74002,"game_data"],["bios/mame/hash/pcw16.xml",2116,"game_data"],["bios/mame/hash/pcx_flop.xml",7886,"game_data"],["bios/mame/hash/pda600.xml",1050,"game_data"],["bios/mame/hash/pdp1_ptp.xml",2537,"game_data"],["bios/mame/hash/pecom_cass.xml",3816,"game_data"],["bios/mame/hash/pegasus_cart.xml",8532,"game_data"],["bios/mame/hash/pencil2.xml",4876,"game_data"],["bios/mame/hash/pencil2_cass.xml",7881,"game_data"],["bios/mame/hash/pentagon_cass.xml",1246,"game_data"],["bios/mame/hash/pet_cass.xml",106400,"game_data"],["bios/mame/hash/pet_flop.xml",33750,"game_data"],["bios/mame/hash/pet_hdd.xml",1283,"game_data"],["bios/mame/hash/pet_quik.xml",1032,"game_data"],["bios/mame/hash/pet_rom.xml",14809,"game_data"],["bios/mame/hash/phc25_cass.xml",12548,"game_data"],["bios/mame/hash/photo_cd.xml",1400,"game_data"],["bios/mame/hash/pi_storyreader_cart.xml",22422,"game_data"],["bios/mame/hash/pi_storyreader_v2_cart.xml",658,"game_data"],["bios/mame/hash/picno.xml",12147,"game_data"],["bios/mame/hash/pico.xml",288031,"game_data"],["bios/mame/hash/pippin.xml",45021,"game_data"],["bios/mame/hash/pippin_flop.xml",750,"game_data"],["bios/mame/hash/pixter_cart.xml",2630,"game_data"],["bios/mame/hash/playmaker.xml",1242,"game_data"],["bios/mame/hash/pls1000_cart.xml",2938,"game_data"],["bios/mame/hash/plus4_cart.xml",10278,"game_data"],["bios/mame/hash/plus4_cass.xml",1191,"game_data"],["bios/mame/hash/plus4_flop.xml",2108,"game_data"],["bios/mame/hash/plus4_quik.xml",951,"game_data"],["bios/mame/hash/pmd85_cass.xml",45145,"game_data"],["bios/mame/hash/pockchalv2.xml",18615,"game_data"],["bios/mame/hash/pockchalw.xml",30826,"game_data"],["bios/mame/hash/pofo.xml",2062,"game_data"],["bios/mame/hash/poisk1_flop.xml",961,"game_data"],["bios/mame/hash/pokemini.xml",19575,"game_data"],["bios/mame/hash/poly_flop.xml",1085,"game_data"],["bios/mame/hash/polysix.xml",889,"game_data"],["bios/mame/hash/popstar_cart.xml",1581,"game_data"],["bios/mame/hash/precur2w_cart.xml",782,"game_data"],["bios/mame/hash/princ.xml",3746,"game_data"],["bios/mame/hash/pro128_cart.xml",1868,"game_data"],["bios/mame/hash/pro128_cass.xml",81276,"game_data"],["bios/mame/hash/pro128_flop.xml",1233,"game_data"],["bios/mame/hash/pro128s_flop.xml",14348,"game_data"],["bios/mame/hash/prof180.xml",1181,"game_data"],["bios/mame/hash/prof80.xml",865,"game_data"],["bios/mame/hash/psi98.xml",1275,"game_data"],["bios/mame/hash/psion1.xml",3874,"game_data"],["bios/mame/hash/psion2.xml",79959,"game_data"],["bios/mame/hash/psion_flop.xml",1096,"game_data"],["bios/mame/hash/psion_quik.xml",5838,"game_data"],["bios/mame/hash/psion_ssd.xml",21905,"game_data"],["bios/mame/hash/psx.xml",3919227,"game_data"],["bios/mame/hash/pt68k2.xml",555,"game_data"],["bios/mame/hash/pv1000.xml",12768,"game_data"],["bios/mame/hash/pv2000.xml",11468,"game_data"],["bios/mame/hash/px4_cart.xml",3064,"game_data"],["bios/mame/hash/px8_cart.xml",7208,"game_data"],["bios/mame/hash/pyl601.xml",5562,"game_data"],["bios/mame/hash/ql_cart.xml",1279,"game_data"],["bios/mame/hash/ql_cass.xml",1897,"game_data"],["bios/mame/hash/ql_flop.xml",2234,"game_data"],["bios/mame/hash/quizwiz.xml",3091,"game_data"],["bios/mame/hash/qx10_flop.xml",3250,"game_data"],["bios/mame/hash/r8_card.xml",4710,"game_data"],["bios/mame/hash/r9751.xml",10712,"game_data"],["bios/mame/hash/radio86_cart.xml",539,"game_data"],["bios/mame/hash/radio86_cass.xml",36046,"game_data"],["bios/mame/hash/rainbow.xml",10136,"game_data"],["bios/mame/hash/ramstar.xml",6165,"game_data"],["bios/mame/hash/roland_tnsc1.xml",4197,"game_data"],["bios/mame/hash/roland_tnsc2.xml",3332,"game_data"],["bios/mame/hash/rwtrntcs.xml",1090,"game_data"],["bios/mame/hash/rx78_cart.xml",20435,"game_data"],["bios/mame/hash/rx78_cass.xml",1469,"game_data"],["bios/mame/hash/rz1_cass.xml",2687,"game_data"],["bios/mame/hash/s2000_flop.xml",603,"game_data"],["bios/mame/hash/s3000_cdrom.xml",3926,"game_data"],["bios/mame/hash/sagafox.xml",531,"game_data"],["bios/mame/hash/sage2.xml",4188,"game_data"],["bios/mame/hash/saitek_egr.xml",2069,"game_data"],["bios/mame/hash/saitek_kso.xml",1105,"game_data"],["bios/mame/hash/saitek_schess.xml",1334,"game_data"],["bios/mame/hash/samcoupe_cass.xml",1614,"game_data"],["bios/mame/hash/samcoupe_flop.xml",21118,"game_data"],["bios/mame/hash/sat_cart.xml",6332,"game_data"],["bios/mame/hash/sat_vccart.xml",8717,"game_data"],["bios/mame/hash/saturn.xml",1716943,"game_data"],["bios/mame/hash/sawatte.xml",10312,"game_data"],["bios/mame/hash/sb80_flop.xml",2853,"game_data"],["bios/mame/hash/sbrain.xml",525,"game_data"],["bios/mame/hash/sc3000_cart.xml",16483,"game_data"],["bios/mame/hash/sc3000_cass.xml",19145,"game_data"],["bios/mame/hash/scv.xml",15177,"game_data"],["bios/mame/hash/sd132_flop.xml",2596,"game_data"],["bios/mame/hash/sd1_flop.xml",568,"game_data"],["bios/mame/hash/sdk85.xml",1175,"game_data"],["bios/mame/hash/sega_beena_cart.xml",210730,"game_data"],["bios/mame/hash/segaai.xml",34327,"game_data"],["bios/mame/hash/sf7000.xml",10494,"game_data"],["bios/mame/hash/sg1000.xml",118348,"game_data"],["bios/mame/hash/sgi_mips.xml",242357,"game_data"],["bios/mame/hash/sgi_mips_hdd.xml",2337,"game_data"],["bios/mame/hash/sgx.xml",2705,"game_data"],["bios/mame/hash/singingstarkaraoke_cart.xml",1479,"game_data"],["bios/mame/hash/sitcom.xml",6387,"game_data"],["bios/mame/hash/smartcycle_cart.xml",6112,"game_data"],["bios/mame/hash/smarttv_cart.xml",6900,"game_data"],["bios/mame/hash/smc777.xml",71270,"game_data"],["bios/mame/hash/sms.xml",350397,"game_data"],["bios/mame/hash/snes.xml",2841229,"game_data"],["bios/mame/hash/snes_bspack.xml",213194,"game_data"],["bios/mame/hash/snes_strom.xml",8678,"game_data"],["bios/mame/hash/snes_vkun.xml",1383,"game_data"],["bios/mame/hash/snotec.xml",8033,"game_data"],["bios/mame/hash/snread.xml",3415,"game_data"],["bios/mame/hash/snspell.xml",5704,"game_data"],["bios/mame/hash/socrates.xml",4963,"game_data"],["bios/mame/hash/softbox.xml",996,"game_data"],["bios/mame/hash/softwarelist.dtd",2483,"game_data"],["bios/mame/hash/sol20_cass.xml",35251,"game_data"],["bios/mame/hash/sony_news.xml",4134,"game_data"],["bios/mame/hash/sorcerer_cart.xml",7212,"game_data"],["bios/mame/hash/sorcerer_cass.xml",58610,"game_data"],["bios/mame/hash/sorcerer_flop.xml",2033,"game_data"],["bios/mame/hash/spc1000_cass.xml",44923,"game_data"],["bios/mame/hash/spc1500_cass.xml",1620,"game_data"],["bios/mame/hash/special_cass.xml",56426,"game_data"],["bios/mame/hash/special_flop.xml",903,"game_data"],["bios/mame/hash/specnext_sd.xml",1136,"game_data"],["bios/mame/hash/specpls3_flop.xml",813283,"game_data"],["bios/mame/hash/spectrum_betadisc_flop.xml",51683,"game_data"],["bios/mame/hash/spectrum_cart.xml",9023,"game_data"],["bios/mame/hash/spectrum_cass.xml",6897158,"game_data"],["bios/mame/hash/spectrum_flop_opus.xml",30500,"game_data"],["bios/mame/hash/spectrum_mgt_flop.xml",4836,"game_data"],["bios/mame/hash/spectrum_microdrive.xml",28256,"game_data"],["bios/mame/hash/spectrum_wafadrive.xml",701,"game_data"],["bios/mame/hash/sprachmg.xml",4905,"game_data"],["bios/mame/hash/squale_cart.xml",2249,"game_data"],["bios/mame/hash/ssem_quik.xml",4598,"game_data"],["bios/mame/hash/st_cart.xml",3348,"game_data"],["bios/mame/hash/st_flop.xml",210727,"game_data"],["bios/mame/hash/st_flop_demos.xml",3744,"game_data"],["bios/mame/hash/stepone_flop.xml",4628,"game_data"],["bios/mame/hash/studio2.xml",32602,"game_data"],["bios/mame/hash/stv.xml",89130,"game_data"],["bios/mame/hash/sun_sparc.xml",4191,"game_data"],["bios/mame/hash/super6.xml",6296,"game_data"],["bios/mame/hash/super80_cass.xml",102426,"game_data"],["bios/mame/hash/super80_flop.xml",1706,"game_data"],["bios/mame/hash/super_tv_pc_cart.xml",3902,"game_data"],["bios/mame/hash/superpet_flop.xml",13019,"game_data"],["bios/mame/hash/supracan.xml",10722,"game_data"],["bios/mame/hash/sv8000.xml",3267,"game_data"],["bios/mame/hash/svi318_cart.xml",4379,"game_data"],["bios/mame/hash/svi318_cass.xml",86966,"game_data"],["bios/mame/hash/svi318_flop.xml",2959,"game_data"],["bios/mame/hash/svision.xml",29557,"game_data"],["bios/mame/hash/svmu.xml",29673,"game_data"],["bios/mame/hash/t1000.xml",7944,"game_data"],["bios/mame/hash/takara_daigunder_dx_cart.xml",1843,"game_data"],["bios/mame/hash/tandy200.xml",1727,"game_data"],["bios/mame/hash/tandy2k.xml",4874,"game_data"],["bios/mame/hash/tandy6k.xml",4732,"game_data"],["bios/mame/hash/tc4.xml",1582,"game_data"],["bios/mame/hash/tdv2324.xml",3160,"game_data"],["bios/mame/hash/tek4052_cart.xml",2734,"game_data"],["bios/mame/hash/telestory_cart.xml",9328,"game_data"],["bios/mame/hash/teradrive_flop.xml",4861,"game_data"],["bios/mame/hash/teradrive_hdd.xml",954,"game_data"],["bios/mame/hash/tg16.xml",37822,"game_data"],["bios/mame/hash/thinkpad8xx.xml",6558,"game_data"],["bios/mame/hash/ti74_cart.xml",1611,"game_data"],["bios/mame/hash/ti95_cart.xml",1071,"game_data"],["bios/mame/hash/ti99_cart.xml",229953,"game_data"],["bios/mame/hash/tiki100.xml",33003,"game_data"],["bios/mame/hash/timex_cass.xml",53889,"game_data"],["bios/mame/hash/timex_dock.xml",17721,"game_data"],["bios/mame/hash/tmc600_quik.xml",1369,"game_data"],["bios/mame/hash/tntell.xml",2942,"game_data"],["bios/mame/hash/to770_cart.xml",772,"game_data"],["bios/mame/hash/to770a_cart.xml",758,"game_data"],["bios/mame/hash/to7_cart.xml",25832,"game_data"],["bios/mame/hash/to7_cass.xml",305755,"game_data"],["bios/mame/hash/to7_qd.xml",9433,"game_data"],["bios/mame/hash/to8_cass.xml",6669,"game_data"],["bios/mame/hash/to8_qd.xml",3289,"game_data"],["bios/mame/hash/to_flop.xml",545143,"game_data"],["bios/mame/hash/triton_rom.xml",532,"game_data"],["bios/mame/hash/trs80_cass.xml",32516,"game_data"],["bios/mame/hash/trs80_flop.xml",2661,"game_data"],["bios/mame/hash/trs80_quik.xml",40444,"game_data"],["bios/mame/hash/trs80m2.xml",9352,"game_data"],["bios/mame/hash/trsm100.xml",5175,"game_data"],["bios/mame/hash/tsconf.xml",16553,"game_data"],["bios/mame/hash/ttwist_brainquest_cart.xml",682,"game_data"],["bios/mame/hash/turboextreme_cart.xml",607,"game_data"],["bios/mame/hash/tutor.xml",17761,"game_data"],["bios/mame/hash/tvc_cart.xml",5156,"game_data"],["bios/mame/hash/tvc_cass.xml",97888,"game_data"],["bios/mame/hash/tvc_flop.xml",326997,"game_data"],["bios/mame/hash/tvdear.xml",1842,"game_data"],["bios/mame/hash/tvgogo.xml",5603,"game_data"],["bios/mame/hash/tvochken.xml",16440,"game_data"],["bios/mame/hash/tx0_ptp.xml",6329,"game_data"],["bios/mame/hash/u110_card.xml",8800,"game_data"],["bios/mame/hash/unichamp.xml",1778,"game_data"],["bios/mame/hash/ut88.xml",2584,"game_data"],["bios/mame/hash/uzebox.xml",50778,"game_data"],["bios/mame/hash/v1050_flop.xml",4387,"game_data"],["bios/mame/hash/v1050_hdd.xml",1054,"game_data"],["bios/mame/hash/vbaby_cart.xml",4246,"game_data"],["bios/mame/hash/vboy.xml",23269,"game_data"],["bios/mame/hash/vc4000.xml",17828,"game_data"],["bios/mame/hash/vector06_cart.xml",679,"game_data"],["bios/mame/hash/vector06_flop.xml",7730,"game_data"],["bios/mame/hash/vectrex.xml",34697,"game_data"],["bios/mame/hash/vfxsd_flop.xml",994,"game_data"],["bios/mame/hash/vg5k.xml",30437,"game_data"],["bios/mame/hash/vgmplay.xml",19970196,"game_data"],["bios/mame/hash/vic10.xml",13030,"game_data"],["bios/mame/hash/vic1001_cart.xml",159400,"game_data"],["bios/mame/hash/vic1001_cass.xml",1136,"game_data"],["bios/mame/hash/vic1001_flop.xml",3222,"game_data"],["bios/mame/hash/victor9k_flop.xml",1056,"game_data"],["bios/mame/hash/vidbrain.xml",9944,"game_data"],["bios/mame/hash/videoart.xml",3840,"game_data"],["bios/mame/hash/videopac.xml",107901,"game_data"],["bios/mame/hash/vii.xml",903,"game_data"],["bios/mame/hash/vip.xml",981,"game_data"],["bios/mame/hash/vis.xml",61330,"game_data"],["bios/mame/hash/visicom.xml",3074,"game_data"],["bios/mame/hash/vixen.xml",7617,"game_data"],["bios/mame/hash/vsmile_cart.xml",284343,"game_data"],["bios/mame/hash/vsmile_cd.xml",28424,"game_data"],["bios/mame/hash/vsmileb_cart.xml",20217,"game_data"],["bios/mame/hash/vsmilem_cart.xml",84670,"game_data"],["bios/mame/hash/vtech2_cass.xml",2383,"game_data"],["bios/mame/hash/vtech_innotab_cart.xml",10101,"game_data"],["bios/mame/hash/vtech_innotv_cart.xml",2019,"game_data"],["bios/mame/hash/vtech_storio_cart.xml",13859,"game_data"],["bios/mame/hash/vz_cass.xml",8941,"game_data"],["bios/mame/hash/vz_snap.xml",63700,"game_data"],["bios/mame/hash/wangpc.xml",2810,"game_data"],["bios/mame/hash/waveterm.xml",2024,"game_data"],["bios/mame/hash/wicat.xml",10200,"game_data"],["bios/mame/hash/wizard_cart.xml",6438,"game_data"],["bios/mame/hash/wmbullet.xml",1680,"game_data"],["bios/mame/hash/wren_flop.xml",2590,"game_data"],["bios/mame/hash/wscolor.xml",103090,"game_data"],["bios/mame/hash/wswan.xml",145839,"game_data"],["bios/mame/hash/x07_card.xml",698,"game_data"],["bios/mame/hash/x07_cass.xml",51019,"game_data"],["bios/mame/hash/x1_cass.xml",76089,"game_data"],["bios/mame/hash/x1_flop.xml",249940,"game_data"],["bios/mame/hash/x37_flop.xml",6292,"game_data"],["bios/mame/hash/x37_hdd.xml",530,"game_data"],["bios/mame/hash/x68k_flop.xml",1441600,"game_data"],["bios/mame/hash/xegs.xml",23925,"game_data"],["bios/mame/hash/xerox820.xml",5473,"game_data"],["bios/mame/hash/xerox820ii.xml",4778,"game_data"],["bios/mame/hash/yeno_laptop_cart.xml",1742,"game_data"],["bios/mame/hash/z80clock.xml",9043,"game_data"],["bios/mame/hash/z80ne_cass.xml",42440,"game_data"],["bios/mame/hash/z80ne_flop.xml",30301,"game_data"],["bios/mame/hash/z88_cart.xml",24642,"game_data"],["bios/mame/hash/zorba.xml",33048,"game_data"],["bios/mame/hash/zx80_cass.xml",3169,"game_data"],["bios/mame/hash/zx81_cass.xml",474158,"game_data"],["bios/mame/plugins/README.md",88,"game_data"],["bios/mame/plugins/autofire/autofire_menu.lua",11558,"game_data"],["bios/mame/plugins/autofire/autofire_save.lua",2817,"game_data"],["bios/mame/plugins/autofire/init.lua",3223,"game_data"],["bios/mame/plugins/autofire/plugin.json",162,"game_data"],["bios/mame/plugins/boot.lua",990,"game_data"],["bios/mame/plugins/cheat/cheat_json.lua",198,"game_data"],["bios/mame/plugins/cheat/cheat_simple.lua",10784,"game_data"],["bios/mame/plugins/cheat/cheat_xml.lua",7419,"game_data"],["bios/mame/plugins/cheat/init.lua",26494,"game_data"],["bios/mame/plugins/cheat/plugin.json",149,"game_data"],["bios/mame/plugins/cheat/xml_to_json.lua",252,"game_data"],["bios/mame/plugins/cheatfind/init.lua",35221,"game_data"],["bios/mame/plugins/cheatfind/plugin.json",168,"game_data"],["bios/mame/plugins/commonui/init.lua",5312,"game_data"],["bios/mame/plugins/commonui/plugin.json",154,"game_data"],["bios/mame/plugins/console/init.lua",8744,"game_data"],["bios/mame/plugins/console/plugin.json",153,"game_data"],["bios/mame/plugins/data/button_char.lua",7593,"game_data"],["bios/mame/plugins/data/data_command.lua",635,"game_data"],["bios/mame/plugins/data/data_gameinit.lua",466,"game_data"],["bios/mame/plugins/data/data_hiscore.lua",41388,"game_data"],["bios/mame/plugins/data/data_history.lua",5235,"game_data"],["bios/mame/plugins/data/data_mameinfo.lua",908,"game_data"],["bios/mame/plugins/data/data_marp.lua",3763,"game_data"],["bios/mame/plugins/data/data_messinfo.lua",912,"game_data"],["bios/mame/plugins/data/data_story.lua",792,"game_data"],["bios/mame/plugins/data/data_sysinfo.lua",475,"game_data"],["bios/mame/plugins/data/database.lua",3853,"game_data"],["bios/mame/plugins/data/init.lua",1938,"game_data"],["bios/mame/plugins/data/load_dat.lua",6420,"game_data"],["bios/mame/plugins/data/plugin.json",146,"game_data"],["bios/mame/plugins/discord/init.lua",2881,"game_data"],["bios/mame/plugins/discord/plugin.json",155,"game_data"],["bios/mame/plugins/dummy/init.lua",881,"game_data"],["bios/mame/plugins/dummy/plugin.json",167,"game_data"],["bios/mame/plugins/gdbstub/init.lua",7838,"game_data"],["bios/mame/plugins/gdbstub/plugin.json",154,"game_data"],["bios/mame/plugins/hiscore/hiscore.dat",314161,"game_data"],["bios/mame/plugins/hiscore/init.lua",10287,"game_data"],["bios/mame/plugins/hiscore/plugin.json",167,"game_data"],["bios/mame/plugins/hiscore/sort_hiscore.lua",4447,"game_data"],["bios/mame/plugins/inputmacro/init.lua",3797,"game_data"],["bios/mame/plugins/inputmacro/inputmacro_menu.lua",20962,"game_data"],["bios/mame/plugins/inputmacro/inputmacro_persist.lua",3719,"game_data"],["bios/mame/plugins/inputmacro/plugin.json",171,"game_data"],["bios/mame/plugins/json/LICENSE",1079,"game_data"],["bios/mame/plugins/json/README.md",45,"game_data"],["bios/mame/plugins/json/init.lua",21505,"game_data"],["bios/mame/plugins/json/plugin.json",136,"game_data"],["bios/mame/plugins/keypress/init.lua",1162,"game_data"],["bios/mame/plugins/keypress/plugin.json",195,"game_data"],["bios/mame/plugins/layout/init.lua",2376,"game_data"],["bios/mame/plugins/layout/plugin.json",157,"game_data"],["bios/mame/plugins/offscreenreload/init.lua",2415,"game_data"],["bios/mame/plugins/offscreenreload/offscreenreload_menu.lua",11498,"game_data"],["bios/mame/plugins/offscreenreload/offscreenreload_persist.lua",3471,"game_data"],["bios/mame/plugins/offscreenreload/plugin.json",189,"game_data"],["bios/mame/plugins/plugin.schema",655,"game_data"],["bios/mame/plugins/portname/init.lua",5173,"game_data"],["bios/mame/plugins/portname/plugin.json",170,"game_data"],["bios/mame/plugins/timecode/init.lua",11542,"game_data"],["bios/mame/plugins/timecode/plugin.json",175,"game_data"],["bios/mame/plugins/timer/init.lua",2359,"game_data"],["bios/mame/plugins/timer/plugin.json",161,"game_data"],["bios/mame/plugins/timer/timer_persist.lua",7109,"game_data"],["bios/mame/plugins/vector/init.lua",1443,"game_data"],["bios/mame/plugins/vector/plugin.json",182,"game_data"],["bios/mame/plugins/xml/LICENSE.txt",1061,"game_data"],["bios/mame/plugins/xml/init.lua",12842,"game_data"],["bios/mame/plugins/xml/plugin.json",146,"game_data"],["bios/mame/samples/bbc.zip",8469,"game_data"],["bios/mame/samples/floppy/35_seek_12ms.wav",26540,"game_data"],["bios/mame/samples/floppy/35_seek_20ms.wav",44144,"game_data"],["bios/mame/samples/floppy/35_seek_2ms.wav",7450,"game_data"],["bios/mame/samples/floppy/35_seek_6ms.wav",22230,"game_data"],["bios/mame/samples/floppy/35_spin_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_end.wav",17684,"game_data"],["bios/mame/samples/floppy/35_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_empty.wav",17708,"game_data"],["bios/mame/samples/floppy/35_spin_start_loaded.wav",35308,"game_data"],["bios/mame/samples/floppy/35_step_1_1.wav",6878,"game_data"],["bios/mame/samples/floppy/525_seek_12ms.wav",22764,"game_data"],["bios/mame/samples/floppy/525_seek_20ms.wav",30060,"game_data"],["bios/mame/samples/floppy/525_seek_6ms.wav",14860,"game_data"],["bios/mame/samples/floppy/525_spin_empty.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_end.wav",8864,"game_data"],["bios/mame/samples/floppy/525_spin_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_spin_start_empty.wav",11180,"game_data"],["bios/mame/samples/floppy/525_spin_start_loaded.wav",17708,"game_data"],["bios/mame/samples/floppy/525_step_1_1.wav",6628,"game_data"],["bios/maxaflex.zip",13673,"bios"],["bios/mc1502_rom.zip",25819,"bios"],["bios/mc_mk4_hopper.zip",791,"bios"],["bios/mcpx_1.0.bin",512,"bios"],["bios/mcpx_apu.zip",629,"bios"],["bios/mcx128.zip",28343,"bios"],["bios/md_jcart.zip",95467,"bios"],["bios/md_kbd.zip",1044,"bios"],["bios/md_rom_svp.zip",1263,"bios"],["bios/md_seprom_codemast.zip",95467,"bios"],["bios/md_seprom_mm96.zip",95467,"bios"],["bios/mdisplay2.zip",965,"bios"],["bios/mdisplay3.zip",14234,"bios"],["bios/mediagx_cs5530_ide.zip",1151601,"bios"],["bios/megadrive_ar.zip",37759,"bios"],["bios/megadrive_rom_jcart_micromac2.zip",95467,"bios"],["bios/megadrive_rom_jcart_micromac96.zip",95467,"bios"],["bios/megadrive_rom_jcart_sampras.zip",95467,"bios"],["bios/megadrive_rom_jcart_sskid.zip",95467,"bios"],["bios/megaplay.zip",49978,"bios"],["bios/megatech.zip",24831,"bios"],["bios/mg1_kbd_device.zip",740,"bios"],["bios/mga2064w.zip",86678,"bios"],["bios/microtan_kbd_mt009.zip",376,"bios"],["bios/microtouch.zip",41890,"bios"],["bios/midcsd.zip",222,"bios"],["bios/midssio.zip",163,"bios"],["bios/mie.zip",725,"bios"],["bios/mindset_rs232_module.zip",95177,"bios"],["bios/mindset_sound_module.zip",1102,"bios"],["bios/minichif.zip",22917,"bios"],["bios/miuchiz.zip",7286,"bios"],["bios/mks3.zip",2351,"bios"],["bios/mm1kb.zip",499,"bios"],["bios/mm5740.zip",212,"bios"],["bios/mockingboardd.zip",1861,"bios"],["bios/model1io.zip",4700,"bios"],["bios/model1io2.zip",113112,"bios"],["bios/mpcb828.zip",3690,"bios"],["bios/mpcb849.zip",3567,"bios"],["bios/mpcb896.zip",168,"bios"],["bios/mpcb963.zip",164,"bios"],["bios/mpcba79.zip",168,"bios"],["bios/mpcbb68.zip",3163,"bios"],["bios/mpcbb92.zip",3163,"bios"],["bios/mpeg_card.bin",524288,"bios"],["bios/mpf1_epb.zip",1497,"bios"],["bios/mpf1_epb_ibp.zip",2667,"bios"],["bios/mpf1_iom_ip.zip",96299,"bios"],["bios/mpf1_prt.zip",2971,"bios"],["bios/mpf1_prt_ip.zip",2760,"bios"],["bios/mpf1_sgb.zip",2402,"bios"],["bios/mpf1_ssb.zip",3448,"bios"],["bios/mpf1_ssb_ip.zip",4164,"bios"],["bios/mpf1_tva_ip.zip",1790,"bios"],["bios/mpf1_vid.zip",2320,"bios"],["bios/mpr-17933.bin",524288,"bios"],["bios/mpr-18100.bin",524288,"bios"],["bios/mpr-18811-mx.ic1",2097152,"bios"],["bios/mpr-19367-mx.ic1",2097152,"bios"],["bios/mps1200.zip",21255,"bios"],["bios/mps1250.zip",26948,"bios"],["bios/mpu401.zip",3573,"bios"],["bios/mpu_pc98.zip",3573,"bios"],["bios/mr9735_002.zip",542,"bios"],["bios/ms7004.zip",1446,"bios"],["bios/msdsd1.zip",11813,"bios"],["bios/msdsd2.zip",12220,"bios"],["bios/mshark.zip",109067,"bios"],["bios/msm6222b01.zip",972,"bios"],["bios/msmt070.zip",202,"bios"],["bios/msmt071.zip",170,"bios"],["bios/msmt081.zip",170,"bios"],["bios/msmt094.zip",113806,"bios"],["bios/msx_cart_bm_012.zip",5300,"bios"],["bios/msx_cart_easispeech.zip",2011,"bios"],["bios/msx_cart_fmpac.zip",313,"bios"],["bios/msx_cart_gouda_scsi.zip",778041,"bios"],["bios/msx_cart_mega_scsi.zip",778041,"bios"],["bios/msx_cart_sfg01.zip",10912,"bios"],["bios/msx_cart_sfg05.zip",69473,"bios"],["bios/msx_cart_skw01.zip",591507,"bios"],["bios/msx_cart_slotexpander.zip",3909365,"bios"],["bios/msx_cart_sunrise_ataide.zip",1309918,"bios"],["bios/msx_cart_ucn01.zip",671804,"bios"],["bios/msx_moonsound.zip",1922475,"bios"],["bios/msx_segactrl.zip",95467,"bios"],["bios/msx_slot_rs232.zip",95177,"bios"],["bios/msx_slot_rs232_mitsubishi.zip",95177,"bios"],["bios/msx_slot_rs232_sony.zip",95177,"bios"],["bios/msx_slot_rs232_svi738.zip",95177,"bios"],["bios/msx_slot_rs232_toshiba.zip",95177,"bios"],["bios/msx_slot_rs232_toshiba_hx3x.zip",95177,"bios"],["bios/mtx_cfx.zip",1206105,"bios"],["bios/mtx_sdxbas.zip",10404,"bios"],["bios/mtx_sdxcpm.zip",4710,"bios"],["bios/mu5lcd.zip",12098,"bios"],["bios/mulcd.zip",40392,"bios"],["bios/mvme120.zip",142638,"bios"],["bios/mvme121.zip",142638,"bios"],["bios/mvme122.zip",142638,"bios"],["bios/mvme123.zip",142638,"bios"],["bios/mvme147.zip",347124,"bios"],["bios/mvme180.zip",191443,"bios"],["bios/mvme181.zip",222873,"bios"],["bios/mvme187.zip",317218,"bios"],["bios/mvme327a.zip",39770,"bios"],["bios/mvme328.zip",47299,"bios"],["bios/mvme350.zip",8228,"bios"],["bios/mx1600bas.rom",8192,"bios"],["bios/mx1600extbas.rom",8192,"bios"],["bios/mz1e30.zip",13614,"bios"],["bios/mz1p16.zip",3679,"bios"],["bios/mzr8105.zip",10272,"bios"],["bios/mzr8300.zip",95177,"bios"],["bios/n88.rom",32768,"bios"],["bios/n88_0.rom",8192,"bios"],["bios/n88_1.rom",8192,"bios"],["bios/n88_2.rom",8192,"bios"],["bios/n88_3.rom",8192,"bios"],["bios/n88knj1.rom",131072,"bios"],["bios/n88n.rom",32768,"bios"],["bios/nabupc_keyboard.zip",1348,"bios"],["bios/nabupc_option_rs232.zip",95177,"bios"],["bios/namco50.zip",898,"bios"],["bios/namco51.zip",716,"bios"],["bios/namco52.zip",389,"bios"],["bios/namco53.zip",675,"bios"],["bios/namco54.zip",592,"bios"],["bios/namco62.zip",645,"bios"],["bios/namco_amc.zip",130552,"bios"],["bios/namco_asca1.zip",130552,"bios"],["bios/namco_asca3.zip",130552,"bios"],["bios/namco_asca3a.zip",130552,"bios"],["bios/namco_asca5.zip",130552,"bios"],["bios/namco_csz1.zip",130599,"bios"],["bios/namco_cyberlead.zip",130552,"bios"],["bios/namco_cyberlead_led.zip",80055,"bios"],["bios/namco_cyberleada.zip",130552,"bios"],["bios/namco_de_pcb.zip",1721,"bios"],["bios/namco_emio102.zip",130552,"bios"],["bios/namco_empri101.zip",130552,"bios"],["bios/namco_fca10.zip",130552,"bios"],["bios/namco_fca11.zip",130552,"bios"],["bios/namco_fcb.zip",130552,"bios"],["bios/namco_tssio.zip",130552,"bios"],["bios/namco_xmiu1.zip",130552,"bios"],["bios/namcoc65.zip",2163,"bios"],["bios/namcoc67.zip",6552,"bios"],["bios/namcoc68.zip",1721,"bios"],["bios/namcoc69.zip",7771,"bios"],["bios/namcoc70.zip",7822,"bios"],["bios/namcoc71.zip",2756,"bios"],["bios/namcoc74.zip",6936,"bios"],["bios/namcoc75.zip",8709,"bios"],["bios/namcoc76.zip",9579,"bios"],["bios/namcos21_dsp_c67_device.zip",6552,"bios"],["bios/nand/private/movable.sed",320,"bios"],["bios/nand/rw/sys/LocalFriendCodeSeed_B",272,"bios"],["bios/nand/rw/sys/SecureInfo_A",273,"bios"],["bios/nanoreseau_mo.zip",1937,"bios"],["bios/nanoreseau_to.zip",1970,"bios"],["bios/naomi.zip",9321533,"bios"],["bios/naomi2.zip",7022501,"bios"],["bios/naomigd.zip",3371765,"bios"],["bios/nb_aenet.zip",400,"bios"],["bios/nb_amc3b.zip",417,"bios"],["bios/nb_btbug.zip",91614,"bios"],["bios/nb_c264.zip",6489,"bios"],["bios/nb_image.zip",1832,"bios"],["bios/nb_laserview.zip",4885,"bios"],["bios/nb_m2hr.zip",3538,"bios"],["bios/nb_m2vc.zip",2106,"bios"],["bios/nb_mdc48.zip",6576,"bios"],["bios/nb_mdc824.zip",7883,"bios"],["bios/nb_pcs8.zip",9570,"bios"],["bios/nb_qdlink.zip",3316,"bios"],["bios/nb_rtpd.zip",1828,"bios"],["bios/nb_sp8s3.zip",23241,"bios"],["bios/nb_spdq.zip",39282,"bios"],["bios/nb_thungx.zip",18290,"bios"],["bios/nb_thungx16.zip",18318,"bios"],["bios/nb_vikbw.zip",2162,"bios"],["bios/nb_wkstn.zip",2715,"bios"],["bios/nb_wspt.zip",2646,"bios"],["bios/ncr53c825_pci.zip",10043,"bios"],["bios/neocd.bin",524288,"bios"],["bios/neocd/front-sp1.bin",524288,"bios"],["bios/neocd/neocd.bin",524288,"bios"],["bios/neocd/neocd_f.rom",524288,"bios"],["bios/neocd/neocd_sf.rom",524288,"bios"],["bios/neocd/neocd_st.rom",524288,"bios"],["bios/neocd/neocd_sz.rom",524288,"bios"],["bios/neocd/neocd_t.rom",524288,"bios"],["bios/neocd/neocd_z.rom",524288,"bios"],["bios/neocd/top-sp1.bin",524288,"bios"],["bios/neocd/uni-bioscd.rom",524288,"bios"],["bios/neocd_f.rom",524288,"bios"],["bios/neocd_sf.rom",524288,"bios"],["bios/neocd_st.rom",524288,"bios"],["bios/neocd_sz.rom",524288,"bios"],["bios/neocd_t.rom",524288,"bios"],["bios/neocd_z.rom",524288,"bios"],["bios/neocdz.zip",598775,"bios"],["bios/neogeo.zip",1859335,"bios"],["bios/neon250.zip",20999,"bios"],["bios/nes_rob.zip",637,"bios"],["bios/nes_vrc7.zip",313,"bios"],["bios/newbrain_eim.zip",128088,"bios"],["bios/newbrain_fdc.zip",128088,"bios"],["bios/ngp.zip",65536,"bios"],["bios/ngpc.zip",65536,"bios"],["bios/nichidvd.zip",49667,"bios"],["bios/nlq401.zip",7554,"bios"],["bios/nmk004.zip",3556,"bios"],["bios/nms8250_basic-bios2.rom",32768,"bios"],["bios/nms8250_disk.rom",16384,"bios"],["bios/nms8250_msx2sub.rom",16384,"bios"],["bios/nokia_crtc186.zip",5203,"bios"],["bios/novell_dcb.zip",3425,"bios"],["bios/np2kai/2608_BD.WAV",19192,"bios"],["bios/np2kai/2608_HH.WAV",36722,"bios"],["bios/np2kai/2608_RIM.WAV",5288,"bios"],["bios/np2kai/2608_SD.WAV",15558,"bios"],["bios/np2kai/2608_TOM.WAV",23092,"bios"],["bios/np2kai/2608_TOP.WAV",57016,"bios"],["bios/np2kai/2608_bd.wav",19192,"bios"],["bios/np2kai/2608_hh.wav",36722,"bios"],["bios/np2kai/2608_rim.wav",5288,"bios"],["bios/np2kai/2608_sd.wav",15558,"bios"],["bios/np2kai/2608_tom.wav",23092,"bios"],["bios/np2kai/2608_top.wav",57016,"bios"],["bios/np2kai/FONT.ROM",288768,"bios"],["bios/np2kai/bios.rom",98304,"bios"],["bios/np2kai/font.bmp",524350,"bios"],["bios/np2kai/ide.rom",8192,"bios"],["bios/np2kai/pci.rom",32768,"bios"],["bios/np2kai/sasi.rom",4096,"bios"],["bios/np2kai/scsi.rom",8192,"bios"],["bios/np2kai/sound.rom",16384,"bios"],["bios/np600a3.zip",8089,"bios"],["bios/nss.zip",50536,"bios"],["bios/nss_tvinterface.zip",11169,"bios"],["bios/number_9_rev.zip",367,"bios"],["bios/o2rom.bin",1024,"bios"],["bios/ohare.zip",95177,"bios"],["bios/omniwave.zip",880710,"bios"],["bios/omti8621isa.zip",13582,"bios"],["bios/opera-boot.bin",131072,"bios"],["bios/orch90.rom",8192,"bios"],["bios/oric_jasmin.zip",471,"bios"],["bios/oric_microdisc.zip",3254,"bios"],["bios/osa_analyst.zip",348004,"bios"],["bios/osa_bforce.zip",26799,"bios"],["bios/osa_maestro.zip",324479,"bios"],["bios/osa_maestroa.zip",47396,"bios"],["bios/osa_sparc.zip",348745,"bios"],["bios/oti64111_pci.zip",19135,"bios"],["bios/otp.bin",1024,"bios"],["bios/p1_fdc.zip",6158,"bios"],["bios/p1_hdc.zip",6372,"bios"],["bios/p1_rom.zip",5821,"bios"],["bios/p72.zip",351169,"bios"],["bios/pa7234.zip",63947,"bios"],["bios/pa7246.zip",63947,"bios"],["bios/paddington.zip",95177,"bios"],["bios/palmos40-en-m500.rom",2359296,"bios"],["bios/palmos41-en-m515.rom",4194304,"bios"],["bios/palmos52-en-t3.rom",16777216,"bios"],["bios/palmos60-en-t3.rom",16777216,"bios"],["bios/panafz1-kanji.bin",933636,"bios"],["bios/panafz1.bin",1048576,"bios"],["bios/panafz10-norsa.bin",1048576,"bios"],["bios/panafz10.bin",1048576,"bios"],["bios/panafz10e-anvil-norsa.bin",1048576,"bios"],["bios/panafz10e-anvil.bin",1048576,"bios"],["bios/panafz10ja-anvil-kanji.bin",1048576,"bios"],["bios/panafz1j-kanji.bin",1048576,"bios"],["bios/panafz1j-norsa.bin",1048576,"bios"],["bios/panafz1j.bin",1048576,"bios"],["bios/partner_gdp.zip",1917,"bios"],["bios/pc1512kb.zip",733,"bios"],["bios/pc1640_iga.zip",8824,"bios"],["bios/pc6022.zip",3694,"bios"],["bios/pc80s31.zip",3242,"bios"],["bios/pc80s31k.zip",7153,"bios"],["bios/pc87306.zip",479847,"bios"],["bios/pc8801_23.zip",7609,"bios"],["bios/pc88va2_fd_if.zip",3891,"bios"],["bios/pc97338.zip",479847,"bios"],["bios/pc9801_118.zip",7609,"bios"],["bios/pc9801_14.zip",5571,"bios"],["bios/pc9801_26.zip",132073,"bios"],["bios/pc9801_27.zip",2700,"bios"],["bios/pc9801_55l.zip",4654,"bios"],["bios/pc9801_55u.zip",4653,"bios"],["bios/pc9801_86.zip",125153,"bios"],["bios/pc98_fdd_2dd.zip",1959,"bios"],["bios/pc98_fdd_2hd.zip",2702,"bios"],["bios/pc98_otomichan_kai.zip",116066,"bios"],["bios/pc_lpt.zip",479847,"bios"],["bios/pcd_kbd.zip",2572,"bios"],["bios/pcd_video.zip",612,"bios"],["bios/pce_multitap.zip",95467,"bios"],["bios/pce_xhe3.zip",95467,"bios"],["bios/pcfx.rom",1048576,"bios"],["bios/pcfxbios.bin",1048576,"bios"],["bios/pcfxga.rom",1048576,"bios"],["bios/pcfxv101.bin",1048576,"bios"],["bios/pcx_video.zip",8874,"bios"],["bios/pd32.zip",998,"bios"],["bios/pd3_30hr.zip",4685,"bios"],["bios/pd3_30hrint.zip",4685,"bios"],["bios/pd3_c264.zip",5773,"bios"],["bios/pd3_lviw.zip",4760,"bios"],["bios/pd3_mclr.zip",4568,"bios"],["bios/pd3_mclrint.zip",4568,"bios"],["bios/pd3_pc16.zip",8246,"bios"],["bios/pd3_pcs8.zip",9552,"bios"],["bios/pdc20262.zip",1165916,"bios"],["bios/pdc20268.zip",9340,"bios"],["bios/pds30_emac.zip",346,"bios"],["bios/pds_hyper.zip",3836,"bios"],["bios/pds_sefp.zip",14387,"bios"],["bios/pdslc_macconlc.zip",419,"bios"],["bios/pencil2_coleco.zip",5795,"bios"],["bios/peribox.zip",2106147,"bios"],["bios/peribox_ev.zip",2106147,"bios"],["bios/peribox_ev1.zip",2106147,"bios"],["bios/peribox_gen.zip",2106147,"bios"],["bios/peribox_genmod.zip",2106147,"bios"],["bios/peribox_sg.zip",2106147,"bios"],["bios/permedia2.zip",138948,"bios"],["bios/pet_softbox.zip",104992,"bios"],["bios/pet_superpet.zip",110907,"bios"],["bios/pg200.zip",549,"bios"],["bios/pgm.zip",2094614,"bios"],["bios/phc-70fd2_basickun.rom",16384,"bios"],["bios/philips__cdi-220_ph3_r1.2__mb834200b-15__02f_aa__9402_z04.tc574200-le._1.7211",524288,"bios"],["bios/pico-8/pico8",9377000,"bios"],["bios/pico-8/pico8.dat",17721245,"bios"],["bios/pico-8/pico8_dyn",1761480,"bios"],["bios/pl6_fpga.zip",95177,"bios"],["bios/playch10.zip",23388,"bios"],["bios/plg100_vl.zip",333318,"bios"],["bios/plg150_ap.zip",11733949,"bios"],["bios/plus2-0.rom",16384,"bios"],["bios/plus2-1.rom",16384,"bios"],["bios/plus3-0.rom",16384,"bios"],["bios/plus3-1.rom",16384,"bios"],["bios/plus3-2.rom",16384,"bios"],["bios/plus3-3.rom",16384,"bios"],["bios/plus3e-0.rom",16384,"bios"],["bios/plus3e-1.rom",16384,"bios"],["bios/plus3e-2.rom",16384,"bios"],["bios/plus3e-3.rom",16384,"bios"],["bios/plusd.rom",8192,"bios"],["bios/plutonia.wad",17420824,"game_data"],["bios/pofo_hpc101.zip",479847,"bios"],["bios/pofo_hpc102.zip",95177,"bios"],["bios/pofo_hpc104.zip",574980,"bios"],["bios/pofo_hpc104_2.zip",574980,"bios"],["bios/polyvti.zip",859,"bios"],["bios/popira.zip",654918,"bios"],["bios/popira2.zip",1124630,"bios"],["bios/popirak.zip",639838,"bios"],["bios/ppge_atlas.zim",666530,"bios"],["bios/pr8210.zip",2012,"bios"],["bios/prav8ckb.zip",1204,"bios"],["bios/prboom.wad",143312,"bios"],["bios/premier_fdc.zip",6765,"bios"],["bios/profighterq.zip",62808,"bios"],["bios/profighterqa.zip",62747,"bios"],["bios/profighterqb.zip",62747,"bios"],["bios/profighterx.zip",62764,"bios"],["bios/promotion3210.zip",18077,"bios"],["bios/ps1_rom.bin",524288,"bios"],["bios/ps2-0100j-20000117.bin",4194304,"bios"],["bios/ps2-0100jd-20000117.bin",4194304,"bios"],["bios/ps2-0101j-20000217.bin",4194304,"bios"],["bios/ps2-0101jd-20000217.bin",4194304,"bios"],["bios/ps2-0101xd-20000224.bin",4194304,"bios"],["bios/ps2-0110a-20000727.bin",4194304,"bios"],["bios/ps2-0110ad-20000727.bin",4194304,"bios"],["bios/ps2-0120a-20000902.bin",4194304,"bios"],["bios/ps2-0120e-20000902.bin",4194304,"bios"],["bios/ps2-0120ed-20000902-20030110.bin",4194304,"bios"],["bios/ps2-0120ed-20000902.bin",4194304,"bios"],["bios/ps2-0120j-20001027-185015.bin",4194304,"bios"],["bios/ps2-0120j-20001027-191435.bin",4194304,"bios"],["bios/ps2-0150a-20001228.bin",4194304,"bios"],["bios/ps2-0150ad-20001228-20030520.bin",4194304,"bios"],["bios/ps2-0150e-20001228.bin",4194304,"bios"],["bios/ps2-0150ed-20001228-20030520.bin",4194304,"bios"],["bios/ps2-0150j-20010118.bin",4194304,"bios"],["bios/ps2-0150jd-20010118.bin",4194304,"bios"],["bios/ps2-0160a-20010427.bin",4194304,"bios"],["bios/ps2-0160a-20010704.bin",4194304,"bios"],["bios/ps2-0160a-20011004.bin",4194304,"bios"],["bios/ps2-0160a-20020207.bin",4194304,"bios"],["bios/ps2-0160e-20010704.bin",4194304,"bios"],["bios/ps2-0160e-20011004.bin",4194304,"bios"],["bios/ps2-0160e-20020319.bin",4194304,"bios"],["bios/ps2-0160e-20020426.bin",4194304,"bios"],["bios/ps2-0160h-20010730.bin",4194304,"bios"],["bios/ps2-0160h-20020426.bin",4194304,"bios"],["bios/ps2-0160h-20030602.bin",4194304,"bios"],["bios/ps2-0160j-20010427.bin",4194304,"bios"],["bios/ps2-0160j-20011004.bin",4194304,"bios"],["bios/ps2-0160j-20020426.bin",4194304,"bios"],["bios/ps2-0170a-20030325.bin",4194304,"bios"],["bios/ps2-0170ad-20030325.bin",4194304,"bios"],["bios/ps2-0170e-20030227.bin",4194304,"bios"],["bios/ps2-0170ed-20030227.bin",4194304,"bios"],["bios/ps2-0170j-20030206.bin",4194304,"bios"],["bios/ps2-0170jd-20030206.bin",4194304,"bios"],["bios/ps2-0180cd-20030224.bin",4194304,"bios"],["bios/ps2-0180j-20031028.bin",4194304,"bios"],["bios/ps2-0190a-20030623.bin",4194304,"bios"],["bios/ps2-0190a-20040329.bin",4194304,"bios"],["bios/ps2-0190ad-20030623.bin",4194304,"bios"],["bios/ps2-0190c-20030623.bin",4194304,"bios"],["bios/ps2-0190cd-20030623.bin",4194304,"bios"],["bios/ps2-0190e-20030623.bin",4194304,"bios"],["bios/ps2-0190e-20030822.bin",4194304,"bios"],["bios/ps2-0190h-20030623.bin",4194304,"bios"],["bios/ps2-0190j-20030623.bin",4194304,"bios"],["bios/ps2-0190j-20030822.bin",4194304,"bios"],["bios/ps2-0190k-20030623.bin",4194304,"bios"],["bios/ps2-0190r-20030623.bin",4194304,"bios"],["bios/ps2-0200a-20040614.bin",4194304,"bios"],["bios/ps2-0200ad-20040614.bin",4194304,"bios"],["bios/ps2-0200e-20040614.bin",4194304,"bios"],["bios/ps2-0200ed-20040614.bin",4194304,"bios"],["bios/ps2-0200h-20040614.bin",4194304,"bios"],["bios/ps2-0200j-20040614.bin",4194304,"bios"],["bios/ps2-0210j-20040917.bin",4194304,"bios"],["bios/ps2-0220a-20050620.bin",4194304,"bios"],["bios/ps2-0220a-20060210.bin",4194304,"bios"],["bios/ps2-0220a-20060905.bin",4194304,"bios"],["bios/ps2-0220ad-20050620.bin",4194304,"bios"],["bios/ps2-0220ad-20060905.bin",4194304,"bios"],["bios/ps2-0220e-20050620.bin",4194304,"bios"],["bios/ps2-0220e-20060210.bin",4194304,"bios"],["bios/ps2-0220e-20060905.bin",4194304,"bios"],["bios/ps2-0220h-20050620.bin",4194304,"bios"],["bios/ps2-0220h-20060210.bin",4194304,"bios"],["bios/ps2-0220h-20060905.bin",4194304,"bios"],["bios/ps2-0220j-20050620.bin",4194304,"bios"],["bios/ps2-0220j-20060210.bin",4194304,"bios"],["bios/ps2-0220j-20060905.bin",4194304,"bios"],["bios/ps2-0220jd-20050620.bin",4194304,"bios"],["bios/ps2-0220jd-20060905.bin",4194304,"bios"],["bios/ps2-0230a-20080220.bin",4194304,"bios"],["bios/ps2-0230a-20080220.nvm",1024,"bios"],["bios/ps2-0230e-20080220.bin",4194304,"bios"],["bios/ps2-0230h-20080220.bin",4194304,"bios"],["bios/ps2-0230j-20080220.bin",4194304,"bios"],["bios/ps2-0250e-20100415.bin",4194304,"bios"],["bios/ps2-0250j-20100415.bin",4194304,"bios"],["bios/ps2-dvd-300e.bin",4194304,"bios"],["bios/ps2-dvd-300u.bin",4194304,"bios"],["bios/ps2-dvd-302c.bin",4194304,"bios"],["bios/ps2-dvd-302e.bin",4194304,"bios"],["bios/ps2-dvd-302u.bin",4194304,"bios"],["bios/ps2-dvd-310.bin",4194304,"bios"],["bios/ps2-dvd-311.bin",4194304,"bios"],["bios/ps2_keybc.zip",3537,"bios"],["bios/ps2_scph50006.bin",4194304,"bios"],["bios/ps2_scph50008.bin",4194304,"bios"],["bios/psion_3fax.zip",394842,"bios"],["bios/psion_3link_par.zip",479847,"bios"],["bios/psion_3link_ser.zip",145742,"bios"],["bios/psion_parallel.zip",479847,"bios"],["bios/psion_pclink.zip",95177,"bios"],["bios/psion_serpar.zip",574980,"bios"],["bios/psion_siena_ssd.zip",574980,"bios"],["bios/psvita/PSP2UPDAT.PUP",56778752,"bios"],["bios/psvita/PSVUPDAT.PUP",133834240,"bios"],["bios/psx_cd.zip",222667,"bios"],["bios/psxgboost.zip",179516,"bios"],["bios/psxonpsp660.bin",524288,"bios"],["bios/pumpitup.zip",7985810,"bios"],["bios/pvga1a.zip",65692,"bios"],["bios/pvga1a_jk.zip",103539,"bios"],["bios/px320a.zip",1092458,"bios"],["bios/qg640.zip",75366,"bios"],["bios/ql_cumanafdi.zip",16173,"bios"],["bios/ql_gold.zip",66339,"bios"],["bios/ql_kdi.zip",6387,"bios"],["bios/ql_mhd.zip",5988,"bios"],["bios/ql_mpfdi.zip",5067,"bios"],["bios/ql_opdbm.zip",27486,"bios"],["bios/ql_pcmlqdi.zip",10237,"bios"],["bios/ql_qldisc.zip",13083,"bios"],["bios/ql_qplus4.zip",1997923,"bios"],["bios/ql_qubide.zip",1182071,"bios"],["bios/ql_sdisk.zip",488706,"bios"],["bios/ql_sqboard256.zip",541045,"bios"],["bios/ql_sqboard512.zip",541045,"bios"],["bios/ql_sqmouse.zip",541045,"bios"],["bios/ql_sqmouse512.zip",541045,"bios"],["bios/ql_trump.zip",121019,"bios"],["bios/ql_trump256.zip",121019,"bios"],["bios/ql_trump512.zip",121019,"bios"],["bios/ql_trump768.zip",121019,"bios"],["bios/qsound.zip",2654,"bios"],["bios/qsound_hle.zip",2676,"bios"],["bios/qts1.zip",898304,"bios"],["bios/quadro.zip",51307,"bios"],["bios/quasi88/font.rom",2048,"bios"],["bios/quasi88/font2.rom",2048,"bios"],["bios/quasi88/font3.rom",2048,"bios"],["bios/quasi88/n88.rom",32768,"bios"],["bios/quasi88/n88_0.rom",8192,"bios"],["bios/quasi88/n88_1.rom",8192,"bios"],["bios/quasi88/n88_2.rom",8192,"bios"],["bios/quasi88/n88_3.rom",8192,"bios"],["bios/quasi88/n88jisho.rom",524288,"bios"],["bios/quasi88/n88knj1.rom",131072,"bios"],["bios/quasi88/n88knj2.rom",131072,"bios"],["bios/quasi88/n88n.rom",32768,"bios"],["bios/quasi88/n88sub.rom",2048,"bios"],["bios/quoth/pak0.pak",48226771,"game_data"],["bios/quoth/pak1.pak",84961704,"game_data"],["bios/quoth/pak2.pak",8021749,"game_data"],["bios/qvision_wavestar.zip",4834,"bios"],["bios/qx10_keyboard_ascii.zip",963,"bios"],["bios/qx10_keyboard_hasci.zip",963,"bios"],["bios/racedriv_board.zip",95177,"bios"],["bios/racedrivb1_board.zip",95177,"bios"],["bios/racedrivc1_board.zip",95177,"bios"],["bios/racedrivc_board.zip",95177,"bios"],["bios/racedrivc_panorama_side_board.zip",95177,"bios"],["bios/rageiidvd.zip",74874,"bios"],["bios/rc2014_82c55_ide.zip",1151601,"bios"],["bios/rc2014_dual_serial.zip",95177,"bios"],["bios/rc2014_dual_serial_40p.zip",95177,"bios"],["bios/rc2014_ide_hdd.zip",1151601,"bios"],["bios/rc2014_micro.zip",107725,"bios"],["bios/rc2014_mini_cpm.zip",3885695,"bios"],["bios/rc2014_pagable_rom.zip",34021,"bios"],["bios/rc2014_rom_ram_512k.zip",2572870,"bios"],["bios/rc2014_sc106.zip",4617504,"bios"],["bios/rc2014_sc107.zip",4617504,"bios"],["bios/rc2014_sc111.zip",95177,"bios"],["bios/rc2014_sc113.zip",4617504,"bios"],["bios/rc2014_sc141.zip",3861903,"bios"],["bios/rc2014_sc147.zip",3861903,"bios"],["bios/rc2014_serial_io.zip",95177,"bios"],["bios/rc2014_switchable_rom.zip",42387,"bios"],["bios/recel.zip",2156,"bios"],["bios/resources/sharedFonts/CafeCn.ttf",9664448,"bios"],["bios/resources/sharedFonts/CafeKr.ttf",5626464,"bios"],["bios/resources/sharedFonts/CafeStd.ttf",5363768,"bios"],["bios/resources/sharedFonts/CafeTw.ttf",6593548,"bios"],["bios/rf57_932.zip",95177,"bios"],["bios/riva128.zip",60632,"bios"],["bios/riva128zx.zip",59311,"bios"],["bios/rivatnt.zip",82626,"bios"],["bios/rivatnt2.zip",46394,"bios"],["bios/rivatnt2_m64.zip",272160,"bios"],["bios/rivatnt2_ultra.zip",24007,"bios"],["bios/rm_mq2.zip",6064,"bios"],["bios/robotron_k7070.zip",110597,"bios"],["bios/robotron_k7071.zip",4152,"bios"],["bios/rolm_pdc.zip",8595,"bios"],["bios/rolm_smioc.zip",101325,"bios"],["bios/rom.db",17742,"bios"],["bios/rom.key",2069,"bios"],["bios/rotwb.wad",20592999,"game_data"],["bios/rs232_patch_box.zip",95177,"bios"],["bios/rt1000b.zip",5852,"bios"],["bios/rtpc_kbd.zip",1918,"bios"],["bios/rtpc_kls.zip",5044,"bios"],["bios/rx01.zip",2846,"bios"],["bios/s100_am310.zip",96441,"bios"],["bios/s100_djdma.zip",3777,"bios"],["bios/s100_nsmdsa.zip",396,"bios"],["bios/s100_nsmdsad.zip",334,"bios"],["bios/s100_sj2db.zip",1012,"bios"],["bios/s100_wunderbus.zip",95177,"bios"],["bios/s1410.zip",11050,"bios"],["bios/s3_764.zip",18299,"bios"],["bios/s8k_cpu.zip",31998,"bios"],["bios/s8k_cpu10.zip",6294,"bios"],["bios/s8k_hpcpu.zip",11518,"bios"],["bios/s97269pb.zip",566,"bios"],["bios/s97801_device.zip",8720,"bios"],["bios/s97801_kbd.zip",1772,"bios"],["bios/s_smp.zip",209,"bios"],["bios/saa5050.zip",536,"bios"],["bios/saa5051.zip",522,"bios"],["bios/saa5052.zip",514,"bios"],["bios/saa5053.zip",519,"bios"],["bios/saa5054.zip",511,"bios"],["bios/saa5055.zip",525,"bios"],["bios/saa5056.zip",535,"bios"],["bios/saa5057.zip",523,"bios"],["bios/saa5240a.zip",1015,"bios"],["bios/saa5240b.zip",978,"bios"],["bios/saa5243e.zip",1297,"bios"],["bios/sad8852.zip",4434,"bios"],["bios/sam_atom_hdd.zip",1151601,"bios"],["bios/sam_sdide.zip",1151601,"bios"],["bios/sambus.zip",1633379,"bios"],["bios/same_cdi/bios/cdi490a.zip",379558,"bios"],["bios/same_cdi/bios/cdi910.zip",487572,"bios"],["bios/same_cdi/bios/cdimono1.zip",745703,"bios"],["bios/same_cdi/bios/cdimono2.zip",244291,"bios"],["bios/sammymdl.zip",24090,"bios"],["bios/samples/bbc.zip",8469,"game_data"],["bios/sanyotry.bin",1048576,"bios"],["bios/satar4mp.bin",262144,"bios"],["bios/satcdb.zip",101309,"bios"],["bios/saturn_bios.bin",524288,"bios"],["bios/sb16.zip",8003,"bios"],["bios/sb300p.zip",1591,"bios"],["bios/sbus_hme.zip",17450,"bios"],["bios/sbus_sunpc.zip",536,"bios"],["bios/sc119.zip",721668,"bios"],["bios/scorpion_ic.zip",18332,"bios"],["bios/scph100.bin",524288,"bios"],["bios/scph1000.bin",524288,"bios"],["bios/scph1001.bin",524288,"bios"],["bios/scph1002.bin",524288,"bios"],["bios/scph101.bin",524288,"bios"],["bios/scph102A.bin",524288,"bios"],["bios/scph102B.bin",524288,"bios"],["bios/scph102C.bin",524288,"bios"],["bios/scph3000.bin",524288,"bios"],["bios/scph30004fr.nvm",1024,"bios"],["bios/scph3500.bin",524288,"bios"],["bios/scph39001.nvm",1024,"bios"],["bios/scph5000.bin",524288,"bios"],["bios/scph5500.bin",524288,"bios"],["bios/scph5501.bin",524288,"bios"],["bios/scph5502.bin",524288,"bios"],["bios/scph7001.bin",524288,"bios"],["bios/scph7002.bin",524288,"bios"],["bios/scph7003.bin",524288,"bios"],["bios/scph7502.bin",524288,"bios"],["bios/scph9002(7502).bin",524288,"bios"],["bios/scsidma.zip",778041,"bios"],["bios/scummvm.zip",79379908,"bios"],["bios/scummvm/extra/CM32L_CONTROL.ROM",65536,"bios"],["bios/scummvm/extra/CM32L_PCM.ROM",1048576,"bios"],["bios/scummvm/extra/MT32_CONTROL.ROM",65536,"bios"],["bios/scummvm/extra/MT32_PCM.ROM",524288,"bios"],["bios/scv.zip",4073,"bios"],["bios/sdbdos.rom",65536,"bios"],["bios/sdose6.rom",8192,"bios"],["bios/sdose8.rom",8192,"bios"],["bios/sdtandy_fdc.zip",7109,"bios"],["bios/se-0.rom",16384,"bios"],["bios/se-1.rom",16384,"bios"],["bios/sed1200da.zip",749,"bios"],["bios/sed1200db.zip",775,"bios"],["bios/sed1200fa.zip",749,"bios"],["bios/sed1200fb.zip",775,"bios"],["bios/sed1278.zip",2096,"bios"],["bios/seeprom.bin",512,"bios"],["bios/sega1003.bin",524288,"bios"],["bios/sega837_14438.zip",201331,"bios"],["bios/sega_100.bin",524288,"bios"],["bios/sega_100a.bin",524288,"bios"],["bios/sega_101.bin",524288,"bios"],["bios/sega_fm_unit.zip",313,"bios"],["bios/sega_sk1100.zip",3461,"bios"],["bios/sega_sk1100e.zip",3461,"bios"],["bios/sega_sp400.zip",3461,"bios"],["bios/segaai_soundbox.zip",47380,"bios"],["bios/segabill.zip",3117,"bios"],["bios/segadimm.zip",5632733,"bios"],["bios/seganetw.zip",734284,"bios"],["bios/segasp.zip",1281424,"bios"],["bios/sente6vb.zip",4778,"bios"],["bios/serad.zip",99508,"bios"],["bios/serial_heath_h19.zip",49567,"bios"],["bios/serial_votraxtnt.zip",3922,"bios"],["bios/sfcbox.zip",194344,"bios"],["bios/sfd1001.zip",13984,"bios"],["bios/sgb1.boot.rom",256,"bios"],["bios/sgb1.program.rom",262144,"bios"],["bios/sgb2.boot.rom",524288,"bios"],["bios/sgb2_boot.bin",256,"bios"],["bios/sgb_bios.bin",256,"bios"],["bios/sgi_gm1.zip",120530,"bios"],["bios/sgi_ip2.zip",39192,"bios"],["bios/sgi_ip4.zip",307898,"bios"],["bios/sgi_kbd.zip",1233,"bios"],["bios/sgi_pm1.zip",18125,"bios"],["bios/sgi_pm2.zip",35149,"bios"],["bios/shareddata.bin",33554432,"bios"],["bios/shtzone.zip",3332,"bios"],["bios/side116.zip",1155085,"bios"],["bios/simutrek.zip",2912,"bios"],["bios/sis5513_ide.zip",1151601,"bios"],["bios/sis630_gui.zip",49059,"bios"],["bios/sis6326_agp.zip",101579,"bios"],["bios/sis6326_dvd.zip",23245,"bios"],["bios/sis6326_pci.zip",64665,"bios"],["bios/sis85c496_host.zip",1171917,"bios"],["bios/sis900_eth.zip",24831,"bios"],["bios/sis950_lpc.zip",20242,"bios"],["bios/sk.bin",2097152,"bios"],["bios/sk2chip.bin",262144,"bios"],["bios/skns.zip",783788,"bios"],["bios/sl31253.bin",1024,"bios"],["bios/sl31254.bin",1024,"bios"],["bios/sl90025.bin",1024,"bios"],["bios/smoc501.zip",37103,"bios"],["bios/sms_diypaddle.zip",334,"bios"],["bios/sms_rapid_fire.zip",95467,"bios"],["bios/sms_rs232.zip",95177,"bios"],["bios/sms_teamplayer.zip",95467,"bios"],["bios/smvme2000.zip",124406,"bios"],["bios/sn74s262.zip",675,"bios"],["bios/sn74s263.zip",705,"bios"],["bios/snes:st018.data.rom",32768,"bios"],["bios/sns_dsp1bleg.zip",4140,"bios"],["bios/sns_dsp1leg.zip",4135,"bios"],["bios/sns_dsp1leg_hi.zip",4135,"bios"],["bios/sns_dsp2leg.zip",2987,"bios"],["bios/sns_dsp3leg.zip",3522,"bios"],["bios/sns_dsp4leg.zip",3417,"bios"],["bios/sns_rom_sgb.zip",390,"bios"],["bios/sns_rom_sgb2.zip",392,"bios"],["bios/sns_seta10leg.zip",2712,"bios"],["bios/sns_seta11leg.zip",17424,"bios"],["bios/softcard3.zip",407,"bios"],["bios/sound.rom",16384,"bios"],["bios/sound_orchestra.zip",13041,"bios"],["bios/sound_pc9821ce.zip",103032,"bios"],["bios/sound_pc9821cx3.zip",7609,"bios"],["bios/spc1000_fdd_exp.zip",1839,"bios"],["bios/speakboard.zip",116066,"bios"],["bios/spec128.zip",32986,"bios"],["bios/spec1282a.zip",41646,"bios"],["bios/speccyboot-1.4.rom",8192,"bios"],["bios/spectred_kbd.zip",911,"bios"],["bios/spectrum.zip",16506,"bios"],["bios/spectrum_beta128.zip",2046403,"bios"],["bios/spectrum_betacbi.zip",2046403,"bios"],["bios/spectrum_betaclone.zip",2046403,"bios"],["bios/spectrum_betaplus.zip",2046403,"bios"],["bios/spectrum_betav2.zip",2046403,"bios"],["bios/spectrum_betav3.zip",2046403,"bios"],["bios/spectrum_d40.zip",14616,"bios"],["bios/spectrum_d80.zip",14616,"bios"],["bios/spectrum_d80v2.zip",7460,"bios"],["bios/spectrum_disciple.zip",2046403,"bios"],["bios/spectrum_flpone.zip",2046403,"bios"],["bios/spectrum_fuller.zip",2046403,"bios"],["bios/spectrum_gamma.zip",2046403,"bios"],["bios/spectrum_intf1.zip",2046403,"bios"],["bios/spectrum_kempcentref.zip",481571,"bios"],["bios/spectrum_kempcentreu.zip",481760,"bios"],["bios/spectrum_kempcentrs.zip",479847,"bios"],["bios/spectrum_kempdisc.zip",2046403,"bios"],["bios/spectrum_lprint.zip",481681,"bios"],["bios/spectrum_lprint3.zip",2046403,"bios"],["bios/spectrum_melodik.zip",2046403,"bios"],["bios/spectrum_mface1.zip",2046403,"bios"],["bios/spectrum_mface128.zip",2046403,"bios"],["bios/spectrum_mface128v1.zip",2046403,"bios"],["bios/spectrum_mface1v1.zip",2046403,"bios"],["bios/spectrum_mface1v2.zip",2046403,"bios"],["bios/spectrum_mface1v3.zip",2046403,"bios"],["bios/spectrum_mface3.zip",19134,"bios"],["bios/spectrum_mikroplus.zip",12536,"bios"],["bios/spectrum_mpoker.zip",2573,"bios"],["bios/spectrum_mprint.zip",2046403,"bios"],["bios/spectrum_opus.zip",2046403,"bios"],["bios/spectrum_plus2test.zip",3413,"bios"],["bios/spectrum_plusd.zip",497390,"bios"],["bios/spectrum_proceed.zip",1500724,"bios"],["bios/spectrum_sdi.zip",1496950,"bios"],["bios/spectrum_spdos.zip",2046403,"bios"],["bios/spectrum_speccydos.zip",2046403,"bios"],["bios/spectrum_specmate.zip",2046403,"bios"],["bios/spectrum_swiftdisc.zip",2046403,"bios"],["bios/spectrum_swiftdisc2.zip",2046403,"bios"],["bios/spectrum_uslot.zip",2046403,"bios"],["bios/spectrum_usource.zip",7261,"bios"],["bios/spectrum_uspeech.zip",3944,"bios"],["bios/spectrum_vtx5000.zip",2046403,"bios"],["bios/spectrum_wafa.zip",2046403,"bios"],["bios/spi.zip",479847,"bios"],["bios/square1.pk3",45202919,"game_data"],["bios/squirreljme-0.3.0-fast.jar",2367241,"bios"],["bios/squirreljme-0.3.0-slow-test.jar",3772058,"bios"],["bios/squirreljme-0.3.0-slow.jar",3129653,"bios"],["bios/squirreljme-0.3.0-test.jar",3396757,"bios"],["bios/squirreljme-0.3.0.jar",15181774,"bios"],["bios/squirreljme-fast.jar",15181774,"bios"],["bios/squirreljme-slow-test.jar",15181774,"bios"],["bios/squirreljme-slow.jar",15181774,"bios"],["bios/squirreljme-test.jar",3396757,"bios"],["bios/squirreljme.jar",4700395,"bios"],["bios/ss50_mpc.zip",95177,"bios"],["bios/ss50_mps.zip",95177,"bios"],["bios/ss50_mps2.zip",95177,"bios"],["bios/ss50_piaide.zip",1151601,"bios"],["bios/ssi263hle.zip",588,"bios"],["bios/st010.data.rom",4096,"bios"],["bios/st010.program.rom",49152,"bios"],["bios/st011.data.rom",4096,"bios"],["bios/st011.program.rom",49152,"bios"],["bios/st018.program.rom",131072,"bios"],["bios/st_kbd.zip",3344,"bios"],["bios/steeltal1_board.zip",95177,"bios"],["bios/steeltal_board.zip",95177,"bios"],["bios/steeltalp_board.zip",95177,"bios"],["bios/stereo_fx.zip",3977,"bios"],["bios/stic.zip",1296,"bios"],["bios/strtdriv_board.zip",95177,"bios"],["bios/stunrun_board.zip",95177,"bios"],["bios/stvbios.zip",2699375,"bios"],["bios/su2000.zip",90729,"bios"],["bios/sun1_cpu.zip",57393,"bios"],["bios/sun1cpu.zip",57393,"bios"],["bios/sun_gem.zip",9773,"bios"],["bios/supracan.zip",1849,"bios"],["bios/sv601.zip",577653,"bios"],["bios/sv602.zip",577653,"bios"],["bios/sv603.zip",5695,"bios"],["bios/sv802.zip",479847,"bios"],["bios/sv805.zip",95177,"bios"],["bios/sv806.zip",2717,"bios"],["bios/sw1000xg.zip",20518162,"bios"],["bios/swp30.zip",47545,"bios"],["bios/swtpc8212_device.zip",5070,"bios"],["bios/swtpc8212_terminal.zip",5070,"bios"],["bios/sx1541.zip",30913,"bios"],["bios/sys246.zip",580122,"bios"],["bios/sys256.zip",582110,"bios"],["bios/sys68k_cpu1.zip",605422,"bios"],["bios/sys68k_cpu20.zip",129580,"bios"],["bios/sys68k_cpu21.zip",34447,"bios"],["bios/sys68k_cpu21a.zip",34447,"bios"],["bios/sys68k_cpu21b.zip",34447,"bios"],["bios/sys68k_cpu21s.zip",34447,"bios"],["bios/sys68k_cpu21ya.zip",34447,"bios"],["bios/sys68k_cpu21yb.zip",34447,"bios"],["bios/sys68k_cpu30.zip",291856,"bios"],["bios/sys68k_cpu30be.zip",291856,"bios"],["bios/sys68k_cpu30x.zip",291856,"bios"],["bios/sys68k_cpu30xa.zip",291856,"bios"],["bios/sys68k_cpu30za.zip",291856,"bios"],["bios/sys68k_cpu33.zip",218296,"bios"],["bios/sys68k_iscsi1.zip",17599,"bios"],["bios/sys68k_isio1.zip",7302,"bios"],["bios/syscard1.pce",262144,"bios"],["bios/syscard2.pce",262144,"bios"],["bios/syscard2u.pce",262144,"bios"],["bios/syscard3.pce",262144,"bios"],["bios/syscard3u.pce",262144,"bios"],["bios/sysdata/keys.txt",7424,"bios"],["bios/sysdata/otp.bin",256,"bios"],["bios/sysdata/seeddb.bin",53264,"bios"],["bios/sysdata/shared_font.bin",3145728,"bios"],["bios/t5182.zip",2681,"bios"],["bios/taikodp.zip",1141771,"bios"],["bios/taito68705tiger.zip",266,"bios"],["bios/taitosjsecmcu.zip",266,"bios"],["bios/taitotz.zip",77002,"bios"],["bios/tak_daig.zip",951997,"bios"],["bios/tanbus_mpvdu.zip",536,"bios"],["bios/tanbus_ra32krom.zip",4189,"bios"],["bios/tanbus_ravdu.zip",525,"bios"],["bios/tanbus_tandos.zip",297319,"bios"],["bios/tanbus_tanex.zip",121959,"bios"],["bios/tanbus_vid8082.zip",5374,"bios"],["bios/tandberg_tdv2100_disp_logic.zip",96432,"bios"],["bios/tandberg_tdv2100_keyboard.zip",572,"bios"],["bios/tandy_1000_graphics.zip",3739,"bios"],["bios/tandy_1000x_graphics.zip",3731,"bios"],["bios/tape_128.sz",1464,"bios"],["bios/tape_16.szx",591,"bios"],["bios/tape_2048.szx",720,"bios"],["bios/tape_2068.szx",1799,"bios"],["bios/tape_48.szx",1799,"bios"],["bios/tape_pentagon.szx",1479,"bios"],["bios/tape_plus2.szx",1571,"bios"],["bios/tape_plus2a.szx",1617,"bios"],["bios/tape_plus3.szx",1856,"bios"],["bios/tape_plus3e.szx",1970,"bios"],["bios/tape_scorpion.szx",3500,"bios"],["bios/tape_se.szx",2146,"bios"],["bios/tape_ts2068.szx",1840,"bios"],["bios/tc2048.rom",16384,"bios"],["bios/tc2068-0.rom",16384,"bios"],["bios/tc2068-1.rom",8192,"bios"],["bios/tdl12.zip",786047,"bios"],["bios/technica.zip",12198,"bios"],["bios/tek410x_kbd.zip",936,"bios"],["bios/tek_msu_fdc.zip",2453,"bios"],["bios/teletex800.zip",1260,"bios"],["bios/tetriskr_cga.zip",160878,"bios"],["bios/tgui9680.zip",22311,"bios"],["bios/ti8x_glinkhle.zip",95177,"bios"],["bios/ti8x_tconn.zip",95177,"bios"],["bios/ti99_4a.zip",21377,"bios"],["bios/ti99_arcturus.zip",11432,"bios"],["bios/ti99_bwg.zip",7452,"bios"],["bios/ti99_ccdcc.zip",9611,"bios"],["bios/ti99_ccfdc.zip",9712,"bios"],["bios/ti99_ddcc1.zip",6231,"bios"],["bios/ti99_evpc.zip",17207,"bios"],["bios/ti99_fdc.zip",4969,"bios"],["bios/ti99_gkracker.zip",5998,"bios"],["bios/ti99_hfdc.zip",11813,"bios"],["bios/ti99_ide.zip",1151601,"bios"],["bios/ti99_iosplit.zip",2106147,"bios"],["bios/ti99_myarcmem.zip",6085,"bios"],["bios/ti99_pcode.zip",41460,"bios"],["bios/ti99_rs232.zip",1782,"bios"],["bios/ti99_speech.zip",31291,"bios"],["bios/ti99_speechconn.zip",2106147,"bios"],["bios/ti99_thermal.zip",1544,"bios"],["bios/ti99_tipi.zip",5838,"bios"],["bios/ti99_whtscsi.zip",790364,"bios"],["bios/ti_hx5102.zip",9758,"bios"],["bios/tiki100_8088.zip",1246,"bios"],["bios/tim011_kbd.zip",1862,"bios"],["bios/tk02.zip",2839,"bios"],["bios/tms32030.zip",573,"bios"],["bios/tms32031.zip",573,"bios"],["bios/tms32032.zip",620,"bios"],["bios/tms32033.zip",573,"bios"],["bios/tms320c30.zip",573,"bios"],["bios/tms320c31.zip",573,"bios"],["bios/tms320c32.zip",620,"bios"],["bios/tms320vc33.zip",573,"bios"],["bios/tnt.wad",18195736,"game_data"],["bios/top-sp1.bin",524288,"bios"],["bios/tos.img",196608,"bios"],["bios/tourvis.zip",29492,"bios"],["bios/tp880v.zip",150415,"bios"],["bios/tp881v.zip",167178,"bios"],["bios/trdos.rom",16384,"bios"],["bios/triforce.zip",2046778,"bios"],["bios/trio64dx_pci.zip",73424,"bios"],["bios/trs80m2kb.zip",920,"bios"],["bios/tsvme104.zip",120366,"bios"],["bios/turbogx.zip",11121,"bios"],["bios/turbogxp.zip",11215,"bios"],["bios/tv950kb.zip",1046,"bios"],["bios/tv955kb.zip",1417,"bios"],["bios/tvc_hbf.zip",36960,"bios"],["bios/tvga9000.zip",37841,"bios"],["bios/uae_data/drive_click_A500.wav",3313326,"bios"],["bios/uae_data/drive_click_LOUD.wav",3308526,"bios"],["bios/uae_data/drive_snatch_A500.wav",34450,"bios"],["bios/uae_data/drive_snatch_LOUD.wav",39864,"bios"],["bios/uae_data/drive_spin_A500.wav",134294,"bios"],["bios/uae_data/drive_spin_LOUD.wav",20216,"bios"],["bios/uae_data/drive_spinnd_A500.wav",352430,"bios"],["bios/uae_data/drive_spinnd_LOUD.wav",241790,"bios"],["bios/uae_data/drive_startup_A500.wav",34450,"bios"],["bios/uae_data/drive_startup_LOUD.wav",43492,"bios"],["bios/ubpnic.zip",171,"bios"],["bios/ultra12f.zip",44397,"bios"],["bios/ultra12f32.zip",20138,"bios"],["bios/ultra14f.zip",794627,"bios"],["bios/ultra24f.zip",797445,"bios"],["bios/umc6650.zip",160,"bios"],["bios/uni-bioscd.rom",524288,"bios"],["bios/uniap2ti.zip",1716,"bios"],["bios/upc82c710.zip",479847,"bios"],["bios/upc82c711.zip",479847,"bios"],["bios/upd7220.zip",367,"bios"],["bios/upd7801g.s01",4096,"bios"],["bios/uts_400kbd.zip",853,"bios"],["bios/uts_extw.zip",1046,"bios"],["bios/v102_kbd.zip",1329,"bios"],["bios/v4bios.zip",3753,"bios"],["bios/v50_kbd.zip",1066,"bios"],["bios/v550_kbd.zip",1184,"bios"],["bios/vanta.zip",72613,"bios"],["bios/vector4_kbd.zip",1267,"bios"],["bios/vic1010.zip",10861,"bios"],["bios/vic1011.zip",95177,"bios"],["bios/vic1112.zip",291066,"bios"],["bios/vic1515.zip",2699,"bios"],["bios/vic1520.zip",3695,"bios"],["bios/vic20_fe3.zip",9529,"bios"],["bios/vic20_speakeasy.zip",590,"bios"],["bios/vic20_videopak.zip",830,"bios"],["bios/vice/C64/basic-901226-01.bin",8192,"bios"],["bios/vice/C64/chargen-901225-01.bin",4096,"bios"],["bios/vice/C64/chargen-906143-02.bin",4096,"bios"],["bios/vice/C64/kernal-251104-04.bin",8192,"bios"],["bios/vice/C64/kernal-390852-01.bin",8192,"bios"],["bios/vice/C64/kernal-901227-01.bin",8192,"bios"],["bios/vice/C64/kernal-901227-02.bin",8192,"bios"],["bios/vice/C64/kernal-901227-03.bin",8192,"bios"],["bios/vice/C64/kernal-901246-01.bin",8192,"bios"],["bios/vice/C64/kernal-906145-02.bin",8192,"bios"],["bios/vice/DRIVES/dos1540-325302+3-01.bin",16384,"bios"],["bios/vice/DRIVES/dos1541-325302-01+901229-05.bin",16384,"bios"],["bios/vice/DRIVES/dos1541ii-251968-03.bin",16384,"bios"],["bios/vice/DRIVES/dos1570-315090-01.bin",32768,"bios"],["bios/vice/DRIVES/dos1571-310654-05.bin",32768,"bios"],["bios/vice/DRIVES/dos1581-318045-02.bin",32768,"bios"],["bios/vice/JiffyDOS_1541-II.bin",16384,"bios"],["bios/vice/JiffyDOS_1571_repl310654.bin",32768,"bios"],["bios/vice/JiffyDOS_1581.bin",32768,"bios"],["bios/vice/JiffyDOS_C64.bin",8192,"bios"],["bios/vice/JiffyDOS_SX-64.bin",8192,"bios"],["bios/vice/SCPU64/chargen-901225-01.bin",4096,"bios"],["bios/vice/SCPU64/chargen-906143-02.bin",4096,"bios"],["bios/vice/SCPU64/scpu-dos-1.4.bin",131072,"bios"],["bios/vice/SCPU64/scpu-dos-2.04.bin",131072,"bios"],["bios/vice/SCPU64/scpu64",65536,"bios"],["bios/vice/VIC20/chargen-901460-02.bin",4096,"bios"],["bios/vice/VIC20/kernal.901486-02.bin",8192,"bios"],["bios/victor9k_fdc.zip",1152,"bios"],["bios/victor9k_kb.zip",669,"bios"],["bios/videnh2.zip",1713,"bios"],["bios/virge_pci.zip",35167,"bios"],["bios/virgedx_pci.zip",56560,"bios"],["bios/virgevx_pci.zip",19358,"bios"],["bios/vision864.zip",18539,"bios"],["bios/vision964.zip",18202,"bios"],["bios/vision968.zip",55852,"bios"],["bios/voice/E480.WAV",101,"game_data"],["bios/voice/E481.WAV",554,"game_data"],["bios/voice/E482.WAV",554,"game_data"],["bios/voice/E483.WAV",1096,"game_data"],["bios/voice/E484.WAV",2219,"game_data"],["bios/voice/E485.WAV",4592,"game_data"],["bios/voice/E486.WAV",2902,"game_data"],["bios/voice/E487.WAV",804,"game_data"],["bios/voice/E488.WAV",1378,"game_data"],["bios/voice/E489.WAV",576,"game_data"],["bios/voice/E48A.WAV",1556,"game_data"],["bios/voice/E48B.WAV",1516,"game_data"],["bios/voice/E48C.WAV",794,"game_data"],["bios/voice/E48D.WAV",1510,"game_data"],["bios/voice/E48E.WAV",1892,"game_data"],["bios/voice/E48F.WAV",788,"game_data"],["bios/voice/E490.WAV",2020,"game_data"],["bios/voice/E491.WAV",1122,"game_data"],["bios/voice/E492.WAV",1862,"game_data"],["bios/voice/E493.WAV",2772,"game_data"],["bios/voice/E494.WAV",3120,"game_data"],["bios/voice/E495.WAV",854,"game_data"],["bios/voice/E496.WAV",1154,"game_data"],["bios/voice/E497.WAV",1122,"game_data"],["bios/voice/E498.WAV",1144,"game_data"],["bios/voice/E499.WAV",2056,"game_data"],["bios/voice/E49A.WAV",1302,"game_data"],["bios/voice/E49B.WAV",2492,"game_data"],["bios/voice/E49C.WAV",936,"game_data"],["bios/voice/E49D.WAV",2038,"game_data"],["bios/voice/E49E.WAV",1146,"game_data"],["bios/voice/E49F.WAV",2884,"game_data"],["bios/voice/E4A0.WAV",4096,"game_data"],["bios/voice/E4A1.WAV",1702,"game_data"],["bios/voice/E4A2.WAV",1570,"game_data"],["bios/voice/E4A3.WAV",2060,"game_data"],["bios/voice/E4A4.WAV",846,"game_data"],["bios/voice/E4A5.WAV",1756,"game_data"],["bios/voice/E4A6.WAV",2144,"game_data"],["bios/voice/E4A7.WAV",1388,"game_data"],["bios/voice/E4A8.WAV",1586,"game_data"],["bios/voice/E4A9.WAV",2022,"game_data"],["bios/voice/E4AA.WAV",1624,"game_data"],["bios/voice/E4AB.WAV",2302,"game_data"],["bios/voice/E4AC.WAV",2484,"game_data"],["bios/voice/E4AD.WAV",1252,"game_data"],["bios/voice/E4AE.WAV",1978,"game_data"],["bios/voice/E4AF.WAV",3984,"game_data"],["bios/voice/E4B0.WAV",2184,"game_data"],["bios/voice/E4B1.WAV",1448,"game_data"],["bios/voice/E4B2.WAV",2040,"game_data"],["bios/voice/E4B3.WAV",1762,"game_data"],["bios/voice/E4B4.WAV",3334,"game_data"],["bios/voice/E4B5.WAV",2604,"game_data"],["bios/voice/E4B6.WAV",2654,"game_data"],["bios/voice/E4B7.WAV",984,"game_data"],["bios/voice/E4B8.WAV",2156,"game_data"],["bios/voice/E4B9.WAV",890,"game_data"],["bios/voice/E4BA.WAV",3656,"game_data"],["bios/voice/E4BB.WAV",3166,"game_data"],["bios/voice/E4BC.WAV",3840,"game_data"],["bios/voice/E4BD.WAV",464,"game_data"],["bios/voice/E4BE.WAV",2084,"game_data"],["bios/voice/E4BF.WAV",646,"game_data"],["bios/voice/E4C0.WAV",5348,"game_data"],["bios/voice/E4C1.WAV",8577,"game_data"],["bios/voice/E4C2.WAV",5504,"game_data"],["bios/voice/E4C3.WAV",12420,"game_data"],["bios/voice/E4C4.WAV",11286,"game_data"],["bios/voice/E4C5.WAV",7194,"game_data"],["bios/voice/E4C6.WAV",7078,"game_data"],["bios/voice/E4C7.WAV",4566,"game_data"],["bios/voice/E4C8.WAV",7740,"game_data"],["bios/voice/E4C9.WAV",9504,"game_data"],["bios/voice/E4CA.WAV",12896,"game_data"],["bios/voice/E4FA.WAV",11049,"game_data"],["bios/voice/E4FB.WAV",7604,"game_data"],["bios/voice/E880.WAV",10745,"game_data"],["bios/voice/E881.WAV",7324,"game_data"],["bios/voice/E882.WAV",6876,"game_data"],["bios/voice/E883.WAV",7418,"game_data"],["bios/voice/E884.WAV",13296,"game_data"],["bios/voice/E885.WAV",10055,"game_data"],["bios/voice/E886.WAV",5827,"game_data"],["bios/voice/E887.WAV",6215,"game_data"],["bios/voice/E888.WAV",5264,"game_data"],["bios/voice/E889.WAV",8524,"game_data"],["bios/voice/E88A.WAV",4348,"game_data"],["bios/voice/E88B.WAV",4104,"game_data"],["bios/voice/E88C.WAV",9624,"game_data"],["bios/voice/E88D.WAV",6914,"game_data"],["bios/voice/E88E.WAV",8319,"game_data"],["bios/voice/E88F.WAV",9592,"game_data"],["bios/voice/E890.WAV",9479,"game_data"],["bios/voice/E891.WAV",8697,"game_data"],["bios/voice/E892.WAV",6878,"game_data"],["bios/voice/E893.WAV",6220,"game_data"],["bios/voice/E894.WAV",6830,"game_data"],["bios/voice/E895.WAV",6283,"game_data"],["bios/voice/E980.WAV",6300,"game_data"],["bios/voice/E981.WAV",5324,"game_data"],["bios/voice/E982.WAV",11267,"game_data"],["bios/voice/E983.WAV",7202,"game_data"],["bios/voice/E984.WAV",6732,"game_data"],["bios/voice/E985.WAV",6317,"game_data"],["bios/voice/E986.WAV",6638,"game_data"],["bios/voice/E987.WAV",8261,"game_data"],["bios/voice/E988.WAV",10269,"game_data"],["bios/voice/E989.WAV",5644,"game_data"],["bios/voice/E98A.WAV",6008,"game_data"],["bios/voice/E98B.WAV",10470,"game_data"],["bios/voice/E98C.WAV",6304,"game_data"],["bios/voice/E98D.WAV",3478,"game_data"],["bios/voice/E98E.WAV",12232,"game_data"],["bios/voice/E98F.WAV",13922,"game_data"],["bios/voice/E990.WAV",10460,"game_data"],["bios/voice/E991.WAV",2924,"game_data"],["bios/voice/E992.WAV",16808,"game_data"],["bios/voice/E993.WAV",12544,"game_data"],["bios/voice/E994.WAV",7100,"game_data"],["bios/voice/E995.WAV",6452,"game_data"],["bios/voice/E996.WAV",6685,"game_data"],["bios/voice/EA80.WAV",3092,"game_data"],["bios/voice/EA81.WAV",5390,"game_data"],["bios/voice/EA82.WAV",14341,"game_data"],["bios/voice/EA83.WAV",4719,"game_data"],["bios/voice/EA84.WAV",5252,"game_data"],["bios/voice/EA85.WAV",7018,"game_data"],["bios/voice/EA86.WAV",8480,"game_data"],["bios/voice/EA87.WAV",9496,"game_data"],["bios/voice/EA88.WAV",38600,"game_data"],["bios/voice/EA89.WAV",29892,"game_data"],["bios/voice/EA8A.WAV",11328,"game_data"],["bios/voice/EA8B.WAV",2604,"game_data"],["bios/voice/EA8C.WAV",16184,"game_data"],["bios/voice/EA8D.WAV",3308,"game_data"],["bios/voice/EA8E.WAV",3350,"game_data"],["bios/voice/EA8F.WAV",18174,"game_data"],["bios/voice/EA90.WAV",3348,"game_data"],["bios/voice/EA91.WAV",3299,"game_data"],["bios/voice/EA92.WAV",3302,"game_data"],["bios/voice/EA93.WAV",3306,"game_data"],["bios/voice/EA94.WAV",3267,"game_data"],["bios/voice/EA95.WAV",3388,"game_data"],["bios/voice/EA96.WAV",3392,"game_data"],["bios/voice/EA97.WAV",3393,"game_data"],["bios/voice/EA98.WAV",3359,"game_data"],["bios/voice/EA99.WAV",3300,"game_data"],["bios/voice/EA9A.WAV",3312,"game_data"],["bios/voice/EA9B.WAV",3402,"game_data"],["bios/voice/EA9C.WAV",3308,"game_data"],["bios/voice/EA9D.WAV",3313,"game_data"],["bios/voice/EA9E.WAV",3302,"game_data"],["bios/voice/EA9F.WAV",3340,"game_data"],["bios/voice/EAA0.WAV",3314,"game_data"],["bios/voice/EAA1.WAV",3306,"game_data"],["bios/voice/EAA2.WAV",3308,"game_data"],["bios/voice/EAA3.WAV",3314,"game_data"],["bios/voice/EAA4.WAV",3313,"game_data"],["bios/voice/EAA5.WAV",3311,"game_data"],["bios/voice/EAA6.WAV",3340,"game_data"],["bios/voice/EAA7.WAV",3302,"game_data"],["bios/voice/EB80.WAV",7226,"game_data"],["bios/voice/EB81.WAV",5558,"game_data"],["bios/voice/EB82.WAV",5566,"game_data"],["bios/voice/EB83.WAV",6276,"game_data"],["bios/voice/EB84.WAV",7508,"game_data"],["bios/voice/EB85.WAV",5400,"game_data"],["bios/voice/EB86.WAV",8981,"game_data"],["bios/voice/EB87.WAV",8844,"game_data"],["bios/voice/EB88.WAV",6554,"game_data"],["bios/voice/EB89.WAV",6932,"game_data"],["bios/voice/EB8A.WAV",7059,"game_data"],["bios/voice/EB8B.WAV",7544,"game_data"],["bios/voice/EB8C.WAV",5790,"game_data"],["bios/voice/EB8D.WAV",6700,"game_data"],["bios/voice/EB8E.WAV",6188,"game_data"],["bios/voice/EB8F.WAV",4880,"game_data"],["bios/voice/EB90.WAV",7480,"game_data"],["bios/voice/EB91.WAV",6804,"game_data"],["bios/voice/EB92.WAV",7419,"game_data"],["bios/voice/EB93.WAV",6105,"game_data"],["bios/voice/EB94.WAV",4972,"game_data"],["bios/voice/EB95.WAV",5084,"game_data"],["bios/voice/EB96.WAV",6492,"game_data"],["bios/voice/EB97.WAV",8819,"game_data"],["bios/voice/EB98.WAV",6104,"game_data"],["bios/voice/EB99.WAV",5896,"game_data"],["bios/voice/EB9A.WAV",5784,"game_data"],["bios/voice/EB9B.WAV",5742,"game_data"],["bios/voice/EB9C.WAV",6154,"game_data"],["bios/voice/EB9D.WAV",4984,"game_data"],["bios/voice/EC80.WAV",6815,"game_data"],["bios/voice/EC81.WAV",5628,"game_data"],["bios/voice/EC82.WAV",17440,"game_data"],["bios/voice/EC83.WAV",8162,"game_data"],["bios/voice/EC84.WAV",7944,"game_data"],["bios/voice/EC85.WAV",6848,"game_data"],["bios/voice/EC86.WAV",8225,"game_data"],["bios/voice/EC87.WAV",5588,"game_data"],["bios/voice/EC88.WAV",8954,"game_data"],["bios/voice/EC89.WAV",7340,"game_data"],["bios/voice/EC8A.WAV",9092,"game_data"],["bios/voice/EC8B.WAV",7754,"game_data"],["bios/voice/EC8C.WAV",7100,"game_data"],["bios/voice/EC8D.WAV",5732,"game_data"],["bios/voice/EC8E.WAV",6200,"game_data"],["bios/voice/EC8F.WAV",6504,"game_data"],["bios/voice/EC90.WAV",7853,"game_data"],["bios/voice/EC91.WAV",8378,"game_data"],["bios/voice/EC92.WAV",5336,"game_data"],["bios/voice/EC93.WAV",8294,"game_data"],["bios/voice/EC94.WAV",7838,"game_data"],["bios/voice/EC95.WAV",6927,"game_data"],["bios/voice/EC96.WAV",7524,"game_data"],["bios/voice/EC97.WAV",8140,"game_data"],["bios/voice/EC98.WAV",8370,"game_data"],["bios/voice/EC99.WAV",7292,"game_data"],["bios/voice/EC9A.WAV",6884,"game_data"],["bios/voice/EC9B.WAV",6846,"game_data"],["bios/voice/ED80.WAV",6308,"game_data"],["bios/voice/ED81.WAV",5772,"game_data"],["bios/voice/ED82.WAV",6794,"game_data"],["bios/voice/ED83.WAV",6680,"game_data"],["bios/voice/ED84.WAV",6624,"game_data"],["bios/voice/ED85.WAV",7450,"game_data"],["bios/voice/ED86.WAV",7055,"game_data"],["bios/voice/ED87.WAV",5955,"game_data"],["bios/voice/ED88.WAV",6789,"game_data"],["bios/voice/ED89.WAV",6542,"game_data"],["bios/voice/ED8A.WAV",6924,"game_data"],["bios/voice/ED8B.WAV",7062,"game_data"],["bios/voice/ED8C.WAV",6967,"game_data"],["bios/voice/ED8D.WAV",7205,"game_data"],["bios/voice/ED8E.WAV",7381,"game_data"],["bios/voice/ED8F.WAV",5168,"game_data"],["bios/voice/ED90.WAV",5344,"game_data"],["bios/voice/ED91.WAV",5345,"game_data"],["bios/voice/ED92.WAV",7924,"game_data"],["bios/voice/ED93.WAV",7415,"game_data"],["bios/voice/ED94.WAV",6820,"game_data"],["bios/voice/ED95.WAV",6464,"game_data"],["bios/voice/ED96.WAV",6576,"game_data"],["bios/voice/ED97.WAV",6124,"game_data"],["bios/voice/ED98.WAV",7688,"game_data"],["bios/voice/ED99.WAV",6369,"game_data"],["bios/voice/ED9A.WAV",6254,"game_data"],["bios/voice/EE80.WAV",6012,"game_data"],["bios/voice/EE81.WAV",8294,"game_data"],["bios/voice/EE82.WAV",7128,"game_data"],["bios/voice/EE83.WAV",4256,"game_data"],["bios/voice/EE84.WAV",7514,"game_data"],["bios/voice/EE85.WAV",8176,"game_data"],["bios/voice/EE86.WAV",6824,"game_data"],["bios/voice/EE87.WAV",8117,"game_data"],["bios/voice/EE88.WAV",8756,"game_data"],["bios/voice/EE89.WAV",7406,"game_data"],["bios/voice/EE8A.WAV",7352,"game_data"],["bios/voice/EE8B.WAV",8651,"game_data"],["bios/voice/EE8C.WAV",7511,"game_data"],["bios/voice/EE8D.WAV",8024,"game_data"],["bios/voice/EE8E.WAV",9809,"game_data"],["bios/voice/EE8F.WAV",8364,"game_data"],["bios/voice/EE90.WAV",4828,"game_data"],["bios/voice/EE91.WAV",6092,"game_data"],["bios/voice/EE92.WAV",5000,"game_data"],["bios/voice/EE93.WAV",7197,"game_data"],["bios/voice/EE94.WAV",6785,"game_data"],["bios/voice/EE95.WAV",6105,"game_data"],["bios/voice/EE96.WAV",7604,"game_data"],["bios/voicebox.zip",2019,"bios"],["bios/voodoo_3000_x86.zip",40056,"bios"],["bios/votraxtnt.zip",3922,"bios"],["bios/votrsc01.zip",588,"bios"],["bios/votrsc01a.zip",590,"bios"],["bios/vp575.zip",3613,"bios"],["bios/vp700.zip",3613,"bios"],["bios/vrc5074.zip",95177,"bios"],["bios/vsaturn.bin",524288,"bios"],["bios/vsmile.zip",5065220,"bios"],["bios/vsmile_v100.bin",2097152,"bios"],["bios/vsmile_v102.bin",2097152,"bios"],["bios/vsmile_v103.bin",2097152,"bios"],["bios/vtech_fdc.zip",123619,"bios"],["bios/vtech_printer.zip",479847,"bios"],["bios/vtech_rs232.zip",97591,"bios"],["bios/vtech_rtty.zip",2488,"bios"],["bios/vtech_sdloader.zip",11160,"bios"],["bios/vtech_wordpro.zip",8125,"bios"],["bios/w83787f.zip",479847,"bios"],["bios/w83977tf.zip",479847,"bios"],["bios/wangpc_lic.zip",2810,"bios"],["bios/wangpc_rtc.zip",3197,"bios"],["bios/wangpc_tig.zip",367,"bios"],["bios/wangpc_wdc.zip",3193,"bios"],["bios/wangpckb.zip",1228,"bios"],["bios/wd1002a_wx1.zip",1868,"bios"],["bios/wd1007a.zip",3971,"bios"],["bios/wd90c00_jk.zip",58499,"bios"],["bios/wd90c11_lr.zip",18343,"bios"],["bios/wd90c30_lr.zip",41732,"bios"],["bios/wd90c31_lr.zip",22513,"bios"],["bios/wd90c31a_lr.zip",38568,"bios"],["bios/wd90c31a_zs.zip",18777,"bios"],["bios/wd90c33_zz.zip",19105,"bios"],["bios/wd90c90_jk.zip",15497,"bios"],["bios/wd9710_pci.zip",18718,"bios"],["bios/wdxt_gen.zip",4266,"bios"],["bios/wg130.zip",1861561,"bios"],["bios/wildmidi.cfg",192,"game_data"],["bios/wpcap.dll",499128,"bios"],["bios/wyse700.zip",4164,"bios"],["bios/x68k_cz6bs1.zip",3156,"bios"],["bios/x820iikb.zip",1128,"bios"],["bios/x820kb.zip",1128,"bios"],["bios/xegs.zip",23089,"bios"],["bios/xerox820_16_8.zip",1338,"bios"],["bios/xerox820_emii_flpy5.zip",2303,"bios"],["bios/xerox820_emii_rgd5.zip",2303,"bios"],["bios/xetec_c5181.zip",3192,"bios"],["bios/xmil/FNT0808.X1",2048,"bios"],["bios/xmil/FNT0816.X1",4096,"bios"],["bios/xmil/FNT1616.X1",306176,"bios"],["bios/xmil/IPLROM.X1",4096,"bios"],["bios/xmil/IPLROM.X1T",32768,"bios"],["bios/xroarbios.rom",8192,"bios"],["bios/xt446.zip",18613894,"bios"],["bios/xtide.zip",1300467,"bios"],["bios/yados.rom",16384,"bios"],["bios/ym2413.zip",286,"bios"],["bios/ym2423.zip",313,"bios"],["bios/ym2608.zip",7587,"bios"],["bios/ymf281.zip",313,"bios"],["bios/yrw801.rom",2097152,"bios"],["bios/z8671.zip",2028,"bios"],["bios/z8682.zip",201,"bios"],["bios/z_89_11.zip",95177,"bios"],["bios/zc405351p__servo_cdi_4.1__0d67p__lluk9404.mc68hc705c8a.7490",8192,"bios"],["bios/zc405352p__slave_cdi_4.1__0d67p__lltr9403.mc68hc705c8a.7206",8192,"bios"],["bios/zip100_ide.zip",36071,"bios"],["bios/zorba_kbd.zip",1406,"bios"],["bios/zx405037p__cdi_servo_2.1__b43t__llek9215.mc68hc705c8a_withtestrom.7201",8192,"bios"],["bios/zx405042p__cdi_slave_2.0__b43t__zzmk9213.mc68hc705c8a_withtestrom.7206",8192,"bios"],["bios/zxbus_adapter.zip",297163,"bios"],["bios/zxbus_neogs.zip",297163,"bios"],["bios/zxs:48.rom",16384,"bios"],["bios/zxs:if1-2.rom",8192,"bios"],["cps/hiscore.dat",322458,"bios"],["cps1/hiscore.dat",322458,"bios"],["cps2/hiscore.dat",322458,"bios"],["cps3/hiscore.dat",322458,"bios"],["fba/hiscore.dat",322458,"bios"],["gc/User/GBA/gba_bios.bin",16384,"bios"],["gc/User/Load/WiiSD.raw",134217728,"bios"],["gc/User/Wii/clientca.pem",1005,"bios"],["gc/User/Wii/clientcakey.pem",609,"bios"],["gc/User/Wii/rootca.pem",897,"bios"],["gc/User/Wii/shared2/sys/SYSCONF",16384,"bios"],["gc/User/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["mame/hiscore.dat",322458,"bios"],["n3ds/Azahar/nand/private/movable.sed",320,"bios"],["n3ds/Azahar/nand/rw/sys/LocalFriendCodeSeed_B",272,"bios"],["n3ds/Azahar/nand/rw/sys/SecureInfo_A",273,"bios"],["n3ds/Azahar/sysdata/keys.txt",7424,"bios"],["n3ds/Azahar/sysdata/otp.bin",256,"bios"],["n3ds/Azahar/sysdata/seeddb.bin",53264,"bios"],["n3ds/Azahar/sysdata/shared_font.bin",3145728,"bios"],["roms/neogeo/neogeo.zip",1859335,"bios"],["wii/User/GBA/gba_bios.bin",16384,"bios"],["wii/User/Load/WiiSD.raw",134217728,"bios"],["wii/User/Wii/clientca.pem",1005,"bios"],["wii/User/Wii/clientcakey.pem",609,"bios"],["wii/User/Wii/rootca.pem",897,"bios"],["wii/User/Wii/shared2/sys/SYSCONF",16384,"bios"],["wii/User/Wii/title/00000001/00000002/data/setting.txt",256,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeCn.ttf",13110604,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeKr.ttf",2260660,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeStd.ttf",2442464,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10042400/content/CafeTw.ttf",8229724,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/1004f000/content/00/swkbd/swkbd.pack",1907900,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10051000/content/00/erreula/erreula.pack",1252759,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_ACCOUNT_1_CERT.der",1226,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_ACCOUNT_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_COMMON_1_CERT.der",1224,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_COMMON_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_OLIVE_1_CERT.der",1224,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_OLIVE_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_VINO_1_CERT.der",1223,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_VINO_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_WOOD_1_CERT.der",1223,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/ccerts/WIIU_WOOD_1_RSA_KEY.aes",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ADDTRUST_EXT_CA_ROOT.der",1082,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/BALTIMORE_CYBERTRUST_ROOT_CA.der",891,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA.der",897,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA_G2.der",1173,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CA_G3.der",1060,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA.der",924,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA_G2.der",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CACERT_NINTENDO_CLASS2_CA_G3.der",1200,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/COMODO_CA.der",980,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/CYBERTRUST_GLOBAL_ROOT_CA.der",933,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_ASSURED_ID_ROOT_CA.der",955,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_ASSURED_ID_ROOT_CA_G2.der",922,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_GLOBAL_ROOT_CA.der",947,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_GLOBAL_ROOT_CA_G2.der",914,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/DIGICERT_HIGH_ASSURANCE_EV_ROOT_CA.der",969,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_CA_2048.der",1070,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_ROOT_CA.der",1173,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_ROOT_CA_G2.der",1090,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/ENTRUST_SECURE_SERVER_CA.der",1244,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/EQUIFAX_SECURE_CA.der",804,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_GLOBAL_CA.der",856,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_GLOBAL_CA2.der",874,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_PRIMARY_CA.der",896,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GEOTRUST_PRIMARY_CA_G3.der",1026,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA.der",889,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA_R2.der",958,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GLOBALSIGN_ROOT_CA_R3.der",867,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/GTE_CYBERTRUST_GLOBAL_ROOT.der",606,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PREMIUM_SERVER_CA.der",811,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PRIMARY_ROOT_CA.der",1060,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/THAWTE_PRIMARY_ROOT_CA_G3.der",1070,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/UTN_DATACORP_SGC_CA.der",1122,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/UTN_USERFIRST_HARDWARE_CA.der",1144,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA.der",576,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G2.der",774,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G3.der",1054,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_CLASS3_PUBLIC_PRIMARY_CA_G5.der",1239,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERISIGN_UNIVERSAL_ROOT_CA.der",1213,"bios"],["wiiu/Cemu/mlc01/sys/title/0005001b/10054000/content/scerts/VERIZON_GLOBAL_ROOT_CA.der",889,"bios"]],"format_version":1,"platform":"retrodeck","sets":{"acorn-archimedes|mame":{"bytes":6536273,"files":[361],"optional":[],"required_bytes":6536273},"acorn-bbc-micro|mame":{"bytes":623105,"files":[617,634,639,640,641,642,643,2303,2934],"optional":[617,634,639,640,641,2303,2934],"required_bytes":500688},"amstrad-cpc|cap32":{"bytes":114688,"files":[853,854,855,856],"optional":[853,854,855,856],"required_bytes":0},"apple-iigs|mame":{"bytes":148893457,"files":[31,39,186,187,283,284,285,286,288,289,290,292,293,294,295,297,299,300,301,302,305,306,307,308,309,310,311,312,315,318,319,320,321,325,327,329,330,331,332,334,335,336,338,373,390,450,451,452,453,538,570,697,706,709,714,723,724,746,751,759,760,761,762,763,771,778,785,802,841,845,872,883,884,886,893,926,990,1025,1026,1027,1028,1029,1030,1031,1060,1061,1062,1066,1079,1081,1189,1238,1243,1244,1245,1246,1247,1248,1250,1261,1262,1269,1280,1283,1285,1329,1341,1416,1419,1420,1428,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2331,2354,2357,2358,2398,2435,2504,2536,2565,2585,2606,2611,2686,2687,2688,2808,2911,2912,2915,2917,2918,2920,2921,2924,2944,2981,2982,3014,3034,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3155,3186,3190,3257,3295,3621,3622,3624,3680,3682,3689],"optional":[297,301,305,306,307,308,309,390,570,706,709,1280,1449,1457,1458,1459,1472,1473,1474,1476,1501,1502,1507,1508,1509,1511,1512,1513,1522,1523,1524,1525,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1549,1550,1551,1555,1577,1578,1581,1589,1595,1601,1602,1603,1604,1612,1620,1627,1628,1629,1630,1631,1633,1638,1639,1640,1641,1642,1644,1645,1646,1649,1659,1660,1661,1662,1670,1672,1676,1680,1695,1696,1702,1723,1772,1775,1776,1797,1798,1799,1800,1801,1802,1809,1817,1892,1893,1904,1905,1942,1943,1944,1958,1961,1967,1970,1977,2005,2017,2035,2036,2055,2059,2060,2071,2079,2093,2094,2095,2096,2097,2098,2099,2108,2123,2137,2139,2140,2152,2153,2154,2160,2179,2181,2193,2196,2199,2204,2205,2221,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2606,2911,2912,3014,3257,3621],"required_bytes":124377548},"apple-macintosh|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"apple2|applewin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"arcade|fbalpha2012":{"bytes":1335159885,"files":[0,13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,288,289,290,291,292,293,294,295,296,298,299,300,302,310,311,312,313,314,315,316,318,319,320,321,322,323,324,325,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,427,428,429,430,431,432,436,437,439,440,441,442,443,444,445,446,447,448,449,450,451,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,512,513,514,515,516,517,518,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,565,566,567,568,569,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,635,636,637,644,645,646,647,665,666,667,668,669,670,671,672,673,674,675,677,678,679,680,681,682,683,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,707,708,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,738,739,740,741,742,743,744,745,746,747,748,749,750,751,755,759,760,761,762,763,764,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,782,783,785,786,787,788,789,791,793,794,795,796,797,798,799,800,801,802,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,831,834,835,836,837,838,839,840,841,842,843,844,845,846,851,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,881,882,883,884,885,886,893,901,902,903,904,917,918,919,920,927,928,929,934,935,936,937,938,939,940,941,942,943,944,945,951,953,954,955,956,957,958,959,960,961,962,963,964,965,980,981,982,983,984,985,986,987,990,991,1002,1003,1004,1005,1006,1007,1008,1010,1011,1012,1013,1017,1018,1019,1020,1022,1023,1024,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1075,1076,1077,1078,1080,1081,1083,1084,1085,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1103,1104,1105,1106,1109,1110,1111,1112,1113,1114,1116,1123,1139,1140,1180,1181,1190,1191,1193,1194,1196,1200,1201,1202,1208,1209,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1224,1225,1226,1229,1230,1231,1232,1233,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1251,1253,1254,1255,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1282,1283,1284,1285,1287,1288,1289,1290,1291,1292,1294,1295,1296,1297,1303,1304,1305,1306,1307,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1330,1331,1332,1333,1338,1339,1342,1343,1344,1345,1346,1347,1348,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1370,1371,1372,1388,1389,1390,1391,1392,1393,1395,1396,1397,1398,1399,1400,1401,1402,1403,1405,1409,1410,1411,1415,1416,1417,1418,1419,1420,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,2323,2324,2327,2328,2329,2330,2331,2332,2333,2334,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2369,2370,2371,2372,2373,2374,2375,2377,2378,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2434,2435,2436,2437,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2526,2527,2528,2529,2530,2531,2532,2535,2536,2537,2542,2563,2564,2565,2566,2568,2569,2570,2573,2574,2575,2577,2578,2579,2580,2582,2583,2584,2585,2586,2587,2588,2603,2604,2605,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2632,2634,2635,2636,2637,2638,2639,2640,2641,2642,2644,2645,2646,2647,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2665,2666,2667,2668,2681,2682,2683,2684,2685,2690,2693,2694,2695,2696,2697,2698,2790,2793,2794,2795,2796,2797,2798,2799,2802,2803,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2894,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2910,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2933,2937,2939,2940,2941,2942,2943,2944,2966,2976,2979,2980,2981,2982,2983,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3010,3012,3013,3017,3018,3019,3020,3021,3022,3025,3026,3027,3030,3034,3035,3036,3037,3038,3039,3040,3041,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3056,3057,3058,3059,3060,3061,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3123,3124,3125,3126,3127,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3144,3145,3147,3148,3149,3150,3151,3152,3154,3155,3156,3157,3158,3159,3160,3161,3185,3187,3188,3189,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3217,3218,3219,3220,3221,3222,3223,3224,3225,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3261,3262,3263,3265,3267,3268,3269,3270,3271,3272,3273,3274,3285,3286,3287,3288,3289,3290,3293,3294,3295,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3341,3342,3344,3345,3346,3347,3348,3349,3620,3622,3623,3624,3625,3626,3627,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3661,3662,3664,3676,3677,3679,3680,3681,3682,3684,3685,3686,3689,3690,3693,3694,3697,3698,3699,3700,3701,3709],"optional":[0,1093,1094,1095,1096,1097,1098,1099,1100,3697,3698,3699,3700,3701,3709],"required_bytes":516192146},"arcade|fbneo":{"bytes":825758776,"files":[13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,288,289,290,291,292,293,294,295,296,298,299,300,302,310,311,312,313,314,315,316,318,319,320,321,322,323,324,325,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,427,428,429,430,431,432,436,437,439,440,441,442,443,444,445,446,447,448,449,450,451,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,512,513,514,515,516,517,518,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,565,566,567,568,569,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,635,636,637,644,645,646,647,665,666,667,668,669,670,671,672,673,674,675,677,678,679,680,681,682,683,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,707,708,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,738,739,740,741,742,743,744,745,746,747,748,749,750,751,755,759,760,761,762,763,764,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,782,783,785,786,787,788,789,791,793,794,795,796,797,798,799,800,801,802,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,831,834,835,836,837,838,839,840,841,842,843,844,845,846,851,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,881,882,883,884,885,886,893,901,902,903,904,917,918,919,920,927,928,929,934,935,936,937,938,939,940,941,942,943,944,945,951,953,954,955,956,957,958,959,960,961,962,963,964,965,980,981,982,983,984,985,986,987,990,991,1002,1003,1004,1005,1006,1007,1008,1010,1011,1012,1013,1017,1018,1019,1020,1022,1023,1024,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1075,1076,1077,1078,1080,1081,1083,1084,1085,1090,1091,1092,1101,1102,1103,1104,1105,1106,1109,1110,1111,1112,1113,1114,1116,1123,1139,1140,1180,1181,1190,1191,1193,1194,1196,1200,1201,1202,1208,1209,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1224,1225,1226,1229,1230,1231,1232,1233,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1251,1253,1254,1255,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1282,1283,1284,1285,1287,1288,1289,1290,1291,1292,1294,1295,1296,1297,1303,1304,1305,1306,1307,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1330,1331,1332,1333,1338,1339,1342,1343,1344,1345,1346,1347,1348,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1370,1371,1372,1388,1389,1390,1391,1392,1393,1395,1396,1397,1398,1399,1400,1401,1402,1403,1405,1409,1410,1411,1415,1416,1417,1418,1419,1420,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,2323,2324,2327,2328,2329,2330,2331,2332,2333,2334,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2369,2370,2371,2372,2373,2374,2375,2377,2378,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2434,2435,2436,2437,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2526,2527,2528,2529,2530,2531,2532,2535,2536,2537,2542,2563,2564,2565,2566,2568,2569,2570,2573,2574,2575,2577,2578,2579,2580,2582,2583,2584,2585,2586,2587,2588,2603,2604,2605,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2632,2634,2635,2636,2637,2638,2639,2640,2641,2642,2644,2645,2646,2647,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2665,2666,2667,2668,2681,2682,2683,2684,2685,2690,2693,2694,2695,2696,2697,2698,2790,2793,2794,2795,2796,2797,2798,2799,2802,2803,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2894,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2910,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2933,2937,2939,2940,2941,2942,2943,2944,2966,2976,2979,2980,2981,2982,2983,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3010,3012,3013,3017,3018,3019,3020,3021,3022,3025,3026,3027,3030,3034,3035,3036,3037,3038,3039,3040,3041,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3056,3057,3058,3059,3060,3061,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3123,3124,3125,3126,3127,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3144,3145,3147,3148,3149,3150,3151,3152,3154,3155,3156,3157,3158,3159,3160,3161,3185,3187,3188,3189,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3217,3218,3219,3220,3221,3222,3223,3224,3225,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3261,3262,3263,3265,3267,3268,3269,3270,3271,3272,3273,3274,3285,3286,3287,3288,3289,3290,3293,3294,3295,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3341,3342,3344,3345,3346,3347,3348,3349,3620,3622,3623,3624,3625,3626,3627,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3661,3662,3664,3676,3677,3679,3680,3681,3682,3684,3685,3686,3689,3690,3693,3694],"optional":[1101,1102],"required_bytes":516192146},"arcade|mame":{"bytes":644070374,"files":[13,27,29,30,31,34,37,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,399,400,401,402,403,404,405,406,407,408,409,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,512,513,514,515,516,517,518,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,635,636,637,638,644,645,646,647,665,666,667,668,669,670,671,672,673,674,675,677,678,679,680,681,682,683,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,738,739,740,741,742,743,744,745,746,747,748,749,750,751,755,759,760,761,762,763,764,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,782,783,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,831,834,835,836,837,838,839,840,841,842,843,844,845,846,851,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,893,901,902,903,904,917,918,919,920,927,928,929,934,935,936,937,938,939,940,941,942,943,944,945,951,953,954,955,956,957,958,959,960,961,962,963,964,965,980,981,982,983,984,985,986,987,990,991,992,1002,1003,1004,1005,1006,1007,1008,1010,1011,1012,1013,1017,1018,1019,1020,1021,1022,1023,1024,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1080,1081,1083,1084,1085,1086,1090,1091,1092,1103,1104,1105,1106,1109,1110,1111,1112,1113,1114,1115,1116,1123,1139,1140,1180,1181,1185,1190,1191,1193,1194,1196,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1224,1225,1226,1229,1230,1231,1232,1233,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1251,1253,1254,1255,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1282,1283,1284,1285,1287,1288,1289,1290,1291,1292,1294,1295,1296,1297,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1330,1331,1332,1333,1335,1338,1339,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1370,1371,1372,1388,1389,1390,1391,1392,1393,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1450,1451,1452,1453,1454,1455,1456,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1475,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1503,1504,1505,1506,1510,1514,1515,1516,1517,1518,1519,1520,1521,1526,1527,1528,1529,1530,1531,1532,1548,1552,1553,1554,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1579,1580,1582,1583,1584,1585,1586,1587,1588,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1603,1604,1605,1606,1607,1608,1609,1610,1611,1613,1614,1615,1616,1617,1618,1619,1621,1622,1623,1624,1625,1626,1632,1634,1635,1636,1637,1643,1647,1648,1650,1651,1652,1653,1654,1655,1656,1657,1658,1663,1664,1665,1666,1667,1668,1669,1671,1673,1674,1675,1677,1678,1679,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1697,1698,1699,1700,1701,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1773,1774,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1803,1804,1805,1806,1807,1808,1810,1811,1812,1813,1814,1815,1816,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1959,1960,1962,1963,1964,1965,1966,1968,1969,1970,1971,1972,1973,1974,1975,1976,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2056,2057,2058,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2072,2073,2074,2075,2076,2077,2078,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2155,2156,2157,2158,2159,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2180,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2194,2195,2197,2198,2200,2201,2202,2203,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2434,2435,2436,2437,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2526,2527,2528,2529,2530,2531,2532,2535,2536,2537,2541,2542,2563,2564,2565,2566,2568,2569,2570,2573,2574,2575,2576,2577,2578,2579,2580,2582,2583,2584,2585,2586,2587,2588,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2665,2666,2667,2668,2681,2682,2683,2684,2685,2690,2691,2693,2694,2695,2696,2697,2698,2790,2793,2794,2795,2796,2797,2798,2799,2802,2803,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2933,2937,2939,2940,2941,2942,2943,2944,2966,2976,2979,2980,2981,2982,2983,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3010,3011,3012,3013,3014,3015,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3030,3034,3035,3036,3037,3038,3039,3040,3041,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3055,3056,3057,3058,3059,3060,3061,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3123,3124,3125,3126,3127,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3185,3187,3188,3189,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3217,3218,3219,3220,3221,3222,3223,3224,3225,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3261,3262,3263,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3285,3286,3287,3288,3289,3290,3292,3293,3294,3295,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3341,3342,3343,3344,3345,3346,3347,3348,3349,3620,3621,3622,3623,3624,3625,3626,3627,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3661,3662,3663,3664,3666,3667,3668,3669,3676,3677,3679,3680,3681,3682,3684,3685,3686,3689,3690,3693,3694],"optional":[287,297,301,303,304,305,306,307,308,309,317,326,390,426,438,564,570,611,612,613,614,615,616,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,638,706,709,790,792,877,992,1021,1074,1086,1115,1185,1203,1204,1205,1206,1207,1280,1308,1335,1349,1404,1406,1407,1408,1412,1413,1414,1446,1447,1595,1603,1604,1892,1893,1904,1905,1970,2093,2094,2095,2096,2097,2098,2099,2139,2140,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2325,2335,2376,2541,2576,2606,2633,2643,2648,2691,2895,2907,2908,2909,2911,2912,3011,3014,3015,3023,3024,3055,3063,3143,3153,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3243,3254,3255,3256,3257,3266,3292,3343,3621,3663,3666,3667,3668,3669],"required_bytes":610609152},"arduboy|arduous":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"atari-2600|stella":{"bytes":33793052,"files":[1,2,3,4,5,6,7],"optional":[1,2,3,4,5,6,7],"required_bytes":0},"atari-400-800|atari800":{"bytes":373297,"files":[32,42,43,44,45,48,188,191,192,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,256,684,3665],"optional":[42,43,44,45,48,188,191,192,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,256,684,3665],"required_bytes":2048},"atari-5200|a5200":{"bytes":124928,"files":[32,42,43,44,45,189,190,193,202,203,205,207],"optional":[32,189,190,193],"required_bytes":110592},"atari-7800|prosystem":{"bytes":53208,"files":[35,36,38,185],"optional":[35,36,38,185],"required_bytes":0},"atari-jaguar|virtualjaguar":{"bytes":917504,"files":[47,257,258,1336,1337],"optional":[47,257,258,1336,1337],"required_bytes":0},"atari-lynx|handy":{"bytes":1025,"files":[1256,1421],"optional":[1256],"required_bytes":512},"atari-st|hatari":{"bytes":933888,"files":[1228,3260],"optional":[1228],"required_bytes":196608},"bally-astrocade|mame":{"bytes":20412,"files":[519,520,521],"optional":[520,521],"required_bytes":6800},"capcom-cps1|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps2|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"capcom-cps3|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"casio-pv1000|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"coco|xroar":{"bytes":3331197,"files":[55,56,76,77,373,410,411,412,450,538,540,541,542,543,544,697,714,723,724,747,778,785,803,804,805,806,809,810,811,812,813,814,815,816,817,833,841,845,847,848,849,850,851,852,883,884,933,947,948,949,990,1061,1062,1066,1081,1087,1088,1107,1108,1234,1238,1243,1244,1245,1246,1247,1248,1283,1285,1416,1419,1420,2331,2357,2358,2398,2432,2433,2435,2504,2536,2565,2572,2585,2611,2808,2915,2917,2918,2920,2921,2924,2944,2981,2982,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3155,3622,3624,3675,3678,3679,3680,3682,3689],"optional":[55,56,76,77,410,411,412,540,541,542,544,803,804,833,848,850,852,947,948,1087,1088,1107,1108,1234,2572,3675,3678],"required_bytes":2938825},"coleco-adam|mame":{"bytes":52891,"files":[398],"optional":[],"required_bytes":52891},"colecovision|bluemsx":{"bytes":52590,"files":[50,830,831,832],"optional":[830,832],"required_bytes":36206},"commodore-amiga-cd32|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-amiga|puae":{"bytes":15415966,"files":[46,249,735,736,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,2892,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284],"optional":[249,735,736,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,2892,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284],"required_bytes":524288},"commodore-c64|vice_x64sc":{"bytes":770048,"files":[98,99,100,101,102,1361,1362,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338],"optional":[98,99,100,101,102,1361,1362,3318,3319,3329,3330,3331,3332,3333],"required_bytes":540672},"commodore-cdtv|puae":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-plus4|vice_xplus4":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"commodore-vic20|vice_xvic":{"bytes":24576,"files":[784,1363,3339,3340],"optional":[784,1363,3339,3340],"required_bytes":0},"crvision|jollycv":{"bytes":2048,"files":[662],"optional":[],"required_bytes":2048},"doom|gzdoom":{"bytes":613419140,"files":[397,930,974,975,976,1122,1124,1125,1222,1223,1227,2680,2692,2893,3112,3258],"optional":[397,930,974,975,976,1122,1124,1125,1222,1223,1227,2680,2893,3112,3258],"required_bytes":143312},"dos|dosbox_pure":{"bytes":41236388,"files":[57,58,59,80,167,168,210,211,212,213,214,215,216,217,218,219],"optional":[57,58,59,80,167,168,210,211,212,213,214,215,216,217,218,219],"required_bytes":0},"dragon32|xroar":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"dragon64|xroar":{"bytes":1315508,"files":[373,433,434,435,450,538,558,562,697,714,723,724,758,778,785,809,810,813,841,847,883,884,888,889,890,891,892,894,895,896,897,898,921,922,923,924,925,931,932,977,978,979,981,982,983,986,987,988,989,990,1061,1062,1066,1081,1230,1238,1243,1244,1245,1246,1247,1248,1283,1285,1416,1419,1420,2331,2357,2358,2398,2435,2504,2536,2565,2585,2611,2693,2915,2917,2918,2920,2921,2924,2944,2973,2974,2975,2976,2981,2982,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3155,3622,3624,3679,3680,3682],"optional":[434,758,847,889,890,891,892,895,897,898,922,923,924,925,931,932,977,978,979,988,989,2973,2974,2975],"required_bytes":1016500},"electron|mame":{"bytes":50660,"files":[1032,1033],"optional":[1033],"required_bytes":25571},"emerson-arcadia-2001|amiarcadia":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fairchild-channelf|freechaf":{"bytes":5777,"files":[783,3031,3032,3033],"optional":[],"required_bytes":5777},"famicom|mesen":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"flash|ruffle":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"fm7|mame":{"bytes":178012,"files":[1118,1119,1120],"optional":[1120],"required_bytes":151197},"fmtowns|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"gamate|mame":{"bytes":5072,"files":[1182],"optional":[],"required_bytes":5072},"hartung-game-master|mame":{"bytes":133753522,"files":[373,538,570,697,706,709,714,723,724,778,883,884,899,926,990,1025,1026,1027,1028,1029,1030,1031,1060,1079,1189,1198,1250,1329,1341,1416,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2331,2354,2398,2504,2611,2686,2687,2688,2915,2917,2918,2920,2921,2924,2981,2982,3014,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3186,3190,3257,3621,3680,3682],"optional":[570,706,709,899,1198,1449,1457,1458,1459,1472,1473,1474,1476,1501,1502,1507,1508,1509,1511,1512,1513,1522,1523,1524,1525,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1549,1550,1551,1555,1577,1578,1581,1589,1595,1601,1602,1603,1604,1612,1620,1627,1628,1629,1630,1631,1633,1638,1639,1640,1641,1642,1644,1645,1646,1649,1659,1660,1661,1662,1670,1672,1676,1680,1695,1696,1702,1723,1772,1775,1776,1797,1798,1799,1800,1801,1802,1809,1817,1892,1893,1904,1905,1942,1943,1944,1958,1961,1967,1970,1977,2005,2017,2035,2036,2055,2059,2060,2071,2079,2093,2094,2095,2096,2097,2098,2099,2108,2123,2137,2139,2140,2152,2153,2154,2160,2179,2181,2193,2196,2199,2204,2205,2221,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,3014,3257,3621],"required_bytes":109934054},"intellivision|freeintv":{"bytes":10240,"files":[1082,1210],"optional":[],"required_bytes":10240},"j2me|squirreljme":{"bytes":83146081,"files":[1126,1127,1128,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122],"optional":[3113,3114,3115,3116,3117,3118,3119,3120,3121,3122],"required_bytes":1656124},"lowresnx|lowresnx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"mega-duck|sameduck":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"microsoft-xbox|xemu":{"bytes":3645624,"files":[73,74,75,1015,2326,3660],"optional":[73,74,75,1015,2326,3660],"required_bytes":0},"msx1|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx2|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msxturbor|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"msx|bluemsx":{"bytes":13300736,"files":[40,41,49,54,60,78,79,81,82,92,93,94,95,96,103,105,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,178,179,181,182,183,184,209,242,243,255,1130,1131,1132,1133,1134,1135,1136,1137,1138,2538,2539,2540,2660,3683],"optional":[49,60,78,81,92,94,95,122,123,127,128,129,134,138,139,142,143,144,145,146,147,148,149,150,152,153,154,155,158,159,160,161,162,163,164,165,166,178,179,181,182,183,184,242,243,255,1130,1131,1132,1133,1134,1135,1136,1138,2538,2539,2540,2660,3683],"required_bytes":1152000},"nec-pc-88|quasi88":{"bytes":2508802,"files":[97,104,170,171,172,173,174,175,176,177,947,2438,2439,2440,2441,2442,2443,2444,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845],"optional":[97,104,170,171,172,173,174,175,176,177,947,2440,2441,2442,2833,2834,2835,2838,2839,2840,2841,2842,2843,2844,2845],"required_bytes":245760},"nec-pc-engine-cd|beetle_pce":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nec-pc-engine|beetle_pce":{"bytes":1343488,"files":[1192,3176,3177,3178,3179,3180],"optional":[1192,3176,3177,3178,3180],"required_bytes":262144},"nec-pcfx|beetle_pcfx":{"bytes":4718592,"files":[1178,2628,2629,2630,2631],"optional":[],"required_bytes":4718592},"nec-supergrafx|mednafen_supergrafx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"neogeo|fbneo":{"bytes":2709646,"files":[413,3717],"optional":[413],"required_bytes":1859335},"nintendo-3ds|azahar":{"bytes":6422431,"files":[414,2480,2481,2482,3181,3182,3183,3184,3710,3711,3712,3713,3714,3715,3716],"optional":[2480,2481,2482,3181,3182,3183,3184,3710,3711,3712,3713,3714,3715,3716],"required_bytes":7357},"nintendo-64dd|parallel_n64":{"bytes":4194304,"files":[33],"optional":[],"required_bytes":4194304},"nintendo-64|mupen64plus_next":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-ds|desmume":{"bytes":413696,"files":[652,653,663,664,1117],"optional":[],"required_bytes":413696},"nintendo-fds|mesen":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-gamecube|dolphin":{"bytes":12582912,"files":[85,86,87,966,967,968],"optional":[85,86,87,966,967,968],"required_bytes":0},"nintendo-gamecube|primehack":{"bytes":6291456,"files":[85,86,87],"optional":[85,86,87],"required_bytes":0},"nintendo-gba|mgba":{"bytes":16384,"files":[1187],"optional":[],"required_bytes":16384},"nintendo-gbc|gambatte":{"bytes":1978880,"files":[53,239,240,993,994,995,996,997,998,999,1000,1001,1188,3008,3128,3129,3130,3131],"optional":[],"required_bytes":1978880},"nintendo-gb|gambatte":{"bytes":1976832,"files":[53,239,240,993,994,995,996,997,998,999,1000,1001,1186,3008,3128,3129,3130,3131],"optional":[],"required_bytes":1976832},"nintendo-nes|mesen":{"bytes":1280062,"files":[169,180,244,952],"optional":[169,180,244,952],"required_bytes":0},"nintendo-pokemon-mini|pokemini":{"bytes":4096,"files":[649],"optional":[649],"required_bytes":0},"nintendo-satellaview|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-sgb|mesen-s":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-snes|snes9x":{"bytes":5289728,"files":[51,52,53,239,240,241,887,993,994,995,996,997,998,999,1000,1001,3005,3006,3007,3008,3009,3042,3128,3129,3130,3131,3132],"optional":[51,52,53,241],"required_bytes":1881856},"nintendo-sufami-turbo|snes9x":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-switch|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-virtualboy|beetle_vb":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wiiu|cemu":{"bytes":156415016,"files":[61,62,63,64,65,66,67,68,69,70,71,72,731,732,733,734,765,1369,2581,2875,2876,2877,2878,2984,3016,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779],"optional":[61,62,63,64,66,67,68,69,70,71,72,731,732,733,734,2581,2875,2876,2877,2878,2984,3016,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779],"required_bytes":1348521},"nintendo-wii|dolphin":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"nintendo-wii|primehack":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"odyssey2|o2em":{"bytes":1606321,"files":[705,1179,1340,2567,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619],"optional":[1179,1340],"required_bytes":1604273},"olivetti-pc128|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"openbor|openbor":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"oric|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"palm-os|mu":{"bytes":40108544,"files":[676,2589,2590,2591,2592],"optional":[676,2589,2591,2592],"required_bytes":4194304},"panasonic-3do|opera":{"bytes":51909016,"files":[28,29,373,428,429,430,431,432,455,512,513,528,538,681,697,714,723,724,778,875,883,884,990,1090,1091,1181,1199,1202,1211,1255,1328,1332,1390,1416,1445,2323,2331,2398,2504,2571,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2611,2915,2917,2918,2920,2921,2924,2933,2935,2981,2982,2998,3017,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3142,3189,3261,3300,3680,3682],"optional":[28,1199,2571,2594,2595,2596,2597,2598,2601,2602,2935],"required_bytes":41816472},"pc-98|np2kai":{"bytes":2453192,"files":[18,19,20,21,22,23,83,650,654,900,1121,1334,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,3054],"optional":[18,19,20,21,22,23,654,900,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562],"required_bytes":960574},"philips-cdi|same_cdi":{"bytes":41795490,"files":[373,428,429,431,432,455,512,513,528,538,681,697,714,723,724,752,753,754,755,756,757,778,875,883,884,990,1090,1091,1181,1202,1211,1255,1328,1332,1390,1416,1445,2323,2331,2398,2504,2611,2661,2915,2917,2918,2920,2921,2924,2929,2930,2931,2932,2933,2981,2982,2998,3017,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3142,3189,3261,3300,3680,3682,3687,3688,3691,3692],"optional":[752,753,754,755,756,757,2661,2929,2930,2932,3687,3688,3691,3692],"required_bytes":37095495},"philips-videopac|o2em":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"pico8|lexaloffle":{"bytes":28859725,"files":[2662,2663,2664],"optional":[],"required_bytes":28859725},"quake|tyrquake":{"bytes":159899459,"files":[1281,2846,2847,2848],"optional":[2847,2848],"required_bytes":66916006},"rpgmaker|easyrpg":{"bytes":148398498,"files":[1009,3659],"optional":[1009,3659],"required_bytes":0},"sammy-atomiswave|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"scummvm|scummvm":{"bytes":81083844,"files":[2967,2968,2969,2970,2971],"optional":[2968,2969,2970,2971],"required_bytes":79379908},"scv|mame":{"bytes":94685913,"files":[373,538,570,697,706,709,714,723,724,778,883,884,990,1416,1448,1450,1451,1452,1453,1454,1455,1456,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1475,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1503,1504,1505,1506,1510,1514,1515,1516,1517,1518,1519,1520,1521,1526,1527,1528,1529,1530,1531,1532,1548,1552,1553,1554,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1579,1580,1582,1583,1584,1585,1586,1587,1588,1590,1591,1592,1593,1594,1596,1597,1598,1599,1600,1605,1606,1607,1608,1609,1610,1611,1613,1614,1615,1616,1617,1618,1619,1621,1622,1623,1624,1625,1626,1632,1634,1635,1636,1637,1643,1647,1648,1650,1651,1652,1653,1654,1655,1656,1657,1658,1663,1664,1665,1666,1667,1668,1669,1671,1673,1674,1675,1677,1678,1679,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1697,1698,1699,1700,1701,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1773,1774,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1803,1804,1805,1806,1807,1808,1810,1811,1812,1813,1814,1815,1816,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1959,1960,1962,1963,1964,1965,1966,1968,1969,1971,1972,1973,1974,1975,1976,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2072,2073,2074,2075,2076,2077,2078,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2100,2101,2102,2103,2104,2105,2106,2107,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2138,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2155,2156,2157,2158,2159,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2180,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2194,2195,2197,2198,2200,2201,2202,2203,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2331,2398,2504,2611,2915,2917,2918,2920,2921,2924,2972,2981,2982,3014,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3257,3296,3621,3680,3682],"optional":[570,706,709,2055,2972,3014,3257,3296,3621],"required_bytes":94599593},"sega-32x|picodrive":{"bytes":19695,"files":[24,25,26,737],"optional":[24,25,26,737],"required_bytes":0},"sega-dreamcast|flycast":{"bytes":27286439,"files":[905,906,907,908,909,910,911,912,913,914,915,916],"optional":[909,915],"required_bytes":20132866},"sega-gamegear|gearsystem":{"bytes":1024,"files":[648],"optional":[648],"required_bytes":0},"sega-gamegear|genesis_plus_gx":{"bytes":1024,"files":[648],"optional":[648],"required_bytes":0},"sega-genesis|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-mastersystem|gearsystem":{"bytes":16384,"files":[651,659],"optional":[],"required_bytes":16384},"sega-mastersystem|genesis_plus_gx":{"bytes":32768,"files":[651,658,659,661],"optional":[658,661],"required_bytes":16384},"sega-megacd|genesis_plus_gx":{"bytes":393216,"files":[655,656,657],"optional":[],"required_bytes":393216},"sega-megadrive|genesis_plus_gx":{"bytes":2444622,"files":[511,660,1195,2891,3028,3029],"optional":[],"required_bytes":2444622},"sega-model2|mame":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomi2|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomigd|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-naomi|flycast":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-saturn|beetle_saturn":{"bytes":12398703,"files":[1252,2368,2379,2380,2381,2382,2936,2938,2985,2987,2988,2989,3141,3628],"optional":[1252,2368,2380,2936,2987,2988,3628],"required_bytes":8990831},"sega-sg1000|gearsystem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-sg1000|genesis_plus_gx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sega-stv|kronos":{"bytes":3455065,"files":[1394],"optional":[],"required_bytes":3455065},"sega-triforce|dolphin":{"bytes":452637838,"files":[84,88,89,90,91,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,245,250,251,252,253,254,373,428,429,431,432,455,512,513,528,538,681,697,714,723,724,778,875,883,884,969,970,971,972,973,990,1090,1091,1181,1202,1208,1211,1254,1255,1328,1332,1390,1416,1445,2323,2331,2398,2504,2611,2915,2917,2918,2920,2921,2924,2933,2981,2982,2996,2998,3017,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3142,3189,3261,3265,3300,3680,3682,3702,3703,3704,3705,3706,3707,3708,3718,3719,3720,3721,3722,3723,3724],"optional":[84,88,89,90,91,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,250,251,252,253,254,969,970,971,972,3702,3703,3704,3705,3706,3707,3708,3718,3719,3720,3721,3722,3723,3724],"required_bytes":48339661},"sharp-x1|x1":{"bytes":349184,"files":[3670,3671,3672,3673,3674],"optional":[3670,3671,3672,3673,3674],"required_bytes":0},"sharp-x68000|px68k":{"bytes":2752512,"files":[781,1298,1299,1300,1301,1302,1364,1365,1366,1367,1368],"optional":[1299,1300,1301,1302,1366,1367,1368],"required_bytes":1835008},"sinclair-zx-spectrum|fuse":{"bytes":996720,"files":[9,10,11,12,14,15,16,17,946,950,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1197,1286,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2977,2978,3062,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3264,3695,3696],"optional":[9,10,11,12,14,15,16,17,946,950,1197,1286,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2977,2978,3062,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3264,3695,3696],"required_bytes":514048},"sinclair-zx81|81":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"snk-neogeo-cd|neocd":{"bytes":11215607,"files":[8,1129,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,3259,3291],"optional":[8,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,3291],"required_bytes":5317367},"snk-ngpc|beetle_ngp":{"bytes":65536,"files":[2534],"optional":[2534],"required_bytes":0},"snk-ngp|beetle_ngp":{"bytes":65536,"files":[2533],"optional":[2533],"required_bytes":0},"solarus|solarus":{"bytes":600521,"files":[1184],"optional":[1184],"required_bytes":0},"sony-playstation-2|pcsx2":{"bytes":408963140,"files":[220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,1016,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2789,2791,2792,2954,2956],"optional":[230,1016,2777],"required_bytes":408953860},"sony-playstation-3|":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"sony-playstation-vita|vita3k":{"bytes":190612992,"files":[2800,2801],"optional":[2800],"required_bytes":133834240},"sony-playstation|swanstation":{"bytes":11010048,"files":[2699,2804,2945,2946,2947,2948,2949,2950,2951,2952,2953,2955,2957,2958,2959,2960,2961,2962,2963,2964,2965],"optional":[],"required_bytes":11010048},"sony-psp|ppsspp":{"bytes":666530,"files":[2689],"optional":[2689],"required_bytes":0},"spectravideo|bluemsx":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"supracan|mame":{"bytes":133504188,"files":[926,1025,1026,1027,1028,1029,1030,1031,1060,1079,1189,1250,1329,1341,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2354,2686,2687,2688,3146,3186,3190,3290],"optional":[1449,1457,1458,1459,1472,1473,1474,1476,1501,1502,1507,1508,1509,1511,1512,1513,1522,1523,1524,1525,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1549,1550,1551,1555,1577,1578,1581,1589,1595,1601,1602,1603,1604,1612,1620,1627,1628,1629,1630,1631,1633,1638,1639,1640,1641,1642,1644,1645,1646,1649,1659,1660,1661,1662,1670,1672,1676,1680,1695,1696,1702,1723,1772,1775,1776,1797,1798,1799,1800,1801,1802,1809,1817,1892,1893,1904,1905,1942,1943,1944,1958,1961,1967,1970,1977,2005,2017,2035,2036,2055,2059,2060,2071,2079,2093,2094,2095,2096,2097,2098,2099,2108,2123,2137,2139,2140,2152,2153,2154,2160,2179,2181,2193,2196,2199,2204,2205,2221,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,3146,3290],"required_bytes":109751467},"thomson-mo5|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-mo6|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to770|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to7|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8d|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to8|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9plus|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"thomson-to9|theodore":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"ti99|mame":{"bytes":21377,"files":[3226],"optional":[],"required_bytes":21377},"tic80|tic80":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"tiger-game-com|mame":{"bytes":134159118,"files":[373,538,570,697,706,709,714,723,724,778,883,884,926,990,1025,1026,1027,1028,1029,1030,1031,1060,1079,1089,1183,1189,1250,1293,1329,1341,1416,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2331,2354,2398,2504,2611,2686,2687,2688,2915,2917,2918,2920,2921,2924,2981,2982,3014,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3186,3190,3257,3621,3680,3682],"optional":[570,706,709,1089,1183,1293,1449,1457,1458,1459,1472,1473,1474,1476,1501,1502,1507,1508,1509,1511,1512,1513,1522,1523,1524,1525,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1549,1550,1551,1555,1577,1578,1581,1589,1595,1601,1602,1603,1604,1612,1620,1627,1628,1629,1630,1631,1633,1638,1639,1640,1641,1642,1644,1645,1646,1649,1659,1660,1661,1662,1670,1672,1676,1680,1695,1696,1702,1723,1772,1775,1776,1797,1798,1799,1800,1801,1802,1809,1817,1892,1893,1904,1905,1942,1943,1944,1958,1961,1967,1970,1977,2005,2017,2035,2036,2055,2059,2060,2071,2079,2093,2094,2095,2096,2097,2098,2099,2108,2123,2137,2139,2140,2152,2153,2154,2160,2179,2181,2193,2196,2199,2204,2205,2221,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,3014,3257,3621],"required_bytes":109934054},"uzebox|uzem":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"vectrex|vecx":{"bytes":194875,"files":[246,247,373,538,697,714,723,724,778,883,884,990,1416,2331,2398,2504,2611,2915,2917,2918,2920,2921,2924,2981,2982,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3680,3682],"optional":[246,247],"required_bytes":182587},"vircon32|vircon32":{"bytes":1073060,"files":[248],"optional":[248],"required_bytes":0},"vtech-vsmile|mame":{"bytes":106388256,"files":[373,538,570,697,706,709,714,723,724,778,883,884,990,1416,1448,1450,1451,1452,1453,1454,1455,1456,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1475,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1503,1504,1505,1506,1510,1514,1515,1516,1517,1518,1519,1520,1521,1526,1527,1528,1529,1530,1531,1532,1548,1552,1553,1554,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1579,1580,1582,1583,1584,1585,1586,1587,1588,1590,1591,1592,1593,1594,1596,1597,1598,1599,1600,1605,1606,1607,1608,1609,1610,1611,1613,1614,1615,1616,1617,1618,1619,1621,1622,1623,1624,1625,1626,1632,1634,1635,1636,1637,1643,1647,1648,1650,1651,1652,1653,1654,1655,1656,1657,1658,1663,1664,1665,1666,1667,1668,1669,1671,1673,1674,1675,1677,1678,1679,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1697,1698,1699,1700,1701,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1773,1774,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1803,1804,1805,1806,1807,1808,1810,1811,1812,1813,1814,1815,1816,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1959,1960,1962,1963,1964,1965,1966,1968,1969,1971,1972,1973,1974,1975,1976,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2056,2057,2058,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2072,2073,2074,2075,2076,2077,2078,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2100,2101,2102,2103,2104,2105,2106,2107,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2138,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2155,2156,2157,2158,2159,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2180,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2331,2398,2504,2611,2915,2917,2918,2920,2921,2924,2981,2982,3014,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3257,3621,3629,3630,3631,3632,3680,3682],"optional":[570,706,709,2196,2199,3014,3257,3621,3629,3630,3631,3632],"required_bytes":94599593},"watara-supervision|potator":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wolfenstein3d|ecwolf":{"bytes":178755,"files":[1014],"optional":[],"required_bytes":178755},"wonderswan-color|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"wonderswan|beetle_wswan":{"bytes":0,"files":[],"optional":[],"required_bytes":0},"zmachine|mojozork":{"bytes":0,"files":[],"optional":[],"required_bytes":0}}}
diff --git a/install/games/index.json b/install/games/index.json
index d031f8768..a467ce605 100644
--- a/install/games/index.json
+++ b/install/games/index.json
@@ -1 +1 @@
-{"arcade":{"fbneo":{"file":"arcade/fbneo.json","gzip_size":115955,"sha256":"88961c9a6be804772baa767f6ee3a9162478c30c60fe55c8363d8fe4fbc909da","size":423362},"flycast":{"file":"arcade/flycast.json","gzip_size":1841,"sha256":"957189a6e993fda08e21c90ffc6ad94aed9ca9e6dd9ed8c7724e29db036791cb","size":5441},"mame":{"file":"arcade/mame.json","gzip_size":154527,"sha256":"b12010301293a218ecfac45706d81a26c3ac0c27eebeca7409bc8f6ce0163e9e","size":604648},"mame0258":{"file":"arcade/mame0258.json","gzip_size":141151,"sha256":"7ecff1979ed2ac123ea3ba4825dde6e2c31906415165fabefc9af93fa48a6de4","size":556059},"mame0278":{"file":"arcade/mame0278.json","gzip_size":148595,"sha256":"7881e3516f451ec83e886aaf41ebac9d60f497e1f954f49749d52890d7955cbf","size":582797},"mame2000":{"file":"arcade/mame2000.json","gzip_size":8624,"sha256":"f0d69b0872ecfc2845eeb7304543e5b17c11db82060b5514c206b6962ed08263","size":23316},"mame2003":{"file":"arcade/mame2003.json","gzip_size":17456,"sha256":"3b44e2a92c80a8f104b7781fcc1c776d025ad2cf4986638efa3ea041baa9a56d","size":48929},"mame2003_plus":{"file":"arcade/mame2003_plus.json","gzip_size":21077,"sha256":"2857283556fa49c20d8160ed113465bf0c2e643ed0b8acd2d38266a78be8e25e","size":62373},"mame2010":{"file":"arcade/mame2010.json","gzip_size":30869,"sha256":"50b1b381b4b07463f69f1f4c512dd1c98a78d4d0e9c3aeaf49b7b1b007b42152","size":96528},"mame2015":{"file":"arcade/mame2015.json","gzip_size":86990,"sha256":"afeb8c32f651421f74c6de057b0c0b837acd14c533b5160bb31f4411e0afffec","size":360117},"mame2016":{"file":"arcade/mame2016.json","gzip_size":101249,"sha256":"1f75147977d9d082a38b8f8e47a02b301f3d6e6db97c9b9282f3e7f27f26ee47","size":406190}},"containers":{"7z":{"description":"Per-file CRCs and sizes sit in the header at the end of the archive, LZMA-compressed by default (kEncodedHeader). One LZMA decode of the header, independent of the archive size, gives them. Python's lzma is an optional module.","re_read":true,"signature":{"bytes_hex":"377abcaf271c","offset":0},"source_ref":"ip7z/7zip@b88c6bc0 DOC/7zFormat.txt:171-189, DOC/7zFormat.txt:318-334, CPP/7zip/Archive/7z/7zHandlerOut.cpp:859"},"cd-sector":{"description":"User data of a CD sector. In a 2048-byte image (.iso) sector N starts at N * 2048. In a raw 2352-byte image it starts at N * 2352 plus 16 for Mode 1 and plus 24 for Mode 2 Form 1 (12 sync bytes, a 4-byte header, and for Mode 2 an 8-byte subheader).","re_read":true,"sector_size":{"iso":2048,"raw":2352},"source_ref":"stenzek/duckstation@526b4a12 src/util/iso_reader.cpp:157-171, src/util/cd_image.h:28-34","user_data_offset":{"mode1":16,"mode2":24}},"chd-v5":{"description":"MAME compressed hunks, big-endian. The header holds sizes, codecs and hashes only, never the system or the region. The overall SHA-1 is what MAME software lists record. Neither SHA-1 equals a Redump track hash: chdman hashes 2448-byte frames (subcode included, zero-filled), pads each track to 4 frames and byte-swaps audio, all tracks in one stream.","fields":{"compressors":{"encoding":"fourcc4","length":16,"offset":16},"header_length":{"encoding":"u32be","length":4,"offset":8,"value":124},"hunk_bytes":{"encoding":"u32be","length":4,"offset":56},"logical_bytes":{"encoding":"u64be","length":8,"offset":32},"map_offset":{"encoding":"u64be","length":8,"offset":40},"metadata_offset":{"encoding":"u64be","length":8,"offset":48},"overall_sha1":{"encoding":"hex","length":20,"offset":84},"parent_sha1":{"encoding":"hex","length":20,"offset":104},"raw_sha1":{"encoding":"hex","length":20,"offset":64},"unit_bytes":{"encoding":"u32be","length":4,"offset":60},"version":{"encoding":"u32be","length":4,"offset":12,"value":5}},"magic":{"bytes":"MComprHD","offset":0},"media_tags":{"CHCD":"cd","CHGD":"gd-rom","CHGT":"gd-rom","CHT2":"cd","CHTR":"cd","DVD ":"dvd","GDDD":"hard-disk"},"metadata_entry":{"description":"16-byte entry header, payload follows. Linked list from metadata_offset.","flags":{"encoding":"u8","length":1,"offset":4},"length":{"encoding":"u24be","length":3,"offset":5},"next":{"encoding":"u64be","length":8,"offset":8},"tag":{"encoding":"ascii","length":4,"offset":0}},"re_read":true,"source_ref":"mamedev/mame@f34f0250 src/lib/util/chd.h:148-162, src/lib/util/chd.cpp:2021-2061, src/lib/util/chd.cpp:2822-2831, src/lib/util/chd.h:212-235, src/lib/util/chd.cpp:1709-1749, src/tools/chdman.cpp:443-445, src/tools/chdman.cpp:2195-2203, src/lib/util/cdrom.cpp:2669-2672, src/emu/romload.cpp:1211"},"gamecube-disc":{"description":"Where disc offset 0 sits inside each container Dolphin opens.","formats":{"ciso":{"disc_header_at":32768,"magic":"CISO"},"gcz":{"disc_header_at":null,"magic_u32le":2970337281,"note":"block 0 is zlib unless bit 63 of its pointer is set"},"iso":{"disc_header_at":0,"magic":null},"rvz":{"disc_header_at":88,"magic":"RVZ\u0001","note":"first 0x80 disc bytes copied into header 2"},"wbfs":{"disc_header_at":null,"magic":"WBFS","note":"disc offset 0 at wlba[0] << wbfs_sector_shift"},"wia":{"disc_header_at":88,"magic":"WIA\u0001","note":"first 0x80 disc bytes copied into header 2"}},"re_read":true,"source_ref":"dolphin-emu/dolphin@0d93fc03 Source/Core/DiscIO/WIABlob.h:80-119, Source/Core/DiscIO/WIABlob.cpp:320-330, Source/Core/DiscIO/CISOBlob.cpp:66-69, Source/Core/DiscIO/CompressedBlob.cpp:140-150, Source/Core/DiscIO/WbfsBlob.cpp:148-155"},"iso9660":{"description":"Primary volume descriptor in sector 16 ('CD001' at offset 1), root directory record at PVD offset 156 (34 bytes). A file is found by name in the root directory, with the ';1' version suffix.","pvd_sector":16,"re_read":true,"root_record_offset":156,"source_ref":"stenzek/duckstation@526b4a12 src/util/iso_reader.cpp:68-90, src/util/iso_reader.h:60-99"},"zip":{"description":"The central directory gives each member's CRC-32 (offset 16) and uncompressed size (offset 24) without inflating. Python's zipfile reads it on open (ZipInfo.CRC, ZipInfo.file_size).","re_read":true,"source_ref":"python/cpython@fa919fdf Lib/zipfile.py:99-115, Lib/zipfile.py:1293-1347"}},"data_version":"d3665abc4702ae22","fallback":{"amberelec":{"file":"fallback/amberelec.json","gzip_size":10509,"sha256":"67db1b95497f894a997f9fd3a5bd7ee4f6866fb31ad89f573c4351af4df3fd87","size":48420},"batocera":{"file":"fallback/batocera.json","gzip_size":42010,"sha256":"6ce9e1d47d35c4a61f821a3088baeb6d8f5f2fdab8b1f624f9e5df3e42069017","size":308403},"bizhawk":{"file":"fallback/bizhawk.json","gzip_size":1944,"sha256":"152b14f3aff69714698a58837d6331ebcbcd3aaaa5f62939b9c743e535a319f4","size":7320},"emudeck":{"file":"fallback/emudeck.json","gzip_size":26125,"sha256":"8606f6a92147b42db10855a3c208344cc858f5914fa770c8f81cbb7d4cc66a4c","size":109272},"emuelec":{"file":"fallback/emuelec.json","gzip_size":15046,"sha256":"e77c87df67e6536362f09257199b500e055046f91b3ced09c2baf569a7d8785c","size":69084},"knulli":{"file":"fallback/knulli.json","gzip_size":39564,"sha256":"33a3953252a100066b0789bc0f81909b4c0fc0df21a4c3d17efed9728c1c30e7","size":266492},"minui":{"file":"fallback/minui.json","gzip_size":701,"sha256":"d68b30917db60263e57331271ebc33d00520dcbc15cdcaba8ccaf2901be2c870","size":2761},"misterfpga":{"file":"fallback/misterfpga.json","gzip_size":1898,"sha256":"b8f457378063d2f9b4010c2fefc21561df71e2e2d06f4ad1a7d945f4ad0a6f55","size":9569},"myminui":{"file":"fallback/myminui.json","gzip_size":1887,"sha256":"029242a5d03083b697c3c801f5a7f86687d62432fa925e0ec1c4759c3e3c20a5","size":7993},"nextui":{"file":"fallback/nextui.json","gzip_size":3088,"sha256":"3c28a4e3d67d5e5b653303419423c4326845b7e8b047c5f4ee1fdf44da0f5faf","size":15502},"recalbox":{"file":"fallback/recalbox.json","gzip_size":13622,"sha256":"2a3ff14a44a8247cb02ac012d6da69231d7629683962fc8878240bcb16896cd2","size":61681},"retroarch":{"file":"fallback/retroarch.json","gzip_size":44967,"sha256":"3e47ced745261b6b5ae30318e0b8fd5c709cc17096c5737276d0effee5406b74","size":217221},"retrobat":{"file":"fallback/retrobat.json","gzip_size":32746,"sha256":"3bd858147ab94890d7b4f7a8aab31183e0b3b7e22483cec9233cbd31ebb13023","size":138983},"retrodeck":{"file":"fallback/retrodeck.json","gzip_size":45842,"sha256":"cd2ddace7a91c25c867af4cb5a55bc7ff8d02c756c71c842bfddf53989689b86","size":235806},"retropie":{"file":"fallback/retropie.json","gzip_size":36894,"sha256":"6546b9111388b3e2e63598343eb4b39e840694dd0c77b8eda09e540db6ba026b","size":151630},"rocknix":{"file":"fallback/rocknix.json","gzip_size":9274,"sha256":"83a59961c7e5869fda2444f96870591dcf576f764d58f7bc5fe5e329e68a15b1","size":38952},"romm":{"file":"fallback/romm.json","gzip_size":6111,"sha256":"e4009ba31a3a5e08d7cf0c6cfcdfaa0e704faa19460d8e1c0fc169b745a4a15e","size":27444}},"folders":{"240ptestsuite":["nintendo-fds","nintendo-nes"],"2600":["atari-2600"],"2ship":["2ship"],"32x":["sega-32x"],"3d0":["panasonic-3do"],"3do":["panasonic-3do"],"3ds":["nintendo-3ds"],"5200":["atari-5200"],"64":["nintendo-64"],"64dd":["nintendo-64","nintendo-64dd"],"7800":["atari-7800"],"800":["atari-400-800"],"a2600":["atari-2600"],"a5200":["atari-5200"],"a7800":["atari-7800"],"a800":["atari-400-800"],"acclaim-zn1":["acclaim-zn1"],"acorn-archimedes":["acorn-archimedes"],"acorn-bbc-micro":["acorn-bbc-micro"],"acpc":["amstrad-cpc"],"actionmax":["arcade-laserdisc"],"adam":["coleco-adam"],"advision":["entex-advision"],"advmame":["arcade"],"agb":["nintendo-gba"],"ags":["ags"],"amiga":["commodore-amiga"],"amiga (puae)":["commodore-amiga","commodore-amiga-cd32","commodore-cdtv"],"amiga-cd32":["commodore-amiga-cd32"],"amiga1200":["commodore-amiga"],"amiga4000":["commodore-amiga"],"amiga500":["commodore-amiga"],"amiga600":["commodore-amiga"],"amigacd32":["commodore-amiga","commodore-amiga-cd32"],"amigacdtv":["commodore-amiga"],"amstrad":["amstrad-cpc"],"amstrad cpc (cpc)":["amstrad-cpc"],"amstrad-cpc":["amstrad-cpc"],"amstradcpc":["amstrad-cpc"],"amstradgx4000":["amstrad-cpc"],"apf-m1000":["apf-m1000"],"apfm1000":["apf-m1000"],"apple":["apple2"],"apple ii":["apple-ii"],"apple-ii":["apple-ii"],"apple-iigs":["apple-iigs"],"apple-ios":["apple-ios"],"apple-macintosh":["apple-macintosh"],"apple-macintosh-ii":["apple-macintosh-ii"],"apple2":["apple2"],"apple2gs":["apple-iigs"],"applemacintosh":["apple-macintosh"],"aquaplus-piece":["aquaplus-piece"],"aquarius":["mattel-aquarius"],"arcade":["arcade","capcom-cps1","capcom-cps2","capcom-cps3"],"arcade (mame)":["arcade"],"arcade-laserdisc":["arcade-laserdisc"],"arcadeatomiswave":["sammy-atomiswave"],"arcadehbmame":["arcade"],"arcadenaomi":["sammy-atomiswave"],"arcadeneogeo":["neogeo"],"arcadeneogeocd":["snk-neogeo-cd"],"arcadesegaatomiswave":["sammy-atomiswave"],"arcadeseganaomi":["sammy-atomiswave"],"arcadesnk":["neogeo"],"arcadesnkneogeo":["neogeo"],"arcadevertical":["arcade"],"arcadia":["emerson-arcadia-2001"],"arcatomiswave":["sammy-atomiswave"],"archimedes":["acorn-archimedes"],"arcnaomi":["sammy-atomiswave"],"arcneogeo":["neogeo"],"arcneogeocd":["snk-neogeo-cd"],"arcsegaatomiswave":["sammy-atomiswave"],"arcseganaomi":["sammy-atomiswave"],"arduboy":["arduboy"],"ast":["atari-st"],"aste":["atari-st"],"astrocade":["bally-astrocade"],"astrocde":["bally-astrocade"],"atari":["atari-2600"],"atari 2600 (a2600)":["atari-2600"],"atari 5200 (a5200)":["atari-5200"],"atari 7800":["atari-7800"],"atari 7800 (a7800)":["atari-7800"],"atari jaguar":["atari-jaguar"],"atari lynx (lynx)":["atari-lynx"],"atari st":["atari-st"],"atari-2600":["atari-2600"],"atari-2600-plus":["atari-2600"],"atari-400-800":["atari-400-800"],"atari-5200":["atari-5200"],"atari-7800":["atari-7800"],"atari-jaguar":["atari-jaguar"],"atari-jaguarcd":["atari-jaguarcd"],"atari-lynx":["atari-lynx"],"atari-lynx-mkii":["atari-lynx"],"atari-st":["atari-st"],"atari-zn1":["atari-zn1"],"atari2600":["atari-2600"],"atari5200":["atari-5200"],"atari5200 (a5200)":["atari-5200"],"atari7800":["atari-7800"],"atari7800 (a7800)":["atari-7800"],"atari800":["atari-400-800"],"atari8bit":["atari-400-800"],"atarifalcon":["atari-st"],"atarijaguar":["atari-jaguar"],"atarijaguarcd":["atari-jaguar","atari-jaguarcd"],"atarilynx":["atari-lynx"],"atarist":["atari-st"],"atariste":["atari-st"],"ataritt":["atari-st"],"atarixe":["atari-400-800"],"atarixegs":["xegs"],"atlus-zn1":["atlus-zn1"],"atom":["atom"],"atomiswave":["sammy-atomiswave","sega-dreamcast-arcade"],"aw":["sammy-atomiswave"],"bally-astrocade":["bally-astrocade"],"bandai-rx78":["bandai-rx78"],"bandai-wswan":["bandai-wswan"],"bandai-wswanc":["bandai-wswanc"],"bandaiwonderswan":["wonderswan"],"bandaiwonderswancolor":["wonderswan"],"bbc":["acorn-bbc-micro"],"bbcmicro":["acorn-bbc-micro"],"bbk":["bbk-longman-4980","bbk-longman-4988"],"bbk-longman-4980":["bbk-longman-4980"],"bbk-longman-4988":["bbk-longman-4988"],"beena":["sega-beena"],"bennugd":["bennugd"],"bermuda-syndrome":["bermuda-syndrome"],"bgb":["game-boy-color"],"bk":["elektronika-bk"],"blake-stone":["blake-stone"],"blood":["blood"],"bshift":["bshift"],"bstone":["blake-stone"],"bsx":["nintendo-satellaview"],"bsyndrome":["bermuda-syndrome"],"build":["blood","duke3d","exhumed","nam","powerslave","redneck","shadow-warrior","ww2gi"],"bws":["wonderswan"],"bwsc":["wonderswan"],"c-plus-4":["commodore-plus4"],"c128":["commodore-c128"],"c16":["commodore-plus4"],"c20":["commodore-vic20"],"c64":["commodore-c64"],"caesar3":["caesar3"],"camplynx":["camplynx"],"cannonball":["sega-outrun"],"capcom-cps1":["capcom-cps1"],"capcom-cps2":["capcom-cps2"],"capcom-cps3":["capcom-cps3"],"capcom-zn1":["capcom-zn1"],"capcom-zn2":["capcom-zn2"],"capcomcps1":["capcom-cps1"],"capcomcps2":["capcom-cps2"],"capcomcps3":["capcom-cps3"],"casio-loopy":["casio-loopy"],"casio-pv1000":["casio-pv1000"],"casio-pv2000":["casio-pv2000"],"casio_pv-1000":["casio-pv1000"],"casio_pv-2000":["casio-pv2000"],"casioloopy":["casio-loopy"],"cassettevision":["epochcv"],"catacomb":["catacomb-3d","catacomb-adventure"],"catacomb-3d":["catacomb-3d"],"catacomb-adventure":["catacomb-adventure"],"cave-story":["cave-story"],"cavestory":["cave-story"],"cbm-ii":["commodore-cbm-ii"],"cbmii":["commodore-cbm-ii"],"cd-i":["philips-cdi"],"cdi":["philips-cdi"],"cdimono1":["philips-cdi"],"cdtv":["commodore-amiga","commodore-cdtv"],"cgb":["nintendo-gbc"],"cgenie":["cgenie"],"cgenius":["commander-keen"],"channel f":["fairchild-channelf"],"channelf":["fairchild-channelf"],"chex":["chex"],"chf":["fairchild-channelf"],"chihiro":["sega-chihiro"],"chip-8":["chip8"],"chip8":["chip8"],"chipeight":["chip8"],"coco":["coco"],"coco3":["coco","coco3"],"coleco":["colecovision"],"coleco vision":["colecovision"],"coleco-adam":["coleco-adam"],"colecovision":["colecovision"],"colecovision (coleco)":["colecovision"],"commander-keen":["commander-keen"],"commanderx16":["commanderx16"],"commmodore-128":["commodore-c128"],"commodore":["commodore-c64"],"commodore 128 (c128)":["commodore-c128"],"commodore 64 (c64)":["commodore-c64"],"commodore pet (pet)":["commodore-pet"],"commodore plus4 (plus4)":["commodore-plus4"],"commodore vic20 (vic)":["commodore-vic20"],"commodore-64c":["commodore-c64"],"commodore-amiga":["commodore-amiga"],"commodore-amiga-cd32":["commodore-amiga-cd32"],"commodore-c128":["commodore-c128"],"commodore-c64":["commodore-c64"],"commodore-cbm-ii":["commodore-cbm-ii"],"commodore-cdtv":["commodore-cdtv"],"commodore-pet":["commodore-pet"],"commodore-plus4":["commodore-plus4"],"commodore-vic20":["commodore-vic20"],"commodore128":["commodore-c128"],"commodore64":["commodore-c64"],"commodoreamiga":["commodore-amiga"],"commodorec128":["commodore-c128"],"commodorec64":["commodore-c64"],"commodorecbmii":["commodore-cbm-ii"],"commodorepet":["commodore-pet"],"commodoreplus4":["commodore-plus4"],"commodorevic20":["commodore-vic20"],"corsixth":["theme-hospital"],"cougarboy":["mega-duck"],"cpc":["amstrad-cpc"],"cpet":["commodore-pet"],"cplus4":["commodore-plus4"],"cps":["arcade"],"cps1":["arcade","capcom-cps1"],"cps2":["arcade","capcom-cps2"],"cps3":["arcade","capcom-cps3"],"creativision":["crvision"],"crvision":["crvision"],"cstrike":["cstrike"],"cv":["colecovision"],"czero":["czero"],"czeror":["czeror"],"daphne":["arcade-laserdisc"],"dark-forces":["dark-forces"],"dark-forces-ii":["dark-forces-ii"],"dc":["sega-dreamcast"],"descent":["descent"],"descent2":["descent2"],"devilutionx":["diablo"],"diablo":["diablo"],"dice":["discrete-arcade"],"dinothawr":["dinothawr"],"discrete-arcade":["discrete-arcade"],"disksystem":["nintendo-fds"],"dmc":["dmc"],"dmg":["game-boy","nintendo-gb"],"doom":["doom"],"doom (doom)":["doom"],"doom (prboom)":["doom","heretic"],"doom3":["doom3"],"dos":["dos"],"dosbox":["dos"],"dragon":["coco","dragon64"],"dragon32":["coco","dragon32"],"dragon64":["coco","dragon64"],"dreamcast":["sega-dreamcast"],"dreamm":["dos","fmtowns","ibm-pc","tandy-1000"],"droidworks":["droidworks"],"ds":["nintendo-ds"],"dsi":["nintendo-ds","nintendo-dsi"],"duke3d":["duke3d"],"dusklight":["dusklight"],"dxx-rebirth":["descent","descent2"],"easyrpg":["rpgmaker"],"ecwolf":["wolfenstein3d"],"eduke32":["duke3d"],"eighthundred":["atari-400-800"],"eighting-zn1":["eighting-zn1"],"electron":["electron"],"elektor-tv-games-computer":["elektor-tv-games-computer"],"elektronika":["elektronika-bk"],"elektronika-bk":["elektronika-bk"],"elektronikabk":["elektronika-bk"],"emerson-arcadia-2001":["emerson-arcadia-2001"],"enemyterritory":["enemyterritory"],"enterprise":["enterprise-128","enterprise-64-128"],"enterprise-128":["enterprise-128"],"enterprise-64-128":["enterprise-64-128"],"enterprise128":["enterprise-128"],"entex-advision":["entex-advision"],"ep128":["enterprise-128"],"ep64-128":["enterprise-64-128"],"epochcv":["epochcv"],"epochsupercassettevision":["scv"],"epsxe":["sony-playstation"],"etlegacy":["enemyterritory"],"exelvision-exl100":["exelvision-exl100"],"exhumed":["exhumed"],"exl100":["exelvision-exl100"],"fairchild":["fairchild-channelf"],"fairchild-channel-f":["fairchild-channelf"],"fairchild-channelf":["fairchild-channelf"],"fairchildchannelf":["fairchild-channelf"],"fake08":["pico8"],"falcon":["atari-st"],"fallout":["fallout"],"fallout1-ce":["fallout"],"fallout2":["fallout2"],"fallout2-ce":["fallout2"],"famicom":["famicom","nintendo-nes"],"famicom disk system (fds)":["nintendo-fds"],"famicom-disk-system":["famicom-disk-system"],"famicomdisk":["nintendo-fds"],"famicomdisksystem":["famicom-disk-system"],"famicomds":["famicom-disk-system"],"fat plumber shit":["nintendo-nes"],"fba":["arcade"],"fbneo":["arcade"],"fbnneogeo":["neogeo"],"fc":["famicom","nintendo-fds","nintendo-nes"],"fcds":["famicom-disk-system"],"fcnes":["famicom"],"fds":["famicom-disk-system","nintendo-fds"],"fiftytwohundred":["atari-5200"],"finalburnneo":["arcade"],"flash":["flash"],"flashback":["flashback"],"flycast":["sega-dreamcast"],"fm-7":["fm7"],"fm7":["fm7"],"fmtowns":["fmtowns"],"fmtownsux":["fmtowns"],"fpinball":["fpinball"],"freej2me":["j2me"],"fury":["fury"],"galaksija":["galaksija"],"galretro":["galaksija"],"gamate":["gamate"],"game boy (gb)":["nintendo-gb"],"game boy advance (gba)":["nintendo-gba"],"game boy advance (mgba)":["nintendo-gba"],"game boy color (gbc)":["nintendo-gbc"],"game gear":["sega-gamegear"],"game-boy":["game-boy"],"game-boy-adavance-sp":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"game-boy-advance":["game-boy-advance"],"game-boy-color":["game-boy-color"],"game-boy-light":["nintendo-gb","nintendo-gbc"],"game-boy-micro":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"game-boy-pocket":["nintendo-gb","nintendo-gbc"],"game-televisison":["nintendo-fds","nintendo-nes"],"gameandwatch":["handheld-electronic"],"gameboy":["game-boy","nintendo-gb"],"gameboyadvance":["game-boy-advance","nintendo-gba"],"gameboycolor":["game-boy-color","nintendo-gbc"],"gamecom":["tiger-game-com"],"gamecube":["nintendo-gamecube"],"gamegear":["sega-gamegear"],"gamegearh":["sega-gamegear"],"gamegearhacks":["sega-gamegear"],"gameking":["gameking"],"gamemaster":["hartung-game-master"],"gamenwatch":["handheld-electronic"],"gamepark-gp32":["gamepark-gp32"],"gamepock":["gamepock"],"gamepocketcomputer":["gamepock"],"gametank":["gametank"],"gb":["game-boy","nintendo-gb","nintendo-gbc"],"gb2players":["nintendo-gb"],"gba":["game-boy-advance","nintendo-gba"],"gba2players":["nintendo-gba"],"gbadvance":["game-boy-advance"],"gbah":["nintendo-gba"],"gbahacks":["game-boy-advance"],"gbav":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"gbc":["game-boy-color","nintendo-gb","nintendo-gbc"],"gbc2players":["nintendo-gbc"],"gbch":["nintendo-gbc"],"gbchacks":["game-boy-color"],"gbcolor":["game-boy-color"],"gbdmg":["game-boy"],"gbh":["nintendo-gb"],"gbhacks":["game-boy"],"gbsp":["game-boy-advance"],"gc":["nintendo-gamecube"],"gce":["vectrex"],"gcevectrex":["vectrex"],"gearbox":["gearbox"],"gen":["sega-megadrive"],"gen32x":["sega-32x"],"gencd":["sega-megacd"],"genesis":["sega-genesis","sega-megadrive"],"genesiscd":["sega-megacd"],"genesishacks":["sega-megadrive"],"genh":["sega-megadrive"],"genmd":["sega-megadrive"],"gens":["sega-megadrive"],"gensegacd":["sega-megacd"],"gg":["sega-gamegear"],"ggsms":["sega-mastersystem"],"ghostship":["ghostship"],"gmaster":["hartung-game-master"],"gp32":["gamepark-gp32"],"gt":["gametank"],"gw":["handheld-electronic"],"gx4000":["amstrad-cpc"],"gzdoom":["chex","doom","heretic","hexen","strife"],"half-life":["half-life"],"halflife":["half-life"],"handheld-electronic":["handheld-electronic"],"handheldelectronic":["handheld-electronic"],"harcade":["arcade"],"hartung-game-master":["hartung-game-master"],"hbmame":["arcade"],"heretic":["heretic"],"hexen":["hexen"],"hikaru":["sega-hikaru"],"horizontal":["arcade"],"horizontalarcade":["arcade"],"hyper-neogeo64":["hyper-neogeo64"],"ibm-pc":["ibm-pc"],"ibm-pcjr":["ibm-pcjr"],"idquake":["quake"],"idquake2":["quake2"],"igs-pgm":["igs-pgm"],"intelli":["intellivision"],"intellivision":["intellivision"],"interact":["interact"],"interton-vc4000":["interton-vc4000"],"intv":["intellivision"],"iortcw":["return-to-castle-wolfenstein"],"ios":["apple-ios"],"iphone":["apple-ios"],"ique-player":["nintendo-64","nintendo-64dd"],"itv":["intellivision"],"j2me":["j2me"],"jag":["atari-jaguar"],"jaguar":["atari-jaguar"],"jaguarcd":["atari-jaguarcd"],"java":["j2me"],"jazz-jackrabbit":["jazz-jackrabbit"],"jazz-jackrabbit-2":["jazz-jackrabbit-2"],"jazz2":["jazz-jackrabbit-2"],"jedi-academy":["jedi-academy"],"jediknight2":["jediknight2"],"jkdf2":["dark-forces-ii","droidworks","mysteries-of-the-sith"],"jknight":["jedi-academy","jediknight2"],"kega":["sega-megadrive"],"konami-gq":["konami-gq"],"konami-gv":["konami-gv"],"laser310":["laser310"],"laseractive":["laseractive"],"laserdisc":["arcade-laserdisc"],"libgametank":["gametank"],"lindbergh":["sega-lindbergh"],"loopy":["casio-loopy"],"lowresnx":["lowresnx"],"lucasart":["scummvm"],"lucasarts":["scummvm"],"lynx":["atari-lynx"],"mac":["apple-macintosh","apple-macintosh-ii"],"macintosh":["apple-macintosh"],"magnavox":["odyssey2"],"magnavoxodyssey":["odyssey2"],"magnavoxodyssey2":["odyssey2"],"magnavoxvideopac":["odyssey2"],"mame":["arcade"],"mame-advmame":["arcade"],"mame-libretro":["arcade"],"mame-mame4all":["arcade"],"mame2000":["arcade"],"mame2003":["arcade"],"mame2003plus":["arcade"],"mame2010":["arcade"],"mark3":["sega-mastersystem"],"marty":["marty"],"master-system-girl":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"master-system-super-compact":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"mastersystem":["sega-mastersystem"],"mastersystemhacks":["sega-mastersystem"],"mattel-aquarius":["mattel-aquarius"],"mattelintellivision":["intellivision"],"mc10":["mc10"],"md":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megadrive"],"md32x":["sega-32x"],"mdcd":["sega-megacd"],"mdgen":["sega-megadrive"],"mdmsu":["sega-megadrive"],"mdmsu1":["sega-megadrive"],"mdsegacd":["sega-megacd"],"mega-duck":["mega-duck"],"mega-pc":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"megacd":["sega-megacd"],"megacdjp":["sega-megacd"],"megachip8":["chip8"],"megadrive":["sega-genesis","sega-megadrive"],"megadrive-japan":["sega-megadrive"],"megadrive-msu":["sega-megacd"],"megadrivecd":["sega-megacd"],"megadriveh":["sega-megadrive"],"megadrivehacks":["sega-megadrive"],"megadrivejp":["sega-genesis","sega-megadrive"],"megadrivemsu":["sega-megadrive"],"megaduck":["mega-duck"],"mgba":["game-boy-advance","nintendo-gba"],"microsoft msx (msx)":["msx"],"microsoft-xbox":["microsoft-xbox"],"microsoft-xbox-360":["microsoft-xbox-360"],"microsoftdos":["dos"],"microsoftmsx":["msx"],"midp":["j2me"],"minivmac":["apple-macintosh"],"mkxp":["rpgmaker"],"mkxp-z":["rpgmaker"],"mobile":["j2me"],"model2":["sega-model2"],"model2/roms":["sega-model2"],"model3":["sega-model3"],"mohaa":["mohaa"],"moto":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"ms":["sega-mastersystem"],"msdos":["dos"],"msdos (dos)":["dos"],"msu":["nintendo-snes"],"msu-md":["sega-megacd"],"msu1":["nintendo-snes"],"msumd":["sega-megacd","sega-megadrive"],"msx":["msx"],"msx1":["msx","msx1"],"msx2":["msx","msx2"],"msx2+":["msx2+"],"msx2plus":["msx2plus"],"msxturbor":["msx","msxturbor"],"multivision":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"mysteries-of-the-sith":["mysteries-of-the-sith"],"myvision":["myvision"],"mz2000":["mz2000"],"mz2500":["mz2500"],"mz700":["mz700"],"mz800":["mz800"],"mz80k":["mz80k"],"n3ds":["nintendo-3ds"],"n64":["nintendo-64"],"n64dd":["nintendo-64","nintendo-64dd"],"n64hacks":["nintendo-64"],"nam":["nam"],"namco-system11":["namco-system11"],"namco-system246":["namco-system246"],"namco-system256":["namco-system256"],"namco-system357":["namco-system357"],"namco2x6":["namco-system246"],"naomi":["sammy-atomiswave","sega-dreamcast-arcade","sega-naomi"],"naomi2":["sega-naomi2"],"naomigd":["sega-dreamcast-arcade","sega-naomigd"],"native32":["sunplus-native32"],"nds":["nintendo-ds"],"ndsi":["nintendo-dsi"],"ndsiware":["nintendo-dsi"],"nec-pc-88":["nec-pc-88"],"nec-pc-engine":["nec-pc-engine"],"nec-pc-engine-cd":["nec-pc-engine-cd"],"nec-pcfx":["nec-pcfx"],"nec-supergrafx":["nec-supergrafx"],"necpc8000":["nec-pc-88","pc80"],"necpc98":["pc-98"],"necpce":["nec-pc-engine"],"necpcecd":["nec-pc-engine-cd"],"necpcengine":["nec-pc-engine"],"necpcenginecd":["nec-pc-engine-cd"],"necpcfx":["nec-pcfx"],"necsgfx":["nec-supergrafx"],"necsupergrafx":["nec-supergrafx"],"nectg16":["nec-pc-engine"],"nectgcd":["nec-pc-engine-cd"],"necturbografx":["nec-pc-engine"],"necturbografx16":["nec-pc-engine"],"necturbografxcd":["nec-pc-engine-cd"],"neo geo pocket (ngp)":["snk-ngp"],"neo geo pocket color (ngpc)":["snk-ngpc"],"neo-geo-cd":["snk-neogeo-cd"],"neo-geo-pocket":["snk-neogeo-pocket"],"neo-geo-pocket-color":["neo-geo-pocket-color"],"neocd":["snk-neogeo-cd"],"neocdz":["snk-neogeo-cd"],"neogeo":["neogeo"],"neogeo cd (ngcd)":["snk-neogeo-cd"],"neogeo-cd":["snk-neogeo-cd"],"neogeo64":["hyper-neogeo64"],"neogeoaes":["snk-neogeo-aes"],"neogeocd":["snk-neogeo-cd"],"neogeocdjp":["snk-neogeo-cd"],"neogeomvs":["snk-neogeo-mvs"],"neogeopocket":["snk-neogeo-pocket","snk-ngp"],"neogeopocketcolor":["snk-neogeo-pocket","snk-ngpc"],"nes":["famicom","nintendo-nes"],"nescd":["famicom"],"nesds":["famicom"],"nesfc":["famicom"],"nesh":["nintendo-nes"],"neshacks":["famicom"],"new-nintendo-3ds":["nintendo-3ds"],"new-style-nes":["nintendo-fds","nintendo-nes"],"new-style-super-nes-model-sns-101":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"ng":["neogeo"],"ngage":["ngage"],"ngb":["game-boy"],"ngba":["game-boy-advance"],"ngbc":["game-boy-color"],"ngc":["nintendo-gamecube","snk-ngp"],"ngcd":["snk-neogeo-cd"],"ngp":["snk-neogeo-pocket","snk-ngp","snk-ngpc"],"ngpc":["snk-neogeo-pocket","snk-ngp","snk-ngpc"],"ngpocket":["snk-neogeo-pocket"],"ngpocketcolor":["snk-neogeo-pocket"],"ngw":["handheld-electronic"],"ninds":["nintendo-ds"],"ninetyeight":["pc-98"],"ningba":["game-boy-advance"],"ningbc":["game-boy-color"],"ninnes":["famicom"],"ninsnes":["nintendo-satellaview"],"nintendo ds (nds)":["nintendo-ds"],"nintendo entertainment system (fc)":["nintendo-nes"],"nintendo-3ds":["nintendo-3ds"],"nintendo-64":["nintendo-64"],"nintendo-64dd":["nintendo-64dd"],"nintendo-ds":["nintendo-ds"],"nintendo-ds-lite":["nintendo-ds","nintendo-dsi"],"nintendo-dsi":["nintendo-dsi"],"nintendo-dsi-xl":["nintendo-ds","nintendo-dsi"],"nintendo-fds":["nintendo-fds"],"nintendo-gamecube":["nintendo-gamecube"],"nintendo-gb":["nintendo-gb"],"nintendo-gba":["nintendo-gba"],"nintendo-gbc":["nintendo-gbc"],"nintendo-nes":["nintendo-nes"],"nintendo-pokemon-mini":["nintendo-pokemon-mini"],"nintendo-satellaview":["nintendo-satellaview"],"nintendo-sgb":["nintendo-sgb"],"nintendo-snes":["nintendo-snes"],"nintendo-sufami-turbo":["nintendo-sufami-turbo"],"nintendo-switch":["nintendo-switch"],"nintendo-virtualboy":["nintendo-virtualboy"],"nintendo-wii":["nintendo-wii"],"nintendo-wiiu":["nintendo-wiiu"],"nintendo3ds":["nintendo-3ds"],"nintendo64":["nintendo-64"],"nintendods":["nintendo-ds"],"nintendodsi":["nintendo-ds","nintendo-dsi"],"nintendoentertainmentsystem":["famicom"],"nintendofamicom":["famicom"],"nintendofamicomdisksystem":["famicom-disk-system"],"nintendogameandwatch":["handheld-electronic"],"nintendogameboy":["game-boy"],"nintendogameboyadvance":["game-boy-advance"],"nintendogameboycolor":["game-boy-color"],"nintendogb":["game-boy"],"nintendogba":["game-boy-advance"],"nintendogbc":["game-boy-color"],"nintendogw":["handheld-electronic"],"nintendon64":["nintendo-64"],"nintendones":["famicom"],"nintendonintendo64":["nintendo-64"],"nintendonintendo64dd":["nintendo-64"],"nintendonintendodsi":["nintendo-ds"],"nintendonintendoentertainmentsystem":["famicom"],"nintendopokemini":["nintendo-pokemon-mini"],"nintendopokemonmini":["nintendo-pokemon-mini"],"nintendosfc":["nintendo-satellaview"],"nintendosnes":["nintendo-satellaview"],"nintendosnesmsu":["nintendo-satellaview"],"nintendosnesmsu1":["nintendo-satellaview"],"nintendosupernintendo":["nintendo-satellaview"],"nintendosupernintendoentertainmentsystem":["nintendo-satellaview"],"nintendovb":["nintendo-virtualboy"],"nintendovitrualboy":["nintendo-virtualboy"],"nomad":["sega-megadrive"],"nsnes":["nintendo-satellaview"],"nsv":["nintendo-satellaview"],"nvb":["nintendo-virtualboy"],"nxengine":["cave-story"],"o2":["philips-videopac"],"o2em":["odyssey2"],"odyssey":["odyssey2","philips-videopac"],"odyssey-2-slash-videopac-g7000":["odyssey2"],"odyssey2":["odyssey2"],"olivetti-pc128":["olivetti-pc128"],"onscripter":["onscripter"],"openbeatsofrage":["openbor"],"openbor":["openbor"],"opengoal":["opengoal"],"openjazz":["jazz-jackrabbit"],"openlara":["tomb-raider"],"oric":["oric"],"oricatmos":["oricatmos"],"originalgameboy":["game-boy"],"outlaws":["outlaws"],"outrun":["sega-outrun"],"p2000t":["philips-p2000t"],"p8":["pico8"],"palm":["palm-os"],"palm-os":["palm-os"],"palmos":["palm-os"],"panasonic":["panasonic-3do"],"panasonic-3do":["panasonic-3do"],"pbp":["sony-playstation"],"pbps":["sony-playstation"],"pc":["dos"],"pc engine":["nec-pc-engine"],"pc-8800":["nec-pc-88"],"pc-98":["pc-98"],"pc-9800":["pc-98"],"pc-9800-series":["pc-98"],"pc-fx":["nec-pcfx"],"pc60":["pc60"],"pc80":["pc80"],"pc8000":["nec-pc-88","pc80"],"pc88":["nec-pc-88"],"pc8801":["nec-pc-88"],"pc98":["pc-98"],"pce":["nec-pc-engine","nec-supergrafx"],"pcecd":["nec-pc-engine","nec-pc-engine-cd"],"pcengine":["nec-pc-engine"],"pcenginecd":["nec-pc-engine","nec-pc-engine-cd"],"pcfx":["nec-pcfx"],"pcninetyeight":["pc-98"],"pcsx":["sony-playstation"],"pcv2":["bandai-wswan","bandai-wswanc"],"pcw":["pcw"],"pdark":["pdark"],"pegasus":["pegasus"],"pet":["commodore-pet"],"pgm":["arcade","igs-pgm"],"philips-cd-i":["philips-cdi"],"philips-cdi":["philips-cdi"],"philips-p2000t":["philips-p2000t"],"philips-vg5k":["philips-vg5k"],"philips-videopac":["philips-videopac"],"philipscdi":["philips-cdi"],"pico":["pico8","sega-pico"],"pico-8":["pico8"],"pico-8 (p8)":["pico8"],"pico-8/carts":["pico8"],"pico8":["pico8"],"piece":["aquaplus-piece"],"pkm":["nintendo-pokemon-mini"],"playstation":["sony-playstation"],"playstationchds":["sony-playstation"],"playstationpbps":["sony-playstation"],"playstationportable":["sony-psp"],"plus4":["commodore-plus4"],"pocket-challenge-v2":["pocket-challenge-v2"],"pocketchallengev2":["pocket-challenge-v2"],"pocketstation":["sony-pocketstation"],"poke":["nintendo-pokemon-mini"],"pokemini":["nintendo-pokemon-mini"],"pokemon-mini":["nintendo-pokemon-mini"],"pokemonmini":["nintendo-pokemon-mini"],"pokémon mini (pkm)":["nintendo-pokemon-mini"],"ports":["wolfenstein3d"],"ports/caesar3":["caesar3"],"ports/cave story":["cave-story"],"ports/dinothawr":["dinothawr"],"ports/doom":["chex","doom","heretic","hexen","strife"],"ports/doom 3":["doom3"],"ports/ecwolf/games":["wolfenstein3d"],"ports/flashback":["flashback"],"ports/out run":["sega-outrun"],"ports/prince of persia":["prince-of-persia"],"ports/quake":["quake"],"ports/quake 2":["quake2"],"ports/quake 3":["quake3"],"ports/rick dangerous":["xrick"],"ports/star trek voyager":["quake3"],"ports/tamagotchi":["tamagotchi-p1"],"ports/theme hospital":["theme-hospital"],"ports/tomb raider":["tomb-raider"],"ports/vvvvvv":["vvvvvv"],"ports/wolfenstein 3d":["wolfenstein3d"],"powerslave":["powerslave"],"ppsspp":["sony-psp"],"prboom":["doom","heretic"],"primehack":["nintendo-gamecube","nintendo-wii"],"prince-of-persia":["prince-of-persia"],"ps":["sony-playstation"],"ps1":["sony-playstation"],"ps2":["sony-playstation-2"],"ps3":["sony-playstation-3"],"ps4":["ps4"],"ps4/shortcuts":["ps4"],"pschd":["sony-playstation"],"pschds":["sony-playstation"],"psiso":["sony-playstation"],"psisos":["sony-playstation"],"psone":["sony-playstation"],"psp":["sony-psp"],"pspbp":["sony-playstation"],"pspbps":["sony-playstation"],"pspminis":["sony-psp"],"psvita":["sony-playstation-vita"],"psx":["sony-playstation"],"psxchd":["sony-playstation"],"psxchds":["sony-playstation"],"psxiso":["sony-playstation"],"psxisos":["sony-playstation"],"psxpbp":["sony-playstation"],"psxpbps":["sony-playstation"],"puae":["commodore-amiga","commodore-amiga-cd32","commodore-cdtv"],"pv1000":["casio-pv1000"],"pv2000":["casio-pv2000"],"ql":["sinclair-ql"],"quake":["quake"],"quake (quake)":["quake"],"quake2":["quake2"],"quake3":["quake3"],"raze":["blood","duke3d","exhumed","nam","powerslave","redneck","shadow-warrior","ww2gi"],"redneck":["redneck"],"redream":["sega-dreamcast"],"reminiscence":["flashback"],"retcom":["galaksija"],"retro8":["pico8"],"return-to-castle-wolfenstein":["return-to-castle-wolfenstein"],"ricochet":["ricochet"],"rott":["rott"],"rpgmaker":["rpgmaker"],"rtcw":["return-to-castle-wolfenstein","rott"],"rx78":["bandai-rx78"],"s32x":["sega-32x"],"sam-coupe":["sam-coupe"],"samcoupe":["sam-coupe"],"sameduck":["mega-duck"],"sammy-atomiswave":["sammy-atomiswave"],"sat":["sega-saturn"],"satella":["nintendo-satellaview"],"satellaview":["nintendo-satellaview"],"satourne":["sega-saturn"],"saturn":["sega-saturn"],"saturnjp":["sega-saturn"],"sc-3000":["sega-sc3000"],"sc3000":["sega-sc3000"],"scd":["sega-megacd"],"scumm":["scummvm"],"scummvm":["scummvm"],"scummvm/shortcuts":["scummvm"],"scv":["scv"],"sdc":["sega-dreamcast"],"sdlpop":["prince-of-persia"],"sega 32x (32x)":["sega-32x"],"sega cd (segacd)":["sega-megacd"],"sega dreamcast":["sega-dreamcast"],"sega game gear (gg)":["sega-gamegear"],"sega genesis (md)":["sega-megadrive"],"sega master system (sms)":["sms"],"sega sg-1000 (sg1000)":["sega-sg1000"],"sega-32x":["sega-32x"],"sega-ai":["sega-ai"],"sega-beena":["sega-beena"],"sega-chihiro":["sega-chihiro"],"sega-dreamcast":["sega-dreamcast"],"sega-dreamcast-arcade":["sega-dreamcast-arcade"],"sega-game-box-9":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-gamegear":["sega-gamegear"],"sega-genesis":["sega-genesis"],"sega-hikaru":["sega-hikaru"],"sega-lindbergh":["sega-lindbergh"],"sega-mark-iii":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-master-system-ii":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-mastersystem":["sega-mastersystem"],"sega-mega-drive-2-slash-genesis":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-mega-jet":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-megacd":["sega-megacd"],"sega-megadrive":["sega-megadrive"],"sega-model2":["sega-model2"],"sega-model3":["sega-model3"],"sega-naomi":["sega-naomi"],"sega-naomi2":["sega-naomi2"],"sega-naomigd":["sega-naomigd"],"sega-nomad":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-outrun":["sega-outrun"],"sega-pico":["sega-pico"],"sega-saturn":["sega-saturn"],"sega-sc3000":["sega-sc3000"],"sega-sf7000":["sega-sf7000"],"sega-sg1000":["sega-sg1000"],"sega-stv":["sega-stv"],"sega-systemsp":["sega-systemsp"],"sega-triforce":["sega-triforce"],"sega-vmu":["sega-vmu"],"sega32":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"sega32x":["sega-32x"],"sega32xjp":["sega-32x"],"sega32xna":["sega-32x"],"segaai":["sega-ai"],"segaatomiswave":["sammy-atomiswave"],"segacd":["sega-megacd"],"segadc":["sega-dreamcast"],"segadreamcast":["sega-dreamcast"],"segagamegear":["sega-gamegear"],"segagenesis":["sega-megadrive"],"segagenesismsu":["sega-megadrive"],"segagg":["sega-gamegear"],"segamastersystem":["sega-mastersystem"],"segamcd":["sega-megacd"],"segamdmsu":["sega-megadrive"],"segamegacd":["sega-megacd"],"segamegadrive":["sega-megadrive"],"segamodel3":["sega-model3"],"segams":["sega-mastersystem"],"seganaomi":["sammy-atomiswave"],"segapico":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"segasat":["sega-saturn"],"segasaturn":["sega-saturn"],"segascd":["sega-megacd"],"segasegacd":["sega-megacd"],"segasg1000":["sega-sg1000"],"segasgone":["sega-sg1000"],"segasms":["sega-mastersystem"],"segastv":["sega-stv"],"seggg":["sega-gamegear"],"segms":["sega-mastersystem"],"seventyeighthundred":["atari-7800"],"sfam":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"sfc":["nintendo-satellaview","nintendo-snes"],"sg-1000":["sega-sg1000"],"sg1000":["sega-sg1000"],"sg1k":["sega-sg1000"],"sgb":["nintendo-gb","nintendo-sgb"],"sgb-msu1":["nintendo-sgb"],"sgfx":["nec-pc-engine","nec-supergrafx"],"sgg":["sega-gamegear"],"sgonethousand":["sega-sg1000"],"sgx":["nec-pc-engine","nec-supergrafx"],"sgxcd":["nec-pc-engine"],"shadow-warrior":["shadow-warrior"],"sharp-x1":["sharp-x1"],"sharp-x68000":["sharp-x68000"],"sharpx1":["sharp-x1"],"sharpx6800":["sharp-x68000"],"sharpx68000":["sharp-x68000"],"sharpx68k":["sharp-x68000"],"sinclair-ql":["sinclair-ql"],"sinclair-spectrum":["sinclair-spectrum"],"sinclair-zx-spectrum":["sinclair-zx-spectrum"],"sinclair-zx-spectrum-next":["sinclair-zx-spectrum-next"],"sinclair-zx81":["sinclair-zx81"],"sinclairzx81":["sinclair-zx81"],"singe":["arcade-laserdisc"],"smbx":["smbx"],"sms":["sega-mastersystem","sms"],"smsgg":["sega-mastersystem"],"snes":["nintendo-satellaview","nintendo-snes"],"snes-hacks":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"snes-msu1":["nintendo-snes"],"snes9x":["nintendo-satellaview"],"snesh":["nintendo-snes"],"sneshacks":["nintendo-satellaview"],"snesmsu":["nintendo-satellaview"],"snesmsu1":["nintendo-satellaview","nintendo-snes"],"snesna":["nintendo-snes"],"sng":["neogeo"],"snk-neogeo-aes":["snk-neogeo-aes"],"snk-neogeo-cd":["snk-neogeo-cd"],"snk-neogeo-mvs":["snk-neogeo-mvs"],"snk-neogeo-pocket":["snk-neogeo-pocket"],"snk-ngp":["snk-ngp"],"snk-ngpc":["snk-ngpc"],"snkneogeo":["neogeo"],"snkneogeocd":["snk-neogeo-cd"],"snkneogeopocket":["snk-neogeo-pocket"],"snkneogeopocketcolor":["snk-neogeo-pocket"],"snkngcd":["snk-neogeo-cd"],"snkngp":["snk-neogeo-pocket"],"snkngpc":["snk-neogeo-pocket"],"socrates":["vtech-socrates"],"soh":["soh"],"solarus":["solarus"],"sonic-1-2013":["sonic-1-2013"],"sonic-2-2013":["sonic-2-2013"],"sonic-mania":["sonic-mania"],"sonic3-air":["sonic3-air"],"sonicretro":["sonic-1-2013","sonic-2-2013"],"sony playstation (ps)":["sony-playstation"],"sony-playstation":["sony-playstation"],"sony-playstation-2":["sony-playstation-2"],"sony-playstation-3":["sony-playstation-3"],"sony-playstation-vita":["sony-playstation-vita"],"sony-pocketstation":["sony-pocketstation"],"sony-psp":["sony-psp"],"sonyplaystation":["sony-playstation"],"sonyplaystationportable":["sony-psp"],"sonyps":["sony-playstation"],"sonyps1":["sony-playstation"],"sonypsp":["sony-psp"],"sonypsx":["sony-playstation"],"spec":["sinclair-zx-spectrum"],"spectravideo":["spectravideo"],"spectrum":["sinclair-spectrum","sinclair-zx-spectrum"],"spmp8000":["sunplus-spmp8000"],"ss":["sega-saturn"],"st":["atari-st"],"st-v":["sega-stv"],"star-control-2":["star-control-2"],"starship":["starship"],"ste":["atari-st"],"story":["onscripter"],"strife":["strife"],"studio-ii":["studio-ii"],"stv":["sega-stv"],"sufami":["nintendo-satellaview","nintendo-sufami-turbo"],"sufami-turbo":["nintendo-sufami-turbo"],"sufamiturbo":["nintendo-sufami-turbo"],"sunplus-native32":["sunplus-native32"],"sunplus-spmp8000":["sunplus-spmp8000"],"supa":["nintendo-snes"],"super game boy (sgb)":["nintendo-sgb"],"super nintendo entertainment system (sfc)":["nintendo-snes"],"super nintendo entertainment system (supa)":["nintendo-snes"],"super-famicom-jr-model-shvc-101":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"super-famicom-shvc-001":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"super-gb":["nintendo-sgb"],"super-mario-war":["super-mario-war"],"super-nintendo-original-european-version":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"superacan":["superacan"],"superbroswar":["super-mario-war"],"supercassettevision":["scv"],"superchip":["chip8"],"superfamicom":["nintendo-satellaview","nintendo-snes"],"supergameboy":["nintendo-sgb"],"supergrafx":["nec-supergrafx"],"supermariowar":["super-mario-war"],"supernes":["nintendo-satellaview","nintendo-snes"],"supernintendo":["nintendo-satellaview"],"supernintendoentertainmentsystem":["nintendo-satellaview"],"superpretendo":["nintendo-satellaview"],"supervision":["watara-supervision"],"supracan":["supracan"],"svi":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"svicoleco":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"svicolecovision":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"swancrystal":["bandai-wswan","bandai-wswanc"],"switch":["nintendo-switch"],"symbian":["symbian"],"systemsp":["sega-systemsp"],"t80":["tic80"],"taito-fx1":["taito-fx1"],"tamagotchi-p1":["tamagotchi-p1"],"tandy-1000":["tandy-1000"],"tandy-vis":["tandy-vis"],"tandy1000":["tandy-1000"],"tanodragon":["dragon64"],"tecmo-tps":["tecmo-tps"],"teknoparrot":["namco-system246","namco-system256","namco-system357","sammy-atomiswave","sega-chihiro","sega-hikaru","sega-lindbergh","sega-naomi","sega-naomi2","sega-naomigd","sega-triforce"],"tera-drive":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"texas-instruments-ti-83":["texas-instruments-ti-83"],"texasinstrumentsti83":["texas-instruments-ti-83"],"tfc":["tfc"],"tg":["nec-pc-engine"],"tg-cd":["nec-pc-engine-cd"],"tg16":["nec-pc-engine"],"tg16cd":["nec-pc-engine-cd"],"tgb_dual":["nintendo-gb"],"tgcd":["nec-pc-engine-cd"],"tgfx":["nec-pc-engine"],"tgfx16-cd":["nec-pc-engine-cd"],"tgrafx":["nec-pc-engine"],"tgrafx16":["nec-pc-engine"],"theforceengine":["dark-forces","outlaws"],"theme-hospital":["theme-hospital"],"theodore":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"thextech":["smbx"],"thirtytwox":["sega-32x"],"thomson":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"thomson-mo5":["thomson-mo5"],"thomson-mo6":["thomson-mo6"],"thomson-to7":["thomson-to7"],"thomson-to770":["thomson-to770"],"thomson-to8":["thomson-to8"],"thomson-to8d":["thomson-to8d"],"thomson-to9":["thomson-to9"],"thomson-to9plus":["thomson-to9plus"],"thomsonmoto":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"ti-99_4a":["ti99"],"ti83":["texas-instruments-ti-83"],"ti99":["ti99"],"ti994a":["ti99"],"tic":["tic80"],"tic-80":["tic80"],"tic80":["tic80"],"tiger-game-com":["tiger-game-com"],"to8":["thomson-to8"],"tomb-raider":["tomb-raider"],"tomb-raider-1":["tomb-raider-1"],"tomb-raider-2":["tomb-raider-2"],"tombraider":["tomb-raider"],"traider1":["tomb-raider-1"],"traider2":["tomb-raider-2"],"triforce":["sega-triforce"],"trs-80":["trs80"],"trs80":["trs80"],"trs80coco":["coco"],"tt":["atari-st"],"turbocd":["nec-pc-engine-cd"],"turbografx":["nec-pc-engine"],"turbografx-16 (pce)":["nec-pc-engine"],"turbografx-cd":["nec-pc-engine"],"turbografx16":["nec-pc-engine"],"turbografxcd":["nec-pc-engine-cd"],"turbographix":["nec-pc-engine"],"tutor":["tutor"],"tvc":["videoton-tvc"],"tvgames":["tvgames"],"tvgc":["elektor-tv-games-computer","emerson-arcadia-2001","interton-vc4000"],"twentysixhundred":["atari-2600"],"tyrian":["tyrian"],"tyrquake":["quake"],"uqm":["star-control-2","ur-quan-masters"],"ur-quan-masters":["ur-quan-masters"],"uzebox":["uzebox"],"varcade":["arcade"],"vb":["nintendo-virtualboy"],"vc4000":["interton-vc4000"],"vec":["vectrex"],"vecrtex":["vectrex"],"vectrex":["vectrex"],"vemulator":["sega-vmu"],"vertarcade":["arcade"],"vertical":["arcade"],"verticalarcade":["arcade"],"vg5000":["philips-vg5k"],"vg5k":["philips-vg5k"],"vgmplay":["vgmplay"],"vic":["commodore-vic20"],"vic-20":["commodore-vic20"],"vic20":["commodore-vic20"],"videobrain":["videobrain"],"videopac":["odyssey2","philips-videopac"],"videopac-g7400":["philips-videopac"],"videopacplus":["philips-videopac"],"videosystem-zn1":["videosystem-zn1"],"videoton-tvc":["videoton-tvc"],"vircon32":["vircon32"],"virtboy":["nintendo-virtualboy"],"virtuaboy":["nintendo-virtualboy"],"virtual boy (vb)":["nintendo-virtualboy"],"virtualboy":["nintendo-virtualboy"],"vis":["tandy-vis"],"visualstory":["onscripter"],"vmac":["apple-macintosh"],"vmu":["sega-vmu"],"vpinball":["vpinball"],"vsmile":["vtech-vsmile"],"vtech-socrates":["vtech-socrates"],"vtech-vsmile":["vtech-vsmile"],"vvvvvv":["vvvvvv"],"watara":["watara-supervision"],"watara-supervision":["watara-supervision"],"watarasupervision":["watara-supervision"],"wii":["nintendo-wii"],"wiiu":["nintendo-wiiu"],"wiiu/roms":["nintendo-wiiu"],"wiiware":["nintendo-wii"],"windows3x":["dos","ibm-pc","ibm-pcjr","pc-98","tandy-1000"],"windows9x":["dos","ibm-pc","ibm-pcjr","pc-98","tandy-1000"],"wolf":["wolfenstein3d"],"wolf3d":["wolfenstein3d"],"wolfenstein":["wolfenstein3d"],"wolfenstein3d":["wolfenstein3d"],"wonderswan":["bandai-wswan","wonderswan","wonderswan-color"],"wonderswan-color":["wonderswan-color"],"wonderswanc":["wonderswan-color"],"wonderswancolor":["wonderswan","wonderswan-color"],"ws":["bandai-wswan","bandai-wswanc","wonderswan","wonderswan-color"],"wsc":["wonderswan","wonderswan-color"],"wswan":["bandai-wswan"],"wswanc":["bandai-wswanc"],"ww2gi":["ww2gi"],"x1":["sharp-x1"],"x16":["commanderx16"],"x68000":["sharp-x68000"],"x68k":["sharp-x68000"],"xash3d_fwgs":["bshift","cstrike","czero","czeror","dmc","gearbox","half-life","ricochet","tfc"],"xbox":["microsoft-xbox"],"xbox360":["microsoft-xbox-360"],"xbox360/roms":["microsoft-xbox-360"],"xegs":["xegs"],"xone":["sharp-x1"],"xrick":["xrick"],"xroar":["coco"],"zc210":["zc210"],"zeldac":["zeldaclassic"],"zeldaclassic":["zeldaclassic"],"zinc":["acclaim-zn1","atari-zn1","atlus-zn1","capcom-zn1","capcom-zn2","eighting-zn1","konami-gq","konami-gv","namco-system11","taito-fx1","tecmo-tps","videosystem-zn1"],"zmachine":["zmachine"],"zsnes":["nintendo-satellaview"],"zx spectrum (zxs)":["sinclair-zx-spectrum"],"zx81":["sinclair-zx81"],"zxeightyone":["sinclair-zx81"],"zxnext":["sinclair-zx-spectrum-next"],"zxs":["sinclair-zx-spectrum"],"zxspectrum":["sinclair-zx-spectrum"]},"format_version":1,"licences":[{"mirror":{"licence":"MIT","repo":"https://github.com/hugo19941994/auto-datfile-generator","scope":"the mirror's scripts only, the DATs it republishes stay under the terms above"},"quote":"Unless otherwise stated on the website, the data made available through this website (\"Data\") may be freely used, copied, reproduced, modified, adapted, combined, published, distributed, and otherwise reused by anyone for any lawful purpose, to the extent that the website operator owns or controls the applicable rights or is authorized to grant such permission. No permission, attribution, citation, backlink, or acknowledgment of the website or its operators is required for such use.","read":"2026-11-03","terms_title":"Data Usage License","terms_updated":"2026-09-11","terms_url":"https://datomatic.no-intro.org/terms.html"},{"quote":"Dumpers only submit metadata and Redump only stores metadata. This information is considered public domain to be used however people see fit","read":"2026-11-03","terms_url":"https://redump.info/about"}],"setups":{"allium":{"file":"setups/allium.json","gzip_size":5091,"sha256":"7e1b5914e15cc2ff710052fc7385fb9457ca955f5a633313d4ce4e8496b32033","size":35139},"amberelec":{"file":"setups/amberelec.json","gzip_size":5613,"sha256":"7c25ef2b727003a6ff285cb255286264acdc726fefbcea43f6f254ed708250be","size":38051},"archr":{"file":"setups/archr.json","gzip_size":7548,"sha256":"b5fe00e263b6df7c536260bbd8b7c41fe3e031a812f40644c8dacc93e049a88f","size":57318},"arkos":{"file":"setups/arkos.json","gzip_size":6069,"sha256":"0f4cf86ae6afb1ecb1c5019f8ac7c598044118b902f11aa9d8823e90ac2ca82d","size":39966},"batocera":{"file":"setups/batocera.json","gzip_size":14457,"sha256":"af163f68ee5069620ebf6b0fcb98ebd7ee721203c0dbf21d55244a024649d5fc","size":134476},"bizhawk":{"file":"setups/bizhawk.json","gzip_size":2469,"sha256":"1bd6306d2f485700b531d3d3ac502cbf36aaa9cfeb954f751ea3bb862aeb7aa9","size":16059},"chaos":{"file":"setups/chaos.json","gzip_size":5625,"sha256":"3a56b30c0992cd78eef8e097e9b1ef8aa479a664ea550d32d7777e18cbed0bb6","size":38023},"crossmix-os":{"file":"setups/crossmix-os.json","gzip_size":4628,"sha256":"8361175b1aebab116d878cc9117f531678969758c13a83b8ece2289c5eca9f46","size":30935},"darkos":{"file":"setups/darkos.json","gzip_size":5877,"sha256":"cc13afb7b04ac99eca20df747da975f55fb0757df63ef70b7923087f75f5a9df","size":37501},"emudeck":{"file":"setups/emudeck.json","gzip_size":8178,"sha256":"0a0d0b8a9c0fa9e6251dc28f88040ed6bc931a0f763ba1df0c07c72791995838","size":59403},"emudeck-windows":{"file":"setups/emudeck-windows.json","gzip_size":8145,"sha256":"e3b15545aafdc94411ba5cea61b6de9d9ce75889dff7ee6fefe3e63d4966fc17","size":60030},"emuelec":{"file":"setups/emuelec.json","gzip_size":7916,"sha256":"3117d2dd0ffb721e11f1e70385ed599f36d54c2d19db1dc598be52b5f8b73445","size":55398},"jelos":{"file":"setups/jelos.json","gzip_size":6646,"sha256":"52d5260b6ef397e1e41f957dc51808d8943848950322107336e886ae963bc2fd","size":47161},"knulli":{"file":"setups/knulli.json","gzip_size":11986,"sha256":"73cda1ec1afde3494896c2d82ae185eb0013721b817cf46293be84a7967900af","size":97205},"kolos":{"file":"setups/kolos.json","gzip_size":6170,"sha256":"1ab8b0c0a57bf6bb16f781bd1b97fe28e3c0d961a575af86546a482e5de4d150","size":43277},"koriki":{"file":"setups/koriki.json","gzip_size":4029,"sha256":"d2f15741cd1b16ac6f1f51dc1afa09a1831e6502b5d2ead7ee507a051ba414f1","size":22608},"lakka":{"file":"setups/lakka.json","gzip_size":517,"sha256":"3adec2a8c4f9a992e271382650338d00310db3de3bffd5448109c635ec03e2fd","size":1037},"minui":{"file":"setups/minui.json","gzip_size":2055,"sha256":"0a38d3d3b6d0fc16ed59a9fa420aba91a3402dc4ae584b349dc19076ad4818cc","size":10242},"misterfpga":{"file":"setups/misterfpga.json","gzip_size":3578,"sha256":"5c6e306970b67c12e6cc25c82328691fd13ad0c554ce1309efd1f0278158ad07","size":23518},"miyoocfw":{"file":"setups/miyoocfw.json","gzip_size":959,"sha256":"cb13cdcae35830c58d6465ff2f6e36c2d0558c576fd8eb8fd053537fb007573b","size":2285},"muos":{"file":"setups/muos.json","gzip_size":7386,"sha256":"3beffb9369d734978047ec64a440202704d9682bfe25c9c05e159c3b4618ed87","size":46601},"myminui":{"file":"setups/myminui.json","gzip_size":2797,"sha256":"8cac64f671ed745b8cd713be9e88b9f83e8e83061c32ff62fca646c91ea986ea","size":14717},"nextui":{"file":"setups/nextui.json","gzip_size":2950,"sha256":"e9eb9a3d06cc796bf54b185691144c828a2c7dc767a9b83c25fb310ca3b64d1d","size":15309},"onion":{"file":"setups/onion.json","gzip_size":6337,"sha256":"35cad2ef2a7162b93035cbeafd2ac881ba17a777ae11d05e16c4c4fb071071e8","size":34615},"pan4elec":{"file":"setups/pan4elec.json","gzip_size":5717,"sha256":"2534db783b7eb7037c4457fc9ae540d885aa6fdd3a59411df7856aeb64ef68b9","size":39455},"plumos-mf":{"file":"setups/plumos-mf.json","gzip_size":6141,"sha256":"5c2ae5292af66a32a16ad6c70ead6cbabef934c5e3e5261d6d92e9942bfd403b","size":33703},"plumos-pixel2":{"file":"setups/plumos-pixel2.json","gzip_size":6180,"sha256":"4c674898610e234f9a6711db34f9cebec91eaeb76d160e13a62eabd13a702720","size":31896},"recalbox":{"file":"setups/recalbox.json","gzip_size":9153,"sha256":"965c44508d9fe798954cdf392db0726e8b3be5796b0b5dea6b3a92aaba12bb47","size":69567},"retroarch":{"file":"setups/retroarch.json","gzip_size":476,"sha256":"025188a526422c7d79c996edc19c486c9b4f322798325a18405733066483b3d6","size":786},"retrobat":{"file":"setups/retrobat.json","gzip_size":10307,"sha256":"39e0945e6d33c1312f73b3b3ff26ee9a81d70d5061cd78a415ca87c0d68ad1b6","size":70854},"retrodeck":{"file":"setups/retrodeck.json","gzip_size":7183,"sha256":"f29336cedac2da9e8b1ccb89d9b608a9a8f147564ed6abafdaa8e0b4c922fbae","size":53597},"retropie":{"file":"setups/retropie.json","gzip_size":4670,"sha256":"f80f62e4d96cf62937da5f3e434fa6754bbf9eb17738b0d24062be7de9e5c4a2","size":24007},"rocknix":{"file":"setups/rocknix.json","gzip_size":7590,"sha256":"ff85bfdbdbc852265f5a7d71327e4df6512c53515a70add8d124f4ac3281689e","size":58836},"romm":{"file":"setups/romm.json","gzip_size":3790,"sha256":"73d2f0f4d95e9146ac9f850bf41e3a85bb133e543749dcecb785e80c67648946","size":30844},"spruceos":{"file":"setups/spruceos.json","gzip_size":6419,"sha256":"ccbe920491891b66c1db61e4c09abae154d367421856a8817d4c7e22111000c2","size":28367},"unofficialos":{"file":"setups/unofficialos.json","gzip_size":7152,"sha256":"bec913e663e25217e0a84db7bb0042a6f0b38d7d2a34d52e5de0c7a3fc5de4a6","size":51670}},"systems":{"atari-5200":{"file":"systems/atari-5200.json","gzip_size":4092,"sha256":"55bf18d45a6a7d75cda37ac27088b2510c4a27894157bca7f15452d67b5b76af","size":12435},"atari-7800":{"file":"systems/atari-7800.json","gzip_size":887,"sha256":"2ff726865df34502c72be99d18948dedd0782f19a38a215297c89c813d648481","size":1668},"atari-jaguar":{"file":"systems/atari-jaguar.json","gzip_size":292,"sha256":"a0215745664dcfdbe9f454e226561e61fdb8f60c0d72ba877b52e8f1b7929934","size":413},"atari-lynx":{"file":"systems/atari-lynx.json","gzip_size":1678,"sha256":"ab7cc8614064981951ddcca1c4a9d263b49b04fc0a89f2a984de08c20392a3d0","size":3634},"colecovision":{"file":"systems/colecovision.json","gzip_size":4412,"sha256":"9eb8ecd30e9877d6a36551ef03eb70b4151152023d0133a3b05109022d56151c","size":11293},"commodore-amiga":{"file":"systems/commodore-amiga.json","gzip_size":290,"sha256":"9988cce7dd6403204ab580edbc9522e5a9080c790bf04a98e6c3d435bbee42e3","size":788},"commodore-amiga-cd32":{"file":"systems/commodore-amiga-cd32.json","gzip_size":265,"sha256":"2c4d3823a40cdd4197209b2abaf38db755218130812f92c03ddad2ee0fd4a46d","size":456},"intellivision":{"file":"systems/intellivision.json","gzip_size":4507,"sha256":"748c7d7887370f16d5992fa7e53381108a24366584239543ccadf4347ccc8f01","size":12528},"laseractive":{"file":"systems/laseractive.json","gzip_size":363,"sha256":"d96ade3209fda8314cf9010a5ced458ad95037867fa204c8e457b05c46f5d80d","size":723},"msx":{"file":"systems/msx.json","gzip_size":214,"sha256":"e73b146104ffeb5ececb7173a5a3ce3903d0d0de1fde5e301658252c5675359b","size":285},"msx2plus":{"file":"systems/msx2plus.json","gzip_size":331,"sha256":"21b724cfbe529d2d992a7a633c570674c70753a42153befabe8c86c689b66c49","size":462},"nec-pc-engine":{"file":"systems/nec-pc-engine.json","gzip_size":9241,"sha256":"1fe6db213678d40878dfa6c411d1031319ef9f0d605b5653d1b4aa01e8a04452","size":27628},"nec-pc-engine-cd":{"file":"systems/nec-pc-engine-cd.json","gzip_size":12487,"sha256":"754e02b8e7e99135454008a89e883c9d6829a1f62cbc759abba2e5991866f9e9","size":43447},"nec-supergrafx":{"file":"systems/nec-supergrafx.json","gzip_size":831,"sha256":"111bd2ee40d75db1d140f263313bb6c97e31965883dbdf16906893e043f8d52d","size":1441},"neo-geo-pocket-color":{"file":"systems/neo-geo-pocket-color.json","gzip_size":3371,"sha256":"484bdf90a16917d464f28e8de1bbdce8d369c274d20d3d8c55ba0911a7a5e9ba","size":10072},"nintendo-3ds":{"file":"systems/nintendo-3ds.json","gzip_size":485,"sha256":"5e903462cea76f28681397aee0e6e3f119cd206ea60dd18ae734cbc5c5779cf7","size":808},"nintendo-64":{"file":"systems/nintendo-64.json","gzip_size":21504,"sha256":"24acf25d8c43e5227dc674057b41deffcc5c6db39f0f09e4ab258334749acd28","size":73974},"nintendo-64dd":{"file":"systems/nintendo-64dd.json","gzip_size":2541,"sha256":"82a62ff230513d4b3b7ec6bcb1ac8efe4101ff4e301dfea4300e13dea12cbc4a","size":7705},"nintendo-ds":{"file":"systems/nintendo-ds.json","gzip_size":186345,"sha256":"9f74ade6f2fff15b51c410ce83aafccdb3cb0c1701c9cd42a593ca84d1ab4c33","size":566900},"nintendo-dsi":{"file":"systems/nintendo-dsi.json","gzip_size":240,"sha256":"a470b580ca27fdf66bcf1213d3f7d3ab3acbf2a6272dd445a9ade5fc4cd4b569","size":345},"nintendo-fds":{"file":"systems/nintendo-fds.json","gzip_size":9025,"sha256":"59f40fb23866487b95f2a0b709b216c6c66de694f4528b0c4b53aae3fc1f4e7d","size":30626},"nintendo-gamecube":{"file":"systems/nintendo-gamecube.json","gzip_size":46580,"sha256":"afd0881edb18be56407268b9c2c6a6437e2670baa76203e4e03da33fac8ed4ee","size":189501},"nintendo-gb":{"file":"systems/nintendo-gb.json","gzip_size":39786,"sha256":"8cfeadc99c49af41435728dc1e5343ca14d632bcc4681e87f286ca41e3281868","size":127687},"nintendo-gba":{"file":"systems/nintendo-gba.json","gzip_size":76891,"sha256":"c254fa7973aa84f1b9e49f256437a03360d06ecf3b80838cae36bc5bbd84b80f","size":248499},"nintendo-gbc":{"file":"systems/nintendo-gbc.json","gzip_size":44917,"sha256":"3c281676ea9778761b00d454661d9fa7c5dfb70cbe435c1bb30158ef766d418f","size":154739},"nintendo-nes":{"file":"systems/nintendo-nes.json","gzip_size":89663,"sha256":"6e0e1d1f2681c10998518abe4b46cd2ea4a9f993316432876f19f8a52167e332","size":274177},"nintendo-pokemon-mini":{"file":"systems/nintendo-pokemon-mini.json","gzip_size":1537,"sha256":"083eed4eccdfcb12daab714d7cf3a595cbe7554010a7c79171916bc97b4611dc","size":4199},"nintendo-satellaview":{"file":"systems/nintendo-satellaview.json","gzip_size":13245,"sha256":"fc91880841ba301ff3fc2e7edfe53eed876edb33f9d7534d814d39dacd0a1654","size":51819},"nintendo-sgb":{"file":"systems/nintendo-sgb.json","gzip_size":746,"sha256":"617365112f8b93207b50323f761c4073d1c5aee87d877675822fb34247bab373","size":1621},"nintendo-snes":{"file":"systems/nintendo-snes.json","gzip_size":79838,"sha256":"5a1ffe5d5c958424793b77ce016c65205967f1d8ff910ffc6e8118f00b584001","size":249778},"nintendo-sufami-turbo":{"file":"systems/nintendo-sufami-turbo.json","gzip_size":1512,"sha256":"8070d9473708fee7ada3481daecd09e5389573652f1986e4a00275821337ac09","size":3210},"nintendo-wii":{"file":"systems/nintendo-wii.json","gzip_size":563,"sha256":"bff9fd15aa2896dbe9b5f60e713b04dd2d40dcfbee5dc8699a7ccec14536a466","size":1229},"odyssey2":{"file":"systems/odyssey2.json","gzip_size":3297,"sha256":"978953171a55509460854a4747ffbb94d9a0f16f0b2304abfe1aedbc3392582d","size":7851},"panasonic-3do":{"file":"systems/panasonic-3do.json","gzip_size":17243,"sha256":"38035ce01095a974ae7d0e1818f0d0c65f54cd89d326fa315893ef1062de9c0d","size":50013},"sega-32x":{"file":"systems/sega-32x.json","gzip_size":3894,"sha256":"6b0da0c37349c2340197d7a178f5862d942c43819f494ab2552e00e6dc83d360","size":16064},"sega-dreamcast":{"file":"systems/sega-dreamcast.json","gzip_size":36655,"sha256":"0041c8525fa27290841faa607ac8047e016f98896c5ff33b502495e8b37e14ed","size":122845},"sega-gamegear":{"file":"systems/sega-gamegear.json","gzip_size":14821,"sha256":"12ddb73bef81410d643f6b09ac0da2e49adb3dca8943f273f776d9c5c67583a2","size":54189},"sega-mastersystem":{"file":"systems/sega-mastersystem.json","gzip_size":14536,"sha256":"5669393a76b922ed2e14995c66c2804ccc7a1165a2416e50722c954aba560360","size":47411},"sega-megacd":{"file":"systems/sega-megacd.json","gzip_size":15396,"sha256":"ce94f85bf4ff3c8d4e58357c68cdb39a2b12d4b8052e61e77fd3189d2a3052c9","size":46794},"sega-megadrive":{"file":"systems/sega-megadrive.json","gzip_size":53279,"sha256":"10507cfccd4ec9fc2c63e71bbc83fda1001e565819665bb0b65d09f4506054bb","size":180871},"sega-naomi":{"file":"systems/sega-naomi.json","gzip_size":276,"sha256":"7da5520e2aa6c2f0e1e4e8f5417be5776d196960e793f740c3dd05ff37ab88e9","size":486},"sega-saturn":{"file":"systems/sega-saturn.json","gzip_size":66052,"sha256":"d3a87b71ce4771f0c4a93fa2d0621f100da77005b37e75faa541aec873a0f319","size":199102},"sega-stv":{"file":"systems/sega-stv.json","gzip_size":782,"sha256":"eb73b6449be6a70bf942f39c49322c03770ddd3bbb6a40f1add7f0ab90bd0841","size":2424},"sega-triforce":{"file":"systems/sega-triforce.json","gzip_size":286,"sha256":"7c68241a76bef2b4ff0cba2ea2f312250abc8585fcc52b41ced2bcbc76175726","size":539},"snk-neogeo-cd":{"file":"systems/snk-neogeo-cd.json","gzip_size":4649,"sha256":"ccc757ea85e9398347cc4ff1db29118a1923422aed21a7437d7c54806330fa8e","size":12370},"snk-neogeo-pocket":{"file":"systems/snk-neogeo-pocket.json","gzip_size":1070,"sha256":"c88819387ac6a344a017198e7bc2560fe306ba9f80350483dab29dd48a03342b","size":2179},"sony-playstation":{"file":"systems/sony-playstation.json","gzip_size":323936,"sha256":"e27d244a888c5246e00166eba8a893032cf96a85dff08905c77d696d997bd861","size":939819},"sony-playstation-2":{"file":"systems/sony-playstation-2.json","gzip_size":361140,"sha256":"410adb750ffbce2e2389facace712c1ad784cfa128da2763b5821ba5cc0ffac7","size":1075273},"vectrex":{"file":"systems/vectrex.json","gzip_size":1615,"sha256":"908725537d457bd597c180c61705f494209c412d728951944d86e504f40387ad","size":3457},"wonderswan":{"file":"systems/wonderswan.json","gzip_size":5961,"sha256":"e0949ae3fd96c11f54db7f56d1d9bc7b9613afe54d411ac16241095eb20f42ba","size":18778},"wonderswan-color":{"file":"systems/wonderswan-color.json","gzip_size":5618,"sha256":"41931c79d3546731ac4665f711c3d6296d30a26244be08e3bd9da01cbfdfa470","size":18027}}}
+{"arcade":{"fbneo":{"file":"arcade/fbneo.json","gzip_size":115955,"sha256":"88961c9a6be804772baa767f6ee3a9162478c30c60fe55c8363d8fe4fbc909da","size":423362},"flycast":{"file":"arcade/flycast.json","gzip_size":1841,"sha256":"957189a6e993fda08e21c90ffc6ad94aed9ca9e6dd9ed8c7724e29db036791cb","size":5441},"mame":{"file":"arcade/mame.json","gzip_size":154527,"sha256":"b12010301293a218ecfac45706d81a26c3ac0c27eebeca7409bc8f6ce0163e9e","size":604648},"mame0258":{"file":"arcade/mame0258.json","gzip_size":141151,"sha256":"7ecff1979ed2ac123ea3ba4825dde6e2c31906415165fabefc9af93fa48a6de4","size":556059},"mame0278":{"file":"arcade/mame0278.json","gzip_size":148595,"sha256":"7881e3516f451ec83e886aaf41ebac9d60f497e1f954f49749d52890d7955cbf","size":582797},"mame2000":{"file":"arcade/mame2000.json","gzip_size":8624,"sha256":"f0d69b0872ecfc2845eeb7304543e5b17c11db82060b5514c206b6962ed08263","size":23316},"mame2003":{"file":"arcade/mame2003.json","gzip_size":17456,"sha256":"3b44e2a92c80a8f104b7781fcc1c776d025ad2cf4986638efa3ea041baa9a56d","size":48929},"mame2003_plus":{"file":"arcade/mame2003_plus.json","gzip_size":21077,"sha256":"2857283556fa49c20d8160ed113465bf0c2e643ed0b8acd2d38266a78be8e25e","size":62373},"mame2010":{"file":"arcade/mame2010.json","gzip_size":30869,"sha256":"50b1b381b4b07463f69f1f4c512dd1c98a78d4d0e9c3aeaf49b7b1b007b42152","size":96528},"mame2015":{"file":"arcade/mame2015.json","gzip_size":86990,"sha256":"afeb8c32f651421f74c6de057b0c0b837acd14c533b5160bb31f4411e0afffec","size":360117},"mame2016":{"file":"arcade/mame2016.json","gzip_size":101249,"sha256":"1f75147977d9d082a38b8f8e47a02b301f3d6e6db97c9b9282f3e7f27f26ee47","size":406190}},"containers":{"7z":{"description":"Per-file CRCs and sizes sit in the header at the end of the archive, LZMA-compressed by default (kEncodedHeader). One LZMA decode of the header, independent of the archive size, gives them. Python's lzma is an optional module.","re_read":true,"signature":{"bytes_hex":"377abcaf271c","offset":0},"source_ref":"ip7z/7zip@b88c6bc0 DOC/7zFormat.txt:171-189, DOC/7zFormat.txt:318-334, CPP/7zip/Archive/7z/7zHandlerOut.cpp:859"},"cd-sector":{"description":"User data of a CD sector. In a 2048-byte image (.iso) sector N starts at N * 2048. In a raw 2352-byte image it starts at N * 2352 plus 16 for Mode 1 and plus 24 for Mode 2 Form 1 (12 sync bytes, a 4-byte header, and for Mode 2 an 8-byte subheader).","re_read":true,"sector_size":{"iso":2048,"raw":2352},"source_ref":"stenzek/duckstation@526b4a12 src/util/iso_reader.cpp:157-171, src/util/cd_image.h:28-34","user_data_offset":{"mode1":16,"mode2":24}},"chd-v5":{"description":"MAME compressed hunks, big-endian. The header holds sizes, codecs and hashes only, never the system or the region. The overall SHA-1 is what MAME software lists record. Neither SHA-1 equals a Redump track hash: chdman hashes 2448-byte frames (subcode included, zero-filled), pads each track to 4 frames and byte-swaps audio, all tracks in one stream.","fields":{"compressors":{"encoding":"fourcc4","length":16,"offset":16},"header_length":{"encoding":"u32be","length":4,"offset":8,"value":124},"hunk_bytes":{"encoding":"u32be","length":4,"offset":56},"logical_bytes":{"encoding":"u64be","length":8,"offset":32},"map_offset":{"encoding":"u64be","length":8,"offset":40},"metadata_offset":{"encoding":"u64be","length":8,"offset":48},"overall_sha1":{"encoding":"hex","length":20,"offset":84},"parent_sha1":{"encoding":"hex","length":20,"offset":104},"raw_sha1":{"encoding":"hex","length":20,"offset":64},"unit_bytes":{"encoding":"u32be","length":4,"offset":60},"version":{"encoding":"u32be","length":4,"offset":12,"value":5}},"magic":{"bytes":"MComprHD","offset":0},"media_tags":{"CHCD":"cd","CHGD":"gd-rom","CHGT":"gd-rom","CHT2":"cd","CHTR":"cd","DVD ":"dvd","GDDD":"hard-disk"},"metadata_entry":{"description":"16-byte entry header, payload follows. Linked list from metadata_offset.","flags":{"encoding":"u8","length":1,"offset":4},"length":{"encoding":"u24be","length":3,"offset":5},"next":{"encoding":"u64be","length":8,"offset":8},"tag":{"encoding":"ascii","length":4,"offset":0}},"re_read":true,"source_ref":"mamedev/mame@f34f0250 src/lib/util/chd.h:148-162, src/lib/util/chd.cpp:2021-2061, src/lib/util/chd.cpp:2822-2831, src/lib/util/chd.h:212-235, src/lib/util/chd.cpp:1709-1749, src/tools/chdman.cpp:443-445, src/tools/chdman.cpp:2195-2203, src/lib/util/cdrom.cpp:2669-2672, src/emu/romload.cpp:1211"},"gamecube-disc":{"description":"Where disc offset 0 sits inside each container Dolphin opens.","formats":{"ciso":{"disc_header_at":32768,"magic":"CISO"},"gcz":{"disc_header_at":null,"magic_u32le":2970337281,"note":"block 0 is zlib unless bit 63 of its pointer is set"},"iso":{"disc_header_at":0,"magic":null},"rvz":{"disc_header_at":88,"magic":"RVZ\u0001","note":"first 0x80 disc bytes copied into header 2"},"wbfs":{"disc_header_at":null,"magic":"WBFS","note":"disc offset 0 at wlba[0] << wbfs_sector_shift"},"wia":{"disc_header_at":88,"magic":"WIA\u0001","note":"first 0x80 disc bytes copied into header 2"}},"re_read":true,"source_ref":"dolphin-emu/dolphin@0d93fc03 Source/Core/DiscIO/WIABlob.h:80-119, Source/Core/DiscIO/WIABlob.cpp:320-330, Source/Core/DiscIO/CISOBlob.cpp:66-69, Source/Core/DiscIO/CompressedBlob.cpp:140-150, Source/Core/DiscIO/WbfsBlob.cpp:148-155"},"iso9660":{"description":"Primary volume descriptor in sector 16 ('CD001' at offset 1), root directory record at PVD offset 156 (34 bytes). A file is found by name in the root directory, with the ';1' version suffix.","pvd_sector":16,"re_read":true,"root_record_offset":156,"source_ref":"stenzek/duckstation@526b4a12 src/util/iso_reader.cpp:68-90, src/util/iso_reader.h:60-99"},"zip":{"description":"The central directory gives each member's CRC-32 (offset 16) and uncompressed size (offset 24) without inflating. Python's zipfile reads it on open (ZipInfo.CRC, ZipInfo.file_size).","re_read":true,"source_ref":"python/cpython@fa919fdf Lib/zipfile.py:99-115, Lib/zipfile.py:1293-1347"}},"data_version":"6e5578928b20cfd8","fallback":{"amberelec":{"file":"fallback/amberelec.json","gzip_size":10532,"sha256":"ab0030080b1fed8ed6515cd0eea845ece9f7ba147760d6b2e9706a7907097400","size":48636},"batocera":{"file":"fallback/batocera.json","gzip_size":42010,"sha256":"6ce9e1d47d35c4a61f821a3088baeb6d8f5f2fdab8b1f624f9e5df3e42069017","size":308403},"bizhawk":{"file":"fallback/bizhawk.json","gzip_size":1944,"sha256":"152b14f3aff69714698a58837d6331ebcbcd3aaaa5f62939b9c743e535a319f4","size":7320},"emudeck":{"file":"fallback/emudeck.json","gzip_size":26125,"sha256":"8606f6a92147b42db10855a3c208344cc858f5914fa770c8f81cbb7d4cc66a4c","size":109272},"emuelec":{"file":"fallback/emuelec.json","gzip_size":15073,"sha256":"ac4c16deaf1fc55f5a1e0bea4edcef3528cfcbb387cb217a2c47a1b93ea34d9c","size":69392},"knulli":{"file":"fallback/knulli.json","gzip_size":39564,"sha256":"33a3953252a100066b0789bc0f81909b4c0fc0df21a4c3d17efed9728c1c30e7","size":266492},"minui":{"file":"fallback/minui.json","gzip_size":701,"sha256":"d68b30917db60263e57331271ebc33d00520dcbc15cdcaba8ccaf2901be2c870","size":2761},"misterfpga":{"file":"fallback/misterfpga.json","gzip_size":1898,"sha256":"b8f457378063d2f9b4010c2fefc21561df71e2e2d06f4ad1a7d945f4ad0a6f55","size":9569},"myminui":{"file":"fallback/myminui.json","gzip_size":1887,"sha256":"029242a5d03083b697c3c801f5a7f86687d62432fa925e0ec1c4759c3e3c20a5","size":7993},"nextui":{"file":"fallback/nextui.json","gzip_size":3088,"sha256":"3c28a4e3d67d5e5b653303419423c4326845b7e8b047c5f4ee1fdf44da0f5faf","size":15502},"recalbox":{"file":"fallback/recalbox.json","gzip_size":13622,"sha256":"2a3ff14a44a8247cb02ac012d6da69231d7629683962fc8878240bcb16896cd2","size":61681},"retroarch":{"file":"fallback/retroarch.json","gzip_size":44967,"sha256":"3e47ced745261b6b5ae30318e0b8fd5c709cc17096c5737276d0effee5406b74","size":217221},"retrobat":{"file":"fallback/retrobat.json","gzip_size":32746,"sha256":"3bd858147ab94890d7b4f7a8aab31183e0b3b7e22483cec9233cbd31ebb13023","size":138983},"retrodeck":{"file":"fallback/retrodeck.json","gzip_size":46568,"sha256":"5843ed5b3fdb1782908e0fc7ceed32d15882869de9965753b60a2c15b6cc41b6","size":239089},"retropie":{"file":"fallback/retropie.json","gzip_size":36894,"sha256":"6546b9111388b3e2e63598343eb4b39e840694dd0c77b8eda09e540db6ba026b","size":151630},"rocknix":{"file":"fallback/rocknix.json","gzip_size":9274,"sha256":"83a59961c7e5869fda2444f96870591dcf576f764d58f7bc5fe5e329e68a15b1","size":38952},"romm":{"file":"fallback/romm.json","gzip_size":6111,"sha256":"e4009ba31a3a5e08d7cf0c6cfcdfaa0e704faa19460d8e1c0fc169b745a4a15e","size":27444}},"folders":{"240ptestsuite":["nintendo-fds","nintendo-nes"],"2600":["atari-2600"],"2ship":["2ship"],"32x":["sega-32x"],"3d0":["panasonic-3do"],"3do":["panasonic-3do"],"3ds":["nintendo-3ds"],"5200":["atari-5200"],"64":["nintendo-64"],"64dd":["nintendo-64","nintendo-64dd"],"7800":["atari-7800"],"800":["atari-400-800"],"a2600":["atari-2600"],"a5200":["atari-5200"],"a7800":["atari-7800"],"a800":["atari-400-800"],"acclaim-zn1":["acclaim-zn1"],"acorn-archimedes":["acorn-archimedes"],"acorn-bbc-micro":["acorn-bbc-micro"],"acpc":["amstrad-cpc"],"actionmax":["arcade-laserdisc"],"adam":["coleco-adam"],"advision":["entex-advision"],"advmame":["arcade"],"agb":["nintendo-gba"],"ags":["ags"],"amiga":["commodore-amiga"],"amiga (puae)":["commodore-amiga","commodore-amiga-cd32","commodore-cdtv"],"amiga-cd32":["commodore-amiga-cd32"],"amiga1200":["commodore-amiga"],"amiga4000":["commodore-amiga"],"amiga500":["commodore-amiga"],"amiga600":["commodore-amiga"],"amigacd32":["commodore-amiga","commodore-amiga-cd32"],"amigacdtv":["commodore-amiga"],"amstrad":["amstrad-cpc"],"amstrad cpc (cpc)":["amstrad-cpc"],"amstrad-cpc":["amstrad-cpc"],"amstradcpc":["amstrad-cpc"],"amstradgx4000":["amstrad-cpc"],"apf-m1000":["apf-m1000"],"apfm1000":["apf-m1000"],"apple":["apple2"],"apple ii":["apple-ii"],"apple-ii":["apple-ii"],"apple-iigs":["apple-iigs"],"apple-ios":["apple-ios"],"apple-macintosh":["apple-macintosh"],"apple-macintosh-ii":["apple-macintosh-ii"],"apple2":["apple2"],"apple2gs":["apple-iigs"],"applemacintosh":["apple-macintosh"],"aquaplus-piece":["aquaplus-piece"],"aquarius":["mattel-aquarius"],"arcade":["arcade","capcom-cps1","capcom-cps2","capcom-cps3"],"arcade (mame)":["arcade"],"arcade-laserdisc":["arcade-laserdisc"],"arcadeatomiswave":["sammy-atomiswave"],"arcadehbmame":["arcade"],"arcadenaomi":["sammy-atomiswave"],"arcadeneogeo":["neogeo"],"arcadeneogeocd":["snk-neogeo-cd"],"arcadesegaatomiswave":["sammy-atomiswave"],"arcadeseganaomi":["sammy-atomiswave"],"arcadesnk":["neogeo"],"arcadesnkneogeo":["neogeo"],"arcadevertical":["arcade"],"arcadia":["emerson-arcadia-2001"],"arcatomiswave":["sammy-atomiswave"],"archimedes":["acorn-archimedes"],"arcnaomi":["sammy-atomiswave"],"arcneogeo":["neogeo"],"arcneogeocd":["snk-neogeo-cd"],"arcsegaatomiswave":["sammy-atomiswave"],"arcseganaomi":["sammy-atomiswave"],"arduboy":["arduboy"],"ast":["atari-st"],"aste":["atari-st"],"astrocade":["bally-astrocade"],"astrocde":["bally-astrocade"],"atari":["atari-2600"],"atari 2600 (a2600)":["atari-2600"],"atari 5200 (a5200)":["atari-5200"],"atari 7800":["atari-7800"],"atari 7800 (a7800)":["atari-7800"],"atari jaguar":["atari-jaguar"],"atari lynx (lynx)":["atari-lynx"],"atari st":["atari-st"],"atari-2600":["atari-2600"],"atari-2600-plus":["atari-2600"],"atari-400-800":["atari-400-800"],"atari-5200":["atari-5200"],"atari-7800":["atari-7800"],"atari-jaguar":["atari-jaguar"],"atari-jaguarcd":["atari-jaguarcd"],"atari-lynx":["atari-lynx"],"atari-lynx-mkii":["atari-lynx"],"atari-st":["atari-st"],"atari-zn1":["atari-zn1"],"atari2600":["atari-2600"],"atari5200":["atari-5200"],"atari5200 (a5200)":["atari-5200"],"atari7800":["atari-7800"],"atari7800 (a7800)":["atari-7800"],"atari800":["atari-400-800"],"atari8bit":["atari-400-800"],"atarifalcon":["atari-st"],"atarijaguar":["atari-jaguar"],"atarijaguarcd":["atari-jaguar","atari-jaguarcd"],"atarilynx":["atari-lynx"],"atarist":["atari-st"],"atariste":["atari-st"],"ataritt":["atari-st"],"atarixe":["atari-400-800"],"atarixegs":["xegs"],"atlus-zn1":["atlus-zn1"],"atom":["atom"],"atomiswave":["sammy-atomiswave","sega-dreamcast-arcade"],"aw":["sammy-atomiswave"],"bally-astrocade":["bally-astrocade"],"bandai-rx78":["bandai-rx78"],"bandai-wswan":["bandai-wswan"],"bandai-wswanc":["bandai-wswanc"],"bandaiwonderswan":["wonderswan"],"bandaiwonderswancolor":["wonderswan"],"bbc":["acorn-bbc-micro"],"bbcmicro":["acorn-bbc-micro"],"bbk":["bbk-longman-4980","bbk-longman-4988"],"bbk-longman-4980":["bbk-longman-4980"],"bbk-longman-4988":["bbk-longman-4988"],"beena":["sega-beena"],"bennugd":["bennugd"],"bermuda-syndrome":["bermuda-syndrome"],"bgb":["game-boy-color"],"bk":["elektronika-bk"],"blake-stone":["blake-stone"],"blood":["blood"],"bshift":["bshift"],"bstone":["blake-stone"],"bsx":["nintendo-satellaview"],"bsyndrome":["bermuda-syndrome"],"build":["blood","duke3d","exhumed","nam","powerslave","redneck","shadow-warrior","ww2gi"],"bws":["wonderswan"],"bwsc":["wonderswan"],"c-plus-4":["commodore-plus4"],"c128":["commodore-c128"],"c16":["commodore-plus4"],"c20":["commodore-vic20"],"c64":["commodore-c64"],"caesar3":["caesar3"],"camplynx":["camplynx"],"cannonball":["sega-outrun"],"capcom-cps1":["capcom-cps1"],"capcom-cps2":["capcom-cps2"],"capcom-cps3":["capcom-cps3"],"capcom-zn1":["capcom-zn1"],"capcom-zn2":["capcom-zn2"],"capcomcps1":["capcom-cps1"],"capcomcps2":["capcom-cps2"],"capcomcps3":["capcom-cps3"],"casio-loopy":["casio-loopy"],"casio-pv1000":["casio-pv1000"],"casio-pv2000":["casio-pv2000"],"casio_pv-1000":["casio-pv1000"],"casio_pv-2000":["casio-pv2000"],"casioloopy":["casio-loopy"],"cassettevision":["epochcv"],"catacomb":["catacomb-3d","catacomb-adventure"],"catacomb-3d":["catacomb-3d"],"catacomb-adventure":["catacomb-adventure"],"cave-story":["cave-story"],"cavestory":["cave-story"],"cbm-ii":["commodore-cbm-ii"],"cbmii":["commodore-cbm-ii"],"cd-i":["philips-cdi"],"cdi":["philips-cdi"],"cdimono1":["philips-cdi"],"cdtv":["commodore-amiga","commodore-cdtv"],"cgb":["nintendo-gbc"],"cgenie":["cgenie"],"cgenius":["commander-keen"],"channel f":["fairchild-channelf"],"channelf":["fairchild-channelf"],"chex":["chex"],"chf":["fairchild-channelf"],"chihiro":["sega-chihiro"],"chip-8":["chip8"],"chip8":["chip8"],"chipeight":["chip8"],"coco":["coco"],"coco3":["coco","coco3"],"coleco":["colecovision"],"coleco vision":["colecovision"],"coleco-adam":["coleco-adam"],"colecovision":["colecovision"],"colecovision (coleco)":["colecovision"],"commander-keen":["commander-keen"],"commanderx16":["commanderx16"],"commmodore-128":["commodore-c128"],"commodore":["commodore-c64"],"commodore 128 (c128)":["commodore-c128"],"commodore 64 (c64)":["commodore-c64"],"commodore pet (pet)":["commodore-pet"],"commodore plus4 (plus4)":["commodore-plus4"],"commodore vic20 (vic)":["commodore-vic20"],"commodore-64c":["commodore-c64"],"commodore-amiga":["commodore-amiga"],"commodore-amiga-cd32":["commodore-amiga-cd32"],"commodore-c128":["commodore-c128"],"commodore-c64":["commodore-c64"],"commodore-cbm-ii":["commodore-cbm-ii"],"commodore-cdtv":["commodore-cdtv"],"commodore-pet":["commodore-pet"],"commodore-plus4":["commodore-plus4"],"commodore-vic20":["commodore-vic20"],"commodore128":["commodore-c128"],"commodore64":["commodore-c64"],"commodoreamiga":["commodore-amiga"],"commodorec128":["commodore-c128"],"commodorec64":["commodore-c64"],"commodorecbmii":["commodore-cbm-ii"],"commodorepet":["commodore-pet"],"commodoreplus4":["commodore-plus4"],"commodorevic20":["commodore-vic20"],"corsixth":["theme-hospital"],"cougarboy":["mega-duck"],"cpc":["amstrad-cpc"],"cpet":["commodore-pet"],"cplus4":["commodore-plus4"],"cps":["arcade"],"cps1":["arcade","capcom-cps1"],"cps2":["arcade","capcom-cps2"],"cps3":["arcade","capcom-cps3"],"creativision":["crvision"],"crvision":["crvision"],"cstrike":["cstrike"],"cv":["colecovision"],"czero":["czero"],"czeror":["czeror"],"daphne":["arcade-laserdisc"],"dark-forces":["dark-forces"],"dark-forces-ii":["dark-forces-ii"],"dc":["sega-dreamcast"],"descent":["descent"],"descent2":["descent2"],"devilutionx":["diablo"],"diablo":["diablo"],"dice":["discrete-arcade"],"dinothawr":["dinothawr"],"discrete-arcade":["discrete-arcade"],"disksystem":["nintendo-fds"],"dmc":["dmc"],"dmg":["game-boy","nintendo-gb"],"doom":["doom"],"doom (doom)":["doom"],"doom (prboom)":["doom","heretic"],"doom3":["doom3"],"dos":["dos"],"dosbox":["dos"],"dragon":["coco","dragon64"],"dragon32":["coco","dragon32"],"dragon64":["coco","dragon64"],"dreamcast":["sega-dreamcast"],"dreamm":["dos","fmtowns","ibm-pc","tandy-1000"],"droidworks":["droidworks"],"ds":["nintendo-ds"],"dsi":["nintendo-ds","nintendo-dsi"],"duke3d":["duke3d"],"dusklight":["dusklight"],"dxx-rebirth":["descent","descent2"],"easyrpg":["rpgmaker"],"ecwolf":["wolfenstein3d"],"eduke32":["duke3d"],"eighthundred":["atari-400-800"],"eighting-zn1":["eighting-zn1"],"electron":["electron"],"elektor-tv-games-computer":["elektor-tv-games-computer"],"elektronika":["elektronika-bk"],"elektronika-bk":["elektronika-bk"],"elektronikabk":["elektronika-bk"],"emerson-arcadia-2001":["emerson-arcadia-2001"],"enemyterritory":["enemyterritory"],"enterprise":["enterprise-128","enterprise-64-128"],"enterprise-128":["enterprise-128"],"enterprise-64-128":["enterprise-64-128"],"enterprise128":["enterprise-128"],"entex-advision":["entex-advision"],"ep128":["enterprise-128"],"ep64-128":["enterprise-64-128"],"epochcv":["epochcv"],"epochsupercassettevision":["scv"],"epsxe":["sony-playstation"],"etlegacy":["enemyterritory"],"exelvision-exl100":["exelvision-exl100"],"exhumed":["exhumed"],"exl100":["exelvision-exl100"],"fairchild":["fairchild-channelf"],"fairchild-channel-f":["fairchild-channelf"],"fairchild-channelf":["fairchild-channelf"],"fairchildchannelf":["fairchild-channelf"],"fake08":["pico8"],"falcon":["atari-st"],"fallout":["fallout"],"fallout1-ce":["fallout"],"fallout2":["fallout2"],"fallout2-ce":["fallout2"],"famicom":["famicom","nintendo-nes"],"famicom disk system (fds)":["nintendo-fds"],"famicom-disk-system":["famicom-disk-system"],"famicomdisk":["nintendo-fds"],"famicomdisksystem":["famicom-disk-system"],"famicomds":["famicom-disk-system"],"fat plumber shit":["nintendo-nes"],"fba":["arcade"],"fbneo":["arcade"],"fbnneogeo":["neogeo"],"fc":["famicom","nintendo-fds","nintendo-nes"],"fcds":["famicom-disk-system"],"fcnes":["famicom"],"fds":["famicom-disk-system","nintendo-fds"],"fiftytwohundred":["atari-5200"],"finalburnneo":["arcade"],"flash":["flash"],"flashback":["flashback"],"flycast":["sega-dreamcast"],"fm-7":["fm7"],"fm7":["fm7"],"fmtowns":["fmtowns"],"fmtownsux":["fmtowns"],"fpinball":["fpinball"],"freej2me":["j2me"],"fury":["fury"],"galaksija":["galaksija"],"galretro":["galaksija"],"gamate":["gamate"],"game boy (gb)":["nintendo-gb"],"game boy advance (gba)":["nintendo-gba"],"game boy advance (mgba)":["nintendo-gba"],"game boy color (gbc)":["nintendo-gbc"],"game gear":["sega-gamegear"],"game-boy":["game-boy"],"game-boy-adavance-sp":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"game-boy-advance":["game-boy-advance"],"game-boy-color":["game-boy-color"],"game-boy-light":["nintendo-gb","nintendo-gbc"],"game-boy-micro":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"game-boy-pocket":["nintendo-gb","nintendo-gbc"],"game-televisison":["nintendo-fds","nintendo-nes"],"gameandwatch":["handheld-electronic"],"gameboy":["game-boy","nintendo-gb"],"gameboyadvance":["game-boy-advance","nintendo-gba"],"gameboycolor":["game-boy-color","nintendo-gbc"],"gamecom":["tiger-game-com"],"gamecube":["nintendo-gamecube"],"gamegear":["sega-gamegear"],"gamegearh":["sega-gamegear"],"gamegearhacks":["sega-gamegear"],"gameking":["gameking"],"gamemaster":["hartung-game-master"],"gamenwatch":["handheld-electronic"],"gamepark-gp32":["gamepark-gp32"],"gamepock":["gamepock"],"gamepocketcomputer":["gamepock"],"gametank":["gametank"],"gb":["game-boy","nintendo-gb","nintendo-gbc"],"gb2players":["nintendo-gb"],"gba":["game-boy-advance","nintendo-gba"],"gba2players":["nintendo-gba"],"gbadvance":["game-boy-advance"],"gbah":["nintendo-gba"],"gbahacks":["game-boy-advance"],"gbav":["nintendo-gb","nintendo-gba","nintendo-gbc","nintendo-sgb"],"gbc":["game-boy-color","nintendo-gb","nintendo-gbc"],"gbc2players":["nintendo-gbc"],"gbch":["nintendo-gbc"],"gbchacks":["game-boy-color"],"gbcolor":["game-boy-color"],"gbdmg":["game-boy"],"gbh":["nintendo-gb"],"gbhacks":["game-boy"],"gbsp":["game-boy-advance"],"gc":["nintendo-gamecube"],"gce":["vectrex"],"gcevectrex":["vectrex"],"gearbox":["gearbox"],"gen":["sega-megadrive"],"gen32x":["sega-32x"],"gencd":["sega-megacd"],"genesis":["sega-genesis","sega-megadrive"],"genesiscd":["sega-megacd"],"genesishacks":["sega-megadrive"],"genh":["sega-megadrive"],"genmd":["sega-megadrive"],"gens":["sega-megadrive"],"gensegacd":["sega-megacd"],"gg":["sega-gamegear"],"ggsms":["sega-mastersystem"],"ghostship":["ghostship"],"gmaster":["hartung-game-master"],"gp32":["gamepark-gp32"],"gt":["gametank"],"gw":["handheld-electronic"],"gx4000":["amstrad-cpc"],"gzdoom":["chex","doom","heretic","hexen","strife"],"half-life":["half-life"],"halflife":["half-life"],"handheld-electronic":["handheld-electronic"],"handheldelectronic":["handheld-electronic"],"harcade":["arcade"],"hartung-game-master":["hartung-game-master"],"hbmame":["arcade"],"heretic":["heretic"],"hexen":["hexen"],"hikaru":["sega-hikaru"],"horizontal":["arcade"],"horizontalarcade":["arcade"],"hyper-neogeo64":["hyper-neogeo64"],"ibm-pc":["ibm-pc"],"ibm-pcjr":["ibm-pcjr"],"idquake":["quake"],"idquake2":["quake2"],"igs-pgm":["igs-pgm"],"intelli":["intellivision"],"intellivision":["intellivision"],"interact":["interact"],"interton-vc4000":["interton-vc4000"],"intv":["intellivision"],"iortcw":["return-to-castle-wolfenstein"],"ios":["apple-ios"],"iphone":["apple-ios"],"ique-player":["nintendo-64","nintendo-64dd"],"itv":["intellivision"],"j2me":["j2me"],"jag":["atari-jaguar"],"jaguar":["atari-jaguar"],"jaguarcd":["atari-jaguarcd"],"java":["j2me"],"jazz-jackrabbit":["jazz-jackrabbit"],"jazz-jackrabbit-2":["jazz-jackrabbit-2"],"jazz2":["jazz-jackrabbit-2"],"jedi-academy":["jedi-academy"],"jediknight2":["jediknight2"],"jkdf2":["dark-forces-ii","droidworks","mysteries-of-the-sith"],"jknight":["jedi-academy","jediknight2"],"kega":["sega-megadrive"],"konami-gq":["konami-gq"],"konami-gv":["konami-gv"],"laser310":["laser310"],"laseractive":["laseractive"],"laserdisc":["arcade-laserdisc"],"libgametank":["gametank"],"lindbergh":["sega-lindbergh"],"loopy":["casio-loopy"],"lowresnx":["lowresnx"],"lucasart":["scummvm"],"lucasarts":["scummvm"],"lynx":["atari-lynx"],"mac":["apple-macintosh","apple-macintosh-ii"],"macintosh":["apple-macintosh"],"magnavox":["odyssey2"],"magnavoxodyssey":["odyssey2"],"magnavoxodyssey2":["odyssey2"],"magnavoxvideopac":["odyssey2"],"mame":["arcade"],"mame-advmame":["arcade"],"mame-libretro":["arcade"],"mame-mame4all":["arcade"],"mame2000":["arcade"],"mame2003":["arcade"],"mame2003plus":["arcade"],"mame2010":["arcade"],"mark3":["sega-mastersystem"],"marty":["marty"],"master-system-girl":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"master-system-super-compact":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"mastersystem":["sega-mastersystem"],"mastersystemhacks":["sega-mastersystem"],"mattel-aquarius":["mattel-aquarius"],"mattelintellivision":["intellivision"],"mc10":["mc10"],"md":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megadrive"],"md32x":["sega-32x"],"mdcd":["sega-megacd"],"mdgen":["sega-megadrive"],"mdmsu":["sega-megadrive"],"mdmsu1":["sega-megadrive"],"mdsegacd":["sega-megacd"],"mega-duck":["mega-duck"],"mega-pc":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"megacd":["sega-megacd"],"megacdjp":["sega-megacd"],"megachip8":["chip8"],"megadrive":["sega-genesis","sega-megadrive"],"megadrive-japan":["sega-megadrive"],"megadrive-msu":["sega-megacd"],"megadrivecd":["sega-megacd"],"megadriveh":["sega-megadrive"],"megadrivehacks":["sega-megadrive"],"megadrivejp":["sega-genesis","sega-megadrive"],"megadrivemsu":["sega-megadrive"],"megaduck":["mega-duck"],"mgba":["game-boy-advance","nintendo-gba"],"microsoft msx (msx)":["msx"],"microsoft-xbox":["microsoft-xbox"],"microsoft-xbox-360":["microsoft-xbox-360"],"microsoftdos":["dos"],"microsoftmsx":["msx"],"midp":["j2me"],"minivmac":["apple-macintosh"],"mkxp":["rpgmaker"],"mkxp-z":["rpgmaker"],"mobile":["j2me"],"model2":["sega-model2"],"model2/roms":["sega-model2"],"model3":["sega-model3"],"mohaa":["mohaa"],"moto":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"ms":["sega-mastersystem"],"msdos":["dos"],"msdos (dos)":["dos"],"msu":["nintendo-snes"],"msu-md":["sega-megacd"],"msu1":["nintendo-snes"],"msumd":["sega-megacd","sega-megadrive"],"msx":["msx"],"msx1":["msx","msx1"],"msx2":["msx","msx2"],"msx2+":["msx2+"],"msx2plus":["msx2plus"],"msxturbor":["msx","msxturbor"],"multivision":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"mysteries-of-the-sith":["mysteries-of-the-sith"],"myvision":["myvision"],"mz2000":["mz2000"],"mz2500":["mz2500"],"mz700":["mz700"],"mz800":["mz800"],"mz80k":["mz80k"],"n3ds":["nintendo-3ds"],"n64":["nintendo-64"],"n64dd":["nintendo-64","nintendo-64dd"],"n64hacks":["nintendo-64"],"nam":["nam"],"namco-system11":["namco-system11"],"namco-system246":["namco-system246"],"namco-system256":["namco-system256"],"namco-system357":["namco-system357"],"namco2x6":["namco-system246"],"naomi":["sammy-atomiswave","sega-dreamcast-arcade","sega-naomi"],"naomi2":["sega-naomi2"],"naomigd":["sega-dreamcast-arcade","sega-naomigd"],"native32":["sunplus-native32"],"nds":["nintendo-ds"],"ndsi":["nintendo-dsi"],"ndsiware":["nintendo-dsi"],"nec-pc-88":["nec-pc-88"],"nec-pc-engine":["nec-pc-engine"],"nec-pc-engine-cd":["nec-pc-engine-cd"],"nec-pcfx":["nec-pcfx"],"nec-supergrafx":["nec-supergrafx"],"necpc8000":["nec-pc-88","pc80"],"necpc98":["pc-98"],"necpce":["nec-pc-engine"],"necpcecd":["nec-pc-engine-cd"],"necpcengine":["nec-pc-engine"],"necpcenginecd":["nec-pc-engine-cd"],"necpcfx":["nec-pcfx"],"necsgfx":["nec-supergrafx"],"necsupergrafx":["nec-supergrafx"],"nectg16":["nec-pc-engine"],"nectgcd":["nec-pc-engine-cd"],"necturbografx":["nec-pc-engine"],"necturbografx16":["nec-pc-engine"],"necturbografxcd":["nec-pc-engine-cd"],"neo geo pocket (ngp)":["snk-ngp"],"neo geo pocket color (ngpc)":["snk-ngpc"],"neo-geo-cd":["snk-neogeo-cd"],"neo-geo-pocket":["snk-neogeo-pocket"],"neo-geo-pocket-color":["neo-geo-pocket-color"],"neocd":["snk-neogeo-cd"],"neocdz":["snk-neogeo-cd"],"neogeo":["neogeo"],"neogeo cd (ngcd)":["snk-neogeo-cd"],"neogeo-cd":["snk-neogeo-cd"],"neogeo64":["hyper-neogeo64"],"neogeoaes":["snk-neogeo-aes"],"neogeocd":["snk-neogeo-cd"],"neogeocdjp":["snk-neogeo-cd"],"neogeomvs":["snk-neogeo-mvs"],"neogeopocket":["snk-neogeo-pocket","snk-ngp"],"neogeopocketcolor":["snk-neogeo-pocket","snk-ngpc"],"nes":["famicom","nintendo-nes"],"nescd":["famicom"],"nesds":["famicom"],"nesfc":["famicom"],"nesh":["nintendo-nes"],"neshacks":["famicom"],"new-nintendo-3ds":["nintendo-3ds"],"new-style-nes":["nintendo-fds","nintendo-nes"],"new-style-super-nes-model-sns-101":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"ng":["neogeo"],"ngage":["ngage"],"ngb":["game-boy"],"ngba":["game-boy-advance"],"ngbc":["game-boy-color"],"ngc":["nintendo-gamecube","snk-ngp"],"ngcd":["snk-neogeo-cd"],"ngp":["snk-neogeo-pocket","snk-ngp","snk-ngpc"],"ngpc":["snk-neogeo-pocket","snk-ngp","snk-ngpc"],"ngpocket":["snk-neogeo-pocket"],"ngpocketcolor":["snk-neogeo-pocket"],"ngw":["handheld-electronic"],"ninds":["nintendo-ds"],"ninetyeight":["pc-98"],"ningba":["game-boy-advance"],"ningbc":["game-boy-color"],"ninnes":["famicom"],"ninsnes":["nintendo-satellaview"],"nintendo ds (nds)":["nintendo-ds"],"nintendo entertainment system (fc)":["nintendo-nes"],"nintendo-3ds":["nintendo-3ds"],"nintendo-64":["nintendo-64"],"nintendo-64dd":["nintendo-64dd"],"nintendo-ds":["nintendo-ds"],"nintendo-ds-lite":["nintendo-ds","nintendo-dsi"],"nintendo-dsi":["nintendo-dsi"],"nintendo-dsi-xl":["nintendo-ds","nintendo-dsi"],"nintendo-fds":["nintendo-fds"],"nintendo-gamecube":["nintendo-gamecube"],"nintendo-gb":["nintendo-gb"],"nintendo-gba":["nintendo-gba"],"nintendo-gbc":["nintendo-gbc"],"nintendo-nes":["nintendo-nes"],"nintendo-pokemon-mini":["nintendo-pokemon-mini"],"nintendo-satellaview":["nintendo-satellaview"],"nintendo-sgb":["nintendo-sgb"],"nintendo-snes":["nintendo-snes"],"nintendo-sufami-turbo":["nintendo-sufami-turbo"],"nintendo-switch":["nintendo-switch"],"nintendo-virtualboy":["nintendo-virtualboy"],"nintendo-wii":["nintendo-wii"],"nintendo-wiiu":["nintendo-wiiu"],"nintendo3ds":["nintendo-3ds"],"nintendo64":["nintendo-64"],"nintendods":["nintendo-ds"],"nintendodsi":["nintendo-ds","nintendo-dsi"],"nintendoentertainmentsystem":["famicom"],"nintendofamicom":["famicom"],"nintendofamicomdisksystem":["famicom-disk-system"],"nintendogameandwatch":["handheld-electronic"],"nintendogameboy":["game-boy"],"nintendogameboyadvance":["game-boy-advance"],"nintendogameboycolor":["game-boy-color"],"nintendogb":["game-boy"],"nintendogba":["game-boy-advance"],"nintendogbc":["game-boy-color"],"nintendogw":["handheld-electronic"],"nintendon64":["nintendo-64"],"nintendones":["famicom"],"nintendonintendo64":["nintendo-64"],"nintendonintendo64dd":["nintendo-64"],"nintendonintendodsi":["nintendo-ds"],"nintendonintendoentertainmentsystem":["famicom"],"nintendopokemini":["nintendo-pokemon-mini"],"nintendopokemonmini":["nintendo-pokemon-mini"],"nintendosfc":["nintendo-satellaview"],"nintendosnes":["nintendo-satellaview"],"nintendosnesmsu":["nintendo-satellaview"],"nintendosnesmsu1":["nintendo-satellaview"],"nintendosupernintendo":["nintendo-satellaview"],"nintendosupernintendoentertainmentsystem":["nintendo-satellaview"],"nintendovb":["nintendo-virtualboy"],"nintendovitrualboy":["nintendo-virtualboy"],"nomad":["sega-megadrive"],"nsnes":["nintendo-satellaview"],"nsv":["nintendo-satellaview"],"nvb":["nintendo-virtualboy"],"nxengine":["cave-story"],"o2":["philips-videopac"],"o2em":["odyssey2"],"odyssey":["odyssey2","philips-videopac"],"odyssey-2-slash-videopac-g7000":["odyssey2"],"odyssey2":["odyssey2"],"olivetti-pc128":["olivetti-pc128"],"onscripter":["onscripter"],"openbeatsofrage":["openbor"],"openbor":["openbor"],"opengoal":["opengoal"],"openjazz":["jazz-jackrabbit"],"openlara":["tomb-raider"],"oric":["oric"],"oricatmos":["oricatmos"],"originalgameboy":["game-boy"],"outlaws":["outlaws"],"outrun":["sega-outrun"],"p2000t":["philips-p2000t"],"p8":["pico8"],"palm":["palm-os"],"palm-os":["palm-os"],"palmos":["palm-os"],"panasonic":["panasonic-3do"],"panasonic-3do":["panasonic-3do"],"pbp":["sony-playstation"],"pbps":["sony-playstation"],"pc":["dos"],"pc engine":["nec-pc-engine"],"pc-8800":["nec-pc-88"],"pc-98":["pc-98"],"pc-9800":["pc-98"],"pc-9800-series":["pc-98"],"pc-fx":["nec-pcfx"],"pc60":["pc60"],"pc80":["pc80"],"pc8000":["nec-pc-88","pc80"],"pc88":["nec-pc-88"],"pc8801":["nec-pc-88"],"pc98":["pc-98"],"pce":["nec-pc-engine","nec-supergrafx"],"pcecd":["nec-pc-engine","nec-pc-engine-cd"],"pcengine":["nec-pc-engine"],"pcenginecd":["nec-pc-engine","nec-pc-engine-cd"],"pcfx":["nec-pcfx"],"pcninetyeight":["pc-98"],"pcsx":["sony-playstation"],"pcv2":["bandai-wswan","bandai-wswanc"],"pcw":["pcw"],"pdark":["pdark"],"pegasus":["pegasus"],"pet":["commodore-pet"],"pgm":["arcade","igs-pgm"],"philips-cd-i":["philips-cdi"],"philips-cdi":["philips-cdi"],"philips-p2000t":["philips-p2000t"],"philips-vg5k":["philips-vg5k"],"philips-videopac":["philips-videopac"],"philipscdi":["philips-cdi"],"pico":["pico8","sega-pico"],"pico-8":["pico8"],"pico-8 (p8)":["pico8"],"pico-8/carts":["pico8"],"pico8":["pico8"],"piece":["aquaplus-piece"],"pkm":["nintendo-pokemon-mini"],"playstation":["sony-playstation"],"playstationchds":["sony-playstation"],"playstationpbps":["sony-playstation"],"playstationportable":["sony-psp"],"plus4":["commodore-plus4"],"pocket-challenge-v2":["pocket-challenge-v2"],"pocketchallengev2":["pocket-challenge-v2"],"pocketstation":["sony-pocketstation"],"poke":["nintendo-pokemon-mini"],"pokemini":["nintendo-pokemon-mini"],"pokemon-mini":["nintendo-pokemon-mini"],"pokemonmini":["nintendo-pokemon-mini"],"pokémon mini (pkm)":["nintendo-pokemon-mini"],"ports":["wolfenstein3d"],"ports/caesar3":["caesar3"],"ports/cave story":["cave-story"],"ports/dinothawr":["dinothawr"],"ports/doom":["chex","doom","heretic","hexen","strife"],"ports/doom 3":["doom3"],"ports/ecwolf/games":["wolfenstein3d"],"ports/flashback":["flashback"],"ports/out run":["sega-outrun"],"ports/prince of persia":["prince-of-persia"],"ports/quake":["quake"],"ports/quake 2":["quake2"],"ports/quake 3":["quake3"],"ports/rick dangerous":["xrick"],"ports/star trek voyager":["quake3"],"ports/tamagotchi":["tamagotchi-p1"],"ports/theme hospital":["theme-hospital"],"ports/tomb raider":["tomb-raider"],"ports/vvvvvv":["vvvvvv"],"ports/wolfenstein 3d":["wolfenstein3d"],"powerslave":["powerslave"],"ppsspp":["sony-psp"],"prboom":["doom","heretic"],"primehack":["nintendo-gamecube","nintendo-wii"],"prince-of-persia":["prince-of-persia"],"ps":["sony-playstation"],"ps1":["sony-playstation"],"ps2":["sony-playstation-2"],"ps3":["sony-playstation-3"],"ps4":["ps4"],"ps4/shortcuts":["ps4"],"pschd":["sony-playstation"],"pschds":["sony-playstation"],"psiso":["sony-playstation"],"psisos":["sony-playstation"],"psone":["sony-playstation"],"psp":["sony-psp"],"pspbp":["sony-playstation"],"pspbps":["sony-playstation"],"pspminis":["sony-psp"],"psvita":["sony-playstation-vita"],"psx":["sony-playstation"],"psxchd":["sony-playstation"],"psxchds":["sony-playstation"],"psxiso":["sony-playstation"],"psxisos":["sony-playstation"],"psxpbp":["sony-playstation"],"psxpbps":["sony-playstation"],"puae":["commodore-amiga","commodore-amiga-cd32","commodore-cdtv"],"pv1000":["casio-pv1000"],"pv2000":["casio-pv2000"],"ql":["sinclair-ql"],"quake":["quake"],"quake (quake)":["quake"],"quake2":["quake2"],"quake3":["quake3"],"raze":["blood","duke3d","exhumed","nam","powerslave","redneck","shadow-warrior","ww2gi"],"redneck":["redneck"],"redream":["sega-dreamcast"],"reminiscence":["flashback"],"retcom":["galaksija"],"retro8":["pico8"],"return-to-castle-wolfenstein":["return-to-castle-wolfenstein"],"ricochet":["ricochet"],"rott":["rott"],"rpgmaker":["rpgmaker"],"rtcw":["return-to-castle-wolfenstein","rott"],"rx78":["bandai-rx78"],"s32x":["sega-32x"],"sam-coupe":["sam-coupe"],"samcoupe":["sam-coupe"],"sameduck":["mega-duck"],"sammy-atomiswave":["sammy-atomiswave"],"sat":["sega-saturn"],"satella":["nintendo-satellaview"],"satellaview":["nintendo-satellaview"],"satourne":["sega-saturn"],"saturn":["sega-saturn"],"saturnjp":["sega-saturn"],"sc-3000":["sega-sc3000"],"sc3000":["sega-sc3000"],"scd":["sega-megacd"],"scumm":["scummvm"],"scummvm":["scummvm"],"scummvm/shortcuts":["scummvm"],"scv":["scv"],"sdc":["sega-dreamcast"],"sdlpop":["prince-of-persia"],"sega 32x (32x)":["sega-32x"],"sega cd (segacd)":["sega-megacd"],"sega dreamcast":["sega-dreamcast"],"sega game gear (gg)":["sega-gamegear"],"sega genesis (md)":["sega-megadrive"],"sega master system (sms)":["sms"],"sega sg-1000 (sg1000)":["sega-sg1000"],"sega-32x":["sega-32x"],"sega-ai":["sega-ai"],"sega-beena":["sega-beena"],"sega-chihiro":["sega-chihiro"],"sega-dreamcast":["sega-dreamcast"],"sega-dreamcast-arcade":["sega-dreamcast-arcade"],"sega-game-box-9":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-gamegear":["sega-gamegear"],"sega-genesis":["sega-genesis"],"sega-hikaru":["sega-hikaru"],"sega-lindbergh":["sega-lindbergh"],"sega-mark-iii":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-master-system-ii":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-mastersystem":["sega-mastersystem"],"sega-mega-drive-2-slash-genesis":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-mega-jet":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-megacd":["sega-megacd"],"sega-megadrive":["sega-megadrive"],"sega-model2":["sega-model2"],"sega-model3":["sega-model3"],"sega-naomi":["sega-naomi"],"sega-naomi2":["sega-naomi2"],"sega-naomigd":["sega-naomigd"],"sega-nomad":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"sega-outrun":["sega-outrun"],"sega-pico":["sega-pico"],"sega-saturn":["sega-saturn"],"sega-sc3000":["sega-sc3000"],"sega-sf7000":["sega-sf7000"],"sega-sg1000":["sega-sg1000"],"sega-stv":["sega-stv"],"sega-systemsp":["sega-systemsp"],"sega-triforce":["sega-triforce"],"sega-vmu":["sega-vmu"],"sega32":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"sega32x":["sega-32x"],"sega32xjp":["sega-32x"],"sega32xna":["sega-32x"],"segaai":["sega-ai"],"segaatomiswave":["sammy-atomiswave"],"segacd":["sega-megacd"],"segadc":["sega-dreamcast"],"segadreamcast":["sega-dreamcast"],"segagamegear":["sega-gamegear"],"segagenesis":["sega-megadrive"],"segagenesismsu":["sega-megadrive"],"segagg":["sega-gamegear"],"segamastersystem":["sega-mastersystem"],"segamcd":["sega-megacd"],"segamdmsu":["sega-megadrive"],"segamegacd":["sega-megacd"],"segamegadrive":["sega-megadrive"],"segamodel3":["sega-model3"],"segams":["sega-mastersystem"],"seganaomi":["sammy-atomiswave"],"segapico":["sega-32x","sega-gamegear","sega-genesis","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sc3000","sega-sg1000"],"segasat":["sega-saturn"],"segasaturn":["sega-saturn"],"segascd":["sega-megacd"],"segasegacd":["sega-megacd"],"segasg1000":["sega-sg1000"],"segasgone":["sega-sg1000"],"segasms":["sega-mastersystem"],"segastv":["sega-stv"],"seggg":["sega-gamegear"],"segms":["sega-mastersystem"],"seventyeighthundred":["atari-7800"],"sfam":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"sfc":["nintendo-satellaview","nintendo-snes"],"sg-1000":["sega-sg1000"],"sg1000":["sega-sg1000"],"sg1k":["sega-sg1000"],"sgb":["nintendo-gb","nintendo-sgb"],"sgb-msu1":["nintendo-sgb"],"sgfx":["nec-pc-engine","nec-supergrafx"],"sgg":["sega-gamegear"],"sgonethousand":["sega-sg1000"],"sgx":["nec-pc-engine","nec-supergrafx"],"sgxcd":["nec-pc-engine"],"shadow-warrior":["shadow-warrior"],"sharp-x1":["sharp-x1"],"sharp-x68000":["sharp-x68000"],"sharpx1":["sharp-x1"],"sharpx6800":["sharp-x68000"],"sharpx68000":["sharp-x68000"],"sharpx68k":["sharp-x68000"],"sinclair-ql":["sinclair-ql"],"sinclair-spectrum":["sinclair-spectrum"],"sinclair-zx-spectrum":["sinclair-zx-spectrum"],"sinclair-zx-spectrum-next":["sinclair-zx-spectrum-next"],"sinclair-zx81":["sinclair-zx81"],"sinclairzx81":["sinclair-zx81"],"singe":["arcade-laserdisc"],"smbx":["smbx"],"sms":["sega-mastersystem","sms"],"smsgg":["sega-mastersystem"],"snes":["nintendo-satellaview","nintendo-snes"],"snes-hacks":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"snes-msu1":["nintendo-snes"],"snes9x":["nintendo-satellaview"],"snesh":["nintendo-snes"],"sneshacks":["nintendo-satellaview"],"snesmsu":["nintendo-satellaview"],"snesmsu1":["nintendo-satellaview","nintendo-snes"],"snesna":["nintendo-snes"],"sng":["neogeo"],"snk-neogeo-aes":["snk-neogeo-aes"],"snk-neogeo-cd":["snk-neogeo-cd"],"snk-neogeo-mvs":["snk-neogeo-mvs"],"snk-neogeo-pocket":["snk-neogeo-pocket"],"snk-ngp":["snk-ngp"],"snk-ngpc":["snk-ngpc"],"snkneogeo":["neogeo"],"snkneogeocd":["snk-neogeo-cd"],"snkneogeopocket":["snk-neogeo-pocket"],"snkneogeopocketcolor":["snk-neogeo-pocket"],"snkngcd":["snk-neogeo-cd"],"snkngp":["snk-neogeo-pocket"],"snkngpc":["snk-neogeo-pocket"],"socrates":["vtech-socrates"],"soh":["soh"],"solarus":["solarus"],"sonic-1-2013":["sonic-1-2013"],"sonic-2-2013":["sonic-2-2013"],"sonic-mania":["sonic-mania"],"sonic3-air":["sonic3-air"],"sonicretro":["sonic-1-2013","sonic-2-2013"],"sony playstation (ps)":["sony-playstation"],"sony-playstation":["sony-playstation"],"sony-playstation-2":["sony-playstation-2"],"sony-playstation-3":["sony-playstation-3"],"sony-playstation-vita":["sony-playstation-vita"],"sony-pocketstation":["sony-pocketstation"],"sony-psp":["sony-psp"],"sonyplaystation":["sony-playstation"],"sonyplaystationportable":["sony-psp"],"sonyps":["sony-playstation"],"sonyps1":["sony-playstation"],"sonypsp":["sony-psp"],"sonypsx":["sony-playstation"],"spec":["sinclair-zx-spectrum"],"spectravideo":["spectravideo"],"spectrum":["sinclair-spectrum","sinclair-zx-spectrum"],"spmp8000":["sunplus-spmp8000"],"ss":["sega-saturn"],"st":["atari-st"],"st-v":["sega-stv"],"star-control-2":["star-control-2"],"starship":["starship"],"ste":["atari-st"],"story":["onscripter"],"strife":["strife"],"studio-ii":["studio-ii"],"stv":["sega-stv"],"sufami":["nintendo-satellaview","nintendo-sufami-turbo"],"sufami-turbo":["nintendo-sufami-turbo"],"sufamiturbo":["nintendo-sufami-turbo"],"sunplus-native32":["sunplus-native32"],"sunplus-spmp8000":["sunplus-spmp8000"],"supa":["nintendo-snes"],"super game boy (sgb)":["nintendo-sgb"],"super nintendo entertainment system (sfc)":["nintendo-snes"],"super nintendo entertainment system (supa)":["nintendo-snes"],"super-famicom-jr-model-shvc-101":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"super-famicom-shvc-001":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"super-gb":["nintendo-sgb"],"super-mario-war":["super-mario-war"],"super-nintendo-original-european-version":["nintendo-satellaview","nintendo-snes","nintendo-sufami-turbo"],"superacan":["superacan"],"superbroswar":["super-mario-war"],"supercassettevision":["scv"],"superchip":["chip8"],"superfamicom":["nintendo-satellaview","nintendo-snes"],"supergameboy":["nintendo-sgb"],"supergrafx":["nec-supergrafx"],"supermariowar":["super-mario-war"],"supernes":["nintendo-satellaview","nintendo-snes"],"supernintendo":["nintendo-satellaview"],"supernintendoentertainmentsystem":["nintendo-satellaview"],"superpretendo":["nintendo-satellaview"],"supervision":["watara-supervision"],"supracan":["supracan"],"svi":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"svicoleco":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"svicolecovision":["colecovision","msx","msx2","msx2plus","msxturbor","sega-sc3000","sega-sf7000","sega-sg1000","spectravideo"],"swancrystal":["bandai-wswan","bandai-wswanc"],"switch":["nintendo-switch"],"symbian":["symbian"],"systemsp":["sega-systemsp"],"t80":["tic80"],"taito-fx1":["taito-fx1"],"tamagotchi-p1":["tamagotchi-p1"],"tandy-1000":["tandy-1000"],"tandy-vis":["tandy-vis"],"tandy1000":["tandy-1000"],"tanodragon":["dragon64"],"tecmo-tps":["tecmo-tps"],"teknoparrot":["namco-system246","namco-system256","namco-system357","sammy-atomiswave","sega-chihiro","sega-hikaru","sega-lindbergh","sega-naomi","sega-naomi2","sega-naomigd","sega-triforce"],"tera-drive":["sega-gamegear","sega-mastersystem","sega-megacd","sega-megadrive","sega-pico","sega-sg1000"],"texas-instruments-ti-83":["texas-instruments-ti-83"],"texasinstrumentsti83":["texas-instruments-ti-83"],"tfc":["tfc"],"tg":["nec-pc-engine"],"tg-cd":["nec-pc-engine-cd"],"tg16":["nec-pc-engine"],"tg16cd":["nec-pc-engine-cd"],"tgb_dual":["nintendo-gb"],"tgcd":["nec-pc-engine-cd"],"tgfx":["nec-pc-engine"],"tgfx16-cd":["nec-pc-engine-cd"],"tgrafx":["nec-pc-engine"],"tgrafx16":["nec-pc-engine"],"theforceengine":["dark-forces","outlaws"],"theme-hospital":["theme-hospital"],"theodore":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"thextech":["smbx"],"thirtytwox":["sega-32x"],"thomson":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"thomson-mo5":["thomson-mo5"],"thomson-mo6":["thomson-mo6"],"thomson-to7":["thomson-to7"],"thomson-to770":["thomson-to770"],"thomson-to8":["thomson-to8"],"thomson-to8d":["thomson-to8d"],"thomson-to9":["thomson-to9"],"thomson-to9plus":["thomson-to9plus"],"thomsonmoto":["olivetti-pc128","thomson-mo5","thomson-mo6","thomson-to7","thomson-to770","thomson-to8","thomson-to8d","thomson-to9","thomson-to9plus"],"ti-99_4a":["ti99"],"ti83":["texas-instruments-ti-83"],"ti99":["ti99"],"ti994a":["ti99"],"tic":["tic80"],"tic-80":["tic80"],"tic80":["tic80"],"tiger-game-com":["tiger-game-com"],"to8":["thomson-to8"],"tomb-raider":["tomb-raider"],"tomb-raider-1":["tomb-raider-1"],"tomb-raider-2":["tomb-raider-2"],"tombraider":["tomb-raider"],"traider1":["tomb-raider-1"],"traider2":["tomb-raider-2"],"triforce":["sega-triforce"],"trs-80":["trs80"],"trs80":["trs80"],"trs80coco":["coco"],"tt":["atari-st"],"turbocd":["nec-pc-engine-cd"],"turbografx":["nec-pc-engine"],"turbografx-16 (pce)":["nec-pc-engine"],"turbografx-cd":["nec-pc-engine"],"turbografx16":["nec-pc-engine"],"turbografxcd":["nec-pc-engine-cd"],"turbographix":["nec-pc-engine"],"tutor":["tutor"],"tvc":["videoton-tvc"],"tvgames":["tvgames"],"tvgc":["elektor-tv-games-computer","emerson-arcadia-2001","interton-vc4000"],"twentysixhundred":["atari-2600"],"tyrian":["tyrian"],"tyrquake":["quake"],"uqm":["star-control-2","ur-quan-masters"],"ur-quan-masters":["ur-quan-masters"],"uzebox":["uzebox"],"varcade":["arcade"],"vb":["nintendo-virtualboy"],"vc4000":["interton-vc4000"],"vec":["vectrex"],"vecrtex":["vectrex"],"vectrex":["vectrex"],"vemulator":["sega-vmu"],"vertarcade":["arcade"],"vertical":["arcade"],"verticalarcade":["arcade"],"vg5000":["philips-vg5k"],"vg5k":["philips-vg5k"],"vgmplay":["vgmplay"],"vic":["commodore-vic20"],"vic-20":["commodore-vic20"],"vic20":["commodore-vic20"],"videobrain":["videobrain"],"videopac":["odyssey2","philips-videopac"],"videopac-g7400":["philips-videopac"],"videopacplus":["philips-videopac"],"videosystem-zn1":["videosystem-zn1"],"videoton-tvc":["videoton-tvc"],"vircon32":["vircon32"],"virtboy":["nintendo-virtualboy"],"virtuaboy":["nintendo-virtualboy"],"virtual boy (vb)":["nintendo-virtualboy"],"virtualboy":["nintendo-virtualboy"],"vis":["tandy-vis"],"visualstory":["onscripter"],"vmac":["apple-macintosh"],"vmu":["sega-vmu"],"vpinball":["vpinball"],"vsmile":["vtech-vsmile"],"vtech-socrates":["vtech-socrates"],"vtech-vsmile":["vtech-vsmile"],"vvvvvv":["vvvvvv"],"watara":["watara-supervision"],"watara-supervision":["watara-supervision"],"watarasupervision":["watara-supervision"],"wii":["nintendo-wii"],"wiiu":["nintendo-wiiu"],"wiiu/roms":["nintendo-wiiu"],"wiiware":["nintendo-wii"],"windows3x":["dos","ibm-pc","ibm-pcjr","pc-98","tandy-1000"],"windows9x":["dos","ibm-pc","ibm-pcjr","pc-98","tandy-1000"],"wolf":["wolfenstein3d"],"wolf3d":["wolfenstein3d"],"wolfenstein":["wolfenstein3d"],"wolfenstein3d":["wolfenstein3d"],"wonderswan":["bandai-wswan","wonderswan","wonderswan-color"],"wonderswan-color":["wonderswan-color"],"wonderswanc":["wonderswan-color"],"wonderswancolor":["wonderswan","wonderswan-color"],"ws":["bandai-wswan","bandai-wswanc","wonderswan","wonderswan-color"],"wsc":["wonderswan","wonderswan-color"],"wswan":["bandai-wswan"],"wswanc":["bandai-wswanc"],"ww2gi":["ww2gi"],"x1":["sharp-x1"],"x16":["commanderx16"],"x68000":["sharp-x68000"],"x68k":["sharp-x68000"],"xash3d_fwgs":["bshift","cstrike","czero","czeror","dmc","gearbox","half-life","ricochet","tfc"],"xbox":["microsoft-xbox"],"xbox360":["microsoft-xbox-360"],"xbox360/roms":["microsoft-xbox-360"],"xegs":["xegs"],"xone":["sharp-x1"],"xrick":["xrick"],"xroar":["coco"],"zc210":["zc210"],"zeldac":["zeldaclassic"],"zeldaclassic":["zeldaclassic"],"zinc":["acclaim-zn1","atari-zn1","atlus-zn1","capcom-zn1","capcom-zn2","eighting-zn1","konami-gq","konami-gv","namco-system11","taito-fx1","tecmo-tps","videosystem-zn1"],"zmachine":["zmachine"],"zsnes":["nintendo-satellaview"],"zx spectrum (zxs)":["sinclair-zx-spectrum"],"zx81":["sinclair-zx81"],"zxeightyone":["sinclair-zx81"],"zxnext":["sinclair-zx-spectrum-next"],"zxs":["sinclair-zx-spectrum"],"zxspectrum":["sinclair-zx-spectrum"]},"format_version":1,"licences":[{"mirror":{"licence":"MIT","repo":"https://github.com/hugo19941994/auto-datfile-generator","scope":"the mirror's scripts only, the DATs it republishes stay under the terms above"},"quote":"Unless otherwise stated on the website, the data made available through this website (\"Data\") may be freely used, copied, reproduced, modified, adapted, combined, published, distributed, and otherwise reused by anyone for any lawful purpose, to the extent that the website operator owns or controls the applicable rights or is authorized to grant such permission. No permission, attribution, citation, backlink, or acknowledgment of the website or its operators is required for such use.","read":"2026-11-03","terms_title":"Data Usage License","terms_updated":"2026-09-11","terms_url":"https://datomatic.no-intro.org/terms.html"},{"quote":"Dumpers only submit metadata and Redump only stores metadata. This information is considered public domain to be used however people see fit","read":"2026-11-03","terms_url":"https://redump.info/about"}],"setups":{"allium":{"file":"setups/allium.json","gzip_size":5091,"sha256":"7e1b5914e15cc2ff710052fc7385fb9457ca955f5a633313d4ce4e8496b32033","size":35139},"amberelec":{"file":"setups/amberelec.json","gzip_size":5613,"sha256":"7c25ef2b727003a6ff285cb255286264acdc726fefbcea43f6f254ed708250be","size":38051},"archr":{"file":"setups/archr.json","gzip_size":7548,"sha256":"b5fe00e263b6df7c536260bbd8b7c41fe3e031a812f40644c8dacc93e049a88f","size":57318},"arkos":{"file":"setups/arkos.json","gzip_size":6069,"sha256":"0f4cf86ae6afb1ecb1c5019f8ac7c598044118b902f11aa9d8823e90ac2ca82d","size":39966},"batocera":{"file":"setups/batocera.json","gzip_size":14457,"sha256":"af163f68ee5069620ebf6b0fcb98ebd7ee721203c0dbf21d55244a024649d5fc","size":134476},"bizhawk":{"file":"setups/bizhawk.json","gzip_size":2469,"sha256":"1bd6306d2f485700b531d3d3ac502cbf36aaa9cfeb954f751ea3bb862aeb7aa9","size":16059},"chaos":{"file":"setups/chaos.json","gzip_size":5625,"sha256":"3a56b30c0992cd78eef8e097e9b1ef8aa479a664ea550d32d7777e18cbed0bb6","size":38023},"crossmix-os":{"file":"setups/crossmix-os.json","gzip_size":4628,"sha256":"8361175b1aebab116d878cc9117f531678969758c13a83b8ece2289c5eca9f46","size":30935},"darkos":{"file":"setups/darkos.json","gzip_size":5877,"sha256":"cc13afb7b04ac99eca20df747da975f55fb0757df63ef70b7923087f75f5a9df","size":37501},"emudeck":{"file":"setups/emudeck.json","gzip_size":8178,"sha256":"0a0d0b8a9c0fa9e6251dc28f88040ed6bc931a0f763ba1df0c07c72791995838","size":59403},"emudeck-windows":{"file":"setups/emudeck-windows.json","gzip_size":8145,"sha256":"e3b15545aafdc94411ba5cea61b6de9d9ce75889dff7ee6fefe3e63d4966fc17","size":60030},"emuelec":{"file":"setups/emuelec.json","gzip_size":7916,"sha256":"3117d2dd0ffb721e11f1e70385ed599f36d54c2d19db1dc598be52b5f8b73445","size":55398},"jelos":{"file":"setups/jelos.json","gzip_size":6646,"sha256":"52d5260b6ef397e1e41f957dc51808d8943848950322107336e886ae963bc2fd","size":47161},"knulli":{"file":"setups/knulli.json","gzip_size":11986,"sha256":"73cda1ec1afde3494896c2d82ae185eb0013721b817cf46293be84a7967900af","size":97205},"kolos":{"file":"setups/kolos.json","gzip_size":6170,"sha256":"1ab8b0c0a57bf6bb16f781bd1b97fe28e3c0d961a575af86546a482e5de4d150","size":43277},"koriki":{"file":"setups/koriki.json","gzip_size":4029,"sha256":"d2f15741cd1b16ac6f1f51dc1afa09a1831e6502b5d2ead7ee507a051ba414f1","size":22608},"lakka":{"file":"setups/lakka.json","gzip_size":517,"sha256":"3adec2a8c4f9a992e271382650338d00310db3de3bffd5448109c635ec03e2fd","size":1037},"minui":{"file":"setups/minui.json","gzip_size":2055,"sha256":"0a38d3d3b6d0fc16ed59a9fa420aba91a3402dc4ae584b349dc19076ad4818cc","size":10242},"misterfpga":{"file":"setups/misterfpga.json","gzip_size":3578,"sha256":"5c6e306970b67c12e6cc25c82328691fd13ad0c554ce1309efd1f0278158ad07","size":23518},"miyoocfw":{"file":"setups/miyoocfw.json","gzip_size":959,"sha256":"cb13cdcae35830c58d6465ff2f6e36c2d0558c576fd8eb8fd053537fb007573b","size":2285},"muos":{"file":"setups/muos.json","gzip_size":7386,"sha256":"3beffb9369d734978047ec64a440202704d9682bfe25c9c05e159c3b4618ed87","size":46601},"myminui":{"file":"setups/myminui.json","gzip_size":2797,"sha256":"8cac64f671ed745b8cd713be9e88b9f83e8e83061c32ff62fca646c91ea986ea","size":14717},"nextui":{"file":"setups/nextui.json","gzip_size":2950,"sha256":"e9eb9a3d06cc796bf54b185691144c828a2c7dc767a9b83c25fb310ca3b64d1d","size":15309},"onion":{"file":"setups/onion.json","gzip_size":6337,"sha256":"35cad2ef2a7162b93035cbeafd2ac881ba17a777ae11d05e16c4c4fb071071e8","size":34615},"pan4elec":{"file":"setups/pan4elec.json","gzip_size":5717,"sha256":"2534db783b7eb7037c4457fc9ae540d885aa6fdd3a59411df7856aeb64ef68b9","size":39455},"plumos-mf":{"file":"setups/plumos-mf.json","gzip_size":6141,"sha256":"5c2ae5292af66a32a16ad6c70ead6cbabef934c5e3e5261d6d92e9942bfd403b","size":33703},"plumos-pixel2":{"file":"setups/plumos-pixel2.json","gzip_size":6180,"sha256":"4c674898610e234f9a6711db34f9cebec91eaeb76d160e13a62eabd13a702720","size":31896},"recalbox":{"file":"setups/recalbox.json","gzip_size":9153,"sha256":"965c44508d9fe798954cdf392db0726e8b3be5796b0b5dea6b3a92aaba12bb47","size":69567},"retroarch":{"file":"setups/retroarch.json","gzip_size":476,"sha256":"025188a526422c7d79c996edc19c486c9b4f322798325a18405733066483b3d6","size":786},"retrobat":{"file":"setups/retrobat.json","gzip_size":10307,"sha256":"39e0945e6d33c1312f73b3b3ff26ee9a81d70d5061cd78a415ca87c0d68ad1b6","size":70854},"retrodeck":{"file":"setups/retrodeck.json","gzip_size":7183,"sha256":"f29336cedac2da9e8b1ccb89d9b608a9a8f147564ed6abafdaa8e0b4c922fbae","size":53597},"retropie":{"file":"setups/retropie.json","gzip_size":4670,"sha256":"f80f62e4d96cf62937da5f3e434fa6754bbf9eb17738b0d24062be7de9e5c4a2","size":24007},"rocknix":{"file":"setups/rocknix.json","gzip_size":7590,"sha256":"ff85bfdbdbc852265f5a7d71327e4df6512c53515a70add8d124f4ac3281689e","size":58836},"romm":{"file":"setups/romm.json","gzip_size":3790,"sha256":"73d2f0f4d95e9146ac9f850bf41e3a85bb133e543749dcecb785e80c67648946","size":30844},"spruceos":{"file":"setups/spruceos.json","gzip_size":6419,"sha256":"ccbe920491891b66c1db61e4c09abae154d367421856a8817d4c7e22111000c2","size":28367},"unofficialos":{"file":"setups/unofficialos.json","gzip_size":7152,"sha256":"bec913e663e25217e0a84db7bb0042a6f0b38d7d2a34d52e5de0c7a3fc5de4a6","size":51670}},"systems":{"atari-5200":{"file":"systems/atari-5200.json","gzip_size":4092,"sha256":"55bf18d45a6a7d75cda37ac27088b2510c4a27894157bca7f15452d67b5b76af","size":12435},"atari-7800":{"file":"systems/atari-7800.json","gzip_size":887,"sha256":"2ff726865df34502c72be99d18948dedd0782f19a38a215297c89c813d648481","size":1668},"atari-jaguar":{"file":"systems/atari-jaguar.json","gzip_size":292,"sha256":"a0215745664dcfdbe9f454e226561e61fdb8f60c0d72ba877b52e8f1b7929934","size":413},"atari-lynx":{"file":"systems/atari-lynx.json","gzip_size":1678,"sha256":"ab7cc8614064981951ddcca1c4a9d263b49b04fc0a89f2a984de08c20392a3d0","size":3634},"colecovision":{"file":"systems/colecovision.json","gzip_size":4412,"sha256":"9eb8ecd30e9877d6a36551ef03eb70b4151152023d0133a3b05109022d56151c","size":11293},"commodore-amiga":{"file":"systems/commodore-amiga.json","gzip_size":290,"sha256":"9988cce7dd6403204ab580edbc9522e5a9080c790bf04a98e6c3d435bbee42e3","size":788},"commodore-amiga-cd32":{"file":"systems/commodore-amiga-cd32.json","gzip_size":265,"sha256":"2c4d3823a40cdd4197209b2abaf38db755218130812f92c03ddad2ee0fd4a46d","size":456},"intellivision":{"file":"systems/intellivision.json","gzip_size":4507,"sha256":"748c7d7887370f16d5992fa7e53381108a24366584239543ccadf4347ccc8f01","size":12528},"laseractive":{"file":"systems/laseractive.json","gzip_size":363,"sha256":"d96ade3209fda8314cf9010a5ced458ad95037867fa204c8e457b05c46f5d80d","size":723},"msx":{"file":"systems/msx.json","gzip_size":214,"sha256":"e73b146104ffeb5ececb7173a5a3ce3903d0d0de1fde5e301658252c5675359b","size":285},"msx2plus":{"file":"systems/msx2plus.json","gzip_size":331,"sha256":"21b724cfbe529d2d992a7a633c570674c70753a42153befabe8c86c689b66c49","size":462},"nec-pc-engine":{"file":"systems/nec-pc-engine.json","gzip_size":9241,"sha256":"1fe6db213678d40878dfa6c411d1031319ef9f0d605b5653d1b4aa01e8a04452","size":27628},"nec-pc-engine-cd":{"file":"systems/nec-pc-engine-cd.json","gzip_size":12487,"sha256":"754e02b8e7e99135454008a89e883c9d6829a1f62cbc759abba2e5991866f9e9","size":43447},"nec-supergrafx":{"file":"systems/nec-supergrafx.json","gzip_size":831,"sha256":"111bd2ee40d75db1d140f263313bb6c97e31965883dbdf16906893e043f8d52d","size":1441},"neo-geo-pocket-color":{"file":"systems/neo-geo-pocket-color.json","gzip_size":3371,"sha256":"484bdf90a16917d464f28e8de1bbdce8d369c274d20d3d8c55ba0911a7a5e9ba","size":10072},"nintendo-3ds":{"file":"systems/nintendo-3ds.json","gzip_size":485,"sha256":"5e903462cea76f28681397aee0e6e3f119cd206ea60dd18ae734cbc5c5779cf7","size":808},"nintendo-64":{"file":"systems/nintendo-64.json","gzip_size":21504,"sha256":"24acf25d8c43e5227dc674057b41deffcc5c6db39f0f09e4ab258334749acd28","size":73974},"nintendo-64dd":{"file":"systems/nintendo-64dd.json","gzip_size":2541,"sha256":"82a62ff230513d4b3b7ec6bcb1ac8efe4101ff4e301dfea4300e13dea12cbc4a","size":7705},"nintendo-ds":{"file":"systems/nintendo-ds.json","gzip_size":186345,"sha256":"9f74ade6f2fff15b51c410ce83aafccdb3cb0c1701c9cd42a593ca84d1ab4c33","size":566900},"nintendo-dsi":{"file":"systems/nintendo-dsi.json","gzip_size":240,"sha256":"a470b580ca27fdf66bcf1213d3f7d3ab3acbf2a6272dd445a9ade5fc4cd4b569","size":345},"nintendo-fds":{"file":"systems/nintendo-fds.json","gzip_size":9025,"sha256":"59f40fb23866487b95f2a0b709b216c6c66de694f4528b0c4b53aae3fc1f4e7d","size":30626},"nintendo-gamecube":{"file":"systems/nintendo-gamecube.json","gzip_size":46580,"sha256":"afd0881edb18be56407268b9c2c6a6437e2670baa76203e4e03da33fac8ed4ee","size":189501},"nintendo-gb":{"file":"systems/nintendo-gb.json","gzip_size":39786,"sha256":"8cfeadc99c49af41435728dc1e5343ca14d632bcc4681e87f286ca41e3281868","size":127687},"nintendo-gba":{"file":"systems/nintendo-gba.json","gzip_size":76891,"sha256":"c254fa7973aa84f1b9e49f256437a03360d06ecf3b80838cae36bc5bbd84b80f","size":248499},"nintendo-gbc":{"file":"systems/nintendo-gbc.json","gzip_size":44917,"sha256":"3c281676ea9778761b00d454661d9fa7c5dfb70cbe435c1bb30158ef766d418f","size":154739},"nintendo-nes":{"file":"systems/nintendo-nes.json","gzip_size":89663,"sha256":"6e0e1d1f2681c10998518abe4b46cd2ea4a9f993316432876f19f8a52167e332","size":274177},"nintendo-pokemon-mini":{"file":"systems/nintendo-pokemon-mini.json","gzip_size":1537,"sha256":"083eed4eccdfcb12daab714d7cf3a595cbe7554010a7c79171916bc97b4611dc","size":4199},"nintendo-satellaview":{"file":"systems/nintendo-satellaview.json","gzip_size":13245,"sha256":"fc91880841ba301ff3fc2e7edfe53eed876edb33f9d7534d814d39dacd0a1654","size":51819},"nintendo-sgb":{"file":"systems/nintendo-sgb.json","gzip_size":746,"sha256":"617365112f8b93207b50323f761c4073d1c5aee87d877675822fb34247bab373","size":1621},"nintendo-snes":{"file":"systems/nintendo-snes.json","gzip_size":79838,"sha256":"5a1ffe5d5c958424793b77ce016c65205967f1d8ff910ffc6e8118f00b584001","size":249778},"nintendo-sufami-turbo":{"file":"systems/nintendo-sufami-turbo.json","gzip_size":1512,"sha256":"8070d9473708fee7ada3481daecd09e5389573652f1986e4a00275821337ac09","size":3210},"nintendo-wii":{"file":"systems/nintendo-wii.json","gzip_size":563,"sha256":"bff9fd15aa2896dbe9b5f60e713b04dd2d40dcfbee5dc8699a7ccec14536a466","size":1229},"odyssey2":{"file":"systems/odyssey2.json","gzip_size":3297,"sha256":"978953171a55509460854a4747ffbb94d9a0f16f0b2304abfe1aedbc3392582d","size":7851},"panasonic-3do":{"file":"systems/panasonic-3do.json","gzip_size":17243,"sha256":"38035ce01095a974ae7d0e1818f0d0c65f54cd89d326fa315893ef1062de9c0d","size":50013},"sega-32x":{"file":"systems/sega-32x.json","gzip_size":3894,"sha256":"6b0da0c37349c2340197d7a178f5862d942c43819f494ab2552e00e6dc83d360","size":16064},"sega-dreamcast":{"file":"systems/sega-dreamcast.json","gzip_size":36655,"sha256":"0041c8525fa27290841faa607ac8047e016f98896c5ff33b502495e8b37e14ed","size":122845},"sega-gamegear":{"file":"systems/sega-gamegear.json","gzip_size":14821,"sha256":"12ddb73bef81410d643f6b09ac0da2e49adb3dca8943f273f776d9c5c67583a2","size":54189},"sega-mastersystem":{"file":"systems/sega-mastersystem.json","gzip_size":14536,"sha256":"5669393a76b922ed2e14995c66c2804ccc7a1165a2416e50722c954aba560360","size":47411},"sega-megacd":{"file":"systems/sega-megacd.json","gzip_size":15396,"sha256":"ce94f85bf4ff3c8d4e58357c68cdb39a2b12d4b8052e61e77fd3189d2a3052c9","size":46794},"sega-megadrive":{"file":"systems/sega-megadrive.json","gzip_size":53279,"sha256":"10507cfccd4ec9fc2c63e71bbc83fda1001e565819665bb0b65d09f4506054bb","size":180871},"sega-naomi":{"file":"systems/sega-naomi.json","gzip_size":276,"sha256":"7da5520e2aa6c2f0e1e4e8f5417be5776d196960e793f740c3dd05ff37ab88e9","size":486},"sega-saturn":{"file":"systems/sega-saturn.json","gzip_size":66052,"sha256":"d3a87b71ce4771f0c4a93fa2d0621f100da77005b37e75faa541aec873a0f319","size":199102},"sega-stv":{"file":"systems/sega-stv.json","gzip_size":782,"sha256":"eb73b6449be6a70bf942f39c49322c03770ddd3bbb6a40f1add7f0ab90bd0841","size":2424},"sega-triforce":{"file":"systems/sega-triforce.json","gzip_size":286,"sha256":"7c68241a76bef2b4ff0cba2ea2f312250abc8585fcc52b41ced2bcbc76175726","size":539},"snk-neogeo-cd":{"file":"systems/snk-neogeo-cd.json","gzip_size":4649,"sha256":"ccc757ea85e9398347cc4ff1db29118a1923422aed21a7437d7c54806330fa8e","size":12370},"snk-neogeo-pocket":{"file":"systems/snk-neogeo-pocket.json","gzip_size":1070,"sha256":"c88819387ac6a344a017198e7bc2560fe306ba9f80350483dab29dd48a03342b","size":2179},"sony-playstation":{"file":"systems/sony-playstation.json","gzip_size":323936,"sha256":"e27d244a888c5246e00166eba8a893032cf96a85dff08905c77d696d997bd861","size":939819},"sony-playstation-2":{"file":"systems/sony-playstation-2.json","gzip_size":361140,"sha256":"410adb750ffbce2e2389facace712c1ad784cfa128da2763b5821ba5cc0ffac7","size":1075273},"vectrex":{"file":"systems/vectrex.json","gzip_size":1615,"sha256":"908725537d457bd597c180c61705f494209c412d728951944d86e504f40387ad","size":3457},"wonderswan":{"file":"systems/wonderswan.json","gzip_size":5961,"sha256":"e0949ae3fd96c11f54db7f56d1d9bc7b9613afe54d411ac16241095eb20f42ba","size":18778},"wonderswan-color":{"file":"systems/wonderswan-color.json","gzip_size":5618,"sha256":"41931c79d3546731ac4665f711c3d6296d30a26244be08e3bd9da01cbfdfa470","size":18027}}}
diff --git a/install/retrodeck.json b/install/retrodeck.json
index b70189e03..9ec577166 100644
--- a/install/retrodeck.json
+++ b/install/retrodeck.json
@@ -380,7 +380,11 @@
"reason": "no_save_system",
"cores": [
"trident"
- ]
+ ],
+ "systems": [
+ "nintendo-3ds"
+ ],
+ "held": true
},
{
"dest": "Trident/Emulator Files/sysdata/seeddb.bin",
@@ -2862,6 +2866,10 @@
"repo_path": "bios/Apple/Apple II/apple2gs.zip",
"cores": null,
"systems": [
+ "apple-ii",
+ "apple-iigs"
+ ],
+ "declared_in": [
"apple-ii"
],
"alternatives": [
@@ -3149,6 +3157,10 @@
"repo_path": "bios/Arcade/MAME/.variants/4dparprn.zip.c48d747c",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3292,6 +3304,10 @@
"repo_path": "bios/Arcade/Arcade/3dobios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3647,6 +3663,10 @@
"repo_path": "bios/Arcade/Arcade/a2ap16.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3669,6 +3689,10 @@
"repo_path": "bios/Arcade/Arcade/a2ap16a.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3691,6 +3715,10 @@
"repo_path": "bios/Arcade/Arcade/a2aevm80.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3713,6 +3741,10 @@
"repo_path": "bios/Arcade/MAME/a2booti.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3735,6 +3767,10 @@
"repo_path": "bios/Arcade/Arcade/a2aplcrd.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3757,6 +3793,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2bufgrapplerplus.zip.6fc70a25",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3790,6 +3830,10 @@
"repo_path": "bios/Arcade/Arcade/a2corvus.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3812,6 +3856,11 @@
"repo_path": "bios/Apple/Apple II/a2diskiing.zip",
"cores": null,
"systems": [
+ "apple-ii",
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"apple-ii",
"arcade"
],
@@ -3847,6 +3896,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2cffa2.zip.412c3834",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3891,6 +3944,10 @@
"repo_path": "bios/Apple/Apple II/a2cffa02.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3914,6 +3971,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2bufgrapplerplus.zip.6fc70a25",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3936,6 +3997,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2grappler.zip.7bb9144a",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3958,6 +4023,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2grapplerplus.zip.dbca76b5",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -3980,6 +4049,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2ieee488.zip.a7d7e258",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4002,6 +4075,10 @@
"repo_path": "bios/Arcade/MAME/a2q68.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4024,6 +4101,10 @@
"repo_path": "bios/Arcade/MAME/a2q68.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4046,6 +4127,10 @@
"repo_path": "bios/Arcade/Arcade/a2ramfac.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4112,6 +4197,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2scsi.zip.db6dbc79",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4156,6 +4245,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2ssc.zip.2a708d20",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4178,6 +4271,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2sider1.zip.17f6c1e2",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4200,6 +4297,10 @@
"repo_path": "bios/Arcade/MAME/a2superdrive.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4266,6 +4367,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2sider2.zip.c8ec70ff",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4310,6 +4415,10 @@
"repo_path": "bios/Arcade/Arcade/a2thunpl.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4332,6 +4441,10 @@
"repo_path": "bios/Arcade/Arcade/a2tmstho.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4376,6 +4489,10 @@
"repo_path": "bios/Arcade/MAME/a2vidtrm.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4398,6 +4515,10 @@
"repo_path": "bios/Arcade/Arcade/a2ultrme.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4420,6 +4541,10 @@
"repo_path": "bios/Arcade/Arcade/a2ulttrm.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4442,6 +4567,10 @@
"repo_path": "bios/Arcade/Arcade/a2vtc1.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4464,6 +4593,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2uniprint.zip.189b3977",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4508,6 +4641,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2vulgld.zip.3c35dfcc",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4530,6 +4667,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2vulcan.zip.ca1faf2b",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -4574,6 +4715,10 @@
"repo_path": "bios/Arcade/MAME/.variants/a2zipdrv.zip.d90e8d67",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -5300,6 +5445,22 @@
"repo_path": "bios/Arcade/MAME/abc830.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -5924,6 +6085,10 @@
"repo_path": "bios/Apple/Macintosh II/adbmodem.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6211,6 +6376,12 @@
"repo_path": "bios/Arcade/Arcade/.variants/airlbios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6277,6 +6448,12 @@
"repo_path": "bios/Arcade/Arcade/aleck64.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6313,6 +6490,10 @@
"repo_path": "bios/Arcade/Arcade/alg3do.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6335,6 +6516,12 @@
"repo_path": "bios/Arcade/Arcade/allied.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6368,6 +6555,12 @@
"repo_path": "bios/Arcade/Arcade/alg_bios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6656,6 +6849,13 @@
"repo_path": "bios/Arcade/Arcade/ap2000.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6700,6 +6900,11 @@
"repo_path": "bios/Arcade/MAME/aplcd150.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6722,6 +6927,10 @@
"repo_path": "bios/Arcade/MAME/.variants/aprissi.zip.f4b7587f",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -6755,6 +6964,12 @@
"repo_path": "bios/Arcade/Arcade/ar_bios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -7971,6 +8186,12 @@
"repo_path": "bios/Arcade/Arcade/aristmk5.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -8136,6 +8357,12 @@
"repo_path": "bios/Arcade/Arcade/atarisy1.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -8312,6 +8539,12 @@
"repo_path": "bios/Arcade/Arcade/aristmk6.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -8395,6 +8628,22 @@
"repo_path": "bios/Arcade/MAME/ax208p.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -8760,6 +9009,10 @@
"repo_path": "bios/Arcade/Arcade/bbc_beebspch.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -8782,6 +9035,10 @@
"repo_path": "bios/Arcade/MAME/bbc_chameleon.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -10179,6 +10436,12 @@
"repo_path": "bios/Arcade/Arcade/.variants/bubsys.zip.9a48e38c",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -10513,6 +10776,22 @@
"repo_path": "bios/Arcade/Arcade/c1571cr.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -10733,6 +11012,22 @@
"repo_path": "bios/Arcade/Arcade/c64_mscr.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -10854,6 +11149,22 @@
"repo_path": "bios/Arcade/MAME/c64_z80videopak.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -10876,6 +11187,22 @@
"repo_path": "bios/Arcade/Arcade/c64_xl80.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11240,6 +11567,10 @@
"repo_path": "bios/Arcade/Arcade/cd6809_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11306,6 +11637,11 @@
"repo_path": "bios/Arcade/MAME/cdd2000.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11328,6 +11664,10 @@
"repo_path": "bios/Arcade/MAME/.variants/ccs7710.zip.5aa34c6b",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11372,6 +11712,11 @@
"repo_path": "bios/Arcade/MAME/cdr4210.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11394,6 +11739,11 @@
"repo_path": "bios/Arcade/MAME/cdrn820s.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11463,6 +11813,11 @@
"repo_path": "bios/Arcade/MAME/cdu415.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11485,6 +11840,11 @@
"repo_path": "bios/Arcade/MAME/cdu75s.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11507,6 +11867,11 @@
"repo_path": "bios/Arcade/MAME/cdu561_25.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11640,6 +12005,11 @@
"repo_path": "bios/Arcade/MAME/cfp1080s.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11761,6 +12131,22 @@
"repo_path": "bios/Arcade/Arcade/cga.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -11883,6 +12269,13 @@
"repo_path": "bios/Arcade/MAME/chessmachine.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12204,6 +12597,10 @@
"repo_path": "bios/Arcade/MAME/.variants/coco_dcmodem.zip.3cd646b2",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12226,6 +12623,10 @@
"repo_path": "bios/Arcade/MAME/.variants/cmsscsi.zip.50055fab",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12248,6 +12649,11 @@
"repo_path": "bios/Arcade/MAME/coco_psg.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12270,6 +12676,11 @@
"repo_path": "bios/Arcade/Arcade/coco_orch90.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12303,6 +12714,10 @@
"repo_path": "bios/Arcade/MAME/.variants/coco_rs232.zip.5ea00bef",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12325,6 +12740,10 @@
"repo_path": "bios/Arcade/MAME/coco_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12358,6 +12777,10 @@
"repo_path": "bios/Arcade/MAME/coco_wpk.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12380,6 +12803,10 @@
"repo_path": "bios/Arcade/MAME/.variants/coco_scii.zip.c435d412",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12402,6 +12829,11 @@
"repo_path": "bios/Arcade/Arcade/coco_ssc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12424,6 +12856,10 @@
"repo_path": "bios/Arcade/MAME/.variants/coco_t4426.zip.ba47d47f",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12446,6 +12882,10 @@
"repo_path": "bios/Arcade/MAME/coco_wpk.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12468,6 +12908,10 @@
"repo_path": "bios/Arcade/MAME/coco_wpk.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -12947,6 +13391,13 @@
"repo_path": "bios/Arcade/Arcade/comx_pl80.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13013,6 +13464,11 @@
"repo_path": "bios/Arcade/MAME/cp2024.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13079,6 +13535,10 @@
"repo_path": "bios/Arcade/Arcade/cp450_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13420,6 +13880,11 @@
"repo_path": "bios/Arcade/MAME/crd254sh.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13519,6 +13984,12 @@
"repo_path": "bios/Arcade/Arcade/crysbios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13591,6 +14062,22 @@
"repo_path": "bios/Arcade/MAME/cuda302.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13635,6 +14122,22 @@
"repo_path": "bios/Arcade/MAME/cudalite.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13657,6 +14160,11 @@
"repo_path": "bios/Arcade/MAME/cw7501.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -13727,6 +14235,11 @@
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
"cores": null,
"systems": [
+ "apple-ii",
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"apple-ii",
"arcade"
],
@@ -14465,6 +14978,10 @@
"repo_path": "bios/Arcade/Arcade/dragon_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14487,6 +15004,10 @@
"repo_path": "bios/Arcade/Arcade/dragon_jcbsnd.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14509,6 +15030,10 @@
"repo_path": "bios/Arcade/MAME/dragon_jcbspch.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14553,6 +15078,10 @@
"repo_path": "bios/Arcade/MAME/.variants/dragon_serial.zip.86197dbe",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14575,6 +15104,10 @@
"repo_path": "bios/Arcade/MAME/dragon_sprites.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14597,6 +15130,22 @@
"repo_path": "bios/Arcade/MAME/ds1001.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -14938,6 +15487,10 @@
"repo_path": "bios/Apple/Macintosh/egret.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15367,6 +15920,10 @@
"repo_path": "bios/Arcade/MAME/enetlctp.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15389,6 +15946,10 @@
"repo_path": "bios/Arcade/MAME/enetlc.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15433,6 +15994,10 @@
"repo_path": "bios/Arcade/MAME/enetnbtp.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15499,6 +16064,13 @@
"repo_path": "bios/Arcade/MAME/epson_jx80.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15521,6 +16093,13 @@
"repo_path": "bios/Arcade/MAME/epson_fx80.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15543,6 +16122,10 @@
"repo_path": "bios/Enterprise/64-128/ep64_exdos.zip",
"cores": null,
"systems": [
+ "arcade",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15609,6 +16192,13 @@
"repo_path": "bios/Arcade/MAME/epson_rx80.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15950,6 +16540,13 @@
"repo_path": "bios/Arcade/Arcade/ex800.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -15972,6 +16569,12 @@
"repo_path": "bios/Arcade/Arcade/f355dlx.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16014,6 +16617,12 @@
"repo_path": "bios/Arcade/Arcade/f355bios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16355,6 +16964,12 @@
"repo_path": "bios/Arcade/Arcade/galgbios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16491,6 +17106,12 @@
"repo_path": "bios/Arcade/Arcade/gp_110.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16524,6 +17145,10 @@
"repo_path": "bios/Arcade/Arcade/gq863.zip",
"cores": null,
"systems": [
+ "arcade",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16593,6 +17218,12 @@
"repo_path": "bios/Arcade/Arcade/gts1.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -16868,6 +17499,10 @@
"repo_path": "bios/Arcade/MAME/bbc_lcd.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17000,6 +17635,14 @@
"repo_path": "bios/Arcade/MAME/heath_gp19_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17110,6 +17753,14 @@
"repo_path": "bios/Arcade/MAME/heath_super19_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17132,6 +17783,14 @@
"repo_path": "bios/Arcade/MAME/heath_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17154,6 +17813,14 @@
"repo_path": "bios/Arcade/MAME/heath_ultra_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17176,6 +17843,14 @@
"repo_path": "bios/Arcade/MAME/heath_imaginator_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17198,6 +17873,14 @@
"repo_path": "bios/Arcade/MAME/heath_watz_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17220,6 +17903,14 @@
"repo_path": "bios/Arcade/MAME/heath_superset_tlb.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17242,6 +17933,10 @@
"repo_path": "bios/Arcade/MAME/hng64.zip",
"cores": null,
"systems": [
+ "arcade",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17385,6 +18080,10 @@
"repo_path": "bios/Arcade/Arcade/hp9122c.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17429,6 +18128,12 @@
"repo_path": "bios/Arcade/Arcade/.variants/hod2bios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17479,6 +18184,10 @@
"repo_path": "bios/Arcade/MAME/hp9133.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17567,6 +18276,10 @@
"repo_path": "bios/Arcade/Arcade/hp9895.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17743,6 +18456,14 @@
"repo_path": "bios/Arcade/Arcade/a2232.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -17842,6 +18563,14 @@
"repo_path": "bios/Arcade/Arcade/ie15kbd.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -18513,6 +19242,12 @@
"repo_path": "bios/Arcade/Arcade/isgsm.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -18798,6 +19533,12 @@
"repo_path": "bios/Arcade/Arcade/.variants/iteagle.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19247,6 +19988,12 @@
"repo_path": "bios/Arcade/Arcade/.variants/konamigx.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19640,6 +20387,22 @@
"repo_path": "bios/Arcade/MAME/abc830.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19662,6 +20425,13 @@
"repo_path": "bios/Arcade/Arcade/lx810l.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19684,6 +20454,13 @@
"repo_path": "bios/Arcade/Arcade/lx800.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19816,6 +20593,10 @@
"repo_path": "bios/Arcade/Arcade/m68705p3.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -19992,6 +20773,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110a.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20014,6 +20799,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110a.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20058,6 +20847,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110a.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20080,6 +20873,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20102,6 +20899,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20124,6 +20925,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20146,6 +20951,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20168,6 +20977,10 @@
"repo_path": "bios/Apple/Macintosh/mackbd_m0110.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20190,6 +21003,10 @@
"repo_path": "bios/Apple/Macintosh II/mackbd_m0120.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20212,6 +21029,10 @@
"repo_path": "bios/Arcade/Arcade/mackbd.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20267,6 +21088,12 @@
"repo_path": "bios/Arcade/Arcade/macsbios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20319,6 +21146,12 @@
"repo_path": "bios/Arcade/Arcade/maxaflex.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20388,6 +21221,22 @@
"repo_path": "bios/Arcade/MAME/md_rom_svp.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20819,6 +21668,13 @@
"repo_path": "bios/Arcade/MAME/miuchiz.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "hartung-game-master",
+ "supracan",
+ "tiger-game-com"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20931,6 +21787,14 @@
"repo_path": "bios/Arcade/Arcade/mm5740.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -20976,6 +21840,14 @@
"repo_path": "bios/Arcade/MAME/mockingboardd.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -21603,6 +22475,22 @@
"repo_path": "bios/Arcade/Arcade/c64_cs.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -22318,6 +23206,13 @@
"repo_path": "bios/Arcade/MAME/mz1p16.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23112,6 +24007,10 @@
"repo_path": "bios/Arcade/Arcade/nb_aenet.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23198,6 +24097,10 @@
"repo_path": "bios/Arcade/Arcade/nb_image.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23220,6 +24123,10 @@
"repo_path": "bios/Arcade/MAME/nb_laserview.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23242,6 +24149,10 @@
"repo_path": "bios/Arcade/Arcade/nb_amc3b.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23264,6 +24175,10 @@
"repo_path": "bios/Arcade/Arcade/nb_m2hr.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23286,6 +24201,10 @@
"repo_path": "bios/Arcade/Arcade/nb_btbug.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23308,6 +24227,10 @@
"repo_path": "bios/Arcade/Arcade/nb_c264.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23330,6 +24253,10 @@
"repo_path": "bios/Arcade/Arcade/nb_m2vc.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23352,6 +24279,10 @@
"repo_path": "bios/Apple/Macintosh II/nb_mdc824.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23374,6 +24305,10 @@
"repo_path": "bios/Grundy/NewBrain/nb_48gc.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23396,6 +24331,10 @@
"repo_path": "bios/Arcade/Arcade/nb_qdlink.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23418,6 +24357,10 @@
"repo_path": "bios/Arcade/Arcade/nb_rtpd.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23440,6 +24383,10 @@
"repo_path": "bios/Arcade/MAME/nb_pcs8.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23462,6 +24409,10 @@
"repo_path": "bios/Arcade/Arcade/nb_sp8s3.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23484,6 +24435,10 @@
"repo_path": "bios/Arcade/Arcade/nb_spdq.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23506,6 +24461,10 @@
"repo_path": "bios/Arcade/MAME/nb_thungx.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23528,6 +24487,10 @@
"repo_path": "bios/Arcade/MAME/nb_wkstn.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23550,6 +24513,22 @@
"repo_path": "bios/Arcade/MAME/nb_thungx16.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23572,6 +24551,10 @@
"repo_path": "bios/Arcade/Arcade/nb_vikbw.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23638,6 +24621,10 @@
"repo_path": "bios/Arcade/Arcade/nb_wspt.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -23880,6 +24867,13 @@
"repo_path": "bios/Arcade/MAME/nlq401.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24059,6 +25053,14 @@
"repo_path": "bios/Arcade/MAME/nss_tvinterface.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24389,6 +25391,13 @@
"repo_path": "bios/Arcade/Arcade/p72.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24565,6 +25574,22 @@
"repo_path": "bios/Arcade/MAME/pc88va2_fd_if.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24906,6 +25931,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_30hr.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24928,6 +25957,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_lviw.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24950,6 +25983,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_mclr.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24972,6 +26009,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_30hr.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -24994,6 +26035,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_c264.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25016,6 +26061,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_mclr.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25038,6 +26087,10 @@
"repo_path": "bios/Arcade/MAME/pd3_pcs8.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25060,6 +26113,10 @@
"repo_path": "bios/Arcade/Arcade/pd3_pc16.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25082,6 +26139,10 @@
"repo_path": "bios/Arcade/MAME/pds30_emac.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25126,6 +26187,10 @@
"repo_path": "bios/Arcade/MAME/pdslc_macconlc.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25148,6 +26213,10 @@
"repo_path": "bios/Arcade/MAME/pds_hyper.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25170,6 +26239,10 @@
"repo_path": "bios/Arcade/Arcade/pds_sefp.zip",
"cores": null,
"systems": [
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25551,6 +26624,10 @@
"repo_path": "bios/Arcade/Arcade/premier_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -25980,6 +27057,11 @@
"repo_path": "bios/Arcade/MAME/px320a.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27466,6 +28548,22 @@
"repo_path": "bios/Arcade/MAME/saa5051.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27510,6 +28608,22 @@
"repo_path": "bios/Arcade/Arcade/saa5053.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27554,6 +28668,22 @@
"repo_path": "bios/Arcade/Arcade/saa5054.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27576,6 +28706,22 @@
"repo_path": "bios/Arcade/Arcade/saa5057.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27598,6 +28744,22 @@
"repo_path": "bios/Arcade/Arcade/saa5056.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27664,6 +28826,22 @@
"repo_path": "bios/Arcade/MAME/saa5243e.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27708,6 +28886,12 @@
"repo_path": "bios/Arcade/Arcade/sammymdl.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27890,6 +29074,14 @@
"repo_path": "bios/Arcade/MAME/scorpion_ic.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27945,6 +29137,10 @@
"repo_path": "bios/Arcade/Arcade/sdtandy_fdc.zip",
"cores": null,
"systems": [
+ "arcade",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -27989,6 +29185,22 @@
"repo_path": "bios/Arcade/Arcade/sed1200da.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28033,6 +29245,22 @@
"repo_path": "bios/Arcade/Arcade/sed1200db.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28242,6 +29470,12 @@
"repo_path": "bios/Arcade/Arcade/segasp.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28273,6 +29507,10 @@
"repo_path": "bios/Arcade/MAME/segadimm.zip",
"cores": null,
"systems": [
+ "arcade",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28439,6 +29677,12 @@
"repo_path": "bios/Arcade/Arcade/shtzone.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28637,6 +29881,11 @@
"repo_path": "bios/Arcade/MAME/smoc501.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28827,6 +30076,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp1bleg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28849,6 +30114,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp1leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28871,6 +30152,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp1leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28893,6 +30190,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp2leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28915,6 +30228,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp3leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28937,6 +30266,22 @@
"repo_path": "bios/Arcade/Arcade/sns_rom_sgb.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28959,6 +30304,22 @@
"repo_path": "bios/Arcade/Arcade/sns_rom_sgb2.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -28981,6 +30342,22 @@
"repo_path": "bios/Arcade/Arcade/sns_dsp4leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -29003,6 +30380,22 @@
"repo_path": "bios/Arcade/Arcade/sns_seta11leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -29025,6 +30418,22 @@
"repo_path": "bios/Arcade/Arcade/sns_seta10leg.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -30268,6 +31677,12 @@
"repo_path": "bios/Arcade/Arcade/su2000.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -30520,6 +31935,14 @@
"repo_path": "bios/Arcade/MAME/swtpc8212_device.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -30777,6 +32200,12 @@
"repo_path": "bios/Arcade/Arcade/taitotz.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -31651,6 +33080,12 @@
"repo_path": "bios/Arcade/Arcade/tourvis.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -31808,6 +33243,10 @@
"repo_path": "bios/Arcade/Arcade/triforce.zip",
"cores": null,
"systems": [
+ "arcade",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -32057,6 +33496,10 @@
"repo_path": "bios/Arcade/Arcade/upd7220.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -32123,6 +33566,12 @@
"repo_path": "bios/Arcade/Arcade/v4bios.zip",
"cores": null,
"systems": [
+ "3do",
+ "arcade",
+ "philips-cdi",
+ "triforce"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -32620,6 +34069,14 @@
"repo_path": "bios/Arcade/MAME/votraxtnt.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -32697,6 +34154,15 @@
"repo_path": "bios/Arcade/Arcade/votrax.zip",
"cores": null,
"systems": [
+ "apple-ii",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128"
+ ],
+ "declared_in": [
"apple-ii",
"arcade"
],
@@ -33379,6 +34845,22 @@
"repo_path": "bios/Arcade/MAME/ymf281.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33401,6 +34883,22 @@
"repo_path": "bios/Arcade/MAME/ym2423.zip",
"cores": null,
"systems": [
+ "3do",
+ "apple-iigs",
+ "apple-macintosh-ii",
+ "arcade",
+ "coco",
+ "dragon64",
+ "enterprise-64-128",
+ "epoch-scv",
+ "hartung-game-master",
+ "philips-cdi",
+ "tiger-game-com",
+ "triforce",
+ "vectrex",
+ "vtech-vsmile"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33423,6 +34921,11 @@
"repo_path": "bios/Arcade/MAME/ym2413.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coco",
+ "dragon64"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33555,6 +35058,11 @@
"repo_path": "bios/Arcade/MAME/zip100_ide.zip",
"cores": null,
"systems": [
+ "apple-iigs",
+ "arcade",
+ "coco"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33599,6 +35107,10 @@
"repo_path": "bios/SNK/Neo Geo CD/neocdz.zip",
"cores": null,
"systems": [
+ "arcade",
+ "snk-neogeo-cd"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33630,6 +35142,10 @@
"repo_path": "bios/Arcade/Arcade/coleco.zip",
"cores": null,
"systems": [
+ "arcade",
+ "coleco-colecovision"
+ ],
+ "declared_in": [
"arcade"
],
"alternatives": [
@@ -33918,6 +35434,10 @@
"repo_path": "bios/Atari/400-800/ROM_OS_BB02R3V4",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -33940,6 +35460,10 @@
"repo_path": "bios/Atari/400-800/ROM_OS_CC01R4",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -33984,6 +35508,10 @@
"repo_path": "bios/Atari/400-800/ROM_OS_BB01R59",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -34006,6 +35534,10 @@
"repo_path": "bios/Atari/400-800/ROM_OS_BB01R59A",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-400-800"
],
"alternatives": [
@@ -34105,6 +35637,10 @@
"repo_path": "bios/Atari/5200/5200.rom",
"cores": null,
"systems": [
+ "atari-400-800",
+ "atari-5200"
+ ],
+ "declared_in": [
"atari-5200"
],
"alternatives": [
@@ -35338,6 +36874,10 @@
"repo_path": "bios/Tandy/CoCo/cp400bas.rom",
"cores": null,
"systems": [
+ "coco",
+ "dragon64"
+ ],
+ "declared_in": [
"dragon64"
],
"alternatives": [
@@ -37857,6 +39397,11 @@
"repo_path": "bios/Nintendo/SNES/Satellaview_BS-X.sfc",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -37932,6 +39477,11 @@
"repo_path": "bios/Nintendo/Super Game Boy/SGB1.sfc/program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -37956,6 +39506,11 @@
"repo_path": "bios/Nintendo/Super Game Boy/SGB2.sfc/program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38047,6 +39602,11 @@
"repo_path": "bios/Nintendo/Game Boy/GB_sgb2.bin",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38114,6 +39674,11 @@
"repo_path": "bios/Nintendo/SNES/dsp1.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38143,6 +39708,11 @@
"repo_path": "bios/Nintendo/SNES/dsp1b.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38173,6 +39743,11 @@
"repo_path": "bios/Nintendo/SNES/dsp1b.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38203,6 +39778,11 @@
"repo_path": "bios/Nintendo/SNES/dsp2.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38233,6 +39813,11 @@
"repo_path": "bios/Nintendo/SNES/dsp2.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38263,6 +39848,11 @@
"repo_path": "bios/Nintendo/SNES/dsp3.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38293,6 +39883,11 @@
"repo_path": "bios/Nintendo/SNES/dsp3.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38323,6 +39918,11 @@
"repo_path": "bios/Nintendo/SNES/dsp4.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38353,6 +39953,11 @@
"repo_path": "bios/Nintendo/SNES/dsp4.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38383,6 +39988,11 @@
"repo_path": "bios/Nintendo/SNES/st010.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38413,6 +40023,11 @@
"repo_path": "bios/Nintendo/SNES/st010.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38443,6 +40058,11 @@
"repo_path": "bios/Nintendo/SNES/st011.data.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -38473,6 +40093,11 @@
"repo_path": "bios/Nintendo/SNES/st011.program.rom",
"cores": null,
"systems": [
+ "nintendo-gb",
+ "nintendo-gbc",
+ "nintendo-snes"
+ ],
+ "declared_in": [
"nintendo-snes"
],
"alternatives": [
@@ -39115,6 +40740,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-master-system"
+ ],
"region_system_groups": [
"sega-master-system"
],
@@ -39145,6 +40773,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -39177,6 +40808,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -39208,6 +40842,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sega-mega-cd"
+ ],
"region_system_groups": [
"sega-mega-cd"
],
@@ -40265,6 +41902,9 @@
"regions": [
"japan"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -40299,6 +41939,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -40334,6 +41977,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -40570,6 +42216,9 @@
"europe",
"oceania"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -40632,6 +42281,9 @@
"latin-america",
"north-america"
],
+ "region_groups": [
+ "sony-playstation"
+ ],
"region_system_groups": [
"sony-playstation"
],
@@ -119889,7 +121541,14 @@
],
"systems": [
"sony-playstation"
- ]
+ ],
+ "regions": [
+ "world"
+ ],
+ "region_groups": [
+ "sony-playstation"
+ ],
+ "priority": 200
},
{
"dest": "bios/epr-20091.ic8",
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index 907f0bb8f..ba948fc7a 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -1250,7 +1250,7 @@ def generate_pack(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
- if region_drops and dest in region_drops:
+ if region_drops and extra_region_key(fe, declared_root(config)) in region_drops:
continue
if not dest:
continue
@@ -4168,7 +4168,8 @@ def _manifest_core_entries(
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
if not dest:
continue
- if region_drops and dest in region_drops:
+ region_key = extra_region_key(fe, declared_root(config))
+ if region_drops and region_key in region_drops:
continue
full_dest = extra_full_destination(fe, extras_pfx)
if not full_dest:
@@ -4242,7 +4243,7 @@ def _manifest_core_entries(
entry, file_size = _manifest_entry(
local_path, manifest_dest, [source_emu] if source_emu else [],
db, repo_root,
- selection.fields(dest, fe.get("name", "")),
+ selection.fields(region_key, fe.get("name", "")),
)
if entry is not None and save_root:
entry.update(save_entry_fields(fe))
@@ -4356,7 +4357,8 @@ def _manifest_selection(
else set()
)
return drops, SelectionIndex.build(
- region_groups, region_index, pack_systems, extras, required_only
+ region_groups, region_index, pack_systems, extras, required_only,
+ extras_prefix=declared_root(config),
), held
@@ -4381,7 +4383,9 @@ def _record_absent(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe.get("name", "")))
- if not dest or (region_drops and dest in region_drops):
+ if not dest or (
+ region_drops and extra_region_key(fe, declared_root(config)) in region_drops
+ ):
continue
full_dest = extra_full_destination(fe, extras_pfx)
if not full_dest:
@@ -4576,8 +4580,10 @@ def generate_manifest(
reason: str,
cores: list[str] | None,
) -> None:
- bare = sanitize_pack_path(
- file_entry.get("destination", file_entry.get("name", ""))
+ # A core extra (cores given) is keyed as the region pass keys it.
+ bare = (
+ sanitize_pack_path(file_entry.get("destination", file_entry.get("name", "")))
+ if cores is None else extra_region_key(file_entry, declared_root(config))
)
save_root = file_entry.get("root") == "save"
omitted_by_destination[full_destination] = {
@@ -5464,6 +5470,7 @@ from packpaths import ( # noqa: E402,F401
from packextras import ( # noqa: E402,F401
ExtraResolver,
extra_full_destination,
+ extra_region_key,
prefixed_destination,
save_entry_fields,
save_manifest_dest,
diff --git a/scripts/manifestselect.py b/scripts/manifestselect.py
index cc6057421..5093957f1 100644
--- a/scripts/manifestselect.py
+++ b/scripts/manifestselect.py
@@ -19,7 +19,13 @@ from dataclasses import dataclass
import region as region_mod
from common import _norm_system_id, sanitize_pack_path
-from packextras import _kept, _serving_system_ids, extra_region_groups, system_spellings
+from packextras import (
+ _kept,
+ _serving_system_ids,
+ extra_region_groups,
+ extra_region_key,
+ system_spellings,
+)
def _dest(entry: dict) -> str:
@@ -44,6 +50,7 @@ class SelectionIndex:
pack_systems: dict[str, dict],
extras: list[dict],
required_only: bool = False,
+ extras_prefix: str = "",
) -> SelectionIndex:
by_norm: dict[str, set[str]] = {}
for sys_id in pack_systems:
@@ -60,7 +67,8 @@ class SelectionIndex:
extra_groups: dict[str, set[str]] = {}
spellings = system_spellings(pack_systems)
for extra in extras:
- dest = _dest(extra)
+ # Keyed as platform_region_groups keys it (extra_region_key).
+ dest = extra_region_key(extra, extras_prefix)
if not dest:
continue
extra_groups.setdefault(dest, set()).update(
diff --git a/scripts/packextras.py b/scripts/packextras.py
index 76ff19c1a..1fa563273 100644
--- a/scripts/packextras.py
+++ b/scripts/packextras.py
@@ -62,6 +62,20 @@ def prefixed_destination(dest: str, prefix: str) -> str:
return f"{prefix}/{dest}"
+def extra_region_key(fe: dict, prefix: str) -> str:
+ """The key a core extra is grouped, dropped and held under by --region.
+
+ Its destination with the BIOS directory the platform writes in front of
+ its own (declared_root): RetroDECK declares bios/scph5501.bin, and
+ Beetle PSX's scph5501.bin grouped bare was looked up under another key,
+ kept by the pack while the declaration of the same file was dropped,
+ and the installer, which records the path once, dropped it.
+ """
+ return prefixed_destination(
+ sanitize_pack_path(fe.get("destination", fe.get("name", ""))), prefix
+ )
+
+
def save_entry_fields(fe: dict) -> dict:
"""What a manifest entry adds for a file read below the save directory.
@@ -364,6 +378,7 @@ def hidden_extras(
content[dest.lower()] = sha1_by_path.get(local)
lower = set(content) if case_insensitive else set()
prefix = _detect_extras_prefix(config, base_dest)
+ region_prefix = declared_root(config)
hidden: dict[tuple[str, str, str], str] = {}
packed_keys: set[tuple[str, str, str]] = set()
extras = _collect_emulator_extras(
@@ -377,7 +392,7 @@ def hidden_extras(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe.get("name", "")))
- if not dest or (region_drops and dest in region_drops):
+ if not dest or (region_drops and extra_region_key(fe, region_prefix) in region_drops):
continue
full = extra_full_destination(fe, prefix)
if not full:
@@ -1705,8 +1720,9 @@ def platform_region_groups(
)
held = {id(extra) for extra in extras}
spellings = system_spellings(systems)
+ region_prefix = declared_root(config)
for extra in _kept(extras + absent, required_only):
- dest = sanitize_pack_path(extra.get("destination", extra.get("name", "")))
+ dest = extra_region_key(extra, region_prefix)
if not dest:
continue
name = extra.get("name", "")
diff --git a/tests/test_install_selection.py b/tests/test_install_selection.py
index 905c5e3ce..71dbd5725 100644
--- a/tests/test_install_selection.py
+++ b/tests/test_install_selection.py
@@ -1148,6 +1148,99 @@ class AStandaloneLayoutBelowTheBiosFolder(unittest.TestCase):
self.assertEqual({f["dest"] for f in files}, {f["dest"] for f in built["files"]})
+class AnExtraBesideItsDeclarationBelowTheBiosFolder(unittest.TestCase):
+ """RetroDECK declares bios/scph5501.bin and writes core files below bios/.
+ Beetle PSX's scph5501.bin was grouped bare, a key whose region lookup
+ another core leaves untagged, while the declaration's key resolved to
+ DuckStation's American tag: `--region japan` dropped the declaration and
+ the pack kept the file through the core's claim, while the installer,
+ which records the path once, dropped it."""
+
+ def setUp(self):
+ import common
+ import generate_db
+ import generate_pack
+
+ self.gp = generate_pack
+ tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
+ self.addCleanup(tmp.cleanup)
+ previous = os.getcwd()
+ os.chdir(tmp.name)
+ self.addCleanup(os.chdir, previous)
+ Path("bios/Sys").mkdir(parents=True)
+ files = {}
+ for name in ("us.bin", "jp.bin"):
+ payload = name.encode()
+ Path(f"bios/Sys/{name}").write_bytes(payload)
+ sha1 = hashlib.sha1(payload).hexdigest()
+ files[sha1] = {"path": f"bios/Sys/{name}", "name": name,
+ "size": len(payload), "sha1": sha1,
+ "md5": hashlib.md5(payload).hexdigest(),
+ "sha256": hashlib.sha256(payload).hexdigest(),
+ "crc32": "00000001"}
+ self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
+ Path("platforms").mkdir()
+ Path("platforms/p.yml").write_text(json.dumps({
+ "platform": "P", "version": "2.1", "verification_mode": "existence",
+ "base_destination": "", "cores": ["beetle", "dsa", "other"],
+ "standalone_cores": ["dsa"], "systems": {"sys": {"files": [
+ {"name": name, "destination": f"bios/{name}", "required": False}
+ for name in ("us.bin", "jp.bin")
+ ]}},
+ }))
+ Path("platforms/_registry.yml").write_text(
+ json.dumps({"platforms": {"p": {"status": "active"}}})
+ )
+ Path("emulators").mkdir()
+ Path("emulators/dsa.yml").write_text(json.dumps({
+ "emulator": "dsa", "type": "standalone + libretro", "systems": ["sys"],
+ "files": [
+ {"name": name, "standalone_path": f"bios/{name}", "system": "sys",
+ "region": [region_name], "required": False}
+ for name, region_name in (("us.bin", "north-america"), ("jp.bin", "japan"))
+ ]}))
+ # Read before dsa, as beetle_psx is before duckstation, and untagged
+ # by name through a second reader, as pcsx1 leaves scph5501.bin.
+ Path("emulators/beetle.yml").write_text(json.dumps({
+ "emulator": "beetle", "type": "libretro", "systems": ["sys"], "files": [
+ {"name": "us.bin", "system": "sys", "region": ["north-america"],
+ "required": False},
+ ]}))
+ Path("emulators/other.yml").write_text(json.dumps({
+ "emulator": "other", "type": "libretro", "systems": ["sys"], "files": [
+ {"name": "us.bin", "path": "alt/us.bin", "system": "sys", "required": False},
+ ]}))
+ common._platform_config_cache.clear()
+ common._emulator_profiles_cache.clear()
+ self.addCleanup(common._platform_config_cache.clear)
+ self.addCleanup(common._emulator_profiles_cache.clear)
+ self.profiles = common.load_emulator_profiles("emulators")
+
+ def _manifest(self, regions):
+ return self.gp.generate_manifest(
+ "p", "platforms", self.db, "bios", "platforms/_registry.yml",
+ emulators_dir="emulators", emu_profiles=self.profiles,
+ regions=regions, offline=True,
+ )
+
+ def _pack(self, regions):
+ record = self.gp.PackRecord()
+ self.gp.generate_pack(
+ "p", "platforms", self.db, "bios", "", emulators_dir="emulators",
+ emu_profiles=self.profiles, regions=regions, offline=True, record=record,
+ )
+ return {m for m in record.members if m.startswith("bios/")}
+
+ def test_the_pack_and_the_installer_drop_the_same_files(self):
+ full = self._manifest(None)
+ files, _omitted = install.narrow(
+ full["files"], full["omitted_files"], [], [], ["japan"]
+ )
+ installed = {f["dest"] for f in files if f["dest"].startswith("bios/")}
+ self.assertIn("bios/jp.bin", installed)
+ self.assertEqual(self._pack(["japan"]), installed)
+
+
class ACoreWithNothingHeldIsAnOmission(unittest.TestCase):
"""DOSBox serves SC-55/WAVEROM3.BIN, DOSBox Pure wants it and nothing is
held for it. A pack built for a target without DOSBox lists it as left
From ada7738fa77e5896c69bd8cad933e31bd1435c07 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:02:18 +0100
Subject: [PATCH 64/83] feat: pin_installer writes the installer pins
Every change to install.py meant a sha256sum pasted by hand into
install.sh and install.ps1, and the tests that caught a stale pin
failed on two bare hashes. scripts/pin_installer.py writes both pins
(--check only reports), the pin tests name it, check_freshness reads
the pins through it and refresh_stale runs it for a stale pin row.
---
scripts/check_freshness.py | 17 ++++----
scripts/pin_installer.py | 82 +++++++++++++++++++++++++++++++++++++
scripts/refresh_stale.py | 7 +++-
tests/test_install.py | 31 +++++++++++++-
tests/test_refresh_stale.py | 5 +++
wiki/installer.md | 4 +-
wiki/tools.md | 1 +
7 files changed, 133 insertions(+), 14 deletions(-)
create mode 100644 scripts/pin_installer.py
diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py
index 2fbee0d48..8f1ca775f 100644
--- a/scripts/check_freshness.py
+++ b/scripts/check_freshness.py
@@ -32,7 +32,6 @@ from __future__ import annotations
import argparse
import contextlib
-import hashlib
import io
import json
import re
@@ -51,6 +50,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parent))
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import export_native # noqa: E402
+import pin_installer # noqa: E402
import refresh_data_dirs # noqa: E402
import upstream # noqa: E402
from common import ( # noqa: E402
@@ -83,7 +83,6 @@ PYPI_URL = "https://pypi.org/pypi/{name}/json"
NPM_URL = "https://registry.npmjs.org/{name}/latest"
# The site's npm dependencies, pinned to exact versions and built by Deploy Site.
SITE_PACKAGE = REPO_ROOT / "website" / "package.json"
-INSTALLERS = ("install.sh", "install.ps1")
SHOWN_ITEMS = 4 # items named in a diff summary before ", ..."
SHOWN_NAMES = 12 # core names named in an unresolved row before ", ..."
@@ -1465,18 +1464,16 @@ def check_ci(cache_dir: str, offline: bool) -> list[Finding]:
def _check_installer_pins() -> Finding:
"""The bootstraps pin install.py by SHA-256, so a stale pin refuses every install."""
- digest = hashlib.sha256((REPO_ROOT / "install.py").read_bytes()).hexdigest()
- stale = []
- for name in INSTALLERS:
- text = (REPO_ROOT / name).read_text(encoding="utf-8", errors="replace")
- if digest not in text:
- stale.append(name)
+ stale = pin_installer.stale_pins(REPO_ROOT)
return Finding(
"ci",
"install.py pin",
STALE if stale else OK,
- local=digest[:12],
- detail=("pin outdated in " + ", ".join(stale)) if stale else "install.sh and install.ps1 match",
+ local=pin_installer.installer_sha256(REPO_ROOT)[:12],
+ detail=(
+ f"pin outdated in {', '.join(stale)}, {pin_installer.COMMAND} writes it"
+ if stale else "install.sh and install.ps1 match"
+ ),
)
diff --git a/scripts/pin_installer.py b/scripts/pin_installer.py
new file mode 100644
index 000000000..07e366cf0
--- /dev/null
+++ b/scripts/pin_installer.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+"""Write the SHA-256 of install.py into the bootstraps that pin it.
+
+install.sh and install.ps1 refuse an installer whose hash is not the one
+they carry, so every change to install.py moves both pins in the same
+commit. --check writes nothing and exits 1 naming each stale pin.
+
+Usage:
+ python scripts/pin_installer.py
+ python scripts/pin_installer.py --check
+"""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import re
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+INSTALLER = "install.py"
+# Each bootstrap and its one pin line, the value between the two groups.
+PINS: dict[str, re.Pattern[str]] = {
+ "install.sh": re.compile(r'^(DEFAULT_INSTALL_SHA256=")[0-9a-f]{64}(")', re.M),
+ "install.ps1": re.compile(r'^(\s*\$defaultInstallSha256 = ")[0-9a-f]{64}(")', re.M),
+}
+COMMAND = "python scripts/pin_installer.py"
+
+
+def installer_sha256(root: Path = ROOT) -> str:
+ return hashlib.sha256((root / INSTALLER).read_bytes()).hexdigest()
+
+
+def stale_pins(root: Path = ROOT) -> list[str]:
+ """The bootstraps whose pin is not the SHA-256 of install.py."""
+ digest = installer_sha256(root)
+ stale = []
+ for name, pin in PINS.items():
+ found = pin.search((root / name).read_bytes().decode("utf-8"))
+ if found is None:
+ raise ValueError(f"{name}: no installer pin line")
+ if found.group(0) != f"{found.group(1)}{digest}{found.group(2)}":
+ stale.append(name)
+ return stale
+
+
+def write_pins(root: Path = ROOT) -> list[str]:
+ """Rewrite each stale pin. Returns the bootstraps written."""
+ digest = installer_sha256(root)
+ written = []
+ for name in stale_pins(root):
+ path = root / name
+ text = path.read_bytes().decode("utf-8")
+ new, count = PINS[name].subn(rf"\g<1>{digest}\g<2>", text)
+ if count != 1:
+ raise ValueError(f"{name}: {count} installer pin lines, expected 1")
+ path.write_bytes(new.encode("utf-8"))
+ written.append(name)
+ return written
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.split("\n\n")[0])
+ parser.add_argument("--check", action="store_true",
+ help="write nothing, exit 1 if a pin is stale")
+ args = parser.parse_args()
+ if args.check:
+ stale = stale_pins()
+ for name in stale:
+ print(f"{name}: pin is not the SHA-256 of {INSTALLER}, {COMMAND} writes it",
+ file=sys.stderr)
+ return 1 if stale else 0
+ for name in write_pins():
+ print(f"{name}: pinned {installer_sha256()}")
+ return 0
+
+
+if __name__ == "__main__":
+ from common import run_cli
+
+ run_cli(main)
diff --git a/scripts/refresh_stale.py b/scripts/refresh_stale.py
index 960b2c3da..5ec112efc 100755
--- a/scripts/refresh_stale.py
+++ b/scripts/refresh_stale.py
@@ -34,7 +34,8 @@ has ended, and its export is rewritten even when no row named it.
Surfaced only (no refresh): data rows that are not a _data_dirs.yml key
(the registry itself, buildbot assets it does not track), coreinfo gaps, redump/no-intro/tosec packs,
-CI pins (install.py SHA-256, PyPI, pinned actions), profile_sync, rom-folder
+CI pins (PyPI, pinned actions; the install.py SHA-256 pin is written by
+scripts/pin_installer.py), profile_sync, rom-folder
pins (moved by hand, then python -m scripts.scraper.romfolders --setup NAME
reads them again). Each needs
a human read (new .info file, manual DAT download, PyPI version bump).
@@ -401,6 +402,10 @@ def _command_for(
"--force",
]
+ if area == "ci" and subject == "install.py pin":
+ # The pin is the hash of the committed install.py, nothing to judge.
+ return [sys.executable, "scripts/pin_installer.py"]
+
if area == "catalogs":
if subject == "mame recipes":
return [
diff --git a/tests/test_install.py b/tests/test_install.py
index f36389a1e..f128216e6 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -36,6 +36,9 @@ _spec.loader.exec_module(install)
sys.path.insert(0, str(REPO_ROOT / "tests"))
from netguard import module_guard # noqa: E402
+# What a stale pin's failure says: the fix is one command.
+PIN_ADVICE = "install.py changed: python scripts/pin_installer.py rewrites both pins"
+
# No connection off the loopback and no card of the host reaches a test:
# the module fails at its end otherwise.
setUpModule, tearDownModule = module_guard("test_install")
@@ -2201,7 +2204,7 @@ class TestAvailablePlatforms(unittest.TestCase):
match = re.search(r'\$defaultInstallSha256 = "([0-9a-f]{64})"', content)
self.assertIsNotNone(match, "install.ps1 must embed the installer SHA256")
expected = hashlib.sha256((REPO_ROOT / "install.py").read_bytes()).hexdigest()
- self.assertEqual(match.group(1), expected)
+ self.assertEqual(match.group(1), expected, PIN_ADVICE)
def test_powershell_wrapper_rejects_non_https_bootstrap(self):
content = (REPO_ROOT / "install.ps1").read_text()
@@ -2212,7 +2215,31 @@ class TestAvailablePlatforms(unittest.TestCase):
match = re.search(r'DEFAULT_INSTALL_SHA256="([0-9a-f]{64})"', content)
self.assertIsNotNone(match, "install.sh must embed the installer SHA256")
expected = hashlib.sha256((REPO_ROOT / "install.py").read_bytes()).hexdigest()
- self.assertEqual(match.group(1), expected)
+ self.assertEqual(match.group(1), expected, PIN_ADVICE)
+
+ def test_pin_script_writes_both_pins(self):
+ """Every edit to install.py meant a sha256sum pasted by hand into two
+ files with two syntaxes, and the failing test named no command."""
+ sys.path.insert(0, str(REPO_ROOT / "scripts"))
+ import pin_installer # noqa: PLC0415
+
+ with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp" / "tests") as directory:
+ root = Path(directory)
+ for name in ("install.py", "install.sh", "install.ps1"):
+ shutil.copy2(REPO_ROOT / name, root / name)
+ (root / "install.py").write_text("# changed\n", encoding="utf-8")
+ sh_mode = (root / "install.sh").stat().st_mode
+ self.assertEqual(pin_installer.stale_pins(root), ["install.sh", "install.ps1"])
+ self.assertEqual(pin_installer.write_pins(root), ["install.sh", "install.ps1"])
+ self.assertEqual(pin_installer.stale_pins(root), [])
+ digest = hashlib.sha256(b"# changed\n").hexdigest()
+ for name in ("install.sh", "install.ps1"):
+ before = (REPO_ROOT / name).read_text(encoding="utf-8").splitlines()
+ after = (root / name).read_text(encoding="utf-8").splitlines()
+ changed = [b for a, b in zip(before, after) if a != b]
+ self.assertEqual(len(changed), 1, name)
+ self.assertIn(digest, changed[0])
+ self.assertEqual((root / "install.sh").stat().st_mode, sh_mode)
def test_shell_one_liner_downloads_verifies_and_forwards_arguments(self):
scratch = REPO_ROOT / "tmp" / "tests"
diff --git a/tests/test_refresh_stale.py b/tests/test_refresh_stale.py
index a1c463b0c..e92887a66 100644
--- a/tests/test_refresh_stale.py
+++ b/tests/test_refresh_stale.py
@@ -162,6 +162,11 @@ class Planning(unittest.TestCase):
self.assertEqual(jobs, [])
self.assertEqual(len(surfaced), 3)
+ def test_the_installer_pin_is_written_by_its_script(self):
+ jobs, surfaced, _ = self._plan(finding("ci", "install.py pin"))
+ self.assertEqual([job.command[1:] for job in jobs], [["scripts/pin_installer.py"]])
+ self.assertEqual(surfaced, [])
+
class Running(unittest.TestCase):
def test_a_child_starts_after_its_parent_ends(self):
diff --git a/wiki/installer.md b/wiki/installer.md
index 73719bf16..d5a930694 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -1702,7 +1702,9 @@ a real 3.8 interpreter, which CI installs beside 3.12 so the check cannot skip.
The build scripts need 3.9 and are not bound by this.
Every change to `install.py` recomputes the SHA-256 pinned in `install.sh` and
-`install.ps1` in the same commit. The tests compare the pins with the file.
+`install.ps1` in the same commit: `python scripts/pin_installer.py` writes both
+(`--check` writes nothing and exits 1 on a stale pin). The tests compare the
+pins with the file and name that command when they differ.
The tables of options, events, exit codes, keys and card markers, the line
menu and the run samples on this page sit between `generated` markers and are
diff --git a/wiki/tools.md b/wiki/tools.md
index f566efe53..65296bcee 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -1346,6 +1346,7 @@ before a release (wiki/release-process.md). Its lines stay in
| `validate_schemas.py` | Validate the data contracts: schemas and semantic invariants. `--source-only` checks `emulators/` and `platforms/` alone, which is what PR validation runs |
| `generate_event_schema.py` | Write `schemas/install-events.schema.json` from `EVENT_KEYS` in `install.py` (`--check` exits 1 when the file is stale, which `validate_schemas.py` also reports) |
| `generate_installer_doc.py` | Rewrite the generated blocks of `wiki/installer.md` from `install.py`: the tables (options, events, exit codes, keys per route, card markers), the line menu, and the run samples `install.py` prints in a sandbox against the committed `install/*.json`, so a new list rewrites the page (`--check` exits 1 when a block is stale, `--page FILE` writes another copy of the page). Pipeline step 7 |
+| `pin_installer.py` | Write the SHA-256 of `install.py` into the pins of `install.sh` and `install.ps1`, which refuse any other installer (`--check` writes nothing and exits 1 when a pin is stale). `check_freshness.py` reports a stale pin and `refresh_stale.py` runs this |
| `auto_fetch.py` | Fetch missing BIOS files from known sources (4-step pipeline). A download is accepted only when every cryptographic hash the entry declares (sha256, sha1, md5) matches. crc32 and size find a file the database already holds, never accept a download. An entry with no cryptographic hash is reported and not searched |
| `list_platforms.py` | List active platforms (`--include-archived` adds the archived ones) |
| `download.py` | Download a pack from GitHub releases, every part checked (Python, stdlib only) |
From 55e2c8328e2555c7ea6745ae6d9fc0c2aedb70ac Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:02:51 +0100
Subject: [PATCH 65/83] feat: pack readme names spellings left out
A pack folded for Windows and macOS keeps one spelling of each case twin. Extracted on a Steam Deck or Linux, the core asking for the other spelling finds nothing, and only the installer added it. Where the platform also runs on a filesystem that keeps case, the README now lists each spelling left out beside the one it holds: 12 for EmuDeck and 10 for RetroArch, the manifest's case_variants.
---
scripts/generate_pack.py | 57 +++++++++++++++-
scripts/packreadme.py | 19 ++++++
tests/test_case_insensitive_platforms.py | 82 ++++++++++++++++++++++++
wiki/architecture.md | 2 +-
4 files changed, 157 insertions(+), 3 deletions(-)
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index ba948fc7a..3e3c2754c 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -608,6 +608,17 @@ def _pack_data_directories(
return added
+def _case_twin_pairs(
+ twins: list[str], seen_destinations: set[str], base_dest: str, flatten: bool,
+) -> list[tuple[str, str]]:
+ """Each spelling left out, with the spelling the pack holds."""
+ held = {
+ _flat(dest, base_dest, flatten).lower(): _flat(dest, base_dest, flatten)
+ for dest in seen_destinations
+ }
+ return sorted({(twin, held[twin.lower()]) for twin in twins if twin.lower() in held})
+
+
def _report_pack_counts(
zip_path: str,
file_status: dict,
@@ -879,6 +890,8 @@ def generate_pack(
user_provided = []
seen_destinations: set[str] = set()
seen_lower: set[str] = set() # only used when case_insensitive=True
+ # Spellings left out as case twins of a packed file, for the README.
+ case_twins: list[str] = []
seen_parents: set[str] = (
set()
) # parent dirs of added files (path conflict detection)
@@ -1185,6 +1198,8 @@ def generate_pack(
)
if already_packed:
+ if dedup_key not in seen_destinations:
+ case_twins.append(_flat(full_dest, base_dest, flatten))
continue
if within is not None and not _same_bytes(
local_path, within.get(_flat(full_dest, base_dest, flatten))
@@ -1267,10 +1282,13 @@ def generate_pack(
# Taken, a case twin on a case-insensitive filesystem, or a
# file/directory conflict (SGB1.sfc vs SGB1.sfc/): verify replays
# the same rule (packextras.hidden_extras).
- if placement_block(
+ block = placement_block(
full_dest, seen_destinations, seen_lower, seen_parents,
case_insensitive,
- ):
+ )
+ if block:
+ if block == "case_twin" and extra_resolver.resolve(fe, dest)[0]:
+ case_twins.append(_flat(full_dest, base_dest, flatten))
continue
# The emulator's own check picks the copy, as for a declared file
@@ -1364,6 +1382,37 @@ def generate_pack(
if _registry_path.exists():
with open(_registry_path) as _rf:
_pack_registry = (yaml_load(_rf) or {}).get("platforms", {})
+ keeps_case = case_insensitive and any(
+ d.get("os") not in CASE_FOLDING_OS
+ for d in (_pack_registry.get(platform_name, {}).get("install", {}) or {})
+ .get("detect", [])
+ )
+ if keeps_case and source != "platform" and precomputed_extras is None:
+ # The spellings a folded platform counts as declared never reach
+ # the extras: collected as the filesystem that keeps case sees
+ # them, as the manifest's case_variants are (Mesen-CE's bios.col
+ # beside the declared BIOS.col).
+ unfolded = _collect_emulator_extras(
+ {**config, "case_insensitive_fs": False}, emulators_dir, db, set(),
+ base_dest, emu_profiles, target_cores=target_cores,
+ include_all=(source == "truth"),
+ )
+ if system_filter:
+ unfolded = _extras_for_systems(unfolded, system_filter)
+ prefix = _detect_extras_prefix(config, base_dest)
+ for fe in unfolded:
+ if required_only and fe.get("required") is False:
+ continue
+ if region_drops and extra_region_key(fe, declared_root(config)) in region_drops:
+ continue
+ full = extra_full_destination(fe, prefix)
+ if (
+ full and full not in seen_destinations and full.lower() in seen_lower
+ and extra_resolver.resolve(
+ fe, sanitize_pack_path(fe.get("destination", fe["name"]))
+ )[0]
+ ):
+ case_twins.append(_flat(full, base_dest, flatten))
readme_text = _build_readme(
platform_name, platform_display, base_dest, total_files, num_systems,
source=source,
@@ -1389,6 +1438,10 @@ def generate_pack(
) if save_count else ""
),
save_by_system=bool(save_count and save_layout(config).by_system),
+ case_twins=(
+ _case_twin_pairs(case_twins, seen_destinations, base_dest, flatten)
+ if keeps_case else []
+ ),
)
_write_generated_member(zf, "README.txt", readme_text)
diff --git a/scripts/packreadme.py b/scripts/packreadme.py
index 06ee483a3..a9a12879b 100644
--- a/scripts/packreadme.py
+++ b/scripts/packreadme.py
@@ -207,6 +207,7 @@ def _build_readme(
save_folder: str = "",
save_where: str = "",
save_by_system: bool = False,
+ case_twins: list[tuple[str, str]] | None = None,
) -> str:
"""Build a personalized step-by-step README for each platform pack.
@@ -216,6 +217,10 @@ def _build_readme(
frontend's save directory, empty when the pack holds none, and
``save_where`` that directory's default place (save_place).
``save_by_system`` is set when the launcher hands each system a folder.
+ ``case_twins`` pairs each spelling the pack leaves out, a case twin of a
+ packed file, with the one it holds: given for a platform that also runs
+ where names keep their case (EmuDeck and RetroArch on Linux), where the
+ core asking for the other spelling finds nothing.
"""
narrowings = narrowings or []
sep = "=" * 50
@@ -245,6 +250,20 @@ def _build_readme(
+ (pack_manual(platform_name) or _generic_manual(bios_paths))
)
+ if case_twins:
+ listed = "".join(
+ f" {missing} (the pack has {held})\n" for missing, held in case_twins
+ )
+ guide += (
+ "NAMES THAT DIFFER ONLY BY CASE\n\n"
+ " Some cores open the same file under another spelling. This\n"
+ " pack holds one spelling of each, all Windows and macOS can\n"
+ " store in one folder. Linux, SteamOS and Android keep both:\n"
+ " there, run the installer, which adds these spellings, or\n"
+ " copy each file under the name below.\n\n"
+ f"{listed}\n"
+ )
+
if save_folder:
guide += _save_section(
platform_display, save_folder, save_where, save_by_system,
diff --git a/tests/test_case_insensitive_platforms.py b/tests/test_case_insensitive_platforms.py
index cf88467dd..0653505a3 100644
--- a/tests/test_case_insensitive_platforms.py
+++ b/tests/test_case_insensitive_platforms.py
@@ -7,7 +7,12 @@ went red. The flag lived in retrobat.yml and vanished at the next scrape.
from __future__ import annotations
+import contextlib
+import hashlib
+import io
+import os
import sys
+import tempfile
import unittest
from pathlib import Path
@@ -29,5 +34,82 @@ class CaseInsensitiveWhereTheFilesystemIs(unittest.TestCase):
self.assertTrue(config.get("case_insensitive_fs"))
+class ThePackReadmeNamesTheSpellingsItLeavesOut(unittest.TestCase):
+ """The EmuDeck pack is folded for Windows and extracted on a Steam Deck,
+ where the core asking for bios.col finds only BIOS.col. Only the
+ installer adds that spelling (case_variants), and the pack's README said
+ nothing about it."""
+
+ def setUp(self):
+ import common
+ import generate_db
+ import generate_pack
+
+ self.gp = generate_pack
+ tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
+ self.addCleanup(tmp.cleanup)
+ previous = os.getcwd()
+ os.chdir(tmp.name)
+ self.addCleanup(os.chdir, previous)
+ Path("bios/Coleco").mkdir(parents=True)
+ payload = b"coleco bios"
+ Path("bios/Coleco/BIOS.col").write_bytes(payload)
+ sha1 = hashlib.sha1(payload).hexdigest()
+ files = {sha1: {"path": "bios/Coleco/BIOS.col", "name": "BIOS.col",
+ "size": len(payload), "sha1": sha1,
+ "md5": hashlib.md5(payload).hexdigest(),
+ "sha256": hashlib.sha256(payload).hexdigest(),
+ "crc32": "00000001"}}
+ self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
+ Path("platforms").mkdir()
+ Path("emulators").mkdir()
+ self.config = {
+ "platform": "P", "verification_mode": "existence",
+ "case_insensitive_fs": True, "cores": ["mesence"],
+ "systems": {"coleco": {"files": [{"name": "BIOS.col"}]}},
+ }
+ Path("emulators/mesence.yml").write_text(yaml.dump({
+ "emulator": "mesence", "type": "libretro", "systems": ["coleco"],
+ "files": [{"name": "bios.col", "required": True}],
+ }))
+ common._platform_config_cache.clear()
+ common._emulator_profiles_cache.clear()
+ self.addCleanup(common._platform_config_cache.clear)
+ self.addCleanup(common._emulator_profiles_cache.clear)
+
+ def _readme(self, systems: list[str]) -> str:
+ import common
+
+ Path("platforms/p.yml").write_text(yaml.dump(self.config))
+ Path("platforms/_registry.yml").write_text(yaml.dump({"platforms": {"p": {
+ "status": "active",
+ "install": {"detect": [{"os": os_name} for os_name in systems]},
+ }}}))
+ common._platform_config_cache.clear()
+ texts: dict[str, str] = {}
+ real = self.gp._write_generated_member
+
+ def capture(zf, arcname, text):
+ texts[arcname] = text
+ return real(zf, arcname, text)
+
+ self.gp._write_generated_member = capture
+ self.addCleanup(setattr, self.gp, "_write_generated_member", real)
+ with contextlib.redirect_stdout(io.StringIO()):
+ self.gp.generate_pack(
+ "p", "platforms", self.db, "bios", "", emulators_dir="emulators",
+ offline=True, record=self.gp.PackRecord(),
+ )
+ return texts["README.txt"]
+
+ def test_a_platform_also_on_linux_names_them(self):
+ readme = self._readme(["windows", "linux"])
+ self.assertIn("NAMES THAT DIFFER ONLY BY CASE", readme)
+ self.assertIn(" bios.col (the pack has BIOS.col)", readme)
+
+ def test_a_platform_only_on_windows_does_not(self):
+ self.assertNotIn("DIFFER ONLY BY CASE", self._readme(["windows"]))
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/wiki/architecture.md b/wiki/architecture.md
index fea8231df..75f4a9e89 100644
--- a/wiki/architecture.md
+++ b/wiki/architecture.md
@@ -405,7 +405,7 @@ resolution.
| MAME BIOS ZIPs | `contents` field documents inner structure |
| Trees addressed by path (RPG Maker, ScummVM, tzdata, c64-emu and the rest of `NODEDUP_DIRS`) | excluded from dedup to keep files that are equal by design |
| `strip_components` in data dirs | flattens cache prefix to match expected path |
-| case-insensitive dedup | prevents `font.rom` + `FONT.ROM` conflicts on Windows/macOS |
+| case-insensitive dedup | prevents `font.rom` + `FONT.ROM` conflicts on Windows/macOS. Where the platform also runs on a filesystem that keeps case (EmuDeck and RetroArch on Linux), the pack README lists each spelling it leaves out, and the installer adds them (`case_variants`) |
| frozen snapshot cores | `.info` may reflect current version while code is pinned to an old one. Only the frozen source at the pinned tag is reliable (e.g. desmume2015, mame2003) |
### File resolution chain
From 43cb0f84ab6d79aca99ccd2ea300cd7fc77439a8 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:04:51 +0100
Subject: [PATCH 66/83] feat: add AmberELEC hardware targets
AmberELEC's metapackage adds LIBRETRO_CORES_EXTRA (bsnes, Mesen, melonDS, geolith) only on RG552, RG353 and RG503, and deletes those cores from es_systems.cfg on every other device (packages/amberelec/package.mk:23-31, 45-58 at a21975bf). The new target scraper reads the Makefile's device images, that test and es_systems.cfg the way the platform scraper does: RG351P, RG351V and RG351MP list 125 cores, the other three 136. The installer reads the device from COREELEC_DEVICE in os-release (scripts/image:168).
---
install.ps1 | 2 +-
install.py | 5 +-
install.sh | 2 +-
install/launchers/index.json | 16 +-
install/targets/amberelec.json | 797 +++++++++++++++++
platforms/_registry.yml | 4 +-
platforms/targets/amberelec.yml | 805 ++++++++++++++++++
.../targets/amberelec_targets_scraper.py | 157 ++++
tests/test_amberelec_targets.py | 102 +++
tests/test_install.py | 22 +-
wiki/tools.md | 1 +
11 files changed, 1895 insertions(+), 18 deletions(-)
create mode 100644 install/targets/amberelec.json
create mode 100644 platforms/targets/amberelec.yml
create mode 100644 scripts/scraper/targets/amberelec_targets_scraper.py
create mode 100644 tests/test_amberelec_targets.py
diff --git a/install.ps1 b/install.ps1
index 896cdaf76..4ddc9ef79 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858"
+ $defaultInstallSha256 = "f90d3dc9f71f7d4b309f2a9a564907291eb694eb6f88dd651b861e54f7414e38"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index 01c0b9425..e3b82854b 100644
--- a/install.py
+++ b/install.py
@@ -109,7 +109,7 @@ TARGETS_URL = f"{BASE_URL}/install/targets/{{platform}}.json"
# has no hardware targets, where the run sent the user after a list that
# exists nowhere.
TARGET_PLATFORMS = frozenset({
- "batocera", "emudeck", "knulli", "lakka", "recalbox", "retroarch", "retrobat",
+ "amberelec", "batocera", "emudeck", "knulli", "lakka", "recalbox", "retroarch", "retrobat",
"retrodeck", "retropie", "rocknix", "romm",
})
RAW_FILE_URL = f"{BASE_URL}/{{path}}"
@@ -1472,7 +1472,10 @@ def _parse_bash_var(path: Path, key: str) -> str | None:
# /usr/share/batocera to /usr/share/knulli (knulli-linux 57afa662,
# board/scripts/post-build-script.sh:264-278) and writes KNULLI_SYSTEM_ARCH
# to knulli.arch (package/system/knulli-system/knulli-system.mk:98-99).
+# AmberELEC's scripts/image writes COREELEC_DEVICE (a21975bf, line 168), the
+# DEVICE its Makefile builds (RG351P).
_BOARD_SOURCES: dict[str, tuple[str, str]] = {
+ "amberelec": ("os_release", "COREELEC_DEVICE"),
"batocera": ("file", "/usr/share/batocera/batocera.arch"),
"recalbox": ("file", "/recalbox/recalbox.arch"),
"rocknix": ("os_release", "HW_DEVICE"),
diff --git a/install.sh b/install.sh
index b085a4cbb..d5f49f5e2 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858"
+DEFAULT_INSTALL_SHA256="f90d3dc9f71f7d4b309f2a9a564907291eb694eb6f88dd651b861e54f7414e38"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 358ee41c9..771cf18b9 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103292,
+ "sha256": "f90d3dc9f71f7d4b309f2a9a564907291eb694eb6f88dd651b861e54f7414e38",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1156738,
- "sha256": "35c0920008baadca997d0f778e99ce46d702bbe3d3f0d33104d7158422b292aa"
+ "size": 1156919,
+ "sha256": "2efccc205141dfffc016b4ef9988e11877ef249634052835069ca1dd8921cdce"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103292,
+ "sha256": "f90d3dc9f71f7d4b309f2a9a564907291eb694eb6f88dd651b861e54f7414e38",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1103111,
- "sha256": "34fd006cc0456c61b9a621e52f35cee6d3fd55ff14bbc6cea207ddc7bc57d858",
+ "size": 1103292,
+ "sha256": "f90d3dc9f71f7d4b309f2a9a564907291eb694eb6f88dd651b861e54f7414e38",
"executable": false
},
{
diff --git a/install/targets/amberelec.json b/install/targets/amberelec.json
new file mode 100644
index 000000000..ff186677e
--- /dev/null
+++ b/install/targets/amberelec.json
@@ -0,0 +1,797 @@
+{
+ "rg351mp": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ],
+ "rg351p": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ],
+ "rg351v": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ],
+ "rg353": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_snes",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "bsnes",
+ "bsnes2014_balanced",
+ "bsnes2014_performance",
+ "bsnes_mercury_balanced",
+ "bsnes_mercury_performance",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "melonds",
+ "melondsds",
+ "mesen",
+ "mesen-s",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ],
+ "rg503": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_snes",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "bsnes",
+ "bsnes2014_balanced",
+ "bsnes2014_performance",
+ "bsnes_mercury_balanced",
+ "bsnes_mercury_performance",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "melonds",
+ "melondsds",
+ "mesen",
+ "mesen-s",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ],
+ "rg552": [
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DoubleCherryGB",
+ "HATARISA",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "SCUMMVMSA",
+ "a5200",
+ "arduous",
+ "atari800",
+ "beetle_gba",
+ "beetle_lynx",
+ "beetle_ngp",
+ "beetle_pce",
+ "beetle_pce_fast",
+ "beetle_pcfx",
+ "beetle_snes",
+ "beetle_supafaust",
+ "beetle_supergrafx",
+ "beetle_vb",
+ "beetle_wswan",
+ "bluemsx",
+ "bsnes",
+ "bsnes2014_balanced",
+ "bsnes2014_performance",
+ "bsnes_mercury_balanced",
+ "bsnes_mercury_performance",
+ "cap32",
+ "crocods",
+ "dosbox_core",
+ "dosbox_pure",
+ "drastic",
+ "duckstation",
+ "easyrpg",
+ "ecwolf",
+ "emuscv",
+ "ep128emu_core",
+ "fake08",
+ "fbalpha2012",
+ "fbalpha2019",
+ "fbneo",
+ "fceumm",
+ "flycast",
+ "flycast2021",
+ "flycast2021le",
+ "fmsx",
+ "freechaf",
+ "freeintv",
+ "freej2me",
+ "freej2me-plus",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "gzdoom",
+ "handy",
+ "hatari",
+ "hypseus_singe",
+ "jaxe",
+ "lowresnx",
+ "lzdoom",
+ "mame",
+ "mame2000",
+ "mame2003_plus",
+ "mame2010",
+ "mame2015",
+ "mame2016",
+ "melonds",
+ "melondsds",
+ "mesen",
+ "mesen-s",
+ "mgba",
+ "mojozork",
+ "mupen64plus_next",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "o2em",
+ "opera",
+ "parallel_n64",
+ "pcsx_rearmed",
+ "pico8",
+ "picodrive",
+ "piemu",
+ "pokemini",
+ "potator",
+ "ppsspp",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "quasi88",
+ "quicknes",
+ "race",
+ "raze",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "smsplus",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "solarus",
+ "stella",
+ "stella2014",
+ "swanstation",
+ "tgbdual",
+ "theodore",
+ "tic80",
+ "uae4arm",
+ "uw8",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_xplus4",
+ "vice_xvic",
+ "vircon32",
+ "virtualjaguar",
+ "wasm4",
+ "x1",
+ "yabasanshiroSA"
+ ]
+}
diff --git a/platforms/_registry.yml b/platforms/_registry.yml
index 891b01a95..e93abe5a7 100644
--- a/platforms/_registry.yml
+++ b/platforms/_registry.yml
@@ -868,8 +868,8 @@ platforms:
# setsettings.py leaves it: saves sit beside each game, no single place.
save_directory: null
schedule: monthly
- target_scraper: null
- target_source: null
+ target_scraper: amberelec_targets
+ target_source: https://github.com/AmberELEC/AmberELEC/blob/dev/packages/amberelec/package.mk
install:
detect:
# AmberELEC 5a3882cb scripts/image:150-152, options:17. CHAos
diff --git a/platforms/targets/amberelec.yml b/platforms/targets/amberelec.yml
new file mode 100644
index 000000000..1515bed13
--- /dev/null
+++ b/platforms/targets/amberelec.yml
@@ -0,0 +1,805 @@
+platform: amberelec
+source: https://github.com/AmberELEC/AmberELEC/blob/a21975bfb1a3af68f66e07a931b994b523e1e6e2/packages/amberelec/package.mk
+scraped_at: '2026-11-06T07:53:33Z'
+targets:
+ rg351mp:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
+ rg351p:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
+ rg351v:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
+ rg353:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_snes
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - bsnes
+ - bsnes2014_balanced
+ - bsnes2014_performance
+ - bsnes_mercury_balanced
+ - bsnes_mercury_performance
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - melonds
+ - melondsds
+ - mesen
+ - mesen-s
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
+ rg503:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_snes
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - bsnes
+ - bsnes2014_balanced
+ - bsnes2014_performance
+ - bsnes_mercury_balanced
+ - bsnes_mercury_performance
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - melonds
+ - melondsds
+ - mesen
+ - mesen-s
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
+ rg552:
+ architecture: aarch64
+ cores:
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DoubleCherryGB
+ - HATARISA
+ - OPENBOR
+ - PPSSPPSDL
+ - SCUMMVMSA
+ - a5200
+ - arduous
+ - atari800
+ - beetle_gba
+ - beetle_lynx
+ - beetle_ngp
+ - beetle_pce
+ - beetle_pce_fast
+ - beetle_pcfx
+ - beetle_snes
+ - beetle_supafaust
+ - beetle_supergrafx
+ - beetle_vb
+ - beetle_wswan
+ - bluemsx
+ - bsnes
+ - bsnes2014_balanced
+ - bsnes2014_performance
+ - bsnes_mercury_balanced
+ - bsnes_mercury_performance
+ - cap32
+ - crocods
+ - dosbox_core
+ - dosbox_pure
+ - drastic
+ - duckstation
+ - easyrpg
+ - ecwolf
+ - emuscv
+ - ep128emu_core
+ - fake08
+ - fbalpha2012
+ - fbalpha2019
+ - fbneo
+ - fceumm
+ - flycast
+ - flycast2021
+ - flycast2021le
+ - fmsx
+ - freechaf
+ - freeintv
+ - freej2me
+ - freej2me-plus
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - gzdoom
+ - handy
+ - hatari
+ - hypseus_singe
+ - jaxe
+ - lowresnx
+ - lzdoom
+ - mame
+ - mame2000
+ - mame2003_plus
+ - mame2010
+ - mame2015
+ - mame2016
+ - melonds
+ - melondsds
+ - mesen
+ - mesen-s
+ - mgba
+ - mojozork
+ - mupen64plus_next
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - o2em
+ - opera
+ - parallel_n64
+ - pcsx_rearmed
+ - pico8
+ - picodrive
+ - piemu
+ - pokemini
+ - potator
+ - ppsspp
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - quasi88
+ - quicknes
+ - race
+ - raze
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - smsplus
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - solarus
+ - stella
+ - stella2014
+ - swanstation
+ - tgbdual
+ - theodore
+ - tic80
+ - uae4arm
+ - uw8
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_xplus4
+ - vice_xvic
+ - vircon32
+ - virtualjaguar
+ - wasm4
+ - x1
+ - yabasanshiroSA
diff --git a/scripts/scraper/targets/amberelec_targets_scraper.py b/scripts/scraper/targets/amberelec_targets_scraper.py
new file mode 100644
index 000000000..72b3b557f
--- /dev/null
+++ b/scripts/scraper/targets/amberelec_targets_scraper.py
@@ -0,0 +1,157 @@
+"""Scraper for AmberELEC per-device emulator availability.
+
+Sources (AmberELEC/AmberELEC, at the commit platforms/amberelec.yml names):
+ - Makefile -- one `DEVICE= ARCH= ./scripts/build_distro` target
+ per image (RG351P, RG351V, RG351MP, RG552, RG353, RG503 at a21975bf)
+ - packages/amberelec/package.mk -- LIBRETRO_CORES_EXTRA joins PKG_EMUS
+ only on the devices its `if` names (lines 23-31 at a21975bf: RG552,
+ RG353, RG503), and on every other device makeinstall_target deletes
+ each of those cores from es_systems.cfg (lines 45-58)
+ - packages/ui/emulationstation/config/es_systems.cfg -- read the way the
+ platform scraper reads it, after that deletion
+
+An RG351P image carries neither melonDS nor bsnes: without a target list,
+its pack shipped the Nintendo DS firmware anyway.
+"""
+
+from __future__ import annotations
+
+import argparse
+import re
+import sys
+from datetime import datetime, timezone
+
+import yaml
+
+from . import BaseTargetScraper
+
+PLATFORM_NAME = "amberelec"
+
+RAW_BASE = "https://raw.githubusercontent.com/AmberELEC/AmberELEC/{ref}"
+META_MK = "packages/amberelec/package.mk"
+
+try:
+ from ..amberelec_scraper import BUILDS_OF, ES_SYSTEMS_TEMPLATE, RUNNERS
+ from ..base_scraper import fetch_bytes
+ from ..batocera_scraper import _not_cores
+ from ..es_emulators import es_cores, xml_systems
+except ImportError:
+ from scraper.amberelec_scraper import BUILDS_OF, ES_SYSTEMS_TEMPLATE, RUNNERS
+ from scraper.base_scraper import fetch_bytes
+ from scraper.batocera_scraper import _not_cores
+ from scraper.es_emulators import es_cores, xml_systems
+
+_DEVICE_RE = re.compile(
+ r"^(\w+):\n\tDEVICE=(\w+) ARCH=(\w+) \./scripts/build_distro$", re.MULTILINE
+)
+_EXTRA_RE = re.compile(r'LIBRETRO_CORES_EXTRA="([^"]*)"')
+# The `if` whose body adds the extra cores to PKG_EMUS.
+_EXTRA_IF_RE = re.compile(
+ r"if \[\[ (?P[^\n]*?) \]\]; then\s*\n\s*PKG_EMUS\+=\" \$\{LIBRETRO_CORES_EXTRA\}\""
+)
+# What makeinstall_target does to es_systems.cfg on the other devices.
+_REMOVAL_LINES = (
+ "for CORE in ${LIBRETRO_CORES_EXTRA}; do",
+ 'sed -i "s|$CORE||g"',
+ r"sed -i -e '//!ba;/melonds/d}'",
+)
+_EMULATOR_BLOCK_RE = re.compile(r"[^\n]*[^\n]*\n?", re.DOTALL)
+
+
+def devices(makefile: str) -> dict[str, str]:
+ """{device: architecture} of each image the Makefile builds."""
+ found = {device: arch for target, device, arch in _DEVICE_RE.findall(makefile)
+ if target == device}
+ if not found:
+ raise RuntimeError("the AmberELEC Makefile builds no device image")
+ return found
+
+
+def extra_cores(package_mk: str) -> tuple[list[str], set[str]]:
+ """(the extra cores, the devices that keep them) from the metapackage."""
+ listed = _EXTRA_RE.search(package_mk)
+ test = _EXTRA_IF_RE.search(package_mk)
+ if listed is None or test is None:
+ raise RuntimeError(f"{META_MK}: no LIBRETRO_CORES_EXTRA or no test adding it")
+ missing = [line for line in _REMOVAL_LINES if line not in package_mk]
+ if missing:
+ raise RuntimeError(f"{META_MK}: makeinstall_target no longer reads {missing[0]!r}")
+ keep = set(re.findall(r'"\$\{DEVICE\}" == "(\w+)"', test.group("test")))
+ for alternatives in re.findall(r'"\$\{DEVICE\}" =~ \^\(([\w|]+)\)\$', test.group("test")):
+ keep.update(alternatives.split("|"))
+ if not keep:
+ raise RuntimeError(f"{META_MK}: the test adding the extra cores names no device")
+ return listed.group(1).split(), keep
+
+
+def without_cores(es_systems: str, cores: list[str]) -> str:
+ """es_systems.cfg as makeinstall_target leaves it on a device without them."""
+ for core in cores:
+ if core == "melonds":
+ es_systems = _EMULATOR_BLOCK_RE.sub(
+ lambda block: "" if "melonds" in block.group(0) else block.group(0),
+ es_systems,
+ )
+ es_systems = es_systems.replace(f"{core}", "")
+ return es_systems
+
+
+def device_cores(es_systems: str, extra: list[str], keeps_extra: bool) -> list[str]:
+ """Every core and standalone emulator one device's es_systems.cfg offers."""
+ text = es_systems if keeps_extra else without_cores(es_systems, extra)
+ cores, _standalone, _dual = es_cores(
+ xml_systems(text), RUNNERS, BUILDS_OF, _not_cores(PLATFORM_NAME)
+ )
+ return sorted(set(cores))
+
+
+class Scraper(BaseTargetScraper):
+ """Per-device core lists from AmberELEC's metapackage."""
+
+ def __init__(self, url: str = "https://github.com/AmberELEC/AmberELEC") -> None:
+ super().__init__(url=url)
+ self.ref = ""
+
+ def _raw(self, path: str) -> str:
+ return fetch_bytes(f"{RAW_BASE.format(ref=self.ref)}/{path}").decode("utf-8")
+
+ def fetch_targets(self) -> dict:
+ self.ref = self.pinned_revision(PLATFORM_NAME)
+ extra, keep = extra_cores(self._raw(META_MK))
+ es_systems = fetch_bytes(ES_SYSTEMS_TEMPLATE.format(ref=self.ref)).decode("utf-8")
+ targets: dict[str, dict] = {}
+ for device, arch in sorted(devices(self._raw("Makefile")).items()):
+ cores = device_cores(es_systems, extra, device in keep)
+ targets[device.lower()] = {"architecture": arch, "cores": cores}
+ print(f" {device.lower()} ({arch}): {len(cores)} cores", file=sys.stderr)
+ return {
+ "platform": PLATFORM_NAME,
+ "source": f"{self.url}/blob/{self.ref}/{META_MK}",
+ "scraped_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
+ "targets": targets,
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ allow_abbrev=False, description="Scrape AmberELEC per-device cores"
+ )
+ parser.add_argument("--dry-run", action="store_true", help="Show target summary")
+ parser.add_argument("--output", "-o", help="Output YAML file")
+ args = parser.parse_args()
+
+ scraper = Scraper()
+ data = scraper.fetch_targets()
+ if args.dry_run:
+ for name, info in data["targets"].items():
+ print(f" {name} ({info['architecture']}): {len(info['cores'])} cores")
+ return
+ if args.output:
+ scraper.write_output(data, args.output)
+ print(f"Written to {args.output}")
+ return
+ print(yaml.dump(data, default_flow_style=False, sort_keys=False))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/test_amberelec_targets.py b/tests/test_amberelec_targets.py
new file mode 100644
index 000000000..3724fd0d5
--- /dev/null
+++ b/tests/test_amberelec_targets.py
@@ -0,0 +1,102 @@
+"""AmberELEC's images differ by device, and only its metapackage says how.
+
+packages/amberelec/package.mk adds LIBRETRO_CORES_EXTRA (melonDS, bsnes,
+Mesen, geolith) on RG552, RG353 and RG503 and deletes those cores from
+es_systems.cfg everywhere else. With no target list, an RG351P pack carried
+the firmware of cores its image never had.
+"""
+
+from __future__ import annotations
+
+import sys
+import unittest
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(REPO_ROOT / "scripts"))
+
+from scraper.targets import amberelec_targets_scraper as scraper # noqa: E402
+
+MAKEFILE = """RG351P:
+\tDEVICE=RG351P ARCH=aarch64 ./scripts/build_distro
+
+RG552:
+\tDEVICE=RG552 ARCH=aarch64 ./scripts/build_distro
+
+toolchain-RK3326:
+\tDEVICE=RK3326 ARCH=aarch64 ./scripts/build toolchain
+"""
+
+PACKAGE_MK = """ LIBRETRO_CORES_EXTRA="bsnes melonds"
+
+ PKG_EMUS="${LIBRETRO_CORES}"
+
+ if [[ "${DEVICE}" == "RG552" || "${DEVICE}" =~ ^(RG353|RG503)$ ]]; then
+ PKG_EMUS+=" ${LIBRETRO_CORES_EXTRA}"
+ fi
+
+makeinstall_target() {
+ for CORE in ${LIBRETRO_CORES_EXTRA}; do
+ if [[ $CORE == "melonds" ]]; then
+ sed -i -e '//!ba;/melonds/d}' es_systems.cfg
+ fi
+ sed -i "s|$CORE||g" es_systems.cfg
+ done
+}
+"""
+
+ES_SYSTEMS = """
+
+ snes
+
+
+
+ snes9x
+ bsnes
+
+
+
+
+
+ nds
+
+
+
+ melonds
+
+
+
+
+ drastic
+
+
+
+
+
+"""
+
+
+class TheMetapackageDecidesEachDevice(unittest.TestCase):
+ def test_devices_are_the_images_the_makefile_builds(self):
+ self.assertEqual(scraper.devices(MAKEFILE), {"RG351P": "aarch64", "RG552": "aarch64"})
+
+ def test_the_extra_cores_and_their_devices(self):
+ extra, keep = scraper.extra_cores(PACKAGE_MK)
+ self.assertEqual(extra, ["bsnes", "melonds"])
+ self.assertEqual(keep, {"RG552", "RG353", "RG503"})
+
+ def test_a_device_without_them_loses_their_cores(self):
+ extra, _keep = scraper.extra_cores(PACKAGE_MK)
+ full = scraper.device_cores(ES_SYSTEMS, extra, True)
+ lean = scraper.device_cores(ES_SYSTEMS, extra, False)
+ self.assertEqual(set(full) - set(lean), {"bsnes", "melonds"})
+ self.assertIn("drastic", lean)
+
+ def test_a_changed_removal_stops_the_scrape(self):
+ changed = PACKAGE_MK.replace('sed -i "s|$CORE||g"', "true")
+ with self.assertRaises(RuntimeError):
+ scraper.extra_cores(changed)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_install.py b/tests/test_install.py
index f36389a1e..0ea26705f 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -3420,7 +3420,8 @@ class ACardPreparedOnAComputerGetsItsBoard(unittest.TestCase):
class APlatformWithoutTargetsSaysSoOffline(unittest.TestCase):
"""Offline, --target on AmberELEC asked for install/targets/amberelec.json,
- which exists nowhere: online the same run says it has no targets."""
+ which existed nowhere: online the same run said it had no targets.
+ EmuELEC has none still."""
def test_the_list_matches_the_published_targets(self):
published = {path.stem for path in (REPO_ROOT / "install" / "targets").glob("*.json")}
@@ -3428,16 +3429,16 @@ class APlatformWithoutTargetsSaysSoOffline(unittest.TestCase):
def test_offline_says_there_are_no_targets(self):
dest = Path(_tempdir(self))
- for extra in ([], ["--manifest", str(REPO_ROOT / "install" / "amberelec.json")]):
+ for extra in ([], ["--manifest", str(REPO_ROOT / "install" / "emuelec.json")]):
with self.subTest(manifest=bool(extra)):
proc = subprocess.run(
- [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "amberelec",
+ [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "emuelec",
"--dest", str(dest), "--target", "rk3326", "--offline", "--no-input",
"--dry-run", *extra],
capture_output=True, text=True, timeout=120, stdin=subprocess.DEVNULL)
self.assertEqual(proc.returncode, 2, proc.stderr)
- self.assertIn("AmberELEC has no hardware targets", proc.stderr)
- self.assertNotIn("targets/amberelec.json", proc.stderr)
+ self.assertIn("EmuELEC has no hardware targets", proc.stderr)
+ self.assertNotIn("targets/emuelec.json", proc.stderr)
class TheBoardTheSystemNamesIsTheTarget(unittest.TestCase):
@@ -3492,6 +3493,17 @@ class TheBoardTheSystemNamesIsTheTarget(unittest.TestCase):
.read_text(encoding="utf-8"))
self.assertLessEqual({*install._RPI_MODELS.values(), "x86_64"}, set(targets))
+ def test_amberelec_names_its_device(self):
+ # An RG351P image carries no melonDS or bsnes, and the full list was
+ # installed: AmberELEC had no target list to read the device against.
+ with unittest.mock.patch.object(
+ install, "_parse_os_release", return_value={"COREELEC_DEVICE": "RG351P"}
+ ):
+ self.assertEqual(install.detect_board("amberelec"), "rg351p")
+ targets = json.loads((REPO_ROOT / "install" / "targets" / "amberelec.json")
+ .read_text(encoding="utf-8"))
+ self.assertIn("rg351p", targets)
+
def test_lakka_names_its_device_or_its_project(self):
# An RPi4 Lakka installed 5.7 GB of every board's files: its board
# was in os-release and never read.
diff --git a/wiki/tools.md b/wiki/tools.md
index dab60e5b0..a42c26adb 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -1701,6 +1701,7 @@ Located in `scripts/scraper/targets/`. Each inherits `BaseTargetScraper` and imp
| `knulli_targets_scraper` | the same, read from KNULLI's tree and Buildroot fork | board |
| `recalbox_targets_scraper` | board defconfigs + system.ini cores | board |
| `rocknix_targets_scraper` | emulators package.mk + device options | device |
+| `amberelec_targets_scraper` | Makefile devices + metapackage extra cores + es_systems.cfg | device |
| `lakka_targets_scraper` | libretro_cores package.mk + project and device options | device image |
| `emudeck_targets_scraper` | EmuScripts (SteamOS and Windows) | operating system |
| `retropie_targets_scraper` | scriptmodules + rp_module_flags | platform flag |
From 333f1ac3cabd8317007f7cd58821789e8d029784 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:04:52 +0100
Subject: [PATCH 67/83] fix: resume a cut data archive
A data archive cut mid-download was deleted on every failure: the retry and the next run started from zero, while the run said nothing was lost. The archive is now kept beside its tree with the validator its server sent, and the rest is asked for with Range and If-Range. Checked against the release: fbneo-samples stopped at 16 MB, the next run downloaded 34.6 MB of 50.5.
---
install.ps1 | 2 +-
install.py | 114 ++++++++++++++++++++++++++++++-----
install.sh | 2 +-
install/launchers/index.json | 16 ++---
tests/test_install.py | 104 ++++++++++++++++++++++++++++++--
wiki/installer.md | 6 +-
6 files changed, 210 insertions(+), 34 deletions(-)
diff --git a/install.ps1 b/install.ps1
index 7225221c0..c8d2c3399 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f"
+ $defaultInstallSha256 = "fdccf00cb56c4caf3ddf916e126d538539e0d9efa527fb808cde954b6b0d29b1"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index 8a4f6cb3c..16c011ea6 100644
--- a/install.py
+++ b/install.py
@@ -7086,20 +7086,72 @@ def download_files(
return failed, interrupted
-def _fetch_archive(url: str, directory: Path, progress: Progress | None = None) -> Path:
+def _archive_validator(headers: object) -> str:
+ """What names this revision of an archive to its server: an If-Range
+ with it gets the rest of the same bytes, or the whole new archive."""
+ if not headers:
+ return ""
+ etag = headers.get("ETag", "") or ""
+ # A weak tag never answers a range (RFC 9110 13.1.5).
+ return etag if etag and not etag.startswith("W/") else headers.get("Last-Modified", "") or ""
+
+
+def _fetch_archive(url: str, directory: Path, progress: Progress | None = None,
+ keep: Path | None = None) -> Path:
"""A data directory's source archive, in *directory*, retried like files.
- progress draws its bytes as they come, an attempt that failed taken back."""
+ progress draws its bytes as they come, an attempt that failed taken back.
+
+ With keep, the archive is written there and kept when the transfer is
+ cut, beside a note of its address and the validator its server sent:
+ the next attempt, or the next run, asks for the rest with Range and
+ If-Range, and a server that changed the archive sends it whole. A cut
+ 50 MB archive started again from zero, and a link that drops more often
+ than one archive takes never installed the tree.
+ """
_network_allowed(url)
+ note = keep.with_name(keep.name + ".source") if keep is not None else None
reason: Exception | None = None
for attempt in range(1, MAX_RETRIES + 1):
- handle = tempfile.NamedTemporaryFile(dir=directory, suffix=".archive", delete=False)
+ offset = 0
+ validator = ""
+ if keep is not None:
+ try:
+ recorded = note.read_text(encoding="utf-8").split("\n")
+ if recorded[0] == url and len(recorded) > 1 and recorded[1]:
+ validator = recorded[1]
+ offset = keep.stat().st_size
+ except (OSError, UnicodeError):
+ offset = 0
+ request = urllib.request.Request(url)
+ if offset:
+ request.add_header("Range", f"bytes={offset}-")
+ request.add_header("If-Range", validator)
+ handle = (open(keep, "r+b" if offset else "wb") if keep is not None else
+ tempfile.NamedTemporaryFile(dir=directory, suffix=".archive", delete=False))
received = 0
+ resumed = 0
try:
- with handle, urllib.request.urlopen(url, timeout=60) as resp:
+ with handle, urllib.request.urlopen(request, timeout=60) as resp:
+ headers = resp.headers or {}
+ ranged = (offset and getattr(resp, "status", 200) == 206 and str(
+ headers.get("Content-Range", "")).startswith(f"bytes {offset}-"))
+ if not ranged:
+ offset = 0
+ handle.seek(offset)
+ handle.truncate()
+ if keep is not None and not offset:
+ # Written before the first byte: a cut transfer is then
+ # resumed only against the revision it holds.
+ note.write_text(f"{url}\n{_archive_validator(headers)}\n",
+ encoding="utf-8")
if progress is not None:
- length = resp.headers.get("Content-Length", "")
+ length = headers.get("Content-Length", "")
if length.isdigit():
- progress.expect(int(length))
+ progress.expect(offset + int(length))
+ if offset:
+ progress.add(offset, resumed=True)
+ resumed = offset
+ total = offset
while True:
if _stop.is_set():
raise _Interrupted()
@@ -7107,30 +7159,51 @@ def _fetch_archive(url: str, directory: Path, progress: Progress | None = None)
if not chunk:
break
received += len(chunk)
- if received > MAX_DATA_ARCHIVE_SIZE:
+ total += len(chunk)
+ if total > MAX_DATA_ARCHIVE_SIZE:
raise ValueError("archive exceeds the size limit")
handle.write(chunk)
if progress is not None:
progress.add(len(chunk))
- return Path(handle.name)
+ return keep if keep is not None else Path(handle.name)
except urllib.error.HTTPError as exc:
- Path(handle.name).unlink(missing_ok=True)
- if exc.code < 500 and exc.code != 429:
+ if keep is None or exc.code == 416 or exc.code < 500 and exc.code != 429:
+ # Refused, or a range past an archive that shrank: no
+ # attempt resumes it.
+ _drop_archive(Path(handle.name), note)
+ if exc.code < 500 and exc.code not in (416, 429):
raise
reason = exc
except (urllib.error.URLError, OSError, http.client.HTTPException) as exc:
- Path(handle.name).unlink(missing_ok=True)
+ if keep is None:
+ Path(handle.name).unlink(missing_ok=True)
reason = exc if isinstance(exc, OSError) else ConnectionError(repr(exc))
- except BaseException:
- Path(handle.name).unlink(missing_ok=True)
+ except ValueError:
+ _drop_archive(Path(handle.name), note)
raise
- if progress is not None and received:
- progress.add(-received)
+ except BaseException:
+ # Stopped: a kept archive waits for the next run.
+ if keep is None:
+ Path(handle.name).unlink(missing_ok=True)
+ raise
+ if progress is not None:
+ if received:
+ progress.add(-received)
+ if resumed:
+ progress.add(-resumed)
+ progress.forget_resumed(resumed)
if attempt < MAX_RETRIES:
time.sleep(_retry_delay(attempt, None))
raise reason if reason else OSError("download failed")
+def _drop_archive(path: Path, note: Path | None) -> None:
+ """Remove an archive and the note of where it came from."""
+ path.unlink(missing_ok=True)
+ if note is not None:
+ note.unlink(missing_ok=True)
+
+
def _archive_members(
archive: Path, entry: dict
) -> Iterator[tuple[str, int, Callable[[], BinaryIO]]]:
@@ -7223,6 +7296,7 @@ def install_data_directory(entry: dict, bios_path: Path,
if not needed:
return counts
_writing.set()
+ fetched: Path | None = None
try:
root.mkdir(parents=True, exist_ok=True)
with tempfile.TemporaryDirectory(dir=root) as scratch:
@@ -7230,7 +7304,11 @@ def install_data_directory(entry: dict, bios_path: Path,
# The pack holds the tree where it extracts, already mapped.
members = LOCAL.pack.tree(entry.get("dest", ""))
else:
- archive = _fetch_archive(entry["url"], Path(scratch), progress)
+ # Beside the tree, outside the scratch folder: a transfer
+ # cut short is resumed by the next attempt or the next run.
+ kept = root / f".{entry['ref']}.archive.part"
+ archive = _fetch_archive(entry["url"], Path(scratch), progress, kept)
+ fetched = archive
members = _archive_members(archive, entry)
for rel, declared, opener in members:
meta = needed.pop(rel, None)
@@ -7264,6 +7342,10 @@ def install_data_directory(entry: dict, bios_path: Path,
except _MEMBER_ERRORS as exc:
# A damaged, encrypted or unsupported member, in words.
counts["error"] = unreadable_words(exc)
+ finally:
+ if fetched is not None:
+ # Read whole: the next run fetches the archive afresh.
+ _drop_archive(fetched, fetched.with_name(fetched.name + ".source"))
counts["absent"] = len(needed)
return counts
diff --git a/install.sh b/install.sh
index fe3d4fd6e..4e6c1560d 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f"
+DEFAULT_INSTALL_SHA256="fdccf00cb56c4caf3ddf916e126d538539e0d9efa527fb808cde954b6b0d29b1"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index acfb61130..2f435fcb1 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1108265,
- "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
+ "size": 1112094,
+ "sha256": "fdccf00cb56c4caf3ddf916e126d538539e0d9efa527fb808cde954b6b0d29b1",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1161892,
- "sha256": "1031750dcd599e0c4dd2e6c39296b3bcada68494a4837ad442150da64b67a55c"
+ "size": 1165721,
+ "sha256": "1b6ea28a5fc2f413aa7444ddb9ebe00b4b89c29ef639d62e3e1cf4d10793ed16"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1108265,
- "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
+ "size": 1112094,
+ "sha256": "fdccf00cb56c4caf3ddf916e126d538539e0d9efa527fb808cde954b6b0d29b1",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1108265,
- "sha256": "567d810f5c4f5cbb6793d6f0c96a7492d90b53664d74f045aae4ef75d6058a0f",
+ "size": 1112094,
+ "sha256": "fdccf00cb56c4caf3ddf916e126d538539e0d9efa527fb808cde954b6b0d29b1",
"executable": false
},
{
diff --git a/tests/test_install.py b/tests/test_install.py
index a918d7d06..13deeaa5c 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -3867,6 +3867,96 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
(len(body), len(body)))
emit.assert_not_called()
+ def test_a_cut_archive_resumes_where_it_stopped(self):
+ """A data archive cut at 90% was deleted and fetched again from
+ zero, on the retry and on the next run, while the run said that
+ nothing was lost."""
+ work = Path(_tempdir(self))
+ body = self._zip(work).read_bytes()
+ keep = work / ".dolphin-sys.archive.part"
+ requests: list[dict] = []
+
+ class Response(io.BytesIO):
+ def __init__(self, data, status, headers):
+ super().__init__(data)
+ self.status, self.headers = status, headers
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc):
+ return False
+
+ def urlopen(request, timeout=None):
+ sent = dict(request.header_items())
+ requests.append(sent)
+ if "Range" in sent:
+ start = int(sent["Range"][len("bytes="):-1])
+ if sent.get("If-range") != '"v1"':
+ return Response(body, 200, {"ETag": '"v2"'})
+ return Response(body[start:], 206, {
+ "Content-Range": f"bytes {start}-{len(body) - 1}/{len(body)}",
+ "Content-Length": str(len(body) - start), "ETag": '"v1"'})
+ cut = len(body) * 9 // 10
+
+ class Cut(Response):
+ def read(self, size=-1):
+ if self.tell() >= cut:
+ raise ConnectionResetError("cut")
+ return super().read(min(size, cut - self.tell()))
+ return Cut(body, 200, {"Content-Length": str(len(body)), "ETag": '"v1"'})
+
+ with unittest.mock.patch.object(install.urllib.request, "urlopen", urlopen), \
+ unittest.mock.patch.object(install, "_network_allowed", lambda url: None), \
+ unittest.mock.patch.object(install, "_retry_delay", lambda *a: 0):
+ # The next run, after a stop: what the cut attempt wrote is kept.
+ with unittest.mock.patch.object(install, "MAX_RETRIES", 1), \
+ self.assertRaises(ConnectionResetError):
+ install._fetch_archive("https://example.invalid/D.zip", work, None, keep)
+ self.assertEqual(keep.stat().st_size, len(body) * 9 // 10)
+ path = install._fetch_archive("https://example.invalid/D.zip", work, None, keep)
+ self.assertEqual(path.read_bytes(), body)
+ self.assertEqual(requests[-1]["Range"], f"bytes={len(body) * 9 // 10}-")
+ self.assertEqual(requests[-1]["If-range"], '"v1"')
+
+ def test_a_changed_archive_is_fetched_whole(self):
+ work = Path(_tempdir(self))
+ body = self._zip(work).read_bytes()
+ keep = work / ".dolphin-sys.archive.part"
+ keep.write_bytes(b"older revision")
+ keep.with_name(keep.name + ".source").write_text(
+ 'https://example.invalid/D.zip\n"v0"\n')
+
+ class Whole(io.BytesIO):
+ status, headers = 200, {"ETag": '"v1"'}
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc):
+ return False
+
+ with unittest.mock.patch.object(install.urllib.request, "urlopen",
+ lambda request, timeout=None: Whole(body)), \
+ unittest.mock.patch.object(install, "_network_allowed", lambda url: None):
+ path = install._fetch_archive("https://example.invalid/D.zip", work, None, keep)
+ self.assertEqual(path.read_bytes(), body)
+
+ def test_a_tree_read_whole_leaves_no_archive(self):
+ work = Path(_tempdir(self))
+ archive = self._zip(work)
+ bios = work / "system"
+ bios.mkdir()
+
+ def fetch(url, directory, progress=None, keep=None):
+ shutil.copy(archive, keep)
+ keep.with_name(keep.name + ".source").write_text(f"{url}\n\"v1\"\n")
+ return keep
+
+ with unittest.mock.patch.object(install, "_fetch_archive", fetch):
+ install.install_data_directory(self._entry(), bios)
+ self.assertEqual([p.name for p in (bios / "dolphin-emu").iterdir()], ["Sys"])
+
def test_the_run_ends_on_the_archive_bytes_too(self):
from test_install_selection import FakeRepository # noqa: PLC0415
@@ -3925,7 +4015,7 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
bios = work / "system"
bios.mkdir()
- def fetch(url, directory, progress=None):
+ def fetch(url, directory, progress=None, keep=None):
copy = Path(directory) / "a.zip"
shutil.copy(archive, copy)
return copy
@@ -3961,8 +4051,9 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
def members(_archive, _entry):
yield "Sys/GC/font.bin", 4, lambda: io.BufferedReader(Endless())
- with unittest.mock.patch.object(install, "_fetch_archive",
- lambda url, d, progress=None: Path(d) / "a"), \
+ with unittest.mock.patch.object(
+ install, "_fetch_archive",
+ lambda url, d, progress=None, keep=None: Path(d) / "a"), \
unittest.mock.patch.object(install, "_archive_members", members):
counts = install.install_data_directory(entry, work)
self.assertEqual(counts["changed"], 1)
@@ -3989,8 +4080,9 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
def members(_archive, _entry):
yield "Sys/GC/font.bin", 4, lambda: io.BufferedReader(Broken())
- with unittest.mock.patch.object(install, "_fetch_archive",
- lambda url, d, progress=None: Path(d) / "a"), \
+ with unittest.mock.patch.object(
+ install, "_fetch_archive",
+ lambda url, d, progress=None, keep=None: Path(d) / "a"), \
unittest.mock.patch.object(install, "_archive_members", members):
counts = install.install_data_directory(entry, work)
self.assertTrue(counts["error"])
@@ -6714,7 +6806,7 @@ class AFileYouHadIsKept(unittest.TestCase):
"type": "zip", "files": {"Sys/a.ini": {
"sha1": hashlib.sha1(self.NEW).hexdigest(), "size": len(self.NEW)}}}
- def fetch(url, directory, progress=None):
+ def fetch(url, directory, progress=None, keep=None):
copy = Path(directory) / "a.zip"
shutil.copy(archive, copy)
return copy
diff --git a/wiki/installer.md b/wiki/installer.md
index 796938117..1aa89e133 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -352,8 +352,10 @@ file list is downloaded once and handed to each run.
times, after 1, 2 then 4 seconds or the delay a `Retry-After` header asks.
A file of 16 MB or more keeps its partial copy (`..part`) when a
transfer stops, and the next attempt or the next run requests only the
- rest. A file already there with other contents is moved aside first, see
- [Files you already had](#files-you-already-had).
+ rest. A data tree's archive does the same beside the tree
+ (`.[.archive.part`), asking with `If-Range` so that a server whose
+ archive changed sends it whole. A file already there with other contents
+ is moved aside first, see [Files you already had](#files-you-already-had).
8. Copies into standalone emulator directories, only with `--standalone-copies`.
The file list names the version of the platform it was built for (Batocera
From 9633ce3dd4e9c7d5fe63af339d8072f2aee6fd9c Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:08:09 +0100
Subject: [PATCH 68/83] refactor: normalize each system id once
SelectionIndex.build and system_group called _norm_system_id 1.7 million times per manifest run for about a thousand ids, each through the manufacturer prefix loop. The function reads only its argument and two constant tables, so its answer is cached. Measured on the call volume of one manifest run (630 ids, 1,686,618 calls): 1.53 s uncached, 0.07 s cached. The end-to-end manifest run moves inside its own noise on this host (45.9 to 50.6 s across four runs).
---
scripts/common.py | 4 ++++
tests/test_system_ids.py | 12 ++++++++++++
2 files changed, 16 insertions(+)
diff --git a/scripts/common.py b/scripts/common.py
index 50c90874d..1a88caaff 100644
--- a/scripts/common.py
+++ b/scripts/common.py
@@ -3036,12 +3036,16 @@ SYSTEM_ALIASES: dict[str, str] = {
}
+@functools.lru_cache(maxsize=None)
def _norm_system_id(sid: str) -> str:
"""Normalize system ID for cross-platform matching.
Resolves known aliases, then strips manufacturer prefixes and separators
so that platform-specific IDs (e.g., "xbox", "nintendo-wiiu") match
profile IDs (e.g., "microsoft-xbox", "nintendo-wii-u").
+
+ A function of the string and two constant tables: a manifest run asks it
+ 1.7 million times for about 1,100 ids.
"""
s = sid.lower().replace("_", "-")
s = SYSTEM_ALIASES.get(s, s)
diff --git a/tests/test_system_ids.py b/tests/test_system_ids.py
index cc054d902..1b8098c58 100644
--- a/tests/test_system_ids.py
+++ b/tests/test_system_ids.py
@@ -73,6 +73,18 @@ class PlatformNamesReachTheProfileSystem(unittest.TestCase):
with self.subTest(alias=alias):
self.assertEqual(_norm_system_id(alias), _norm_system_id(canonical))
+ def test_each_id_is_normalized_once(self):
+ """A manifest run asked 1.7 million times for about a thousand ids,
+ 1.5 seconds of prefix loops: the answer is kept per id."""
+ _norm_system_id.cache_clear()
+ for _ in range(3):
+ _norm_system_id("Nintendo_WiiU")
+ info = _norm_system_id.cache_info()
+ self.assertEqual((info.misses, info.hits), (1, 2))
+ self.assertEqual(
+ _norm_system_id("Nintendo_WiiU"), _norm_system_id.__wrapped__("Nintendo_WiiU")
+ )
+
class AFoldedClaimKeepsItsProof(unittest.TestCase):
"""One spelling per machine folds bsnes-hd's SGB1.sfc onto bsnes's: the
From ef6607302d333d2e3b98592062d2fd6bbc21a59c Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:11:02 +0100
Subject: [PATCH 69/83] chore: rebuild the site when siteinputs changes
Every page module reads its inputs from scripts/siteinputs.py, so the
deploy workflow names it with the other site modules.
---
.github/workflows/deploy-site.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml
index 145b8dd4b..67130fe8f 100644
--- a/.github/workflows/deploy-site.yml
+++ b/.github/workflows/deploy-site.yml
@@ -49,6 +49,7 @@ on:
- "scripts/sitediagrams.py"
- "scripts/siteentries.py"
- "scripts/siteguides.py"
+ - "scripts/siteinputs.py"
- "scripts/sitemarkup.py"
- "scripts/sitemeasurements.py"
- "scripts/siteexports.py"
From 462b61a4bcbcaef48ecac3c4712f9ed4a3317bc7 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:11:37 +0100
Subject: [PATCH 70/83] refactor: compute slot choices once per manifest
generate_manifest called slot_choices, and pack_overrides called it again with the same five arguments. pack_overrides takes the choices when the caller holds them. Measured on generate_pack.py --all --manifest --offline: 48 calls and 7.0 s in slot_choices before, 24 calls and 4.3 s after (wall 45.7 s and 42.4 s, one run each on a loaded host). The manifests written are identical.
---
scripts/generate_pack.py | 16 +++++++++-------
scripts/slots.py | 12 +++++++-----
tests/test_install_selection.py | 10 ++++++++++
3 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py
index 3e3c2754c..8fa8faabb 100644
--- a/scripts/generate_pack.py
+++ b/scripts/generate_pack.py
@@ -4609,16 +4609,18 @@ def generate_manifest(
# (cache file, size). Settled once the trees are walked.
cache_held: dict[str, tuple[str, int]] = {}
rename_notes: set[str] = set()
+ # The full manifest records every core's answer at a contested slot, so a
+ # target narrowed from it gets what that target's own pack serves.
+ whole = target_cores is None and source != "platform" and bool(emu_profiles)
+ slot_choices = (
+ slots.slot_choices(config, emu_profiles, db, zip_contents, data_registry)
+ if whole else {}
+ )
+ # Derived from the same choices: computed twice, it was 8% of a run.
slot_overrides = slots.pack_overrides(
config, emu_profiles, db, zip_contents, data_registry,
target_cores=target_cores, source=source,
- )
- # The full manifest records every core's answer at a contested slot, so a
- # target narrowed from it gets what that target's own pack serves.
- slot_choices = (
- slots.slot_choices(config, emu_profiles, db, zip_contents, data_registry)
- if target_cores is None and source != "platform" and emu_profiles
- else {}
+ choices=slot_choices if whole else None,
)
def manifest_destination(full_destination: str) -> str:
diff --git a/scripts/slots.py b/scripts/slots.py
index 8e7f826cd..5fac56af1 100644
--- a/scripts/slots.py
+++ b/scripts/slots.py
@@ -514,6 +514,7 @@ def pack_overrides(
data_dir_registry: dict | None = None,
target_cores: set[str] | None = None,
source: str = "full",
+ choices: dict[str, list[tuple[str, str | None]]] | None = None,
) -> dict[str, str]:
"""Full pack destination -> the file a platform pack serves there instead.
@@ -522,7 +523,8 @@ def pack_overrides(
existence mode the frontend never reads the bytes, so serving the
emulator's file satisfies both. The ZIP builder, the install manifest and
verify all read this: two of them deciding alone gave the one-line
- installer different bytes than the ZIP.
+ installer different bytes than the ZIP. ``choices`` is slot_choices
+ for the same arguments when the caller already holds it.
"""
# A baseline-only pack serves what the platform declares, and a target's
# pack answers to the cores that hardware builds: DuckStation does not
@@ -531,10 +533,10 @@ def pack_overrides(
return {}
cores = set(resolve_platform_cores(config, profiles, target_cores=target_cores))
overrides: dict[str, str] = {}
- for destination, choices in slot_choices(
- config, profiles, db, zip_contents, data_dir_registry
- ).items():
- path = next((path for emulator, path in choices if emulator in cores), None)
+ if choices is None:
+ choices = slot_choices(config, profiles, db, zip_contents, data_dir_registry)
+ for destination, ordered in choices.items():
+ path = next((path for emulator, path in ordered if emulator in cores), None)
if path:
overrides[destination] = path
return overrides
diff --git a/tests/test_install_selection.py b/tests/test_install_selection.py
index 71dbd5725..94f5589c8 100644
--- a/tests/test_install_selection.py
+++ b/tests/test_install_selection.py
@@ -1231,6 +1231,16 @@ class AnExtraBesideItsDeclarationBelowTheBiosFolder(unittest.TestCase):
)
return {m for m in record.members if m.startswith("bios/")}
+ def test_the_slot_choices_are_computed_once(self):
+ """pack_overrides recomputed the choices the manifest had just
+ computed with the same arguments: 8% of a manifest run."""
+ import slots
+
+ real = slots.slot_choices
+ with mock.patch.object(slots, "slot_choices", side_effect=real) as counted:
+ self._manifest(None)
+ self.assertEqual(counted.call_count, 1)
+
def test_the_pack_and_the_installer_drop_the_same_files(self):
full = self._manifest(None)
files, _omitted = install.narrow(
From 856cb5618fcbed70c834a74da1b8be521e25bce5 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:14:42 +0100
Subject: [PATCH 71/83] fix: link a build file only where it is recorded
Every source link on the site leads to a path the source record saw at
a commit. The Build file row linked pin_build files unchecked, eight of
them at commits the record did not hold. build_source_paths now records
the build files read at a commit, and the row links only those: a tag
can move and stays plain text. The record run also picked up two cited
paths it had not seen before (pom2 CMakeLists.txt, pcem configure.ac).
---
scripts/generate_site.py | 13 ++++++++-----
scripts/sitesources.py | 19 +++++++++++++++++++
tests/test_audit_regressions.py | 27 +++++++++++++++++++++++----
website/src/data/source-paths.json | 14 ++++++++++++++
4 files changed, 64 insertions(+), 9 deletions(-)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index fe43620af..127c8aa3e 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -8198,17 +8198,20 @@ def _exact_size(size: int) -> str:
def _build_file_links(pin_build: list[dict]) -> list[str]:
"""Each platform build file that holds the revision, linked at the
- revision it was read at. The prose of pin_frozen named the file as
- plain text, while pin_build carries all a pinned link needs."""
- from sitesources import _browse_repo, _source_permalink # noqa: PLC0415
+ commit it was read at when the source record holds it. The prose of
+ pin_frozen named the file as plain text."""
+ from sitesources import _browse_repo, _source_permalink, tree_holds # noqa: PLC0415
links = []
for build in pin_build:
repo = _browse_repo(str(build["repo"]))
path = str(build["path"])
+ revision = str(build["revision"])
text = f"{_escape_tags(_platform_display(str(build['platform'])))} {_code(path)}"
- if repo is not None:
- text = f"[{text}]({_source_permalink(repo, str(build['revision']), path, None, None)})"
+ # Linked where the record saw the file at that commit, as every
+ # source link is: a tag can move, and is never recorded.
+ if repo is not None and tree_holds(repo, revision, path):
+ text = f"[{text}]({_source_permalink(repo, revision, path, None, None)})"
links.append(f"{text} at {_code(str(build['revision']))} sets {_code(str(build['variable']))}")
return links
diff --git a/scripts/sitesources.py b/scripts/sitesources.py
index f42de04ae..c28b7c5f1 100644
--- a/scripts/sitesources.py
+++ b/scripts/sitesources.py
@@ -321,9 +321,28 @@ def build_source_paths(
# Recorded even when it holds no cited path, so a pinned tree
# missing from the record is one no run has read.
held.setdefault(tree_key(repo, pin), set()).update(paths & tree)
+ for repo, pin, path in build_files(profile):
+ tree = (_cached_tree(repo, pin, cache_dirs, fetch)
+ or _listed_directories(repo, pin, {path}, cache_dirs, fetch))
+ if tree is None:
+ unread.add(tree_key(repo, pin))
+ continue
+ held.setdefault(tree_key(repo, pin), set()).update({path} & tree)
return {key: sorted(paths) for key, paths in sorted(held.items())}, sorted(unread)
+def build_files(profile: dict) -> list[tuple[upstream.Repo, str, str]]:
+ """The platform build files `pin_build` names at a commit, as (repo,
+ revision, path). A tag can move, so a build read at a tag is not linked."""
+ found = []
+ for build in profile.get("pin_build") or []:
+ repo = _browse_repo(str(build.get("repo", "")))
+ revision = str(build.get("revision", ""))
+ if repo is not None and re.fullmatch(r"[0-9a-f]{40}", revision):
+ found.append((repo, revision, str(build.get("path", ""))))
+ return found
+
+
def keep_unread(
held: dict[str, list[str]], unread: list[str], previous: dict[str, list[str]]
) -> dict[str, list[str]]:
diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py
index 6776263b8..da75706d6 100644
--- a/tests/test_audit_regressions.py
+++ b/tests/test_audit_regressions.py
@@ -5222,11 +5222,30 @@ class AHeldRevisionLinksItsBuildFile(unittest.TestCase):
"platform": "knulli", "repo": "https://github.com/knulli-cfw/knulli-linux",
"revision": "20260511", "path": "package/emulators/advanced_drastic/advanced_drastic.mk",
"variable": "ADVANCED_DRASTIC_VERSION", "value": "eaf41ab9"}]})
+ # A tag can move: named, never linked.
self.assertIn(
- "| Build file | [KNULLI `package/emulators/advanced_drastic/advanced_drastic.mk`]"
- "(https://github.com/knulli-cfw/knulli-linux/blob/20260511/package/emulators/"
- "advanced_drastic/advanced_drastic.mk) at `20260511` sets `ADVANCED_DRASTIC_VERSION` |",
- rows)
+ "| Build file | KNULLI `package/emulators/advanced_drastic/advanced_drastic.mk` "
+ "at `20260511` sets `ADVANCED_DRASTIC_VERSION` |", rows)
+
+ def test_a_build_read_at_a_recorded_commit_links(self):
+ from scripts.generate_site import _build_rows
+
+ pin = "46128cd252cdecae852a4d0bafa2aaf9d03ab563"
+ rows = _build_rows({"pin_build": [{
+ "platform": "retropie", "repo": "https://github.com/RetroPie/RetroPie-Setup",
+ "revision": pin, "path": "scriptmodules/emulators/advmame-1.4.sh",
+ "variable": "rp_module_repo", "value": "x"}]})
+ self.assertIn(
+ f"[RetroPie `scriptmodules/emulators/advmame-1.4.sh`](https://github.com/RetroPie/"
+ f"RetroPie-Setup/blob/{pin}/scriptmodules/emulators/advmame-1.4.sh)", rows[0])
+
+ def test_the_record_holds_the_build_files(self):
+ import sitesources # noqa: PLC0415
+
+ files = sitesources.build_files({"pin_build": [
+ {"repo": "https://github.com/o/r", "revision": "a" * 40, "path": "p.mk"},
+ {"repo": "https://github.com/o/r", "revision": "v1", "path": "q.mk"}]})
+ self.assertEqual([(f[1], f[2]) for f in files], [("a" * 40, "p.mk")])
class AVariantCardSaysWhatToSaveItAs(unittest.TestCase):
diff --git a/website/src/data/source-paths.json b/website/src/data/source-paths.json
index d591448f7..d0f00e7a2 100644
--- a/website/src/data/source-paths.json
+++ b/website/src/data/source-paths.json
@@ -424,6 +424,11 @@
"crates/wqxemu/src/keypad.rs",
"crates/wqxemu/src/main.rs"
],
+ "github.com/AmberELEC/AmberELEC@a21975bfb1a3af68f66e07a931b994b523e1e6e2": [
+ "packages/games/emulators/lzdoom/package.mk",
+ "packages/games/emulators/piemu/package.mk",
+ "packages/games/libretro/flycast2021le/package.mk"
+ ],
"github.com/Amjad50/plastic@74152adb3acd890d3abee2ff5906408f26a199e2": [
"plastic_core/src/cartridge/mod.rs",
"plastic_core/src/display/color.rs",
@@ -1584,6 +1589,13 @@
"imagine/src/font/FreetypeFont.cc",
"imagine/src/fs/ArchiveFS.cc"
],
+ "github.com/RetroPie/RetroPie-Setup@46128cd252cdecae852a4d0bafa2aaf9d03ab563": [
+ "scriptmodules/emulators/advmame-1.4.sh",
+ "scriptmodules/emulators/ppsspp-1.5.4.sh",
+ "scriptmodules/ports/alephone.sh",
+ "scriptmodules/ports/love-0.10.2.sh",
+ "scriptmodules/ports/lzdoom.sh"
+ ],
"github.com/RetroPie/mame4all-pi@c6bfd2aef331b5a5e157c15d8bf8a77393c85689": [
"readme.txt",
"src/cheat.cpp",
@@ -3475,6 +3487,7 @@
"src/ui/video.rs"
],
"github.com/habib256/pom2@de86e8e35df96fe6ffced56dfb727bbd567f8568": [
+ "CMakeLists.txt",
"packaging/bundle.manifest",
"packaging/fujinet/stage.py",
"src/AppleParallelCard.cpp",
@@ -8930,6 +8943,7 @@
"nes.c"
],
"github.com/sarah-walker-pcem/pcem@10739b9618e388a5bf8c21e752f12b3952fa83e1": [
+ "configure.ac",
"src/mem.c",
"src/nvr.c",
"src/ps1.c",
From adcfa283fb125a2bd853c4517a78a77e9aa0e5c7 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:14:47 +0100
Subject: [PATCH 72/83] docs: keep the FAQ under its word ceiling
The --core answer added 14 words to a page held at 450. It now names the
command in as many words as the line it replaced, and the --region line
goes: what --region keeps is on the installer page.
---
wiki/faq.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/wiki/faq.md b/wiki/faq.md
index 70548bfc3..f3429d353 100644
--- a/wiki/faq.md
+++ b/wiki/faq.md
@@ -25,15 +25,13 @@ curl -fsSL https://abdess.github.io/retrobios/i | sh -s -- --dry-run
## Do I need every file of a console?
-No. `--core` keeps what your emulator reads, here PCSX for PlayStation:
+No. `--core pcsx1` keeps what PCSX reads:
```sh
curl -fsSL https://abdess.github.io/retrobios/i | sh -s -- --system sony-playstation --core pcsx1
```
-`--region us` drops another region's BIOS where a US one exists.
-
## Does the BIOS set the game's language?
Rarely. It comes from the game. Some follow the console's setting, like Flycast's **Language**
From 21f4122c83b397370d3506aa8527292c9e36ebaf Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:43:06 +0100
Subject: [PATCH 73/83] fix: collisions keep the platform's order
Walking the systems sorted reordered the declarations doubled.py
reports from, so the export report named the CoCo reader first. The
declarations keep the platform's order again, and the packed file is
picked from the sorted walk the builder makes.
---
scripts/slots.py | 16 ++++++++++------
tests/test_slots.py | 2 +-
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/scripts/slots.py b/scripts/slots.py
index 0b69507d3..d08a0b7a4 100644
--- a/scripts/slots.py
+++ b/scripts/slots.py
@@ -675,7 +675,7 @@ class Collision:
destination: str
resolved: list[str]
- # Each declaration with the file it resolved to, in the builder's order.
+ # Each declaration with the file it resolved to, in the platform's order.
declarations: list[tuple[dict, str | None]] = field(default_factory=list)
# The system of each declaration, in the same order.
systems: list[str] = field(default_factory=list)
@@ -712,14 +712,14 @@ def find_collisions(
"""
fold = bool(config.get("case_insensitive_fs", False))
systems = config.get("systems") or {}
- # The builder walks the systems sorted and lets a hash-constrained
- # declaration that resolves by content take the path: the same order
- # and the same choice say which file ships.
+ # The builder lets a hash-constrained declaration that resolves by
+ # content take the path, else the first it reaches walking the systems
+ # sorted: the same choice says which file ships.
preferred = set(
preferred_entries(systems, db, "bios", "", False, zip_contents, True).values()
)
by_dest: dict[str, list[tuple[str, dict]]] = {}
- for sys_id, system in sorted(systems.items()):
+ for sys_id, system in systems.items():
for entry in system.get("files") or []:
if not isinstance(entry, dict):
continue
@@ -751,9 +751,13 @@ def find_collisions(
# also names the first one's file.
if any(_accepted_by_all(path, entries, db) for path in resolved):
continue
+ reached = sorted(
+ (sys_id, local)
+ for (sys_id, _entry), (_e, local) in zip(claims, declarations) if local
+ )
shipped = next(
(local for entry, local in declarations if local and id(entry) in preferred),
- resolved[0],
+ reached[0][1],
)
collisions.append(
Collision(
diff --git a/tests/test_slots.py b/tests/test_slots.py
index 64dd87669..fb0e33e6c 100644
--- a/tests/test_slots.py
+++ b/tests/test_slots.py
@@ -520,7 +520,7 @@ class TestSelfContradictingDestinations(unittest.TestCase):
}}
collision = slots.find_collisions(config, REGIONS_DB)[0]
line = slots.format_collision(collision)
- packed, left = collision.resolved
+ left, packed = collision.resolved
# The builder walks the systems sorted: alpha's declaration ships.
self.assertIn(f"{packed} (alpha) packed", line)
self.assertIn(f"{left} (zeta) left out", line)
From 2c60b5f20da98eb05957b8a71c5a307298e6b043 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:43:07 +0100
Subject: [PATCH 74/83] docs: refresh_stale names pin_installer plainly
The docstring line naming pin_installer.py read as a clause after a
semicolon, which the prose test refuses.
---
scripts/refresh_stale.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/refresh_stale.py b/scripts/refresh_stale.py
index 5ec112efc..bf65bb6ac 100755
--- a/scripts/refresh_stale.py
+++ b/scripts/refresh_stale.py
@@ -34,8 +34,8 @@ has ended, and its export is rewritten even when no row named it.
Surfaced only (no refresh): data rows that are not a _data_dirs.yml key
(the registry itself, buildbot assets it does not track), coreinfo gaps, redump/no-intro/tosec packs,
-CI pins (PyPI, pinned actions; the install.py SHA-256 pin is written by
-scripts/pin_installer.py), profile_sync, rom-folder
+CI pins (PyPI, pinned actions, while scripts/pin_installer.py writes the
+install.py SHA-256 pin), profile_sync, rom-folder
pins (moved by hand, then python -m scripts.scraper.romfolders --setup NAME
reads them again). Each needs
a human read (new .info file, manual DAT download, PyPI version bump).
From 508dc4d0394a85f989d3c36e46db406e2e098047 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:44:28 +0100
Subject: [PATCH 75/83] docs: list the new test modules
test_twin_declaration_status and test_verify_data_dir_notice join the testing guide table, and test_large_file_cache calls unittest.main after its last class.
---
tests/test_large_file_cache.py | 8 ++++----
wiki/testing-guide.md | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/test_large_file_cache.py b/tests/test_large_file_cache.py
index 783c5541b..909ede2cf 100644
--- a/tests/test_large_file_cache.py
+++ b/tests/test_large_file_cache.py
@@ -790,10 +790,6 @@ class ASameSizeReuploadIsSeen(unittest.TestCase):
)
-if __name__ == "__main__":
- unittest.main()
-
-
class AVerifiedPathKeepsItsBytes(unittest.TestCase):
"""fetch_large_file verified a cached copy and returned its name. Another
run that found the release re-uploaded then replaced that name with the
@@ -838,3 +834,7 @@ class AVerifiedPathKeepsItsBytes(unittest.TestCase):
[p.name for p in (self.dir / largefiles.VERIFIED_STORE).iterdir()],
[hashlib.sha1(PAYLOAD_B).hexdigest()],
)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md
index 3ef512d15..c1de78249 100644
--- a/wiki/testing-guide.md
+++ b/wiki/testing-guide.md
@@ -50,8 +50,8 @@ Every module in `tests/`, by the area it guards.
| Area | Fixtures | Modules |
|------|----------|---------|
| Core regression suites | synthetic | `test_e2e`, `test_audit_regressions`, `test_tool_messages` |
-| File resolution and identity | synthetic + collection | `test_adler32_resolution`, `test_agnostic_scan`, `test_agnostic_scan_mode`, `test_agnostic_scope`, `test_agnostic_substitute`, `test_archive_choice`, `test_archive_recipes`, `test_bios_companions`, `test_bundled_identity`, `test_casefold_cache`, `test_db_aliases`, `test_declared_names`, `test_derivations`, `test_directory_entries`, `test_extra_identity`, `test_foreign_tree`, `test_foreign_tree_names`, `test_frontend_digest`, `test_game_data_homonyms`, `test_hashing`, `test_identity`, `test_maker_folder_names`, `test_md5_pack_context`, `test_name_tiebreak`, `test_nec_filing`, `test_np2_fonts`, `test_owner_resolution`, `test_path_suffix`, `test_resolution_evidence`, `test_sega_filing`, `test_shipped_content`, `test_twin_declarations`, `test_validated_choice`, `test_variant_choice`, `test_variant_identity`, `test_zipped_member` |
-| Verification, cross-reference and profile checks | synthetic + profiles | `test_bios_layout`, `test_cache_independent_counts`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_entry_categories`, `test_file_consumers`, `test_fileless_audit`, `test_flycast_layout`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_aliases`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_profile_names`, `test_profile_paths`, `test_profile_repositories`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_links`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` |
+| File resolution and identity | synthetic + collection | `test_adler32_resolution`, `test_agnostic_scan`, `test_agnostic_scan_mode`, `test_agnostic_scope`, `test_agnostic_substitute`, `test_archive_choice`, `test_archive_recipes`, `test_bios_companions`, `test_bundled_identity`, `test_casefold_cache`, `test_db_aliases`, `test_declared_names`, `test_derivations`, `test_directory_entries`, `test_extra_identity`, `test_foreign_tree`, `test_foreign_tree_names`, `test_frontend_digest`, `test_game_data_homonyms`, `test_hashing`, `test_identity`, `test_maker_folder_names`, `test_md5_pack_context`, `test_name_tiebreak`, `test_nec_filing`, `test_np2_fonts`, `test_owner_resolution`, `test_path_suffix`, `test_resolution_evidence`, `test_sega_filing`, `test_shipped_content`, `test_twin_declaration_status`, `test_twin_declarations`, `test_validated_choice`, `test_variant_choice`, `test_variant_identity`, `test_zipped_member` |
+| Verification, cross-reference and profile checks | synthetic + profiles | `test_bios_layout`, `test_cache_independent_counts`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_entry_categories`, `test_file_consumers`, `test_fileless_audit`, `test_flycast_layout`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_aliases`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_profile_names`, `test_profile_paths`, `test_profile_repositories`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_links`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_data_dir_notice`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` |
| Packs and manifests | synthetic + real packs | `test_artifact_lock`, `test_atomic_artifacts`, `test_batocera_cores`, `test_core_data_trees`, `test_deterministic_zip`, `test_emulator_pack_counts`, `test_finalize_pack_names`, `test_large_file_cache`, `test_libretro_layout`, `test_manifest_entry`, `test_minui_platform`, `test_no_game_data`, `test_pack_conformance_dirs`, `test_pack_core_extras`, `test_pack_counts`, `test_pack_destinations`, `test_pack_failures`, `test_pack_file_names`, `test_pack_grouping`, `test_pack_integrity`, `test_pack_member_identity`, `test_pack_readme`, `test_platform_inheritance`, `test_platform_keys`, `test_release_packs`, `test_required_only_archives`, `test_required_only_twins`, `test_save_root`, `test_split_extras`, `test_split_names`, `test_split_pack`, `test_system_pack_extras`, `test_system_pack_parity`, `test_torrentzip`, `test_which_pack` |
| Slots and regions | synthetic + profiles | `test_region`, `test_region_agnostic_scan`, `test_region_groups`, `test_region_held`, `test_region_platform_index`, `test_region_required_only`, `test_slot`, `test_slots`, `test_slots_shipped_file` |
| Hardware targets and systems | synthetic + target files | `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |
From f9f7ad3b922a1a39edc75f38a6edc6b748c1bed2 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:46:37 +0100
Subject: [PATCH 76/83] docs: quote the bundled line in the verify excerpt
reading-reports quotes a RetroDECK run, which now prints the bundled count and 30 missing game data instead of 38. The comment introducing the bundled names also loses its semicolon.
---
scripts/verify.py | 2 +-
wiki/reading-reports.md | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/scripts/verify.py b/scripts/verify.py
index b12991d90..f63d70d4a 100644
--- a/scripts/verify.py
+++ b/scripts/verify.py
@@ -1887,7 +1887,7 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
for u in opt_not_in_repo:
_print_undeclared_entry(u, "MISSING (optional)", verbose, repeated)
if bundled:
- # The required firmware is named, as a missing one would be; the
+ # The required firmware is named, as a missing one would be. The
# rest (shaders, runtime libraries, engine data) on request.
shown = bundled if verbose else [
u for u in bundled
diff --git a/wiki/reading-reports.md b/wiki/reading-reports.md
index 09345c90c..a3bfd6765 100644
--- a/wiki/reading-reports.md
+++ b/wiki/reading-reports.md
@@ -110,7 +110,8 @@ RetroDECK: 2007/2008 OK, 1 untested [md5]
Core files: 1764 in pack, 1 required missing, 26 optional missing (--verbose lists them)
Core files held but not packed: 154 (142 installed with its emulator, 8 read below a save folder per system and no system runs the core there, 4 a packed file occupies its directory)
MISSING (required): FinalBurn Neo needs sfiii2a.zip (1 file)
- Game data: 5099 in pack, 38 missing (--verbose lists them)
+ Bundled with their emulator, not collected: 20
+ Game data: 5099 in pack, 30 missing (--verbose lists them)
Game data held but not packed: 30 (installed with its emulator)
No external files: 78 cores (--verbose lists them)
Ground truth: 97/2008 files have emulator validation (5%)
From 3672c6de4a7bd8ce18eee84f82c97a2414b5c8fb Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:46:37 +0100
Subject: [PATCH 77/83] docs: list the AmberELEC target scraper
---
wiki/adding-a-scraper.md | 1 +
wiki/testing-guide.md | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/wiki/adding-a-scraper.md b/wiki/adding-a-scraper.md
index df8db46d0..7dc29ef32 100644
--- a/wiki/adding-a-scraper.md
+++ b/wiki/adding-a-scraper.md
@@ -338,6 +338,7 @@ Register the target scraper in `_registry.yml`:
| `lakka_targets` | Lakka-LibreELEC `package.mk` and project options | Core list minus each project and device's exclusions |
| `recalbox_targets` | board defconfigs + `system.ini` | Buildroot packages each image enables, cores per system |
| `rocknix_targets` | emulators `package.mk` + device options | Cores per SoC block and 32-bit support per device |
+| `amberelec_targets` | Makefile devices + metapackage `package.mk` + `es_systems.cfg` | Extra cores kept only on the devices the metapackage names |
## Parser modules
diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md
index 3ef512d15..27866d49b 100644
--- a/wiki/testing-guide.md
+++ b/wiki/testing-guide.md
@@ -54,7 +54,7 @@ Every module in `tests/`, by the area it guards.
| Verification, cross-reference and profile checks | synthetic + profiles | `test_bios_layout`, `test_cache_independent_counts`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_entry_categories`, `test_file_consumers`, `test_fileless_audit`, `test_flycast_layout`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_aliases`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_profile_names`, `test_profile_paths`, `test_profile_repositories`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_links`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` |
| Packs and manifests | synthetic + real packs | `test_artifact_lock`, `test_atomic_artifacts`, `test_batocera_cores`, `test_core_data_trees`, `test_deterministic_zip`, `test_emulator_pack_counts`, `test_finalize_pack_names`, `test_large_file_cache`, `test_libretro_layout`, `test_manifest_entry`, `test_minui_platform`, `test_no_game_data`, `test_pack_conformance_dirs`, `test_pack_core_extras`, `test_pack_counts`, `test_pack_destinations`, `test_pack_failures`, `test_pack_file_names`, `test_pack_grouping`, `test_pack_integrity`, `test_pack_member_identity`, `test_pack_readme`, `test_platform_inheritance`, `test_platform_keys`, `test_release_packs`, `test_required_only_archives`, `test_required_only_twins`, `test_save_root`, `test_split_extras`, `test_split_names`, `test_split_pack`, `test_system_pack_extras`, `test_system_pack_parity`, `test_torrentzip`, `test_which_pack` |
| Slots and regions | synthetic + profiles | `test_region`, `test_region_agnostic_scan`, `test_region_groups`, `test_region_held`, `test_region_platform_index`, `test_region_required_only`, `test_slot`, `test_slots`, `test_slots_shipped_file` |
-| Hardware targets and systems | synthetic + target files | `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |
+| Hardware targets and systems | synthetic + target files | `test_amberelec_targets`, `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |
| Installer and downloads | loopback server | `test_check_release`, `test_download`, `test_install`, `test_install_cores`, `test_install_experience`, `test_install_app`, `test_install_from`, `test_install_games`, `test_install_offline`, `test_install_selection`, `test_install_tui` |
| Handheld launchers | a pty as the console, fake installer and firmware tools, stubbed PortMaster dialogs | `test_handheld_launchers`, `test_port` |
| Running cores | parsers on fixed inputs, a libretro core built from C in the test when a compiler exists | `test_core_probe` |
From 8a14a1f75c0729e3115b30a1895dfa8db9c6452e Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 09:58:47 +0100
Subject: [PATCH 78/83] docs: regenerate README counts
et4000.bin is no longer counted held for dosbox-x on Batocera and KNULLI.
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index ed1f62cc9..49f4de09f 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ These are the files an emulator loads from disk instead of carrying inside itsel
Each file is checked the way your platform checks it. Most compare a checksum, the fingerprint of a file's contents, which catches a corrupt or unexpected copy. RetroArch, Lakka and RetroPie check that the file is present under its name without reading its contents (`path_is_valid` in RetroArch's `core_info.c`), and MinUI, NextUI and MyMinUI hand each core its folder without opening a file in it: the Coverage table says which applies to you. Independently of that, the collection records five fingerprints per file, and wherever an emulator's code states an expected size or hash, that value is read from its source and rechecked here.
-- **1,086 files** the platforms' emulators load are still to be found, and 138 more the collection does not hold and does not serve by name (retail data, per-user keys, user-filled slots), each with its reason. Both are named in the [gap analysis](https://abdess.github.io/retrobios/gaps/)
+- **1,087 files** the platforms' emulators load are still to be found, and 138 more the collection does not hold and does not serve by name (retail data, per-user keys, user-filled slots), each with its reason. Both are named in the [gap analysis](https://abdess.github.io/retrobios/gaps/)
- **18 platforms** supported with platform-specific verification
- **623 emulators** profiled from source (RetroArch cores + standalone)
- **532 systems** handled by those emulators (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
@@ -102,11 +102,11 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
| Platform | On its BIOS list | Files its emulators load | Checked by |
|----------|-----------------:|-------------------------:|------------|
| AmberELEC | 414/434 | 4,754/4,937 | MD5 |
-| Batocera | 353/353 | 14,173/15,292 | MD5 |
+| Batocera | 353/353 | 14,172/15,292 | MD5 |
| BizHawk | 118/118 | - | SHA-1 |
| EmuDeck | 168/168 | 8,427/8,529 | MD5 |
| EmuELEC | 543/572 | 4,788/10,217 | MD5 |
-| KNULLI | 290/290 | 9,128/15,351 | MD5 |
+| KNULLI | 290/290 | 9,127/15,351 | MD5 |
| Lakka | 532/532 | 7,910/7,995 | name only |
| MiSTer FPGA | 81/81 | - | MD5 |
| MinUI | 0/0 | 78/79 | name only |
@@ -208,4 +208,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-11-06T05:38:30Z*
+*Auto-generated on 2026-11-06T08:56:19Z*
From 1396350795df5b80bc28b81b60e5e6d28f232baa Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 10:14:02 +0100
Subject: [PATCH 79/83] fix: count build file trees as pinned
check_source_paths read the trees profiles pin from source and upstream
only, so the two platform trees the record now holds for pin_build
files read as orphaned and the record as stale.
---
scripts/check_freshness.py | 5 +++++
tests/test_site_integration.py | 15 +++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py
index b8e03f28b..075c45641 100644
--- a/scripts/check_freshness.py
+++ b/scripts/check_freshness.py
@@ -1492,6 +1492,11 @@ def check_source_paths(profiles: dict) -> Finding:
sitesources.tree_key(repo, pin)
for profile in profiles.values() if sitesources.cited_paths(profile)
for repo, pin in sitesources.profile_trees(profile)
+ } | {
+ # The platform build files pin_build names, linked from a page too.
+ sitesources.tree_key(repo, pin)
+ for profile in profiles.values()
+ for repo, pin, _path in sitesources.build_files(profile)
}
try:
recorded = set(json.loads(sitesources.SOURCE_PATHS.read_text(encoding="utf-8")))
diff --git a/tests/test_site_integration.py b/tests/test_site_integration.py
index 91a3dad0d..a3371662a 100644
--- a/tests/test_site_integration.py
+++ b/tests/test_site_integration.py
@@ -117,6 +117,21 @@ class SourcePathsFreshness(unittest.TestCase):
finding = check_freshness.check_source_paths(profiles)
self.assertEqual(finding.status, check_freshness.OK, finding.detail)
+ def test_a_recorded_build_file_tree_is_pinned(self):
+ """The record holds the platform trees pin_build reads at a commit,
+ and the check called them orphaned."""
+ import sitesources # noqa: PLC0415
+
+ pin = "a" * 40
+ profile = {"pin_build": [{"repo": "https://github.com/o/r", "revision": pin,
+ "path": "p.mk"}]}
+ with tempfile.TemporaryDirectory() as tmp:
+ path = Path(tmp) / "source-paths.json"
+ path.write_text(json.dumps({f"github.com/o/r@{pin}": ["p.mk"]}), encoding="utf-8")
+ with mock.patch.object(sitesources, "SOURCE_PATHS", path):
+ finding = check_freshness.check_source_paths({"p": profile})
+ self.assertEqual(finding.status, check_freshness.OK, finding.detail)
+
def test_a_moved_pin_is_stale(self):
profile = _profile("geolith")
moved = dict(profile, source_commit="f" * 40, upstream_commit="e" * 40)
From 2e98be936677e4ade0d9c37a359fa90790bd105b Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 11:10:33 +0100
Subject: [PATCH 80/83] fix: accept the bundled line in the report excerpt
verify now prints a line for files installed with their emulator, and
reading-reports.md quotes it. The shapes the excerpt may hold did not
list it.
---
tests/test_doc_surfaces.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/test_doc_surfaces.py b/tests/test_doc_surfaces.py
index 2c2c28c94..499f97bb2 100644
--- a/tests/test_doc_surfaces.py
+++ b/tests/test_doc_surfaces.py
@@ -322,6 +322,8 @@ class ShownOutputIsPrintedOutput(unittest.TestCase):
r"(0 optional missing|\d+ optional missing \(--verbose lists them\))$",
'" Core files: {core_in_pack} in pack'),
(r"^ Core files held but not packed: \d+ \(.+\)$", '" Core files held but not packed: '),
+ (r"^ Bundled with their emulator, not collected: \d+( \(.+\))?$",
+ '" Bundled with their emulator, not collected: {len(bundled)}"'),
(r"^ Game data: \d+ in pack, (0 missing|\d+ missing \(--verbose lists them\))$",
'" Game data: {gd_packed} in pack'),
(r"^ Game data held but not packed: \d+ \(.+\)$", '" Game data held but not packed: '),
From 5e90a455e43448404f01102c3828633b64dbed19 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 12:09:05 +0100
Subject: [PATCH 81/83] feat: add EmuELEC hardware targets
The v4.8 release publishes four images (Amlogic-ng, GameForce,
OdroidGoAdvance, OdroidM1, read from its asset names). The metapackage
(packages/sx05re/emuelec/package.mk:8-77) builds the S922X cores, dolphinSA
and mame only on Amlogic-ng, Amlogic-no, RK356x and OdroidM1, and removes
duckstation on the handhelds with a sed that replaces the first match only:
pcsx_rearmed, written twice, keeps its 64-bit build. Each package is mapped
to its cores by the .so or program its install step copies, PKG_ARCH is
applied as scripts/build:28-30 does, and es_systems.cfg is edited per
device as emuelec-emulationstation/package.mk:114-143 does. Amlogic-ng and
OdroidM1 list 124 cores, the handhelds 117.
---
platforms/_registry.yml | 8 +-
platforms/targets/_overrides.yml | 2 +-
platforms/targets/emuelec.yml | 499 +++++++++++++
.../targets/emuelec_targets_scraper.py | 662 ++++++++++++++++++
tests/test_emuelec_targets.py | 266 +++++++
wiki/adding-a-scraper.md | 1 +
wiki/testing-guide.md | 2 +-
wiki/tools.md | 1 +
8 files changed, 1435 insertions(+), 6 deletions(-)
create mode 100644 platforms/targets/emuelec.yml
create mode 100644 scripts/scraper/targets/emuelec_targets_scraper.py
create mode 100644 tests/test_emuelec_targets.py
diff --git a/platforms/_registry.yml b/platforms/_registry.yml
index 545ad2f82..bff39bebe 100644
--- a/platforms/_registry.yml
+++ b/platforms/_registry.yml
@@ -865,7 +865,6 @@ platforms:
# 99-distribution.conf:320 passes --strictfilter, an argument the script
# does not handle, so that path reports nothing. No release since
# 20230203: the scraper reads the commit of the newest prerelease.
- # Several device images, no per-device core list: no target file.
amberelec:
config: amberelec.yml
status: active
@@ -906,7 +905,8 @@ platforms:
# member's md5 and report UNTESTED whatever the archive holds. Run by
# EmulationStation's BIOS screen and by ee_check_bios after a failed
# launch (99-emuelec.conf:261). naomi and Dinothawr are written twice in
- # the dict and the later entry is the one Python keeps.
+ # the dict and the later entry is the one Python keeps. One image per
+ # device the release publishes, its cores read by emuelec_targets_scraper.
emuelec:
config: emuelec.yml
status: active
@@ -922,8 +922,8 @@ platforms:
# RetroArch saves beside each game: no single place.
save_directory: null
schedule: monthly
- target_scraper: null
- target_source: null
+ target_scraper: emuelec_targets
+ target_source: https://github.com/EmuELEC/EmuELEC/blob/dev/packages/sx05re/emuelec/package.mk
install:
detect:
# EmuELEC d4c7b2f1 scripts/image:172-176, options:4.
diff --git a/platforms/targets/_overrides.yml b/platforms/targets/_overrides.yml
index d07226f89..c6ed66feb 100644
--- a/platforms/targets/_overrides.yml
+++ b/platforms/targets/_overrides.yml
@@ -195,7 +195,7 @@ knulli:
- rice
- vaixterm
-# EmuELEC and AmberELEC have no target file: the scrapers read these lists.
+# Read by the EmuELEC and AmberELEC platform and target scrapers alike.
# mpv and ffplay play the Media Player system's videos (EmuELEC
# emuelecRunEmu.sh:301-303, AmberELEC runemu.py:122). gmloader runs a
# GameMaker game's own Android library (emuelecRunEmu.sh:331-334). Ports
diff --git a/platforms/targets/emuelec.yml b/platforms/targets/emuelec.yml
new file mode 100644
index 000000000..31041341a
--- /dev/null
+++ b/platforms/targets/emuelec.yml
@@ -0,0 +1,499 @@
+platform: emuelec
+source: https://github.com/EmuELEC/EmuELEC/blob/v4.8/packages/sx05re/emuelec/package.mk
+devices_source: https://github.com/EmuELEC/EmuELEC/releases/tag/v4.8
+scraped_at: '2026-11-06T10:27:34Z'
+targets:
+ amlogic-ng:
+ architecture: aarch64
+ cores:
+ - '2048'
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DOSBOXSDL2
+ - Duckstation
+ - ECWolf
+ - FBNEOSA
+ - HATARISA
+ - HYPSEUS
+ - OPENBOR
+ - PPSSPPSDL
+ - Pico-8
+ - SCUMMVMSA
+ - STELLASA
+ - Solarus
+ - a5200
+ - atari800
+ - bgdi
+ - bk
+ - bluemsx
+ - cannonball
+ - cap32
+ - daphne
+ - dinothawr
+ - dolphin
+ - dosbox_pure
+ - dosbox_svn
+ - easyrpg
+ - fake08
+ - fbalpha2012
+ - fbneo
+ - fceumm
+ - fceumm_mod
+ - flycast
+ - flycast_32b
+ - flycastsa
+ - fmsx
+ - freeintv
+ - freej2me
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - geargrafx
+ - gearlynx
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_cart_special
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - handy
+ - hatari
+ - ikemen
+ - jzintv
+ - mame
+ - mame2003_plus
+ - mame2010
+ - mednafen_lynx
+ - mednafen_ngp
+ - mednafen_pce_fast
+ - mednafen_pcfx
+ - mednafen_saturn
+ - mednafen_supafaust
+ - mednafen_supergrafx
+ - mednafen_vb
+ - mednafen_wswan
+ - mesen
+ - mesen-s
+ - mgba
+ - mrboom
+ - mupen64plus_32b
+ - mupen64plus_next
+ - mupen64plus_next_alt
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - nxengine
+ - o2em
+ - opera
+ - parallel_n64_32b
+ - pcsx_rearmed
+ - pcsx_rearmed_32b
+ - picodrive
+ - pocketcdg
+ - pokemini
+ - potator
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - reminiscence
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - stella
+ - swanstation
+ - tgbdual
+ - tic80
+ - tyrquake
+ - uae4arm_32b
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_x64sc
+ - vice_xplus4
+ - vice_xvic
+ - virtualjaguar
+ - x1
+ - xrick
+ - yabasanshiro
+ gameforce:
+ architecture: aarch64
+ cores:
+ - '2048'
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DOSBOXSDL2
+ - ECWolf
+ - FBNEOSA
+ - HATARISA
+ - HYPSEUS
+ - OPENBOR
+ - PPSSPPSDL
+ - Pico-8
+ - SCUMMVMSA
+ - STELLASA
+ - Solarus
+ - a5200
+ - atari800
+ - bgdi
+ - bk
+ - bluemsx
+ - cannonball
+ - cap32
+ - daphne
+ - dinothawr
+ - dosbox_pure
+ - dosbox_svn
+ - easyrpg
+ - fake08
+ - fbalpha2012
+ - fbneo
+ - fceumm
+ - fceumm_mod
+ - flycast
+ - flycast_32b
+ - flycastsa
+ - fmsx
+ - freeintv
+ - freej2me
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - geargrafx
+ - gearlynx
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_cart_special
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - handy
+ - hatari
+ - ikemen
+ - jzintv
+ - mame2003_plus
+ - mame2010
+ - mednafen_lynx
+ - mednafen_ngp
+ - mednafen_pce_fast
+ - mednafen_pcfx
+ - mednafen_supafaust
+ - mednafen_supergrafx
+ - mednafen_vb
+ - mednafen_wswan
+ - mgba
+ - mrboom
+ - mupen64plus_32b
+ - mupen64plus_next
+ - mupen64plus_next_alt
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - nxengine
+ - o2em
+ - opera
+ - parallel_n64_32b
+ - pcsx_rearmed
+ - pcsx_rearmed_32b
+ - picodrive
+ - pocketcdg
+ - pokemini
+ - potator
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - reminiscence
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - stella
+ - swanstation
+ - tgbdual
+ - tic80
+ - tyrquake
+ - uae4arm_32b
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_x64sc
+ - vice_xplus4
+ - vice_xvic
+ - x1
+ - xrick
+ - yabasanshiro
+ odroidgoadvance:
+ architecture: aarch64
+ cores:
+ - '2048'
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DOSBOXSDL2
+ - ECWolf
+ - FBNEOSA
+ - HATARISA
+ - HYPSEUS
+ - OPENBOR
+ - PPSSPPSDL
+ - Pico-8
+ - SCUMMVMSA
+ - STELLASA
+ - Solarus
+ - a5200
+ - atari800
+ - bgdi
+ - bk
+ - bluemsx
+ - cannonball
+ - cap32
+ - daphne
+ - dinothawr
+ - dosbox_pure
+ - dosbox_svn
+ - easyrpg
+ - fake08
+ - fbalpha2012
+ - fbneo
+ - fceumm
+ - fceumm_mod
+ - flycast
+ - flycast_32b
+ - flycastsa
+ - fmsx
+ - freeintv
+ - freej2me
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - geargrafx
+ - gearlynx
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_cart_special
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - handy
+ - hatari
+ - ikemen
+ - jzintv
+ - mame2003_plus
+ - mame2010
+ - mednafen_lynx
+ - mednafen_ngp
+ - mednafen_pce_fast
+ - mednafen_pcfx
+ - mednafen_supafaust
+ - mednafen_supergrafx
+ - mednafen_vb
+ - mednafen_wswan
+ - mgba
+ - mrboom
+ - mupen64plus_32b
+ - mupen64plus_next
+ - mupen64plus_next_alt
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - nxengine
+ - o2em
+ - opera
+ - parallel_n64_32b
+ - pcsx_rearmed
+ - pcsx_rearmed_32b
+ - picodrive
+ - pocketcdg
+ - pokemini
+ - potator
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - reminiscence
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - stella
+ - swanstation
+ - tgbdual
+ - tic80
+ - tyrquake
+ - uae4arm_32b
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_x64sc
+ - vice_xplus4
+ - vice_xvic
+ - x1
+ - xrick
+ - yabasanshiro
+ odroidm1:
+ architecture: aarch64
+ cores:
+ - '2048'
+ - '81'
+ - AMIBERRY
+ - AdvanceMame
+ - DOSBOXSDL2
+ - Duckstation
+ - ECWolf
+ - FBNEOSA
+ - HATARISA
+ - HYPSEUS
+ - OPENBOR
+ - PPSSPPSDL
+ - Pico-8
+ - SCUMMVMSA
+ - STELLASA
+ - Solarus
+ - a5200
+ - atari800
+ - bgdi
+ - bk
+ - bluemsx
+ - cannonball
+ - cap32
+ - daphne
+ - dinothawr
+ - dolphin
+ - dosbox_pure
+ - dosbox_svn
+ - easyrpg
+ - fake08
+ - fbalpha2012
+ - fbneo
+ - fceumm
+ - fceumm_mod
+ - flycast
+ - flycast_32b
+ - flycastsa
+ - fmsx
+ - freeintv
+ - freej2me
+ - fuse
+ - gambatte
+ - gearboy
+ - gearcoleco
+ - geargrafx
+ - gearlynx
+ - gearsystem
+ - genesis_plus_gx
+ - genesis_plus_gx_cart_special
+ - genesis_plus_gx_wide
+ - geolith
+ - gpsp
+ - gw
+ - handy
+ - hatari
+ - ikemen
+ - jzintv
+ - mame
+ - mame2003_plus
+ - mame2010
+ - mednafen_lynx
+ - mednafen_ngp
+ - mednafen_pce_fast
+ - mednafen_pcfx
+ - mednafen_saturn
+ - mednafen_supafaust
+ - mednafen_supergrafx
+ - mednafen_vb
+ - mednafen_wswan
+ - mesen
+ - mesen-s
+ - mgba
+ - mrboom
+ - mupen64plus_32b
+ - mupen64plus_next
+ - mupen64plus_next_alt
+ - mupen64plussa
+ - nekop2
+ - neocd
+ - nestopia
+ - np2kai
+ - nxengine
+ - o2em
+ - opera
+ - parallel_n64_32b
+ - pcsx_rearmed
+ - pcsx_rearmed_32b
+ - picodrive
+ - pocketcdg
+ - pokemini
+ - potator
+ - prboom
+ - prosystem
+ - puae
+ - puae2021
+ - px68k
+ - reminiscence
+ - same_cdi
+ - sameboy
+ - sameduck
+ - scummvm
+ - snes9x
+ - snes9x2002
+ - snes9x2005_plus
+ - snes9x2010
+ - stella
+ - swanstation
+ - tgbdual
+ - tic80
+ - tyrquake
+ - uae4arm_32b
+ - uzem
+ - vba_next
+ - vbam
+ - vecx
+ - vice_x128
+ - vice_x64
+ - vice_x64sc
+ - vice_xplus4
+ - vice_xvic
+ - virtualjaguar
+ - x1
+ - xrick
+ - yabasanshiro
diff --git a/scripts/scraper/targets/emuelec_targets_scraper.py b/scripts/scraper/targets/emuelec_targets_scraper.py
new file mode 100644
index 000000000..3991c68c2
--- /dev/null
+++ b/scripts/scraper/targets/emuelec_targets_scraper.py
@@ -0,0 +1,662 @@
+"""Scraper for EmuELEC per-device emulator availability.
+
+Sources (EmuELEC/EmuELEC, at the tag platforms/emuelec.yml names, v4.8):
+ - the release's asset names: one `EmuELEC-.-`
+ image per device (Amlogic-ng, GameForce, OdroidGoAdvance, OdroidM1 at
+ v4.8). The tree names no device list: projects/ holds the directories
+ of many more devices than the release builds.
+ - packages/sx05re/emuelec/package.mk -- the metapackage, whose
+ PKG_DEPENDS_TARGET is each device's package list (lines 8-77)
+ - distributions/EmuELEC/options -- LIBRETRO_CORES and
+ LIBRETRO_S922X_CORES (lines 274-373)
+ - each core package's package.mk -- PKG_ARCH, which scripts/build:28-30
+ reads to skip a package, and the install step naming the .so or binary
+ - packages/sx05re/emuelec-emulationstation/package.mk -- the cores and
+ emulators makeinstall_target deletes from es_systems.cfg per device
+ (lines 114-143)
+ - es_systems.json and ports.yaml, read the way the platform scraper reads
+ them
+
+A device keeps a core when a package it builds installs that core and its
+es_systems.cfg still offers it. The OdroidGoAdvance image carries neither
+DuckStation nor Dolphin nor the MAME core: without a target list, its pack
+shipped their firmware anyway.
+"""
+
+from __future__ import annotations
+
+import argparse
+import json
+import re
+import sys
+from datetime import datetime, timezone
+from typing import NamedTuple
+
+import yaml
+
+from . import BaseTargetScraper
+
+PLATFORM_NAME = "emuelec"
+
+REPO = "EmuELEC/EmuELEC"
+RAW = "https://raw.githubusercontent.com/EmuELEC/EmuELEC/{ref}/{path}"
+RELEASE_API = "https://api.github.com/repos/EmuELEC/EmuELEC/releases/tags/{ref}"
+META_MK = "packages/sx05re/emuelec/package.mk"
+OPTIONS = "distributions/EmuELEC/options"
+ES_MK = "packages/sx05re/emuelec-emulationstation/package.mk"
+
+try:
+ from ..base_scraper import fetch_bytes, github_headers
+ from ..batocera_scraper import _not_cores
+ from ..emuelec_scraper import (
+ BUILDS_OF, ES_SYSTEMS_TEMPLATE, PORTS_TEMPLATE, RUNNERS, port_engines, with_ports,
+ )
+ from ..es_emulators import SystemEmulators, es_cores
+except ImportError:
+ from scraper.base_scraper import fetch_bytes, github_headers
+ from scraper.batocera_scraper import _not_cores
+ from scraper.emuelec_scraper import (
+ BUILDS_OF, ES_SYSTEMS_TEMPLATE, PORTS_TEMPLATE, RUNNERS, port_engines, with_ports,
+ )
+ from scraper.es_emulators import SystemEmulators, es_cores
+
+_ASSET_RE = re.compile(r"^EmuELEC-(?P[A-Za-z0-9-]+)\.(?P[a-z0-9_]+)-")
+
+# The metapackage, line for line. Each rule below transcribes these lines;
+# a tag that rewrites one stops the scrape instead of reading it wrong.
+_META_LINES = (
+ 'PKG_DEPENDS_TARGET="toolchain ${OPENGLES} emuelec-emulationstation retroarch"',
+ 'PKG_DEPENDS_TARGET+=" emuelec-tools ${PKG_EMUS} ${PKG_EXPERIMENTAL}"',
+ 'if [ "${DEVICE}" == "Amlogic-ng" ] || [ "${DEVICE}" == "Amlogic-no" ] || '
+ '[ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then',
+ 'PKG_DEPENDS_TARGET+=" ${LIBRETRO_S922X_CORES}"',
+ 'if [ "${DEVICE}" == "OdroidGoAdvance" ] || [ "${DEVICE}" == "GameForce" ]; then',
+ 'PKG_DEPENDS_TARGET+=" kmscon odroidgoa-utils"',
+ "for discore in duckstation mesen-s virtualjaguar quicknes MC; do",
+ 'PKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore} | |")',
+ 'PKG_DEPENDS_TARGET+=" yabasanshiro"',
+ 'PKG_DEPENDS_TARGET+=" fbterm"',
+ 'if [ "${ARCH}" == "aarch64" ]; then',
+ "for discore in quicknes parallel-n64 pcsx_rearmed; do",
+ 'PKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore}| |")',
+ 'PKG_DEPENDS_TARGET+=" dolphinSA"',
+ 'if [ "${DEVICE}" == "Amlogic-old" ]; then',
+ "for discore in yabasanshiroSA_1_11 yabasanshiroSA_1_5 yabasanshiro same_cdi duckstation; do",
+ 'PKG_DEPENDS_TARGET+=" mame"',
+ 'if [ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then',
+ "for discore in flycast-dojo; do",
+)
+_LIB32_RE = re.compile(r'PKG_DEPENDS_TARGET\+=" (swanstation [^"]*)"')
+_BIG = ("Amlogic-ng", "Amlogic-no", "RK356x", "OdroidM1")
+_HANDHELD = ("OdroidGoAdvance", "GameForce")
+
+# What emuelec-emulationstation's makeinstall_target does to es_systems.cfg.
+_ES_LINES = (
+ 'if [[ "${DEVICE}" != "Amlogic-ng" || "${DEVICE}" != "Amlogic-ne" || '
+ '"${DEVICE}" != "Amlogic-no" ]]; then',
+ 'if [[ ${DEVICE} == "OdroidGoAdvance" || "${DEVICE}" == "GameForce" ]]; then',
+ 'remove_cores="mesen-s quicknes mame2016 mesen"',
+ 'remove_cores="mesen-s quicknes mame2016 mesen yabasanshiroSA yabasanshiro"',
+ "xmlstarlet ed -L -P -d \"/systemList/system[name='saturn']\" ${CORESFILE}",
+ "xmlstarlet ed -L -P -d \"/systemList/system[name='phillips-cdi']\" ${CORESFILE}",
+ 'sed -i "s|${discore}||g" ${CORESFILE}',
+ 'if [[ ${DEVICE} != "OdroidGoAdvance" ]] && [[ "${DEVICE}" != "GameForce" ]]; then',
+ "xmlstarlet ed -L -P -d \"/systemList/system/emulators/emulator[@name='retrorun']\" ${CORESFILE}",
+ "xmlstarlet ed -L -P -d \"/systemList/system/emulators/emulator[@name='Duckstation']\" ${CORESFILE}",
+)
+
+
+class Install(NamedTuple):
+ """One line of a package.mk that puts a core on the image."""
+
+ path: str
+ line: str
+ cores: tuple[str, ...]
+ # The ARCH test the line sits under in makeinstall_target, if any.
+ arch: str | None = None
+
+
+def _lr(package: str, line: str, *cores: str, arch: str | None = None) -> Install:
+ return Install(f"packages/sx05re/libretro/{package}/package.mk", line, cores, arch)
+
+
+def _sa(package: str, line: str, *cores: str) -> Install:
+ return Install(f"packages/sx05re/emulators/{package}/package.mk", line, cores)
+
+
+def _lib32(package: str, line: str, *cores: str) -> Install:
+ return Install(f"packages/lib32/emuelec/libretro/{package}/package.mk", line, cores)
+
+
+_TO = "${INSTALL}/usr/lib/libretro/"
+
+# Package -> the ES core names its install step puts on the image, with the
+# line that does it (v4.8). A libretro core is the .so it copies to
+# /usr/lib/libretro, the name emuelecRunEmu.sh:101-116 loads as
+# ${CORE}_libretro. A standalone name is the program the runner's case for
+# it starts (emuelecRunEmu.sh:164-353), installed by the line cited, or by
+# the package's default make/cmake/meson install where the line cited only
+# adds the launch script beside it.
+PROVIDERS: dict[str, tuple[Install, ...]] = {
+ "2048": (_lr("2048", f"cp 2048_libretro.so {_TO}", "2048"),),
+ "81": (_lr("81", f"cp 81_libretro.so {_TO}", "81"),),
+ "a5200": (_lr("a5200", f"cp a5200_libretro.so {_TO}", "a5200"),),
+ "atari800": (_lr("atari800", f"cp atari800_libretro.so {_TO}", "atari800"),),
+ "beetle-lynx": (_lr("beetle-lynx", f"cp mednafen_lynx_libretro.so {_TO}", "mednafen_lynx"),),
+ "beetle-ngp": (_lr("beetle-ngp", f"cp mednafen_ngp_libretro.so {_TO}", "mednafen_ngp"),),
+ "beetle-pce": (_lr("beetle-pce", f"cp mednafen_pce_fast_libretro.so {_TO}",
+ "mednafen_pce_fast"),),
+ "beetle-pcfx": (_lr("beetle-pcfx", f"cp mednafen_pcfx_libretro.so {_TO}", "mednafen_pcfx"),),
+ # line 20: the build makes mednafen_saturn_libretro.so (Makefile TARGET_NAME).
+ "beetle-saturn": (_lr("beetle-saturn", "cp mednafen_saturn_*.so $INSTALL/usr/lib/libretro/",
+ "mednafen_saturn"),),
+ "beetle-supergrafx": (_lr("beetle-supergrafx", f"cp mednafen_supergrafx_libretro.so {_TO}",
+ "mednafen_supergrafx"),),
+ "beetle-vb": (_lr("beetle-vb", f"cp mednafen_vb_libretro.so {_TO}", "mednafen_vb"),),
+ "beetle-wswan": (_lr("beetle-wswan", f"cp mednafen_wswan_libretro.so {_TO}",
+ "mednafen_wswan"),),
+ "bk": (_lr("bk", f"cp ${{PKG_BUILD}}/bk_libretro.so {_TO}", "bk"),),
+ "bluemsx": (_lr("bluemsx", f"cp bluemsx_libretro.so {_TO}", "bluemsx"),),
+ "cannonball": (_lr("cannonball", f"cp cannonball_libretro.so {_TO}", "cannonball"),),
+ "cap32": (_lr("cap32", f"cp cap32_libretro.so {_TO}", "cap32"),),
+ "daphne": (_lr("daphne", f"cp daphne_libretro.so {_TO}", "daphne"),),
+ "dinothawr": (_lr("dinothawr", f"cp dinothawr_libretro.so {_TO}", "dinothawr"),),
+ "dosbox-pure": (_lr("dosbox-pure", f"cp dosbox_pure_libretro.so {_TO}dosbox_pure_libretro.so",
+ "dosbox_pure"),),
+ "dosbox-svn": (_lr("dosbox-svn", "cp ${PKG_BUILD}/libretro/dosbox_svn_libretro.so "
+ "${INSTALL}/usr/lib/libretro", "dosbox_svn"),),
+ "easyrpg": (_lr("easyrpg", f"cp ${{PKG_BUILD}}/.${{TARGET_NAME}}/easyrpg_libretro.so {_TO}",
+ "easyrpg"),),
+ "fake_08": (_lr("fake_08", f"cp -v ${{PKG_BUILD}}/platform/libretro/fake08_libretro.so {_TO}",
+ "fake08"),),
+ "fbalpha2012": (_lr("fbalpha2012", f"cp fbalpha2012_libretro.so {_TO}", "fbalpha2012"),),
+ "fbneo": (_lr("fbneo", f"cp ${{PKG_BUILD}}/src/burner/libretro/fbneo_libretro.so {_TO}",
+ "fbneo"),),
+ "fceumm": (_lr("fceumm", f"cp fceumm_libretro.so {_TO}", "fceumm"),),
+ "fceumm-mod": (_lr("fceumm-mod", f"cp ${{PKG_BUILD}}/fceumm_mod_libretro.* {_TO}",
+ "fceumm_mod"),),
+ # lines 47-51: flycast_32b on arm, flycast elsewhere.
+ "flycast": (
+ _lr("flycast", f"cp flycast_libretro.so {_TO}flycast_32b_libretro.so", "flycast_32b",
+ arch="arm"),
+ _lr("flycast", f"cp flycast_libretro.so {_TO}", "flycast", arch="!arm"),
+ ),
+ "fmsx-libretro": (_lr("fmsx-libretro", f"cp fmsx_libretro.so {_TO}", "fmsx"),),
+ "freeintv": (_lr("freeintv", f"cp freeintv_libretro.so {_TO}", "freeintv"),),
+ "freej2me": (_lr("freej2me", 'cp `find . -name "freej2me_libretro.so" | xargs echo` '
+ "${INSTALL}/usr/lib/libretro", "freej2me"),),
+ "fuse-libretro": (_lr("fuse-libretro", f"cp fuse_libretro.so {_TO}", "fuse"),),
+ "gambatte": (_lr("gambatte", f"cp gambatte_libretro.so {_TO}", "gambatte"),),
+ "gearboy": (_lr("gearboy", f"cp platforms/libretro/gearboy_libretro.so {_TO}", "gearboy"),),
+ "gearcoleco": (_lr("gearcoleco", f"cp platforms/libretro/gearcoleco_libretro.so {_TO}",
+ "gearcoleco"),),
+ "geargrafx": (_lr("geargrafx", f"cp platforms/libretro/geargrafx_libretro.so {_TO}",
+ "geargrafx"),),
+ "gearlynx": (_lr("gearlynx", f"cp platforms/libretro/gearlynx_libretro.so {_TO}",
+ "gearlynx"),),
+ "gearsystem": (_lr("gearsystem", f"cp platforms/libretro/gearsystem_libretro.so {_TO}",
+ "gearsystem"),),
+ "genesis-plus-gx": (_lr("genesis-plus-gx",
+ f"cp genesis_plus_gx_libretro.so {_TO}genesis_plus_gx_libretro.so",
+ "genesis_plus_gx"),),
+ "genesis-plus-gx-wide": (_lr("genesis-plus-gx-wide", "cp genesis_plus_gx_wide_libretro.so "
+ f"{_TO}genesis_plus_gx_wide_libretro.so",
+ "genesis_plus_gx_wide"),),
+ # PKG_NAME is genesis_plus_gx_cart_special (line 4).
+ "genesis_plus_gx_cart_special": (_lr("genesis_plus_gx_cart_special",
+ f"cp genesis_plus_gx_libretro.so {_TO}"
+ "${PKG_NAME}_libretro.so",
+ "genesis_plus_gx_cart_special"),),
+ "geolith": (_lr("geolith", f"cp geolith_libretro.so {_TO}", "geolith"),),
+ "gpsp": (_lr("gpsp", f"cp -v gpsp_libretro.so {_TO}", "gpsp"),),
+ "gw-libretro": (_lr("gw-libretro", f"cp gw_libretro.so {_TO}", "gw"),),
+ "handy": (_lr("handy", f"cp handy_libretro.so {_TO}", "handy"),),
+ "hatari": (_lr("hatari", f"cp ../hatari_libretro.so {_TO}", "hatari"),),
+ # line 65: the build's only .so is mame_libretro.so.
+ "mame": (_lr("mame", f"cp *.so {_TO}", "mame"),),
+ "mame2003-plus": (_lr("mame2003-plus", f"cp mame2003_plus_libretro.so {_TO}",
+ "mame2003_plus"),),
+ "mame2010": (_lr("mame2010", f"cp mame2010_libretro.so {_TO}", "mame2010"),),
+ "meowpc98": (_lr("meowpc98", f"cp libretro/nekop2_libretro.so {_TO}", "nekop2"),),
+ "mesen": (_lr("mesen", f"cp Libretro/mesen_libretro.so {_TO}", "mesen"),),
+ "mesen-s": (_lr("mesen-s", f"cp Libretro/mesen-s_libretro.so {_TO}", "mesen-s"),),
+ "mgba": (_lr("mgba", f"cp mgba_libretro.so {_TO}", "mgba"),),
+ "mrboom": (_lr("mrboom", f"cp mrboom_libretro.so {_TO}", "mrboom"),),
+ # PKG_ARCH="arm" (line 25): scripts/build skips it on aarch64.
+ "mupen64plus": (_lr("mupen64plus", f"cp mupen64plus_libretro.so {_TO}"
+ "mupen64plus_32b_libretro.so", "mupen64plus_32b"),),
+ "mupen64plus-nx": (_lr("mupen64plus-nx", f"cp mupen64plus_next_libretro.so {_TO}",
+ "mupen64plus_next"),),
+ "mupen64plus-nx-alt": (_lr("mupen64plus-nx-alt", f"cp mupen64plus_next_libretro.so {_TO}"
+ "mupen64plus_next_alt_libretro.so", "mupen64plus_next_alt"),),
+ "neocd_libretro": (_lr("neocd_libretro", f"cp ${{PKG_BUILD}}/neocd_libretro.so {_TO}",
+ "neocd"),),
+ "nestopia": (_lr("nestopia", f"cp libretro/nestopia_libretro.so {_TO}", "nestopia"),),
+ "np2kai": (_lr("np2kai", f"cp ${{PKG_BUILD}}/sdl/np2kai_libretro.so {_TO}", "np2kai"),),
+ "nxengine": (_lr("nxengine", f"cp nxengine_libretro.so {_TO}", "nxengine"),),
+ "o2em": (_lr("o2em", f"cp o2em_libretro.so {_TO}", "o2em"),),
+ "opera": (_lr("opera", f"cp opera_libretro.so {_TO}", "opera"),),
+ # lines 42-46: pcsx_rearmed_32b on arm, pcsx_rearmed elsewhere.
+ "pcsx_rearmed": (
+ _lr("pcsx_rearmed", "cp pcsx_rearmed_libretro.so "
+ "${INSTALL}${INSTALLTO}/pcsx_rearmed_32b_libretro.so", "pcsx_rearmed_32b", arch="arm"),
+ _lr("pcsx_rearmed", "cp pcsx_rearmed_libretro.so ${INSTALL}${INSTALLTO}",
+ "pcsx_rearmed", arch="!arm"),
+ ),
+ "picodrive": (_lr("picodrive", f"cp ${{PKG_BUILD}}/picodrive_libretro.so {_TO}",
+ "picodrive"),),
+ "pocketcdg": (_lr("pocketcdg", f"cp pocketcdg_libretro.so {_TO}", "pocketcdg"),),
+ "pokemini": (_lr("pokemini", f"cp pokemini_libretro.so {_TO}", "pokemini"),),
+ "potator": (_lr("potator", "cp ${PKG_BUILD}/platform/libretro/potator_libretro.so "
+ f"{_TO}potator_libretro.so", "potator"),),
+ "prboom": (_lr("prboom", f"cp prboom_libretro.so {_TO}prboom_libretro.so", "prboom"),),
+ "prosystem": (_lr("prosystem", f"cp prosystem_libretro.so {_TO}", "prosystem"),),
+ "puae": (_lr("puae", f"cp puae_libretro.so {_TO}", "puae"),),
+ "puae2021": (_lr("puae2021", f"cp -v puae2021_libretro.so {_TO}", "puae2021"),),
+ "px68k": (_lr("px68k", f"cp px68k_libretro.so {_TO}", "px68k"),),
+ "reminiscence": (_lr("reminiscence", f"cp reminiscence_libretro.so {_TO}", "reminiscence"),),
+ "same_cdi": (_lr("same_cdi", f"cp -v same_cdi_libretro.so {_TO}", "same_cdi"),),
+ "sameboy": (_lr("sameboy", f"cp libretro/sameboy_libretro.so {_TO}", "sameboy"),),
+ "sameduck": (_lr("sameduck", f"cp build/bin/sameduck_libretro.so {_TO}", "sameduck"),),
+ "scummvm": (_lr("scummvm", 'cp "${PKG_BUILD}/backends/platform/libretro/scummvm_libretro."'
+ "{so,info} ${INSTALL}/usr/lib/libretro/", "scummvm"),),
+ "snes9x": (_lr("snes9x", f"cp libretro/snes9x_libretro.so {_TO}", "snes9x"),),
+ "snes9x2002": (_lr("snes9x2002", f"cp snes9x2002_libretro.so {_TO}", "snes9x2002"),),
+ "snes9x2005_plus": (_lr("snes9x2005_plus", f"cp snes9x2005_plus_libretro.so {_TO}",
+ "snes9x2005_plus"),),
+ "snes9x2010": (_lr("snes9x2010", f"cp snes9x2010_libretro.so {_TO}", "snes9x2010"),),
+ "stella": (_lr("stella", f"cp ${{PKG_BUILD}}/src/os/libretro/stella_libretro.so {_TO}",
+ "stella"),),
+ "supafaust": (_lr("supafaust", f"cp -v mednafen_supafaust_libretro.so {_TO}",
+ "mednafen_supafaust"),),
+ "swanstation": (_lr("swanstation", "cp ${PKG_BUILD}/.${TARGET_NAME}/swanstation_libretro.so "
+ f"{_TO}", "swanstation"),),
+ "tgbdual": (_lr("tgbdual", f"cp tgbdual_libretro.so {_TO}", "tgbdual"),),
+ "tic-80": (_lr("tic-80", "cp ${PKG_BUILD}/.${TARGET_NAME}/bin/tic80_libretro.so "
+ f"{_TO}tic80_libretro.so", "tic80"),),
+ "tyrquake": (_lr("tyrquake", f"cp tyrquake_libretro.so {_TO}", "tyrquake"),),
+ # PKG_ARCH="arm" (line 25): scripts/build skips it on aarch64.
+ "uae4arm": (_lr("uae4arm", f"cp uae4arm_libretro.so {_TO}uae4arm_32b_libretro.so",
+ "uae4arm_32b"),),
+ "uzem": (_lr("uzem", f"cp uzem_libretro.so {_TO}", "uzem"),),
+ "vba-next": (_lr("vba-next", f"cp vba_next_libretro.so {_TO}", "vba_next"),),
+ "vbam": (_lr("vbam", f"cp ../src/libretro/vbam_libretro.so {_TO}", "vbam"),),
+ "vecx": (_lr("vecx", f"cp vecx_libretro.so {_TO}vecx_libretro.so", "vecx"),),
+ # line 55: make_target builds one vice__libretro.so per emulator it
+ # loops over (lines 37-50), x64, x64sc, x128, xplus4 and xvic among them.
+ "vice": (_lr("vice", f"cp built/vice_*_libretro.so {_TO}",
+ "vice_x128", "vice_x64", "vice_x64sc", "vice_xplus4", "vice_xvic"),),
+ "virtualjaguar": (_lr("virtualjaguar", f"cp virtualjaguar_libretro.so {_TO}",
+ "virtualjaguar"),),
+ "xmil": (_lr("xmil", f"cp ${{PKG_BUILD}}/libretro/x1_libretro.so {_TO}", "x1"),),
+ "xrick": (_lr("xrick", f"cp xrick_libretro.so {_TO}", "xrick"),),
+ "yabasanshiro": (_lr("yabasanshiro", f"cp yabause/src/libretro/yabasanshiro_libretro.so {_TO}",
+ "yabasanshiro"),),
+ "lib32-flycast": (_lib32("lib32-flycast", "cp -va flycast_libretro.so "
+ f"{_TO}flycast_32b_libretro.so", "flycast_32b"),),
+ "lib32-mupen64plus": (_lib32("lib32-mupen64plus", "cp mupen64plus_libretro.so "
+ f"{_TO}mupen64plus_32b_libretro.so", "mupen64plus_32b"),),
+ "lib32-parallel-n64": (_lib32("lib32-parallel-n64", "cp parallel_n64_libretro.so "
+ f"{_TO}parallel_n64_32b_libretro.so", "parallel_n64_32b"),),
+ "lib32-pcsx_rearmed": (_lib32("lib32-pcsx_rearmed", "cp pcsx_rearmed_libretro.so "
+ f"{_TO}pcsx_rearmed_32b_libretro.so", "pcsx_rearmed_32b"),),
+ "lib32-uae4arm": (_lib32("lib32-uae4arm", "cp uae4arm_libretro.so "
+ f"{_TO}uae4arm_32b_libretro.so", "uae4arm_32b"),),
+ # Standalone emulators, by the program the runner starts.
+ "PPSSPPSDL": (_sa("PPSSPPSDL", 'cp `find . -name "PPSSPPSDL" | xargs echo` '
+ "${INSTALL}/usr/bin/PPSSPPSDL", "PPSSPPSDL"),),
+ "advancemame": (_sa("advancemame", "cp -r ${PKG_BUILD}/obj/mame/linux/blend/advmame "
+ "${INSTALL}/usr/bin", "AdvanceMame"),),
+ "amiberry": (_sa("amiberry", "cp -a amiberry* ${INSTALL}/usr/bin/amiberry", "AMIBERRY"),),
+ "dolphinSA": (_sa("dolphinSA", "cp -rf ${PKG_BUILD}/.${TARGET_NAME}/Binaries/"
+ "dolphin-emu-nogui ${INSTALL}/usr/bin", "dolphin"),),
+ # dosbox comes from the meson install, dosbox.start from line 28.
+ "dosbox-staging": (_sa("dosbox-staging", "cp -a ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin/",
+ "DOSBOXSDL2"),),
+ "duckstation": (_sa("duckstation", "cp -rf ${PKG_BUILD}/.${TARGET_NAME}/bin/"
+ "duckstation-nogui ${INSTALL}/usr/bin", "Duckstation"),),
+ "ecwolf": (_sa("ecwolf", "cp ${PKG_BUILD}/ecwolf ${INSTALL}/usr/bin/ecwolf", "ECWolf"),),
+ "fbneoSA": (_sa("fbneoSA", "cp -rf ${PKG_BUILD}/fbneo ${INSTALL}/usr/bin", "FBNEOSA"),),
+ "flycastsa": (_sa("flycastsa", "cp ${PKG_BUILD}/.${TARGET_NAME}/flycast "
+ "${INSTALL}/usr/bin/flycast", "flycastsa"),),
+ "hatarisa": (_sa("hatarisa", "cp src/hatari ${INSTALL}/usr/bin", "HATARISA"),),
+ # hypseus comes from the cmake install (PKG_TOOLCHAIN, line 13).
+ "hypseus-singe": (_sa("hypseus-singe", 'PKG_TOOLCHAIN="cmake"', "HYPSEUS"),),
+ "ikemen-go": (_sa("ikemen-go", 'cp "$PKG_BUILD/bin/Ikemen_Go_"* "$INSTALL/usr/bin/Ikemen_Go"',
+ "ikemen"),),
+ "jzintv": (_sa("jzintv", "cp bin/jzintv ${INSTALL}/usr/bin", "jzintv"),),
+ # The metapackage's dependencies (line 10); mupen64plus itself comes from
+ # mupen64plussa-ui-console's makeinstall_target.
+ "mupen64plussa": (
+ _sa("mupen64plussa", 'PKG_DEPENDS_TARGET="toolchain mupen64plussa-core '
+ "mupen64plussa-ui-console mupen64plussa-audio-sdl mupen64plussa-input-sdl "
+ 'mupen64plussa-rsp-hle mupen64plussa-video-rice mupen64plussa-video-glide64mk2"',
+ "mupen64plussa"),
+ Install("packages/sx05re/emulators/mupen64plussa/mupen64plussa-ui-console/package.mk",
+ "cp ${PKG_BUILD}/projects/unix/mupen64plus ${UBINDIR}", ()),
+ ),
+ "openbor": (_sa("openbor", 'cp `find . -name "OpenBOR.elf" | xargs echo` '
+ "${INSTALL}/usr/bin/OpenBOR", "OPENBOR"),),
+ # scummvm comes from the make install, moved to /usr/bin at line 51.
+ "scummvmsa": (_sa("scummvmsa", "mv ${INSTALL}/usr/local/bin ${INSTALL}/usr/", "SCUMMVMSA"),),
+ # solarus-run comes from the cmake install, solarus.sh from line 22.
+ "solarus": (_sa("solarus", "cp ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin", "Solarus"),),
+ "stellasa": (_sa("stellasa", "cp -rf ${PKG_BUILD}/stella ${INSTALL}/usr/bin", "STELLASA"),),
+ "yabasanshiroSA_1_11": (_sa("yabasanshiroSA_1_11", "cp -a ${PKG_BUILD}/src/retro_arena/"
+ "yabasanshiro ${INSTALL}/usr/bin", "yabasanshiro"),),
+ "lib32-bennugd-monolithic": (Install(
+ "packages/lib32/emuelec/ports/lib32-bennugd-monolithic/package.mk",
+ "cp ${PKG_BUILD}/projects/cmake/bgdi/bgdi ${INSTALL}/usr/bin", ("bgdi",)),),
+ # The metapackage's own bin/ (line 82) carries pico8.sh, which starts the
+ # PICO-8 binary the user copies to bios/pico-8.
+ "emuelec": (Install(META_MK, "cp -rf ${PKG_DIR}/bin ${INSTALL}/usr", ("Pico-8",)),),
+}
+
+# Packages of a device list whose install step puts no ES core on the image.
+NO_ES_CORE: dict[str, str] = {
+ "toolchain": "build toolchain",
+ "${OPENGLES}": "graphics driver",
+ "emuelec-emulationstation": "the frontend",
+ "retroarch": "the libretro frontend",
+ "lib32-retroarch": "the 32-bit libretro frontend, retroarch32",
+ "emuelec-tools": "system tools",
+ "emuelec-32bit-info": "the .info files of the 32-bit cores",
+ "lib32-essential": "32-bit runtime",
+ "lib32-libusb": "32-bit library",
+ "lib32-box86": "x86 translator",
+ "fbterm": "terminal",
+ "kmscon": "terminal",
+ "odroidgoa-utils": "device tools and retrorun, a runner",
+ "amiberry-lite": "amiberry-lite, which es_systems.json names nowhere",
+ "yabasanshiroSA_1_5": "yabasanshiro1_5, which es_systems.json names nowhere",
+ "lib32-droidports": "gmloader, which es_cores drops (_overrides.yml)",
+ "gme": "gme_libretro.so, which es_systems.json names nowhere",
+ "nestopiaCV": "nestopiaCV_libretro.so, which es_systems.json names nowhere",
+ "quasi88": "quasi88_libretro.so, which es_systems.json names nowhere",
+ "spring": "spring_*_libretro.so, which es_systems.json names nowhere",
+}
+
+# ES core names no package of any device builds, by the package that would.
+# The port engines are dependencies of emuelec-ports (its package.mk,
+# lines 17-59), and no package of the image depends on emuelec-ports;
+# flycast-dojo is in no device list.
+UNBUILT: dict[str, str] = {
+ **dict.fromkeys(
+ ("CGeniusExe", "Chocolate-Doom", "GZDoom", "LZDoom", "OpenJazz", "RigelEngine",
+ "VVVVVV", "abuse", "bs", "bstone", "ccleste", "cdogs-sdl", "devilutionx",
+ "eduke32", "fallout-ce", "fallout2-ce", "fheroes2", "hcl", "hode", "hurrican",
+ "opentyrian", "prince", "smw", "sonic2013", "soniccd", "sonicmania", "supertux2",
+ "supertuxkart", "xash3d"),
+ "emuelec-ports",
+ ),
+ "flycast_dojo": "flycast-dojo",
+}
+
+
+def release_devices(asset_names: list[str]) -> dict[str, str]:
+ """{device: architecture} of each image a release publishes."""
+ found: dict[str, str] = {}
+ for name in asset_names:
+ match = _ASSET_RE.match(name)
+ if match:
+ found.setdefault(match.group("device"), match.group("arch"))
+ if not found:
+ raise RuntimeError("the EmuELEC release publishes no device image")
+ return found
+
+
+def _require(text: str, lines: tuple[str, ...], where: str) -> None:
+ present = {line.strip() for line in text.splitlines()}
+ missing = [line for line in lines if line not in present]
+ if missing:
+ raise RuntimeError(f"{where} no longer reads {missing[0]!r}")
+
+
+def _quoted(text: str, name: str, where: str) -> list[str]:
+ """The words of `NAME="..."`; a backslash-newline inside the quotes is
+ removed by bash, so the value reads as one line."""
+ match = re.search(rf'^\s*{name}="([^"]*)"', text, re.MULTILINE)
+ if match is None:
+ raise RuntimeError(f"{where} sets no {name}")
+ return match.group(1).replace("\\\n", " ").split()
+
+
+class Metapackage(NamedTuple):
+ emus: list[str]
+ experimental: list[str]
+ s922x: list[str]
+ lib32: list[str]
+
+
+def read_metapackage(package_mk: str, options: str) -> Metapackage:
+ """The lists the metapackage rules work on, with PKG_EMUS expanded."""
+ _require(package_mk, _META_LINES, META_MK)
+ emus = _quoted(package_mk, "PKG_EMUS", META_MK)
+ if emus[:1] != ["${LIBRETRO_CORES}"]:
+ raise RuntimeError(f"{META_MK}: PKG_EMUS no longer starts with ${{LIBRETRO_CORES}}")
+ lib32 = _LIB32_RE.search(package_mk)
+ if lib32 is None:
+ raise RuntimeError(f"{META_MK}: no aarch64 lib32 list")
+ return Metapackage(
+ emus=_quoted(options, "LIBRETRO_CORES", OPTIONS) + emus[1:],
+ experimental=_quoted(package_mk, "PKG_EXPERIMENTAL", META_MK),
+ s922x=_quoted(options, "LIBRETRO_S922X_CORES", OPTIONS),
+ lib32=lib32.group(1).replace("\\\n", " ").split(),
+ )
+
+
+def _sed_first(words: str, pattern: str) -> str:
+ """`echo ${PKG_DEPENDS_TARGET} | sed "s|| |"`: the unquoted echo
+ joins the words with single spaces, sed replaces the first match only,
+ anywhere in the line, a word's tail included."""
+ line = " ".join(words.split())
+ at = line.find(pattern)
+ return line if at < 0 else f"{line[:at]} {line[at + len(pattern):]}"
+
+
+def device_packages(meta: Metapackage, device: str, arch: str) -> list[str]:
+ """PKG_DEPENDS_TARGET of the metapackage for one device (lines 8-77)."""
+ depends = "toolchain ${OPENGLES} emuelec-emulationstation retroarch"
+ depends += " emuelec-tools " + " ".join(meta.emus) + " " + " ".join(meta.experimental)
+ if device in _BIG:
+ depends += " " + " ".join(meta.s922x)
+ if device in _HANDHELD:
+ depends += " kmscon odroidgoa-utils"
+ for discore in ("duckstation", "mesen-s", "virtualjaguar", "quicknes", "MC"):
+ depends = _sed_first(depends, f"{discore} ")
+ depends += " yabasanshiro"
+ else:
+ depends += " fbterm"
+ if arch == "aarch64":
+ for discore in ("quicknes", "parallel-n64", "pcsx_rearmed"):
+ depends = _sed_first(depends, discore)
+ depends += " " + " ".join(meta.lib32)
+ if device in _BIG:
+ depends += " dolphinSA"
+ if device == "Amlogic-old":
+ for discore in ("yabasanshiroSA_1_11", "yabasanshiroSA_1_5", "yabasanshiro",
+ "same_cdi", "duckstation"):
+ depends = _sed_first(depends, f"{discore} ")
+ if device in _BIG:
+ depends += " mame"
+ if device in ("RK356x", "OdroidM1"):
+ depends = _sed_first(depends, "flycast-dojo")
+ return depends.split()
+
+
+def arch_builds(pkg_arch: str, arch: str) -> bool:
+ """scripts/build:28-30: an empty PKG_ARCH builds everywhere, `!`
+ excludes, otherwise the list names the arch or `any`."""
+ words = pkg_arch.split()
+ if not words:
+ return True
+ if f"!{arch}" in words:
+ return False
+ return arch in words or "any" in words
+
+
+def pkg_arch(package_mk: str) -> str:
+ match = re.search(r'^PKG_ARCH="([^"]*)"', package_mk, re.MULTILINE)
+ return match.group(1) if match else ""
+
+
+def es_systems_for(es_json: str, es_mk: str, device: str) -> SystemEmulators:
+ """es_systems.json as es_systems.cfg reads after makeinstall_target's
+ deletions on one device (emuelec-emulationstation/package.mk:114-143).
+
+ `sed "s|X||g"` matches a core written without attributes:
+ generate_es_systems.py gives `default="true"` to the first default core
+ of a system and `incompatible_extensions` to a core listing them.
+ """
+ _require(es_mk, _ES_LINES, ES_MK)
+ if device in _HANDHELD:
+ remove_cores = {"mesen-s", "quicknes", "mame2016", "mesen"}
+ drop_systems: set[str] = set()
+ drop_emulators = {"Duckstation"}
+ elif device == "Amlogic-old":
+ remove_cores = {"mesen-s", "quicknes", "mame2016", "mesen", "yabasanshiroSA",
+ "yabasanshiro"}
+ drop_systems = {"saturn", "phillips-cdi"}
+ drop_emulators = {"Duckstation", "retrorun"}
+ else:
+ # Line 117 holds for every device: no name is all three at once.
+ remove_cores = set()
+ drop_systems = set()
+ drop_emulators = {"retrorun"}
+ systems: SystemEmulators = {}
+ for system in json.loads(es_json).get("systems", []):
+ if system["name"] in drop_systems:
+ continue
+ default_set = False
+ emulators = []
+ for emulator in system.get("emulators") or []:
+ kept = []
+ for core in emulator.get("cores") or []:
+ bare = "incompatible" not in core
+ if core.get("default", False) and not default_set:
+ default_set = True
+ bare = False
+ if not (bare and core["name"] in remove_cores):
+ kept.append(core["name"])
+ if emulator["name"] not in drop_emulators:
+ emulators.append((emulator["name"], kept))
+ systems[system["name"]] = emulators
+ return systems
+
+
+def device_cores(
+ packages: list[str],
+ arch: str,
+ archs: dict[str, str],
+ systems: SystemEmulators,
+) -> list[str]:
+ """ES core names a device both installs and offers.
+
+ `archs` maps each package of PROVIDERS to its PKG_ARCH.
+ """
+ unknown = sorted(
+ p for p in set(packages) if p not in PROVIDERS and p not in NO_ES_CORE
+ and p not in UNBUILT.values()
+ )
+ if unknown:
+ raise RuntimeError(f"{META_MK}: no install step read for {', '.join(unknown)}")
+ unbuilt = sorted(set(packages) & set(UNBUILT.values()))
+ if unbuilt:
+ raise RuntimeError(f"{META_MK}: {unbuilt[0]} is built and its cores are read as absent")
+ installed: set[str] = set()
+ for package in [*set(packages), "emuelec"]:
+ if package not in PROVIDERS or not arch_builds(archs[package], arch):
+ continue
+ for install in PROVIDERS[package]:
+ if install.arch is None or (install.arch == arch) or (
+ install.arch.startswith("!") and install.arch[1:] != arch
+ ):
+ installed.update(install.cores)
+ offered, _standalone, _dual = es_cores(
+ systems, RUNNERS, BUILDS_OF, _not_cores(PLATFORM_NAME)
+ )
+ return sorted(installed & set(offered))
+
+
+def check_names(systems: SystemEmulators) -> None:
+ """Every ES core name is installed by a package read or known unbuilt."""
+ offered, _standalone, _dual = es_cores(
+ systems, RUNNERS, BUILDS_OF, _not_cores(PLATFORM_NAME)
+ )
+ provided = {core for installs in PROVIDERS.values() for i in installs for core in i.cores}
+ unread = sorted(set(offered) - provided - set(UNBUILT))
+ if unread:
+ raise RuntimeError(f"es_systems.json names {', '.join(unread)}, no package read installs it")
+
+
+def check_installs(texts: dict[str, str]) -> dict[str, str]:
+ """{package: PKG_ARCH}, after checking each cited install line is there."""
+ archs: dict[str, str] = {}
+ for package, installs in PROVIDERS.items():
+ for install in installs:
+ _require(texts[install.path], (install.line,), install.path)
+ archs[package] = pkg_arch(texts[installs[0].path])
+ return archs
+
+
+class Scraper(BaseTargetScraper):
+ """Per-device core lists from EmuELEC's metapackage."""
+
+ def __init__(self, url: str = "https://github.com/" + REPO) -> None:
+ super().__init__(url=url)
+ self.ref = ""
+
+ def _raw(self, path: str) -> str:
+ return fetch_bytes(RAW.format(ref=self.ref, path=path)).decode("utf-8")
+
+ def fetch_targets(self) -> dict:
+ self.ref = self.pinned_revision(PLATFORM_NAME)
+ release = json.loads(
+ fetch_bytes(RELEASE_API.format(ref=self.ref), headers=github_headers())
+ )
+ devices = release_devices([asset["name"] for asset in release.get("assets", [])])
+ meta = read_metapackage(self._raw(META_MK), self._raw(OPTIONS))
+ paths = sorted({i.path for installs in PROVIDERS.values() for i in installs})
+ archs = check_installs({path: self._raw(path) for path in paths})
+ es_json = fetch_bytes(ES_SYSTEMS_TEMPLATE.format(ref=self.ref)).decode("utf-8")
+ ports = port_engines(fetch_bytes(PORTS_TEMPLATE.format(ref=self.ref)).decode("utf-8"))
+ es_mk = self._raw(ES_MK)
+ check_names(with_ports(es_systems_for(es_json, es_mk, "Amlogic-ng"), ports))
+ targets: dict[str, dict] = {}
+ for device, arch in sorted(devices.items()):
+ systems = with_ports(es_systems_for(es_json, es_mk, device), ports)
+ cores = device_cores(device_packages(meta, device, arch), arch, archs, systems)
+ targets[device.lower()] = {"architecture": arch, "cores": cores}
+ print(f" {device.lower()} ({arch}): {len(cores)} cores", file=sys.stderr)
+ return {
+ "platform": PLATFORM_NAME,
+ "source": f"{self.url}/blob/{self.ref}/{META_MK}",
+ "devices_source": release["html_url"],
+ "scraped_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
+ "targets": targets,
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ allow_abbrev=False, description="Scrape EmuELEC per-device cores"
+ )
+ parser.add_argument("--dry-run", action="store_true", help="Show target summary")
+ parser.add_argument("--output", "-o", help="Output YAML file")
+ args = parser.parse_args()
+
+ scraper = Scraper()
+ data = scraper.fetch_targets()
+ if args.dry_run:
+ for name, info in data["targets"].items():
+ print(f" {name} ({info['architecture']}): {len(info['cores'])} cores")
+ return
+ if args.output:
+ scraper.write_output(data, args.output)
+ print(f"Written to {args.output}")
+ return
+ print(yaml.dump(data, default_flow_style=False, sort_keys=False))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/test_emuelec_targets.py b/tests/test_emuelec_targets.py
new file mode 100644
index 000000000..c8f911433
--- /dev/null
+++ b/tests/test_emuelec_targets.py
@@ -0,0 +1,266 @@
+"""EmuELEC's images differ by device, and only its metapackage says how.
+
+packages/sx05re/emuelec/package.mk (v4.8) builds the S922X cores, Dolphin
+and the MAME core only on Amlogic-ng, Amlogic-no, RK356x and OdroidM1, and
+takes DuckStation out on the two handhelds with a sed that replaces the
+first match only. With no target list, an OdroidGoAdvance pack carried the
+firmware of cores its image never had.
+"""
+
+from __future__ import annotations
+
+import json
+import sys
+import unittest
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(REPO_ROOT / "scripts"))
+
+from scraper.targets import emuelec_targets_scraper as scraper # noqa: E402
+
+# packages/sx05re/emuelec/package.mk:8-77 at v4.8, PKG_EMUS and
+# PKG_EXPERIMENTAL shortened.
+PACKAGE_MK = """PKG_DEPENDS_TARGET="toolchain ${OPENGLES} emuelec-emulationstation retroarch"
+PKG_EXPERIMENTAL="nestopiaCV quasi88 yabasanshiroSA_1_11 yabasanshiroSA_1_5 fbneoSA"
+PKG_EMUS="${LIBRETRO_CORES} advancemame duckstation pcsx_rearmed flycastsa"
+PKG_DEPENDS_TARGET+=" emuelec-tools ${PKG_EMUS} ${PKG_EXPERIMENTAL}"
+
+if [ "${DEVICE}" == "Amlogic-ng" ] || [ "${DEVICE}" == "Amlogic-no" ] || [ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then
+\tPKG_DEPENDS_TARGET+=" ${LIBRETRO_S922X_CORES}"
+fi
+
+if [ "${DEVICE}" == "OdroidGoAdvance" ] || [ "${DEVICE}" == "GameForce" ]; then
+\tPKG_DEPENDS_TARGET+=" kmscon odroidgoa-utils"
+\tfor discore in duckstation mesen-s virtualjaguar quicknes MC; do
+\t\tPKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore} | |")
+\tdone
+\tPKG_DEPENDS_TARGET+=" yabasanshiro"
+else
+\tPKG_DEPENDS_TARGET+=" fbterm"
+fi
+
+if [ "${ARCH}" == "aarch64" ]; then
+ for discore in quicknes parallel-n64 pcsx_rearmed; do
+\t\tPKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore}| |")
+\tdone
+
+ PKG_DEPENDS_TARGET+=" swanstation \\
+ lib32-essential \\
+ lib32-pcsx_rearmed \\
+ lib32-parallel-n64
+ lib32-libusb"
+
+ if [ "${DEVICE}" == "Amlogic-ng" ] || [ "${DEVICE}" == "Amlogic-no" ] || [ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then
+ PKG_DEPENDS_TARGET+=" dolphinSA"
+ fi
+
+ if [ "${DEVICE}" == "Amlogic-old" ]; then
+ for discore in yabasanshiroSA_1_11 yabasanshiroSA_1_5 yabasanshiro same_cdi duckstation; do
+ PKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore} | |")
+ done
+ fi
+fi
+
+if [ "${DEVICE}" == "Amlogic-ng" ] || [ "${DEVICE}" == "Amlogic-no" ] || [ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then
+\tPKG_DEPENDS_TARGET+=" mame"
+fi
+
+if [ "${DEVICE}" == "RK356x" ] || [ "${DEVICE}" == "OdroidM1" ]; then
+ for discore in flycast-dojo; do
+\t\tPKG_DEPENDS_TARGET=$(echo ${PKG_DEPENDS_TARGET} | sed "s|${discore}| |")
+\tdone
+fi
+"""
+
+# distributions/EmuELEC/options:274-373 at v4.8, shortened.
+OPTIONS = """LIBRETRO_CORES="mgba \\
+parallel-n64 \\
+pcsx_rearmed \\
+flycast"
+
+LIBRETRO_S922X_CORES="beetle-saturn \\
+mesen \\
+quicknes \\
+virtualjaguar"
+"""
+
+# packages/sx05re/emuelec-emulationstation/package.mk:114-143 at v4.8.
+ES_MK = """CORESFILE="${INSTALL}/usr/config/emulationstation/es_systems.cfg"
+
+if [[ "${DEVICE}" != "Amlogic-ng" || "${DEVICE}" != "Amlogic-ne" || "${DEVICE}" != "Amlogic-no" ]]; then
+ if [[ ${DEVICE} == "OdroidGoAdvance" || "${DEVICE}" == "GameForce" ]]; then
+ remove_cores="mesen-s quicknes mame2016 mesen"
+ elif [ "${DEVICE}" == "Amlogic-old" ]; then
+ remove_cores="mesen-s quicknes mame2016 mesen yabasanshiroSA yabasanshiro"
+ xmlstarlet ed -L -P -d "/systemList/system[name='saturn']" ${CORESFILE}
+ xmlstarlet ed -L -P -d "/systemList/system[name='phillips-cdi']" ${CORESFILE}
+ xmlstarlet ed -L -P -d "/systemList/system/emulators/emulator[@name='Duckstation']" ${CORESFILE}
+ fi
+ for discore in ${remove_cores}; do
+ sed -i "s|${discore}||g" ${CORESFILE}
+ sed -i '/^[[:space:]]*$/d' ${CORESFILE}
+ done
+fi
+
+if [[ ${DEVICE} != "OdroidGoAdvance" ]] && [[ "${DEVICE}" != "GameForce" ]]; then
+\txmlstarlet ed -L -P -d "/systemList/system/emulators/emulator[@name='retrorun']" ${CORESFILE}
+else
+\txmlstarlet ed -L -P -d "/systemList/system/emulators/emulator[@name='Duckstation']" ${CORESFILE}
+fi
+"""
+
+
+def _system(name: str, *emulators: tuple[str, list[dict]]) -> dict:
+ return {"name": name, "emulators": [{"name": e, "cores": c} for e, c in emulators]}
+
+
+ES_JSON = json.dumps({"systems": [
+ _system("nes", ("libretro", [{"name": "mesen", "default": True}])),
+ _system("snes", ("libretro", [{"name": "snes9x", "default": True}, {"name": "mesen-s"}])),
+ _system("psx",
+ ("libretro", [{"name": "pcsx_rearmed", "default": True},
+ {"name": "pcsx_rearmed_32b"}, {"name": "swanstation"}]),
+ ("Duckstation", [{"name": "Duckstation"}]),
+ ("retrorun", [{"name": "pcsx_rearmed_32b"}])),
+ _system("n64", ("libretro", [{"name": "parallel_n64_32b"}])),
+]})
+
+ARCHS = {"mesen": "", "duckstation": "aarch64", "pcsx_rearmed": "any",
+ "lib32-pcsx_rearmed": "aarch64", "swanstation": "any",
+ "lib32-parallel-n64": "aarch64"}
+
+ASSETS = [
+ "EmuELEC-Amlogic-ng.aarch64-4.8-Generic.img.gz",
+ "EmuELEC-Amlogic-ng.aarch64-4.8.tar",
+ "EmuELEC-GameForce.aarch64-4.8-chi.img.gz.sha256",
+ "EmuELEC-OdroidGoAdvance.aarch64-4.8-odroidgo2.tar",
+ "EmuELEC-OdroidM1.aarch64-4.8.img.gz",
+]
+
+
+class TheMetapackageDecidesEachDevice(unittest.TestCase):
+ def setUp(self):
+ self.meta = scraper.read_metapackage(PACKAGE_MK, OPTIONS)
+
+ def test_devices_are_the_images_the_release_publishes(self):
+ self.assertEqual(scraper.release_devices(ASSETS), {
+ "Amlogic-ng": "aarch64", "GameForce": "aarch64",
+ "OdroidGoAdvance": "aarch64", "OdroidM1": "aarch64",
+ })
+
+ def test_the_lists_the_rules_work_on(self):
+ self.assertEqual(self.meta.emus, ["mgba", "parallel-n64", "pcsx_rearmed", "flycast",
+ "advancemame", "duckstation", "pcsx_rearmed",
+ "flycastsa"])
+ self.assertEqual(self.meta.lib32, ["swanstation", "lib32-essential",
+ "lib32-pcsx_rearmed", "lib32-parallel-n64",
+ "lib32-libusb"])
+
+ def test_the_big_devices_build_the_s922x_cores_dolphin_and_mame(self):
+ packages = scraper.device_packages(self.meta, "Amlogic-ng", "aarch64")
+ for package in ("beetle-saturn", "mesen", "virtualjaguar", "dolphinSA", "mame",
+ "duckstation", "fbterm"):
+ self.assertIn(package, packages)
+ # quicknes is added, then the aarch64 loop takes it out.
+ self.assertNotIn("quicknes", packages)
+
+ def test_the_handhelds_lose_duckstation_and_gain_their_tools(self):
+ packages = scraper.device_packages(self.meta, "OdroidGoAdvance", "aarch64")
+ for package in ("duckstation", "mesen", "beetle-saturn", "dolphinSA", "mame", "fbterm"):
+ self.assertNotIn(package, packages)
+ self.assertEqual(packages[-1:], ["lib32-libusb"])
+ self.assertIn("kmscon", packages)
+ self.assertIn("yabasanshiro", packages)
+
+ def test_sed_takes_out_the_first_match_only(self):
+ # pcsx_rearmed is written twice, in LIBRETRO_CORES and in PKG_EMUS:
+ # the aarch64 loop removes the first and the 64-bit core is built.
+ for device in ("Amlogic-ng", "OdroidGoAdvance"):
+ packages = scraper.device_packages(self.meta, device, "aarch64")
+ self.assertEqual(packages.count("pcsx_rearmed"), 1, device)
+ self.assertNotIn("parallel-n64", packages, device)
+
+ def test_a_pattern_with_a_trailing_space_misses_the_last_word(self):
+ self.assertEqual(scraper._sed_first("a duckstation", "duckstation "), "a duckstation")
+ self.assertEqual(scraper._sed_first("a duckstation b", "duckstation "), "a b")
+ # Without the space, the pattern takes a word's tail too.
+ self.assertEqual(scraper._sed_first("lib32-pcsx_rearmed", "pcsx_rearmed"), "lib32- ")
+
+ def test_a_changed_rule_stops_the_scrape(self):
+ changed = PACKAGE_MK.replace("duckstation mesen-s virtualjaguar quicknes MC",
+ "duckstation mesen-s")
+ with self.assertRaises(RuntimeError):
+ scraper.read_metapackage(changed, OPTIONS)
+
+
+class EachPackageBuildsWhereItsArchAllows(unittest.TestCase):
+ def test_pkg_arch(self):
+ self.assertTrue(scraper.arch_builds("", "aarch64"))
+ self.assertTrue(scraper.arch_builds("any", "aarch64"))
+ self.assertTrue(scraper.arch_builds("aarch64 arm", "aarch64"))
+ # mupen64plus and uae4arm say PKG_ARCH="arm": skipped on aarch64.
+ self.assertFalse(scraper.arch_builds("arm", "aarch64"))
+ self.assertFalse(scraper.arch_builds("any !aarch64", "aarch64"))
+
+ def test_every_cited_install_line_is_read(self):
+ install = scraper.PROVIDERS["mgba"][0]
+ text = f'PKG_ARCH="any"\nmakeinstall_target() {{\n {install.line}\n}}\n'
+ with self.assertRaises(RuntimeError):
+ scraper._require(text.replace("mgba_libretro", "mgba2_libretro"),
+ (install.line,), install.path)
+ scraper._require(text, (install.line,), install.path)
+
+
+class TheFrontendOffersWhatTheDeviceKeeps(unittest.TestCase):
+ def test_handhelds_drop_bare_cores_and_duckstation(self):
+ systems = scraper.es_systems_for(ES_JSON, ES_MK, "GameForce")
+ # mesen is the nes default: written with an attribute, sed misses it.
+ self.assertEqual(systems["nes"], [("libretro", ["mesen"])])
+ self.assertEqual(systems["snes"], [("libretro", ["snes9x"])])
+ self.assertEqual([e for e, _ in systems["psx"]], ["libretro", "retrorun"])
+
+ def test_other_devices_drop_retrorun(self):
+ systems = scraper.es_systems_for(ES_JSON, ES_MK, "Amlogic-ng")
+ self.assertEqual([e for e, _ in systems["psx"]], ["libretro", "Duckstation"])
+ self.assertEqual(systems["snes"], [("libretro", ["snes9x", "mesen-s"])])
+
+ def test_a_device_keeps_what_it_builds_and_offers(self):
+ meta = scraper.read_metapackage(PACKAGE_MK, OPTIONS)
+ archs = {**dict.fromkeys(scraper.PROVIDERS, "any"), **ARCHS}
+ cores = {}
+ for device in ("Amlogic-ng", "OdroidGoAdvance"):
+ packages = [p for p in scraper.device_packages(meta, device, "aarch64")
+ if p in scraper.PROVIDERS or p in scraper.NO_ES_CORE]
+ systems = scraper.es_systems_for(ES_JSON, ES_MK, device)
+ cores[device] = scraper.device_cores(packages, "aarch64", archs, systems)
+ self.assertEqual(cores["Amlogic-ng"], ["Duckstation", "mesen", "parallel_n64_32b",
+ "pcsx_rearmed", "pcsx_rearmed_32b",
+ "swanstation"])
+ self.assertEqual(cores["OdroidGoAdvance"], ["parallel_n64_32b", "pcsx_rearmed",
+ "pcsx_rearmed_32b", "swanstation"])
+
+ def test_a_package_never_read_stops_the_scrape(self):
+ archs = dict.fromkeys(scraper.PROVIDERS, "any")
+ with self.assertRaises(RuntimeError):
+ scraper.device_cores(["mgba", "newcore"], "aarch64", archs, {})
+
+
+class TheCommittedListFollowsTheRules(unittest.TestCase):
+ def test_the_handhelds_list_no_core_they_do_not_build(self):
+ import yaml # noqa: PLC0415
+
+ targets = yaml.safe_load((REPO_ROOT / "platforms" / "targets" / "emuelec.yml")
+ .read_text(encoding="utf-8"))["targets"]
+ self.assertEqual(set(targets), {"amlogic-ng", "gameforce", "odroidgoadvance", "odroidm1"})
+ big = set(targets["amlogic-ng"]["cores"])
+ for device in ("gameforce", "odroidgoadvance"):
+ self.assertEqual(big - set(targets[device]["cores"]), {
+ "Duckstation", "dolphin", "mame", "mednafen_saturn", "mesen", "mesen-s",
+ "virtualjaguar",
+ })
+ self.assertEqual(targets["odroidm1"]["cores"], targets["amlogic-ng"]["cores"])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/wiki/adding-a-scraper.md b/wiki/adding-a-scraper.md
index 7dc29ef32..a8ea434ef 100644
--- a/wiki/adding-a-scraper.md
+++ b/wiki/adding-a-scraper.md
@@ -339,6 +339,7 @@ Register the target scraper in `_registry.yml`:
| `recalbox_targets` | board defconfigs + `system.ini` | Buildroot packages each image enables, cores per system |
| `rocknix_targets` | emulators `package.mk` + device options | Cores per SoC block and 32-bit support per device |
| `amberelec_targets` | Makefile devices + metapackage `package.mk` + `es_systems.cfg` | Extra cores kept only on the devices the metapackage names |
+| `emuelec_targets` | release asset names + metapackage `package.mk` + each core's install step | Packages per device, mapped to cores by the `.so` or program each installs |
## Parser modules
diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md
index 38ce5b358..8eb805706 100644
--- a/wiki/testing-guide.md
+++ b/wiki/testing-guide.md
@@ -56,7 +56,7 @@ Every module in `tests/`, by the area it guards.
| Verification, cross-reference and profile checks | synthetic + profiles | `test_bios_layout`, `test_cache_independent_counts`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_entry_categories`, `test_file_consumers`, `test_fileless_audit`, `test_flycast_layout`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_aliases`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_profile_names`, `test_profile_paths`, `test_profile_repositories`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_links`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_data_dir_notice`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` |
| Packs and manifests | synthetic + real packs | `test_artifact_lock`, `test_atomic_artifacts`, `test_batocera_cores`, `test_core_data_trees`, `test_deterministic_zip`, `test_emulator_pack_counts`, `test_finalize_pack_names`, `test_large_file_cache`, `test_libretro_layout`, `test_manifest_entry`, `test_minui_platform`, `test_no_game_data`, `test_pack_conformance_dirs`, `test_pack_core_extras`, `test_pack_counts`, `test_pack_destinations`, `test_pack_failures`, `test_pack_file_names`, `test_pack_grouping`, `test_pack_integrity`, `test_pack_member_identity`, `test_pack_readme`, `test_platform_inheritance`, `test_platform_keys`, `test_release_packs`, `test_required_only_archives`, `test_required_only_twins`, `test_save_root`, `test_split_extras`, `test_split_names`, `test_split_pack`, `test_system_pack_extras`, `test_system_pack_parity`, `test_torrentzip`, `test_which_pack` |
| Slots and regions | synthetic + profiles | `test_region`, `test_region_agnostic_scan`, `test_region_groups`, `test_region_held`, `test_region_platform_index`, `test_region_required_only`, `test_slot`, `test_slots`, `test_slots_shipped_file` |
-| Hardware targets and systems | synthetic + target files | `test_amberelec_targets`, `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |
+| Hardware targets and systems | synthetic + target files | `test_amberelec_targets`, `test_emuelec_targets`, `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |
| Installer and downloads | loopback server | `test_check_release`, `test_download`, `test_install`, `test_install_cores`, `test_install_experience`, `test_install_app`, `test_install_from`, `test_install_games`, `test_install_offline`, `test_install_selection`, `test_install_tui` |
| Handheld launchers | a pty as the console, fake installer and firmware tools, stubbed PortMaster dialogs | `test_handheld_launchers`, `test_port` |
| Running cores | parsers on fixed inputs, a libretro core built from C in the test when a compiler exists | `test_core_probe` |
diff --git a/wiki/tools.md b/wiki/tools.md
index c8911f3b5..65a175d91 100644
--- a/wiki/tools.md
+++ b/wiki/tools.md
@@ -1719,6 +1719,7 @@ Located in `scripts/scraper/targets/`. Each inherits `BaseTargetScraper` and imp
| `recalbox_targets_scraper` | board defconfigs + system.ini cores | board |
| `rocknix_targets_scraper` | emulators package.mk + device options | device |
| `amberelec_targets_scraper` | Makefile devices + metapackage extra cores + es_systems.cfg | device |
+| `emuelec_targets_scraper` | release assets + metapackage package.mk + core install steps + es_systems.json | device |
| `lakka_targets_scraper` | libretro_cores package.mk + project and device options | device image |
| `emudeck_targets_scraper` | EmuScripts (SteamOS and Windows) | operating system |
| `retropie_targets_scraper` | scriptmodules + rp_module_flags | platform flag |
From 44565a07bb87342733be26ae77658f1ff71e4315 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 12:09:09 +0100
Subject: [PATCH 82/83] feat: read the EmuELEC device in the installer
EmuELEC's scripts/image writes COREELEC_DEVICE to os-release (v4.8, line
189), as a GameForce image shows. The installer reads it the way it does
for AmberELEC and applies install/targets/emuelec.json. MiSTer FPGA takes
EmuELEC's place in the test of a platform without targets.
---
install.ps1 | 2 +-
install.py | 8 +-
install.sh | 2 +-
install/launchers/index.json | 16 +-
install/targets/emuelec.json | 492 +++++++++++++++++++++++++++++++++++
tests/test_install.py | 24 +-
wiki/installer.md | 2 +-
7 files changed, 526 insertions(+), 20 deletions(-)
create mode 100644 install/targets/emuelec.json
diff --git a/install.ps1 b/install.ps1
index 3b53ab0a0..28de54233 100644
--- a/install.ps1
+++ b/install.ps1
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
- $defaultInstallSha256 = "b532d7f12f92dc5934e210b7359e849e796abf39d9d1598eac14fe91dc8c86ac"
+ $defaultInstallSha256 = "57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
diff --git a/install.py b/install.py
index bd32bf94b..04a697af5 100644
--- a/install.py
+++ b/install.py
@@ -109,8 +109,8 @@ TARGETS_URL = f"{BASE_URL}/install/targets/{{platform}}.json"
# has no hardware targets, where the run sent the user after a list that
# exists nowhere.
TARGET_PLATFORMS = frozenset({
- "amberelec", "batocera", "emudeck", "knulli", "lakka", "recalbox", "retroarch", "retrobat",
- "retrodeck", "retropie", "rocknix", "romm",
+ "amberelec", "batocera", "emudeck", "emuelec", "knulli", "lakka", "recalbox", "retroarch",
+ "retrobat", "retrodeck", "retropie", "rocknix", "romm",
})
RAW_FILE_URL = f"{BASE_URL}/{{path}}"
RELEASE_URL = (
@@ -1484,9 +1484,11 @@ def _parse_bash_var(path: Path, key: str) -> str | None:
# board/scripts/post-build-script.sh:264-278) and writes KNULLI_SYSTEM_ARCH
# to knulli.arch (package/system/knulli-system/knulli-system.mk:98-99).
# AmberELEC's scripts/image writes COREELEC_DEVICE (a21975bf, line 168), the
-# DEVICE its Makefile builds (RG351P).
+# DEVICE its Makefile builds (RG351P). EmuELEC's writes the same line (v4.8,
+# line 189), the DEVICE of the release image (OdroidGoAdvance).
_BOARD_SOURCES: dict[str, tuple[str, str]] = {
"amberelec": ("os_release", "COREELEC_DEVICE"),
+ "emuelec": ("os_release", "COREELEC_DEVICE"),
"batocera": ("file", "/usr/share/batocera/batocera.arch"),
"recalbox": ("file", "/recalbox/recalbox.arch"),
"rocknix": ("os_release", "HW_DEVICE"),
diff --git a/install.sh b/install.sh
index 8e65e5916..a03428f05 100755
--- a/install.sh
+++ b/install.sh
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
-DEFAULT_INSTALL_SHA256="b532d7f12f92dc5934e210b7359e849e796abf39d9d1598eac14fe91dc8c86ac"
+DEFAULT_INSTALL_SHA256="57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4"
MAX_INSTALLER_BYTES=2097152
cleanup() {
diff --git a/install/launchers/index.json b/install/launchers/index.json
index 428c911fc..f6dc104a6 100644
--- a/install/launchers/index.json
+++ b/install/launchers/index.json
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
- "size": 1112275,
- "sha256": "b532d7f12f92dc5934e210b7359e849e796abf39d9d1598eac14fe91dc8c86ac",
+ "size": 1112438,
+ "sha256": "57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
- "size": 1165902,
- "sha256": "30b3cd30b3a75c4e2fb0784589f1b12d3ac2fb6ec345e874a2a8d58681c236c8"
+ "size": 1166065,
+ "sha256": "1c9e5737a0b32c85108f556c2799cf0ebb5ce52cbd2bf501bc24783fa3a04b9a"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
- "size": 1112275,
- "sha256": "b532d7f12f92dc5934e210b7359e849e796abf39d9d1598eac14fe91dc8c86ac",
+ "size": 1112438,
+ "sha256": "57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
- "size": 1112275,
- "sha256": "b532d7f12f92dc5934e210b7359e849e796abf39d9d1598eac14fe91dc8c86ac",
+ "size": 1112438,
+ "sha256": "57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4",
"executable": false
},
{
diff --git a/install/targets/emuelec.json b/install/targets/emuelec.json
new file mode 100644
index 000000000..c3363d940
--- /dev/null
+++ b/install/targets/emuelec.json
@@ -0,0 +1,492 @@
+{
+ "amlogic-ng": [
+ "2048",
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DOSBOXSDL2",
+ "Duckstation",
+ "ECWolf",
+ "FBNEOSA",
+ "HATARISA",
+ "HYPSEUS",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "Pico-8",
+ "SCUMMVMSA",
+ "STELLASA",
+ "Solarus",
+ "a5200",
+ "atari800",
+ "bgdi",
+ "bk",
+ "bluemsx",
+ "cannonball",
+ "cap32",
+ "daphne",
+ "dinothawr",
+ "dolphin",
+ "dosbox_pure",
+ "dosbox_svn",
+ "easyrpg",
+ "fake08",
+ "fbalpha2012",
+ "fbneo",
+ "fceumm",
+ "fceumm_mod",
+ "flycast",
+ "flycast_32b",
+ "flycastsa",
+ "fmsx",
+ "freeintv",
+ "freej2me",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "geargrafx",
+ "gearlynx",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_cart_special",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "handy",
+ "hatari",
+ "ikemen",
+ "jzintv",
+ "mame",
+ "mame2003_plus",
+ "mame2010",
+ "mednafen_lynx",
+ "mednafen_ngp",
+ "mednafen_pce_fast",
+ "mednafen_pcfx",
+ "mednafen_saturn",
+ "mednafen_supafaust",
+ "mednafen_supergrafx",
+ "mednafen_vb",
+ "mednafen_wswan",
+ "mesen",
+ "mesen-s",
+ "mgba",
+ "mrboom",
+ "mupen64plus_32b",
+ "mupen64plus_next",
+ "mupen64plus_next_alt",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "nxengine",
+ "o2em",
+ "opera",
+ "parallel_n64_32b",
+ "pcsx_rearmed",
+ "pcsx_rearmed_32b",
+ "picodrive",
+ "pocketcdg",
+ "pokemini",
+ "potator",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "reminiscence",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "stella",
+ "swanstation",
+ "tgbdual",
+ "tic80",
+ "tyrquake",
+ "uae4arm_32b",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_x64sc",
+ "vice_xplus4",
+ "vice_xvic",
+ "virtualjaguar",
+ "x1",
+ "xrick",
+ "yabasanshiro"
+ ],
+ "gameforce": [
+ "2048",
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DOSBOXSDL2",
+ "ECWolf",
+ "FBNEOSA",
+ "HATARISA",
+ "HYPSEUS",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "Pico-8",
+ "SCUMMVMSA",
+ "STELLASA",
+ "Solarus",
+ "a5200",
+ "atari800",
+ "bgdi",
+ "bk",
+ "bluemsx",
+ "cannonball",
+ "cap32",
+ "daphne",
+ "dinothawr",
+ "dosbox_pure",
+ "dosbox_svn",
+ "easyrpg",
+ "fake08",
+ "fbalpha2012",
+ "fbneo",
+ "fceumm",
+ "fceumm_mod",
+ "flycast",
+ "flycast_32b",
+ "flycastsa",
+ "fmsx",
+ "freeintv",
+ "freej2me",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "geargrafx",
+ "gearlynx",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_cart_special",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "handy",
+ "hatari",
+ "ikemen",
+ "jzintv",
+ "mame2003_plus",
+ "mame2010",
+ "mednafen_lynx",
+ "mednafen_ngp",
+ "mednafen_pce_fast",
+ "mednafen_pcfx",
+ "mednafen_supafaust",
+ "mednafen_supergrafx",
+ "mednafen_vb",
+ "mednafen_wswan",
+ "mgba",
+ "mrboom",
+ "mupen64plus_32b",
+ "mupen64plus_next",
+ "mupen64plus_next_alt",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "nxengine",
+ "o2em",
+ "opera",
+ "parallel_n64_32b",
+ "pcsx_rearmed",
+ "pcsx_rearmed_32b",
+ "picodrive",
+ "pocketcdg",
+ "pokemini",
+ "potator",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "reminiscence",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "stella",
+ "swanstation",
+ "tgbdual",
+ "tic80",
+ "tyrquake",
+ "uae4arm_32b",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_x64sc",
+ "vice_xplus4",
+ "vice_xvic",
+ "x1",
+ "xrick",
+ "yabasanshiro"
+ ],
+ "odroidgoadvance": [
+ "2048",
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DOSBOXSDL2",
+ "ECWolf",
+ "FBNEOSA",
+ "HATARISA",
+ "HYPSEUS",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "Pico-8",
+ "SCUMMVMSA",
+ "STELLASA",
+ "Solarus",
+ "a5200",
+ "atari800",
+ "bgdi",
+ "bk",
+ "bluemsx",
+ "cannonball",
+ "cap32",
+ "daphne",
+ "dinothawr",
+ "dosbox_pure",
+ "dosbox_svn",
+ "easyrpg",
+ "fake08",
+ "fbalpha2012",
+ "fbneo",
+ "fceumm",
+ "fceumm_mod",
+ "flycast",
+ "flycast_32b",
+ "flycastsa",
+ "fmsx",
+ "freeintv",
+ "freej2me",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "geargrafx",
+ "gearlynx",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_cart_special",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "handy",
+ "hatari",
+ "ikemen",
+ "jzintv",
+ "mame2003_plus",
+ "mame2010",
+ "mednafen_lynx",
+ "mednafen_ngp",
+ "mednafen_pce_fast",
+ "mednafen_pcfx",
+ "mednafen_supafaust",
+ "mednafen_supergrafx",
+ "mednafen_vb",
+ "mednafen_wswan",
+ "mgba",
+ "mrboom",
+ "mupen64plus_32b",
+ "mupen64plus_next",
+ "mupen64plus_next_alt",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "nxengine",
+ "o2em",
+ "opera",
+ "parallel_n64_32b",
+ "pcsx_rearmed",
+ "pcsx_rearmed_32b",
+ "picodrive",
+ "pocketcdg",
+ "pokemini",
+ "potator",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "reminiscence",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "stella",
+ "swanstation",
+ "tgbdual",
+ "tic80",
+ "tyrquake",
+ "uae4arm_32b",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_x64sc",
+ "vice_xplus4",
+ "vice_xvic",
+ "x1",
+ "xrick",
+ "yabasanshiro"
+ ],
+ "odroidm1": [
+ "2048",
+ "81",
+ "AMIBERRY",
+ "AdvanceMame",
+ "DOSBOXSDL2",
+ "Duckstation",
+ "ECWolf",
+ "FBNEOSA",
+ "HATARISA",
+ "HYPSEUS",
+ "OPENBOR",
+ "PPSSPPSDL",
+ "Pico-8",
+ "SCUMMVMSA",
+ "STELLASA",
+ "Solarus",
+ "a5200",
+ "atari800",
+ "bgdi",
+ "bk",
+ "bluemsx",
+ "cannonball",
+ "cap32",
+ "daphne",
+ "dinothawr",
+ "dolphin",
+ "dosbox_pure",
+ "dosbox_svn",
+ "easyrpg",
+ "fake08",
+ "fbalpha2012",
+ "fbneo",
+ "fceumm",
+ "fceumm_mod",
+ "flycast",
+ "flycast_32b",
+ "flycastsa",
+ "fmsx",
+ "freeintv",
+ "freej2me",
+ "fuse",
+ "gambatte",
+ "gearboy",
+ "gearcoleco",
+ "geargrafx",
+ "gearlynx",
+ "gearsystem",
+ "genesis_plus_gx",
+ "genesis_plus_gx_cart_special",
+ "genesis_plus_gx_wide",
+ "geolith",
+ "gpsp",
+ "gw",
+ "handy",
+ "hatari",
+ "ikemen",
+ "jzintv",
+ "mame",
+ "mame2003_plus",
+ "mame2010",
+ "mednafen_lynx",
+ "mednafen_ngp",
+ "mednafen_pce_fast",
+ "mednafen_pcfx",
+ "mednafen_saturn",
+ "mednafen_supafaust",
+ "mednafen_supergrafx",
+ "mednafen_vb",
+ "mednafen_wswan",
+ "mesen",
+ "mesen-s",
+ "mgba",
+ "mrboom",
+ "mupen64plus_32b",
+ "mupen64plus_next",
+ "mupen64plus_next_alt",
+ "mupen64plussa",
+ "nekop2",
+ "neocd",
+ "nestopia",
+ "np2kai",
+ "nxengine",
+ "o2em",
+ "opera",
+ "parallel_n64_32b",
+ "pcsx_rearmed",
+ "pcsx_rearmed_32b",
+ "picodrive",
+ "pocketcdg",
+ "pokemini",
+ "potator",
+ "prboom",
+ "prosystem",
+ "puae",
+ "puae2021",
+ "px68k",
+ "reminiscence",
+ "same_cdi",
+ "sameboy",
+ "sameduck",
+ "scummvm",
+ "snes9x",
+ "snes9x2002",
+ "snes9x2005_plus",
+ "snes9x2010",
+ "stella",
+ "swanstation",
+ "tgbdual",
+ "tic80",
+ "tyrquake",
+ "uae4arm_32b",
+ "uzem",
+ "vba_next",
+ "vbam",
+ "vecx",
+ "vice_x128",
+ "vice_x64",
+ "vice_x64sc",
+ "vice_xplus4",
+ "vice_xvic",
+ "virtualjaguar",
+ "x1",
+ "xrick",
+ "yabasanshiro"
+ ]
+}
diff --git a/tests/test_install.py b/tests/test_install.py
index 7e1659a07..252f8a4c8 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -3552,7 +3552,7 @@ class ACardPreparedOnAComputerGetsItsBoard(unittest.TestCase):
class APlatformWithoutTargetsSaysSoOffline(unittest.TestCase):
"""Offline, --target on AmberELEC asked for install/targets/amberelec.json,
which existed nowhere: online the same run said it had no targets.
- EmuELEC has none still."""
+ MiSTer FPGA has none still."""
def test_the_list_matches_the_published_targets(self):
published = {path.stem for path in (REPO_ROOT / "install" / "targets").glob("*.json")}
@@ -3560,16 +3560,16 @@ class APlatformWithoutTargetsSaysSoOffline(unittest.TestCase):
def test_offline_says_there_are_no_targets(self):
dest = Path(_tempdir(self))
- for extra in ([], ["--manifest", str(REPO_ROOT / "install" / "emuelec.json")]):
+ for extra in ([], ["--manifest", str(REPO_ROOT / "install" / "misterfpga.json")]):
with self.subTest(manifest=bool(extra)):
proc = subprocess.run(
- [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "emuelec",
- "--dest", str(dest), "--target", "rk3326", "--offline", "--no-input",
+ [sys.executable, str(REPO_ROOT / "install.py"), "--platform", "misterfpga",
+ "--dest", str(dest), "--target", "de10-nano", "--offline", "--no-input",
"--dry-run", *extra],
capture_output=True, text=True, timeout=120, stdin=subprocess.DEVNULL)
self.assertEqual(proc.returncode, 2, proc.stderr)
- self.assertIn("EmuELEC has no hardware targets", proc.stderr)
- self.assertNotIn("targets/emuelec.json", proc.stderr)
+ self.assertIn("MiSTer FPGA has no hardware targets", proc.stderr)
+ self.assertNotIn("targets/misterfpga.json", proc.stderr)
class TheBoardTheSystemNamesIsTheTarget(unittest.TestCase):
@@ -3635,6 +3635,18 @@ class TheBoardTheSystemNamesIsTheTarget(unittest.TestCase):
.read_text(encoding="utf-8"))
self.assertIn("rg351p", targets)
+ def test_emuelec_names_its_device(self):
+ # An OdroidGoAdvance image carries no DuckStation, Dolphin or MAME
+ # core, and the full list was installed: EmuELEC had no target list.
+ with unittest.mock.patch.object(
+ install, "_parse_os_release", return_value={"COREELEC_DEVICE": "OdroidGoAdvance"}
+ ):
+ self.assertEqual(install.detect_board("emuelec"), "odroidgoadvance")
+ targets = json.loads((REPO_ROOT / "install" / "targets" / "emuelec.json")
+ .read_text(encoding="utf-8"))
+ self.assertIn("odroidgoadvance", targets)
+ self.assertNotIn("Duckstation", targets["odroidgoadvance"])
+
def test_lakka_names_its_device_or_its_project(self):
# An RPi4 Lakka installed 5.7 GB of every board's files: its board
# was in os-release and never read.
diff --git a/wiki/installer.md b/wiki/installer.md
index d7061b97d..6378b191a 100644
--- a/wiki/installer.md
+++ b/wiki/installer.md
@@ -968,7 +968,7 @@ what the options name, everything by default.
|--------|--------|
| `--platform NAME` | Install for this platform instead of the detected one. A system `--list-platforms` names under its own files (`muos`, `arkos`) stands for the file list it gets, and the run says which. ES-DE, LaunchBox and Android, which keep no BIOS folder, are answered with the run that fills each emulator's folder. Unknown names are refused with the closest ones |
| `--dest PATH` | Destination directory, overriding detection. Without `--platform`, the file list is the platform detected here: at a terminal the installer asks, Enter taking the one found, and otherwise it uses the one found, RetroArch's when nothing is found, and refuses when several are. The run prints whose list it is. A folder that does not exist is named with the nearest one that does, then created, except for a system that runs from its SD card, which refuses it. When more than its last level is missing (a mistyped path), a run at a terminal asks first, and the answer defaults to no |
-| `--target NAME` | Keep only the files the cores of that hardware target need, and the systems they emulate. An unknown target is refused rather than ignored, since carrying on would install everything. On Batocera, Recalbox, ROCKNIX, Lakka, KNULLI and RetroPie the board is read from the system (`batocera.arch`, `recalbox.arch`, `HW_DEVICE`, `LIBREELEC_DEVICE` or `LIBREELEC_PROJECT`, `knulli.arch`, the Pi model in `/proc/cpuinfo` where `/opt/retropie` exists) and applied when no `--target` is given, from a pack alone too when it carries the core list per board. On a computer, the board a Batocera or KNULLI card names on its boot partition (`boot/batocera.board`, `boot/knulli.board`) is applied the same way, in line mode and on the full screen. The card names its image (`anbernic-rg35xx-plus`, `x86-64-v3`), which the target list maps to its board (`h700`, `zen3`) |
+| `--target NAME` | Keep only the files the cores of that hardware target need, and the systems they emulate. An unknown target is refused rather than ignored, since carrying on would install everything. On Batocera, Recalbox, ROCKNIX, Lakka, KNULLI, AmberELEC, EmuELEC and RetroPie the board is read from the system (`batocera.arch`, `recalbox.arch`, `HW_DEVICE`, `LIBREELEC_DEVICE` or `LIBREELEC_PROJECT`, `knulli.arch`, `COREELEC_DEVICE`, the Pi model in `/proc/cpuinfo` where `/opt/retropie` exists) and applied when no `--target` is given, from a pack alone too when it carries the core list per board. On a computer, the board a Batocera or KNULLI card names on its boot partition (`boot/batocera.board`, `boot/knulli.board`) is applied the same way, in line mode and on the full screen. The card names its image (`anbernic-rg35xx-plus`, `x86-64-v3`), which the target list maps to its board (`h700`, `zen3`) |
| `--every-board` | Install the files of every board instead of the one the system names, for a card that moves between devices |
| `--installed-cores` | Keep only what the cores already installed read (RetroArch, Lakka, RetroPie). See [Installed cores](#installed-cores) |
| `--cores-dir PATH` | The folder RetroArch loads its cores from, for `--installed-cores` when it is not found. Implies `--installed-cores`. A folder that does not exist or cannot be opened is refused with the reason (code 1) |
From f55e473183fa39f84d37e53f092f0f9b1853fac0 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 6 Nov 2026 12:55:13 +0100
Subject: [PATCH 83/83] chore: one clause per sentence in a comment
---
scripts/scraper/targets/emuelec_targets_scraper.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/scraper/targets/emuelec_targets_scraper.py b/scripts/scraper/targets/emuelec_targets_scraper.py
index 3991c68c2..aa1faf6c1 100644
--- a/scripts/scraper/targets/emuelec_targets_scraper.py
+++ b/scripts/scraper/targets/emuelec_targets_scraper.py
@@ -325,7 +325,7 @@ PROVIDERS: dict[str, tuple[Install, ...]] = {
"ikemen-go": (_sa("ikemen-go", 'cp "$PKG_BUILD/bin/Ikemen_Go_"* "$INSTALL/usr/bin/Ikemen_Go"',
"ikemen"),),
"jzintv": (_sa("jzintv", "cp bin/jzintv ${INSTALL}/usr/bin", "jzintv"),),
- # The metapackage's dependencies (line 10); mupen64plus itself comes from
+ # The metapackage's dependencies (line 10). mupen64plus itself comes from
# mupen64plussa-ui-console's makeinstall_target.
"mupen64plussa": (
_sa("mupen64plussa", 'PKG_DEPENDS_TARGET="toolchain mupen64plussa-core '
]