From f5c8bece3abadec3c97443d88d4cf2f1984606dc Mon Sep 17 00:00:00 2001 From: goyuken Date: Sat, 6 Jun 2015 17:34:19 +0000 Subject: [PATCH] satesvates for mgba --- BizHawk.Common/Extensions/BufferExtensions.cs | 22 +++-- BizHawk.Common/Util.cs | 11 --- .../Consoles/Nintendo/GBA/LibmGBA.cs | 7 ++ .../Consoles/Nintendo/GBA/MGBAHawk.cs | 87 ++++++++++++++++++- 4 files changed, 106 insertions(+), 21 deletions(-) diff --git a/BizHawk.Common/Extensions/BufferExtensions.cs b/BizHawk.Common/Extensions/BufferExtensions.cs index fde22c76ee..eeec0f2ce3 100644 --- a/BizHawk.Common/Extensions/BufferExtensions.cs +++ b/BizHawk.Common/Extensions/BufferExtensions.cs @@ -18,18 +18,22 @@ namespace BizHawk.Common.BufferExtensions writer.WriteLine(); } + private static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + public unsafe static void SaveAsHexFast(this byte[] buffer, TextWriter writer) { - char* table = Util.HexConvPtr; - if (buffer.Length > 0) + fixed (char* table = HexConvArr) { - int len = buffer.Length; - fixed (byte* src = &buffer[0]) - for (int i = 0; i < len; i++) - { - writer.Write(table[src[i] >> 4]); - writer.Write(table[src[i] & 15]); - } + if (buffer.Length > 0) + { + int len = buffer.Length; + fixed (byte* src = buffer) + for (int i = 0; i < len; i++) + { + writer.Write(table[src[i] >> 4]); + writer.Write(table[src[i] & 15]); + } + } } writer.WriteLine(); } diff --git a/BizHawk.Common/Util.cs b/BizHawk.Common/Util.cs index e467f6e5bf..58be27a1d2 100644 --- a/BizHawk.Common/Util.cs +++ b/BizHawk.Common/Util.cs @@ -10,15 +10,6 @@ namespace BizHawk.Common { public static unsafe class Util { - private static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - private static System.Runtime.InteropServices.GCHandle HexConvHandle; - - static Util() - { - HexConvHandle = System.Runtime.InteropServices.GCHandle.Alloc(HexConvArr, System.Runtime.InteropServices.GCHandleType.Pinned); - HexConvPtr = (char*)HexConvHandle.AddrOfPinnedObject().ToPointer(); - } - public static void CopyStream(Stream src, Stream dest, long len) { const int size = 0x2000; @@ -33,8 +24,6 @@ namespace BizHawk.Common } } - public static char* HexConvPtr { get; set; } - public static bool IsPowerOfTwo(int x) { if (x == 0 || x == 1) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs index f2c7db00ea..8194d50e4a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs @@ -49,5 +49,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public static extern void BizGetSaveRam(IntPtr ctx, byte[] dest); [DllImport(dll, CallingConvention = cc)] public static extern void BizPutSaveRam(IntPtr ctx, byte[] src); + + [DllImport(dll, CallingConvention = cc)] + public static extern int BizGetStateSize(); + [DllImport(dll, CallingConvention = cc)] + public static extern void BizGetState(IntPtr ctx, byte[] dest); + [DllImport(dll, CallingConvention = cc)] + public static extern void BizPutState(IntPtr ctx, byte[] src); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs index 3e34c18320..ccf05bf021 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs @@ -5,11 +5,12 @@ using System.Text; using BizHawk.Common; using BizHawk.Emulation.Common; using System.Runtime.InteropServices; +using System.IO; namespace BizHawk.Emulation.Cores.Nintendo.GBA { [CoreAttributes("mGBA", "endrift", true, false, "NOT DONE", "NOT DONE", false)] - public class MGBAHawk : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable, ISaveRam + public class MGBAHawk : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable { IntPtr core; @@ -44,6 +45,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA ServiceProvider = ser; CoreComm = comm; + + InitStates(); } catch { @@ -76,6 +79,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public void ResetCounters() { Frame = 0; + _lagCount = 0; + IsLagFrame = false; } public CoreComm CoreComm { get; private set; } @@ -209,5 +214,85 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA } #endregion + + private void InitStates() + { + savebuff = new byte[LibmGBA.BizGetStateSize()]; + savebuff2 = new byte[savebuff.Length + 13]; + } + + private byte[] savebuff; + private byte[] savebuff2; + + public bool BinarySaveStatesPreferred + { + get { return true; } + } + + public void SaveStateText(TextWriter writer) + { + var tmp = SaveStateBinary(); + BizHawk.Common.BufferExtensions.BufferExtensions.SaveAsHexFast(tmp, writer); + } + public void LoadStateText(TextReader reader) + { + string hex = reader.ReadLine(); + byte[] state = new byte[hex.Length / 2]; + BizHawk.Common.BufferExtensions.BufferExtensions.ReadFromHexFast(state, hex); + LoadStateBinary(new BinaryReader(new MemoryStream(state))); + } + + public void SaveStateBinary(BinaryWriter writer) + { + LibmGBA.BizGetState(core, savebuff); + writer.Write(savebuff.Length); + writer.Write(savebuff); + + // other variables + writer.Write(IsLagFrame); + writer.Write(LagCount); + writer.Write(Frame); + } + + public void LoadStateBinary(BinaryReader reader) + { + int length = reader.ReadInt32(); + if (length != savebuff.Length) + throw new InvalidOperationException("Save buffer size mismatch!"); + reader.Read(savebuff, 0, length); + LibmGBA.BizPutState(core, savebuff); + + // other variables + IsLagFrame = reader.ReadBoolean(); + _lagCount = reader.ReadInt32(); + Frame = reader.ReadInt32(); + } + + public byte[] SaveStateBinary() + { + var ms = new MemoryStream(savebuff2, true); + var bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + if (ms.Position != savebuff2.Length) + throw new InvalidOperationException(); + ms.Close(); + return savebuff2; + } + + public int LagCount + { + get { return _lagCount; } + set { throw new InvalidOperationException(); } + } + private int _lagCount; + + public bool IsLagFrame { get; private set; } + + [FeatureNotImplemented] + public IInputCallbackSystem InputCallbacks + { + get { throw new NotImplementedException(); } + } } }