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)]
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);

View File

@ -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<object, MGBAHawk.SyncSettings>
{
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<IDisassemblable>(new ArmV4Disassembler());
ser.Register<IMemoryDomains>(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();
}
}
}
}

View File

@ -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);
}
}

Binary file not shown.