From df288f8c33e70508ed5e95f5a90a5e821588cdb0 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 18 Oct 2026 03:59:37 +0200 Subject: [PATCH] fix: drop np2kai font.rom, a fallback of FONT.ROM The np2kai shared group declared font.rom as a second required file while NP2kai reads it only when FONT.ROM, which System.dat already declares, is absent. Case-sensitive platforms packed the font twice. A shared group may now add a second spelling only where some code opens that spelling itself, as the two rhythm engines do. --- platforms/_shared.yml | 9 ++---- tests/test_no_case_collisions.py | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/platforms/_shared.yml b/platforms/_shared.yml index 23f1c106..1ec84b41 100644 --- a/platforms/_shared.yml +++ b/platforms/_shared.yml @@ -40,6 +40,8 @@ shared_groups: # NEC PC-9801/9821 — NP2kai core # np2kai hardcodes "np2kai/" subfolder for firmware lookups # ref: NP2kai/sdl/libretro/libretro.c:1804,1806 — milstr_ncat(np2path, "/np2kai") + # font.rom is the lowercase fallback for FONT.ROM, which System.dat declares + # (font/font.c:192-195): an alias in the profile, not a second file here. np2kai: - name: bios.rom destination: np2kai/bios.rom @@ -48,13 +50,6 @@ shared_groups: md5: "cd237e16e7e77c06bb58540e9e9fca68" crc32: "0a682b93" size: 98304 - - name: font.rom - destination: np2kai/font.rom - required: true - sha1: "78ba9960f135372825ab7244b5e4e73a810002ff" - md5: "38d32748ae49d1815b0614970849fd40" - crc32: "456d9fc7" - size: 288768 - name: itf.rom destination: np2kai/itf.rom required: true diff --git a/tests/test_no_case_collisions.py b/tests/test_no_case_collisions.py index c081baa4..e85f2b02 100644 --- a/tests/test_no_case_collisions.py +++ b/tests/test_no_case_collisions.py @@ -54,5 +54,53 @@ class TestNoCaseCollisions(unittest.TestCase): ) +class SharedGroupsAddNoSecondSpelling(unittest.TestCase): + """The np2kai group added np2kai/font.rom beside System.dat's + np2kai/FONT.ROM. NP2kai reads font.rom only when FONT.ROM is absent: an + alternative name, which belongs in the profile's aliases. On Lakka and + RetroPie, whose filesystems keep both, the pack carried the font twice + and verify counted one more required file.""" + + def test_no_group_entry_respells_a_declared_destination(self) -> None: + import sys + + sys.path.insert(0, str(REPO_ROOT / "scripts")) + from common import ( + list_registered_platforms, + load_emulator_profiles, + load_platform_config, + ) + + # A spelling some code opens as its own file stands: NP2kai's rhythm + # engine reads 2608_bd.wav, its fmgen engine 2608_BD.WAV, and a + # case-sensitive filesystem needs both. A spelling that is only ever + # an alias is the same file asked for twice. + read_as_named = { + str(entry.get("path") or entry.get("name") or "") + for profile in load_emulator_profiles(str(REPO_ROOT / "emulators")).values() + for entry in profile.get("files", []) + if isinstance(entry, dict) + } + platforms_dir = str(REPO_ROOT / "platforms") + respelled: list[str] = [] + for name in list_registered_platforms(platforms_dir, include_archived=True): + config = load_platform_config(name, platforms_dir) + own: dict[str, str] = {} + grouped: list[tuple[str, str]] = [] + for system in config.get("systems", {}).values(): + for entry in system.get("files", []): + dest = entry.get("destination") or entry.get("name") or "" + if entry.get("shared_group"): + grouped.append((dest, entry["shared_group"])) + else: + own.setdefault(dest.casefold(), dest) + for dest, group in grouped: + spelled = own.get(dest.casefold()) + named = dest in read_as_named + if spelled and spelled != dest and not named: + respelled.append(f"{name}: {group} adds {dest} beside {spelled}") + self.assertEqual(respelled, []) + + if __name__ == "__main__": unittest.main()