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.
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.
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.
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.
"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.
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.
Where the truth names no value the platform lacks, hashes() still put
the truth's values first and rewrote the list in another order:
Recalbox's msx/CARTS.SHA md5 attribute came out with its two values
swapped, a diff line that changes nothing the frontend checks. The
platform's own list now stands when it already holds every value.
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.
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.
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.
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.
21 device archives collected for MAME 0.289 are byte-identical to sets already held under another name: a set renamed in 0.289 (tms32030 to tms320c30, hardbox to gpib_hardbox) or one ROM set several devices share (sys68k_cpu21 family, voicebox). One copy stays and the other names go to the MAME clone map, through which each name still resolves.
40 files BizHawk 2.11.1's FirmwareDatabase.cs names that the collection lacked, each verified against the sha1 it states: Mega CD and Master System revisions, TI-83 and TI-83 Plus ROMs, Game Boy and Game Boy Color boot ROMs, Super Game Boy, NDS firmware, 64DD IPL, 3DO and LaserActive PAC-S10 v1.02 (No-Intro [BIOS] LaserActive (USA) (v1.02)). Sources: archive.org bizhawk-firmware-files_20250516 and pioneer-laseractive-bios-pack.
The profile was pinned at 427556b5 (2.11) while the platform transcribes 2.11.1. In 2.11.1 FirmwareDatabase.cs rates one option per slot Ideal (MCD_eu_100, MCD_jp_100p, SCD_m1_us_110, SMS v1.3, gbaNormal and others), adds TI83_110.rom and a doom2.wad slot (DSDA.cs:85-99), and resizes the TI-83 Plus ROMs. The Ideal option of each slot is the required one, refs into the 12 changed files are remapped, and the 40 firmware files 2.11.1 names that the collection lacked are collected, each sha1-verified (LA_us_102.bin matches No-Intro [BIOS] LaserActive (USA) (v1.02)).
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.
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.
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.
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.
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.
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.
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.
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.
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.
parallel.rom (slot 1, src/config.c:527) and lib/letgothl.ttf (default printer font, src/sim65816.c:166) taken from gsplus-legacy-archive at 48057205, the revision the profile pins.
coco.zip held only bas10.rom, the MAME 0.190 to 0.250 set, while 0.289's coco loads bas10, bas11, bas12, extbas10 and extbas11. The complete set is rebuilt with build_torrentzip from held ROMs plus extbas10.rom (crc32 6111a086) checked against the listxml sha1. The old archive goes to .variants, no platform pins its md5. RetroBat and RetroDECK pin scv.zip without upd1771c-017.s03, which 0.289 requires: the pinned copy stays and the complete set goes to .variants.
The primary (sha1 f7101b40) is named by no dump catalog and differs from the catalogued dump in 60 runs of 16 bytes. The variant (sha1 b3b1d880) is the dump No-Intro, TOSEC and MAME 0.289 (laseractj, v105) name and the only one BizHawk 2.11.1 accepts (FirmwareDatabase.cs:294). No platform pins either md5, so the catalogued dump becomes the primary.
Recalbox builds digarok/gsplus-legacy-archive (gsplus.mk:8-9), Batocera a fork of it whose loading code matches, and RetroBat runs its gsplus-win-sdl release (GsPlus.Generator.cs:26-30). digarok/gsplus, which gsplus.yml documents, is a later KEGS 1.38 import sharing no history with it. The legacy build reads ROM, ROM1, ROM3, ROM01, ROM03, ROM.01, ROM.03 at 128 or 256 KB (src/config.c:863-908), refuses to start without one, and reads c600.rom, parallel.rom and printer fonts as optional.
The resolver reads built_by as the platforms on which a core name means this build. Its definition said platforms that compile a libretro build, which excludes a standalone build a platform installs from the project's release. The field now says what it decides: platforms that ship this build under its core name, compiled or installed from the release.
DuckStation (bios.cpp:208, 397-427), SwanStation (host_interface.cpp:
136-194), rustation (lib.rs:107-160), FS-UAE (rommgr.cpp:92-151),
ares (firmware.cpp:116-136) and Altirra (uifirmwarescan.cpp:29-113)
scan a folder and identify firmware by hash; Ymir does in its
standalone build only. FS-UAE still opens rom.key by name
(rommgr.cpp:1397-1498). The export then stops writing their labels
into platform lists: Batocera's psx block goes from 106 entries to 10,
and System.dat's scph5000.bin keeps its own hashes.
Entries without a system in multi-system profiles were left unattributed by the truth model, and four System.dat additions left the export. Each system is read from the core's code at its pin. hiscore.dat, cheats and history serve every running machine (mame2000 cpuintrf.c:664-666, mame2003 cpuexec.c:280-282, mame2003_plus cpuexec.c:296-298, fbneo hiscore.cpp:154-161 gated on BDF_HISCORE_SUPPORTED), all arcade in those builds, so arcade. BIOS sets take the id their driver gives in the other MAME profiles, and bctvidbs is barcrest-mpu4 everywhere. Files serving several systems of one build (groovymame data files, raine) keep no system. Core resolution is unchanged on every platform.
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.
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.
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.
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.