From 9409ec12b3ca96751fdd8dd60dfe98284190b980 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 09:50:40 +0200 Subject: [PATCH 01/10] fix: keep the two mt32emu.h citations together Each MT-32 entry cites the SHA-1 line and the ROMInfo line of one mt32emu.h. dosbox_pure wrote them under two repository words, so the ROMInfo line was self-checked alone and read MOVED onto the SHA-1 line. Both now sit in the port that carries the file, and in the upstream for dosbox-pure-unleashed, whose tree has no src/gui. A recale that lands on a line a sibling part already cites goes to review, and a part settled by its anchor keeps that anchor's repository. --- emulators/dosbox-pure-unleashed.yml | 28 +++++++++--------- emulators/dosbox_pure.yml | 28 +++++++++--------- scripts/profile_sync.py | 46 ++++++++++++++++++++++++----- tests/test_profile_sync.py | 27 +++++++++++++++++ 4 files changed, 94 insertions(+), 35 deletions(-) diff --git a/emulators/dosbox-pure-unleashed.yml b/emulators/dosbox-pure-unleashed.yml index 56a85c24..cd37dd29 100644 --- a/emulators/dosbox-pure-unleashed.yml +++ b/emulators/dosbox-pure-unleashed.yml @@ -103,7 +103,7 @@ files: size: 65536 sha1: "5a5cb5a77d7d55ee69657c2f870416daed52dea7" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" + source_ref: "upstream src/gui/mt32emu.h:5112, upstream src/gui/mt32emu.h:5129" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.05" @@ -112,7 +112,7 @@ files: size: 65536 sha1: "e17a3a6d265bf1fa150312061134293d2b58288c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" + source_ref: "upstream src/gui/mt32emu.h:5113, upstream src/gui/mt32emu.h:5130" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.06" @@ -121,7 +121,7 @@ files: size: 65536 sha1: "a553481f4e2794c10cfe597fef154eef0d8257de" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" + source_ref: "upstream src/gui/mt32emu.h:5114, upstream src/gui/mt32emu.h:5131" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.07" @@ -130,7 +130,7 @@ files: size: 65536 sha1: "b083518fffb7f66b03c23b7eb4f868e62dc5a987" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" + source_ref: "upstream src/gui/mt32emu.h:5115, upstream src/gui/mt32emu.h:5132" - name: "MT32_CONTROL.ROM" description: "MT-32 Control BlueRidge" @@ -139,7 +139,7 @@ files: size: 65536 sha1: "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" + source_ref: "upstream src/gui/mt32emu.h:5116, upstream src/gui/mt32emu.h:5133" # -- MT-32 v2.x control ROMs (128 KB, pair with MT32_PCM.ROM) -- @@ -150,7 +150,7 @@ files: size: 131072 sha1: "5837064c9df4741a55f7c4d8787ac158dff2d3ce" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" + source_ref: "upstream src/gui/mt32emu.h:5118, upstream src/gui/mt32emu.h:5135" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.04" @@ -159,7 +159,7 @@ files: size: 131072 sha1: "2c16432b6c73dd2a3947cba950a0f4c19d6180eb" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" + source_ref: "upstream src/gui/mt32emu.h:5119, upstream src/gui/mt32emu.h:5136" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.06" @@ -168,7 +168,7 @@ files: size: 131072 sha1: "2869cf4c235d671668cfcb62415e2ce8323ad4ed" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" + source_ref: "upstream src/gui/mt32emu.h:5120, upstream src/gui/mt32emu.h:5137" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.07" @@ -177,7 +177,7 @@ files: size: 131072 sha1: "47b52adefedaec475c925e54340e37673c11707c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" + source_ref: "upstream src/gui/mt32emu.h:5121, upstream src/gui/mt32emu.h:5138" # -- CM-32L / LAPC-I control ROMs (64 KB, pair with CM32L_PCM.ROM) -- @@ -188,7 +188,7 @@ files: size: 65536 sha1: "73683d585cd6948cc19547942ca0e14a0319456d" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" + source_ref: "upstream src/gui/mt32emu.h:5122, upstream src/gui/mt32emu.h:5139" - name: "CM32L_CONTROL.ROM" description: "CM-32L/LAPC-I Control v1.02" @@ -197,7 +197,7 @@ files: size: 65536 sha1: "a439fbb390da38cada95a7cbb1d6ca199cd66ef8" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" + source_ref: "upstream src/gui/mt32emu.h:5123, upstream src/gui/mt32emu.h:5140" # -- CM-32LN / CM-500 / LAPC-N control ROM (64 KB, pairs with CM32L_PCM.ROM) -- @@ -208,7 +208,7 @@ files: size: 65536 sha1: "dc1c5b1b90a4646d00f7daf3679733c7badc7077" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" + source_ref: "upstream src/gui/mt32emu.h:5124, upstream src/gui/mt32emu.h:5141" # -- PCM ROMs -- @@ -219,7 +219,7 @@ files: size: 524288 sha1: "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" + source_ref: "upstream src/gui/mt32emu.h:5126, upstream src/gui/mt32emu.h:5143" note: "accepted by every MT-32 control ROM, v1.x and v2.x (pcmCount 128)" - name: "CM32L_PCM.ROM" @@ -230,7 +230,7 @@ files: sha1: "289cc298ad532b702461bfc738009d9ebe8025ea" validation: [sha1, size] aliases: ["CM32LN_PCM.ROM"] - source_ref: "upstream src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" + source_ref: "upstream src/gui/mt32emu.h:5127, upstream src/gui/mt32emu.h:5144" note: > accepted by the CM-32L and CM-32LN control ROMs (pcmCount 256). The alias covers the name derived from CM32LN_CONTROL.ROM. diff --git a/emulators/dosbox_pure.yml b/emulators/dosbox_pure.yml index eeaa8c51..b6d84a53 100644 --- a/emulators/dosbox_pure.yml +++ b/emulators/dosbox_pure.yml @@ -61,7 +61,7 @@ files: size: 65536 sha1: "5a5cb5a77d7d55ee69657c2f870416daed52dea7" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" + source_ref: "source src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.05" @@ -70,7 +70,7 @@ files: size: 65536 sha1: "e17a3a6d265bf1fa150312061134293d2b58288c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" + source_ref: "source src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.06" @@ -79,7 +79,7 @@ files: size: 65536 sha1: "a553481f4e2794c10cfe597fef154eef0d8257de" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" + source_ref: "source src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.07" @@ -88,7 +88,7 @@ files: size: 65536 sha1: "b083518fffb7f66b03c23b7eb4f868e62dc5a987" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" + source_ref: "source src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" - name: "MT32_CONTROL.ROM" description: "MT-32 Control BlueRidge" @@ -97,7 +97,7 @@ files: size: 65536 sha1: "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" + source_ref: "source src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" # -- MT-32 v2.x Control ROMs (128 KB) -- @@ -108,7 +108,7 @@ files: size: 131072 sha1: "5837064c9df4741a55f7c4d8787ac158dff2d3ce" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" + source_ref: "source src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.04" @@ -117,7 +117,7 @@ files: size: 131072 sha1: "2c16432b6c73dd2a3947cba950a0f4c19d6180eb" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" + source_ref: "source src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.06" @@ -126,7 +126,7 @@ files: size: 131072 sha1: "2869cf4c235d671668cfcb62415e2ce8323ad4ed" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" + source_ref: "source src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.07" @@ -135,7 +135,7 @@ files: size: 131072 sha1: "47b52adefedaec475c925e54340e37673c11707c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" + source_ref: "source src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" # -- CM-32L / LAPC-I Control ROMs (64 KB) -- @@ -146,7 +146,7 @@ files: size: 65536 sha1: "73683d585cd6948cc19547942ca0e14a0319456d" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" + source_ref: "source src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" - name: "CM32L_CONTROL.ROM" description: "CM-32L/LAPC-I Control v1.02" @@ -155,7 +155,7 @@ files: size: 65536 sha1: "a439fbb390da38cada95a7cbb1d6ca199cd66ef8" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" + source_ref: "source src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" # -- CM-32LN / CM-500 / LAPC-N Control ROM (64 KB) -- @@ -166,7 +166,7 @@ files: size: 65536 sha1: "dc1c5b1b90a4646d00f7daf3679733c7badc7077" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" + source_ref: "source src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" # -- PCM ROMs -- @@ -177,7 +177,7 @@ files: size: 524288 sha1: "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" + source_ref: "source src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" note: > accepted by every MT-32 control ROM, v1.x and v2.x. Each control ROM fixes the PCM size it accepts through its pcmCount: 128 requires this @@ -191,7 +191,7 @@ files: sha1: "289cc298ad532b702461bfc738009d9ebe8025ea" validation: [sha1, size] aliases: ["CM32LN_PCM.ROM"] - source_ref: "upstream src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" + source_ref: "source src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" note: > accepted by the CM-32L and CM-32LN control ROMs, which carry pcmCount 256 and require this 1048576 byte image. The alias covers the name diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index b91627d1..e56e0e9b 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -902,6 +902,33 @@ def resolve_by_shift(part: PartResult, shifts: dict[str, int]) -> PartResult: ) +def refuse_collapsing_moves(parts: list[PartResult]) -> list[PartResult]: + """Hold back a recale that would land on another part of the same ref. + + Two parts of one source_ref cite two places on purpose. dosbox_pure cited + the SHA-1 line of mt32emu.h and the ROMInfo line that ties it to a file + name, under two repository words: the second was self-checked alone, + found the hash once, and read MOVED onto the first line. Recaling it + would drop the ROMInfo citation without a word, so the part goes to + review instead. + """ + cited = { + (p.part.path, p.part.start, p.part.last) + for p in parts if p.part.start is not None + } + held = [] + for part in parts: + target = (part.new_path or part.part.path, part.start, part.end or part.start) + own = (part.part.path, part.part.start, part.part.last) + if part.status in REBASE_STATUSES and target != own and target in cited: + part = replace( + part, status="AMBIGUOUS", candidates=[part.start], + reason="lands on a line another part of this ref already cites", + ) + held.append(part) + return held + + @dataclass class EntryReport: name: str @@ -1246,14 +1273,19 @@ def reconcile_self_check( against HEAD rather than self-checked is never rewritten. """ eligible = eligible if eligible is not None else [True] * len(parts) - anchored_files = { - part.part.path - for part, ok in zip(parts, eligible) - if ok and part.status == "ANCHORED" - } + # The settled part lies in the tree its anchor was found in: without the + # repository, attribution wrote dosbox-pure-unleashed's ROMInfo line + # under `source`, a repository that carries no mt32emu.h. + anchored_files: dict[str, str | None] = {} + for part, ok in zip(parts, eligible): + if ok and part.status == "ANCHORED": + anchored_files.setdefault(part.part.path, part.repo) kept = ("ANCHORED", "GONE", "EXTERNAL", "BINARY") return [ - PartResult(part.part, "ANCHORED", None, None, None, []) + PartResult( + part.part, "ANCHORED", None, None, None, [], + repo=anchored_files[part.part.path], + ) if ok and part.status not in kept and part.part.path in anchored_files else part for part, ok in zip(parts, eligible) @@ -1918,7 +1950,7 @@ def build_report( shifts = dominant_shifts([p for _, _, _, parts in staged for p in parts]) for entry_name, ref, citation, parts in staged: - parts = [resolve_by_shift(p, shifts) for p in parts] + parts = refuse_collapsing_moves([resolve_by_shift(p, shifts) for p in parts]) status = worst_status([p.status for p in parts]) report.entries.append(EntryReport( entry_name, ref, status, parts, citation.kind, citation.field diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index dd69ddb3..ab98ce32 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -4158,6 +4158,15 @@ class TestReconcilePerFile(unittest.TestCase): result = profile_sync.reconcile_self_check([anchored, same, other]) self.assertEqual([p.status for p in result], ["ANCHORED", "ANCHORED", "AMBIGUOUS"]) + def test_a_settled_part_keeps_the_repository_of_its_anchor(self): + anchored = PartResult(RefPart("mt32emu.h", 5112, 5112, "5112"), "ANCHORED", + None, None, None, [], repo="schelling/dosbox-pure") + same = PartResult(RefPart("mt32emu.h", 5129, 5129, "5129"), "MOVED", + None, 5112, 5112, [5112]) + result = profile_sync.reconcile_self_check([anchored, same]) + self.assertEqual(result[1].status, "ANCHORED") + self.assertEqual(result[1].repo, "schelling/dosbox-pure") + def test_a_compared_part_is_never_rewritten(self): anchored = PartResult(RefPart("a.c", 5, 5, "5"), "ANCHORED", None, None, None, []) shifted = PartResult(RefPart("a.c", 9, 9, "9"), "SHIFTED", None, 12, 12, []) @@ -4165,6 +4174,24 @@ class TestReconcilePerFile(unittest.TestCase): self.assertEqual(result[1].status, "SHIFTED") +class TestCollapsingMoves(unittest.TestCase): + """A recale never folds two parts of one ref onto the same line.""" + + def test_a_move_onto_a_sibling_part_goes_to_review(self): + sha = PartResult(RefPart("mt32emu.h", 5112, 5112, "upstream mt32emu.h:5112", "upstream"), + "ANCHORED", None, None, None, []) + info = PartResult(RefPart("mt32emu.h", 5129, 5129, "source mt32emu.h:5129", "source"), + "MOVED", None, 5112, 5112, [5112]) + result = profile_sync.refuse_collapsing_moves([sha, info]) + self.assertEqual([p.status for p in result], ["ANCHORED", "AMBIGUOUS"]) + + def test_a_move_to_a_free_line_is_kept(self): + first = PartResult(RefPart("a.c", 5, 5, "a.c:5"), "ANCHORED", None, None, None, []) + moved = PartResult(RefPart("a.c", 9, 9, "a.c:9"), "MOVED", None, 12, 12, [12]) + result = profile_sync.refuse_collapsing_moves([first, moved]) + self.assertEqual(result[1].status, "MOVED") + + class TestRealignFlagMatrix(unittest.TestCase): """--realign-prose applies a flag or refuses it, never swallows it.""" From c3fdfba412958ae1eae0a8e93fca60cf232577b9 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 09:56:25 +0200 Subject: [PATCH 02/10] fix: profile flycast from flyinghead/flycast libretro/flycast now answers as libretro/parallel-dc, a separate core. The buildbot builds flycast from flyinghead/flycast master (libretro-super recipes, cores-linux-x64-generic), so the profile is read again at 34ad8c82 and pinned there. At that revision the Dreamcast boot ROM is dc_boot.bin or dc_bios.bin, the flash is dc_nvmem.bin, arcade platforms read no flat boot ROM, the system font is compiled in, and NAOMI 2 and System SP load naomi2.zip and segasp.zip. Archive members carry the CRC the loader looks up. --- emulators/flycast.yml | 279 +++++++++++++++++++++++++++++------------- 1 file changed, 197 insertions(+), 82 deletions(-) diff --git a/emulators/flycast.yml b/emulators/flycast.yml index c1abd8ac..97e3bf94 100644 --- a/emulators/flycast.yml +++ b/emulators/flycast.yml @@ -1,12 +1,11 @@ emulator: Flycast type: standalone + libretro core_classification: official_port -source: "https://github.com/libretro/flycast" -upstream: "https://github.com/flyinghead/flycast" +source: "https://github.com/flyinghead/flycast" logo: "https://raw.githubusercontent.com/flyinghead/flycast/master/shell/linux/flycast.png" -profiled_date: "2026-03-23" -source_commit: "bde196bfbf541435d0e7d3e3fa91dbd154e7c502" -core_version: "0.1" +profiled_date: "2026-10-21" +source_commit: "34ad8c8262c82db237a8b9cee0d8046d9cdd6f78" +core_version: "Git" display_name: "Sega - Dreamcast/Naomi (Flycast)" cores: - flycast @@ -18,43 +17,47 @@ systems: - sega-naomi - sega-naomi2 - sega-atomiswave + - sega-systemsp notes: | - Flycast has a built-in HLE BIOS (reios) for Dreamcast that can boot most - games without real BIOS files. Arcade systems (NAOMI, Atomiswave) require - MAME-format BIOS ROM archives. + The libretro core is built from flyinghead/flycast, the same tree as the + standalone emulator: the wrapper lives in shell/libretro and is compiled + with -DLIBRETRO=ON. - The libretro port (libretro/flycast, last updated 2025-12-12) is significantly - behind upstream (flyinghead/flycast). Key divergences: - - NAOMI 2 has no separate BIOS entry or platform detection: NAOMI 2 games - run as NAOMI using naomi.zip. Upstream has naomi2.zip with dedicated ROMs. - - System SP is not supported. Upstream has segasp.zip support. - - The n2_ prefix for NAOMI 2 flat boot ROMs is dead code (DC_PLATFORM_NAOMI2 - is never assigned to settings.System in the libretro port). - - Flash search includes legacy names (%flash_wb.bin, %flash.bin, %flash.bin.bin) - that upstream has removed. - - NAOMI flat boot ROM search includes epr-21576d.bin fallback not in upstream. + Flycast has a built-in HLE BIOS (reios) for Dreamcast that boots most + games without a real boot ROM. A short list of product ids forces the + real BIOS (core/emulator.cpp:277-278) and is told "This game requires a + real BIOS" when it is absent (core/emulator.cpp:616-621). Without content, + the core boots the BIOS and fails when none is found + (core/emulator.cpp:601-605). Arcade systems (NAOMI, NAOMI 2, Atomiswave, + System SP) load MAME-format BIOS archives. - BIOS file search uses prefix + name pattern. The libretro port appends "dc/" - to the system directory (core/libretro/libretro.cpp:1972). All files below are relative - to system_dir/dc/. + The libretro port appends "dc/" to the system directory + (shell/libretro/libretro.cpp:2249-2250). All files below are relative to + system_dir/dc/. - The prefix is determined by platform (core/hw/holly/sb_mem.cpp:32-49): - Dreamcast -> dc_ - Dev Unit -> hkt_ - NAOMI -> naomi_ - Atomiswave -> (no prefix, BIOS loaded from awbios.zip) + Only the Dreamcast reads flat files. The prefix is dc_ for Dreamcast + (core/hw/flashrom/nvmem.cpp:35-50), and the boot ROM is searched as + {prefix}boot.bin then {prefix}bios.bin (core/hw/flashrom/nvmem.cpp:304). + Flash is {prefix}nvmem.bin and is created when absent + (core/hw/flashrom/nvmem.cpp:252-256). Arcade platforms return before the + boot ROM search (core/hw/flashrom/nvmem.cpp:300-302), and their flash is a + per-game save file. The system font is a resource compiled into the + binary (core/reios/reios.cpp:761-764). - Boot ROM search pattern (core/hw/holly/sb_mem.cpp:51-68): - {prefix}boot.bin, {prefix}boot.bin.bin, {prefix}bios.bin, {prefix}bios.bin.bin - NAOMI also tries: epr-21576d.bin (core/hw/holly/sb_mem.cpp:59) - Flash/NVRAM search pattern (core/hw/holly/sb_mem.cpp:231): - {prefix}nvmem.bin, {prefix}flash_wb.bin, {prefix}flash.bin, {prefix}flash.bin.bin + Arcade BIOS archives are opened as .zip, then .7z + (core/hw/naomi/naomi_cart.cpp:75-78), first in system_dir/dc, then in + the content directory (shell/libretro/oslib.cpp:118-130). Each ROM inside + is looked up by CRC, then by file name, in the game archive, its parent, + then the BIOS archive (core/hw/naomi/naomi_cart.cpp:89-106). The blob of + the configured region is mapped first, any region otherwise; a game + whose BIOS cannot be loaded aborts (core/hw/naomi/naomi_cart.cpp:196-207). + Games whose bios field is naomi2 run as NAOMI 2 and those whose bios + field is segasp as System SP (core/hw/naomi/naomi_cart.cpp:810-821). - BIOS[] also declares airlbios and naomigd. No entry of Games[] carries - either name in its bios field and naomi_LoadBios is only ever called with - that field or the literal naomi, so neither archive is opened. - ref: core/hw/naomi/naomi_cart.cpp:79,229-240,476-479, core/hw/naomi/naomi_roms.h:79,191 + BIOS[] also declares naomidev and naomigd. No entry of Games[] carries + either name in its bios field, so neither archive is opened. naomi-jp-d + and naomi-ko-h read naomi.zip (core/hw/naomi/naomi_roms.cpp:219-242). files: # ------------------------------------------------------- @@ -62,104 +65,194 @@ files: # ------------------------------------------------------- - name: "dc_boot.bin" path: "dc/dc_boot.bin" - aliases: ["dc_bios.bin", "dc_boot.bin.bin", "dc_bios.bin.bin"] + aliases: ["dc_bios.bin"] system: sega-dreamcast required: false hle_fallback: true size: 2097152 - note: "Dreamcast boot ROM. HLE BIOS (reios) used as fallback. Code searches prefix + boot.bin, boot.bin.bin, bios.bin, bios.bin.bin sequentially." - source_ref: "upstream core/hw/holly/sb_mem.cpp:219, 55-57" + note: "Dreamcast boot ROM. reios is used when it is absent, except for the product ids that force the real BIOS. Searched as dc_boot.bin then dc_bios.bin." + source_ref: "core/hw/flashrom/nvmem.cpp:298-316, core/emulator.cpp:613-622" - name: "dc_nvmem.bin" path: "dc/dc_nvmem.bin" - aliases: ["dc_flash_wb.bin", "dc_flash.bin", "dc_flash.bin.bin"] system: sega-dreamcast required: false hle_fallback: true size: 131072 - note: "Dreamcast flash memory / NVRAM. Created if not found. Code searches prefix + nvmem.bin, flash_wb.bin, flash.bin, flash.bin.bin sequentially." - source_ref: "upstream core/hw/holly/sb_mem.cpp:231, 196-213" - - - name: "font.bin" - path: "dc/font.bin" - system: sega-dreamcast - required: false - note: "Dreamcast system font for HLE BIOS text rendering. Built-in font used as fallback." - source_ref: "upstream core/reios/reios.cpp:737-753" + note: "Dreamcast flash memory. Created with factory settings when absent, written back on exit." + source_ref: "core/hw/flashrom/nvmem.cpp:252-256, core/hw/flashrom/nvmem.cpp:321-322" # ------------------------------------------------------- # Sega NAOMI # ------------------------------------------------------- - - name: "naomi_boot.bin" - path: "dc/naomi_boot.bin" - aliases: ["naomi_bios.bin", "naomi_boot.bin.bin", "naomi_bios.bin.bin", "epr-21576d.bin"] - system: sega-naomi - required: false - size: 2097152 - note: "NAOMI boot ROM (flat binary). Alternative to naomi.zip. epr-21576d.bin is searched without prefix." - source_ref: "upstream core/hw/holly/sb_mem.cpp:219, 58-59" - - name: "naomi.zip" path: "dc/naomi.zip" system: sega-naomi required: true - note: > - NAOMI system BIOS archive (MAME format). Contains region-specific - BIOS ROMs: epr-21576h.ic27 (Japan), epr-21577h.ic27 (USA), - epr-21578h.ic27 (Export), epr-21579d.ic27 (Korea). - Also used for NAOMI 2 games in the libretro port (no separate naomi2.zip). - source_ref: "source core/hw/naomi/naomi_roms.h:133-188" + category: bios_zip + note: "NAOMI system BIOS archive. Games with no bios field or with naomi, naomi-jp-d or naomi-ko-h read it and abort without it." + source_ref: "core/hw/naomi/naomi_roms.cpp:86-144, core/hw/naomi/naomi_roms.cpp:219-242, core/hw/naomi/naomi_cart.cpp:196-207" contents: - name: "epr-21576h.ic27" + description: Japan size: 2097152 + crc32: "d4895685" + - name: "epr-21576g.ic27" + description: Japan + size: 2097152 + crc32: "d2a1c6bf" - name: "epr-21578h.ic27" + description: Export size: 2097152 + crc32: "7b452946" + - name: "epr-21578g.ic27" + description: Export + size: 2097152 + crc32: "55413214" - name: "epr-21577h.ic27" + description: USA size: 2097152 + crc32: "fdf17452" + - name: "epr-21577g.ic27" + description: USA + size: 2097152 + crc32: "25f64af7" - name: "epr-21579d.ic27" + description: Korea size: 2097152 + crc32: "33513691" + - name: "epr-21576h_multi.ic27" + description: "Multi-region, the BIOS of naomi-ko-h" + size: 2097152 + crc32: "cce01f1f" + - name: "epr-21576d.ic27" + description: "Japan, the BIOS of naomi-jp-d" + size: 2097152 + crc32: "3b2afa7b" + + - name: "airlbios.zip" + path: "dc/airlbios.zip" + system: sega-naomi + required: false + category: bios_zip + note: "Airline Pilots Deluxe BIOS. Required by the two Airline Pilots entries." + source_ref: "core/hw/naomi/naomi_roms.cpp:29-37, core/hw/naomi/naomi_roms.cpp:1000, core/hw/naomi/naomi_roms.cpp:1032" + contents: + - name: "epr-21802.ic27" + description: Export + size: 2097152 + crc32: "a77c6b1c" + - name: "epr-21801.ic27" + description: USA + size: 2097152 + crc32: "a21bef24" - name: "f355bios.zip" path: "dc/f355bios.zip" system: sega-naomi required: false - note: "Ferrari F355 Challenge BIOS. Japan/USA/Export variants." - source_ref: "source core/hw/naomi/naomi_roms.h:96-103" + category: bios_zip + note: "Ferrari F355 Challenge twin BIOS. Required by the three twin entries." + source_ref: "core/hw/naomi/naomi_roms.cpp:49-59, core/hw/naomi/naomi_roms.cpp:1887, core/hw/naomi/naomi_roms.cpp:1926, core/hw/naomi/naomi_roms.cpp:1965" contents: - name: "epr-22851.ic27" + description: Export size: 2097152 + crc32: "62483677" - name: "epr-22850.ic27" + description: USA size: 2097152 + crc32: "28aa539d" - name: "epr-22849.ic27" + description: Japan size: 2097152 + crc32: "121e009c" - name: "f355dlx.zip" path: "dc/f355dlx.zip" system: sega-naomi required: false - note: "Ferrari F355 Challenge Deluxe BIOS. Japan/USA/Export variants." - source_ref: "source core/hw/naomi/naomi_roms.h:105-119" + category: bios_zip + note: "Ferrari F355 Challenge deluxe BIOS. Required by f355." + source_ref: "core/hw/naomi/naomi_roms.cpp:60-74, core/hw/naomi/naomi_roms.cpp:1843" contents: - name: "epr-21864.ic27" + description: Export size: 2097152 + crc32: "12ed7c66" - name: "epr-21863.ic27" + description: USA size: 2097152 + crc32: "0615a4d1" - name: "epr-21862.ic27" + description: Japan size: 2097152 + crc32: "1f630716" - name: "hod2bios.zip" path: "dc/hod2bios.zip" system: sega-naomi required: false - note: "House of the Dead 2 BIOS. Japan/USA/Export variants." - source_ref: "source core/hw/naomi/naomi_roms.h:121-131" + category: bios_zip + note: "The House of the Dead 2 BIOS. Required by the four hotd2 entries." + source_ref: "core/hw/naomi/naomi_roms.cpp:75-85, core/hw/naomi/naomi_roms.cpp:2203, core/hw/naomi/naomi_roms.cpp:2241, core/hw/naomi/naomi_roms.cpp:2279, core/hw/naomi/naomi_roms.cpp:2317" contents: - name: "epr-21331.ic27" + description: Export size: 2097152 + crc32: "065f8500" - name: "epr-21330.ic27" + description: USA size: 2097152 + crc32: "9e3bfa1b" - name: "epr-21329.ic27" + description: Japan size: 2097152 + crc32: "d99e5b9b" + + # ------------------------------------------------------- + # Sega NAOMI 2 + # ------------------------------------------------------- + - name: "naomi2.zip" + path: "dc/naomi2.zip" + system: sega-naomi2 + required: true + category: bios_zip + note: "NAOMI 2 system BIOS archive. Every game whose bios field is naomi2 aborts without it." + source_ref: "core/hw/naomi/naomi_roms.cpp:182-202, core/hw/naomi/naomi_cart.cpp:818-819, core/hw/naomi/naomi_cart.cpp:196-207" + contents: + - name: "epr-23605c.ic27" + description: Japan + size: 2097152 + crc32: "297ea6ed" + - name: "epr-23605b.ic27" + description: Japan + size: 2097152 + crc32: "3a3242d4" + - name: "epr-23607c.ic27" + description: USA + size: 2097152 + crc32: "750e254b" + - name: "epr-23607b.ic27" + description: USA + size: 2097152 + crc32: "f308c5e9" + - name: "epr-23608c.ic27" + description: Export + size: 2097152 + crc32: "6ef1dd8e" + - name: "epr-23608b.ic27" + description: Export + size: 2097152 + crc32: "a554b1e3" + - name: "epr-23609b.ic27" + description: Korea + size: 2097152 + crc32: "99e3751f" + - name: "epr-23605c_multi.ic27" + description: Multi-region + size: 2097152 + crc32: "353fdbcd" # ------------------------------------------------------- # Sega Atomiswave @@ -168,20 +261,36 @@ files: path: "dc/awbios.zip" system: sega-atomiswave required: true - note: "Atomiswave system BIOS archive (MAME format). Contains bios0.ic23 (Sammy, 128 KB)." - source_ref: "upstream core/hw/naomi/naomi_roms.h:87-94" + category: bios_zip + note: "Atomiswave system BIOS archive. The first 64 KB of bios0.ic23 are mapped. Every Atomiswave game aborts without it." + source_ref: "core/hw/naomi/naomi_roms.cpp:38-48, core/hw/naomi/naomi_cart.cpp:196-207" contents: - name: "bios0.ic23" size: 131072 + crc32: "719b2b0b" # ------------------------------------------------------- - # Not supported by libretro port + # Sega System SP # ------------------------------------------------------- - # naomi2.zip: no BIOS[] entry in libretro fork (naomi_roms.h). NAOMI 2 games - # use the "naomi" BIOS. naomi_cart_GetSystemType() never returns - # DC_PLATFORM_NAOMI2. Upstream has full naomi2.zip support. - # - # segasp.zip: no System SP support in libretro fork. Upstream has full support. + - name: "segasp.zip" + path: "dc/segasp.zip" + system: sega-systemsp + required: true + category: bios_zip + note: "System SP BIOS archive. The USA and Export regions also load a default motherboard EEPROM from it. Every game whose bios field is segasp aborts without it." + source_ref: "core/hw/naomi/naomi_roms.cpp:203-218, core/hw/naomi/naomi_cart.cpp:820-821, core/hw/naomi/naomi_cart.cpp:126-139" + contents: + - name: "epr-24328a.ic50" + size: 2097152 + crc32: "03ec3805" + - name: "mb_eeprom_us.ic54s" + description: USA + size: 128 + crc32: "4186d7ab" + - name: "mb_eeprom_exp.ic54s" + description: Export + size: 128 + crc32: "947ddfad" platform_details: dreamcast: @@ -189,26 +298,32 @@ platform_details: flash_size: 131072 ram_size: 16777216 hle_available: true - source_ref: "source core/nullDC.cpp:333-345" + source_ref: "core/emulator.cpp:456-462" naomi: bios_size: 2097152 sram_size: 32768 ram_size: 33554432 hle_available: false - source_ref: "source core/nullDC.cpp:346-354" + source_ref: "core/emulator.cpp:463-469" naomi2: bios_size: 2097152 sram_size: 32768 ram_size: 33554432 hle_available: false - note: "Treated as NAOMI in the libretro port. Separate platform only in upstream." - source_ref: "source core/nullDC.cpp:355-363" + source_ref: "core/emulator.cpp:470-477" atomiswave: bios_size: 131072 sram_size: 131072 ram_size: 16777216 hle_available: false - source_ref: "source core/nullDC.cpp:364-375" + source_ref: "core/emulator.cpp:478-484" + + systemsp: + bios_size: 2097152 + sram_size: 131072 + ram_size: 33554432 + hle_available: false + source_ref: "core/emulator.cpp:485-491" From 56eebb849d9de23c5eb8c3bda5e0a14bb8aab472 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 09:58:33 +0200 Subject: [PATCH 03/10] fix: profile ppsspp from hrydgard/ppsspp libretro/ppsspp answers as libretro-mirrors/ppsspp-old, a 2020 tree frozen in 2022. The buildbot builds ppsspp from hrydgard/ppsspp master, whose libretro/ directory holds the wrapper, so the profile is read again at 58935bbf and pinned there. The asset directory, PPGe atlas and font lookup are cited where they sit now. The notes record the NAND under the save directory that a disc's firmware updater fills, and the modules it replaces. --- emulators/ppsspp.yml | 49 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/emulators/ppsspp.yml b/emulators/ppsspp.yml index f8c95907..7aa43c55 100644 --- a/emulators/ppsspp.yml +++ b/emulators/ppsspp.yml @@ -1,10 +1,9 @@ emulator: PPSSPP type: standalone + libretro core_classification: official_port -source: "https://github.com/libretro/ppsspp" -upstream: "https://github.com/hrydgard/ppsspp" -profiled_date: "2026-03-24" -source_commit: "7b4ddb426bbe9e287bb7f19b0cfaebb4ea0d41d8" +source: "https://github.com/hrydgard/ppsspp" +profiled_date: "2026-10-21" +source_commit: "58935bbf282ddd446cc490574c2c09b9c8f8b470" core_version: "Git" display_name: "Sony - PlayStation Portable (PPSSPP)" cores: @@ -19,22 +18,32 @@ data_directories: installed_on: [batocera, emudeck, lakka, recalbox, retrobat, retrodeck, retropie] mode: libretro destination: "" - source_ref: "libretro/libretro.cpp:537, 546, 549" + source_ref: "libretro/libretro.cpp:1216-1225, libretro/libretro.cpp:1271" notes: | Full HLE emulator. No Sony firmware or BIOS required. - All PSP kernel modules (flash0:/kd/*.prx) are reimplemented in C++. - Libretro core loads assets from system/PPSSPP/ via VFS. - Assets include replacement PGF fonts (18 files in flash0/font/), + The libretro core is built from hrydgard/ppsspp, the tree of the + standalone emulator, with its wrapper in libretro/. + Libretro core loads assets from system/PPSSPP/ via VFS + (libretro/libretro.cpp:1216-1225, 1271) and warns that core system files + are missing when compat.ini is absent (libretro/libretro.cpp:1229-1261). + Assets include replacement PGF fonts (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. + Fonts are read from the game disc, then from flash0:/font of the NAND, + then from flash0/font/ in system/PPSSPP/ (Core/HLE/sceFont.cpp:1026-1048). + Without any of them the font library holds no internal font and + sceFontOpen returns SCE_FONT_ERROR_INVALID_PARAMETER to the game + (Core/HLE/sceFont.cpp:1197-1199), 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:252-255). + A real firmware is optional. The NAND is /PSP/NAND + (Core/Util/PathUtil.cpp:144-145), which the libretro core places under + the save directory (libretro/libretro.cpp:1265, 1269). On boot, a game + disc carrying a newer firmware updater than the installed one is + unpacked into it (Core/System.cpp:575-578). Its flash0:/font, + kd/libmp4.prx, kd/mp4msv.prx and kd/mpeg.prx replace the HLE modules + when present (Core/HLE/HLE.cpp:408-446). PSP_DEFAULT_FIRMWARE = 660 (Core/ConfigValues.h:40). files: @@ -44,8 +53,8 @@ files: path: "PPSSPP/ppge_atlas.zim" description: "PPGe dialog texture atlas for save/load dialogs, on-screen keyboard, system UI" required: false - source_ref: "source Core/Util/PPGeDraw.cpp:227-228" - note: "PanicAlert if missing. System dialogs render without graphics but core continues running. Batocera, Recalbox, Lakka, RetroPie, RetroBat, EmuDeck and RetroDECK install the assets folder where their core reads it." + source_ref: "Core/Util/PPGeDraw.cpp:252-255" + note: "Logged as an error if missing. System dialogs render without graphics but core continues running. Batocera, Recalbox, Lakka, RetroPie, RetroBat, EmuDeck and RetroDECK install the assets folder where their core reads it." - name: "ppge_atlas.meta" installed_on: [batocera, emudeck, lakka, recalbox, retrobat, retrodeck, retropie] @@ -53,7 +62,7 @@ files: path: "PPSSPP/ppge_atlas.meta" description: "PPGe atlas metadata (glyph positions, UV coords)" required: false - source_ref: "source Core/Util/PPGeDraw.cpp:235-237" + source_ref: "Core/Util/PPGeDraw.cpp:257-263" note: "Loaded after ppge_atlas.zim. Without it, dialog UI has no glyph layout. Batocera, Recalbox, Lakka, RetroPie, RetroBat, EmuDeck and RetroDECK install the assets folder where their core reads it." - name: "ppge_atlas.zim" @@ -64,7 +73,7 @@ files: size: 666530 sha1: "30a33f3651f8e1b0967a5dfe6ff714baebcce41a" bundled: true - source_ref: "source Core/Util/PPGeDraw.cpp:227-228" + source_ref: "Core/Util/PPGeDraw.cpp:252-255" note: "Shipped in assets/ of the PPSSPP 1.20.4 Windows zip, which the standalone reads it from." - name: "ppge_atlas.meta" @@ -75,5 +84,5 @@ files: size: 50242 sha1: "ab398f667d6fd778859307c105fe16388b8fdf63" bundled: true - source_ref: "source Core/Util/PPGeDraw.cpp:235-237" + source_ref: "Core/Util/PPGeDraw.cpp:257-263" note: "Shipped in assets/ of the PPSSPP 1.20.4 Windows zip, beside ppge_atlas.zim." From 0f45cbc97dcbd087dd4b38dd25babddbbc4c9c00 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 09:59:07 +0200 Subject: [PATCH 04/10] fix: record the pin blastem's tmss prose names The tmss.md note lived under three pins, so profile_sync could not tell which revision its three citations describe and refused any bump. At 1e0de94d libblastem.c:514-529 is the tmss.md and bios_MD.bin lookup, genesis.c:3036-3051 the fatal_error without a TMSS ROM and 3054-3065 the mirror loop, as the note says. prose_written_at names that pin. --- emulators/blastem.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/emulators/blastem.yml b/emulators/blastem.yml index 10a0f005..fa5d09a8 100644 --- a/emulators/blastem.yml +++ b/emulators/blastem.yml @@ -5,6 +5,7 @@ source: "https://github.com/libretro/blastem" upstream: "https://www.retrodev.com/blastem/" profiled_date: "2026-10-20" source_commit: "1e0de94dc7e669c0925a22c0fccf6cdc837af0a0" +prose_written_at: "1e0de94dc7e669c0925a22c0fccf6cdc837af0a0" core_version: "1.0.1-pre" display_name: "Sega - Mega Drive - Genesis (BlastEm)" cores: From 99c9993c170340f56cac62ff985fc75f74840015 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:02:32 +0200 Subject: [PATCH 05/10] fix: profile stella from stella-emu/stella The buildbot builds the stella core from stella-emu/stella master (src/os/libretro), not from stella2014 code, and stella2023 claimed the stella name. stella.yml now documents that tree at 2c3d7023: the KidVid tapes are read from a stella folder under the save directory, loose or in KidVidAudio.zip, and played. stella2023 keeps its own name only. --- emulators/stella.yml | 91 +++++++++++++++++++++++++++++---- emulators/stella2023.yml | 1 - tests/test_audit_regressions.py | 7 +-- 3 files changed, 84 insertions(+), 15 deletions(-) diff --git a/emulators/stella.yml b/emulators/stella.yml index eeab8549..cb53f71c 100644 --- a/emulators/stella.yml +++ b/emulators/stella.yml @@ -1,18 +1,87 @@ emulator: Stella -type: alias -alias_of: stella2014 -source: "https://github.com/libretro/stella-libretro" -profiled_date: "2026-03-25" -core_version: "3.9.3" +type: standalone + libretro +core_classification: official_port +source: "https://github.com/stella-emu/stella" +profiled_date: "2026-10-21" +source_commit: "2c3d7023e9136f75c789803b44f119d8749dc104" +core_version: "8.0_pre" display_name: "Atari - 2600 (Stella)" cores: - stella systems: - atari-2600 -note: | - Identical codebase to stella2014-libretro. Both repos share the same HEAD - commit and produce a binary reporting library_name "Stella 2014". The - stella_libretro.info lists display_version "6.6", and the binary reports - 3.9.3. See stella2014.yml for firmware requirements - and KidVid audio files. +notes: | + The libretro core is built from stella-emu/stella, the tree of the + standalone emulator, with its wrapper in src/os/libretro. The binary + reports library_name "Stella" (src/os/libretro/StellaLIBRETRO.hxx:59) + and the version of src/common/Version.hxx:35. The stella_libretro.info + lists display_version "6.6". + + The Atari 2600 has no BIOS ROM: TIA, RIOT and 6507 CPU are emulated in + software. The SuperCharger (Starpath) BIOS is replaced by built-in code + (ourDummyROMCode in src/emucore/CartAR.cxx:635). + + The libretro core reads the system directory (src/os/libretro/libretro.cxx:1716-1724) + but nothing reads the path it stores. Its base directory is a stella + folder under the save directory, or ./ without one + (src/os/libretro/OSystemLIBRETRO.hxx:71-79). The standalone base + directory is the configuration directory, $XDG_CONFIG_HOME/stella on + Linux and the application data folder on Windows + (src/os/unix/OSystemUNIX.cxx:79, src/os/windows/OSystemWINDOWS.cxx:32). + + KidVid Voice Module tapes: the tape the game selects and KVSHARED.WAV are + looked up in KidVidAudio.zip in the base directory, then loose in the + base directory, and both must be present (src/emucore/KidVid.cxx:255-268). + The archive holds the same seven files listed below. + The libretro build compiles with SOUND_SUPPORT and ZIP_SUPPORT + (src/os/libretro/Makefile:599) and plays them (src/os/libretro/SoundLIBRETRO.hxx:127-133). + Without them the game runs on a timing-based fallback with a beep + (src/emucore/KidVid.cxx:343-348). + + EEPROM save data for AtariVox and SaveKey peripherals is managed as + NVRAM, not user-supplied. + +files: + - name: KVS1.WAV + description: "KidVid Voice Module audio tape 1 (Smurfs Save the Day)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVS2.WAV + description: "KidVid Voice Module audio tape 2 (Smurfs Save the Day)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVS3.WAV + description: "KidVid Voice Module audio tape 3 (Smurfs Save the Day)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVB1.WAV + description: "KidVid Voice Module audio tape 1 (Berenstain Bears)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVB2.WAV + description: "KidVid Voice Module audio tape 2 (Berenstain Bears)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVB3.WAV + description: "KidVid Voice Module audio tape 3 (Berenstain Bears)" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:246-248, src/emucore/KidVid.cxx:255-268" + - name: KVSHARED.WAV + description: "KidVid Voice Module shared audio samples" + required: false + load_from: {libretro: save_dir, standalone: config_dir} + category: game_data + source_ref: "src/emucore/KidVid.cxx:255-268, src/emucore/KidVid.cxx:329-331" diff --git a/emulators/stella2023.yml b/emulators/stella2023.yml index 9551e64b..afc3d7ac 100644 --- a/emulators/stella2023.yml +++ b/emulators/stella2023.yml @@ -9,7 +9,6 @@ core_version: "7.0_pre" display_name: "Atari - 2600 (Stella 2023)" cores: - stella2023 - - stella systems: - atari_2600 diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index d12efd68..1753b1bb 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -3138,15 +3138,16 @@ class TheDatabaseCacheIsWrittenWhole(unittest.TestCase): class KidVidTapesStayWithTheContent(unittest.TestCase): """Stella opens its KidVid tapes by bare name (stella2014, from the working directory) or from its base directory (stella2023, the content - folder): never the system directory. Without load_from every Linux pack - put about 68 MB of WAVs at the BIOS root, in two cases.""" + folder, and stella, a folder under the save directory): never the system + directory. Without load_from every Linux pack put about 68 MB of WAVs at + the BIOS root, in two cases.""" def test_no_pack_places_them_in_the_system_directory(self): from scripts.common import load_emulator_profiles from scripts.validation import outside_gap_scope profiles = load_emulator_profiles(str(ROOT / "emulators")) - for name in ("stella2014", "stella2023"): + for name in ("stella", "stella2014", "stella2023"): tapes = [f for f in profiles[name]["files"] if f["name"].lower().endswith(".wav")] with self.subTest(profile=name): From 4e41fad9b632d6b4deb901d8f8c412d84a7373e3 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:04:58 +0200 Subject: [PATCH 06/10] fix: give bios_U.sms every export territory sms_cart_region_detect returns REGION_USA for any cartridge outside its CRC list whose header is not Japanese, so Genesis Plus GX and its two forks open bios_U.sms for Australian and Brazilian cartridges as well. Tagged north-america and europe only, --region australia,japan dropped it from the pack. The tag now adds latin-america and oceania. --- emulators/genesis_plus_gx.yml | 4 ++-- emulators/genesis_plus_gx_expanded.yml | 4 ++-- emulators/genesis_plus_gx_wide.yml | 4 ++-- tests/test_region.py | 4 ++++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/emulators/genesis_plus_gx.yml b/emulators/genesis_plus_gx.yml index f7b87bd7..042fc165 100644 --- a/emulators/genesis_plus_gx.yml +++ b/emulators/genesis_plus_gx.yml @@ -63,9 +63,9 @@ files: # ------------------------------------------------------- - name: bios_U.sms system: sega-mastersystem - region: [north-america, europe] + region: [north-america, latin-america, europe, oceania] required: false - note: "Master System (NTSC-U) boot ROM. Snail maze game built in. REGION_USA is the default of sms_cart_region_detect for any export header outside the PAL CRC list, so European cartridges load it too (core/cart_hw/sms_cart.c:831-874)." + note: "Master System (NTSC-U) boot ROM. Snail maze game built in. REGION_USA is the default of sms_cart_region_detect for any export header outside the PAL CRC list, so European, Australian and Brazilian cartridges outside that list load it too (core/cart_hw/sms_cart.c:831-874)." source_ref: "source core/loadrom.c:511" - name: bios_E.sms diff --git a/emulators/genesis_plus_gx_expanded.yml b/emulators/genesis_plus_gx_expanded.yml index 6baed6b5..18e54e52 100644 --- a/emulators/genesis_plus_gx_expanded.yml +++ b/emulators/genesis_plus_gx_expanded.yml @@ -68,9 +68,9 @@ files: - name: bios_U.sms system: sega-mastersystem - region: [north-america, europe] + region: [north-america, latin-america, europe, oceania] required: false - note: "Master System (NTSC-U) boot ROM, loaded for REGION_USA when the bios option is on." + note: "Master System (NTSC-U) boot ROM, loaded for REGION_USA when the bios option is on. REGION_USA is the default of sms_cart_region_detect for any export header outside its CRC list, so European, Australian and Brazilian cartridges outside that list load it too (core/cart_hw/sms_cart.c:865-866)." source_ref: "source core/loadrom.c:510" - name: bios_E.sms diff --git a/emulators/genesis_plus_gx_wide.yml b/emulators/genesis_plus_gx_wide.yml index f97100fd..ae9d229b 100644 --- a/emulators/genesis_plus_gx_wide.yml +++ b/emulators/genesis_plus_gx_wide.yml @@ -49,9 +49,9 @@ files: - name: bios_U.sms system: sega-mastersystem - region: [north-america, europe] + region: [north-america, latin-america, europe, oceania] required: false - note: "REGION_USA is the default of sms_cart_region_detect for any export header outside the PAL CRC list, so European cartridges load it too (core/cart_hw/sms_cart.c:863-864)." + note: "REGION_USA is the default of sms_cart_region_detect for any export header outside the PAL CRC list, so European, Australian and Brazilian cartridges outside that list load it too (core/cart_hw/sms_cart.c:863-864)." source_ref: "source core/loadrom.c:512" - name: bios_E.sms diff --git a/tests/test_region.py b/tests/test_region.py index 0e54c0c9..0068e364 100644 --- a/tests/test_region.py +++ b/tests/test_region.py @@ -919,6 +919,10 @@ class RegionalRequestsKeepWhatTheCodeLoads(unittest.TestCase): ("bizhawk", ["north-america"], "DSi_Nand_USA.bin"), ("bizhawk", ["oceania"], "DSi_Nand_AUS.bin"), ("bizhawk", ["china", "japan"], "DSi_Nand_CHN.bin"), + ("genesis_plus_gx", ["australia", "japan"], "bios_U.sms"), + ("genesis_plus_gx", ["brazil", "japan"], "bios_U.sms"), + ("genesis_plus_gx_wide", ["australia", "japan"], "bios_U.sms"), + ("genesis_plus_gx_expanded", ["brazil", "japan"], "bios_U.sms"), ) def test_each_request_keeps_its_file(self): From 10dc9a11acf66c9544221ca229456360ea3fdb32 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:12:07 +0200 Subject: [PATCH 07/10] feat: accept ISO country codes for --region jp, us, kr and gb were aliases but au was unknown, and the first spelling offered for it was auto, which means world. Every territory of the region tree now answers to its ISO 3166-1 code, in the build scripts and in the installer, whose SHA-256 is pinned again. --- install.ps1 | 2 +- install.py | 24 ++++++++++++++++++++++++ install.sh | 2 +- scripts/region.py | 28 +++++++++++++++++++++++++++- tests/test_region.py | 18 ++++++++++++++++++ wiki/advanced-usage.md | 5 +++-- 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/install.ps1 b/install.ps1 index f67d62ec..5c41787d 100644 --- a/install.ps1 +++ b/install.ps1 @@ -11,7 +11,7 @@ $ErrorActionPreference = "Stop" $defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" - $defaultInstallSha256 = "1cf3bd0d3985e3a728513be75cb80682fe1e7a9224da6437e8f1cd9b2a3eedb1" + $defaultInstallSha256 = "3f6f906ede89a0a6c350a1f85f668a213031ec8e84215595cdbd160c22ed3352" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index 4e3581a9..249846ce 100644 --- a/install.py +++ b/install.py @@ -138,6 +138,30 @@ REGION_ALIASES: dict[str, str] = { "korea": "south-korea", "auto": WORLD_REGION, "gb": "uk", + "ca": "canada", + "br": "brazil", + "mx": "mexico", + "ar": "argentina", + "fr": "france", + "de": "germany", + "it": "italy", + "es": "spain", + "nl": "netherlands", + "pt": "portugal", + "gr": "greece", + "pl": "poland", + "ru": "russia", + "se": "sweden", + "no": "norway", + "dk": "denmark", + "fi": "finland", + "cn": "china", + "tw": "taiwan", + "hk": "hong-kong", + "sg": "singapore", + "in": "india", + "au": "australia", + "nz": "new-zealand", } AREA_TERRITORIES: dict[str, frozenset] = { "asia-ntsc": frozenset({"taiwan"}), diff --git a/install.sh b/install.sh index c5c3ec4a..199d31e1 100755 --- a/install.sh +++ b/install.sh @@ -18,7 +18,7 @@ esac TEMP_INSTALLER="" TEMP_DIRECTORY="" DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" -DEFAULT_INSTALL_SHA256="1cf3bd0d3985e3a728513be75cb80682fe1e7a9224da6437e8f1cd9b2a3eedb1" +DEFAULT_INSTALL_SHA256="3f6f906ede89a0a6c350a1f85f668a213031ec8e84215595cdbd160c22ed3352" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/scripts/region.py b/scripts/region.py index a299a8a0..bb7cfaf9 100644 --- a/scripts/region.py +++ b/scripts/region.py @@ -64,7 +64,9 @@ _PARENT: dict[str, str] = { REGIONS: frozenset[str] = frozenset({WORLD} | set(REGION_TREE) | set(_PARENT)) -# Accepted on the CLI and for legacy profile values. +# Accepted on the CLI and for legacy profile values. Every territory also +# answers to its ISO 3166-1 code: `au` alone was unknown, and the closest +# spelling offered first was `auto`, which means world. ALIASES: dict[str, str] = { "jp": "japan", "ntsc-j": "japan", @@ -78,6 +80,30 @@ ALIASES: dict[str, str] = { "korea": "south-korea", "auto": WORLD, "gb": "uk", + "ca": "canada", + "br": "brazil", + "mx": "mexico", + "ar": "argentina", + "fr": "france", + "de": "germany", + "it": "italy", + "es": "spain", + "nl": "netherlands", + "pt": "portugal", + "gr": "greece", + "pl": "poland", + "ru": "russia", + "se": "sweden", + "no": "norway", + "dk": "denmark", + "fi": "finland", + "cn": "china", + "tw": "taiwan", + "hk": "hong-kong", + "sg": "singapore", + "in": "india", + "au": "australia", + "nz": "new-zealand", } diff --git a/tests/test_region.py b/tests/test_region.py index 0068e364..523951a1 100644 --- a/tests/test_region.py +++ b/tests/test_region.py @@ -1048,6 +1048,24 @@ class UnknownRegionSaysWhatToType(unittest.TestCase): self.assertIn("Short forms:", str(caught.exception)) +class CountryCodesNameTheirTerritory(unittest.TestCase): + """`au` was unknown while `jp`, `us`, `kr` and `gb` were aliases, and the + first spelling offered for it was `auto`, which means world.""" + + def test_au_is_australia(self): + self.assertEqual(region.parse_requested("au,jp"), ["australia", "japan"]) + + def test_every_territory_answers_to_a_two_letter_code(self): + areas = set(region.AREA_TERRITORIES) + territories = { + member for members in region.REGION_TREE.values() for member in members + } - areas + coded = { + target for alias, target in region.ALIASES.items() if len(alias) == 2 + } | {slug for slug in territories if len(slug) == 2} + self.assertEqual(territories - coded, set()) + + class GenesisPlusGxUsBiosServesEurope(unittest.TestCase): """sms_cart_region_detect returns REGION_USA for any export header diff --git a/wiki/advanced-usage.md b/wiki/advanced-usage.md index 0379e491..27ad6818 100644 --- a/wiki/advanced-usage.md +++ b/wiki/advanced-usage.md @@ -76,8 +76,9 @@ fall back to Japan. It does not mean "keep all three": when a US BIOS exists for a system, the European and Japanese ones are dropped. Accepted names are territory slugs (`japan`, `north-america`, `europe`, -`south-korea`, `taiwan`, `brazil`, `france`...) plus short aliases (`jp`, `us`, -`eu`, `kr`) and the signal spellings (`ntsc-j`, `ntsc-u`, `pal`). Territories +`south-korea`, `taiwan`, `brazil`, `france`...) plus short aliases (`us`, `eu`, +and the ISO 3166 code of each territory: `jp`, `kr`, `au`, `br`, `fr`...) and +the signal spellings (`ntsc-j`, `ntsc-u`, `pal`). Territories nest, so `--region europe` keeps a BIOS declared `[france]`, and `--region france` keeps one declared `[europe]`. From fe3236ad970af30563ff41203a75534c0775c933 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:13:22 +0200 Subject: [PATCH 08/10] fix: let the NTSC-U IPL answer Latin America Dolphin and its forks map the Brazilian disc country code B, and the SYSCONF countries of the Americas, to NTSC-U (DiscIO/Enums.cpp), whose boot ROM is read from GC/USA. Tagged north-america alone, the IPL a Brazilian disc boots left a --region brazil,europe pack. GC/USA/IPL.bin in six profiles and triforce's IPL_TRI.bin now carry latin-america. --- emulators/dolphin-mmjr.yml | 4 ++-- emulators/dolphin-mmjr2.yml | 4 ++-- emulators/dolphin.yml | 4 ++-- emulators/ishiiruka.yml | 4 ++-- emulators/primehack.yml | 4 ++-- emulators/triforce.yml | 6 +++--- tests/test_region.py | 7 +++++++ 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/emulators/dolphin-mmjr.yml b/emulators/dolphin-mmjr.yml index d9c5a874..52189e58 100644 --- a/emulators/dolphin-mmjr.yml +++ b/emulators/dolphin-mmjr.yml @@ -83,13 +83,13 @@ files: system: nintendo-gamecube required: false hle_fallback: true - region: [north-america] + region: [north-america, latin-america] size: 2097152 crc32: ["6dac1f2a", "d5e6feea", "86573808", "667d0b64"] validation: [crc32] on_mismatch: warn description: "GameCube boot ROM, NTSC-U directory" - note: "Read whole into a 2 MiB buffer with no size check, then descrambled from 0x100 for 0x1afe00 bytes. The crc32 gate runs when the IPL itself is booted, and the four non-PAL dumps pass here without complaint." + note: "Read whole into a 2 MiB buffer with no size check, then descrambled from 0x100 for 0x1afe00 bytes. The crc32 gate runs when the IPL itself is booted, and the four non-PAL dumps pass here without complaint. Discs with the Brazilian country code B map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:184-186)." source_ref: "source Source/Core/Core/ConfigManager.cpp:861-868, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:99-112, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.h:43, source Source/Core/Core/Boot/Boot.cpp:296-330" - name: IPL.bin diff --git a/emulators/dolphin-mmjr2.yml b/emulators/dolphin-mmjr2.yml index fcce0ee4..82acc01a 100644 --- a/emulators/dolphin-mmjr2.yml +++ b/emulators/dolphin-mmjr2.yml @@ -119,13 +119,13 @@ files: system: nintendo-gamecube required: false hle_fallback: true - region: [north-america] + region: [north-america, latin-america] size: 2097152 crc32: ["6dac1f2a", "d5e6feea", "86573808", "667d0b64"] validation: [crc32] on_mismatch: warn description: "GameCube boot ROM, NTSC-U directory" - note: "Read whole into a 2 MiB buffer with no size check, then descrambled from 0x100 for 0x1afe00 bytes. The crc32 gate runs when the IPL itself is booted and only warns: the four non-PAL dumps, the Brazilian MPAL one included, pass here without complaint." + note: "Read whole into a 2 MiB buffer with no size check, then descrambled from 0x100 for 0x1afe00 bytes. The crc32 gate runs when the IPL itself is booted and only warns: the four non-PAL dumps, the Brazilian MPAL one included, pass here without complaint. Discs with the Brazilian country code B and SYSCONF countries of the Americas map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:172-173, 223-225)." source_ref: "source Source/Core/Core/Config/MainSettings.cpp:594-600, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:105-113, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.h:43, upstream Source/Core/Core/Boot/Boot.cpp:408-442, source Source/Core/Core/Boot/Boot.cpp:444-449" - name: IPL.bin diff --git a/emulators/dolphin.yml b/emulators/dolphin.yml index f7a1a468..5c80a76a 100644 --- a/emulators/dolphin.yml +++ b/emulators/dolphin.yml @@ -41,11 +41,11 @@ files: path: "dolphin-emu/Sys/GC/USA/IPL.bin" standalone_path: "GC/USA/IPL.bin" system: nintendo-gamecube - region: [north-america] + region: [north-america, latin-america] size: 2097152 required: false hle_fallback: true - note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts" + note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts. Discs with the Brazilian country code B and SYSCONF countries of the Americas map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:198-199, 249-251)." source_ref: "upstream Source/Core/Common/CommonPaths.h:139, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:108" - name: "IPL.bin" diff --git a/emulators/ishiiruka.yml b/emulators/ishiiruka.yml index fed1148c..225ccc05 100644 --- a/emulators/ishiiruka.yml +++ b/emulators/ishiiruka.yml @@ -37,11 +37,11 @@ files: path: "dolphin-emu/Sys/GC/USA/IPL.bin" standalone_path: "GC/USA/IPL.bin" system: nintendo-gamecube - region: [north-america] + region: [north-america, latin-america] size: 2097152 required: false hle_fallback: true - note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts" + note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts. Discs with the Brazilian country code B map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:162-166)." source_ref: "source Source/Core/Core/ConfigManager.cpp:876-883, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:105" - name: "IPL.bin" diff --git a/emulators/primehack.yml b/emulators/primehack.yml index 7fe78122..71917d14 100644 --- a/emulators/primehack.yml +++ b/emulators/primehack.yml @@ -36,11 +36,11 @@ files: - name: "IPL.bin" path: "GC/USA/IPL.bin" system: nintendo-gamecube - region: [north-america] + region: [north-america, latin-america] size: 2097152 required: false hle_fallback: true - note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts" + note: "GameCube NTSC-U boot ROM. HLE available but real IPL needed for GC menu boot and accurate fonts. Discs with the Brazilian country code B and SYSCONF countries of the Americas map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:198-199, 249-251)." source_ref: "upstream Source/Core/Common/CommonPaths.h:138, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:109-110" - name: "IPL.bin" diff --git a/emulators/triforce.yml b/emulators/triforce.yml index 675a5b44..a321a743 100644 --- a/emulators/triforce.yml +++ b/emulators/triforce.yml @@ -115,7 +115,7 @@ files: path: "GC/USA/IPL_TRI.bin" description: "Triforce boot ROM, NTSC-U directory" system: sega-triforce - region: [north-america] + region: [north-america, latin-america] size: 2097152 crc32: "d1883221" validation: [crc32] @@ -199,12 +199,12 @@ files: path: "GC/USA/IPL.bin" description: "GameCube NTSC-U boot ROM" system: nintendo-gamecube - region: [north-america] + region: [north-america, latin-america] size: 2097152 required: false hle_fallback: true source_ref: "source Source/Core/Common/CommonPaths.h:148, source Source/Core/Core/Config/MainSettings.cpp:627-630, source Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp:109-118, 182-183" - note: "Needed to boot the GameCube menu and to take the fonts from a real dump." + note: "Needed to boot the GameCube menu and to take the fonts from a real dump. Discs with the Brazilian country code B and SYSCONF countries of the Americas map to NTSC-U, so Latin America reads this directory too (Source/Core/DiscIO/Enums.cpp:198-199, 249-251)." - name: "IPL.bin" path: "GC/EUR/IPL.bin" diff --git a/tests/test_region.py b/tests/test_region.py index 523951a1..8fe967f9 100644 --- a/tests/test_region.py +++ b/tests/test_region.py @@ -923,6 +923,13 @@ class RegionalRequestsKeepWhatTheCodeLoads(unittest.TestCase): ("genesis_plus_gx", ["brazil", "japan"], "bios_U.sms"), ("genesis_plus_gx_wide", ["australia", "japan"], "bios_U.sms"), ("genesis_plus_gx_expanded", ["brazil", "japan"], "bios_U.sms"), + ("dolphin", ["brazil", "europe"], "dolphin-emu/Sys/GC/USA/IPL.bin"), + ("ishiiruka", ["brazil", "europe"], "dolphin-emu/Sys/GC/USA/IPL.bin"), + ("dolphin-mmjr", ["brazil", "europe"], "GC/USA/IPL.bin"), + ("dolphin-mmjr2", ["brazil", "europe"], "GC/USA/IPL.bin"), + ("primehack", ["brazil", "europe"], "GC/USA/IPL.bin"), + ("triforce", ["brazil", "europe"], "GC/USA/IPL.bin"), + ("triforce", ["brazil", "europe"], "GC/USA/IPL_TRI.bin"), ) def test_each_request_keeps_its_file(self): From 040302f75cfb1afcdceb5769f08432d571128b06 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:26:04 +0200 Subject: [PATCH 09/10] docs: drop a clause semicolon from flycast notes --- emulators/flycast.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulators/flycast.yml b/emulators/flycast.yml index 97e3bf94..c25b9135 100644 --- a/emulators/flycast.yml +++ b/emulators/flycast.yml @@ -50,7 +50,7 @@ notes: | the content directory (shell/libretro/oslib.cpp:118-130). Each ROM inside is looked up by CRC, then by file name, in the game archive, its parent, then the BIOS archive (core/hw/naomi/naomi_cart.cpp:89-106). The blob of - the configured region is mapped first, any region otherwise; a game + the configured region is mapped first, any region otherwise, and a game whose BIOS cannot be loaded aborts (core/hw/naomi/naomi_cart.cpp:196-207). Games whose bios field is naomi2 run as NAOMI 2 and those whose bios field is segasp as System SP (core/hw/naomi/naomi_cart.cpp:810-821). From ccf61b96d7b560dfea3d9ea41a2a738bce260592 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:26:04 +0200 Subject: [PATCH 10/10] fix: report names a RetroPie sentence gains flycast now reads naomi2.zip, which the RetroArch list RetroPie inherits already declares. The render added it to the flycast help sentences but landed_changes counted additions only for entries the platform layer lacks, so the report missed a name the diff carries. names_anew lets an exporter whose unit is not the entry say so. --- scripts/export_native.py | 4 ++++ scripts/exporter/base_exporter.py | 7 +++++++ scripts/exporter/retropie_exporter.py | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/scripts/export_native.py b/scripts/export_native.py index 1ccddb68..ccddee82 100644 --- a/scripts/export_native.py +++ b/scripts/export_native.py @@ -535,6 +535,10 @@ def landed_changes(exporter: object, systems: dict) -> LandedChanges: "added", entry, None, None, _added_fields(exporter, entry) )) continue + if entry.name and exporter.names_anew(entry): + records.append(_change( + "added", entry, None, None, _added_fields(exporter, entry) + )) # Asked of the exporter: a format that names each entry's cores # reads every entry of those cores, not only the paired one. if ( diff --git a/scripts/exporter/base_exporter.py b/scripts/exporter/base_exporter.py index 020f6a2e..b08f9866 100644 --- a/scripts/exporter/base_exporter.py +++ b/scripts/exporter/base_exporter.py @@ -155,6 +155,13 @@ class BaseExporter(ABC): the render learned from the platform's own file.""" return self.writable(fe) + def names_anew(self, fe: NativeFile) -> bool: + """Whether the render wrote, for the first time, a file the platform + layer already declares. Only a format whose unit is not the entry + does: a RetroPie help sentence can lack a name the inherited RetroArch + list carries.""" + return False + @classmethod def writable(cls, fe: NativeFile, require: str = "") -> bool: """Whether this format can carry the entry. diff --git a/scripts/exporter/retropie_exporter.py b/scripts/exporter/retropie_exporter.py index 802ad57f..0847f7a7 100644 --- a/scripts/exporter/retropie_exporter.py +++ b/scripts/exporter/retropie_exporter.py @@ -400,6 +400,11 @@ class Exporter(BaseExporter): return self.writable(fe) return id(fe) in getattr(self, "_named", set()) + def names_anew(self, fe: NativeFile) -> bool: + """flycast's naomi2.zip is in the RetroArch list RetroPie inherits, + yet no flycast help sentence named it: the render adds it there.""" + return fe.platform is not None and id(fe) in getattr(self, "_named", set()) + def outcome( self, systems: dict[str, NativeSystem],