hook up clear NAND flag and dsiware saveram support

do various cleanups
enforce clear NAND flag for movie recording and retroachievements hardcore mode
This commit is contained in:
CasualPokePlayer 2023-03-31 06:22:11 -07:00
parent 8ce2aac868
commit 6284c98d72
9 changed files with 157 additions and 112 deletions

View File

@ -5,6 +5,7 @@ using System.Linq;
using BizHawk.Client.Common;
using BizHawk.Emulation.Cores.Atari.Atari2600;
using BizHawk.Emulation.Cores.Computers.MSX;
using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS;
using BizHawk.Emulation.Cores.Consoles.O2Hawk;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
using BizHawk.Emulation.Cores.Nintendo.BSNES;
@ -136,6 +137,15 @@ namespace BizHawk.Client.EmuHawk
}
break;
}
case NDS { IsDSi: true } nds:
{
var ss = nds.GetSyncSettings();
if (!ss.ClearNAND)
{
HandleHardcoreModeDisable("Disabling DSi NAND clear in hardcore mode is not allowed.");
}
break;
}
default:
if (CoreGraphicsLayers.TryGetValue(Emu.GetType(), out var layers))
{

View File

@ -48,7 +48,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
USE_REAL_BIOS = 0x01,
SKIP_FIRMWARE = 0x02,
GBA_CART_PRESENT = 0x04,
RESERVED_FLAG = 0x08,
CLEAR_NAND = 0x08,
FIRMWARE_OVERRIDE = 0x10,
IS_DSI = 0x20,
LOAD_DSIWARE = 0x40,
@ -98,6 +98,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
[BizImport(CC)]
public abstract bool SaveRamIsDirty();
[BizImport(CC)]
public abstract void ImportDSiWareSavs(uint titleId);
[BizImport(CC)]
public abstract void ExportDSiWareSavs(uint titleId);
[BizImport(CC)]
public abstract void DSiWareSavsLength(uint titleId, out int publicSavSize, out int privateSavSize, out int bannerSavSize);
[BizImport(CC)]
public abstract void GetRegs(uint[] regs);

View File

@ -5,18 +5,18 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
partial class NDS : IDebuggable
public partial class NDS : IDebuggable
{
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
{
uint[] regs = new uint[2 * 16];
var regs = new uint[2 * 16];
_core.GetRegs(regs);
var ret = new Dictionary<string, RegisterValue>();
for (int i = 0; i < 2; i++)
for (var i = 0; i < 2; i++)
{
int ncpu = i == 0 ? 9 : 7;
for (int j = 0; j < 16; j++)
var ncpu = i == 0 ? 9 : 7;
for (var j = 0; j < 16; j++)
{
ret["ARM" + ncpu + " r" + j] = regs[i * 16 + j];
}
@ -30,13 +30,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
throw new InvalidOperationException("Wrong String Length???");
}
int ncpu = int.Parse(register.Substring(3, 1));
if (ncpu != 9 && ncpu != 7)
var ncpu = int.Parse(register.Substring(3, 1));
if (ncpu is not (9 or 7))
{
throw new InvalidOperationException("Invalid CPU???");
}
int index = int.Parse(register.Substring(6, register.Length - 6));
if (index < 0 || index > 15)
var index = int.Parse(register.Substring(6, register.Length - 6));
if (index is < 0 or > 15)
{
throw new InvalidOperationException("Invalid Reg Index???");
}
@ -63,7 +63,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
LibMelonDS.MemoryCallback CreateCallback(MemoryCallbackFlags flags, Func<bool> getHasCBOfType)
{
var rawFlags = (uint)flags;
return (address) =>
return address =>
{
if (getHasCBOfType())
{

View File

@ -1,28 +1,68 @@
using System;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
partial class NDS : ISaveRam
public partial class NDS : ISaveRam
{
public new bool SaveRamModified => _core.SaveRamIsDirty();
public new bool SaveRamModified => IsDSiWare || _core.SaveRamIsDirty();
public new byte[] CloneSaveRam()
{
int length = _core.GetSaveRamLength();
if (IsDSiWare)
{
_core.DSiWareSavsLength(DSiTitleId.Lower, out var publicSavSize, out var privateSavSize, out var bannerSavSize);
if (publicSavSize + privateSavSize + bannerSavSize == 0) return null;
_exe.AddTransientFile(Array.Empty<byte>(), "public.sav");
_exe.AddTransientFile(Array.Empty<byte>(), "private.sav");
_exe.AddTransientFile(Array.Empty<byte>(), "banner.sav");
_core.ExportDSiWareSavs(DSiTitleId.Lower);
var publicSav = _exe.RemoveTransientFile("public.sav");
var privateSav = _exe.RemoveTransientFile("private.sav");
var bannerSav = _exe.RemoveTransientFile("banner.sav");
if (publicSav.Length != publicSavSize || privateSav.Length != privateSavSize ||
bannerSav.Length != bannerSavSize)
{
throw new InvalidOperationException("Unexpected size difference in DSiWare sav files!");
}
var ret = new byte[publicSavSize + privateSavSize + bannerSavSize];
publicSav.AsSpan().CopyTo(ret.AsSpan().Slice(0, publicSavSize));
privateSav.AsSpan().CopyTo(ret.AsSpan().Slice(publicSavSize, privateSavSize));
bannerSav.AsSpan().CopyTo(ret.AsSpan().Slice(publicSavSize + privateSavSize, bannerSavSize));
return ret;
}
var length = _core.GetSaveRamLength();
if (length > 0)
{
byte[] ret = new byte[length];
var ret = new byte[length];
_core.GetSaveRam(ret);
return ret;
}
return new byte[0];
return null;
}
public new void StoreSaveRam(byte[] data)
{
if (data.Length > 0)
if (IsDSiWare)
{
_core.DSiWareSavsLength(DSiTitleId.Lower, out var publicSavSize, out var privateSavSize, out var bannerSavSize);
if (data.Length == publicSavSize + privateSavSize + bannerSavSize)
{
if (publicSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(0, publicSavSize).ToArray(), "public.sav");
if (privateSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(publicSavSize, privateSavSize).ToArray(), "private.sav");
if (bannerSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(publicSavSize + privateSavSize, bannerSavSize).ToArray(), "banner.sav");
_core.ImportDSiWareSavs(DSiTitleId.Lower);
if (publicSavSize > 0) _exe.RemoveReadonlyFile("public.sav");
if (privateSavSize > 0) _exe.RemoveReadonlyFile("private.sav");
if (bannerSavSize > 0) _exe.RemoveReadonlyFile("banner.sav");
}
}
else if (data.Length > 0)
{
_core.PutSaveRam(data, (uint)data.Length);
}

View File

@ -9,7 +9,7 @@ using Newtonsoft.Json;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
partial class NDS : ISettable<NDS.NDSSettings, NDS.NDSSyncSettings>
public partial class NDS : ISettable<NDS.NDSSettings, NDS.NDSSyncSettings>
{
private NDSSettings _settings;
private NDSSyncSettings _syncSettings;
@ -153,7 +153,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public bool UseRealTime { get; set; }
[DisplayName("DSi Mode")]
[Description("If true, DSi mode will be used.")]
[Description("If true, DSi mode will be used. Forced true if a DSiWare rom is detected.")]
[DefaultValue(false)]
public bool UseDSi { get; set; }
@ -169,9 +169,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
[DisplayName("Firmware Override")]
[Description("If true, the firmware settings will be overriden by provided settings. Forced true when recording a movie.")]
[DefaultValue(false)]
[DefaultValue(true)]
public bool FirmwareOverride { get; set; }
[DisplayName("Clear NAND")]
[Description("If true, the DSi NAND will have all its titles cleared. Forced true when recording a movie.")]
[DefaultValue(true)]
public bool ClearNAND { get; set; }
public enum StartUp : int
{
[Display(Name = "Auto Boot")]

View File

@ -5,14 +5,14 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
partial class NDS
public partial class NDS
{
private ITraceable Tracer { get; }
private readonly LibMelonDS.TraceCallback _tracecb;
private unsafe void MakeTrace(LibMelonDS.TraceMask type, uint opcode, IntPtr r, IntPtr disasm, uint cyclesOff)
{
string cpu = type switch
var cpu = type switch
{
LibMelonDS.TraceMask.ARM7_THUMB => "ARM7 (Thumb)",
LibMelonDS.TraceMask.ARM7_ARM => "ARM7",
@ -21,33 +21,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
_ => throw new InvalidOperationException("Invalid CPU Mode???"),
};
uint* regs = (uint*)r;
var regs = (uint*)r;
bool isthumb = type is LibMelonDS.TraceMask.ARM7_THUMB or LibMelonDS.TraceMask.ARM9_THUMB;
uint opaddr = regs[15] - (isthumb ? 4u : 8u); // handle prefetch
var isthumb = type is LibMelonDS.TraceMask.ARM7_THUMB or LibMelonDS.TraceMask.ARM9_THUMB;
var opaddr = regs![15] - (isthumb ? 4u : 8u); // handle prefetch
Tracer.Put(new(
disassembly: string.Format("{0:x8}: {1:x8} ", opaddr, opcode).PadRight(12) + Marshal.PtrToStringAnsi(disasm).PadRight(36),
registerInfo: string.Format(
"r0:{0:x8} r1:{1:x8} r2:{2:x8} r3:{3:x8} r4:{4:x8} r5:{5:x8} r6:{6:x8} r7:{7:x8} r8:{8:x8} r9:{9:x8} r10:{10:x8} r11:{11:x8} r12:{12:x8} SP:{13:x8} LR:{14:x8} PC:{15:x8} Cy:{16} {17}",
regs[0],
regs[1],
regs[2],
regs[3],
regs[4],
regs[5],
regs[6],
regs[7],
regs[8],
regs[9],
regs[10],
regs[11],
regs[12],
regs[13],
regs[14],
regs[15],
CycleCount + cyclesOff,
cpu)));
disassembly: $"{opaddr:x8}: {opcode:x8} ".PadRight(12) + Marshal.PtrToStringAnsi(disasm)!.PadRight(36),
registerInfo: $"r0:{regs[0]:x8} r1:{regs[1]:x8} r2:{regs[2]:x8} r3:{regs[3]:x8} r4:{regs[4]:x8} r5:{regs[5]:x8} " +
$"r6:{regs[6]:x8} r7:{regs[7]:x8} r8:{regs[8]:x8} r9:{regs[9]:x8} r10:{regs[10]:x8} r11:{regs[11]:x8} " +
$"r12:{regs[12]:x8} SP:{regs[13]:x8} LR:{regs[14]:x8} PC:{regs[15]:x8} Cy:{CycleCount + cyclesOff} {cpu}"));
}
}
}

View File

@ -13,7 +13,7 @@ using BizHawk.Emulation.Cores.Waterbox;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
[PortedCore(CoreNames.MelonDS, "Arisotura", "0.9.4", "http://melonds.kuribo64.net/")]
[PortedCore(CoreNames.MelonDS, "Arisotura", "0.9.5", "https://melonds.kuribo64.net/")]
[ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(IRegionable) })]
public partial class NDS : WaterboxCore
{
@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
[CoreConstructor(VSystemID.Raw.NDS)]
public NDS(CoreLoadParameters<NDSSettings, NDSSyncSettings> lp)
: base(lp.Comm, new Configuration
: base(lp.Comm, new()
{
DefaultWidth = 256,
DefaultHeight = 384,
@ -34,28 +34,29 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
SystemId = VSystemID.Raw.NDS,
})
{
_syncSettings = lp.SyncSettings ?? new NDSSyncSettings();
_settings = lp.Settings ?? new NDSSettings();
_syncSettings = lp.SyncSettings ?? new();
_settings = lp.Settings ?? new();
IsDSi = _syncSettings.UseDSi;
var roms = lp.Roms.Select(r => r.RomData).ToList();
DSiTitleId = GetDSiTitleId(roms[0]);
IsDSi |= IsDSiWare;
if (roms.Count > (IsDSi ? 1 : 3))
{
throw new InvalidOperationException("Wrong number of ROMs!");
}
IsDSiWare = IsDSi && RomIsWare(roms[0]);
bool gbacartpresent = roms.Count > 1;
bool gbasrampresent = roms.Count == 3;
var gbacartpresent = roms.Count > 1;
var gbasrampresent = roms.Count == 3;
InitMemoryCallbacks();
_tracecb = MakeTrace;
_threadstartcb = ThreadStartCallback;
_core = PreInit<LibMelonDS>(new WaterboxOptions
_core = PreInit<LibMelonDS>(new()
{
Filename = "melonDS.wbx",
SbrkHeapSizeKB = 2 * 1024,
@ -91,13 +92,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "firmwarei"))
: CoreComm.CoreFileProvider.GetFirmware(new("NDS", "firmware"));
var tmd = IsDSi && IsDSiWare
? GetTMDData(roms[0])
var tmd = IsDSiWare
? GetTMDData(DSiTitleId.Full)
: null;
bool skipfw = _syncSettings.SkipFirmware || !_syncSettings.UseRealBIOS || fw == null;
var skipfw = _syncSettings.SkipFirmware || !_syncSettings.UseRealBIOS || fw == null;
LibMelonDS.LoadFlags loadFlags = LibMelonDS.LoadFlags.NONE;
var loadFlags = LibMelonDS.LoadFlags.NONE;
if (_syncSettings.UseRealBIOS || IsDSi)
loadFlags |= LibMelonDS.LoadFlags.USE_REAL_BIOS;
@ -105,11 +106,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
loadFlags |= LibMelonDS.LoadFlags.SKIP_FIRMWARE;
if (gbacartpresent)
loadFlags |= LibMelonDS.LoadFlags.GBA_CART_PRESENT;
if (IsDSi && (_syncSettings.ClearNAND || lp.DeterministicEmulationRequested))
loadFlags |= LibMelonDS.LoadFlags.CLEAR_NAND; // TODO: need a way to send through multiple DSiWare titles at once for this approach
if (fw is null || _syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested)
loadFlags |= LibMelonDS.LoadFlags.FIRMWARE_OVERRIDE;
if (IsDSi)
loadFlags |= LibMelonDS.LoadFlags.IS_DSI;
if (IsDSi && IsDSiWare)
if (IsDSiWare)
loadFlags |= LibMelonDS.LoadFlags.LOAD_DSIWARE;
if (_syncSettings.ThreadedRendering)
loadFlags |= LibMelonDS.LoadFlags.THREADED_RENDERING;
@ -122,7 +125,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
fwSettings.FirmwareBirthdayMonth = _syncSettings.FirmwareBirthdayMonth;
fwSettings.FirmwareBirthdayDay = _syncSettings.FirmwareBirthdayDay;
fwSettings.FirmwareFavouriteColour = _syncSettings.FirmwareFavouriteColour;
var message = _syncSettings.FirmwareMessage.Length != 0 ? Encoding.UTF8.GetBytes(_syncSettings.FirmwareMessage) : new byte[1] { 0 };
var message = _syncSettings.FirmwareMessage.Length != 0 ? Encoding.UTF8.GetBytes(_syncSettings.FirmwareMessage) : new byte[1];
fwSettings.FirmwareMessageLength = message.Length;
var loadData = new LibMelonDS.LoadData
@ -217,27 +220,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
_serviceProvider.Register(Tracer);
}
private static bool RomIsWare(byte[] file)
{
uint lowerWareTitleId = 0;
for (int i = 0; i < 4; i++)
{
lowerWareTitleId <<= 8;
lowerWareTitleId |= file[0x237 - i];
}
return lowerWareTitleId == 0x00030004;
}
private static byte[] GetTMDData(byte[] ware)
private static (ulong Full, uint Upper, uint Lower) GetDSiTitleId(byte[] file)
{
ulong titleId = 0;
for (int i = 0; i < 8; i++)
for (var i = 0; i < 8; i++)
{
titleId <<= 8;
titleId |= ware[0x237 - i];
titleId |= file[0x237 - i];
}
return (titleId, (uint)(titleId >> 32), (uint)(titleId & 0xFFFFFFFFU));
}
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 Exception($"Cannot find TMD for title ID {titleId:x16}, please report");
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;
@ -246,7 +243,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
// todo: wire this up w/ frontend
public byte[] GetNAND()
{
int length = _core.GetNANDSize();
var length = _core.GetNANDSize();
if (length > 0)
{
@ -255,12 +252,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
return ret;
}
return new byte[0];
return null;
}
public bool IsDSi { get; }
public bool IsDSiWare { get; }
public bool IsDSiWare => DSiTitleId.Upper == 0x00030004;
private (ulong Full, uint Upper, uint Lower) DSiTitleId { get; }
public override ControllerDefinition ControllerDefinition => NDSController;
@ -275,7 +274,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
.AddAxis("GBA Light Sensor", 0.RangeTo(10), 0)
.MakeImmutable();
private LibMelonDS.Buttons GetButtons(IController c)
private static LibMelonDS.Buttons GetButtons(IController c)
{
LibMelonDS.Buttons b = 0;
if (c.IsPressed("Up"))

View File

@ -43,14 +43,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
if (Cpu.Length == 14)
{
addr &= ~1u;
uint op = m.PeekByte(addr) | (uint)m.PeekByte(addr + 1) << 8;
var op = m.PeekByte(addr) | (uint)m.PeekByte(addr + 1) << 8;
_core.GetDisassembly(type, op, ret);
length = 2;
}
else
{
addr &= ~3u;
uint op = m.PeekByte(addr)
var op = m.PeekByte(addr)
| (uint)m.PeekByte(addr + 1) << 8
| (uint)m.PeekByte(addr + 2) << 16
| (uint)m.PeekByte(addr + 3) << 24;

View File

@ -21,8 +21,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
comm.ShowMessage("Hacked firmware detected! Firmware might not work!");
return false;
}
int fwMask = fw.Length - 1;
string badCrc16s = "";
var fwMask = fw.Length - 1;
var badCrc16s = string.Empty;
if (!VerifyCrc16(fw, 0x2C, (fw[0x2C + 1] << 8) | fw[0x2C], 0x0000, 0x2A))
{
badCrc16s += " Wifi ";
@ -58,12 +58,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public static void SanitizeFw(byte[] fw)
{
int fwMask = fw.Length - 1;
int[] apstart = new int[3] { 0x07FA00 & fwMask, 0x07FB00 & fwMask, 0x07FC00 & fwMask };
var fwMask = fw.Length - 1;
var apstart = new int[3] { 0x07FA00 & fwMask, 0x07FB00 & fwMask, 0x07FC00 & fwMask };
for (int i = 0; i < 3; i++)
for (var i = 0; i < 3; i++)
{
for (int j = 0; j < 0x100; j++)
for (var j = 0; j < 0x100; j++)
{
fw[apstart[i] + j] = 0;
}
@ -78,21 +78,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
// F8 98 C1 E6 CC 5D 92 E1 85 8C 96
// different mac address
// 18 90 15 E9 7C 1D F1 E1 85 74 02
byte[] macdependentbytes = new byte[11] { 0xF8, 0x98, 0xC1, 0xE6, 0xCC, 0x9D, 0xBE, 0xE1, 0x85, 0x71, 0x5F };
var macdependentbytes = new byte[11] { 0xF8, 0x98, 0xC1, 0xE6, 0xCC, 0x9D, 0xBE, 0xE1, 0x85, 0x71, 0x5F };
int apoffset = 0xF5;
var apoffset = 0xF5;
for (int i = 0; i < 2; i++)
for (var i = 0; i < 2; i++)
{
for (int j = 0; j < 11; j++)
for (var j = 0; j < 11; j++)
{
fw[apstart[i] + apoffset + j] = macdependentbytes[j];
}
}
int ffoffset = 0xE7;
var ffoffset = 0xE7;
for (int i = 0; i < 3; i++)
for (var i = 0; i < 3; i++)
{
fw[apstart[i] + ffoffset] = 0xFF;
}
@ -101,9 +101,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
fw[apstart[2] + 0xFE] = 0x0A;
fw[apstart[2] + 0xFF] = 0xF0;
int[] usersettings = new int[2] { 0x7FE00 & fwMask, 0x7FF00 & fwMask };
var usersettings = new int[2] { 0x7FE00 & fwMask, 0x7FF00 & fwMask };
for (int i = 0; i < 2; i++)
for (var i = 0; i < 2; i++)
{
unsafe
{
@ -136,11 +136,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
var poly = new ushort[8] { 0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801, 0xF001, 0xA001 };
for (int i = 0; i < len; i++)
for (var i = 0; i < len; i++)
{
seed ^= data[i];
for (int j = 0; j < 8; j++)
for (var j = 0; j < 8; j++)
{
if ((seed & 0x1) != 0)
{
@ -159,10 +159,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
private static unsafe bool VerifyCrc16(byte[] fw, int startaddr, int len, int seed, int crcaddr)
{
ushort storedCrc16 = (ushort)((fw[crcaddr + 1] << 8) | fw[crcaddr]);
var storedCrc16 = (ushort)((fw[crcaddr + 1] << 8) | fw[crcaddr]);
fixed (byte* start = &fw[startaddr])
{
ushort actualCrc16 = Crc16(start, len, seed);
var actualCrc16 = Crc16(start, len, seed);
return storedCrc16 == actualCrc16;
}
}
@ -173,7 +173,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
[DllImport("libfwunpack", CallingConvention = CallingConvention.Cdecl)]
private static extern void FreeDecryptedFirmware(IntPtr decryptedFw);
private static string[] goodhashes = new string[]
private static readonly string[] goodhashes =
{
"D83861C66796665A9777B4E9078E9CC8EB13D880", // MACP nds (one of v1-v4), supposedly the most common
"F87038265D24677419FE0AF9EED63B4CE1378CC9", // MACg nds (v5)
@ -182,23 +182,22 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
private static bool CheckDecryptedCodeChecksum(byte[] fw, CoreComm comm)
{
if (!GetDecryptedFirmware(fw, fw.Length, out IntPtr decryptedfw, out int decrypedfwlen))
if (!GetDecryptedFirmware(fw, fw.Length, out var decryptedfw, out var decrypedfwlen))
{
comm.ShowMessage("Firmware could not be decryped for verification! This firmware might be not work!");
return false;
}
else
var DecryptedFirmware = new byte[decrypedfwlen];
Marshal.Copy(decryptedfw, DecryptedFirmware, 0, decrypedfwlen);
FreeDecryptedFirmware(decryptedfw);
var hash = SHA1Checksum.ComputeDigestHex(DecryptedFirmware);
if (hash != goodhashes[0] && hash != goodhashes[1] && hash != goodhashes[2])
{
byte[] DecryptedFirmware = new byte[decrypedfwlen];
Marshal.Copy(decryptedfw, DecryptedFirmware, 0, decrypedfwlen);
FreeDecryptedFirmware(decryptedfw);
var hash = SHA1Checksum.ComputeDigestHex(DecryptedFirmware);
if (hash != goodhashes[0] && hash != goodhashes[1] && hash != goodhashes[2])
{
comm.ShowMessage("Potentially bad firmware dump! Decrypted hash " + hash + " does not match known good dumps.");
return false;
}
comm.ShowMessage("Potentially bad firmware dump! Decrypted hash " + hash + " does not match known good dumps.");
return false;
}
return true;
}
}