gambatte: support text savestates
This commit is contained in:
parent
bcf2924a23
commit
1ef04c0cb5
|
@ -238,6 +238,7 @@
|
||||||
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
|
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
|
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\Gameboy\StateDebug.cs" />
|
<Compile Include="Consoles\Nintendo\Gameboy\StateDebug.cs" />
|
||||||
|
<Compile Include="Consoles\Nintendo\Gameboy\TextState.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\GBA\LibMeteor.cs" />
|
<Compile Include="Consoles\Nintendo\GBA\LibMeteor.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />
|
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\N64\N64Input.cs" />
|
<Compile Include="Consoles\Nintendo\N64\N64Input.cs" />
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.IO;
|
||||||
|
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
{
|
{
|
||||||
|
@ -438,20 +439,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
throw new Exception("gambatte_newstateload() returned false");
|
throw new Exception("gambatte_newstateload() returned false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonSerializer ser = new JsonSerializer() { Formatting = Formatting.Indented };
|
||||||
|
|
||||||
public void SaveStateText(System.IO.TextWriter writer)
|
public void SaveStateText(System.IO.TextWriter writer)
|
||||||
{
|
{
|
||||||
var temp = SaveStateBinary();
|
var s = new TextState();
|
||||||
temp.SaveAsHex(writer);
|
s.Prepare();
|
||||||
|
LibGambatte.gambatte_newstatesave_ex(GambatteState,
|
||||||
|
s.Save,
|
||||||
|
s.EnterSection,
|
||||||
|
s.ExitSection);
|
||||||
|
s.IsLagFrame = IsLagFrame;
|
||||||
|
s.LagCount = LagCount;
|
||||||
|
s.Frame = Frame;
|
||||||
|
s.frameOverflow = frameOverflow;
|
||||||
|
s._cycleCount = _cycleCount;
|
||||||
|
|
||||||
|
ser.Serialize(writer, s);
|
||||||
// write extra copy of stuff we don't use
|
// write extra copy of stuff we don't use
|
||||||
|
writer.WriteLine();
|
||||||
writer.WriteLine("Frame {0}", Frame);
|
writer.WriteLine("Frame {0}", Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadStateText(System.IO.TextReader reader)
|
public void LoadStateText(System.IO.TextReader reader)
|
||||||
{
|
{
|
||||||
string hex = reader.ReadLine();
|
var s = (TextState)ser.Deserialize(reader, typeof(TextState));
|
||||||
byte[] state = new byte[hex.Length / 2];
|
s.Prepare();
|
||||||
state.ReadFromHex(hex);
|
LibGambatte.gambatte_newstateload_ex(GambatteState,
|
||||||
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
|
s.Load,
|
||||||
|
s.EnterSection,
|
||||||
|
s.ExitSection);
|
||||||
|
IsLagFrame = s.IsLagFrame;
|
||||||
|
LagCount = s.LagCount;
|
||||||
|
Frame = s.Frame;
|
||||||
|
frameOverflow = s.frameOverflow;
|
||||||
|
_cycleCount = s._cycleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveStateBinary(System.IO.BinaryWriter writer)
|
public void SaveStateBinary(System.IO.BinaryWriter writer)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
|
{
|
||||||
|
public class TextState
|
||||||
|
{
|
||||||
|
public class Node
|
||||||
|
{
|
||||||
|
public Dictionary<string, byte[]> Data = new Dictionary<string, byte[]>();
|
||||||
|
public Dictionary<string, Node> Objects = new Dictionary<string, Node>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node Root = new Node();
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
Stack<Node> Nodes;
|
||||||
|
[JsonIgnore]
|
||||||
|
Node Current { get { return Nodes.Peek(); } }
|
||||||
|
|
||||||
|
public void Prepare()
|
||||||
|
{
|
||||||
|
Nodes = new Stack<Node>();
|
||||||
|
Nodes.Push(Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(IntPtr data, int length, string name)
|
||||||
|
{
|
||||||
|
byte[] d = new byte[length];
|
||||||
|
Marshal.Copy(data, d, 0, length);
|
||||||
|
Current.Data.Add(name, d);
|
||||||
|
}
|
||||||
|
public void Load(IntPtr data, int length, string name)
|
||||||
|
{
|
||||||
|
byte[] d = Current.Data[name];
|
||||||
|
Marshal.Copy(d, 0, data, length);
|
||||||
|
}
|
||||||
|
public void EnterSection(string name)
|
||||||
|
{
|
||||||
|
Node next = null;
|
||||||
|
Current.Objects.TryGetValue(name, out next);
|
||||||
|
if (next == null)
|
||||||
|
{
|
||||||
|
next = new Node();
|
||||||
|
Current.Objects.Add(name, next);
|
||||||
|
}
|
||||||
|
Nodes.Push(next);
|
||||||
|
}
|
||||||
|
public void ExitSection(string name)
|
||||||
|
{
|
||||||
|
Node last = Nodes.Pop();
|
||||||
|
if (Current.Objects[name] != last)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// other data besides the core
|
||||||
|
public int Frame;
|
||||||
|
public int LagCount;
|
||||||
|
public bool IsLagFrame;
|
||||||
|
public ulong _cycleCount;
|
||||||
|
public uint frameOverflow;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue