Commit Graph
1172 Commits
Author SHA1 Message Date
Abdessamad Derraz cdb2cfa6f0 feat: find RetroBat through the folder it records
RetroBat.exe writes its folder to HKCU\SOFTWARE\RetroBat
LatestKnownInstallPath on every start (retrobat-executable 702da66a,
Program.cs:57 and 99, RegistryTools.cs:15-50). Only C:\RetroBat and the
profile folder were looked at, so an install on D: was missed and a forced
--platform retrobat wrote into C:\RetroBat\bios. The value is read
through winreg, or reg.exe under WSL, before the fixed folders.
2026-10-21 05:28:35 +02:00
Abdessamad Derraz 4f20b5daaf fix: name the network when every transfer fails
A run whose downloads were all cut ended on "Location that was being
written to" and "once that is resolved", pointing at the disk. A
failure caused by the connection (lookup, reset, timeout, TLS, a cut
transfer, HTTP 5xx or 429) is now marked as such, and the summary says to
check the connection and HTTPS_PROXY.
2026-10-21 05:25:19 +02:00
Abdessamad Derraz 253a41ebc8 feat: list the names --emulator accepts
An unknown --emulator name pointed at --list-cores and counted 441 names
while --list-cores prints 189: the buildbot names --emulator accepts
(mednafen_psx for beetle_psx) were listed nowhere. --list-emulators prints
each accepted name beside the emulator it stands for, and the hint names
it.
2026-10-21 05:22:08 +02:00
Abdessamad Derraz 8a19d647a8 fix: pass -v and every short flag to install.py
A [Parameter()] attribute made install.ps1 an advanced script: its common
parameters took -v (-Verbose), -vb, -d and -ea before install.py saw them,
and the scriptblock form printed PowerShell's own VERBOSE lines. The
wrapper now forwards $args as typed.
2026-10-21 05:16:52 +02:00
Abdessamad Derraz 1392f00c8d fix: replace a link at a standalone copy's name
A link already at the destination was skipped without a word and counted
as "dir not found" while the folder existed, so the emulator kept the file
the link pointed at. The link now gives way to the file, written beside it
and renamed over the name, and a name leading out of the folder is a named
failure.
2026-10-21 05:16:16 +02:00
Abdessamad Derraz 9b1d378d2f fix: never truncate a copy another run renames
On Windows a verified partial copy is closed before its rename. A second
run that claimed it in that moment truncated it and the first rename failed
with a sharing violation, reported as an unwritable folder. A complete
partial is now left whole there, the rename waits for a sharing violation
to clear, and a sharing violation no longer reads as a refused folder.
2026-10-21 05:16:12 +02:00
Abdessamad Derraz c638c12ca8 fix: replay the builder's held and one-file groups
install.region_drops now skips one-file groups (:file:) and lets no
omitted match displace an installable file, as region.resolve_region_drops
does on the builder side. The property test draws both cases and
compares against the builder.
2026-10-21 05:15:56 +02:00
Abdessamad Derraz 82acd55ebc fix: guide installer users with their own command
Names are matched on letters and digits, so the site's display names
work, and a typo gets the closest names instead of a full list. Hints
and advice give back the command the user ran (curl or PowerShell form,
every flag kept), --dest alone follows detection and says whose list it
installs, Ctrl+C at a question exits 130, and --cores-dir names a core
folder. install.ps1 runs in its own scope so irm | iex leaves the
session alone, and an override that causes a fingerprint mismatch is
named. --check lists hash mismatches first, missing required files are
grouped by system, and --help ends with examples.
2026-10-21 04:47:50 +02:00
Abdessamad Derraz 7095aa61e7 fix: make maintainer tool output actionable
--emulator accepts a buildbot core name from a profile's cores:, and a
mistyped target gets the closest names instead of every target. diff_truth
shows destinations and reports unpaired entries as evidence, not removals.
The verify summary counts discrepancies, a shared destination names both
systems, a truth hash conflict names both cores, and pipeline steps carry
their place in the real run instead of N/8. Every GitHub API caller takes
the token from github_token(), which falls back to gh auth token.
2026-10-21 04:42:01 +02:00
Abdessamad Derraz 6ee138a819 docs: point users to --check and exact pack files
Troubleshooting, the FAQ and the download page sent people who only ran
the installer to verify.py, which reads the repository, not their BIOS
folder. Download links now name the exact asset of the recorded release,
the --dest example names the BIOS folder on the card, the slice layout
left with the last release that used it, and the shown verify output is
what the tool prints.
2026-10-21 04:34:04 +02:00
Abdessamad Derraz 621f4fcdee fix: give fork pull requests the hash report
A fork's GITHUB_TOKEN is read-only, so the comment never arrived and a
valid file turned red. The report now goes to the job summary for every
pull request, and the comment and labels run only where the token can
write. validate_pr points an oversized file to an issue instead of a
platform setting a contributor cannot use.
2026-10-21 04:25:25 +02:00
Abdessamad Derraz 392aacb207 fix: hash a large download through its own handle
On Windows the partial copy of a file of 16 MB or more is locked with msvcrt.locking, a LockFile region: the locking process cannot access that region through a second handle (Microsoft LockFile remarks). Hashing reopened the path, the read failed with a sharing violation, and every large file was reported as 'folder not writable' (issue 82). Both digests are now read in one pass through the handle that holds the lock. A read-only file already at the destination had the same misleading report: on Windows its attribute is now cleared before the verified copy replaces it, and a refusal that remains is named for what it is.
2026-10-21 03:46:14 +02:00
Abdessamad Derraz cf54730a17 fix: lay out RetroPie standalone packages
RetroPie's YAML listed no standalone_cores, so every package was laid
out as a libretro core and the standalone files of amiberry, dolphin,
hatari, mame and ppsspp never reached the pack. Packages without the
lr- prefix (bar the retroarch frontend) are now standalone, and names
shipped both ways are dual-mode.
2026-10-20 23:04:42 +02:00
Abdessamad Derraz 6d38e597db fix: keep a RetroPie list's comma before its and
quasi88 writes its list "N88KNJ2.ROM, and N88SUB.ROM". Extended with
N88EXT0.ROM, which QUASI88kai reads, it came back as "N88SUB.ROM and
N88EXT0.ROM": every list was rewritten in one idiom. A list that puts a
comma before its final and keeps it.
2026-10-20 22:38:32 +02:00
Abdessamad Derraz e787efca22 fix: match a size-checked entry to its launcher
EmuDeck passes Complex_4627v1.03.bin as xemu's flash ROM
(emuDeckXemu.sh:60-61), and xemu's entry Complex_4627.bin states no hash,
only the sizes it maps. The layer matched entries by name or content
only, so without the alias the default name was still asked for. A
hashless entry that checks a size now takes a launcher file of a size
it accepts, when no other entry of that core accepts that size too.
2026-10-20 22:20:42 +02:00
Abdessamad Derraz 540374b40d fix: count a launcher's names as read
The removal candidates looked for a reading in the profiles only, so a
name the platform's own launch code opens, links or copies was listed
as read by no core: Batocera's DuckStation generator walks 22 names
(duckstationGenerator.py:501-515). Every name a launcher record names
is now a reading on that platform. Recalbox's unexplained entries drop
from 20 to 13, RetroBat's from 24 to 20, EmuDeck's from 25 to 22.
2026-10-20 22:20:42 +02:00
Abdessamad Derraz c702cdf62e fix: pack no launcher file the emulator installs
The launcher layer packed a file under the launcher's name whatever the
platform installs: ROCKNIX's xemu config reads hdd/xbox_hdd.qcow2, and
the profile marks that image installed_on rocknix, yet the pack brought
one. A place whose entry the emulator installs on that platform is now
filled by the install, as validation.deliverable has it for the pack.
2026-10-20 21:28:57 +02:00
Abdessamad Derraz b2b8dcd62c feat: read platform launchers in verify and packs
A names_searched list is one place the launcher fills with the first name it finds, so a core file it would never open once another name of the list is held is not reported missing. A place no declared file and no packed core file fills receives, under the launcher's name, a file the core accepts by content. The layer is applied inside find_undeclared_files, which verify and the pack builder both read, and a test reads their source to keep it there.
2026-10-20 21:26:48 +02:00
Abdessamad Derraz 74a9d7beea feat: read RetroDECK launchers from components
The scraper reads each component's prepare, launcher and functions scripts at the components commit the BIOS list comes from, and the presets they copy: the fixed paths set_setting_value writes (melonDS seven, xemu three, Dolphin GBA), the folders handed over, the dir_prep links (LRPS2 pcsx2/bios back to bios/, Dolphin and PrimeHack GC regions under saves/), package copies into bios/, RetroArch core options naming a file (pcsx2_bios, DuckStation per region), XRoar romlists, the PICO-8 exec and the RPCS3 and Vita3K firmware downloads.

