33 Commits

Author SHA1 Message Date
Abdessamad Derraz
caf6285a04 fix: skip entries without md5 in batocera and retrobat exports 2026-03-30 17:46:48 +02:00
Abdessamad Derraz
529cb8a915 fix: recalbox paths from scrape, batocera md5 fallback from scrape 2026-03-30 17:35:39 +02:00
Abdessamad Derraz
1146fdf177 fix: rewrite emudeck exporter to match exact checkBIOS.sh format 2026-03-30 17:21:56 +02:00
Abdessamad Derraz
4fbb3571f8 fix: exporters use _dest fallback, merge colliding systems, per-platform subdirs 2026-03-30 17:15:44 +02:00
Abdessamad Derraz
0be68edad0 feat: add exporters for lakka, retropie, emudeck, retrodeck, romm 2026-03-30 17:07:08 +02:00
Abdessamad Derraz
1ffc4f89ca refactor: registry merge is fully flexible, no hardcoded lists 2026-03-30 16:38:13 +02:00
Abdessamad Derraz
f1ebfff5bd refactor: registry merge uses exclusion list instead of hardcoded fields 2026-03-30 16:36:40 +02:00
Abdessamad Derraz
425ea064ae fix: scrapers merge into existing YAML instead of overwriting 2026-03-30 16:31:40 +02:00
Abdessamad Derraz
6818a18a42 feat: load_platform_config merges all metadata from registry 2026-03-30 16:24:40 +02:00
Abdessamad Derraz
c11de6dba6 fix: restore retroarch.yml fields lost by scraper regeneration 2026-03-30 16:22:16 +02:00
Abdessamad Derraz
c4f3192020 fix: system.dat rom quoting, native_ids, acronym display names 2026-03-30 16:17:50 +02:00
Abdessamad Derraz
e2d0510f4e fix: exporters match exact native formats with display names 2026-03-30 16:09:02 +02:00
Abdessamad Derraz
74269bab84 fix: rewrite exporters to match exact native formats 2026-03-30 15:49:33 +02:00
Abdessamad Derraz
1e6b499602 feat: add batocera, recalbox, retrobat native exporters 2026-03-30 15:31:44 +02:00
Abdessamad Derraz
9b785ec785 feat: add missing laseractive sega pac bios files
v1.05 japan and v1.01 japan from archive.org.
v1.04 us variant alias for pioneer-named file.
resolves retrobat laseractive missing files.
2026-03-30 15:16:23 +02:00
Abdessamad Derraz
d415777f2c feat: add PS3UPDAT.PUP to rpcs3 profile
storage: large_file, validated via SCEUF magic + HMAC-SHA1
per entry (PUP.cpp:23-77). also adds missing standard fields
(cores, core_classification, upstream), removes non-standard
firmware_file/validation/firmware_version fields.
2026-03-30 15:06:51 +02:00
Abdessamad Derraz
eafabd20f3 refactor: skip writing generated files when content unchanged
write_if_changed in common.py compares content after stripping
timestamps (generated_at, Auto-generated on, Generated on).
applied to generate_db, generate_readme, generate_site.
eliminates timestamp-only diffs in database.json, README.md,
mkdocs.yml, and 423 docs pages.
2026-03-30 14:33:44 +02:00
Abdessamad Derraz
2aca4927c0 chore: regenerate database, readme, manifests, site 2026-03-30 14:19:00 +02:00
Abdessamad Derraz
17777f315b feat: agnostic bios mode for filename-agnostic emulators
bios_mode: agnostic (profile) and agnostic: true (file) for
emulators that accept any valid BIOS without specific filename.
find_undeclared_files skips agnostic entries, pack extras scan
includes all matching DB files by path prefix + size criteria,
resolve_local_file has agnostic fallback with rename README.
applied to pcsx2, lrps2 (bios_mode), melonds dsi_nand (file).
2026-03-30 14:18:54 +02:00
Abdessamad Derraz
692484d32d refactor: remove false aliases from pcsx2 and melonds profiles
aliases must be same-SHA1 alternative names, not distinct files.
pcsx2: 164 different BIOS dumps are separate DB entries, not aliases.
melonds: 6 regional NAND dumps are separate DB entries, not aliases.
also cleans pcsx2 non-standard fields, fixes display_name.
2026-03-30 12:37:32 +02:00
Abdessamad Derraz
a8430940f9 feat: add regional nand aliases to melonds profile
dsi_nand.bin aliases: DSi_Nand_USA/EUR/JPN/AUS/CHN/KOR.bin
for repo resolution. Code loads a single configurable path
(libretro.cpp:836, EmuInstance.cpp:1036-1050), validates
nocash footer (DSi_NAND.cpp:42-111). size + storage added.
2026-03-30 12:20:26 +02:00
Abdessamad Derraz
1f073f521d fix: preserve batocera version when github fetch fails 2026-03-30 11:55:57 +02:00
Abdessamad Derraz
903c49edcf feat: add tests for registry merge, all_libretro expansion, hash fallback, system normalization 2026-03-30 11:33:59 +02:00
Abdessamad Derraz
d3a2224dd2 chore: regenerate database, readme, manifests, site 2026-03-30 09:42:39 +02:00
Abdessamad Derraz
f898f26847 chore: regenerate retrobat.yml with corrected system slugs 2026-03-30 09:11:00 +02:00
Abdessamad Derraz
2712307420 feat: add tandy vis bios root set to mame profiles
vis.zip (p513bk0b.bin + p513bk1b.bin) from src/mame/trs/vis.cpp.
Driver added in MAME 0.180, not present in older cores.
2026-03-30 09:09:58 +02:00
Abdessamad Derraz
54022e9db1 feat: hash-based matching for cross-reference
expand_platform_declared_names resolves platform file MD5s
through the database to recover canonical names and aliases,
eliminating false positive undeclared files when a platform
renames a file (e.g. Batocera ROM1 vs gsplus ROM).
2026-03-30 08:25:54 +02:00
Abdessamad Derraz
4db9e4350c fix: add missing system slugs to batocera and retrobat scrapers 2026-03-30 07:58:46 +02:00
Abdessamad Derraz
6864ce6584 feat: diff hash fallback detects platform renames 2026-03-30 07:53:59 +02:00
Abdessamad Derraz
12196b6445 feat: add 55 missing cores across 6 platform registries 2026-03-30 07:17:57 +02:00
Abdessamad Derraz
7551e41a7b feat: load_platform_config merges cores from registry 2026-03-30 07:13:15 +02:00
Abdessamad Derraz
7b484605d4 feat: add 47 missing cores to batocera platform config 2026-03-30 07:09:52 +02:00
Abdessamad Derraz
b587381f05 feat: resolve_platform_cores expands all_libretro in list 2026-03-30 07:06:32 +02:00
47 changed files with 20222 additions and 2727 deletions

View File

