From 3b9e54c250f559f76d8c1fb2b3d65bf2bc26a3b8 Mon Sep 17 00:00:00 2001 From: adelikat Date: Sat, 15 Jun 2019 12:11:52 -0500 Subject: [PATCH] refactor TasLagLog to allow for gaps in the history. Note that this is a breaking .tasproj format change currently --- BizHawk.Client.Common/SavestateManager.cs | 8 +- .../movie/tasproj/TasLagLog.cs | 155 +++++------------- .../movie/tasproj/TasMovie.IO.cs | 6 +- 3 files changed, 45 insertions(+), 124 deletions(-) diff --git a/BizHawk.Client.Common/SavestateManager.cs b/BizHawk.Client.Common/SavestateManager.cs index 8f250bc135..9b4051be49 100644 --- a/BizHawk.Client.Common/SavestateManager.cs +++ b/BizHawk.Client.Common/SavestateManager.cs @@ -91,9 +91,9 @@ namespace BizHawk.Client.Common if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie) { bs.PutLump(BinaryStateLump.LagLog, - delegate(BinaryWriter bw) + delegate(TextWriter tw) { - (Global.MovieSession.Movie as TasMovie).TasLagLog.Save(bw); + (Global.MovieSession.Movie as TasMovie).TasLagLog.Save(tw); }); } } @@ -195,9 +195,9 @@ namespace BizHawk.Client.Common if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie) { - bl.GetLump(BinaryStateLump.LagLog, false, delegate(BinaryReader br, long length) + bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { - ((TasMovie)Global.MovieSession.Movie).TasLagLog.Load(br); + ((TasMovie)Global.MovieSession.Movie).TasLagLog.Load(tr); }); } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs b/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs index 1be5406de8..29a45919ce 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasLagLog.cs @@ -1,34 +1,30 @@ using System.Collections.Generic; using System.IO; using System.Linq; - +using Newtonsoft.Json; using BizHawk.Emulation.Common.IEmulatorExtensions; namespace BizHawk.Client.Common { public class TasLagLog { - // TODO: Change this into a regular list. - private List _lagLog = new List(); - private List _wasLag = new List(); + private Dictionary _lagLog = new Dictionary(); + private Dictionary _wasLag = new Dictionary(); public bool? this[int frame] { get { - if (frame < _lagLog.Count) + bool lag; + var result = _lagLog.TryGetValue(frame, out lag); + if (result) { - if (frame < 0) - { - return null; - } - - return _lagLog[frame]; + return lag; } - if (frame == Global.Emulator.Frame && frame == _lagLog.Count) + // TODO: don't do this here, the calling code should decide if showing the current emulator state is the right decision + if (frame == Global.Emulator.Frame) { - ////LagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame; // Note: Side effects! return Global.Emulator.AsInputPollable().IsLagFrame; } @@ -39,21 +35,10 @@ namespace BizHawk.Client.Common { if (!value.HasValue) { - _lagLog.RemoveAt(frame); + _lagLog.Remove(frame); return; } - if (frame < 0) - { - return; // Nothing to do - } - - if (frame > _lagLog.Count) - { - System.Diagnostics.Debug.Print($"Lag Log error. f{frame}, log: {_lagLog.Count}"); - return; // Can this break anything? - } - bool wasValue; if (frame < _lagLog.Count) { @@ -68,147 +53,83 @@ namespace BizHawk.Client.Common wasValue = _wasLag[frame]; } - if (frame == _wasLag.Count) - { - _wasLag.Add(wasValue); - } - else - { - _wasLag[frame] = wasValue; - } + _wasLag[frame] = wasValue; if (frame != 0) { _wasLag[frame - 1] = _lagLog[frame - 1]; } - if (frame >= _lagLog.Count) - { - _lagLog.Add(value.Value); - } - else - { - _lagLog[frame] = value.Value; - } + _lagLog[frame] = value.Value; } } public void Clear() { + // TODO: shouldn't _waslag get cleared too? _lagLog.Clear(); } public bool RemoveFrom(int frame) { - if (_lagLog.Count > frame && frame >= 0) + var frames = _lagLog.Keys.Where(k => k > frame).ToList(); + foreach (var f in frames) { - _lagLog.RemoveRange(frame + 1, _lagLog.Count - frame - 1); - return true; + _lagLog.Remove(f); } - return false; + return frames.Any(); } public void RemoveHistoryAt(int frame) { - _wasLag.RemoveAt(frame); + _wasLag.Remove(frame); } public void InsertHistoryAt(int frame, bool isLag) { - // LagLog was invalidated when the frame was inserted - if (frame <= _lagLog.Count) - { - _lagLog.Insert(frame, isLag); - } - - _wasLag.Insert(frame, isLag); + _lagLog[frame] = isLag; + _wasLag[frame] = isLag; } - public void Save(BinaryWriter bw) + public void Save(TextWriter tw) { - bw.Write((byte)1); // New saving format. - bw.Write(_lagLog.Count); - bw.Write(_wasLag.Count); - for (int i = 0; i < _lagLog.Count; i++) - { - bw.Write(_lagLog[i]); - bw.Write(_wasLag[i]); - } - - for (int i = _lagLog.Count; i < _wasLag.Count; i++) - { - bw.Write(_wasLag[i]); - } + tw.WriteLine(JsonConvert.SerializeObject(_lagLog)); + tw.WriteLine(JsonConvert.SerializeObject(_wasLag)); } - public void Load(BinaryReader br) + public void Load(TextReader tr) { - _lagLog.Clear(); - _wasLag.Clear(); - int formatVersion = br.ReadByte(); - if (formatVersion == 0) - { - int length = (br.ReadByte() << 8) | formatVersion; // The first byte should be a part of length. - length = (br.ReadInt16() << 16) | length; - for (int i = 0; i < length; i++) - { - br.ReadInt32(); - _lagLog.Add(br.ReadBoolean()); - _wasLag.Add(_lagLog.Last()); - } - } - else if (formatVersion == 1) - { - int length = br.ReadInt32(); - int lenWas = br.ReadInt32(); - for (int i = 0; i < length; i++) - { - _lagLog.Add(br.ReadBoolean()); - _wasLag.Add(br.ReadBoolean()); - } - - for (int i = length; i < lenWas; i++) - { - _wasLag.Add(br.ReadBoolean()); - } - } + // TODO: support legacy lag logs that were List + _lagLog = JsonConvert.DeserializeObject>(tr.ReadLine()); + _wasLag = JsonConvert.DeserializeObject>(tr.ReadLine()); } public bool? History(int frame) { - if (frame < _wasLag.Count) + bool wasLag; + var result = _wasLag.TryGetValue(frame, out wasLag); + if (result) { - if (frame < 0) - { - return null; - } - - return _wasLag[frame]; + return wasLag; } return null; } - public TasLagLog Clone() - { - return new TasLagLog - { - _lagLog = _lagLog.ToList(), - _wasLag = _wasLag.ToList() - }; - } - public void FromLagLog(TasLagLog log) { - _lagLog = log._lagLog.ToList(); - _wasLag = log._wasLag.ToList(); + _lagLog = log._lagLog.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + _wasLag = log._wasLag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } public void StartFromFrame(int index) { - _lagLog.RemoveRange(0, index); - _wasLag.RemoveRange(0, index); + for (int i = 0; i < index; i++) + { + _lagLog.Remove(i); + _wasLag.Remove(i); + } } } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs index 9cbc90ebcb..4f0f27339f 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs @@ -29,7 +29,7 @@ namespace BizHawk.Client.Common // TasProj extras bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(_stateManager.Settings.ToString())); - bs.PutLump(BinaryStateLump.LagLog, (BinaryWriter bw) => _lagLog.Save(bw)); + bs.PutLump(BinaryStateLump.LagLog, tw => _lagLog.Save(tw)); bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString())); if (StartsFromSavestate) @@ -179,9 +179,9 @@ namespace BizHawk.Client.Common } // TasMovie enhanced information - bl.GetLump(BinaryStateLump.LagLog, false, delegate(BinaryReader br, long length) + bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { - _lagLog.Load(br); + _lagLog.Load(tr); }); bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)