Commit Graph

378 Commits

Author SHA1 Message Date
Abdessamad Derraz
78fa5c3d0f feat: re-profile citra, regenerate database 2026-03-23 11:02:53 +01:00
Abdessamad Derraz
26f2824259 feat: re-profile 37 emulators with upstream verification
source-verified core_classification, upstream URLs, validation fields,
and hle_fallback flags. trimmed verbose notes. removed phantom files
(azahar boot9/sector0x96). added bsnes2014 variant profiles.
2026-03-23 10:58:32 +01:00
Abdessamad Derraz
06f5157c35 feat: profile mame, mame2010, mame2015, mame2016, fix aliases
source-verified BIOS root sets for all MAME cores:
- mame (0.286): 99 sets, official_port, new profile
- mame2010 (0.139): 51 sets, remove cvs.zip phantom
- mame2015 (0.160): 69 sets, replace false mame2016 alias
- mame2016 (0.174): 69 sets, fix 3 phantoms, add 2 missing
- mamearcade/mamemess: fix alias_of mame2016 to mame
2026-03-22 22:30:11 +01:00
Abdessamad Derraz
4883520dbf feat: profile mame2000, migrate bios_zips to structured files
Replace bios_zips section with structured files entries (category:
bios_zip, contents: with name/description/size/crc32) across all 4
MAME profiles. Profile mame2000 from source (was false alias of
mame2003_plus). Adds neogeo.zip, decocass.zip, hiscore.dat, cheat.dat.
2026-03-22 19:57:30 +01:00
Abdessamad Derraz
c342b61cdf feat: profile jumpnbump, kronos, lowresnx, lutro, m2000
add core_classification and upstream to all five profiles. kronos:
add ROM cartridge files (mpr-18811-mx.ic1, mpr-19367-mx.ic1), add
archive: field to STV blobs, remove unverified MD5 hashes, fix
cores list (remove yabause_libretro). jumpnbump: fix incorrect
note about embedded data. lowresnx, lutro, m2000: add missing
classification fields.
2026-03-22 14:39:47 +01:00
Abdessamad Derraz
1d350f0578 feat: add emulator/system pack generation, validation checks, path resolution
add --emulator, --system, --standalone, --list-emulators, --list-systems
to verify.py and generate_pack.py. packs are RTU with data directories,
regional BIOS variants, and archive support.

validation: field per file (size, crc32, md5, sha1) with conflict
detection. by_path_suffix index in database.json for regional variant
resolution via dest_hint. restructure GameCube IPL to regional subdirs.

66 E2E tests, full pipeline verified.
2026-03-22 14:02:20 +01:00
Abdessamad Derraz
d2adde9846 feat: update 47 emulator profiles with core_classification and fixes
add core_classification, cores, upstream fields. fix false aliases
(fixnes, fsuae, gearboy, higan_sfc, higan_sfc_balanced, potator,
quicknes). add new profiles (fbneo_neogeo, flycast_gles2,
genesis_plus_gx_wide). remove verbose notes and disclaimers.
2026-03-22 14:01:38 +01:00
Abdessamad Derraz
74f17694c2 feat: add category field to emulator profiles, source missing BIOS
Add category: game_data to sdlpal, nxengine, opentyrian, easyrpg,
mkxp_z profiles. verify.py separates game_data from bios in core
gap metrics for cleaner coverage numbers.

New BIOS files: Cemu fonts (4), QEMU bios-256k + vgabios-stdvga,
GAM4980 ROMs (2), SC-3000 Export variant.
2026-03-21 07:37:22 +01:00
Abdessamad Derraz
13a2938dc7 fix: correct 338 retrodeck hashes (sha1 truncation + stale mame 0.285) 2026-03-20 23:40:09 +01:00
github-actions[bot]
1996135cd1 regenerate database and docs 2026-03-20 19:12:35 +00:00
Abdessamad Derraz
27df5c8fb5 fix: resolve case collisions on case-insensitive filesystems
Move 17 case-colliding BIOS variants to .variants/ so Windows
and macOS clones no longer lose files. Existence-based platforms
keep the primary, MD5-based platforms resolve from .variants/.