@@ -2,7 +2,7 @@
Complete BIOS and firmware packs for Batocera, BizHawk, EmuDeck, Lakka, Recalbox, RetroArch, RetroBat, RetroDECK, RetroPie, and RomM.
**7,244** verified files across **387** systems, ready to extract into your emulator's BIOS directory.
**7,239** verified files across **396** systems, ready to extract into your emulator's BIOS directory.
## Quick Install
@@ -27,14 +27,14 @@ Pick your platform, download the ZIP, extract to the BIOS path.
| Platform | BIOS files | Extract to | Download |
|----------|-----------|-----------|----------|
| Batocera | 359 | `/userdata/bios/` | [Download](../../releases/latest) |
| Batocera | 362 | `/userdata/bios/` | [Download](../../releases/latest) |
| BizHawk | 118 | `Firmware/` | [Download](../../releases/latest) |
| EmuDeck | 161 | `Emulation/bios/` | [Download](../../releases/latest) |
| Lakka | 448 | `system/` | [Download](../../releases/latest) |
| Recalbox | 346 | `/recalbox/share/bios/` | [Download](../../releases/latest) |
| RetroArch | 448 | `system/` | [Download](../../releases/latest) |
| RetroBat | 331 | `bios/` | [Download](../../releases/latest) |
| RetroDECK | 2007 | `~/retrodeck/bios/` | [Download](../../releases/latest) |
| RetroBat | 339 | `bios/` | [Download](../../releases/latest) |
| RetroDECK | 2006 | `~/retrodeck/bios/` | [Download](../../releases/latest) |
| RetroPie | 448 | `BIOS/` | [Download](../../releases/latest) |
| RomM | 374 | `bios/{platform_slug}/` | [Download](../../releases/latest) |
@@ -44,14 +44,14 @@ BIOS, firmware, and system files for consoles from Atari to PlayStation 3.
Each file is checked against the emulator's source code to match what the code actually loads at runtime.
- **10 platforms** supported with platform-specific verification
- **328 emulators** profiled from source (RetroArch cores + standalone)
- **387 systems** covered (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
- **7,244 files** verified with MD5, SHA1, CRC32 checksums
- **9266 MB** total collection size
- **329 emulators** profiled from source (RetroArch cores + standalone)
- **396 systems** covered (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
- **7,239 files** verified with MD5, SHA1, CRC32 checksums
- **8144 MB** total collection size
## Supported systems
NES, SNES, Nintendo 64, GameCube, Wii, Game Boy, Game Boy Advance, Nintendo DS, Nintendo 3DS, Switch, PlayStation, PlayStation 2, PlayStation 3, PSP, PS Vita, Mega Drive, Saturn, Dreamcast, Game Gear, Master System, Neo Geo, Atari 2600, Atari 7800, Atari Lynx, Atari ST, MSX, PC Engine, TurboGrafx-16, ColecoVision, Intellivision, Commodore 64, Amiga, ZX Spectrum, Arcade (MAME), and 353+ more.
NES, SNES, Nintendo 64, GameCube, Wii, Game Boy, Game Boy Advance, Nintendo DS, Nintendo 3DS, Switch, PlayStation, PlayStation 2, PlayStation 3, PSP, PS Vita, Mega Drive, Saturn, Dreamcast, Game Gear, Master System, Neo Geo, Atari 2600, Atari 7800, Atari Lynx, Atari ST, MSX, PC Engine, TurboGrafx-16, ColecoVision, Intellivision, Commodore 64, Amiga, ZX Spectrum, Arcade (MAME), and 362+ more.
Full list with per-file details: **[https://abdess.github.io/retrobios/](https://abdess.github.io/retrobios/)**
@@ -59,15 +59,15 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
| Platform | Coverage | Verified | Untested | Missing |
|----------|----------|----------|----------|---------|
| Batocera | 359/359 (100.0%) | 354 | 5 | 0 |
| Batocera | 356/362 (98.3%) | 349 | 7 | 6 |
| BizHawk | 118/118 (100.0%) | 118 | 0 | 0 |
| EmuDeck | 161/161 (100.0%) | 161 | 0 | 0 |
| Lakka | 443/448 (98.9%) | 443 | 0 | 5 |
| Recalbox | 276/346 (79.8%) | 273 | 3 | 70 |
| RetroArch | 443/448 (98.9%) | 443 | 0 | 5 |
| RetroBat | 330/331 (99.7%) | 326 | 4 | 1 |
| RetroDECK | 1958/2007 (97.6%) | 1932 | 26 | 49 |
| RetroPie | 443/448 (98.9%) | 443 | 0 | 5 |
| Lakka | 442/448 (98.7%) | 442 | 0 | 6 |
| Recalbox | 277/346 (80.1%) | 274 | 3 | 69 |
| RetroArch | 442/448 (98.7%) | 442 | 0 | 6 |
| RetroBat | 337/339 (99.4%) | 333 | 4 | 2 |
| RetroDECK | 1960/2006 (97.7%) | 1934 | 26 | 46 |
| RetroPie | 442/448 (98.7%) | 442 | 0 | 6 |
| RomM | 372/374 (99.5%) | 372 | 0 | 2 |
## Build your own pack
@@ -104,7 +104,7 @@ The [documentation site](https://abdess.github.io/retrobios/) provides:
- **Per-emulator profiles** with source code references for every file
- **Per-system pages** showing which emulators and platforms cover each console
- **Gap analysis** identifying missing files and undeclared core requirements
- **Cross-reference** mapping files across 10 platforms and 328 emulators
- **Cross-reference** mapping files across 10 platforms and 329 emulators
## How it works
@@ -130,4 +130,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
This repository provides BIOS files for personal backup and archival purposes.
*Auto-generated on 2026-03-29T21:00:40Z*
*Auto-generated on 2026-03-30T12:09:51Z*

View File

@@ -1,7 +1,7 @@
{
"generated_at": "2026-03-30T04:10:12Z",
"total_files": 7239,
"total_size": 8539795099,
"generated_at": "2026-03-30T13:15:58Z",
"total_files": 7241,
"total_size": 8540057243,
"files": {
"520d3d1b5897800af47f92efd2444a26b7a7dead": {
"path": "bios/3DO Company/3DO/3do_arcade_saot.bin",
@@ -40843,16 +40843,6 @@
"crc32": "11647ca5",
"adler32": "1817f6f4"
},
"26237b333db4a4c6770297fa5e655ea95840d5d9": {
"path": "bios/Pioneer/LaserActive/Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin",
"name": "Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin",
"size": 131072,
"sha1": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"md5": "a5a2f9aae57d464bc66b80ee79c3da6e",
"sha256": "dca942d977217f703d8d1c6eb1aeb6b32c78ecc421486bbb46c459d385161c94",
"crc32": "00eedb3a",
"adler32": "94a45a21"
},
"aa811861f8874775075bd3f53008c8aaf59b07db": {
"path": "bios/Pioneer/LaserActive/Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin",
"name": "Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin",
@@ -40863,6 +40853,16 @@
"crc32": "50cd3d23",
"adler32": "72a13133"
},
"26237b333db4a4c6770297fa5e655ea95840d5d9": {
"path": "bios/Pioneer/LaserActive/Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin",
"name": "Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin",
"size": 131072,
"sha1": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"md5": "a5a2f9aae57d464bc66b80ee79c3da6e",
"sha256": "dca942d977217f703d8d1c6eb1aeb6b32c78ecc421486bbb46c459d385161c94",
"crc32": "00eedb3a",
"adler32": "94a45a21"
},
"6973e2593e66fd21627fedccec98d4a364afaaff": {
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
"name": "[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
@@ -40883,6 +40883,26 @@
"crc32": "01223dd5",
"adler32": "74e98625"
},
"bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3": {
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PAC-S1 (Japan) (v1.01).bin",
"name": "[BIOS] LaserActive PAC-S1 (Japan) (v1.01).bin",
"size": 131072,
"sha1": "bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3",
"md5": "219dc2aa7cb8d1ad5142c86d50c2ffa5",
"sha256": "3300e3771b468b41818b90c2358ff288da69bada92b8247acd793a437b30731c",
"crc32": "24ad336e",
"adler32": "6993a1dd"
},
"f7101b40cae0484a0f43f3bbee2d55033ff1e3ec": {
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin",
"name": "[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin",
"size": 131072,
"sha1": "f7101b40cae0484a0f43f3bbee2d55033ff1e3ec",
"md5": "515636778430c8e01027234c38c4ddf8",
"sha256": "369c1e699abbaecd231a3ab7b98443d28097366ff3cdd978698417195d54ca3c",
"crc32": "1493522c",
"adler32": "9e972082"
},
"c1b9202cbe072db12114b223a9ba5374b30718fb": {
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
"name": "[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
@@ -76480,10 +76500,12 @@
"c500ff71236068e0dc0d0603d265ae76": "5130243429b40b01a14e1304d0394b8459a6fbae",
"f1071cdb0b6b10dde94d3bc8a6146387": "a6120aed50831c9c0d95dbdf707820f601d9452e",
"279008e4a0db2dc5f1c048853b033828": "54b8d2c1317628de51a85fc1c424423a986775e4",
"a5a2f9aae57d464bc66b80ee79c3da6e": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"0e7393cd0951d6dde818fcd4cd819466": "aa811861f8874775075bd3f53008c8aaf59b07db",
"a5a2f9aae57d464bc66b80ee79c3da6e": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"f69f173b251d8bf7649b10a9167a10bf": "6973e2593e66fd21627fedccec98d4a364afaaff",
"f0fb8a4605ac7eefbafd4f2d5a793cc8": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
"219dc2aa7cb8d1ad5142c86d50c2ffa5": "bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3",
"515636778430c8e01027234c38c4ddf8": "f7101b40cae0484a0f43f3bbee2d55033ff1e3ec",
"761fea207d0eafd4cfd78da7c44cac88": "c1b9202cbe072db12114b223a9ba5374b30718fb",
"69489153dde910a69d5ae6de5dd65323": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
"3fd0d13282b031f4c017cd6bf6597183": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
@@ -91151,18 +91173,24 @@
"jopac.bin": [
"54b8d2c1317628de51a85fc1c424423a986775e4"
],
"Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin": [
"26237b333db4a4c6770297fa5e655ea95840d5d9"
],
"Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin": [
"aa811861f8874775075bd3f53008c8aaf59b07db"
],
"Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin": [
"26237b333db4a4c6770297fa5e655ea95840d5d9"
],
"[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin": [
"6973e2593e66fd21627fedccec98d4a364afaaff"
],
"[BIOS] LaserActive PAC-N10 (US) (v1.02).bin": [
"f7412aa822d70a55b2ff3d7095137263dc54f6b6"
],
"[BIOS] LaserActive PAC-S1 (Japan) (v1.01).bin": [
"bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3"
],
"[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin": [
"f7101b40cae0484a0f43f3bbee2d55033ff1e3ec"
],
"[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin": [
"c1b9202cbe072db12114b223a9ba5374b30718fb"
],
@@ -101218,6 +101246,9 @@
"g7400.bin": [
"5130243429b40b01a14e1304d0394b8459a6fbae"
],
"[BIOS] LaserActive PAC-S10 (US) (v1.04).bin": [
"aa811861f8874775075bd3f53008c8aaf59b07db"
],
"Battle 1.mid": [
"dc5cc32fafa442b09ab2d814ed32074d02597234"
],
@@ -102371,6 +102402,9 @@
"ts1500.zxpand.ovl": [
"0334b35f164089df7b2a82d46fa0ec6e43fafa90"
],
"tvc64.zip": [
"abf119cf947ea32defd08b29a8a25d75f6bd4987"
],
"TVC22_D7.64K": [
"abf119cf947ea32defd08b29a8a25d75f6bd4987"
],
@@ -102413,6 +102447,24 @@
"EXOS21.ROM": [
"55315b20fecb4441a07ee4bc5dc7153f396e0a2e"
],
"bk0010.zip": [
"4e83a94ae5155bbea14d7331a5a8db82457bd5ae",
"34fa37599f2f9eb607390ef2458a3c22d87f09a9",
"f087af69044432a1ef2431a72ac06946e32f2dd3",
"7e9a30e38d7b78981999821640a68a201bb6df01"
],
"monit10.rom": [
"4e83a94ae5155bbea14d7331a5a8db82457bd5ae"
],
"bas11m_1.rom": [
"34fa37599f2f9eb607390ef2458a3c22d87f09a9"
],
"b11m_ext.rom": [
"f087af69044432a1ef2431a72ac06946e32f2dd3"
],
"b11m_bos.rom": [
"7e9a30e38d7b78981999821640a68a201bb6df01"
],
"sony-playstation:239665b1a3dade1b5a52c06338011044": [
"343883a7b555646da8cee54aadd2795b6e7dd070"
],
@@ -103185,27 +103237,15 @@
"Kickstart v3.0 rev 39.106 (1992)(Commodore)(A4000)[!].rom": [
"f0b4e9e29e12218c2d5bd7020e4e785297d91fd7"
],
"monit10.rom": [
"4e83a94ae5155bbea14d7331a5a8db82457bd5ae"
],
"focal10.rom": [
"6386e58bc1bba5e76baec9e8a1ca4b99dc3c573f"
],
"disk_327.rom": [
"28eefbb63047b26e4aec104aeeca74e2f9d0276c"
],
"b11m_bos.rom": [
"7e9a30e38d7b78981999821640a68a201bb6df01"
],
"b11m_ext.rom": [
"f087af69044432a1ef2431a72ac06946e32f2dd3"
],
"bas11m_0.rom": [
"9d76f3eefd64e032c763fa1ebf9cd3d9bd22317a"
],
"bas11m_1.rom": [
"34fa37599f2f9eb607390ef2458a3c22d87f09a9"
],
"terak.rom": [
"273a9933b68a290c5aedcd6d69faa7b1d22c0344"
],
@@ -107481,10 +107521,12 @@
"e20a9f41": "5130243429b40b01a14e1304d0394b8459a6fbae",
"a318e8d6": "a6120aed50831c9c0d95dbdf707820f601d9452e",
"11647ca5": "54b8d2c1317628de51a85fc1c424423a986775e4",
"00eedb3a": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"50cd3d23": "aa811861f8874775075bd3f53008c8aaf59b07db",
"00eedb3a": "26237b333db4a4c6770297fa5e655ea95840d5d9",
"a8cb694c": "6973e2593e66fd21627fedccec98d4a364afaaff",
"01223dd5": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
"24ad336e": "bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3",
"1493522c": "f7101b40cae0484a0f43f3bbee2d55033ff1e3ec",
"76116a02": "c1b9202cbe072db12114b223a9ba5374b30718fb",
"4e70e3c0": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
"92bcc762": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
@@ -124501,6 +124543,10 @@
"9451a1a09d8f75944dbd6f91193fc360f1de80ac",
"03bbb386cf530e804363acdfc1d13e64cf28af2e",
"55315b20fecb4441a07ee4bc5dc7153f396e0a2e",
"4e83a94ae5155bbea14d7331a5a8db82457bd5ae",
"34fa37599f2f9eb607390ef2458a3c22d87f09a9",
"f087af69044432a1ef2431a72ac06946e32f2dd3",
"7e9a30e38d7b78981999821640a68a201bb6df01",
"343883a7b555646da8cee54aadd2795b6e7dd070",
"e38466a4ba8005fba7e9e3c7b9efeba7205bee3f",
"ffa7f9a7fb19d773a0c3985a541c8e5623d2c30d",
@@ -124623,13 +124669,9 @@
"4192c505d130f446b2ada6bdc91dae730acafb4c",
"16df8b5fd524c5a1c7584b2457ac15aff9e3ad6d",
"f0b4e9e29e12218c2d5bd7020e4e785297d91fd7",
"4e83a94ae5155bbea14d7331a5a8db82457bd5ae",
"6386e58bc1bba5e76baec9e8a1ca4b99dc3c573f",
"28eefbb63047b26e4aec104aeeca74e2f9d0276c",
"7e9a30e38d7b78981999821640a68a201bb6df01",
"f087af69044432a1ef2431a72ac06946e32f2dd3",
"9d76f3eefd64e032c763fa1ebf9cd3d9bd22317a",
"34fa37599f2f9eb607390ef2458a3c22d87f09a9",
"273a9933b68a290c5aedcd6d69faa7b1d22c0344",
"4891d739a8a8b67923681bad4fb67edab2e90e50",
"6e89d1227581c76441a53d605f9e324185f1da33",
@@ -124956,6 +124998,9 @@
"roms/win486/ALI1429G.AMW": [
"72c60172fb1ba77c9b24b06b7755f0a16f0b3a13"
],
".variants/[BIOS] LaserActive PAC-S10 (US) (v1.04).bin": [
"aa811861f8874775075bd3f53008c8aaf59b07db"
],
"rtp/2003/Battle/Arrow.png": [
"7aa8d4c377efcea1c9fad01924da1ba7b8575e1e"
],

View File

@@ -5,6 +5,7 @@
emulator: LRPS2
type: libretro
core_classification: community_fork
bios_mode: agnostic
source: "https://github.com/libretro/ps2"
upstream: "https://github.com/PCSX2/pcsx2"
profiled_date: "2026-03-25"

View File

@@ -71,12 +71,13 @@ systems:
- philips-vg5k
- ti99
- tutor
- tandy-vis
- trs80
- vgmplay
notes: |
Rolling release tracking mamedev/mame upstream (currently 0.286).
80 BIOS root sets + 27 system ROM sets + 3 device ROMs (apple2gs, astrocade, adam, advision, apfm1000, beena, camplynx, casloopy, crvision, fm7, gamate, gamecom, gamepock, gmaster, gp32, laser310, pcw, pegasus, pv2000, rx78, segaai, socrates, ti99_4a, trs80, tutor, vg5k, vsmile). romload.cpp
81 BIOS root sets + 28 system ROM sets + 3 device ROMs (apple2gs, astrocade, adam, advision, apfm1000, beena, camplynx, casloopy, crvision, fm7, gamate, gamecom, gamepock, gmaster, gp32, laser310, pcw, pegasus, pv2000, rx78, segaai, socrates, ti99_4a, trs80, tutor, vg5k, vis, vsmile). romload.cpp
unmodified. No hiscore support.
Paths under system_dir/mame/ (artwork, cheat, hash, ini, plugins,
samples, crosshair). ROM search: content_dir + system_dir/mame/bios +
@@ -1311,6 +1312,24 @@ files:
size: 8192
crc32: a64d450a
# Tandy VIS (Video Information System)
# vis.cpp: vis (parent, WORKING). Tandy/Memorex MD-2500 (1992).
# CD-ROM-based multimedia system built on modified 286 PC hardware.
- name: vis.zip
required: true
category: bios_zip
system: tandy-vis
source_ref: "src/mame/trs/vis.cpp:1062-1066"
contents:
- name: p513bk0b.bin
description: "BIOS bank 0"
size: 524288
crc32: 364e3f74
- name: p513bk1b.bin
description: "BIOS bank 1"
size: 524288
crc32: e18239c4
# Tandy TRS-80 family
# Model I (trs80.cpp): trs80 (Level I, parent, WORKING), trs80l2 (Level II, parent),
# eg3003 (EACA Video Genie, parent), sys80/sys80p (clones), ht1080z/ht1080z2/ht108064 (clones).

View File

@@ -42,6 +42,7 @@ systems:
- supracan
- ti99
- interton-vc4000
- tandy-vis
- trs80
notes: |
@@ -1660,6 +1661,24 @@ files:
size: 16
crc32: 0ba78597
# Tandy VIS (Video Information System)
# vis.cpp: vis (parent, WORKING). Tandy/Memorex MD-2500 (1992).
# CD-ROM-based multimedia system built on modified 286 PC hardware.
- name: vis.zip
required: true
category: bios_zip
system: tandy-vis
source_ref: "src/mame/trs/vis.cpp:1062-1066"
contents:
- name: p513bk0b.bin
description: "BIOS bank 0"
size: 524288
crc32: 364e3f74
- name: p513bk1b.bin
description: "BIOS bank 1"
size: 524288
crc32: e18239c4
# Tandy TRS-80 family
# Model I (trs80.cpp): trs80 (Level I, parent, WORKING), trs80l2 (Level II, parent),
# eg3003 (EACA Video Genie, parent), sys80/sys80p (clones), ht1080z/ht1080z2/ht108064 (clones).

View File

@@ -77,11 +77,14 @@ files:
source_ref: "src/SPI.cpp:197-211, src/frontend/Util_ROM.cpp:201-217"
- name: dsi_nand.bin
agnostic: true
system: nintendo-dsi
description: "DSi NAND dump"
required: true
source_ref: "src/frontend/Util_ROM.cpp:224-235, src/DSi_NAND.cpp"
note: "Uses AES keys from ARM7i BIOS offset 0x8308"
size: 251658304
storage: large_file
source_ref: "src/frontend/Util_ROM.cpp:224-235, src/DSi_NAND.cpp:58-97"
note: "Any regional dump works. Nocash footer required (DSi eMMC CID/CPU at EOF-0x40 or 0xFF800). AES keys derived from ARM7i BIOS offset 0x8308."
- name: dsi_sd_card.bin
system: nintendo-dsi

View File

@@ -1,219 +1,74 @@
# PCSX2 emulator BIOS profile
# Generated from source analysis of https://github.com/PCSX2/pcsx2
# Commit analyzed: HEAD as of 2026-03-17
emulator: PCSX2
type: standalone
core_classification: official_port
bios_mode: agnostic
source: "https://github.com/PCSX2/pcsx2"
logo: "https://raw.githubusercontent.com/PCSX2/pcsx2/master/pcsx2-qt/resources/icons/PCSX2logo.svg"
profiled_date: "2026-03-18"
upstream: "https://github.com/PCSX2/pcsx2"
cores:
- pcsx2
profiled_date: "2026-03-30"
core_version: "Git"
display_name: "Sony - PlayStation 2 (LRPS2)"
display_name: "Sony - PlayStation 2 (PCSX2)"
systems: [sony-playstation-2]
bios_directory: "bios/"
bios_detection: "romdir" # scans romdir structure inside binary, looks for RESET/ROMVER/EXTINFO entries
bios_selection: "automatic" # scans all files in bios dir matching 4-8 MB size, validates via romdir
validation:
method: "romdir_parse"
min_size: 4194304 # 4 MB (MIN_BIOS_SIZE = 4 * _1mb)
max_size: 8388608 # 8 MB (MAX_BIOS_SIZE = 8 * _1mb)
required_entries: ["RESET", "ROMVER"]
optional_entries: ["EXTINFO"]
note: "Any file in bios/ between 4-8 MB with valid romdir containing RESET+ROMVER is accepted"
regions:
J: {zone: "Japan", id: 0}
A: {zone: "USA", id: 1}
E: {zone: "Europe", id: 2}
H: {zone: "Asia", id: 4}
C: {zone: "China", id: 6}
T: {zone: "T10K/COH-H", id: 8}
X: {zone: "Test", id: 9}
P: {zone: "Free", id: 10}
notes: |
Filename-agnostic BIOS detection. Scans bios/ for any file between 4-8 MB
with valid romdir structure (RESET + ROMVER entries). No hash validation.
Companion files (.rom1, .rom2, .nvm, .mec) derive paths from selected BIOS.
ROM1 (DVD player) and ROM2 (Chinese extension) silently skipped if missing.
NVM and MEC auto-created with defaults if missing.
files:
# -- Main BIOS binary (required) --
- name: "<user-selected>.bin"
pattern: "*"
- name: ps2-0230a-20080220.bin
required: true
size_range: "4MB-8MB"
source_ref: "pcsx2/ps2/BiosTools.cpp:258-282"
note: >
PCSX2 does not mandate a specific filename. It scans the entire bios/ directory
for any file between 4-8 MB that contains a valid romdir structure (RESET + ROMVER entries).
Common filenames follow the SCPH-XXXXX_BIOS_VYYY_REGION_ZZZ.BIN convention but this is
not enforced. The file is loaded into the 4 MB ROM region of EE memory.
min_size: 4194304
max_size: 8388608
validation: [size]
source_ref: "pcsx2/ps2/BiosTools.cpp:258-362"
note: "Accepts any file 4-8 MB with valid romdir (RESET + ROMVER). Naming convention ps2-VVVVr-YYYYMMDD.bin (version, region, date)."
# -- ROM1 (optional, DVD player) --
- name: "<biosname>.rom1"
pattern: "{biosname}.rom1 or {biosbase}.rom1"
- name: rom1.bin
required: false
max_size: 4194304 # 4 MB (Ps2MemSize::Rom1)
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241"
note: >
DVD player ROM. Loaded via LoadExtraRom("rom1"). PCSX2 tries two naming patterns:
1) Full bios path + ".rom1" appended (e.g. scph70004.bin.rom1)
2) Bios path with extension replaced (e.g. scph70004.rom1)
Mapped to EE memory at ROM1 region (0x1FC00000 + 4MB offset).
Contains DVD player and region detection data (DVDID).
max_size: 4194304
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241,366"
note: "DVD player ROM. Tries {biospath}.rom1 then {biosbase}.rom1. Silently skipped if missing."
# -- ROM2 (optional, Chinese ROM extension) --
- name: "<biosname>.rom2"
pattern: "{biosname}.rom2 or {biosbase}.rom2"
- name: ROM2.BIN
required: false
max_size: 4194304 # 4 MB (Ps2MemSize::Rom2)
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241"
note: >
Chinese ROM extension. Loaded via LoadExtraRom("rom2"). Same naming convention
as rom1: tries appended extension first, then replaced extension.
Only present on Chinese region consoles.
max_size: 4194304
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241,367"
note: "Chinese ROM extension. Same naming convention as rom1. Only present on Chinese region consoles."
# -- NVM / NVRAM (optional, auto-created) --
- name: "<biosname>.nvm"
pattern: "{biosbase}.nvm"
- name: EROM.BIN
required: false
source_ref: "pcsx2/ps2/BiosTools.cpp"
note: "Extended ROM. Present in some BIOS dumps but not loaded by PCSX2 code via LoadExtraRom."
path: null
- name: eeprom.dat
required: false
hle_fallback: true
size: 1024 # NVRAM_SIZE = 1024 bytes
source_ref: "pcsx2/CDVD/CDVD.cpp:160-238"
note: >
EEPROM / NVRAM data. Path derived from BiosPath with extension replaced to ".nvm"
(cdvdGetNVRAMPath). Contains console configuration: language, timezone, iLink ID,
region parameters, OSD settings. Auto-created with defaults if missing.
Two NVM layouts exist: v0.00+ (biosVer 0x000) and v1.70+ (biosVer 0x146).
# -- MEC file (optional, auto-created) --
- name: "<biosname>.mec"
pattern: "{biosbase}.mec"
required: false
hle_fallback: true
size: 4 # u32 s_mecha_version
source_ref: "pcsx2/CDVD/CDVD.cpp:190-204"
note: >
Mechacon (mechanism controller) version file. 4 bytes containing the mecha version
as a u32 value. Auto-created with DEFAULT_MECHA_VERSION (0x00020603) if missing.
Path derived from BiosPath with extension replaced to ".mec".
# -- IRX override (optional, advanced) --
- name: "<custom>.irx"
pattern: "*.irx"
required: false
source_ref: "pcsx2/ps2/BiosTools.cpp:243-256,384-385"
note: >
Custom IOP Reboot eXecutable module. Loaded into ROM at offset 0x3C0000 if
EmuConfig.CurrentIRX is set (path length > 3). Injected at IOP reset (PC=0x1630).
Used for debugging/development, not needed for normal operation.
# -- DEV9 EEPROM (optional, network adapter) --
- name: "eeprom.dat"
required: false
hle_fallback: true
size: 64 # 64 bytes, mmap'd
size: 64
source_ref: "pcsx2/DEV9/DEV9.cpp:110-160"
note: >
DEV9 (network adapter / HDD expansion bay) EEPROM data. Fixed filename "eeprom.dat"
opened from working directory. Contains network adapter configuration.
Falls back to built-in defaults if file not found. Only relevant when using
DEV9 features (online play, HDD).
note: "DEV9 network adapter EEPROM. Falls back to built-in defaults if missing."
common_bios_filenames:
# Japan
- "SCPH-10000_BIOS_V1_JAP_100.BIN"
- "SCPH-15000_BIOS_V3_JAP_120.BIN"
- "SCPH-30000_BIOS_V4_JAP_150.BIN"
- "SCPH-30001R_BIOS_V7_JAP_160.BIN"
- "SCPH-30004R_BIOS_V7_JAP_160.BIN"
- "SCPH-35000_BIOS_V5_JAP_160.BIN"
- "SCPH-50000_BIOS_V9_JAP_170.BIN"
- "SCPH-50004_BIOS_V9_JAP_170.BIN"
- "SCPH-70000_BIOS_V12_JAP_200.BIN"
- "SCPH-75000_BIOS_V14_JAP_220.BIN"
- "SCPH-77000_BIOS_V14_JAP_220.BIN"
- "SCPH-90000_BIOS_V18_JAP_230.BIN"
# USA
- "SCPH-30001_BIOS_V4_USA_150.BIN"
- "SCPH-39001_BIOS_V6_USA_160.BIN"
- "SCPH-50001_BIOS_V9_USA_170.BIN"
- "SCPH-50003_BIOS_V9_USA_170.BIN"
- "SCPH-70002_BIOS_V12_USA_200.BIN"
- "SCPH-70004_BIOS_V12_USA_200.BIN"
- "SCPH-70012_BIOS_V12_USA_200.BIN"
- "SCPH-75001_BIOS_V14_USA_220.BIN"
- "SCPH-77001_BIOS_V14_USA_220.BIN"
- "SCPH-90001_BIOS_V18_USA_230.BIN"
# Europe
- "SCPH-30002_BIOS_V4_EUR_150.BIN"
- "SCPH-30003_BIOS_V4_EUR_150.BIN"
- "SCPH-30004_BIOS_V4_EUR_150.BIN"
- "SCPH-39002_BIOS_V6_EUR_160.BIN"
- "SCPH-39003_BIOS_V6_EUR_160.BIN"
- "SCPH-39004_BIOS_V6_EUR_160.BIN"
- "SCPH-50002_BIOS_V9_EUR_170.BIN"
- "SCPH-50004_BIOS_V9_EUR_170.BIN"
- "SCPH-70002_BIOS_V12_EUR_200.BIN"
- "SCPH-70003_BIOS_V12_EUR_200.BIN"
- "SCPH-70004_BIOS_V12_EUR_200.BIN"
- "SCPH-70008_BIOS_V12_EUR_200.BIN"
- "SCPH-75002_BIOS_V14_EUR_220.BIN"
- "SCPH-75003_BIOS_V14_EUR_220.BIN"
- "SCPH-75004_BIOS_V14_EUR_220.BIN"
- "SCPH-77002_BIOS_V14_EUR_220.BIN"
- "SCPH-77003_BIOS_V14_EUR_220.BIN"
- "SCPH-77004_BIOS_V14_EUR_220.BIN"
- "SCPH-90002_BIOS_V18_EUR_230.BIN"
- "SCPH-90003_BIOS_V18_EUR_230.BIN"
- "SCPH-90004_BIOS_V18_EUR_230.BIN"
# Asia
- "SCPH-50009_BIOS_V9_HK_170.BIN"
- "SCPH-70005_BIOS_V12_HK_200.BIN"
- "SCPH-70006_BIOS_V12_HK_200.BIN"
- "SCPH-70008_BIOS_V12_HK_200.BIN"
# China
- "SCPH-50009_BIOS_V9_CHN_170.BIN"
- "SCPH-70006_BIOS_V12_CHN_200.BIN"
- name: GameIndex.yaml
path: pcsx2/resources/GameIndex.yaml
required: false
mode: libretro
source_ref: "pcsx2/GameDatabase.cpp:48,880"
note: "Game compatibility database. OSD warning if missing."
memory_layout:
ROM: {offset: "0x1FC00000", size: "4 MB", purpose: "Main BIOS binary"}
ROM1: {offset: "ROM + 4MB", size: "4 MB", purpose: "DVD player"}
ROM2: {offset: "ROM + 8MB", size: "4 MB", purpose: "Chinese ROM extension"}
- name: cheats_ws.zip
path: pcsx2/resources/cheats_ws.zip
required: false
mode: libretro
source_ref: "pcsx2/VMManager.cpp:340-353"
note: "Widescreen patches archive."
nvm_layout:
format_0:
applies_to: "BIOS v0.00+"
biosVer: 0x000
config0: 0x280
config1: 0x300
config2: 0x200
consoleId: 0x1C8
ilinkId: 0x1C0
modelNum: 0x1A0
regparams: 0x180
mac: 0x198
format_1:
applies_to: "BIOS v1.70+"
biosVer: 0x146
config0: 0x270
config1: 0x2B0
config2: 0x200
consoleId: 0x1F0
ilinkId: 0x1E0
modelNum: 0x1B0
regparams: 0x180
mac: 0x198
notes: |
PCSX2 is filename-agnostic for the main BIOS. Detection relies on romdir structure
parsing inside the binary itself, not on filename or extension. Any file between 4-8 MB
with a valid romdir (containing at least RESET and ROMVER entries) is accepted.
The ROMVER entry encodes: version (2+2 digits), region letter, console/devel flag,
build date (YYYYMMDD), and is used to determine the BIOS description and region.
Companion files (.nvm, .mec) are auto-created with sane defaults if missing.
ROM1/ROM2 are silently skipped if not found - only the main BIOS binary is strictly required.
PCSX2 no longer ships as a libretro core in official builds. The standalone emulator
is the primary distribution channel.
Devel console BIOSes (< ~2.3 MB) lack the OSD and are handled with NoOSD=true flag.
- name: cheats_ni.zip
path: pcsx2/resources/cheats_ni.zip
required: false
mode: libretro
source_ref: "pcsx2/VMManager.cpp:375-388"
note: "No-interlacing patches archive."

View File

@@ -1,32 +1,21 @@
# RPCS3 emulator firmware profile
# Generated from source analysis of https://github.com/RPCS3/rpcs3
# Commit analyzed: HEAD as of 2026-03-17
emulator: RPCS3
type: standalone
core_classification: official_port
source: "https://github.com/RPCS3/rpcs3"
logo: "https://raw.githubusercontent.com/RPCS3/rpcs3/master/rpcs3/rpcs3.svg"
profiled_date: "2026-03-18"
upstream: "https://github.com/RPCS3/rpcs3"
cores:
- rpcs3
profiled_date: "2026-03-30"
core_version: "0.0.35"
display_name: "RPCS3 (PS3)"
display_name: "Sony - PlayStation 3 (RPCS3)"
systems: [sony-playstation-3]
firmware_file: "PS3UPDAT.PUP"
firmware_source: "https://www.playstation.com/en-us/support/hardware/ps3/system-software/"
firmware_detection: "pup_header" # validates PUP magic bytes, HMAC-SHA1 hash per entry
firmware_install: "extracts dev_flash_* TAR packages from PUP into dev_flash/"
validation:
method: "pup_object"
magic: "SCEUF"
hash_algo: "HMAC-SHA1"
source_ref: "rpcs3/Loader/PUP.cpp:8-114"
note: "PUP file is validated by magic header, file count, HMAC-SHA1 per entry against PUP_KEY"
firmware_version:
path: "dev_flash/vsh/etc/version.txt"
source_ref: "rpcs3/util/sysinfo.cpp:686"
note: "Read at startup, displayed as 'Firmware version: X.XX'. Missing = 'Missing Firmware'"
files:
- name: PS3UPDAT.PUP
required: true
storage: large_file
source_ref: "rpcs3/Loader/PUP.cpp:23-77"
note: "PUP firmware package. Validated via SCEUF magic + HMAC-SHA1 per entry. Extracted to dev_flash/ at install time."
# dev_flash filesystem layout extracted from PUP
dev_flash:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"platform": "emudeck",
"display_name": "EmuDeck",
"version": "1.0",
"generated": "2026-03-29T14:02:36Z",
"generated": "2026-03-30T09:46:25Z",
"base_destination": "bios",
"detect": [
{
@@ -50,8 +50,8 @@
}
}
],
"total_files": 270,
"total_size": 913637720,
"total_files": 290,
"total_size": 717377323,
"files": [
{
"dest": "colecovision.rom",
@@ -473,24 +473,6 @@
"Dolphin"
]
},
{
"dest": "scph1000.bin",
"sha1": "343883a7b555646da8cee54aadd2795b6e7dd070",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1000.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph1001.bin",
"sha1": "10155d8d6e6e832d6ea66db9bc098321fb5e8ebf",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1001.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph1002a.bin",
"sha1": "20b98f3d80f11cbf5a7bfd0779b0e63760ecc62c",
@@ -500,132 +482,6 @@
"DuckStation"
]
},
{
"dest": "scph1002b.bin",
"sha1": "76cf6b1b2a7c571a6ad07f2bac0db6cd8f71e2cc",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1002b.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph1002c.bin",
"sha1": "b6a11579caef3875504fcf3831b8e3922746df2c",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1002c.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "dtlh1100.bin",
"sha1": "73107d468fc7cb1d2c5b18b269715dd889ecef06",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/dtlh1100.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph3000.bin",
"sha1": "b06f4a861f74270be819aa2a07db8d0563a7cc4e",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph3000.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph1001_v20.bin",
"sha1": "649895efd79d14790eabb362e94eb0622093dfb9",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1001_v20.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph3500.bin",
"sha1": "e38466a4ba8005fba7e9e3c7b9efeba7205bee3f",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph3500.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph1001_v21.bin",
"sha1": "ca7af30b50d9756cbd764640126c454cff658479",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1001_v21.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph5000.bin",
"sha1": "ffa7f9a7fb19d773a0c3985a541c8e5623d2c30d",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph5000.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph7000.bin",
"sha1": "77b10118d21ac7ffa9b35f9c4fd814da240eb3e9",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph7000.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph7000w.bin",
"sha1": "1b0dbdb23da9dc0776aac58d0755dc80fea20975",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph7000w.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph7001.bin",
"sha1": "14df4f6c1e367ce097c11deae21566b4fe5647a9",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph7001.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph7002.bin",
"sha1": "8d5de56a79954f29e9006929ba3fed9b6a418c1d",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph7002.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph100.bin",
"sha1": "339a48f4fcf63e10b5b867b8c93cfd40945faf6c",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph100.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph101_v44.bin",
"sha1": "7771d6e90980408f753891648685def6dd42ef6d",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph101_v44.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "scph101_v45.bin",
"sha1": "dcffe16bd90a723499ad46c641424981338d8378",
@@ -653,15 +509,6 @@
"DuckStation"
]
},
{
"dest": "scph1000r.bin",
"sha1": "7082bd57141fa0007b3adcd031f7ba23a20108a0",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/scph1000r.bin",
"cores": [
"DuckStation"
]
},
{
"dest": "ps2_scph18000.bin",
"sha1": "d7d6be084f51354bc951d8fa2d8d912aa70abc5e",
@@ -2111,6 +1958,42 @@
"MAME"
]
},
{
"dest": "astrocde.zip",
"sha1": "8641b09be090c0dc45f4ee5459fec3cc6fb9d78e",
"size": 6800,
"repo_path": "bios/Bally/Astrocade/astrocde.zip",
"cores": [
"MAME"
]
},
{
"dest": "apple2gs.zip",
"sha1": "799e2fc90d6bfd8cb74e331e04d5afd36f2f21a1",
"size": 174124,
"repo_path": "bios/Apple/Apple II/apple2gs.zip",
"cores": [
"MAME"
]
},
{
"dest": "casloopy.zip",
"sha1": "144ea9d0f20113632dde6d21c62a01c02cf7666d",
"size": 478191,
"repo_path": "bios/Casio/Loopy/casloopy.zip",
"cores": [
"MAME"
]
},
{
"dest": "pv2000.zip",
"sha1": "c18f460301177b64bbfcbedc3010e734d0803d4c",
"size": 13622,
"repo_path": "bios/Casio/PV-2000/pv2000.zip",
"cores": [
"MAME"
]
},
{
"dest": "adam.zip",
"sha1": "dc4b77cd3ac45cf448e427eff5c0a7b138fd9d81",
@@ -2219,6 +2102,303 @@
"MAME"
]
},
{
"dest": "beena.zip",
"sha1": "f63eca9a1b1e92ee1582ff5e4c0db55193f97e33",
"size": 85176,
"repo_path": "bios/Sega/Beena/beena.zip",
"cores": [
"MAME"
]
},
{
"dest": "rx78.zip",
"sha1": "b3a26e21574395a279a37922238802b349c303b7",
"size": 6397,
"repo_path": "bios/Bandai/RX-78/rx78.zip",
"cores": [
"MAME"
]
},
{
"dest": "segaai.zip",
"sha1": "39a0fec854e438f6757882604a8dc56e62e401d9",
"size": 343220,
"repo_path": "bios/Sega/AI/segaai.zip",
"cores": [
"MAME"
]
},
{
"dest": "segaai_soundbox.zip",
"sha1": "d90e0b3545e60c59c20a7fb32d0785f6c3abbf60",
"size": 47380,
"repo_path": "bios/Arcade/MAME/segaai_soundbox.zip",
"cores": [
"MAME"
]
},
{
"dest": "lynx48k.zip",
"sha1": "64947e9b7d17870839aba5d93217183d480ff897",
"size": 25078,
"repo_path": "bios/Camputers/Lynx/lynx48k.zip",
"cores": [
"MAME"
]
},
{
"dest": "lynx96k.zip",
"sha1": "df95ea702606e88b4c906a0233c8fec54c02ff01",
"size": 32888,
"repo_path": "bios/Camputers/Lynx/lynx96k.zip",
"cores": [
"MAME"
]
},
{
"dest": "lynx128k.zip",
"sha1": "5300a352007976102d61d53f1e8c48063d2f3026",
"size": 24796,
"repo_path": "bios/Camputers/Lynx/lynx128k.zip",
"cores": [
"MAME"
]
},
{
"dest": "crvision.zip",
"sha1": "87526fb12fabbcc01292dd01dc698fdc762ab7dc",
"size": 441619,
"repo_path": "bios/VTech/CreatiVision/crvision.zip",
"cores": [
"MAME"
]
},
{
"dest": "laser310.zip",
"sha1": "9fa5f366c4ec43d7c23f03f054733894bf42912f",
"size": 42630,
"repo_path": "bios/VTech/Laser 310/laser310.zip",
"cores": [
"MAME"
]
},
{
"dest": "socrates.zip",
"sha1": "6bbaa8f73027eaca2c6988ee3b9b3f3b0b29d18e",
"size": 218299,
"repo_path": "bios/VTech/Socrates/socrates.zip",
"cores": [
"MAME"
]
},
{
"dest": "vsmile.zip",
"sha1": "65e526ae3e4795a9186c53c7428d8b946170befe",
"size": 3078731,
"repo_path": "bios/VTech/V.Smile/vsmile.zip",
"cores": [
"MAME"
]
},
{
"dest": "gamate.zip",
"sha1": "e99667ea5cfe6a5eceb53faaa39cdda0cbf69c69",
"size": 5072,
"repo_path": "bios/Bit Corporation/Gamate/gamate.zip",
"cores": [
"MAME"
]
},
{
"dest": "gamepock.zip",
"sha1": "83e94c56f2fc4ab60de94021a1283cca09d65ee5",
"size": 3455,
"repo_path": "bios/Epoch/Game Pocket/gamepock.zip",
"cores": [
"MAME"
]
},
{
"dest": "gmaster.zip",
"sha1": "a89263689f19e046dab6dadea24c5d07270548a6",
"size": 1686,
"repo_path": "bios/Hartung/Game Master/gmaster.zip",
"cores": [
"MAME"
]
},
{
"dest": "gamecom.zip",
"sha1": "e0f5e2eced447abf9948342b2facc40179f0f527",
"size": 145138,
"repo_path": "bios/Tiger/Game.com/gamecom.zip",
"cores": [
"MAME"
]
},
{
"dest": "gp32.zip",
"sha1": "35def9830e797fb0788740b5da0a7202933554df",
"size": 1378301,
"repo_path": "bios/GamePark/GP32/gp32.zip",
"cores": [
"MAME"
]
},
{
"dest": "fm7.zip",
"sha1": "1c29ba16151255cd916f49ea25570956f1353b71",
"size": 104276,
"repo_path": "bios/Fujitsu/FM Towns/fm7.zip",
"cores": [
"MAME"
]
},
{
"dest": "fm77av.zip",
"sha1": "b558bb5472cfa727dccab92229c66afa0d64404f",
"size": 46921,
"repo_path": "bios/Fujitsu/FM Towns/fm77av.zip",
"cores": [
"MAME"
]
},
{
"dest": "pegasus.zip",
"sha1": "fc10ef402bcac78c70e1cff57d51613fa12202f9",
"size": 27305,
"repo_path": "bios/Arcade/MAME/pegasus.zip",
"cores": [
"MAME"
]
},
{
"dest": "pcw8256.zip",
"sha1": "f8a11b4e03bb8c3caee604ca591676eab6535d1b",
"size": 1710,
"repo_path": "bios/Amstrad/PCW/pcw8256.zip",
"cores": [
"MAME"
]
},
{
"dest": "pcw9512.zip",
"sha1": "844988dc5a36917b002d0140d3a7692d1407f783",
"size": 2625,
"repo_path": "bios/Amstrad/PCW/pcw9512.zip",
"cores": [
"MAME"
]
},
{
"dest": "vis.zip",
"sha1": "beff39b4edb449c66b704e1c64ee6ed58e30a868",
"size": 605047,
"repo_path": "bios/Tandy/VIS/vis.zip",
"cores": [
"MAME"
]
},
{
"dest": "trs80.zip",
"sha1": "a9b8931c42303e8dfb475112fc18ff200b7252ce",
"size": 14558,
"repo_path": "bios/Tandy/TRS-80/trs80.zip",
"cores": [
"MAME"
]
},
{
"dest": "trs80m3.zip",
"sha1": "b804a031c8db6def59e077a4b6938dcac25093d7",
"size": 32854,
"repo_path": "bios/Tandy/TRS-80/trs80m3.zip",
"cores": [
"MAME"
]
},
{
"dest": "trs80m4.zip",
"sha1": "bc58ac28be4854fb198b895c7fd999f599b5a961",
"size": 25371,
"repo_path": "bios/Tandy/TRS-80/trs80m4.zip",
"cores": [
"MAME"
]
},
{
"dest": "trs80m4p.zip",
"sha1": "497eea6e0ed80501ca3beee714d71a5815495b07",
"size": 4880,
"repo_path": "bios/Tandy/TRS-80/trs80m4p.zip",
"cores": [
"MAME"
]
},
{
"dest": "ti99_4a.zip",
"sha1": "e05575b630bea7ff98b9ca1f083d745abb3110b6",
"size": 21377,
"repo_path": "bios/Texas Instruments/TI-99/ti99_4a.zip",
"cores": [
"MAME"
]
},
{
"dest": "ti99_speech.zip",
"sha1": "b58fe2dbbc254d363c2ec4a459e6ec1d91b2ac86",
"size": 31206,
"repo_path": "bios/Arcade/Arcade/ti99_speech.zip",
"cores": [
"MAME"
]
},
{
"dest": "tutor.zip",
"sha1": "273dbb7a93eb0ab83c2e13e9db51b897cc18f838",
"size": 34653,
"repo_path": "bios/Tomy/Tutor/tutor.zip",
"cores": [
"MAME"
]
},
{
"dest": "vg5k.zip",
"sha1": "5ad489a58fc457d2bfb7a348f4a312c3b49daad1",
"size": 26356,
"repo_path": "bios/Arcade/MAME/vg5k.zip",
"cores": [
"MAME"
]
},
{
"dest": "qsound.zip",
"sha1": "f1ccedb2c6e8f15cfebab52c3923e4b35f4df43f",
"size": 2654,
"repo_path": "bios/Arcade/Arcade/qsound.zip",
"cores": [
"MAME"
]
},
{
"dest": "ym2413.zip",
"sha1": "900e8c6cd152704a79905b6838fe3229c9499f8c",
"size": 286,
"repo_path": "bios/Arcade/MAME/ym2413.zip",
"cores": [
"MAME"
]
},
{
"dest": "ym2608.zip",
"sha1": "06fc753d015b43ca1787f4cfd9331b1674202e64",
"size": 7609,
"repo_path": "bios/Arcade/Arcade/ym2608.zip",
"cores": [
"MAME"
]
},
{
"dest": "dsi_bios9.bin",
"sha1": "db61fa39ddbc5f5ed71fb19cda47609ef0201723",
@@ -2246,17 +2426,6 @@
"melonDS"
]
},
{
"dest": "dsi_nand.bin",
"sha1": "b48f44194fe918aaaec5298861479512b581d661",
"size": 251658304,
"repo_path": ".cache/large/dsi_nand.bin",
"cores": [
"melonDS"
],
"storage": "release",
"release_asset": "dsi_nand.bin"
},
{
"dest": "dsi_sd_card.bin",
"sha1": "3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3",
@@ -2365,6 +2534,17 @@
"shadps4"
]
},
{
"dest": "psvita/PSP2UPDAT.PUP",
"sha1": "3ae832c9800fcaa007eccfc48f24242967c111f8",
"size": 56768512,
"repo_path": "bios/Sony/PlayStation Vita/.variants/PSP2UPDAT.PUP",
"cores": [
"Vita3K"
],
"storage": "release",
"release_asset": "PSP2UPDAT.PUP"
},
{
"dest": "Complex_4627.bin",
"sha1": "3944392c954cfb176d4210544e88353b3c5d36b1",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"platform": "romm",
"display_name": "RomM",
"version": "1.0",
"generated": "2026-03-29T14:04:16Z",
"generated": "2026-03-30T09:49:20Z",
"base_destination": "bios",
"detect": [
{
@@ -13,8 +13,8 @@
}
],
"standalone_copies": [],
"total_files": 545,
"total_size": 1197706137,
"total_files": 638,
"total_size": 1316397979,
"files": [
{
"dest": "3do/3do_arcade_saot.bin",
@@ -2623,12 +2623,21 @@
"cores": null
},
{
"dest": "psxonpsp660.bin",
"sha1": "96880d1ca92a016ff054be5159bb06fe03cb4e14",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/psxonpsp660.bin",
"dest": "BB01R4_OS.ROM",
"sha1": "decde89fbae90adb591ad2fc553d35f49030c129",
"size": 16384,
"repo_path": "bios/Atari/400-800/BB01R4_OS.ROM",
"cores": [
"Beetle PSX (Mednafen PSX)"
"Atari800"
]
},
{
"dest": "XEGAME.ROM",
"sha1": "a107db7f16a1129cf9d933c9cf4f013b068c9e82",
"size": 8192,
"repo_path": "bios/Atari/400-800/XEGAME.ROM",
"cores": [
"Atari800"
]
},
{
@@ -2640,6 +2649,98 @@
"Beetle PSX (Mednafen PSX)"
]
},
{
"dest": "openbios.bin",
"sha1": "389df7981873d9e6e46c84c20cd43af0e4226cf8",
"size": 524288,
"repo_path": "bios/Sony/PlayStation/openbios.bin",
"cores": [
"Beetle PSX (Mednafen PSX)"
]
},
{
"dest": "cromwell_1024.bin",
"sha1": "4e1c2c2ee308ca4591542b3ca48653f65fae6e0f",
"size": 1048576,
"repo_path": "bios/Microsoft/Xbox/cromwell_1024.bin",
"cores": [
"DirectXBox"
]
},
{
"dest": "GC/dsp_rom.bin",
"sha1": "f4f683a49d7eb4155566f793f2c1c27e90159992",
"size": 8192,
"repo_path": "bios/Nintendo/GameCube/Sys/GC/dsp_rom.bin",
"cores": [
"Dolphin"
]
},
{
"dest": "GC/dsp_coef.bin",
"sha1": "c116d867ba001dcd6bf6d399ff4bf38d340f556c",
"size": 4096,
"repo_path": "bios/Nintendo/GameCube/.variants/dsp_coef.bin.c116d867",
"cores": [
"Dolphin"
]
},
{
"dest": "Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"Dolphin"
]
},
{
"dest": "Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"Dolphin"
]
},
{
"dest": "Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"Dolphin"
],
"storage": "release",
"release_asset": "WiiSD.raw"
},
{
"dest": "Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"Dolphin"
]
},
{
"dest": "Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"Dolphin"
]
},
{
"dest": "Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"Dolphin"
]
},
{
"dest": "MT32_CONTROL.ROM",
"sha1": "b083518fffb7f66b03c23b7eb4f868e62dc5a987",
@@ -2694,6 +2795,33 @@
"DOSBox Pure"
]
},
{
"dest": "ep128emu/roms/exdos14isdos10uk.rom",
"sha1": "b82e21b6e3214432b6dc13f650e97de88fc90a72",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/exdos14isdos10uk.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/epdos16f.rom",
"sha1": "9a9eac31e601a1ab0f7a5d2b13175d092fa84bd3",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/epdos16f.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/zx128.rom",
"sha1": "16375d42ea109b47edded7a16028de7fdb3013a1",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/zx128.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "fbalpha2012/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
@@ -3063,6 +3191,53 @@
"Handy"
]
},
{
"dest": "hatari/BOOT.ST",
"sha1": "5bcabba35bb8fbfe5a65b85efccf5ed657388308",
"size": 737280,
"repo_path": "bios/Atari/ST/hatari/BOOT.ST",
"cores": [
"Hatari"
]
},
{
"dest": "Wii/sd.raw",
"sha1": "8c8134f08b2e3baa603206ede30d3935365009b8",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/sd.raw",
"cores": [
"Ishiiruka"
],
"storage": "release",
"release_asset": "sd.raw"
},
{
"dest": "pcsx2/resources/GameIndex.yaml",
"sha1": "b22389650f6c0a1e276b48213fed8a9c1c6476ce",
"size": 2669341,
"repo_path": "bios/Sony/PlayStation 2/GameIndex.yaml",
"cores": [
"LRPS2"
]
},
{
"dest": "pcsx2/resources/cheats_ws.zip",
"sha1": "773b4279d8c8e182dc57e444dbf448a1d115e7e0",
"size": 1273296,
"repo_path": "bios/Sony/PlayStation 2/cheats_ws.zip",
"cores": [
"LRPS2"
]
},
{
"dest": "pcsx2/resources/cheats_ni.zip",
"sha1": "dec5e4f137890c338babe13cfb9d41ff869fa721",
"size": 42525,
"repo_path": "bios/Sony/PlayStation 2/cheats_ni.zip",
"cores": [
"LRPS2"
]
},
{
"dest": "mame2003/cheat.dat",
"sha1": "32fc78415114a976af9c2ee53ea13de9f40b55ee",
@@ -3234,17 +3409,6 @@
"melonDS"
]
},
{
"dest": "dsi_nand.bin",
"sha1": "b48f44194fe918aaaec5298861479512b581d661",
"size": 251658304,
"repo_path": ".cache/large/dsi_nand.bin",
"cores": [
"melonDS"
],
"storage": "release",
"release_asset": "dsi_nand.bin"
},
{
"dest": "dsi_sd_card.bin",
"sha1": "3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3",
@@ -3254,6 +3418,15 @@
"melonDS"
]
},
{
"dest": "MacIIx.ROM",
"sha1": "753b94351d94c369616c2c87b19d568dc5e2764e",
"size": 262144,
"repo_path": "bios/Apple/Macintosh II/MacIIx.ROM",
"cores": [
"Mini vMac"
]
},
{
"dest": "Mupen64plus/IPL.n64",
"sha1": "bf861922dcb78c316360e3e742f4f70ff63c9bc3",
@@ -3272,6 +3445,33 @@
"Mupen64Plus-Next"
]
},
{
"dest": "np2/bios9821.rom",
"sha1": "2e92346727b0355bc1ec9a7ded1b444a4917f2b9",
"size": 98304,
"repo_path": "bios/NEC/PC-98/bios9821.rom",
"cores": [
"nekop2"
]
},
{
"dest": "np2/scsi.rom",
"sha1": "3d7166f05daad1b022fa04c2569e788580158095",
"size": 8192,
"repo_path": "bios/NEC/PC-98/scsi.rom",
"cores": [
"nekop2"
]
},
{
"dest": "np2/sasi.rom",
"sha1": "b607707d74b5a7d3ba211825de31a8f32aec8146",
"size": 4096,
"repo_path": "bios/NEC/PC-98/sasi.rom",
"cores": [
"nekop2"
]
},
{
"dest": "custom.pal",
"sha1": "c7635019127aa28d84d28ae48304bfca6d5baefb",
@@ -3281,6 +3481,33 @@
"Nestopia UE"
]
},
{
"dest": "np2kai/ide.rom",
"sha1": "0877ffb4b4d1c18283468be3579b72ed8c22e3ac",
"size": 8192,
"repo_path": "bios/NEC/PC-98/ide.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/pci.rom",
"sha1": "1246203bebf9f04e3bac2df7fc64719304f9f1bd",
"size": 32768,
"repo_path": "bios/NEC/PC-98/pci.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "eeprom.dat",
"sha1": "ffc6261e487efa8c7442069f71acfc4aa826993d",
"size": 64,
"repo_path": "bios/Sony/PlayStation 2/eeprom.dat",
"cores": [
"PCSX2"
]
},
{
"dest": "carthw.cfg",
"sha1": "d3fe0b958705e4cb5eeb7822e60d474204df4bd3",
@@ -3515,6 +3742,15 @@
"PUAE (P-UAE)"
]
},
{
"dest": "keropi/cgrom.tmp",
"sha1": "8d72c5b4d63bb14c5dbdac495244d659aa1498b6",
"size": 786432,
"repo_path": "bios/Sharp/X68000/cgrom.dat",
"cores": [
"px68k"
]
},
{
"dest": "same_cdi/bios/cdimono1.zip",
"sha1": "5d0b1b55b0d0958a5c9069c3219d4da5a87a6b93",
@@ -3561,12 +3797,93 @@
]
},
{
"dest": "BIOS.col",
"sha1": "45bedc4cbdeac66c7df59e9e599195c778d86a92",
"size": 8192,
"repo_path": "bios/Coleco/ColecoVision/BIOS.col",
"dest": "squirreljme-0.3.0-fast.jar",
"sha1": "7c4cd0a5451eedeac9b328f48408dbc312198ccf",
"size": 2367241,
"repo_path": "bios/Other/SquirrelJME/squirreljme-0.3.0-fast.jar",
"cores": [
"SMS Plus GX"
"SquirrelJME"
]
},
{
"dest": "squirreljme-0.3.0.jar",
"sha1": "8a2ddc37df2366d4e205e9904cd8bac22db2afd5",
"size": 15181774,
"repo_path": "bios/Java/J2ME/squirreljme.sqc",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-0.3.0-test.jar",
"sha1": "600cf0440594b0c69339ba4b626a47288b342d77",
"size": 3396757,
"repo_path": "bios/Java/J2ME/squirreljme-test.jar",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-0.3.0-slow.jar",
"sha1": "3a23de6999b94fc088bdd9c9e4a73781a1d42233",
"size": 3129653,
"repo_path": "bios/Other/SquirrelJME/squirreljme-0.3.0-slow.jar",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-0.3.0-slow-test.jar",
"sha1": "b411c128bfd8411f339a49bbcb1c9e97189c2161",
"size": 3772058,
"repo_path": "bios/Other/SquirrelJME/squirreljme-0.3.0-slow-test.jar",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-fast.jar",
"sha1": "8a2ddc37df2366d4e205e9904cd8bac22db2afd5",
"size": 15181774,
"repo_path": "bios/Java/J2ME/squirreljme.sqc",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme.jar",
"sha1": "6933bbe1fc29f58581a7f64f859f756db9ef78a7",
"size": 4700395,
"repo_path": "bios/Java/J2ME/squirreljme.jar",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-test.jar",
"sha1": "600cf0440594b0c69339ba4b626a47288b342d77",
"size": 3396757,
"repo_path": "bios/Java/J2ME/squirreljme-test.jar",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-slow.jar",
"sha1": "8a2ddc37df2366d4e205e9904cd8bac22db2afd5",
"size": 15181774,
"repo_path": "bios/Java/J2ME/squirreljme.sqc",
"cores": [
"SquirrelJME"
]
},
{
"dest": "squirreljme-slow-test.jar",
"sha1": "8a2ddc37df2366d4e205e9904cd8bac22db2afd5",
"size": 15181774,
"repo_path": "bios/Java/J2ME/squirreljme.sqc",
"cores": [
"SquirrelJME"
]
},
{
@@ -3722,6 +4039,51 @@
"VICE xvic"
]
},
{
"dest": "xmil/IPLROM.X1",
"sha1": "c4db9a6e99873808c8022afd1c50fef556a8b44d",
"size": 4096,
"repo_path": "bios/Sharp/X1/.variants/IPLROM.X1.c4db9a6e",
"cores": [
"X Millennium"
]
},
{
"dest": "xmil/IPLROM.X1T",
"sha1": "44620f57a25f0bcac2b57ca2b0f1ebad3bf305d3",
"size": 32768,
"repo_path": "bios/Sharp/X1/.variants/IPLROM.X1T.44620f57",
"cores": [
"X Millennium"
]
},
{
"dest": "xmil/FNT0816.X1",
"sha1": "4f06d20c997a79ee6af954b69498147789bf1847",
"size": 4096,
"repo_path": "bios/Sharp/X1/FNT0816.X1",
"cores": [
"X Millennium"
]
},
{
"dest": "xmil/FNT1616.X1",
"sha1": "b9e6c320611f0842df6f45673c47c3e23bc14272",
"size": 306176,
"repo_path": "bios/Sharp/X1/FNT1616.X1",
"cores": [
"X Millennium"
]
},
{
"dest": "xbox_hdd.qcow2",
"sha1": "9da5f9ecfb1c9c32efa616f0300d02e8f702244d",
"size": 1638400,
"repo_path": "bios/Microsoft/Xbox/xbox_hdd.qcow2",
"cores": [
"Xemu"
]
},
{
"dest": "channelf.zip",
"sha1": "1cb23b462b990241013deb4b5e07ce741af28267",
@@ -4127,6 +4489,213 @@
"FinalBurn Neo"
]
},
{
"dest": "GC/USA/IPL.bin",
"sha1": "a1837968288253ed541f2b11440b68f5a9b33875",
"size": 2097152,
"repo_path": "bios/Nintendo/GameCube/GC/JAP/IPL.bin",
"cores": [
"Dolphin"
]
},
{
"dest": "GC/EUR/IPL.bin",
"sha1": "a1837968288253ed541f2b11440b68f5a9b33875",
"size": 2097152,
"repo_path": "bios/Nintendo/GameCube/GC/JAP/IPL.bin",
"cores": [
"Dolphin"
]
},
{
"dest": "GC/JAP/IPL.bin",
"sha1": "a1837968288253ed541f2b11440b68f5a9b33875",
"size": 2097152,
"repo_path": "bios/Nintendo/GameCube/GC/JAP/IPL.bin",
"cores": [
"Dolphin"
]
},
{
"dest": "GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"Dolphin"
]
},
{
"dest": "ep128emu/roms/exos21.rom",
"sha1": "55315b20fecb4441a07ee4bc5dc7153f396e0a2e",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/exos21.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/exos20.rom",
"sha1": "6033a0535136c40c47137e4d1cd9273c06d5fdff",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/exos20.bin",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/exos24uk.rom",
"sha1": "cf12e971623a54bf8c4f891ca3a36d969f205c49",
"size": 65536,
"repo_path": "bios/Enterprise/64-128/exos24uk.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/basic21.rom",
"sha1": "03bbb386cf530e804363acdfc1d13e64cf28af2e",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/basic21.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/basic20.rom",
"sha1": "61d0987b906146e21b94f265d5b51b4938c986a9",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/basic20.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/exdos13.rom",
"sha1": "cb43ab3676b93c279f1ed8ffcb0d4dcd4b34e631",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/exdos13.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/epfileio.rom",
"sha1": "2f9077bcd89b1ec42dbdcd55d335bdbaf361eff3",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/epfileio.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/zt19uk.rom",
"sha1": "b7af62f0bc95fdca4b31d236f8327dafc80f83b7",
"size": 32768,
"repo_path": "bios/Enterprise/64-128/zt19uk.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/hun.rom",
"sha1": "325a5e28c2a0d896711f8829e7ff14fed5dd4103",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/hun.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/brd.rom",
"sha1": "f34f0c330b44dbf2548329bea954d5991dec30ca",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/brd.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/tvc22_sys.rom",
"sha1": "f2572ee83d09fc08f4de4a62f101c8bb301a9505",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/tvc22_sys.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/tvc22_ext.rom",
"sha1": "abf119cf947ea32defd08b29a8a25d75f6bd4987",
"size": 8192,
"repo_path": "bios/Enterprise/64-128/tvc22_ext.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/tvcfileio.rom",
"sha1": "98889c3a56b11dedf077f866ed2e12d51b604113",
"size": 8192,
"repo_path": "bios/Enterprise/64-128/tvcfileio.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/tvc_dos12d.rom",
"sha1": "072c6160d4e7d406f5d8f5b1b66066c797d35561",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/tvc_dos12d.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/cpc464.rom",
"sha1": "56d39c463da60968d93e58b4ba0e675829412a20",
"size": 32768,
"repo_path": "bios/Amstrad/CPC/cpc464.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/cpc664.rom",
"sha1": "073a7665527b5bd8a148747a3947dbd3328682c8",
"size": 32768,
"repo_path": "bios/Amstrad/CPC/cpc664.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/cpc6128.rom",
"sha1": "5977adbad3f7c1e0e082cd02fe76a700d9860c30",
"size": 32768,
"repo_path": "bios/Amstrad/CPC/cpc6128.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/cpc_amsdos.rom",
"sha1": "39102c8e9cb55fcc0b9b62098780ed4a3cb6a4bb",
"size": 16384,
"repo_path": "bios/Amstrad/CPC/amsdos.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "ep128emu/roms/zx48.rom",
"sha1": "5ea7c2b824672e914525d1d5c419d71b84a426a2",
"size": 16384,
"repo_path": "bios/Enterprise/64-128/zx48.rom",
"cores": [
"ep128emu-core"
]
},
{
"dest": "fbneo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
@@ -4180,6 +4749,276 @@
"cores": [
"MAME 2003-Plus"
]
},
{
"dest": "np2/bios.rom",
"sha1": "1f5f7013f18c08ff50d7942e76c4fbd782412414",
"size": 65536,
"repo_path": "bios/IBM/PC/ibmpcjr/bios.rom",
"cores": [
"nekop2"
]
},
{
"dest": "np2/font.bmp",
"sha1": "b4f14e58030ed40fff2dc312b58ea4440bdf8cc5",
"size": 524350,
"repo_path": "bios/NEC/PC-98/font.bmp",
"cores": [
"nekop2"
]
},
{
"dest": "np2/sound.rom",
"sha1": "d5dbc4fea3b8367024d363f5351baecd6adcd8ef",
"size": 16384,
"repo_path": "bios/NEC/PC-98/sound.rom",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_bd.wav",
"sha1": "0a56c142ef40cec50f3ee56a6e42d0029c9e2818",
"size": 19192,
"repo_path": "bios/NEC/PC-98/2608_bd.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_sd.wav",
"sha1": "3c79663ef74c0b0439d13351326eb1c52a657008",
"size": 15558,
"repo_path": "bios/NEC/PC-98/2608_sd.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_top.wav",
"sha1": "aa4a8f766a86b830687d5083fd3b9db0652f46fc",
"size": 57016,
"repo_path": "bios/NEC/PC-98/2608_top.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_hh.wav",
"sha1": "12f676cef249b82480b6f19c454e234b435ca7b6",
"size": 36722,
"repo_path": "bios/NEC/PC-98/2608_hh.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_tom.wav",
"sha1": "9513fb4a3f41e75a972a273a5104cbd834c1e2c5",
"size": 23092,
"repo_path": "bios/NEC/PC-98/2608_tom.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2/2608_rim.wav",
"sha1": "c65592330c9dd84011151daed52f9aec926b7e56",
"size": 5288,
"repo_path": "bios/NEC/PC-98/2608_rim.wav",
"cores": [
"nekop2"
]
},
{
"dest": "np2kai/bios.rom",
"sha1": "1f5f7013f18c08ff50d7942e76c4fbd782412414",
"size": 65536,
"repo_path": "bios/IBM/PC/ibmpcjr/bios.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/font.bmp",
"sha1": "b4f14e58030ed40fff2dc312b58ea4440bdf8cc5",
"size": 524350,
"repo_path": "bios/NEC/PC-98/font.bmp",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/sound.rom",
"sha1": "d5dbc4fea3b8367024d363f5351baecd6adcd8ef",
"size": 16384,
"repo_path": "bios/NEC/PC-98/sound.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_bd.wav",
"sha1": "0a56c142ef40cec50f3ee56a6e42d0029c9e2818",
"size": 19192,
"repo_path": "bios/NEC/PC-98/2608_bd.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_sd.wav",
"sha1": "3c79663ef74c0b0439d13351326eb1c52a657008",
"size": 15558,
"repo_path": "bios/NEC/PC-98/2608_sd.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_top.wav",
"sha1": "aa4a8f766a86b830687d5083fd3b9db0652f46fc",
"size": 57016,
"repo_path": "bios/NEC/PC-98/2608_top.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_hh.wav",
"sha1": "12f676cef249b82480b6f19c454e234b435ca7b6",
"size": 36722,
"repo_path": "bios/NEC/PC-98/2608_hh.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_tom.wav",
"sha1": "9513fb4a3f41e75a972a273a5104cbd834c1e2c5",
"size": 23092,
"repo_path": "bios/NEC/PC-98/2608_tom.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/2608_rim.wav",
"sha1": "c65592330c9dd84011151daed52f9aec926b7e56",
"size": 5288,
"repo_path": "bios/NEC/PC-98/2608_rim.wav",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/scsi.rom",
"sha1": "3d7166f05daad1b022fa04c2569e788580158095",
"size": 8192,
"repo_path": "bios/NEC/PC-98/scsi.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "np2kai/sasi.rom",
"sha1": "b607707d74b5a7d3ba211825de31a8f32aec8146",
"size": 4096,
"repo_path": "bios/NEC/PC-98/sasi.rom",
"cores": [
"NP2kai"
]
},
{
"dest": "keropi/iplrom.dat",
"sha1": "0ed038ed2133b9f78c6e37256807424e0d927560",
"size": 131072,
"repo_path": "bios/Sharp/X68000/iplrom.dat",
"cores": [
"px68k"
]
},
{
"dest": "keropi/iplrom30.dat",
"sha1": "239e9124568c862c31d9ec0605e32373ea74b86a",
"size": 131072,
"repo_path": "bios/Sharp/X68000/iplrom30.dat",
"cores": [
"px68k"
]
},
{
"dest": "keropi/iplromco.dat",
"sha1": "77511fc58798404701f66b6bbc9cbde06596eba7",
"size": 131072,
"repo_path": "bios/Sharp/X68000/iplromco.dat",
"cores": [
"px68k"
]
},
{
"dest": "keropi/iplromxv.dat",
"sha1": "e33cdcdb69cd257b0b211ef46e7a8b144637db57",
"size": 131072,
"repo_path": "bios/Sharp/X68000/iplromxv.dat",
"cores": [
"px68k"
]
},
{
"dest": "keropi/cgrom.dat",
"sha1": "8d72c5b4d63bb14c5dbdac495244d659aa1498b6",
"size": 786432,
"repo_path": "bios/Sharp/X68000/cgrom.dat",
"cores": [
"px68k"
]
},
{
"dest": "scummvm/extra/MT32_CONTROL.ROM",
"sha1": "b083518fffb7f66b03c23b7eb4f868e62dc5a987",
"size": 65536,
"repo_path": "bios/Commodore/Amiga/mt32-roms/mt32_control.rom",
"cores": [
"ScummVM"
]
},
{
"dest": "scummvm/extra/MT32_PCM.ROM",
"sha1": "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/mt32-roms/pcm_mt32.rom",
"cores": [
"ScummVM"
]
},
{
"dest": "scummvm/extra/CM32L_CONTROL.ROM",
"sha1": "a439fbb390da38cada95a7cbb1d6ca199cd66ef8",
"size": 65536,
"repo_path": "bios/Commodore/Amiga/mt32-roms/cm32l_control.rom",
"cores": [
"ScummVM"
]
},
{
"dest": "scummvm/extra/CM32L_PCM.ROM",
"sha1": "289cc298ad532b702461bfc738009d9ebe8025ea",
"size": 1048576,
"repo_path": "bios/Commodore/Amiga/mt32-roms/pcm_cm32l.rom",
"cores": [
"ScummVM"
]
},
{
"dest": "xmil/FNT0808.X1",
"sha1": "1c1a0d8c9f4c446ccd7470516b215ddca5052fb2",
"size": 2048,
"repo_path": "bios/Sharp/X1/FNT0808.X1",
"cores": [
"X Millennium"
]
}
]
}

