mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 12:33:53 -06:00
chore: merge launcher names
This commit is contained in:
commit
2fe15e99f9
24 files changed
+1400
-62
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+661
-12
@@ -109,30 +109,34 @@ files:
|
||||
system: commodore-amiga
|
||||
required: true
|
||||
size: 262144
|
||||
crc32: "c4f0f55f"
|
||||
note: "A500 Kickstart v1.3 rev 34.005, default for A500 model"
|
||||
source_ref: "source libretro/libretro.cpp:1818 (candidates_a500)"
|
||||
source_ref: "source libretro/libretro.cpp:1818 (candidates_a500), source src/rommgr.cpp:161-162"
|
||||
|
||||
- name: kick12.rom
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "a6ce1636"
|
||||
note: "A500 Kickstart v1.2 rev 33.180, for A500OG model"
|
||||
source_ref: "source libretro/libretro.cpp:1817 (candidates_a500og)"
|
||||
source_ref: "source libretro/libretro.cpp:1817 (candidates_a500og), source src/rommgr.cpp:159-160"
|
||||
|
||||
- name: kick20.rom
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
aliases: [kick204.rom]
|
||||
crc32: "c3bdb240"
|
||||
note: "A500+ Kickstart v2.04 rev 37.175"
|
||||
source_ref: "source libretro/libretro.cpp:1819 (candidates_a500p)"
|
||||
source_ref: "source libretro/libretro.cpp:1819 (candidates_a500p), source src/rommgr.cpp:169-170"
|
||||
|
||||
- name: kick205.rom
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "43b0df7b"
|
||||
note: "A600 Kickstart v2.05 rev 37.350, also used for WHDLoad"
|
||||
source_ref: "source libretro/libretro.cpp:1820 (candidates_a600)"
|
||||
source_ref: "source libretro/libretro.cpp:1820 (candidates_a600), source src/rommgr.cpp:175-176"
|
||||
|
||||
- name: kick31.rom
|
||||
system: commodore-amiga
|
||||
@@ -145,15 +149,17 @@ files:
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "1483a091"
|
||||
note: "A1200 Kickstart v3.1 rev 40.68, fallback after kick31.rom"
|
||||
source_ref: "source libretro/libretro.cpp:775 (option label), source libretro/libretro.cpp:1821 (candidates_a1200)"
|
||||
source_ref: "source libretro/libretro.cpp:775 (option label), source libretro/libretro.cpp:1821 (candidates_a1200), source src/rommgr.cpp:196-197"
|
||||
|
||||
- name: kick40068.A4000
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "d6bae334"
|
||||
note: "A4000 Kickstart v3.1 rev 40.68, fallback after kick31.rom"
|
||||
source_ref: "source libretro/libretro.cpp:776 (option label), source libretro/libretro.cpp:1822 (candidates_a4000)"
|
||||
source_ref: "source libretro/libretro.cpp:776 (option label), source libretro/libretro.cpp:1822 (candidates_a4000), source src/rommgr.cpp:206-207"
|
||||
|
||||
- name: kick.rom
|
||||
system: commodore-amiga
|
||||
@@ -165,41 +171,49 @@ files:
|
||||
|
||||
- name: cd32.rom
|
||||
system: commodore-cd32
|
||||
min_size: 524288
|
||||
max_size: 1048576
|
||||
required: false
|
||||
size: 524288
|
||||
aliases: [amiga-os-310-cd32.rom, kick40060.CD32]
|
||||
crc32: ["1e62d4a5", "f5d4f3c8"]
|
||||
note: "CD32 Kickstart v3.1 rev 40.60. candidates_cd32 tries cd32.rom, amiga-os-310-cd32.rom, kick40060.CD32, kick31.rom, then kick.rom."
|
||||
source_ref: "source libretro/libretro.cpp:1823 (candidates_cd32)"
|
||||
source_ref: "source libretro/libretro.cpp:1823 (candidates_cd32), source src/rommgr.cpp:334-335, source src/rommgr.cpp:340-341"
|
||||
|
||||
- name: cd32ext.rom
|
||||
system: commodore-cd32
|
||||
required: false
|
||||
size: 524288
|
||||
aliases: [amiga-ext-310-cd32.rom, "CD32 Extended.ROM"]
|
||||
crc32: "87746be2"
|
||||
note: "CD32 extended ROM rev 40.60. Not needed if using a combined 1MB ROM."
|
||||
source_ref: "source libretro/libretro.cpp:1881 (candidates_cd32 in find_ext_rom_in_system_dir)"
|
||||
source_ref: "source libretro/libretro.cpp:1881 (candidates_cd32 in find_ext_rom_in_system_dir), source src/rommgr.cpp:336-337"
|
||||
|
||||
# --- CDTV ROMs ---
|
||||
|
||||
- name: cdtv.rom
|
||||
system: commodore-cdtv
|
||||
size: 262144
|
||||
required: false
|
||||
aliases: [kick34005.CDTV]
|
||||
crc32: "42baa124"
|
||||
note: "CDTV extended ROM v1.00, used as kickstart candidate. candidates_cdtv tries cdtv.rom, kick34005.CDTV, kick13.rom, then kick.rom."
|
||||
source_ref: "source libretro/libretro.cpp:1824 (candidates_cdtv)"
|
||||
source_ref: "source libretro/libretro.cpp:1824 (candidates_cdtv), source src/rommgr.cpp:350-351"
|
||||
|
||||
- name: cdtvext.rom
|
||||
system: commodore-cdtv
|
||||
size: 262144
|
||||
required: false
|
||||
aliases: ["CDTV Extended.ROM"]
|
||||
crc32: ["42baa124", "30b54232", "ceae68d2"]
|
||||
note: "CDTV extended ROM file"
|
||||
source_ref: "source libretro/libretro.cpp:1883 (candidates_cdtv in find_ext_rom_in_system_dir)"
|
||||
source_ref: "source libretro/libretro.cpp:1883 (candidates_cdtv in find_ext_rom_in_system_dir), source src/rommgr.cpp:350-351, source src/rommgr.cpp:354-355, source src/rommgr.cpp:358-359"
|
||||
|
||||
# --- Kickstart ROMs found by the standalone ROM scan ---
|
||||
# The scan opens every file under the ROM path whose extension is rom, bin,
|
||||
# a1000, a500, a600, a1200, a3000, a4000, cdtv, cd32, roz or U followed by a
|
||||
# digit and names it by the SHA-1 the ROM database lists. A model then takes
|
||||
# the first ROM id on its list that the scan found.
|
||||
# the first ROM id on its list that the scan found. Split chip dumps the
|
||||
# table lists for an image are identified one by one and merged.
|
||||
# ref: src/osdep/amiberry_gui.cpp:228-254, src/osdep/amiberry_gui.cpp:285-307,
|
||||
# src/osdep/amiberry_gui.cpp:431-469, src/rommgr.cpp:3186-3256,
|
||||
# src/rommgr.cpp:1668-1681
|
||||
@@ -217,6 +231,641 @@ files:
|
||||
is called. The A4000 model takes id 16 first and id 31 after it.
|
||||
source_ref: "source src/rommgr.cpp:204-205, source src/cfgfile.cpp:10099-10107, source src/cfgfile.cpp:10160-10161"
|
||||
|
||||
- name: "KS ROM v23.93 (Velvet).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 131072
|
||||
crc32: "adcb44c9"
|
||||
sha1: "7c36b2ba298da3dace60d0ba8511d47076a40d5c"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v23.93 (Velvet), ROM id 125."
|
||||
source_ref: "source src/rommgr.cpp:144-145, source src/cfgfile.cpp:10244"
|
||||
|
||||
- name: "KS ROM v1.0 (A1000)(NTSC).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "299790ff"
|
||||
sha1: "00c15406beb4b8ab1a16aa66c05860e1a7c1ad79"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v1.0 (A1000)(NTSC), ROM id 1."
|
||||
source_ref: "source src/rommgr.cpp:151-152, source src/cfgfile.cpp:9436"
|
||||
|
||||
- name: "KS ROM v1.1 (A1000)(NTSC).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "d060572a"
|
||||
sha1: "4192c505d130f446b2ada6bdc91dae730acafb4c"
|
||||
found_by: content
|
||||
aliases: ["kick31034.A1000"]
|
||||
note: "Identified as KS ROM v1.1 (A1000)(NTSC), ROM id 2. WHDLoad booting links it into its Kickstarts folder as kick31034.A1000, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:153-154, source src/cfgfile.cpp:9436, source src/osdep/amiberry_whdbooter.cpp:368, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "KS ROM v1.1 (A1000)(PAL).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "ec86dae2"
|
||||
sha1: "16df8b5fd524c5a1c7584b2457ac15aff9e3ad6d"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v1.1 (A1000)(PAL), ROM id 3."
|
||||
source_ref: "source src/rommgr.cpp:155-156, source src/cfgfile.cpp:9436"
|
||||
|
||||
- name: "KS ROM v1.2 (A1000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "9ed783d0"
|
||||
sha1: "6a7bfb5dbd6b8f179f03da84d8d9528267b6273b"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v1.2 (A1000), ROM id 4."
|
||||
source_ref: "source src/rommgr.cpp:157-158, source src/cfgfile.cpp:9436, 10557, 10565"
|
||||
|
||||
- name: "amiga-os-120.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "a6ce1636"
|
||||
sha1: "11f9e62cf299f72184835b7b2a70a16333fc0d88"
|
||||
found_by: content
|
||||
aliases: ["kick33180.A500"]
|
||||
note: "Identified as KS ROM v1.2 (A500,A1000,A2000), ROM id 5. WHDLoad booting links it into its Kickstarts folder as kick33180.A500, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:159-160, source src/cfgfile.cpp:9436, 10556, 10564, source src/osdep/amiberry_whdbooter.cpp:369, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "amiga-os-130.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "c4f0f55f"
|
||||
sha1: "891e9a547772fe0c6c19b610baf8bc4ea7fcb785"
|
||||
found_by: content
|
||||
aliases: ["kick34005.A500"]
|
||||
note: "Identified as KS ROM v1.3 (A500,A1000,A2000), ROM id 6. WHDLoad booting links it into its Kickstarts folder as kick34005.A500, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:161-162, source src/cfgfile.cpp:9436, 10311, 10533, 10538, 10542, 10548, source src/osdep/amiberry_whdbooter.cpp:370, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "KS ROM v1.3 (A3000)(SK).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 262144
|
||||
crc32: "e0f37258"
|
||||
sha1: "c39bd9094d4e5f4e28c1411f3086950406062e87"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v1.3 (A3000)(SK), ROM id 32."
|
||||
source_ref: "source src/rommgr.cpp:163-164, source src/cfgfile.cpp:10312, 10534, 10539, 10543, 10549"
|
||||
|
||||
- name: "KS ROM v1.4 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "bc0ec13f"
|
||||
sha1: "f76316bf36dff14b20fa349ed02e4b11dd932b07"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v1.4 (A3000), ROM id 59."
|
||||
source_ref: "source src/rommgr.cpp:165-166, source src/cfgfile.cpp:10069"
|
||||
|
||||
- name: "amiga-os-204.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "c3bdb240"
|
||||
sha1: "c5839f5cb98a7a8947065c3ed2f14f5f42e334a1"
|
||||
found_by: content
|
||||
aliases: ["kick37175.A500"]
|
||||
note: "Identified as KS ROM v2.04 (A500+), ROM id 7. WHDLoad booting links it into its Kickstarts folder as kick37175.A500, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:169-170, source src/cfgfile.cpp:9436, 10509, source src/osdep/amiberry_whdbooter.cpp:371, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "KS ROM v2.05 (A600).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "83028fb5"
|
||||
sha1: "87508de834dc7eb47359cede72d2e3c8a2e5d8db"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v2.05 (A600), ROM id 8."
|
||||
source_ref: "source src/rommgr.cpp:171-172, source src/cfgfile.cpp:9436, 10474"
|
||||
|
||||
- name: "KS ROM v2.05 (A600HD).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "64466c2a"
|
||||
sha1: "f72d89148dac39c696e30b10859ebc859226637b"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v2.05 (A600HD), ROM id 9."
|
||||
source_ref: "source src/rommgr.cpp:173-174, source src/cfgfile.cpp:9436, 10272, 10473"
|
||||
|
||||
- name: "amiga-os-205-a600.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "43b0df7b"
|
||||
sha1: "02843c4253bbd29aba535b0aa3bd9a85034ecde4"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v2.05 (A600HD), ROM id 10."
|
||||
source_ref: "source src/rommgr.cpp:175-176, source src/cfgfile.cpp:9436, 10273, 10472"
|
||||
|
||||
- name: "KS ROM v2.04 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "234a7233"
|
||||
sha1: "d82ebb59afc53540ddf2d7187ecf239b7ea91590"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v2.04 (A3000), ROM id 71."
|
||||
source_ref: "source src/rommgr.cpp:177-178, source src/cfgfile.cpp:10067"
|
||||
|
||||
- name: "amiga-os-300-a1200.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "6c9b07d2"
|
||||
sha1: "70033828182fffc7ed106e5373a8b89dda76faa5"
|
||||
found_by: content
|
||||
aliases: ["kick39106.A1200"]
|
||||
note: "Identified as KS ROM v3.0 (A1200), ROM id 11. WHDLoad booting links it into its Kickstarts folder as kick39106.A1200, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:182-183, source src/cfgfile.cpp:10387, 10447, 10585, source src/osdep/amiberry_whdbooter.cpp:372, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "amiga-os-300-a4000.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "9e6ac152"
|
||||
sha1: "f0b4e9e29e12218c2d5bd7020e4e785297d91fd7"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.0 (A4000), ROM id 12."
|
||||
source_ref: "source src/rommgr.cpp:186-187, source src/cfgfile.cpp:10109, 10584"
|
||||
|
||||
- name: "KS ROM v3.1 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "2b4566f1"
|
||||
sha1: "81c631dd096bbb31d2af90299c76b774db74076c"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1 (A4000), ROM id 13."
|
||||
source_ref: "source src/rommgr.cpp:190-191, source src/cfgfile.cpp:10108"
|
||||
|
||||
- name: "amiga-os-310-a600.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "fc24ae0d"
|
||||
sha1: "3b7f1493b27e212830f989f26ca76c02049f09ca"
|
||||
found_by: content
|
||||
aliases: ["kick40063.A600"]
|
||||
note: "Identified as KS ROM v3.1 (A500,A600,A2000), ROM id 14. WHDLoad booting links it into its Kickstarts folder as kick40063.A600, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:194-195, source src/cfgfile.cpp:9436, 10583, source src/osdep/amiberry_whdbooter.cpp:373, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "amiga-os-310-a1200.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "1483a091"
|
||||
sha1: "e21545723fe8374e91342617604f1b3d703094f1"
|
||||
found_by: content
|
||||
aliases: ["kick40068.A1200"]
|
||||
note: "Identified as KS ROM v3.1 (A1200), ROM id 15. WHDLoad booting links it into its Kickstarts folder as kick40068.A1200, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:196-197, source src/cfgfile.cpp:10388, 10446, 10582, source src/osdep/amiberry_whdbooter.cpp:374, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "amiga-os-310-a3000.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "efb239cc"
|
||||
sha1: "f8e210d72b4c4853e0c9b85d223ba20e3d1b36ee"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1 (A3000), ROM id 61."
|
||||
source_ref: "source src/rommgr.cpp:200-201, source src/cfgfile.cpp:10065"
|
||||
|
||||
- name: "amiga-os-310-a4000.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "d6bae334"
|
||||
sha1: "5fe04842d04a489720f0f4bb0e46948199406f49"
|
||||
found_by: content
|
||||
aliases: ["kick40068.A4000"]
|
||||
note: "Identified as KS ROM v3.1 (A4000), ROM id 16. WHDLoad booting links it into its Kickstarts folder as kick40068.A4000, unless a file of that name is there."
|
||||
source_ref: "source src/rommgr.cpp:206-207, source src/cfgfile.cpp:10106, 10580, source src/osdep/amiberry_whdbooter.cpp:375, source src/osdep/amiberry_whdbooter.cpp:297-342"
|
||||
|
||||
- name: "amiga-os-310-a4000t.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "75932c3a"
|
||||
sha1: "b0ec8b84d6768321e01209f11e6248f2f5281a21"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1 (A4000T), ROM id 17."
|
||||
source_ref: "source src/rommgr.cpp:210-211, source src/cfgfile.cpp:10168"
|
||||
|
||||
- name: "KS ROM v3.X (A4000)(Cloanto).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "3ac99edc"
|
||||
sha1: "3cbfc9e1fe396360157bd161de74fc901abee7ec"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.X (A4000)(Cloanto), ROM id 46."
|
||||
source_ref: "source src/rommgr.cpp:214-215, source src/cfgfile.cpp:10111"
|
||||
|
||||
- name: "KS ROM v3.1.4-1 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "f17fa97f"
|
||||
sha1: "6355a9ed5dc840422f9b73308a91be0d0bb506bd"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-1 (A1200), ROM id 276."
|
||||
source_ref: "source src/rommgr.cpp:217-218, source src/cfgfile.cpp:10390"
|
||||
|
||||
- name: "KS ROM v3.1.4-1 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "50c3529c"
|
||||
sha1: "1a34b25a25e260e38e879172850143c80b461a64"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-1 (A3000), ROM id 277."
|
||||
source_ref: "source src/rommgr.cpp:221-222"
|
||||
|
||||
- name: "KS ROM v3.1.4-1 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "d47e18fd"
|
||||
sha1: "bad0ae388442db02eaeb6a5363ef43eb4e308ae6"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-1 (A4000), ROM id 278."
|
||||
source_ref: "source src/rommgr.cpp:225-226, source src/cfgfile.cpp:10112"
|
||||
|
||||
- name: "KS ROM v3.1.4-1 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "75a2b2a5"
|
||||
sha1: "938a60a1d2c0d411f64bb27e5af40258b8decbf3"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-1 (A4000T), ROM id 279."
|
||||
source_ref: "source src/rommgr.cpp:229-230, source src/cfgfile.cpp:10169"
|
||||
|
||||
- name: "KS ROM v3.1.4-1 (A500).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "d52b52fd"
|
||||
sha1: "8a2405087ce182225656dd0b93069c45743f9e34"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-1 (A500), ROM id 280."
|
||||
source_ref: "source src/rommgr.cpp:233-234"
|
||||
|
||||
- name: "KS ROM v3.1.4-2 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "b87506a7"
|
||||
sha1: "ef36c4638ee45de6bb93701761216c958cd0d57b"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-2 (A1200), ROM id 281."
|
||||
source_ref: "source src/rommgr.cpp:236-237, source src/cfgfile.cpp:10391"
|
||||
|
||||
- name: "KS ROM v3.1.4-2 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "ba35f8eb"
|
||||
sha1: "d73ae3a36f12bb49bbf6ba04a890ff7aac419015"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-2 (A3000), ROM id 282."
|
||||
source_ref: "source src/rommgr.cpp:240-241"
|
||||
|
||||
- name: "KS ROM v3.1.4-2 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "1b84cb33"
|
||||
sha1: "aab44cd651e6b6f81a3effd8e0ba6b37ab322f32"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-2 (A4000), ROM id 283."
|
||||
source_ref: "source src/rommgr.cpp:244-245, source src/cfgfile.cpp:10113"
|
||||
|
||||
- name: "KS ROM v3.1.4-2 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "d6d0ef3e"
|
||||
sha1: "cd73aefe9cbfc258e7966cd14a7b2f4647c9ba45"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-2 (A4000T), ROM id 284."
|
||||
source_ref: "source src/rommgr.cpp:248-249, source src/cfgfile.cpp:10170"
|
||||
|
||||
- name: "KS ROM v3.1.4-2 (A500).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "568f8786"
|
||||
sha1: "d81cd6f131040895843d9dfa95a45bc95edd9704"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.1.4-2 (A500), ROM id 285."
|
||||
source_ref: "source src/rommgr.cpp:252-253"
|
||||
|
||||
- name: "KS ROM v3.2 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "bd1ff75e"
|
||||
sha1: "5b2982876fec2166673be447643881262c84090e"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (A1200), ROM id 286."
|
||||
source_ref: "source src/rommgr.cpp:255-256, source src/cfgfile.cpp:10392"
|
||||
|
||||
- name: "KS ROM v3.2 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "f3af46cc"
|
||||
sha1: "7bc0e75622d7254e11ea708e5d149007866c93ab"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (A3000), ROM id 287."
|
||||
source_ref: "source src/rommgr.cpp:259-260"
|
||||
|
||||
- name: "KS ROM v3.2 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "9bb8fc93"
|
||||
sha1: "37a8aa0b83782d75ce0b4a80631ff3459e91dc63"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (A4000), ROM id 288."
|
||||
source_ref: "source src/rommgr.cpp:263-264, source src/cfgfile.cpp:10114"
|
||||
|
||||
- name: "KS ROM v3.2 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "9188a509"
|
||||
sha1: "ede1748eb2cbb1e86ac5bf7dc9b97246a4a54358"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (A4000T), ROM id 289."
|
||||
source_ref: "source src/rommgr.cpp:267-268, source src/cfgfile.cpp:10171"
|
||||
|
||||
- name: "KS ROM v3.2 (A500/A600/A2000/A1000/CDTV).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "8173d7b6"
|
||||
sha1: "b88e364daf23c9c9920e548b0d3d944e65b1031d"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (A500/A600/A2000/A1000/CDTV), ROM id 290."
|
||||
source_ref: "source src/rommgr.cpp:271-272"
|
||||
|
||||
- name: "KS ROM v3.2.1 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "2b653371"
|
||||
sha1: "0984fc0df07dc0585db0923d580629f70fca420d"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.1 (A1200), ROM id 291."
|
||||
source_ref: "source src/rommgr.cpp:274-275, source src/cfgfile.cpp:10393"
|
||||
|
||||
- name: "KS ROM v3.2.1 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "0078f607"
|
||||
sha1: "eb93508f0bb0cde81d88bf22d05045565d66ef74"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.1 (A3000), ROM id 292."
|
||||
source_ref: "source src/rommgr.cpp:278-279"
|
||||
|
||||
- name: "KS ROM v3.2.1 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "f3ced3b8"
|
||||
sha1: "7db3c3226acc0bfe548c788cf1bc7c4c8774d66f"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.1 (A4000), ROM id 293."
|
||||
source_ref: "source src/rommgr.cpp:282-283, source src/cfgfile.cpp:10115"
|
||||
|
||||
- name: "KS ROM v3.2.1 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "af3452ec"
|
||||
sha1: "a75fcd349680cedeab06e496c6338394e81788d7"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.1 (A4000T), ROM id 294."
|
||||
source_ref: "source src/rommgr.cpp:286-287, source src/cfgfile.cpp:10172"
|
||||
|
||||
- name: "KS ROM v3.2.1 (A500/A600/A2000/A1000/CDTV).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "4f078456"
|
||||
sha1: "8f64ada68a7f128ba782e8dc9fa583344171590a"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.1 (A500/A600/A2000/A1000/CDTV), ROM id 295."
|
||||
source_ref: "source src/rommgr.cpp:290-291"
|
||||
|
||||
- name: "KS ROM v3.2.2 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "5c40328a"
|
||||
sha1: "d9622547d84741b52c5472607f9aca75565cbba3"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.2 (A1200), ROM id 304."
|
||||
source_ref: "source src/rommgr.cpp:293-294, source src/cfgfile.cpp:10394"
|
||||
|
||||
- name: "KS ROM v3.2.2 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "46335b57"
|
||||
sha1: "443d98369aca3ba51ab2d4789d14fa9a26379c0b"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.2 (A3000), ROM id 305."
|
||||
source_ref: "source src/rommgr.cpp:297-298"
|
||||
|
||||
- name: "KS ROM v3.2.2 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "4bea9798"
|
||||
sha1: "a3207bd5b5a3ca629010f3159ac793040fa813ef"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.2 (A4000), ROM id 306."
|
||||
source_ref: "source src/rommgr.cpp:301-302, source src/cfgfile.cpp:10116"
|
||||
|
||||
- name: "KS ROM v3.2.2 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "36bbcd8a"
|
||||
sha1: "8e3fff2675cc1b97b4f072b63fd4de7093f7c627"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.2 (A4000T), ROM id 307."
|
||||
source_ref: "source src/rommgr.cpp:305-306, source src/cfgfile.cpp:10173"
|
||||
|
||||
- name: "KS ROM v3.2.2 (A500/A600/A2000/A1000/CDTV).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "e4458462"
|
||||
sha1: "7d5ebe686b69d59a863cc77a36b2cd60359a9ed2"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.2 (A500/A600/A2000/A1000/CDTV), ROM id 308."
|
||||
source_ref: "source src/rommgr.cpp:309-310"
|
||||
|
||||
- name: "KS ROM v3.2.3 (A1200).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "b18d3b67"
|
||||
sha1: "3f48ef0eca607855d7872796ba886d7889451fad"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.3 (A1200), ROM id 333."
|
||||
source_ref: "source src/rommgr.cpp:312-313"
|
||||
|
||||
- name: "KS ROM v3.2.3 (A3000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "74c0b23f"
|
||||
sha1: "76222baa6d5654dbba4a769bb86c1f39322d1c1c"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.3 (A3000), ROM id 334."
|
||||
source_ref: "source src/rommgr.cpp:314-315"
|
||||
|
||||
- name: "KS ROM v3.2.3 (A4000).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "b6a4698e"
|
||||
sha1: "81902f41cbf6fc6b7d18c691a4ada6245d174bde"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.3 (A4000), ROM id 335."
|
||||
source_ref: "source src/rommgr.cpp:316-317"
|
||||
|
||||
- name: "KS ROM v3.2.3 (A4000T).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "588a5e6d"
|
||||
sha1: "8eeb6c2b282e589bd1589ebba3a78a41722499ec"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.3 (A4000T), ROM id 336."
|
||||
source_ref: "source src/rommgr.cpp:318-319"
|
||||
|
||||
- name: "KS ROM v3.2.3 (A500/A600/A2000/A1000/CDTV).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "e1f50b0b"
|
||||
sha1: "a9d51491d4b1356673621b61f789aed979bd01be"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2.3 (A500/A600/A2000/A1000/CDTV), ROM id 337."
|
||||
source_ref: "source src/rommgr.cpp:320-321"
|
||||
|
||||
- name: "KS ROM v3.2 (Walker).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "261339f8"
|
||||
sha1: "7a9095f1107966f90267dc4cb3c1972efb4b78a8"
|
||||
found_by: content
|
||||
note: "Identified as KS ROM v3.2 (Walker), ROM id 296."
|
||||
source_ref: "source src/rommgr.cpp:323-324"
|
||||
|
||||
- name: "Casablanca 74095 - 00 717 - 02.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 1048576
|
||||
crc32: "2ec384e3"
|
||||
sha1: "47f9ee6d0f8ac5a65c6eddc30bcd47c8574d8725"
|
||||
found_by: content
|
||||
note: "Identified as Casablanca 74095 - 00 717 - 02, ROM id 231."
|
||||
source_ref: "source src/rommgr.cpp:325-326"
|
||||
|
||||
- name: "A1000 bootstrap ROM.rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 65536
|
||||
crc32: "0b1ad2d0"
|
||||
sha1: "ba93b8b85ca0d83a68225cc33b95050d72d2fdd7"
|
||||
found_by: content
|
||||
note: "Identified as A1000 bootstrap ROM, ROM id 24."
|
||||
source_ref: "source src/rommgr.cpp:372-373, source src/cfgfile.cpp:10227"
|
||||
|
||||
- name: "The Diagnostic 2.0 (Logica).rom"
|
||||
mode: standalone
|
||||
system: commodore-amiga
|
||||
required: false
|
||||
size: 524288
|
||||
crc32: "8484f426"
|
||||
sha1: "ba10d16166b2e2d6177c979c99edf8462b21651e"
|
||||
found_by: content
|
||||
note: "Identified as The Diagnostic 2.0 (Logica), ROM id 72."
|
||||
source_ref: "source src/rommgr.cpp:378-379"
|
||||
|
||||
# --- CD32 and CDTV ROMs found by the standalone ROM scan ---
|
||||
# configure_rom() writes a CD32 Kickstart to the Kickstart setting and a
|
||||
# CD32 or CDTV extended ROM to the extended ROM setting.
|
||||
|
||||
+4
-2
@@ -311,7 +311,8 @@ files:
|
||||
sha256: "0293555b21c4fac516d25199df7809b26beeae150e1d4504a050db32264a6ad7"
|
||||
validation: [sha256]
|
||||
description: "Neo Geo Pocket BIOS"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket.cpp:12"
|
||||
config_key: "NeoGeoPocket/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket.cpp:12, desktop-ui/settings/settings.cpp:263-264, 280-283"
|
||||
|
||||
# --- Neo Geo Pocket Color ---
|
||||
- name: ngpc_bios.rom
|
||||
@@ -320,7 +321,8 @@ files:
|
||||
sha256: "8fb845a2f71514cec20728e2f0fecfade69444f8d50898b92c2259f1ba63e10d"
|
||||
validation: [sha256]
|
||||
description: "Neo Geo Pocket Color BIOS"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket-color.cpp:12"
|
||||
config_key: "NeoGeoPocketColor/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket-color.cpp:12, desktop-ui/settings/settings.cpp:263-264, 280-283"
|
||||
|
||||
# --- Nintendo 64DD ---
|
||||
- name: 64dd_ipl_J.bin
|
||||
|
||||
+50
-27
@@ -49,11 +49,12 @@ files:
|
||||
note: >
|
||||
Atari 5200 BIOS (original). Mapped at $F800-$FFFF.
|
||||
Altirra 5200 OS is used when this file is absent.
|
||||
source_ref: "source atari800/src/sysrom.c:103-104, source atari800/src/sysrom.c:290"
|
||||
config_key: "ROM_5200"
|
||||
source_ref: "source atari800/src/sysrom.c:103-104, source atari800/src/sysrom.c:290, source atari800/src/sysrom.c:138, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-5200-os-2port.rom"
|
||||
found_by: content
|
||||
path: "atari-5200-os-2port.rom"
|
||||
aliases: [ROM_5200_A]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 2048
|
||||
@@ -65,7 +66,8 @@ files:
|
||||
as SYSROM_5200A, and the automatic choice for the 5200 tries it after
|
||||
the original OS and before the Altirra 5200 OS. ROM_5200_A is the
|
||||
configuration key this ROM is stored under in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:104, source atari800/src/sysrom.c:139, source atari800/src/sysrom.c:317-420, source atari800/src/sysrom.c:473, source atari800/src/sysrom.c:674, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_5200_A"
|
||||
source_ref: "source atari800/src/sysrom.c:104, source atari800/src/sysrom.c:139, source atari800/src/sysrom.c:317-420, source atari800/src/sysrom.c:473, source atari800/src/sysrom.c:674, source atari800/src/atari.c:537, source atari800/src/sysrom.c:139, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Atari BASIC ROM --
|
||||
# Atari BASIC interpreter (8 KB). Three known revisions:
|
||||
@@ -85,7 +87,8 @@ files:
|
||||
note: >
|
||||
Atari BASIC Rev C. Required for 400/800 software that needs BASIC.
|
||||
Altirra BASIC is used as fallback. Enable via core option atari800_opt2.
|
||||
source_ref: "source atari800/src/sysrom.c:105-107, source atari800/src/sysrom.c:292"
|
||||
config_key: "ROM_BASIC_C"
|
||||
source_ref: "source atari800/src/sysrom.c:105-107, source atari800/src/sysrom.c:292, source atari800/src/sysrom.c:142, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Atari 400/800 OS A --
|
||||
# Original Atari 400/800 OS (10 KB). Two known CRC32 values:
|
||||
@@ -103,7 +106,8 @@ files:
|
||||
note: >
|
||||
Atari 400/800 OS Rev A. Altirra OS 800 is used as fallback.
|
||||
Auto-select order: OS B NTSC, OS A NTSC, OS A PAL, custom, Altirra.
|
||||
source_ref: "source atari800/src/sysrom.c:89-90, source atari800/src/sysrom.c:285"
|
||||
config_key: "ROM_OS_A_PAL"
|
||||
source_ref: "source atari800/src/sysrom.c:89-90, source atari800/src/sysrom.c:285, source atari800/src/sysrom.c:125, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Atari 400/800 OS B --
|
||||
# OS revision B (10 KB), NTSC: CRC32 0x0e86d61d
|
||||
@@ -123,7 +127,8 @@ files:
|
||||
SYSROM_B_NTSC. Preferred over Rev A for 400/800 mode.
|
||||
The .info lists md5 a3e8d617c95d08031fe1b20d541434b2, a different
|
||||
dump (crc32 3e28a1fe). sysrom.c detects the CRC32-matched one.
|
||||
source_ref: "source atari800/src/sysrom.c:91, source atari800/src/sysrom.c:286"
|
||||
config_key: "ROM_OS_B_NTSC"
|
||||
source_ref: "source atari800/src/sysrom.c:91, source atari800/src/sysrom.c:286, source atari800/src/sysrom.c:126, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Atari XL/XE OS --
|
||||
# XL/XE OS (16 KB). Many revisions known by CRC32 in sysrom.c:
|
||||
@@ -144,7 +149,8 @@ files:
|
||||
note: >
|
||||
Atari XL/XE OS. Used for 800XL, 130XE, and XEGS modes.
|
||||
Altirra XL OS is used as fallback.
|
||||
source_ref: "source atari800/src/sysrom.c:92-101, source atari800/src/sysrom.c:288"
|
||||
config_key: "ROM_OS_BB01R2"
|
||||
source_ref: "source atari800/src/sysrom.c:92-101, source atari800/src/sysrom.c:288, source atari800/src/sysrom.c:130, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Atari XL/XE/XEGS OS v4 (BB01R4) --
|
||||
# XEGS-specific OS revision BB01R4 (16 KB), CRC32: 0x1eaf4002
|
||||
@@ -160,7 +166,8 @@ files:
|
||||
validation: [size, crc32]
|
||||
note: >
|
||||
Atari XEGS OS Rev 4 (BB01R4). Preferred OS for XEGS machine mode.
|
||||
source_ref: "source atari800/src/sysrom.c:100"
|
||||
config_key: "ROM_OS_BB01R4"
|
||||
source_ref: "source atari800/src/sysrom.c:100, source atari800/src/sysrom.c:135, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- XEGS Missile Command built-in game --
|
||||
# The XEGS had Missile Command in ROM (8 KB), CRC32: 0xbdca01fb
|
||||
@@ -176,13 +183,14 @@ files:
|
||||
note: >
|
||||
XEGS built-in Missile Command ROM. Only used in XEGS machine mode.
|
||||
No built-in replacement exists for this ROM.
|
||||
source_ref: "source atari800/src/sysrom.c:108"
|
||||
config_key: "ROM_XEGAME"
|
||||
source_ref: "source atari800/src/sysrom.c:108, source atari800/src/sysrom.c:143, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# -- Further revisions identified by CRC32 in the system directory scan --
|
||||
|
||||
- name: "atari-800-os-a-ntsc.rom"
|
||||
found_by: content
|
||||
path: "atari-800-os-a-ntsc.rom"
|
||||
aliases: [ROM_OS_A_NTSC]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 10240
|
||||
@@ -194,11 +202,12 @@ files:
|
||||
10240 bytes whose CRC32 is c1b3bb02 is taken for this slot.
|
||||
ROM_OS_A_NTSC is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:89, source atari800/src/sysrom.c:124, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_A_NTSC"
|
||||
source_ref: "source atari800/src/sysrom.c:89, source atari800/src/sysrom.c:124, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:124, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-1200xl-os-rev-10.rom"
|
||||
found_by: content
|
||||
path: "atari-1200xl-os-rev-10.rom"
|
||||
aliases: [ROM_OS_AA00R10]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 16384
|
||||
@@ -210,11 +219,12 @@ files:
|
||||
16384 bytes whose CRC32 is c5c11546 is taken for this slot.
|
||||
ROM_OS_AA00R10 is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:92, source atari800/src/sysrom.c:127, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_AA00R10"
|
||||
source_ref: "source atari800/src/sysrom.c:92, source atari800/src/sysrom.c:127, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:127, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-1200xl-os-rev-11.rom"
|
||||
found_by: content
|
||||
path: "atari-1200xl-os-rev-11.rom"
|
||||
aliases: [ROM_OS_AA00R11]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 16384
|
||||
@@ -226,11 +236,12 @@ files:
|
||||
16384 bytes whose CRC32 is 1a1d7b1b is taken for this slot.
|
||||
ROM_OS_AA00R11 is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:93, source atari800/src/sysrom.c:128, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_AA00R11"
|
||||
source_ref: "source atari800/src/sysrom.c:93, source atari800/src/sysrom.c:128, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:128, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-xl-os-ver-1.rom"
|
||||
found_by: content
|
||||
path: "atari-xl-os-ver-1.rom"
|
||||
aliases: [ROM_OS_BB00R1]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 16384
|
||||
@@ -242,9 +253,11 @@ files:
|
||||
16384 bytes whose CRC32 is 643bcc98 is taken for this slot.
|
||||
ROM_OS_BB00R1 is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:94, source atari800/src/sysrom.c:129, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_BB00R1"
|
||||
source_ref: "source atari800/src/sysrom.c:94, source atari800/src/sysrom.c:129, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:129, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "ROM_OS_BB02R3V4"
|
||||
found_by: content
|
||||
path: "ROM_OS_BB02R3V4"
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -257,9 +270,11 @@ files:
|
||||
16384 bytes whose CRC32 is d425a9cf is taken for this slot.
|
||||
The name is the configuration key this ROM is stored under in
|
||||
.atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:97, source atari800/src/sysrom.c:132, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_BB02R3V4"
|
||||
source_ref: "source atari800/src/sysrom.c:97, source atari800/src/sysrom.c:132, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:132, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "ROM_OS_CC01R4"
|
||||
found_by: content
|
||||
path: "ROM_OS_CC01R4"
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -272,11 +287,12 @@ files:
|
||||
16384 bytes whose CRC32 is 0e000b99 is taken for this slot.
|
||||
The name is the configuration key this ROM is stored under in
|
||||
.atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:98, source atari800/src/sysrom.c:133, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_CC01R4"
|
||||
source_ref: "source atari800/src/sysrom.c:98, source atari800/src/sysrom.c:133, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:133, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-xl-os-ver-3.rom"
|
||||
found_by: content
|
||||
path: "atari-xl-os-ver-3.rom"
|
||||
aliases: [ROM_OS_BB01R3]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 16384
|
||||
@@ -288,9 +304,11 @@ files:
|
||||
16384 bytes whose CRC32 is 29f133f7 is taken for this slot.
|
||||
ROM_OS_BB01R3 is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:99, source atari800/src/sysrom.c:134, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_BB01R3"
|
||||
source_ref: "source atari800/src/sysrom.c:99, source atari800/src/sysrom.c:134, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:134, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "ROM_OS_BB01R59"
|
||||
found_by: content
|
||||
path: "ROM_OS_BB01R59"
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -303,9 +321,11 @@ files:
|
||||
16384 bytes whose CRC32 is 45f47988 is taken for this slot.
|
||||
The name is the configuration key this ROM is stored under in
|
||||
.atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:101, source atari800/src/sysrom.c:136, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_BB01R59"
|
||||
source_ref: "source atari800/src/sysrom.c:101, source atari800/src/sysrom.c:136, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:136, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "ROM_OS_BB01R59A"
|
||||
found_by: content
|
||||
path: "ROM_OS_BB01R59A"
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -318,11 +338,12 @@ files:
|
||||
16384 bytes whose CRC32 is f0a236d3 is taken for this slot.
|
||||
The name is the configuration key this ROM is stored under in
|
||||
.atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:102, source atari800/src/sysrom.c:137, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_OS_BB01R59A"
|
||||
source_ref: "source atari800/src/sysrom.c:102, source atari800/src/sysrom.c:137, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:137, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-basic-rev-a.rom"
|
||||
found_by: content
|
||||
path: "atari-basic-rev-a.rom"
|
||||
aliases: [ROM_BASIC_A]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 8192
|
||||
@@ -334,11 +355,12 @@ files:
|
||||
8192 bytes whose CRC32 is 4bec4de2 is taken for this slot.
|
||||
ROM_BASIC_A is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:105, source atari800/src/sysrom.c:140, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_BASIC_A"
|
||||
source_ref: "source atari800/src/sysrom.c:105, source atari800/src/sysrom.c:140, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:140, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
- name: "atari-basic-rev-b.rom"
|
||||
found_by: content
|
||||
path: "atari-basic-rev-b.rom"
|
||||
aliases: [ROM_BASIC_B]
|
||||
required: false
|
||||
hle_fallback: true
|
||||
size: 8192
|
||||
@@ -350,7 +372,8 @@ files:
|
||||
8192 bytes whose CRC32 is f0202fb3 is taken for this slot.
|
||||
ROM_BASIC_B is the configuration key this ROM is stored under
|
||||
in .atari800.cfg.
|
||||
source_ref: "source atari800/src/sysrom.c:106, source atari800/src/sysrom.c:141, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537"
|
||||
config_key: "ROM_BASIC_B"
|
||||
source_ref: "source atari800/src/sysrom.c:106, source atari800/src/sysrom.c:141, source atari800/src/sysrom.c:317-427, source atari800/src/atari.c:537, source atari800/src/sysrom.c:141, source atari800/src/sysrom.c:616-623"
|
||||
|
||||
# Known ROM revisions from sysrom.c (CRC32 identifiers):
|
||||
#
|
||||
|
||||
@@ -283,3 +283,10 @@ files:
|
||||
Any .SF2 or .SF3 in the system directory is listed in the MIDI option.
|
||||
DOSBOX.SF2 is the fixed name looked up on the mounted C: drive as a per
|
||||
game override.
|
||||
|
||||
- name: "Roland_SC-88.sf2"
|
||||
path: "system/Roland_SC-88.sf2"
|
||||
description: "General MIDI SoundFont under a Roland SC-88 name"
|
||||
required: false
|
||||
unsourceable: "user supplied, no canonical file: the system directory scan lists any SoundFont by its own name"
|
||||
source_ref: "upstream dosbox_pure_libretro.cpp:1380-1412"
|
||||
@@ -696,6 +696,13 @@ files:
|
||||
name, and gets its own chorus and reverb parameters in auto mode
|
||||
source_ref: "src/midi/fluidsynth.cpp:194-230, src/midi/fluidsynth.cpp:802-808, src/midi/fluidsynth.cpp:430-434, src/midi/fluidsynth.cpp:573-577, src/midi/fluidsynth.cpp:962-987"
|
||||
|
||||
- name: "Roland_SC-88.sf2"
|
||||
path: "soundfonts/Roland_SC-88.sf2"
|
||||
description: "SoundFont under a Roland SC-88 name"
|
||||
required: false
|
||||
unsourceable: "user supplied, no canonical file: the soundfont setting opens any SoundFont it names"
|
||||
source_ref: "src/midi/fluidsynth.cpp:194-230"
|
||||
|
||||
- name: "FluidR3_GM.sf2"
|
||||
path: "soundfonts/FluidR3_GM.sf2"
|
||||
description: "Fluid R3 GM SoundFont by Frank Wen"
|
||||
|
||||
+2
-1
@@ -73,7 +73,8 @@ files:
|
||||
min_size: 4194304
|
||||
max_size: 8388608
|
||||
validation: [size]
|
||||
source_ref: "source pcsx2/ps2/BiosTools.cpp:32-33, 64-187, 257-289, 349-415"
|
||||
config_key: "pcsx2_bios"
|
||||
source_ref: "source pcsx2/ps2/BiosTools.cpp:32-33, 64-187, 257-289, 349-415, source libretro/main.cpp:525-536"
|
||||
note: >
|
||||
Scans pcsx2/bios/ for any file between 4 MB and 8 MB. Validates via romdir
|
||||
structure parsing (RESET + ROMVER entries). User selects BIOS via core option
|
||||
|
||||
@@ -329,3 +329,41 @@ files:
|
||||
description: "Philips VG 8020 MSX1 BIOS and BASIC ROM (also used by AVT DPC-200, Goldstar FC-200, Toshiba HX-20E, HX-22I, HX-51I)"
|
||||
validation: [sha1]
|
||||
source_ref: "share/machines/Philips_VG_8020.xml:53-54"
|
||||
|
||||
- name: svi-738_basic-bios1.rom
|
||||
path: "openmsx/share/systemroms/svi-738_basic-bios1.rom"
|
||||
sha1: c53b3f2c00f31683914f7452f3f4d94ae2929c0d
|
||||
required: false
|
||||
size: 32768
|
||||
description: "Spectravideo SVI-738 MSX1 BIOS and BASIC ROM"
|
||||
validation: [sha1]
|
||||
source_ref: "share/machines/Spectravideo_SVI-738.xml:53-54"
|
||||
|
||||
- name: svi-738_se_basic-bios1.rom
|
||||
path: "openmsx/share/systemroms/svi-738_se_basic-bios1.rom"
|
||||
sha1: 87f4d0fa58cfe9cef818a3185df2735e6da6168c
|
||||
required: false
|
||||
size: 32768
|
||||
description: "Spectravideo SVI-738 (Sweden) MSX1 BIOS and BASIC ROM"
|
||||
validation: [sha1]
|
||||
source_ref: "share/machines/Spectravideo_SVI-738_SE.xml:53-54"
|
||||
|
||||
- name: svi-738_rs232.rom
|
||||
path: "openmsx/share/systemroms/svi-738_rs232.rom"
|
||||
sha1: 4e9384c9d137f0ab65ffc5a78f04cd8c9df6c8b7
|
||||
required: false
|
||||
size: 8192
|
||||
description: "Spectravideo SVI-738 RS-232 interface ROM"
|
||||
validation: [sha1]
|
||||
source_ref: "share/machines/Spectravideo_SVI-738.xml:76-77, share/machines/Spectravideo_SVI-738_SE.xml:76-77"
|
||||
|
||||
- name: svi-738_disk.rom
|
||||
path: "openmsx/share/systemroms/svi-738_disk.rom"
|
||||
sha1:
|
||||
- 99a40266bc296cef1d432cb0caa8df1a7e570be4
|
||||
- 55d5d1fd57d35384b821af62083f2a23d85580e6
|
||||
- 465fab904a22b3e29f0c00daaf326dc4a6862088
|
||||
required: false
|
||||
description: "Spectravideo SVI-738 disk controller ROM"
|
||||
validation: [sha1]
|
||||
source_ref: "share/machines/Spectravideo_SVI-738.xml:90-93, share/machines/Spectravideo_SVI-738_SE.xml:90-93"
|
||||
@@ -35,6 +35,20 @@ files:
|
||||
source_ref: "pcsx2/ps2/BiosTools.cpp:16-17,80-197,258-283,317-370"
|
||||
note: "Accepts any file 4-8 MB with valid romdir (RESET + ROMVER). Naming convention ps2-VVVVr-YYYYMMDD.bin (version, region, date)."
|
||||
|
||||
- name: ps3_ps2_emu_bios.bin
|
||||
found_by: content
|
||||
required: false
|
||||
size: 4194304
|
||||
sha1: "2dc921be6eb8d17e276cd4bbfde86343452073e0"
|
||||
md5: "ca27dd917b4be56a229dd1fabb0c07da"
|
||||
source_ref: "pcsx2/ps2/BiosTools.cpp:16-17,80-197,258-283,317-370"
|
||||
note: >
|
||||
ROMVER 0220JD20121227, the PS2 BIOS the PS3's ps2_emu carries. Cut from
|
||||
dev_flash/ps2emu/ps2_emu.self of PS3 system software 4.90, decrypted by
|
||||
RPCS3, from 0x12F bytes before "compatible mode" to 0x262 bytes after
|
||||
"Parity error" and padded to 4 MiB, as firmware_bios_claim release 2
|
||||
does. Accepted like any image with a valid romdir.
|
||||
|
||||
- name: ps2-0230a-20080220.rom1
|
||||
aliases: [SCPH-70004_BIOS_V12_EUR_200.ROM1]
|
||||
required: false
|
||||
|
||||
@@ -15,6 +15,9 @@ cores:
|
||||
- sdl2trs
|
||||
- sdltrs
|
||||
- "sdltrs-model1"
|
||||
- "sdltrs-model3"
|
||||
- "sdltrs-model4"
|
||||
- "sdltrs-model4p"
|
||||
systems:
|
||||
- trs80
|
||||
mode: standalone
|
||||
@@ -68,6 +71,7 @@ files:
|
||||
description: "TRS-80 Model I ROM"
|
||||
required: true
|
||||
max_size: 18432
|
||||
config_key: "romfile1"
|
||||
source_ref: "src/trs_options.c:81 (romfile1), src/trs_options.c:867 (default name), src/trs_cmd_rom.c:871-884 (trs_model 1)"
|
||||
note: >
|
||||
Model I is the model a stock configuration selects (src/trs_options.c:900), so
|
||||
@@ -80,6 +84,7 @@ files:
|
||||
description: "TRS-80 Model III and Model 4 ROM"
|
||||
required: true
|
||||
max_size: 18432
|
||||
config_key: "romfile3"
|
||||
source_ref: "src/trs_options.c:82 (romfile3), src/trs_options.c:868 (default name), src/trs_cmd_rom.c:885-889 (trs_model 3 and 4)"
|
||||
note: >
|
||||
Serves Model III and Model 4 alike. The stub text spells out that Model 4
|
||||
@@ -94,6 +99,7 @@ files:
|
||||
description: "TRS-80 Model 4P boot ROM"
|
||||
required: false
|
||||
max_size: 18432
|
||||
config_key: "romfile4p"
|
||||
source_ref: "src/trs_options.c:83 (romfile4p), src/trs_options.c:869 (default name), src/trs_cmd_rom.c:890-893 (trs_model 5)"
|
||||
note: >
|
||||
Optional because the compiled-in replacement is a working boot ROM rather
|
||||
|
||||
@@ -145,14 +145,23 @@ files:
|
||||
- name: relay_on.wav
|
||||
description: "Cassette relay on sound"
|
||||
required: false
|
||||
sha1: "85c43404f3f701e87f5c3b30bb2624465feb537c"
|
||||
md5: "6233f2d067d775cd7a5951e7f56044c7"
|
||||
source_ref: "linux-sdl/sdl/api_snd2.cpp:155-157, 213-267, 660"
|
||||
note: "Hashes of the copy in Win32/ of the XM7 V3.4L77SX+z09 final release archive (xm7_3477sxz09.zip, PI. and Ryu Takegami, retropc.net/ryu/xm7), dated 2003-01-23."
|
||||
|
||||
- name: relayoff.wav
|
||||
description: "Cassette relay off sound"
|
||||
required: false
|
||||
sha1: "ab06b4ce5ab88da51a6d0223dfcf7402e83cf965"
|
||||
md5: "58f696bffef634819e0769a5c6e7c95f"
|
||||
source_ref: "linux-sdl/sdl/api_snd2.cpp:155-158, 213-267, 660"
|
||||
note: "Hashes of the copy in Win32/ of the XM7 V3.4L77SX+z09 final release archive (xm7_3477sxz09.zip, PI. and Ryu Takegami, retropc.net/ryu/xm7), dated 2003-01-23."
|
||||
|
||||
- name: fddseek.wav
|
||||
description: "Floppy drive seek sound"
|
||||
required: false
|
||||
sha1: "bb36a2980975f6c469a861d64dbfdaacbf8c7f00"
|
||||
md5: "b56fa2df7681a97190804f67f3e6900b"
|
||||
source_ref: "linux-sdl/sdl/api_snd2.cpp:155-159, 213-267, 660"
|
||||
note: "Hashes of the copy in Win32/ of the XM7 V3.4L77SX+z09 final release archive (xm7_3477sxz09.zip, PI. and Ryu Takegami, retropc.net/ryu/xm7), dated 2003-01-23."
|
||||
@@ -3581,6 +3581,50 @@ def declared_root(config: dict) -> str:
|
||||
return root if count / len(roots) > 0.9 else ""
|
||||
|
||||
|
||||
def platform_declared_contents(config: dict, db: dict) -> dict[str, set[str]]:
|
||||
"""The folders each declared file's content sits in, keyed by its hashes.
|
||||
|
||||
A core that scans a folder and identifies a ROM by its checksum reads a
|
||||
declared file whatever its name: RetroDECK lists atari800's Atari BASIC
|
||||
Rev A as ROM_BASIC_A, and the core takes it by CRC32. Keys are
|
||||
"md5:", "sha1:" and "crc32:" values of the database file the
|
||||
declaration resolves to, each with the declared slot's folder.
|
||||
"""
|
||||
prefix = declared_root(config).lower()
|
||||
by_md5 = db.get("indexes", {}).get("by_md5", {})
|
||||
files_db = db.get("files", {})
|
||||
contents: dict[str, set[str]] = {}
|
||||
for system in config.get("systems", {}).values():
|
||||
for fe in system.get("files", []):
|
||||
if fe.get("zipped_file"):
|
||||
continue
|
||||
record = files_db.get((fe.get("sha1") or "").lower())
|
||||
md5 = (fe.get("md5") or "").lower()
|
||||
if record is None and md5 and "," not in md5:
|
||||
sha1 = by_md5.get(md5, "")
|
||||
record = files_db.get(sha1[0] if isinstance(sha1, list) else sha1)
|
||||
if not record:
|
||||
continue
|
||||
slot = sanitize_pack_path(fe.get("destination") or fe.get("name", "")).lower()
|
||||
if prefix and slot.startswith(prefix + "/"):
|
||||
slot = slot[len(prefix) + 1:]
|
||||
folder = slot.rpartition("/")[0]
|
||||
for field in ("md5", "sha1", "crc32"):
|
||||
value = str(record.get(field) or "").lower()
|
||||
if value:
|
||||
contents.setdefault(f"{field}:{value}", set()).add(folder)
|
||||
return contents
|
||||
|
||||
|
||||
def merged_platform_declared_contents(configs: list[dict], db: dict) -> dict[str, set[str]]:
|
||||
"""`platform_declared_contents` of several platforms, one index."""
|
||||
merged: dict[str, set[str]] = {}
|
||||
for config in configs:
|
||||
for key, folders in platform_declared_contents(config, db).items():
|
||||
merged.setdefault(key, set()).update(folders)
|
||||
return merged
|
||||
|
||||
|
||||
def merged_platform_declarations(
|
||||
configs: list[dict], db: dict
|
||||
) -> dict[str, list[tuple[int | None, str]]]:
|
||||
|
||||
+106
-4
@@ -35,6 +35,7 @@ from common import (
|
||||
get_mame_clone_map,
|
||||
list_emulator_profiles,
|
||||
list_registered_platforms,
|
||||
merged_platform_declared_contents,
|
||||
load_data_dir_registry,
|
||||
load_database,
|
||||
load_emulator_profiles,
|
||||
@@ -50,7 +51,17 @@ from common import (
|
||||
select_emulator_profiles,
|
||||
)
|
||||
from hashing import parse_hash_list
|
||||
from launchers import LauncherLayer, declared_destinations, held_record
|
||||
from launchers import (
|
||||
LauncherLayer,
|
||||
catalogued_model_files,
|
||||
declared_destinations,
|
||||
held_record,
|
||||
name_settings,
|
||||
set_by,
|
||||
setting_readers,
|
||||
suffixed_stem,
|
||||
)
|
||||
from launchers import _directories as launcher_directories
|
||||
from launchers import _names as launcher_names
|
||||
from validation import (
|
||||
case_folded_slots,
|
||||
@@ -857,7 +868,8 @@ def _cross_reference_profile(
|
||||
# A platform declares files of its BIOS tree: none answers for one
|
||||
# the core reads below the save directory.
|
||||
in_platform = not save_root and f.get("root") != "roms" and declaration_settles(
|
||||
f, fname, platform_names, effective_path, index.get("folded_slots", frozenset())
|
||||
f, fname, platform_names, effective_path, index.get("folded_slots", frozenset()),
|
||||
index.get("declared_contents"),
|
||||
)
|
||||
|
||||
if in_platform:
|
||||
@@ -1119,8 +1131,11 @@ class _NameHolder:
|
||||
return self._cache[name]
|
||||
base = name.rsplit("/", 1)[-1]
|
||||
found: tuple[str, bool] | None = None
|
||||
stem = suffixed_stem(base)
|
||||
if base in self.by_name or any(map(self._entry_held, self.exact.get(base, []))):
|
||||
found = (base, True)
|
||||
elif stem is not None and any(map(self._entry_held, self.exact.get(stem, []))):
|
||||
found = (base, True)
|
||||
else:
|
||||
path, _status = resolve_local_file(
|
||||
{"name": name}, self.db, data_dir_registry=self.registry
|
||||
@@ -1155,6 +1170,16 @@ def launcher_reads_not_held(
|
||||
a copy is reported with `held_as`, since the launcher does not open it
|
||||
under the name it asks for. *emulator* keeps the records whose emulator
|
||||
name designates that profile.
|
||||
|
||||
Three records ask for nothing the collection lacks. A search keeps the
|
||||
first name it finds, so one held name fills it: RetroBat's Amiberry
|
||||
launcher returns the first of kick34005.A500, kick34005.A500.rom and
|
||||
amiga-os-130.rom that exists (Amiberry.Generator.cs:674-699). A copy
|
||||
whose source lies outside the BIOS directory brings a file the platform
|
||||
installs itself, from its own package or written by its own script
|
||||
(RetroPie's lr-vecx copies $md_inst/system.bin). A file handed to the
|
||||
setting a reader's profile entry is read from is that entry's file,
|
||||
which the pack places under the launcher's name.
|
||||
"""
|
||||
holder = _NameHolder(db, profiles, data_dir_registry)
|
||||
every_profile = set(profiles)
|
||||
@@ -1170,9 +1195,45 @@ def launcher_reads_not_held(
|
||||
for part in str(record.get("emulator", "")).split(",")
|
||||
for key in LauncherLayer._profiles_named(part.strip(), profiles, every_profile)
|
||||
})
|
||||
if not readers:
|
||||
# RetroDECK names its frontend and the core option names the core.
|
||||
readers = setting_readers(
|
||||
str(record.get("passes_to") or ""), profiles, every_profile
|
||||
)
|
||||
if emulator and emulator not in readers:
|
||||
continue
|
||||
folds = bool(record.get("case_insensitive") or config.get("case_insensitive_fs"))
|
||||
base = str(config.get("base_destination") or "bios")
|
||||
if record.get("kind") == "copies" and not launcher_directories(record, base):
|
||||
continue
|
||||
settings = name_settings(record, names)
|
||||
|
||||
def by_setting(name: str) -> bool:
|
||||
"""Whether the setting the name is written to reads a held file.
|
||||
|
||||
A placeholder read from the setting takes the held dump the
|
||||
catalogues name after the model the launcher's name spells.
|
||||
"""
|
||||
entries = [
|
||||
entry
|
||||
for key in readers
|
||||
for entry in profiles[key].get("files") or []
|
||||
if settings[name] and set_by(entry, settings[name])
|
||||
]
|
||||
return any(holder._entry_held(entry) for entry in entries) or any(
|
||||
"<" in str(entry.get("name", ""))
|
||||
and any(
|
||||
name_match_size_ok(entry, found.get("size"))
|
||||
for found in catalogued_model_files(name, db)
|
||||
)
|
||||
for entry in entries
|
||||
)
|
||||
|
||||
by_model = {name for name in names if by_setting(name)}
|
||||
if record.get("kind") == "names_searched" and any(
|
||||
(found := holder.held(name)) and (found[1] or folds) for name in names
|
||||
):
|
||||
continue
|
||||
reader = {
|
||||
"emulator": str(record.get("emulator", "")),
|
||||
"build": str(record.get("build", "")),
|
||||
@@ -1180,9 +1241,19 @@ def launcher_reads_not_held(
|
||||
"source_ref": str(record.get("source_ref", "")),
|
||||
"profiles": readers,
|
||||
}
|
||||
# A name a reader's entry declares unsourceable is no gap: its
|
||||
# row carries the reason and is counted apart.
|
||||
unsourceable = {
|
||||
str(n).rsplit("/", 1)[-1]: str(entry["unsourceable"])
|
||||
for key in readers
|
||||
for entry in profiles[key].get("files") or []
|
||||
if entry.get("unsourceable")
|
||||
for n in (entry.get("name"), *(entry.get("aliases") or []))
|
||||
if n
|
||||
}
|
||||
for name in names:
|
||||
found = holder.held(name)
|
||||
if found and (found[1] or folds):
|
||||
if found and (found[1] or folds) or name in by_model:
|
||||
continue
|
||||
key = name.casefold() if folds else name
|
||||
row = by_key.get(key)
|
||||
@@ -1195,6 +1266,9 @@ def launcher_reads_not_held(
|
||||
}
|
||||
if found:
|
||||
row["held_as"] = found[0]
|
||||
reason = unsourceable.get(name.rsplit("/", 1)[-1])
|
||||
if reason and "unsourceable" not in row:
|
||||
row["unsourceable"] = reason
|
||||
if reader["emulator"] not in row["emulators"]:
|
||||
row["emulators"].append(reader["emulator"])
|
||||
if reader not in row["readers"]:
|
||||
@@ -1204,7 +1278,13 @@ def launcher_reads_not_held(
|
||||
|
||||
|
||||
def print_launcher_reads(rows: list[dict]) -> None:
|
||||
"""The launcher reads gap category, after the profile gaps."""
|
||||
"""The launcher reads gap category, after the profile gaps.
|
||||
|
||||
A name its reader declares unsourceable is listed apart, with the
|
||||
reason: it is no file left to find.
|
||||
"""
|
||||
unsourceable = [r for r in rows if r.get("unsourceable")]
|
||||
rows = [r for r in rows if not r.get("unsourceable")]
|
||||
platforms = sorted({r["platform"] for r in rows})
|
||||
noun = "platform" if len(platforms) == 1 else "platforms"
|
||||
print(f"\nLauncher reads, not held: {len(rows)} names across {len(platforms)} {noun}")
|
||||
@@ -1218,6 +1298,19 @@ def print_launcher_reads(rows: list[dict]) -> None:
|
||||
f" {row['name']} [{', '.join(row['emulators'])}, {first['kind']}, "
|
||||
f"{first['source_ref']}]{more}{casing}"
|
||||
)
|
||||
if not unsourceable:
|
||||
return
|
||||
platforms = sorted({r["platform"] for r in unsourceable})
|
||||
noun = "platform" if len(platforms) == 1 else "platforms"
|
||||
print(
|
||||
f"\nLauncher reads, unsourceable: {len(unsourceable)} names "
|
||||
f"across {len(platforms)} {noun}"
|
||||
)
|
||||
for row in unsourceable:
|
||||
print(
|
||||
f" {row['platform']}: {row['name']} [{', '.join(row['emulators'])}, "
|
||||
f"{row['readers'][0]['source_ref']}]: {row['unsourceable']}"
|
||||
)
|
||||
|
||||
|
||||
def cross_reference(
|
||||
@@ -1231,6 +1324,7 @@ def cross_reference(
|
||||
folded_slots: frozenset[str] = frozenset(),
|
||||
platform: str = "",
|
||||
launcher_layer: LauncherLayer | None = None,
|
||||
declared_contents: dict[str, set[str]] | None = None,
|
||||
) -> dict:
|
||||
"""Compare emulator profiles against platform declarations.
|
||||
|
||||
@@ -1268,6 +1362,7 @@ def cross_reference(
|
||||
"data_names": data_names,
|
||||
"all_declared": all_declared,
|
||||
"folded_slots": folded_slots,
|
||||
"declared_contents": declared_contents,
|
||||
"bios_dir": db.get("bios_dir"),
|
||||
"launcher_candidates": [] if launcher_layer else None,
|
||||
}
|
||||
@@ -1474,6 +1569,13 @@ def main() -> None:
|
||||
all_declared=declared_names(args.platforms_dir, selected, db),
|
||||
standalone_cores=standalone_cores,
|
||||
folded_slots=folded_declared_slots(args.platforms_dir, selected, db),
|
||||
declared_contents=merged_platform_declared_contents(
|
||||
[
|
||||
load_platform_config(name, args.platforms_dir)
|
||||
for name in selected or list_registered_platforms(args.platforms_dir)
|
||||
],
|
||||
db,
|
||||
),
|
||||
platform=config.get("_key", args.platform) if args.platform else "",
|
||||
# What the platform's launchers open, as verify and the builder read it.
|
||||
launcher_layer=LauncherLayer(
|
||||
|
||||
+205
-6
@@ -65,6 +65,7 @@ class LauncherPlace:
|
||||
anchored: bool
|
||||
conditional: bool
|
||||
source_ref: str
|
||||
passes_to: str = ""
|
||||
|
||||
def fold(self, name: str) -> str:
|
||||
return name.lower() if self.case_insensitive else name
|
||||
@@ -87,6 +88,103 @@ class LauncherPlace:
|
||||
)
|
||||
|
||||
|
||||
def setting_tokens(passes_to: str) -> set[str]:
|
||||
"""The words of a record's ``passes_to``, as an emulator setting is spelled.
|
||||
|
||||
"command line -romfile4p" hands the file to sdltrs's romfile4p option,
|
||||
"settings.bml NeoGeoPocket/Firmware/BIOS.World" to an ares setting.
|
||||
"""
|
||||
return {
|
||||
word.strip("()\"',;").lstrip("-")
|
||||
for word in passes_to.split()
|
||||
} - {""}
|
||||
|
||||
|
||||
def suffixed_stem(name: str) -> str | None:
|
||||
"""The file name a launcher name carries before an extension it appended.
|
||||
|
||||
ROCKNIX's Amiberry config passes kick34005.A500.rom, the name Amiberry
|
||||
gives Kickstart 1.3 (amiberry_whdbooter.cpp:370) followed by ".rom". A
|
||||
stem that is no file name itself (scph1001 of scph1001.bin) is none.
|
||||
"""
|
||||
base = name.rsplit("/", 1)[-1]
|
||||
stem = base.rsplit(".", 1)[0]
|
||||
return stem if "." in stem else None
|
||||
|
||||
|
||||
_MODEL = re.compile(r"\b([A-Z]{2,5})-?(\d{3,6}[A-Z]?)\b")
|
||||
|
||||
|
||||
def catalogued_model_files(name: str, db: dict) -> list[dict]:
|
||||
"""Held files a dump catalogue describes as the model a launcher name spells.
|
||||
|
||||
RetroDECK sets LRPS2's pcsx2_bios option to scph10000.bin, a name no code
|
||||
hashes: the SCPH-10000 is the model whose BIOS it means. Redump and TOSEC
|
||||
describe two revisions for it. Primaries come before .variants copies,
|
||||
then the Redump name, which carries the version (ps2-0100j before
|
||||
ps2-0101j), then the No-Intro and TOSEC names.
|
||||
"""
|
||||
stem = name.rsplit("/", 1)[-1].rsplit(".", 1)[0].casefold()
|
||||
if not re.fullmatch(r"[a-z]{2,5}\d{3,6}[a-z]?", stem):
|
||||
return []
|
||||
found = []
|
||||
for record in db.get("files", {}).values():
|
||||
catalogues = record.get("provenance") or {}
|
||||
models = {
|
||||
(a + b).casefold()
|
||||
for entry in catalogues.values()
|
||||
for a, b in _MODEL.findall(str(entry.get("description") or ""))
|
||||
}
|
||||
if stem in models:
|
||||
names = [
|
||||
str((catalogues.get(source) or {}).get("name") or "")
|
||||
for source in ("redump", "no-intro", "tosec")
|
||||
]
|
||||
found.append(("/.variants/" in str(record.get("path", "")), names, record))
|
||||
# The core accepts every revision of the model, and neither priority nor
|
||||
# region separates two primaries. The pick must still be the same on
|
||||
# every run, so it goes to the original revision: the Redump name carries
|
||||
# the version, and ps2-0100j sorts before ps2-0101j.
|
||||
return [record for *_key, record in sorted(found, key=lambda f: (f[0], f[1]))]
|
||||
|
||||
|
||||
def name_settings(record: dict, names: list[str]) -> dict[str, str]:
|
||||
"""The setting each name of a record is written to.
|
||||
|
||||
A record naming several files of one config spells passes_to as
|
||||
describe_keys does (shell_launchers.py), "atari800.cfg ROM_OS_A_PAL,
|
||||
ROM_5200_A, ...", one key per name and in the order of the names. When
|
||||
the counts differ, each name keeps the whole description.
|
||||
"""
|
||||
passes_to = str(record.get("passes_to") or "")
|
||||
head, _, rest = passes_to.partition(" ")
|
||||
keys = [
|
||||
key.strip()
|
||||
for key in re.sub(r"\[[^\]]*\]", ",", rest).split(",")
|
||||
if key.strip()
|
||||
]
|
||||
if len(names) > 1 and len(keys) == len(names) and all(" " not in k for k in keys):
|
||||
return {name: f"{head} {key}" for name, key in zip(names, keys)}
|
||||
return {name: passes_to for name in names}
|
||||
|
||||
|
||||
def setting_readers(passes_to: str, profiles: dict, keys: Iterable[str]) -> list[str]:
|
||||
"""The profiles with an entry read from the setting a launcher writes."""
|
||||
if not passes_to:
|
||||
return []
|
||||
return sorted(
|
||||
key for key in keys
|
||||
if (profile := profiles.get(key)) is not None
|
||||
and any(set_by(entry, passes_to) for entry in profile.get("files") or [])
|
||||
)
|
||||
|
||||
|
||||
def set_by(entry: dict, passes_to: str) -> bool:
|
||||
"""Whether a launcher hands its file to the setting a profile entry is read from."""
|
||||
key = str(entry.get("config_key") or "")
|
||||
return bool(key) and key in setting_tokens(passes_to)
|
||||
|
||||
|
||||
def _bios_relative(directory: str, base: str) -> str | None:
|
||||
"""A launcher directory relative to the BIOS root, None when it is not one."""
|
||||
directory = directory.strip().rstrip("/")
|
||||
@@ -190,15 +288,21 @@ def launcher_places(config: dict) -> list[LauncherPlace]:
|
||||
"conditional": bool(record.get("depends_on_option")),
|
||||
"source_ref": str(record.get("source_ref", "")),
|
||||
}
|
||||
settings = name_settings(record, names)
|
||||
if kind == "names_searched":
|
||||
# Each directory in turn, every name in it.
|
||||
depth = len(directories) if anchored else 1
|
||||
ordered = tuple(paths_of(name)[i] for i in range(depth) for name in names)
|
||||
places.append(LauncherPlace(paths=ordered, **common))
|
||||
places.append(LauncherPlace(
|
||||
paths=ordered, passes_to=str(record.get("passes_to") or ""), **common
|
||||
))
|
||||
continue
|
||||
# A fixed name is the one file passed, and a core option offers
|
||||
# each value as the file the user picks: one place per name.
|
||||
places.extend(LauncherPlace(paths=paths_of(name), **common) for name in names)
|
||||
places.extend(
|
||||
LauncherPlace(paths=paths_of(name), passes_to=settings[name], **common)
|
||||
for name in names
|
||||
)
|
||||
return places
|
||||
|
||||
|
||||
@@ -551,6 +655,8 @@ class _Candidate:
|
||||
by_content: bool
|
||||
# Matched by the size the code checks, the entry naming no hash.
|
||||
by_shape: bool = False
|
||||
# Matched through the setting the launcher writes or the name it extends.
|
||||
by_setting_or_stem: bool = False
|
||||
|
||||
|
||||
class LauncherLayer:
|
||||
@@ -580,12 +686,30 @@ class LauncherLayer:
|
||||
self._by_name_folded.setdefault(name.lower(), []).extend(sha1s)
|
||||
self._files = db.get("files", {})
|
||||
self._owners: dict[tuple[str, bool], list[LauncherPlace]] = {}
|
||||
self._unoffered: dict[tuple[str, bool], list[tuple[dict, dict]]] = {}
|
||||
relevant = set(relevant)
|
||||
for place in self.places:
|
||||
standalone = place.build == "standalone"
|
||||
for emulator in (e.strip() for e in place.emulator.split(",")):
|
||||
for key in self._profiles_named(emulator, profiles, relevant):
|
||||
self._owners.setdefault((key, standalone), []).append(place)
|
||||
owners = {
|
||||
key
|
||||
for emulator in (e.strip() for e in place.emulator.split(","))
|
||||
for key in self._profiles_named(emulator, profiles, relevant)
|
||||
}
|
||||
# RetroDECK names its frontend, retroarch, and the core option it
|
||||
# writes, pcsx2_bios, names the core.
|
||||
if not owners:
|
||||
owners = set(setting_readers(place.passes_to, profiles, relevant))
|
||||
for key in sorted(owners):
|
||||
self._owners.setdefault((key, standalone), []).append(place)
|
||||
# The report never offers a placeholder, which stands for every
|
||||
# file a scan finds, nor an entry the platform's list settles
|
||||
# (AmberELEC declares kick34005.A500): the launcher still reads
|
||||
# its file under its own name.
|
||||
self._unoffered.setdefault((key, standalone), [
|
||||
(entry, _placeholder_report(key, profiles[key], entry))
|
||||
for entry in profiles[key].get("files") or []
|
||||
])
|
||||
self._db = db
|
||||
|
||||
@staticmethod
|
||||
def _profiles_named(name: str, profiles: dict, relevant: set[str]) -> list[str]:
|
||||
@@ -622,6 +746,17 @@ class LauncherLayer:
|
||||
names = own & basenames
|
||||
if names:
|
||||
return _Candidate(entry, names, False)
|
||||
# RetroPie runs sdl2trs with -romfile4p $biosdir/level4p.rom: the
|
||||
# file under that name is the one the romfile4p slot reads.
|
||||
if set_by(entry, place.passes_to):
|
||||
return _Candidate(entry, basenames, False, by_setting_or_stem=True)
|
||||
if place.kind == "fixed_name":
|
||||
stems = {
|
||||
base for base in basenames
|
||||
if (stem := suffixed_stem(base)) is not None and place.fold(stem) in own
|
||||
}
|
||||
if stems:
|
||||
return _Candidate(entry, stems, False, by_setting_or_stem=True)
|
||||
content = {
|
||||
place.fold(path.rsplit("/", 1)[-1])
|
||||
for path in place.paths
|
||||
@@ -686,13 +821,26 @@ class LauncherLayer:
|
||||
by_layout: dict[tuple[str, bool], list[tuple[dict, dict]]] = {}
|
||||
for emulator, standalone, entry, report in candidates:
|
||||
by_layout.setdefault((emulator, standalone), []).append((entry, report))
|
||||
offered = {id(entry) for _e, _s, entry, _r in candidates}
|
||||
for layout, members in self._unoffered.items():
|
||||
for entry, report in members:
|
||||
if id(entry) in offered:
|
||||
continue
|
||||
if "<" not in str(entry.get("name", "")):
|
||||
report["in_repo"] = resolve_held(report) is not None
|
||||
report["unoffered"] = True
|
||||
by_layout.setdefault(layout, []).append((entry, report))
|
||||
placed: set[str] = set()
|
||||
for (emulator, standalone), members in sorted(by_layout.items()):
|
||||
for place in self.places_for(emulator, standalone):
|
||||
# An entry the report left out answers only through the
|
||||
# setting or the extended name: by its own name it was left
|
||||
# out for a reason (a region variant, a settled duplicate).
|
||||
matched = [
|
||||
(candidate, report)
|
||||
for entry, report in members
|
||||
if (candidate := self.match(place, entry)) is not None
|
||||
and (candidate.by_setting_or_stem or not report.get("unoffered"))
|
||||
]
|
||||
# A size names one entry only when no other of the core's
|
||||
# entries takes that size too.
|
||||
@@ -745,7 +893,31 @@ class LauncherLayer:
|
||||
):
|
||||
return True
|
||||
if not place.anchored:
|
||||
continue
|
||||
# A setting holds a name the core resolves in the directory
|
||||
# of the entry read from it: LRPS2 joins pcsx2_bios under
|
||||
# pcsx2/bios.
|
||||
setting = [
|
||||
(candidate, report) for candidate, report in matched
|
||||
if set_by(candidate.entry, place.passes_to)
|
||||
]
|
||||
directory = next(
|
||||
(
|
||||
str(c.entry.get("path") or "").rpartition("/")[0]
|
||||
for c, _report in setting
|
||||
if "/" in str(c.entry.get("path") or "")
|
||||
),
|
||||
None,
|
||||
)
|
||||
if directory is None:
|
||||
continue
|
||||
path = f"{directory}/{name}"
|
||||
if place.fold(path) in folded_reported:
|
||||
return True
|
||||
source = self._content_for(place, name, key, setting, resolve_held)
|
||||
if source is None or place.fold(path) in placed:
|
||||
continue
|
||||
placed.add(place.fold(path))
|
||||
return _launcher_entry(source[0], name, path, source[1], place)
|
||||
# The emulator as this platform installs it brings the file: the
|
||||
# place is filled, nothing is packed (ROCKNIX's xemu hdd image).
|
||||
if any(key in candidate.names and report.get("bundled")
|
||||
@@ -794,9 +966,36 @@ class LauncherLayer:
|
||||
record = resolve_held(report)
|
||||
if record is not None:
|
||||
return report, record
|
||||
for candidate, report in matched:
|
||||
if key not in candidate.names or not set_by(candidate.entry, place.passes_to):
|
||||
continue
|
||||
for record in catalogued_model_files(name, self._db):
|
||||
if name_match_size_ok(candidate.entry, record.get("size")):
|
||||
return report, record
|
||||
return None
|
||||
|
||||
|
||||
def _placeholder_report(key: str, profile: dict, entry: dict) -> dict:
|
||||
"""The report entry of an entry the gap report never builds."""
|
||||
identity = {
|
||||
field: entry[field]
|
||||
for field in ("aliases", "md5", "sha1", "sha256", "crc32", "size", "min_size", "max_size")
|
||||
if entry.get(field) is not None
|
||||
}
|
||||
return {
|
||||
**identity,
|
||||
"profile": key,
|
||||
"emulator": profile.get("emulator", key),
|
||||
"name": entry.get("name", ""),
|
||||
"path": entry.get("path") or entry.get("name", ""),
|
||||
"system": entry.get("system"),
|
||||
"systems": profile.get("systems"),
|
||||
"required": entry.get("required", False),
|
||||
"category": entry.get("category"),
|
||||
"in_repo": False,
|
||||
}
|
||||
|
||||
|
||||
def _launcher_entry(
|
||||
report: dict, name: str, path: str, record: dict, place: LauncherPlace
|
||||
) -> dict:
|
||||
|
||||
@@ -606,9 +606,15 @@ def declaration_settles(
|
||||
declared_names: Mapping[str, list[tuple[int | None, str]]] | set[str],
|
||||
dest: str = "",
|
||||
folded_slots: frozenset[str] = frozenset(),
|
||||
declared_contents: Mapping[str, set[str]] | None = None,
|
||||
) -> bool:
|
||||
"""Whether a platform declaration meets a core's requirement.
|
||||
|
||||
An entry the core finds by content (``found_by: content`` on the entry)
|
||||
is met by any declaration of a file it accepts by hash, in the folder it
|
||||
scans: atari800 takes RetroDECK's ROM_BASIC_A by its CRC32, so its own
|
||||
label for that ROM is not one more file to ship.
|
||||
|
||||
A platform declaring the name the core reads has met the requirement
|
||||
where the declaration fills the entry's own slot, whose content the slot
|
||||
arbitration decides, or elsewhere at a size the core accepts: the builder
|
||||
@@ -630,6 +636,13 @@ def declaration_settles(
|
||||
return True
|
||||
slot = sanitize_pack_path(dest or fname).lower()
|
||||
directory = slot if dest.endswith("/") else slot.rpartition("/")[0]
|
||||
if declared_contents and file_entry.get("found_by") == "content":
|
||||
for field in ("md5", "sha1", "crc32"):
|
||||
values = file_entry.get(field) or []
|
||||
for value in values if isinstance(values, list) else str(values).split(","):
|
||||
folders = declared_contents.get(f"{field}:{str(value).strip().lower()}")
|
||||
if folders and directory in folders:
|
||||
return True
|
||||
if not dest.endswith("/") and slot in folded_slots:
|
||||
return True
|
||||
for name in (fname, *file_entry.get("aliases", [])):
|
||||
|
||||
+14
-5
@@ -60,6 +60,7 @@ from common import (
|
||||
compute_hashes,
|
||||
expand_directory_entries,
|
||||
platform_declarations,
|
||||
platform_declared_contents,
|
||||
group_identical_platforms,
|
||||
list_emulator_profiles,
|
||||
list_system_ids,
|
||||
@@ -454,6 +455,7 @@ def _candidate_verdict(
|
||||
declared_names: Mapping[str, list[tuple[int | None, str]]] | set[str],
|
||||
dest: str = "",
|
||||
folded_slots: frozenset[str] = frozenset(),
|
||||
declared_contents: Mapping[str, set[str]] | None = None,
|
||||
) -> str:
|
||||
"""Whether a profile entry can be a gap, and whether it is settled.
|
||||
|
||||
@@ -469,7 +471,7 @@ def _candidate_verdict(
|
||||
if outside_gap_scope(file_entry, is_standalone):
|
||||
return "skip"
|
||||
if not include_all and declaration_settles(
|
||||
file_entry, fname, declared_names, dest, folded_slots
|
||||
file_entry, fname, declared_names, dest, folded_slots, declared_contents
|
||||
):
|
||||
return "settled"
|
||||
return "keep"
|
||||
@@ -503,6 +505,7 @@ def find_undeclared_files(
|
||||
if declared_names is None:
|
||||
declared_names = platform_declarations(config, db)
|
||||
folded_slots = case_folded_slots(config, declared_names)
|
||||
declared_contents = platform_declared_contents(config, db)
|
||||
|
||||
# Whether the builder drops a file whose local copy contradicts its
|
||||
# declared hash, which decides if such a copy counts as held here.
|
||||
@@ -608,6 +611,7 @@ def find_undeclared_files(
|
||||
f, fname, is_standalone, include_all,
|
||||
{} if save_root or f.get("root") == "roms" else declared_names,
|
||||
dest, folded_slots,
|
||||
None if save_root or f.get("root") == "roms" else declared_contents,
|
||||
)
|
||||
if verdict == "settled":
|
||||
seen_files.add(seen_key)
|
||||
@@ -1986,13 +1990,18 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
|
||||
|
||||
def _print_launcher_reads(result: dict, verbose: bool) -> None:
|
||||
"""Names the platform's launch code reads that the collection lacks."""
|
||||
rows = result.get("launcher_reads_not_held") or []
|
||||
if not rows:
|
||||
return
|
||||
every = result.get("launcher_reads_not_held") or []
|
||||
rows = [r for r in every if not r.get("unsourceable")]
|
||||
unsourceable = [r for r in every if r.get("unsourceable")]
|
||||
listed = "" if verbose else " (--verbose lists them)"
|
||||
print(f" Launcher reads, not held: {len(rows)}{listed}")
|
||||
if rows:
|
||||
print(f" Launcher reads, not held: {len(rows)}{listed}")
|
||||
if unsourceable:
|
||||
print(f" Launcher reads, unsourceable: {len(unsourceable)}{listed}")
|
||||
if not verbose:
|
||||
return
|
||||
for row in unsourceable:
|
||||
print(f" {row['name']} [{', '.join(row['emulators'])}]: {row['unsourceable']}")
|
||||
for row in rows:
|
||||
kinds = ", ".join(sorted({r["kind"] for r in row["readers"]}))
|
||||
casing = f", held as {row['held_as']}" if row.get("held_as") else ""
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
"""A platform declaration that a content-found core entry accepts by hash.
|
||||
|
||||
atari800 identifies its ROMs by CRC32 in the folder it scans. RetroDECK
|
||||
lists Atari BASIC Rev A as ROM_BASIC_A, a name atari800 never opens, and
|
||||
the profile answered it with a false alias. Settled by content instead, the
|
||||
declared file meets the entry and the label is not shipped a second time.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))
|
||||
|
||||
from common import platform_declared_contents # noqa: E402
|
||||
from validation import declaration_settles # noqa: E402
|
||||
|
||||
SHA1 = "70cdf57469a208528f78a14275837352e90e20f1"
|
||||
DB = {
|
||||
"files": {SHA1: {"path": "bios/Atari/ROM_BASIC_A", "name": "ROM_BASIC_A", "sha1": SHA1,
|
||||
"md5": "a4dc52536d526ecc51ea857b9fa2b90f", "crc32": "4bec4de2",
|
||||
"size": 8192}},
|
||||
"indexes": {"by_md5": {"a4dc52536d526ecc51ea857b9fa2b90f": SHA1}},
|
||||
}
|
||||
CONFIG = {
|
||||
"base_destination": "",
|
||||
"systems": {"atari800": {"files": [
|
||||
{"name": "ROM_BASIC_A", "destination": "bios/ROM_BASIC_A",
|
||||
"md5": "a4dc52536d526ecc51ea857b9fa2b90f"},
|
||||
]}},
|
||||
}
|
||||
ENTRY = {"name": "atari-basic-rev-a.rom", "found_by": "content", "crc32": "4bec4de2"}
|
||||
|
||||
|
||||
class ContentDeclarationTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.contents = platform_declared_contents(CONFIG, DB)
|
||||
|
||||
def test_the_declared_file_is_indexed_by_each_hash(self) -> None:
|
||||
self.assertEqual(self.contents["crc32:4bec4de2"], {""})
|
||||
self.assertEqual(self.contents[f"sha1:{SHA1}"], {""})
|
||||
|
||||
def test_a_content_found_entry_is_met_by_its_hash(self) -> None:
|
||||
self.assertTrue(declaration_settles(
|
||||
ENTRY, ENTRY["name"], {}, ENTRY["name"], declared_contents=self.contents,
|
||||
))
|
||||
|
||||
def test_an_entry_opened_by_name_is_not(self) -> None:
|
||||
entry = {key: value for key, value in ENTRY.items() if key != "found_by"}
|
||||
self.assertFalse(declaration_settles(
|
||||
entry, entry["name"], {}, entry["name"], declared_contents=self.contents,
|
||||
))
|
||||
|
||||
def test_another_folder_is_not_the_one_scanned(self) -> None:
|
||||
self.assertFalse(declaration_settles(
|
||||
ENTRY, ENTRY["name"], {}, "atari800/" + ENTRY["name"],
|
||||
declared_contents=self.contents,
|
||||
))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -66,8 +66,15 @@ LAUNCHERS = [
|
||||
_record("diremu", "passes_path", []),
|
||||
{"emulator": "pkg", "build": "standalone", "kind": "package", "names": [],
|
||||
"source_ref": "pkg.sh:1"},
|
||||
_record("missemu", "names_searched", ["held.bin", "absent.bin"]),
|
||||
_record("missemu", "names_searched", ["absent.bin"]),
|
||||
_record("otheremu", "copies", ["absent.bin"]),
|
||||
_record("altemu", "names_searched", ["alt.bin", "held.bin", "late.bin"]),
|
||||
_record("pkgemu", "copies", ["shipped.bin"], search_dir="$md_inst"),
|
||||
{"emulator": "pkgemu", "build": "standalone", "kind": "copies",
|
||||
"names": ["written.ini"], "source_ref": "pkg.sh:2"},
|
||||
_record("setemu", "fixed_name", ["setname.bin"], passes_to="command line -romslot"),
|
||||
_record("aliasemu", "fixed_name", ["alias.bin.rom"]),
|
||||
_record("setemu", "copies", ["user.sf2"]),
|
||||
_record("caseemu", "fixed_name", ["mixed.rom"]),
|
||||
_record("foldemu", "fixed_name", ["MIXED.rom"], case_insensitive=True),
|
||||
_record("labelemu", "core_option", ["labelled.rom (CDZ)"]),
|
||||
@@ -128,6 +135,12 @@ class LauncherGapTest(unittest.TestCase):
|
||||
"emulator": "AliasEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "core.bin", "aliases": ["alias.bin"], "required": True}],
|
||||
},
|
||||
"setemu": {
|
||||
"emulator": "SetEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "core.bin", "config_key": "romslot", "required": True},
|
||||
{"name": "user.sf2", "required": False,
|
||||
"unsourceable": "user supplied, no canonical file"}],
|
||||
},
|
||||
"missemu": {
|
||||
"emulator": "MissEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "absent.bin", "required": True, "md5": "0" * 32}],
|
||||
@@ -167,6 +180,39 @@ class LauncherGapTest(unittest.TestCase):
|
||||
reported = {r["emulators"][0] for r in self._rows().values()}
|
||||
self.assertFalse(reported & {"tplemu", "diremu", "pkg"})
|
||||
|
||||
def test_a_search_with_one_held_name_reads_nothing_missing(self) -> None:
|
||||
"""The launcher keeps the first name it finds, so the held one fills it."""
|
||||
names = {name for _, name in self._rows()}
|
||||
self.assertFalse(names & {"alt.bin", "late.bin"})
|
||||
|
||||
def test_a_copy_from_the_platform_package_is_not_owed(self) -> None:
|
||||
"""RetroPie copies lr-vecx's system.bin from $md_inst and writes mame.ini."""
|
||||
names = {name for _, name in self._rows()}
|
||||
self.assertFalse(names & {"shipped.bin", "written.ini"})
|
||||
|
||||
def test_a_name_with_an_appended_extension_is_held(self) -> None:
|
||||
"""ROCKNIX's kick34005.A500.rom is Amiberry's kick34005.A500."""
|
||||
self.assertNotIn("alias.bin.rom", {name for _, name in self._rows()})
|
||||
|
||||
def test_a_name_its_reader_declares_unsourceable_is_counted_apart(self) -> None:
|
||||
"""RetroBat copies any SoundFont saved as Roland_SC-88.sf2: not a
|
||||
file to find, yet never dropped silently."""
|
||||
row = self._rows()[("gaptest", "user.sf2")]
|
||||
self.assertEqual(row["unsourceable"], "user supplied, no canonical file")
|
||||
out = io.StringIO()
|
||||
with contextlib.redirect_stdout(out):
|
||||
print_launcher_reads(list(self._rows().values()))
|
||||
text = out.getvalue()
|
||||
self.assertIn("Launcher reads, not held: 3 names", text)
|
||||
self.assertIn("Launcher reads, unsourceable: 1 names across 1 platform", text)
|
||||
self.assertIn("gaptest: user.sf2 [setemu, gen/setemu.py:1]: user supplied, no canonical file",
|
||||
text)
|
||||
held_part = text.split("Launcher reads, unsourceable")[0]
|
||||
self.assertNotIn("user.sf2", held_part)
|
||||
|
||||
def test_a_name_handed_to_a_held_entry_setting_is_held(self) -> None:
|
||||
self.assertNotIn("setname.bin", {name for _, name in self._rows()})
|
||||
|
||||
def test_a_label_after_the_name_is_dropped(self) -> None:
|
||||
self.assertEqual(launcher_file_names(LAUNCHERS[-1]), ["labelled.rom"])
|
||||
self.assertIn(("gaptest", "labelled.rom"), self._rows())
|
||||
@@ -223,9 +269,9 @@ class LauncherGapTest(unittest.TestCase):
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
report = json.loads(result.stdout)
|
||||
names = {r["name"] for r in report[LAUNCHER_READS_KEY]}
|
||||
self.assertEqual(names, {"absent.bin", "mixed.rom", "labelled.rom"})
|
||||
self.assertEqual(names, {"absent.bin", "mixed.rom", "labelled.rom", "user.sf2"})
|
||||
# The emulator rows keep their own shape and counts.
|
||||
self.assertEqual(set(report) - {LAUNCHER_READS_KEY}, {"aliasemu", "missemu"})
|
||||
self.assertEqual(set(report) - {LAUNCHER_READS_KEY}, {"aliasemu", "missemu", "setemu"})
|
||||
|
||||
def test_verify_counts_and_exit_code_are_unchanged(self) -> None:
|
||||
"""A launcher name is reported, not judged: nothing else moves."""
|
||||
@@ -239,7 +285,8 @@ class LauncherGapTest(unittest.TestCase):
|
||||
)
|
||||
rows = with_rows.pop("launcher_reads_not_held")
|
||||
without.pop("launcher_reads_not_held")
|
||||
self.assertEqual({r["name"] for r in rows}, {"absent.bin", "mixed.rom", "labelled.rom"})
|
||||
self.assertEqual({r["name"] for r in rows},
|
||||
{"absent.bin", "mixed.rom", "labelled.rom", "user.sf2"})
|
||||
self.assertEqual(with_rows, without)
|
||||
|
||||
def exit_code(result: dict) -> int:
|
||||
|
||||
@@ -24,7 +24,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))
|
||||
import yaml # noqa: E402
|
||||
|
||||
from common import _emulator_profiles_cache, load_emulator_profiles, load_platform_config # noqa: E402
|
||||
from launchers import LauncherLayer, launcher_places # noqa: E402
|
||||
from launchers import LauncherLayer, launcher_places, suffixed_stem # noqa: E402
|
||||
from verify import find_undeclared_files, verify_platform # noqa: E402
|
||||
|
||||
CONTENT = {
|
||||
@@ -252,6 +252,108 @@ class LauncherLayerTest(unittest.TestCase):
|
||||
self.assertNotIn("core.bin", {u["name"] for u in self._report()})
|
||||
self.assertNotIn("core.bin", self._pack_names())
|
||||
|
||||
def test_a_file_handed_to_an_entry_setting_takes_the_entry_content(self) -> None:
|
||||
"""RetroPie runs sdl2trs with -romfile4p $biosdir/level4p.rom and
|
||||
EmuDeck writes a No-Intro name into ares's NeoGeoPocket firmware
|
||||
setting: neither name is the core's, and the held file of the entry
|
||||
that setting reads went in under no name at all."""
|
||||
profile = {
|
||||
"emulator": "FixEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "core.bin", "required": True, "config_key": "romslot"},
|
||||
{"name": "other.bin", "required": True, "config_key": "otherslot"}],
|
||||
}
|
||||
with open(os.path.join(self.emulators_dir, "fixemu.yml"), "w") as fh:
|
||||
yaml.dump(profile, fh)
|
||||
self.config["launchers"][2]["names"] = ["launcher.rom"]
|
||||
self.config["launchers"][2]["passes_to"] = "command line -romslot"
|
||||
_emulator_profiles_cache.clear()
|
||||
self.profiles = load_emulator_profiles(self.emulators_dir)
|
||||
added = {u["path"]: u for u in self._report() if u.get("launcher")}
|
||||
self.assertEqual(added["launcher.rom"]["launcher_of"], "core.bin")
|
||||
self.assertEqual(added["launcher.rom"]["md5"], _md5(CONTENT["core.bin"]))
|
||||
self.assertIn("launcher.rom", self._pack_names())
|
||||
|
||||
def test_a_fixed_name_with_an_appended_extension_takes_the_entry(self) -> None:
|
||||
"""ROCKNIX passes kick34005.A500.rom to Amiberry, which names
|
||||
Kickstart 1.3 kick34005.A500: the pack shipped nothing under it."""
|
||||
profile = {
|
||||
"emulator": "FixEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "core.bin", "aliases": ["kick.A500"], "required": True}],
|
||||
}
|
||||
with open(os.path.join(self.emulators_dir, "fixemu.yml"), "w") as fh:
|
||||
yaml.dump(profile, fh)
|
||||
self.config["launchers"][2]["names"] = ["kick.A500.rom"]
|
||||
_emulator_profiles_cache.clear()
|
||||
self.profiles = load_emulator_profiles(self.emulators_dir)
|
||||
added = {u["path"]: u for u in self._report() if u.get("launcher")}
|
||||
self.assertEqual(added["kick.A500.rom"]["md5"], _md5(CONTENT["core.bin"]))
|
||||
self.assertIsNone(suffixed_stem("scph1001.bin"))
|
||||
|
||||
def test_an_entry_the_platform_declares_still_fills_the_launcher_name(self) -> None:
|
||||
"""AmberELEC declares kick34005.A500, so the report never offers
|
||||
Amiberry's entry, and its config still passes kick34005.A500.rom."""
|
||||
profile = {
|
||||
"emulator": "FixEmu", "type": "standalone", "systems": ["test-sys"],
|
||||
"files": [{"name": "core.bin", "aliases": ["kick.A500"], "required": True}],
|
||||
}
|
||||
with open(os.path.join(self.emulators_dir, "fixemu.yml"), "w") as fh:
|
||||
yaml.dump(profile, fh)
|
||||
self.config["launchers"][2]["names"] = ["kick.A500.rom"]
|
||||
self.config["systems"]["test-sys"]["files"].append(
|
||||
{"name": "core.bin", "destination": "core.bin", "required": True}
|
||||
)
|
||||
_emulator_profiles_cache.clear()
|
||||
self.profiles = load_emulator_profiles(self.emulators_dir)
|
||||
added = {u["path"]: u for u in self._report() if u.get("launcher")}
|
||||
self.assertEqual(added["kick.A500.rom"]["md5"], _md5(CONTENT["core.bin"]))
|
||||
|
||||
def test_each_name_of_a_config_takes_its_own_key(self) -> None:
|
||||
"""AmberELEC's atari800.cfg names eight ROMs under eight keys, and
|
||||
one record describes them in order: 5200a.rom is ROM_5200_A's file,
|
||||
not every key's."""
|
||||
config = {"base_destination": "bios", "launchers": [{
|
||||
"emulator": "e", "build": "libretro", "kind": "fixed_name",
|
||||
"names": ["a.rom", "b.rom"], "search_dir": "/storage/roms/bios",
|
||||
"passes_to": "e.cfg ROM_A, ROM_B", "source_ref": "e.cfg:1",
|
||||
}]}
|
||||
places = {p.paths[0]: p.passes_to for p in launcher_places(config)}
|
||||
self.assertEqual(places, {"a.rom": "e.cfg ROM_A", "b.rom": "e.cfg ROM_B"})
|
||||
|
||||
def test_a_core_option_names_the_dump_of_a_model(self) -> None:
|
||||
"""RetroDECK sets LRPS2's pcsx2_bios to scph10000.bin. LRPS2's entry
|
||||
is a placeholder for every BIOS its scan finds, and the catalogues
|
||||
name two revisions of the SCPH-10000: the earlier goes in."""
|
||||
older, newer = b"S" * 64, b"T" * 64
|
||||
for data, catalogue in ((newer, "ps2-0101j-20000217.bin"),
|
||||
(older, "ps2-0100j-20000117.bin")):
|
||||
sha1 = hashlib.sha1(data).hexdigest()
|
||||
path = os.path.join(self.bios_dir, catalogue)
|
||||
with open(path, "wb") as fh:
|
||||
fh.write(data)
|
||||
self.db["files"][sha1] = {
|
||||
"path": path, "name": catalogue, "md5": _md5(data), "sha1": sha1,
|
||||
"size": len(data), "crc32": "",
|
||||
"provenance": {"redump": {"name": catalogue,
|
||||
"description": "SCPH-10000 (Version 5.0)"}},
|
||||
}
|
||||
profile = {
|
||||
"emulator": "OptEmu", "type": "libretro", "systems": ["test-sys"],
|
||||
"files": [{"name": "<bios>.bin", "path": "ps2/bios/<bios>.bin", "required": True,
|
||||
"min_size": 32, "max_size": 64, "validation": ["size"],
|
||||
"config_key": "emu_bios"}],
|
||||
}
|
||||
with open(os.path.join(self.emulators_dir, "optemu.yml"), "w") as fh:
|
||||
yaml.dump(profile, fh)
|
||||
self.config["launchers"].append({
|
||||
"emulator": "retroarch", "build": "libretro", "kind": "core_option",
|
||||
"names": ["scph10000.bin"], "passes_to": "core option emu_bios",
|
||||
"source_ref": "core-options.cfg:515",
|
||||
})
|
||||
_emulator_profiles_cache.clear()
|
||||
self.profiles = load_emulator_profiles(self.emulators_dir)
|
||||
added = {u["path"]: u for u in self._report() if u.get("launcher")}
|
||||
self.assertEqual(added["ps2/bios/scph10000.bin"]["md5"], _md5(older))
|
||||
|
||||
def test_the_default_name_a_launcher_replaces_is_not_packed(self) -> None:
|
||||
"""EmuDeck passes Complex_4627v1.03.bin to xemu, which then never
|
||||
opens Complex_4627.bin: the pack carried both, one read by nobody."""
|
||||
|
||||
Reference in new issue
Block a user