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