update c# side for melonDS changes

This commit is contained in:
CasualPokePlayer 2023-09-17 00:58:26 -07:00
parent f7786e81b9
commit d3dff6fe37
3 changed files with 363 additions and 160 deletions

View File

@ -41,50 +41,155 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public bool ConsiderAltLag;
}
[Flags]
public enum LoadFlags : uint
[StructLayout(LayoutKind.Sequential)]
public struct RenderSettings
{
NONE = 0x00,
USE_REAL_BIOS = 0x01,
SKIP_FIRMWARE = 0x02,
GBA_CART_PRESENT = 0x04,
CLEAR_NAND = 0x08,
FIRMWARE_OVERRIDE = 0x10,
IS_DSI = 0x20,
LOAD_DSIWARE = 0x40,
THREADED_RENDERING = 0x80,
[MarshalAs(UnmanagedType.U1)]
public bool SoftThreaded;
public int GLScaleFactor;
[MarshalAs(UnmanagedType.U1)]
public bool GLBetterPolygons;
}
[StructLayout(LayoutKind.Sequential)]
public struct LoadData
public struct InitConfig
{
public IntPtr DsRomData;
public int DsRomLength;
public IntPtr GbaRomData;
public int GbaRomLength;
public IntPtr GbaRamData;
public int GbaRamLength;
public IntPtr NandData;
public int NandLength;
public IntPtr TmdData;
public NDS.NDSSettings.AudioBitrateType AudioBitrate;
[MarshalAs(UnmanagedType.U1)]
public bool SkipFW;
[MarshalAs(UnmanagedType.U1)]
public bool HasGBACart;
[MarshalAs(UnmanagedType.U1)]
public bool DSi;
[MarshalAs(UnmanagedType.U1)]
public bool ClearNAND;
[MarshalAs(UnmanagedType.U1)]
public bool LoadDSiWare;
public NDS.NDSSyncSettings.ThreeDeeRendererType ThreeDeeRenderer;
public RenderSettings RenderSettings;
}
public enum ConfigEntry
{
ExternalBIOSEnable,
BIOS9Path,
BIOS7Path,
FirmwarePath,
DSi_BIOS9Path,
DSi_BIOS7Path,
DSi_FirmwarePath,
DSi_NANDPath,
DLDI_Enable,
DLDI_ImagePath,
DLDI_ImageSize,
DLDI_ReadOnly,
DLDI_FolderSync,
DLDI_FolderPath,
DSiSD_Enable,
DSiSD_ImagePath,
DSiSD_ImageSize,
DSiSD_ReadOnly,
DSiSD_FolderSync,
DSiSD_FolderPath,
Firm_OverrideSettings,
Firm_Username,
Firm_Language,
Firm_BirthdayMonth,
Firm_BirthdayDay,
Firm_Color,
Firm_Message,
Firm_MAC,
WifiSettingsPath,
AudioBitDepth,
DSi_FullBIOSBoot,
// BizHawk-melonDS specific
UseRealTime,
FixedBootTime,
TimeAtBoot,
}
[UnmanagedFunctionPointer(CC)]
public delegate bool GetBooleanSettingCallback(ConfigEntry configEntry);
[UnmanagedFunctionPointer(CC)]
public delegate int GetIntegerSettingCallback(ConfigEntry configEntry);
[UnmanagedFunctionPointer(CC)]
public delegate void GetStringSettingCallback(ConfigEntry configEntry, IntPtr buffer, int bufferSize);
[UnmanagedFunctionPointer(CC)]
public delegate void GetArraySettingCallback(ConfigEntry configEntry, IntPtr buffer);
[StructLayout(LayoutKind.Sequential)]
public struct FirmwareSettings
public struct ConfigCallbackInterface
{
public IntPtr FirmwareUsername; // max 10 length (then terminator)
public int FirmwareUsernameLength;
public NDS.NDSSyncSettings.Language FirmwareLanguage;
public NDS.NDSSyncSettings.Month FirmwareBirthdayMonth;
public int FirmwareBirthdayDay;
public NDS.NDSSyncSettings.Color FirmwareFavouriteColour;
public IntPtr FirmwareMessage; // max 26 length (then terminator)
public int FirmwareMessageLength;
public GetBooleanSettingCallback GetBoolean;
public GetIntegerSettingCallback GetInteger;
public GetStringSettingCallback GetString;
public GetArraySettingCallback GetArray;
}
[BizImport(CC)]
public abstract bool Init(LoadFlags loadFlags, ref LoadData loadData, ref FirmwareSettings fwSettings);
[UnmanagedFunctionPointer(CC)]
public delegate int GetFileLengthCallback(string path);
[UnmanagedFunctionPointer(CC)]
public delegate void GetFileDataCallback(string path, IntPtr buffer);
[StructLayout(LayoutKind.Sequential)]
public struct FileCallbackInterface
{
public GetFileLengthCallback GetLength;
public GetFileDataCallback GetData;
}
[UnmanagedFunctionPointer(CC)]
public delegate IntPtr RequestGLContextCallback();
[UnmanagedFunctionPointer(CC)]
public delegate void ReleaseGLContextCallback(IntPtr context);
[UnmanagedFunctionPointer(CC)]
public delegate void ActivateGLContextCallback(IntPtr context);
[UnmanagedFunctionPointer(CC)]
public delegate IntPtr GetGLProcAddressCallback(string proc);
[StructLayout(LayoutKind.Sequential)]
public struct GLCallbackInterface
{
public RequestGLContextCallback RequestGLContext;
public ReleaseGLContextCallback ReleaseGLContext;
public ActivateGLContextCallback ActivateGLContext;
public GetGLProcAddressCallback GetGLProcAddress;
public bool IsWinApi;
}
public enum LogLevel : int
{
Debug,
Info,
Warn,
Error,
}
[UnmanagedFunctionPointer(CC)]
public delegate void LogCallback(LogLevel level, string message);
[BizImport(CC, Compatibility = true)]
public abstract IntPtr Init(
ref InitConfig loadData,
ref ConfigCallbackInterface configCallbackInterface,
ref FileCallbackInterface fileCallbackInterface,
//ref GLCallbackInterface glCallbackInterface, // TODO
LogCallback logCallback);
[BizImport(CC)]
public abstract void PutSaveRam(byte[] data, uint len);
@ -155,8 +260,5 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
[BizImport(CC)]
public abstract void GetNANDData(byte[] buf);
[BizImport(CC)]
public abstract void ResetCaches();
}
}

