using BizHawk.Emulation.Common; using System.IO; using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Jellyfish.Virtu; using Newtonsoft.Json.Bson; 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 { get { return true; } } public override bool CanWrite { get { return 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 { get { return true; } } private void SerializeEverything(JsonWriter w) { // this is much faster than other possibilities for serialization w.WriteStartObject(); w.WritePropertyName("Frame"); w.WriteValue(Frame); w.WritePropertyName("LagCount"); w.WriteValue(LagCount); w.WritePropertyName("IsLagFrame"); w.WriteValue(IsLagFrame); w.WritePropertyName("CurrentDisk"); w.WriteValue(CurrentDisk); 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; // should not be needed. // InitDisk(); } private class OtherData { public int Frame; public int LagCount; public bool IsLagFrame; public int CurrentDisk; public Machine Core; } private void InitSaveStates() { ser.Converters.Add(new CoreConverter()); } private 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(); } } }