Commit Graph
825 Commits
Author SHA1 Message Date
Abdessamad Derraz 4ffc11b4cf feat: document the pre-v7 happy 810 images 2026-08-11 09:41:06 +02:00
Abdessamad Derraz d272d07b82 feat: collect the altirra and amstrad firmware sets 2026-08-11 09:35:28 +02:00
Abdessamad Derraz 4e0458dc83 feat: place per-machine variants at their declared paths 2026-08-11 09:19:25 +02:00
Abdessamad Derraz eea4d4254f feat: track the nxengine data table 2026-08-11 09:09:35 +02:00
Abdessamad Derraz 6450c18154 fix: fold the nxengine data into its existing directory 2026-08-11 09:08:55 +02:00
Abdessamad Derraz 08f68e647c feat: collect the pc and atari rom sets 2026-08-11 08:50:17 +02:00
Abdessamad Derraz f313e5b41c feat: collect the assets shipped with each emulator 2026-08-11 08:44:33 +02:00
Abdessamad Derraz f2b7b91476 feat: add the mo6 v2 rom for clock signal 2026-08-11 08:30:28 +02:00
Abdessamad Derraz d8a0d975d7 feat: judge a ref against every declared repository 2026-08-11 07:25:31 +02:00
Abdessamad Derraz 1d309852b6 feat: carry the visual-pinball citations to the new tree 2026-08-11 06:55:10 +02:00
Abdessamad Derraz 0c404e6275 feat: resolve the zesarux source paths 2026-08-11 06:51:12 +02:00
Abdessamad Derraz 759d3c0341 chore: refresh manifests, readme and nav 2026-08-11 06:22:49 +02:00
Abdessamad Derraz 37df4ef38a fix: narrow two cspect decompilation refs 2026-08-11 06:15:10 +02:00
Abdessamad Derraz 3032e0429d feat: profile cspect
ZX Spectrum Next emulator, read from its own distribution.
2026-08-11 06:12:06 +02:00
Abdessamad Derraz a8a89b3182 chore: index the acquired thomson roms 2026-08-11 06:10:14 +02:00
Abdessamad Derraz 222edcdc21 feat: add the mo6 v1 rom for clock signal 2026-08-11 06:08:06 +02:00
Abdessamad Derraz cf3302efd9 chore: refresh database, manifests and readme 2026-08-11 06:01:01 +02:00
Abdessamad Derraz 436f5f85de feat: add two more thomson roms for clock signal 2026-08-11 05:50:25 +02:00
Abdessamad Derraz dbb055f4ac feat: add the thomson cd90-640 controller rom
Clock Signal loads it from Thomson/cd90-640.rom.
2026-08-11 05:45:46 +02:00
Abdessamad Derraz 3bc9e5ec96 feat: attribute a shared path by its declared subject 2026-08-11 05:42:27 +02:00
Abdessamad Derraz 266567b9a0 feat: profile ten more standalone emulators
PS2, PS3, Xbox 360, Atari, C64, BBC Micro and arcade front-ends read
from their own source trees.
2026-08-11 05:34:21 +02:00
Abdessamad Derraz ca3a91d65b fix: trim two profiles to their load sites 2026-08-11 05:34:21 +02:00
Abdessamad Derraz d8e4325af2 fix: skip conformance on required-only packs
A required-only build is narrower than the platform declares by
design, like the source-restricted variants already handled, so the
full expectation must not be applied to it. --region is also refused
alongside --manifest-targets, which carries no region dimension.
2026-08-11 05:34:21 +02:00
Abdessamad Derraz 2879f489c4 feat: give every page a link preview
Links to this site get shared on Discord, Reddit and forums, where a
page with no Open Graph tags renders as a grey rectangle. The pages
already carry a per-page title and description, so a theme override
fills the tags from those; mkdocs-material would otherwise only emit
them through its social plugin, which pulls in Pillow and CairoSVG to
render a preview image these pages do not need.
2026-08-11 05:33:42 +02:00
Abdessamad Derraz 63672e246f feat: reprofile three cores on current upstream 2026-08-11 05:24:15 +02:00
Abdessamad Derraz cc24ff1bea fix: ignore the rendered timestamp when comparing
Decorated site pages carry the generation stamp twice: once as the
markdown footer and once as a rendered element. write_if_changed knew
only the first, so every page was rewritten on every run for the clock
alone.

The comparison is what makes the deploy-site freshness guard a real
staleness check rather than a guaranteed failure, and it had no tests.
2026-08-11 05:23:52 +02:00
Abdessamad Derraz c562459567 refactor: split the emulator page renderer
generate_emulator_page carried a 228-line loop body rendering one file
row from thirty-odd optional fields, which put its complexity at 141,
more than twice the next function in the repository. The row renderer
and its badge strip are now their own functions and the page function
sits at 68.

