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] 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 b45bee37..672dc506 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 9ebf16ab..aab29b92 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()