From 116bc2655697ccb182142a9265e1341fe481ba5d Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Fri, 31 Mar 2023 20:22:23 -0700 Subject: [PATCH] add in entries for the various regions for DSi NAND, add in handling to autodetect region tentatively add in the bios7i and bios9i hashes from nointro --- .../Database/FirmwareDatabase.cs | 19 ++++++++-- .../Consoles/Nintendo/NDS/MelonDS.cs | 37 ++++++++++++++++--- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs index 3ceee8c7a0..a21bc5747b 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs @@ -134,10 +134,13 @@ namespace BizHawk.Emulation.Common FirmwareAndOption("24F67BDEA115A2C847C8813A262502EE1607B7DF", 16384, "NDS", "bios7", "NDS_Bios7.bin", "ARM7 BIOS"); FirmwareAndOption("BFAAC75F101C135E32E2AAF541DE6B1BE4C8C62D", 4096, "NDS", "bios9", "NDS_Bios9.bin", "ARM9 BIOS"); - FirmwareAndOption(SHA1Checksum.Dummy, 65536, "NDS", "bios7i", "NDS_Bios7i.bin", "ARM7i BIOS"); - FirmwareAndOption(SHA1Checksum.Dummy, 65536, "NDS", "bios9i", "NDS_Bios9i.bin", "ARM9i BIOS"); + // CHECKME: bios7i supposedly is different due to crypto keys and such, but yet it seems to work for various different NAND dumps? + // supposedly two different systems dumped the same bios7i too? (according to nointro) + FirmwareAndOption("C7C7570BFE51C3C7C5DA3B01331B94E7E7CB4F53", 65536, "NDS", "bios7i", "NDS_Bios7i.bin", "ARM7i BIOS"); + // full hash according to nointro, although incomplete dumps work just as well... + FirmwareAndOption("719B9EEF33692406D7170FF526069615759C4DFC", 65536, "NDS", "bios9i", "NDS_Bios9i.bin", "ARM9i BIOS"); Firmware("NDS", "firmware", "NDS Firmware"); - // throwing a ton of hashes from the interwebs + // throwing a ton of hashes from various reported firmwares var knownhack1 = File("22A7547DBC302BCBFB4005CFB5A2D426D3F85AC6", 262144, "NDS_Firmware [b1].bin", "NDS Firmware", "known hack", true); var knownhack2 = File("AE22DE59FBF3F35CCFBEACAEBA6FA87AC5E7B14B", 262144, "NDS_Firmware [b2].bin", "NDS Firmware", "known hack", true); var knownhack3 = File("1CF9E67C2C703BB9961BBCDD39CD2C7E319A803B", 262144, "NDS_Firmware [b3].bin", "NDS Firmware", "known hack", true); @@ -151,8 +154,16 @@ namespace BizHawk.Emulation.Common Option("NDS", "firmware", in likelygood2); Option("NDS", "firmware", in likelygood3); + // really, this is pointless, firmwarei would just contain user settings for old DS mode? some wifi settings too? (maybe some crypto keys?) FirmwareAndOption(SHA1Checksum.Dummy, 131072, "NDS", "firmwarei", "DSi_Firmware.bin", "DSi Firmware"); - FirmwareAndOption(SHA1Checksum.Dummy, 251658304, "NDS", "nand", "DSi_Nand.bin", "DSi NAND"); + // options for each region due to region locking of the DSi + // also, the sizes include the "nocash footer" which contains the eMMC CID and CPU/Console ID + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (JPN)", "DSi_Nand_JPN.bin", "DSi NAND (Japan)"); + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (EUR)", "DSi_Nand_EUR.bin", "DSi NAND (Europe)"); + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (USA)", "DSi_Nand_USA.bin", "DSi NAND (USA)"); + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (AUS)", "DSi_Nand_AUS.bin", "DSi NAND (Australia)"); + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (CHN)", "DSi_Nand_CHN.bin", "DSi NAND (China)"); + FirmwareAndOption(SHA1Checksum.Dummy, 251658264 + 40, "NDS", "NAND (KOR)", "DSi_Nand_KOR.bin", "DSi NAND (Korea)"); FirmwareAndOption("E4ED47FAE31693E016B081C6BDA48DA5B70D7CCB", 512, "Lynx", "Boot", "LYNX_boot.img", "Boot Rom"); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs index 30c58bfd04..b6843bac20 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; @@ -7,6 +8,8 @@ using System.Threading.Tasks; using BizHawk.BizInvoke; using BizHawk.Common; +using BizHawk.Common.IOExtensions; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Properties; using BizHawk.Emulation.Cores.Waterbox; @@ -85,7 +88,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS : null; var nand = IsDSi - ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "nand")) + ? DecideNAND(CoreComm.CoreFileProvider, (DSiTitleId.Upper & ~0xFF) == 0x00030000, roms[0][0x1B0]) : null; var fw = IsDSi @@ -207,7 +210,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS _frameThreadPtr = _core.GetFrameThreadProc(); if (_frameThreadPtr != IntPtr.Zero) { - Console.WriteLine($"Setting up waterbox thread for 0x{_frameThreadPtr:X16}"); + Console.WriteLine($"Setting up waterbox thread for 0x{(ulong)_frameThreadPtr:X16}"); _frameThreadStart = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer(_frameThreadPtr); _core.SetThreadStartCallback(_threadstartcb); } @@ -220,7 +223,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS _serviceProvider.Register(Tracer); } - private static (ulong Full, uint Upper, uint Lower) GetDSiTitleId(byte[] file) + private static (ulong Full, uint Upper, uint Lower) GetDSiTitleId(IReadOnlyList file) { ulong titleId = 0; for (var i = 0; i < 8; i++) @@ -231,13 +234,35 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS return (titleId, (uint)(titleId >> 32), (uint)(titleId & 0xFFFFFFFFU)); } + private static byte[] DecideNAND(ICoreFileProvider cfp, bool isDSiEnhanced, byte regionFlags) + { + // TODO: priority settings? + var nandOptions = new List { "NAND (JPN)", "NAND (USA)", "NAND (EUR)", "NAND (AUS)", "NAND (CHN)", "NAND (KOR)" }; + if (isDSiEnhanced) // NB: Core makes cartridges region free regardless, DSiWare must follow DSi region locking however (we'll enforce it regardless) + { + nandOptions.Clear(); + if (regionFlags.Bit(0)) nandOptions.Add("NAND (JPN)"); + if (regionFlags.Bit(1)) nandOptions.Add("NAND (USA)"); + if (regionFlags.Bit(2)) nandOptions.Add("NAND (EUR)"); + if (regionFlags.Bit(3)) nandOptions.Add("NAND (AUS)"); + if (regionFlags.Bit(4)) nandOptions.Add("NAND (CHN)"); + if (regionFlags.Bit(5)) nandOptions.Add("NAND (KOR)"); + } + + foreach (var option in nandOptions) + { + var ret = cfp.GetFirmware(new("NDS", option)); + if (ret is not null) return ret; + } + + throw new MissingFirmwareException("Suitable NAND file not found!"); + } + private static byte[] GetTMDData(ulong titleId) { using var zip = new ZipArchive(Zstd.DecompressZstdStream(new MemoryStream(Resources.TMDS.Value)), ZipArchiveMode.Read, false); using var tmd = zip.GetEntry($"{titleId:x16}.tmd")?.Open() ?? throw new($"Cannot find TMD for title ID {titleId:x16}, please report"); - var ret = new byte[tmd.Length]; - tmd.Read(ret, 0, (int)tmd.Length); - return ret; + return tmd.ReadAllBytes(); } // todo: wire this up w/ frontend