_forge_sources went from 18 to 32 when it learned to pair each
repository with its own revision; the pairing is now its own function
and the caller is back under the threshold.

Verified by regenerating the site and diffing: all 505 pages are
identical apart from their generation timestamps.
2026-08-11 05:22:25 +02:00
Abdessamad Derraz 3a58167823 chore: keep one copy per unique content 2026-08-11 05:22:18 +02:00
Abdessamad Derraz 1f33148180 chore: make the release a manual dispatch
The job carried if: false, which blocks workflow_dispatch as well as
push, so there was no way to cut a release through CI at all and the
comment described a temporary state that had become permanent.

Releasing is deliberate: the push trigger is gone and the job runs when
someone dispatches it. The seven-day rate limit stays as the guard
against dispatching twice, and concurrency no longer cancels a run that
may be midway through uploading assets.
2026-08-11 05:08:40 +02:00
Abdessamad Derraz 0ea21912ce chore: add 2600.emu to the site nav 2026-08-11 01:47:43 +02:00
Abdessamad Derraz 7c79e4ff4f chore: refresh database and readme 2026-08-11 01:46:46 +02:00
Abdessamad Derraz 0d59979f2a fix: pin the digest order in cached entries
The cached hashes were rebuilt by iterating a set, so their order in
each database entry followed set hashing rather than a declared one. A
run with a warm cache rewrote all 7,850 entries with no content change.
The order is now the one compute_hashes returns, and a test holds a
warm-cache run byte-identical to a --force rehash.
2026-08-11 01:46:46 +02:00
Abdessamad Derraz f9d1b43ccf feat: profile 2600.emu
Atari 2600 port of Stella in the emu-ex-plus-alpha tree.
2026-08-11 01:46:46 +02:00
Abdessamad Derraz 0b5c534af4 fix: settle a contributed path before reading it
validate_pr.py inspects paths chosen by whoever opened the pull
request, and it hashed the file before deciding whether it was a
symlink. A link to /dev/zero was read until the job timed out, and a
link out of the checkout was hashed and reported as though its target
had been contributed. The shape is now settled first, and a test that
used to hang the run covers it.

The gate had no tests at all, and neither did the 3DS crypto reached
by dynamic import from validation.py: RSA PKCS#1 v1.5, AES-128-CBC and
ECDSA over GF(2^233), all written by hand. Coverage goes from 0 to 95%
on the curve, 0 to 55% on the gate, 9 to 35% on the rest. The curve
tests check against the published SEC 2 parameters rather than against
the module: the generator satisfies the curve equation and the group
order takes it to infinity.
2026-08-11 01:39:29 +02:00
Abdessamad Derraz e41b0dab9c feat: advance the gpsp and swanstation pins 2026-08-11 01:19:33 +02:00
Abdessamad Derraz ee08bd5c28 feat: give smsplus refs their source root 2026-08-11 01:18:41 +02:00
Abdessamad Derraz e32ae3a558 chore: refresh database, manifests and readme
The database drops the duplicate PS3UPDAT.PUP entry and regains
adler32 on every file. RetroPie gains an install manifest, so the
download table reports its size instead of a dash.
2026-08-11 01:13:36 +02:00
Abdessamad Derraz d815faeea6 feat: add six upstream core aliases
Each name is one a platform or the buildbot uses for a core the
profile already documents; without it the reverse index cannot reach
the profile and target filtering skips it.
2026-08-11 01:09:22 +02:00
Abdessamad Derraz 833a86cb0e feat: close the last anchored gaps 2026-08-11 01:08:30 +02:00
Abdessamad Derraz 13886ebead feat: resolve paths and load sites in six profiles 2026-08-11 01:01:11 +02:00
Abdessamad Derraz 825aa78bc5 feat: profile xm6 pro-68k, typeg and zesarux
X68000 and ZX Spectrum emulators read from their own source trees.
2026-08-11 00:56:14 +02:00
Abdessamad Derraz 367d4efaac feat: tag filtered packs by region and target
A region- or target-filtered build wrote to the same filename as the
full one. Both filters now appear in the pack and manifest names, and
verify.py accepts --region for emulator and system reports so the
coverage figures come from the same selection the builder used.
2026-08-11 00:56:14 +02:00
Abdessamad Derraz 87e19191b6 fix: pair each source repository with its own pin
A profile whose builds live in separate repositories keys source,
upstream and source_commit by build mode. The site flattened the URLs
but read a single scalar revision, so a libretro fork could be pinned
to the standalone commit, and binding the object form into SQLite
failed outright once ymir adopted it. URL and revision are now read as
pairs.

