update c# side for melonDS changes
This commit is contained in:
parent
f7786e81b9
commit
d3dff6fe37
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Reference in New Issue