refactor TasLagLog to allow for gaps in the history. Note that this is a breaking .tasproj format change currently
This commit is contained in:
parent
9cedf68407
commit
3b9e54c250
|
@ -91,9 +91,9 @@ namespace BizHawk.Client.Common
|
||||||
if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie)
|
if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie)
|
||||||
{
|
{
|
||||||
bs.PutLump(BinaryStateLump.LagLog,
|
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)
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,30 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public class TasLagLog
|
public class TasLagLog
|
||||||
{
|
{
|
||||||
// TODO: Change this into a regular list.
|
private Dictionary<int, bool> _lagLog = new Dictionary<int, bool>();
|
||||||
private List<bool> _lagLog = new List<bool>();
|
private Dictionary<int, bool> _wasLag = new Dictionary<int, bool>();
|
||||||
private List<bool> _wasLag = new List<bool>();
|
|
||||||
|
|
||||||
public bool? this[int frame]
|
public bool? this[int frame]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (frame < _lagLog.Count)
|
bool lag;
|
||||||
|
var result = _lagLog.TryGetValue(frame, out lag);
|
||||||
|
if (result)
|
||||||
{
|
{
|
||||||
if (frame < 0)
|
return lag;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _lagLog[frame];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return Global.Emulator.AsInputPollable().IsLagFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,21 +35,10 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
if (!value.HasValue)
|
if (!value.HasValue)
|
||||||
{
|
{
|
||||||
_lagLog.RemoveAt(frame);
|
_lagLog.Remove(frame);
|
||||||
return;
|
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;
|
bool wasValue;
|
||||||
if (frame < _lagLog.Count)
|
if (frame < _lagLog.Count)
|
||||||
{
|
{
|
||||||
|
@ -68,147 +53,83 @@ namespace BizHawk.Client.Common
|
||||||
wasValue = _wasLag[frame];
|
wasValue = _wasLag[frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame == _wasLag.Count)
|
_wasLag[frame] = wasValue;
|
||||||
{
|
|
||||||
_wasLag.Add(wasValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_wasLag[frame] = wasValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame != 0)
|
if (frame != 0)
|
||||||
{
|
{
|
||||||
_wasLag[frame - 1] = _lagLog[frame - 1];
|
_wasLag[frame - 1] = _lagLog[frame - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame >= _lagLog.Count)
|
_lagLog[frame] = value.Value;
|
||||||
{
|
|
||||||
_lagLog.Add(value.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lagLog[frame] = value.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
// TODO: shouldn't _waslag get cleared too?
|
||||||
_lagLog.Clear();
|
_lagLog.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveFrom(int frame)
|
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);
|
_lagLog.Remove(f);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return frames.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveHistoryAt(int frame)
|
public void RemoveHistoryAt(int frame)
|
||||||
{
|
{
|
||||||
_wasLag.RemoveAt(frame);
|
_wasLag.Remove(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InsertHistoryAt(int frame, bool isLag)
|
public void InsertHistoryAt(int frame, bool isLag)
|
||||||
{
|
{
|
||||||
// LagLog was invalidated when the frame was inserted
|
_lagLog[frame] = isLag;
|
||||||
if (frame <= _lagLog.Count)
|
_wasLag[frame] = isLag;
|
||||||
{
|
|
||||||
_lagLog.Insert(frame, isLag);
|
|
||||||
}
|
|
||||||
|
|
||||||
_wasLag.Insert(frame, isLag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(BinaryWriter bw)
|
public void Save(TextWriter tw)
|
||||||
{
|
{
|
||||||
bw.Write((byte)1); // New saving format.
|
tw.WriteLine(JsonConvert.SerializeObject(_lagLog));
|
||||||
bw.Write(_lagLog.Count);
|
tw.WriteLine(JsonConvert.SerializeObject(_wasLag));
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(BinaryReader br)
|
public void Load(TextReader tr)
|
||||||
{
|
{
|
||||||
_lagLog.Clear();
|
// TODO: support legacy lag logs that were List<bool>
|
||||||
_wasLag.Clear();
|
_lagLog = JsonConvert.DeserializeObject<Dictionary<int, bool>>(tr.ReadLine());
|
||||||
int formatVersion = br.ReadByte();
|
_wasLag = JsonConvert.DeserializeObject<Dictionary<int, bool>>(tr.ReadLine());
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool? History(int frame)
|
public bool? History(int frame)
|
||||||
{
|
{
|
||||||
if (frame < _wasLag.Count)
|
bool wasLag;
|
||||||
|
var result = _wasLag.TryGetValue(frame, out wasLag);
|
||||||
|
if (result)
|
||||||
{
|
{
|
||||||
if (frame < 0)
|
return wasLag;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _wasLag[frame];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TasLagLog Clone()
|
|
||||||
{
|
|
||||||
return new TasLagLog
|
|
||||||
{
|
|
||||||
_lagLog = _lagLog.ToList(),
|
|
||||||
_wasLag = _wasLag.ToList()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FromLagLog(TasLagLog log)
|
public void FromLagLog(TasLagLog log)
|
||||||
{
|
{
|
||||||
_lagLog = log._lagLog.ToList();
|
_lagLog = log._lagLog.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||||
_wasLag = log._wasLag.ToList();
|
_wasLag = log._wasLag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartFromFrame(int index)
|
public void StartFromFrame(int index)
|
||||||
{
|
{
|
||||||
_lagLog.RemoveRange(0, index);
|
for (int i = 0; i < index; i++)
|
||||||
_wasLag.RemoveRange(0, index);
|
{
|
||||||
|
_lagLog.Remove(i);
|
||||||
|
_wasLag.Remove(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace BizHawk.Client.Common
|
||||||
// TasProj extras
|
// TasProj extras
|
||||||
bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(_stateManager.Settings.ToString()));
|
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()));
|
bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString()));
|
||||||
|
|
||||||
if (StartsFromSavestate)
|
if (StartsFromSavestate)
|
||||||
|
@ -179,9 +179,9 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
// TasMovie enhanced information
|
// 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)
|
bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
|
||||||
|
|
Loading…
Reference in New Issue