platforms/retrodeck.yml is regenerated at fcd0d729: only the launchers section is new.
2026-10-20 21:13:09 +02:00
Abdessamad Derraz 15ffeddfe3 feat: read RetroPie launchers from scriptmodules
The scraper walks each package's functions the way RetroPie runs them in one shell (assignments, arrays, for loops, brace expansion, $md_id, calls into other packages) and records every link, copy, move and setting that names $biosdir, the addEmulator flags (sdltrs -romfile3), the BIOS read outside $biosdir (basilisk --rom, gngeopi -B) and the launch scripts that exit without their file (fs-uae kick13.rom, reicast dc_boot.bin).

Each package also gets a package record with its rp_module_repo and the systems it registers, which maps a package to the build it compiles. The schema gains package, repo, systems and the moves and package kinds. platforms/retropie.yml is regenerated at 46128cd2: only the launchers section is new.
2026-10-20 21:13:09 +02:00
Abdessamad Derraz fe9a081cfb feat: read Recalbox launchers from configgen
The scraper now records, from configgen at the pinned tag, the names each Recalbox launcher tries and where it hands them: the Hatari TOS cascades (standalone, hatari and hatarib cores), GSplus, Amiberry kickstarts, the PCSX2 region choice, the Dolphin IPL presence test, xemu, the mupen64plus 64DD IPL, the Mini vMac boot disk and the o2em_bios option. The system_directory libretroRetroarch gives each core, and the per-system overrides after it, are passes_path records.
2026-10-20 20:59:51 +02:00
Abdessamad Derraz 3837d6f097 feat: read EmuDeck launchers from EmuScripts
The scraper reads the EmuScripts at the commit checkBIOS.sh is pinned to: the BIOS paths changeLine, iniFieldUpdate and RetroArch_setConfigOverride write, the ares and melonDS configs whose paths sed rewrites, and the bios/ directories linked to Flycast, Azahar, the Switch emulators and shadPS4. The script to emulator mapping moves beside the extractors so both read one table.
2026-10-20 20:45:19 +02:00
Abdessamad Derraz 57af8e4921 feat: read ROCKNIX launchers from its packages
The scraper reads the start scripts and the configs each package installs at the tag the BIOS list is pinned to: configs that name a BIOS path, the yabasanshiro search, directories handed to DuckStation and the PCSX2 builds, and the ln -s commands that put bios/ where an emulator reads. A package that ships one config per device gets a device field only where the values differ, as melonDS does on AMD64.
2026-10-20 20:45:19 +02:00
Abdessamad Derraz a9c175d322 chore: regenerate the updated platform files 2026-10-20 20:44:42 +02:00
Abdessamad Derraz 419d68d1f2 feat: read RetroBat launcher records
The scraper reads emulatorLauncher's generators and es_features.cfg at the commit the BIOS list is pinned to: Ares, Hatari, Mesen, Amiberry, WinUAE, PCSX2, the PSX BIOS cascades, Xemu, openMSX and DuckStation. Each extractor raises when its construct is gone.
2026-10-20 20:14:52 +02:00
Abdessamad Derraz 897fe17ab2 feat: read Batocera launchers from configgen
The scraper parses the configgen generators with ast at the pinned tag: DuckStation and its legacy build, Hatari, xemu, melonDS, mupen64plus 64DD, x16emu, GSplus, and the o2em and neocd core options. An extractor that no longer recognises its code raises instead of writing an empty list.
2026-10-20 20:14:30 +02:00
Abdessamad Derraz 479ada29fe docs: word removal candidates by what was searched
"No core opens it" claimed more than the search shows: what was
checked is that no profile of a core the platform runs names the
entry by name, path or hash. The reason and the page sentence now
say that.
2026-10-20 20:00:54 +02:00
Abdessamad Derraz 545e3f3ba1 feat: record each export change before and after
The page named the entries a change touched and never the values, so
a maintainer could not check a correction. The report now carries
changes, one object per change with kind, entry, field, old and new,
read from the platform entry and from the value the render writes
(written() per format: record value for System.dat and RomM, one md5
where a single one is checked). The existing label lists are derived
from it. The page writes "md5 X becomes Y" and names each required
flag with its new value. A test parses the original and updated
System.dat and es_bios.xml and checks the list equals the diff.
2026-10-20 20:00:54 +02:00
Abdessamad Derraz 0b4f98ce79 feat: report entries no examined core opens
The export keeps every entry a platform declares. An entry the truth
does not pair was still read in 1189 of 2776 cases (alias, hash, a
type: directory tree, a core outside the resolved set), so absence of
a pairing proves nothing. Each report now lists, under
removal_candidates, the unpaired entries that no profile of the cores
the platform runs answers by name, path tail, hash, directory or data
directory, with the cores examined and a reason. A core the platform
names without a profile, or a ROM set under a core that opens sets by
name, leaves the verdict undetermined. The exports page states the
count and lists the entries per platform.
2026-10-20 20:00:54 +02:00
Abdessamad Derraz 7e0b3a08b9 fix: keep System.dat lines whose values agree
The rom line renderer upper-cased every crc, so Dinothawr.zip's
683ed4ad, the one lower-case crc libretro writes, changed with no
correction behind it. A line whose values match ours now keeps its
bytes, a corrected crc follows the case of its own line, and an added
line keeps the file's upper case. An empty truth hands System.dat back
byte for byte for RetroArch and Lakka.
2026-10-20 19:39:36 +02:00
Abdessamad Derraz eba5f1dd62 fix: patch Recalbox's attributes, not its elements
A changed element was rendered again, losing its alignment and the
place of its attributes, and an element whose md5 list was only
reordered (neogeo.zip, the same 24 digests) was rewritten too: Recalbox
accepts any digest of the list (Bios.cpp:109-130), so the order is not
content. A changed attribute is now replaced where it stands, one
dropped goes with its space, one added goes before />, and each system's
opening tag keeps its own indentation. An empty truth gives back the
cached es_bios.xml byte for byte.
2026-10-20 19:36:09 +02:00
Abdessamad Derraz aaffcdcb63 fix: patch Batocera's values, not its entries
An entry with one md5 to correct was written again whole: atarist lost
its eight blank lines, every '"x"},' became '"x" },', and most of the
819 lines Batocera's export changed were layout. Each item now keeps
its own text and only the md5 inside it changes; an addition follows
the last item in its indentation and spacing. The patched entry must
read as the one that would have been written, or that one is written.
Batocera's diff to the original drops to 273 lines, ROCKNIX's to 3.
2026-10-20 19:22:58 +02:00
Abdessamad Derraz 659e9b591f fix: keep RetroBat's blank line between systems
RetroBat separates every system after the first with a blank line.
json.dumps dropped all 100 of them: 100 hunks of noise in a diff meant
to show corrections. The separator is written again where the original
has it, and an added system takes it too where the original separates
them all. An empty truth gives back the cached file byte for byte.
2026-10-20 19:07:46 +02:00
Abdessamad Derraz 804534397f fix: write the MiSTer database on one line
The BiosDB is published as a single line of JSON without a final
newline. Written with indent=2 it came out as 1499 changed lines for a
database whose content had not changed, which would bury any real
correction. It is now written in MiSTer's own form: an empty truth
gives back the cached database byte for byte.
2026-10-20 18:54:28 +02:00
Abdessamad Derraz 3ed5f68b82 fix: hand RetroDECK manifests back as written
With nothing to correct, nine of ten manifests still changed: a final
newline was added where the original ends without one, "md5": null was
written 39 times where no md5 key was, and PPSSPP's single bios object
became a list rebuilt from our data. A manifest now ends as the
original does, keeps no key it did not have, and a single object stays
one while nothing is added. An empty truth gives back every cached
manifest byte for byte.
2026-10-20 18:41:26 +02:00
Abdessamad Derraz 85c2433c98 fix: write each export as its bytes and mode
write_text translated line ends on Windows, so FirmwareDatabase.cs's
CRLF would have come out CR CR LF; it replaced the published file in
place, so a run stopped mid-write left it truncated; and it dropped the
mode, while rocknix-systems is 100755 in ROCKNIX's tree. Files are
written atomically as UTF-8 bytes, and an exporter states the mode of
any file the platform does not publish as 0644.
2026-10-20 18:27:22 +02:00
Abdessamad Derraz cbe769e74c fix: read all RetroPie helps, propose only its own
Eight scriptmodules write "bios" in lower case (xm7, np2pi, quasi88,
minivmac, px68k...) and none was examined. A module reported "left as
is" for a name no profile documents was written all the same: the skip
had no continue. The cap of six names came from that case-sensitive
reading, where xm7 writes thirteen: a sentence now grows no longer than
the longest RetroPie writes. lr- was stripped whatever the build, so the
standalone minivmac package matched the libretro profile, which reads
another file. A file of a system RetroPie lacks is proposed to no
package: lr-geargrafx adds pcengine only (lr-geargrafx.sh:41-42) and
was given the LaserActive's pac-n1.bin and pac-n10.bin.
2026-10-20 18:12:56 +02:00
Abdessamad Derraz 95476afb28 fix: make the report directory before writing it
A platform with nothing left to correct writes no file, so its output
directory was never made: RetroPie's report then raised
FileNotFoundError into a fresh --output-dir and stopped --all.
2026-10-20 18:12:45 +02:00
Abdessamad Derraz d92291684c fix: dual-mode only what ROCKNIX runs both ways
The scraper declared every standalone package launched both ways,
reasoning that RetroArch carries every libretro core. package.mk says
otherwise: it adds ARMSX2 as armsx2-sa only (add_emu_core ps2 armsx2
armsx2-sa true), so the libretro build's pcsx2/resources entries
reached ROCKNIX's list as armsx2-sa files the standalone installs
itself. An emulator is now dual-mode only when package.mk also adds it
as a retroarch core: ten of the 63 standalone names.
2026-10-20 17:53:57 +02:00
Abdessamad Derraz a5d7a6572d fix: ask for no file the emulator installs
The pack leaves out what an emulator installs itself
(validation.deliverable); the truth did not. RetroPie's gngeopi help
asked users to copy gngeo_data.zip, which make install puts in the
package's data directory, and amiberry's whdboot tree, scummvm's extra
data and dosbox-x's FREECG98.BMP went into platform lists as files to
bring.

