diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs index 5919b0b8f5..803c45c6ec 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs @@ -159,7 +159,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA /// /// save saveram to a byte buffer /// - /// buffer generated by core. coyp from, but do not modify + /// buffer generated by core. copy from, but do not modify /// length of buffer /// success [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] @@ -184,5 +184,32 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA /// [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void libmeteor_clearsaveram(); + + /// + /// serialize state + /// + /// buffer generated by core + /// size of buffer + /// success + [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern bool libmeteor_savestate(ref IntPtr data, ref uint size); + + /// + /// destroy a buffer previously returned by libmeteor_savestate() to avoid leakage + /// + /// + [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void libmeteor_savestate_destroy(IntPtr data); + + /// + /// unserialize state + /// + /// + /// + /// success + [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern bool libmeteor_loadstate(byte[] data, uint size); + + } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs index a04ee143b4..d8e0133456 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs @@ -94,20 +94,63 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA #region savestates + byte[] SaveCoreBinary() + { + IntPtr ndata = IntPtr.Zero; + uint nsize = 0; + if (!LibMeteor.libmeteor_savestate(ref ndata, ref nsize)) + throw new Exception("libmeteor_savestate() failed!"); + if (ndata == IntPtr.Zero || nsize == 0) + throw new Exception("libmeteor_savestate() returned bad!"); + + byte[] ret = new byte[nsize]; + Marshal.Copy(ndata, ret, 0, (int)nsize); + LibMeteor.libmeteor_savestate_destroy(ndata); + return ret; + } + + void LoadCoreBinary(byte[] data) + { + if (!LibMeteor.libmeteor_loadstate(data, (uint)data.Length)) + throw new Exception("libmeteor_loadstate() failed!"); + } + public void SaveStateText(System.IO.TextWriter writer) { + var temp = SaveStateBinary(); + temp.SaveAsHex(writer); + // write extra copy of stuff we don't use + writer.WriteLine("Frame {0}", Frame); } public void LoadStateText(System.IO.TextReader reader) { + string hex = reader.ReadLine(); + byte[] state = new byte[hex.Length / 2]; + state.ReadFromHex(hex); + LoadStateBinary(new BinaryReader(new MemoryStream(state))); } public void SaveStateBinary(System.IO.BinaryWriter writer) { + byte[] data = SaveCoreBinary(); + writer.Write(data.Length); + writer.Write(data); + // other variables + writer.Write(IsLagFrame); + writer.Write(LagCount); + writer.Write(Frame); } public void LoadStateBinary(System.IO.BinaryReader reader) { + int length = reader.ReadInt32(); + byte[] data = reader.ReadBytes(length); + LoadCoreBinary(data); + // other variables + IsLagFrame = reader.ReadBoolean(); + LagCount = reader.ReadInt32(); + Frame = reader.ReadInt32(); } public byte[] SaveStateBinary() diff --git a/BizHawk.MultiClient/output/dll/libmeteor.dll b/BizHawk.MultiClient/output/dll/libmeteor.dll index a45555a0b7..adb24f1a77 100644 Binary files a/BizHawk.MultiClient/output/dll/libmeteor.dll and b/BizHawk.MultiClient/output/dll/libmeteor.dll differ diff --git a/libmeteor/cinterface.cpp b/libmeteor/cinterface.cpp index 98f5f79144..9f956d01a2 100644 --- a/libmeteor/cinterface.cpp +++ b/libmeteor/cinterface.cpp @@ -1,6 +1,7 @@ #include "ameteor.hpp" #include "ameteor/cartmem.hpp" #include "source/debug.hpp" +#include #define EXPORT extern "C" __declspec(dllexport) @@ -131,8 +132,6 @@ EXPORT void libmeteor_frameadvance() AMeteor::Run(10000000); } -// TODO: serialize, unserialize - EXPORT void libmeteor_loadrom(const void *data, unsigned size) { AMeteor::_memory.LoadRom((const uint8_t*)data, size); @@ -173,5 +172,35 @@ EXPORT void libmeteor_clearsaveram() AMeteor::_memory.DeleteCart(); } +EXPORT int libmeteor_savestate(void **data, unsigned *size) +{ + if (!data || !size) + return 0; + + std::ostringstream ss = std::ostringstream(std::ios_base::binary); + AMeteor::SaveState(ss); + + std::string s = ss.str(); + + void *ret = std::malloc(s.size()); + if (!ret) + return 0; + std::memcpy(ret, s.data(), s.size()); + *data = ret; + *size = s.size(); + return 1; +} + +EXPORT void libmeteor_savestate_destroy(void *data) +{ + std::free(data); +} + +EXPORT int libmeteor_loadstate(const void *data, unsigned size) +{ + std::istringstream ss = std::istringstream(std::string((const char*)data, size), std::ios_base::binary); + return AMeteor::LoadState(ss); +} + // TODO: cartram and system bus memory domains diff --git a/libmeteor/source/memory.cpp b/libmeteor/source/memory.cpp index f82ac18aec..6fb2b01c84 100644 --- a/libmeteor/source/memory.cpp +++ b/libmeteor/source/memory.cpp @@ -519,7 +519,9 @@ namespace AMeteor bool b = m_brom; SS_WRITE_VAR(b); if (b) + { SS_WRITE_DATA(m_brom, 0x00004000); + } SS_WRITE_DATA(m_wbram, 0x00040000); SS_WRITE_DATA(m_wcram, 0x00008000); SS_WRITE_DATA(m_pram , 0x00000400); @@ -545,9 +547,13 @@ namespace AMeteor bool b; SS_READ_VAR(b); if (b) + { SS_READ_DATA(m_brom , 0x00004000); + } else + { UnloadBios(); + } SS_READ_DATA(m_wbram, 0x00040000); SS_READ_DATA(m_wcram, 0x00008000); SS_READ_DATA(m_pram , 0x00000400);