View File

@@ -132,7 +132,7 @@ nav:
- ZC: systems/zc.md
- Emulators:
- Overview: emulators/index.md
- Official ports (61):
- Official ports (62):
- amiarcadia: emulators/amiarcadia.md
- Amiberry: emulators/amiberry.md
- Ardens: emulators/ardens.md
@@ -176,6 +176,7 @@ nav:
- mGBA: emulators/mgba.md
- Mr.Boom: emulators/mrboom.md
- Panda3DS: emulators/panda3ds.md
- PCSX2: emulators/pcsx2.md
- PicoDrive: emulators/picodrive.md
- play: emulators/play.md
- PPSSPP: emulators/ppsspp.md
@@ -440,12 +441,12 @@ nav:
- Lexaloffle: emulators/lexaloffle.md
- Model 2 Emulator: emulators/model2.md
- openMSX: emulators/openmsx.md
- PCSX2: emulators/pcsx2.md
- Redream: emulators/redream.md
- RPCS3: emulators/rpcs3.md
- Ryujinx: emulators/ryujinx.md
- shadps4: emulators/shadps4.md
- Supermodel: emulators/supermodel.md
- ti99sim: emulators/ti99sim.md
- tsugaru: emulators/tsugaru.md
- VBA-M: emulators/vba_m.md
- VICE: emulators/vice.md