The truth applies deliverable per platform and per build: an entry
nobody has to bring is kept and marked bundled, never added, still
corrected where the platform declares it. A rebuilt archive is
installed only when every member is. The runner written beside an
addition is the build that needs the file (_brought_by), and the
RetroPie sentence names only what its package's core must be given.
2026-10-20 17:39:21 +02:00
Abdessamad Derraz f957b5f893 fix: open no System.dat section libretro lacks
libretro titles each section with the system as it spells it,
"Commodore - Amiga". An addition for a system it has no section for
opened one under our slug: 21 sections came out as commodore-c64,
quake, laseractive or xrick, which no libretro DAT carries. An addition
now lands only in a section the original holds and is otherwise counted
as left out, so the export keeps the original's 66 sections. A platform
entry is always written, under its own section.
2026-10-20 17:21:16 +02:00
Abdessamad Derraz e5174a07bf feat: mark files a core finds by content
DuckStation identifies its BIOS by MD5 in a folder it scans
(bios.cpp:208), so its entries' names are labels. The export wrote them
into Batocera's and ROCKNIX's lists as files to hold: a user with only
scph5501.bin read 104 missing BIOS where DuckStation boots. Labels also
lent their md5 to a name another core opens, and paired by name they
replaced System.dat's scph5000.bin hashes.

