chore: merge origin/main

This commit is contained in:
Abdessamad Derraz committed 2026-11-05 23:25:48 +01:00
commit 49ff682eda
40 files changed
+1304 -222

No files matched your search

+14 -10
View File
@@ -180,7 +180,11 @@ A platform and an emulator profile can each name a different file for the same
place in the BIOS folder: RetroBat puts its own `ATARIOSB.ROM` at
`bios/ATARIOSB.ROM`, where atari800 reads another dump. A claim counts only when
it rests on content or on the path. A file found by its name alone claims
nothing. The pack then answers to whoever asked for it:
nothing, unless its copy has the exact size the profile declares and the
platform's file has another size (`size_exact`): RetroDECK's `sgb2.boot.rom` is
the Super Game Boy 2 SNES program ROM where supersnes9x reads a 256-byte boot ROM.
Two files of equal size are revisions, not a conflict. The pack then answers to
whoever asked for it:
- A **platform pack** must leave the frontend's own check green, since a user
reading red concludes the pack is broken. Where the frontend only looks for
@@ -280,17 +284,16 @@ being intact: see [verifying a release](release-process.md#verifying-a-release).
Three things make that hold. Generated members (`README.txt`, `manifest.json`)
carry a fixed date rather than the wall clock, and the manifest's `generated`
field is read from `database.json` instead of the build time. MAME and FBNeo
romsets are rebuilt deterministically from their ROMs, so a pack does not
inherit whatever metadata the source archive happened to carry. And every
member is written with the same fixed date: `ZipFile.write` copies the source
file's mtime, which is the checkout time for a file from the collection and
the wall clock for one the build just staged in `tmp/`.
field is read from `database.json` instead of the build time. Each ZIP of the
collection, MAME and FBNeo romsets included, is copied byte for byte, so it
hashes to the SHA1 the install list and the site publish, and git fixes those
bytes. And every member is written with the same fixed date: `ZipFile.write`
copies the source file's mtime, which is the checkout time for a file from the
collection and the wall clock for one the build just staged in `tmp/`.
`tests/test_deterministic_zip.py` builds the same fixture twice and compares
the bytes, for both the platform and the emulator pack paths. Its fixture
holds a romset, because without one the comparison never reaches the rebuild
path and passes while the real packs still move.
holds a ZIP, so the comparison covers the archive copy as well as loose files.
## Collection rules
@@ -383,7 +386,8 @@ resolution.
deploy identity. No workflow builds or publishes a release.
- `safe_extract_zip()` prevents zip-slip path traversal attacks
- `deterministic_zip` rebuilds MAME ZIPs so same ROMs always produce the same hash
- a pack copies each ZIP of the collection byte for byte, so every member
hashes to the SHA1 the install list publishes
- `crypto_verify.py` and `sect233r1.py` verify 3DS RSA-2048 signatures and AES-128-CBC integrity
- ZIP inner ROM verification via `checkInsideZip()` replicates Batocera's behavior
- `md5_composite()` replicates Recalbox's composite ZIP hash
+7 -2
View File
@@ -140,8 +140,13 @@ are still included in packs automatically. A required one the collection lacks
is listed under the counts, and `--verbose` lists the optional ones too.
The cross-reference uses `resolve_platform_cores()` to determine which emulator
profiles are relevant for each platform, then checks whether each profile's files
appear in the platform config.
profiles are relevant for each platform, then checks whether the platform
already declares each profile's files (`declaration_settles()`). A name alone
is not enough. The declaration must fill the core's own slot or have a size the
core accepts: Galaksija's 4 KiB `ROM1.BIN` does not stand for DOSBox's 32 KiB
SC-55 one. An alias counts only at the path where the core reads it, so
RetroDECK's root `MSX.ROM` is not CLK's `MSX/MSX.ROM`. An archive counts by its
name.
### Filtering output
+3 -3
View File
@@ -166,9 +166,9 @@ PR based on changed paths:
## Large files management
Files too large for git are stored as assets on a permanent GitHub release
named `large-files`. Size does not decide it: four committed files are over
50 MB (`history.xml`, `default-GM.sf3`, `5.avi`, `tbblue.mmc`) and are served
from the repository like any other.
named `large-files`. Size does not decide it: four committed files are
over 50 MB (`history.xml`, `default-GM.sf3`, `5.avi`, `uqm-remix-disc1.uqm`)
and are served from the repository like any other.
Examples: PS3UPDAT.PUP, PSVUPDAT.PUP, PSP2UPDAT.PUP, the DSi NAND images,
maclc3.zip, Firmware.19.0.0.zip (Switch), the QEMU EDK2 firmware, the ScummVM
+5 -5
View File
@@ -15,7 +15,7 @@ Run everything in sequence:
```bash
python scripts/pipeline.py --offline # DB + verify + packs + manifests + integrity + readme + site
python scripts/pipeline.py --offline --skip-packs # DB + verify + readme + site
python scripts/pipeline.py --offline --skip-packs # no packs or manifests
python scripts/pipeline.py --offline --skip-docs # skip readme + site generation
python scripts/pipeline.py --offline --target switch # filter by hardware target
python scripts/pipeline.py --offline --with-truth # include truth generation + diff
@@ -63,8 +63,8 @@ Pipeline flags:
| Flag | Effect |
|------|--------|
| `--offline` | skip every step that needs the network (2, 2a, 2a2, 2b, 2b2), and pack only the release assets already in `.cache/large/` |
| `--skip-packs` | skip steps 4, 4b, 4c, 6 and the consistency check. README and site are still rewritten unless `--skip-docs` is given too |
| `--skip-docs` | skip steps 7 and 8 |
| `--skip-packs` | skip steps 4, 4b, 4c, 5 and 6. Steps 4d and 4e still run, and README and site are still rewritten unless `--skip-docs` is given too |
| `--skip-docs` | skip steps 7, 8 and 8b |
| `--include-archived` | include archived platforms in verify, packs, truth and export |
| `--target TARGET` | filter verify, packs and truth by hardware target |
| `--source {platform,truth,full}` | pack file source, passed through to `generate_pack.py`. Refused with `--skip-packs` |
@@ -1334,7 +1334,7 @@ before a release (wiki/release-process.md). Its lines stay in
| `validate_site.py` | Validate rendered metadata, heading order, image alternatives, JSON-LD, local resources, links and fragments, and the page size and search index budgets |
| `romset_recipes.py` | Identify which emulator version an arcade archive matches, and rebuild a pinned archive from ROMs already held |
| `scraper/romset_dat_importer.py` | Fetch and import per-set recipes from MAME `-listxml` or FBNeo DATs into `recipes/`. `--fetch` alone takes the newest MAME release, and FBNeo DATs are refreshed by git blob sha. `--fetch <revision>` reads FBNeo at that tag, branch or commit |
| `deterministic_zip.py` | Rebuild MAME BIOS ZIPs deterministically (same ROMs = same hash) |
| `deterministic_zip.py` | The fixed date pack members carry. Its archive rebuild is no longer called by the pack, which copies each ZIP byte for byte |
| `torrentzip.py` | Build TorrentZip archives for MAME/FBNeo ROM sets (archive bytes depend only on contents) |
| `crypto_verify.py` | 3DS RSA signature and AES crypto verification |
| `sect233r1.py` | Pure Python ECDSA verification on sect233r1 curve (3DS OTP cert) |
@@ -1373,7 +1373,7 @@ Further options, by script:
| `romset_recipes.py` | `--dat-recipes PATH`, a snapshot or a directory of them (default `recipes/`) |
| `split_pack.py` | `--max-size 1900M`, the ceiling per part (K, M, G, default 2G) |
| `torrentzip.py` | `--check ZIP` reports conformance, `--rebuild ZIP -o OUT` normalizes an archive |
| `validate_pr.py` | `--changed` takes the BIOS files the branch changes, a folder named checks every file under it, `--markdown`, `--json` |
| `validate_pr.py` | `--changed` takes the BIOS files the branch changes, a folder named checks every file under it, `--place` copies each recognised file from outside `bios/` to its folder and declared name (or its `.variants/` slot), `--markdown`, `--json` |
| `validate_site.py` | `--site-dir` (rendered site, default `website/dist`), `--base` (path the site is served under), `--max-errors N` |
| `scraper/coreinfo_scraper.py` | `--compare-db database.json` lists the `.info` firmware the database lacks |
| `scraper/mame_hash_scraper.py` | `--release mameNNNN --profile FILE --source-commit SHA --core NAME --built-by PLATFORM` writes the profile of a MAME build a platform compiles. `--devices --listxml FILE` documents in `mame.yml` every device set with dumped ROMs that the release's `-listxml` names (`isdevice="yes"`), with `--dry-run` to preview |