View File

@@ -1,231 +1,870 @@
# Platform Registry
# Central configuration for all supported platforms and their scraper sources.
# Adding a new platform = adding an entry here + creating its YAML config.
#
# status: active | archived
# active -- included in automated releases, scraped weekly/monthly
# archived -- config preserved, user can generate pack manually, excluded from CI releases
platforms:
retroarch:
config: retroarch.yml
status: active
logo: "https://raw.githubusercontent.com/libretro/RetroArch/master/media/retroarch-vector_invader-only.svg"
logo: https://raw.githubusercontent.com/libretro/RetroArch/master/media/retroarch-vector_invader-only.svg
scraper: libretro
source_url: "https://raw.githubusercontent.com/libretro/libretro-database/master/dat/System.dat"
source_url: https://raw.githubusercontent.com/libretro/libretro-database/master/dat/System.dat
source_format: clrmamepro_dat
hash_type: sha1
verification_mode: existence
base_destination: system
case_insensitive_fs: true
schedule: weekly
cores: all_libretro
target_scraper: retroarch_targets
target_source: "https://buildbot.libretro.com/nightly/"
target_source: https://buildbot.libretro.com/nightly/
install:
detect:
- os: linux
method: config_file
config: "$HOME/.var/app/org.libretro.RetroArch/config/retroarch/retroarch.cfg"
parse_key: system_directory
- os: linux
method: config_file
config: "$HOME/.config/retroarch/retroarch.cfg"
parse_key: system_directory
- os: darwin
method: config_file
config: "$HOME/Library/Application Support/RetroArch/retroarch.cfg"
parse_key: system_directory
- os: windows
method: config_file
config: "%APPDATA%\\RetroArch\\retroarch.cfg"
parse_key: system_directory
- os: linux
method: config_file
config: $HOME/.var/app/org.libretro.RetroArch/config/retroarch/retroarch.cfg
parse_key: system_directory
- os: linux
method: config_file
config: $HOME/.config/retroarch/retroarch.cfg
parse_key: system_directory
- os: darwin
method: config_file
config: $HOME/Library/Application Support/RetroArch/retroarch.cfg
parse_key: system_directory
- os: windows
method: config_file
config: '%APPDATA%\RetroArch\retroarch.cfg'
parse_key: system_directory
batocera:
config: batocera.yml
status: active
logo: "https://raw.githubusercontent.com/batocera-linux/batocera-emulationstation/master/resources/splash_batocera.svg"
logo: https://raw.githubusercontent.com/batocera-linux/batocera-emulationstation/master/resources/splash_batocera.svg
scraper: batocera
source_url: "https://raw.githubusercontent.com/batocera-linux/batocera.linux/master/package/batocera/core/batocera-scripts/scripts/batocera-systems"
source_url: https://raw.githubusercontent.com/batocera-linux/batocera.linux/master/package/batocera/core/batocera-scripts/scripts/batocera-systems
source_format: python_dict
hash_type: md5
schedule: weekly
cores: [81, a5200, abuse, arduous, atari800, azahar, bennugd, bk, bluemsx, bsnes, bstone, cannonball, cap32, catacombgl, cdogs, cemu, cgenius, citron, clk, corsixth, demul, devilutionx, dhewm3, dice, dolphin, dosbox_pure, dxx-rebirth, easyrpg, ecwolf, eduke32, eka2l1, emuscv, etlegacy, fake08, fallout1-ce, fallout2-ce, fbneo, fceumm, flatpak, flycast, freechaf, freeintv, fury, fuse, gambatte, gearsystem, genesisplusgx, glide64mk2, gong, gsplus, gw, gzdoom, hatari, hcl, hurrican, hypseus-singe, ikemen, ioquake3, iortcw, jazz2-native, lindbergh-loader, lowresnx, lutro, mame, mame078plus, mednafen_lynx, mednafen_ngp, mednafen_supergrafx, mednafen_wswan, melonds, mgba, minivmac, model2emu, moonlight, mrboom, neocd, np2kai, nxengine, o2em, odcommander, openbor6412, openjazz, openjk, openjkdf2, openmohaa, opera, pce_fast, pcfx, pcsx2, pcsx_rearmed, pd777, picodrive, play, pokemini, potator, ppsspp, prboom, prosystem, puae, px68k, pygame, pyxel, quasi88, raze, reminiscence, rpcs3, ruffle, samcoupe, sameduck, scummvm, sdlpop, sh, shadps4, snes9x, solarus, sonic2013, sonic3-air, sonic-mania, steam, stella, superbroswar, supermodel, taradino, tgbdual, theforceengine, theodore, thextech, tic80, tr1x, tr2x, tsugaru, tyrian, tyrquake, uqm, uzem, vb, vecx, vice_x64, vircon32, virtualjaguar, vita3k, vox_official, vpinball, wasm4, wine-tkg, x1, x128, x16emu, xash3d_fwgs, xemu, xenia-canary, xpet, xplus4, xrick, xvic, yabasanshiro, yquake2, zc210]
cores:
- '81'
- a5200
- abuse
- amiberry
- applewin
- arduous
- atari800
- azahar
- beetle-saturn
- bennugd
- bigpemu
- bk
- blastem
- bluemsx
- boom3
- bsnes
- bstone
- cannonball
- cap32
- catacombgl
- cdogs
- cemu
- cgenius
- citron
- clk
- corsixth
- demul
- desmume
- devilutionx
- dhewm3
- dice
- dolphin
- dosbox
- dosbox_pure
- duckstation
- dxx-rebirth
- easyrpg
- ecwolf
- eduke32
- eka2l1
- emuscv
- ep128emu-core
- etlegacy
- fake08
- fallout1-ce
- fallout2-ce
- fbneo
- fceumm
- flatpak
- flycast
- fmsx
- freechaf
- freeintv
- freej2me
- fsuae
- fury
- fuse
- gambatte
- gearcoleco
- gearsystem
- genesisplusgx
- glide64mk2
- gong
- gpsp
- gsplus
- gw
- gzdoom
- handy
- hatari
- hcl
- holani
- hurrican
- hypseus-singe
- ikemen
- ioquake3
- iortcw
- jazz2-native
- kronos
- lindbergh-loader
- lowresnx
- lutro
- mame
- mame078plus
- mamemess
- mednafen_lynx
- mednafen_ngp
- mednafen_psx
- mednafen_supergrafx
- mednafen_wswan
- melonds
- mesen
- mesen-s
- mgba
- minivmac
- model2emu
- moonlight
- mrboom
- mupen64plus-next
- neocd
- nestopia
- np2kai
- nxengine
- o2em
- odcommander
- openbor6412
- openjazz
- openjk
- openjkdf2
- openmohaa
- openmsx
- opera
- parallel_n64
- pce_fast
- pcfx
- pcsx2
- pcsx_rearmed
- pd777
- picodrive
- play
- pokemini
- potator
- ppsspp
- prboom
- prosystem
- puae
- puae2021
- px68k
- pygame
- pyxel
- quasi88
- raze
- redream
- reminiscence
- rpcs3
- ruffle
- ryujinx
- samcoupe
- same_cdi
- sameduck
- scummvm
- sdlpop
- sh
- shadps4
- smsplus
- snes9x
- solarus
- sonic-mania
- sonic2013
- sonic3-air
- squirreljme
- steam
- stella
- stella2014
- superbroswar
- supermodel
- swanstation
- taradino
- tgbdual
- theforceengine
- theodore
- thextech
- tic80
- tr1x
- tr2x
- tsugaru
- tyrian
- tyrquake
- uae4arm
- uqm
- uzem
- vb
- vba-m
- vecx
- vemulator
- vice
- vice_x128
- vice_x64
- vice_x64sc
- vice_xpet
- vice_xplus4
- vice_xscpu64
- vice_xvic
- vircon32
- virtualjaguar
- vita3k
- vitaquake2
- vox_official
- vpinball
- wasm4
- wine-tkg
- x1
- x128
- x16emu
- xash3d_fwgs
- xemu
- xenia
- xenia-canary
- xpet
- xplus4
- xrick
- xroar
- xvic
- yabasanshiro
- ymir
- yquake2
- zc210
target_scraper: batocera_targets
target_source: "https://github.com/batocera-linux/batocera.linux"
target_source: https://github.com/batocera-linux/batocera.linux
install:
detect:
- os: linux
method: file_exists
file: /etc/batocera-version
bios_path: /userdata/bios
- os: linux
method: file_exists
file: /etc/batocera-version
bios_path: /userdata/bios
recalbox:
config: recalbox.yml
status: active
logo: "https://raw.githubusercontent.com/homarr-labs/dashboard-icons/main/svg/recalbox.svg"
logo: https://raw.githubusercontent.com/homarr-labs/dashboard-icons/main/svg/recalbox.svg
scraper: recalbox
source_url: "https://gitlab.com/recalbox/recalbox/-/raw/master/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml"
source_url: https://gitlab.com/recalbox/recalbox/-/raw/master/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml
source_format: xml
hash_type: md5
schedule: monthly
target_scraper: null
target_source: null
cores: ["2048", 81, a5200, advancemame, amiberry, applewin, arduous, atari800, b2, beebem, bk, bluemsx, boom3, bsnes, bsneshd, cannonball, cap32, cdi2015, corsixth, craft, crocods, daphne, desmume, dice, dinothawr, dirksimple, dolphin, dolphin-gui, dosbox, dosbox_pure, duckstation, easyrpg, ecwolf, emuscv, fake08, fba2x, fbneo, fceumm, flycast, flycast-next, fmsx, freechaf, freeintv, frotz, fuse, gambatte, gearcoleco, geargrafx, gearsystem, genesisplusgx, genesisplusgx_ex, genesisplusgxwide, geolith, glide64mk2, gliden64, gliden64_20, gong, gpsp, gsplus, gw, handy, hatari, hatarib, holani, imageviewer, julius, kronos, lowresnx, lutro, mame0258, mame0278, mame2000, mame2003, mame2003_plus, mame2010, mame2015, mame2016, mednafen_lynx, mednafen_ngp, mednafen_pce_fast, mednafen_pcfx, mednafen_psx, mednafen_psx_hw, mednafen_saturn, mednafen_supafaust, mednafen_supergrafx, mednafen_vb, mednafen_wswan, melonds, mesen, mesen_s, meteor, mgba, minivmac, mojozork, moonlight, mrboom, mu, mupen64plus, mupen64plus_next, n64_gles2, neocd, nestopia, np2kai, nxengine, o2em, openbor, openlara, opera, oricutron, parallel_n64, pcsx2, pcsx_rearmed, pico8, picodrive, pisnes, pokemini, potator, ppsspp, prboom, prosystem, ps2, puae, px68k, quasi88, quicknes, race, rb5000, reicast, reminiscence, retro8, retrodream, rice, rice_gles2, sameboy, same_cdi, sameduck, scummvm, sdlpop, simcoupe, snes9x, snes9x2002, snes9x2005, snes9x2010, solarus, stella, stella2014, stonesoup, supermodel, swanstation, tamalibretro, tgbdual, theodore, thepowdertoy, ti99sim, tic80, tyrquake, uae4all, uae4arm, uzem, vecx, vice_x128, vice_x64, vice_x64sc, vice_xcbm2, vice_xcbm5x0, vice_xpet, vice_xplus4, vice_xscpu64, vice_xvic, virtualjaguar, vitaquake2, vitaquake3, vitavoyager, vpinball, vvvvvv, wasm4, x1, x128, x64, x64sx, xcbm2, xcbm5x0, xemu, xpet, xplus4, xrick, xroar, xscpu64, xvic, yabasanshiro, yabause]
cores:
- '2048'
- '81'
- a5200
- advancemame
- amiberry
- applewin
- arduous
- atari800
- b2
- beebem
- bk
- bluemsx
- boom3
- bsnes
- bsneshd
- cannonball
- cap32
- cdi2015
- corsixth
- craft
- crocods
- daphne
- desmume
- dice
- dinothawr
- dirksimple
- dolphin
- dolphin-gui
- dosbox
- dosbox_pure
- duckstation
- easyrpg
- ecwolf
- emuscv
- fake08
- fba2x
- fbneo
- fceumm
- flycast
- flycast-next
- fmsx
- freechaf
- freeintv
- frotz
- fuse
- gambatte
- gearcoleco
- geargrafx
- gearsystem
- genesisplusgx
- genesisplusgx_ex
- genesisplusgxwide
- geolith
- glide64mk2
- gliden64
- gliden64_20
- gong
- gpsp
- gsplus
- gw
- handy
- hatari
- hatarib
- holani
- imageviewer
- julius
- kronos
- lowresnx
- lutro
- mame
- mame0258
- mame0278
- mame2000
- mame2003
- mame2003_plus
- mame2010
- mame2015
- mame2016
- mamemess
- mednafen_lynx
- mednafen_ngp
- mednafen_pce_fast
- mednafen_pcfx
- mednafen_psx
- mednafen_psx_hw
- mednafen_saturn
- mednafen_supafaust
- mednafen_supergrafx
- mednafen_vb
- mednafen_wswan
- melonds
- mesen
- mesen_s
- meteor
- mgba
- minivmac
- mojozork
- moonlight
- mrboom
- mu
- mupen64plus
- mupen64plus_next
- n64_gles2
- neocd
- nestopia
- np2kai
- nxengine
- o2em
- openbor
- openlara
- opera
- oricutron
- parallel_n64
- pcsx2
- pcsx_rearmed
- pico8
- picodrive
- pisnes
- pokemini
- potator
- ppsspp
- prboom
- prosystem
- ps2
- puae
- px68k
- quasi88
- quicknes
- race
- rb5000
- reicast
- reminiscence
- retro8
- retrodream
- rice
- rice_gles2
- same_cdi
- sameboy
- sameduck
- scummvm
- sdlpop
- simcoupe
- snes9x
- snes9x2002
- snes9x2005
- snes9x2010
- solarus
- stella
- stella2014
- stonesoup
- supermodel
- swanstation
- tamalibretro
- tgbdual
- theodore
- thepowdertoy
- ti99sim
- tic80
- tyrquake
- uae4all
- uae4arm
- uzem
- vecx
- vice_x128
- vice_x64
- vice_x64sc
- vice_xcbm2
- vice_xcbm5x0
- vice_xpet
- vice_xplus4
- vice_xscpu64
- vice_xvic
- virtualjaguar
- vitaquake2
- vitaquake3
- vitavoyager
- vpinball
- vvvvvv
- wasm4
- x1
- x128
- x64
- x64sx
- xcbm2
- xcbm5x0
- xemu
- xpet
- xplus4
- xrick
- xroar
- xscpu64
- xvic
- yabasanshiro
- yabause
install:
detect:
- os: linux
method: file_exists
file: /usr/bin/recalbox-settings
bios_path: /recalbox/share/bios
- os: linux
method: file_exists
file: /usr/bin/recalbox-settings
bios_path: /recalbox/share/bios
retrobat:
config: retrobat.yml
status: active
logo: "https://raw.githubusercontent.com/RetroBat-Official/retrobat/main/system/resources/retrobat_logo_notext.png"
logo: https://raw.githubusercontent.com/RetroBat-Official/retrobat/main/system/resources/retrobat_logo_notext.png
scraper: retrobat
source_url: "https://raw.githubusercontent.com/RetroBat-Official/emulatorlauncher/master/batocera-systems/Resources/batocera-systems.json"
source_url: https://raw.githubusercontent.com/RetroBat-Official/emulatorlauncher/master/batocera-systems/Resources/batocera-systems.json
source_format: json
hash_type: md5
schedule: weekly
cores: [81, a5200, abuse, arduous, atari800, azahar, bennugd, bk, bluemsx, bsnes, bstone, cannonball, cap32, catacombgl, cdogs, cemu, cgenius, citron, clk, corsixth, demul, devilutionx, dhewm3, dice, dolphin, dosbox_pure, dxx-rebirth, easyrpg, ecwolf, eduke32, eka2l1, emuscv, etlegacy, fake08, fallout1-ce, fallout2-ce, fbneo, fceumm, flatpak, flycast, freechaf, freeintv, fury, fuse, gambatte, gearsystem, genesisplusgx, glide64mk2, gong, gsplus, gw, gzdoom, hatari, hcl, hurrican, hypseus-singe, ikemen, ioquake3, iortcw, jazz2-native, lindbergh-loader, lowresnx, lutro, mame, mame078plus, mednafen_lynx, mednafen_ngp, mednafen_supergrafx, mednafen_wswan, melonds, mgba, minivmac, model2emu, moonlight, mrboom, neocd, np2kai, nxengine, o2em, odcommander, openbor6412, openjazz, openjk, openjkdf2, openmohaa, opera, pce_fast, pcfx, pcsx2, pcsx_rearmed, pd777, picodrive, play, pokemini, potator, ppsspp, prboom, prosystem, puae, px68k, pygame, pyxel, quasi88, raze, reminiscence, rpcs3, ruffle, samcoupe, sameduck, scummvm, sdlpop, sh, shadps4, snes9x, solarus, sonic2013, sonic3-air, sonic-mania, steam, stella, superbroswar, supermodel, taradino, tgbdual, theforceengine, theodore, thextech, tic80, tr1x, tr2x, tsugaru, tyrian, tyrquake, uqm, uzem, vb, vecx, vice_x64, vircon32, virtualjaguar, vita3k, vox_official, vpinball, wasm4, wine-tkg, x1, x128, x16emu, xash3d_fwgs, xemu, xenia-canary, xpet, xplus4, xrick, xvic, yabasanshiro, yquake2, zc210]
cores:
- '81'
- a5200
- abuse
- arduous
- ares
- atari800
- azahar
- bennugd
- bk
- bluemsx
- bsnes
- bstone
- cannonball
- cap32
- catacombgl
- cdogs
- cemu
- cgenius
- citron
- clk
- corsixth
- demul
- devilutionx
- dhewm3
- dice
- dolphin
- dosbox_pure
- dxx-rebirth
- easyrpg
- ecwolf
- eduke32
- eka2l1
- emuscv
- etlegacy
- fake08
- fallout1-ce
- fallout2-ce
- fbalpha2012
- fbalpha2012_neogeo
- fbneo
- fceumm
- flatpak
- flycast
- freechaf
- freeintv
- freej2me
- fury
- fuse
- gambatte
- geargrafx
- gearsystem
- genesisplusgx
- glide64mk2
- gong
- gsplus
- gw
- gzdoom
- hatari
- hcl
- hurrican
- hypseus-singe
- ikemen
- ioquake3
- iortcw
- jazz2-native
- lindbergh-loader
- lowresnx
- lutro
- mame
- mame078plus
- mamemess
- mednafen_lynx
- mednafen_ngp
- mednafen_supergrafx
- mednafen_wswan
- melonds
- mgba
- minivmac
- model2emu
- moonlight
- mrboom
- mupen64plus_next
- neocd
- np2kai
- nxengine
- o2em
- odcommander
- openbor6412
- openjazz
- openjk
- openjkdf2
- openmohaa
- opera
- parallel_n64
- pce_fast
- pcfx
- pcsx2
- pcsx_rearmed
- pd777
- picodrive
- play
- pokemini
- potator
- ppsspp
- prboom
- prosystem
- puae
- px68k
- pygame
- pyxel
- quasi88
- raze
- reminiscence
- rpcs3
- ruffle
- samcoupe
- sameduck
- scummvm
- sdlpop
- sh
- shadps4
- snes9x
- solarus
- sonic-mania
- sonic2013
- sonic3-air
- squirreljme
- steam
- stella
- superbroswar
- supermodel
- taradino
- tgbdual
- theforceengine
- theodore
- thextech
- tic80
- tr1x
- tr2x
- tsugaru
- tyrian
- tyrquake
- uqm
- uzem
- vb
- vecx
- vice_x64
- vircon32
- virtualjaguar
- vita3k
- vox_official
- vpinball
- wasm4
- wine-tkg
- x1
- x128
- x16emu
- xash3d_fwgs
- xemu
- xenia-canary
- xpet
- xplus4
- xrick
- xroar
- xvic
- yabasanshiro
- yquake2
- zc210
target_scraper: null
target_source: null
install:
detect:
- os: windows
method: path_exists
path: "%USERPROFILE%\\RetroBat\\bios"
- os: windows
method: path_exists
path: '%USERPROFILE%\RetroBat\bios'
emudeck:
config: emudeck.yml
status: active
logo: "https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/icons/EmuDeck.png"
logo: https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/icons/EmuDeck.png
scraper: emudeck
source_url: "https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/functions/checkBIOS.sh"
source_wiki: "https://raw.githubusercontent.com/EmuDeck/emudeck.github.io/main/docs/tables/"
source_url: https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/functions/checkBIOS.sh
source_wiki: https://raw.githubusercontent.com/EmuDeck/emudeck.github.io/main/docs/tables/
source_format: bash_script+csv
hash_type: md5
schedule: weekly
target_scraper: emudeck_targets
target_source: "https://github.com/dragoonDorise/EmuDeck"
# dragoonDorise/EmuDeck = official repo (creator's account, 3.4k stars)
# EmuDeck/emudeck.github.io = official wiki (org account)
target_source: https://github.com/dragoonDorise/EmuDeck
install:
detect:
- os: linux
method: config_file
config: "$HOME/.config/EmuDeck/settings.sh"
parse_key: emulationPath
bios_subdir: bios
- os: linux
method: path_exists
path: "$HOME/Emulation/bios"
- os: windows
method: config_file
config: "%APPDATA%\\EmuDeck\\settings.ps1"
parse_key: "$emulationPath"
bios_subdir: bios
- os: linux
method: config_file
config: $HOME/.config/EmuDeck/settings.sh
parse_key: emulationPath
bios_subdir: bios
- os: linux
method: path_exists
path: $HOME/Emulation/bios
- os: windows
method: config_file
config: '%APPDATA%\EmuDeck\settings.ps1'
parse_key: $emulationPath
bios_subdir: bios
standalone_copies:
- file: prod.keys
targets:
linux:
- "$HOME/.local/share/yuzu/keys"
- "$HOME/.local/share/eden/keys"
- "$HOME/.config/Ryujinx/system"
windows:
- "%APPDATA%\\yuzu\\keys"
- "%APPDATA%\\eden\\keys"
- file: aes_keys.txt
targets:
linux:
- "$HOME/Emulation/bios/citra/keys"
- file: prod.keys
targets:
linux:
- $HOME/.local/share/yuzu/keys
- $HOME/.local/share/eden/keys
- $HOME/.config/Ryujinx/system
windows:
- '%APPDATA%\yuzu\keys'
- '%APPDATA%\eden\keys'
- file: aes_keys.txt
targets:
linux:
- $HOME/Emulation/bios/citra/keys
lakka:
config: lakka.yml
status: active
logo: "https://raw.githubusercontent.com/libretro/retroarch-assets/master/src/xmb/flatui/lakka.svg"
logo: https://raw.githubusercontent.com/libretro/retroarch-assets/master/src/xmb/flatui/lakka.svg
scraper: libretro
inherits_from: retroarch
cores: all_libretro
schedule: weekly
target_scraper: lakka_targets
target_source: "https://buildbot.libretro.com/nightly/"
target_source: https://buildbot.libretro.com/nightly/
install:
detect:
- os: linux
method: os_release
id: lakka
bios_path: /storage/system
- os: linux
method: os_release
id: lakka
bios_path: /storage/system
retrodeck:
config: retrodeck.yml
status: active
logo: "https://raw.githubusercontent.com/RetroDECK/RetroDECK/main/res/icon.svg"
logo: https://raw.githubusercontent.com/RetroDECK/RetroDECK/main/res/icon.svg
scraper: retrodeck
source_url: "https://github.com/RetroDECK/components"
source_url: https://github.com/RetroDECK/components
source_format: github_component_manifests
hash_type: md5
schedule: monthly
cores: [azahar, cemu, dolphin, duckstation, gzdoom, mame, melonds, openbor, pcsx2, pico-8, ppsspp, primehack, retroarch, rpcs3, ruffle, solarus, vita3k, xemu, xroar]
cores:
- azahar
- cemu
- clk
- dolphin
- duckstation
- gsplus
- gzdoom
- mame
- melonds
- openbor
- pcsx2
- pico-8
- ppsspp
- primehack
- retroarch
- rpcs3
- ruffle
- solarus
- vita3k
- xemu
- xroar
target_scraper: null
target_source: null
# Each component/<name>/component_manifest.json declares BIOS requirements
# Scraper enumerates top-level dirs via GitHub API, fetches each manifest directly
install:
detect:
- os: linux
method: path_exists
path: "$HOME/.var/app/net.retrodeck.retrodeck"
bios_path: "$HOME/retrodeck/bios"
- os: linux
method: path_exists
path: $HOME/.var/app/net.retrodeck.retrodeck
bios_path: $HOME/retrodeck/bios
romm:
config: romm.yml
status: active
logo: "https://avatars.githubusercontent.com/u/168586850"
logo: https://avatars.githubusercontent.com/u/168586850
scraper: romm
source_url: "https://raw.githubusercontent.com/rommapp/romm/master/backend/models/fixtures/known_bios_files.json"
source_url: https://raw.githubusercontent.com/rommapp/romm/master/backend/models/fixtures/known_bios_files.json
source_format: json
hash_type: sha1
schedule: monthly
inherits_from: emulatorjs # cores inherited from emulatorjs.yml
inherits_from: emulatorjs
target_scraper: null
target_source: null
install:
detect:
- os: linux
method: path_exists
path: /romm/library/bios
- os: linux
method: path_exists
path: /romm/library/bios
cores:
- atari800
- clk
- directxbox
- dolphin
- dolphin_launcher
- ecwolf
- ep128emu
- ep128emu_core
- freej2me
- hatari
- ishiiruka
- lrps2
- minivmac
- nekop2
- np2kai
- o2em
- pcsx2
- play
- pokemini
- primehack
- px68k
- scummvm
- squirreljme
- x1
- xemu
retropie:
config: retropie.yml
status: archived # Last release: v4.8 (March 2022) - no update in 4 years
logo: "https://avatars.githubusercontent.com/u/11378204"
status: archived
logo: https://avatars.githubusercontent.com/u/11378204
scraper: null
cores: all_libretro
schedule: null
target_scraper: retropie_targets
target_source: "https://retropie.org.uk/stats/pkgflags/"
target_source: https://retropie.org.uk/stats/pkgflags/
install:
detect:
- os: linux
method: path_exists
path: "$HOME/RetroPie/BIOS"
- os: linux
method: path_exists
path: $HOME/RetroPie/BIOS
bizhawk:
config: bizhawk.yml
status: active
logo: "https://raw.githubusercontent.com/TASEmulators/BizHawk/master/Assets/bizhawk.ico"
logo: https://raw.githubusercontent.com/TASEmulators/BizHawk/master/Assets/bizhawk.ico
scraper: bizhawk
source_url: "https://raw.githubusercontent.com/TASEmulators/BizHawk/master/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs"
source_url: https://raw.githubusercontent.com/TASEmulators/BizHawk/master/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs
source_format: csharp_firmware_database
hash_type: sha1
schedule: monthly
cores: [gambatte, mgba, sameboy, melonds, snes9x, bsnes, beetle_psx, beetle_saturn, beetle_pce, beetle_pcfx, beetle_wswan, beetle_vb, beetle_ngp, opera, stella, picodrive, ppsspp, handy, quicknes, genesis_plus_gx, ares, mupen64plus_next, puae, prboom, virtualjaguar, vice_x64, mame]
cores:
- applewin
- ares
- azahar
- beetle_ngp
- beetle_pce
- beetle_pcfx
- beetle_psx
- beetle_saturn
- beetle_vb
- beetle_wswan
- bsnes
- citra
- citra2018
- citra_canary
- clk
- fbneo
- freechaf
- freeintv
- gambatte
- genesis_plus_gx
- handy
- mame
- melonds
- mgba
- mupen64plus_next
- numero
- o2em
- opera
- panda3ds
- picodrive
- ppsspp
- prboom
- prosystem
- puae
- quicknes
- sameboy
- snes9x
- stella
- trident
- vecx
- vice_x64
- virtualjaguar
target_scraper: null
target_source: null
install:
detect:
- os: windows
method: path_exists
path: "%USERPROFILE%\\BizHawk\\Firmware"
- os: linux
method: path_exists
path: "$HOME/.config/BizHawk/Firmware"
- os: windows
method: path_exists
path: '%USERPROFILE%\BizHawk\Firmware'
- os: linux
method: path_exists
path: $HOME/.config/BizHawk/Firmware

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,8 @@ dat_version: v1.19.0
homepage: https://www.retroarch.com
source: https://github.com/libretro/libretro-database/blob/master/dat/System.dat
base_destination: system
cores: all_libretro
hash_type: sha1
verification_mode: existence
case_insensitive_fs: true
systems:
3do:
files:
@@ -102,6 +100,7 @@ systems:
md5: 35fa1a1ebaaeea286dc5cd15487c13ea
crc32: d5cbc509
size: 1048576
native_id: 3DO Company, The - 3DO
core: opera
manufacturer: Panasonic|GoldStar|Sanyo
docs: https://docs.libretro.com/library/opera/
@@ -135,6 +134,7 @@ systems:
md5: 25629dfe870d097469c217b95fdc1c95
crc32: 1fe22ecd
size: 16384
native_id: Amstrad - CPC
arcade:
files:
- name: bubsys.zip
@@ -249,6 +249,10 @@ systems:
- name: aes.zip
destination: aes.zip
required: true
native_id: Arcade
core: fbneo
manufacturer: Various
docs: https://docs.libretro.com/library/fbneo/
data_directories:
- ref: fbneo-hiscore
destination: ''
@@ -256,9 +260,6 @@ systems:
destination: fbneo
- ref: fbneo-samples
destination: fbneo
core: fbneo
manufacturer: Various
docs: https://docs.libretro.com/library/fbneo/
atari-400-800:
files:
- name: ATARIBAS.ROM
@@ -303,6 +304,7 @@ systems:
md5: d7eb37aec6960cba36bc500e0e5d00bc
crc32: bdca01fb
size: 8192
native_id: Atari - 400-800
atari-5200:
files:
- name: 5200.rom
@@ -312,6 +314,7 @@ systems:
md5: 281f20ea4320404ec820fb7ec0693b38
crc32: 4248d3e3
size: 2048
native_id: Atari - 5200
core: a5200
manufacturer: Atari
docs: https://docs.libretro.com/library/a5200/
@@ -331,6 +334,7 @@ systems:
md5: 0763f1ffb006ddbe32e52d497ee848ae
crc32: 5d13730c
size: 4096
native_id: Atari - 7800
core: prosystem
manufacturer: Atari
docs: https://docs.libretro.com/library/prosystem/
@@ -343,6 +347,7 @@ systems:
md5: fcd403db69f54290b51035d82f835e7b
crc32: 0d973c9d
size: 512
native_id: Atari - Lynx
core: handy
manufacturer: Atari
docs: https://docs.libretro.com/library/handy/
@@ -355,6 +360,7 @@ systems:
md5: c1c57ce48e8ee4135885cee9e63a68a2
crc32: d3c32283
size: 196608
native_id: Atari - ST
core: hatari
manufacturer: Atari
docs: https://docs.libretro.com/library/hatari/
@@ -376,6 +382,7 @@ systems:
- name: bioscv.rom
destination: bioscv.rom
required: true
native_id: Coleco - ColecoVision
commodore-amiga:
files:
- name: kick33180.A500
@@ -462,6 +469,7 @@ systems:
md5: bb72565701b1b6faece07d68ea5da639
crc32: 87746be2
size: 524288
native_id: Commodore - Amiga
core: puae
manufacturer: Commodore
docs: https://docs.libretro.com/library/puae/
@@ -510,6 +518,7 @@ systems:
destination: scpu-dos-2.04.bin
required: true
md5: b2869f8678b8b274227f35aad26ba509
native_id: Commodore - C128
core: vice_x128
manufacturer: Commodore
docs: https://docs.libretro.com/library/vice_x128/
@@ -522,6 +531,7 @@ systems:
md5: a2e891e330d146c4046c2b622fc31462
crc32: 683ed4ad
size: 5763199
native_id: Dinothawr
dos:
files:
- name: MT32_CONTROL.ROM
@@ -552,6 +562,7 @@ systems:
md5: 08cdcfa0ed93e9cb16afa76e6ac5f0a4
crc32: 4b961eba
size: 1048576
native_id: DOS
elektronika-bk:
files:
- name: B11M_BOS.ROM
@@ -610,6 +621,7 @@ systems:
md5: 95f8c41c6abf7640e35a6a03cecebd01
crc32: 26c6e8a0
size: 8192
native_id: Elektronika - BK-0010/BK-0011(M)
enterprise-64-128:
files:
- name: hun.rom
@@ -696,6 +708,7 @@ systems:
md5: 55af78f877a21ca45eb2df68a74fcc60
crc32: c099a5e3
size: 65536
native_id: Enterprise - 64/128
includes:
- ep128emu
epoch-scv:
@@ -707,6 +720,7 @@ systems:
md5: 635a978fd40db9a18ee44eff449fc126
crc32: 7ac06182
size: 4096
native_id: EPOCH/YENO Super Cassette Vision
fairchild-channel-f:
files:
- name: sl31253.bin
@@ -730,6 +744,7 @@ systems:
md5: 95d339631d867c8f1d15a5f2ec26069d
crc32: 015c1e38
size: 1024
native_id: Fairchild Channel F
doom:
files:
- name: prboom.wad
@@ -739,6 +754,7 @@ systems:
md5: 72ae1b47820fcc93cc0df9c428d0face
crc32: a5751b99
size: 143312
native_id: Id Software - Doom
j2me:
files:
- name: freej2me-lr.jar
@@ -762,6 +778,7 @@ systems:
md5: 29a92d0867da2917275b7c6c805d256f
crc32: ffb98ffa
size: 552039
native_id: J2ME
core: freej2me
manufacturer: Java
docs: https://docs.libretro.com/library/freej2me/
@@ -774,6 +791,7 @@ systems:
md5: 66223be1497460f1e60885eeb35e03cc
crc32: 4df6d054
size: 262144
native_id: MacII
magnavox-odyssey2:
files:
- name: o2rom.bin
@@ -804,6 +822,7 @@ systems:
md5: 279008e4a0db2dc5f1c048853b033828
crc32: 11647ca5
size: 1024
native_id: Magnavox - Odyssey2
core: o2em
manufacturer: Magnavox|Philips
docs: https://docs.libretro.com/library/o2em/
@@ -823,6 +842,7 @@ systems:
md5: 0cd5946c6473e42e8e4c2137785e427f
crc32: 683a4158
size: 2048
native_id: Mattel - Intellivision
data_directories:
- ref: freeintv-overlays
destination: freeintv_overlays
@@ -933,6 +953,7 @@ systems:
md5: 279efd1eae0d358eecd4edc7d9adedf3
crc32: ab6874f8
size: 16640
native_id: Microsoft - MSX
core: bluemsx
manufacturer: Spectravideo|Philips|Al Alamiah|Sony|Sanyo|Mitsubishi|Toshiba|Hitachi|Panasonic|Canon|Casio|Pioneer|Fujitsu|Yamaha|JVC|Kyocera|GoldStar|Samsung|Daewoo|Gradiente|Sharp|Talent|NTT|ACVS/CIEL|DDX|AGE
Labs
@@ -991,6 +1012,7 @@ systems:
md5: 0754f903b52e3b3342202bdafb13efa5
crc32: 2b5b75fe
size: 262144
native_id: NEC - PC Engine - TurboGrafx 16 - SuperGrafx
core: mednafen_pce_fast
manufacturer: NEC
docs: https://docs.libretro.com/library/mednafen_pce_fast/
@@ -1073,6 +1095,7 @@ systems:
md5: 524473c1a5a03b17e21d86a0408ff827
crc32: fe9f57f2
size: 16384
native_id: NEC - PC-98
core: np2kai
manufacturer: NEC
docs: https://docs.libretro.com/library/np2kai/
@@ -1115,6 +1138,7 @@ systems:
md5: e2fb7c7220e3a7838c2dd7e401a7f3d8
crc32: 236102c9
size: 1048576
native_id: NEC - PC-FX
core: mednafen_pcfx
manufacturer: NEC
docs: https://docs.libretro.com/library/mednafen_pcfx/
@@ -1134,6 +1158,7 @@ systems:
md5: 7f98d77d7a094ad7d069b74bd553ec98
crc32: 4c514089
size: 24592
native_id: Nintendo - Famicom Disk System
nintendo-gb:
files:
- name: dmg_boot.bin
@@ -1150,6 +1175,7 @@ systems:
md5: 32fbbd84168d3482956eb3c5051637f5
crc32: 59c8598e
size: 256
native_id: Nintendo - Gameboy
core: gambatte
manufacturer: Nintendo
docs: https://docs.libretro.com/library/gambatte/
@@ -1162,6 +1188,7 @@ systems:
md5: a860e8c0b6d573d191e4ec7db1b1e4f6
crc32: '81977335'
size: 16384
native_id: Nintendo - Game Boy Advance
core: gpsp
manufacturer: Nintendo
docs: https://docs.libretro.com/library/gpsp/
@@ -1181,6 +1208,7 @@ systems:
md5: dbfce9db9deaa2567f6a84fde55f9680
crc32: 41884e46
size: 2304
native_id: Nintendo - Gameboy Color
nintendo-gamecube:
files:
- name: gc-dvd-20010608.bin
@@ -1274,6 +1302,7 @@ systems:
- name: font_japanese.bin
destination: dolphin-emu/Sys/GC/font_japanese.bin
required: false
native_id: Nintendo - GameCube
core: dolphin
manufacturer: Nintendo
docs: https://docs.libretro.com/library/dolphin/
@@ -1289,6 +1318,7 @@ systems:
md5: 8d3d9f294b6e174bc7b1d2fd1c727530
crc32: 7f933ce2
size: 4194304
native_id: Nintendo - Nintendo 64DD
nintendo-ds:
files:
- name: bios7.bin
@@ -1324,6 +1354,7 @@ systems:
- name: dsi_nand.bin
destination: dsi_nand.bin
required: true
native_id: Nintendo - Nintendo DS
core: desmume
manufacturer: Nintendo
docs: https://docs.libretro.com/library/desmume/
@@ -1332,10 +1363,11 @@ systems:
- name: NstDatabase.xml
destination: NstDatabase.xml
required: true
sha1: f92312bae56e29c5bf00a5103105fce78472bf5c
md5: 0ee6cbdc6f5c96ce9c8aa5edb59066f4
crc32: 0e4d552b
sha1: 26322f182540211e9b5e3647675b7c593706ae2b
md5: 7bfe8c0540ed4bd6a0f1e2a0f0118ced
crc32: ebb2196c
size: 1009534
native_id: Nintendo - Nintendo Entertainment System
core: fceumm
manufacturer: Nintendo
docs: https://docs.libretro.com/library/fceumm/
@@ -1348,6 +1380,7 @@ systems:
md5: 1e4fb124a3a886865acb574f388c803d
crc32: aed3c14d
size: 4096
native_id: Nintendo - Pokemon Mini
nintendo-satellaview:
files:
- name: BS-X.bin
@@ -1371,6 +1404,7 @@ systems:
md5: 4ed9648505ab33a4daec93707b16caba
crc32: 8c573c7e
size: 1048576
native_id: Nintendo - Satellaview
nintendo-sufami-turbo:
files:
- name: STBIOS.bin
@@ -1380,6 +1414,7 @@ systems:
md5: d3a44ba7d42a74d3ac58cb9c14c6a5ca
crc32: 9b4ca911
size: 262144
native_id: Nintendo - SuFami Turbo
nintendo-sgb:
files:
- name: SGB1.sfc
@@ -1441,6 +1476,7 @@ systems:
- name: sgb.boot.rom
destination: sgb.boot.rom
required: false
native_id: Nintendo - Super Game Boy
nintendo-snes:
files:
- name: cx4.data.rom
@@ -1562,6 +1598,7 @@ systems:
md5: dda40ccd57390c96e49d30a041f9a9e7
crc32: f73d5e10
size: 131072
native_id: Nintendo - Super Nintendo Entertainment System
core: bsnes
manufacturer: Nintendo
docs: https://docs.libretro.com/library/bsnes/
@@ -1588,6 +1625,7 @@ systems:
md5: 279008e4a0db2dc5f1c048853b033828
crc32: 11647ca5
size: 1024
native_id: Phillips - Videopac+
sega-dreamcast:
files:
- name: dc_boot.bin
@@ -1611,6 +1649,7 @@ systems:
md5: 0a93f7940c455905bea6e392dfde92a4
crc32: c611b498
size: 131072
native_id: Sega - Dreamcast
core: flycast
manufacturer: Sega
docs: https://docs.libretro.com/library/flycast/
@@ -1668,6 +1707,7 @@ systems:
- name: segasp.zip
destination: dc/segasp.zip
required: true
native_id: Sega - Dreamcast-based Arcade
sega-game-gear:
files:
- name: bios.gg
@@ -1677,6 +1717,7 @@ systems:
md5: 672e104c3be3a238301aceffc3b23fd6
crc32: 0ebea9d4
size: 1024
native_id: Sega - Game Gear
sega-master-system:
files:
- name: bios.sms
@@ -1707,6 +1748,7 @@ systems:
md5: 840481177270d5642a14ca71ee72844c
crc32: 0072ed54
size: 8192
native_id: Sega - Master System - Mark III
sega-mega-cd:
files:
- name: bios_CD_E.bin
@@ -1730,6 +1772,7 @@ systems:
md5: 2efd74e3232ff260e371b99f84024f7f
crc32: c6d10268
size: 131072
native_id: Sega - Mega CD - Sega CD
sega-mega-drive:
files:
- name: areplay.bin
@@ -1774,6 +1817,7 @@ systems:
md5: b4e76e416b887f4e7413ba76fa735f16
crc32: 4dcfd55c
size: 262144
native_id: Sega - Mega Drive - Genesis
core: genesis_plus_gx
manufacturer: Sega
docs: https://docs.libretro.com/library/genesis_plus_gx/
@@ -1859,6 +1903,7 @@ systems:
- name: stvbios.zip
destination: kronos/stvbios.zip
required: true
native_id: Sega - Saturn
core: kronos
manufacturer: Sega
docs: https://docs.libretro.com/library/kronos/
@@ -1880,6 +1925,7 @@ systems:
md5: 851e4a5936f17d13f8c39a980cf00d77
crc32: e3995a57
size: 2048
native_id: Sharp - X1
core: x1
manufacturer: Sharp
docs: https://docs.libretro.com/library/x1/
@@ -1920,6 +1966,7 @@ systems:
md5: 0617321daa182c3f3d6f41fd02fb3275
crc32: 00eeb408
size: 131072
native_id: Sharp - X68000
core: px68k
manufacturer: Sharp
docs: https://docs.libretro.com/library/px68k/
@@ -2270,6 +2317,7 @@ systems:
md5: 85fede415f4294cc777517d7eada482e
crc32: 2cbe8995
size: 32768
native_id: Sinclair - ZX Spectrum
core: fuse
manufacturer: Sinclair|Amstrad
docs: https://docs.libretro.com/library/fuse/
@@ -2352,6 +2400,7 @@ systems:
md5: 08ca8b2dba6662e8024f9e789711c6fc
crc32: ff3abc59
size: 524288
native_id: SNK - NeoGeo CD
core: neocd
manufacturer: SNK
docs: https://docs.libretro.com/library/neocd/
@@ -2511,6 +2560,7 @@ systems:
md5: 81bbe60ba7a3d1cea1d48c14cbcc647b
crc32: 2f53b852
size: 524288
native_id: Sony - PlayStation
core: duckstation
manufacturer: Sony
docs: https://docs.libretro.com/library/duckstation/
@@ -3027,6 +3077,7 @@ systems:
md5: d3e81e95db25f5a86a7b7474550a2155
crc32: 4e8c160c
size: 4194304
native_id: Sony - PlayStation 2
sony-psp:
files:
- name: ppge_atlas.zim
@@ -3036,6 +3087,7 @@ systems:
md5: 866855cc330b9b95cc69135fb7b41d38
crc32: 7b57fa78
size: 666530
native_id: Sony - PlayStation Portable
core: ppsspp
manufacturer: Sony
docs: https://docs.libretro.com/library/ppsspp/
@@ -3065,6 +3117,7 @@ systems:
md5: d4448d09bbfde687c04f9e3310e023ab
crc32: 4bf05697
size: 262144
native_id: Texas Instruments TI-83
core: numero
manufacturer: Texas Instruments
docs: https://docs.libretro.com/library/numero/
@@ -3098,6 +3151,7 @@ systems:
md5: 88dc7876d584f90e4106f91444ab23b7
crc32: 1466aed4
size: 16384
native_id: Videoton - TV Computer
wolfenstein-3d:
files:
- name: ecwolf.pk3
@@ -3107,6 +3161,7 @@ systems:
md5: c011b428819eea4a80b455c245a5a04d
crc32: 26dc3fba
size: 178755
native_id: Wolfenstein 3D
scummvm:
files:
- name: scummvm.zip
@@ -3116,6 +3171,7 @@ systems:
md5: a17e0e0150155400d8cced329563d9c8
crc32: a93f1c4b
size: 9523360
native_id: ScummVM
core: scummvm
manufacturer: Various
docs: https://docs.libretro.com/library/scummvm/
@@ -3141,3 +3197,5 @@ systems:
core: xrick
manufacturer: Other
docs: https://docs.libretro.com/library/xrick/
case_insensitive_fs: true
cores: all_libretro