View File

@ -4,9 +4,13 @@ using BizHawk.Emulation.Common;
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.InteropServices;
using System.Text;
using BizHawk.Common.CollectionExtensions;
using Newtonsoft.Json;
// ReSharper disable SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
{
public partial class NDS : ISettable<NDS.NDSSettings, NDS.NDSSyncSettings>
@ -14,6 +18,87 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
private NDSSettings _settings;
private NDSSyncSettings _syncSettings;
private readonly NDSSyncSettings _activeSyncSettings;
private readonly LibMelonDS.ConfigCallbackInterface _configCallbackInterface;
private bool GetBooleanSettingCallback(LibMelonDS.ConfigEntry configEntry) => configEntry switch
{
LibMelonDS.ConfigEntry.ExternalBIOSEnable => _activeSyncSettings.UseRealBIOS,
LibMelonDS.ConfigEntry.DLDI_Enable => false, // TODO
LibMelonDS.ConfigEntry.DLDI_ReadOnly => false, // TODO
LibMelonDS.ConfigEntry.DLDI_FolderSync => false, // TODO
LibMelonDS.ConfigEntry.DSiSD_Enable => false, // TODO
LibMelonDS.ConfigEntry.DSiSD_ReadOnly => false, // TODO
LibMelonDS.ConfigEntry.DSiSD_FolderSync => false, // TODO
LibMelonDS.ConfigEntry.Firm_OverrideSettings => _activeSyncSettings.FirmwareOverride,
LibMelonDS.ConfigEntry.DSi_FullBIOSBoot => false, // TODO
LibMelonDS.ConfigEntry.UseRealTime => false, // RTC callback overrides this anyways, really this is so gmtime_r is used over localtime_r
LibMelonDS.ConfigEntry.FixedBootTime => true, // this just means use TimeAtBoot (which we always want at Unix epoch)
_ => throw new InvalidOperationException()
};
private int GetIntegerSettingCallback(LibMelonDS.ConfigEntry configEntry) => configEntry switch
{
LibMelonDS.ConfigEntry.DLDI_ImageSize => 0, // TODO
LibMelonDS.ConfigEntry.DSiSD_ImageSize => 0, // TODO
LibMelonDS.ConfigEntry.Firm_Language => (int)_activeSyncSettings.FirmwareLanguage,
LibMelonDS.ConfigEntry.Firm_BirthdayMonth => (int)_activeSyncSettings.FirmwareBirthdayMonth,
LibMelonDS.ConfigEntry.Firm_BirthdayDay => _activeSyncSettings.FirmwareBirthdayDay,
LibMelonDS.ConfigEntry.Firm_Color => (int)_activeSyncSettings.FirmwareFavouriteColour,
LibMelonDS.ConfigEntry.AudioBitDepth => (int)_settings.AudioBitDepth,
LibMelonDS.ConfigEntry.TimeAtBoot => 0,
_ => throw new InvalidOperationException()
};
private void GetStringSettingCallback(LibMelonDS.ConfigEntry configEntry, IntPtr buffer, int bufferSize)
{
var ret = configEntry switch
{
LibMelonDS.ConfigEntry.BIOS9Path => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.BIOS7Path => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.FirmwarePath => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.DSi_BIOS9Path => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.DSi_BIOS7Path => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.DSi_FirmwarePath => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.DSi_NANDPath => _configEntryToPath.GetValueOrDefault(configEntry),
LibMelonDS.ConfigEntry.DLDI_ImagePath => "dldi.bin",
LibMelonDS.ConfigEntry.DLDI_FolderPath => "dldi",
LibMelonDS.ConfigEntry.DSiSD_ImagePath => "sd.bin",
LibMelonDS.ConfigEntry.DSiSD_FolderPath => "sd",
LibMelonDS.ConfigEntry.Firm_Username => _activeSyncSettings.FirmwareUsername,
LibMelonDS.ConfigEntry.Firm_Message => _activeSyncSettings.FirmwareMessage,
LibMelonDS.ConfigEntry.WifiSettingsPath => "wfcsettings.bin",
_ => throw new InvalidOperationException()
};
if (string.IsNullOrEmpty(ret))
{
Marshal.WriteByte(buffer, 0, 0);
return;
}
var bytes = Encoding.UTF8.GetBytes(ret);
var numToCopy = Math.Min(bytes.Length, bufferSize - 1);
Marshal.Copy(bytes, 0, buffer, numToCopy);
Marshal.WriteByte(buffer, numToCopy, 0);
}
private void GetArraySettingCallback(LibMelonDS.ConfigEntry configEntry, IntPtr buffer)
{
if (configEntry != LibMelonDS.ConfigEntry.Firm_MAC)
{
throw new InvalidOperationException();
}
// TODO make MAC configurable
Marshal.WriteByte(buffer, 0, 0x00);
Marshal.WriteByte(buffer, 1, 0x09);
Marshal.WriteByte(buffer, 2, 0xBF);
Marshal.WriteByte(buffer, 3, 0x0E);
Marshal.WriteByte(buffer, 4, 0x49);
Marshal.WriteByte(buffer, 5, 0x16);
}
public enum ScreenLayoutKind
{
Vertical,
@ -59,17 +144,17 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
set => _screengap = Math.Max(0, Math.Min(128, value));
}
public enum AudioBitrateType : int
public enum AudioBitDepthType : int
{
Auto,
Ten,
Sixteen,
}
[DisplayName("Audio Bitrate")]
[Description("Auto will set the audio bitrate most accurate to the console (10 for DS, 16 for DSi).")]
[DefaultValue(AudioBitrateType.Auto)]
public AudioBitrateType AudioBitrate { get; set; }
[DisplayName("Audio Bit Depth")]
[Description("Auto will set the audio bit depth most accurate to the console (10 for DS, 16 for DSi).")]
[DefaultValue(AudioBitDepthType.Auto)]
public AudioBitDepthType AudioBitDepth { get; set; }
[DisplayName("Alt Lag")]
[Description("If true, touch screen polling and ARM7 key polling will be considered for lag frames. Otherwise, only ARM9 key polling will be considered.")]
@ -129,8 +214,20 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
public class NDSSyncSettings
{
public enum ThreeDeeRendererType : int
{
Software,
//OpenGL_Classic,
//OpenGL_Compute,
}
[DisplayName("3D Renderer")]
[Description("Renderer used for 3D. OpenGL Classic requires at least OpenGL 3.2, OpenGL Compute requires at least OpenGL 4.3. Forced to Software when recording a movie.")]
[DefaultValue(ThreeDeeRendererType.Software)]
public ThreeDeeRendererType ThreeDeeRenderer { get; set; }
[DisplayName("Threaded 3D Rendering")]
[Description("Offloads 3D rendering to a separate thread")]
[Description("Offloads 3D rendering to a separate thread. Only used for the software 3D renderer.")]
[DefaultValue(true)]
public bool ThreadedRendering { get; set; }

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using BizHawk.BizInvoke;
@ -23,6 +23,35 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
private readonly LibMelonDS _core;
private readonly NDSDisassembler _disassembler;
private readonly Dictionary<string, byte[]> _coreFiles = new();
private readonly Dictionary<LibMelonDS.ConfigEntry, string> _configEntryToPath = new();
private readonly LibMelonDS.FileCallbackInterface _fileCallbackInterface;
private int GetFileLengthCallback(string path)
=> _coreFiles.TryGetValue(path, out var file) ? file.Length : 0;
private void GetFileDataCallback(string path, IntPtr buffer)
{
var file = _coreFiles[path];
Marshal.Copy(file, 0, buffer, file.Length);
}
private void AddCoreFile(LibMelonDS.ConfigEntry configEntry, string path, byte[] file)
{
if (file.Length == 0)
{
throw new InvalidOperationException($"Tried to add 0-sized core file to {path}");
}
_configEntryToPath.Add(configEntry, path);
_coreFiles.Add(path, file);
}
private readonly LibMelonDS.LogCallback _logCallback;
private static void LogCallback(LibMelonDS.LogLevel level, string message)
=> Console.WriteLine($"[{level}] {message}");
[CoreConstructor(VSystemID.Raw.NDS)]
public NDS(CoreLoadParameters<NDSSettings, NDSSyncSettings> lp)
: base(lp.Comm, new()
@ -40,25 +69,37 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
_syncSettings = lp.SyncSettings ?? new();
_settings = lp.Settings ?? new();
IsDSi = _syncSettings.UseDSi;
_activeSyncSettings = _syncSettings.Clone();
IsDSi = _activeSyncSettings.UseDSi;
var roms = lp.Roms.Select(r => r.RomData).ToList();
DSiTitleId = GetDSiTitleId(roms[0]);
IsDSi |= IsDSiWare;
if (roms.Count > (IsDSi ? 1 : 3))
if (roms.Count > (IsDSi ? 1 : 2))
{
throw new InvalidOperationException("Wrong number of ROMs!");
}
var gbacartpresent = roms.Count > 1;
var gbasrampresent = roms.Count == 3;
var gbacartpresent = roms.Count == 2;
InitMemoryCallbacks();
_tracecb = MakeTrace;
_threadstartcb = ThreadStartCallback;
_configCallbackInterface.GetBoolean = GetBooleanSettingCallback;
_configCallbackInterface.GetInteger = GetIntegerSettingCallback;
_configCallbackInterface.GetString = GetStringSettingCallback;
_configCallbackInterface.GetArray = GetArraySettingCallback;
_fileCallbackInterface.GetLength = GetFileLengthCallback;
_fileCallbackInterface.GetData = GetFileDataCallback;
_logCallback = LogCallback;
_core = PreInit<LibMelonDS>(new()
{
Filename = "melonDS.wbx",
@ -69,143 +110,105 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
MmapHeapSizeKB = 1024 * 1024,
SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
}, new Delegate[] { _readcb, _writecb, _execcb, _tracecb, _threadstartcb });
var bios7 = IsDSi || _syncSettings.UseRealBIOS
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7"))
: null;
var bios9 = IsDSi || _syncSettings.UseRealBIOS
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9"))
: null;
var bios7i = IsDSi
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7i"))
: null;
var bios9i = IsDSi
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9i"))
: null;
var nand = IsDSi
? DecideNAND(CoreComm.CoreFileProvider, (DSiTitleId.Upper & ~0xFF) == 0x00030000, roms[0][0x1B0])
: null;
var fw = IsDSi
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "firmwarei"))
: CoreComm.CoreFileProvider.GetFirmware(new("NDS", "firmware"));
var tmd = IsDSiWare
? GetTMDData(DSiTitleId.Full)
: null;
var skipfw = _syncSettings.SkipFirmware || !_syncSettings.UseRealBIOS || fw == null;
var loadFlags = LibMelonDS.LoadFlags.NONE;
if (_syncSettings.UseRealBIOS || IsDSi)
loadFlags |= LibMelonDS.LoadFlags.USE_REAL_BIOS;
if (skipfw && !IsDSi)
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 (IsDSiWare)
loadFlags |= LibMelonDS.LoadFlags.LOAD_DSIWARE;
if (_syncSettings.ThreadedRendering)
loadFlags |= LibMelonDS.LoadFlags.THREADED_RENDERING;
var fwSettings = new LibMelonDS.FirmwareSettings();
var name = Encoding.UTF8.GetBytes(_syncSettings.FirmwareUsername);
fwSettings.FirmwareUsernameLength = name.Length;
fwSettings.FirmwareLanguage = _syncSettings.FirmwareLanguage;
if (!IsDSi && _syncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot) fwSettings.FirmwareLanguage |= (NDSSyncSettings.Language)0x40;
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];
fwSettings.FirmwareMessageLength = message.Length;
var loadData = new LibMelonDS.LoadData
}, new Delegate[]
{
DsRomLength = roms[0].Length,
GbaRomLength = gbacartpresent ? roms[1].Length : 0,
GbaRamLength = gbasrampresent ? roms[2].Length : 0,
NandLength = nand?.Length ?? 0,
AudioBitrate = _settings.AudioBitrate,
};
if (_syncSettings.UseRealBIOS || IsDSi)
_readcb, _writecb, _execcb, _tracecb, _threadstartcb,
_configCallbackInterface.GetBoolean, _configCallbackInterface.GetArray,
_configCallbackInterface.GetString, _configCallbackInterface.GetArray,
_fileCallbackInterface.GetLength, _fileCallbackInterface.GetData,
_logCallback
});
_activeSyncSettings.UseRealBIOS |= IsDSi;
if (_activeSyncSettings.UseRealBIOS)
{
_exe.AddReadonlyFile(bios7, "bios7.rom");
_exe.AddReadonlyFile(bios9, "bios9.rom");
AddCoreFile(LibMelonDS.ConfigEntry.BIOS7Path, "bios7.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7")));
AddCoreFile(LibMelonDS.ConfigEntry.BIOS9Path, "bios9.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9")));
}
if (IsDSi)
{
_exe.AddReadonlyFile(bios7i, "bios7i.rom");
_exe.AddReadonlyFile(bios9i, "bios9i.rom");
if (IsDSiWare)
AddCoreFile(LibMelonDS.ConfigEntry.DSi_BIOS7Path, "bios7i.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7i")));
AddCoreFile(LibMelonDS.ConfigEntry.DSi_BIOS9Path, "bios9i.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9i")));
AddCoreFile(LibMelonDS.ConfigEntry.DSi_FirmwarePath, "firmwarei.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "firmwarei")));
AddCoreFile(LibMelonDS.ConfigEntry.DSi_NANDPath, "nand.bin",
DecideNAND(CoreComm.CoreFileProvider, (DSiTitleId.Upper & ~0xFF) == 0x00030000, roms[0][0x1B0]));
}
else if (_activeSyncSettings.UseRealBIOS)
{
AddCoreFile(LibMelonDS.ConfigEntry.FirmwarePath, "firmware.bin",
CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "firmware")));
}
if (IsDSiWare)
{
_coreFiles.Add("tmd.rom", GetTMDData(DSiTitleId.Full));
_coreFiles.Add("dsiware.rom", roms[0]);
}
else
{
_coreFiles.Add("nds.rom", roms[0]);
if (gbacartpresent)
{
_exe.AddReadonlyFile(roms[0], "dsiware.rom");
_coreFiles.Add("gba.rom", roms[1]);
}
}
if (fw != null)
LibMelonDS.InitConfig initConfig;
initConfig.SkipFW = _activeSyncSettings.SkipFirmware;
initConfig.HasGBACart = gbacartpresent;
initConfig.DSi = IsDSi;
initConfig.ClearNAND = _activeSyncSettings.ClearNAND || lp.DeterministicEmulationRequested;
initConfig.LoadDSiWare = IsDSiWare;
initConfig.ThreeDeeRenderer = _activeSyncSettings.ThreeDeeRenderer;
initConfig.RenderSettings.SoftThreaded = _activeSyncSettings.ThreadedRendering;
initConfig.RenderSettings.GLScaleFactor = 1; // TODO
initConfig.RenderSettings.GLBetterPolygons = false; // TODO
_activeSyncSettings.FirmwareOverride |= !_activeSyncSettings.UseRealBIOS || lp.DeterministicEmulationRequested;
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
if (!IsDSi && _syncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot)
{
_activeSyncSettings.FirmwareLanguage |= (NDSSyncSettings.Language)0x40;
}
if (_activeSyncSettings.UseRealBIOS)
{
var fw = _coreFiles[_configEntryToPath[IsDSi ? LibMelonDS.ConfigEntry.DSi_FirmwarePath : LibMelonDS.ConfigEntry.FirmwarePath]];
if (IsDSi || NDSFirmware.MaybeWarnIfBadFw(fw, CoreComm)) // fw checks dont work on dsi firmware, don't bother
{
if (_syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested)
if (_activeSyncSettings.FirmwareOverride)
{
NDSFirmware.SanitizeFw(fw);
}
}
_exe.AddReadonlyFile(fw, IsDSi ? "firmwarei.bin" : "firmware.bin");
}
unsafe
var error = _core.Init(ref initConfig, ref _configCallbackInterface, ref _fileCallbackInterface, _logCallback);
if (error != IntPtr.Zero)
{
fixed (byte*
dsRomPtr = roms[0],
gbaRomPtr = gbacartpresent ? roms[1] : null,
gbaRamPtr = gbasrampresent ? roms[2] : null,
nandPtr = nand,
tmdPtr = tmd,
namePtr = name,
messagePtr = message)
using (_exe.EnterExit())
{
loadData.DsRomData = (IntPtr)dsRomPtr;
loadData.GbaRomData = (IntPtr)gbaRomPtr;
loadData.GbaRamData = (IntPtr)gbaRamPtr;
loadData.NandData = (IntPtr)nandPtr;
loadData.TmdData = (IntPtr)tmdPtr;
fwSettings.FirmwareUsername = (IntPtr)namePtr;
fwSettings.FirmwareMessage = (IntPtr)messagePtr;
if (!_core.Init(loadFlags, ref loadData, ref fwSettings))
{
throw new InvalidOperationException("Init returned false!");
}
throw new InvalidOperationException(Marshal.PtrToStringAnsi(error));
}
}
if (fw != null)
{
_exe.RemoveReadonlyFile(IsDSi ? "firmwarei.bin" : "firmware.bin");
}
if (IsDSi && IsDSiWare)
{
_exe.RemoveReadonlyFile("dsiware.rom");
}
// the semantics of firmware override mean that sync settings will override firmware on a hard reset, which we don't want here
_activeSyncSettings.FirmwareOverride = false;
PostInit();
((MemoryDomainList)this.AsMemoryDomains()).SystemBus = new NDSSystemBus(this.AsMemoryDomains()["ARM9 System Bus"], this.AsMemoryDomains()["ARM7 System Bus"]);
DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime);
InitializeRtc(_syncSettings.InitialTime);
DeterministicEmulation = lp.DeterministicEmulationRequested || !_activeSyncSettings.UseRealTime;
InitializeRtc(_activeSyncSettings.InitialTime);
_frameThreadPtr = _core.GetFrameThreadProc();
if (_frameThreadPtr != IntPtr.Zero)
@ -213,7 +216,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
Console.WriteLine($"Setting up waterbox thread for 0x{(ulong)_frameThreadPtr:X16}");
_frameThread = new(FrameThreadProc) { IsBackground = true };
_frameThread.Start();
_frameThreadAction = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer<Action>(_frameThreadPtr);
_frameThreadAction = CallingConventionAdapters
.GetWaterboxUnsafeUnwrapped()
.GetDelegateForFunctionPointer<Action>(_frameThreadPtr);
_core.SetThreadStartCallback(_threadstartcb);
}
@ -410,7 +415,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
protected override void LoadStateBinaryInternal(BinaryReader reader)
{
_core.ResetCaches();
SetMemoryCallbacks();
_core.SetThreadStartCallback(_threadstartcb);
if (_frameThreadPtr != _core.GetFrameThreadProc())