diff --git a/emulators/2ship.yml b/emulators/2ship.yml index 89bb7c6c..8b8c6e53 100644 --- a/emulators/2ship.yml +++ b/emulators/2ship.yml @@ -1,8 +1,8 @@ emulator: 2 Ship 2 Harkinian type: standalone core_classification: game_engine -source: "https://github.com/HarbourMasters/2ship2harkinian" -upstream: "https://github.com/HarbourMasters/2ship2harkinian" +source: "https://github.com/2ship2harkinian/2ship2harkinian" +upstream: "https://github.com/2ship2harkinian/2ship2harkinian" source_commit: "8a24047fbce8915993804e7819f4df4fa591551f" profiled_date: "2026-10-20" core_version: "5.0.1" diff --git a/emulators/amiberry.yml b/emulators/amiberry.yml index 13cbb308..42d8d6c5 100644 --- a/emulators/amiberry.yml +++ b/emulators/amiberry.yml @@ -129,7 +129,7 @@ files: required: false size: 524288 aliases: [amiga-os-310-cd32.rom, kick40060.CD32] - note: "CD32 Kickstart v3.1 rev 40.60" + note: "CD32 Kickstart v3.1 rev 40.60. candidates_cd32 tries cd32.rom, amiga-os-310-cd32.rom, kick40060.CD32, kick31.rom, then kick.rom." source_ref: "source libretro/libretro.cpp:1811 (candidates_cd32)" - name: cd32ext.rom @@ -146,7 +146,7 @@ files: system: commodore-cdtv required: false aliases: [kick34005.CDTV] - note: "CDTV extended ROM v1.00, used as kickstart candidate" + note: "CDTV extended ROM v1.00, used as kickstart candidate. candidates_cdtv tries cdtv.rom, kick34005.CDTV, kick13.rom, then kick.rom." source_ref: "source libretro/libretro.cpp:1812 (candidates_cdtv)" - name: cdtvext.rom diff --git a/emulators/ares.yml b/emulators/ares.yml index f0d9ac96..0bd66a8c 100644 --- a/emulators/ares.yml +++ b/emulators/ares.yml @@ -57,8 +57,7 @@ notes: | (desktop-ui/emulator/emulators.cpp). Firmware identification uses SHA256 hashes. Filenames are user-defined: ares - scans a configured directory and matches by hash. EmuDeck installs ares as - Flatpak (dev.ares.ares), configures biosPath in settings.bml. + scans a configured directory and matches by hash. ref: desktop-ui/settings/firmware.cpp:116-136 Firmware path resolution: settings.paths.firmware (user override) or @@ -83,10 +82,18 @@ notes: | after loading. ref: mia/system/neo-geo-aes.cpp:12-30, mia/system/neo-geo-mvs.cpp:12-30 - SFC subsystem ROMs (SuFami Turbo, Satellaview, Super Game Boy): loaded as - game cartridges via CLI args, not through the firmware system. EmuDeck creates - launcher shortcuts that pass these alongside game ROMs. - ref: emuDeckares.sh (EmuDeck repo) + SFC base cartridges (Super Game Boy, Satellaview BS-X, Sufami Turbo) are + games, not firmware: the file opened as the Super Famicom game is the base + cartridge, and the cartridge it describes then asks for the Game Boy, BS + Memory or Sufami Turbo medium through its slot. Each medium comes from the + load queue, then the command line, then a file dialog, so ares names none of + these files. mia identifies the base cartridge by the SHA-256 of its ROM in + the Super Famicom database, else by its header: the BANDAI SFC-ADX + signature makes a Sufami Turbo board, serial ZBSJ a BS-X board, serial 042J + or cartridge type 0xE3 a Super Game Boy board. + ref: desktop-ui/emulator/super-famicom.cpp:158-217, + desktop-ui/emulator/emulator.cpp:155-186, + mia/medium/super-famicom.cpp:88-95, mia/medium/super-famicom.cpp:570-602 Systems with no firmware: Arcade, Atari 2600, Famicom, MyVision, PC Engine, SuperGrafx, SG-1000, SC-3000. @@ -418,26 +425,34 @@ files: system: super-famicom required: false category: game_data - description: "Super Game Boy cartridge ROM. Loaded via CLI as SFC cartridge alongside GB game." - source_ref: "EmuDeck emuDeckares.sh (launcher)" + description: "Super Game Boy cartridge ROM, opened as the Super Famicom game. The SGB1 boot ROM is embedded and appended when the image lacks it." + note: >- + Without its own boot ROM the image gets the embedded SGB1 boot ROM appended before hashing, so the database SHA-256 (4d7fc331, SYS-SGB-2) is that of the 256 KiB ROM followed by the 256-byte boot ROM. + source_ref: "desktop-ui/emulator/super-famicom.cpp:179-187, mia/medium/super-famicom.cpp:42-62, mia/medium/super-famicom.cpp:88-95, mia/medium/super-famicom.cpp:891-895" - name: SGB2.sfc system: super-famicom required: false category: game_data - description: "Super Game Boy 2 cartridge ROM. Loaded via CLI as SFC cartridge alongside GB game." - source_ref: "EmuDeck emuDeckares.sh (launcher)" + description: "Super Game Boy 2 cartridge ROM, opened as the Super Famicom game. The SGB2 boot ROM is embedded and appended when the image lacks it." + note: >- + Identified by serial 042J or the label Super GAMEBOY2. Without its own boot ROM the image gets the embedded SGB2 boot ROM appended before hashing, so the database SHA-256 (e1db895a, SYS-SGB2-10) is that of the 512 KiB ROM followed by the 256-byte boot ROM, and the board carries its own 20971520 Hz oscillator. + source_ref: "desktop-ui/emulator/super-famicom.cpp:179-187, mia/medium/super-famicom.cpp:42-62, mia/medium/super-famicom.cpp:88-95, mia/medium/super-famicom.cpp:590-592, mia/medium/super-famicom.cpp:891-895" - name: STBIOS.bin system: super-famicom required: false category: game_data - description: "SuFami Turbo adapter BIOS. Loaded via CLI as SFC cartridge alongside SuFami games." - source_ref: "EmuDeck emuDeckares.sh (launcher)" + description: "Sufami Turbo base cartridge ROM, opened as the Super Famicom game. Its two slots then ask for Sufami Turbo cartridges." + note: >- + Identified by the BANDAI SFC-ADX signature at offset 0, since another game shares its serial A9PJ. The database lists the 256 KiB ROM as SHVC-A9PJ-0 (SHA-256 edacb453). + source_ref: "desktop-ui/emulator/super-famicom.cpp:199-217, mia/medium/super-famicom.cpp:570-576" - name: BS-X.bin system: super-famicom required: false category: game_data - description: "Satellaview BS-X Town cartridge ROM. Loaded via CLI as SFC cartridge for BS games." - source_ref: "EmuDeck emuDeckares.sh (launcher)" + description: "Satellaview BS-X cartridge ROM, opened as the Super Famicom game. Its slot then asks for a BS Memory pack." + note: >- + Identified by serial ZBSJ, which gives the BS-MCC board. The database lists the 1 MiB ROM as SHVC-ZBSJ-1 (SHA-256 3ce32149). + source_ref: "desktop-ui/emulator/super-famicom.cpp:189-197, mia/medium/super-famicom.cpp:587-589" diff --git a/emulators/beetle_pce.yml b/emulators/beetle_pce.yml index 4d75588c..c85c06e9 100644 --- a/emulators/beetle_pce.yml +++ b/emulators/beetle_pce.yml @@ -55,5 +55,4 @@ files: description: "Games Express CD Card" required: false source_ref: "libretro.cpp:1057-1058, mednafen/settings.cpp:41, mednafen/pce/pce.cpp:374-411" - aliases: ["gecard.pce"] note: "pce_cdbios = 'Games Express' or auto-detected via DetectGECD()." diff --git a/emulators/beetle_psx.yml b/emulators/beetle_psx.yml index fb466937..d2df9ecf 100644 --- a/emulators/beetle_psx.yml +++ b/emulators/beetle_psx.yml @@ -110,7 +110,7 @@ files: mode: libretro source_ref: "libretro.c:523-529" aliases: ["PSXONPSP660.bin"] - note: "override_bios=1. Falls back to region BIOS if not found." + note: "override_bios=1. Tried as psxonpsp660.bin, PSXONPSP660.bin, then PSXONPSP660.BIN. Falls back to region BIOS if not found." - name: "ps1_rom.bin" description: "PS3 embedded PS1 BIOS, first 512KB extracted (region-free override)" @@ -121,7 +121,7 @@ files: mode: libretro source_ref: "libretro.c:531-537" aliases: ["PS1_ROM.bin"] - note: "override_bios=2. Falls back to region BIOS if not found." + note: "override_bios=2. Tried as ps1_rom.bin, PS1_ROM.bin, then PS1_ROM.BIN. Falls back to region BIOS if not found." - name: "openbios.bin" description: "OpenBIOS (open-source PS1 HLE BIOS, region-free override)" diff --git a/emulators/bnes.yml b/emulators/bnes.yml index b0bce76d..1dc180c5 100644 --- a/emulators/bnes.yml +++ b/emulators/bnes.yml @@ -2,7 +2,7 @@ emulator: bnes type: libretro core_classification: frozen_snapshot source: "https://github.com/libretro/bnes-libretro" -upstream: "https://github.com/Alcaro/bsnes-gc" +upstream: "https://github.com/Sir-Walrus/bsnes-gc" profiled_date: "2026-03-23" source_commit: "8e26e89a93bef8eb8992d1921b539dce1792660a" core_version: "v083" diff --git a/emulators/clk.yml b/emulators/clk.yml index 537db3fd..e38d61ff 100644 --- a/emulators/clk.yml +++ b/emulators/clk.yml @@ -730,8 +730,7 @@ files: # MSX (machine_name: "MSX") # ------------------------------------------------------- - name: msx.rom - aliases: [MSX.ROM] - path: MSX/MSX.ROM + path: MSX/msx.rom system: microsoft-msx description: "Generic MSX BIOS" size: 32768 @@ -778,8 +777,7 @@ files: source_ref: "Machines/Utility/ROMCatalogue.cpp:809-816" - name: msx2.rom - aliases: [MSX2.ROM] - path: MSX/MSX2.ROM + path: MSX/msx2.rom system: microsoft-msx2 description: "Generic MSX2 BIOS" size: 32768 @@ -789,8 +787,7 @@ files: source_ref: "Machines/Utility/ROMCatalogue.cpp:818-825" - name: msx2ext.rom - aliases: [MSX2EXT.ROM] - path: MSX/MSX2EXT.ROM + path: MSX/msx2ext.rom system: microsoft-msx2 description: "MSX2 extension ROM" size: 16384 diff --git a/emulators/clownmdemu.yml b/emulators/clownmdemu.yml index 8655c143..cacf2a6d 100644 --- a/emulators/clownmdemu.yml +++ b/emulators/clownmdemu.yml @@ -2,7 +2,7 @@ emulator: ClownMDEmu type: standalone + libretro core_classification: official_port source: "https://github.com/Clownacy/clownmdemu-libretro" -upstream: "https://github.com/Clownacy/clownmdemu" +upstream: "https://github.com/Clownacy/clownmdemu-core" profiled_date: "2026-03-23" source_commit: "d43c2708b0a31c285ce16724b6c4a2e92af07346" # The core the port vendors at source_commit (common -> core submodule). diff --git a/emulators/dosbox-staging.yml b/emulators/dosbox-staging.yml index 6d387b36..3f63ba72 100644 --- a/emulators/dosbox-staging.yml +++ b/emulators/dosbox-staging.yml @@ -637,7 +637,6 @@ files: description: "IBM PCjr system ROM" sha1: "1f5f7013f18c08ff50d7942e76c4fbd782412414" required: false - aliases: ["bios.rom"] min_size: 57344 validation: [size] note: > diff --git a/emulators/dosbox-x.yml b/emulators/dosbox-x.yml index 5c443ace..56abe48d 100644 --- a/emulators/dosbox-x.yml +++ b/emulators/dosbox-x.yml @@ -3,7 +3,7 @@ type: standalone core_classification: enhanced_fork source: "https://github.com/joncampbell123/dosbox-x" upstream: "https://github.com/joncampbell123/dosbox-x" -source_commit: "e013b8bf8e27ef878a646049bf5b2e732878d616" +source_commit: "029bd65c5dcc7cdc7f2e14e35278620d9707d969" profiled_date: "2026-09-17" core_version: "2026.08.31" display_name: "DOS (DOSBox-X)" @@ -39,14 +39,14 @@ notes: | or ~/.config/dosbox-x, and the resource directory is $APPDIR/usr/share/dosbox-x inside an AppImage, otherwise $XDG_DATA_HOME/dosbox-x, then /usr/local/share/dosbox-x, then /usr/share/dosbox-x. Windows uses C:\DOSBox-X. - ref: src/ints/int10.cpp:1442-1485, src/misc/cross.cpp:129-190, 193-226 + ref: src/ints/int10.cpp:1442-1485, src/misc/cross.cpp:129-194, 197-230 Configuration: -conf and -userconf name the files to read. Otherwise dosbox-x.conf then dosbox.conf is tried in the working directory, then in the program directory, then in the configuration directory, which is last tried for dosbox-x-.conf. That file is written with the defaults when it does not exist. - ref: src/gui/sdlmain.cpp:8667-8743, src/misc/cross.cpp:229-245 + ref: src/gui/sdlmain.cpp:8671-8747, src/misc/cross.cpp:233-249 MT-32: libmt32emu is built from src/libs/mt32. Only four file names are ever opened, and each candidate is identified by exact file size then SHA1, so the @@ -58,13 +58,18 @@ notes: | the MT32 names. The directory is mt32.romdir, then the working directory, then the resource directory, then the configuration directory. A missing pair logs the accepted file names and disables the device. - ref: src/gui/midi_mt32.h:246-275, src/dosbox.cpp:3607-3617 + ref: src/gui/midi_mt32.h:246-275, src/dosbox.cpp:3603-3613 - FluidSynth reads fluid.soundfont, and fluid_synth_sfload is the only check. With - the setting empty it probes /usr/share/soundfonts/default.sf2, - /usr/share/sounds/sf2/FluidR3_GM.sf2 and GeneralUser_GS.sf2 on Linux, and - C:\soundfonts\default.sf2 then the two same names under C:\DOSBox-X on Windows. - ref: src/gui/midi_synth.h:342-384, 462-480 + FluidSynth reads fluid.soundfont, and fluid_synth_sfload is the only check. + Find_SoundFont tries default.sf2, FluidR3_GM.sf2, GeneralUser_GS.sf2 and + GeneralUser-GS.sf2, after the name fluid.soundfont gives when it has no + directory, in the working directory, the resource directory, the program + directory, then C:\soundfonts and C:\DOSBox-X on Windows, /usr/share/soundfonts + and /usr/share/sounds/sf2 elsewhere, and /Library/Audio/Sounds/Banks and + ~/Library/Audio/Sounds/Banks on macOS. The first name found in a directory + is kept, and a later directory holding one replaces it. The synth device + searches the same way. + ref: src/gui/midi_synth.h:82-134, 228-242, 383-399, 478-496 PC-98 character generator, tried in order: FONT.ROM as generated by T98Tools, then the FONTX2 files named by pc-98 fontx sbcs and pc-98 fontx dbcs, then the @@ -84,7 +89,7 @@ notes: | identified by its size, which covers ASC16 and ASCFONT.15 from UCDOS and ETen Chinese DOS, ASC24, HZK14, HZK16, HZK24 and STDFONT.15 and STDFONT.24. Unset settings fall back to the built-in font data. - ref: src/ints/int_dosv.cpp:654-749, 1631-1710, src/dosbox.cpp:2550-2583 + ref: src/ints/int_dosv.cpp:654-749, 1631-1710, src/dosbox.cpp:2556-2589 BOOT -bios loads a BIOS image at the top of the first megabyte, truncated to 128 KB, or 96 KB on PC-98 where it also looks for .itf.rom, .ITF.ROM, @@ -96,15 +101,15 @@ notes: | the reset vector. It is compiled only when the debugger is enabled. The settings call binary on reset and call binary on boot load blobs of up to 128 KB into the ROM BIOS area for CPU testing. - ref: src/dos/dos_programs.cpp:3666-3719, src/ints/bios.cpp:13298-13374 + ref: src/dos/dos_programs.cpp:3666-3719, src/ints/bios.cpp:13306-13382 A build configured with --enable-dosbox_agent reads the key=value file named by -agent-config to start the RPC debugger agent. The file names the transport and endpoint, nothing else is read from disk. - ref: configure.ac:1441-1448, src/gui/sdlmain.cpp:8490-8496, src/agent/protocol/agent_protocol.cpp:477-632 + ref: configure.ac:1441-1448, src/gui/sdlmain.cpp:8494-8500, src/agent/protocol/agent_protocol.cpp:477-632 Glide passthrough loads glide2x.dll, libglide2x.so or libglide2x.dylib. - ref: src/hardware/glide.cpp:353-359, src/dosbox.cpp:3507-3509 + ref: src/hardware/glide.cpp:353-359, src/dosbox.cpp:3503-3505 ttf.font, ttf.fontbold, ttf.fontital and ttf.fontboit name a TTF, OTF, FON or TTC font resolved through the same search order plus the system font @@ -121,9 +126,9 @@ notes: | the customcodepage translation table, .kl layout files and the KEYBOARD.SYS to KEYBRD4.SYS libraries read from a mounted drive, the glshaders directory and the .lng translations. - ref: src/ints/bios.cpp:11466-11475, src/gui/sdlmain.cpp:968-970, 7012-7020, - src/gui/sdl_mapper.cpp:5731-5787, src/dos/dos.cpp:4402-4437, - src/dos/dos_keyboard_layout.cpp:300-340, src/gui/render.cpp:1547-1554, + ref: src/ints/bios.cpp:11474-11483, src/gui/sdlmain.cpp:972-974, 7016-7024, + src/gui/sdl_mapper.cpp:5731-5787, src/dos/dos.cpp:4414-4449, + src/dos/dos_keyboard_layout.cpp:300-340, src/gui/render.cpp:1556-1563, src/misc/messages.cpp:300-326 files: @@ -284,36 +289,34 @@ files: system: dos unsourceable: "a link the operating system creates to the SoundFont it installs as default, FluidR3_GM.sf2 on Fedora. No file of this name is distributed, and a same-named file of another program must not stand in" note: > - first probe when fluid.soundfont is empty: - /usr/share/soundfonts/default.sf2, or C:\soundfonts\default.sf2 on - Windows. The source marks the first path as the Red Hat and Fedora - one, where the name links to FluidR3_GM.sf2, the file of the second - probe. Any SF2 or SF3 file loads: fluid.soundfont names it and + first name Find_SoundFont tries in each directory when fluid.soundfont + is empty. The source marks /usr/share/soundfonts as the Red Hat and + Fedora location, where the name links to FluidR3_GM.sf2, the second + name. Any SF2 or SF3 file loads: fluid.soundfont names it and fluid_synth_sfload is the only check - source_ref: "src/gui/midi_synth.h:346-352, src/gui/midi_synth.h:364-368, src/gui/midi_synth.h:381-384, src/gui/midi_synth.h:462-473, src/dosbox.cpp:3746-3747" + source_ref: "src/gui/midi_synth.h:82-134, src/gui/midi_synth.h:383-399, src/gui/midi_synth.h:228-242, src/gui/midi_synth.h:478-489, src/dosbox.cpp:3742-3743" - name: "FluidR3_GM.sf2" description: "Fluid R3 GM SoundFont by Frank Wen" required: false system: dos note: > - second probe when fluid.soundfont is empty: - /usr/share/sounds/sf2/FluidR3_GM.sf2, or C:\DOSBox-X\FluidR3_GM.sf2 on - Windows. Elsewhere the file loads when fluid.soundfont gives its path. - The synth device probes the same paths - source_ref: "src/gui/midi_synth.h:353-355, src/gui/midi_synth.h:370-372, src/gui/midi_synth.h:176-178, src/gui/midi_synth.h:193-195" + second name Find_SoundFont tries in each directory when fluid.soundfont + is empty. Elsewhere the file loads when fluid.soundfont gives its path. + The synth device searches the same way + source_ref: "src/gui/midi_synth.h:82-134, src/gui/midi_synth.h:383-399, src/gui/midi_synth.h:228-242, src/gui/midi_synth.h:478-489" - name: "GeneralUser_GS.sf2" + aliases: ["GeneralUser-GS.sf2"] description: "GeneralUser GS SoundFont by S. Christian Collins" required: false system: dos note: > - third probe when fluid.soundfont is empty: - /usr/share/sounds/sf2/GeneralUser_GS.sf2, or - C:\DOSBox-X\GeneralUser_GS.sf2 on Windows. Elsewhere the file loads - when fluid.soundfont gives its path, and the setting's help text names this - file as its example. The synth device probes the same paths - source_ref: "src/gui/midi_synth.h:356-358, src/gui/midi_synth.h:373-375, src/gui/midi_synth.h:179-181, src/gui/midi_synth.h:196-198, src/dosbox.cpp:3747" + third name Find_SoundFont tries in each directory when fluid.soundfont + is empty, GeneralUser-GS.sf2 being the fourth. Elsewhere the file loads + when fluid.soundfont gives its path, and the setting's help text names + GeneralUser_GS.sf2 as its example. The synth device searches the same way + source_ref: "src/gui/midi_synth.h:82-134, src/gui/midi_synth.h:383-399, src/gui/midi_synth.h:228-242, src/gui/midi_synth.h:478-489, src/dosbox.cpp:3743" # -- PC-98 character generator -- @@ -328,7 +331,7 @@ files: 256 8x8 cells at 0x0, 256 8x16 cells at 0x800, 96 by 92 16x16 cells at 0x1800. A file of any other length is rejected. Enabled by pc-98 try font rom, on by default - source_ref: "src/ints/int10.cpp:1487-1549, src/dosbox.cpp:2494-2495" + source_ref: "src/ints/int10.cpp:1487-1549, src/dosbox.cpp:2500-2501" - name: "ANEX86.BMP" description: "PC-98 character generator, Anex86 bitmap" @@ -340,7 +343,7 @@ files: pixel, no compression, inverse colour scheme. The first row is the 8x16 single-width set and the rest is 16x16 full-width. Also reachable through the pc-98 anex86 font setting, which is tried before FONT.ROM - source_ref: "src/ints/int10.cpp:1555-1647, src/dosbox.cpp:2498-2501" + source_ref: "src/ints/int10.cpp:1555-1647, src/dosbox.cpp:2504-2507" - name: "FREECG98.BMP" description: "PC-98 character generator, free generated bitmap" @@ -424,28 +427,28 @@ files: required: false system: dos note: "also the fallback typeface for any unmapped LQ selection" - source_ref: "src/hardware/parport/printer.cpp:320-321, src/hardware/parport/printer.cpp:336-337, src/dosbox.cpp:4691-4693" + source_ref: "src/hardware/parport/printer.cpp:320-321, src/hardware/parport/printer.cpp:336-337, src/dosbox.cpp:4687-4689" - name: "sansserif.ttf" path: "FONTS/sansserif.ttf" description: "Printer Sans Serif typeface" required: false system: dos - source_ref: "src/hardware/parport/printer.cpp:323-324, src/dosbox.cpp:4691-4693" + source_ref: "src/hardware/parport/printer.cpp:323-324, src/dosbox.cpp:4687-4689" - name: "courier.ttf" path: "FONTS/courier.ttf" description: "Printer Courier typeface" required: false system: dos - source_ref: "src/hardware/parport/printer.cpp:326-327, src/dosbox.cpp:4691-4693" + source_ref: "src/hardware/parport/printer.cpp:326-327, src/dosbox.cpp:4687-4689" - name: "script.ttf" path: "FONTS/script.ttf" description: "Printer Script typeface" required: false system: dos - source_ref: "src/hardware/parport/printer.cpp:329-330, src/dosbox.cpp:4691-4693" + source_ref: "src/hardware/parport/printer.cpp:329-330, src/dosbox.cpp:4687-4689" - name: "ocra.ttf" path: "FONTS/ocra.ttf" @@ -453,7 +456,7 @@ files: required: false system: dos note: "serves both the OCR-A and OCR-B selections" - source_ref: "src/hardware/parport/printer.cpp:332-334, src/dosbox.cpp:4691-4693" + source_ref: "src/hardware/parport/printer.cpp:332-334, src/dosbox.cpp:4687-4689" # -- PC-98 sound board BIOS -- @@ -467,7 +470,7 @@ files: note: > 16 KB read into CC000h from the working directory only, when pc-98 sound bios and pc-98 load sound bios rom file are both set - source_ref: "src/hardware/pc98_fm.cpp:367-385, src/dosbox.cpp:2395-2402" + source_ref: "src/hardware/pc98_fm.cpp:367-385, src/dosbox.cpp:2401-2408" # -- Video BIOS ROM images -- # Loaded in place of the built-in INT 10h when vga bios use rom image is set. @@ -482,7 +485,7 @@ files: max_size: 65536 validation: [size] note: "default file name for machine = svga_et4000" - source_ref: "src/dosbox.cpp:943-994, src/dosbox.cpp:2762-2773" + source_ref: "src/dosbox.cpp:943-994, src/dosbox.cpp:2768-2779" - name: "TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin" description: "S3 Trio64 video BIOS" @@ -494,7 +497,7 @@ files: max_size: 65536 validation: [size] note: "default file name for machine = svga_s3" - source_ref: "src/dosbox.cpp:951-953, src/dosbox.cpp:2762-2773" + source_ref: "src/dosbox.cpp:951-953, src/dosbox.cpp:2768-2779" - name: "ibm-vga.bin" description: "IBM VGA option ROM of 10/27/86, laid out as mapped at C000:0" @@ -526,7 +529,7 @@ files: 32 KB to 64 KB in 4 KB steps. LOADROM.COM maps the same image at F600:0 when it is exactly 32768 bytes, starts with E9 8F 7E and carries the string IBM at offset 0x4CD4 - source_ref: "src/ints/bios.cpp:13230-13250, src/dos/dos_programs.cpp:3633-3637, src/dosbox.cpp:1948-1950" + source_ref: "src/ints/bios.cpp:13238-13258, src/dos/dos_programs.cpp:3633-3637, src/dosbox.cpp:1948-1950" # -- PCjr -- @@ -535,7 +538,6 @@ files: sha1: "1f5f7013f18c08ff50d7942e76c4fbd782412414" required: false system: ibm-pcjr - aliases: ["bios.rom"] min_size: 57344 validation: [size] note: > diff --git a/emulators/dsda-doom.yml b/emulators/dsda-doom.yml index 8bc17594..84732892 100644 --- a/emulators/dsda-doom.yml +++ b/emulators/dsda-doom.yml @@ -1,7 +1,7 @@ emulator: dsda-doom type: standalone core_classification: game_engine -source: "https://github.com/kraflab/dsda-doom" +source: "https://github.com/dsda-org/dsda-doom" profiled_date: "2026-10-20" source_commit: "e443ff7a3e6090a1ff92ad7a426916c4fd35ecc5" core_version: "0.29.4" diff --git a/emulators/fbalpha2019.yml b/emulators/fbalpha2019.yml index 2f64305e..3d113071 100644 --- a/emulators/fbalpha2019.yml +++ b/emulators/fbalpha2019.yml @@ -1,7 +1,7 @@ emulator: "FB Alpha 2019" type: libretro core_classification: frozen_snapshot -source: "https://github.com/libretro/fbalpha" +source: "https://github.com/libretro/beetle-finalarcade2019" upstream: "https://github.com/barry65536/FBAlpha" profiled_date: "2026-10-17" source_commit: "0581797db6fdffd826086b053ced4b6b29bb6678" diff --git a/emulators/flycast2021.yml b/emulators/flycast2021.yml index 925af60c..4567469d 100644 --- a/emulators/flycast2021.yml +++ b/emulators/flycast2021.yml @@ -2,7 +2,7 @@ emulator: "Flycast 2021" type: libretro core_classification: frozen_snapshot source: "https://github.com/metallic77/flycast" -upstream: "https://github.com/libretro/flycast" +upstream: "https://github.com/libretro/parallel-dc" profiled_date: "2026-10-17" source_commit: "603814c9f73b773c455d9a497f389d2f93a257fd" upstream_commit: "4c293f306bc16a265c2d768af5d0cea138426054" @@ -20,6 +20,8 @@ notes: | The libretro/flycast tree as of April 2022 (merge base 4c293f30), from before the libretro fork was rebased on flyinghead's Flycast, with 22 commits by metallic77 on top that tune defaults and build flags for low-end handhelds. + That repository now answers as libretro/parallel-dc, and its master still + descends from 4c293f30. ROCKNIX renames the core option prefix from reicast to flycast2021 and installs the library as flycast2021_libretro.so. ref: core/libretro/libretro.cpp:2296-2300 diff --git a/emulators/gsplus.yml b/emulators/gsplus.yml index 1a351be4..cf6469ce 100644 --- a/emulators/gsplus.yml +++ b/emulators/gsplus.yml @@ -36,7 +36,7 @@ files: required: true description: "Apple IIGS system ROM" source_ref: "gsplus/src/config.c:136, gsplus/src/config.c:477-480, gsplus/src/config.c:1260-1317" - note: "Accepted sizes: 32768 (Apple //e), 131072 (ROM 01), 262144 (ROM 03)" + note: "g_kegs_rom_names tries the configured ROM path, then ROM, ROM.01, ROM.03, APPLE2GS.ROM, APPLE2GS.ROM2, xgs.rom, XGS.ROM, Rom03gd and 342-0077-b. Accepted sizes: 32768 (Apple //e), 131072 (ROM 01), 262144 (ROM 03)" size: [32768, 131072, 262144] validation: [size] diff --git a/emulators/lzdoom.yml b/emulators/lzdoom.yml index c38a8635..13ac7907 100644 --- a/emulators/lzdoom.yml +++ b/emulators/lzdoom.yml @@ -1,7 +1,7 @@ emulator: LZDoom type: standalone core_classification: game_engine -source: "https://github.com/drfrag666/gzdoom" +source: "https://github.com/drfrag666/lzdoom" profiled_date: "2026-10-20" source_commit: "4ce19a12164ebd6802b7fb2f94d700a6e736d0fb" core_version: "3.88b" diff --git a/emulators/mame4droid-2024.yml b/emulators/mame4droid-2024.yml index 7bc0a3b9..82e87436 100644 --- a/emulators/mame4droid-2024.yml +++ b/emulators/mame4droid-2024.yml @@ -1,7 +1,7 @@ emulator: MAME4droid 2024 type: standalone core_classification: community_fork -source: "https://github.com/seleuco/MAME4droid-2024" +source: "https://github.com/seleuco/MAME4droid-Current" upstream: "https://github.com/mamedev/mame/tree/mame0289" logo: "https://raw.githubusercontent.com/mamedev/mame/master/docs/source/images/MAMElogo.svg" profiled_date: "2026-08-11" diff --git a/emulators/mednafen_pce.yml b/emulators/mednafen_pce.yml index f1d8d0fc..153ee458 100644 --- a/emulators/mednafen_pce.yml +++ b/emulators/mednafen_pce.yml @@ -44,7 +44,6 @@ files: - name: "gexpress.pce" description: "Games Express CD Card" required: false - aliases: ["gecard.pce"] source_ref: "libretro.cpp:1057-1058, mednafen/settings.cpp:41, mednafen/pce/pce.cpp:373-411" note: "pce_cdbios = 'Games Express' or auto-detected via DetectGECD()." diff --git a/emulators/mednafen_pce_fast.yml b/emulators/mednafen_pce_fast.yml index f249c52b..d03a6565 100644 --- a/emulators/mednafen_pce_fast.yml +++ b/emulators/mednafen_pce_fast.yml @@ -42,7 +42,6 @@ files: - name: "gexpress.pce" description: "Games Express CD Card" required: false - aliases: ["gecard.pce"] source_ref: "libretro.c:1906-1907" note: "pce_fast_cdbios = 'Games Express'. For unlicensed Games Express titles." diff --git a/emulators/mu.yml b/emulators/mu.yml index b2f05446..ffb58670 100644 --- a/emulators/mu.yml +++ b/emulators/mu.yml @@ -1,7 +1,7 @@ emulator: Mu type: libretro core_classification: pure_libretro -source: "https://github.com/libretro/Mu" +source: "https://github.com/SquirrelJME/Mu" upstream: "https://github.com/meepingsnesroms/Mu" profiled_date: "2026-03-24" source_commit: "afaeb157b8ba38a4a9bdf426ba663f7efb2cc6f8" diff --git a/emulators/openmsx.yml b/emulators/openmsx.yml index 69bfc748..efa59f83 100644 --- a/emulators/openmsx.yml +++ b/emulators/openmsx.yml @@ -152,7 +152,8 @@ files: required: true description: "Kanji font ROM (shared by FS-A1WSX and FS-A1GT machines)" validation: [sha1] - source_ref: "share/machines/Boosted_MSX2+_JP.xml:28, share/machines/Boosted_MSXturboR_with_IDE.xml:216" + source_ref: "share/machines/Boosted_MSX2+_JP.xml:27-28, share/machines/Panasonic_FS-A1WSX.xml:29-30, share/machines/Boosted_MSXturboR_with_IDE.xml:215-216, share/machines/Panasonic_FS-A1GT.xml:141-142" + note: "Panasonic_FS-A1WSX.xml and Boosted_MSX2+_JP.xml name it fs-a1wsx_kanjifont.rom, Panasonic_FS-A1GT.xml and Boosted_MSXturboR_with_IDE.xml name it fs-a1gt_kanjifont.rom, all four with the same sha1." # ------------------------------------------------------- # Boosted_MSXturboR_with_IDE (msxturbor) diff --git a/emulators/pdark.yml b/emulators/pdark.yml index 3df59e72..c7ac7731 100644 --- a/emulators/pdark.yml +++ b/emulators/pdark.yml @@ -1,10 +1,10 @@ emulator: Perfect Dark (PC port) type: standalone core_classification: game_engine -source: "https://github.com/fgsfdsfgs/perfect_dark" -upstream: "https://github.com/fgsfdsfgs/perfect_dark" +source: "https://github.com/perfect-dark-pc-port/perfect_dark" +upstream: "https://github.com/perfect-dark-pc-port/perfect_dark" source_branch: port -source_commit: "618a1f33865cc98c6fff95c9a5df8162443a643c" +source_commit: "32a1cb9f268dd3ac73016801025c6bbbfa20130f" profiled_date: "2026-10-20" core_version: "port 2025-06-14" display_name: "Perfect Dark (PC port)" @@ -28,9 +28,8 @@ notes: | Files are read from the base directory: --basedir, else data beside the executable in portable mode, else ./data when it exists, else data under - the home path (port/src/fs.c:18, 96-121). At this revision the home path - test reads a failed size lookup as success, so data beside the executable - is not reached outside portable mode. RetroBat starts the port from its + the home path when it exists, else data beside the executable + (port/src/fs.c:18, 96-121). RetroBat starts the port from its install folder, where ./data exists. The ROM is pd..z64 there unless --rom-file names another path. A missing ROM, an archive, a size other than 33554432 bytes, or a header whose game code and title do not match @@ -41,7 +40,7 @@ notes: | size, title, licensee and checksum bytes. When it passes, the game acts as if the cartridge sat in a Transfer Pak, which unlocks the cheats tied to it (port/src/romdata.c:53-54, 404-448, port/src/main.c:112, - src/game/pak.c:5992-6007, src/game/cheats.c:406, 436). + src/game/pak.c:5992-6007, src/game/cheats.c:430, 460). files: - name: "pd.ntsc-final.z64" diff --git a/emulators/pocketcdg.yml b/emulators/pocketcdg.yml index 5e4d0660..a4e0b297 100644 --- a/emulators/pocketcdg.yml +++ b/emulators/pocketcdg.yml @@ -2,7 +2,7 @@ emulator: PocketCDG type: libretro core_classification: pure_libretro source: "https://github.com/libretro/libretro-pocketcdg" -upstream: "https://github.com/redbug26/libretro-pocketcdg" +upstream: "https://github.com/libretro/libretro-pocketcdg" profiled_date: "2026-03-24" source_commit: "b48b807e770aeea9a9e8f7af36f5e04ed4727aaa" core_version: "Git" diff --git a/emulators/puzzlescript.yml b/emulators/puzzlescript.yml index 31288c33..33d4fae7 100644 --- a/emulators/puzzlescript.yml +++ b/emulators/puzzlescript.yml @@ -1,7 +1,7 @@ emulator: PuzzleScript type: libretro core_classification: game_engine -source: "https://github.com/nwhitehead/pzretro" +source: "https://github.com/amberwhitehead/pzretro" upstream: "https://github.com/increpare/PuzzleScript" profiled_date: "2026-03-25" source_commit: "6d859b47092f585a7ec05804c1d51a1676a06531" diff --git a/emulators/raze.yml b/emulators/raze.yml index 4c804b20..338a101a 100644 --- a/emulators/raze.yml +++ b/emulators/raze.yml @@ -66,7 +66,6 @@ files: note: "I_FatalError(\"Cannot find raze.pk3\") if absent. Built from the tree at each release. The hash is the copy in the 1.11.0b Windows zip." - name: "raze.sf2" - aliases: ["Roland_SC-55.sf2"] category: game_data path: "soundfonts/raze.sf2" required: false diff --git a/emulators/reicast.yml b/emulators/reicast.yml index 66ebc0d0..fa5fc5b8 100644 --- a/emulators/reicast.yml +++ b/emulators/reicast.yml @@ -1,8 +1,8 @@ emulator: Reicast type: standalone core_classification: community_fork -source: "https://github.com/reicast/reicast-emulator" -upstream: "https://github.com/reicast/reicast-emulator" +source: "https://github.com/skmp/reicast-emulator" +upstream: "https://github.com/skmp/reicast-emulator" profiled_date: "2026-10-17" source_commit: "ad61f95dd6b4c6218846a25de6194550311a5d28" pin_frozen: "Recalbox 10.1.1 builds this revision (package/reicast/reicast.mk REICAST_VERSION). Later commits on reicast-emulator are not part of that build." @@ -61,4 +61,4 @@ files: validation: [size] description: "Dreamcast flash memory" source_ref: "core/hw/holly/sb_mem.cpp:22-23, 37-48, 58-64, core/types.h:212, 217" - note: "Written back as dc_nvmem.bin on exit. Missing, LoadRomFiles() fails even with a boot ROM present and the HLE BIOS runs." + note: "Tried as dc_nvmem.bin, dc_flash_wb.bin, dc_flash.bin, then dc_flash.bin.bin. Written back as dc_nvmem.bin on exit. Missing, LoadRomFiles() fails even with a boot ROM present and the HLE BIOS runs." diff --git a/emulators/rosalies-mupen-gui.yml b/emulators/rosalies-mupen-gui.yml index f56707b8..8bfab72d 100644 --- a/emulators/rosalies-mupen-gui.yml +++ b/emulators/rosalies-mupen-gui.yml @@ -121,7 +121,7 @@ files: source_ref: "Source/RMG-Core/MediaLoader.cpp:47-74, Source/RMG-Core/Settings.cpp:284-286, Source/3rdParty/mupen64plus-core/src/main/main.c:1189-1254, Source/3rdParty/mupen64plus-core/src/device/dd/disk.c:434-445" - name: "64DD_IPL_US.n64" - aliases: ["64DD_IPL_USA.bin", "IPL_USA.n64"] + aliases: ["64DD_IPL_USA.bin"] system: nintendo-64dd region: [north-america] required: true @@ -134,7 +134,7 @@ files: source_ref: "Source/RMG-Core/MediaLoader.cpp:54-56, Source/RMG-Core/Settings.cpp:287-289, Source/3rdParty/mupen64plus-core/src/main/main.c:1189-1254, Source/3rdParty/mupen64plus-core/src/device/dd/disk.c:434-445" - name: "64DD_IPL_DEV.n64" - aliases: ["64DD_IPL_DEV.bin", "IPL_DEV.n64"] + aliases: ["64DD_IPL_DEV.bin"] system: nintendo-64dd required: true description: "64DD IPL ROM (Japanese development)" diff --git a/emulators/theforceengine.yml b/emulators/theforceengine.yml index a348eb8a..2b3838da 100644 --- a/emulators/theforceengine.yml +++ b/emulators/theforceengine.yml @@ -1,8 +1,8 @@ emulator: The Force Engine type: standalone core_classification: game_engine -source: "https://github.com/luciusDXL/TheForceEngine" -upstream: "https://github.com/luciusDXL/TheForceEngine" +source: "https://github.com/TheForceEngine/TheForceEngine" +upstream: "https://github.com/TheForceEngine/TheForceEngine" profiled_date: "2026-10-04" source_commit: "cc25205cc94c36a396f6f50295772f6ec83069a2" core_version: "v1.22.420" diff --git a/emulators/thepowdertoy.yml b/emulators/thepowdertoy.yml index 8e749a91..2784f52d 100644 --- a/emulators/thepowdertoy.yml +++ b/emulators/thepowdertoy.yml @@ -2,7 +2,7 @@ emulator: The Powder Toy type: libretro core_classification: pure_libretro source: "https://github.com/libretro/ThePowderToy" -upstream: "https://github.com/ThePowderToy/The-Powder-Toy" +upstream: "https://github.com/The-Powder-Toy/The-Powder-Toy" profiled_date: "2026-03-25" source_commit: "cb3cd4c2e5beddb98b34e6b800fa24e8f96322d9" core_version: "v92.5.336" diff --git a/emulators/vitavoyager.yml b/emulators/vitavoyager.yml index 9ca3204d..b168f3bc 100644 --- a/emulators/vitavoyager.yml +++ b/emulators/vitavoyager.yml @@ -2,7 +2,7 @@ emulator: vitavoyager type: libretro core_classification: community_fork source: "https://github.com/libretro/vitavoyager" -upstream: "https://github.com/zturtleman/lilium-voyager" +upstream: "https://github.com/clover-moe/lilium-voyager" profiled_date: "2026-03-25" source_commit: "58b70dd7ea891c2e8ddc37d03a5d58116b0ea118" core_version: "git" diff --git a/emulators/wolf4sdl.yml b/emulators/wolf4sdl.yml index 90659d12..c55166e5 100644 --- a/emulators/wolf4sdl.yml +++ b/emulators/wolf4sdl.yml @@ -1,8 +1,8 @@ emulator: Wolf4SDL type: standalone core_classification: game_engine -source: "https://github.com/AryanWolf3D/Wolf4SDL" -upstream: "https://github.com/AryanWolf3D/Wolf4SDL" +source: "https://github.com/KS-Presto/Wolf4SDL" +upstream: "https://github.com/KS-Presto/Wolf4SDL" profiled_date: "2026-10-20" source_commit: "dc8b250af35fb0ace68db5eb879490b50068c20e" core_version: "2.0" diff --git a/emulators/xemu.yml b/emulators/xemu.yml index 020a3791..48aadd67 100644 --- a/emulators/xemu.yml +++ b/emulators/xemu.yml @@ -82,7 +82,7 @@ files: - name: Complex_4627.bin path: Complex_4627.bin - aliases: [Complex.bin, Complex_4627v1.03.bin, cerbios.bin] + aliases: [Complex.bin, cerbios.bin] required: true size: [262144, 524288, 1048576] validation: [size] @@ -98,12 +98,6 @@ files: Complex_4627_v1.03.bin, complex_4627.bin, cerbios.bin, Cerbios.bin, bios.bin, xbox_bios.bin and Complex.bin offered as alternatives. The core refuses to load when the chosen file is absent. - RetroDECK writes the BIOS folder's Complex.bin into flashrom_path of - the xemu.toml it prepares. ROCKNIX ships an xemu.toml whose - flashrom_path is bios/xemu/bios/Complex_4627v1.03.bin. Batocera writes - bios/cerbios.bin into flashrom_path for its chihiro system and - bios/Complex_4627.bin for xbox. EmuDeck writes - bios/Complex_4627v1.03.bin into flashrom_path. source_ref: standalone: "system/vl.c:3041-3053, hw/xbox/xbox.c:63-123" libretro: "ui/xemu-libretro.c:115-118, ui/xemu-libretro.c:195-196, ui/xemu-libretro.c:210-236" diff --git a/emulators/xroar.yml b/emulators/xroar.yml index 78924acb..38d7ff49 100644 --- a/emulators/xroar.yml +++ b/emulators/xroar.yml @@ -47,7 +47,7 @@ files: validation: [crc32] aliases: [dragon32, d32rom, "Dragon Data Ltd - Dragon 32 - IC17"] source_ref: "src/xroar.c:649 (romlist d32), src/dragon/dragon32.c:40 (default @dragon32), src/dragon/dragon32.c:107,110-116,131-132 (load + CRC)" - note: "Combined 16K ROM. Loaded into a single 16384-byte rombank slot." + note: "Combined 16K ROM. Loaded into a single 16384-byte rombank slot. Romlist d32 tries d32, dragon32, d32rom, Dragon Data Ltd - Dragon 32 - IC17." # ---- Dragon 64 ---- @@ -60,7 +60,7 @@ files: validation: [crc32] aliases: [d64rom1, d64rom1.rom, dragrom, "Dragon Data Ltd - Dragon 64 - IC17", "Dragon Data Ltd - TANO IC18", "Eurohard S.A. - Dragon 200 IC18"] source_ref: "src/xroar.c:647 (romlist d64_1), src/xroar.c:653 (romlist dragon64), src/dragon/dragon64.c:151-157,169-171 (load + CRC)" - note: "IC17 ROM. Required for the machine to start." + note: "IC17 ROM. Required for the machine to start. Romlist d64_1 tries d64_1, d64rom1, Dragon Data Ltd - Dragon 64 - IC17, Dragon Data Ltd - TANO IC18, Eurohard S.A. - Dragon 200 IC18, dragrom." - name: "d64_2.rom" system: dragon64 @@ -71,7 +71,7 @@ files: validation: [crc32] aliases: [d64rom2, "Dragon Data Ltd - Dragon 64 - IC18", "Dragon Data Ltd - TANO IC17", "Eurohard S.A. - Dragon 200 IC17"] source_ref: "src/xroar.c:648 (romlist d64_2), src/xroar.c:654 (romlist dragon64_alt), src/dragon/dragon64.c:160-166,174-176 (load + CRC)" - note: "IC18 ROM. 64K mode alternate BASIC. Machine starts without it (32K mode only)." + note: "IC18 ROM. 64K mode alternate BASIC. Machine starts without it (32K mode only). Romlist d64_2 tries d64_2, d64rom2, Dragon Data Ltd - Dragon 64 - IC18, Dragon Data Ltd - TANO IC17, Eurohard S.A. - Dragon 200 IC17." # ---- Dragon 200-E ---- @@ -85,7 +85,7 @@ files: validation: [crc32] aliases: [d200e_rom1, ic18_v1.4e.ic34] source_ref: "src/xroar.c:650 (romlist d200e_1), src/xroar.c:656 (romlist dragon200e), src/xroar.c:741 (crclist)" - note: "Required for Dragon 200-E. Falls back to d64_1 then generic dragon if not found." + note: "Required for Dragon 200-E. Falls back to d64_1 then generic dragon if not found. Romlist d200e_1 tries d200e_1, d200e_rom1, ic18_v1.4e.ic34." - name: "d200e_2.rom" system: dragon64 @@ -96,7 +96,7 @@ files: crc32: "48b985df" aliases: [d200e_rom2, ic17_v1.4e.ic37] source_ref: "src/xroar.c:651 (romlist d200e_2), src/xroar.c:657 (romlist dragon200e_alt), src/rom.c:91 (0x48b985df = Dragon 200-E 64K BASIC)" - note: "64K mode alternate. Falls back to d64_2 if not found." + note: "64K mode alternate. Falls back to d64_2 if not found. Romlist d200e_2 tries d200e_2, d200e_rom2, ic17_v1.4e.ic37." - name: "d200e_26.rom" system: dragon64 @@ -107,7 +107,7 @@ files: crc32: "565724bc" aliases: [rom26.ic1] source_ref: "src/xroar.c:658 (romlist dragon200e_charset), src/dragon/dragon.c:430-447 (ext_charset load), src/rom.c:92 (0x565724bc = Dragon 200-E Character Set)" - note: "Spanish character set. Loaded into a 4096-byte rombank. Machine works without it (uses standard charset)." + note: "Spanish character set. Loaded into a 4096-byte rombank. Machine works without it (uses standard charset). Romlist dragon200e_charset tries d200e_26, rom26.ic1." # ---- Dragon Professional (Alpha) ---- @@ -124,6 +124,7 @@ files: Required for Dragon Professional machine. Loaded as extbas_rom into the BOOT bank. rombank_verify_crc accepts any member of @dragonpro_boot, which also holds 0xd6172b56 for the v0.4 slot. + Romlist dragonpro_boot tries alpha-boot-v1.0, alpha_bt_10, Dragon Data Ltd - Dragon Alpha Boot v1.0 150584, alpha-boot-v0.4, alpha_bt_04. - name: "alpha-boot-v0.4.rom" system: dragon64 @@ -139,6 +140,7 @@ files: v1.0 image is found. The dragonpro_boot crclist carries 0xd6172b56 next to the v1.0 value, and the ROM metadata table names it Dragon Professional Boot 0.4. + Romlist dragonpro_boot tries alpha-boot-v1.0, alpha_bt_10, Dragon Data Ltd - Dragon Alpha Boot v1.0 150584, alpha-boot-v0.4, alpha_bt_04. - name: "alpha-basic.rom" system: dragon64 @@ -149,7 +151,7 @@ files: validation: [crc32] aliases: [alpha_ba, "Dragon Data Ltd - Dragon Alpga Basic"] source_ref: "src/xroar.c:661 (romlist dragonpro_basic), src/xroar.c:748 (crclist = @d64_1), src/dragon/dragonpro.c:247 (ROM0 bank 16384), src/dragon/dragonpro.c:260-263 (load), src/dragon/dragonpro.c:274 (0x84f68bf9 = Dragon 64 32K mode BASIC)" - note: "Loaded as altbas_rom into the 32K BASIC bank. Falls back to d64_1 if not found." + note: "Loaded as altbas_rom into the 32K BASIC bank. Falls back to d64_1 if not found. Romlist dragonpro_basic tries alpha-basic, alpha_ba, Dragon Data Ltd - Dragon Alpga Basic, @d64_1." # ---- Tandy CoCo (Colour BASIC) ---- @@ -172,7 +174,7 @@ files: validation: [crc32] aliases: ["Color Basic v1.2 (1982)(Tandy)"] source_ref: "src/xroar.c:663 (romlist coco), src/xroar.c:752 (crclist bas12)" - note: "Alternative to bas13. Second in fallback order." + note: "Alternative to bas13. Second in fallback order. Romlist coco tries bas13, bas12, Color Basic v1.2 (1982)(Tandy), bas11, bas10. Romlist coco2 tries bas12, @coco." - name: "bas11.rom" system: coco @@ -271,7 +273,7 @@ files: validation: [crc32] aliases: [adv070_u24] source_ref: "src/xroar.c:679 (romlist deluxecoco), src/xroar.c:763 (crclist), src/dragon/deluxecoco.c:213-216 (load)" - note: "Primary ROM for the Deluxe CoCo prototype. Loaded as extbas_rom." + note: "Primary ROM for the Deluxe CoCo prototype. Loaded as extbas_rom. Romlist deluxecoco tries adv070_u24, deluxe." - name: "adv071_u24.rom" system: coco @@ -291,6 +293,7 @@ files: required: false aliases: [adv073_u24] source_ref: "src/xroar.c:683 (romlist deluxecoco3), src/dragon/deluxecoco.c:237-240 (load)" + note: "Romlist deluxecoco3 tries adv073-2_u24, adv073_u24." # ---- Dynacom MX-1600 (Brazilian clone) ---- @@ -302,7 +305,7 @@ files: validation: [crc32] aliases: [mx1600bas_zephyr] source_ref: "src/xroar.c:685 (romlist mx1600), src/xroar.c:754 (crclist mx1600)" - note: "Required for MX-1600. Zephyr-patched variant (CRC32 d11b1c96) is an alias." + note: "Required for MX-1600. Zephyr-patched variant (CRC32 d11b1c96) is an alias. Romlist mx1600 tries mx1600bas, mx1600bas_zephyr." - name: "mx1600extbas.rom" system: coco @@ -381,7 +384,7 @@ files: crc32: "b44536f6" aliases: ["Dragon Data Ltd - DragonDOS 1.0"] source_ref: "src/xroar.c:708 (romlist dragondos), src/xroar.c:712 (romlist dragondos_compat), src/dragondos.c:173 (default @dragondos_compat), src/rom.c:131 (0xb44536f6 = DragonDOS 1.0)" - note: "Fifth name in the dragondos romlist, which @dragondos_compat tries after the dosplus and superdos lists." + note: "Fifth name in the dragondos romlist, which @dragondos_compat tries after the dosplus and superdos lists. Romlist dragondos tries ddos12a, ddos12, ddos40, ddos15, ddos10, Dragon Data Ltd - DragonDOS 1.0." - name: "dplus49b.rom" system: dragon64 @@ -400,7 +403,7 @@ files: crc32: "d4d954a0" aliases: [dosplus-4.8, DOSPLUS] source_ref: "src/xroar.c:709 (romlist dosplus), src/xroar.c:712 (romlist dragondos_compat), src/dragondos.c:173 (default @dragondos_compat), src/rom.c:137 (0xd4d954a0 = DOSplus 4.8)" - note: "Second name in the dosplus romlist, the first list @dragondos_compat tries." + note: "Second name in the dosplus romlist, the first list @dragondos_compat tries. Romlist dosplus tries dplus49b, dplus48, dosplus-4.8, DOSPLUS." - name: "sdose6.rom" system: dragon64 @@ -410,7 +413,7 @@ files: crc32: "8c1d6c45" aliases: ["PNP - SuperDOS E6"] source_ref: "src/xroar.c:710 (romlist superdos), src/rom.c:141 (0x8c1d6c45 = SuperDOS E6)" - note: "Latest SuperDOS. Older versions: sdose5, sdose4." + note: "Latest SuperDOS. Older versions: sdose5, sdose4. Romlist superdos tries sdose6, PNP - SuperDOS E6, sdose5, sdose4." - name: "cdos20.rom" system: dragon64 @@ -418,6 +421,7 @@ files: required: false aliases: [CDOS20, "CumanaDOSv2.0"] source_ref: "src/xroar.c:711 (romlist cumana)" + note: "Romlist cumana tries cdos20, CDOS20, CumanaDOSv2.0." - name: "delta2.rom" system: dragon64 @@ -427,7 +431,7 @@ files: crc32: "307fb37c" aliases: ["Premier Micros - DeltaDOS"] source_ref: "src/xroar.c:717 (romlist delta), src/deltados.c:160 (default @delta), src/rom.c:146 (0x307fb37c = Delta System 2.0)" - note: "Latest Delta version. Older versions: delta1a, delta19, delta, deltados." + note: "Latest Delta version. Older versions: delta1a, delta19, delta, deltados. Romlist delta tries delta2, delta1a, delta19, delta, deltados, Premier Micros - DeltaDOS." - name: "cp450dsk.rom" system: coco @@ -453,7 +457,7 @@ files: required: false aliases: [MCX_Basic_21] source_ref: "src/xroar.c:730 (romlist mcx128), src/mcx128.c:208 (default @mcx128)" - note: "128K memory expansion for MC-10. Adds enhanced BASIC." + note: "128K memory expansion for MC-10. Adds enhanced BASIC. Romlist mcx128 tries mcx128, MCX_Basic_21." - name: "mcx128a.rom" system: mc10 @@ -461,7 +465,7 @@ files: required: false aliases: [MCX_Basic_21_AZERTY] source_ref: "src/xroar.c:731 (romlist mcx128_azerty), src/xroar.c:638-639 (cart mcx128a)" - note: "AZERTY keyboard variant for Alice. Same MCX128 hardware." + note: "AZERTY keyboard variant for Alice. Same MCX128 hardware. Romlist mcx128_azerty tries mcx128a, MCX_Basic_21_AZERTY." - name: "yados.rom" system: coco diff --git a/emulators/ymir.yml b/emulators/ymir.yml index 1ee71dee..35cf6600 100644 --- a/emulators/ymir.yml +++ b/emulators/ymir.yml @@ -2,16 +2,16 @@ emulator: ymir type: standalone + libretro core_classification: community_fork source: - standalone: "https://github.com/StrikerX3/Ymir" + standalone: "https://github.com/ymir-emu/Ymir" libretro: "https://github.com/warmenhoven/Emir/tree/libretro" -upstream: "https://github.com/StrikerX3/Ymir" -profiled_date: "2026-03-26" +upstream: "https://github.com/ymir-emu/Ymir" +profiled_date: "2026-10-21" source_commit: - standalone: "5e9310410baa47cb7da5b068f399c9e4a34eedbc" - libretro: "5d99cbbf813206736f38b3574ecca7a8aedc07e5" + standalone: "8cdf0a530ec1927f44bf3cd02c6ab51a586c4407" + libretro: "8174cbbeea4070654841cdd4604361b3eee8fdd1" core_version: - standalone: "v0.2.1" - libretro: "PR#746" + standalone: "v0.4.1-1-g8cdf0a53" + libretro: "libretro branch" display_name: "Sega - Saturn (Ymir)" cores: - ymir @@ -21,7 +21,9 @@ systems: notes: | Ymir is a Sega Saturn emulator by StrikerX3. The libretro port by - warmenhoven wraps the shared ymir-core library (PR #746, not yet merged). + warmenhoven wraps the shared ymir-core library on the libretro branch of + warmenhoven/Emir, which the buildbot builds (include_core_ymir in + libretro-super). PR #746 was closed unmerged. No .info file exists in libretro-core-info. Standalone: scans configured directories recursively for files matching @@ -29,8 +31,14 @@ notes: | by XXH128 hash from an internal database (19 IPL variants, 4 CD Block versions, 2 ROM carts). Unknown files are accepted if size matches. - Libretro: searches {system}/sega_101.bin, mpr-17933.bin, saturn_bios.bin - in order. First file found with exact 512 KiB size wins. + Libretro: reads {system}/sega_101.bin, mpr-17933.bin and saturn_bios.bin, + each kept when it is exactly 512 KiB. A candidate's region comes from the + IPL database, else from two hashes the port knows (sega_101.bin Japan, + mpr-17933.bin North America and Europe). The ymir_region option picks the + candidate of its region, else the first found, and once the disc is loaded + a candidate whose region matches the disc's area code replaces it. + ref: apps/ymir-libretro/src/libretro.cpp:305-309, 584-712, + apps/ymir-libretro/src/libretro.cpp:1228-1238, 1285-1306 Batocera standalone: configgen maps IPLROMImages to /userdata/bios, CDBlockROMImages to /userdata/roms/saturn/cdb/, ROMCartImages to @@ -56,8 +64,8 @@ files: aliases: [mpr-17933.bin, saturn_bios.bin] description: "Saturn IPL ROM (BIOS). Any region accepted." source_ref: - standalone: "apps/ymir-sdl3/src/util/rom_loader.cpp:9-22, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56, libs/ymir-core/include/ymir/sys/memory_defs.hpp:9" - libretro: "apps/ymir-libretro/src/libretro.cpp:260-263,534-558" + standalone: "apps/ymir-sdl3/src/util/rom_loader.cpp:9-22, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53, libs/ymir-core/include/ymir/sys/memory_defs.hpp:9" + libretro: "apps/ymir-libretro/src/libretro.cpp:305-309, apps/ymir-libretro/src/libretro.cpp:651-690, apps/ymir-libretro/src/libretro.cpp:692-703" # IPL images named by the standalone XXH128 database. The md5 is that of # the image whose seeded XXH128 matches the database row. @@ -71,7 +79,7 @@ files: description: "Saturn IPL ROM 1.00 (1994-09-21), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:9, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:9, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "sega_101.bin" system: sega-saturn @@ -83,7 +91,7 @@ files: description: "Saturn IPL ROM 1.01 (1994-12-28), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:10, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:10, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "SAT_1.00a-(U+E).bin" system: sega-saturn @@ -95,7 +103,7 @@ files: description: "Saturn IPL ROM 1.00a (1994-11-15), North America and Europe." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:11, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:11, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "mpr-17933.bin" system: sega-saturn @@ -107,7 +115,7 @@ files: description: "Saturn IPL ROM 1.01a (1994-11-15), North America and Europe." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:12, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:12, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "hisaturn.bin" system: sega-saturn @@ -119,7 +127,7 @@ files: description: "HiSaturn IPL ROM 1.01 (1995-01-30), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:14, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:14, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "mpr-18100.bin" system: sega-saturn @@ -131,7 +139,7 @@ files: description: "HiSaturn IPL ROM 1.02 (1995-05-19), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:15, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:15, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "hisaturn_v103.bin" system: sega-saturn @@ -143,7 +151,7 @@ files: description: "HiSaturn IPL ROM 1.03 (1995-07-20), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:16, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:16, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "vsaturn.bin" system: sega-saturn @@ -155,7 +163,7 @@ files: description: "V-Saturn IPL ROM 1.01 (1995-07-03), Japan." note: "Picked up by the recursive IPL scan like any 512 KiB file and identified by its XXH128 row." source_ref: - standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:17, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-56" + standalone: "libs/ymir-core/src/ymir/db/ipl_db.cpp:17, libs/ymir-core/include/ymir/sys/memory_defs.hpp:10, apps/ymir-sdl3/src/app/rom_manager.cpp:14-53" - name: "cdb/cdb_rom.bin" system: sega-saturn @@ -165,8 +173,8 @@ files: validation: [size] description: "SH1 CD Block ROM for low-level CD drive emulation. Scans cdb/ subdirectory for any matching file." source_ref: - standalone: "apps/ymir-sdl3/src/util/rom_loader.cpp:25-38, apps/ymir-sdl3/src/app/rom_manager.cpp:58-93, libs/ymir-core/include/ymir/hw/sh1/sh1_defs.hpp:7" - libretro: "apps/ymir-libretro/src/libretro.cpp:565-591" + standalone: "apps/ymir-sdl3/src/util/rom_loader.cpp:25-38, apps/ymir-sdl3/src/app/rom_manager.cpp:55-91, libs/ymir-core/include/ymir/hw/sh1/sh1_defs.hpp:7" + libretro: "apps/ymir-libretro/src/libretro.cpp:720-737" - name: "mpr-18811-mx.ic1" system: sega-saturn @@ -176,8 +184,8 @@ files: validation: [size] description: "ROM cartridge for The King of Fighters '95." source_ref: - standalone: "apps/ymir-sdl3/src/app/rom_manager.cpp:96-131, libs/ymir-core/include/ymir/db/rom_cart_db.hpp:19-22" - libretro: "apps/ymir-libretro/src/libretro.cpp:621, 598-618" + standalone: "apps/ymir-sdl3/src/app/rom_manager.cpp:93-130, libs/ymir-core/include/ymir/db/rom_cart_db.hpp:19-22" + libretro: "apps/ymir-libretro/src/libretro.cpp:760, apps/ymir-libretro/src/libretro.cpp:744-756" - name: "mpr-19367-mx.ic1" system: sega-saturn @@ -187,8 +195,8 @@ files: validation: [size] description: "ROM cartridge for Ultraman: Hikari no Kyojin Densetsu." source_ref: - standalone: "apps/ymir-sdl3/src/app/rom_manager.cpp:96-131, libs/ymir-core/include/ymir/db/rom_cart_db.hpp:25-28" - libretro: "apps/ymir-libretro/src/libretro.cpp:622, 598-618" + standalone: "apps/ymir-sdl3/src/app/rom_manager.cpp:93-130, libs/ymir-core/include/ymir/db/rom_cart_db.hpp:25-28" + libretro: "apps/ymir-libretro/src/libretro.cpp:761, apps/ymir-libretro/src/libretro.cpp:744-756" - name: "gamecontrollerdb.txt" system: sega-saturn @@ -206,4 +214,4 @@ files: v0.2.1 Linux and macOS packages and, with CRLF line ends, the Windows zips. source_ref: - standalone: "apps/ymir-sdl3/src/app/settings.hpp:41, apps/ymir-sdl3/src/app/app.cpp:5084-5119, apps/ymir-sdl3/src/app/profile.cpp:36-41, .github/workflows/build.yaml:198-230" + standalone: "apps/ymir-sdl3/src/app/settings.hpp:42, apps/ymir-sdl3/src/app/services/rom_service.cpp:33-68, apps/ymir-sdl3/src/app/profile.cpp:36-46, .github/workflows/build.yaml:202-236" diff --git a/tests/test_launcher_aliases.py b/tests/test_launcher_aliases.py new file mode 100644 index 00000000..cfb0abf9 --- /dev/null +++ b/tests/test_launcher_aliases.py @@ -0,0 +1,153 @@ +"""A profile alias is a name the emulator's own code opens. + +Platform launchers pick names of their own: Batocera passes cerbios.bin to +xemu, ROCKNIX and EmuDeck write Complex_4627v1.03.bin into xemu.toml. Those +names live in the platform's ``launchers:`` layer. Copied into a profile as +aliases, they claimed that xemu opens them, and xemu-libretro offers +Complex_4627_v1.03.bin, not Complex_4627v1.03.bin (ui/xemu-libretro.c:115-118). + +Two checks read the committed data: + +- an alias equal to a name a launcher of the same emulator chooses is kept + only when the entry's own note or description names it in a sentence that + speaks of no platform, next to a ``source_ref`` into the emulator's code; +- no entry cites a platform's launcher script as its source. +""" + +from __future__ import annotations + +import re +import unittest +from collections import defaultdict +from pathlib import Path + +import yaml + +REPO_ROOT = Path(__file__).resolve().parent.parent +PLATFORMS = REPO_ROOT / "platforms" +EMULATORS = REPO_ROOT / "emulators" + +# Words that name a platform in prose. MiSTer's registry key carries its +# hardware suffix, the prose says MiSTer. +PLATFORM_WORDS = ( + "retroarch", "batocera", "recalbox", "retrobat", "emudeck", "lakka", + "retrodeck", "romm", "rocknix", "retropie", "bizhawk", "mister", +) + +# Launcher sources: configgen and emulatorLauncher generators, EmuDeck and +# RetroPie scripts, a ref annotated as a launcher. +LAUNCHER_REF = re.compile( + r"Generator\.(?:py|cs)\b|\bconfiggen\b|\bemulatorLauncher\b|" + r"\bemuDeck\w*\.sh\b|\bscriptmodules/|\(launcher\)", +) + +# Profiles whose entries still rest on a launcher, with the fact that blocks +# reading the emulator itself. +LAUNCHER_SOURCED = { + "lexaloffle": "PICO-8 and Voxatron are sold binaries, and no copy of either is held to read", +} + +_SENTENCE = re.compile(r"(?<=[.!?])\s+(?=[A-Z0-9(\"'])") + + +def _profiles() -> dict[str, dict]: + return { + path.stem: yaml.safe_load(path.read_text(encoding="utf-8")) or {} + for path in sorted(EMULATORS.glob("*.yml")) + } + + +def _launcher_names() -> dict[str, set[tuple[str, str]]]: + """Folded file name -> (platform, emulator) of each launcher choosing it.""" + names: dict[str, set[tuple[str, str]]] = defaultdict(set) + for path in sorted(PLATFORMS.glob("*.yml")): + config = yaml.safe_load(path.read_text(encoding="utf-8")) or {} + for record in config.get("launchers") or []: + for name in record.get("names") or []: + base = str(name).rsplit("/", 1)[-1].casefold() + names[base].add((path.stem, str(record.get("emulator", "")))) + return names + + +def _text(value: object) -> str: + if isinstance(value, dict): + return " ".join(_text(v) for v in value.values()) + if isinstance(value, list): + return " ".join(_text(v) for v in value) + return str(value or "") + + +def _named_without_platform(alias: str, prose: str) -> bool: + for sentence in _SENTENCE.split(" ".join(prose.split())): + if alias not in sentence: + continue + folded = sentence.casefold() + if not any(re.search(rf"\b{word}", folded) for word in PLATFORM_WORDS): + return True + return False + + +class ProfileAliasesAreCodeNames(unittest.TestCase): + def test_alias_a_launcher_chooses_is_named_by_the_code(self) -> None: + launchers = _launcher_names() + offenders = [] + for key, profile in _profiles().items(): + emulator_names = {key} | {str(c) for c in profile.get("cores") or []} + for entry in profile.get("files") or []: + prose = _text(entry.get("note")) + " " + _text(entry.get("description")) + for alias in entry.get("aliases") or []: + alias = str(alias) + chosen_by = { + platform + for platform, emulator in launchers.get( + alias.rsplit("/", 1)[-1].casefold(), () + ) + if emulator in emulator_names + } + if not chosen_by: + continue + if entry.get("source_ref") and _named_without_platform(alias, prose): + continue + offenders.append( + f"{key}: {entry.get('name')} alias {alias} " + f"(launchers: {', '.join(sorted(chosen_by))})" + ) + self.assertEqual( + offenders, [], + "an alias a platform launcher chooses must be named by the emulator's " + "code, stated in the entry's note with its source_ref, or removed", + ) + + def test_check_catches_a_launcher_name(self) -> None: + self.assertFalse(_named_without_platform( + "cerbios.bin", "Batocera writes bios/cerbios.bin into flashrom_path.", + )) + self.assertTrue(_named_without_platform( + "cerbios.bin", "The core option offers cerbios.bin. Batocera writes it.", + )) + + +class EntriesCiteTheEmulator(unittest.TestCase): + def test_no_source_ref_is_a_launcher_script(self) -> None: + offenders = [] + for key, profile in _profiles().items(): + if key in LAUNCHER_SOURCED: + continue + for entry in profile.get("files") or []: + ref = _text(entry.get("source_ref")) + if LAUNCHER_REF.search(ref): + offenders.append(f"{key}: {entry.get('name')}: {ref}") + self.assertEqual(offenders, []) + + def test_known_exceptions_still_need_it(self) -> None: + profiles = _profiles() + for key in LAUNCHER_SOURCED: + refs = [_text(e.get("source_ref")) for e in profiles[key].get("files") or []] + self.assertTrue( + any(LAUNCHER_REF.search(r) for r in refs), + f"{key} no longer cites a launcher: drop it from LAUNCHER_SOURCED", + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_profile_repositories.py b/tests/test_profile_repositories.py new file mode 100644 index 00000000..c00f94a8 --- /dev/null +++ b/tests/test_profile_repositories.py @@ -0,0 +1,55 @@ +"""A profile names each repository under the name its forge answers today. + +GitHub follows a renamed or transferred repository's old name in silence: +flycast2021 declared libretro/flycast, which answers as libretro/parallel-dc, +and reicast declared reicast/reicast-emulator, which answers as +skmp/reicast-emulator. profile_sync counts such a move as review work. This +test reads the forge answers profile_sync has cached and fails on any +profile still declaring an old name. Without a cache it has nothing to read +and skips. +""" + +from __future__ import annotations + +import sys +import unittest +from pathlib import Path + +import yaml + +REPO_ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(REPO_ROOT / "scripts")) + +import upstream # noqa: E402 +from profile_sync import declared_repositories # noqa: E402 + +CACHE = Path(upstream.CACHE_DIR) +if not CACHE.is_absolute(): + CACHE = REPO_ROOT / CACHE + + +class DeclaredRepositoriesAreCurrent(unittest.TestCase): + def test_no_profile_declares_a_moved_repository(self) -> None: + if not (CACHE / "_api").is_dir(): + self.skipTest("no forge answers cached") + checked = 0 + moved = [] + for path in sorted((REPO_ROOT / "emulators").glob("*.yml")): + profile = yaml.safe_load(path.read_text(encoding="utf-8")) or {} + for field, _key, url in declared_repositories(profile): + repo = upstream.parse_repo(url) + if repo is None: + continue + current = upstream.current_slug(repo, str(CACHE), offline=True) + if current is None: + continue + checked += 1 + if current.lower() != repo.slug.lower(): + moved.append(f"{path.stem} {field}: {repo.slug} answers as {current}") + if not checked: + self.skipTest("no declared repository has a cached forge answer") + self.assertEqual(moved, []) + + +if __name__ == "__main__": + unittest.main() diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md index 7f8fc09f..52742fce 100644 --- a/wiki/testing-guide.md +++ b/wiki/testing-guide.md @@ -39,7 +39,7 @@ Every module in `tests/`, by the area it guards. |------|----------|---------| | Core regression suites | synthetic | `test_e2e`, `test_audit_regressions`, `test_tool_messages` | | File resolution and identity | synthetic + collection | `test_adler32_resolution`, `test_agnostic_scan`, `test_agnostic_scan_mode`, `test_agnostic_scope`, `test_agnostic_substitute`, `test_archive_choice`, `test_bios_companions`, `test_bundled_identity`, `test_casefold_cache`, `test_db_aliases`, `test_declared_names`, `test_derivations`, `test_directory_entries`, `test_extra_identity`, `test_foreign_tree`, `test_foreign_tree_names`, `test_frontend_digest`, `test_game_data_homonyms`, `test_hashing`, `test_identity`, `test_md5_pack_context`, `test_name_tiebreak`, `test_nec_filing`, `test_owner_resolution`, `test_path_suffix`, `test_resolution_evidence`, `test_shipped_content`, `test_twin_declarations`, `test_validated_choice`, `test_variant_choice`, `test_variant_identity`, `test_zipped_member` | -| Verification, cross-reference and profile checks | synthetic + profiles | `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_file_consumers`, `test_fileless_audit`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` | +| Verification, cross-reference and profile checks | synthetic + profiles | `test_crypto_aes`, `test_crypto_unique_data`, `test_crypto_verify`, `test_case_insensitive_platforms`, `test_checks_have_values`, `test_core_file_fills_declaration`, `test_core_size_refusal`, `test_cross_reference_sources`, `test_file_consumers`, `test_fileless_audit`, `test_gap_settlement`, `test_hidden_extras`, `test_launcher_aliases`, `test_launcher_layer`, `test_native_mode`, `test_no_case_collisions`, `test_path_conflict_status`, `test_path_null_copies`, `test_profile_checks`, `test_profile_repositories`, `test_romm_hash_rule`, `test_shared_groups`, `test_standalone_mode`, `test_undeclared_dedup`, `test_unplaced_extras`, `test_validation_scope`, `test_verify_all_dir`, `test_verify_emulator_evidence`, `test_verify_listing`, `test_verify_pack_choice`, `test_verify_release_asset` | | Packs and manifests | synthetic + real packs | `test_artifact_lock`, `test_atomic_artifacts`, `test_batocera_cores`, `test_deterministic_zip`, `test_emulator_pack_counts`, `test_finalize_pack_names`, `test_large_file_cache`, `test_libretro_layout`, `test_manifest_entry`, `test_pack_conformance_dirs`, `test_pack_core_extras`, `test_pack_counts`, `test_pack_destinations`, `test_pack_failures`, `test_pack_file_names`, `test_pack_grouping`, `test_pack_integrity`, `test_pack_member_identity`, `test_pack_readme`, `test_platform_inheritance`, `test_platform_keys`, `test_required_only_archives`, `test_required_only_twins`, `test_split_extras`, `test_split_names`, `test_split_pack`, `test_system_pack_extras`, `test_system_pack_parity`, `test_torrentzip`, `test_which_pack` | | Slots and regions | synthetic + profiles | `test_region`, `test_region_agnostic_scan`, `test_region_groups`, `test_region_held`, `test_region_platform_index`, `test_region_required_only`, `test_slot`, `test_slots`, `test_slots_shipped_file` | | Hardware targets and systems | synthetic + target files | `test_extract_targets`, `test_lakka_targets`, `test_libretro_slugs`, `test_system_ids`, `test_system_selection`, `test_target_names`, `test_target_scrapers`, `test_target_systems`, `test_target_verify` |