The site also published a sitemap nothing pointed at, so robots.txt is
generated alongside it.
2026-08-11 00:56:00 +02:00
Abdessamad Derraz 24e9b820ae feat: make packs reproducible byte for byte
Two builds of the same pack from the same inputs produced different
archives. Of 67 members, 65 were already identical: only README.txt
and manifest.json differed, both stamped with the wall clock by
writestr and the second carrying a generated timestamp. Generated
members now use the epoch the archive rebuilder already applies, and
the timestamp comes from the database snapshot the pack was built
from, so the same data yields the same bytes.

Install manifests skipped archived platforms, which is why RetroPie
had none; archived means upstream is no longer scraped, not that the
packs stopped shipping. A target-filtered manifest also had no record
of its filter beyond the filename, so it carries one the way a
region-filtered manifest already does.
2026-08-11 00:55:42 +02:00
Abdessamad Derraz dc14089932 fix: keep the database free of stale entries
Two entries claimed bios/Sony/PlayStation 3/PS3UPDAT.PUP with different
SHA1s. Preserving large-file entries matched on path and keyed on
SHA1, so replacing a firmware revision on disk left the old entry
pointing at a path that now serves other bytes. A preserved entry whose
path the scan has already claimed is dropped, and validate_schemas
refuses a database where one path carries two entries.

Separately, a run without --force rebuilt each cached entry from a
hand-written list of four digests and wrote it back without adler32,
so one such run stripped the digest from every file permanently. A
cache entry missing any digest is now a miss.
2026-08-11 00:55:32 +02:00
Abdessamad Derraz 3b8f2d75d5 perf: read yaml through the c loader
Loading the emulator profiles is the most expensive step of every
command here, and all forty call sites used the pure-Python scanner
while libyaml sat unused in the same wheel. One shared yaml_load picks
the C loader when pyyaml ships it: the 375 profiles parse in 0.18s
instead of 1.39s, and verify --platform retroarch drops from 2.17s to
0.73s. The loader class is the same restricted one safe_load uses.

es_bios.xml was parsed straight from the network while install.py
already refused a document declaring entities; both now share one
guard. Scrapers reach it through a single path bootstrap in the
package rather than two ad-hoc ones.
2026-08-11 00:55:16 +02:00
Abdessamad Derraz ab6a3bb26d refactor: single-source the native mode policy
verify.py and generate_pack.py must reach the same verdict on the same
file, and CLAUDE.md calls any divergence critical, but each spelled out
mode == 'existence' in its own words. Both now ask nativemode whether
the frontend reads the file's bytes, which is the one fact the rest
follows from, and a test holds the two answers together.

The BaseScraper contract the wiki asks contributors to implement had no
caller anywhere, so nothing proved compare_with_config, has_changes or
test_connection still worked.
2026-08-11 00:54:46 +02:00
Abdessamad Derraz 057b0c18f2 chore: widen the build triggers and pin set
A pack is the platform baseline plus what its cores need, so a profile
change alters pack contents; build.yml did not watch emulators/. Its
release notes read git log -15 on a depth-1 clone, which returns one
commit, and its test step ran a single module out of nineteen.

validate.yml ignored install.sh and install.ps1, so a PR touching only
a bootstrap skipped the test that pins them to install.py.

checkout and setup-python were pinned to v6 in two workflows and v7 in
the others; jsonschema was imported by validate_schemas.py and
declared nowhere, and requires-python claimed 3.10 while both
bootstraps accept 3.8.
2026-08-11 00:54:36 +02:00
Abdessamad Derraz 185cf47bbc fix: hold manifest paths inside the trust boundary
Every other manifest field was treated as hostile input, but
standalone_copies targets were only length-checked before being
expanded and written to: a traversal component or a symlink already
sitting at the destination sent the copy outside the directory the
user opted into. Targets are now validated like the other paths and a
symlinked destination is never followed.

RETROBIOS_BASE_URL serves the manifest and the files it declares, so
it now has to be HTTPS the way both bootstraps already require of the
installer URL; loopback stays open for the end-to-end tests.

install.ps1 left TLS at the Windows PowerShell 5.1 default, which
GitHub refuses, so the download failed before any hash was checked.

check_local read every file once per declared digest, single threaded.
One read now feeds both, across the same pool the downloads use.

RetroPie had no manifest, so the one-line installer answered 'unknown
platform' for a frontend whose packs do ship.
2026-08-11 00:54:27 +02:00
Abdessamad Derraz 958b988015 docs: scope the licence and temper the legal claims
LICENSE covered the whole repository, so the MIT grant read as
covering 9.9 GB of third-party firmware. It now states its scope and
NOTICE describes the files it does not cover, with a removal channel.

The FAQ cited Connectix and Accolade for redistribution when both
decided intermediate copying during reverse engineering, presented fair
use as settled, read section 1201(f) as a general permission, and
listed abandonware among legal doctrines. Each claim is now stated at
the strength it actually has, and the weakest ground is named.
2026-08-11 00:54:10 +02:00