cleanup MGBAHawk code
This commit is contained in:
parent
167ed41a51
commit
15a25bdd87
|
@ -7,20 +7,46 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
public partial class MGBAHawk : IDebuggable
|
||||
{
|
||||
public IMemoryCallbackSystem MemoryCallbacks
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
get
|
||||
var values = new int[RegisterNames.Length];
|
||||
LibmGBA.BizGetRegisters(_core, values);
|
||||
var ret = new Dictionary<string, RegisterValue>();
|
||||
for (var i = 0; i < RegisterNames.Length; i++)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
ret[RegisterNames[i]] = new RegisterValue(values[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public IMemoryCallbackSystem MemoryCallbacks
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool CanStep(StepType type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public int TotalExecutedCycles
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
private static readonly string[] RegisterNames =
|
||||
|
@ -44,32 +70,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
"CPSR",
|
||||
"SPSR"
|
||||
};
|
||||
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
var values = new int[RegisterNames.Length];
|
||||
LibmGBA.BizGetRegisters(_core, values);
|
||||
var ret = new Dictionary<string, RegisterValue>();
|
||||
for (var i = 0; i < RegisterNames.Length; i++)
|
||||
{
|
||||
ret[RegisterNames[i]] = new RegisterValue(values[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CanStep(StepType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Step(StepType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
public partial class MGBAHawk
|
||||
{
|
||||
unsafe byte PeekWRAM(IntPtr xwram, long addr) { return ((byte*)xwram)[addr]; }
|
||||
unsafe void PokeWRAM(IntPtr xwram, long addr, byte value) { ((byte*)xwram)[addr] = value; }
|
||||
private MemoryDomainList _memoryDomains;
|
||||
|
||||
void WireMemoryDomainPointers()
|
||||
private MemoryDomainIntPtr _iwram;
|
||||
private MemoryDomainIntPtr _ewram;
|
||||
private MemoryDomainIntPtr _bios;
|
||||
private MemoryDomainIntPtr _palram;
|
||||
private MemoryDomainIntPtr _vram;
|
||||
private MemoryDomainIntPtr _oam;
|
||||
private MemoryDomainIntPtr _rom;
|
||||
private MemoryDomainIntPtr _sram;
|
||||
private MemoryDomainDelegate _cwram;
|
||||
|
||||
private void CreateMemoryDomains(int romsize)
|
||||
{
|
||||
var le = MemoryDomain.Endian.Little;
|
||||
|
||||
var mm = new List<MemoryDomain>();
|
||||
mm.Add(_iwram = new MemoryDomainIntPtr("IWRAM", le, IntPtr.Zero, 32 * 1024, true, 4));
|
||||
mm.Add(_ewram = new MemoryDomainIntPtr("EWRAM", le, IntPtr.Zero, 256 * 1024, true, 4));
|
||||
mm.Add(_bios = new MemoryDomainIntPtr("BIOS", le, IntPtr.Zero, 16 * 1024, false, 4));
|
||||
mm.Add(_palram = new MemoryDomainIntPtr("PALRAM", le, IntPtr.Zero, 1024, true, 4));
|
||||
mm.Add(_vram = new MemoryDomainIntPtr("VRAM", le, IntPtr.Zero, 96 * 1024, true, 4));
|
||||
mm.Add(_oam = new MemoryDomainIntPtr("OAM", le, IntPtr.Zero, 1024, true, 4));
|
||||
mm.Add(_rom = new MemoryDomainIntPtr("ROM", le, IntPtr.Zero, romsize, false, 4));
|
||||
mm.Add(_sram = new MemoryDomainIntPtr("SRAM", le, IntPtr.Zero, 0, true, 4)); // size will be fixed in wireup
|
||||
mm.Add(_cwram = new MemoryDomainDelegate("Combined WRAM", (256 + 32) * 1024, le, null, null, 4));
|
||||
|
||||
_memoryDomains = new MemoryDomainList(mm);
|
||||
WireMemoryDomainPointers();
|
||||
}
|
||||
|
||||
private void WireMemoryDomainPointers()
|
||||
{
|
||||
var s = new LibmGBA.MemoryAreas();
|
||||
LibmGBA.BizGetMemoryAreas(_core, s);
|
||||
|
@ -26,26 +54,37 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
_sram.SetSize(s.sram_size);
|
||||
|
||||
// special combined ram memory domain
|
||||
|
||||
_cwram.Peek =
|
||||
delegate (long addr)
|
||||
delegate(long addr)
|
||||
{
|
||||
if (addr < 0 || addr >= (256 + 32) * 1024)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
if (addr >= 256 * 1024)
|
||||
{
|
||||
return PeekWRAM(s.iwram, addr & 32767);
|
||||
else
|
||||
return PeekWRAM(s.wram, addr);
|
||||
}
|
||||
|
||||
return PeekWRAM(s.wram, addr);
|
||||
};
|
||||
_cwram.Poke =
|
||||
delegate (long addr, byte val)
|
||||
delegate(long addr, byte val)
|
||||
{
|
||||
if (addr < 0 || addr >= (256 + 32) * 1024)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
if (addr >= 256 * 1024)
|
||||
{
|
||||
PokeWRAM(s.iwram, addr & 32767, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
PokeWRAM(s.wram, addr, val);
|
||||
}
|
||||
};
|
||||
|
||||
_gpumem = new GBAGPUMemoryAreas
|
||||
|
@ -57,33 +96,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
};
|
||||
}
|
||||
|
||||
private MemoryDomainIntPtr _iwram;
|
||||
private MemoryDomainIntPtr _ewram;
|
||||
private MemoryDomainIntPtr _bios;
|
||||
private MemoryDomainIntPtr _palram;
|
||||
private MemoryDomainIntPtr _vram;
|
||||
private MemoryDomainIntPtr _oam;
|
||||
private MemoryDomainIntPtr _rom;
|
||||
private MemoryDomainIntPtr _sram;
|
||||
private MemoryDomainDelegate _cwram;
|
||||
|
||||
private void CreateMemoryDomains(int romsize)
|
||||
private unsafe byte PeekWRAM(IntPtr xwram, long addr)
|
||||
{
|
||||
var LE = MemoryDomain.Endian.Little;
|
||||
return ((byte*)xwram)[addr];
|
||||
}
|
||||
|
||||
var mm = new List<MemoryDomain>();
|
||||
mm.Add(_iwram = new MemoryDomainIntPtr("IWRAM", LE, IntPtr.Zero, 32 * 1024, true, 4));
|
||||
mm.Add(_ewram = new MemoryDomainIntPtr("EWRAM", LE, IntPtr.Zero, 256 * 1024, true, 4));
|
||||
mm.Add(_bios = new MemoryDomainIntPtr("BIOS", LE, IntPtr.Zero, 16 * 1024, false, 4));
|
||||
mm.Add(_palram = new MemoryDomainIntPtr("PALRAM", LE, IntPtr.Zero, 1024, true, 4));
|
||||
mm.Add(_vram = new MemoryDomainIntPtr("VRAM", LE, IntPtr.Zero, 96 * 1024, true, 4));
|
||||
mm.Add(_oam = new MemoryDomainIntPtr("OAM", LE, IntPtr.Zero, 1024, true, 4));
|
||||
mm.Add(_rom = new MemoryDomainIntPtr("ROM", LE, IntPtr.Zero, romsize, false, 4));
|
||||
mm.Add(_sram = new MemoryDomainIntPtr("SRAM", LE, IntPtr.Zero, 0, true, 4)); //size will be fixed in wireup
|
||||
mm.Add(_cwram = new MemoryDomainDelegate("Combined WRAM", (256 + 32) * 1024, LE, null, null, 4));
|
||||
|
||||
MemoryDomains = new MemoryDomainList(mm);
|
||||
WireMemoryDomainPointers();
|
||||
private unsafe void PokeWRAM(IntPtr xwram, long addr, byte value)
|
||||
{
|
||||
((byte*)xwram)[addr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
||||
|
@ -13,15 +12,32 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
int len = LibmGBA.BizGetSaveRam(_core, _saveScratch, _saveScratch.Length);
|
||||
if (len == _saveScratch.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Save buffer not long enough");
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = new byte[len];
|
||||
Array.Copy(_saveScratch, ret, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (data.Take(8).SequenceEqual(Encoding.ASCII.GetBytes("GBABATT\0")))
|
||||
{
|
||||
data = LegacyFix(data);
|
||||
}
|
||||
|
||||
LibmGBA.BizPutSaveRam(_core, data, data.Length);
|
||||
}
|
||||
|
||||
public bool SaveRamModified => LibmGBA.BizGetSaveRam(_core, _saveScratch, _saveScratch.Length) > 0;
|
||||
|
||||
private static byte[] LegacyFix(byte[] saveram)
|
||||
{
|
||||
// at one point vbanext-hawk had a special saveram format which we want to load.
|
||||
|
@ -31,32 +47,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
int eepromsize = br.ReadInt32();
|
||||
byte[] flash = br.ReadBytes(flashSize);
|
||||
byte[] eeprom = br.ReadBytes(eepromsize);
|
||||
|
||||
if (flash.Length == 0)
|
||||
{
|
||||
return eeprom;
|
||||
else if (eeprom.Length == 0)
|
||||
}
|
||||
|
||||
if (eeprom.Length == 0)
|
||||
{
|
||||
return flash;
|
||||
else
|
||||
{
|
||||
// well, isn't this a sticky situation!
|
||||
return flash; // woops
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (data.Take(8).SequenceEqual(Encoding.ASCII.GetBytes("GBABATT\0")))
|
||||
{
|
||||
data = LegacyFix(data);
|
||||
}
|
||||
LibmGBA.BizPutSaveRam(_core, data, data.Length);
|
||||
}
|
||||
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get
|
||||
{
|
||||
return LibmGBA.BizGetSaveRam(_core, _saveScratch, _saveScratch.Length) > 0;
|
||||
}
|
||||
// well, isn't this a sticky situation!
|
||||
return flash; // woops
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,15 +43,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
[DisplayName("Display BG Layer 0")]
|
||||
[DefaultValue(true)]
|
||||
public bool DisplayBG0 { get; set; }
|
||||
|
||||
[DisplayName("Display BG Layer 1")]
|
||||
[DefaultValue(true)]
|
||||
public bool DisplayBG1 { get; set; }
|
||||
|
||||
[DisplayName("Display BG Layer 2")]
|
||||
[DefaultValue(true)]
|
||||
public bool DisplayBG2 { get; set; }
|
||||
|
||||
[DisplayName("Display BG Layer 3")]
|
||||
[DefaultValue(true)]
|
||||
public bool DisplayBG3 { get; set; }
|
||||
|
||||
[DisplayName("Display Sprite Layer")]
|
||||
[DefaultValue(true)]
|
||||
public bool DisplayOBJ { get; set; }
|
||||
|
@ -59,18 +63,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
[DisplayName("Play Square 1")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayCh0 { get; set; }
|
||||
|
||||
[DisplayName("Play Square 2")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayCh1 { get; set; }
|
||||
|
||||
[DisplayName("Play Wave")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayCh2 { get; set; }
|
||||
|
||||
[DisplayName("Play Noise")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayCh3 { get; set; }
|
||||
|
||||
[DisplayName("Play Direct Sound A")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayChA { get; set; }
|
||||
|
||||
[DisplayName("Play Direct Sound B")]
|
||||
[DefaultValue(true)]
|
||||
public bool PlayChB { get; set; }
|
||||
|
|
|
@ -5,23 +5,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
public partial class MGBAHawk : ISoundProvider
|
||||
{
|
||||
private readonly short[] soundbuff = new short[2048];
|
||||
private int nsamp;
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = soundbuff;
|
||||
DiscardSamples();
|
||||
}
|
||||
public void DiscardSamples()
|
||||
{
|
||||
nsamp = 0;
|
||||
}
|
||||
private readonly short[] _soundbuff = new short[2048];
|
||||
private int _nsamp;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public bool CanProvideAsync => false;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
|
@ -31,14 +18,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
nsamp = _nsamp;
|
||||
samples = _soundbuff;
|
||||
DiscardSamples();
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_nsamp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
private byte[] _savebuff = new byte[0];
|
||||
private byte[] _savebuff2 = new byte[13];
|
||||
|
||||
public bool BinarySaveStatesPreferred
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public bool BinarySaveStatesPreferred => true;
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
|
@ -33,12 +30,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
IntPtr p = IntPtr.Zero;
|
||||
int size = 0;
|
||||
if (!LibmGBA.BizStartGetState(_core, ref p, ref size))
|
||||
{
|
||||
throw new InvalidOperationException("Core failed to save!");
|
||||
}
|
||||
|
||||
if (size != _savebuff.Length)
|
||||
{
|
||||
_savebuff = new byte[size];
|
||||
_savebuff2 = new byte[size + 13];
|
||||
}
|
||||
|
||||
LibmGBA.BizFinishGetState(p, _savebuff, size);
|
||||
}
|
||||
|
||||
|
@ -67,9 +68,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
_savebuff = new byte[length];
|
||||
_savebuff2 = new byte[length + 13];
|
||||
}
|
||||
|
||||
reader.Read(_savebuff, 0, length);
|
||||
if (!LibmGBA.BizPutState(_core, _savebuff, length))
|
||||
{
|
||||
throw new InvalidOperationException("Core rejected the savestate!");
|
||||
}
|
||||
|
||||
// other variables
|
||||
IsLagFrame = reader.ReadBoolean();
|
||||
|
|
|
@ -4,18 +4,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
public partial class MGBAHawk : IVideoProvider
|
||||
{
|
||||
public int VirtualWidth { get { return 240; } }
|
||||
public int VirtualHeight { get { return 160; } }
|
||||
public int BufferWidth { get { return 240; } }
|
||||
public int BufferHeight { get { return 160; } }
|
||||
public int BackgroundColor
|
||||
{
|
||||
get { return unchecked((int)0xff000000); }
|
||||
}
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
return videobuff;
|
||||
return _videobuff;
|
||||
}
|
||||
private readonly int[] videobuff = new int[240 * 160];
|
||||
|
||||
public int VirtualWidth => 240;
|
||||
public int VirtualHeight => 160;
|
||||
|
||||
public int BufferWidth => 240;
|
||||
public int BufferHeight => 160;
|
||||
|
||||
public int BackgroundColor => unchecked((int)0xff000000);
|
||||
|
||||
private readonly int[] _videobuff = new int[240 * 160];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
ISaveRam, IStatable, IInputPollable, ISettable<MGBAHawk.Settings, MGBAHawk.SyncSettings>,
|
||||
IDebuggable
|
||||
{
|
||||
private IntPtr _core;
|
||||
private byte[] _saveScratch = new byte[262144];
|
||||
|
||||
[CoreConstructor("GBA")]
|
||||
public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, Settings settings, bool deterministic, GameInfo game)
|
||||
{
|
||||
|
@ -26,6 +23,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
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
|
||||
|
@ -36,6 +34,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
throw new InvalidOperationException("BIOS must be exactly 16384 bytes!");
|
||||
}
|
||||
|
||||
var skipBios = !DeterministicEmulation && _syncSettings.SkipBios;
|
||||
|
||||
_core = LibmGBA.BizCreate(bios, file, file.Length, GetOverrideInfo(game), skipBios);
|
||||
|
@ -43,12 +42,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
throw new InvalidOperationException("BizCreate() returned NULL! Bad BIOS? and/or ROM?");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CreateMemoryDomains(file.Length);
|
||||
var ser = new BasicServiceProvider(this);
|
||||
ser.Register<IDisassemblable>(new ArmV4Disassembler());
|
||||
ser.Register<IMemoryDomains>(MemoryDomains);
|
||||
ser.Register<IMemoryDomains>(_memoryDomains);
|
||||
|
||||
ServiceProvider = ser;
|
||||
CoreComm = comm;
|
||||
|
@ -66,6 +66,84 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
}
|
||||
}
|
||||
|
||||
public IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
public ControllerDefinition ControllerDefinition => GBA.GBAController;
|
||||
|
||||
public IController Controller { get; set; }
|
||||
|
||||
public void FrameAdvance(bool render, bool rendersound = true)
|
||||
{
|
||||
Frame++;
|
||||
if (Controller.IsPressed("Power"))
|
||||
{
|
||||
LibmGBA.BizReset(_core);
|
||||
|
||||
// BizReset caused memorydomain pointers to change.
|
||||
WireMemoryDomainPointers();
|
||||
}
|
||||
|
||||
IsLagFrame = LibmGBA.BizAdvance(
|
||||
_core,
|
||||
VBANext.GetButtons(Controller),
|
||||
_videobuff,
|
||||
ref _nsamp,
|
||||
_soundbuff,
|
||||
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++;
|
||||
}
|
||||
|
||||
// this should be called in hblank on the appropriate line, but until we implement that, just do it here
|
||||
_scanlinecb?.Invoke();
|
||||
}
|
||||
|
||||
public int Frame { get; private set; }
|
||||
|
||||
public string SystemId => "GBA";
|
||||
|
||||
public bool DeterministicEmulation { get; }
|
||||
|
||||
public string BoardName => null;
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
Frame = 0;
|
||||
LagCount = 0;
|
||||
IsLagFrame = false;
|
||||
}
|
||||
|
||||
public CoreComm CoreComm { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_core != IntPtr.Zero)
|
||||
{
|
||||
LibmGBA.BizDestroy(_core);
|
||||
_core = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public GBAGPUMemoryAreas GetMemoryAreas()
|
||||
{
|
||||
return _gpumem;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void SetScanlineCallback(Action callback, int scanline)
|
||||
{
|
||||
_scanlinecb = callback;
|
||||
}
|
||||
|
||||
private readonly byte[] _saveScratch = new byte[262144];
|
||||
private IntPtr _core;
|
||||
|
||||
private static LibmGBA.OverrideInfo GetOverrideInfo(GameInfo game)
|
||||
{
|
||||
if (!game.OptionPresent("mgbaNeedsOverrides"))
|
||||
|
@ -82,9 +160,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
switch (game.GetIntValue("flashSize"))
|
||||
{
|
||||
case 65536: ret.Savetype = LibmGBA.SaveType.Flash512; break;
|
||||
case 131072: ret.Savetype = LibmGBA.SaveType.Flash1m; break;
|
||||
default: throw new InvalidOperationException("Unknown flashSize");
|
||||
case 65536:
|
||||
ret.Savetype = LibmGBA.SaveType.Flash512;
|
||||
break;
|
||||
case 131072:
|
||||
ret.Savetype = LibmGBA.SaveType.Flash1m;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown flashSize");
|
||||
}
|
||||
}
|
||||
else if (game.OptionPresent("saveType"))
|
||||
|
@ -92,9 +175,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
switch (game.GetIntValue("saveType"))
|
||||
{
|
||||
// 3 specifies either flash 512 or 1024, but in vba-over.ini, the latter will have a flashSize as well
|
||||
case 3: ret.Savetype = LibmGBA.SaveType.Flash512; break;
|
||||
case 4: ret.Savetype = LibmGBA.SaveType.Eeprom; break;
|
||||
default: throw new InvalidOperationException("Unknown saveType");
|
||||
case 3:
|
||||
ret.Savetype = LibmGBA.SaveType.Flash512;
|
||||
break;
|
||||
case 4:
|
||||
ret.Savetype = LibmGBA.SaveType.Eeprom;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown saveType");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,94 +190,31 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
ret.Hardware |= LibmGBA.Hardware.Rtc;
|
||||
}
|
||||
|
||||
if (game.GetInt("mirroringEnabled", 0) == 1)
|
||||
{
|
||||
throw new InvalidOperationException("Don't know what to do with mirroringEnabled!");
|
||||
}
|
||||
|
||||
if (game.OptionPresent("idleLoop"))
|
||||
{
|
||||
ret.IdleLoop = (uint)game.GetHexValue("idleLoop");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MemoryDomainList MemoryDomains;
|
||||
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
public ControllerDefinition ControllerDefinition { get { return GBA.GBAController; } }
|
||||
public IController Controller { get; set; }
|
||||
|
||||
public void FrameAdvance(bool render, bool rendersound = true)
|
||||
{
|
||||
Frame++;
|
||||
if (Controller.IsPressed("Power"))
|
||||
{
|
||||
LibmGBA.BizReset(_core);
|
||||
//BizReset caused memorydomain pointers to change.
|
||||
WireMemoryDomainPointers();
|
||||
}
|
||||
|
||||
IsLagFrame = LibmGBA.BizAdvance(_core, VBANext.GetButtons(Controller), videobuff, ref nsamp, soundbuff,
|
||||
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++;
|
||||
// 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; private set; }
|
||||
|
||||
public string BoardName { get { return null; } }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
Frame = 0;
|
||||
LagCount = 0;
|
||||
IsLagFrame = false;
|
||||
}
|
||||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_core != IntPtr.Zero)
|
||||
{
|
||||
LibmGBA.BizDestroy(_core);
|
||||
_core = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private Action _scanlinecb;
|
||||
|
||||
private GBAGPUMemoryAreas _gpumem;
|
||||
|
||||
public GBAGPUMemoryAreas GetMemoryAreas()
|
||||
{
|
||||
return _gpumem;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void SetScanlineCallback(Action callback, int scanline)
|
||||
{
|
||||
_scanlinecb = callback;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue