From 9a02a5cac0aaeb8c9c96c5ca7d56432400ac57b5 Mon Sep 17 00:00:00 2001 From: goyuken Date: Sat, 13 Jun 2015 18:01:26 +0000 Subject: [PATCH] mgba: RTC and syncsettings --- .../Consoles/Nintendo/GBA/LibmGBA.cs | 3 + .../Consoles/Nintendo/GBA/MGBAHawk.cs | 124 +++++++++++++++--- BizHawk.Emulation.Cores/CoreInventory.cs | 7 +- output/dll/mgba.dll | Bin 820736 -> 820736 bytes 4 files changed, 115 insertions(+), 19 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs index aadcef7abd..644b987178 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs @@ -21,6 +21,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA [DllImport(dll, CallingConvention = cc)] public static extern void BizReset(IntPtr ctx); + [DllImport(dll, CallingConvention = cc)] + public static extern void BizSkipBios(IntPtr ctx); + [DllImport(dll, CallingConvention = cc)] public static extern bool BizLoad(IntPtr ctx, byte[] data, int length); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs index cf1c64217a..4eff95be9b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs @@ -6,21 +6,32 @@ using BizHawk.Common; using BizHawk.Emulation.Common; using System.Runtime.InteropServices; using System.IO; +using System.ComponentModel; namespace BizHawk.Emulation.Cores.Nintendo.GBA { [CoreAttributes("mGBA", "endrift", true, false, "NOT DONE", "NOT DONE", false)] - public class MGBAHawk : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable + public class MGBAHawk : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable, ISettable { IntPtr core; [CoreConstructor("GBA")] - public MGBAHawk(byte[] file, CoreComm comm) + public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, bool deterministic) { - byte[] bios = null; - if (true) // TODO: config me + _syncSettings = syncSettings ?? new SyncSettings(); + DeterministicEmulation = deterministic; + + byte[] bios = comm.CoreFileProvider.GetFirmware("GBA", "Bios", false); + DeterministicEmulation &= bios != null; + + if (DeterministicEmulation != deterministic) { - bios = comm.CoreFileProvider.GetFirmware("GBA", "Bios", true); + throw new InvalidOperationException("A BIOS is required for deterministic recordings!"); + } + if (!DeterministicEmulation && bios != null && !_syncSettings.RTCUseRealTime && !_syncSettings.SkipBios) + { + // in these situations, this core is deterministic even though it wasn't asked to be + DeterministicEmulation = true; } if (bios != null && bios.Length != 16384) @@ -39,6 +50,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA throw new InvalidOperationException("BizLoad() returned FALSE! Bad ROM?"); } + if (!DeterministicEmulation && _syncSettings.SkipBios) + { + LibmGBA.BizSkipBios(core); + } + var ser = new BasicServiceProvider(this); ser.Register(new ArmV4Disassembler()); ser.Register(CreateMemoryDomains(file.Length)); @@ -46,6 +62,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA ServiceProvider = ser; CoreComm = comm; + CoreComm.VsyncNum = 262144; + CoreComm.VsyncDen = 4389; + CoreComm.NominalWidth = 240; + CoreComm.NominalHeight = 160; + InitStates(); } catch @@ -66,27 +87,31 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA LibmGBA.BizReset(core); IsLagFrame = LibmGBA.BizAdvance(core, VBANext.GetButtons(Controller), videobuff, ref nsamp, soundbuff, - 0, // TODO RTC hookup + RTCTime(), (short)Controller.GetFloat("Tilt X"), (short)Controller.GetFloat("Tilt Y"), (short)Controller.GetFloat("Tilt Z"), (byte)(255 - Controller.GetFloat("Light Sensor"))); + if (IsLagFrame) - _lagCount++; + LagCount++; + // this should be called in hblank on the appropriate line, but until we implement that, just do it here + if (_scanlinecb != null) + _scanlinecb(); } public int Frame { get; private set; } public string SystemId { get { return "GBA"; } } - public bool DeterministicEmulation { get { return true; } } + public bool DeterministicEmulation { get; private set; } public string BoardName { get { return null; } } public void ResetCounters() { Frame = 0; - _lagCount = 0; + LagCount = 0; IsLagFrame = false; } @@ -168,6 +193,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA #endregion + private Action _scanlinecb; + private GBAGPUMemoryAreas _gpumem; public GBAGPUMemoryAreas GetMemoryAreas() @@ -178,6 +205,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA [FeatureNotImplemented] public void SetScanlineCallback(Action callback, int scanline) { + _scanlinecb = callback; } #region ISaveRam @@ -296,7 +324,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA // other variables IsLagFrame = reader.ReadBoolean(); - _lagCount = reader.ReadInt32(); + LagCount = reader.ReadInt32(); Frame = reader.ReadInt32(); } @@ -312,13 +340,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA return savebuff2; } - public int LagCount - { - get { return _lagCount; } - } - - private int _lagCount; - + public int LagCount { get; private set; } public bool IsLagFrame { get; private set; } [FeatureNotImplemented] @@ -326,5 +348,73 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA { get { throw new NotImplementedException(); } } + + private long RTCTime() + { + if (!DeterministicEmulation && _syncSettings.RTCUseRealTime) + { + return (long)DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + } + long basetime = (long)_syncSettings.RTCInitialTime.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + long increment = Frame * 4389L >> 18; + return basetime + increment; + } + + public object GetSettings() + { + return null; + } + + public SyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(object o) + { + return false; + } + + public bool PutSyncSettings(SyncSettings o) + { + bool ret = SyncSettings.NeedsReboot(o, _syncSettings); + _syncSettings = o; + return ret; + } + + private SyncSettings _syncSettings; + + public class SyncSettings + { + [DisplayName("Skip BIOS")] + [Description("Skips the BIOS intro. Not applicable when a BIOS is not provided.")] + [DefaultValue(true)] + public bool SkipBios { get; set; } + + [DisplayName("RTC Use Real Time")] + [Description("Causes the internal clock to reflect your system clock. Only relevant when a game has an RTC chip. Forced to false for movie recording.")] + [DefaultValue(true)] + public bool RTCUseRealTime { get; set; } + + [DisplayName("RTC Initial Time")] + [Description("The initial time of emulation. Only relevant when a game has an RTC chip and \"RTC Use Real Time\" is false.")] + [DefaultValue(typeof(DateTime), "2010-01-01")] + public DateTime RTCInitialTime { get; set; } + + public SyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + + public static bool NeedsReboot(SyncSettings x, SyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public SyncSettings Clone() + { + return (SyncSettings)MemberwiseClone(); + } + } } } diff --git a/BizHawk.Emulation.Cores/CoreInventory.cs b/BizHawk.Emulation.Cores/CoreInventory.cs index 2c03d9eaa1..153900a623 100644 --- a/BizHawk.Emulation.Cores/CoreInventory.cs +++ b/BizHawk.Emulation.Cores/CoreInventory.cs @@ -33,8 +33,11 @@ namespace BizHawk.Emulation.Cores Type expectedtype; if (!paramtypes.TryGetValue(pname, out expectedtype)) throw new InvalidOperationException(string.Format("Unexpected parameter name {0} in constructor for {1}", p.Name, Type)); - if (expectedtype != p.ParameterType) - throw new InvalidOperationException(string.Format("Unexpected type mismatch in parameter {0} in constructor for {1}", p.Name, Type)); + + // disabling the typecheck here doesn't really hurt anything, because the Invoke call will still catch any forbidden casts + // it does allow us to write "MySettingsType settings" instead of "object settings" + // if (expectedtype != p.ParameterType) + // throw new InvalidOperationException(string.Format("Unexpected type mismatch in parameter {0} in constructor for {1}", p.Name, Type)); parammap.Add(pname, i); } } diff --git a/output/dll/mgba.dll b/output/dll/mgba.dll index 99bea41e75aa276eccd9d07e6468fad62a5394db..2fd267109c354ee4c56a55c33a645cc1172709fa 100644 GIT binary patch delta 4720 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 Wi^qhxH{*_2FGvwuv363PPWf--ahNCo delta 4622 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 gGnK8k