mgba: RTC and syncsettings

This commit is contained in:
goyuken 2015-06-13 18:01:26 +00:00
parent 0de4c85d14
commit 9a02a5cac0
4 changed files with 115 additions and 19 deletions

View File

@ -21,6 +21,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
[DllImport(dll, CallingConvention = cc)] [DllImport(dll, CallingConvention = cc)]
public static extern void BizReset(IntPtr ctx); public static extern void BizReset(IntPtr ctx);
[DllImport(dll, CallingConvention = cc)]
public static extern void BizSkipBios(IntPtr ctx);
[DllImport(dll, CallingConvention = cc)] [DllImport(dll, CallingConvention = cc)]
public static extern bool BizLoad(IntPtr ctx, byte[] data, int length); public static extern bool BizLoad(IntPtr ctx, byte[] data, int length);

View File

@ -6,21 +6,32 @@ using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO; using System.IO;
using System.ComponentModel;
namespace BizHawk.Emulation.Cores.Nintendo.GBA namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
[CoreAttributes("mGBA", "endrift", true, false, "NOT DONE", "NOT DONE", false)] [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<object, MGBAHawk.SyncSettings>
{ {
IntPtr core; IntPtr core;
[CoreConstructor("GBA")] [CoreConstructor("GBA")]
public MGBAHawk(byte[] file, CoreComm comm) public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, bool deterministic)
{ {
byte[] bios = null; _syncSettings = syncSettings ?? new SyncSettings();
if (true) // TODO: config me 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) if (bios != null && bios.Length != 16384)
@ -39,6 +50,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
throw new InvalidOperationException("BizLoad() returned FALSE! Bad ROM?"); throw new InvalidOperationException("BizLoad() returned FALSE! Bad ROM?");
} }
if (!DeterministicEmulation && _syncSettings.SkipBios)
{
LibmGBA.BizSkipBios(core);
}
var ser = new BasicServiceProvider(this); var ser = new BasicServiceProvider(this);
ser.Register<IDisassemblable>(new ArmV4Disassembler()); ser.Register<IDisassemblable>(new ArmV4Disassembler());
ser.Register<IMemoryDomains>(CreateMemoryDomains(file.Length)); ser.Register<IMemoryDomains>(CreateMemoryDomains(file.Length));
@ -46,6 +62,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
ServiceProvider = ser; ServiceProvider = ser;
CoreComm = comm; CoreComm = comm;
CoreComm.VsyncNum = 262144;
CoreComm.VsyncDen = 4389;
CoreComm.NominalWidth = 240;
CoreComm.NominalHeight = 160;
InitStates(); InitStates();
} }
catch catch
@ -66,27 +87,31 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
LibmGBA.BizReset(core); LibmGBA.BizReset(core);
IsLagFrame = LibmGBA.BizAdvance(core, VBANext.GetButtons(Controller), videobuff, ref nsamp, soundbuff, 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 X"),
(short)Controller.GetFloat("Tilt Y"), (short)Controller.GetFloat("Tilt Y"),
(short)Controller.GetFloat("Tilt Z"), (short)Controller.GetFloat("Tilt Z"),
(byte)(255 - Controller.GetFloat("Light Sensor"))); (byte)(255 - Controller.GetFloat("Light Sensor")));
if (IsLagFrame) 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 int Frame { get; private set; }
public string SystemId { get { return "GBA"; } } 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 string BoardName { get { return null; } }
public void ResetCounters() public void ResetCounters()
{ {
Frame = 0; Frame = 0;
_lagCount = 0; LagCount = 0;
IsLagFrame = false; IsLagFrame = false;
} }
@ -168,6 +193,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
#endregion #endregion
private Action _scanlinecb;
private GBAGPUMemoryAreas _gpumem; private GBAGPUMemoryAreas _gpumem;
public GBAGPUMemoryAreas GetMemoryAreas() public GBAGPUMemoryAreas GetMemoryAreas()
@ -178,6 +205,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
[FeatureNotImplemented] [FeatureNotImplemented]
public void SetScanlineCallback(Action callback, int scanline) public void SetScanlineCallback(Action callback, int scanline)
{ {
_scanlinecb = callback;
} }
#region ISaveRam #region ISaveRam
@ -296,7 +324,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
// other variables // other variables
IsLagFrame = reader.ReadBoolean(); IsLagFrame = reader.ReadBoolean();
_lagCount = reader.ReadInt32(); LagCount = reader.ReadInt32();
Frame = reader.ReadInt32(); Frame = reader.ReadInt32();
} }
@ -312,13 +340,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
return savebuff2; return savebuff2;
} }
public int LagCount public int LagCount { get; private set; }
{
get { return _lagCount; }
}
private int _lagCount;
public bool IsLagFrame { get; private set; } public bool IsLagFrame { get; private set; }
[FeatureNotImplemented] [FeatureNotImplemented]
@ -326,5 +348,73 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
get { throw new NotImplementedException(); } 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();
}
}
} }
} }

View File

@ -33,8 +33,11 @@ namespace BizHawk.Emulation.Cores
Type expectedtype; Type expectedtype;
if (!paramtypes.TryGetValue(pname, out expectedtype)) if (!paramtypes.TryGetValue(pname, out expectedtype))
throw new InvalidOperationException(string.Format("Unexpected parameter name {0} in constructor for {1}", p.Name, Type)); 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); parammap.Add(pname, i);
} }
} }

Binary file not shown.