found_by: name | content, on a profile or a file and keyed by build like
load_from. The truth records which cores open each name (_named_by). A
label pairs with a platform entry by hash only, is never added, merges
with an opened name only on a shared hash, and is counted in the export
report rather than listed as missing.
2026-10-20 16:32:22 +02:00
Abdessamad Derraz 0eec5ab4be fix: file a truth entry by content, not by name
A name the platform declares filed an entry under that system before
its own system:, and the last declaration of a name won. fmsx's 16 KB
DISK.ROM went to nec-pc-88 for quasi88's 2 KB disk.rom and came out as
a second DISK.ROM line under "NEC - PC-8801"; dosbox's SC-55
ROM1.BIN/ROM2.BIN went to galaksija.

A declaration now files an entry only when it can be the same file: a
shared hash, or no size both admit. The same content declared under two
systems is filed under both, an entry's own system stands against a
refuted homonym, and a systemless profile's placeholder takes only names
the platform does not declare. Merging reads the same size rule, so a
24 KB ROM and an entry capped at 16 KB stay two files.
2026-10-20 16:14:55 +02:00
Abdessamad Derraz f758efd062 fix: write no export its validator refuses
validate() ran after the files were written, so an export the
exporter's own validator refused still replaced the published one in
exports/, and only the exit code said so. The platform now fails before
anything is cleared or written.
2026-10-20 15:55:29 +02:00
Abdessamad Derraz 49b79a6d52 fix: refuse a file read off the pinned revision
pinned_base returned an empty base when the platform's source named no
revision or no longer ended in the exported file, and the exporter's
own branch URL was then patched without a word. Every file an export
reads must now carry the revision the platform YAML records, or the
platform fails and asks for a rescrape. The check covers every file of
every platform: ROCKNIX's second file, RetroDECK's manifests and
RetroPie's tarball were checked by nothing before.
2026-10-20 15:40:28 +02:00
Abdessamad Derraz 4da40c471d fix: isolate an unreadable original per platform
A cached bios_db.json.zip that was not a zip raised BadZipFile out of
run(): --all stopped and the platforms after it were never exported.
fetch() also cached any 200 reply, so an error page replaced a good
archive and was served on every later run, and an IncompleteRead or an
oversized reply escaped the same way. An archive is now read before it
is cached, and an unreadable file fails its own platform with the
--refresh-cache remedy.
2026-10-20 15:24:30 +02:00
Abdessamad Derraz 8de45b6f45 feat: generate MAME device sets from -listxml
A machine that instantiates a device loads the device's ROMs from <shortname>.zip (src/emu/device.cpp:140-152), and a missing required ROM stops that machine (romload.cpp:529-570, 667-671). The BIOS root scan never sees these sets. mame_hash_scraper --devices --listxml reads them from the -listxml of the release mame.yml pins, refuses another release, and cites each set at the ROM_START block holding its ROMs. The BIOS root merge also wrote refs without the upstream prefix and would have rewritten all 171 of them in mame.yml.
2026-10-20 15:12:23 +02:00
Abdessamad Derraz 7a65a2cf83 fix: refuse an export without its original
System.dat, RomM, Recalbox and RetroBat were rebuilt from our data when
their file was not cached: libretro's quoted names, Recalbox's comments
and one of its two zxspectrum blocks were lost, and the run said OK.
needs_original now follows native_sources, so every format we patch
fails without the file it patches and writes nothing.
2026-10-20 15:09:16 +02:00
Abdessamad Derraz 19b88ca055 fix: refuse an export without its truth
dist/ is not committed and exports/ is. On a fresh clone, or with a
mistyped --truth-dir, the export copied each platform's file back
uncorrected, said OK and replaced the corrected export in exports/.
check_freshness then reported a stale export instead of the missing
model. The platform now fails, writes nothing, and names the
generate_truth command.
2026-10-20 14:54:16 +02:00
Abdessamad Derraz e81c63804a fix: correct no hash the code does not check
validation: names what the code verifies. dosbox checks
MT32_CONTROL.ROM against nine sha1 and size; the truth's one md5 and
crc32 describe one of those revisions, and the export wrote them beside
System.dat's own sha1, a rom line no file satisfies, and replaced
Batocera's md5. pcsx_rearmed and DuckStation check scph1001.bin by size,
and the v2.0 md5 platforms name was replaced by v4.1's.

checked_hashes keeps a hash the code does not name only where a checked
hash pins one content. Otherwise it still pairs a renamed file but never
corrects or fills a value the platform wrote. Additions keep every hash.
diff_truth reads the same rule.
2026-10-20 14:40:10 +02:00