From d678e6acfa45c1cf7237300276197652ee2e920b Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:06:07 +0200 Subject: [PATCH 1/4] fix: declare the FreeIntv overlays on the core FreeIntv declared no data tree while its alias freeintv_ts_overlay, the same code, declared freeintv_overlays. The core reads freeintv_overlays/.png only with the multi-screen option and draws its embedded keypad image without one (src/libretro.c:278-280, 294, 321-325), so the tree is optional. A test holds every alias to the trees of its core. --- emulators/freeintv.yml | 10 ++++++++++ tests/test_audit_regressions.py | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/emulators/freeintv.yml b/emulators/freeintv.yml index e24f3023d..06a196437 100644 --- a/emulators/freeintv.yml +++ b/emulators/freeintv.yml @@ -29,6 +29,16 @@ notes: | No ECS support. No ecs.bin loading code in the source. + Per-game controller overlays are read from freeintv_overlays/.png + (or .jpg) in the system directory, only when the multi-screen option is + on (src/libretro.c:278-280, 294). Without one the core draws the keypad + image embedded in the binary (src/libretro.c:321-325). + +data_directories: + - ref: freeintv-overlays + destination: freeintv_overlays + required: false + files: - name: "exec.bin" system: intellivision diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index 0c392b3a7..b05b3418d 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -5923,6 +5923,28 @@ class RequiredOnlyReachesDataDirectories(unittest.TestCase): "required": False}, ]) + def test_an_alias_reads_the_trees_of_its_core(self): + """An alias is the same binary under another name. FreeIntv declared + no overlay tree while its alias freeintv_ts_overlay did, so the + emulator pack of the core itself left the overlays out.""" + profiles = { + path.stem: yaml.safe_load(path.read_text(encoding="utf-8")) + for path in (ROOT / "emulators").glob("*.yml") + } + + def trees(profile: dict) -> dict: + return { + dd["ref"]: dd.get("required", True) + for dd in profile.get("data_directories") or [] + } + + for name, profile in profiles.items(): + target = profile.get("alias_of") + if not target or target not in profiles: + continue + with self.subTest(alias=name, core=target): + self.assertEqual(trees(profile), trees(profiles[target])) + class InstallerJsonKindsNeverOverwriteEachOther(unittest.TestCase): """Install manifests and target core lists are both .json. From 7056dd84ea6f74dee199c8e9cc62881224446677 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:06:35 +0200 Subject: [PATCH 2/4] fix: state why WinUAE needs the CD extended ROMs A missing extended ROM only raises a notice (memory.cpp:1833-1849), but the machine then runs on the Kickstart alone. cdstrap, cd.device, cdtv.device and cdfs.library are resident modules of the CD32 and CDTV extended ROMs and absent from their Kickstarts, the CD32 and base CDTV models have no floppy drive (cfgfile.cpp:9375-9379, 9405-9406), so no CD is read or booted. Both entries stay required. The AROS replacement stands in only for a missing Kickstart (memory.cpp:3055-3063), so the CDTV entry loses hle_fallback. --- emulators/winuae.yml | 12 ++++++++++-- tests/test_audit_regressions.py | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/emulators/winuae.yml b/emulators/winuae.yml index 5bd1a1a50..1a3c4cfe8 100644 --- a/emulators/winuae.yml +++ b/emulators/winuae.yml @@ -35,7 +35,16 @@ notes: | file name matches the configured one (rommgr.cpp:2428-2461). The Kickstart entries below are named after other profiles' names for the same dumps: the code opens none of those names. kickstart_ext_rom_file is opened as given, and a missing extended ROM - only raises a notice (memory.cpp:1833-1849). + only raises a notice (memory.cpp:1833-1849). The machine then starts on + the Kickstart alone with nothing mapped in place of the extended ROM, and + the AROS replacement is used only when the Kickstart itself is missing + (memory.cpp:3055-3063). The CD drivers and CD boot code are resident + modules of the extended ROMs: cdstrap, cd.device and cdfs.library in the + CD32 ROM, cdtv.device, cdfs.library and cdstrap in the CDTV ROM. The CD32 + and CDTV Kickstarts carry none. The CD32 quickstart model and the base + CDTV model have no floppy drive (cfgfile.cpp:9375-9379, 9405-9406), and + both ask for the extended ROM (cfgfile.cpp:9390-9395, 9414-9423), so + without it no CD is read or booted. CDTV and A600/A1200 internal devices are enabled with :ENABLED, which needs no ROM file. Cloanto encrypted ROMs are decoded with rom.key, searched in the @@ -126,7 +135,6 @@ files: - name: "amiga-ext-130-cdtv.rom" system: commodore-cdtv required: true - hle_fallback: true size: 262144 crc32: "42baa124" sha1: "7ba40ffa17e500ed9fed041f3424bd81d9c907be" diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index b05b3418d..9ebf16ab2 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -6147,5 +6147,23 @@ class SkipPacksHelpSaysWhatRuns(unittest.TestCase): self.assertEqual(skipped, {"4", "4b", "4c", "6"}) +class AmigaCdDriversLiveInTheExtendedRom(unittest.TestCase): + """WinUAE starts without the CD32 or CDTV extended ROM, but cd.device, + cdtv.device, cdfs.library and cdstrap are resident modules of those ROMs + and the Kickstarts carry none. Its AROS replacement stands in only for a + missing Kickstart (memory.cpp:3055-3063), so the CDTV ROM has no + fallback to downgrade its absence.""" + + def test_both_extended_roms_are_required_without_fallback(self): + profile = yaml.safe_load( + (ROOT / "emulators" / "winuae.yml").read_text(encoding="utf-8") + ) + entries = {f["name"]: f for f in profile["files"]} + for name in ("amiga-ext-310-cd32.rom", "amiga-ext-130-cdtv.rom"): + with self.subTest(name=name): + self.assertIs(entries[name]["required"], True) + self.assertNotIn("hle_fallback", entries[name]) + + if __name__ == "__main__": unittest.main() From 6b4010907d1573f8837eedba886c168192ec7e31 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:07:30 +0200 Subject: [PATCH 3/4] feat: list the six BizHawk DSi NAND slots FirmwareDatabase.cs:405-410 declares NDS+NAND_JPN, EUR, USA, AUS, CHN and KOR, each with a placeholder hash and 251658240 + 64 bytes. In DSi mode DecideNAND takes the first one set, limited to the regions a DSi-enhanced header allows, and stops the load with none (MelonDS.cs:114, 304, 484, 684-706). DSi mode is off by default, so the entries are optional, like DSi_Firmware.bin and the DSi BIOS slots. --- emulators/bizhawk.yml | 64 +++++++++++++++++++++++++++++++-- tests/test_audit_regressions.py | 20 +++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/emulators/bizhawk.yml b/emulators/bizhawk.yml index b45bee378..672dc5063 100644 --- a/emulators/bizhawk.yml +++ b/emulators/bizhawk.yml @@ -79,10 +79,14 @@ notes: | firmware folder by hash, and a user specification can name any file. Unacceptable and Bad options, and slots with a placeholder hash, are reached only through a user specification. The six DSi NAND slots - (NDS+NAND_JPN, EUR, USA, AUS, CHN, KOR) are of that kind and are not - listed. + (NDS+NAND_JPN, EUR, USA, AUS, CHN, KOR) are of that kind. In DSi mode + (the UseDSi setting, or DSiWare content) the core takes the first of + them that is set, in the order JPN, USA, EUR, AUS, CHN, KOR, and for a + DSi-enhanced title only the regions its header flags allow. With none it + stops the load. ref: src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:35-71, - src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:405-410 + src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:405-410, + src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:114, 304, 684-706 required follows what the core does on a default configuration for that system's content. GetFirmwareOrThrow stops the load, GetFirmware lets the @@ -144,6 +148,60 @@ files: source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:402, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:469" note: "Slot NDS+firmwarei has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode with real BIOS files." + - name: "DSi_Nand_JPN.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (Japan)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:405, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_JPN has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + + - name: "DSi_Nand_EUR.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (Europe)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:406, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_EUR has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + + - name: "DSi_Nand_USA.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (USA)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:407, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_USA has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + + - name: "DSi_Nand_AUS.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (Australia)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:408, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_AUS has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + + - name: "DSi_Nand_CHN.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (China)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:409, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_CHN has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + + - name: "DSi_Nand_KOR.bin" + system: nintendo-ds + required: false + size: 251658304 + storage: large_file + description: "DSi NAND (Korea)" + source_ref: "src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs:410, src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs:484, 684-706" + note: "Slot NDS+NAND_KOR has a placeholder hash, so the scan never finds it. Only a user specification reaches it. Read in DSi mode. The size includes the 64-byte nocash footer." + - name: "32X_G_BIOS.BIN" system: sega-32x required: false diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index 9ebf16ab2..aab29b925 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -6165,5 +6165,25 @@ class AmigaCdDriversLiveInTheExtendedRom(unittest.TestCase): self.assertNotIn("hle_fallback", entries[name]) +class BizHawkListsEveryDsiNandSlot(unittest.TestCase): + """FirmwareDatabase.cs:405-410 declares six DSi NAND slots, each a + placeholder hash and 251658240 + 64 bytes, and DecideNAND + (MelonDS.cs:684-706) stops a DSi load when none is set. The profile + listed DSi_Firmware.bin, a placeholder slot of the same kind, and left + the NANDs out.""" + + def test_the_six_regional_nands_are_declared(self): + profile = yaml.safe_load( + (ROOT / "emulators" / "bizhawk.yml").read_text(encoding="utf-8") + ) + entries = {f["name"]: f for f in profile["files"]} + for region_code in ("JPN", "EUR", "USA", "AUS", "CHN", "KOR"): + with self.subTest(region=region_code): + entry = entries[f"DSi_Nand_{region_code}.bin"] + self.assertEqual(entry["size"], 251658240 + 64) + self.assertIs(entry["required"], False) + self.assertNotIn("sha1", entry) + + if __name__ == "__main__": unittest.main() From 67f1f05ff2c46bd75907904d4881ca584876c402 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:12:41 +0200 Subject: [PATCH 4/4] docs: state what three cores do without data trees The Dolphin Sys, PPSSPP assets and blueMSX trees stay required, and the profiles now cite why. blueMSX finds no machine without Machines/, the C-BIOS ones included, and the load fails (Src/Board/Machine.c:637-656, libretro.c:1447-1449). Its tree reference cited libretro.c:1119-1120, which at the pinned revision is the Sunrise IDE option, and now cites 1196-1197. PPSSPP has no internal font without flash0/font, so sceFontOpen fails for games using the system fonts (Core/HLE/sceFont.cpp:805-864, 984-986). Dolphin loads no GameCube font without Sys/GC/ or an IPL dump and warns that games may crash (Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:328-340). --- emulators/bluemsx.yml | 8 ++++++-- emulators/dolphin.yml | 10 ++++++++++ emulators/ppsspp.yml | 8 +++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/emulators/bluemsx.yml b/emulators/bluemsx.yml index ad6297fb8..b5b78c22e 100644 --- a/emulators/bluemsx.yml +++ b/emulators/bluemsx.yml @@ -55,6 +55,10 @@ notes: | C-BIOS machines work for cartridge-based games without any copyrighted BIOS. For disk/tape support, real BIOS ROMs are required. + The C-BIOS machines are Machines/ entries too. Without the tree + machineCreate finds neither config.ini nor a zip for any machine and the + game load fails (Src/Board/Machine.c:637-656, libretro.c:1447-1449). + The libretro core zip holds the library only, and the Machines/ and Databases/ trees come from the buildbot's blueMSX.zip system files. The standalone blueMSXv282full.zip ships both trees, machine ROMs included, so every file @@ -63,10 +67,10 @@ notes: | data_directories: # 302 files: 296 in Machines/ (200 machine configs + ROMs) + 6 in Databases/ # buildbot source: https://buildbot.libretro.com/assets/system/blueMSX.zip - # ref: libretro.c:1118-1119: system_dir/Machines/ + system_dir/Databases/ + # ref: libretro.c:1196-1197: system_dir/Machines/ + system_dir/Databases/ - ref: bluemsx installed_on: [batocera, recalbox, retrobat, retrodeck] - source_ref: "libretro.c:1119-1120" + source_ref: "libretro.c:1196-1197, 1447-1449, Src/Board/Machine.c:637-656" files: # ============================================================ diff --git a/emulators/dolphin.yml b/emulators/dolphin.yml index 7ed174cb4..f7a1a468d 100644 --- a/emulators/dolphin.yml +++ b/emulators/dolphin.yml @@ -386,6 +386,16 @@ notes: Fonts can come from three sources: real IPL dump (preferred), standalone font files in Sys/GC/, or bundled free alternatives. The free fonts have different padding that causes text positioning issues in some games. + sys_note: > + Without Sys/ the libretro core logs that codehandler.bin is missing and + goes on. With no IPL dump the GameCube fonts are read from Sys/GC/, so + none is loaded, and a game reading them raises "Games may not show fonts correctly, or + crash". The per-game settings in Sys/GameSettings/ and the WiiConnect24 + files some Wii games expect are skipped too. + ref: Source/Core/DolphinLibretro/Boot.cpp:313-340, + Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:128-130, 160-167, 328-340, + Source/Core/Core/ConfigManager.cpp:570, 586, + Source/Core/Core/WiiRoot.cpp:325-330 nand_note: > Wii NAND content (channels, saves, system menu) is managed by Dolphin internally. Users can import a BootMii NAND backup (nand.bin + optional keys.bin) to populate it. diff --git a/emulators/ppsspp.yml b/emulators/ppsspp.yml index b959d55ed..f8c95907a 100644 --- a/emulators/ppsspp.yml +++ b/emulators/ppsspp.yml @@ -19,7 +19,7 @@ data_directories: installed_on: [batocera, emudeck, lakka, recalbox, retrobat, retrodeck, retropie] mode: libretro destination: "" - source_ref: "libretro/libretro.cpp:537, 549" + source_ref: "libretro/libretro.cpp:537, 546, 549" notes: | Full HLE emulator. No Sony firmware or BIOS required. @@ -28,6 +28,12 @@ notes: | Assets include replacement PGF fonts (18 files in flash0/font/), game compatibility database (compat.ini), language mapping (langregion.ini), and post-processing shaders (shaders/). + flash0/ is read from system/PPSSPP/flash0/ (libretro/libretro.cpp:546). + Without its fonts the font library holds no internal font and + sceFontOpen returns ERROR_FONT_INVALID_PARAMETER to the game + (Core/HLE/sceFont.cpp:805-864, 984-986), so text a game draws with the + PSP system fonts is lost. Without ppge_atlas.zim the system dialogs are + not drawn (Core/Util/PPGeDraw.cpp:227-230). Libretro fork (2020-03-18) behind upstream. PSP_DEFAULT_FIRMWARE = 660 (Core/ConfigValues.h:40).