Also fix resolve_local_file zipped_file resolution: when multiple
ZIPs share a name, verify the inner ROM exists before accepting
a candidate. Fixes adam_fdc.zip resolving to the wrong archive.
2026-03-20 20:02:42 +01:00
github-actions[bot]
3a7050a8cb regenerate database and docs 2026-03-20 12:10:56 +00:00
Abdessamad Derraz
30c104ac8e fix: correct Jaguar BIOS MD5 in retrodeck platform 2026-03-20 13:05:09 +01:00
Abdessamad Derraz
59ee9088fa chore: add Atari 1450XLD OS Rev 3 (1984-03-27) 2026-03-20 12:52:34 +01:00
Abdessamad Derraz
1c9261d304 chore: add Atari 1450XLD, Arabic 65XE, compiled OS 2026-03-20 10:04:06 +01:00
Abdessamad Derraz
4a76c5ca15 chore: add Atari OS-A NTSC, XEGS, doc format ares 2026-03-20 09:50:59 +01:00
Abdessamad Derraz
7b712ca089 chore: add Game Master, MSX, Atari BIOS files 2026-03-20 07:06:11 +01:00
Abdessamad Derraz
789ff0a32b chore: add MAME and RetroDECK ROM sets 2026-03-20 06:52:57 +01:00
Abdessamad Derraz
21bc225cac fix: resolve truncated md5 in batocera scraper
Batocera upstream has a truncated 29-char MD5 for zx48.rom.
The scraper now resolves truncated hashes via prefix match
against database.json, preventing schema validation failures.
2026-03-19 23:52:25 +01:00
github-actions[bot]
16fd815099 regenerate database and docs 2026-03-19 22:32:31 +00:00
Abdessamad Derraz
6ee162f8fb chore: add MAME and RetroDECK ROM sets 2026-03-19 23:26:49 +01:00
monster-penguin
1fcb948a00 Add RetroDECK Platform Support (#36)
* Add files via upload

* Add files via upload

* Update _registry.yml
2026-03-19 17:10:37 +01:00
github-actions[bot]
4992af07e7 regenerate database and docs 2026-03-19 15:15:53 +00:00
Abdessamad Derraz
6a21a99c22 feat: platform-core registry for exact pack generation
resolve_platform_cores() links platforms to their cores via
three strategies: all_libretro, explicit list, system ID
fallback. Pack generation always includes core requirements
beyond platform baseline. Case-insensitive dedup prevents
conflicts on Windows/macOS. Data dir strip_components fixes
doubled paths for Dolphin and PPSSPP caches.
2026-03-19 16:10:43 +01:00
Abdessamad Derraz
257ec1a527 fix: round 2 audit fixes, updated emulator profiles
Scripts:
- fix generate_site nav regex destroying mkdocs.yml content
- fix auto_fetch comma-separated MD5 in find_missing
- fix verify print_platform_result conflating untested/missing
- fix validate_pr path traversal and symlink check
- fix batocera_scraper brace counting and escaped quotes in strings
- fix emudeck_scraper hash search crossing function boundaries
- fix pipeline.py cwd to repo root via Path(__file__)
- normalize SHA1 comparison to lowercase in generate_pack

Emulator profiles:
- emux_gb/nes/sms: reclassify from alias to standalone profiles
- ep128emu: remove .info-only files not referenced in source
- fbalpha2012 variants: full source-verified profiles
- fbneo_cps12: add new profile
2026-03-19 15:00:18 +01:00
Abdessamad Derraz
38d605c7d5 fix: audit fixes across verify, pack, security, and performance
- fix KeyError in compute_coverage (generate_readme, generate_site)
- fix comma-separated MD5 handling in generate_pack check_inside_zip
- fix _verify_file_hash to handle multi-MD5 for large files
- fix external downloads not tracked in seen_destinations/file_status
- fix tar path traversal in _is_safe_tar_member (refresh_data_dirs)
- fix predictable tmp path in download.py
- fix _sanitize_path to filter "." components
- remove blanket data_dir suppression in find_undeclared_files
- remove blanket data_dir suppression in cross_reference
- add status_counts to verify_platform return value
- add md5_composite cache for repeated ZIP hashing
2026-03-19 14:04:34 +01:00
Abdessamad Derraz
e1410ef4a6 fix: exclusion reasons from YAML, not hardcoded in Python
Added exclusion_note field to emulator profiles. verify.py reads
this field instead of parsing notes text with fragile keywords.

desmume2015: explains .info vs code discrepancy
dolphin_launcher: explains standalone BIOS management

All exclusion messages now come from YAML data, not Python strings.
2026-03-19 13:17:55 +01:00
Abdessamad Derraz
eb21d214ab chore: regenerate database with updated profiles 2026-03-19 13:16:18 +01:00
Abdessamad Derraz
114732dc6d feat: intentional exclusion notes in verify report
New section "Intentional exclusions" explains why certain emulator
files are NOT in the pack:
- [frozen_snapshot]: code doesn't load .info firmware (desmume2015)
- [launcher]: BIOS managed by standalone emulator (dolphin_launcher)
- [standalone_only]: files for standalone mode, not libretro

Makes it clear that omissions are by design, not bugs.
2026-03-19 13:15:26 +01:00
Abdessamad Derraz
2509c61ffe feat: detailed core gap categories in verify report 2026-03-19 13:12:14 +01:00
Abdessamad Derraz
98afc86d0c feat: separate frozen snapshot profiles, fix shared cores
Created desmume2015.yml with files: [] (code doesn't load BIOS).
Removed desmume2015 from desmume.yml cores list.
Removed cdi2015 from same_cdi.yml (separate profile exists).

Frozen snapshots must have their own profiles because their
firmware behavior differs from the current version.
2026-03-19 13:11:25 +01:00
Abdessamad Derraz
316d2467eb refactor: replace emulator extras with cross-reference discovery
_collect_emulator_extras() now uses find_undeclared_files() from
verify.py instead of manual emulator name lists. This gives:
- System-overlap matching (automatic, no manual config needed)
- mode: standalone filtering (no standalone files in libretro packs)
- type: launcher filtering (no launcher BIOS in system_dir)
- data_directories coverage (no false gaps)
- hle_fallback propagation
- Works for ANY platform (same logic for RetroArch, Batocera, etc.)

RetroArch --include-extras now discovers 91 extra files from
emulator profiles automatically.
2026-03-19 13:10:36 +01:00
Abdessamad Derraz
de1940d57c feat: hle_fallback on 39 emulator profiles (266 entries)
Batch analysis of all 273 profiles to identify HLE/embedded
fallbacks. Added hle_fallback: true where the core has verified
software replacement for missing BIOS files:

- Embedded ROMs: vice (102), ep128emu (22), fuse (18), frodo (4)
- HLE BIOS: bsnes* (33 across 3 profiles), puae (9 AROS),
  noods (4), melonds* (6 FreeBIOS), flycast (3 reios)
- Open-source replacements: sameboy (8), pokemini (1), gpsp (1)
- Built-in fallbacks: np2kai (7), atari800 (6 Altirra),
  picodrive (3), quasi88 (4), gambatte (2)

Conservative: only added where notes or source code confirm HLE.
Skipped 50+ profiles where files are optional alternatives, not
HLE replaceable (neocd, opera, kronos, pcem, etc.)
2026-03-19 13:03:48 +01:00
Abdessamad Derraz
69ac957a3c feat: add hle_fallback to 9 emulator profiles
Marked files with HLE fallback based on source code analysis:
- desmume: 3 files (NDSSystem.cpp fake BIOS generation)
- dolphin: 31 files (HLE for IPL, DSP, fonts, Wii system)
- pcsx_rearmed: 7 files (psxbios.c full HLE replacement)
- easyrpg: 4 files (RTP and soundfonts optional)
- dosbox_core: all MT-32/soundfont/BASS files
- dosbox_pure: all MT-32/soundfont files
- boytacean: 8 boot ROMs (open-source embedded in binary)
- citra: shared_font.bin only (HLE for font rendering)
- azahar: shared_font.bin only

Not modified (no HLE): beetle_psx, duckstation, ecwolf, emuscv.
2026-03-19 12:55:03 +01:00
Abdessamad Derraz
d5daf98e5e feat: hle_fallback field + launcher filtering in verify
Added hle_fallback: true/false per file in emulator profiles.
When a core has HLE and the file is missing, severity downgrades
to INFO instead of CRITICAL — core works without it.

verify.py builds an HLE index from emulator profiles and applies
it during severity computation. Cross-reference now skips launcher
profiles (type: launcher) and includes hle_fallback in undeclared
file reports.

33 E2E tests (4 new: HLE severity, HLE index, launcher skip,
cross-ref HLE). 0 regressions.

Based on source code analysis:
- RetroArch core_info.c:2233 — existence check only, no blocking
- PCSX ReARMed psxbios.c:28 — full HLE BIOS replacement
- Dolphin CommonPaths.h — all files optional with HLE
- snes9x — DSP HLE built-in, coprocessor files optional
2026-03-19 12:51:52 +01:00
Abdessamad Derraz
13e5dd37f4 chore: remove redundant tests, keep E2E only (29 tests)
Removed 7 test files (135 tests) fully covered by test_e2e.py.
The E2E creates all fixtures in setUp, exercises every code path
with real files and real functions. Single source of regression.
2026-03-19 12:22:56 +01:00
Abdessamad Derraz
eb270a030f feat: E2E regression test with unified YAML fixtures (164 total)
Single test class with shared setUp creating all synthetic fixtures:
- bios files with known hashes (present/missing/wrong/alias/variants)
- ZIPs with inner ROMs (correct/wrong/missing inner)
- platform YAMLs (existence, md5, inherited, shared groups)
- emulator profiles (aliases, standalone mode, data_directories)

29 E2E tests covering: resolution (9), verification (5), severity (2),
platform config (2), cross-reference (4), grouping (2), storage (2),
md5_composite (1), check_inside_zip (4).

One fixture set, all scenarios, easy to maintain.
2026-03-19 11:37:11 +01:00
Abdessamad Derraz
c8861192e6 feat: advanced tests — md5_composite, storage tiers, data dirs (135 total)
17 new tests covering remaining scenarios:
- md5_composite: manual calc, dirs excluded, compression-independent,
  used in resolve_local_file
- storage tiers: external, user_provided, embedded, fetch_large_file
  with cache hit and hash rejection
- data_directories: suppress cross-ref gaps when matched, show gaps
  when unmatched
- shared groups: _shared.yml includes injection, empty group safe
- YAML inheritance: systems inherited, verification_mode override
- platform grouping: identical merged, different base_dest separated
2026-03-19 11:34:30 +01:00
Abdessamad Derraz
06d39cedad feat: YAML integration tests with fixtures (35 new, 118 total)
tests/fixtures/ with synthetic platforms, emulators, bios files:
- test_existence.yml: required/optional present/missing
- test_md5.yml: correct/wrong hash, zipped_file (3 cases),
  multi-hash Recalbox, truncated MD5 Batocera, dedup
- test_inherit.yml: YAML inheritance
- _shared.yml: shared groups
- emulator profiles with aliases, standalone mode, alias type

tests/test_integration.py covers:
- existence/md5 mode severity counts
- zipped_file inner ROM verification (3 cases)
- Recalbox multi-hash + Batocera truncated MD5
- worst-status aggregation per destination
- YAML inheritance
- cross-reference: undeclared, standalone skipped, alias skipped
- alias resolution
- pack consistency (verify == pack counts)
- shared groups parsing

All tests use real files, real hashes, real functions, no mocking.
2026-03-19 11:29:00 +01:00
Abdessamad Derraz
6d9edc5110 fix: review findings — hoist constants, cache emu profiles, renumber steps
- Hoist sev_order/sev_prio dicts to module-level constants (was rebuilt
  every loop iteration)
- Cache emulator profiles across platforms in verify main() (was loading
  260 YAMLs per platform, now loaded once)
- Renumber resolve_local_file steps 1-5 (was 1,2,3,5,6 after removal)
- Pass emu_profiles through verify_platform → find_undeclared_files
2026-03-19 11:22:58 +01:00
Abdessamad Derraz
b9cdda07ee refactor: DRY consolidation + 83 unit tests
Moved shared functions to common.py (single source of truth):
- check_inside_zip (was in verify.py, imported by generate_pack)
- build_zip_contents_index (was duplicated in verify + generate_pack)
- load_emulator_profiles (was in verify, cross_reference, generate_site)
- group_identical_platforms (was in verify + generate_pack)

Added tests/ with 83 unit tests covering:
- resolve_local_file: SHA1, MD5, name, alias, truncated, zip_contents
- verify: existence, md5, zipped_file, multi-hash, severity mapping
- aliases: field parsing, by_name indexing, beetle_psx field rename
- pack: dedup, file_status, zipped_file inner check, EmuDeck entries
- severity: all 12 combinations, platform-native behavior

0 regressions: pipeline.py --all produces identical results.
2026-03-19 11:19:50 +01:00
Abdessamad Derraz
011d0f9441 chore: regenerate database with alias indexes 2026-03-19 11:04:01 +01:00
Abdessamad Derraz
e240c70126 feat: complete platform-native verification with cross-reference
verify.py output now uses platform-native terminology:
- md5 platforms: X/Y OK, N untested, M missing
- existence platforms: X/Y present, M missing

Each problem shows (required/optional) from platform YAML.

Core gaps section summarizes undeclared files by severity:
- required NOT in repo: critical gaps needing sourcing
- required in repo: can be added to platform config
- optional: informational

Consistency check in pipeline.py updated to match new format.
All 7 platforms verified, consistency OK across verify and pack.
2026-03-19 10:44:17 +01:00
Abdessamad Derraz
5fd3b148df feat: platform-native verification with severity and cross-reference
verify.py now simulates each platform's exact BIOS check behavior:
- RetroArch: existence only (core_info.c path_is_valid)
- Batocera: MD5 + checkInsideZip, no required distinction
- Recalbox: MD5 + mandatory/hashMatchMandatory, 3-level severity

Per-file required/optional from platform YAMLs now affects severity:
- CRITICAL: required file missing or bad hash (md5 platforms)
- WARNING: optional missing or hash mismatch
- INFO: optional missing on existence-only platforms
- OK: verified

Cross-references emulator profiles to list undeclared files used by
cores available on each platform (420 for Batocera, 465 for RetroArch).

Verified against source code:
- Batocera: batocera-systems:967-1091 (BiosStatus, checkBios, checkInsideZip)
- Recalbox: Bios.cpp:109-130 (mandatory, hashMatchMandatory, Green/Yellow/Red)
- RetroArch: .info firmware_opt (existence check only)
2026-03-19 10:11:39 +01:00
Abdessamad Derraz
1bde934c45 chore: regenerate database.json with emulator aliases 2026-03-19 09:56:20 +01:00
Abdessamad Derraz
be5937d514 fix: align status terminology with Batocera source code
Batocera uses exactly 2 statuses (batocera-systems:967-969):
- MISSING: file not found on disk
- UNTESTED: file present but hash not confirmed

Removed the wrong_hash/untested split — both are UNTESTED per
Batocera's design (file accepted by emulator, just not guaranteed
correct). Fixed duplicate count bug from rename. Reason detail
(MD5 mismatch vs inner file not found) preserved in the message.

Verified against Batocera source: checkBios() lines 1062-1091,
checkInsideZip() lines 978-1009, BiosStatus class lines 967-969.
2026-03-19 09:49:16 +01:00
Abdessamad Derraz
c27720d710 feat: unified pipeline script with consistency check
scripts/pipeline.py runs the full retrobios pipeline in one command:
1. generate_db --force (rebuild database.json)
2. refresh_data_dirs (update data directories, skippable with --offline)
3. verify --all (check all platforms)
4. generate_pack --all (build ZIP packs)
5. consistency check (verify counts == pack counts per platform)

Flags: --offline, --skip-packs, --include-archived, --include-extras.
Summary table shows OK/FAILED per step with total elapsed time.
2026-03-19 09:33:50 +01:00
Abdessamad Derraz
6e421f6d84 fix: verify uses list_platforms for --all, add --include-archived
verify.py now uses the same platform listing as generate_pack.py:
--all shows active platforms, --include-archived adds archived ones.
Before, verify --all listed all .yml files without filtering.
2026-03-19 09:23:33 +01:00
Abdessamad Derraz
cfe2b1ff3d refactor: group identical platforms in verify output
Platforms sharing the same pack (same files + base_destination)
are grouped on one line: "Lakka / RetroArch: 449/449 files OK".
RetroPie stays separate (different base_destination BIOS/ vs system/).
Archived platforms (RetroPie) excluded from --all, available via
--platform retropie. Grouping matches generate_pack behavior.
2026-03-19 09:15:29 +01:00
Abdessamad Derraz
a88a452469 refactor: clear, consistent output for verify and generate_pack
Both tools now count by unique destination (what the user sees on
disk), not by YAML entry or internal check. Same file shared by
multiple systems = counted once. Same file checked for multiple
inner ROMs = counted once with worst-case status.

Output format:
  verify:  "Platform: X/Y files OK, N wrong hash, M missing [mode]"
  pack:    "pack.zip: P files packed, X/Y files OK, N wrong hash [mode]"

X/Y is the same number in both tools for the same platform.
"files packed" differs from "files OK" when data_directories or
EmuDeck MD5-only entries are involved — this is expected and clear
from the numbers (e.g. 34 packed but 161 verified for EmuDeck).
2026-03-19 09:06:00 +01:00