mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-04-13 12:22:33 -05:00
Compare commits
20 Commits
a8430940f9
...
caf6285a04
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caf6285a04 | ||
|
|
529cb8a915 | ||
|
|
1146fdf177 | ||
|
|
4fbb3571f8 | ||
|
|
0be68edad0 | ||
|
|
1ffc4f89ca | ||
|
|
f1ebfff5bd | ||
|
|
425ea064ae | ||
|
|
6818a18a42 | ||
|
|
c11de6dba6 | ||
|
|
c4f3192020 | ||
|
|
e2d0510f4e | ||
|
|
74269bab84 | ||
|
|
1e6b499602 | ||
|
|
9b785ec785 | ||
|
|
d415777f2c | ||
|
|
eafabd20f3 | ||
|
|
2aca4927c0 | ||
|
|
17777f315b | ||
|
|
692484d32d |
@@ -130,4 +130,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|||||||
|
|
||||||
This repository provides BIOS files for personal backup and archival purposes.
|
This repository provides BIOS files for personal backup and archival purposes.
|
||||||
|
|
||||||
*Auto-generated on 2026-03-30T07:40:45Z*
|
*Auto-generated on 2026-03-30T12:09:51Z*
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"generated_at": "2026-03-30T07:24:43Z",
|
"generated_at": "2026-03-30T13:15:58Z",
|
||||||
"total_files": 7239,
|
"total_files": 7241,
|
||||||
"total_size": 8539795099,
|
"total_size": 8540057243,
|
||||||
"files": {
|
"files": {
|
||||||
"520d3d1b5897800af47f92efd2444a26b7a7dead": {
|
"520d3d1b5897800af47f92efd2444a26b7a7dead": {
|
||||||
"path": "bios/3DO Company/3DO/3do_arcade_saot.bin",
|
"path": "bios/3DO Company/3DO/3do_arcade_saot.bin",
|
||||||
@@ -40843,16 +40843,6 @@
|
|||||||
"crc32": "11647ca5",
|
"crc32": "11647ca5",
|
||||||
"adler32": "1817f6f4"
|
"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": {
|
"aa811861f8874775075bd3f53008c8aaf59b07db": {
|
||||||
"path": "bios/Pioneer/LaserActive/Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin",
|
"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",
|
"name": "Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin",
|
||||||
@@ -40863,6 +40853,16 @@
|
|||||||
"crc32": "50cd3d23",
|
"crc32": "50cd3d23",
|
||||||
"adler32": "72a13133"
|
"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": {
|
"6973e2593e66fd21627fedccec98d4a364afaaff": {
|
||||||
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
|
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
|
||||||
"name": "[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
|
"name": "[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin",
|
||||||
@@ -40883,6 +40883,26 @@
|
|||||||
"crc32": "01223dd5",
|
"crc32": "01223dd5",
|
||||||
"adler32": "74e98625"
|
"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": {
|
"c1b9202cbe072db12114b223a9ba5374b30718fb": {
|
||||||
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
|
"path": "bios/Pioneer/LaserActive/[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
|
||||||
"name": "[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
|
"name": "[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin",
|
||||||
@@ -76480,10 +76500,12 @@
|
|||||||
"c500ff71236068e0dc0d0603d265ae76": "5130243429b40b01a14e1304d0394b8459a6fbae",
|
"c500ff71236068e0dc0d0603d265ae76": "5130243429b40b01a14e1304d0394b8459a6fbae",
|
||||||
"f1071cdb0b6b10dde94d3bc8a6146387": "a6120aed50831c9c0d95dbdf707820f601d9452e",
|
"f1071cdb0b6b10dde94d3bc8a6146387": "a6120aed50831c9c0d95dbdf707820f601d9452e",
|
||||||
"279008e4a0db2dc5f1c048853b033828": "54b8d2c1317628de51a85fc1c424423a986775e4",
|
"279008e4a0db2dc5f1c048853b033828": "54b8d2c1317628de51a85fc1c424423a986775e4",
|
||||||
"a5a2f9aae57d464bc66b80ee79c3da6e": "26237b333db4a4c6770297fa5e655ea95840d5d9",
|
|
||||||
"0e7393cd0951d6dde818fcd4cd819466": "aa811861f8874775075bd3f53008c8aaf59b07db",
|
"0e7393cd0951d6dde818fcd4cd819466": "aa811861f8874775075bd3f53008c8aaf59b07db",
|
||||||
|
"a5a2f9aae57d464bc66b80ee79c3da6e": "26237b333db4a4c6770297fa5e655ea95840d5d9",
|
||||||
"f69f173b251d8bf7649b10a9167a10bf": "6973e2593e66fd21627fedccec98d4a364afaaff",
|
"f69f173b251d8bf7649b10a9167a10bf": "6973e2593e66fd21627fedccec98d4a364afaaff",
|
||||||
"f0fb8a4605ac7eefbafd4f2d5a793cc8": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
|
"f0fb8a4605ac7eefbafd4f2d5a793cc8": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
|
||||||
|
"219dc2aa7cb8d1ad5142c86d50c2ffa5": "bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3",
|
||||||
|
"515636778430c8e01027234c38c4ddf8": "f7101b40cae0484a0f43f3bbee2d55033ff1e3ec",
|
||||||
"761fea207d0eafd4cfd78da7c44cac88": "c1b9202cbe072db12114b223a9ba5374b30718fb",
|
"761fea207d0eafd4cfd78da7c44cac88": "c1b9202cbe072db12114b223a9ba5374b30718fb",
|
||||||
"69489153dde910a69d5ae6de5dd65323": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
|
"69489153dde910a69d5ae6de5dd65323": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
|
||||||
"3fd0d13282b031f4c017cd6bf6597183": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
|
"3fd0d13282b031f4c017cd6bf6597183": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
|
||||||
@@ -91151,18 +91173,24 @@
|
|||||||
"jopac.bin": [
|
"jopac.bin": [
|
||||||
"54b8d2c1317628de51a85fc1c424423a986775e4"
|
"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": [
|
"Pioneer LaserActive Sega PAC Boot ROM v1.04 (1993)(Pioneer - Sega)(US).bin": [
|
||||||
"aa811861f8874775075bd3f53008c8aaf59b07db"
|
"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": [
|
"[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin": [
|
||||||
"6973e2593e66fd21627fedccec98d4a364afaaff"
|
"6973e2593e66fd21627fedccec98d4a364afaaff"
|
||||||
],
|
],
|
||||||
"[BIOS] LaserActive PAC-N10 (US) (v1.02).bin": [
|
"[BIOS] LaserActive PAC-N10 (US) (v1.02).bin": [
|
||||||
"f7412aa822d70a55b2ff3d7095137263dc54f6b6"
|
"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": [
|
"[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin": [
|
||||||
"c1b9202cbe072db12114b223a9ba5374b30718fb"
|
"c1b9202cbe072db12114b223a9ba5374b30718fb"
|
||||||
],
|
],
|
||||||
@@ -101218,6 +101246,9 @@
|
|||||||
"g7400.bin": [
|
"g7400.bin": [
|
||||||
"5130243429b40b01a14e1304d0394b8459a6fbae"
|
"5130243429b40b01a14e1304d0394b8459a6fbae"
|
||||||
],
|
],
|
||||||
|
"[BIOS] LaserActive PAC-S10 (US) (v1.04).bin": [
|
||||||
|
"aa811861f8874775075bd3f53008c8aaf59b07db"
|
||||||
|
],
|
||||||
"Battle 1.mid": [
|
"Battle 1.mid": [
|
||||||
"dc5cc32fafa442b09ab2d814ed32074d02597234"
|
"dc5cc32fafa442b09ab2d814ed32074d02597234"
|
||||||
],
|
],
|
||||||
@@ -107490,10 +107521,12 @@
|
|||||||
"e20a9f41": "5130243429b40b01a14e1304d0394b8459a6fbae",
|
"e20a9f41": "5130243429b40b01a14e1304d0394b8459a6fbae",
|
||||||
"a318e8d6": "a6120aed50831c9c0d95dbdf707820f601d9452e",
|
"a318e8d6": "a6120aed50831c9c0d95dbdf707820f601d9452e",
|
||||||
"11647ca5": "54b8d2c1317628de51a85fc1c424423a986775e4",
|
"11647ca5": "54b8d2c1317628de51a85fc1c424423a986775e4",
|
||||||
"00eedb3a": "26237b333db4a4c6770297fa5e655ea95840d5d9",
|
|
||||||
"50cd3d23": "aa811861f8874775075bd3f53008c8aaf59b07db",
|
"50cd3d23": "aa811861f8874775075bd3f53008c8aaf59b07db",
|
||||||
|
"00eedb3a": "26237b333db4a4c6770297fa5e655ea95840d5d9",
|
||||||
"a8cb694c": "6973e2593e66fd21627fedccec98d4a364afaaff",
|
"a8cb694c": "6973e2593e66fd21627fedccec98d4a364afaaff",
|
||||||
"01223dd5": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
|
"01223dd5": "f7412aa822d70a55b2ff3d7095137263dc54f6b6",
|
||||||
|
"24ad336e": "bc746df0c5d2b779ca41a94954b60d6ac6a7c2a3",
|
||||||
|
"1493522c": "f7101b40cae0484a0f43f3bbee2d55033ff1e3ec",
|
||||||
"76116a02": "c1b9202cbe072db12114b223a9ba5374b30718fb",
|
"76116a02": "c1b9202cbe072db12114b223a9ba5374b30718fb",
|
||||||
"4e70e3c0": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
|
"4e70e3c0": "f2a9ce387019bf272c6e3459d961b30f28942ac5",
|
||||||
"92bcc762": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
|
"92bcc762": "9dda4cbcc1d3f6d38c10fee3de53b9abd5e47ec0",
|
||||||
@@ -124965,6 +124998,9 @@
|
|||||||
"roms/win486/ALI1429G.AMW": [
|
"roms/win486/ALI1429G.AMW": [
|
||||||
"72c60172fb1ba77c9b24b06b7755f0a16f0b3a13"
|
"72c60172fb1ba77c9b24b06b7755f0a16f0b3a13"
|
||||||
],
|
],
|
||||||
|
".variants/[BIOS] LaserActive PAC-S10 (US) (v1.04).bin": [
|
||||||
|
"aa811861f8874775075bd3f53008c8aaf59b07db"
|
||||||
|
],
|
||||||
"rtp/2003/Battle/Arrow.png": [
|
"rtp/2003/Battle/Arrow.png": [
|
||||||
"7aa8d4c377efcea1c9fad01924da1ba7b8575e1e"
|
"7aa8d4c377efcea1c9fad01924da1ba7b8575e1e"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
emulator: LRPS2
|
emulator: LRPS2
|
||||||
type: libretro
|
type: libretro
|
||||||
core_classification: community_fork
|
core_classification: community_fork
|
||||||
|
bios_mode: agnostic
|
||||||
source: "https://github.com/libretro/ps2"
|
source: "https://github.com/libretro/ps2"
|
||||||
upstream: "https://github.com/PCSX2/pcsx2"
|
upstream: "https://github.com/PCSX2/pcsx2"
|
||||||
profiled_date: "2026-03-25"
|
profiled_date: "2026-03-25"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ files:
|
|||||||
source_ref: "src/SPI.cpp:197-211, src/frontend/Util_ROM.cpp:201-217"
|
source_ref: "src/SPI.cpp:197-211, src/frontend/Util_ROM.cpp:201-217"
|
||||||
|
|
||||||
- name: dsi_nand.bin
|
- name: dsi_nand.bin
|
||||||
aliases: [DSi_Nand_USA.bin, DSi_Nand_EUR.bin, DSi_Nand_JPN.bin, DSi_Nand_AUS.bin, DSi_Nand_CHN.bin, DSi_Nand_KOR.bin]
|
agnostic: true
|
||||||
system: nintendo-dsi
|
system: nintendo-dsi
|
||||||
description: "DSi NAND dump"
|
description: "DSi NAND dump"
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -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
|
emulator: PCSX2
|
||||||
type: standalone
|
type: standalone
|
||||||
|
core_classification: official_port
|
||||||
|
bios_mode: agnostic
|
||||||
source: "https://github.com/PCSX2/pcsx2"
|
source: "https://github.com/PCSX2/pcsx2"
|
||||||
logo: "https://raw.githubusercontent.com/PCSX2/pcsx2/master/pcsx2-qt/resources/icons/PCSX2logo.svg"
|
upstream: "https://github.com/PCSX2/pcsx2"
|
||||||
profiled_date: "2026-03-18"
|
cores:
|
||||||
|
- pcsx2
|
||||||
|
profiled_date: "2026-03-30"
|
||||||
core_version: "Git"
|
core_version: "Git"
|
||||||
display_name: "Sony - PlayStation 2 (LRPS2)"
|
display_name: "Sony - PlayStation 2 (PCSX2)"
|
||||||
systems: [sony-playstation-2]
|
systems: [sony-playstation-2]
|
||||||
|
|
||||||
bios_directory: "bios/"
|
notes: |
|
||||||
bios_detection: "romdir" # scans romdir structure inside binary, looks for RESET/ROMVER/EXTINFO entries
|
Filename-agnostic BIOS detection. Scans bios/ for any file between 4-8 MB
|
||||||
bios_selection: "automatic" # scans all files in bios dir matching 4-8 MB size, validates via romdir
|
with valid romdir structure (RESET + ROMVER entries). No hash validation.
|
||||||
|
Companion files (.rom1, .rom2, .nvm, .mec) derive paths from selected BIOS.
|
||||||
validation:
|
ROM1 (DVD player) and ROM2 (Chinese extension) silently skipped if missing.
|
||||||
method: "romdir_parse"
|
NVM and MEC auto-created with defaults if missing.
|
||||||
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}
|
|
||||||
|
|
||||||
files:
|
files:
|
||||||
# -- Main BIOS binary (required) --
|
- name: ps2-0230a-20080220.bin
|
||||||
- name: "<user-selected>.bin"
|
|
||||||
pattern: "*"
|
|
||||||
required: true
|
required: true
|
||||||
size_range: "4MB-8MB"
|
min_size: 4194304
|
||||||
source_ref: "pcsx2/ps2/BiosTools.cpp:258-282"
|
max_size: 8388608
|
||||||
note: >
|
validation: [size]
|
||||||
PCSX2 does not mandate a specific filename. It scans the entire bios/ directory
|
source_ref: "pcsx2/ps2/BiosTools.cpp:258-362"
|
||||||
for any file between 4-8 MB that contains a valid romdir structure (RESET + ROMVER entries).
|
note: "Accepts any file 4-8 MB with valid romdir (RESET + ROMVER). Naming convention ps2-VVVVr-YYYYMMDD.bin (version, region, date)."
|
||||||
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.
|
|
||||||
|
|
||||||
# -- ROM1 (optional, DVD player) --
|
- name: rom1.bin
|
||||||
- name: "<biosname>.rom1"
|
|
||||||
pattern: "{biosname}.rom1 or {biosbase}.rom1"
|
|
||||||
required: false
|
required: false
|
||||||
max_size: 4194304 # 4 MB (Ps2MemSize::Rom1)
|
max_size: 4194304
|
||||||
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241"
|
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241,366"
|
||||||
note: >
|
note: "DVD player ROM. Tries {biospath}.rom1 then {biosbase}.rom1. Silently skipped if missing."
|
||||||
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).
|
|
||||||
|
|
||||||
# -- ROM2 (optional, Chinese ROM extension) --
|
- name: ROM2.BIN
|
||||||
- name: "<biosname>.rom2"
|
|
||||||
pattern: "{biosname}.rom2 or {biosbase}.rom2"
|
|
||||||
required: false
|
required: false
|
||||||
max_size: 4194304 # 4 MB (Ps2MemSize::Rom2)
|
max_size: 4194304
|
||||||
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241"
|
source_ref: "pcsx2/ps2/BiosTools.cpp:214-241,367"
|
||||||
note: >
|
note: "Chinese ROM extension. Same naming convention as rom1. Only present on Chinese region consoles."
|
||||||
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.
|
|
||||||
|
|
||||||
# -- NVM / NVRAM (optional, auto-created) --
|
- name: EROM.BIN
|
||||||
- name: "<biosname>.nvm"
|
required: false
|
||||||
pattern: "{biosbase}.nvm"
|
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
|
required: false
|
||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
size: 1024 # NVRAM_SIZE = 1024 bytes
|
size: 64
|
||||||
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
|
|
||||||
source_ref: "pcsx2/DEV9/DEV9.cpp:110-160"
|
source_ref: "pcsx2/DEV9/DEV9.cpp:110-160"
|
||||||
note: >
|
note: "DEV9 network adapter EEPROM. Falls back to built-in defaults if missing."
|
||||||
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).
|
|
||||||
|
|
||||||
common_bios_filenames:
|
- name: GameIndex.yaml
|
||||||
# Japan
|
path: pcsx2/resources/GameIndex.yaml
|
||||||
- "SCPH-10000_BIOS_V1_JAP_100.BIN"
|
required: false
|
||||||
- "SCPH-15000_BIOS_V3_JAP_120.BIN"
|
mode: libretro
|
||||||
- "SCPH-30000_BIOS_V4_JAP_150.BIN"
|
source_ref: "pcsx2/GameDatabase.cpp:48,880"
|
||||||
- "SCPH-30001R_BIOS_V7_JAP_160.BIN"
|
note: "Game compatibility database. OSD warning if missing."
|
||||||
- "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"
|
|
||||||
|
|
||||||
memory_layout:
|
- name: cheats_ws.zip
|
||||||
ROM: {offset: "0x1FC00000", size: "4 MB", purpose: "Main BIOS binary"}
|
path: pcsx2/resources/cheats_ws.zip
|
||||||
ROM1: {offset: "ROM + 4MB", size: "4 MB", purpose: "DVD player"}
|
required: false
|
||||||
ROM2: {offset: "ROM + 8MB", size: "4 MB", purpose: "Chinese ROM extension"}
|
mode: libretro
|
||||||
|
source_ref: "pcsx2/VMManager.cpp:340-353"
|
||||||
|
note: "Widescreen patches archive."
|
||||||
|
|
||||||
nvm_layout:
|
- name: cheats_ni.zip
|
||||||
format_0:
|
path: pcsx2/resources/cheats_ni.zip
|
||||||
applies_to: "BIOS v0.00+"
|
required: false
|
||||||
biosVer: 0x000
|
mode: libretro
|
||||||
config0: 0x280
|
source_ref: "pcsx2/VMManager.cpp:375-388"
|
||||||
config1: 0x300
|
note: "No-interlacing patches archive."
|
||||||
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.
|
|
||||||
|
|||||||
@@ -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
|
emulator: RPCS3
|
||||||
type: standalone
|
type: standalone
|
||||||
|
core_classification: official_port
|
||||||
source: "https://github.com/RPCS3/rpcs3"
|
source: "https://github.com/RPCS3/rpcs3"
|
||||||
logo: "https://raw.githubusercontent.com/RPCS3/rpcs3/master/rpcs3/rpcs3.svg"
|
upstream: "https://github.com/RPCS3/rpcs3"
|
||||||
profiled_date: "2026-03-18"
|
cores:
|
||||||
|
- rpcs3
|
||||||
|
profiled_date: "2026-03-30"
|
||||||
core_version: "0.0.35"
|
core_version: "0.0.35"
|
||||||
display_name: "RPCS3 (PS3)"
|
display_name: "Sony - PlayStation 3 (RPCS3)"
|
||||||
systems: [sony-playstation-3]
|
systems: [sony-playstation-3]
|
||||||
|
|
||||||
firmware_file: "PS3UPDAT.PUP"
|
files:
|
||||||
firmware_source: "https://www.playstation.com/en-us/support/hardware/ps3/system-software/"
|
- name: PS3UPDAT.PUP
|
||||||
firmware_detection: "pup_header" # validates PUP magic bytes, HMAC-SHA1 hash per entry
|
required: true
|
||||||
firmware_install: "extracts dev_flash_* TAR packages from PUP into dev_flash/"
|
storage: large_file
|
||||||
|
source_ref: "rpcs3/Loader/PUP.cpp:23-77"
|
||||||
validation:
|
note: "PUP firmware package. Validated via SCEUF magic + HMAC-SHA1 per entry. Extracted to dev_flash/ at install time."
|
||||||
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'"
|
|
||||||
|
|
||||||
# dev_flash filesystem layout extracted from PUP
|
# dev_flash filesystem layout extracted from PUP
|
||||||
dev_flash:
|
dev_flash:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "batocera",
|
"platform": "batocera",
|
||||||
"display_name": "Batocera",
|
"display_name": "Batocera",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:37:55Z",
|
"generated": "2026-03-30T09:46:19Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "bizhawk",
|
"platform": "bizhawk",
|
||||||
"display_name": "BizHawk",
|
"display_name": "BizHawk",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:37:59Z",
|
"generated": "2026-03-30T09:46:23Z",
|
||||||
"base_destination": "Firmware",
|
"base_destination": "Firmware",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "emudeck",
|
"platform": "emudeck",
|
||||||
"display_name": "EmuDeck",
|
"display_name": "EmuDeck",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:38:01Z",
|
"generated": "2026-03-30T09:46:25Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "lakka",
|
"platform": "lakka",
|
||||||
"display_name": "Lakka",
|
"display_name": "Lakka",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:38:59Z",
|
"generated": "2026-03-30T09:47:34Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "recalbox",
|
"platform": "recalbox",
|
||||||
"display_name": "Recalbox",
|
"display_name": "Recalbox",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:39:27Z",
|
"generated": "2026-03-30T09:48:01Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "retroarch",
|
"platform": "retroarch",
|
||||||
"display_name": "RetroArch",
|
"display_name": "RetroArch",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:38:59Z",
|
"generated": "2026-03-30T09:47:34Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "retrobat",
|
"platform": "retrobat",
|
||||||
"display_name": "RetroBat",
|
"display_name": "RetroBat",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:39:32Z",
|
"generated": "2026-03-30T09:48:07Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "retrodeck",
|
"platform": "retrodeck",
|
||||||
"display_name": "RetroDECK",
|
"display_name": "RetroDECK",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:40:43Z",
|
"generated": "2026-03-30T09:49:19Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"platform": "romm",
|
"platform": "romm",
|
||||||
"display_name": "RomM",
|
"display_name": "RomM",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-03-30T07:40:45Z",
|
"generated": "2026-03-30T09:49:20Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ nav:
|
|||||||
- ZC: systems/zc.md
|
- ZC: systems/zc.md
|
||||||
- Emulators:
|
- Emulators:
|
||||||
- Overview: emulators/index.md
|
- Overview: emulators/index.md
|
||||||
- Official ports (61):
|
- Official ports (62):
|
||||||
- amiarcadia: emulators/amiarcadia.md
|
- amiarcadia: emulators/amiarcadia.md
|
||||||
- Amiberry: emulators/amiberry.md
|
- Amiberry: emulators/amiberry.md
|
||||||
- Ardens: emulators/ardens.md
|
- Ardens: emulators/ardens.md
|
||||||
@@ -176,6 +176,7 @@ nav:
|
|||||||
- mGBA: emulators/mgba.md
|
- mGBA: emulators/mgba.md
|
||||||
- Mr.Boom: emulators/mrboom.md
|
- Mr.Boom: emulators/mrboom.md
|
||||||
- Panda3DS: emulators/panda3ds.md
|
- Panda3DS: emulators/panda3ds.md
|
||||||
|
- PCSX2: emulators/pcsx2.md
|
||||||
- PicoDrive: emulators/picodrive.md
|
- PicoDrive: emulators/picodrive.md
|
||||||
- play: emulators/play.md
|
- play: emulators/play.md
|
||||||
- PPSSPP: emulators/ppsspp.md
|
- PPSSPP: emulators/ppsspp.md
|
||||||
@@ -428,7 +429,7 @@ nav:
|
|||||||
- PCSX-ReARMed: emulators/pcsx_rearmed.md
|
- PCSX-ReARMed: emulators/pcsx_rearmed.md
|
||||||
- Launchers (1):
|
- Launchers (1):
|
||||||
- Dolphin Launcher: emulators/dolphin_launcher.md
|
- Dolphin Launcher: emulators/dolphin_launcher.md
|
||||||
- Other (25):
|
- Other (24):
|
||||||
- ares: emulators/ares.md
|
- ares: emulators/ares.md
|
||||||
- Beetle GBA (Mednafen): emulators/beetle_gba.md
|
- Beetle GBA (Mednafen): emulators/beetle_gba.md
|
||||||
- BigPEmu: emulators/bigpemu.md
|
- BigPEmu: emulators/bigpemu.md
|
||||||
@@ -440,7 +441,6 @@ nav:
|
|||||||
- Lexaloffle: emulators/lexaloffle.md
|
- Lexaloffle: emulators/lexaloffle.md
|
||||||
- Model 2 Emulator: emulators/model2.md
|
- Model 2 Emulator: emulators/model2.md
|
||||||
- openMSX: emulators/openmsx.md
|
- openMSX: emulators/openmsx.md
|
||||||
- PCSX2: emulators/pcsx2.md
|
|
||||||
- Redream: emulators/redream.md
|
- Redream: emulators/redream.md
|
||||||
- RPCS3: emulators/rpcs3.md
|
- RPCS3: emulators/rpcs3.md
|
||||||
- Ryujinx: emulators/ryujinx.md
|
- Ryujinx: emulators/ryujinx.md
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ platforms:
|
|||||||
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
|
source_format: clrmamepro_dat
|
||||||
hash_type: sha1
|
hash_type: sha1
|
||||||
|
verification_mode: existence
|
||||||
|
base_destination: system
|
||||||
|
case_insensitive_fs: true
|
||||||
schedule: weekly
|
schedule: weekly
|
||||||
cores: all_libretro
|
cores: all_libretro
|
||||||
target_scraper: retroarch_targets
|
target_scraper: retroarch_targets
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 0bac0c6a50104045d902df4503a4c30b
|
md5: 0bac0c6a50104045d902df4503a4c30b
|
||||||
native_id: atari800
|
native_id: atari800
|
||||||
|
name: Atari 800
|
||||||
atari-5200:
|
atari-5200:
|
||||||
files:
|
files:
|
||||||
- name: 5200.rom
|
- name: 5200.rom
|
||||||
@@ -190,6 +191,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 281f20ea4320404ec820fb7ec0693b38
|
md5: 281f20ea4320404ec820fb7ec0693b38
|
||||||
native_id: atari5200
|
native_id: atari5200
|
||||||
|
name: Atari 5200
|
||||||
atari-st:
|
atari-st:
|
||||||
files:
|
files:
|
||||||
- name: tos.img
|
- name: tos.img
|
||||||
@@ -337,6 +339,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: e5ea0f216fb446f1c4a4f476bc5f03d4
|
md5: e5ea0f216fb446f1c4a4f476bc5f03d4
|
||||||
native_id: atarist
|
native_id: atarist
|
||||||
|
name: Atari ST
|
||||||
atari-lynx:
|
atari-lynx:
|
||||||
files:
|
files:
|
||||||
- name: lynxboot.img
|
- name: lynxboot.img
|
||||||
@@ -344,6 +347,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: fcd403db69f54290b51035d82f835e7b
|
md5: fcd403db69f54290b51035d82f835e7b
|
||||||
native_id: lynx
|
native_id: lynx
|
||||||
|
name: Lynx
|
||||||
magnavox-odyssey2:
|
magnavox-odyssey2:
|
||||||
files:
|
files:
|
||||||
- name: o2rom.bin
|
- name: o2rom.bin
|
||||||
@@ -355,6 +359,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: f1071cdb0b6b10dde94d3bc8a6146387
|
md5: f1071cdb0b6b10dde94d3bc8a6146387
|
||||||
native_id: odyssey2
|
native_id: odyssey2
|
||||||
|
name: Odyssey 2
|
||||||
videopacplus:
|
videopacplus:
|
||||||
files:
|
files:
|
||||||
- name: g7400.bin
|
- name: g7400.bin
|
||||||
@@ -366,6 +371,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 279008e4a0db2dc5f1c048853b033828
|
md5: 279008e4a0db2dc5f1c048853b033828
|
||||||
native_id: videopacplus
|
native_id: videopacplus
|
||||||
|
name: Videopac+ G7400
|
||||||
mattel-intellivision:
|
mattel-intellivision:
|
||||||
files:
|
files:
|
||||||
- name: exec.bin
|
- name: exec.bin
|
||||||
@@ -377,6 +383,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 0cd5946c6473e42e8e4c2137785e427f
|
md5: 0cd5946c6473e42e8e4c2137785e427f
|
||||||
native_id: intellivision
|
native_id: intellivision
|
||||||
|
name: Mattel Intellivision
|
||||||
nec-pc-engine:
|
nec-pc-engine:
|
||||||
files:
|
files:
|
||||||
- name: syscard3.pce
|
- name: syscard3.pce
|
||||||
@@ -388,6 +395,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 38179df8f4ac870017db21ebcbf53114
|
md5: 38179df8f4ac870017db21ebcbf53114
|
||||||
native_id: pcengine
|
native_id: pcengine
|
||||||
|
name: Supergrafx
|
||||||
nec-pc-fx:
|
nec-pc-fx:
|
||||||
files:
|
files:
|
||||||
- name: pcfx.rom
|
- name: pcfx.rom
|
||||||
@@ -395,6 +403,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 08e36edbea28a017f79f8d4f7ff9b6d7
|
md5: 08e36edbea28a017f79f8d4f7ff9b6d7
|
||||||
native_id: pcfx
|
native_id: pcfx
|
||||||
|
name: PC-FX
|
||||||
snk-neogeo:
|
snk-neogeo:
|
||||||
files:
|
files:
|
||||||
- name: neogeo.zip
|
- name: neogeo.zip
|
||||||
@@ -402,6 +411,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: dffb72f116d36d025068b23970a4f6df
|
md5: dffb72f116d36d025068b23970a4f6df
|
||||||
native_id: neogeo
|
native_id: neogeo
|
||||||
|
name: NeoGeo
|
||||||
snk-neogeo-cd:
|
snk-neogeo-cd:
|
||||||
files:
|
files:
|
||||||
- name: neocd_f.rom
|
- name: neocd_f.rom
|
||||||
@@ -445,6 +455,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 08ca8b2dba6662e8024f9e789711c6fc
|
md5: 08ca8b2dba6662e8024f9e789711c6fc
|
||||||
native_id: neogeocd
|
native_id: neogeocd
|
||||||
|
name: NeoGeo CD
|
||||||
sharp-x68000:
|
sharp-x68000:
|
||||||
files:
|
files:
|
||||||
- name: iplrom.dat
|
- name: iplrom.dat
|
||||||
@@ -456,6 +467,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: cb0a5cfcf7247a7eab74bb2716260269
|
md5: cb0a5cfcf7247a7eab74bb2716260269
|
||||||
native_id: x68000
|
native_id: x68000
|
||||||
|
name: Sharp x68000
|
||||||
3do:
|
3do:
|
||||||
files:
|
files:
|
||||||
- name: panafz1.bin
|
- name: panafz1.bin
|
||||||
@@ -471,6 +483,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 8639fd5e549bd6238cfee79e3e749114
|
md5: 8639fd5e549bd6238cfee79e3e749114
|
||||||
native_id: 3do
|
native_id: 3do
|
||||||
|
name: 3DO
|
||||||
sega-dreamcast:
|
sega-dreamcast:
|
||||||
files:
|
files:
|
||||||
- name: dc_boot.bin
|
- name: dc_boot.bin
|
||||||
@@ -478,6 +491,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: e10c53c2f8b90bab96ead2d368858623
|
md5: e10c53c2f8b90bab96ead2d368858623
|
||||||
native_id: dreamcast
|
native_id: dreamcast
|
||||||
|
name: Dreamcast
|
||||||
sega-dreamcast-arcade:
|
sega-dreamcast-arcade:
|
||||||
files:
|
files:
|
||||||
- name: naomi.zip
|
- name: naomi.zip
|
||||||
@@ -597,6 +611,7 @@ systems:
|
|||||||
md5: 960ece0dc22a7c5ff81c812a2993e7cc
|
md5: 960ece0dc22a7c5ff81c812a2993e7cc
|
||||||
zipped_file: x76f100_eeprom.bin
|
zipped_file: x76f100_eeprom.bin
|
||||||
native_id: naomi
|
native_id: naomi
|
||||||
|
name: Naomi 2
|
||||||
sega-mega-cd:
|
sega-mega-cd:
|
||||||
files:
|
files:
|
||||||
- name: bios_CD_E.bin
|
- name: bios_CD_E.bin
|
||||||
@@ -612,6 +627,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 278a9397d192149e84e820ac621a8edd
|
md5: 278a9397d192149e84e820ac621a8edd
|
||||||
native_id: segacd
|
native_id: segacd
|
||||||
|
name: Sega CD
|
||||||
megadrive-msu:
|
megadrive-msu:
|
||||||
files:
|
files:
|
||||||
- name: bios_CD_E.bin
|
- name: bios_CD_E.bin
|
||||||
@@ -627,6 +643,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 278a9397d192149e84e820ac621a8edd
|
md5: 278a9397d192149e84e820ac621a8edd
|
||||||
native_id: megadrive-msu
|
native_id: megadrive-msu
|
||||||
|
name: MSU-MD
|
||||||
sega-saturn:
|
sega-saturn:
|
||||||
files:
|
files:
|
||||||
- name: sega_101.bin
|
- name: sega_101.bin
|
||||||
@@ -650,6 +667,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: af5828fdff51384f99b3c4926be27762
|
md5: af5828fdff51384f99b3c4926be27762
|
||||||
native_id: saturn
|
native_id: saturn
|
||||||
|
name: Sega Saturn
|
||||||
sony-playstation:
|
sony-playstation:
|
||||||
files:
|
files:
|
||||||
- name: psxonpsp660.bin
|
- name: psxonpsp660.bin
|
||||||
@@ -681,6 +699,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 1e68c231d0896b7eadcad1d7d8e76129
|
md5: 1e68c231d0896b7eadcad1d7d8e76129
|
||||||
native_id: psx
|
native_id: psx
|
||||||
|
name: PSX
|
||||||
sony-playstation-2:
|
sony-playstation-2:
|
||||||
files:
|
files:
|
||||||
- name: ps2-0230a-20080220.bin
|
- name: ps2-0230a-20080220.bin
|
||||||
@@ -688,6 +707,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 21038400dc633070a78ad53090c53017
|
md5: 21038400dc633070a78ad53090c53017
|
||||||
native_id: ps2
|
native_id: ps2
|
||||||
|
name: PS2
|
||||||
sony-playstation-3:
|
sony-playstation-3:
|
||||||
files:
|
files:
|
||||||
- name: PS3UPDAT.PUP
|
- name: PS3UPDAT.PUP
|
||||||
@@ -695,6 +715,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 05fe32f5dc8c78acbcd84d36ee7fdc5b
|
md5: 05fe32f5dc8c78acbcd84d36ee7fdc5b
|
||||||
native_id: ps3
|
native_id: ps3
|
||||||
|
name: PS3
|
||||||
nintendo-fds:
|
nintendo-fds:
|
||||||
files:
|
files:
|
||||||
- name: disksys.rom
|
- name: disksys.rom
|
||||||
@@ -702,6 +723,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: ca30b50f880eb660a320674ed365ef7a
|
md5: ca30b50f880eb660a320674ed365ef7a
|
||||||
native_id: fds
|
native_id: fds
|
||||||
|
name: Nintendo Family Computer Disk System
|
||||||
nintendo-ds:
|
nintendo-ds:
|
||||||
files:
|
files:
|
||||||
- name: firmware.bin
|
- name: firmware.bin
|
||||||
@@ -730,6 +752,7 @@ systems:
|
|||||||
destination: dsi_nand.bin
|
destination: dsi_nand.bin
|
||||||
required: true
|
required: true
|
||||||
native_id: nds
|
native_id: nds
|
||||||
|
name: Nintendo DS
|
||||||
nintendo-gba:
|
nintendo-gba:
|
||||||
files:
|
files:
|
||||||
- name: gba_bios.bin
|
- name: gba_bios.bin
|
||||||
@@ -749,6 +772,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: d574d4f9c12f305074798f54c091a8b4
|
md5: d574d4f9c12f305074798f54c091a8b4
|
||||||
native_id: gba
|
native_id: gba
|
||||||
|
name: Nintendo Gameboy Advance
|
||||||
nintendo-satellaview:
|
nintendo-satellaview:
|
||||||
files:
|
files:
|
||||||
- name: BS-X.bin
|
- name: BS-X.bin
|
||||||
@@ -756,6 +780,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 96cf17bf589fcbfa6f8de2dc84f19fa2
|
md5: 96cf17bf589fcbfa6f8de2dc84f19fa2
|
||||||
native_id: satellaview
|
native_id: satellaview
|
||||||
|
name: Satellaview
|
||||||
sufami:
|
sufami:
|
||||||
files:
|
files:
|
||||||
- name: STBIOS.bin
|
- name: STBIOS.bin
|
||||||
@@ -763,6 +788,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: d3a44ba7d42a74d3ac58cb9c14c6a5ca
|
md5: d3a44ba7d42a74d3ac58cb9c14c6a5ca
|
||||||
native_id: sufami
|
native_id: sufami
|
||||||
|
name: Sufami
|
||||||
nintendo-sgb:
|
nintendo-sgb:
|
||||||
files:
|
files:
|
||||||
- name: sgb_boot.bin
|
- name: sgb_boot.bin
|
||||||
@@ -782,6 +808,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 8ecd73eb4edf7ed7e81aef1be80031d5
|
md5: 8ecd73eb4edf7ed7e81aef1be80031d5
|
||||||
native_id: sgb
|
native_id: sgb
|
||||||
|
name: Super Game Boy
|
||||||
microsoft-msx:
|
microsoft-msx:
|
||||||
files:
|
files:
|
||||||
- name: MSX.ROM
|
- name: MSX.ROM
|
||||||
@@ -861,6 +888,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 42af93619160ef2116416f74a6cb12f2
|
md5: 42af93619160ef2116416f74a6cb12f2
|
||||||
native_id: msx
|
native_id: msx
|
||||||
|
name: MSX-Turbo
|
||||||
xbox:
|
xbox:
|
||||||
files:
|
files:
|
||||||
- name: mcpx_1.0.bin
|
- name: mcpx_1.0.bin
|
||||||
@@ -872,6 +900,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 39cee882148a87f93cb440b99dde3ceb
|
md5: 39cee882148a87f93cb440b99dde3ceb
|
||||||
native_id: xbox
|
native_id: xbox
|
||||||
|
name: Xbox
|
||||||
amiga500:
|
amiga500:
|
||||||
files:
|
files:
|
||||||
- name: kick33180.A500
|
- name: kick33180.A500
|
||||||
@@ -915,6 +944,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: e40a5dfb3d017ba8779faba30cbd1c8e
|
md5: e40a5dfb3d017ba8779faba30cbd1c8e
|
||||||
native_id: amiga500
|
native_id: amiga500
|
||||||
|
name: Amiga 500
|
||||||
commodore-amiga:
|
commodore-amiga:
|
||||||
files:
|
files:
|
||||||
- name: kick34005.A500
|
- name: kick34005.A500
|
||||||
@@ -982,6 +1012,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: bb72565701b1b6faece07d68ea5da639
|
md5: bb72565701b1b6faece07d68ea5da639
|
||||||
native_id: amigacdtv
|
native_id: amigacdtv
|
||||||
|
name: Amiga CD32
|
||||||
pc60:
|
pc60:
|
||||||
files:
|
files:
|
||||||
- name: pc6001.zip
|
- name: pc6001.zip
|
||||||
@@ -1050,6 +1081,7 @@ systems:
|
|||||||
md5: 9d61f3cbd47c4a281c5241c4f1d80919
|
md5: 9d61f3cbd47c4a281c5241c4f1d80919
|
||||||
zipped_file: cgrom68.64
|
zipped_file: cgrom68.64
|
||||||
native_id: pc60
|
native_id: pc60
|
||||||
|
name: NEC PC-6000
|
||||||
nec-pc-88:
|
nec-pc-88:
|
||||||
files:
|
files:
|
||||||
- name: N88.ROM
|
- name: N88.ROM
|
||||||
@@ -1085,6 +1117,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: fc4b76a402ba501e6ba6de4b3e8b4273
|
md5: fc4b76a402ba501e6ba6de4b3e8b4273
|
||||||
native_id: pc88
|
native_id: pc88
|
||||||
|
name: NEC PC-8800
|
||||||
nec-pc-98:
|
nec-pc-98:
|
||||||
files:
|
files:
|
||||||
- name: BIOS.ROM
|
- name: BIOS.ROM
|
||||||
@@ -1108,6 +1141,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 7da1e5b7c482d4108d22a5b09631d967
|
md5: 7da1e5b7c482d4108d22a5b09631d967
|
||||||
native_id: pc98
|
native_id: pc98
|
||||||
|
name: NEC PC-9800
|
||||||
loopy:
|
loopy:
|
||||||
files:
|
files:
|
||||||
- name: casloopy.zip
|
- name: casloopy.zip
|
||||||
@@ -1125,6 +1159,7 @@ systems:
|
|||||||
md5: c0f1c899c9ca098663d046d60779711d
|
md5: c0f1c899c9ca098663d046d60779711d
|
||||||
zipped_file: hn62434fa.lsi352
|
zipped_file: hn62434fa.lsi352
|
||||||
native_id: loopy
|
native_id: loopy
|
||||||
|
name: Casio Loopy
|
||||||
fairchild-channel-f:
|
fairchild-channel-f:
|
||||||
files:
|
files:
|
||||||
- name: sl31253.bin
|
- name: sl31253.bin
|
||||||
@@ -1140,6 +1175,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 95d339631d867c8f1d15a5f2ec26069d
|
md5: 95d339631d867c8f1d15a5f2ec26069d
|
||||||
native_id: channelf
|
native_id: channelf
|
||||||
|
name: Fairchild ChannelF
|
||||||
sharp-x1:
|
sharp-x1:
|
||||||
files:
|
files:
|
||||||
- name: IPLROM.X1
|
- name: IPLROM.X1
|
||||||
@@ -1151,6 +1187,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 56c28adcf1f3a2f87cf3d57c378013f5
|
md5: 56c28adcf1f3a2f87cf3d57c378013f5
|
||||||
native_id: x1
|
native_id: x1
|
||||||
|
name: Sharp X1
|
||||||
fmtowns:
|
fmtowns:
|
||||||
files:
|
files:
|
||||||
- name: FMT_DIC.ROM
|
- name: FMT_DIC.ROM
|
||||||
@@ -1238,6 +1275,7 @@ systems:
|
|||||||
md5: 1a15f6c1b58ec7e5f850118610a787a7
|
md5: 1a15f6c1b58ec7e5f850118610a787a7
|
||||||
zipped_file: mytownsux.rom
|
zipped_file: mytownsux.rom
|
||||||
native_id: fmtowns
|
native_id: fmtowns
|
||||||
|
name: Fujistu FM-Towns
|
||||||
gp32:
|
gp32:
|
||||||
files:
|
files:
|
||||||
- name: gp32.zip
|
- name: gp32.zip
|
||||||
@@ -1274,6 +1312,7 @@ systems:
|
|||||||
md5: d4af2bc352bdaf4972ea40902feda114
|
md5: d4af2bc352bdaf4972ea40902feda114
|
||||||
zipped_file: gp32mfv2.bin
|
zipped_file: gp32mfv2.bin
|
||||||
native_id: gp32
|
native_id: gp32
|
||||||
|
name: GamePark GP32
|
||||||
laser310:
|
laser310:
|
||||||
files:
|
files:
|
||||||
- name: laser310.zip
|
- name: laser310.zip
|
||||||
@@ -1290,6 +1329,7 @@ systems:
|
|||||||
md5: f7e5d9a3eb2b57bf5f4e2a4565318a8f
|
md5: f7e5d9a3eb2b57bf5f4e2a4565318a8f
|
||||||
zipped_file: vtechv21.u12
|
zipped_file: vtechv21.u12
|
||||||
native_id: laser310
|
native_id: laser310
|
||||||
|
name: VTech Laser 310
|
||||||
scv:
|
scv:
|
||||||
files:
|
files:
|
||||||
- name: upd7801g.s01
|
- name: upd7801g.s01
|
||||||
@@ -1297,6 +1337,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 635a978fd40db9a18ee44eff449fc126
|
md5: 635a978fd40db9a18ee44eff449fc126
|
||||||
native_id: scv
|
native_id: scv
|
||||||
|
name: Super Cassette Vision
|
||||||
apple-iigs:
|
apple-iigs:
|
||||||
files:
|
files:
|
||||||
- name: ROM1
|
- name: ROM1
|
||||||
@@ -1332,6 +1373,7 @@ systems:
|
|||||||
md5: 68ff96a624237d233e8d4c701f660dd1
|
md5: 68ff96a624237d233e8d4c701f660dd1
|
||||||
zipped_file: apple2gs.chr
|
zipped_file: apple2gs.chr
|
||||||
native_id: gsplus
|
native_id: gsplus
|
||||||
|
name: Apple IIgs
|
||||||
zc210:
|
zc210:
|
||||||
files:
|
files:
|
||||||
- name: zcdata.dat
|
- name: zcdata.dat
|
||||||
@@ -1387,6 +1429,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: e0ba7a8634b12cfee4b6760a6f89051a
|
md5: e0ba7a8634b12cfee4b6760a6f89051a
|
||||||
native_id: zc210
|
native_id: zc210
|
||||||
|
name: Zelda Classic
|
||||||
apple-macintosh-ii:
|
apple-macintosh-ii:
|
||||||
files:
|
files:
|
||||||
- name: MacII.ROM
|
- name: MacII.ROM
|
||||||
@@ -1594,6 +1637,7 @@ systems:
|
|||||||
destination: mac755.chd
|
destination: mac755.chd
|
||||||
required: true
|
required: true
|
||||||
native_id: macintosh
|
native_id: macintosh
|
||||||
|
name: Apple Macintosh
|
||||||
sc3000:
|
sc3000:
|
||||||
files:
|
files:
|
||||||
- name: sc3000.zip
|
- name: sc3000.zip
|
||||||
@@ -1605,18 +1649,21 @@ systems:
|
|||||||
md5: a6a47eae38600e41cc67e887e36e70b7
|
md5: a6a47eae38600e41cc67e887e36e70b7
|
||||||
zipped_file: sc3000.rom
|
zipped_file: sc3000.rom
|
||||||
native_id: sc3000
|
native_id: sc3000
|
||||||
|
name: Sega SC-3000
|
||||||
segaai:
|
segaai:
|
||||||
files:
|
files:
|
||||||
- name: segaai.zip
|
- name: segaai.zip
|
||||||
destination: segaai.zip
|
destination: segaai.zip
|
||||||
required: true
|
required: true
|
||||||
native_id: segaai
|
native_id: segaai
|
||||||
|
name: Sega AI Computer
|
||||||
beena:
|
beena:
|
||||||
files:
|
files:
|
||||||
- name: beena.zip
|
- name: beena.zip
|
||||||
destination: beena.zip
|
destination: beena.zip
|
||||||
required: true
|
required: true
|
||||||
native_id: beena
|
native_id: beena
|
||||||
|
name: Advanced Pico Beena
|
||||||
coco:
|
coco:
|
||||||
files:
|
files:
|
||||||
- name: coco.zip
|
- name: coco.zip
|
||||||
@@ -1678,12 +1725,14 @@ systems:
|
|||||||
md5: 8cab28f4b7311b8df63c07bb3b59bfd5
|
md5: 8cab28f4b7311b8df63c07bb3b59bfd5
|
||||||
zipped_file: disk11.rom
|
zipped_file: disk11.rom
|
||||||
native_id: coco
|
native_id: coco
|
||||||
|
name: Tandy Color Computer
|
||||||
cgenie:
|
cgenie:
|
||||||
files:
|
files:
|
||||||
- name: cgenie.zip
|
- name: cgenie.zip
|
||||||
destination: cgenie.zip
|
destination: cgenie.zip
|
||||||
required: true
|
required: true
|
||||||
native_id: cgenie
|
native_id: cgenie
|
||||||
|
name: Colour Genie
|
||||||
dragon64:
|
dragon64:
|
||||||
files:
|
files:
|
||||||
- name: dragon64.zip
|
- name: dragon64.zip
|
||||||
@@ -1711,6 +1760,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
zipped_file: d32.rom
|
zipped_file: d32.rom
|
||||||
native_id: dragon64
|
native_id: dragon64
|
||||||
|
name: Dragon 64
|
||||||
mc10:
|
mc10:
|
||||||
files:
|
files:
|
||||||
- name: mc10.zip
|
- name: mc10.zip
|
||||||
@@ -1730,6 +1780,7 @@ systems:
|
|||||||
md5: 78af465c2f31cf4e05dec1efda77da01
|
md5: 78af465c2f31cf4e05dec1efda77da01
|
||||||
zipped_file: alice.rom
|
zipped_file: alice.rom
|
||||||
native_id: mc10
|
native_id: mc10
|
||||||
|
name: Tandy MC-10
|
||||||
trs80:
|
trs80:
|
||||||
files:
|
files:
|
||||||
- name: trs80.zip
|
- name: trs80.zip
|
||||||
@@ -1761,6 +1812,7 @@ systems:
|
|||||||
destination: trs80m4p.zip
|
destination: trs80m4p.zip
|
||||||
required: true
|
required: true
|
||||||
native_id: trs80
|
native_id: trs80
|
||||||
|
name: TRS-80
|
||||||
tutor:
|
tutor:
|
||||||
files:
|
files:
|
||||||
- name: tutor.zip
|
- name: tutor.zip
|
||||||
@@ -1777,6 +1829,7 @@ systems:
|
|||||||
md5: 5770834c10946ac2c3617504ba530884
|
md5: 5770834c10946ac2c3617504ba530884
|
||||||
zipped_file: tutor2.bin
|
zipped_file: tutor2.bin
|
||||||
native_id: tutor
|
native_id: tutor
|
||||||
|
name: Tomy Tutor
|
||||||
ti99:
|
ti99:
|
||||||
files:
|
files:
|
||||||
- name: ti99_4a.zip
|
- name: ti99_4a.zip
|
||||||
@@ -1821,6 +1874,7 @@ systems:
|
|||||||
md5: 206daf498ac5d0141de1d47d38afd899
|
md5: 206daf498ac5d0141de1d47d38afd899
|
||||||
zipped_file: cd2326a.u2b
|
zipped_file: cd2326a.u2b
|
||||||
native_id: ti99
|
native_id: ti99
|
||||||
|
name: Texas Instruments TI-99
|
||||||
astrocade:
|
astrocade:
|
||||||
files:
|
files:
|
||||||
- name: astrocde.zip
|
- name: astrocde.zip
|
||||||
@@ -1832,6 +1886,7 @@ systems:
|
|||||||
md5: 7d25a26e5c4841b364cfe6b1735eaf03
|
md5: 7d25a26e5c4841b364cfe6b1735eaf03
|
||||||
zipped_file: astro.bin
|
zipped_file: astro.bin
|
||||||
native_id: astrocade
|
native_id: astrocade
|
||||||
|
name: Bally Astrocade
|
||||||
gmaster:
|
gmaster:
|
||||||
files:
|
files:
|
||||||
- name: gmaster.zip
|
- name: gmaster.zip
|
||||||
@@ -1843,6 +1898,7 @@ systems:
|
|||||||
md5: 6bff08b5e5f96de405cd56d5f04a08f8
|
md5: 6bff08b5e5f96de405cd56d5f04a08f8
|
||||||
zipped_file: d78c11agf_e19.u1
|
zipped_file: d78c11agf_e19.u1
|
||||||
native_id: gmaster
|
native_id: gmaster
|
||||||
|
name: Hartung Game Master
|
||||||
adam:
|
adam:
|
||||||
files:
|
files:
|
||||||
- name: adam.zip
|
- name: adam.zip
|
||||||
@@ -1951,6 +2007,7 @@ systems:
|
|||||||
md5: 3cdf2fe48ac4224b56f26c03f6c68982
|
md5: 3cdf2fe48ac4224b56f26c03f6c68982
|
||||||
zipped_file: printer.u2
|
zipped_file: printer.u2
|
||||||
native_id: adam
|
native_id: adam
|
||||||
|
name: Coleco Adam
|
||||||
coleco-colecovision:
|
coleco-colecovision:
|
||||||
files:
|
files:
|
||||||
- name: colecovision.rom
|
- name: colecovision.rom
|
||||||
@@ -1958,6 +2015,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 2c66f5911e5b42b8ebe113403548eee7
|
md5: 2c66f5911e5b42b8ebe113403548eee7
|
||||||
native_id: colecovision
|
native_id: colecovision
|
||||||
|
name: ColecoVision
|
||||||
bbc:
|
bbc:
|
||||||
files:
|
files:
|
||||||
- name: bbcb.zip
|
- name: bbcb.zip
|
||||||
@@ -2150,6 +2208,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: f083f49d6fe66344c650d7e74249cb96
|
md5: f083f49d6fe66344c650d7e74249cb96
|
||||||
native_id: bbc
|
native_id: bbc
|
||||||
|
name: BBC Micro
|
||||||
pcw:
|
pcw:
|
||||||
files:
|
files:
|
||||||
- name: pcw8256.zip
|
- name: pcw8256.zip
|
||||||
@@ -2174,6 +2233,7 @@ systems:
|
|||||||
md5: b664af93987d575b0248832832c61505
|
md5: b664af93987d575b0248832832c61505
|
||||||
zipped_file: 40103.ic109
|
zipped_file: 40103.ic109
|
||||||
native_id: pcw
|
native_id: pcw
|
||||||
|
name: Amstrad PCW
|
||||||
apfm1000:
|
apfm1000:
|
||||||
files:
|
files:
|
||||||
- name: apfm1000.zip
|
- name: apfm1000.zip
|
||||||
@@ -2195,6 +2255,7 @@ systems:
|
|||||||
md5: 89a7cfa5469ce24773721d65b28f8544
|
md5: 89a7cfa5469ce24773721d65b28f8544
|
||||||
zipped_file: trash-ii.bin
|
zipped_file: trash-ii.bin
|
||||||
native_id: apfm1000
|
native_id: apfm1000
|
||||||
|
name: APF M-1000
|
||||||
fm7:
|
fm7:
|
||||||
files:
|
files:
|
||||||
- name: fm7.zip
|
- name: fm7.zip
|
||||||
@@ -2254,6 +2315,7 @@ systems:
|
|||||||
md5: 7db27dede3e358017d518101850bccfa
|
md5: 7db27dede3e358017d518101850bccfa
|
||||||
zipped_file: subsyscg.rom
|
zipped_file: subsyscg.rom
|
||||||
native_id: fm7
|
native_id: fm7
|
||||||
|
name: Fujitsu FM-7
|
||||||
archimedes:
|
archimedes:
|
||||||
files:
|
files:
|
||||||
- name: aa310.zip
|
- name: aa310.zip
|
||||||
@@ -2463,6 +2525,7 @@ systems:
|
|||||||
md5: 1a8617c1abe3e0729d20ce844e1e12a8
|
md5: 1a8617c1abe3e0729d20ce844e1e12a8
|
||||||
zipped_file: acorn_0280,022-01_philips_8051ah-2.bin
|
zipped_file: acorn_0280,022-01_philips_8051ah-2.bin
|
||||||
native_id: archimedes
|
native_id: archimedes
|
||||||
|
name: Acorn Archimedes
|
||||||
atom:
|
atom:
|
||||||
files:
|
files:
|
||||||
- name: atom.zip
|
- name: atom.zip
|
||||||
@@ -2484,6 +2547,7 @@ systems:
|
|||||||
md5: 9627dfb5f8302db8dd5702dbf7c09f72
|
md5: 9627dfb5f8302db8dd5702dbf7c09f72
|
||||||
zipped_file: dosrom.u15
|
zipped_file: dosrom.u15
|
||||||
native_id: atom
|
native_id: atom
|
||||||
|
name: Acorn Atom
|
||||||
electron:
|
electron:
|
||||||
files:
|
files:
|
||||||
- name: electron.zip
|
- name: electron.zip
|
||||||
@@ -2544,6 +2608,7 @@ systems:
|
|||||||
md5: 5c39baa89fe8a40a5167a53cc5ae7791
|
md5: 5c39baa89fe8a40a5167a53cc5ae7791
|
||||||
zipped_file: pres_adfs_115.rom
|
zipped_file: pres_adfs_115.rom
|
||||||
native_id: electron
|
native_id: electron
|
||||||
|
name: Acorn Electron
|
||||||
apple-ii:
|
apple-ii:
|
||||||
files:
|
files:
|
||||||
- name: apple2e.zip
|
- name: apple2e.zip
|
||||||
@@ -2671,6 +2736,7 @@ systems:
|
|||||||
md5: 5f1be0c1cdff26f5956eef9643911886
|
md5: 5f1be0c1cdff26f5956eef9643911886
|
||||||
zipped_file: 341-0028-a.rom
|
zipped_file: 341-0028-a.rom
|
||||||
native_id: apple2
|
native_id: apple2
|
||||||
|
name: Apple II
|
||||||
camplynx:
|
camplynx:
|
||||||
files:
|
files:
|
||||||
- name: lynx48k.zip
|
- name: lynx48k.zip
|
||||||
@@ -2753,6 +2819,7 @@ systems:
|
|||||||
md5: f9f54913cdedb22bb8f0c549ad121379
|
md5: f9f54913cdedb22bb8f0c549ad121379
|
||||||
zipped_file: lynx128-3.ic3
|
zipped_file: lynx128-3.ic3
|
||||||
native_id: camplynx
|
native_id: camplynx
|
||||||
|
name: Camputers Lynx
|
||||||
mz80k:
|
mz80k:
|
||||||
files:
|
files:
|
||||||
- name: mz80k.zip
|
- name: mz80k.zip
|
||||||
@@ -2782,6 +2849,7 @@ systems:
|
|||||||
md5: 4138784bdd2e2cbacd6c55eff195b2ac
|
md5: 4138784bdd2e2cbacd6c55eff195b2ac
|
||||||
zipped_file: mz80kfdif.rom
|
zipped_file: mz80kfdif.rom
|
||||||
native_id: mz80k
|
native_id: mz80k
|
||||||
|
name: Sharp MZ-80K
|
||||||
mz700:
|
mz700:
|
||||||
files:
|
files:
|
||||||
- name: mz700.zip
|
- name: mz700.zip
|
||||||
@@ -2798,6 +2866,7 @@ systems:
|
|||||||
md5: e9045d57e8574f3eb3f775c02369fbfe
|
md5: e9045d57e8574f3eb3f775c02369fbfe
|
||||||
zipped_file: mz700fon.int
|
zipped_file: mz700fon.int
|
||||||
native_id: mz700
|
native_id: mz700
|
||||||
|
name: Sharp MZ-700
|
||||||
mz800:
|
mz800:
|
||||||
files:
|
files:
|
||||||
- name: mz800.zip
|
- name: mz800.zip
|
||||||
@@ -2809,6 +2878,7 @@ systems:
|
|||||||
md5: 7d3909267b3f3e6ce7aa999de0ded226
|
md5: 7d3909267b3f3e6ce7aa999de0ded226
|
||||||
zipped_file: mz800.rom
|
zipped_file: mz800.rom
|
||||||
native_id: mz800
|
native_id: mz800
|
||||||
|
name: Sharp MZ-800
|
||||||
mz2000:
|
mz2000:
|
||||||
files:
|
files:
|
||||||
- name: mz2000.zip
|
- name: mz2000.zip
|
||||||
@@ -2825,6 +2895,7 @@ systems:
|
|||||||
md5: dea49b39998885631db16de1176e71b9
|
md5: dea49b39998885631db16de1176e71b9
|
||||||
zipped_file: font.bin
|
zipped_file: font.bin
|
||||||
native_id: mz2000
|
native_id: mz2000
|
||||||
|
name: Sharp MZ-2000
|
||||||
mz2500:
|
mz2500:
|
||||||
files:
|
files:
|
||||||
- name: mz2500.zip
|
- name: mz2500.zip
|
||||||
@@ -2861,6 +2932,7 @@ systems:
|
|||||||
md5: 04843d14a8e2f69a7fcaff394a8cc012
|
md5: 04843d14a8e2f69a7fcaff394a8cc012
|
||||||
zipped_file: phone.rom
|
zipped_file: phone.rom
|
||||||
native_id: mz2500
|
native_id: mz2500
|
||||||
|
name: Sharp MZ-2500
|
||||||
vgmplay:
|
vgmplay:
|
||||||
files:
|
files:
|
||||||
- name: qsound.zip
|
- name: qsound.zip
|
||||||
@@ -2888,6 +2960,7 @@ systems:
|
|||||||
md5: 8740932cda05e518a9955f1d08d6786f
|
md5: 8740932cda05e518a9955f1d08d6786f
|
||||||
zipped_file: ym2608_adpcm_rom.bin
|
zipped_file: ym2608_adpcm_rom.bin
|
||||||
native_id: vgmplay
|
native_id: vgmplay
|
||||||
|
name: Video Game Music Player
|
||||||
gamepock:
|
gamepock:
|
||||||
files:
|
files:
|
||||||
- name: gamepock.zip
|
- name: gamepock.zip
|
||||||
@@ -2899,6 +2972,7 @@ systems:
|
|||||||
md5: a0dd595eafb407a6a4b4ed800005a394
|
md5: a0dd595eafb407a6a4b4ed800005a394
|
||||||
zipped_file: egpcboot.bin
|
zipped_file: egpcboot.bin
|
||||||
native_id: gamepock
|
native_id: gamepock
|
||||||
|
name: Epoch Game Pocket Computer
|
||||||
gamecom:
|
gamecom:
|
||||||
files:
|
files:
|
||||||
- name: gamecom.zip
|
- name: gamecom.zip
|
||||||
@@ -2915,6 +2989,7 @@ systems:
|
|||||||
md5: f7bcefb6daf923c8e5ea2eb69f619efe
|
md5: f7bcefb6daf923c8e5ea2eb69f619efe
|
||||||
zipped_file: internal.bin
|
zipped_file: internal.bin
|
||||||
native_id: gamecom
|
native_id: gamecom
|
||||||
|
name: Tiger Game.com
|
||||||
xegs:
|
xegs:
|
||||||
files:
|
files:
|
||||||
- name: xegs.zip
|
- name: xegs.zip
|
||||||
@@ -2926,6 +3001,7 @@ systems:
|
|||||||
md5: 42cbd989802c17d0ac3731d33270d835
|
md5: 42cbd989802c17d0ac3731d33270d835
|
||||||
zipped_file: c101687.rom
|
zipped_file: c101687.rom
|
||||||
native_id: xegs
|
native_id: xegs
|
||||||
|
name: Atari XE Game System
|
||||||
crvision:
|
crvision:
|
||||||
files:
|
files:
|
||||||
- name: crvision.zip
|
- name: crvision.zip
|
||||||
@@ -2937,6 +3013,7 @@ systems:
|
|||||||
md5: 3b1ef759d8e3fb4071582efd33dd05f9
|
md5: 3b1ef759d8e3fb4071582efd33dd05f9
|
||||||
zipped_file: crvision.u20
|
zipped_file: crvision.u20
|
||||||
native_id: crvision
|
native_id: crvision
|
||||||
|
name: VTech CreatiVision
|
||||||
vsmile:
|
vsmile:
|
||||||
files:
|
files:
|
||||||
- name: vsmile.zip
|
- name: vsmile.zip
|
||||||
@@ -2958,6 +3035,7 @@ systems:
|
|||||||
md5: 11e59253c578c8f16ea2375ec398e4e9
|
md5: 11e59253c578c8f16ea2375ec398e4e9
|
||||||
zipped_file: vsmile_v103.bin
|
zipped_file: vsmile_v103.bin
|
||||||
native_id: vsmile
|
native_id: vsmile
|
||||||
|
name: VTech V.Smile
|
||||||
socrates:
|
socrates:
|
||||||
files:
|
files:
|
||||||
- name: socrates.zip
|
- name: socrates.zip
|
||||||
@@ -2989,6 +3067,7 @@ systems:
|
|||||||
md5: 31c29c57e3d3e6788ba5817eaaa8b17a
|
md5: 31c29c57e3d3e6788ba5817eaaa8b17a
|
||||||
zipped_file: speech_eng_vsm3.bin
|
zipped_file: speech_eng_vsm3.bin
|
||||||
native_id: socrates
|
native_id: socrates
|
||||||
|
name: VTech Socrates
|
||||||
rx78:
|
rx78:
|
||||||
files:
|
files:
|
||||||
- name: rx78.zip
|
- name: rx78.zip
|
||||||
@@ -3000,6 +3079,7 @@ systems:
|
|||||||
md5: f613b15c4b965013e4827d2ad79c7080
|
md5: f613b15c4b965013e4827d2ad79c7080
|
||||||
zipped_file: ipl.rom
|
zipped_file: ipl.rom
|
||||||
native_id: rx78
|
native_id: rx78
|
||||||
|
name: Bandai RX-78
|
||||||
advision:
|
advision:
|
||||||
files:
|
files:
|
||||||
- name: advision.zip
|
- name: advision.zip
|
||||||
@@ -3016,6 +3096,7 @@ systems:
|
|||||||
md5: fc5e71445e4947a9d00eedbc66b13a8f
|
md5: fc5e71445e4947a9d00eedbc66b13a8f
|
||||||
zipped_file: b8223__cop411l-kcn_n.u8
|
zipped_file: b8223__cop411l-kcn_n.u8
|
||||||
native_id: advision
|
native_id: advision
|
||||||
|
name: Entex Adventure Vision
|
||||||
gamate:
|
gamate:
|
||||||
files:
|
files:
|
||||||
- name: gamate.zip
|
- name: gamate.zip
|
||||||
@@ -3032,12 +3113,14 @@ systems:
|
|||||||
md5: ef67993a94503c4b7798b5901c7dda52
|
md5: ef67993a94503c4b7798b5901c7dda52
|
||||||
zipped_file: gamate_bios_umc.bin
|
zipped_file: gamate_bios_umc.bin
|
||||||
native_id: gamate
|
native_id: gamate
|
||||||
|
name: Bitcorp Gamate
|
||||||
pv2000:
|
pv2000:
|
||||||
files:
|
files:
|
||||||
- name: pv2000.zip
|
- name: pv2000.zip
|
||||||
destination: pv2000.zip
|
destination: pv2000.zip
|
||||||
required: true
|
required: true
|
||||||
native_id: pv2000
|
native_id: pv2000
|
||||||
|
name: Casio PV-2000
|
||||||
pc80:
|
pc80:
|
||||||
files:
|
files:
|
||||||
- name: pc8001.zip
|
- name: pc8001.zip
|
||||||
@@ -3092,6 +3175,7 @@ systems:
|
|||||||
md5: d81c6d5d7ad1a4bbbd6ae22a01257603
|
md5: d81c6d5d7ad1a4bbbd6ae22a01257603
|
||||||
zipped_file: kanji1.rom
|
zipped_file: kanji1.rom
|
||||||
native_id: pc80
|
native_id: pc80
|
||||||
|
name: NEC PC-8001
|
||||||
cdi:
|
cdi:
|
||||||
files:
|
files:
|
||||||
- name: cdimono1.zip
|
- name: cdimono1.zip
|
||||||
@@ -3123,6 +3207,7 @@ systems:
|
|||||||
md5: 3d20cf7550f1b723158b42a1fd5bac62
|
md5: 3d20cf7550f1b723158b42a1fd5bac62
|
||||||
zipped_file: zx405042p__cdi_slave_2.0__b43t__zzmk9213.mc68hc705c8a_withtestrom.7206
|
zipped_file: zx405042p__cdi_slave_2.0__b43t__zzmk9213.mc68hc705c8a_withtestrom.7206
|
||||||
native_id: cdi
|
native_id: cdi
|
||||||
|
name: Phillips CD-i
|
||||||
hikaru:
|
hikaru:
|
||||||
files:
|
files:
|
||||||
- name: hikaru.zip
|
- name: hikaru.zip
|
||||||
@@ -3138,6 +3223,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: ee643e8c7369fe7feca610d4daa4a57c
|
md5: ee643e8c7369fe7feca610d4daa4a57c
|
||||||
native_id: hikaru
|
native_id: hikaru
|
||||||
|
name: Hikaru
|
||||||
sony-playstation-vita:
|
sony-playstation-vita:
|
||||||
files:
|
files:
|
||||||
- name: PSP2UPDAT.PUP
|
- name: PSP2UPDAT.PUP
|
||||||
@@ -3149,6 +3235,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: f2c7b12fe85496ec88a0391b514d6e3b
|
md5: f2c7b12fe85496ec88a0391b514d6e3b
|
||||||
native_id: psvita
|
native_id: psvita
|
||||||
|
name: PS Vita
|
||||||
vectrex:
|
vectrex:
|
||||||
files:
|
files:
|
||||||
- name: vectrex.zip
|
- name: vectrex.zip
|
||||||
@@ -3165,6 +3252,7 @@ systems:
|
|||||||
md5: a9c238473229912eb757ff3dfe6f4631
|
md5: a9c238473229912eb757ff3dfe6f4631
|
||||||
zipped_file: exec_rom_intl_284001-1.bin
|
zipped_file: exec_rom_intl_284001-1.bin
|
||||||
native_id: vectrex
|
native_id: vectrex
|
||||||
|
name: GCE Vectrex
|
||||||
scummvm:
|
scummvm:
|
||||||
files:
|
files:
|
||||||
- name: MT32_PCM.ROM
|
- name: MT32_PCM.ROM
|
||||||
@@ -3176,6 +3264,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 5626206284b22c2734f3e9efefcd2675
|
md5: 5626206284b22c2734f3e9efefcd2675
|
||||||
native_id: scummvm
|
native_id: scummvm
|
||||||
|
name: ScummVM
|
||||||
supracan:
|
supracan:
|
||||||
files:
|
files:
|
||||||
- name: supracan.zip
|
- name: supracan.zip
|
||||||
@@ -3187,6 +3276,7 @@ systems:
|
|||||||
md5: 53c4343e062bb3b337370bbb58e64d16
|
md5: 53c4343e062bb3b337370bbb58e64d16
|
||||||
zipped_file: internal_68k.bin
|
zipped_file: internal_68k.bin
|
||||||
native_id: supracan
|
native_id: supracan
|
||||||
|
name: Supr'A'can
|
||||||
tandy-vis:
|
tandy-vis:
|
||||||
files:
|
files:
|
||||||
- name: vis.zip
|
- name: vis.zip
|
||||||
@@ -3203,6 +3293,7 @@ systems:
|
|||||||
md5: 758f8fec271fbf526bb22b36e88f154b
|
md5: 758f8fec271fbf526bb22b36e88f154b
|
||||||
zipped_file: p513bk1b.bin
|
zipped_file: p513bk1b.bin
|
||||||
native_id: vis
|
native_id: vis
|
||||||
|
name: Tandy Video Information System
|
||||||
nintendo-64dd:
|
nintendo-64dd:
|
||||||
files:
|
files:
|
||||||
- name: 64DD_IPL.bin
|
- name: 64DD_IPL.bin
|
||||||
@@ -3210,6 +3301,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 8d3d9f294b6e174bc7b1d2fd1c727530
|
md5: 8d3d9f294b6e174bc7b1d2fd1c727530
|
||||||
native_id: n64dd
|
native_id: n64dd
|
||||||
|
name: Nintendo 64DD
|
||||||
nintendo-gamecube:
|
nintendo-gamecube:
|
||||||
files:
|
files:
|
||||||
- name: IPL.bin
|
- name: IPL.bin
|
||||||
@@ -3225,6 +3317,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: b17148254a5799684c7d783206504926
|
md5: b17148254a5799684c7d783206504926
|
||||||
native_id: gamecube
|
native_id: gamecube
|
||||||
|
name: Nintendo GameCube
|
||||||
chihiro:
|
chihiro:
|
||||||
files:
|
files:
|
||||||
- name: mcpx_1.0.bin
|
- name: mcpx_1.0.bin
|
||||||
@@ -3236,6 +3329,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: f23d7e00ae8fbf88908ed1f9165f35eb
|
md5: f23d7e00ae8fbf88908ed1f9165f35eb
|
||||||
native_id: chihiro
|
native_id: chihiro
|
||||||
|
name: Sega Chihiro
|
||||||
oricatmos:
|
oricatmos:
|
||||||
files:
|
files:
|
||||||
- name: basic11.rom
|
- name: basic11.rom
|
||||||
@@ -3247,6 +3341,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: c888b36bf0fc222c3585c3fabe556d21
|
md5: c888b36bf0fc222c3585c3fabe556d21
|
||||||
native_id: oricatmos
|
native_id: oricatmos
|
||||||
|
name: Oric Atmos
|
||||||
enterprise-64-128:
|
enterprise-64-128:
|
||||||
files:
|
files:
|
||||||
- name: basic21.bin
|
- name: basic21.bin
|
||||||
@@ -3361,6 +3456,7 @@ systems:
|
|||||||
md5: 47258d03aec37bc24df5dbc5d50fc9f8
|
md5: 47258d03aec37bc24df5dbc5d50fc9f8
|
||||||
zipped_file: exdos13.rom
|
zipped_file: exdos13.rom
|
||||||
native_id: enterprise
|
native_id: enterprise
|
||||||
|
name: Enterprise
|
||||||
videoton-tvc:
|
videoton-tvc:
|
||||||
files:
|
files:
|
||||||
- name: tvc22_sys.rom
|
- name: tvc22_sys.rom
|
||||||
@@ -3413,6 +3509,7 @@ systems:
|
|||||||
md5: 5ce95a26ceed5bec73995d83568da9cf
|
md5: 5ce95a26ceed5bec73995d83568da9cf
|
||||||
zipped_file: tvc22_d7.64k
|
zipped_file: tvc22_d7.64k
|
||||||
native_id: tvc
|
native_id: tvc
|
||||||
|
name: Videoton TVC
|
||||||
triforce:
|
triforce:
|
||||||
files:
|
files:
|
||||||
- name: segaboot.gcm
|
- name: segaboot.gcm
|
||||||
@@ -3420,6 +3517,7 @@ systems:
|
|||||||
required: true
|
required: true
|
||||||
md5: 2ef01c0e93f7ee3a0a4b139aa14728b9
|
md5: 2ef01c0e93f7ee3a0a4b139aa14728b9
|
||||||
native_id: triforce
|
native_id: triforce
|
||||||
|
name: Triforce
|
||||||
bk:
|
bk:
|
||||||
files:
|
files:
|
||||||
- name: B11M_BOS.ROM
|
- name: B11M_BOS.ROM
|
||||||
@@ -3513,6 +3611,7 @@ systems:
|
|||||||
md5: fe4627d1e3a1535874085050733263e7
|
md5: fe4627d1e3a1535874085050733263e7
|
||||||
zipped_file: bk11m_324_bos.rom
|
zipped_file: bk11m_324_bos.rom
|
||||||
native_id: bk
|
native_id: bk
|
||||||
|
name: Elektronika BK
|
||||||
standalone_cores:
|
standalone_cores:
|
||||||
- abuse
|
- abuse
|
||||||
- azahar
|
- azahar
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ dat_version: v1.19.0
|
|||||||
homepage: https://www.retroarch.com
|
homepage: https://www.retroarch.com
|
||||||
source: https://github.com/libretro/libretro-database/blob/master/dat/System.dat
|
source: https://github.com/libretro/libretro-database/blob/master/dat/System.dat
|
||||||
base_destination: system
|
base_destination: system
|
||||||
cores: all_libretro
|
|
||||||
hash_type: sha1
|
hash_type: sha1
|
||||||
verification_mode: existence
|
verification_mode: existence
|
||||||
case_insensitive_fs: true
|
|
||||||
systems:
|
systems:
|
||||||
3do:
|
3do:
|
||||||
files:
|
files:
|
||||||
@@ -102,6 +100,7 @@ systems:
|
|||||||
md5: 35fa1a1ebaaeea286dc5cd15487c13ea
|
md5: 35fa1a1ebaaeea286dc5cd15487c13ea
|
||||||
crc32: d5cbc509
|
crc32: d5cbc509
|
||||||
size: 1048576
|
size: 1048576
|
||||||
|
native_id: 3DO Company, The - 3DO
|
||||||
core: opera
|
core: opera
|
||||||
manufacturer: Panasonic|GoldStar|Sanyo
|
manufacturer: Panasonic|GoldStar|Sanyo
|
||||||
docs: https://docs.libretro.com/library/opera/
|
docs: https://docs.libretro.com/library/opera/
|
||||||
@@ -135,6 +134,7 @@ systems:
|
|||||||
md5: 25629dfe870d097469c217b95fdc1c95
|
md5: 25629dfe870d097469c217b95fdc1c95
|
||||||
crc32: 1fe22ecd
|
crc32: 1fe22ecd
|
||||||
size: 16384
|
size: 16384
|
||||||
|
native_id: Amstrad - CPC
|
||||||
arcade:
|
arcade:
|
||||||
files:
|
files:
|
||||||
- name: bubsys.zip
|
- name: bubsys.zip
|
||||||
@@ -249,6 +249,10 @@ systems:
|
|||||||
- name: aes.zip
|
- name: aes.zip
|
||||||
destination: aes.zip
|
destination: aes.zip
|
||||||
required: true
|
required: true
|
||||||
|
native_id: Arcade
|
||||||
|
core: fbneo
|
||||||
|
manufacturer: Various
|
||||||
|
docs: https://docs.libretro.com/library/fbneo/
|
||||||
data_directories:
|
data_directories:
|
||||||
- ref: fbneo-hiscore
|
- ref: fbneo-hiscore
|
||||||
destination: ''
|
destination: ''
|
||||||
@@ -256,9 +260,6 @@ systems:
|
|||||||
destination: fbneo
|
destination: fbneo
|
||||||
- ref: fbneo-samples
|
- ref: fbneo-samples
|
||||||
destination: fbneo
|
destination: fbneo
|
||||||
core: fbneo
|
|
||||||
manufacturer: Various
|
|
||||||
docs: https://docs.libretro.com/library/fbneo/
|
|
||||||
atari-400-800:
|
atari-400-800:
|
||||||
files:
|
files:
|
||||||
- name: ATARIBAS.ROM
|
- name: ATARIBAS.ROM
|
||||||
@@ -303,6 +304,7 @@ systems:
|
|||||||
md5: d7eb37aec6960cba36bc500e0e5d00bc
|
md5: d7eb37aec6960cba36bc500e0e5d00bc
|
||||||
crc32: bdca01fb
|
crc32: bdca01fb
|
||||||
size: 8192
|
size: 8192
|
||||||
|
native_id: Atari - 400-800
|
||||||
atari-5200:
|
atari-5200:
|
||||||
files:
|
files:
|
||||||
- name: 5200.rom
|
- name: 5200.rom
|
||||||
@@ -312,6 +314,7 @@ systems:
|
|||||||
md5: 281f20ea4320404ec820fb7ec0693b38
|
md5: 281f20ea4320404ec820fb7ec0693b38
|
||||||
crc32: 4248d3e3
|
crc32: 4248d3e3
|
||||||
size: 2048
|
size: 2048
|
||||||
|
native_id: Atari - 5200
|
||||||
core: a5200
|
core: a5200
|
||||||
manufacturer: Atari
|
manufacturer: Atari
|
||||||
docs: https://docs.libretro.com/library/a5200/
|
docs: https://docs.libretro.com/library/a5200/
|
||||||
@@ -331,6 +334,7 @@ systems:
|
|||||||
md5: 0763f1ffb006ddbe32e52d497ee848ae
|
md5: 0763f1ffb006ddbe32e52d497ee848ae
|
||||||
crc32: 5d13730c
|
crc32: 5d13730c
|
||||||
size: 4096
|
size: 4096
|
||||||
|
native_id: Atari - 7800
|
||||||
core: prosystem
|
core: prosystem
|
||||||
manufacturer: Atari
|
manufacturer: Atari
|
||||||
docs: https://docs.libretro.com/library/prosystem/
|
docs: https://docs.libretro.com/library/prosystem/
|
||||||
@@ -343,6 +347,7 @@ systems:
|
|||||||
md5: fcd403db69f54290b51035d82f835e7b
|
md5: fcd403db69f54290b51035d82f835e7b
|
||||||
crc32: 0d973c9d
|
crc32: 0d973c9d
|
||||||
size: 512
|
size: 512
|
||||||
|
native_id: Atari - Lynx
|
||||||
core: handy
|
core: handy
|
||||||
manufacturer: Atari
|
manufacturer: Atari
|
||||||
docs: https://docs.libretro.com/library/handy/
|
docs: https://docs.libretro.com/library/handy/
|
||||||
@@ -355,6 +360,7 @@ systems:
|
|||||||
md5: c1c57ce48e8ee4135885cee9e63a68a2
|
md5: c1c57ce48e8ee4135885cee9e63a68a2
|
||||||
crc32: d3c32283
|
crc32: d3c32283
|
||||||
size: 196608
|
size: 196608
|
||||||
|
native_id: Atari - ST
|
||||||
core: hatari
|
core: hatari
|
||||||
manufacturer: Atari
|
manufacturer: Atari
|
||||||
docs: https://docs.libretro.com/library/hatari/
|
docs: https://docs.libretro.com/library/hatari/
|
||||||
@@ -376,6 +382,7 @@ systems:
|
|||||||
- name: bioscv.rom
|
- name: bioscv.rom
|
||||||
destination: bioscv.rom
|
destination: bioscv.rom
|
||||||
required: true
|
required: true
|
||||||
|
native_id: Coleco - ColecoVision
|
||||||
commodore-amiga:
|
commodore-amiga:
|
||||||
files:
|
files:
|
||||||
- name: kick33180.A500
|
- name: kick33180.A500
|
||||||
@@ -462,6 +469,7 @@ systems:
|
|||||||
md5: bb72565701b1b6faece07d68ea5da639
|
md5: bb72565701b1b6faece07d68ea5da639
|
||||||
crc32: 87746be2
|
crc32: 87746be2
|
||||||
size: 524288
|
size: 524288
|
||||||
|
native_id: Commodore - Amiga
|
||||||
core: puae
|
core: puae
|
||||||
manufacturer: Commodore
|
manufacturer: Commodore
|
||||||
docs: https://docs.libretro.com/library/puae/
|
docs: https://docs.libretro.com/library/puae/
|
||||||
@@ -510,6 +518,7 @@ systems:
|
|||||||
destination: scpu-dos-2.04.bin
|
destination: scpu-dos-2.04.bin
|
||||||
required: true
|
required: true
|
||||||
md5: b2869f8678b8b274227f35aad26ba509
|
md5: b2869f8678b8b274227f35aad26ba509
|
||||||
|
native_id: Commodore - C128
|
||||||
core: vice_x128
|
core: vice_x128
|
||||||
manufacturer: Commodore
|
manufacturer: Commodore
|
||||||
docs: https://docs.libretro.com/library/vice_x128/
|
docs: https://docs.libretro.com/library/vice_x128/
|
||||||
@@ -522,6 +531,7 @@ systems:
|
|||||||
md5: a2e891e330d146c4046c2b622fc31462
|
md5: a2e891e330d146c4046c2b622fc31462
|
||||||
crc32: 683ed4ad
|
crc32: 683ed4ad
|
||||||
size: 5763199
|
size: 5763199
|
||||||
|
native_id: Dinothawr
|
||||||
dos:
|
dos:
|
||||||
files:
|
files:
|
||||||
- name: MT32_CONTROL.ROM
|
- name: MT32_CONTROL.ROM
|
||||||
@@ -552,6 +562,7 @@ systems:
|
|||||||
md5: 08cdcfa0ed93e9cb16afa76e6ac5f0a4
|
md5: 08cdcfa0ed93e9cb16afa76e6ac5f0a4
|
||||||
crc32: 4b961eba
|
crc32: 4b961eba
|
||||||
size: 1048576
|
size: 1048576
|
||||||
|
native_id: DOS
|
||||||
elektronika-bk:
|
elektronika-bk:
|
||||||
files:
|
files:
|
||||||
- name: B11M_BOS.ROM
|
- name: B11M_BOS.ROM
|
||||||
@@ -610,6 +621,7 @@ systems:
|
|||||||
md5: 95f8c41c6abf7640e35a6a03cecebd01
|
md5: 95f8c41c6abf7640e35a6a03cecebd01
|
||||||
crc32: 26c6e8a0
|
crc32: 26c6e8a0
|
||||||
size: 8192
|
size: 8192
|
||||||
|
native_id: Elektronika - BK-0010/BK-0011(M)
|
||||||
enterprise-64-128:
|
enterprise-64-128:
|
||||||
files:
|
files:
|
||||||
- name: hun.rom
|
- name: hun.rom
|
||||||
@@ -696,6 +708,7 @@ systems:
|
|||||||
md5: 55af78f877a21ca45eb2df68a74fcc60
|
md5: 55af78f877a21ca45eb2df68a74fcc60
|
||||||
crc32: c099a5e3
|
crc32: c099a5e3
|
||||||
size: 65536
|
size: 65536
|
||||||
|
native_id: Enterprise - 64/128
|
||||||
includes:
|
includes:
|
||||||
- ep128emu
|
- ep128emu
|
||||||
epoch-scv:
|
epoch-scv:
|
||||||
@@ -707,6 +720,7 @@ systems:
|
|||||||
md5: 635a978fd40db9a18ee44eff449fc126
|
md5: 635a978fd40db9a18ee44eff449fc126
|
||||||
crc32: 7ac06182
|
crc32: 7ac06182
|
||||||
size: 4096
|
size: 4096
|
||||||
|
native_id: EPOCH/YENO Super Cassette Vision
|
||||||
fairchild-channel-f:
|
fairchild-channel-f:
|
||||||
files:
|
files:
|
||||||
- name: sl31253.bin
|
- name: sl31253.bin
|
||||||
@@ -730,6 +744,7 @@ systems:
|
|||||||
md5: 95d339631d867c8f1d15a5f2ec26069d
|
md5: 95d339631d867c8f1d15a5f2ec26069d
|
||||||
crc32: 015c1e38
|
crc32: 015c1e38
|
||||||
size: 1024
|
size: 1024
|
||||||
|
native_id: Fairchild Channel F
|
||||||
doom:
|
doom:
|
||||||
files:
|
files:
|
||||||
- name: prboom.wad
|
- name: prboom.wad
|
||||||
@@ -739,6 +754,7 @@ systems:
|
|||||||
md5: 72ae1b47820fcc93cc0df9c428d0face
|
md5: 72ae1b47820fcc93cc0df9c428d0face
|
||||||
crc32: a5751b99
|
crc32: a5751b99
|
||||||
size: 143312
|
size: 143312
|
||||||
|
native_id: Id Software - Doom
|
||||||
j2me:
|
j2me:
|
||||||
files:
|
files:
|
||||||
- name: freej2me-lr.jar
|
- name: freej2me-lr.jar
|
||||||
@@ -762,6 +778,7 @@ systems:
|
|||||||
md5: 29a92d0867da2917275b7c6c805d256f
|
md5: 29a92d0867da2917275b7c6c805d256f
|
||||||
crc32: ffb98ffa
|
crc32: ffb98ffa
|
||||||
size: 552039
|
size: 552039
|
||||||
|
native_id: J2ME
|
||||||
core: freej2me
|
core: freej2me
|
||||||
manufacturer: Java
|
manufacturer: Java
|
||||||
docs: https://docs.libretro.com/library/freej2me/
|
docs: https://docs.libretro.com/library/freej2me/
|
||||||
@@ -774,6 +791,7 @@ systems:
|
|||||||
md5: 66223be1497460f1e60885eeb35e03cc
|
md5: 66223be1497460f1e60885eeb35e03cc
|
||||||
crc32: 4df6d054
|
crc32: 4df6d054
|
||||||
size: 262144
|
size: 262144
|
||||||
|
native_id: MacII
|
||||||
magnavox-odyssey2:
|
magnavox-odyssey2:
|
||||||
files:
|
files:
|
||||||
- name: o2rom.bin
|
- name: o2rom.bin
|
||||||
@@ -804,6 +822,7 @@ systems:
|
|||||||
md5: 279008e4a0db2dc5f1c048853b033828
|
md5: 279008e4a0db2dc5f1c048853b033828
|
||||||
crc32: 11647ca5
|
crc32: 11647ca5
|
||||||
size: 1024
|
size: 1024
|
||||||
|
native_id: Magnavox - Odyssey2
|
||||||
core: o2em
|
core: o2em
|
||||||
manufacturer: Magnavox|Philips
|
manufacturer: Magnavox|Philips
|
||||||
docs: https://docs.libretro.com/library/o2em/
|
docs: https://docs.libretro.com/library/o2em/
|
||||||
@@ -823,6 +842,7 @@ systems:
|
|||||||
md5: 0cd5946c6473e42e8e4c2137785e427f
|
md5: 0cd5946c6473e42e8e4c2137785e427f
|
||||||
crc32: 683a4158
|
crc32: 683a4158
|
||||||
size: 2048
|
size: 2048
|
||||||
|
native_id: Mattel - Intellivision
|
||||||
data_directories:
|
data_directories:
|
||||||
- ref: freeintv-overlays
|
- ref: freeintv-overlays
|
||||||
destination: freeintv_overlays
|
destination: freeintv_overlays
|
||||||
@@ -933,6 +953,7 @@ systems:
|
|||||||
md5: 279efd1eae0d358eecd4edc7d9adedf3
|
md5: 279efd1eae0d358eecd4edc7d9adedf3
|
||||||
crc32: ab6874f8
|
crc32: ab6874f8
|
||||||
size: 16640
|
size: 16640
|
||||||
|
native_id: Microsoft - MSX
|
||||||
core: bluemsx
|
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
|
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
|
Labs
|
||||||
@@ -991,6 +1012,7 @@ systems:
|
|||||||
md5: 0754f903b52e3b3342202bdafb13efa5
|
md5: 0754f903b52e3b3342202bdafb13efa5
|
||||||
crc32: 2b5b75fe
|
crc32: 2b5b75fe
|
||||||
size: 262144
|
size: 262144
|
||||||
|
native_id: NEC - PC Engine - TurboGrafx 16 - SuperGrafx
|
||||||
core: mednafen_pce_fast
|
core: mednafen_pce_fast
|
||||||
manufacturer: NEC
|
manufacturer: NEC
|
||||||
docs: https://docs.libretro.com/library/mednafen_pce_fast/
|
docs: https://docs.libretro.com/library/mednafen_pce_fast/
|
||||||
@@ -1073,6 +1095,7 @@ systems:
|
|||||||
md5: 524473c1a5a03b17e21d86a0408ff827
|
md5: 524473c1a5a03b17e21d86a0408ff827
|
||||||
crc32: fe9f57f2
|
crc32: fe9f57f2
|
||||||
size: 16384
|
size: 16384
|
||||||
|
native_id: NEC - PC-98
|
||||||
core: np2kai
|
core: np2kai
|
||||||
manufacturer: NEC
|
manufacturer: NEC
|
||||||
docs: https://docs.libretro.com/library/np2kai/
|
docs: https://docs.libretro.com/library/np2kai/
|
||||||
@@ -1115,6 +1138,7 @@ systems:
|
|||||||
md5: e2fb7c7220e3a7838c2dd7e401a7f3d8
|
md5: e2fb7c7220e3a7838c2dd7e401a7f3d8
|
||||||
crc32: 236102c9
|
crc32: 236102c9
|
||||||
size: 1048576
|
size: 1048576
|
||||||
|
native_id: NEC - PC-FX
|
||||||
core: mednafen_pcfx
|
core: mednafen_pcfx
|
||||||
manufacturer: NEC
|
manufacturer: NEC
|
||||||
docs: https://docs.libretro.com/library/mednafen_pcfx/
|
docs: https://docs.libretro.com/library/mednafen_pcfx/
|
||||||
@@ -1134,6 +1158,7 @@ systems:
|
|||||||
md5: 7f98d77d7a094ad7d069b74bd553ec98
|
md5: 7f98d77d7a094ad7d069b74bd553ec98
|
||||||
crc32: 4c514089
|
crc32: 4c514089
|
||||||
size: 24592
|
size: 24592
|
||||||
|
native_id: Nintendo - Famicom Disk System
|
||||||
nintendo-gb:
|
nintendo-gb:
|
||||||
files:
|
files:
|
||||||
- name: dmg_boot.bin
|
- name: dmg_boot.bin
|
||||||
@@ -1150,6 +1175,7 @@ systems:
|
|||||||
md5: 32fbbd84168d3482956eb3c5051637f5
|
md5: 32fbbd84168d3482956eb3c5051637f5
|
||||||
crc32: 59c8598e
|
crc32: 59c8598e
|
||||||
size: 256
|
size: 256
|
||||||
|
native_id: Nintendo - Gameboy
|
||||||
core: gambatte
|
core: gambatte
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/gambatte/
|
docs: https://docs.libretro.com/library/gambatte/
|
||||||
@@ -1162,6 +1188,7 @@ systems:
|
|||||||
md5: a860e8c0b6d573d191e4ec7db1b1e4f6
|
md5: a860e8c0b6d573d191e4ec7db1b1e4f6
|
||||||
crc32: '81977335'
|
crc32: '81977335'
|
||||||
size: 16384
|
size: 16384
|
||||||
|
native_id: Nintendo - Game Boy Advance
|
||||||
core: gpsp
|
core: gpsp
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/gpsp/
|
docs: https://docs.libretro.com/library/gpsp/
|
||||||
@@ -1181,6 +1208,7 @@ systems:
|
|||||||
md5: dbfce9db9deaa2567f6a84fde55f9680
|
md5: dbfce9db9deaa2567f6a84fde55f9680
|
||||||
crc32: 41884e46
|
crc32: 41884e46
|
||||||
size: 2304
|
size: 2304
|
||||||
|
native_id: Nintendo - Gameboy Color
|
||||||
nintendo-gamecube:
|
nintendo-gamecube:
|
||||||
files:
|
files:
|
||||||
- name: gc-dvd-20010608.bin
|
- name: gc-dvd-20010608.bin
|
||||||
@@ -1274,6 +1302,7 @@ systems:
|
|||||||
- name: font_japanese.bin
|
- name: font_japanese.bin
|
||||||
destination: dolphin-emu/Sys/GC/font_japanese.bin
|
destination: dolphin-emu/Sys/GC/font_japanese.bin
|
||||||
required: false
|
required: false
|
||||||
|
native_id: Nintendo - GameCube
|
||||||
core: dolphin
|
core: dolphin
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/dolphin/
|
docs: https://docs.libretro.com/library/dolphin/
|
||||||
@@ -1289,6 +1318,7 @@ systems:
|
|||||||
md5: 8d3d9f294b6e174bc7b1d2fd1c727530
|
md5: 8d3d9f294b6e174bc7b1d2fd1c727530
|
||||||
crc32: 7f933ce2
|
crc32: 7f933ce2
|
||||||
size: 4194304
|
size: 4194304
|
||||||
|
native_id: Nintendo - Nintendo 64DD
|
||||||
nintendo-ds:
|
nintendo-ds:
|
||||||
files:
|
files:
|
||||||
- name: bios7.bin
|
- name: bios7.bin
|
||||||
@@ -1324,6 +1354,7 @@ systems:
|
|||||||
- name: dsi_nand.bin
|
- name: dsi_nand.bin
|
||||||
destination: dsi_nand.bin
|
destination: dsi_nand.bin
|
||||||
required: true
|
required: true
|
||||||
|
native_id: Nintendo - Nintendo DS
|
||||||
core: desmume
|
core: desmume
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/desmume/
|
docs: https://docs.libretro.com/library/desmume/
|
||||||
@@ -1332,10 +1363,11 @@ systems:
|
|||||||
- name: NstDatabase.xml
|
- name: NstDatabase.xml
|
||||||
destination: NstDatabase.xml
|
destination: NstDatabase.xml
|
||||||
required: true
|
required: true
|
||||||
sha1: f92312bae56e29c5bf00a5103105fce78472bf5c
|
sha1: 26322f182540211e9b5e3647675b7c593706ae2b
|
||||||
md5: 0ee6cbdc6f5c96ce9c8aa5edb59066f4
|
md5: 7bfe8c0540ed4bd6a0f1e2a0f0118ced
|
||||||
crc32: 0e4d552b
|
crc32: ebb2196c
|
||||||
size: 1009534
|
size: 1009534
|
||||||
|
native_id: Nintendo - Nintendo Entertainment System
|
||||||
core: fceumm
|
core: fceumm
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/fceumm/
|
docs: https://docs.libretro.com/library/fceumm/
|
||||||
@@ -1348,6 +1380,7 @@ systems:
|
|||||||
md5: 1e4fb124a3a886865acb574f388c803d
|
md5: 1e4fb124a3a886865acb574f388c803d
|
||||||
crc32: aed3c14d
|
crc32: aed3c14d
|
||||||
size: 4096
|
size: 4096
|
||||||
|
native_id: Nintendo - Pokemon Mini
|
||||||
nintendo-satellaview:
|
nintendo-satellaview:
|
||||||
files:
|
files:
|
||||||
- name: BS-X.bin
|
- name: BS-X.bin
|
||||||
@@ -1371,6 +1404,7 @@ systems:
|
|||||||
md5: 4ed9648505ab33a4daec93707b16caba
|
md5: 4ed9648505ab33a4daec93707b16caba
|
||||||
crc32: 8c573c7e
|
crc32: 8c573c7e
|
||||||
size: 1048576
|
size: 1048576
|
||||||
|
native_id: Nintendo - Satellaview
|
||||||
nintendo-sufami-turbo:
|
nintendo-sufami-turbo:
|
||||||
files:
|
files:
|
||||||
- name: STBIOS.bin
|
- name: STBIOS.bin
|
||||||
@@ -1380,6 +1414,7 @@ systems:
|
|||||||
md5: d3a44ba7d42a74d3ac58cb9c14c6a5ca
|
md5: d3a44ba7d42a74d3ac58cb9c14c6a5ca
|
||||||
crc32: 9b4ca911
|
crc32: 9b4ca911
|
||||||
size: 262144
|
size: 262144
|
||||||
|
native_id: Nintendo - SuFami Turbo
|
||||||
nintendo-sgb:
|
nintendo-sgb:
|
||||||
files:
|
files:
|
||||||
- name: SGB1.sfc
|
- name: SGB1.sfc
|
||||||
@@ -1441,6 +1476,7 @@ systems:
|
|||||||
- name: sgb.boot.rom
|
- name: sgb.boot.rom
|
||||||
destination: sgb.boot.rom
|
destination: sgb.boot.rom
|
||||||
required: false
|
required: false
|
||||||
|
native_id: Nintendo - Super Game Boy
|
||||||
nintendo-snes:
|
nintendo-snes:
|
||||||
files:
|
files:
|
||||||
- name: cx4.data.rom
|
- name: cx4.data.rom
|
||||||
@@ -1562,6 +1598,7 @@ systems:
|
|||||||
md5: dda40ccd57390c96e49d30a041f9a9e7
|
md5: dda40ccd57390c96e49d30a041f9a9e7
|
||||||
crc32: f73d5e10
|
crc32: f73d5e10
|
||||||
size: 131072
|
size: 131072
|
||||||
|
native_id: Nintendo - Super Nintendo Entertainment System
|
||||||
core: bsnes
|
core: bsnes
|
||||||
manufacturer: Nintendo
|
manufacturer: Nintendo
|
||||||
docs: https://docs.libretro.com/library/bsnes/
|
docs: https://docs.libretro.com/library/bsnes/
|
||||||
@@ -1588,6 +1625,7 @@ systems:
|
|||||||
md5: 279008e4a0db2dc5f1c048853b033828
|
md5: 279008e4a0db2dc5f1c048853b033828
|
||||||
crc32: 11647ca5
|
crc32: 11647ca5
|
||||||
size: 1024
|
size: 1024
|
||||||
|
native_id: Phillips - Videopac+
|
||||||
sega-dreamcast:
|
sega-dreamcast:
|
||||||
files:
|
files:
|
||||||
- name: dc_boot.bin
|
- name: dc_boot.bin
|
||||||
@@ -1611,6 +1649,7 @@ systems:
|
|||||||
md5: 0a93f7940c455905bea6e392dfde92a4
|
md5: 0a93f7940c455905bea6e392dfde92a4
|
||||||
crc32: c611b498
|
crc32: c611b498
|
||||||
size: 131072
|
size: 131072
|
||||||
|
native_id: Sega - Dreamcast
|
||||||
core: flycast
|
core: flycast
|
||||||
manufacturer: Sega
|
manufacturer: Sega
|
||||||
docs: https://docs.libretro.com/library/flycast/
|
docs: https://docs.libretro.com/library/flycast/
|
||||||
@@ -1668,6 +1707,7 @@ systems:
|
|||||||
- name: segasp.zip
|
- name: segasp.zip
|
||||||
destination: dc/segasp.zip
|
destination: dc/segasp.zip
|
||||||
required: true
|
required: true
|
||||||
|
native_id: Sega - Dreamcast-based Arcade
|
||||||
sega-game-gear:
|
sega-game-gear:
|
||||||
files:
|
files:
|
||||||
- name: bios.gg
|
- name: bios.gg
|
||||||
@@ -1677,6 +1717,7 @@ systems:
|
|||||||
md5: 672e104c3be3a238301aceffc3b23fd6
|
md5: 672e104c3be3a238301aceffc3b23fd6
|
||||||
crc32: 0ebea9d4
|
crc32: 0ebea9d4
|
||||||
size: 1024
|
size: 1024
|
||||||
|
native_id: Sega - Game Gear
|
||||||
sega-master-system:
|
sega-master-system:
|
||||||
files:
|
files:
|
||||||
- name: bios.sms
|
- name: bios.sms
|
||||||
@@ -1707,6 +1748,7 @@ systems:
|
|||||||
md5: 840481177270d5642a14ca71ee72844c
|
md5: 840481177270d5642a14ca71ee72844c
|
||||||
crc32: 0072ed54
|
crc32: 0072ed54
|
||||||
size: 8192
|
size: 8192
|
||||||
|
native_id: Sega - Master System - Mark III
|
||||||
sega-mega-cd:
|
sega-mega-cd:
|
||||||
files:
|
files:
|
||||||
- name: bios_CD_E.bin
|
- name: bios_CD_E.bin
|
||||||
@@ -1730,6 +1772,7 @@ systems:
|
|||||||
md5: 2efd74e3232ff260e371b99f84024f7f
|
md5: 2efd74e3232ff260e371b99f84024f7f
|
||||||
crc32: c6d10268
|
crc32: c6d10268
|
||||||
size: 131072
|
size: 131072
|
||||||
|
native_id: Sega - Mega CD - Sega CD
|
||||||
sega-mega-drive:
|
sega-mega-drive:
|
||||||
files:
|
files:
|
||||||
- name: areplay.bin
|
- name: areplay.bin
|
||||||
@@ -1774,6 +1817,7 @@ systems:
|
|||||||
md5: b4e76e416b887f4e7413ba76fa735f16
|
md5: b4e76e416b887f4e7413ba76fa735f16
|
||||||
crc32: 4dcfd55c
|
crc32: 4dcfd55c
|
||||||
size: 262144
|
size: 262144
|
||||||
|
native_id: Sega - Mega Drive - Genesis
|
||||||
core: genesis_plus_gx
|
core: genesis_plus_gx
|
||||||
manufacturer: Sega
|
manufacturer: Sega
|
||||||
docs: https://docs.libretro.com/library/genesis_plus_gx/
|
docs: https://docs.libretro.com/library/genesis_plus_gx/
|
||||||
@@ -1859,6 +1903,7 @@ systems:
|
|||||||
- name: stvbios.zip
|
- name: stvbios.zip
|
||||||
destination: kronos/stvbios.zip
|
destination: kronos/stvbios.zip
|
||||||
required: true
|
required: true
|
||||||
|
native_id: Sega - Saturn
|
||||||
core: kronos
|
core: kronos
|
||||||
manufacturer: Sega
|
manufacturer: Sega
|
||||||
docs: https://docs.libretro.com/library/kronos/
|
docs: https://docs.libretro.com/library/kronos/
|
||||||
@@ -1880,6 +1925,7 @@ systems:
|
|||||||
md5: 851e4a5936f17d13f8c39a980cf00d77
|
md5: 851e4a5936f17d13f8c39a980cf00d77
|
||||||
crc32: e3995a57
|
crc32: e3995a57
|
||||||
size: 2048
|
size: 2048
|
||||||
|
native_id: Sharp - X1
|
||||||
core: x1
|
core: x1
|
||||||
manufacturer: Sharp
|
manufacturer: Sharp
|
||||||
docs: https://docs.libretro.com/library/x1/
|
docs: https://docs.libretro.com/library/x1/
|
||||||
@@ -1920,6 +1966,7 @@ systems:
|
|||||||
md5: 0617321daa182c3f3d6f41fd02fb3275
|
md5: 0617321daa182c3f3d6f41fd02fb3275
|
||||||
crc32: 00eeb408
|
crc32: 00eeb408
|
||||||
size: 131072
|
size: 131072
|
||||||
|
native_id: Sharp - X68000
|
||||||
core: px68k
|
core: px68k
|
||||||
manufacturer: Sharp
|
manufacturer: Sharp
|
||||||
docs: https://docs.libretro.com/library/px68k/
|
docs: https://docs.libretro.com/library/px68k/
|
||||||
@@ -2270,6 +2317,7 @@ systems:
|
|||||||
md5: 85fede415f4294cc777517d7eada482e
|
md5: 85fede415f4294cc777517d7eada482e
|
||||||
crc32: 2cbe8995
|
crc32: 2cbe8995
|
||||||
size: 32768
|
size: 32768
|
||||||
|
native_id: Sinclair - ZX Spectrum
|
||||||
core: fuse
|
core: fuse
|
||||||
manufacturer: Sinclair|Amstrad
|
manufacturer: Sinclair|Amstrad
|
||||||
docs: https://docs.libretro.com/library/fuse/
|
docs: https://docs.libretro.com/library/fuse/
|
||||||
@@ -2352,6 +2400,7 @@ systems:
|
|||||||
md5: 08ca8b2dba6662e8024f9e789711c6fc
|
md5: 08ca8b2dba6662e8024f9e789711c6fc
|
||||||
crc32: ff3abc59
|
crc32: ff3abc59
|
||||||
size: 524288
|
size: 524288
|
||||||
|
native_id: SNK - NeoGeo CD
|
||||||
core: neocd
|
core: neocd
|
||||||
manufacturer: SNK
|
manufacturer: SNK
|
||||||
docs: https://docs.libretro.com/library/neocd/
|
docs: https://docs.libretro.com/library/neocd/
|
||||||
@@ -2511,6 +2560,7 @@ systems:
|
|||||||
md5: 81bbe60ba7a3d1cea1d48c14cbcc647b
|
md5: 81bbe60ba7a3d1cea1d48c14cbcc647b
|
||||||
crc32: 2f53b852
|
crc32: 2f53b852
|
||||||
size: 524288
|
size: 524288
|
||||||
|
native_id: Sony - PlayStation
|
||||||
core: duckstation
|
core: duckstation
|
||||||
manufacturer: Sony
|
manufacturer: Sony
|
||||||
docs: https://docs.libretro.com/library/duckstation/
|
docs: https://docs.libretro.com/library/duckstation/
|
||||||
@@ -3027,6 +3077,7 @@ systems:
|
|||||||
md5: d3e81e95db25f5a86a7b7474550a2155
|
md5: d3e81e95db25f5a86a7b7474550a2155
|
||||||
crc32: 4e8c160c
|
crc32: 4e8c160c
|
||||||
size: 4194304
|
size: 4194304
|
||||||
|
native_id: Sony - PlayStation 2
|
||||||
sony-psp:
|
sony-psp:
|
||||||
files:
|
files:
|
||||||
- name: ppge_atlas.zim
|
- name: ppge_atlas.zim
|
||||||
@@ -3036,6 +3087,7 @@ systems:
|
|||||||
md5: 866855cc330b9b95cc69135fb7b41d38
|
md5: 866855cc330b9b95cc69135fb7b41d38
|
||||||
crc32: 7b57fa78
|
crc32: 7b57fa78
|
||||||
size: 666530
|
size: 666530
|
||||||
|
native_id: Sony - PlayStation Portable
|
||||||
core: ppsspp
|
core: ppsspp
|
||||||
manufacturer: Sony
|
manufacturer: Sony
|
||||||
docs: https://docs.libretro.com/library/ppsspp/
|
docs: https://docs.libretro.com/library/ppsspp/
|
||||||
@@ -3065,6 +3117,7 @@ systems:
|
|||||||
md5: d4448d09bbfde687c04f9e3310e023ab
|
md5: d4448d09bbfde687c04f9e3310e023ab
|
||||||
crc32: 4bf05697
|
crc32: 4bf05697
|
||||||
size: 262144
|
size: 262144
|
||||||
|
native_id: Texas Instruments TI-83
|
||||||
core: numero
|
core: numero
|
||||||
manufacturer: Texas Instruments
|
manufacturer: Texas Instruments
|
||||||
docs: https://docs.libretro.com/library/numero/
|
docs: https://docs.libretro.com/library/numero/
|
||||||
@@ -3098,6 +3151,7 @@ systems:
|
|||||||
md5: 88dc7876d584f90e4106f91444ab23b7
|
md5: 88dc7876d584f90e4106f91444ab23b7
|
||||||
crc32: 1466aed4
|
crc32: 1466aed4
|
||||||
size: 16384
|
size: 16384
|
||||||
|
native_id: Videoton - TV Computer
|
||||||
wolfenstein-3d:
|
wolfenstein-3d:
|
||||||
files:
|
files:
|
||||||
- name: ecwolf.pk3
|
- name: ecwolf.pk3
|
||||||
@@ -3107,6 +3161,7 @@ systems:
|
|||||||
md5: c011b428819eea4a80b455c245a5a04d
|
md5: c011b428819eea4a80b455c245a5a04d
|
||||||
crc32: 26dc3fba
|
crc32: 26dc3fba
|
||||||
size: 178755
|
size: 178755
|
||||||
|
native_id: Wolfenstein 3D
|
||||||
scummvm:
|
scummvm:
|
||||||
files:
|
files:
|
||||||
- name: scummvm.zip
|
- name: scummvm.zip
|
||||||
@@ -3116,6 +3171,7 @@ systems:
|
|||||||
md5: a17e0e0150155400d8cced329563d9c8
|
md5: a17e0e0150155400d8cced329563d9c8
|
||||||
crc32: a93f1c4b
|
crc32: a93f1c4b
|
||||||
size: 9523360
|
size: 9523360
|
||||||
|
native_id: ScummVM
|
||||||
core: scummvm
|
core: scummvm
|
||||||
manufacturer: Various
|
manufacturer: Various
|
||||||
docs: https://docs.libretro.com/library/scummvm/
|
docs: https://docs.libretro.com/library/scummvm/
|
||||||
@@ -3141,3 +3197,5 @@ systems:
|
|||||||
core: xrick
|
core: xrick
|
||||||
manufacturer: Other
|
manufacturer: Other
|
||||||
docs: https://docs.libretro.com/library/xrick/
|
docs: https://docs.libretro.com/library/xrick/
|
||||||
|
case_insensitive_fs: true
|
||||||
|
cores: all_libretro
|
||||||
|
|||||||
@@ -191,10 +191,9 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
|
|||||||
system.setdefault("files", []).append(gf)
|
system.setdefault("files", []).append(gf)
|
||||||
existing.add(key)
|
existing.add(key)
|
||||||
|
|
||||||
# Merge cores from _registry.yml if the registry has a broader list.
|
# Merge metadata from _registry.yml. The registry is our curated source;
|
||||||
# The scraped YAML may have an incomplete cores list; the registry is
|
# the scraped YAML may be incomplete (missing cores, metadata fields).
|
||||||
# our curated source and supplements it. This affects all consumers:
|
# Registry fields supplement (not replace) the scraped config.
|
||||||
# generate_pack, verify, generate_truth, diff_truth.
|
|
||||||
registry_path = os.path.join(platforms_dir, "_registry.yml")
|
registry_path = os.path.join(platforms_dir, "_registry.yml")
|
||||||
if os.path.exists(registry_path):
|
if os.path.exists(registry_path):
|
||||||
reg_real = os.path.realpath(registry_path)
|
reg_real = os.path.realpath(registry_path)
|
||||||
@@ -203,18 +202,26 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
|
|||||||
_shared_yml_cache[reg_real] = yaml.safe_load(f) or {}
|
_shared_yml_cache[reg_real] = yaml.safe_load(f) or {}
|
||||||
reg = _shared_yml_cache[reg_real]
|
reg = _shared_yml_cache[reg_real]
|
||||||
reg_entry = reg.get("platforms", {}).get(platform_name, {})
|
reg_entry = reg.get("platforms", {}).get(platform_name, {})
|
||||||
|
|
||||||
|
# Merge cores (union for lists, override for all_libretro)
|
||||||
reg_cores = reg_entry.get("cores")
|
reg_cores = reg_entry.get("cores")
|
||||||
if reg_cores is not None:
|
if reg_cores is not None:
|
||||||
cfg_cores = config.get("cores")
|
cfg_cores = config.get("cores")
|
||||||
if reg_cores == "all_libretro":
|
if reg_cores == "all_libretro":
|
||||||
config["cores"] = "all_libretro"
|
config["cores"] = "all_libretro"
|
||||||
elif isinstance(reg_cores, list) and isinstance(cfg_cores, list):
|
elif isinstance(reg_cores, list) and isinstance(cfg_cores, list):
|
||||||
# Union: registry supplements scraped cores
|
|
||||||
merged_set = {str(c) for c in cfg_cores} | {str(c) for c in reg_cores}
|
merged_set = {str(c) for c in cfg_cores} | {str(c) for c in reg_cores}
|
||||||
config["cores"] = sorted(merged_set)
|
config["cores"] = sorted(merged_set)
|
||||||
elif isinstance(reg_cores, list) and cfg_cores is None:
|
elif isinstance(reg_cores, list) and cfg_cores is None:
|
||||||
config["cores"] = reg_cores
|
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
|
_platform_config_cache[cache_key] = config
|
||||||
return config
|
return config
|
||||||
|
|
||||||
@@ -546,6 +553,25 @@ def resolve_local_file(
|
|||||||
if fn.casefold() in basename_targets:
|
if fn.casefold() in basename_targets:
|
||||||
return os.path.join(root, fn), "data_dir"
|
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"
|
return None, "not_found"
|
||||||
|
|
||||||
|
|
||||||
@@ -949,6 +975,39 @@ def expand_platform_declared_names(config: dict, db: dict) -> set[str]:
|
|||||||
return declared
|
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.
|
# Validation and mode filtering -extracted to validation.py for SoC.
|
||||||
# Re-exported below for backward compatibility.
|
# Re-exported below for backward compatibility.
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,27 @@ from exporter import discover_exporters
|
|||||||
|
|
||||||
OUTPUT_FILENAMES: dict[str, str] = {
|
OUTPUT_FILENAMES: dict[str, str] = {
|
||||||
"retroarch": "System.dat",
|
"retroarch": "System.dat",
|
||||||
|
"lakka": "System.dat",
|
||||||
|
"retropie": "System.dat",
|
||||||
"batocera": "batocera-systems",
|
"batocera": "batocera-systems",
|
||||||
"recalbox": "es_bios.xml",
|
"recalbox": "es_bios.xml",
|
||||||
"retrobat": "batocera-systems.json",
|
"retrobat": "batocera-systems.json",
|
||||||
|
"emudeck": "checkBIOS.sh",
|
||||||
|
"retrodeck": "component_manifest.json",
|
||||||
|
"romm": "known_bios_files.json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def output_filename(platform: str) -> str:
|
def output_path(platform: str, output_dir: str) -> str:
|
||||||
"""Return the native output filename for a platform."""
|
"""Return the full output path for a platform's native export.
|
||||||
return OUTPUT_FILENAMES.get(platform, f"{platform}_bios.dat")
|
|
||||||
|
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(
|
def run(
|
||||||
@@ -35,8 +47,6 @@ def run(
|
|||||||
) -> int:
|
) -> int:
|
||||||
"""Export truth to native formats, return exit code."""
|
"""Export truth to native formats, return exit code."""
|
||||||
exporters = discover_exporters()
|
exporters = discover_exporters()
|
||||||
output_path = Path(output_dir)
|
|
||||||
output_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
errors = 0
|
errors = 0
|
||||||
|
|
||||||
@@ -60,7 +70,7 @@ def run(
|
|||||||
except (FileNotFoundError, OSError):
|
except (FileNotFoundError, OSError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
dest = str(output_path / output_filename(platform))
|
dest = output_path(platform, output_dir)
|
||||||
exporter = exporter_cls()
|
exporter = exporter_cls()
|
||||||
exporter.export(truth_data, dest, scraped_data=scraped)
|
exporter.export(truth_data, dest, scraped_data=scraped)
|
||||||
|
|
||||||
|
|||||||
@@ -25,3 +25,37 @@ class BaseExporter(ABC):
|
|||||||
@abstractmethod
|
@abstractmethod
|
||||||
def validate(self, truth_data: dict, output_path: str) -> list[str]:
|
def validate(self, truth_data: dict, output_path: str) -> list[str]:
|
||||||
"""Validate exported file against truth data, return list of issues."""
|
"""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)
|
||||||
|
|||||||
111
scripts/exporter/batocera_exporter.py
Normal file
111
scripts/exporter/batocera_exporter.py
Normal 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
|
||||||
207
scripts/exporter/emudeck_exporter.py
Normal file
207
scripts/exporter/emudeck_exporter.py
Normal 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
|
||||||
17
scripts/exporter/lakka_exporter.py
Normal file
17
scripts/exporter/lakka_exporter.py
Normal 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"
|
||||||
130
scripts/exporter/recalbox_exporter.py
Normal file
130
scripts/exporter/recalbox_exporter.py
Normal 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
|
||||||
114
scripts/exporter/retrobat_exporter.py
Normal file
114
scripts/exporter/retrobat_exporter.py
Normal 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
|
||||||
208
scripts/exporter/retrodeck_exporter.py
Normal file
208
scripts/exporter/retrodeck_exporter.py
Normal 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
|
||||||
17
scripts/exporter/retropie_exporter.py
Normal file
17
scripts/exporter/retropie_exporter.py
Normal 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"
|
||||||
160
scripts/exporter/romm_exporter.py
Normal file
160
scripts/exporter/romm_exporter.py
Normal 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
|
||||||
@@ -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
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -13,7 +17,7 @@ from .base_exporter import BaseExporter
|
|||||||
|
|
||||||
|
|
||||||
def _slug_to_native(slug: str) -> str:
|
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)
|
parts = slug.split("-", 1)
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
return parts[0].title()
|
return parts[0].title()
|
||||||
@@ -42,45 +46,69 @@ class Exporter(BaseExporter):
|
|||||||
if nid:
|
if nid:
|
||||||
native_map[sys_id] = nid
|
native_map[sys_id] = nid
|
||||||
|
|
||||||
lines: list[str] = []
|
# Match exact header format of libretro-database/dat/System.dat
|
||||||
lines.append('clrmamepro (')
|
version = ""
|
||||||
lines.append('\tname "System.dat"')
|
if scraped_data:
|
||||||
lines.append(')')
|
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", {})
|
systems = truth_data.get("systems", {})
|
||||||
for sys_id in sorted(systems):
|
for sys_id in sorted(systems):
|
||||||
sys_data = systems[sys_id]
|
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:
|
||||||
for fe in sys_data.get("files", []):
|
|
||||||
name = fe.get("name", "")
|
|
||||||
if name.startswith("_"):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
dest = fe.get("path", name)
|
native_name = native_map.get(sys_id, _slug_to_native(sys_id))
|
||||||
size = fe.get("size", 0)
|
lines.append("")
|
||||||
crc = fe.get("crc32", "")
|
lines.append(f'\tcomment "{native_name}"')
|
||||||
md5 = fe.get("md5", "")
|
|
||||||
sha1 = fe.get("sha1", "")
|
|
||||||
|
|
||||||
rom_parts = [f'name "{name}"']
|
for fe in files:
|
||||||
|
name = fe.get("name", "")
|
||||||
|
if name.startswith("_") or self._is_pattern(name):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 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}")
|
rom_parts.append(f"size {size}")
|
||||||
|
crc = fe.get("crc32", "")
|
||||||
if crc:
|
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:
|
if md5:
|
||||||
rom_parts.append(f"md5 {md5}")
|
rom_parts.append(f"md5 {md5}")
|
||||||
|
sha1 = fe.get("sha1", "")
|
||||||
|
if isinstance(sha1, list):
|
||||||
|
sha1 = sha1[0] if sha1 else ""
|
||||||
if sha1:
|
if sha1:
|
||||||
rom_parts.append(f"sha1 {sha1}")
|
rom_parts.append(f"sha1 {sha1}")
|
||||||
rom_str = " ".join(rom_parts)
|
|
||||||
|
|
||||||
game_name = f"{native_name}/{dest}"
|
lines.append(f"\trom ( {' '.join(rom_parts)} )")
|
||||||
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(")")
|
||||||
|
|
||||||
lines.append("")
|
lines.append("")
|
||||||
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
|
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
|
||||||
|
|
||||||
@@ -93,12 +121,11 @@ class Exporter(BaseExporter):
|
|||||||
exported_names.add(rom.name)
|
exported_names.add(rom.name)
|
||||||
|
|
||||||
issues: list[str] = []
|
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", []):
|
for fe in sys_data.get("files", []):
|
||||||
name = fe.get("name", "")
|
name = fe.get("name", "")
|
||||||
if name.startswith("_"):
|
if name.startswith("_") or self._is_pattern(name):
|
||||||
continue
|
continue
|
||||||
if name not in exported_names:
|
if name not in exported_names:
|
||||||
issues.append(f"missing: {name} (system {sys_id})")
|
issues.append(f"missing: {name}")
|
||||||
|
|
||||||
return issues
|
return issues
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from datetime import datetime, timezone
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(__file__))
|
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_DIR = ".cache"
|
||||||
CACHE_FILE = os.path.join(CACHE_DIR, "db_cache.json")
|
CACHE_FILE = os.path.join(CACHE_DIR, "db_cache.json")
|
||||||
@@ -315,14 +315,15 @@ def main():
|
|||||||
"indexes": indexes,
|
"indexes": indexes,
|
||||||
}
|
}
|
||||||
|
|
||||||
with open(args.output, "w") as f:
|
new_content = json.dumps(database, indent=2)
|
||||||
json.dump(database, f, indent=2)
|
written = write_if_changed(args.output, new_content)
|
||||||
|
|
||||||
save_cache(CACHE_FILE, new_cache)
|
save_cache(CACHE_FILE, new_cache)
|
||||||
|
|
||||||
alias_count = sum(len(v) for v in aliases.values())
|
alias_count = sum(len(v) for v in aliases.values())
|
||||||
name_count = len(indexes["by_name"])
|
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)")
|
print(f" Name index: {name_count} names ({alias_count} aliases)")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -422,6 +422,91 @@ def _collect_emulator_extras(
|
|||||||
"source_emulator": profile.get("emulator", emu_name),
|
"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
|
return extras
|
||||||
|
|
||||||
|
|
||||||
@@ -621,6 +706,24 @@ def _build_readme(platform_name: str, platform_display: str,
|
|||||||
return header + guide + footer
|
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(
|
def generate_pack(
|
||||||
platform_name: str,
|
platform_name: str,
|
||||||
platforms_dir: str,
|
platforms_dir: str,
|
||||||
@@ -788,6 +891,67 @@ def generate_pack(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if status == "not_found":
|
if status == "not_found":
|
||||||
|
# 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:
|
if not already_packed:
|
||||||
missing_files.append(file_entry["name"])
|
missing_files.append(file_entry["name"])
|
||||||
file_status[dedup_key] = "missing"
|
file_status[dedup_key] = "missing"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from datetime import datetime, timezone
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(__file__))
|
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
|
from verify import verify_platform
|
||||||
|
|
||||||
def compute_coverage(platform_name: str, platforms_dir: str, db: dict) -> dict:
|
def compute_coverage(platform_name: str, platforms_dir: str, db: dict) -> dict:
|
||||||
@@ -316,14 +316,12 @@ def main():
|
|||||||
db = load_database(args.db)
|
db = load_database(args.db)
|
||||||
|
|
||||||
readme = generate_readme(db, args.platforms_dir)
|
readme = generate_readme(db, args.platforms_dir)
|
||||||
with open("README.md", "w") as f:
|
status = "Generated" if write_if_changed("README.md", readme) else "Unchanged"
|
||||||
f.write(readme)
|
print(f"{status} ./README.md")
|
||||||
print(f"Generated ./README.md")
|
|
||||||
|
|
||||||
contributing = generate_contributing()
|
contributing = generate_contributing()
|
||||||
with open("CONTRIBUTING.md", "w") as f:
|
status = "Generated" if write_if_changed("CONTRIBUTING.md", contributing) else "Unchanged"
|
||||||
f.write(contributing)
|
print(f"{status} ./CONTRIBUTING.md")
|
||||||
print(f"Generated ./CONTRIBUTING.md")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from datetime import datetime, timezone
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(__file__))
|
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()
|
yaml = require_yaml()
|
||||||
from generate_readme import compute_coverage
|
from generate_readme import compute_coverage
|
||||||
@@ -2064,7 +2064,7 @@ def main():
|
|||||||
|
|
||||||
# Generate home
|
# Generate home
|
||||||
print("Generating home page...")
|
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)
|
# Build system_id -> manufacturer page map (needed by all generators)
|
||||||
print("Building system cross-reference map...")
|
print("Building system cross-reference map...")
|
||||||
@@ -2074,37 +2074,35 @@ def main():
|
|||||||
|
|
||||||
# Generate platform pages
|
# Generate platform pages
|
||||||
print("Generating 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():
|
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
|
# Generate system pages
|
||||||
print("Generating 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():
|
for mfr, consoles in manufacturers.items():
|
||||||
slug = mfr.lower().replace(" ", "-")
|
slug = mfr.lower().replace(" ", "-")
|
||||||
page = generate_system_page(mfr, consoles, platform_files, emulator_files)
|
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
|
# Generate emulator pages
|
||||||
print("Generating 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():
|
for name, profile in profiles.items():
|
||||||
page = generate_emulator_page(name, profile, db, platform_files)
|
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
|
# Generate cross-reference page
|
||||||
print("Generating cross-reference page...")
|
print("Generating cross-reference page...")
|
||||||
(docs / "cross-reference.md").write_text(
|
write_if_changed(str(docs / "cross-reference.md"),
|
||||||
generate_cross_reference(coverages, profiles)
|
generate_cross_reference(coverages, profiles))
|
||||||
)
|
|
||||||
|
|
||||||
# Generate gap analysis page
|
# Generate gap analysis page
|
||||||
print("Generating gap analysis page...")
|
print("Generating gap analysis page...")
|
||||||
(docs / "gaps.md").write_text(
|
write_if_changed(str(docs / "gaps.md"),
|
||||||
generate_gap_analysis(profiles, coverages, db)
|
generate_gap_analysis(profiles, coverages, db))
|
||||||
)
|
|
||||||
|
|
||||||
# Wiki pages: copy manually maintained sources + generate dynamic ones
|
# Wiki pages: copy manually maintained sources + generate dynamic ones
|
||||||
print("Generating wiki pages...")
|
print("Generating wiki pages...")
|
||||||
@@ -2115,11 +2113,11 @@ def main():
|
|||||||
for src_file in wiki_src.glob("*.md"):
|
for src_file in wiki_src.glob("*.md"):
|
||||||
shutil.copy2(src_file, wiki_dest / src_file.name)
|
shutil.copy2(src_file, wiki_dest / src_file.name)
|
||||||
# data-model.md is generated (contains live DB stats)
|
# 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
|
# Generate contributing
|
||||||
print("Generating contributing page...")
|
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)
|
# Update mkdocs.yml nav section only (avoid yaml.dump round-trip mangling quotes)
|
||||||
print("Updating mkdocs.yml nav...")
|
print("Updating mkdocs.yml nav...")
|
||||||
@@ -2173,9 +2171,7 @@ markdown_extensions:
|
|||||||
plugins:
|
plugins:
|
||||||
- search
|
- search
|
||||||
"""
|
"""
|
||||||
with open("mkdocs.yml", "w") as f:
|
write_if_changed("mkdocs.yml", mkdocs_static + nav_yaml)
|
||||||
f.write(mkdocs_static)
|
|
||||||
f.write(nav_yaml)
|
|
||||||
|
|
||||||
total_pages = (
|
total_pages = (
|
||||||
1 # home
|
1 # home
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import urllib.request
|
|||||||
import urllib.error
|
import urllib.error
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -231,7 +232,28 @@ def scraper_cli(scraper_class: type, description: str = "Scrape BIOS requirement
|
|||||||
if req.zipped_file:
|
if req.zipped_file:
|
||||||
entry["zipped_file"] = req.zipped_file
|
entry["zipped_file"] = req.zipped_file
|
||||||
config["systems"][sys_id]["files"].append(entry)
|
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)
|
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
||||||
print(f"Written {len(reqs)} entries to {args.output}")
|
print(f"Written {len(reqs)} entries to {args.output}")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -303,12 +303,25 @@ class Scraper(BaseScraper):
|
|||||||
"""Generate a platform YAML config dict from scraped data."""
|
"""Generate a platform YAML config dict from scraped data."""
|
||||||
requirements = self.fetch_requirements()
|
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 = {}
|
systems = {}
|
||||||
for req in requirements:
|
for req in requirements:
|
||||||
if req.system not in systems:
|
if req.system not in systems:
|
||||||
sys_entry: dict = {"files": []}
|
sys_entry: dict = {"files": []}
|
||||||
if req.native_id:
|
if req.native_id:
|
||||||
sys_entry["native_id"] = 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
|
systems[req.system] = sys_entry
|
||||||
|
|
||||||
entry = {
|
entry = {
|
||||||
|
|||||||
@@ -121,10 +121,25 @@ class Scraper(BaseScraper):
|
|||||||
"""Generate a platform YAML config dict from scraped data."""
|
"""Generate a platform YAML config dict from scraped data."""
|
||||||
requirements = self.fetch_requirements()
|
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 = {}
|
systems = {}
|
||||||
for req in requirements:
|
for req in requirements:
|
||||||
if req.system not in systems:
|
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 = {
|
entry = {
|
||||||
"name": req.name,
|
"name": req.name,
|
||||||
|
|||||||
@@ -291,6 +291,10 @@ def find_undeclared_files(
|
|||||||
if emu_name not in relevant:
|
if emu_name not in relevant:
|
||||||
continue
|
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
|
# Check if this profile is standalone: match profile name or any cores: alias
|
||||||
is_standalone = emu_name in standalone_set or bool(
|
is_standalone = emu_name in standalone_set or bool(
|
||||||
standalone_set & {str(c) for c in profile.get("cores", [])}
|
standalone_set & {str(c) for c in profile.get("cores", [])}
|
||||||
@@ -317,6 +321,10 @@ def find_undeclared_files(
|
|||||||
if load_from and load_from != "system_dir":
|
if load_from and load_from != "system_dir":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Skip agnostic files (filename-agnostic, handled by agnostic scan)
|
||||||
|
if f.get("agnostic"):
|
||||||
|
continue
|
||||||
|
|
||||||
archive = f.get("archive")
|
archive = f.get("archive")
|
||||||
|
|
||||||
# Skip files declared by the platform (by name or archive)
|
# Skip files declared by the platform (by name or archive)
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ class TestE2E(unittest.TestCase):
|
|||||||
"md5": info["md5"],
|
"md5": info["md5"],
|
||||||
"name": name,
|
"name": name,
|
||||||
"crc32": info.get("crc32", ""),
|
"crc32": info.get("crc32", ""),
|
||||||
|
"size": len(info["data"]),
|
||||||
}
|
}
|
||||||
by_md5[info["md5"]] = sha1
|
by_md5[info["md5"]] = sha1
|
||||||
by_name.setdefault(name, []).append(sha1)
|
by_name.setdefault(name, []).append(sha1)
|
||||||
@@ -510,6 +511,33 @@ class TestE2E(unittest.TestCase):
|
|||||||
with open(os.path.join(self.emulators_dir, "test_renamed.yml"), "w") as fh:
|
with open(os.path.join(self.emulators_dir, "test_renamed.yml"), "w") as fh:
|
||||||
yaml.dump(emu_renamed, 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
|
# THE TEST -one method per feature area, all using same fixtures
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
@@ -3142,7 +3170,8 @@ class TestE2E(unittest.TestCase):
|
|||||||
self.assertIn("Sony - PlayStation", content)
|
self.assertIn("Sony - PlayStation", content)
|
||||||
self.assertIn("scph5501.bin", content)
|
self.assertIn("scph5501.bin", content)
|
||||||
self.assertIn("b056ee5a4d65937e1a3a17e1e78f3258ea49c38e", 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)
|
issues = exporter.validate(truth, out_path)
|
||||||
self.assertEqual(issues, [])
|
self.assertEqual(issues, [])
|
||||||
@@ -3411,6 +3440,173 @@ class TestE2E(unittest.TestCase):
|
|||||||
self.assertEqual(result["summary"]["total_missing"], 0)
|
self.assertEqual(result["summary"]["total_missing"], 0)
|
||||||
self.assertEqual(result["summary"]["systems_compared"], 1)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user