gameboy: tweak text savestates a bit in preparation to reuse some code for the wonderswan savestates
This commit is contained in:
parent
63c361f4e2
commit
8f87c2e854
|
@ -35,6 +35,10 @@
|
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\References\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
@ -67,6 +71,7 @@
|
|||
<Compile Include="Serializer.cs" />
|
||||
<Compile Include="SettingsUtil.cs" />
|
||||
<Compile Include="SwitcherStream.cs" />
|
||||
<Compile Include="TextState.cs" />
|
||||
<Compile Include="UndoHistory.cs" />
|
||||
<Compile Include="Util.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -238,8 +238,6 @@
|
|||
<Compile Include="Consoles\Nintendo\Gameboy\GambatteLink.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.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\Meteor.cs" />
|
||||
<Compile Include="Consoles\Nintendo\N64\N64Input.cs" />
|
||||
|
|
|
@ -482,19 +482,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
JsonSerializer ser = new JsonSerializer() { Formatting = Formatting.Indented };
|
||||
|
||||
// other data in the text state besides core
|
||||
class TextStateData
|
||||
{
|
||||
public int Frame;
|
||||
public int LagCount;
|
||||
public bool IsLagFrame;
|
||||
public ulong _cycleCount;
|
||||
public uint frameOverflow;
|
||||
}
|
||||
|
||||
public void SaveStateText(System.IO.TextWriter writer)
|
||||
{
|
||||
var s = new TextState();
|
||||
var s = new TextState<TextStateData>();
|
||||
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;
|
||||
var ff = s.GetFunctionPointers();
|
||||
LibGambatte.gambatte_newstatesave_ex(GambatteState, ref ff);
|
||||
s.ExtraData.IsLagFrame = IsLagFrame;
|
||||
s.ExtraData.LagCount = LagCount;
|
||||
s.ExtraData.Frame = Frame;
|
||||
s.ExtraData.frameOverflow = frameOverflow;
|
||||
s.ExtraData._cycleCount = _cycleCount;
|
||||
|
||||
ser.Serialize(writer, s);
|
||||
// write extra copy of stuff we don't use
|
||||
|
@ -504,17 +512,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
public void LoadStateText(System.IO.TextReader reader)
|
||||
{
|
||||
var s = (TextState)ser.Deserialize(reader, typeof(TextState));
|
||||
var s = (TextState<TextStateData>)ser.Deserialize(reader, typeof(TextState<TextStateData>));
|
||||
s.Prepare();
|
||||
LibGambatte.gambatte_newstateload_ex(GambatteState,
|
||||
s.Load,
|
||||
s.EnterSection,
|
||||
s.ExitSection);
|
||||
IsLagFrame = s.IsLagFrame;
|
||||
LagCount = s.LagCount;
|
||||
Frame = s.Frame;
|
||||
frameOverflow = s.frameOverflow;
|
||||
_cycleCount = s._cycleCount;
|
||||
var ff = s.GetFunctionPointers();
|
||||
LibGambatte.gambatte_newstateload_ex(GambatteState, ref ff);
|
||||
IsLagFrame = s.ExtraData.IsLagFrame;
|
||||
LagCount = s.ExtraData.LagCount;
|
||||
Frame = s.ExtraData.Frame;
|
||||
frameOverflow = s.ExtraData.frameOverflow;
|
||||
_cycleCount = s.ExtraData._cycleCount;
|
||||
}
|
||||
|
||||
public void SaveStateBinary(System.IO.BinaryWriter writer)
|
||||
|
@ -560,6 +566,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
public bool BinarySaveStatesPreferred { get { return true; } }
|
||||
|
||||
/*
|
||||
void DebugStates()
|
||||
{
|
||||
var sd = new StateDebug();
|
||||
|
@ -570,7 +577,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
LibGambatte.gambatte_newstatesave_ex(GambatteState, Save, EnterSection, ExitSection);
|
||||
LibGambatte.gambatte_newstateload_ex(GambatteState, Load, EnterSection, ExitSection);
|
||||
}
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
|
@ -306,10 +307,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
public delegate void SectionFunction(string name);
|
||||
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_newstatesave_ex(IntPtr core, DataFunction Save, SectionFunction EnterSection, SectionFunction ExitSection);
|
||||
public static extern void gambatte_newstatesave_ex(IntPtr core, ref TextStateFPtrs ff);
|
||||
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_newstateload_ex(IntPtr core, DataFunction Load, SectionFunction EnterSection, SectionFunction ExitSection);
|
||||
public static extern void gambatte_newstateload_ex(IntPtr core, ref TextStateFPtrs ff);
|
||||
|
||||
/// <summary>
|
||||
/// ROM header title of currently loaded ROM image.
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
/*
|
||||
* the new gambatte savestater includes functionality that
|
||||
* could be used to make structured text mode savestates. this module just does a bit of
|
||||
* sanity checking using that capability
|
||||
*/
|
||||
|
||||
public class StateDebug
|
||||
{
|
||||
Dictionary<string, byte[]> Data = new Dictionary<string, byte[]>();
|
||||
|
||||
string Path = "/";
|
||||
|
||||
List<string> SaveHistory = new List<string>();
|
||||
int LoadHistoryPos = 0;
|
||||
|
||||
public void Save(IntPtr data, int length, string name)
|
||||
{
|
||||
byte[] d = new byte[length];
|
||||
Marshal.Copy(data, d, 0, length);
|
||||
string s = Path + name;
|
||||
SaveHistory.Add(s);
|
||||
if (Data.ContainsKey(s))
|
||||
throw new Exception("Already stored");
|
||||
Data[s] = d;
|
||||
}
|
||||
|
||||
public void Load(IntPtr data, int length, string name)
|
||||
{
|
||||
string s = Path + name;
|
||||
byte[] d = Data[s];
|
||||
if (SaveHistory[LoadHistoryPos++] != s)
|
||||
throw new Exception("Loading out of order!");
|
||||
Marshal.Copy(d, 0, data, length);
|
||||
}
|
||||
|
||||
public void EnterSection(string name)
|
||||
{
|
||||
Path = Path + name + '/';
|
||||
}
|
||||
|
||||
public void ExitSection(string name)
|
||||
{
|
||||
int i = Path.Substring(0, Path.Length - 1).LastIndexOf('/');
|
||||
if (i < 0)
|
||||
throw new Exception("Couldn't unwind stack!");
|
||||
string newPath = Path.Substring(0, i + 1);
|
||||
string unwind = Path.Substring(0, Path.Length - 1).Substring(i + 1);
|
||||
if (unwind != name)
|
||||
throw new Exception("Left wrong section!");
|
||||
Path = newPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
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;
|
||||
|
||||
}
|
||||
}
|
|
@ -168,23 +168,17 @@ GBEXPORT int gambatte_newstateload(void *core, const char *data, long len)
|
|||
return !loader.Overflow() && loader.GetLength() == len;
|
||||
}
|
||||
|
||||
GBEXPORT void gambatte_newstatesave_ex(void *core,
|
||||
void (*Save_)(const void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name))
|
||||
GBEXPORT void gambatte_newstatesave_ex(void *core, FPtrs *ff)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalFunctions saver(Save_, NULL, EnterSection_, ExitSection_);
|
||||
NewStateExternalFunctions saver(ff);
|
||||
g->SyncState<false>(&saver);
|
||||
}
|
||||
|
||||
GBEXPORT void gambatte_newstateload_ex(void *core,
|
||||
void (*Load_)(void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name))
|
||||
GBEXPORT void gambatte_newstateload_ex(void *core, FPtrs *ff)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalFunctions loader(NULL, Load_, EnterSection_, ExitSection_);
|
||||
NewStateExternalFunctions loader(ff);
|
||||
g->SyncState<true>(&loader);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,15 +40,11 @@ void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name)
|
|||
length += size;
|
||||
}
|
||||
|
||||
NewStateExternalFunctions::NewStateExternalFunctions(
|
||||
void (*Save_)(const void *ptr, size_t size, const char *name),
|
||||
void (*Load_)(void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name))
|
||||
:Save_(Save_),
|
||||
Load_(Load_),
|
||||
EnterSection_(EnterSection_),
|
||||
ExitSection_(ExitSection_)
|
||||
NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff)
|
||||
:Save_(ff->Save_),
|
||||
Load_(ff->Load_),
|
||||
EnterSection_(ff->EnterSection_),
|
||||
ExitSection_(ff->ExitSection_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,14 @@ public:
|
|||
virtual void Load(void *ptr, size_t size, const char *name);
|
||||
};
|
||||
|
||||
struct FPtrs
|
||||
{
|
||||
void (*Save_)(const void *ptr, size_t size, const char *name);
|
||||
void (*Load_)(void *ptr, size_t size, const char *name);
|
||||
void (*EnterSection_)(const char *name);
|
||||
void (*ExitSection_)(const char *name);
|
||||
};
|
||||
|
||||
class NewStateExternalFunctions : public NewState
|
||||
{
|
||||
private:
|
||||
|
@ -50,11 +58,7 @@ private:
|
|||
void (*EnterSection_)(const char *name);
|
||||
void (*ExitSection_)(const char *name);
|
||||
public:
|
||||
NewStateExternalFunctions(
|
||||
void (*Save_)(const void *ptr, size_t size, const char *name),
|
||||
void (*Load_)(void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name));
|
||||
NewStateExternalFunctions(const FPtrs *ff);
|
||||
virtual void Save(const void *ptr, size_t size, const char *name);
|
||||
virtual void Load(void *ptr, size_t size, const char *name);
|
||||
virtual void EnterSection(const char *name);
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue