gba: enable savestates. in the process find and fix an absolutely retarded bug with core savestate loading and bios. fuck #define forever.

This commit is contained in:
goyuken 2012-11-24 21:23:50 +00:00
parent b9fac0643a
commit 366370301f
5 changed files with 108 additions and 3 deletions

View File

@ -159,7 +159,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// <summary>
/// save saveram to a byte buffer
/// </summary>
/// <param name="data">buffer generated by core. coyp from, but do not modify</param>
/// <param name="data">buffer generated by core. copy from, but do not modify</param>
/// <param name="size">length of buffer</param>
/// <returns>success</returns>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
@ -184,5 +184,32 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// </summary>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_clearsaveram();
/// <summary>
/// serialize state
/// </summary>
/// <param name="data">buffer generated by core</param>
/// <param name="size">size of buffer</param>
/// <returns>success</returns>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool libmeteor_savestate(ref IntPtr data, ref uint size);
/// <summary>
/// destroy a buffer previously returned by libmeteor_savestate() to avoid leakage
/// </summary>
/// <param name="data"></param>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_savestate_destroy(IntPtr data);
/// <summary>
/// unserialize state
/// </summary>
/// <param name="data"></param>
/// <param name="size"></param>
/// <returns>success</returns>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool libmeteor_loadstate(byte[] data, uint size);
}
}

View File

@ -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()

View File

@ -1,6 +1,7 @@
#include "ameteor.hpp"
#include "ameteor/cartmem.hpp"
#include "source/debug.hpp"
#include <sstream>
#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

View File

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