View File

@@ -1,170 +1,10 @@
platform: RetroBat
version: 7.5.3
homepage: "https://www.retrobat.org"
source: "https://raw.githubusercontent.com/RetroBat-Official/emulatorlauncher/master/batocera-systems/Resources/batocera-systems.json"
homepage: https://www.retrobat.org
source: https://raw.githubusercontent.com/RetroBat-Official/emulatorlauncher/master/batocera-systems/Resources/batocera-systems.json
base_destination: bios
hash_type: md5
verification_mode: md5
case_insensitive_fs: true
cores:
- 81
- a5200
- abuse
- arduous
- atari800
- azahar
- bennugd
- bk
- bluemsx
- bsnes
- bstone
- cannonball
- cap32
- catacombgl
- cdogs
- cemu
- cgenius
- citron
- clk
- corsixth
- demul
- devilutionx
- dhewm3
- dice
- dolphin
- dosbox_pure
- dxx-rebirth
- easyrpg
- ecwolf
- eduke32
- eka2l1
- emuscv
- etlegacy
- fake08
- fallout1-ce
- fallout2-ce
- fbneo
- fceumm
- flatpak
- flycast
- freechaf
- freeintv
- fury
- fuse
- gambatte
- gearsystem
- genesisplusgx
- glide64mk2
- gong
- gsplus
- gw
- gzdoom
- hatari
- hcl
- hurrican
- hypseus-singe
- ikemen
- ioquake3
- iortcw
- jazz2-native
- lindbergh-loader
- lowresnx
- lutro
- mame
- mame078plus
- mednafen_lynx
- mednafen_ngp
- mednafen_supergrafx
- mednafen_wswan
- melonds
- mgba
- minivmac
- model2emu
- moonlight
- mrboom
- neocd
- np2kai
- nxengine
- o2em
- odcommander
- openbor6412
- openjazz
- openjk
- openjkdf2
- openmohaa
- opera
- pce_fast
- pcfx
- pcsx2
- pcsx_rearmed
- pd777
- picodrive
- play
- pokemini
- potator
- ppsspp
- prboom
- prosystem
- puae
- px68k
- pygame
- pyxel
- quasi88
- raze
- reminiscence
- rpcs3
- ruffle
- samcoupe
- sameduck
- scummvm
- sdlpop
- sh
- shadps4
- snes9x
- solarus
- sonic2013
- sonic3-air
- sonic-mania
- steam
- stella
- superbroswar
- supermodel
- taradino
- tgbdual
- theforceengine
- theodore
- thextech
- tic80
- tr1x
- tr2x
- tsugaru
- tyrian
- tyrquake
- uqm
- uzem
- vb
- vecx
- vice_x64
- vircon32
- virtualjaguar
- vita3k
- vox_official
- vpinball
- wasm4
- wine-tkg
- x1
- x128
- x16emu
- xash3d_fwgs
- xemu
- xenia-canary
- xpet
- xplus4
- xrick
- xvic
- yabasanshiro
- yquake2
- zc210
systems:
3do:
files:
@@ -425,12 +265,12 @@ systems:
md5: 281f20ea4320404ec820fb7ec0693b38
atari7800:
files:
- name: "7800 BIOS (E).rom"
destination: "7800 BIOS (E).rom"
- name: 7800 BIOS (E).rom
destination: 7800 BIOS (E).rom
required: true
md5: 397bb566584be7b9764e7a68974c4263
- name: "7800 BIOS (U).rom"
destination: "7800 BIOS (U).rom"
- name: 7800 BIOS (U).rom
destination: 7800 BIOS (U).rom
required: true
md5: 0763f1ffb006ddbe32e52d497ee848ae
- name: ProSystem.dat
@@ -548,6 +388,40 @@ systems:
- name: bbcmc_flop.xml
destination: mame/hash/bbcmc_flop.xml
required: true
bk:
files:
- name: B11M_BOS.ROM
destination: bk/B11M_BOS.ROM
required: true
md5: fe4627d1e3a1535874085050733263e7
- name: B11M_EXT.ROM
destination: bk/B11M_EXT.ROM
required: true
md5: dc52f365d56fa1951f5d35b1101b9e3f
- name: BAS11M_0.ROM
destination: bk/BAS11M_0.ROM
required: true
md5: 946f6f23ded03c0e26187f0b3ca75993
- name: BAS11M_1.ROM
destination: bk/BAS11M_1.ROM
required: true
md5: 1e6637f32aa7d1de03510030cac40bcf
- name: DISK_327.ROM
destination: bk/DISK_327.ROM
required: true
md5: 5015228eeeb238e65da8edcd1b6dfac7
- name: BASIC10.ROM
destination: bk/BASIC10.ROM
required: true
md5: 3fa774326d75410a065659aea80252f0
- name: FOCAL10.ROM
destination: bk/FOCAL10.ROM
required: true
md5: 5737f972e8638831ab71e9139abae052
- name: MONIT10.ROM
destination: bk/MONIT10.ROM
required: true
md5: 95f8c41c6abf7640e35a6a03cecebd01
loopy:
files:
- name: casloopy.zip
@@ -845,34 +719,30 @@ systems:
md5: a6f31483d1da4558cc19025e21f95c1d
jaguar:
files:
- name: "[BIOS] Atari Jaguar (World).j64"
destination: "[BIOS] Atari Jaguar (World).j64"
- name: '[BIOS] Atari Jaguar (World).j64'
destination: '[BIOS] Atari Jaguar (World).j64'
required: true
md5: bcfe348c565d9dedb173822ee6850dea
laseractive:
files:
- name: "[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin"
destination: "laseractive/[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin"
- name: '[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin'
destination: laseractive/[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin
required: true
md5: f69f173b251d8bf7649b10a9167a10bf
- name: "[BIOS] LaserActive PAC-N10 (US) (v1.02).bin"
destination: "laseractive/[BIOS] LaserActive PAC-N10 (US) (v1.02).bin"
- name: '[BIOS] LaserActive PAC-N10 (US) (v1.02).bin'
destination: laseractive/[BIOS] LaserActive PAC-N10 (US) (v1.02).bin
required: true
md5: f0fb8a4605ac7eefbafd4f2d5a793cc8
- name: "[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin"
destination: "laseractive/[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin"
- name: '[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin'
destination: laseractive/[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin
required: true
md5: 761fea207d0eafd4cfd78da7c44cac88
- name: "Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer - Sega)(JP)(en-ja).bin"
destination: "laseractive/Pioneer LaserActive Sega PAC Boot ROM v1.02 (1993)(Pioneer\
\ - Sega)(JP)(en-ja).bin"
- name: '[BIOS] LaserActive PAC-S10 (US) (v1.04).bin'
destination: laseractive/[BIOS] LaserActive PAC-S10 (US) (v1.04).bin
required: true
md5: a5a2f9aae57d464bc66b80ee79c3da6e
- name: "Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin"
destination: "laseractive/Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer\
\ - Sega)(US).bin"
- name: '[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin'
destination: laseractive/[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin
required: true
md5: 0e7393cd0951d6dde818fcd4cd819466
lynx:
files:
- name: lynxboot.img
@@ -916,11 +786,11 @@ systems:
required: true
mastersystem:
files:
- name: "[BIOS] Sega Master System (USA, Europe) (v1.3).sms"
destination: "[BIOS] Sega Master System (USA, Europe) (v1.3).sms"
- name: '[BIOS] Sega Master System (USA, Europe) (v1.3).sms'
destination: '[BIOS] Sega Master System (USA, Europe) (v1.3).sms'
required: true
- name: "[BIOS] Sega Master System (Japan) (v2.1).sms"
destination: "[BIOS] Sega Master System (Japan) (v2.1).sms"
- name: '[BIOS] Sega Master System (Japan) (v2.1).sms'
destination: '[BIOS] Sega Master System (Japan) (v2.1).sms'
required: true
msx:
files:
@@ -1205,13 +1075,13 @@ systems:
md5: 64a95a4a884cf4cc15a566b856603193
ngp:
files:
- name: "[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"
destination: "[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"
- name: '[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp'
destination: '[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp'
required: true
ngpc:
files:
- name: "[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"
destination: "[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"
- name: '[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp'
destination: '[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp'
required: true
odyssey2:
files:
@@ -1319,7 +1189,7 @@ systems:
destination: bios.min
required: true
md5: 1e4fb124a3a886865acb574f388c803d
ps2:
sony-playstation-2:
files:
- name: ps2-0230a-20080220.bin
destination: pcsx2/bios/ps2-0230a-20080220.bin

View File

@@ -191,6 +191,37 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
system.setdefault("files", []).append(gf)
existing.add(key)
# Merge metadata from _registry.yml. The registry is our curated source;
# the scraped YAML may be incomplete (missing cores, metadata fields).
# Registry fields supplement (not replace) the scraped config.
registry_path = os.path.join(platforms_dir, "_registry.yml")
if os.path.exists(registry_path):
reg_real = os.path.realpath(registry_path)
if reg_real not in _shared_yml_cache:
with open(registry_path) as f:
_shared_yml_cache[reg_real] = yaml.safe_load(f) or {}
reg = _shared_yml_cache[reg_real]
reg_entry = reg.get("platforms", {}).get(platform_name, {})
# Merge cores (union for lists, override for all_libretro)
reg_cores = reg_entry.get("cores")
if reg_cores is not None:
cfg_cores = config.get("cores")
if reg_cores == "all_libretro":
config["cores"] = "all_libretro"
elif isinstance(reg_cores, list) and isinstance(cfg_cores, list):
merged_set = {str(c) for c in cfg_cores} | {str(c) for c in reg_cores}
config["cores"] = sorted(merged_set)
elif isinstance(reg_cores, list) and cfg_cores is None:
config["cores"] = reg_cores
# Merge all registry fields absent from config (except cores,
# handled above with union logic). No hardcoded list — any field
# added to the registry is automatically available in the config.
for key, val in reg_entry.items():
if key != "cores" and key not in config:
config[key] = val
_platform_config_cache[cache_key] = config
return config
@@ -522,6 +553,25 @@ def resolve_local_file(
if fn.casefold() in basename_targets:
return os.path.join(root, fn), "data_dir"
# Agnostic fallback: for filename-agnostic files, find any DB file
# matching the system path prefix and size criteria
if file_entry.get("agnostic"):
agnostic_prefix = file_entry.get("agnostic_path_prefix", "")
min_size = file_entry.get("min_size", 0)
max_size = file_entry.get("max_size", float("inf"))
exact_size = file_entry.get("size")
if exact_size and not min_size:
min_size = exact_size
max_size = exact_size
if agnostic_prefix:
for _sha1, entry in files_db.items():
path = entry.get("path", "")
if not path.startswith(agnostic_prefix):
continue
size = entry.get("size", 0)
if min_size <= size <= max_size and os.path.exists(path):
return path, "agnostic_fallback"
return None, "not_found"
@@ -735,6 +785,15 @@ def resolve_platform_cores(
for c in core_set
if c in core_to_profile
}
# Support "all_libretro" as a list element: combines all libretro
# profiles with explicitly listed standalone cores (e.g. RetroDECK
# ships RetroArch + standalone emulators)
if "all_libretro" in core_set or "retroarch" in core_set:
result |= {
name for name, p in profiles.items()
if "libretro" in p.get("type", "")
and p.get("type") != "alias"
}
else:
# Fallback: system ID intersection with normalization
norm_plat_systems = {_norm_system_id(s) for s in config.get("systems", {})}
@@ -882,6 +941,72 @@ def filter_systems_by_target(
return filtered
def expand_platform_declared_names(config: dict, db: dict) -> set[str]:
"""Build set of file names declared by a platform config.
Enriches the set with canonical names and aliases from the database
by resolving each platform file's MD5 through by_md5. This handles
cases where a platform declares a file under a different name than
the emulator profile (e.g. Batocera ROM1 vs gsplus ROM).
"""
declared: set[str] = set()
by_md5 = db.get("indexes", {}).get("by_md5", {})
files_db = db.get("files", {})
for system in config.get("systems", {}).values():
for fe in system.get("files", []):
name = fe.get("name", "")
if name:
declared.add(name)
md5 = fe.get("md5", "")
if not md5:
continue
# Skip multi-hash and zippedFile entries (inner ROM MD5, not file MD5)
if "," in md5 or fe.get("zippedFile"):
continue
sha1 = by_md5.get(md5.lower())
if not sha1:
continue
entry = files_db.get(sha1, {})
db_name = entry.get("name", "")
if db_name:
declared.add(db_name)
for alias in entry.get("aliases", []):
declared.add(alias)
return declared
import re
_TIMESTAMP_PATTERNS = [
re.compile(r'"generated_at":\s*"[^"]*"'), # database.json
re.compile(r'\*Auto-generated on [^*]*\*'), # README.md
re.compile(r'\*Generated on [^*]*\*'), # docs site pages
]
def write_if_changed(path: str, content: str) -> bool:
"""Write content to path only if the non-timestamp content differs.
Compares new and existing content after stripping timestamp lines.
Returns True if the file was written, False if skipped (unchanged).
"""
if os.path.exists(path):
with open(path) as f:
existing = f.read()
if _strip_timestamps(existing) == _strip_timestamps(content):
return False
with open(path, "w") as f:
f.write(content)
return True
def _strip_timestamps(text: str) -> str:
"""Remove known timestamp patterns for content comparison."""
result = text
for pattern in _TIMESTAMP_PATTERNS:
result = pattern.sub("", result)
return result
# Validation and mode filtering -extracted to validation.py for SoC.
# Re-exported below for backward compatibility.

View File

@@ -16,15 +16,27 @@ from exporter import discover_exporters
OUTPUT_FILENAMES: dict[str, str] = {
"retroarch": "System.dat",
"lakka": "System.dat",
"retropie": "System.dat",
"batocera": "batocera-systems",
"recalbox": "es_bios.xml",
"retrobat": "batocera-systems.json",
"emudeck": "checkBIOS.sh",
"retrodeck": "component_manifest.json",
"romm": "known_bios_files.json",
}
def output_filename(platform: str) -> str:
"""Return the native output filename for a platform."""
return OUTPUT_FILENAMES.get(platform, f"{platform}_bios.dat")
def output_path(platform: str, output_dir: str) -> str:
"""Return the full output path for a platform's native export.
Each platform gets its own subdirectory to avoid filename collisions
(e.g. retroarch, lakka, retropie all produce System.dat).
"""
filename = OUTPUT_FILENAMES.get(platform, f"{platform}_bios.dat")
plat_dir = Path(output_dir) / platform
plat_dir.mkdir(parents=True, exist_ok=True)
return str(plat_dir / filename)
def run(
@@ -35,8 +47,6 @@ def run(
) -> int:
"""Export truth to native formats, return exit code."""
exporters = discover_exporters()
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
errors = 0
@@ -60,7 +70,7 @@ def run(
except (FileNotFoundError, OSError):
pass
dest = str(output_path / output_filename(platform))
dest = output_path(platform, output_dir)
exporter = exporter_cls()
exporter.export(truth_data, dest, scraped_data=scraped)

View File

@@ -25,3 +25,37 @@ class BaseExporter(ABC):
@abstractmethod
def validate(self, truth_data: dict, output_path: str) -> list[str]:
"""Validate exported file against truth data, return list of issues."""
@staticmethod
def _is_pattern(name: str) -> bool:
"""Check if a filename is a placeholder pattern (not a real file)."""
return "<" in name or ">" in name or "*" in name
@staticmethod
def _dest(fe: dict) -> str:
"""Get destination path for a file entry, falling back to name."""
return fe.get("path") or fe.get("destination") or fe.get("name", "")
@staticmethod
def _display_name(
sys_id: str, scraped_sys: dict | None = None,
) -> str:
"""Get display name for a system from scraped data or slug."""
if scraped_sys:
name = scraped_sys.get("name")
if name:
return name
# Fallback: convert slug to display name with acronym handling
_UPPER = {
"3do", "cdi", "cpc", "cps1", "cps2", "cps3", "dos", "gba",
"gbc", "hle", "msx", "nes", "nds", "ngp", "psp", "psx",
"sms", "snes", "stv", "tvc", "vb", "zx",
}
parts = sys_id.replace("-", " ").split()
result = []
for p in parts:
if p.lower() in _UPPER:
result.append(p.upper())
else:
result.append(p.capitalize())
return " ".join(result)

View File

@@ -0,0 +1,111 @@
"""Exporter for Batocera batocera-systems format.
Produces a Python dict matching the exact format of
batocera-linux/batocera-scripts/scripts/batocera-systems.
"""
from __future__ import annotations
from pathlib import Path
from .base_exporter import BaseExporter
class Exporter(BaseExporter):
"""Export truth data to Batocera batocera-systems format."""
@staticmethod
def platform_name() -> str:
return "batocera"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
# Build native_id and display name maps from scraped data
native_map: dict[str, str] = {}
if scraped_data:
for sys_id, sys_data in scraped_data.get("systems", {}).items():
nid = sys_data.get("native_id")
if nid:
native_map[sys_id] = nid
lines: list[str] = ["systems = {", ""]
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
files = sys_data.get("files", [])
if not files:
continue
native_id = native_map.get(sys_id, sys_id)
scraped_sys = scraped_data.get("systems", {}).get(sys_id) if scraped_data else None
display_name = self._display_name(sys_id, scraped_sys)
# Build md5 lookup from scraped data for this system
scraped_md5: dict[str, str] = {}
if scraped_data:
s_sys = scraped_data.get("systems", {}).get(sys_id, {})
for sf in s_sys.get("files", []):
sname = sf.get("name", "").lower()
smd5 = sf.get("md5", "")
if sname and smd5:
scraped_md5[sname] = smd5
# Build biosFiles entries as compact single-line dicts
# Original format ALWAYS has md5 — use scraped md5 as fallback
bios_parts: list[str] = []
for fe in files:
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
dest = self._dest(fe)
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if not md5:
md5 = scraped_md5.get(name.lower(), "")
# Original format requires md5 for every entry — skip without
if not md5:
continue
bios_parts.append(
f'{{ "md5": "{md5}", "file": "bios/{dest}" }}'
)
bios_str = ", ".join(bios_parts)
line = (
f' "{native_id}": '
f'{{ "name": "{display_name}", '
f'"biosFiles": [ {bios_str} ] }},'
)
lines.append(line)
lines.append("")
lines.append("}")
lines.append("")
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
def validate(self, truth_data: dict, output_path: str) -> list[str]:
content = Path(output_path).read_text(encoding="utf-8")
issues: list[str] = []
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
# Skip entries without md5 (not exportable in this format)
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if not md5:
continue
dest = self._dest(fe)
if dest not in content and name not in content:
issues.append(f"missing: {name}")
return issues

View File

@@ -0,0 +1,207 @@
"""Exporter for EmuDeck checkBIOS.sh format.
Produces a bash script matching the exact pattern of EmuDeck's
functions/checkBIOS.sh: per-system check functions with MD5 arrays
inside the function body, iterating over $biosPath/* files.
Two patterns:
- MD5 pattern: systems with known hashes, loop $biosPath/*, md5sum each, match
- File-exists pattern: systems with specific paths, check -f
"""
from __future__ import annotations
import re
from pathlib import Path
from .base_exporter import BaseExporter
# Map our system IDs to EmuDeck function naming conventions
_SYSTEM_CONFIG: dict[str, dict] = {
"sony-playstation": {
"func": "checkPS1BIOS",
"var": "PSXBIOS",
"array": "PSBios",
"pattern": "md5",
},
"sony-playstation-2": {
"func": "checkPS2BIOS",
"var": "PS2BIOS",
"array": "PS2Bios",
"pattern": "md5",
},
"sega-mega-cd": {
"func": "checkSegaCDBios",
"var": "SEGACDBIOS",
"array": "CDBios",
"pattern": "md5",
},
"sega-saturn": {
"func": "checkSaturnBios",
"var": "SATURNBIOS",
"array": "SaturnBios",
"pattern": "md5",
},
"sega-dreamcast": {
"func": "checkDreamcastBios",
"var": "BIOS",
"array": "hashes",
"pattern": "md5",
},
"nintendo-ds": {
"func": "checkDSBios",
"var": "BIOS",
"array": "hashes",
"pattern": "md5",
},
"nintendo-switch": {
"func": "checkCitronBios",
"pattern": "file-exists",
"firmware_path": "$biosPath/citron/firmware",
"keys_path": "$biosPath/citron/keys/prod.keys",
},
}
def _make_md5_function(cfg: dict, md5s: list[str]) -> list[str]:
"""Generate a MD5-checking function matching EmuDeck's exact pattern."""
func = cfg["func"]
var = cfg["var"]
array = cfg["array"]
md5_str = " ".join(md5s)
return [
f"{func}(){{",
"",
f'\t{var}="NULL"',
"",
'\tfor entry in "$biosPath/"*',
"\tdo",
'\t\tif [ -f "$entry" ]; then',
'\t\t\tmd5=($(md5sum "$entry"))',
f'\t\t\tif [[ "${var}" != true ]]; then',
f"\t\t\t\t{array}=({md5_str})",
f'\t\t\t\tfor i in "${{{array}[@]}}"',
"\t\t\t\tdo",
'\t\t\t\tif [[ "$md5" == *"${i}"* ]]; then',
f"\t\t\t\t\t{var}=true",
"\t\t\t\t\tbreak",
"\t\t\t\telse",
f"\t\t\t\t\t{var}=false",
"\t\t\t\tfi",
"\t\t\t\tdone",
"\t\t\tfi",
"\t\tfi",
"\tdone",
"",
"",
f"\tif [ ${var} == true ]; then",
'\t\techo "$entry true";',
"\telse",
'\t\techo "false";',
"\tfi",
"}",
]
def _make_file_exists_function(cfg: dict) -> list[str]:
"""Generate a file-exists function matching EmuDeck's pattern."""
func = cfg["func"]
firmware = cfg.get("firmware_path", "")
keys = cfg.get("keys_path", "")
return [
f"{func}(){{",
"",
f'\tlocal FIRMWARE="{firmware}"',
f'\tlocal KEYS="{keys}"',
'\tif [[ -f "$KEYS" ]] && [[ "$( ls -A "$FIRMWARE")" ]]; then',
'\t\t\techo "true";',
"\telse",
'\t\t\techo "false";',
"\tfi",
"}",
]
class Exporter(BaseExporter):
"""Export truth data to EmuDeck checkBIOS.sh format."""
@staticmethod
def platform_name() -> str:
return "emudeck"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
lines: list[str] = ["#!/bin/bash"]
systems = truth_data.get("systems", {})
for sys_id, cfg in sorted(_SYSTEM_CONFIG.items(), key=lambda x: x[1]["func"]):
sys_data = systems.get(sys_id)
if not sys_data:
continue
lines.append("")
if cfg["pattern"] == "md5":
md5s: list[str] = []
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if self._is_pattern(name) or name.startswith("_"):
continue
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5s.extend(m for m in md5 if m and re.fullmatch(r"[a-f0-9]{32}", m))
elif md5 and re.fullmatch(r"[a-f0-9]{32}", md5):
md5s.append(md5)
if md5s:
lines.extend(_make_md5_function(cfg, md5s))
elif cfg["pattern"] == "file-exists":
lines.extend(_make_file_exists_function(cfg))
lines.append("")
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
def validate(self, truth_data: dict, output_path: str) -> list[str]:
content = Path(output_path).read_text(encoding="utf-8")
issues: list[str] = []
systems = truth_data.get("systems", {})
for sys_id, cfg in _SYSTEM_CONFIG.items():
if cfg["pattern"] != "md5":
continue
sys_data = systems.get(sys_id)
if not sys_data:
continue
for fe in sys_data.get("files", []):
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if md5 and re.fullmatch(r"[a-f0-9]{32}", md5) and md5 not in content:
issues.append(f"missing md5: {md5} ({fe.get('name', '')})")
for sys_id, cfg in _SYSTEM_CONFIG.items():
func = cfg["func"]
if func in content:
continue
sys_data = systems.get(sys_id)
if not sys_data or not sys_data.get("files"):
continue
# Only flag if the system has usable data for the function type
if cfg["pattern"] == "md5":
has_md5 = any(
fe.get("md5") and isinstance(fe.get("md5"), str)
and re.fullmatch(r"[a-f0-9]{32}", fe["md5"])
for fe in sys_data["files"]
)
if has_md5:
issues.append(f"missing function: {func}")
elif cfg["pattern"] == "file-exists":
issues.append(f"missing function: {func}")
return issues

View File

@@ -0,0 +1,17 @@
"""Exporter for Lakka (System.dat format, same as RetroArch).
Lakka inherits RetroArch cores and uses the same System.dat format.
Delegates to systemdat_exporter for export and validation.
"""
from __future__ import annotations
from .systemdat_exporter import Exporter as SystemDatExporter
class Exporter(SystemDatExporter):
"""Export truth data to Lakka System.dat format."""
@staticmethod
def platform_name() -> str:
return "lakka"

View File

@@ -0,0 +1,130 @@
"""Exporter for Recalbox es_bios.xml format.
Produces XML matching the exact format of recalbox's es_bios.xml:
- XML namespace declaration
- <system fullname="..." platform="...">
- <bios path="system/file" md5="..." core="..." /> with optional mandatory, hashMatchMandatory, note
- mandatory absent = true (only explicit when false)
- 2-space indentation
"""
from __future__ import annotations
from pathlib import Path
from .base_exporter import BaseExporter
class Exporter(BaseExporter):
"""Export truth data to Recalbox es_bios.xml format."""
@staticmethod
def platform_name() -> str:
return "recalbox"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
native_map: dict[str, str] = {}
if scraped_data:
for sys_id, sys_data in scraped_data.get("systems", {}).items():
nid = sys_data.get("native_id")
if nid:
native_map[sys_id] = nid
lines: list[str] = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<biosList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
' xsi:noNamespaceSchemaLocation="es_bios.xsd">',
]
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
files = sys_data.get("files", [])
if not files:
continue
native_id = native_map.get(sys_id, sys_id)
scraped_sys = scraped_data.get("systems", {}).get(sys_id) if scraped_data else None
display_name = self._display_name(sys_id, scraped_sys)
lines.append(f' <system fullname="{display_name}" platform="{native_id}">')
# Build path lookup from scraped data for this system
scraped_paths: dict[str, str] = {}
if scraped_data:
s_sys = scraped_data.get("systems", {}).get(sys_id, {})
for sf in s_sys.get("files", []):
sname = sf.get("name", "").lower()
spath = sf.get("destination", sf.get("name", ""))
if sname and spath:
scraped_paths[sname] = spath
for fe in files:
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
# Use scraped path when available (preserves original format)
path = scraped_paths.get(name.lower())
if not path:
dest = self._dest(fe)
path = f"{native_id}/{dest}" if "/" not in dest else dest
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = ",".join(md5)
required = fe.get("required", True)
# Build cores string from _cores
cores_list = fe.get("_cores", [])
core_str = ",".join(f"libretro/{c}" for c in cores_list) if cores_list else ""
attrs = [f'path="{path}"']
if md5:
attrs.append(f'md5="{md5}"')
if not required:
attrs.append('mandatory="false"')
if not required:
attrs.append('hashMatchMandatory="true"')
if core_str:
attrs.append(f'core="{core_str}"')
lines.append(f' <bios {" ".join(attrs)} />')
lines.append(" </system>")
lines.append("</biosList>")
lines.append("")
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
def validate(self, truth_data: dict, output_path: str) -> list[str]:
from xml.etree.ElementTree import parse as xml_parse
tree = xml_parse(output_path)
root = tree.getroot()
exported_paths: set[str] = set()
for bios_el in root.iter("bios"):
path = bios_el.get("path", "")
if path:
exported_paths.add(path.lower())
exported_paths.add(path.split("/")[-1].lower())
issues: list[str] = []
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
dest = self._dest(fe)
if name.lower() not in exported_paths and dest.lower() not in exported_paths:
issues.append(f"missing: {name}")
return issues

View File

@@ -0,0 +1,114 @@
"""Exporter for RetroBat batocera-systems.json format.
Produces JSON matching the exact format of
RetroBat-Official/emulatorlauncher/batocera-systems/Resources/batocera-systems.json:
- System keys with "name" and "biosFiles" fields
- Each biosFile has "md5" before "file" (matching original key order)
"""
from __future__ import annotations
import json
from collections import OrderedDict
from pathlib import Path
from .base_exporter import BaseExporter
class Exporter(BaseExporter):
"""Export truth data to RetroBat batocera-systems.json format."""
@staticmethod
def platform_name() -> str:
return "retrobat"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
native_map: dict[str, str] = {}
if scraped_data:
for sys_id, sys_data in scraped_data.get("systems", {}).items():
nid = sys_data.get("native_id")
if nid:
native_map[sys_id] = nid
output: OrderedDict[str, dict] = OrderedDict()
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
files = sys_data.get("files", [])
if not files:
continue
native_id = native_map.get(sys_id, sys_id)
scraped_sys = scraped_data.get("systems", {}).get(sys_id) if scraped_data else None
display_name = self._display_name(sys_id, scraped_sys)
bios_files: list[OrderedDict] = []
for fe in files:
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
dest = self._dest(fe)
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
# Original format requires md5 for every entry
if not md5:
continue
entry: OrderedDict[str, str] = OrderedDict()
entry["md5"] = md5
entry["file"] = f"bios/{dest}"
bios_files.append(entry)
if bios_files:
if native_id in output:
existing_files = {e.get("file") for e in output[native_id]["biosFiles"]}
for entry in bios_files:
if entry.get("file") not in existing_files:
output[native_id]["biosFiles"].append(entry)
else:
sys_entry: OrderedDict[str, object] = OrderedDict()
sys_entry["name"] = display_name
sys_entry["biosFiles"] = bios_files
output[native_id] = sys_entry
Path(output_path).write_text(
json.dumps(output, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
def validate(self, truth_data: dict, output_path: str) -> list[str]:
data = json.loads(Path(output_path).read_text(encoding="utf-8"))
exported_files: set[str] = set()
for sys_data in data.values():
for bf in sys_data.get("biosFiles", []):
path = bf.get("file", "")
stripped = path.removeprefix("bios/")
exported_files.add(stripped)
basename = path.split("/")[-1] if "/" in path else path
exported_files.add(basename)
issues: list[str] = []
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if not md5:
continue
dest = self._dest(fe)
if name not in exported_files and dest not in exported_files:
issues.append(f"missing: {name}")
return issues

View File

@@ -0,0 +1,208 @@
"""Exporter for RetroDECK component_manifest.json format.
Produces a JSON file compatible with RetroDECK's component manifests.
Each system maps to a component with BIOS entries containing filename,
md5 (comma-separated if multiple), paths ($bios_path default), and
required status.
Path tokens: $bios_path for bios/, $roms_path for roms/.
Entries without an explicit path default to $bios_path.
"""
from __future__ import annotations
import json
import re
from collections import OrderedDict
from pathlib import Path
from .base_exporter import BaseExporter
# retrobios slug -> RetroDECK system ID (reverse of scraper SYSTEM_SLUG_MAP)
_REVERSE_SLUG: dict[str, str] = {
"nintendo-nes": "nes",
"nintendo-snes": "snes",
"nintendo-64": "n64",
"nintendo-64dd": "n64dd",
"nintendo-gamecube": "gc",
"nintendo-wii": "wii",
"nintendo-wii-u": "wiiu",
"nintendo-switch": "switch",
"nintendo-gb": "gb",
"nintendo-gbc": "gbc",
"nintendo-gba": "gba",
"nintendo-ds": "nds",
"nintendo-3ds": "3ds",
"nintendo-fds": "fds",
"nintendo-sgb": "sgb",
"nintendo-virtual-boy": "virtualboy",
"nintendo-pokemon-mini": "pokemini",
"sony-playstation": "psx",
"sony-playstation-2": "ps2",
"sony-playstation-3": "ps3",
"sony-psp": "psp",
"sony-psvita": "psvita",
"sega-mega-drive": "megadrive",
"sega-mega-cd": "megacd",
"sega-saturn": "saturn",
"sega-dreamcast": "dreamcast",
"sega-dreamcast-arcade": "naomi",
"sega-game-gear": "gamegear",
"sega-master-system": "mastersystem",
"nec-pc-engine": "pcengine",
"nec-pc-fx": "pcfx",
"nec-pc-98": "pc98",
"nec-pc-88": "pc88",
"3do": "3do",
"amstrad-cpc": "amstradcpc",
"arcade": "arcade",
"atari-400-800": "atari800",
"atari-5200": "atari5200",
"atari-7800": "atari7800",
"atari-jaguar": "atarijaguar",
"atari-lynx": "atarilynx",
"atari-st": "atarist",
"commodore-c64": "c64",
"commodore-amiga": "amiga",
"philips-cdi": "cdimono1",
"fairchild-channel-f": "channelf",
"coleco-colecovision": "colecovision",
"mattel-intellivision": "intellivision",
"microsoft-msx": "msx",
"microsoft-xbox": "xbox",
"doom": "doom",
"j2me": "j2me",
"apple-macintosh-ii": "macintosh",
"apple-ii": "apple2",
"apple-iigs": "apple2gs",
"enterprise-64-128": "enterprise",
"tiger-game-com": "gamecom",
"hartung-game-master": "gmaster",
"epoch-scv": "scv",
"watara-supervision": "supervision",
"bandai-wonderswan": "wonderswan",
"snk-neogeo-cd": "neogeocd",
"tandy-coco": "coco",
"tandy-trs-80": "trs80",
"dragon-32-64": "dragon",
"pico8": "pico8",
"wolfenstein-3d": "wolfenstein",
"sinclair-zx-spectrum": "zxspectrum",
}
def _dest_to_path_token(destination: str) -> str:
"""Convert a truth destination path to a RetroDECK path token."""
if destination.startswith("roms/"):
return "$roms_path/" + destination.removeprefix("roms/")
if destination.startswith("bios/"):
return "$bios_path/" + destination.removeprefix("bios/")
# Default: bios path
return "$bios_path/" + destination
class Exporter(BaseExporter):
"""Export truth data to RetroDECK component_manifest.json format."""
@staticmethod
def platform_name() -> str:
return "retrodeck"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
native_map: dict[str, str] = {}
if scraped_data:
for sys_id, sys_data in scraped_data.get("systems", {}).items():
nid = sys_data.get("native_id")
if nid:
native_map[sys_id] = nid
manifest: OrderedDict[str, dict] = OrderedDict()
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
files = sys_data.get("files", [])
if not files:
continue
native_id = native_map.get(sys_id, _REVERSE_SLUG.get(sys_id, sys_id))
bios_entries: list[OrderedDict] = []
for fe in files:
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
dest = self._dest(fe)
path_token = _dest_to_path_token(dest)
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = ",".join(m for m in md5 if m)
required = fe.get("required", True)
entry: OrderedDict[str, object] = OrderedDict()
entry["filename"] = name
if md5:
# Validate MD5 entries
parts = [
m.strip().lower()
for m in str(md5).split(",")
if re.fullmatch(r"[0-9a-f]{32}", m.strip())
]
if parts:
entry["md5"] = ",".join(parts) if len(parts) > 1 else parts[0]
entry["paths"] = path_token
entry["required"] = required
system_val = native_id
entry["system"] = system_val
bios_entries.append(entry)
if bios_entries:
if native_id in manifest:
# Merge into existing component (multiple truth systems
# may map to the same native ID)
existing_names = {e["filename"] for e in manifest[native_id]["bios"]}
for entry in bios_entries:
if entry["filename"] not in existing_names:
manifest[native_id]["bios"].append(entry)
else:
component = OrderedDict()
component["system"] = native_id
component["bios"] = bios_entries
manifest[native_id] = component
Path(output_path).write_text(
json.dumps(manifest, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
def validate(self, truth_data: dict, output_path: str) -> list[str]:
data = json.loads(Path(output_path).read_text(encoding="utf-8"))
exported_names: set[str] = set()
for comp_data in data.values():
bios = comp_data.get("bios", [])
if isinstance(bios, list):
for entry in bios:
fn = entry.get("filename", "")
if fn:
exported_names.add(fn)
issues: list[str] = []
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
if name not in exported_names:
issues.append(f"missing: {name}")
return issues

View File

@@ -0,0 +1,17 @@
"""Exporter for RetroPie (System.dat format, same as RetroArch).
RetroPie inherits RetroArch cores and uses the same System.dat format.
Delegates to systemdat_exporter for export and validation.
"""
from __future__ import annotations
from .systemdat_exporter import Exporter as SystemDatExporter
class Exporter(SystemDatExporter):
"""Export truth data to RetroPie System.dat format."""
@staticmethod
def platform_name() -> str:
return "retropie"

View File

@@ -0,0 +1,160 @@
"""Exporter for RomM known_bios_files.json format.
Produces JSON matching the exact format of
rommapp/romm/backend/models/fixtures/known_bios_files.json:
- Keys are "igdb_slug:filename"
- Values contain size, crc, md5, sha1 (all optional but at least one hash)
- Hashes are lowercase hex strings
- Size is an integer
"""
from __future__ import annotations
import json
from collections import OrderedDict
from pathlib import Path
from .base_exporter import BaseExporter
# retrobios slug -> IGDB slug (reverse of scraper SLUG_MAP)
_REVERSE_SLUG: dict[str, str] = {
"3do": "3do",
"nintendo-64dd": "64dd",
"amstrad-cpc": "acpc",
"commodore-amiga": "amiga",
"arcade": "arcade",
"atari-st": "atari-st",
"atari-5200": "atari5200",
"atari-7800": "atari7800",
"atari-400-800": "atari8bit",
"coleco-colecovision": "colecovision",
"sega-dreamcast": "dc",
"doom": "doom",
"enterprise-64-128": "enterprise",
"fairchild-channel-f": "fairchild-channel-f",
"nintendo-fds": "fds",
"sega-game-gear": "gamegear",
"nintendo-gb": "gb",
"nintendo-gba": "gba",
"nintendo-gbc": "gbc",
"sega-mega-drive": "genesis",
"mattel-intellivision": "intellivision",
"j2me": "j2me",
"atari-lynx": "lynx",
"apple-macintosh-ii": "mac",
"microsoft-msx": "msx",
"nintendo-ds": "nds",
"snk-neogeo-cd": "neo-geo-cd",
"nintendo-nes": "nes",
"nintendo-gamecube": "ngc",
"magnavox-odyssey2": "odyssey-2-slash-videopac-g7000",
"nec-pc-98": "pc-9800-series",
"nec-pc-fx": "pc-fx",
"nintendo-pokemon-mini": "pokemon-mini",
"sony-playstation-2": "ps2",
"sony-psp": "psp",
"sony-playstation": "psx",
"nintendo-satellaview": "satellaview",
"sega-saturn": "saturn",
"scummvm": "scummvm",
"sega-mega-cd": "segacd",
"sharp-x68000": "sharp-x68000",
"sega-master-system": "sms",
"nintendo-snes": "snes",
"nintendo-sufami-turbo": "sufami-turbo",
"nintendo-sgb": "super-gb",
"nec-pc-engine": "tg16",
"videoton-tvc": "tvc",
"philips-videopac": "videopac-g7400",
"wolfenstein-3d": "wolfenstein",
"sharp-x1": "x1",
"microsoft-xbox": "xbox",
"sinclair-zx-spectrum": "zxs",
}
class Exporter(BaseExporter):
"""Export truth data to RomM known_bios_files.json format."""
@staticmethod
def platform_name() -> str:
return "romm"
def export(
self,
truth_data: dict,
output_path: str,
scraped_data: dict | None = None,
) -> None:
native_map: dict[str, str] = {}
if scraped_data:
for sys_id, sys_data in scraped_data.get("systems", {}).items():
nid = sys_data.get("native_id")
if nid:
native_map[sys_id] = nid
output: OrderedDict[str, dict] = OrderedDict()
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
files = sys_data.get("files", [])
if not files:
continue
igdb_slug = native_map.get(sys_id, _REVERSE_SLUG.get(sys_id, sys_id))
for fe in files:
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
key = f"{igdb_slug}:{name}"
entry: OrderedDict[str, object] = OrderedDict()
size = fe.get("size")
if size is not None:
entry["size"] = int(size)
crc = fe.get("crc32", "")
if crc:
entry["crc"] = str(crc).strip().lower()
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if md5:
entry["md5"] = str(md5).strip().lower()
sha1 = fe.get("sha1", "")
if isinstance(sha1, list):
sha1 = sha1[0] if sha1 else ""
if sha1:
entry["sha1"] = str(sha1).strip().lower()
output[key] = entry
Path(output_path).write_text(
json.dumps(output, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
def validate(self, truth_data: dict, output_path: str) -> list[str]:
data = json.loads(Path(output_path).read_text(encoding="utf-8"))
exported_names: set[str] = set()
for key in data:
if ":" in key:
_, filename = key.split(":", 1)
exported_names.add(filename)
issues: list[str] = []
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_") or self._is_pattern(name):
continue
if name not in exported_names:
issues.append(f"missing: {name}")
return issues

View File

@@ -1,4 +1,8 @@
"""Exporter for libretro System.dat (clrmamepro DAT format)."""
"""Exporter for libretro System.dat (clrmamepro DAT format).
Produces a single 'game' block with all ROMs grouped by system,
matching the exact format of libretro-database/dat/System.dat.
"""
from __future__ import annotations
@@ -13,7 +17,7 @@ from .base_exporter import BaseExporter
def _slug_to_native(slug: str) -> str:
"""Convert a system slug to a native 'Manufacturer - Console' name."""
"""Convert a system slug to 'Manufacturer - Console' format."""
parts = slug.split("-", 1)
if len(parts) == 1:
return parts[0].title()
@@ -42,45 +46,69 @@ class Exporter(BaseExporter):
if nid:
native_map[sys_id] = nid
lines: list[str] = []
lines.append('clrmamepro (')
lines.append('\tname "System.dat"')
lines.append(')')
# Match exact header format of libretro-database/dat/System.dat
version = ""
if scraped_data:
version = scraped_data.get("dat_version", scraped_data.get("version", ""))
lines: list[str] = [
"clrmamepro (",
'\tname "System"',
'\tdescription "System"',
'\tcomment "System, firmware, and BIOS files used by libretro cores."',
]
if version:
lines.append(f"\tversion {version}")
lines.extend([
'\tauthor "libretro"',
'\thomepage "https://github.com/libretro/libretro-database/blob/master/dat/System.dat"',
'\turl "https://raw.githubusercontent.com/libretro/libretro-database/master/dat/System.dat"',
")",
"",
"game (",
'\tname "System"',
'\tcomment "System"',
])
systems = truth_data.get("systems", {})
for sys_id in sorted(systems):
sys_data = systems[sys_id]
native_name = native_map.get(sys_id, _slug_to_native(sys_id))
files = sys_data.get("files", [])
if not files:
continue
for fe in sys_data.get("files", []):
native_name = native_map.get(sys_id, _slug_to_native(sys_id))
lines.append("")
lines.append(f'\tcomment "{native_name}"')
for fe in files:
name = fe.get("name", "")
if name.startswith("_"):
if name.startswith("_") or self._is_pattern(name):
continue
dest = fe.get("path", name)
size = fe.get("size", 0)
# Quote names with spaces or special chars (matching original format)
needs_quote = " " in name or "(" in name or ")" in name
name_str = f'"{name}"' if needs_quote else name
rom_parts = [f"name {name_str}"]
size = fe.get("size")
if size:
rom_parts.append(f"size {size}")
crc = fe.get("crc32", "")
md5 = fe.get("md5", "")
sha1 = fe.get("sha1", "")
rom_parts = [f'name "{name}"']
rom_parts.append(f"size {size}")
if crc:
rom_parts.append(f"crc {crc}")
rom_parts.append(f"crc {crc.upper()}")
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
if md5:
rom_parts.append(f"md5 {md5}")
sha1 = fe.get("sha1", "")
if isinstance(sha1, list):
sha1 = sha1[0] if sha1 else ""
if sha1:
rom_parts.append(f"sha1 {sha1}")
rom_str = " ".join(rom_parts)
game_name = f"{native_name}/{dest}"
lines.append("")
lines.append("game (")
lines.append(f'\tname "{game_name}"')
lines.append(f'\tdescription "{name}"')
lines.append(f"\trom ( {rom_str} )")
lines.append(")")
lines.append(f"\trom ( {' '.join(rom_parts)} )")
lines.append(")")
lines.append("")
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
@@ -93,12 +121,11 @@ class Exporter(BaseExporter):
exported_names.add(rom.name)
issues: list[str] = []
for sys_id, sys_data in truth_data.get("systems", {}).items():
for sys_data in truth_data.get("systems", {}).values():
for fe in sys_data.get("files", []):
name = fe.get("name", "")
if name.startswith("_"):
if name.startswith("_") or self._is_pattern(name):
continue
if name not in exported_names:
issues.append(f"missing: {name} (system {sys_id})")
issues.append(f"missing: {name}")
return issues

View File

@@ -18,7 +18,7 @@ from datetime import datetime, timezone
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import compute_hashes, list_registered_platforms
from common import compute_hashes, list_registered_platforms, write_if_changed
CACHE_DIR = ".cache"
CACHE_FILE = os.path.join(CACHE_DIR, "db_cache.json")
@@ -315,14 +315,15 @@ def main():
"indexes": indexes,
}
with open(args.output, "w") as f:
json.dump(database, f, indent=2)
new_content = json.dumps(database, indent=2)
written = write_if_changed(args.output, new_content)
save_cache(CACHE_FILE, new_cache)
alias_count = sum(len(v) for v in aliases.values())
name_count = len(indexes["by_name"])
print(f"Generated {args.output}: {len(files)} files, {total_size:,} bytes total")
status = "Generated" if written else "Unchanged"
print(f"{status} {args.output}: {len(files)} files, {total_size:,} bytes total")
print(f" Name index: {name_count} names ({alias_count} aliases)")
return 0

View File

@@ -28,7 +28,7 @@ sys.path.insert(0, os.path.dirname(__file__))
from common import (
MANUFACTURER_PREFIXES,
build_target_cores_cache, build_zip_contents_index, check_inside_zip,
compute_hashes, fetch_large_file, group_identical_platforms,
compute_hashes, expand_platform_declared_names, fetch_large_file, group_identical_platforms,
list_emulator_profiles, list_platform_system_ids, list_registered_platforms,
filter_systems_by_target, list_system_ids, load_database,
load_data_dir_registry, load_emulator_profiles, load_platform_config,
@@ -371,12 +371,8 @@ def _collect_emulator_extras(
by_path_suffix = db.get("indexes", {}).get("by_path_suffix", {})
# Build set of filenames already covered (platform baseline + first pass extras)
covered_names: set[str] = set()
for sys_id, system in config.get("systems", {}).items():
for fe in system.get("files", []):
n = fe.get("name", "")
if n:
covered_names.add(n)
# Enriched with canonical names from DB via MD5 (handles platform renaming)
covered_names = expand_platform_declared_names(config, db)
for e in extras:
covered_names.add(e["name"])
@@ -426,6 +422,91 @@ def _collect_emulator_extras(
"source_emulator": profile.get("emulator", emu_name),
})
# Third pass: agnostic scan — for filename-agnostic cores, include all
# DB files matching the system path prefix and size criteria.
files_db = db.get("files", {})
for emu_name, profile in sorted(profiles.items()):
if profile.get("type") in ("launcher", "alias"):
continue
if emu_name not in relevant:
continue
is_profile_agnostic = profile.get("bios_mode") == "agnostic"
if not is_profile_agnostic:
if not any(f.get("agnostic") for f in profile.get("files", [])):
continue
for f in profile.get("files", []):
if not is_profile_agnostic and not f.get("agnostic"):
continue
fname = f.get("name", "")
if not fname:
continue
# Derive path prefix from the representative file in the DB
path_prefix = None
sha1_list = by_name.get(fname, [])
for sha1 in sha1_list:
entry = files_db.get(sha1, {})
path = entry.get("path", "")
if path:
parts = path.rsplit("/", 1)
if len(parts) == 2:
path_prefix = parts[0] + "/"
break
if not path_prefix:
# Fallback: try other files in the profile for the same system
for other_f in profile.get("files", []):
if other_f is f:
continue
other_name = other_f.get("name", "")
for sha1 in by_name.get(other_name, []):
entry = files_db.get(sha1, {})
path = entry.get("path", "")
if path:
parts = path.rsplit("/", 1)
if len(parts) == 2:
path_prefix = parts[0] + "/"
break
if path_prefix:
break
if not path_prefix:
continue
# Size criteria from the file entry
min_size = f.get("min_size", 0)
max_size = f.get("max_size", float("inf"))
exact_size = f.get("size")
if exact_size and not min_size:
min_size = exact_size
max_size = exact_size
# Scan DB for all files under this prefix matching size
for sha1, entry in files_db.items():
path = entry.get("path", "")
if not path.startswith(path_prefix):
continue
size = entry.get("size", 0)
if not (min_size <= size <= max_size):
continue
scan_name = entry.get("name", "")
if not scan_name:
continue
dest = scan_name
full_dest = f"{base_dest}/{dest}" if base_dest else dest
if full_dest in seen_dests:
continue
seen_dests.add(full_dest)
extras.append({
"name": scan_name,
"destination": dest,
"required": False,
"hle_fallback": False,
"source_emulator": profile.get("emulator", emu_name),
"agnostic_scan": True,
})
return extras
@@ -625,6 +706,24 @@ def _build_readme(platform_name: str, platform_display: str,
return header + guide + footer
def _build_agnostic_rename_readme(
destination: str, original: str, alternatives: list[str],
) -> str:
"""Build a README explaining an agnostic file rename."""
lines = [
"This file was renamed for compatibility:",
f" {destination} <- {original}",
"",
]
if alternatives:
lines.append("All variants included in this pack:")
for alt in sorted(alternatives):
lines.append(f" {alt}")
lines.append("")
lines.append(f"To use a different variant, rename it to: {destination}")
return "\n".join(lines) + "\n"
def generate_pack(
platform_name: str,
platforms_dir: str,
@@ -792,10 +891,71 @@ def generate_pack(
continue
if status == "not_found":
if not already_packed:
missing_files.append(file_entry["name"])
file_status[dedup_key] = "missing"
continue
# Agnostic fallback: if an agnostic core covers this system,
# find any matching file in the DB
by_name = db.get("indexes", {}).get("by_name", {})
files_db = db.get("files", {})
agnostic_path = None
agnostic_resolved = False
if emu_profiles:
for _emu_key, _emu_prof in emu_profiles.items():
if _emu_prof.get("bios_mode") != "agnostic":
continue
if sys_id not in set(_emu_prof.get("systems", [])):
continue
for _ef in _emu_prof.get("files", []):
ef_name = _ef.get("name", "")
for _sha1 in by_name.get(ef_name, []):
_entry = files_db.get(_sha1, {})
_path = _entry.get("path", "")
if _path:
_prefix = _path.rsplit("/", 1)[0] + "/"
_min = _ef.get("min_size", 0)
_max = _ef.get("max_size", float("inf"))
if _ef.get("size") and not _min:
_min = _ef["size"]
_max = _ef["size"]
for _s, _e in files_db.items():
if _e.get("path", "").startswith(_prefix):
if _min <= _e.get("size", 0) <= _max:
if os.path.exists(_e["path"]):
local_path = _e["path"]
agnostic_path = _prefix
agnostic_resolved = True
break
break
if agnostic_resolved:
break
if agnostic_resolved:
break
if agnostic_resolved and local_path:
# Write rename README
original_name = os.path.basename(local_path)
dest_name = file_entry.get("name", "")
if original_name != dest_name and agnostic_path:
alt_names = []
for _s, _e in files_db.items():
_p = _e.get("path", "")
if _p.startswith(agnostic_path):
_n = _e.get("name", "")
if _n and _n != original_name:
alt_names.append(_n)
readme_text = _build_agnostic_rename_readme(
dest_name, original_name, alt_names,
)
readme_name = f"RENAMED_{dest_name}.txt"
readme_full = f"{base_dest}/{readme_name}" if base_dest else readme_name
if readme_full not in seen_destinations:
zf.writestr(readme_full, readme_text)
seen_destinations.add(readme_full)
status = "agnostic_fallback"
# Fall through to normal packing below
else:
if not already_packed:
missing_files.append(file_entry["name"])
file_status[dedup_key] = "missing"
continue
if status == "hash_mismatch" and verification_mode != "existence":
zf_name = file_entry.get("zipped_file")

View File

@@ -18,7 +18,7 @@ from datetime import datetime, timezone
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import list_registered_platforms, load_database, load_platform_config
from common import list_registered_platforms, load_database, load_platform_config, write_if_changed
from verify import verify_platform
def compute_coverage(platform_name: str, platforms_dir: str, db: dict) -> dict:
@@ -316,14 +316,12 @@ def main():
db = load_database(args.db)
readme = generate_readme(db, args.platforms_dir)
with open("README.md", "w") as f:
f.write(readme)
print(f"Generated ./README.md")
status = "Generated" if write_if_changed("README.md", readme) else "Unchanged"
print(f"{status} ./README.md")
contributing = generate_contributing()
with open("CONTRIBUTING.md", "w") as f:
f.write(contributing)
print(f"Generated ./CONTRIBUTING.md")
status = "Generated" if write_if_changed("CONTRIBUTING.md", contributing) else "Unchanged"
print(f"{status} ./CONTRIBUTING.md")
if __name__ == "__main__":

View File

@@ -20,7 +20,7 @@ from datetime import datetime, timezone
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import list_registered_platforms, load_database, load_emulator_profiles, load_platform_config, require_yaml
from common import list_registered_platforms, load_database, load_emulator_profiles, load_platform_config, require_yaml, write_if_changed
yaml = require_yaml()
from generate_readme import compute_coverage
@@ -2064,7 +2064,7 @@ def main():
# Generate home
print("Generating home page...")
(docs / "index.md").write_text(generate_home(db, coverages, profiles, registry))
write_if_changed(str(docs / "index.md"), generate_home(db, coverages, profiles, registry))
# Build system_id -> manufacturer page map (needed by all generators)
print("Building system cross-reference map...")
@@ -2074,37 +2074,35 @@ def main():
# Generate platform pages
print("Generating platform pages...")
(docs / "platforms" / "index.md").write_text(generate_platform_index(coverages))
write_if_changed(str(docs / "platforms" / "index.md"), generate_platform_index(coverages))
for name, cov in coverages.items():
(docs / "platforms" / f"{name}.md").write_text(generate_platform_page(name, cov, registry, emulator_files))
write_if_changed(str(docs / "platforms" / f"{name}.md"), generate_platform_page(name, cov, registry, emulator_files))
# Generate system pages
print("Generating system pages...")
(docs / "systems" / "index.md").write_text(generate_systems_index(manufacturers))
write_if_changed(str(docs / "systems" / "index.md"), generate_systems_index(manufacturers))
for mfr, consoles in manufacturers.items():
slug = mfr.lower().replace(" ", "-")
page = generate_system_page(mfr, consoles, platform_files, emulator_files)
(docs / "systems" / f"{slug}.md").write_text(page)
write_if_changed(str(docs / "systems" / f"{slug}.md"), page)
# Generate emulator pages
print("Generating emulator pages...")
(docs / "emulators" / "index.md").write_text(generate_emulators_index(profiles))
write_if_changed(str(docs / "emulators" / "index.md"), generate_emulators_index(profiles))
for name, profile in profiles.items():
page = generate_emulator_page(name, profile, db, platform_files)
(docs / "emulators" / f"{name}.md").write_text(page)
write_if_changed(str(docs / "emulators" / f"{name}.md"), page)
# Generate cross-reference page
print("Generating cross-reference page...")
(docs / "cross-reference.md").write_text(
generate_cross_reference(coverages, profiles)
)
write_if_changed(str(docs / "cross-reference.md"),
generate_cross_reference(coverages, profiles))
# Generate gap analysis page
print("Generating gap analysis page...")
(docs / "gaps.md").write_text(
generate_gap_analysis(profiles, coverages, db)
)
write_if_changed(str(docs / "gaps.md"),
generate_gap_analysis(profiles, coverages, db))
# Wiki pages: copy manually maintained sources + generate dynamic ones
print("Generating wiki pages...")
@@ -2115,11 +2113,11 @@ def main():
for src_file in wiki_src.glob("*.md"):
shutil.copy2(src_file, wiki_dest / src_file.name)
# data-model.md is generated (contains live DB stats)
(wiki_dest / "data-model.md").write_text(generate_wiki_data_model(db, profiles))
write_if_changed(str(wiki_dest / "data-model.md"), generate_wiki_data_model(db, profiles))
# Generate contributing
print("Generating contributing page...")
(docs / "contributing.md").write_text(generate_contributing())
write_if_changed(str(docs / "contributing.md"), generate_contributing())
# Update mkdocs.yml nav section only (avoid yaml.dump round-trip mangling quotes)
print("Updating mkdocs.yml nav...")
@@ -2173,9 +2171,7 @@ markdown_extensions:
plugins:
- search
"""
with open("mkdocs.yml", "w") as f:
f.write(mkdocs_static)
f.write(nav_yaml)
write_if_changed("mkdocs.yml", mkdocs_static + nav_yaml)
total_pages = (
1 # home

View File

@@ -8,6 +8,7 @@ import urllib.request
import urllib.error
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from pathlib import Path
@dataclass
@@ -231,7 +232,28 @@ def scraper_cli(scraper_class: type, description: str = "Scrape BIOS requirement
if req.zipped_file:
entry["zipped_file"] = req.zipped_file
config["systems"][sys_id]["files"].append(entry)
with open(args.output, "w") as f:
# Merge into existing YAML: preserve fields the scraper doesn't generate
# (data_directories, case_insensitive_fs, manually added metadata).
# The scraper replaces systems + files; everything else is preserved.
output_path = Path(args.output)
if output_path.exists():
with open(output_path) as f:
existing = yaml.safe_load(f) or {}
# Preserve existing keys not generated by the scraper.
# Only keys present in the NEW config are considered scraper-generated.
# Everything else in the existing file is preserved.
for key, val in existing.items():
if key not in config:
config[key] = val
# Preserve per-system fields not generated by the scraper
# (data_directories, native_id from manual additions, etc.)
existing_systems = existing.get("systems", {})
for sys_id, sys_data in config.get("systems", {}).items():
old_sys = existing_systems.get(sys_id, {})
for field in ("data_directories",):
if field in old_sys and field not in sys_data:
sys_data[field] = old_sys[field]
with open(output_path, "w") as f:
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
print(f"Written {len(reqs)} entries to {args.output}")
return

View File

@@ -92,6 +92,27 @@ SYSTEM_SLUG_MAP = {
"dos": "dos",
"videopac": "philips-videopac",
"pokemini": "nintendo-pokemon-mini",
"gsplus": "apple-iigs",
"apple2": "apple-ii",
"apple2gs": "apple-iigs",
"ps3": "sony-playstation-3",
"psvita": "sony-playstation-vita",
"coco": "coco",
"dragon32": "dragon32",
"dragon64": "dragon64",
"mc10": "mc10",
"msx2+": "microsoft-msx",
"msxturbor": "microsoft-msx",
"spectravideo": "spectravideo",
"tvc": "videoton-tvc",
"enterprise": "enterprise-64-128",
"vis": "tandy-vis",
"supracan": "supracan",
"jaguar": "atari-jaguar",
"jaguarcd": "atari-jaguar",
"switch": "nintendo-switch",
"wii": "nintendo-wii",
"xbox360": "microsoft-xbox-360",
}
@@ -282,12 +303,25 @@ class Scraper(BaseScraper):
"""Generate a platform YAML config dict from scraped data."""
requirements = self.fetch_requirements()
# Parse source to extract display names per system
raw = self._fetch_raw()
source_dict = self._extract_systems_dict(raw)
display_names: dict[str, str] = {}
for sys_key, sys_data in source_dict.items():
dname = sys_data.get("name", "")
if dname:
slug = SYSTEM_SLUG_MAP.get(sys_key, sys_key)
display_names[slug] = dname
systems = {}
for req in requirements:
if req.system not in systems:
sys_entry: dict = {"files": []}
if req.native_id:
sys_entry["native_id"] = req.native_id
dname = display_names.get(req.system)
if dname:
sys_entry["name"] = dname
systems[req.system] = sys_entry
entry = {
@@ -308,6 +342,13 @@ class Scraper(BaseScraper):
num = tag.removeprefix("batocera-")
if num.isdigit():
batocera_version = num
if not batocera_version:
# Preserve existing version when fetch fails (offline mode)
existing = Path(__file__).resolve().parents[2] / "platforms" / "batocera.yml"
if existing.exists():
with open(existing) as f:
old = yaml.safe_load(f) or {}
batocera_version = str(old.get("version", ""))
cores, standalone = self._fetch_cores()
result = {

View File

@@ -27,6 +27,14 @@ SOURCE_URL = (
GITHUB_REPO = "RetroBat-Official/retrobat"
# Map RetroBat system keys to our normalized system IDs
SYSTEM_SLUG_MAP = {
"ps2": "sony-playstation-2",
"ps3": "sony-playstation-3",
"psvita": "sony-playstation-vita",
"gsplus": "apple-iigs",
}
class Scraper(BaseScraper):
"""Scraper for RetroBat batocera-systems.json."""
@@ -83,7 +91,7 @@ class Scraper(BaseScraper):
requirements.append(BiosRequirement(
name=name,
system=sys_key,
system=SYSTEM_SLUG_MAP.get(sys_key, sys_key),
md5=md5 or None,
destination=file_path,
required=True,
@@ -113,10 +121,25 @@ class Scraper(BaseScraper):
"""Generate a platform YAML config dict from scraped data."""
requirements = self.fetch_requirements()
# Parse source to extract display names per system
raw = self._fetch_raw()
source_data = json.loads(raw)
display_names: dict[str, str] = {}
for sys_key, sys_data in source_data.items():
if isinstance(sys_data, dict):
dname = sys_data.get("name", "")
if dname:
slug = SYSTEM_SLUG_MAP.get(sys_key, sys_key)
display_names[slug] = dname
systems = {}
for req in requirements:
if req.system not in systems:
systems[req.system] = {"files": []}
sys_entry: dict = {"files": []}
dname = display_names.get(req.system)
if dname:
sys_entry["name"] = dname
systems[req.system] = sys_entry
entry = {
"name": req.name,

View File

@@ -38,8 +38,14 @@ def _enrich_hashes(entry: dict, db: dict) -> None:
sha1 = entry.get("sha1", "")
md5 = entry.get("md5", "")
# Hashes can be lists (multi-hash) — use first string value
if isinstance(sha1, list):
sha1 = sha1[0] if sha1 else ""
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
record = None
if sha1 and db.get("files"):
if sha1 and isinstance(sha1, str) and db.get("files"):
record = db["files"].get(sha1)
if record is None and md5:
by_md5 = db.get("by_md5", {})
@@ -323,9 +329,46 @@ def _diff_system(truth_sys: dict, scraped_sys: dict) -> dict:
"scraped_required": s_req,
})
# Truth files not matched -> missing
for fe in truth_sys.get("files", []):
if fe["name"].lower() not in matched_truth_names:
# Collect unmatched files from both sides
unmatched_truth = [
fe for fe in truth_sys.get("files", [])
if fe["name"].lower() not in matched_truth_names
]
unmatched_scraped = {
s_key: s_entry for s_key, s_entry in scraped_index.items()
if s_key not in truth_index
}
# Hash-based fallback: detect platform renames (e.g. Batocera ROM → ROM1)
# If an unmatched scraped file shares a hash with an unmatched truth file,
# it's the same file under a different name — a platform rename, not a gap.
rename_matched_truth: set[str] = set()
rename_matched_scraped: set[str] = set()
if unmatched_truth and unmatched_scraped:
# Build hash → truth file index for unmatched truth files
truth_hash_index: dict[str, dict] = {}
for fe in unmatched_truth:
for h in ("sha1", "md5", "crc32"):
val = fe.get(h)
if val and isinstance(val, str):
truth_hash_index[val.lower()] = fe
for s_key, s_entry in unmatched_scraped.items():
for h in ("sha1", "md5", "crc32"):
s_val = s_entry.get(h)
if not s_val or not isinstance(s_val, str):
continue
t_entry = truth_hash_index.get(s_val.lower())
if t_entry is not None:
# Rename detected — count as matched
rename_matched_truth.add(t_entry["name"].lower())
rename_matched_scraped.add(s_key)
break
# Truth files not matched (by name, alias, or hash) -> missing
for fe in unmatched_truth:
if fe["name"].lower() not in rename_matched_truth:
missing.append({
"name": fe["name"],
"cores": list(fe.get("_cores", [])),
@@ -335,13 +378,14 @@ def _diff_system(truth_sys: dict, scraped_sys: dict) -> dict:
# Scraped files not in truth -> extra
coverage = truth_sys.get("_coverage", {})
has_unprofiled = bool(coverage.get("cores_unprofiled"))
for s_key, s_entry in scraped_index.items():
if s_key not in truth_index:
entry = {"name": s_entry["name"]}
if has_unprofiled:
extra_unprofiled.append(entry)
else:
extra_phantom.append(entry)
for s_key, s_entry in unmatched_scraped.items():
if s_key in rename_matched_scraped:
continue
entry = {"name": s_entry["name"]}
if has_unprofiled:
extra_unprofiled.append(entry)
else:
extra_phantom.append(entry)
result: dict = {}
if missing:

View File

@@ -31,10 +31,11 @@ from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import (
build_target_cores_cache, build_zip_contents_index, check_inside_zip,
compute_hashes, filter_systems_by_target, group_identical_platforms,
list_emulator_profiles, list_system_ids, load_data_dir_registry,
load_emulator_profiles, load_platform_config, md5sum, md5_composite,
require_yaml, resolve_local_file, resolve_platform_cores,
compute_hashes, expand_platform_declared_names, filter_systems_by_target,
group_identical_platforms, list_emulator_profiles, list_system_ids,
load_data_dir_registry, load_emulator_profiles, load_platform_config,
md5sum, md5_composite, require_yaml, resolve_local_file,
resolve_platform_cores,
)
yaml = require_yaml()
@@ -261,13 +262,9 @@ def find_undeclared_files(
data_names: set[str] | None = None,
) -> list[dict]:
"""Find files needed by cores but not declared in platform config."""
# Collect all filenames declared by this platform
declared_names: set[str] = set()
for sys_id, system in config.get("systems", {}).items():
for fe in system.get("files", []):
name = fe.get("name", "")
if name:
declared_names.add(name)
# Collect all filenames declared by this platform, enriched with
# canonical names from DB via MD5 (handles platform renaming)
declared_names = expand_platform_declared_names(config, db)
# Collect data_directory refs
declared_dd: set[str] = set()
@@ -294,6 +291,10 @@ def find_undeclared_files(
if emu_name not in relevant:
continue
# Skip agnostic profiles entirely (filename-agnostic BIOS detection)
if profile.get("bios_mode") == "agnostic":
continue
# Check if this profile is standalone: match profile name or any cores: alias
is_standalone = emu_name in standalone_set or bool(
standalone_set & {str(c) for c in profile.get("cores", [])}
@@ -320,6 +321,10 @@ def find_undeclared_files(
if load_from and load_from != "system_dir":
continue
# Skip agnostic files (filename-agnostic, handled by agnostic scan)
if f.get("agnostic"):
continue
archive = f.get("archive")
# Skip files declared by the platform (by name or archive)

View File

@@ -31,6 +31,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))
import yaml
from common import (
build_zip_contents_index, check_inside_zip, compute_hashes,
expand_platform_declared_names,
group_identical_platforms, load_emulator_profiles, load_platform_config,
md5_composite, md5sum, parse_md5_list, resolve_local_file,
resolve_platform_cores, safe_extract_zip,
@@ -169,6 +170,7 @@ class TestE2E(unittest.TestCase):
"md5": info["md5"],
"name": name,
"crc32": info.get("crc32", ""),
"size": len(info["data"]),
}
by_md5[info["md5"]] = sha1
by_name.setdefault(name, []).append(sha1)
@@ -269,6 +271,12 @@ class TestE2E(unittest.TestCase):
{"ref": "test-data-dir", "destination": "TestData"},
],
},
"sys-renamed": {
"files": [
{"name": "renamed_file.bin", "destination": "renamed_file.bin",
"md5": f["correct_hash.bin"]["md5"], "required": True},
],
},
},
}
with open(os.path.join(self.platforms_dir, "test_md5.yml"), "w") as fh:
@@ -490,6 +498,46 @@ class TestE2E(unittest.TestCase):
with open(os.path.join(self.emulators_dir, "test_subdir_core.yml"), "w") as fh:
yaml.dump(emu_subdir, fh)
# Emulator whose file is declared by platform under a different name
# (e.g. gsplus ROM vs Batocera ROM1) — hash-based matching should resolve
emu_renamed = {
"emulator": "TestRenamed",
"type": "standalone",
"systems": ["sys-renamed"],
"files": [
{"name": "correct_hash.bin", "required": True},
],
}
with open(os.path.join(self.emulators_dir, "test_renamed.yml"), "w") as fh:
yaml.dump(emu_renamed, fh)
# Agnostic profile (bios_mode: agnostic) — skipped by find_undeclared_files
emu_agnostic = {
"emulator": "TestAgnostic",
"type": "standalone",
"bios_mode": "agnostic",
"systems": ["console-a"],
"files": [
{"name": "correct_hash.bin", "required": True,
"min_size": 1, "max_size": 999999},
],
}
with open(os.path.join(self.emulators_dir, "test_agnostic.yml"), "w") as fh:
yaml.dump(emu_agnostic, fh)
# Mixed profile with per-file agnostic
emu_mixed_agnostic = {
"emulator": "TestMixedAgnostic",
"type": "libretro",
"systems": ["console-a"],
"files": [
{"name": "undeclared_req.bin", "required": True},
{"name": "agnostic_file.bin", "required": True, "agnostic": True},
],
}
with open(os.path.join(self.emulators_dir, "test_mixed_agnostic.yml"), "w") as fh:
yaml.dump(emu_mixed_agnostic, fh)
# ---------------------------------------------------------------
# THE TEST -one method per feature area, all using same fixtures
# ---------------------------------------------------------------
@@ -3122,7 +3170,8 @@ class TestE2E(unittest.TestCase):
self.assertIn("Sony - PlayStation", content)
self.assertIn("scph5501.bin", content)
self.assertIn("b056ee5a4d65937e1a3a17e1e78f3258ea49c38e", content)
self.assertIn('name "System.dat"', content)
self.assertIn('name "System"', content)
self.assertIn("71AF80B4", content) # CRC uppercase
issues = exporter.validate(truth, out_path)
self.assertEqual(issues, [])
@@ -3251,6 +3300,313 @@ class TestE2E(unittest.TestCase):
self.assertEqual(div["extra_unprofiled"][0]["name"], "phantom.bin")
self.assertNotIn("extra_phantom", div)
def test_173_cross_ref_hash_matching(self):
"""Platform file under different name matched by MD5 is not undeclared."""
config = load_platform_config("test_md5", self.platforms_dir)
profiles = load_emulator_profiles(self.emulators_dir)
undeclared = find_undeclared_files(config, self.emulators_dir, self.db, profiles)
names = {u["name"] for u in undeclared}
# correct_hash.bin is declared by platform as renamed_file.bin with same MD5
# hash-based matching should suppress it from undeclared
self.assertNotIn("correct_hash.bin", names)
def test_174_expand_platform_declared_names(self):
"""expand_platform_declared_names enriches with DB canonical names."""
config = load_platform_config("test_md5", self.platforms_dir)
result = expand_platform_declared_names(config, self.db)
# renamed_file.bin is declared directly
self.assertIn("renamed_file.bin", result)
# correct_hash.bin is the DB canonical name for the same MD5
self.assertIn("correct_hash.bin", result)
# ---------------------------------------------------------------
# Registry merge + all_libretro expansion + diff hash fallback
# ---------------------------------------------------------------
def test_175_registry_merge_cores(self):
"""load_platform_config merges cores from _registry.yml."""
from common import _platform_config_cache
# Platform YAML with 1 core
config = {
"platform": "TestMerge",
"cores": ["core_a"],
"systems": {"test-system": {"files": []}},
}
with open(os.path.join(self.platforms_dir, "testmerge.yml"), "w") as f:
yaml.dump(config, f)
# Registry with 2 cores (superset)
registry = {
"platforms": {
"testmerge": {
"config": "testmerge.yml",
"status": "active",
"cores": ["core_a", "core_b"],
}
}
}
with open(os.path.join(self.platforms_dir, "_registry.yml"), "w") as f:
yaml.dump(registry, f)
_platform_config_cache.clear()
loaded = load_platform_config("testmerge", self.platforms_dir)
cores = [str(c) for c in loaded["cores"]]
self.assertIn("core_a", cores)
self.assertIn("core_b", cores)
def test_176_all_libretro_in_list(self):
"""resolve_platform_cores expands all_libretro/retroarch in a list."""
from common import resolve_platform_cores, load_emulator_profiles
# Create a libretro profile and a standalone profile
for name, ptype in [("lr_core", "libretro"), ("sa_core", "standalone")]:
profile = {
"emulator": name,
"type": ptype,
"cores": [name],
"systems": ["test-system"],
"files": [],
}
with open(os.path.join(self.emulators_dir, f"{name}.yml"), "w") as f:
yaml.dump(profile, f)
profiles = load_emulator_profiles(self.emulators_dir)
# Config with retroarch + sa_core in cores list
config = {"cores": ["retroarch", "sa_core"]}
resolved = resolve_platform_cores(config, profiles)
self.assertIn("lr_core", resolved) # expanded via retroarch
self.assertIn("sa_core", resolved) # explicit
def test_177_diff_hash_fallback_rename(self):
"""Diff detects platform renames via hash fallback."""
from truth import diff_platform_truth
truth = {
"systems": {
"test-system": {
"_coverage": {"cores_profiled": ["c"], "cores_unprofiled": []},
"files": [
{"name": "ROM", "required": True, "md5": "abcd1234" * 4,
"_cores": ["c"], "_source_refs": []},
],
}
}
}
scraped = {
"systems": {
"test-system": {
"files": [
{"name": "ROM1", "required": True, "md5": "abcd1234" * 4},
],
}
}
}
result = diff_platform_truth(truth, scraped)
# ROM and ROM1 share the same hash — rename, not missing+phantom
self.assertEqual(result["summary"]["total_missing"], 0)
self.assertEqual(result["summary"]["total_extra_phantom"], 0)
def test_178_diff_system_normalization(self):
"""Diff matches systems with different IDs via normalization."""
from truth import diff_platform_truth
truth = {
"systems": {
"sega-gamegear": {
"_coverage": {"cores_profiled": ["c"], "cores_unprofiled": []},
"files": [
{"name": "bios.gg", "required": True, "md5": "a" * 32,
"_cores": ["c"], "_source_refs": []},
],
},
}
}
scraped = {
"systems": {
"sega-game-gear": {
"files": [
{"name": "bios.gg", "required": True, "md5": "a" * 32},
],
},
}
}
result = diff_platform_truth(truth, scraped)
self.assertEqual(result["summary"]["systems_uncovered"], 0)
self.assertEqual(result["summary"]["total_missing"], 0)
self.assertEqual(result["summary"]["systems_compared"], 1)
def test_179_agnostic_profile_skipped_in_undeclared(self):
"""bios_mode: agnostic profiles are skipped entirely by find_undeclared_files."""
config = load_platform_config("test_existence", self.platforms_dir)
profiles = load_emulator_profiles(self.emulators_dir)
undeclared = find_undeclared_files(config, self.emulators_dir, self.db, profiles)
emulators = {u["emulator"] for u in undeclared}
# TestAgnostic should NOT appear in undeclared (bios_mode: agnostic)
self.assertNotIn("TestAgnostic", emulators)
def test_180_agnostic_file_skipped_in_undeclared(self):
"""Files with agnostic: true are skipped, others in same profile are not."""
config = load_platform_config("test_existence", self.platforms_dir)
profiles = load_emulator_profiles(self.emulators_dir)
undeclared = find_undeclared_files(config, self.emulators_dir, self.db, profiles)
names = {u["name"] for u in undeclared}
# agnostic_file.bin should NOT be in undeclared (agnostic: true)
self.assertNotIn("agnostic_file.bin", names)
# undeclared_req.bin should still be in undeclared (not agnostic)
self.assertIn("undeclared_req.bin", names)
def test_181_agnostic_extras_scan(self):
"""Agnostic profiles add all matching DB files as extras."""
from generate_pack import _collect_emulator_extras
config = load_platform_config("test_existence", self.platforms_dir)
profiles = load_emulator_profiles(self.emulators_dir)
extras = _collect_emulator_extras(
config, self.emulators_dir, self.db, set(), "system", profiles,
)
agnostic_extras = [e for e in extras if e.get("source_emulator") == "TestAgnostic"]
# Agnostic scan should find files in the same directory as correct_hash.bin
self.assertTrue(len(agnostic_extras) > 0, "Agnostic scan should produce extras")
# All agnostic extras should have agnostic_scan flag
for e in agnostic_extras:
self.assertTrue(e.get("agnostic_scan", False))
def test_182_agnostic_rename_readme(self):
"""_build_agnostic_rename_readme generates correct text."""
from generate_pack import _build_agnostic_rename_readme
result = _build_agnostic_rename_readme(
"dsi_nand.bin", "DSi_Nand_AUS.bin",
["DSi_Nand_EUR.bin", "DSi_Nand_USA.bin"],
)
self.assertIn("dsi_nand.bin <- DSi_Nand_AUS.bin", result)
self.assertIn("DSi_Nand_EUR.bin", result)
self.assertIn("DSi_Nand_USA.bin", result)
self.assertIn("rename it to: dsi_nand.bin", result)
def test_183_agnostic_resolve_fallback(self):
"""resolve_local_file with agnostic fallback finds a system file."""
file_entry = {
"name": "nonexistent_agnostic.bin",
"agnostic": True,
"min_size": 1,
"max_size": 999999,
"agnostic_path_prefix": self.bios_dir + "/",
}
path, status = resolve_local_file(file_entry, self.db)
self.assertIsNotNone(path)
self.assertEqual(status, "agnostic_fallback")
def test_179_batocera_exporter_round_trip(self):
"""Batocera exporter produces valid Python dict format."""
from exporter.batocera_exporter import Exporter
truth = {
"systems": {
"sony-playstation": {
"_coverage": {"cores_profiled": ["c"]},
"files": [
{"name": "scph5501.bin", "destination": "scph5501.bin",
"required": True, "md5": "b" * 32,
"_cores": ["c"], "_source_refs": []},
],
}
}
}
scraped = {
"systems": {
"sony-playstation": {"native_id": "psx", "files": []},
}
}
out = os.path.join(self.root, "batocera-systems")
exp = Exporter()
exp.export(truth, out, scraped_data=scraped)
content = open(out).read()
self.assertIn('"psx"', content)
self.assertIn("scph5501.bin", content)
self.assertIn("b" * 32, content)
self.assertEqual(exp.validate(truth, out), [])
def test_180_recalbox_exporter_round_trip(self):
"""Recalbox exporter produces valid es_bios.xml."""
from exporter.recalbox_exporter import Exporter
truth = {
"systems": {
"sony-playstation": {
"_coverage": {"cores_profiled": ["c"]},
"files": [
{"name": "scph5501.bin", "destination": "scph5501.bin",
"required": True, "md5": "b" * 32,
"_cores": ["c"], "_source_refs": []},
],
}
}
}
scraped = {
"systems": {
"sony-playstation": {"native_id": "psx", "files": []},
}
}
out = os.path.join(self.root, "es_bios.xml")
exp = Exporter()
exp.export(truth, out, scraped_data=scraped)
content = open(out).read()
self.assertIn("<biosList", content)
self.assertIn('platform="psx"', content)
self.assertIn('fullname=', content)
self.assertIn("scph5501.bin", content)
# mandatory="true" is the default, not emitted (matching Recalbox format)
self.assertNotIn('mandatory="false"', content)
self.assertIn('core="libretro/c"', content)
self.assertEqual(exp.validate(truth, out), [])
def test_181_retrobat_exporter_round_trip(self):
"""RetroBat exporter produces valid JSON."""
import json as _json
from exporter.retrobat_exporter import Exporter
truth = {
"systems": {
"sony-playstation": {
"_coverage": {"cores_profiled": ["c"]},
"files": [
{"name": "scph5501.bin", "destination": "scph5501.bin",
"required": True, "md5": "b" * 32,
"_cores": ["c"], "_source_refs": []},
],
}
}
}
scraped = {
"systems": {
"sony-playstation": {"native_id": "psx", "files": []},
}
}
out = os.path.join(self.root, "batocera-systems.json")
exp = Exporter()
exp.export(truth, out, scraped_data=scraped)
data = _json.loads(open(out).read())
self.assertIn("psx", data)
self.assertTrue(any("scph5501" in bf["file"] for bf in data["psx"]["biosFiles"]))
self.assertEqual(exp.validate(truth, out), [])
def test_182_exporter_discovery(self):
"""All exporters are discovered by the plugin system."""
from exporter import discover_exporters
exporters = discover_exporters()
self.assertIn("retroarch", exporters)
self.assertIn("batocera", exporters)
self.assertIn("recalbox", exporters)
self.assertIn("retrobat", exporters)
if __name__ == "__main__":
unittest.main()