mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: keep install manifests and release assets true
This commit is contained in:
1 parent
4f67e3cad3
commit
08bce47668
22 files changed
+878
-263
No files matched your search
+5
-9
@@ -15,10 +15,6 @@ node_modules/
|
||||
docs/
|
||||
|
||||
# Large files stored as GitHub Release assets (> 50MB)
|
||||
bios/Arcade/Arcade/Firmware.19.0.0.zip
|
||||
bios/Arcade/Arcade/maclc3.zip
|
||||
bios/Nintendo/Nintendo DS/dsi_nand.bin
|
||||
bios/Other/Batocera42/dsi_nand.bin
|
||||
bios/Sony/PlayStation 3/PS3UPDAT.PUP
|
||||
bios/Sony/PlayStation 3/.variants/PS3UPDAT.PUP.ed8ab192
|
||||
bios/Sony/PlayStation Vita/PSVUPDAT.PUP
|
||||
@@ -66,20 +62,20 @@ tmp/
|
||||
# FBA2012 Toaplan samples (>100MB)
|
||||
bios/Arcade/fba2012/samples/fireshrk.zip
|
||||
bios/Arcade/fba2012/samples/ghox.zip
|
||||
bios/Arcade/fba2012/samples/samesame.zip
|
||||
bios/Arcade/fba2012/samples/tekipaki.zip
|
||||
bios/Arcade/fba2012/samples/vimana.zip
|
||||
bios/Arcade/fba2012/samples/fireshrk.zip
|
||||
bios/Arcade/fba2012/samples/samesame.zip
|
||||
bios/Arcade/fba2012/samples/vimana.zip
|
||||
bios/Nintendo/Switch/Firmware_batocera43.zip
|
||||
bios/Nintendo/DS/.variants/dsi_nand.bin.8b79a73c
|
||||
|
||||
# Wii NAND backup (528MB, fetched from large-files release)
|
||||
bios/Nintendo/Wii/nand.bin
|
||||
|
||||
# FBNeo audio samples (97MB and 155MB, fetched from large-files release)
|
||||
# FBNeo audio samples (96MB, 148MB and 199MB, fetched from large-files release)
|
||||
bios/Other/fbneo/fbneo/samples/donpachi.zip
|
||||
bios/Other/fbneo/fbneo/samples/sfz3mix.zip
|
||||
bios/Other/fbneo/fbneo/samples/twotiger.zip
|
||||
bios/Other/starboard/starboard-rootfs.tar.gz
|
||||
bios/Other/cspect/cspect-next-8gb.zip
|
||||
|
||||
# Output-directory locks (artifact_lock)
|
||||
.lock
|
||||
@@ -39,18 +39,18 @@ Every release ships `SHA256SUMS.txt` and a detached signature of it, checkable a
|
||||
|
||||
| Platform | Extracted size | Extract to | Download |
|
||||
|----------|---------------:|-----------|----------|
|
||||
| Batocera | 4.0 GB | `/userdata/bios/` | [Download](../../releases/latest) |
|
||||
| BizHawk | 2.2 GB | `Firmware/` | [Download](../../releases/latest) |
|
||||
| Batocera | 4.2 GB | `/userdata/bios/` | [Download](../../releases/latest) |
|
||||
| BizHawk | 2.4 GB | `Firmware/` | [Download](../../releases/latest) |
|
||||
| EmuDeck | 3.2 GB | `~/Emulation/bios/` | [Download](../../releases/latest) |
|
||||
| Lakka | 5.5 GB | `/storage/system/` | [Download](../../releases/latest) |
|
||||
| Lakka | 5.7 GB | `/storage/system/` | [Download](../../releases/latest) |
|
||||
| MiSTer FPGA | 24 MB | `/media/fat/games/` | [Download](../../releases/latest) |
|
||||
| ROCKNIX | 5.3 GB | `/storage/roms/bios/` | [Download](../../releases/latest) |
|
||||
| Recalbox | 3.6 GB | `/recalbox/share/bios/` | [Download](../../releases/latest) |
|
||||
| RetroArch | 5.5 GB | `system/` | [Download](../../releases/latest) |
|
||||
| RetroBat | 4.4 GB | `bios/` | [Download](../../releases/latest) |
|
||||
| RetroDECK | 6.2 GB | `~/retrodeck/` | [Download](../../releases/latest) |
|
||||
| RetroPie * | 5.5 GB | `~/RetroPie/BIOS/` | [Download](../../releases/latest) |
|
||||
| RomM | 1.3 GB | `bios/{platform_slug}/` | [Download](../../releases/latest) |
|
||||
| ROCKNIX | 5.5 GB | `/storage/roms/bios/` | [Download](../../releases/latest) |
|
||||
| Recalbox | 3.8 GB | `/recalbox/share/bios/` | [Download](../../releases/latest) |
|
||||
| RetroArch | 5.7 GB | `system/` | [Download](../../releases/latest) |
|
||||
| RetroBat | 4.6 GB | `bios/` | [Download](../../releases/latest) |
|
||||
| RetroDECK | 6.4 GB | `~/retrodeck/` | [Download](../../releases/latest) |
|
||||
| RetroPie * | 5.7 GB | `~/RetroPie/BIOS/` | [Download](../../releases/latest) |
|
||||
| RomM | 1.5 GB | `bios/{platform_slug}/` | [Download](../../releases/latest) |
|
||||
|
||||
The RetroDECK pack already contains its own `bios/` folder, so it extracts into `~/retrodeck/` rather than into the BIOS folder.
|
||||
|
||||
@@ -67,9 +67,9 @@ Each file is checked the way your platform checks it. Most compare a checksum, t
|
||||
- **12 platforms** supported with platform-specific verification
|
||||
- **449 emulators** profiled from source (RetroArch cores + standalone)
|
||||
- **470 systems** handled by those emulators (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
|
||||
- **10,330 files**, each with its SHA1, MD5, SHA256, CRC32 and Adler-32 fingerprints: 4,985 system files, 2,806 arcade ROM sets, 2,539 game and engine data files
|
||||
- **553 of 4,985 system files** matched to dump-preservation catalogs (No-Intro, Redump, TOSEC); arcade sets and engine data fall outside what those catalogs index
|
||||
- **12706 MB** total collection size
|
||||
- **10,331 files**, each with its SHA1, MD5, SHA256, CRC32 and Adler-32 fingerprints: 4,986 system files, 2,806 arcade ROM sets, 2,539 game and engine data files
|
||||
- **553 of 4,986 system files** matched to dump-preservation catalogs (No-Intro, Redump, TOSEC); arcade sets and engine data fall outside what those catalogs index
|
||||
- **12909 MB** total collection size
|
||||
|
||||
## Supported systems
|
||||
|
||||
@@ -174,4 +174,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
|
||||
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
|
||||
The reasoning, and where it is weakest, is in the [FAQ](https://abdess.github.io/retrobios/wiki/faq/#is-this-legal).
|
||||
|
||||
*Auto-generated on 2026-09-07T02:33:05Z*
|
||||
*Auto-generated on 2026-09-13T22:17:47Z*
|
||||
+1
-15
@@ -173,20 +173,6 @@
|
||||
"sha1": "2d7d999e2acb4da55c26d1517934d39e7d0a0c86",
|
||||
"total_copies": 1
|
||||
},
|
||||
"bbb.zip": {
|
||||
"clones": [
|
||||
"aaa_long_name.zip"
|
||||
],
|
||||
"sha1": "0ebda75e11e0fdce192562b5bb65a00e3e3bf240",
|
||||
"total_copies": 1
|
||||
},
|
||||
"bbc_m87.zip": {
|
||||
"clones": [
|
||||
"bbc_24bbc.zip"
|
||||
],
|
||||
"sha1": "0ebda75e11e0fdce192562b5bb65a00e3e3bf240",
|
||||
"total_copies": 1
|
||||
},
|
||||
"beebsid.zip": {
|
||||
"clones": [
|
||||
"bbc_opus3.zip"
|
||||
@@ -607,4 +593,4 @@
|
||||
"sha1": "9139c00e5986b7a86c7e8dcbce39986126ab7db4",
|
||||
"total_copies": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
-19
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"generated_at": "2026-09-07T02:25:37Z",
|
||||
"total_files": 10330,
|
||||
"total_size": 13322705446,
|
||||
"generated_at": "2026-09-13T22:10:18Z",
|
||||
"total_files": 10331,
|
||||
"total_size": 13535566159,
|
||||
"files": {
|
||||
"520d3d1b5897800af47f92efd2444a26b7a7dead": {
|
||||
"path": "bios/3DO Company/3DO/3do_arcade_saot.bin",
|
||||
@@ -51128,15 +51128,25 @@
|
||||
"crc32": "1294ff68",
|
||||
"adler32": "27661d30"
|
||||
},
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1": {
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1": {
|
||||
"path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"name": "donpachi.zip",
|
||||
"size": 208549253,
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"md5": "aa8c5e742ba27cb30ce7a872edd684bf",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"crc32": "8651ffbb",
|
||||
"adler32": "2f229899"
|
||||
},
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc": {
|
||||
"path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"name": "sfz3mix.zip",
|
||||
"size": 96705917,
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"md5": "486c88c15387b4bd83514899e68dec3f",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"crc32": "c6ab431d",
|
||||
"adler32": "ecbdccac"
|
||||
"size": 101017377,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"md5": "ce49f09c41c1c4b59078b2350ff1acaf",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"crc32": "ed686ecb",
|
||||
"adler32": "498e0209"
|
||||
},
|
||||
"b286035624978c94194ef5b83b5d784ec00c3a3c": {
|
||||
"path": "bios/Other/fbneo/fbneo/samples/twotiger.zip",
|
||||
@@ -113272,7 +113282,8 @@
|
||||
"0eb6b12f36508b24f285ffd793438ef3": "d124045eccc562ff0423b23a240e27ad740fa0c9",
|
||||
"c78ac640fcf02eb866b79718f5ed15fa": "20fdca7131478e1ee12691bdafd2d5bb74cbd16f",
|
||||
"5bcfc3374fc9b0c16070f1ac42f3dc63": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"486c88c15387b4bd83514899e68dec3f": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"aa8c5e742ba27cb30ce7a872edd684bf": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"ce49f09c41c1c4b59078b2350ff1acaf": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"733f951177e613819deef4c8f6feb4e7": "b286035624978c94194ef5b83b5d784ec00c3a3c",
|
||||
"659d579ba9aef5b025d87323044e83f4": "a8b7dce572b74e02e65cb949b2c366c87625157f",
|
||||
"e612770bc5da7ee1a21d499ce419ce2c": "8251a8e151e31201dcc346d75158ee3996895e74",
|
||||
@@ -132449,10 +132460,11 @@
|
||||
"20fdca7131478e1ee12691bdafd2d5bb74cbd16f"
|
||||
],
|
||||
"donpachi.zip": [
|
||||
"c0c0b5db93a61276a6fe6842049cb53e564b8413"
|
||||
"c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1"
|
||||
],
|
||||
"sfz3mix.zip": [
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1"
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc"
|
||||
],
|
||||
"twotiger.zip": [
|
||||
"b286035624978c94194ef5b83b5d784ec00c3a3c"
|
||||
@@ -156840,7 +156852,8 @@
|
||||
"88d0be26": "d124045eccc562ff0423b23a240e27ad740fa0c9",
|
||||
"3c79ef05": "20fdca7131478e1ee12691bdafd2d5bb74cbd16f",
|
||||
"1294ff68": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"c6ab431d": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"8651ffbb": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"ed686ecb": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"b5d5b941": "b286035624978c94194ef5b83b5d784ec00c3a3c",
|
||||
"353fdbcd": "a8b7dce572b74e02e65cb949b2c366c87625157f",
|
||||
"31669117": "8251a8e151e31201dcc346d75158ee3996895e74",
|
||||
@@ -167172,7 +167185,8 @@
|
||||
"f76b62e73e7410ab63813b9db36839be12213e4adfd3ee513eb382b7bc3a4a39": "d124045eccc562ff0423b23a240e27ad740fa0c9",
|
||||
"6597f75e97e5337198736b42a4d1ea66d4fdf01d685772482811a55e1eddf8f1": "20fdca7131478e1ee12691bdafd2d5bb74cbd16f",
|
||||
"a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"fe5408e3f513c44a64f573e7a8b68885bce9b263bc9c67bfef13fef13f3e976e": "b286035624978c94194ef5b83b5d784ec00c3a3c",
|
||||
"569541852ed3ff8fdacd04b1c6a57fd491a361ab6c41339bbddfd916bced241e": "a8b7dce572b74e02e65cb949b2c366c87625157f",
|
||||
"ea2e9f8eccb2d590a0d004e0eaffa95ca4eea36f15466b5aa1a9e47393bc004f": "8251a8e151e31201dcc346d75158ee3996895e74",
|
||||
@@ -211209,17 +211223,29 @@
|
||||
"fbneo/donpachi.zip": [
|
||||
"c0c0b5db93a61276a6fe6842049cb53e564b8413"
|
||||
],
|
||||
"Other/fbneo/fbneo/samples/donpachi.zip": [
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1"
|
||||
],
|
||||
"fbneo/fbneo/samples/donpachi.zip": [
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1"
|
||||
],
|
||||
"fbneo/samples/donpachi.zip": [
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1"
|
||||
],
|
||||
"samples/donpachi.zip": [
|
||||
"d380fb29287eb7fc9ff901a7653ad40785f7deb1"
|
||||
],
|
||||
"Other/fbneo/fbneo/samples/sfz3mix.zip": [
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1"
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc"
|
||||
],
|
||||
"fbneo/fbneo/samples/sfz3mix.zip": [
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1"
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc"
|
||||
],
|
||||
"fbneo/samples/sfz3mix.zip": [
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1"
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc"
|
||||
],
|
||||
"samples/sfz3mix.zip": [
|
||||
"227815ce9e55db427d68e075182caffe6ad60ad1"
|
||||
"e39ee9abb19076ef095f67469ca95ff5e7f600dc"
|
||||
],
|
||||
"Other/fbneo/fbneo/samples/twotiger.zip": [
|
||||
"b286035624978c94194ef5b83b5d784ec00c3a3c"
|
||||
|
||||
+18
-16
@@ -5,7 +5,7 @@
|
||||
"platform": "batocera",
|
||||
"display_name": "Batocera",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -238,7 +238,7 @@
|
||||
}
|
||||
],
|
||||
"total_files": 1832,
|
||||
"total_size": 4314998020,
|
||||
"total_size": 4522217423,
|
||||
"total_omitted": 9,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -2271,10 +2271,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -2311,10 +2311,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -8041,19 +8041,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
|
||||
+18
-16
@@ -5,7 +5,7 @@
|
||||
"platform": "bizhawk",
|
||||
"display_name": "BizHawk",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "Firmware",
|
||||
"detect": [
|
||||
{
|
||||
@@ -21,7 +21,7 @@
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 539,
|
||||
"total_size": 2328691103,
|
||||
"total_size": 2535910506,
|
||||
"total_omitted": 1,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -1464,19 +1464,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -3348,10 +3350,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
@@ -3378,10 +3380,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"platform": "emudeck",
|
||||
"display_name": "EmuDeck",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-03T20:45:52Z",
|
||||
"generated": "2026-09-13T17:22:08Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -313,10 +313,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -3991,10 +3991,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
|
||||
+23
-23
@@ -5,7 +5,7 @@
|
||||
"platform": "lakka",
|
||||
"display_name": "Lakka",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "system",
|
||||
"detect": [
|
||||
{
|
||||
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 1871,
|
||||
"total_size": 5865446694,
|
||||
"total_size": 6072666103,
|
||||
"total_omitted": 1,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -1626,10 +1626,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -6912,19 +6912,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -9368,10 +9370,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": [
|
||||
"mamemess"
|
||||
]
|
||||
@@ -13380,9 +13382,7 @@
|
||||
"repo_path": "bios/Other/sdlpal/sdlpal/5.avi",
|
||||
"cores": [
|
||||
"sdlpal"
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "5.avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dest": "sdlpal/6.avi",
|
||||
@@ -15966,10 +15966,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "SkyEmu/firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"skyemu"
|
||||
]
|
||||
|
||||
+19
-17
@@ -5,7 +5,7 @@
|
||||
"platform": "recalbox",
|
||||
"display_name": "Recalbox",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -238,7 +238,7 @@
|
||||
}
|
||||
],
|
||||
"total_files": 1328,
|
||||
"total_size": 3900250204,
|
||||
"total_size": 4107469613,
|
||||
"total_omitted": 4,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -5927,19 +5927,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -8191,10 +8193,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": [
|
||||
"mamemess"
|
||||
]
|
||||
@@ -8681,10 +8683,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
|
||||
+23
-23
@@ -5,7 +5,7 @@
|
||||
"platform": "retroarch",
|
||||
"display_name": "RetroArch",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "system",
|
||||
"detect": [
|
||||
{
|
||||
@@ -256,7 +256,7 @@
|
||||
}
|
||||
],
|
||||
"total_files": 1871,
|
||||
"total_size": 5865446694,
|
||||
"total_size": 6072666103,
|
||||
"total_omitted": 1,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -1865,10 +1865,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -7151,19 +7151,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -9607,10 +9609,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": [
|
||||
"mamemess"
|
||||
]
|
||||
@@ -13619,9 +13621,7 @@
|
||||
"repo_path": "bios/Other/sdlpal/sdlpal/5.avi",
|
||||
"cores": [
|
||||
"sdlpal"
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "5.avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dest": "sdlpal/6.avi",
|
||||
@@ -16205,10 +16205,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "SkyEmu/firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"skyemu"
|
||||
]
|
||||
|
||||
+22
-20
@@ -5,7 +5,7 @@
|
||||
"platform": "retrobat",
|
||||
"display_name": "RetroBat",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -237,7 +237,7 @@
|
||||
}
|
||||
],
|
||||
"total_files": 1464,
|
||||
"total_size": 4733583386,
|
||||
"total_size": 4940802795,
|
||||
"total_omitted": 3,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -514,10 +514,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -2282,10 +2282,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -2322,10 +2322,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -5430,19 +5430,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
|
||||
+19
-19
@@ -5,7 +5,7 @@
|
||||
"platform": "retrodeck",
|
||||
"display_name": "RetroDECK",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "",
|
||||
"detect": [
|
||||
{
|
||||
@@ -238,7 +238,7 @@
|
||||
}
|
||||
],
|
||||
"total_files": 3515,
|
||||
"total_size": 6656314549,
|
||||
"total_size": 6863533952,
|
||||
"total_omitted": 4,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -19433,19 +19433,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "bios/fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "bios/fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -21549,10 +21551,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "bios/dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
@@ -25815,9 +25817,7 @@
|
||||
"repo_path": "bios/Other/sdlpal/sdlpal/5.avi",
|
||||
"cores": [
|
||||
"sdlpal"
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "5.avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dest": "bios/sdlpal/6.avi",
|
||||
@@ -29865,10 +29865,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "bios/SkyEmu/firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"skyemu"
|
||||
]
|
||||
|
||||
+23
-23
@@ -5,7 +5,7 @@
|
||||
"platform": "retropie",
|
||||
"display_name": "RetroPie",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "system",
|
||||
"detect": [
|
||||
{
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 1871,
|
||||
"total_size": 5865446694,
|
||||
"total_size": 6072666103,
|
||||
"total_omitted": 1,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -1625,10 +1625,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": null
|
||||
},
|
||||
{
|
||||
@@ -6911,19 +6911,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -9367,10 +9369,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": [
|
||||
"mamemess"
|
||||
]
|
||||
@@ -13379,9 +13381,7 @@
|
||||
"repo_path": "bios/Other/sdlpal/sdlpal/5.avi",
|
||||
"cores": [
|
||||
"sdlpal"
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "5.avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dest": "sdlpal/6.avi",
|
||||
@@ -15965,10 +15965,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "SkyEmu/firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"skyemu"
|
||||
]
|
||||
|
||||
+20
-20
@@ -5,7 +5,7 @@
|
||||
"platform": "rocknix",
|
||||
"display_name": "ROCKNIX",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-05T09:26:20Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -18,7 +18,7 @@
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 1738,
|
||||
"total_size": 5743476850,
|
||||
"total_size": 5950696259,
|
||||
"total_omitted": 1,
|
||||
"omitted_files": [
|
||||
{
|
||||
@@ -4015,19 +4015,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -7211,10 +7213,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "d2fdc.zip",
|
||||
"sha1": "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4",
|
||||
"sha256": "e5e30615040567c1e7a2d21599681f8dac820edbdcda177b816a64d74b3a12f2",
|
||||
"size": 256,
|
||||
"repo_path": "bios/Apple/Apple II/DiskII/state-machine-16.rom",
|
||||
"sha1": "af56c948598291b284a528f3fce06b961dba55e3",
|
||||
"sha256": "69ee0f8f0862e1a623bcbe9870f9531f7976312f292a20d1aff7ed61b6085a69",
|
||||
"size": 262,
|
||||
"repo_path": "bios/Arcade/Arcade/a3fdc.zip",
|
||||
"cores": [
|
||||
"mamemess"
|
||||
]
|
||||
@@ -12543,9 +12545,7 @@
|
||||
"repo_path": "bios/Other/sdlpal/sdlpal/5.avi",
|
||||
"cores": [
|
||||
"sdlpal"
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "5.avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dest": "sdlpal/6.avi",
|
||||
@@ -15389,10 +15389,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "SkyEmu/firmware.bin",
|
||||
"sha1": "5b2acbd499b39fb1af1b36ef7de5eb047d83401c",
|
||||
"sha256": "7ea4f06ca110f8b7ff7c946f6e4e228d94977dadd4bb51570d14c68488edb32a",
|
||||
"sha1": "cfe072921ee3fb93f688743f8beef89043c3e9ad",
|
||||
"sha256": "57a1d6b43c1399d219ea18644240c4d4c6787c829f0a67ded216472867857cd0",
|
||||
"size": 262144,
|
||||
"repo_path": "bios/Arcade/Arcade/firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/firmware.bin",
|
||||
"cores": [
|
||||
"skyemu"
|
||||
]
|
||||
|
||||
+15
-13
@@ -5,7 +5,7 @@
|
||||
"platform": "romm",
|
||||
"display_name": "RomM",
|
||||
"version": "1.0",
|
||||
"generated": "2026-09-03T20:45:52Z",
|
||||
"generated": "2026-09-13T22:10:18Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 615,
|
||||
"total_size": 1366505831,
|
||||
"total_size": 1573725234,
|
||||
"total_omitted": 0,
|
||||
"omitted_files": [],
|
||||
"files": [
|
||||
@@ -3332,19 +3332,21 @@
|
||||
},
|
||||
{
|
||||
"dest": "colecovision/fbneo/samples/donpachi.zip",
|
||||
"sha1": "c0c0b5db93a61276a6fe6842049cb53e564b8413",
|
||||
"sha256": "a686ebf893d511b5b7667176cd6844593e914595a8bb9ab656b2c66969013b5c",
|
||||
"size": 5641310,
|
||||
"repo_path": "bios/Other/fbneo/donpachi.zip",
|
||||
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||
"sha256": "78a237f1e2774eb396e2f14999f1270597e0767a392729e7a4539455888b6fe0",
|
||||
"size": 208549253,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/donpachi.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
]
|
||||
],
|
||||
"storage": "release",
|
||||
"release_asset": "donpachi.zip"
|
||||
},
|
||||
{
|
||||
"dest": "colecovision/fbneo/samples/sfz3mix.zip",
|
||||
"sha1": "227815ce9e55db427d68e075182caffe6ad60ad1",
|
||||
"sha256": "6a720035646b3488a047ab163a6975b7be82fe75c5eec88155c8503c93a631fe",
|
||||
"size": 96705917,
|
||||
"sha1": "e39ee9abb19076ef095f67469ca95ff5e7f600dc",
|
||||
"sha256": "2c2e67ab762102f50df641280721164ddff0316e71081d5fa62f2a67365dea66",
|
||||
"size": 101017377,
|
||||
"repo_path": "bios/Other/fbneo/fbneo/samples/sfz3mix.zip",
|
||||
"cores": [
|
||||
"fbneo"
|
||||
@@ -3808,10 +3810,10 @@
|
||||
},
|
||||
{
|
||||
"dest": "nds/dsi_firmware.bin",
|
||||
"sha1": "93c0598b08192a1f630e5edb2cd9f60d1e3ea7b3",
|
||||
"sha256": "1f89935da2888cd3e401af2774e06a6b587ca059e85f922826494f317d31c6ae",
|
||||
"sha1": "d2a5af338f09c5cbdd5d7628db5b9c075c69b616",
|
||||
"sha256": "1d7c771de535e6e07182fc9820ac32e76c6f0b5bcefd256a861fdfab144761ec",
|
||||
"size": 131072,
|
||||
"repo_path": "bios/Arcade/Arcade/dsi_firmware.bin",
|
||||
"repo_path": "bios/Nintendo/Nintendo DS/dsi_firmware.bin",
|
||||
"cores": [
|
||||
"melonds"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare the large-files release with the files the collection keeps out of git.
|
||||
|
||||
Every gitignored file under bios/ is served to the installer as an asset of
|
||||
the large-files release, and install.py refuses a download whose
|
||||
Content-Length differs from the manifest size. The manifest size is that of
|
||||
the local copy, so an asset uploaded before the local file was rebuilt fails
|
||||
every install of it until it is uploaded again.
|
||||
|
||||
Usage:
|
||||
python scripts/check_release_assets.py
|
||||
python scripts/check_release_assets.py --json
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
from common import load_database
|
||||
from largefiles import LARGE_FILES_RELEASE, LARGE_FILES_REPO
|
||||
|
||||
Finding = tuple[str, str, int, int | None]
|
||||
|
||||
|
||||
def expected_assets(db: dict, gitignore_text: str) -> dict[str, int]:
|
||||
"""Map each gitignored database path to the size the manifests carry."""
|
||||
ignored = {
|
||||
line.strip()
|
||||
for line in gitignore_text.splitlines()
|
||||
if line.strip().startswith("bios/")
|
||||
}
|
||||
return {
|
||||
entry["path"]: entry["size"]
|
||||
for entry in db.get("files", {}).values()
|
||||
if entry.get("path") in ignored
|
||||
}
|
||||
|
||||
|
||||
def _asset_names(path: str) -> list[str]:
|
||||
"""Names the release may publish a file under.
|
||||
|
||||
GitHub rewrites spaces to dots in asset names, so a file whose name
|
||||
carries spaces is published under the dotted form.
|
||||
"""
|
||||
name = os.path.basename(path)
|
||||
return [name, name.replace(" ", ".")] if " " in name else [name]
|
||||
|
||||
|
||||
def compare(
|
||||
expected: dict[str, int], assets: dict[str, int], notes_current: bool = True
|
||||
) -> list[Finding]:
|
||||
"""Files the release lacks or serves at another size, sorted by kind.
|
||||
|
||||
A release description that no longer matches what render_notes() would
|
||||
write is a finding of its own: the page is what a reader checks a
|
||||
download against.
|
||||
"""
|
||||
findings: list[Finding] = []
|
||||
if not notes_current:
|
||||
findings.append(("notes", "release description", 0, None))
|
||||
for path, size in sorted(expected.items()):
|
||||
published = next(
|
||||
(assets[name] for name in _asset_names(path) if name in assets), None
|
||||
)
|
||||
if published is None:
|
||||
findings.append(("missing", path, size, None))
|
||||
elif published != size:
|
||||
findings.append(("size", path, size, published))
|
||||
return sorted(findings)
|
||||
|
||||
|
||||
ASSET_URL = f"https://github.com/{LARGE_FILES_REPO}/releases/download/{LARGE_FILES_RELEASE}/"
|
||||
NOT_INDEXED = "Not indexed"
|
||||
SECTIONS = (
|
||||
"Console firmware",
|
||||
"Arcade",
|
||||
"Computer",
|
||||
"Game engine data",
|
||||
"Virtual machine firmware",
|
||||
"Other",
|
||||
NOT_INDEXED,
|
||||
)
|
||||
_ROW = re.compile(
|
||||
r"^\| \[(?P<name>[^\]]+)\]\([^)]*\) \| (?P<desc>[^|]*?) \| [^|]* \|"
|
||||
r"(?: `(?P<sha1>[0-9a-f]{40})` \|)?$",
|
||||
re.M,
|
||||
)
|
||||
_HEADING = re.compile(r"^## (.+)$", re.M)
|
||||
|
||||
|
||||
def parse_notes(body: str) -> dict[str, tuple[str, str, str]]:
|
||||
"""Name -> (section, description, sha1) for every row of a release page."""
|
||||
rows: dict[str, tuple[str, str, str]] = {}
|
||||
section = ""
|
||||
for line in body.splitlines():
|
||||
heading = _HEADING.match(line)
|
||||
if heading:
|
||||
section = heading.group(1).strip()
|
||||
continue
|
||||
row = _ROW.match(line)
|
||||
if row:
|
||||
rows[row.group("name")] = (
|
||||
section, row.group("desc").strip(), row.group("sha1") or ""
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def _section_for(path: str) -> str:
|
||||
parts = path.split("/")
|
||||
top = parts[1] if len(parts) > 1 else ""
|
||||
if top in ("Nintendo", "Sony", "Sega", "Microsoft", "NEC", "SNK"):
|
||||
return "Console firmware"
|
||||
if top == "Arcade" or "/samples/" in path:
|
||||
return "Arcade"
|
||||
if top == "QEMU":
|
||||
return "Virtual machine firmware"
|
||||
if top in ("RPG Maker", "ScummVM"):
|
||||
return "Game engine data"
|
||||
if top in ("Apple", "Commodore", "Atari", "Sinclair", "Amstrad"):
|
||||
return "Computer"
|
||||
return "Other"
|
||||
|
||||
|
||||
def _mib(size: int) -> str:
|
||||
return f"{round(size / 1048576)} MB"
|
||||
|
||||
|
||||
def render_notes(
|
||||
db: dict,
|
||||
gitignore_text: str,
|
||||
assets: dict[str, int],
|
||||
previous: str,
|
||||
descriptions: dict[str, str],
|
||||
bundles: dict[str, str],
|
||||
cache_sha1: dict[str, str],
|
||||
) -> str:
|
||||
"""The release page, from what the release actually serves.
|
||||
|
||||
Every asset gets one row. A file the database indexes carries its
|
||||
database SHA1; a data-directory bundle carries the hash of its cached
|
||||
copy when one exists; anything else is listed apart with its size only,
|
||||
so the page never vouches for bytes nobody indexed. Descriptions and
|
||||
sections already written by hand are kept by name.
|
||||
"""
|
||||
known = parse_notes(previous)
|
||||
ignored = {
|
||||
line.strip()
|
||||
for line in gitignore_text.splitlines()
|
||||
if line.strip().startswith("bios/")
|
||||
}
|
||||
indexed: dict[str, tuple[str, str]] = {}
|
||||
for sha1, entry in db.get("files", {}).items():
|
||||
path = entry.get("path", "")
|
||||
if path in ignored:
|
||||
name = os.path.basename(path)
|
||||
for candidate in (name, name.replace(" ", ".")):
|
||||
indexed[candidate] = (sha1, path)
|
||||
|
||||
rows: dict[str, list[tuple[int, str]]] = {section: [] for section in SECTIONS}
|
||||
for name, size in assets.items():
|
||||
section, description, previous_sha1 = known.get(name, ("", "", ""))
|
||||
if name in indexed:
|
||||
sha1, path = indexed[name]
|
||||
section = section if section in SECTIONS[:-1] else _section_for(path)
|
||||
stem = name.split(".")[0] + "." + name.split(".")[1] if name.count(".") > 1 else name
|
||||
description = description or descriptions.get(name) or descriptions.get(stem) or path
|
||||
elif name in bundles:
|
||||
sha1 = cache_sha1.get(name, previous_sha1)
|
||||
section = section if section in SECTIONS[:-1] else "Game engine data"
|
||||
description = description or bundles[name]
|
||||
else:
|
||||
sha1 = ""
|
||||
section = NOT_INDEXED
|
||||
description = description or name
|
||||
link = f"[{name}]({ASSET_URL}{name})"
|
||||
if section == NOT_INDEXED:
|
||||
line = f"| {link} | {description} | {_mib(size)} |"
|
||||
else:
|
||||
line = f"| {link} | {description} | {_mib(size)} | `{sha1}` |"
|
||||
rows[section].append((-size, line))
|
||||
|
||||
out = [
|
||||
"Files too large for the git repository (GitHub 100MB limit), plus game engine data packs.",
|
||||
"Downloaded automatically by `generate_pack.py` when not present locally.",
|
||||
"Manual: `gh release download large-files`",
|
||||
]
|
||||
for section in SECTIONS:
|
||||
if not rows[section]:
|
||||
continue
|
||||
out += ["", f"## {section}", ""]
|
||||
if section == NOT_INDEXED:
|
||||
out += [
|
||||
"Assets the collection does not index: no database entry names them, "
|
||||
"so no hash is vouched for here.",
|
||||
"",
|
||||
"| File | Description | Size |",
|
||||
"|------|-------------|-----:|",
|
||||
]
|
||||
else:
|
||||
out += ["| File | Description | Size | SHA1 |", "|------|-------------|-----:|------|"]
|
||||
out += [line for _, line in sorted(rows[section])]
|
||||
total = sum(assets.values())
|
||||
out += ["", f"{len(assets)} files, {total / 1073741824:.1f} GB total. Verify a download with `sha1sum <file>`.", ""]
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def profile_descriptions(emulators_dir: str = "emulators") -> dict[str, str]:
|
||||
"""Name -> description, from the first profile that declares the file."""
|
||||
from common import load_emulator_profiles
|
||||
|
||||
found: dict[str, str] = {}
|
||||
for profile in load_emulator_profiles(emulators_dir).values():
|
||||
for entry in profile.get("files", []):
|
||||
name = str(entry.get("name") or "")
|
||||
if name and entry.get("description"):
|
||||
found.setdefault(name, str(entry["description"]))
|
||||
return found
|
||||
|
||||
|
||||
def registry_bundles(registry_path: str = "platforms/_data_dirs.yml") -> dict[str, str]:
|
||||
"""Asset name -> description for data directories served from the release."""
|
||||
from common import yaml_load
|
||||
|
||||
with open(registry_path, encoding="utf-8") as handle:
|
||||
registry = yaml_load(handle) or {}
|
||||
bundles: dict[str, str] = {}
|
||||
for entry in (registry.get("data_directories") or registry).values():
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
url = str(entry.get("source_url") or "")
|
||||
if url.startswith(ASSET_URL):
|
||||
bundles[url[len(ASSET_URL):]] = str(entry.get("description") or "")
|
||||
return bundles
|
||||
|
||||
|
||||
def cache_hashes(names: set[str], cache_dir: str = ".cache/large") -> dict[str, str]:
|
||||
"""SHA1 of the cached copy of each named asset that the cache holds."""
|
||||
hashes: dict[str, str] = {}
|
||||
for name in names:
|
||||
path = os.path.join(cache_dir, name)
|
||||
if os.path.isfile(path):
|
||||
digest = hashlib.sha1()
|
||||
with open(path, "rb") as handle:
|
||||
for chunk in iter(lambda: handle.read(1 << 20), b""):
|
||||
digest.update(chunk)
|
||||
hashes[name] = digest.hexdigest()
|
||||
return hashes
|
||||
|
||||
|
||||
def fetch_release() -> tuple[dict[str, int], str]:
|
||||
"""Name and size of every asset of the large-files release, and its page."""
|
||||
result = subprocess.run(
|
||||
[
|
||||
"gh", "release", "view", LARGE_FILES_RELEASE,
|
||||
"-R", LARGE_FILES_REPO, "--json", "assets,body",
|
||||
],
|
||||
capture_output=True, text=True, check=True,
|
||||
)
|
||||
data = json.loads(result.stdout)
|
||||
return {a["name"]: a["size"] for a in data["assets"]}, data.get("body", "")
|
||||
|
||||
|
||||
def fetch_assets() -> dict[str, int]:
|
||||
"""Name and size of every asset of the large-files release."""
|
||||
result = subprocess.run(
|
||||
[
|
||||
"gh", "release", "view", LARGE_FILES_RELEASE,
|
||||
"-R", LARGE_FILES_REPO, "--json", "assets",
|
||||
],
|
||||
capture_output=True, text=True, check=True,
|
||||
)
|
||||
return {a["name"]: a["size"] for a in json.loads(result.stdout)["assets"]}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__.split("\n")[0])
|
||||
parser.add_argument("--db", default="database.json")
|
||||
parser.add_argument("--gitignore", default=".gitignore")
|
||||
parser.add_argument("--json", action="store_true")
|
||||
parser.add_argument(
|
||||
"--notes", metavar="FILE",
|
||||
help="write the release page rendered from the collection to FILE",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.gitignore, encoding="utf-8") as handle:
|
||||
gitignore_text = handle.read()
|
||||
db = load_database(args.db)
|
||||
expected = expected_assets(db, gitignore_text)
|
||||
try:
|
||||
assets, body = fetch_release()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError, KeyError) as exc:
|
||||
print(f"ERROR: cannot list release assets: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
bundles = registry_bundles()
|
||||
rendered = render_notes(
|
||||
db, gitignore_text, assets, body, profile_descriptions(), bundles,
|
||||
cache_hashes(set(bundles)),
|
||||
)
|
||||
if args.notes:
|
||||
with open(args.notes, "w", encoding="utf-8") as handle:
|
||||
handle.write(rendered)
|
||||
findings = compare(expected, assets, notes_current=rendered.strip() == body.strip())
|
||||
|
||||
if args.json:
|
||||
print(json.dumps(
|
||||
[
|
||||
{"kind": kind, "path": path, "expected": size, "published": published}
|
||||
for kind, path, size, published in findings
|
||||
],
|
||||
indent=2,
|
||||
))
|
||||
else:
|
||||
print(f"{len(expected)} gitignored files, {len(assets)} release assets")
|
||||
for kind, path, size, published in findings:
|
||||
if kind == "missing":
|
||||
print(f" MISSING {path} ({size} bytes)")
|
||||
elif kind == "size":
|
||||
print(f" SIZE {path}: local {size} != release {published}")
|
||||
else:
|
||||
print(" NOTES release description differs from the rendered page"
|
||||
" (--notes FILE, then gh release edit large-files --notes-file FILE)")
|
||||
if not findings:
|
||||
print(" release assets and description match the collection")
|
||||
return 1 if findings else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+6
-1
@@ -230,7 +230,12 @@ def deduplicate(bios_dir: str, dry_run: bool = False) -> dict:
|
||||
|
||||
# Write MAME clone mapping
|
||||
if mame_clones:
|
||||
clone_path = "_mame_clones.json"
|
||||
# Beside the scanned tree, where get_mame_clone_map() reads it for
|
||||
# the real layout. A path relative to the working directory let a
|
||||
# scan of a fixture tree rewrite the repository's own map.
|
||||
clone_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(bios_dir)), "_mame_clones.json"
|
||||
)
|
||||
# A group is only visible while both copies are on disk, and this run
|
||||
# has just deleted the clone. Writing only what was seen this time
|
||||
# therefore erases every mapping an earlier run recorded, and the
|
||||
|
||||
@@ -2707,13 +2707,16 @@ def _load_gitignore_entries(repo_root: str) -> set[str]:
|
||||
return entries
|
||||
|
||||
|
||||
def _is_large_file(local_path: str, repo_root: str) -> bool:
|
||||
"""Check if a file is a large file (>50MB or in .gitignore)."""
|
||||
if local_path and os.path.exists(local_path):
|
||||
if os.path.getsize(local_path) > 50_000_000:
|
||||
return True
|
||||
def _is_release_asset(local_path: str, repo_root: str) -> bool:
|
||||
"""Whether the installer fetches this file from the large-files release.
|
||||
|
||||
The repository serves every committed file from its raw URL; only the
|
||||
files kept out of git live as release assets, and .gitignore is the
|
||||
ledger of those. Size is not the criterion: a committed file over 50 MB
|
||||
is still served by the repository, and announcing it as a release asset
|
||||
sends the installer to an asset nobody uploaded.
|
||||
"""
|
||||
gitignore = _load_gitignore_entries(repo_root)
|
||||
# Check if the path relative to repo root is in .gitignore
|
||||
try:
|
||||
rel = os.path.relpath(local_path, repo_root)
|
||||
except ValueError:
|
||||
@@ -2826,7 +2829,7 @@ def _manifest_core_entries(
|
||||
"cores": [source_emu] if source_emu else [],
|
||||
}
|
||||
|
||||
if _is_large_file(local_path or "", repo_root):
|
||||
if _is_release_asset(local_path or "", repo_root):
|
||||
entry["storage"] = "release"
|
||||
entry["release_asset"] = (
|
||||
os.path.basename(local_path) if local_path else fe["name"]
|
||||
@@ -3021,7 +3024,7 @@ def generate_manifest(
|
||||
sha256 = hashes["sha256"]
|
||||
|
||||
repo_path = _get_repo_path(sha1, db) if sha1 else ""
|
||||
is_release_asset = _is_large_file(local_path or "", repo_root)
|
||||
is_release_asset = _is_release_asset(local_path or "", repo_root)
|
||||
|
||||
# An entry needs somewhere to be fetched from. Resolution can
|
||||
# land on a file the database does not index -- a data
|
||||
|
||||
@@ -6,6 +6,7 @@ Steps:
|
||||
1b. provenance_report.py (dump-catalog coverage from provenance/)
|
||||
1c. romset_recipes.py (archive identification, reconstruction targets)
|
||||
2. refresh_data_dirs.py (update Dolphin Sys, PPSSPP, etc.)
|
||||
2b2. check_release_assets.py (large-files release vs gitignored files, online)
|
||||
3. verify.py --all (check all platforms)
|
||||
4. generate_pack.py --all (build ZIP packs)
|
||||
4b. generate install manifests
|
||||
@@ -346,6 +347,20 @@ def main():
|
||||
elif args.check_buildbot:
|
||||
print("\n--- 2b check buildbot system: SKIPPED (--offline) ---")
|
||||
|
||||
# Step 2b2: The release must serve the bytes the manifests describe. The
|
||||
# installer compares Content-Length with the manifest size, so an asset
|
||||
# uploaded before its local file was rebuilt fails every install of it.
|
||||
if not args.offline:
|
||||
ok, _ = run(
|
||||
[sys.executable, "scripts/check_release_assets.py"],
|
||||
"2b2 check release assets",
|
||||
)
|
||||
results["check_release_assets"] = ok
|
||||
all_ok = all_ok and ok
|
||||
else:
|
||||
print("\n--- 2b2 check release assets: SKIPPED (--offline) ---")
|
||||
results["check_release_assets"] = SKIPPED
|
||||
|
||||
# Step 2c: Generate truth YAMLs
|
||||
# A targeted run writes its model in a subdirectory of its own, and the
|
||||
# diff has to read the same one or it compares a narrowed model against
|
||||
|
||||
@@ -1184,6 +1184,211 @@ class EveryManifestEntryIsFetchable(unittest.TestCase):
|
||||
for entry in data.get("omitted_files", []):
|
||||
self.assertIn(entry.get("reason"), allowed)
|
||||
|
||||
def _manifests(self) -> list[Path]:
|
||||
paths = sorted((ROOT / "install").glob("*.json"))
|
||||
paths += sorted((ROOT / "install" / "targets").glob("*.json"))
|
||||
self.assertTrue(paths, "no install manifests to check")
|
||||
return paths
|
||||
|
||||
def test_repo_paths_name_the_file_the_database_holds(self):
|
||||
"""A manifest written before a file moved sends the installer to 404.
|
||||
|
||||
database.json is regenerated whenever a file is refiled; the manifests
|
||||
are a separate artefact and were left behind once (the two DS
|
||||
firmware dumps of the 7 September refile). The installer fetches
|
||||
repo_path from raw.githubusercontent.com, so a stale one is a
|
||||
download that can never succeed.
|
||||
"""
|
||||
database = ROOT / "database.json"
|
||||
if not database.is_file():
|
||||
self.skipTest("database.json not generated")
|
||||
files = json.loads(database.read_text(encoding="utf-8"))["files"]
|
||||
for path in self._manifests():
|
||||
with self.subTest(manifest=path.name):
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
stale = [
|
||||
(entry["dest"], entry["repo_path"], files.get(entry["sha1"], {}).get("path"))
|
||||
for entry in data.get("files", [])
|
||||
if entry.get("repo_path")
|
||||
and files.get(entry.get("sha1", ""), {}).get("path") != entry["repo_path"]
|
||||
]
|
||||
self.assertEqual(stale, [], f"{path.name} names moved files: {stale[:3]}")
|
||||
|
||||
def test_release_entries_are_exactly_the_files_git_does_not_hold(self):
|
||||
"""The installer has two sources, and the manifest must pick the right one.
|
||||
|
||||
A committed file is served by the repository; a gitignored one by
|
||||
the large-files release. Marking a committed file as a release asset
|
||||
sends the installer to an asset nobody uploaded (sdlpal/5.avi, 83 MB
|
||||
in git, was announced as release asset `5.avi`). Marking a gitignored
|
||||
file as a repo file sends it to a raw URL that has no content.
|
||||
"""
|
||||
tracked = set(
|
||||
subprocess.run(
|
||||
["git", "ls-files", "-z", "--", "bios"],
|
||||
capture_output=True, text=True, cwd=ROOT, check=True,
|
||||
).stdout.split("\0")
|
||||
)
|
||||
if not tracked:
|
||||
self.skipTest("not a git checkout")
|
||||
for path in self._manifests():
|
||||
with self.subTest(manifest=path.name):
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
wrong = []
|
||||
for entry in data.get("files", []):
|
||||
repo_path = entry.get("repo_path")
|
||||
if not repo_path:
|
||||
continue
|
||||
committed = repo_path in tracked
|
||||
if bool(entry.get("release_asset")) == committed:
|
||||
wrong.append((entry["dest"], repo_path, "committed" if committed else "gitignored"))
|
||||
self.assertEqual(wrong, [], f"{path.name} picks the wrong source: {wrong[:3]}")
|
||||
|
||||
|
||||
class ReleaseAssetCriterion(unittest.TestCase):
|
||||
"""What decides whether the installer fetches from the release is git, not size.
|
||||
|
||||
Files over 50 MB are supposed to be gitignored and uploaded to the
|
||||
large-files release, but four committed files break that rule and one of
|
||||
them reached a manifest as a release asset that does not exist. The
|
||||
truthful question is whether the repository serves the bytes, and the
|
||||
ledger of what it does not serve is .gitignore.
|
||||
"""
|
||||
|
||||
def _repo(self, directory: str, ignored: str) -> str:
|
||||
Path(directory, ".gitignore").write_text(ignored + "\n", encoding="utf-8")
|
||||
return directory
|
||||
|
||||
def test_a_large_committed_file_is_served_by_the_repository(self):
|
||||
from scripts import generate_pack
|
||||
|
||||
with tempfile.TemporaryDirectory(dir=TMP_ROOT) as directory:
|
||||
root = self._repo(directory, "bios/elsewhere.bin")
|
||||
big = Path(root, "bios", "big.avi")
|
||||
big.parent.mkdir()
|
||||
with big.open("wb") as handle:
|
||||
handle.truncate(60_000_000)
|
||||
generate_pack._GITIGNORE_ENTRIES = None
|
||||
try:
|
||||
self.assertFalse(generate_pack._is_release_asset(str(big), root))
|
||||
finally:
|
||||
generate_pack._GITIGNORE_ENTRIES = None
|
||||
|
||||
def test_a_gitignored_file_is_served_by_the_release_whatever_its_size(self):
|
||||
from scripts import generate_pack
|
||||
|
||||
with tempfile.TemporaryDirectory(dir=TMP_ROOT) as directory:
|
||||
root = self._repo(directory, "bios/small.zip")
|
||||
small = Path(root, "bios", "small.zip")
|
||||
small.parent.mkdir()
|
||||
small.write_bytes(b"PK")
|
||||
generate_pack._GITIGNORE_ENTRIES = None
|
||||
try:
|
||||
self.assertTrue(generate_pack._is_release_asset(str(small), root))
|
||||
finally:
|
||||
generate_pack._GITIGNORE_ENTRIES = None
|
||||
|
||||
|
||||
class ReleaseAssetsMatchTheCollection(unittest.TestCase):
|
||||
"""The bytes the release serves must be the bytes the manifests describe.
|
||||
|
||||
install.py checks Content-Length against the manifest size before it
|
||||
downloads, and the manifest size is that of the local copy. Both FBNeo
|
||||
sample archives were rebuilt locally after their upload and never
|
||||
re-uploaded: same members, different container, every install of them
|
||||
failed. The comparison is offline here on a fixture; the script runs it
|
||||
against the live release.
|
||||
"""
|
||||
|
||||
def test_missing_and_resized_assets_are_reported_and_nothing_else(self):
|
||||
from scripts import check_release_assets
|
||||
|
||||
expected = {
|
||||
"bios/Other/fbneo/fbneo/samples/twotiger.zip": 154985212,
|
||||
"bios/Arcade/MAME/MAME 0.174 Arcade XML.dat": 53677408,
|
||||
"bios/Other/sdlpal/sdlpal/5.avi": 82833972,
|
||||
}
|
||||
assets = {
|
||||
"twotiger.zip": 154888877,
|
||||
"MAME.0.174.Arcade.XML.dat": 53677408,
|
||||
"unrelated.zip": 1,
|
||||
}
|
||||
findings = check_release_assets.compare(expected, assets)
|
||||
self.assertEqual(
|
||||
findings,
|
||||
[
|
||||
("missing", "bios/Other/sdlpal/sdlpal/5.avi", 82833972, None),
|
||||
("size", "bios/Other/fbneo/fbneo/samples/twotiger.zip", 154985212, 154888877),
|
||||
],
|
||||
)
|
||||
|
||||
def test_expected_assets_are_the_gitignored_database_entries(self):
|
||||
from scripts import check_release_assets
|
||||
|
||||
db = {
|
||||
"files": {
|
||||
"a" * 40: {"path": "bios/Other/x/big.zip", "size": 10},
|
||||
"b" * 40: {"path": "bios/Other/x/small.bin", "size": 2},
|
||||
}
|
||||
}
|
||||
gitignore = "# large\nbios/Other/x/big.zip\ntmp/\n"
|
||||
self.assertEqual(
|
||||
check_release_assets.expected_assets(db, gitignore),
|
||||
{"bios/Other/x/big.zip": 10},
|
||||
)
|
||||
|
||||
def test_release_notes_are_rendered_from_the_collection(self):
|
||||
"""The release page is written by hand and drifts; it is rendered instead.
|
||||
|
||||
Three assets had no row, three rows carried the SHA1 of an asset
|
||||
that had since been replaced, and the footer counted 41 files for 44.
|
||||
Hand-written descriptions survive by name; a new row takes its
|
||||
description from the profile that declares the file; an asset the
|
||||
collection does not index is listed apart, with its size only.
|
||||
"""
|
||||
from scripts import check_release_assets
|
||||
|
||||
db = {"files": {
|
||||
"a" * 40: {"path": "bios/Nintendo/Wii/nand.bin", "size": 553649152},
|
||||
"b" * 40: {"path": "bios/Other/fbneo/fbneo/samples/twotiger.zip", "size": 154985212},
|
||||
"c" * 40: {"path": "bios/Other/x/small.bin", "size": 2},
|
||||
}}
|
||||
gitignore = "bios/Nintendo/Wii/nand.bin\nbios/Other/fbneo/fbneo/samples/twotiger.zip\n"
|
||||
assets = {"nand.bin": 553649152, "twotiger.zip": 154985212,
|
||||
"sdlpal-data.zip": 140773720, "whoopee.zip": 222665810}
|
||||
previous = (
|
||||
"## Arcade\n\n| File | Description | Size | SHA1 |\n|---|---|---|---|\n"
|
||||
"| [twotiger.zip](u) | Two Tigers samples | 148 MB | `" + "0" * 40 + "` |\n"
|
||||
"| [whoopee.zip](u) | Toaplan Whoopee samples | 212 MB | `" + "9" * 40 + "` |\n"
|
||||
)
|
||||
descriptions = {"nand.bin": "BootMii NAND backup"}
|
||||
bundles = {"sdlpal-data.zip": "SDLPAL Chinese Paladin game data (.mkf archives)"}
|
||||
body = check_release_assets.render_notes(
|
||||
db, gitignore, assets, previous, descriptions, bundles, {"sdlpal-data.zip": "d" * 40}
|
||||
)
|
||||
self.assertIn("| [twotiger.zip](https://github.com/Abdess/retrobios/releases/download/large-files/twotiger.zip) | Two Tigers samples | 148 MB | `" + "b" * 40 + "` |", body)
|
||||
self.assertIn("| [nand.bin](https://github.com/Abdess/retrobios/releases/download/large-files/nand.bin) | BootMii NAND backup | 528 MB | `" + "a" * 40 + "` |", body)
|
||||
self.assertIn("| [sdlpal-data.zip](https://github.com/Abdess/retrobios/releases/download/large-files/sdlpal-data.zip) | SDLPAL Chinese Paladin game data (.mkf archives) | 134 MB | `" + "d" * 40 + "` |", body)
|
||||
self.assertIn("## Not indexed", body)
|
||||
self.assertIn("| [whoopee.zip](https://github.com/Abdess/retrobios/releases/download/large-files/whoopee.zip) | Toaplan Whoopee samples | 212 MB |", body)
|
||||
self.assertNotIn("9" * 40, body)
|
||||
self.assertNotIn("small.bin", body)
|
||||
self.assertIn("4 files, 1.0 GB total", body)
|
||||
self.assertEqual(body.index("## Console firmware"), min(
|
||||
body.index(h) for h in ("## Console firmware", "## Arcade", "## Not indexed")
|
||||
))
|
||||
|
||||
def test_stale_notes_are_a_finding(self):
|
||||
from scripts import check_release_assets
|
||||
|
||||
findings = check_release_assets.compare({}, {}, notes_current=False)
|
||||
self.assertEqual(findings, [("notes", "release description", 0, None)])
|
||||
|
||||
def test_pipeline_runs_the_check_online_and_marks_it_skipped_offline(self):
|
||||
source = (ROOT / "scripts" / "pipeline.py").read_text(encoding="utf-8")
|
||||
self.assertIn("check_release_assets.py", source)
|
||||
self.assertIn('results["check_release_assets"] = SKIPPED', source)
|
||||
|
||||
|
||||
class PreservedBytesAreNeverNormalised(unittest.TestCase):
|
||||
"""git must not rewrite a preserved file's line endings.
|
||||
|
||||
@@ -204,6 +204,23 @@ class CloneMapSurvivesASecondRun(_Bios):
|
||||
path = Path(self._tmp.name) / "_mame_clones.json"
|
||||
return json.loads(path.read_text()) if path.exists() else {}
|
||||
|
||||
def test_the_map_is_written_beside_the_scanned_tree_not_the_cwd(self):
|
||||
"""A test or a run from another directory must not touch the repo's map.
|
||||
|
||||
The map was written to the working directory. The test suite runs
|
||||
from the repo root, so a fixture scan of a temporary tree rewrote the
|
||||
committed _mame_clones.json with two fixture entries, and a later
|
||||
rewrite left 2 of its 71 parents.
|
||||
"""
|
||||
elsewhere = Path(self._tmp.name) / "elsewhere"
|
||||
elsewhere.mkdir()
|
||||
os.chdir(elsewhere)
|
||||
self.write("Arcade/MAME/bbc_m87.zip")
|
||||
self.write("Arcade/MAME/bbc_24bbc.zip")
|
||||
self.run_dedup()
|
||||
self.assertFalse((elsewhere / "_mame_clones.json").exists())
|
||||
self.assertIn("bbc_m87.zip", self._map())
|
||||
|
||||
def test_a_recorded_mapping_survives_a_later_run(self):
|
||||
self.write("Arcade/MAME/bbc_m87.zip")
|
||||
self.write("Arcade/MAME/bbc_24bbc.zip")
|
||||
|
||||
@@ -132,6 +132,22 @@ gh release upload large-files "bios/Sony/PS3/PS3UPDAT.PUP#PS3UPDAT.PUP"
|
||||
**Local cache.** `generate_pack.py` calls `fetch_large_file()` which downloads
|
||||
from the release and caches in `.cache/large/` for subsequent runs.
|
||||
|
||||
**Check.** The installer refuses a download whose `Content-Length` differs
|
||||
from the manifest size, and the manifest size is that of the local file. A
|
||||
file rebuilt locally after its upload therefore fails every install until it
|
||||
is uploaded again (`--clobber`). `python scripts/check_release_assets.py`
|
||||
compares every gitignored `bios/` path in the database with the asset of the
|
||||
same name, and the release page with the one it renders from the collection;
|
||||
the online pipeline runs it as step 2b2. To refresh the page:
|
||||
|
||||
```bash
|
||||
python scripts/check_release_assets.py --notes tmp/notes.md
|
||||
gh release edit large-files --notes-file tmp/notes.md
|
||||
```
|
||||
|
||||
An asset no database entry names is listed on the page under "Not indexed",
|
||||
with its size only: the collection vouches for no hash it does not hold.
|
||||
|
||||
## Cutting a release
|
||||
|
||||
Releasing is deliberate and local. Nothing on GitHub builds a pack: the
|
||||
|
||||
Reference in new issue
Block a user