feat: give each set its requirement and one pick

Three changes to the search-list model, one commit because the readers
and the profiles must move together for the schema to hold.

Set requirement in a groups map. pom2 falls back on apple2.rom for the
][ and the ][+, and on apple2e.rom for the //e it boots and for the
unenhanced //e: one required on the file could not say both. A profile
now declares groups: {name: {required}}, a member writes no required
of its own (schema and validate_schemas refuse one) and load_emulator_
profiles derives it, true when one of its sets is. group takes a name,
a list, or a map from set to rank where the rank differs per set. pom2
is grouped from SystemProfile.cpp and MainWindow.cpp:246-296 at its pin.

One member per required set under --required-only. The pick is the
first the code reads among the held members the region filter leaves,
by rank then declaration order; a set the platform declares a member
of is carried by that declaration. The emulator pack, verify
--emulator, the platform pack, its manifest and verify --platform read
alternatives.required_only_spares or core_file_spares.

variant_group is now selection_slot: files a core chooses between by
a rule other than first found (disc territory for PicoDrive and
Pizza Boy SC, the o2em_bios option, a WebAssembly probe in SWF
Player). Where the code takes any one, the field became a group:
ARMSX1 (ArmSxBackend.java:149-157, name order), ePSXe (load_bios
0x433540-0x433621 of the 2.0.5 Linux x64 binary, one configured path,
HLE when BiosHLE is set), FPse and FPse-NG, DXX-Rebirth's HOGs
(inferno.cpp:472-512). odin and zesarux carried it with no effect.
slot.py compares ranks only between candidates that share a set.
This commit is contained in:
Abdessamad Derraz committed 2026-11-09 18:19:32 +01:00
1 parent 1e12d9fe38
commit 315dab82b7
38 files changed
+661 -432

No files matched your search

+54 -50
View File
@@ -71,22 +71,26 @@ notes: |
frontend/config.c:1384-1405, frontend/config.c:1541-1560,
frontend/main.cpp:2555-2561, psx/dev/bios.c:22-75
groups:
ps-bios:
required: true
files:
- name: "scph1000.bin"
group: ps-bios
priority: 4
description: "SCPH-1000, DTL-H1000 (v1.0)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "239665b1a3dade1b5a52c06338011044"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:30"
- name: "scph1001.bin"
group: ps-bios
priority: 6
description: "SCPH-1001, 5003, DTL-H1201, H3001 (v2.2 12-04-95 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "924e392ed05558ffdb115408c263dccf"
validation: [size, md5]
@@ -96,230 +100,230 @@ files:
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:31"
- name: "scph1002a.bin"
group: ps-bios
priority: 9
description: "SCPH-1002, DTL-H1002 (v2.0 05-10-95 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "54847e693405ffeb0359c6287434cbef"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:32"
- name: "scph1002b.bin"
group: ps-bios
priority: 10
description: "SCPH-1002, DTL-H1102 (v2.1 07-17-95 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "417b34706319da7cf001e76e40136c23"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:33"
- name: "scph1002c.bin"
group: ps-bios
priority: 11
description: "SCPH-1002, DTL-H1202, H3002 (v2.2 12-04-95 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "e2110b8a2b97a8e0b857a45d32f7e187"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:34"
- name: "dtlh1100.bin"
group: ps-bios
priority: 1
description: "DTL-H1100 (v2.2 03-06-96 D)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "ca5cfc321f916756e3f0effbfaeba13b"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:35"
- name: "scph3000.bin"
group: ps-bios
priority: 16
description: "SCPH-3000, DTL-H1000H (v1.1 01-22-95)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "849515939161e62f6b866f6853006780"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:36"
- name: "scph1001_v20.bin"
group: ps-bios
priority: 7
description: "SCPH-1001, DTL-H1001 (v2.0 05-07-95 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "dc2b9bf8da62ec93e868cfd29f0d067d"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:37"
- name: "scph3500.bin"
group: ps-bios
priority: 17
description: "SCPH-3500 (v2.1 07-17-95 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "cba733ceeff5aef5c32254f1d617fa62"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:38"
- name: "scph1001_v21.bin"
group: ps-bios
priority: 8
description: "SCPH-1001, DTL-H1101 (v2.1 07-17-95 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "da27e8b6dab242d8f91a9b25d80c63b8"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:39"
- name: "scph5000.bin"
group: ps-bios
priority: 18
description: "SCPH-5000, DTL-H1200, H3000 (v2.2 12-04-95 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "57a06303dfa9cf9351222dfcbb4a29d9"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:40"
- name: "scph5500.bin"
group: ps-bios
priority: 19
description: "SCPH-5500 (v3.0 09-09-96 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "8dd7d5296a650fac7319bce665a6a53c"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:41"
- name: "scph5501.bin"
group: ps-bios
priority: 20
description: "SCPH-5501, 5503, 7003 (v3.0 11-18-96 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "490f666e1afb15b7362b406ed1cea246"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:42"
- name: "scph5502.bin"
group: ps-bios
priority: 21
description: "SCPH-5502, 5552 (v3.0 01-06-97 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "32736f17079d0b2b7024407c39bd3050"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:43"
- name: "scph7000.bin"
group: ps-bios
priority: 22
description: "SCPH-7000, 7500, 9000 (v4.0 08-18-97 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "8e4c14f567745eff2f0408c8129f72a6"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:44"
- name: "scph7000w.bin"
group: ps-bios
priority: 23
description: "SCPH-7000W (v4.1 11-14-97 A)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "b84be139db3ee6cbd075630aa20a6553"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:45"
- name: "scph7001.bin"
group: ps-bios
priority: 24
description: "SCPH-7001, 7501, 7503, 9001, 9003, 9903 (v4.1 12-16-97 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "1e68c231d0896b7eadcad1d7d8e76129"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:46"
- name: "scph7002.bin"
group: ps-bios
priority: 25
description: "SCPH-7002, 7502, 9002 (v4.1 12-16-97 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "b9d9a0286c33dc6b7237bb13cd46fdee"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:47"
- name: "scph100.bin"
group: ps-bios
priority: 3
description: "SCPH-100 (v4.3 03-11-00 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "8abc1b549a4a80954addc48ef02c4521"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:48"
- name: "scph101_v44.bin"
group: ps-bios
priority: 12
description: "SCPH-101 (v4.4 03-24-00 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "9a09ab7e49b422c007e6d54d7c49b965"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:49"
- name: "scph101_v45.bin"
group: ps-bios
priority: 13
description: "SCPH-101 (v4.5 05-25-00 A)"
region: [north-america, latin-america]
required: false
variant_group: "psx-bios"
size: 524288
md5: "6e3735ff4c7dc899ee98981385f6f3d0"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:50"
- name: "scph102_v44.bin"
group: ps-bios
priority: 14
description: "SCPH-102 (v4.4 03-24-00 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "b10f5e0e3d9eb60e5159690680b1e774"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:51"
- name: "scph102_v45.bin"
group: ps-bios
priority: 15
description: "SCPH-102 (v4.5 05-25-00 E)"
region: [europe, oceania]
required: false
variant_group: "psx-bios"
size: 524288
md5: "de93caec13d1a141a40a79f5c86168d6"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:52"
- name: "psxonpsp660.bin"
group: ps-bios
priority: 2
description: "PSP, SCPH-1000R (v4.5 05-25-00 J)"
region: [world]
required: false
variant_group: "psx-bios"
size: 524288
md5: "c53ca5908936d412331790f4426c6c33"
validation: [size, md5]
source_ref: "android/app/src/main/java/com/armsx2/core/Ps1BiosProbe.java:53"
- name: "scph1000r.bin"
group: ps-bios
priority: 5
description: "SCPH-1000R (v4.5 05-25-00 J)"
region: [japan]
required: false
variant_group: "psx-bios"
size: 524288
md5: "476d68a94ccec3b9c8303bbd1daf2810"
validation: [size, md5]
+4 -105
View File
@@ -74,6 +74,10 @@ notes: |
The libretro core was removed by the author (license change to non-commercial).
The .info file and buildbot builds still exist from community forks.
groups:
ps-bios:
required: true
files:
# -- PS1 BIOS images (priority <= 20, preferred) --
@@ -82,7 +86,6 @@ files:
description: "SCPH-1000, DTL-H1000 (v1.0)"
region: [japan]
group: ps-bios
required: true
md5: "239665b1a3dade1b5a52c06338011044"
region_check: true
fast_boot: Type1
@@ -94,7 +97,6 @@ files:
description: "SCPH-1001, 5003, DTL-H1201, H3001 (v2.2 12-04-95 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "924e392ed05558ffdb115408c263dccf"
region_check: false
fast_boot: Type1
@@ -106,7 +108,6 @@ files:
description: "SCPH-1002, DTL-H1002 (v2.0 05-10-95 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "54847e693405ffeb0359c6287434cbef"
region_check: false
fast_boot: Type1
@@ -118,7 +119,6 @@ files:
description: "SCPH-1002, DTL-H1102 (v2.1 07-17-95 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "417b34706319da7cf001e76e40136c23"
region_check: false
fast_boot: Type1
@@ -130,7 +130,6 @@ files:
description: "SCPH-1002, DTL-H1202, H3002 (v2.2 12-04-95 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "e2110b8a2b97a8e0b857a45d32f7e187"
region_check: false
fast_boot: Type1
@@ -142,7 +141,6 @@ files:
description: "DTL-H1100 (v2.2 03-06-96 D)"
region: [japan]
group: ps-bios
required: true
md5: "ca5cfc321f916756e3f0effbfaeba13b"
region_check: true
fast_boot: Type1
@@ -154,7 +152,6 @@ files:
description: "SCPH-3000, DTL-H1000H (v1.1 01-22-95)"
region: [japan]
group: ps-bios
required: true
md5: "849515939161e62f6b866f6853006780"
region_check: true
fast_boot: Type1
@@ -166,7 +163,6 @@ files:
description: "SCPH-1001, DTL-H1001 (v2.0 05-07-95 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "dc2b9bf8da62ec93e868cfd29f0d067d"
region_check: false
fast_boot: Type1
@@ -178,7 +174,6 @@ files:
description: "SCPH-3500 (v2.1 07-17-95 J)"
region: [japan]
group: ps-bios
required: true
md5: "cba733ceeff5aef5c32254f1d617fa62"
region_check: true
fast_boot: Type1
@@ -190,7 +185,6 @@ files:
description: "SCPH-1001, DTL-H1101 (v2.1 07-17-95 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "da27e8b6dab242d8f91a9b25d80c63b8"
region_check: false
fast_boot: Type1
@@ -202,7 +196,6 @@ files:
description: "SCPH-5000, DTL-H1200, H3000 (v2.2 12-04-95 J)"
region: [japan]
group: ps-bios
required: true
md5: "57a06303dfa9cf9351222dfcbb4a29d9"
region_check: true
fast_boot: Type1
@@ -214,7 +207,6 @@ files:
description: "SCPH-5500 (v3.0 09-09-96 J)"
region: [japan]
group: ps-bios
required: true
md5: "8dd7d5296a650fac7319bce665a6a53c"
region_check: true
fast_boot: Type1
@@ -226,7 +218,6 @@ files:
description: "SCPH-5501, 5503, 7003 (v3.0 11-18-96 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "490f666e1afb15b7362b406ed1cea246"
region_check: false
fast_boot: Type1
@@ -238,7 +229,6 @@ files:
description: "SCPH-5502, 5552 (v3.0 01-06-97 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "32736f17079d0b2b7024407c39bd3050"
region_check: false
fast_boot: Type1
@@ -250,7 +240,6 @@ files:
description: "SCPH-7000, 7500, 9000 (v4.0 08-18-97 J)"
region: [japan]
group: ps-bios
required: true
md5: "8e4c14f567745eff2f0408c8129f72a6"
region_check: true
fast_boot: Type1
@@ -262,7 +251,6 @@ files:
description: "SCPH-7000W (v4.1 11-14-97 A)"
region: [japan]
group: ps-bios
required: true
md5: "b84be139db3ee6cbd075630aa20a6553"
region_check: false
fast_boot: Type1
@@ -274,7 +262,6 @@ files:
description: "SCPH-7001, 7501, 7503, 9001, 9003, 9903 (v4.1 12-16-97 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "1e68c231d0896b7eadcad1d7d8e76129"
region_check: false
fast_boot: Type1
@@ -286,7 +273,6 @@ files:
description: "SCPH-7002, 7502, 9002 (v4.1 12-16-97 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "b9d9a0286c33dc6b7237bb13cd46fdee"
region_check: false
fast_boot: Type1
@@ -298,7 +284,6 @@ files:
description: "SCPH-100 (v4.3 03-11-00 J)"
region: [japan]
group: ps-bios
required: true
md5: "8abc1b549a4a80954addc48ef02c4521"
region_check: true
fast_boot: Type1
@@ -310,7 +295,6 @@ files:
description: "SCPH-101 (v4.4 03-24-00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "9a09ab7e49b422c007e6d54d7c49b965"
region_check: false
fast_boot: Type1
@@ -322,7 +306,6 @@ files:
description: "SCPH-101 (v4.5 05-25-00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "6e3735ff4c7dc899ee98981385f6f3d0"
region_check: false
fast_boot: Type1
@@ -334,7 +317,6 @@ files:
description: "SCPH-102 (v4.4 03-24-00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "b10f5e0e3d9eb60e5159690680b1e774"
region_check: true
fast_boot: Type1
@@ -346,7 +328,6 @@ files:
description: "SCPH-102 (v4.5 05-25-00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "de93caec13d1a141a40a79f5c86168d6"
region_check: true
fast_boot: Type1
@@ -358,7 +339,6 @@ files:
description: "SCPH-1000R (v4.5 05-25-00 J)"
region: [japan]
group: ps-bios
required: true
md5: "476d68a94ccec3b9c8303bbd1daf2810"
region_check: true
fast_boot: Type1
@@ -374,7 +354,6 @@ files:
description: "PS2, SCPH-18000 (v5.0 10-27-00 J)"
region: [japan]
group: ps-bios
required: true
md5: "d8f485717a5237285e4d7c5f881b7f32"
region_check: true
fast_boot: Type2
@@ -386,7 +365,6 @@ files:
description: "PS2, SCPH-30003 (v5.0 09-02-00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "71f50ef4f4e17c163c78908e16244f7d"
region_check: true
fast_boot: Type2
@@ -398,7 +376,6 @@ files:
description: "PS2, DTL-H10000 (v5.0 01/17/00 T)"
region: [world]
group: ps-bios
required: true
md5: "32f2e4d5ff5ee11072a6bc45530f5765"
region_check: true
fast_boot: Type2
@@ -410,7 +387,6 @@ files:
description: "PS2, SCPH-10000 (v5.0 01/17/00 T)"
region: [world]
group: ps-bios
required: true
md5: "acf4730ceb38ac9d8c7d8e21f2614600"
region_check: true
fast_boot: Type2
@@ -422,7 +398,6 @@ files:
description: "PS2, DTL-H10000 (v5.0 02/17/00 T)"
region: [world]
group: ps-bios
required: true
md5: "acf9968c8f596d2b15f42272082513d1"
region_check: true
fast_boot: Type2
@@ -434,7 +409,6 @@ files:
description: "PS2, SCPH-10000/SCPH-15000 (v5.0 02/17/00 T)"
region: [world]
group: ps-bios
required: true
md5: "b1459d7446c69e3e97e6ace3ae23dd1c"
region_check: true
fast_boot: Type2
@@ -446,7 +420,6 @@ files:
description: "PS2, DTL-H10000 (v5.0 02/24/00 T)"
region: [world]
group: ps-bios
required: true
md5: "d3f1853a16c2ec18f3cd1ae655213308"
region_check: true
fast_boot: Type2
@@ -458,7 +431,6 @@ files:
description: "PS2, DTL-H30001 (v5.0 07/27/00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "63e6fd9b3c72e0d7b920e80cf76645cd"
region_check: true
fast_boot: Type2
@@ -470,7 +442,6 @@ files:
description: "PS2, SCPH-30001 (v5.0 07/27/00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "a20c97c02210f16678ca3010127caf36"
region_check: true
fast_boot: Type2
@@ -482,7 +453,6 @@ files:
description: "PS2, SCPH-30001 (v5.0 09/02/00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "8db2fbbac7413bf3e7154c1e0715e565"
region_check: true
fast_boot: Type2
@@ -494,7 +464,6 @@ files:
description: "PS2, DTL-H30002 (v5.0 09/02/00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "91c87cb2f2eb6ce529a2360f80ce2457"
region_check: true
fast_boot: Type2
@@ -506,7 +475,6 @@ files:
description: "PS2, DTL-H30102 (v5.0 09/02/00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "3016b3dd42148a67e2c048595ca4d7ce"
region_check: true
fast_boot: Type2
@@ -518,7 +486,6 @@ files:
description: "PS2, SCPH-30002/SCPH-30003/SCPH-30004 (v5.0 09/02/00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "b7fa11e87d51752a98b38e3e691cbf17"
region_check: true
fast_boot: Type2
@@ -530,7 +497,6 @@ files:
description: "PS2, SCPH-18000 (GH-003) (v5.0 10/27/00 J)"
region: [japan]
group: ps-bios
required: true
md5: "f63bc530bd7ad7c026fcd6f7bd0d9525"
region_check: true
fast_boot: Type2
@@ -542,7 +508,6 @@ files:
description: "PS2, SCPH-18000 (GH-008) (v5.0 10/27/00 J)"
region: [japan]
group: ps-bios
required: true
md5: "cee06bd68c333fc5768244eae77e4495"
region_check: true
fast_boot: Type2
@@ -554,7 +519,6 @@ files:
description: "PS2, DTL-H30101 (v5.0 12/28/00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "0bf988e9c7aaa4c051805b0fa6eb3387"
region_check: true
fast_boot: Type2
@@ -566,7 +530,6 @@ files:
description: "PS2, SCPH-30001/SCPH-35001 (v5.0 12/28/00 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "8accc3c49ac45f5ae2c5db0adc854633"
region_check: true
fast_boot: Type2
@@ -578,7 +541,6 @@ files:
description: "PS2, DTL-H30102 (v5.0 12/28/00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "6f9a6feb749f0533aaae2cc45090b0ed"
region_check: true
fast_boot: Type2
@@ -590,7 +552,6 @@ files:
description: "PS2, SCPH-30002/SCPH-30003/SCPH-30004/SCHP-35002/SCPH-35003/SCPH-35004 (v5.0 12/28/00 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "838544f12de9b0abc90811279ee223c8"
region_check: true
fast_boot: Type2
@@ -602,7 +563,6 @@ files:
description: "PS2, DTL-H30000 (v5.0 01/18/01 J)"
region: [japan]
group: ps-bios
required: true
md5: "bb6bbc850458fff08af30e969ffd0175"
region_check: true
fast_boot: Type2
@@ -614,7 +574,6 @@ files:
description: "PS2, SCPH-30000/SCPH-35000 (v5.0 01/18/01 J)"
region: [japan]
group: ps-bios
required: true
md5: "815ac991d8bc3b364696bead3457de7d"
region_check: true
fast_boot: Type2
@@ -626,7 +585,6 @@ files:
description: "PS2, SCPH-30001R (v5.0 04/27/01 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "b107b5710042abe887c0f6175f6e94bb"
region_check: true
fast_boot: Type2
@@ -638,7 +596,6 @@ files:
description: "PS2, SCPH-30000 (v5.0 04/27/01 J)"
region: [japan]
group: ps-bios
required: true
md5: "ab55cceea548303c22c72570cfd4dd71"
region_check: true
fast_boot: Type2
@@ -650,7 +607,6 @@ files:
description: "PS2, SCPH-30001R (v5.0 07/04/01 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "18bcaadb9ff74ed3add26cdf709fff2e"
region_check: true
fast_boot: Type2
@@ -662,7 +618,6 @@ files:
description: "PS2, SCPH-30002R/SCPH-30003R/SCPH-30004R (v5.0 07/04/01 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "491209dd815ceee9de02dbbc408c06d6"
region_check: true
fast_boot: Type2
@@ -674,7 +629,6 @@ files:
description: "PS2, SCPH-30001R (v5.0 10/04/01 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "7200a03d51cacc4c14fcdfdbc4898431"
region_check: true
fast_boot: Type2
@@ -686,7 +640,6 @@ files:
description: "PS2, SCPH-30002R/SCPH-30003R/SCPH-30004R (v5.0 10/04/01 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "8359638e857c8bc18c3c18ac17d9cc3c"
region_check: true
fast_boot: Type2
@@ -698,7 +651,6 @@ files:
description: "PS2, SCPH-30005R/SCPH-30006R/SCPH-30007R (v5.0 07/30/01 J)"
region: [japan]
group: ps-bios
required: true
md5: "352d2ff9b3f68be7e6fa7e6dd8389346"
region_check: true
fast_boot: Type2
@@ -710,7 +662,6 @@ files:
description: "PS2, SCPH-39001 (v5.0 02/07/02 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "d5ce2c7d119f563ce04bc04dbc3a323e"
region_check: true
fast_boot: Type2
@@ -722,7 +673,6 @@ files:
description: "PS2, SCPH-39002/SCPH-39003/SCPH-39004 (v5.0 03/19/02 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "0d2228e6fd4fb639c9c39d077a9ec10c"
region_check: true
fast_boot: Type2
@@ -734,7 +684,6 @@ files:
description: "PS2, SCPH-37000/SCPH-39000 (v5.0 04/26/02 J)"
region: [japan]
group: ps-bios
required: true
md5: "72da56fccb8fcd77bba16d1b6f479914"
region_check: true
fast_boot: Type2
@@ -746,7 +695,6 @@ files:
description: "PS2, SCPH-39008 (v5.0 04/26/02 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "5b1f47fbeb277c6be2fccdd6344ff2fd"
region_check: true
fast_boot: Type2
@@ -758,7 +706,6 @@ files:
description: "PS2, SCPH-39005/SCPH-39006/SCPH-39007 (v5.0 04/26/02 J)"
region: [japan]
group: ps-bios
required: true
md5: "315a4003535dfda689752cb25f24785c"
region_check: true
fast_boot: Type2
@@ -770,7 +717,6 @@ files:
description: "PS2, DTL-H50000 (v5.0 02/06/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "54ecde087258557e2ddb5c3ddb004028"
region_check: true
fast_boot: Type2
@@ -782,7 +728,6 @@ files:
description: "PS2, SCPH-50000/SCPH-55000 (v5.0 02/06/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "312ad4816c232a9606e56f946bc0678a"
region_check: true
fast_boot: Type2
@@ -794,7 +739,6 @@ files:
description: "PS2, DTL-H50002 (v5.0 02/27/03 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "666018ffec65c5c7e04796081295c6c7"
region_check: true
fast_boot: Type2
@@ -806,7 +750,6 @@ files:
description: "PS2, SCPH-50002/SCPH-50003/SCPH-50004 (v5.0 02/27/03 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "6e69920fa6eef8522a1d688a11e41bc6"
region_check: true
fast_boot: Type2
@@ -818,7 +761,6 @@ files:
description: "PS2, DTL-H50001 (v5.0 03/25/03 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "eb960de68f0c0f7f9fa083e9f79d0360"
region_check: true
fast_boot: Type2
@@ -830,7 +772,6 @@ files:
description: "PS2, SCPH-50001 (v5.0 03/25/03 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "8aa12ce243210128c5074552d3b86251"
region_check: true
fast_boot: Type2
@@ -842,7 +783,6 @@ files:
description: "PS2, DTL-H50009 (v5.0 02/24/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "240d4c5ddd4b54069bdc4a3cd2faf99d"
region_check: true
fast_boot: Type2
@@ -854,7 +794,6 @@ files:
description: "PS2, DESR-5000/DESR-5100/DESR-7000/DESR-7100 (v5.0 10/28/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "1c6cd089e6c83da618fbf2a081eb4888"
region_check: true
fast_boot: Type2
@@ -866,7 +805,6 @@ files:
description: "PS2, SCPH-55000 (v5.0 06/23/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "463d87789c555a4a7604e97d7db545d1"
region_check: true
fast_boot: Type2
@@ -878,7 +816,6 @@ files:
description: "PS2, DTL-H50001 (v5.0 06/23/03 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "ab9d49ad40ae49f19856ad187777b1b3"
region_check: true
fast_boot: Type2
@@ -890,7 +827,6 @@ files:
description: "PS2, SCPH-50001/SCPH-50010 (v5.0 06/23/03 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "35461cecaa51712b300b2d6798825048"
region_check: true
fast_boot: Type2
@@ -902,7 +838,6 @@ files:
description: "PS2, SCPH-50002/SCPH-50003/SCPH-50004 (v5.0 06/23/03 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "bd6415094e1ce9e05daabe85de807666"
region_check: true
fast_boot: Type2
@@ -914,7 +849,6 @@ files:
description: "PS2, SCPH-50006/SCPH-50007 (v5.0 06/23/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "2e70ad008d4ec8549aada8002fdf42fb"
region_check: true
fast_boot: Type2
@@ -926,7 +860,6 @@ files:
description: "PS2, SCPH-50005 (v5.0 06/23/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "50d5b97b57d8c9b6534adcb46c2027d4"
region_check: true
fast_boot: Type2
@@ -938,7 +871,6 @@ files:
description: "PS2, SCPH-50008 (v5.0 06/23/03 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "b53d51edc7fc086685e31b811dc32aad"
region_check: true
fast_boot: Type2
@@ -950,7 +882,6 @@ files:
description: "PS2, SCPH-50009 (v5.0 06/23/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "1b6e631b536247756287b916f9396872"
region_check: true
fast_boot: Type2
@@ -962,7 +893,6 @@ files:
description: "PS2, SCPH-50000 (v5.0 08/22/03 J)"
region: [japan]
group: ps-bios
required: true
md5: "00da1b177096cfd2532c8fa22b43e667"
region_check: true
fast_boot: Type2
@@ -974,7 +904,6 @@ files:
description: "PS2, SCPH-50004 (v5.0 08/22/03 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "afde410bd026c16be605a1ae4bd651fd"
region_check: true
fast_boot: Type2
@@ -986,7 +915,6 @@ files:
description: "PS2, SCPH-50011 (v5.0 03/29/04 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "81f4336c1de607dd0865011c0447052e"
region_check: true
fast_boot: Type2
@@ -998,7 +926,6 @@ files:
description: "PS2, SCPH-70000 (v5.0 06/14/04 J)"
region: [japan]
group: ps-bios
required: true
md5: "0eee5d1c779aa50e94edd168b4ebf42e"
region_check: true
fast_boot: Type2
@@ -1010,7 +937,6 @@ files:
description: "PS2, SCPH-70001/SCPH-70011/SCPH-70012 (v5.0 06/14/04 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "d333558cc14561c1fdc334c75d5f37b7"
region_check: true
fast_boot: Type2
@@ -1022,7 +948,6 @@ files:
description: "PS2, SCPH-70002/SCPH-70003/SCPH-70004/SCPH-70008 (v5.0 06/14/04 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "dc752f160044f2ed5fc1f4964db2a095"
region_check: true
fast_boot: Type2
@@ -1034,7 +959,6 @@ files:
description: "PS2, SCPH-70002 (v5.0 06/14/04 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "7ebb4fc5eab6f79a27d76ac9aad392b2"
region_check: true
fast_boot: Type2
@@ -1046,7 +970,6 @@ files:
description: "PS2, DTL-H70002 (v5.0 06/14/04 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "63ead1d74893bf7f36880af81f68a82d"
region_check: true
fast_boot: Type2
@@ -1058,7 +981,6 @@ files:
description: "PS2, SCPH-70005/SCPH-70006/SCPH-70007 (v5.0 06/14/04 J)"
region: [japan]
group: ps-bios
required: true
md5: "3e3e030c0f600442fa05b94f87a1e238"
region_check: true
fast_boot: Type2
@@ -1070,7 +992,6 @@ files:
description: "PS2, DESR-5500/DESR-5700/DESR-7500/DESR-7700 (v5.0 09/17/04 J)"
region: [japan]
group: ps-bios
required: true
md5: "1ad977bb539fc9448a08ab276a836bbc"
region_check: true
fast_boot: Type2
@@ -1082,7 +1003,6 @@ files:
description: "PS2, DTL-H75000 (v5.0 06/20/05 J)"
region: [japan]
group: ps-bios
required: true
md5: "bf0078ba5e19d57eae18047407f3b6e5"
region_check: true
fast_boot: Type2
@@ -1094,7 +1014,6 @@ files:
description: "PS2, SCPH-75000 (v5.0 06/20/05 J)"
region: [japan]
group: ps-bios
required: true
md5: "eb4f40fcf4911ede39c1bbfe91e7a89a"
region_check: true
fast_boot: Type2
@@ -1106,7 +1025,6 @@ files:
description: "PS2, DTL-H75000A (v5.0 06/20/05 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "9959ad7a8685cad66206e7752ca23f8b"
region_check: true
fast_boot: Type2
@@ -1118,7 +1036,6 @@ files:
description: "PS2, SCPH-75001/SCPH-75010 (v5.0 06/20/05 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "929a14baca1776b00869f983aa6e14d2"
region_check: true
fast_boot: Type2
@@ -1130,7 +1047,6 @@ files:
description: "PS2, SCPH-75002/SCPH-75003/SCPH-75004/SCPH-75008 (v5.0 06/20/05 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "573f7d4a430c32b3cc0fd0c41e104bbd"
region_check: true
fast_boot: Type2
@@ -1142,7 +1058,6 @@ files:
description: "PS2, SCPH-75006 (v5.0 06/20/05 J)"
region: [japan]
group: ps-bios
required: true
md5: "df63a604e8bff5b0599bd1a6c2721bd0"
region_check: true
fast_boot: Type2
@@ -1154,7 +1069,6 @@ files:
description: "PS2, SCPH-77000 (v5.0 02/10/06 J)"
region: [japan]
group: ps-bios
required: true
md5: "5b1ba4bb914406fae75ab8e38901684d"
region_check: true
fast_boot: Type2
@@ -1166,7 +1080,6 @@ files:
description: "PS2, SCPH-77001/SCPH-77010 (v5.0 02/10/06 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "cb801b7920a7d536ba07b6534d2433ca"
region_check: true
fast_boot: Type2
@@ -1178,7 +1091,6 @@ files:
description: "PS2, SCPH-77002/SCPH-77003/SCPH-77004/SCPH-77008 (v5.0 02/10/06 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "af60e6d1a939019d55e5b330d24b1c25"
region_check: true
fast_boot: Type2
@@ -1190,7 +1102,6 @@ files:
description: "PS2, SCPH-77006/SCPH-77007 (v5.0 02/10/06 J)"
region: [japan]
group: ps-bios
required: true
md5: "549a66d0c698635ca9fa3ab012da7129"
region_check: true
fast_boot: Type2
@@ -1202,7 +1113,6 @@ files:
description: "PS2, DTL-H90000 (v5.0 09/05/06 J)"
region: [japan]
group: ps-bios
required: true
md5: "5e2014472c88f74f7547d8c2c60eca45"
region_check: true
fast_boot: Type2
@@ -1214,7 +1124,6 @@ files:
description: "PS2, SCPH-79000/SCPH-90000 (v5.0 09/05/06 J)"
region: [japan]
group: ps-bios
required: true
md5: "5de9d0d730ff1e7ad122806335332524"
region_check: true
fast_boot: Type2
@@ -1226,7 +1135,6 @@ files:
description: "PS2, DTL-H90000 (v5.0 09/05/06 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "21fe4cad111f7dc0f9af29477057f88d"
region_check: true
fast_boot: Type2
@@ -1238,7 +1146,6 @@ files:
description: "PS2, SCPH-79001/SCPH-79010/SCPH-90001 (v5.0 09/05/06 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "40c11c063b3b9409aa5e4058e984e30c"
region_check: true
fast_boot: Type2
@@ -1250,7 +1157,6 @@ files:
description: "PS2, SCPH-79002/SCPH-79003/SCPH-79004/SCPH-79008/SCPH-90002/SCPH-90003/SCPH-90004 (v5.0 09/05/06 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "80bbb237a6af9c611df43b16b930b683"
region_check: true
fast_boot: Type2
@@ -1262,7 +1168,6 @@ files:
description: "PS2, SCPH-79006/SCPH-79007/SCPH-90006/SCPH-90007 (v5.0 09/05/06 J)"
region: [japan]
group: ps-bios
required: true
md5: "c37bce95d32b2be480f87dd32704e664"
region_check: true
fast_boot: Type2
@@ -1274,7 +1179,6 @@ files:
description: "PS2, SCPH-90000 (v5.0 02/20/08 J)"
region: [japan]
group: ps-bios
required: true
md5: "80ac46fa7e77b8ab4366e86948e54f83"
region_check: true
fast_boot: Type2
@@ -1286,7 +1190,6 @@ files:
description: "PS2, SCPH-90001/SCPH-90010 (v5.0 02/20/08 A)"
region: [north-america, latin-america]
group: ps-bios
required: true
md5: "21038400dc633070a78ad53090c53017"
region_check: true
fast_boot: Type2
@@ -1298,7 +1201,6 @@ files:
description: "PS2, SCPH-90002/SCPH-90003/SCPH-90004/SCPH-90008 (v5.0 02/20/08 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "dc69f0643a3030aaa4797501b483d6c4"
region_check: true
fast_boot: Type2
@@ -1310,7 +1212,6 @@ files:
description: "PS2, SCPH-90005/SCPH-90006/SCPH-90007 (v5.0 02/20/08 J)"
region: [japan]
group: ps-bios
required: true
md5: "30d56e79d89fbddf10938fa67fe3f34e"
region_check: true
fast_boot: Type2
@@ -1322,7 +1223,6 @@ files:
description: "PS2, KDL-22PX300 (v5.0 04/15/10 E)"
region: [europe, oceania]
group: ps-bios
required: true
md5: "93ea3bcee4252627919175ff1b16a1d9"
region_check: true
fast_boot: Type2
@@ -1337,7 +1237,6 @@ files:
description: "OpenBIOS"
region: [world]
group: ps-bios
required: true
md5: null
region_check: false
fast_boot: unsupported
+12 -8
View File
@@ -64,18 +64,23 @@ notes: |
descent2 on install (scriptmodules/ports/dxx-rebirth.sh,
game_data_dxx-rebirth).
groups:
d1-hog:
required: true
d2-hog:
required: true
files:
# ------ Descent 1 shareware (free) ------
- name: descent.hog
group: d1-hog
installed_on: [retropie]
path: descent.hog
system: descent
category: game_data
required: false
size: 2339773
validation: [size]
description: "Descent 1 PC shareware v1.4 HOG"
variant_group: d1-hog
note: "freely redistributable (icculus.org/d2x/data/desc14sw.tar.gz)"
source_ref: "similar/main/mission.cpp:80; common/main/mission.h:67"
@@ -90,14 +95,13 @@ files:
# ------ Descent 1 retail ------
- name: descent.hog
group: d1-hog
path: descent.hog
system: descent
category: game_data
required: false
size: 6856701
validation: [size]
description: "Descent 1 PC retail v1.5 HOG (GOG)"
variant_group: d1-hog
note: "commercial, alternative sizes 6856183 (v1.5 alt), 7261423 (v1.0), 7456179 (Mac retail)"
source_ref: "common/main/mission.h:61-64"
@@ -111,15 +115,15 @@ files:
# ------ Descent 2 shareware (free) ------
- name: d2demo.hog
group: d2-hog
priority: 2
installed_on: [retropie]
path: d2demo.hog
system: descent2
category: game_data
required: false
size: 2292566
validation: [size]
description: "Descent 2 PC shareware HOG"
variant_group: d2-hog
note: "freely redistributable (icculus.org/d2x/data/d2shar10.tar.gz)"
source_ref: "similar/main/mission.cpp:107-108; common/main/mission.h:71"
@@ -143,14 +147,14 @@ files:
# ------ Descent 2 retail ------
- name: descent2.hog
group: d2-hog
priority: 1
path: descent2.hog
system: descent2
category: game_data
required: false
size: 7595079
validation: [size]
description: "Descent 2 PC full v1.1-1.2 HOG (GOG)"
variant_group: d2-hog
note: "commercial, alternative sizes 7107354 (v1.0), 7110007 (Mac full), 6132957 (OEM v1.1), 4292746 (Mac shareware)"
source_ref: "common/main/mission.h:73-76"
+27 -46
View File
@@ -133,13 +133,16 @@ notes: |
ePSXe 2.0.18 Windows 0x4fb220-0x4fb263,
DownloadShaderPluginTask.java:56-80
groups:
ps-bios:
required: false
files:
- name: scph1000.bin
group: ps-bios
path: bios/scph1000.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -149,11 +152,10 @@ files:
source_ref: "ScanBiosTask.java:28, ScanBiosTask.java:162-172, ePSXe 2.0.18 Windows 0x5c10b4"
- name: scph1001.bin
group: ps-bios
path: bios/scph1001.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -163,11 +165,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.5 Linux x64 write_configfiledefault 0x42ae99, ePSXeReadPreferences.java:21, ePSXe 2.0.18 Windows 0x5c10d8"
- name: scph1001_v20.bin
group: ps-bios
path: bios/scph1001_v20.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -177,11 +178,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1120"
- name: scph1002a.bin
group: ps-bios
path: bios/scph1002a.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -191,11 +191,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c10fc"
- name: scph3000.bin
group: ps-bios
path: bios/scph3000.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -205,11 +204,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1144"
- name: scph3500.bin
group: ps-bios
path: bios/scph3500.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -219,11 +217,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1168"
- name: dtlh1100.bin
group: ps-bios
path: bios/dtlh1100.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "biosPref"
size: 524288
validation: [size, md5]
@@ -233,11 +230,10 @@ files:
source_ref: "ScanBiosTask.java:28, ScanBiosTask.java:162-172"
- name: scph1001_v21.bin
group: ps-bios
path: bios/scph1001_v21.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "biosPref"
size: 524288
validation: [size, md5]
@@ -247,11 +243,10 @@ files:
source_ref: "ScanBiosTask.java:28, ScanBiosTask.java:162-172"
- name: scph1002b.bin
group: ps-bios
path: bios/scph1002b.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "biosPref"
size: 524288
validation: [size, md5]
@@ -261,11 +256,10 @@ files:
source_ref: "ScanBiosTask.java:28, ScanBiosTask.java:162-172"
- name: scph5000.bin
group: ps-bios
path: bios/scph5000.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "biosPref"
size: 524288
validation: [size, md5]
@@ -275,11 +269,10 @@ files:
source_ref: "ScanBiosTask.java:28, ScanBiosTask.java:162-172"
- name: scph1002c.bin
group: ps-bios
path: bios/scph1002c.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -289,11 +282,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1090"
- name: scph5500.bin
group: ps-bios
path: bios/scph5500.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -303,11 +295,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c11b0"
- name: scph5501.bin
group: ps-bios
path: bios/scph5501.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -317,11 +308,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1288"
- name: scph5502.bin
group: ps-bios
path: bios/scph5502.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -331,11 +321,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c11f8"
- name: scph7000.bin
group: ps-bios
path: bios/scph7000.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -345,11 +334,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c121c"
- name: scph7001.bin
group: ps-bios
path: bios/scph7001.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -359,11 +347,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1240"
- name: scph7002.bin
group: ps-bios
path: bios/scph7002.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -373,11 +360,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1264, ePSXe 2.0.18 Windows 0x5c12ac, ePSXe 2.0.18 Windows 0x5c12d0"
- name: scph100.bin
group: ps-bios
path: bios/scph100.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -387,11 +373,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c12f4"
- name: scph102_v44.bin
group: ps-bios
path: bios/scph102_v44.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -401,11 +386,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c133c"
- name: scph101_v45.bin
group: ps-bios
path: bios/scph101_v45.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -415,11 +399,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1318"
- name: scph102_v45.bin
group: ps-bios
path: bios/scph102_v45.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size, md5]
@@ -429,11 +412,10 @@ files:
source_ref: "ScanBiosTask.java:28, ePSXe 2.0.18 Windows 0x5c1360"
- name: scph5000_b.bin
group: ps-bios
path: bios/scph5000_b.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size]
@@ -443,11 +425,10 @@ files:
source_ref: "ePSXe 2.0.18 Windows 0x5c118c, ePSXe 2.0.18 Windows 0x42f525-0x42f568"
- name: scph5502_b.bin
group: ps-bios
path: bios/scph5502_b.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosPath"
size: 524288
validation: [size]
+5 -2
View File
@@ -133,13 +133,16 @@ notes: |
Main.java:11014, Main.java:12555-12585, Main.java:15415-15430,
Main.java:15489
groups:
ps-bios:
required: false
files:
- name: scph1001.bin
group: ps-bios
path: bios/scph1001.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "com.emulator.fpse64.biospath"
size: 524288
validation: [size]
+5 -2
View File
@@ -105,13 +105,16 @@ notes: |
ref: Main.java:26892-26895, Main.java:26956-26957, Main.java:29721,
Main.java:29755-29758, Main.java:30046
groups:
ps-bios:
required: false
files:
- name: scph1001.bin
group: ps-bios
path: bios/scph1001.bin
system: sony-playstation
required: false
hle_fallback: true
variant_group: "psx-bios"
config_key: "BiosName"
size: 524288
validation: [size]
+4 -2
View File
@@ -37,12 +37,15 @@ notes: |
The .info file declares all three firmware files as required (opt=false),
but the core does not abort on a missing BIOS. It falls back to HLE.
groups:
psu1:
required: false
files:
- name: "sl31253.bin"
system: fairchild-channelf
group: psu1
priority: 2
required: false
hle_fallback: true
note: "Channel F PSU1 ROM (original). Fallback if sl90025.bin is missing."
source_ref: "src/libretro.c:192"
@@ -58,7 +61,6 @@ files:
system: fairchild-channelf
group: psu1
priority: 1
required: false
hle_fallback: true
note: "Channel F II PSU1 ROM. Tried first, preferred over sl31253.bin."
source_ref: "src/libretro.c:186"
+4 -4
View File
@@ -48,6 +48,10 @@ notes: |
archive_prefix: kronos
groups:
saturn-bios:
required: true
files:
# -----------------------------------------------------------
# Saturn BIOS - primary (any region)
@@ -57,7 +61,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 1
required: true
size: 524288
validation: [size]
note: "Primary Saturn BIOS. Any region accepted. Searched in kronos/ subdir first."
@@ -67,7 +70,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 2
required: true
size: 524288
validation: [size]
note: "The same name in the system directory, read when kronos/ holds none."
@@ -80,7 +82,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 3
required: true
size: 524288
validation: [size]
note: "Saturn BIOS v1.01 (Japan). Fallback if saturn_bios.bin missing."
@@ -93,7 +94,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 4
required: true
size: 524288
validation: [size]
note: "Saturn BIOS (NA/EU). Last fallback for Saturn mode."
+4 -3
View File
@@ -39,13 +39,16 @@ notes: |
underlying engine (calc.cpp:rom_load) auto-detects the model from the ROM
header.
groups:
rom:
required: true
files:
- name: "ti83se.rom"
system: ti-83
description: "TI-83 Plus Silver Edition ROM dump"
group: rom
priority: 1
required: true
source_ref: "source libnumero/libretro/libretronew.cpp:576-578"
note: "Checked first. Recommended for largest storage capacity."
@@ -54,7 +57,6 @@ files:
description: "TI-83 Plus ROM dump"
group: rom
priority: 2
required: true
source_ref: "source libnumero/libretro/libretronew.cpp:583-585"
note: "Checked second, used if ti83se.rom is missing."
@@ -63,6 +65,5 @@ files:
description: "TI-83 ROM dump"
group: rom
priority: 3
required: true
source_ref: "source libnumero/libretro/libretronew.cpp:591-593"
note: "Checked last. Original TI-83 (non-Plus)."
+4 -4
View File
@@ -41,7 +41,7 @@ files:
- name: "o2rom.bin"
system: odyssey2
required: true
variant_group: "o2em-bios"
selection_slot: "o2em-bios"
min_size: 1024
md5: "562d5ebf9e030a40d6fabfc2f33139fd"
sha1: "b2e1955d957a475de2411770452eff4ea19f4cee"
@@ -57,7 +57,7 @@ files:
- name: "c52.bin"
system: videopac
required: false
variant_group: "o2em-bios"
selection_slot: "o2em-bios"
min_size: 1024
md5: "f1071cdb0b6b10dde94d3bc8a6146387"
sha1: "a6120aed50831c9c0d95dbdf707820f601d9452e"
@@ -69,7 +69,7 @@ files:
- name: "g7400.bin"
system: videopac
required: false
variant_group: "o2em-bios"
selection_slot: "o2em-bios"
min_size: 1024
md5: "c500ff71236068e0dc0d0603d265ae76"
sha1: "5130243429b40b01a14e1304d0394b8459a6fbae"
@@ -81,7 +81,7 @@ files:
- name: "jopac.bin"
system: videopac
required: false
variant_group: "o2em-bios"
selection_slot: "o2em-bios"
min_size: 1024
md5: "279008e4a0db2dc5f1c048853b033828"
sha1: "54b8d2c1317628de51a85fc1c424423a986775e4"
+4 -6
View File
@@ -71,6 +71,10 @@ notes: |
archive_prefix: "odin"
groups:
boot-rom:
required: true
files:
- name: "hikaru.zip"
path: "odin/hikaru.zip"
@@ -84,8 +88,6 @@ files:
archive: hikaru.zip
system: sega-hikaru
group: boot-rom
required: true
variant_group: "hikaru-bootrom"
priority: 1
size: 2097152
crc32: "2aa906a7"
@@ -97,8 +99,6 @@ files:
archive: hikaru.zip
system: sega-hikaru
group: boot-rom
required: true
variant_group: "hikaru-bootrom"
priority: 2
size: 2097152
crc32: "3d557104"
@@ -110,8 +110,6 @@ files:
archive: hikaru.zip
system: sega-hikaru
group: boot-rom
required: true
variant_group: "hikaru-bootrom"
priority: 3
size: 2097152
crc32: "d96298b6"
+4 -3
View File
@@ -22,12 +22,15 @@ notes: >
No region detection, no hash validation. First valid BIOS found is used regardless of region.
.info declares scph5500/5501/5502 but code explicitly searches scph1001/5501/7001 first.
groups:
bios:
required: false
files:
- name: "scph1001.bin"
description: "SCPH-1001 (v2.2 12-04-95 A)"
group: bios
priority: 1
required: false
hle_fallback: true
size: 524288
validation: [size]
@@ -40,7 +43,6 @@ files:
description: "SCPH-5501 (v3.0 11-18-96 A)"
group: bios
priority: 2
required: false
hle_fallback: true
size: 524288
validation: [size]
@@ -53,7 +55,6 @@ files:
description: "SCPH-7001 (v4.1 12-16-97 A)"
group: bios
priority: 3
required: false
hle_fallback: true
size: 524288
validation: [size]
+20 -24
View File
@@ -55,6 +55,14 @@ notes: |
initializes VDP registers and RAM to simulate post-BIOS state
(pico/sms.c:1080-1097).
groups:
mega-cd-us:
required: true
mega-cd-eu:
required: true
mega-cd-jp:
required: true
files:
# -------------------------------------------------------
# Cartridge hardware database
@@ -69,44 +77,40 @@ files:
# -------------------------------------------------------
- name: "us_scd2_9306.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [north-america, latin-america]
group: mega-cd-us
priority: 1
required: true
size: 131072 # 128 KB (0x20000)
note: "US Sega CD Model 2 BIOS (September 1993). First in US search order. The US list serves every disc whose security byte is neither 0x64 nor 0xa1 (pico/cd/cd_image.c:190, 247-248)."
source_ref: "source platform/libretro/libretro.c:1273"
- name: "SegaCDBIOS9303.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [north-america, latin-america]
group: mega-cd-us
priority: 2
required: true
size: 131072
note: "US Sega CD BIOS (March 1993). Second in US search order."
source_ref: "source platform/libretro/libretro.c:1273"
- name: "us_scd1_9210.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [north-america, latin-america]
group: mega-cd-us
priority: 3
required: true
size: 131072
note: "US Sega CD Model 1 BIOS (October 1992). Third in US search order."
source_ref: "source platform/libretro/libretro.c:1273"
- name: "bios_CD_U.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [north-america, latin-america]
group: mega-cd-us
priority: 4
required: true
size: 131072
note: "US Sega CD BIOS (generic name). Last in US search order."
source_ref: "source platform/libretro/libretro.c:1273"
@@ -116,44 +120,40 @@ files:
# -------------------------------------------------------
- name: "eu_mcd2_9306.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [europe, oceania]
group: mega-cd-eu
priority: 1
required: true
size: 131072
note: "EU Mega CD Model 2 BIOS (June 1993). First in EU search order, used when security byte 0x20b is 0x64, the only PAL branch for Australian discs (pico/media.c:243-247, platform/libretro/libretro.c:1306-1308)."
source_ref: "source platform/libretro/libretro.c:1276"
- name: "eu_mcd2_9303.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [europe, oceania]
group: mega-cd-eu
priority: 2
required: true
size: 131072
note: "EU Mega CD Model 2 BIOS (March 1993). Second in EU search order."
source_ref: "source platform/libretro/libretro.c:1276"
- name: "eu_mcd1_9210.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [europe, oceania]
group: mega-cd-eu
priority: 3
required: true
size: 131072
note: "EU Mega CD Model 1 BIOS (October 1992). Third in EU search order."
source_ref: "source platform/libretro/libretro.c:1276"
- name: "bios_CD_E.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [europe, oceania]
group: mega-cd-eu
priority: 4
required: true
size: 131072
note: "EU Mega CD BIOS (generic name). Last in EU search order."
source_ref: "source platform/libretro/libretro.c:1276"
@@ -163,44 +163,40 @@ files:
# -------------------------------------------------------
- name: "jp_mcd2_921222.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [japan]
group: mega-cd-jp
priority: 1
required: true
size: 131072
note: "JP Mega CD Model 2 BIOS (December 1992). First in JP search order."
source_ref: "source platform/libretro/libretro.c:1279"
- name: "jp_mcd1_9112.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [japan]
group: mega-cd-jp
priority: 2
required: true
size: 131072
note: "JP Mega CD Model 1 BIOS (December 1991). Second in JP search order."
source_ref: "source platform/libretro/libretro.c:1279"
- name: "jp_mcd1_9111.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [japan]
group: mega-cd-jp
priority: 3
required: true
size: 131072
note: "JP Mega CD Model 1 BIOS (November 1991). Third in JP search order."
source_ref: "source platform/libretro/libretro.c:1279"
- name: "bios_CD_J.bin"
system: sega-megacd
variant_group: "mega-cd-bios"
selection_slot: "mega-cd-bios"
region: [japan]
group: mega-cd-jp
priority: 4
required: true
size: 131072
note: "JP Mega CD BIOS (generic name). Last in JP search order."
source_ref: "source platform/libretro/libretro.c:1279"
+6 -6
View File
@@ -90,7 +90,7 @@ files:
system: sega-megacd
required: true
agnostic: true
variant_group: "megacd-boot-rom"
selection_slot: "megacd-boot-rom"
size: 131072
validation: [size]
description: "Sega CD boot ROM"
@@ -116,7 +116,7 @@ files:
system: sega-megacd
required: true
agnostic: true
variant_group: "megacd-boot-rom"
selection_slot: "megacd-boot-rom"
size: 131072
validation: [size]
description: "Mega CD boot ROM"
@@ -129,7 +129,7 @@ files:
system: sega-megacd
required: true
agnostic: true
variant_group: "megacd-boot-rom"
selection_slot: "megacd-boot-rom"
size: 131072
validation: [size]
description: "Mega CD boot ROM (Japan)"
@@ -142,7 +142,7 @@ files:
system: sega-mastersystem
required: false
agnostic: true
variant_group: "mastersystem-boot-rom"
selection_slot: "mastersystem-boot-rom"
description: "Master System boot ROM"
note: >-
Picked and stored like the Mega CD image and handed to the machine as a path.
@@ -157,7 +157,7 @@ files:
system: sega-mastersystem
required: false
agnostic: true
variant_group: "mastersystem-boot-rom"
selection_slot: "mastersystem-boot-rom"
description: "Master System boot ROM (Europe)"
note: "Same slot and same absence of tests as the other Master System boot ROMs."
source_ref: "Pizza Boy SC Basic 1.2.14 libsc.so frontend/android/src/lib.rs:590,
@@ -167,7 +167,7 @@ files:
system: sega-mastersystem
required: false
agnostic: true
variant_group: "mastersystem-boot-rom"
selection_slot: "mastersystem-boot-rom"
description: "Master System boot ROM (Japan)"
note: "Same slot and same absence of tests as the other Master System boot ROMs."
source_ref: "Pizza Boy SC Basic 1.2.14 libsc.so frontend/android/src/lib.rs:590,
+38 -30
View File
@@ -61,8 +61,10 @@ notes: |
//c apple2c-32Kv0.rom, apple2c-16K.rom, 3420033a.256
//c Plus apple2cp.rom, apple2c-plus.rom, apple2c-32Kv0.rom
With no candidate the machine runs on a $D000-$FFFF stub and the Welcome
panel opens (src/MainWindow.cpp:357-364). A first run with no //e image
falls back to the ][+ chain (src/MainWindow.cpp:246-259).
panel opens (src/MainWindow.cpp:357-364). A first run boots the //e on
apple2e.rom, else the ][+ chain, else the //c chain
(src/MainWindow.cpp:246-296): one of these is the set the machine needs,
each model's chain is a set of its own.
Memory::loadAppleIIRom (src/Memory.cpp:177-264) maps 12 KB at $D000,
16 KB at $C000, skips the 4 KB pad of a 20 KB ][+ dump, and slices a
32 KB dump by profile: //e images carry the firmware in the upper half,
@@ -190,13 +192,32 @@ notes: |
browsed from disks_5.4/, disks_3.5/, hdv/, floppyemu/, bundled_disks/,
cassettes/ and prodos_folder/ next to the executable.
groups:
boot:
required: true
ii:
required: false
ii-plus:
required: false
iie-unenhanced:
required: false
iic:
required: false
iic-plus:
required: false
char:
required: false
char-iie-unenhanced:
required: false
videoterm:
required: false
files:
- name: "apple2o.rom"
path: "roms/apple2o.rom"
group: {ii: 1}
description: "Apple ][ Original monitor and Integer BASIC, $D000-$FFFF"
required: false
bundled: false
priority: 1
size: 12288
sha256: "68d9db6bb4c305d40c3fa89fa0f2d7b7f71516a9431e3138859f23bc5bddb2d1"
sha1: "78008be557f643e956a106121bcc182c0fb9ea6d"
@@ -205,10 +226,9 @@ files:
note: "First candidate of the Apple ][ Original profile. apple2.rom is probed next."
- name: "apple2.rom"
path: "roms/apple2.rom"
group: {ii: 2, ii-plus: 2, boot: 3}
description: "Apple ][ generic 12 KB fallback, Autostart monitor and Applesoft"
required: false
bundled: false
priority: 2
size: 12288
sha256: "fc3e9d41e9428534a883df5aa10eb55b73ea53d2fcbb3ee4f39bed1b07a82905"
sha1: "33a24f5489ba9195b44be77d9afb2252594cb5c7"
@@ -217,10 +237,9 @@ files:
note: "Probed after the profile image for the ][ and ][+ profiles. When it resolves in place of that image the loader logs that the ROM identity may not match the machine."
- name: "apple2p.rom"
path: "roms/apple2p.rom"
group: {ii-plus: 1, boot: 2}
description: "Apple ][+ Autostart monitor and Applesoft, 4 KB pad then $C000-$FFFF"
required: false
bundled: false
priority: 1
size: [12288, 20480]
sha256: "92c4bef609920842ea472d21b661a0d35dbda6cd90963b8b734a205e22d84108"
sha1: "29a53f3bb158b160433369e8e4a1d7cd5bf68ac6"
@@ -229,10 +248,9 @@ files:
note: "First candidate of the ][+ profile and of the first-run fallback (src/MainWindow.cpp:255-259). The loader drops the leading 4 KB of the 20 KB dump. The fetch gate names that dump, but a 12 KB six-chip image already on disk is kept as present without a digest check."
- name: "apple2e.rom"
path: "roms/apple2e.rom"
group: {boot: 1, iie-unenhanced: 3}
description: "Apple //e Enhanced firmware, 32 KB dump with the 16 KB firmware in the upper half"
required: true
bundled: false
priority: 1
size: 32768
sha256: "c17bc38c75ba96c33a30c688a1efd60144811073423533fe7f8453cdd9457aab"
sha1: "d756eba578a6c5a4807510dfee30ee585c63755e"
@@ -241,10 +259,9 @@ files:
note: "Sole candidate of the //e Enhanced profiles, NTSC and PAL, PAL being the default machine. Also the last fallback of the //e Unenhanced chain."
- name: "apple2e_unenh.rom"
path: "roms/apple2e_unenh.rom"
group: {iie-unenhanced: 1}
description: "Apple //e Unenhanced firmware, 4 KB internal $Cx00 ROM then $D000-$FFFF"
required: false
bundled: false
priority: 1
aliases: ["342-0135-b.64.rom"]
size: 16384
sha256: "1fb812584c6633fa16b77b20915986ed1178d1e6fc07a647f7ee8d4e6ab9d40b"
@@ -254,10 +271,9 @@ files:
note: "First candidate of the //e Unenhanced profiles. 342-0135-b.64.rom is probed second, apple2e.rom third. The fetcher assembles it from the two 8 KB chips of the MAME apple2e set, 342-0135-b.64 then 342-0134-a.64."
- name: "apple2c-32Kv0.rom"
path: "roms/apple2c-32Kv0.rom"
group: {iic: 1, iic-plus: 3, boot: 4}
description: "Apple //c two-bank firmware, bank 0 in the lower 16 KB"
required: false
bundled: false
priority: 1
size: 32768
crc32: "323952d1"
sha256: "d65bbf97058b9cdce8eaebf74124048e3b4e42dca1bd42be316747bbc27dc124"
@@ -267,10 +283,9 @@ files:
note: "First candidate of the //c and //c PAL profiles, third of the //c Plus chain. Bank 0 is mapped at reset, the $C028 ROMBANK switch selects the other. Identical to 3420033a.256 with its first 256 bytes zeroed."
- name: "apple2c-16K.rom"
path: "roms/apple2c-16K.rom"
group: {iic: 2, boot: 5}
description: "Apple //c ROM 255, 16 KB, MAME apple2c a2c.128"
required: false
bundled: false
priority: 2
size: 16384
crc32: "f0edaa1b"
sha256: "3ca1c8a27bf111aa0f4dc9372c5e6404457adb9a458ce32ae4b03a7e989e0c76"
@@ -280,10 +295,9 @@ files:
note: "Second candidate of the //c chain, loaded at $C000."
- name: "3420033a.256"
path: "roms/3420033a.256"
group: {iic: 3, boot: 6}
description: "Apple //c ROM 0, UniDisk 3.5 firmware, MAME apple2c0 342-0033-A"
required: false
bundled: false
priority: 3
size: 32768
crc32: "c8b979b3"
sha256: "678d5c9d374664d2ee94ba9c9564d26a917b31116b07c46df30a3e82c640885b"
@@ -293,10 +307,9 @@ files:
note: "Third candidate of the //c chain."
- name: "apple2cp.rom"
path: "roms/apple2cp.rom"
group: {iic-plus: 1}
description: "Apple //c Plus two-bank firmware, MAME apple2cp 341-0625-a.256"
required: false
bundled: false
priority: 1
aliases: ["apple2c-plus.rom"]
size: 32768
crc32: "0b996420"
@@ -307,10 +320,9 @@ files:
note: "First candidate of the //c Plus profile. apple2c-plus.rom is probed second and apple2c-32Kv0.rom third."
- name: "apple2_char.rom"
path: "roms/apple2_char.rom"
group: {char: 2, char-iie-unenhanced: 3}
description: "Apple ][ and ][+ character generator, 2 KB uppercase set"
required: false
bundled: false
priority: 1
size: 2048
sha256: "08f5d22230481019844492dde0a29a018cb193712a9e4a43770a3870608f28de"
sha1: "f9d312f128c9557d9d6ac03bfad6c3ddf83e5659"
@@ -319,10 +331,9 @@ files:
note: "Sole candidate of the ][ and ][+ profiles and the last fallback of every //e-class chain."
- name: "apple2e_char.rom"
path: "roms/apple2e_char.rom"
group: {char: 1}
description: "Apple //e Enhanced character generator 342-0265-A, 4 KB with MouseText"
required: false
bundled: false
priority: 1
aliases: ["apple2e_char_us.rom"]
size: 4096
sha256: "52c3b87900ac939f6525402cab1ccfd8f8259290fc6df54da48fb4c98ae3ed0f"
@@ -332,10 +343,9 @@ files:
note: "First candidate of the //e Enhanced, //c and //c Plus profiles. The same dump answers to apple2e_char_us.rom in the locale picker, and the fetcher writes both names."
- name: "apple2e_char_us_unenh.rom"
path: "roms/apple2e_char_us_unenh.rom"
group: {char-iie-unenhanced: 1}
description: "Apple //e Unenhanced character generator 342-0133-A, 4 KB"
required: false
bundled: false
priority: 1
aliases: ["apple2e_char_2k.rom", "342-0133-a.chr.rom"]
size: 4096
sha256: "ed5bdd4afa509134e85f1d020685af7ff50e279226eb869a17825b471cc1634c"
@@ -629,9 +639,8 @@ files:
note: "The Apple Parallel Interface leaves its slot empty without it. The fetcher extracts it from the MAME a2pic set as 341-0057.7b."
- name: "videx_videoterm_v24_60hz.bin"
path: "roms/videx_videoterm_v24_60hz.bin"
group: {videoterm: 1}
description: "Videx Videoterm firmware v2.4 with the 60 Hz CRTC table, 2 KB, MAME a2videoterm 6.ic6.bin"
required: false
priority: 1
size: 2048
crc32: "5776fa24"
sha256: "420da3867e489824f5fc0377c287c48a125296f19e1306df764e8f63bd23b00a"
@@ -641,9 +650,8 @@ files:
note: "First firmware candidate of the Videoterm card. The 50 Hz dump is probed second. With neither the slot stays empty. The fetcher extracts it from the MAME a2vidtrm set."
- name: "videx_videoterm_v24_50hz.bin"
path: "roms/videx_videoterm_v24_50hz.bin"
group: {videoterm: 2}
description: "Videx Videoterm firmware v2.4 with the 50 Hz CRTC table, 1 KB, MAME a2videoterm videx videoterm rom 2.4.bin"
required: false
priority: 2
size: 1024
crc32: "bbe3bb28"
sha256: "616f4d9f81a7a4ea0fa918842a05dfb3b503927776d2bfe97e6950b5431b562e"
+6 -8
View File
@@ -47,13 +47,18 @@ notes: |
General MIDI SoundFont works. The Mercury unit is compiled out
(Makefile:120-123).
groups:
ipl:
required: true
font:
required: true
files:
- name: "iplrom.dat"
system: sharp-x68000
path: "iplrom.dat"
group: ipl
priority: 1
required: true
size: 131072
source_ref: "SDL/SDL2/winx68k.cpp:277-279,288-307"
note: >
@@ -67,7 +72,6 @@ files:
path: "iplromxv.dat"
group: ipl
priority: 2
required: true
size: 131072
source_ref: "SDL/SDL2/winx68k.cpp:277-279,288-307"
note: "X68000 XVI IPL ROM, read when iplrom.dat is absent."
@@ -77,7 +81,6 @@ files:
path: "iplromco.dat"
group: ipl
priority: 3
required: true
size: 131072
source_ref: "SDL/SDL2/winx68k.cpp:277-279,288-307"
note: "X68000 Compact IPL ROM, read when the first two names are absent."
@@ -87,7 +90,6 @@ files:
path: "iplrom30.dat"
group: ipl
priority: 4
required: true
size: 131072
source_ref: "SDL/SDL2/winx68k.cpp:277-279,288-307"
note: "X68030 IPL ROM, read when the three other names are absent."
@@ -97,7 +99,6 @@ files:
path: "cgrom30.dat"
group: font
priority: 1
required: true
size: 786432
source_ref: "SDL/SDL2/winx68k.cpp:280-282,317-331"
note: >
@@ -110,7 +111,6 @@ files:
path: "cgrom30.tmp"
group: font
priority: 2
required: true
unsourceable: "rendered from TrueType fonts by the font generator, no canonical file"
size: 786432
source_ref: "SDL/SDL2/winx68k.cpp:280-282,317-331"
@@ -121,7 +121,6 @@ files:
path: "cgrom.dat"
group: font
priority: 3
required: true
size: 786432
source_ref: "SDL/SDL2/winx68k.cpp:280-282,317-331"
note: "X68000 character generator ROM, read when neither X68030 font is present."
@@ -131,7 +130,6 @@ files:
path: "cgrom.tmp"
group: font
priority: 4
required: true
unsourceable: "rendered from TrueType fonts by the font generator, no canonical file"
size: 786432
source_ref: "SDL/SDL2/winx68k.cpp:280-282,317-331, SDL/tool/create_cgrom.c:20"
+6 -6
View File
@@ -40,6 +40,12 @@ systems:
# <system_dir>/keropi/sram.dat (auto-created)
# <system_dir>/keropi/config (auto-created, core settings)
groups:
ipl:
required: true
font:
required: true
files:
# IPL ROM, the main system BIOS. The core tries four filenames in order and
# uses the first one found. Only one is needed. iplrom.dat is the original X68000,
@@ -51,7 +57,6 @@ files:
group: ipl
priority: 1
size: 131072
required: true
note: >
X68000 IPL ROM (original model). 128 KB, loaded at IPL buffer offset 0x20000.
The core tries iplrom.dat first, then iplrom30.dat, iplromco.dat, iplromxv.dat
@@ -63,7 +68,6 @@ files:
group: ipl
priority: 2
size: 131072
required: true
note: >
X68030 IPL ROM. Alternative to iplrom.dat for X68030 model emulation.
Only used if iplrom.dat is not found.
@@ -74,7 +78,6 @@ files:
group: ipl
priority: 3
size: 131072
required: true
note: >
X68000 Compact IPL ROM. Alternative to iplrom.dat.
Only used if iplrom.dat and iplrom30.dat are not found.
@@ -85,7 +88,6 @@ files:
group: ipl
priority: 4
size: 131072
required: true
note: >
X68000 XVI IPL ROM. Last fallback in the IPL search order.
Only used if the three other IPL variants are not found.
@@ -99,7 +101,6 @@ files:
size: 786432
group: font
priority: 1
required: true
note: >
X68000 character generator ROM. 768 KB, provides the font glyphs for text
display. If missing, the core falls back to cgrom.tmp (user-generated font
@@ -111,7 +112,6 @@ files:
size: 786432
group: font
priority: 2
required: true
unsourceable: "generated by WinX68k from the host fonts, no canonical file"
note: >
Alternative font file, used as fallback when cgrom.dat is absent.
+4 -4
View File
@@ -104,7 +104,7 @@ files:
system: flash
required: true
bundled: true
variant_group: "ruffle-core"
selection_slot: "ruffle-core"
size: 90386
md5: 5b1d64812875a1341ebd2a611e9324a1
sha1: 0eabbed786f3b8e5656d123e9f4573f918ba63d8
@@ -119,7 +119,7 @@ files:
system: flash
required: true
bundled: true
variant_group: "ruffle-core"
selection_slot: "ruffle-core"
size: 13107470
md5: 834f85979115fd740943a782887d0ab0
sha1: d27da38e4d37727a44bf04d7690a09135fad7115
@@ -134,7 +134,7 @@ files:
system: flash
required: true
bundled: true
variant_group: "ruffle-core"
selection_slot: "ruffle-core"
size: 94169
md5: 5aee868a91c066cc15f8b06999af690b
sha1: 45815723a1bdf4229e289906bf4e52dbfd78da56
@@ -149,7 +149,7 @@ files:
system: flash
required: true
bundled: true
variant_group: "ruffle-core"
selection_slot: "ruffle-core"
size: 13323601
md5: fe843bd0152c714f0449493b0193108f
sha1: fea8e60e86cba7a63258626b13e6adb69ed110f9
+4 -3
View File
@@ -58,11 +58,14 @@ notes: |
or MPEG ROM path is passed, so no other firmware is read.
ref: yabause/src/libretro/libretro.c:1078-1087, yabause/src/libretro/libretro.c:1898-1902
groups:
saturn-bios:
required: true
files:
- name: "saturn_bios.bin"
system: sega-saturn
group: saturn-bios
required: true
max_size: 524288
validation: [max_size]
note: "Any region. Second choice for every disc region."
@@ -71,7 +74,6 @@ files:
- name: "sega_101.bin"
system: sega-saturn
group: saturn-bios
required: true
region: [japan, asia-ntsc, south-korea]
max_size: 524288
validation: [max_size]
@@ -81,7 +83,6 @@ files:
- name: "mpr-17933.bin"
system: sega-saturn
group: saturn-bios
required: true
region: [north-america, europe, oceania, asia-pal, brazil, latin-america]
max_size: 524288
validation: [max_size]
+4 -3
View File
@@ -80,13 +80,16 @@ notes: |
Both build the pi4-update tip and patch the home directory to
/storage/.config/yabasanshiro.
groups:
saturn-bios:
required: true
files:
- name: "saturn_bios.bin"
system: sega-saturn
mode: libretro
group: saturn-bios
priority: 1
required: true
note: "Primary Saturn BIOS. Any region accepted."
source_ref: "yabause/src/libretro/libretro.c:1048"
@@ -95,7 +98,6 @@ files:
mode: libretro
group: saturn-bios
priority: 2
required: true
note: "Saturn BIOS v1.01 (Japan). Fallback if saturn_bios.bin missing."
source_ref: "yabause/src/libretro/libretro.c:1052"
@@ -104,6 +106,5 @@ files:
mode: libretro
group: saturn-bios
priority: 3
required: true
note: "Saturn BIOS v1.003 (NA/EU). Last fallback."
source_ref: "yabause/src/libretro/libretro.c:1056"
+4 -3
View File
@@ -47,12 +47,15 @@ notes: |
BIOS loading: retro_load_game() at yabause/src/libretro/libretro.c:1035-1049.
Core load: LoadBios() at yabause/src/memory.c:1260-1263, T123Load() at yabause/src/memory.h:196-265.
groups:
saturn-bios:
required: true
files:
- name: "saturn_bios.bin"
system: sega-saturn
group: saturn-bios
priority: 1
required: true
hle_fallback: true
max_size: 524288
validation: [max_size]
@@ -63,7 +66,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 2
required: true
hle_fallback: true
max_size: 524288
validation: [max_size]
@@ -74,7 +76,6 @@ files:
system: sega-saturn
group: saturn-bios
priority: 3
required: true
hle_fallback: true
max_size: 524288
validation: [max_size]
+4 -3
View File
@@ -78,6 +78,10 @@ notes: |
XXH128 hashes used for ROM identification only, not validation.
All file loading validates size only.
groups:
ipl:
required: true
files:
- name: "sega_101.bin"
system: sega-saturn
@@ -98,7 +102,6 @@ files:
region: [japan]
group: ipl
priority: 1
required: true
mode: libretro
size: 524288
validation: [size]
@@ -113,7 +116,6 @@ files:
region: [north-america, europe, asia-ntsc, asia-pal, brazil, latin-america]
group: ipl
priority: 2
required: true
mode: libretro
size: 524288
validation: [size]
@@ -127,7 +129,6 @@ files:
system: sega-saturn
group: ipl
priority: 3
required: true
mode: libretro
size: 524288
validation: [size]
-1
View File
@@ -1158,7 +1158,6 @@ files:
required: false
bundled: true
system: jupiter-ace
variant_group: "jupiter-ace-rom"
source_ref: "src/ALTERNATEROMS:11-12, src/start.c:4877-4881"
note: "Jupiter Ace ROM patched by Dutra Lacerda, distinct from the root ace.rom."
+21 -3
View File
@@ -497,6 +497,19 @@
"type": "string"
}
},
"groups": {
"description": "The sets of entries the code takes one of, by name, with the requirement of each. A member names its sets with group and writes no required of its own: it is required when one of its sets is.",
"type": "object",
"minProperties": 1,
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": ["required"],
"properties": {
"required": {"type": "boolean"}
}
}
},
"files": {
"type": "array",
"items": {
@@ -679,10 +692,11 @@
"minimum": 0
},
"group": {
"description": "Entries of one profile sharing a group are one need: the code loads one of them (the first it finds, in priority order where the source states one) and holding any member fills it. required states the set's requirement and is the same on every member. A list puts a file in several sets, a fallback two machine models share.",
"description": "The sets of the profile's groups map this entry belongs to. A set is one need: the code loads one member (the first it finds, in priority order where the source states one) and holding any member fills it. A list puts a file in several sets, a fallback two machine models share, and a map from set to rank gives its place in each when the places differ (priority otherwise). The entry writes no required: it is derived from its sets.",
"oneOf": [
{"type": "string", "minLength": 1},
{"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}
{"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
{"type": "object", "minProperties": 1, "additionalProperties": {"type": ["integer", "null"], "minimum": 0}}
]
},
"region_check": {
@@ -701,7 +715,8 @@
"directory"
]
},
"variant_group": {
"selection_slot": {
"description": "Files one core chooses between by a rule other than first found: the disc's territory, a core option, a feature probe. They fill one slot of the core whatever system each is filed under, region filtering compares them together, and same-named entries in different slots stay apart. A member does not stand in for another: entries that do are a group.",
"type": "string",
"minLength": 1
},
@@ -941,6 +956,9 @@
]
}
},
{
"not": {"required": ["group", "required"]}
},
{
"if": {
"properties": {
+142 -22
View File
@@ -3,32 +3,88 @@
A profile writes ``group:`` on the entries of one search list. Yabause tries
saturn_bios.bin, sega_101.bin, then mpr-17933.bin and loads the first it
finds (libretro.c:1035-1049): it needs one of them and none in particular.
``required`` on a member states the set's requirement, and ``priority`` keeps
the order the code reads them in.
The requirement belongs to the set, in the profile's ``groups:`` map, and a
member's ``required`` is derived from the sets it is in: true when one of
them is required. A fallback two machine models share (pom2's apple2.rom)
then needs no value of its own. ``priority`` keeps the order the code reads
the members in.
Holding one member fills the set, so the other members are not missing. A
set nobody holds is one gap, reported under its first member, never one gap
per member. Every reader settles sets through ``settle_sets`` so that verify,
the gap report and the packs agree on what is missing.
set nobody holds is one gap, reported under its first member with the set's
requirement, never one gap per member. A --required-only build keeps one
member of a required set, the first the code would load among those held.
Every reader goes through this module so that verify, the gap report, the
packs and the manifests agree.
"""
from __future__ import annotations
from collections.abc import Hashable, Iterable, Sequence
from collections.abc import Callable, Hashable, Iterable, Sequence
from dataclasses import dataclass
_UNRANKED = 1 << 30
def groups_of(entry: dict) -> tuple[str, ...]:
"""The sets an entry belongs to: one name, or a list for a file two
machine models both fall back on."""
"""The sets an entry belongs to: one name, a list for a file two machine
models both fall back on, or a map from set to the entry's rank there."""
value = entry.get("group")
if not value:
return ()
values = value if isinstance(value, list) else [value]
values = value if isinstance(value, (list, dict)) else [value]
return tuple(str(v) for v in values if v)
def rank_in(entry: dict, group: str) -> int | None:
"""The rank of an entry in one of its sets: the map's value when the
entry ranks differently in each (pom2's apple2.rom is second for the ][
and third at boot), else its priority."""
value = entry.get("group")
if isinstance(value, dict) and isinstance(value.get(group), int):
return value[group]
priority = entry.get("priority")
return priority if isinstance(priority, int) else None
def set_requirements(profile: dict) -> dict[str, bool]:
"""The requirement of each set the profile declares."""
declared = profile.get("groups") or {}
return {
str(name): bool((spec or {}).get("required", True))
for name, spec in declared.items()
}
def derive_member_requirements(profile: dict) -> None:
"""Write on each member the requirement its sets give it.
Read once when a profile is loaded, so every reader sees ``required``
as it always has. A member is required when one of its sets is.
"""
requirements = set_requirements(profile)
for entry in profile.get("files") or []:
if not isinstance(entry, dict):
continue
names = groups_of(entry)
if names and "required" not in entry:
entry["required"] = any(requirements.get(n, True) for n in names)
def required_groups(entry: dict, profile: dict) -> list[str]:
"""The required sets of its profile an entry is a member of."""
requirements = set_requirements(profile)
return [n for n in groups_of(entry) if requirements.get(n, True)]
def set_fields(entry: dict, profile: dict) -> dict:
"""What a --required-only build reads on a core file to keep one member
of a set: the entry's required sets, each with its rank there."""
sets = required_groups(entry, profile)
if not sets:
return {}
return {"required_groups": {group: rank_in(entry, group) for group in sets}}
def set_keys(owner: Hashable, entry: dict) -> tuple[tuple, ...]:
"""The keys of an entry's sets, scoped to its owner (a profile, or a
profile under one build)."""
@@ -45,39 +101,48 @@ def slot_set_keys(owner: Hashable, entries: Iterable[dict]) -> tuple[tuple, ...]
return tuple(keys)
def _rank(entry: dict, position: int) -> tuple[int, int]:
priority = entry.get("priority")
return (priority if isinstance(priority, int) else _UNRANKED, position)
def _rank(rank: int | None, position: int) -> tuple[int, int]:
return (rank if isinstance(rank, int) else _UNRANKED, position)
@dataclass
class Standing:
"""The member kept as the one gap of the sets nobody holds."""
others: list[str]
required: bool
def settle_sets(
members: Sequence[tuple[tuple[tuple, ...], dict, bool]],
) -> tuple[set[int], dict[int, list[str]]]:
set_required: Callable[[tuple], bool] = lambda _key: True,
) -> tuple[set[int], dict[int, Standing]]:
"""Which unheld members are excused, and which one stands for its set.
``members`` lists ``(set keys, entry, fills)`` in the order the profile
declares them, where ``fills`` says the member is held (or answered by a
declaration that reports it). Returns the positions to leave out of a
report and, for each set no member fills, the position kept as its one
gap with the names of the others. A member fills or not on its own: a
held one is never excused, and an unheld one stays reported when it
stands for at least one unfilled set.
gap with the names of the others and the set's requirement. A member
fills or not on its own: a held one is never excused, and an unheld one
stays reported when it stands for at least one unfilled set.
"""
by_set: dict[tuple, list[int]] = {}
for position, (keys, _entry, _fills) in enumerate(members):
for key in keys:
by_set.setdefault(key, []).append(position)
standing: dict[int, list[str]] = {}
for positions in by_set.values():
standing: dict[int, Standing] = {}
for key, positions in by_set.items():
if any(members[p][2] for p in positions):
continue
first = min(positions, key=lambda p: _rank(members[p][1], p))
names = standing.setdefault(first, [])
first = min(positions, key=lambda p: _rank(rank_in(members[p][1], key[1]), p))
held_up = standing.setdefault(first, Standing([], False))
held_up.required = held_up.required or set_required(key)
for p in positions:
name = str(members[p][1].get("name", ""))
if p != first and name not in names:
names.append(name)
if p != first and name not in held_up.others:
held_up.others.append(name)
excused = {
position
@@ -85,3 +150,58 @@ def settle_sets(
if keys and not fills and position not in standing
}
return excused, standing
def required_only_spares(
entries: Sequence[dict],
owner: Callable[[dict], Hashable],
held: Callable[[dict], bool],
gone: Callable[[dict], bool] = lambda _entry: False,
sets: Callable[[dict], dict[str, int | None]] = lambda e: e.get("required_groups") or {},
) -> set[int]:
"""The ids of the held members a --required-only build leaves out.
``sets`` maps the required sets of an entry to its rank in each: a core
file of a platform pack carries them as ``required_groups``.
A required set needs one file: the build keeps the member the code
would load first among those it holds and still carries (``gone`` says
a region filter took it), by ``priority`` then declaration order, and
drops the others. A member of an optional set is not touched here,
nor one that another required set of its own still needs.
"""
candidates: dict[tuple, list[tuple[tuple[int, int], int]]] = {}
for position, entry in enumerate(entries):
if not held(entry) or gone(entry):
continue
for group, rank in sets(entry).items():
candidates.setdefault((owner(entry), group), []).append(
(_rank(rank, position), position)
)
kept: set[int] = set()
members: set[int] = set()
for ranked in candidates.values():
members.update(position for _rank_key, position in ranked)
kept.add(min(ranked)[1])
return {id(entries[p]) for p in members - kept}
def core_file_spares(
entries: Sequence[dict], gone: Callable[[dict], bool] = lambda _entry: False,
) -> set[int]:
"""The core files of a platform pack a --required-only build leaves out.
A set the platform declares a member of is carried by that declaration,
so its other members are spares. Otherwise one held member per required
set stays, as in an emulator pack. Read by the builder, the manifest
and verify alike.
"""
answered = {id(e) for e in entries if e.get("set_declared")}
rest = [e for e in entries if id(e) not in answered]
return answered | required_only_spares(
rest,
owner=lambda e: e.get("source_profile") or e.get("profile") or "",
held=lambda e: e.get("in_repo", True) is not False,
gone=gone,
)
+3
View File
@@ -22,6 +22,8 @@ import zipfile
from pathlib import Path
from typing import Any, TextIO
from alternatives import derive_member_requirements
# Every build script imports this module. verify.py, slots.py, validate_pr.py
# and cross_reference.py started under 3.8 and stopped halfway on a
# str.removeprefix AttributeError, which named no version.
@@ -2346,6 +2348,7 @@ def load_emulator_profiles(
if "emulator" not in profile:
continue
_normalize_hash_fields(profile)
derive_member_requirements(profile)
profiles[f.stem] = profile
_emulator_profiles_cache[cache_key] = profiles
return profiles
+10 -5
View File
@@ -23,7 +23,7 @@ from collections import Counter
from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from alternatives import set_keys, settle_sets
from alternatives import set_keys, set_requirements, settle_sets
from common import (
platform_arg,
ProfileSelectionError,
@@ -697,7 +697,7 @@ def slot_key(f: dict, standalone: bool = False) -> tuple:
f.get("archive"),
system_dir_path(f, where or fname),
f.get("system"),
f.get("variant_group"),
f.get("selection_slot"),
f.get("mode", "both"),
read_from_save_dir(f, standalone),
)
@@ -886,7 +886,7 @@ def _cross_reference_profile(
archive_key = (
archive,
f.get("system"),
f.get("variant_group"),
f.get("selection_slot"),
f.get("mode", "both"),
)
if archive_key not in archive_gaps:
@@ -969,12 +969,17 @@ def _cross_reference_profile(
# nobody holds is one gap under its first member (alternatives.py), as
# verify and the packs count it.
grouped = [r for r in set_records if r[0]]
excused, standing = settle_sets([(keys, f, fills) for keys, f, fills, _l, _r in grouped])
requirements = set_requirements(profile)
excused, standing = settle_sets(
[(keys, f, fills) for keys, f, fills, _l, _r in grouped],
lambda key: requirements.get(key[1], True),
)
for at, (_keys, member, _fills, rows, set_row) in enumerate(grouped):
if set_row is None or rows is None:
continue
if at in standing:
set_row["alternatives"] = standing[at]
set_row["alternatives"] = standing[at].others
set_row["required"] = standing[at].required
if at in excused:
rows.remove(set_row)
fates[position[id(member)]] = "other_versions"
+25 -5
View File
@@ -36,7 +36,7 @@ import zipfile
from pathlib import Path, PurePosixPath
sys.path.insert(0, os.path.dirname(__file__))
from alternatives import settle_sets, slot_set_keys
from alternatives import core_file_spares, settle_sets, slot_set_keys
from common import resolve_platform_cores as _platform_cores
from common import (
installed_data_refs,
@@ -1295,8 +1295,13 @@ def generate_pack(
db, bios_dir, zip_contents, data_registry, validation_index,
validation_owners, offline, profiles=emu_profiles,
)
spares = core_file_spares(
core_files,
lambda fe: bool(region_drops)
and extra_region_key(fe, declared_root(config)) in region_drops,
) if required_only else set()
for fe in core_files:
if required_only and fe.get("required") is False:
if required_only and (fe.get("required") is False or id(fe) in spares):
continue
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
if region_drops and extra_region_key(fe, declared_root(config)) in region_drops:
@@ -1434,8 +1439,13 @@ def generate_pack(
if system_filter:
unfolded = _extras_for_systems(unfolded, system_filter)
prefix = _detect_extras_prefix(config, base_dest)
unfolded_spares = core_file_spares(
unfolded,
lambda fe: bool(region_drops)
and extra_region_key(fe, declared_root(config)) in region_drops,
) if required_only else set()
for fe in unfolded:
if required_only and fe.get("required") is False:
if required_only and (fe.get("required") is False or id(fe) in unfolded_spares):
continue
if region_drops and extra_region_key(fe, declared_root(config)) in region_drops:
continue
@@ -1826,9 +1836,13 @@ def generate_emulator_pack(
# there (raze's seven SW.GRP): the first one the core accepts
# fills the slot, as verify --emulator credits it, and the slot
# has one outcome however many alternatives it lists.
spares = emulator_required_spares(
emu_name, profile, files, standalone, region_drops, db,
validation_index, zip_contents, data_registry,
) if required_only else set()
slots: dict[str, list[dict]] = {}
for fe in files:
if required_only and fe.get("required") is False:
if required_only and (fe.get("required") is False or id(fe) in spares):
continue
if fe.get("archive"):
continue
@@ -4398,8 +4412,13 @@ def _manifest_core_entries(
db, bios_dir, zip_contents, data_registry, validation_index or {},
owners, offline, profiles=profiles,
)
spares = core_file_spares(
core_files,
lambda fe: bool(region_drops)
and extra_region_key(fe, declared_root(config)) in region_drops,
) if required_only else set()
for fe in core_files:
if required_only and fe.get("required") is False:
if required_only and (fe.get("required") is False or id(fe) in spares):
continue
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
if not dest:
@@ -5770,6 +5789,7 @@ from packextras import ( # noqa: E402,F401
extras_for_systems as _extras_for_systems,
platform_region_groups,
emulator_region_drops,
emulator_required_spares,
_emulator_region_group,
expand_agnostic_entries,
undeclared_report,
+4 -4
View File
@@ -1115,7 +1115,7 @@ def _platform_export_rows(
),
"required": bool(entry.get("required", True)),
"region": _json_text(entry.get("region")),
"variant_group": _json_text(entry.get("variant_group")),
"selection_slot": _json_text(entry.get("selection_slot")),
"size": entry.get("size"),
"sha1": _json_text(entry.get("sha1")),
"sha256": _json_text(entry.get("sha256")),
@@ -1371,7 +1371,7 @@ def _write_sqlite_export(
CREATE TABLE platform_files (
platform_id TEXT NOT NULL, system TEXT NOT NULL, name TEXT NOT NULL,
destination TEXT NOT NULL, required INTEGER NOT NULL,
region TEXT, variant_group TEXT, size INTEGER,
region TEXT, selection_slot TEXT, size INTEGER,
sha1 TEXT, sha256 TEXT, md5 TEXT, crc32 TEXT,
status TEXT, category TEXT, collection_path TEXT, resolved_sha1 TEXT,
zipped_file TEXT, hash_match_mandatory INTEGER, mandatory_declared INTEGER,
@@ -1454,7 +1454,7 @@ def _write_sqlite_export(
connection.executemany(
"INSERT INTO platform_files VALUES "
"(:platform_id, :system, :name, :destination, :required, :region, "
":variant_group, :size, :sha1, :sha256, :md5, :crc32, :status, :category, "
":selection_slot, :size, :sha1, :sha256, :md5, :crc32, :status, :category, "
":collection_path, :resolved_sha1, :zipped_file, :hash_match_mandatory, "
":mandatory_declared, :curated, :shared_group, :mirror_of, :zip_digest)",
platform_files,
@@ -1698,7 +1698,7 @@ def generate_data_exports(
_csv_document(
[
"platform_id", "platform", "system", "name", "destination",
"required", "region", "variant_group", "size", "sha1",
"required", "region", "selection_slot", "size", "sha1",
"sha256", "md5", "crc32", "status", "category",
"collection_path", "resolved_sha1", *ENTRY_EXPORT_FIELDS,
],
+1 -1
View File
@@ -643,7 +643,7 @@ def _launcher_entry(
entry = {
key: report.get(key)
for key in (
"profile", "emulator", "systems", "system", "region", "variant_group",
"profile", "emulator", "systems", "system", "region", "selection_slot",
"required", "hle_fallback", "category",
)
}
+49 -10
View File
@@ -9,6 +9,7 @@ from __future__ import annotations
from collections.abc import Iterable
from common import PROFILE_IDENTITY_FIELDS, _norm_system_id, entry_system_ids
from alternatives import core_file_spares, required_only_spares, set_fields
from common import archive_members, holds_required_members
from common import declared_root, expand_platform_declared_names, platform_declarations
from common import load_emulator_profiles
@@ -388,8 +389,12 @@ def hidden_extras(
)
if system_ids:
extras = extras_for_systems(extras, system_ids)
spares = core_file_spares(
extras,
lambda fe: extra_region_key(fe, region_prefix) in (region_drops or set()),
) if required_only else set()
for fe in extras:
if required_only and fe.get("required") is False:
if required_only and (fe.get("required") is False or id(fe) in spares):
continue
dest = sanitize_pack_path(fe.get("destination", fe.get("name", "")))
if not dest or (region_drops and extra_region_key(fe, region_prefix) in region_drops):
@@ -640,7 +645,7 @@ def _agnostic_scan_extras(
"source_system": f.get("system"),
"source_systems": entry_system_ids(f, profile),
"region": f.get("region"),
"variant_group": f.get("variant_group"),
"selection_slot": f.get("selection_slot"),
"agnostic_scan": True,
}
extra["claim_order"] = (4, 0, emu_name)
@@ -796,7 +801,7 @@ def _companion_extras(
"source_system": seed.get("system"),
"source_systems": entry_system_ids(seed, profile),
"region": seed.get("region"),
"variant_group": seed.get("variant_group"),
"selection_slot": seed.get("selection_slot"),
"agnostic_scan": True,
}
extra["claim_order"] = (4, 0, emu_name)
@@ -970,7 +975,7 @@ def _archive_prefix_copies(
"source_system": archive_entry.get("system"),
"source_systems": entry_system_ids(archive_entry, profile),
"region": archive_entry.get("region"),
"variant_group": archive_entry.get("variant_group"),
"selection_slot": archive_entry.get("selection_slot"),
}
members = archive_members(archive_name, profile.get("files", []))
if members:
@@ -1354,7 +1359,8 @@ def _collect_emulator_extras(
"source_system": f.get("system"),
"source_systems": entry_system_ids(f, profile),
"region": f.get("region"),
"variant_group": f.get("variant_group"),
"selection_slot": f.get("selection_slot"),
**set_fields(f, profile),
}
# The same identity the first pass carries: without it the copy
# resolves on its name alone and a same-named file of another
@@ -1522,7 +1528,8 @@ def _report_extra(u: dict, name: str, dest: str) -> dict:
"source_system": u.get("system"),
"source_systems": u.get("systems", []),
"region": u.get("region"),
"variant_group": u.get("variant_group"),
"selection_slot": u.get("selection_slot"),
**{k: u[k] for k in ("required_groups", "set_declared") if k in u},
}
if u.get("members"):
extra["members"] = u["members"]
@@ -1795,9 +1802,9 @@ def extra_region_groups(
return (spellings or {}).get(_norm_system_id(sys_id), sys_id)
emulator = extra.get("source_emulator", "")
variant = extra.get("variant_group")
variant = extra.get("selection_slot")
if variant:
# A variant group is one slot of one core, whatever system each
# A selection slot is one slot of one core, whatever system each
# member is filed under: PicoDrive files its US Mega CD BIOS under
# sega-segacd and the EU/JP ones under sega-megacd, and find_bios
# picks one of the twelve. Keyed as emulator mode keys it.
@@ -1826,7 +1833,7 @@ def emulator_region_drops(
) -> set[str]:
"""Destinations an emulator-mode `--region` withdraws.
One group per system (or explicit variant_group) inside each profile, so
One group per system (or explicit selection_slot) inside each profile, so
a multi-system core such as O2EM keeps a fallback BIOS for every system
instead of letting one matching system empty another. The emulator pack
and `verify --emulator` both read this, keyed by pack destination.
@@ -1864,6 +1871,38 @@ def emulator_region_drops(
return region_mod.resolve_region_drops(region_groups, region_index, regions, held)
def emulator_required_spares(
emu_name: str,
profile: dict,
files: list[dict],
standalone: bool,
region_drops: set[str],
db: dict,
validation_index: dict,
zip_contents: dict | None,
data_registry: dict | None,
) -> set[int]:
"""The members of required sets an emulator --required-only pack leaves
out: one held member stays per set, the first the code loads among those
the pack still carries after the region filter. The pack and
verify --emulator both read this."""
from alternatives import groups_of, rank_in, required_groups
from packpaths import _resolve_destination
loose = [fe for fe in files if not fe.get("archive") and groups_of(fe)]
if not loose:
return set()
return required_only_spares(
loose,
owner=lambda _fe: emu_name,
held=lambda fe: _emulator_ships(
fe, emu_name, profile, db, validation_index, zip_contents, data_registry,
),
gone=lambda fe: _resolve_destination(fe, standalone) in region_drops,
sets=lambda fe: {g: rank_in(fe, g) for g in required_groups(fe, profile)},
)
def _emulator_ships(
file_entry: dict, emu_name: str, profile: dict, db: dict,
validation_index: dict, zip_contents: dict | None, data_registry: dict | None,
@@ -1904,7 +1943,7 @@ def _emulator_region_group(
Grouped together, geargrafx's LaserActive pac-n1.bin was dropped by
--emulator --region us and kept by --platform --region us.
"""
variant = file_entry.get("variant_group")
variant = file_entry.get("selection_slot")
if variant:
return f"{emu_name}:variant:{variant}"
system = file_entry.get("system")
+37 -6
View File
@@ -127,7 +127,7 @@ def resolve_slot_drops(
# A slot is a system AND a declared region: the Japanese and American
# PlayStation BIOS are not alternatives to each other, and comparing their
# ranks across regions would pick one territory's file for another's.
tiers: dict[tuple[str, tuple[str, ...], tuple], list[tuple[str, int | None]]] = {}
bucketed: dict[tuple[str, tuple[str, ...]], list[tuple[str, int | None, frozenset]]] = {}
for group_id, members in groups.items():
for destination, name in members:
if held is not None and destination not in held:
@@ -136,14 +136,20 @@ def resolve_slot_drops(
if entry is None:
keep.add(destination)
continue
# A rank orders the members of one set: px68k-sdl ranks its IPL
# and its font ROM lists each from 1, and the two never compete.
tier = tuple(sorted(entry["regions"]))
sets = tuple(sorted(entry.get("sets") or ()))
rank = None if entry.get("conflict") else entry["rank"]
tiers.setdefault((group_id, tier, sets), []).append((destination, rank))
bucketed.setdefault((group_id, tier), []).append(
(destination, rank, frozenset(entry.get("sets") or ()))
)
# A rank orders the members of one set: px68k-sdl ranks its IPL and its
# font ROM lists each from 1, and the two never compete. Candidates are
# compared when they share a set, and those in no set among themselves.
tiers: dict[tuple[str, tuple[str, ...], int], list[tuple[str, int | None]]] = {}
for (group_id, tier), found in bucketed.items():
for part, component in enumerate(_by_shared_set(found)):
tiers[(group_id, tier, part)] = component
for (group_id, tier, _sets), candidates in tiers.items():
for (group_id, tier, _part), candidates in tiers.items():
if len(candidates) < 2:
keep.update(dest for dest, _p in candidates)
continue
@@ -167,3 +173,28 @@ def resolve_slot_drops(
drop.update(dest for dest, _p in candidates if dest != winners[0])
return drop - keep, sorted(undecidable)
def _by_shared_set(
found: list[tuple[str, int | None, frozenset]],
) -> list[list[tuple[str, int | None]]]:
"""The candidates of one tier split where no set links them."""
parent = list(range(len(found)))
def root(i: int) -> int:
while parent[i] != i:
parent[i] = parent[parent[i]]
i = parent[i]
return i
first_of: dict[object, int] = {}
for i, (_dest, _rank, sets) in enumerate(found):
for key in sets or {None}:
if key in first_of:
parent[root(i)] = root(first_of[key])
else:
first_of[key] = i
parts: dict[int, list[tuple[str, int | None]]] = {}
for i, (dest, rank, _sets) in enumerate(found):
parts.setdefault(root(i), []).append((dest, rank))
return list(parts.values())
+19 -13
View File
@@ -124,27 +124,33 @@ def _systems_outside_profile(path: Path, document: object) -> list[str]:
def _group_requirement_split(path: Path, document: object) -> list[str]:
"""A group whose members disagree on required.
"""A set named by a member and not declared, declared and never used,
or a member that writes a required of its own.
The members of a group are one need, so required states the set's and
reads the same on each. A true on the first name only wrote the search
order into required, and the other names read as optional files.
The requirement belongs to the set, in the profile's groups map, and a
member's is derived from it. A value on the member is a second source
that can contradict the first: a true on the first name only wrote the
search order into required, and the other names read as optional.
"""
from alternatives import groups_of
if not isinstance(document, dict):
return []
seen: dict[str, set[bool]] = {}
for entry in document.get("files") or []:
label = path.relative_to(ROOT)
declared = set((document.get("groups") or {}).keys())
used: set[str] = set()
out: list[str] = []
for index, entry in enumerate(document.get("files") or []):
if not isinstance(entry, dict):
continue
for group in groups_of(entry):
seen.setdefault(group, set()).add(bool(entry.get("required", True)))
return [
f"{path.relative_to(ROOT)}: group {group} mixes required true and false"
for group, values in sorted(seen.items())
if len(values) > 1
]
names = groups_of(entry)
used.update(names)
if names and "required" in entry:
out.append(f"{label}: files[{index}] ({entry.get('name')}) is in a group "
"and writes required: the set's requirement is in groups")
out.extend(f"{label}: group {g} has no entry in groups" for g in sorted(used - declared))
out.extend(f"{label}: groups declares {g}, which no entry names" for g in sorted(declared - used))
return out
def _checks_without_values(path: Path, document: object) -> list[str]:
+42 -11
View File
@@ -37,7 +37,14 @@ import slots
sys.path.insert(0, os.path.dirname(__file__))
from hashing import parse_md5_list
from alternatives import set_keys, settle_sets, slot_set_keys
from alternatives import (
core_file_spares,
set_fields,
set_keys,
set_requirements,
settle_sets,
slot_set_keys,
)
from common import (
_foreign_tree,
_owner_tokens,
@@ -591,7 +598,7 @@ def find_undeclared_files(
f.get("archive"),
dest,
f.get("system"),
f.get("variant_group"),
f.get("selection_slot"),
region_key,
# Below the save directory each core is handed a folder
# of its own: two cores reading hiscore.dat there read
@@ -625,7 +632,7 @@ def find_undeclared_files(
archive,
f.get("system_dir"),
f.get("system"),
f.get("variant_group"),
f.get("selection_slot"),
region_key,
is_standalone,
)
@@ -640,7 +647,7 @@ def find_undeclared_files(
"systems": entry_system_ids(f, profile),
"system": f.get("system"),
"region": f.get("region"),
"variant_group": f.get("variant_group"),
"selection_slot": f.get("selection_slot"),
"name": archive,
"archive": archive,
"path": system_dir_path(f, archive),
@@ -738,7 +745,7 @@ def find_undeclared_files(
"systems": entry_system_ids(f, profile),
"system": f.get("system"),
"region": f.get("region"),
"variant_group": f.get("variant_group"),
"selection_slot": f.get("selection_slot"),
"name": fname,
"path": dest,
"required": f.get("required", False),
@@ -748,6 +755,7 @@ def find_undeclared_files(
"in_repo": in_repo,
"note": f.get("note", ""),
"checks": sorted(checks) if checks else [],
**set_fields(f, profile),
"source_ref": f.get("source_ref"),
"expected": _build_expected(f, checks),
**_identity_of(f),
@@ -785,7 +793,7 @@ def find_undeclared_files(
undeclared = [u for u in undeclared if id(u) not in settled]
undeclared.extend(added)
undeclared = _settle_core_sets(undeclared, set_records, settled)
undeclared = _settle_core_sets(undeclared, set_records, settled, profiles)
for entry in sorted(archive_entries.values(), key=lambda e: e["name"]):
undeclared.append(entry)
@@ -797,6 +805,7 @@ def _settle_core_sets(
undeclared: list[dict],
records: list[tuple[tuple, dict, bool, tuple[dict, dict | None] | None]],
launcher_settled: set[int],
profiles: dict[str, dict],
) -> list[dict]:
"""The core complement with each set of alternatives settled.
@@ -811,14 +820,23 @@ def _settle_core_sets(
excused, standing = settle_sets([
(keys, f, fills or (ref is not None and id(ref[0]) in launcher_settled))
for keys, f, fills, ref in grouped
])
], lambda key: set_requirements(profiles.get(key[0][0], {})).get(key[1], True))
declared_sets = {
key for keys, _f, _fills, ref in grouped if ref is None for key in keys
}
dropped: set[int] = set()
for position, (_keys, _f, _fills, ref) in enumerate(grouped):
for position, (keys, _f, _fills, ref) in enumerate(grouped):
if ref is None:
continue
entry, host = ref
required_keys = [k for k in keys if k[1] in entry.get("required_groups", ())]
if required_keys and all(k in declared_sets for k in required_keys):
# The platform declares a member of each of its required sets:
# under --required-only that declaration carries them.
entry["set_declared"] = True
if position in standing:
entry["alternatives"] = standing[position]
entry["alternatives"] = standing[position].others
entry["required"] = standing[position].required
if position not in excused:
continue
if host is not None:
@@ -1548,6 +1566,10 @@ def verify_platform(
)
not in region_drops
]
if required_only:
# One member of a required set, as the builder keeps it.
spares = core_file_spares(undeclared)
undeclared = [u for u in undeclared if id(u) not in spares]
_mark_unplaced(config, undeclared, profiles)
from packextras import ExtraResolver
@@ -2343,6 +2365,14 @@ def verify_emulator(
if fe.get("archive")
or _resolve_destination(fe, standalone) not in region_drops
]
if required_only:
from packextras import emulator_required_spares
spares = emulator_required_spares(
emu_name, profile, files, standalone, region_drops, db,
validation_index, zip_contents, data_registry,
)
files = [fe for fe in files if id(fe) not in spares]
# Check data directories (only notice if not cached)
for dd in deliverable(
@@ -2645,13 +2675,14 @@ def verify_emulator(
and result.get("reason") == fallback_reason),
)
for _dest, result, _required, _hle, entries in placed_results
])
], lambda key: set_requirements(profile).get(key[1], True))
for position, (dest, result, required, hle, _fe) in enumerate(placed_results):
if position in excused and result["status"] == Status.MISSING:
set_members.append(result)
continue
if position in standing:
result["alternatives"] = standing[position]
result["alternatives"] = standing[position].others
result["required"] = required = standing[position].required
details.append(result)
# Aggregate by destination (path if available, else name)
+72 -18
View File
@@ -6790,7 +6790,7 @@ class OneOfASearchList(unittest.TestCase):
self.addCleanup(os.chdir, previous)
self.db = {"files": {}, "indexes": {"by_md5": {}, "by_name": {},
"by_crc32": {}, "by_path_suffix": {}}}
for name in ("second.bin", "plain.bin"):
for name in ("second.bin", "third.bin", "plain.bin"):
data = name.encode() * 8
rel = f"bios/Test/Console/{name}"
Path(rel).parent.mkdir(parents=True, exist_ok=True)
@@ -6804,11 +6804,12 @@ class OneOfASearchList(unittest.TestCase):
def member(name: str, group: str, rank: int) -> dict:
return {"name": name, "system": "console-a", "group": group,
"priority": rank, "required": True}
"priority": rank}
self.profile = {
raw = {
"emulator": "Seq", "type": "libretro", "cores": ["seq"],
"systems": ["console-a"],
"groups": {"first": {"required": True}, "none": {"required": True}},
"files": [
member("first.bin", "first", 1),
member("second.bin", "first", 2),
@@ -6818,7 +6819,10 @@ class OneOfASearchList(unittest.TestCase):
{"name": "plain.bin", "system": "console-a", "required": True},
],
}
Path("emulators/seq.yml").write_text(yaml.safe_dump(self.profile))
Path("emulators/seq.yml").write_text(yaml.safe_dump(raw))
self.raw = raw
# What every reader sees: the profile as load_emulator_profiles gives it.
self.profile = load_emulator_profiles("emulators")["seq"]
self.config = {
"platform": "Seqs", "verification_mode": "existence",
"base_destination": "system", "cores": ["seq"],
@@ -6832,11 +6836,11 @@ class OneOfASearchList(unittest.TestCase):
result = self._verify()
reported = {d["name"]: d["status"] for d in result["details"]}
self.assertEqual(reported["second.bin"], "ok")
self.assertEqual(reported["third.bin"], "ok")
self.assertNotIn("first.bin", reported)
self.assertNotIn("third.bin", reported)
self.assertEqual(
sorted(d["name"] for d in result["set_members"]),
["first.bin", "none_b.bin", "third.bin"],
["first.bin", "none_b.bin"],
)
def test_a_set_none_holds_is_one_gap(self):
@@ -6848,7 +6852,7 @@ class OneOfASearchList(unittest.TestCase):
self.assertEqual(result["severity_counts"][Severity.WARNING], 1)
self.assertEqual(result["severity_counts"][Severity.INFO], 0)
self.assertEqual(result["status_counts"].get("missing"), 1)
self.assertEqual(result["total_files"], 3)
self.assertEqual(result["total_files"], 4)
def test_a_required_set_held_through_a_later_member_is_satisfied(self):
"""second.bin used to read required: false beside a required
@@ -6876,21 +6880,23 @@ class OneOfASearchList(unittest.TestCase):
)
with zipfile.ZipFile(zip_path) as zf:
packed = sorted(n for n in zf.namelist() if n != "README.txt")
self.assertEqual(packed, ["plain.bin", "second.bin"])
self.assertEqual(packed, ["plain.bin", "second.bin", "third.bin"])
self.assertEqual(result["severity_counts"]["ok"], len(packed))
lines = out.getvalue().splitlines()
self.assertEqual(
[line.split(": ", 1)[1] for line in lines if line.strip().startswith("MISSING:")],
["none_a.bin"],
)
self.assertIn("2 files packed, 1 missing", out.getvalue())
self.assertIn("3 files packed, 1 missing", out.getvalue())
def test_core_complement_reports_one_gap_per_set(self):
undeclared = find_undeclared_files(
self.config, "emulators", self.db, {"seq": self.profile}
)
by_name = {u["name"]: u for u in undeclared}
self.assertEqual(sorted(by_name), ["none_a.bin", "plain.bin", "second.bin"])
self.assertEqual(
sorted(by_name), ["none_a.bin", "plain.bin", "second.bin", "third.bin"]
)
self.assertTrue(by_name["second.bin"]["in_repo"])
self.assertFalse(by_name["none_a.bin"]["in_repo"])
self.assertEqual(by_name["none_a.bin"]["alternatives"], ["none_b.bin"])
@@ -6905,7 +6911,9 @@ class OneOfASearchList(unittest.TestCase):
undeclared = find_undeclared_files(
config, "emulators", self.db, {"seq": self.profile}
)
self.assertEqual(sorted(u["name"] for u in undeclared), ["plain.bin", "second.bin"])
self.assertEqual(
sorted(u["name"] for u in undeclared), ["plain.bin", "second.bin", "third.bin"]
)
def test_gap_report_counts_the_set_once(self):
import cross_reference
@@ -6919,14 +6927,14 @@ class OneOfASearchList(unittest.TestCase):
report: dict = {}
cross_reference._cross_reference_profile("seq", self.profile, {}, report, index)
gaps = {g["name"]: g for g in report["seq"]["gap_details"]}
self.assertEqual(sorted(gaps), ["none_a.bin", "plain.bin", "second.bin"])
self.assertEqual(sorted(gaps), ["none_a.bin", "plain.bin", "second.bin", "third.bin"])
self.assertEqual(gaps["none_a.bin"]["alternatives"], ["none_b.bin"])
self.assertEqual(report["seq"]["set_aside"]["other_versions"], 3)
self.assertEqual(report["seq"]["set_aside"]["other_versions"], 2)
def test_truth_names_no_member_required_on_its_own(self):
from truth import _fold_into, _new_truth_entry
entry = _new_truth_entry(self.profile["files"][0], "seq", None)
entry = _new_truth_entry(dict(self.profile["files"][0]), "seq", None)
self.assertNotIn("required", entry)
self.assertEqual(entry["_required_by"], set())
self.assertTrue(entry["one_of_required"])
@@ -6974,10 +6982,56 @@ class OneOfASearchList(unittest.TestCase):
from validate_schemas import _group_requirement_split, ROOT
path = ROOT / "emulators" / "seq.yml"
split = {"files": [{"name": "a", "group": "g", "required": True},
{"name": "b", "group": "g", "required": False}]}
self.assertEqual(len(_group_requirement_split(path, split)), 1)
self.assertEqual(_group_requirement_split(path, {"files": self.profile["files"]}), [])
own_value = {"groups": {"g": {"required": True}},
"files": [{"name": "a", "group": "g", "required": False},
{"name": "b", "group": "g"}]}
self.assertEqual(len(_group_requirement_split(path, own_value)), 1)
undeclared_set = {"files": [{"name": "a", "group": "g"}]}
self.assertEqual(len(_group_requirement_split(path, undeclared_set)), 1)
unused = {"groups": {"g": {"required": True}}, "files": [{"name": "a"}]}
self.assertEqual(len(_group_requirement_split(path, unused)), 1)
self.assertEqual(_group_requirement_split(path, self.raw), [])
def test_a_shared_fallback_takes_its_requirement_from_its_sets(self):
"""pom2 falls back on apple2e.rom for the //e it boots by default
and for the unenhanced //e it may be switched to. One value on the
file cannot say both: the sets carry it."""
from alternatives import derive_member_requirements
profile = {"groups": {"iie": {"required": True}, "iie-u": {"required": False}},
"files": [{"name": "apple2e_unenh.rom", "group": "iie-u"},
{"name": "apple2e.rom", "group": ["iie", "iie-u"]}]}
derive_member_requirements(profile)
self.assertEqual([f["required"] for f in profile["files"]], [False, True])
def test_required_only_keeps_one_held_member_per_required_set(self):
"""second.bin and third.bin are both held: a --required-only pack
carries second.bin, the first the code reads among those held, and
verify reports the same single file."""
from generate_pack import generate_emulator_pack
result = verify_emulator(["seq"], "emulators", self.db,
platforms_dir="platforms", required_only=True)
held = sorted(d["name"] for d in result["details"] if d["status"] == "ok")
self.assertEqual(held, ["plain.bin", "second.bin"])
with contextlib.redirect_stdout(io.StringIO()):
zip_path = generate_emulator_pack(
["seq"], "emulators", self.db, "bios", "out", offline=True,
platforms_dir="platforms", required_only=True,
)
with zipfile.ZipFile(zip_path) as zf:
packed = sorted(n for n in zf.namelist() if n != "README.txt")
self.assertEqual(packed, held)
def test_required_only_core_files_keep_one_member(self):
from alternatives import core_file_spares
undeclared = find_undeclared_files(
self.config, "emulators", self.db, {"seq": self.profile}
)
spares = core_file_spares(undeclared)
kept = sorted(u["name"] for u in undeclared if id(u) not in spares)
self.assertEqual(kept, ["none_a.bin", "plain.bin", "second.bin"])
if __name__ == "__main__":
unittest.main()
+4 -4
View File
@@ -36,9 +36,9 @@ class TheGroupFollowsWhatTheProfileSays(unittest.TestCase):
})
self.assertEqual(groups, ["clk:file:MSX/msx-american.rom"])
def test_a_variant_group_stays_one_slot(self):
def test_a_selection_slot_stays_one_slot(self):
self.assertEqual(
extra_region_groups({"source_emulator": "picodrive", "variant_group": "mcd",
extra_region_groups({"source_emulator": "picodrive", "selection_slot": "mcd",
"source_systems": ["sega-segacd", "sega-mega-cd"]}),
["picodrive:variant:mcd"],
)
@@ -91,10 +91,10 @@ class TheGroupTakesThePlatformSpelling(unittest.TestCase):
["sega-saturn"],
)
def test_file_and_variant_groups_are_untouched(self):
def test_file_and_selection_slots_are_untouched(self):
spellings = system_spellings(["sega-megacd"])
self.assertEqual(
extra_region_groups({"source_emulator": "picodrive", "variant_group": "mcd",
extra_region_groups({"source_emulator": "picodrive", "selection_slot": "mcd",
"source_system": "sega-megacd"}, spellings),
["picodrive:variant:mcd"],
)
+1 -1
View File
@@ -275,7 +275,7 @@ own package list, standalone emulators included, and is case-sensitive too, so
it gets a separate pack and a separate install manifest.
With `--target`, the fingerprint includes target cores so platforms
with different hardware filters get separate packs. Emulator and system packs
also retain system identity, `variant_group` and requested region. Same-named
also retain system identity, `selection_slot` and requested region. Same-named
regional files are never collapsed merely because their display label matches.
## Pack reproducibility
+4 -3
View File
@@ -603,7 +603,7 @@ look.
| Field | Description |
|-------|-------------|
| `name` | filename as the core expects it |
| `required` | true if the core needs this file to function. On a member of a `group`, the requirement of the set |
| `required` | true if the core needs this file to function. Not written on a member of a `group`: derived from the sets in `groups` |
| `system` | system ID this file belongs to (for multi-system profiles) |
| `systems` | the systems of the profile this file serves, when it serves several but not all (a MAME device set the machines of two systems load). Never written with `system` |
| `archive` | ROM set the file lives inside, for arcade entries (e.g. `neogeo.zip`) |
@@ -622,7 +622,8 @@ look.
| `region_check` | true if the core refuses to boot a game whose region does not match the BIOS |
| `fast_boot` | BIOS generation label the core uses to decide whether fast boot is available |
| `priority` | preference order when several BIOS satisfy the same slot, **lowest wins**. DuckStation's `FindBIOSImageInDirectory` keeps the image whose priority is lower, and its table de-prioritizes by raising the number: the buggy launch console sits at 50 and PS2 images at 100, while `scph5501` sits at 5. A core that walks an ordered search list, as PicoDrive does with `biosfiles_us/eu/jp`, maps onto the same field as 1, 2, 3. Only set it from the source. `--one-per-slot` reads it, comparing the members of one `group` |
| `group` | entries the code takes one of: it loads the first it finds (Yabause tries `saturn_bios.bin`, `sega_101.bin`, `mpr-17933.bin`), and holding any member fills the need. Verify, the gap report and the packs report a set nobody holds as one gap under its first member, and no member of a held set as missing. `required` is the same on every member, the order stays in `priority`. A list puts a file in several sets. Where the code keeps a list per region, each list is its own group (PicoDrive's `mega-cd-us`, `mega-cd-eu`, `mega-cd-jp`) |
| `group` | the sets of the profile's `groups:` map an entry belongs to. A set is one need: the code loads one member (the first it finds, as Yabause tries `saturn_bios.bin`, `sega_101.bin`, `mpr-17933.bin`) and holding any member fills it. Verify, the gap report and the packs report a set nobody holds as one gap under its first member, and no member of a held set as missing. A `--required-only` build keeps one member per required set, the first the code reads among those held. A list puts a file in several sets, a map from set to rank gives its place in each when it differs (pom2's `apple2.rom` is second for the ][ and third at boot). Where the code keeps a list per region, each list is its own set (PicoDrive's `mega-cd-us`, `mega-cd-eu`, `mega-cd-jp`) |
| `groups` (profile) | the requirement of each set, `{name: {required: bool}}`. A member writes no `required`: it is required when one of its sets is, so a fallback shared by a required set and an optional one needs no value of its own |
| `embedded` | true if the data is compiled into the binary and the external file is optional |
| `bundled` | true if the emulator's own release installs the file where it reads it, for the build `mode` names (all builds when `mode` is absent). Packs and the installer leave it out: the user already has it. A file the standalone release ships but the libretro core does not (PPSSPP's assets, Dolphin's Sys) is bundled with `mode: standalone` only |
| `not_bundled_on` | platforms (registry keys) whose package leaves out a file the release bundles: their packs bring it (Batocera installs hcl without its data) |
@@ -636,7 +637,7 @@ look.
| `path` | destination path relative to the system directory, or to the save directory under `load_from: save_dir` |
| `standalone_path` | where the standalone build reads the file, under its own data folder, when it differs from `path` (the libretro destination). Packs for a platform running the emulator standalone use it |
| `on_mismatch` | what the code does when a declared check fails: `reject` (default) or `warn` and run with it, for every check or check by check (`{size: warn, md5: reject}`) |
| `variant_group` | one slot of one core that several entries fill, whatever system each is filed under (PicoDrive's twelve Mega CD BIOS). Region selection keeps one per group |
| `selection_slot` | files one core chooses between by a rule other than first found (the disc's territory, a core option, a feature probe), one slot of the core whatever system each is filed under: PicoDrive's twelve Mega CD BIOS, picked by disc region, O2EM's four BIOS, picked by a core option. Region selection compares them together and keeps one per slot. A member does not stand in for another: entries that do are a `group` |
| `size_note` | how the code treats the file's size when no size field can say it (a read capped at 32 bytes, a file created empty when absent) |
| `type` | `directory` when the code reads a whole tree (an RTP, a folder of speech samples). `path` is then the directory, written with its trailing slash, and the entry stands for every file the collection holds under it. A name ending in `/` requires it |
| `description` | what this file is |