BizHawk/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IStatable.cs

159 lines
4.3 KiB
C#

using System;
using System.IO;
using BizHawk.Emulation.Common;
using Jellyfish.Virtu;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Linq;
namespace BizHawk.Emulation.Cores.Computers.AppleII
{
public partial class AppleII : IStatable
{
private class CoreConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Machine);
}
public override bool CanRead => true;
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// uses its own serialization context: intentional
return Machine.Deserialize(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public bool BinarySaveStatesPreferred => true;
private void SerializeEverything(JsonWriter w)
{
// this is much faster than other possibilities for serialization
w.WriteStartObject();
w.WritePropertyName(nameof(Frame));
w.WriteValue(Frame);
w.WritePropertyName(nameof(LagCount));
w.WriteValue(LagCount);
w.WritePropertyName(nameof(IsLagFrame));
w.WriteValue(IsLagFrame);
w.WritePropertyName(nameof(CurrentDisk));
w.WriteValue(CurrentDisk);
w.WritePropertyName("PreviousDiskPressed");
w.WriteValue(_prevPressed);
w.WritePropertyName("NextDiskPressed");
w.WriteValue(_nextPressed);
w.WritePropertyName("Core");
_machine.Serialize(w);
w.WriteEndObject();
}
private void DeserializeEverything(JsonReader r)
{
var o = (OtherData)_ser.Deserialize(r, typeof(OtherData));
Frame = o.Frame;
LagCount = o.LagCount;
IsLagFrame = o.IsLagFrame;
CurrentDisk = o.CurrentDisk;
_machine = o.Core;
_prevPressed = o.PreviousDiskPressed;
_nextPressed = o.NextDiskPressed;
// since _machine was replaced, we need to reload settings from frontend
PutSettings(_settings);
}
public class OtherData
{
public int Frame;
public int LagCount;
public bool IsLagFrame;
public int CurrentDisk;
public bool PreviousDiskPressed;
public bool NextDiskPressed;
public Machine Core;
}
private void InitSaveStates()
{
_ser.Converters.Add(new CoreConverter());
}
private readonly JsonSerializer _ser = new JsonSerializer();
public void SaveStateText(TextWriter writer)
{
SerializeEverything(new JsonTextWriter(writer) { Formatting = Formatting.None });
}
public void LoadStateText(TextReader reader)
{
DeserializeEverything(new JsonTextReader(reader));
}
/*
* These are horrible; the LoadStateBinary() takes over 10x as long as LoadStateText()
* Until we figure out why JSON.NET's BSONwriter sucks and how to fix it, stick with text-as-binary
public void SaveStateBinary(BinaryWriter writer)
{
SerializeEverything(new BsonWriter(writer));
}
public void LoadStateBinary(BinaryReader reader)
{
DeserializeEverything(new BsonReader(reader));
}
*/
/*
public void SaveStateBinary(BinaryWriter writer)
{
var tw = new StreamWriter(writer.BaseStream, new System.Text.UTF8Encoding(false));
SaveStateText(tw);
tw.Flush();
}
public void LoadStateBinary(BinaryReader reader)
{
var tr = new StreamReader(reader.BaseStream, System.Text.Encoding.UTF8);
LoadStateText(tr);
}*/
// these homemade classes edge out the stock ones slightly, but need BufferedStream to not be bad
public void SaveStateBinary(BinaryWriter writer)
{
var buffer = new BufferedStream(writer.BaseStream, 16384);
var bw2 = new BinaryWriter(buffer);
SerializeEverything(new LBW(bw2));
bw2.Flush();
buffer.Flush();
}
public void LoadStateBinary(BinaryReader reader)
{
var buffer = new BufferedStream(reader.BaseStream, 16384);
var br2 = new BinaryReader(buffer);
DeserializeEverything(new LBR(br2));
}
public byte[] SaveStateBinary()
{
// our savestate array can be of varying sizes, so this can't be too clever
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
return stream.ToArray();
}
}
}