-More StateHistory names

-Smarter state history management
TAStudio: A few bugfixes and performance boosts
This commit is contained in:
SuuperW 2015-03-03 06:56:45 +00:00
parent b82e19f230
commit 25e54f4390
10 changed files with 166 additions and 72 deletions

View File

@ -23,8 +23,8 @@ namespace BizHawk.Client.Common
// TasMovie // TasMovie
LagLog, LagLog,
Greenzone, // Greenzone actually means StateHistory. Changing these two names would break previous save files, though. StateHistory,
GreenzoneSettings, StateHistorySettings,
Markers, Markers,
ClientSettings, ClientSettings,
VerificationLog VerificationLog
@ -58,8 +58,8 @@ namespace BizHawk.Client.Common
// TasMovie // TasMovie
AddLumpName(BinaryStateLump.LagLog, "LagLog"); AddLumpName(BinaryStateLump.LagLog, "LagLog");
AddLumpName(BinaryStateLump.Greenzone, "GreenZone"); AddLumpName(BinaryStateLump.StateHistory, "GreenZone");
AddLumpName(BinaryStateLump.GreenzoneSettings, "GreenZoneSettings.txt"); AddLumpName(BinaryStateLump.StateHistorySettings, "GreenZoneSettings.txt");
AddLumpName(BinaryStateLump.Markers, "Markers.txt"); AddLumpName(BinaryStateLump.Markers, "Markers.txt");
AddLumpName(BinaryStateLump.ClientSettings, "ClientSettings.json"); AddLumpName(BinaryStateLump.ClientSettings, "ClientSettings.json");
AddLumpName(BinaryStateLump.VerificationLog, "VerificationLog.txt"); AddLumpName(BinaryStateLump.VerificationLog, "VerificationLog.txt");

View File

@ -8,16 +8,9 @@ namespace BizHawk.Client.Common
{ {
get get
{ {
var key = button var key = button.Replace("Key ", "");
.Replace("P1 ", "") if (key.StartsWith("P") && key[1] >= '0' && key[1] <= '9')
.Replace("P2 ", "") key = key.Substring(3);
.Replace("P3 ", "")
.Replace("P4 ", "")
.Replace("P5 ", "")
.Replace("P6 ", "")
.Replace("P7 ", "")
.Replace("P8 ", "")
.Replace("Key ", "");
if (SystemOverrides.ContainsKey(Global.Emulator.SystemId) && SystemOverrides[Global.Emulator.SystemId].ContainsKey(key)) if (SystemOverrides.ContainsKey(Global.Emulator.SystemId) && SystemOverrides[Global.Emulator.SystemId].ContainsKey(key))
{ {

View File

@ -54,12 +54,11 @@ namespace BizHawk.Client.Common
ReportProgress(PROGRESS_STEP); ReportProgress(PROGRESS_STEP);
// TasProj extras // TasProj extras
// Greenzone actually means StateHistory. Changing these two names would break previous save files, though. bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(StateManager.Settings.ToString()));
bs.PutLump(BinaryStateLump.GreenzoneSettings, tw => tw.WriteLine(StateManager.Settings.ToString()));
ReportProgress(PROGRESS_STEP); ReportProgress(PROGRESS_STEP);
if (StateManager.Settings.SaveStateHistory) if (StateManager.Settings.SaveStateHistory)
{ {
bs.PutLump(BinaryStateLump.Greenzone, (BinaryWriter bw) => StateManager.Save(bw)); bs.PutLump(BinaryStateLump.StateHistory, (BinaryWriter bw) => StateManager.Save(bw));
} }
ReportProgress(PROGRESS_STEP); ReportProgress(PROGRESS_STEP);
@ -198,15 +197,14 @@ namespace BizHawk.Client.Common
}); });
} }
// Greenzone actually means StateHistory. Changing these two names would break previous save files, though. bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
bl.GetLump(BinaryStateLump.GreenzoneSettings, false, delegate(TextReader tr)
{ {
StateManager.Settings.PopulateFromString(tr.ReadToEnd()); StateManager.Settings.PopulateFromString(tr.ReadToEnd());
}); });
if (StateManager.Settings.SaveStateHistory) if (StateManager.Settings.SaveStateHistory)
{ {
bl.GetLump(BinaryStateLump.Greenzone, false, delegate(BinaryReader br, long length) bl.GetLump(BinaryStateLump.StateHistory, false, delegate(BinaryReader br, long length)
{ {
StateManager.Load(br); StateManager.Load(br);
}); });

View File

@ -185,9 +185,14 @@ namespace BizHawk.Client.Common
return CreateDisplayValueForButton(adapter, buttonName); return CreateDisplayValueForButton(adapter, buttonName);
} }
public void FlushInputCache() public void FlushInputCache(int FrameToLeave = 0)
{ {
InputStateCache.Clear(); if (InputStateCache.Count <= FrameToLeave)
return;
do
{
InputStateCache.Remove(InputStateCache.Keys.First());
} while (InputStateCache.Count > FrameToLeave);
} }
public string CreateDisplayValueForButton(IController adapter, string buttonName) public string CreateDisplayValueForButton(IController adapter, string buttonName)

View File

@ -31,7 +31,7 @@ namespace BizHawk.Client.Common
private int _expectedStateSize = 0; private int _expectedStateSize = 0;
private int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1; private int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1;
private const int _maxFrequency = 16; private const int _maxFrequency = 16;
private int StateFrequency private int StateFrequency
{ {
get get
@ -51,6 +51,7 @@ namespace BizHawk.Client.Common
return freq; return freq;
} }
} }
private int _lastCapture = 0;
public TasStateManager(TasMovie movie) public TasStateManager(TasMovie movie)
{ {
@ -61,7 +62,7 @@ namespace BizHawk.Client.Common
var cap = Settings.Cap; var cap = Settings.Cap;
int limit = 0; int limit = 0;
_expectedStateSize = Core.SaveStateBinary().Length; _expectedStateSize = Core.SaveStateBinary().Length;
if (_expectedStateSize > 0) if (_expectedStateSize > 0)
@ -85,15 +86,15 @@ namespace BizHawk.Client.Common
{ {
if (frame == 0 && _movie.StartsFromSavestate) if (frame == 0 && _movie.StartsFromSavestate)
{ {
return new KeyValuePair<int,byte[]>(0, _movie.BinarySavestate); return new KeyValuePair<int, byte[]>(0, _movie.BinarySavestate);
} }
if (States.ContainsKey(frame)) if (States.ContainsKey(frame))
{ {
return new KeyValuePair<int,byte[]>(frame, States[frame]); return new KeyValuePair<int, byte[]>(frame, States[frame]);
} }
return new KeyValuePair<int,byte[]>(-1, new byte[0]); return new KeyValuePair<int, byte[]>(-1, new byte[0]);
} }
} }
@ -118,7 +119,8 @@ namespace BizHawk.Client.Common
{ {
bool shouldCapture = false; bool shouldCapture = false;
if (_movie.StartsFromSavestate && Global.Emulator.Frame == 0) // Never capture frame 0 on savestate anchored movies since we have it anyway int frame = Global.Emulator.Frame;
if (_movie.StartsFromSavestate && frame == 0) // Never capture frame 0 on savestate anchored movies since we have it anyway
{ {
shouldCapture = false; shouldCapture = false;
} }
@ -126,22 +128,21 @@ namespace BizHawk.Client.Common
{ {
shouldCapture = force; shouldCapture = force;
} }
else if (Global.Emulator.Frame == 0) // For now, long term, TasMovie should have a .StartState property, and a tasproj file for the start state in non-savestate anchored movies else if (frame == 0) // For now, long term, TasMovie should have a .StartState property, and a tasproj file for the start state in non-savestate anchored movies
{ {
shouldCapture = true; shouldCapture = true;
} }
else if (_movie.Markers.IsMarker(Global.Emulator.Frame)) else if (_movie.Markers.IsMarker(frame))
{ {
shouldCapture = true; // Markers shoudl always get priority shouldCapture = true; // Markers shoudl always get priority
} }
else else
{ {
shouldCapture = Global.Emulator.Frame % StateFrequency == 0; shouldCapture = frame - _lastCapture >= StateFrequency;
} }
if (shouldCapture) if (shouldCapture)
{ {
var frame = Global.Emulator.Frame;
var state = (byte[])Core.SaveStateBinary().Clone(); var state = (byte[])Core.SaveStateBinary().Clone();
if (States.ContainsKey(frame)) if (States.ContainsKey(frame))
@ -150,18 +151,55 @@ namespace BizHawk.Client.Common
} }
else else
{ {
if (Used + state.Length >= Settings.Cap)
{
var first = _movie.StartsFromSavestate ? 0 : 1;
Used -= States.ElementAt(first).Value.Length;
States.RemoveAt(first);
}
States.Add(frame, state); States.Add(frame, state);
Used += state.Length; Used += state.Length;
MaybeRemoveState();
}
_lastCapture = frame;
}
}
private void MaybeRemoveState()
{
int shouldRemove = -1;
if (Used >= Settings.Cap)
shouldRemove = _movie.StartsFromSavestate ? 0 : 1;
if (shouldRemove != -1) // Which one to remove?
{
for (int i = shouldRemove; i < States.Count - 1; i++)
{
if (AllLag(States.ElementAt(i).Key, States.ElementAt(i + 1).Key))
{
shouldRemove = i;
break;
}
} }
} }
if (shouldRemove != -1)
{
Used -= States.ElementAt(shouldRemove).Value.Length;
States.RemoveAt(shouldRemove);
}
}
private bool AllLag(int from, int upTo)
{
if (upTo >= Global.Emulator.Frame)
{
upTo = Global.Emulator.Frame - 1;
if (!Global.Emulator.AsInputPollable().IsLagFrame)
return false;
}
for (int i = from; i < upTo; i++)
{
if (!_movie[i].Lagged.Value)
return false;
}
return true;
} }
public bool HasState(int frame) public bool HasState(int frame)
@ -170,7 +208,7 @@ namespace BizHawk.Client.Common
{ {
return true; return true;
} }
return States.ContainsKey(frame); return States.ContainsKey(frame);
} }
@ -194,6 +232,14 @@ namespace BizHawk.Client.Common
Used -= state.Value.Length; Used -= state.Value.Length;
States.Remove(state.Key); States.Remove(state.Key);
} }
if (!States.ContainsKey(_lastCapture))
{
if (States.Count == 0)
_lastCapture = -1;
else
_lastCapture = States.Last().Key;
}
} }
} }
@ -205,6 +251,7 @@ namespace BizHawk.Client.Common
{ {
States.Clear(); States.Clear();
Used = 0; Used = 0;
_lastCapture = -1;
} }
public void ClearStateHistory() public void ClearStateHistory()
@ -218,10 +265,12 @@ namespace BizHawk.Client.Common
{ {
States.Add(0, power.Value); States.Add(0, power.Value);
Used = power.Value.Length; Used = power.Value.Length;
_lastCapture = 0;
} }
else else
{ {
Used = 0; Used = 0;
_lastCapture = -1;
} }
} }
} }
@ -301,14 +350,12 @@ namespace BizHawk.Client.Common
{ {
get get
{ {
var kk = States.Keys; if (States.Count == 0)
int index = kk.Count;
if (index == 0)
{ {
return 0; return 0;
} }
return kk[index - 1]; return States.Last().Key;
} }
} }

View File

@ -36,7 +36,7 @@ namespace BizHawk.Client.EmuHawk
private int? _currentX; private int? _currentX;
private int? _currentY; private int? _currentY;
// Hiding lag frames (Mainly intended for 30fps play.) // Hiding lag frames (Mainly intended for < 60fps play.)
public int LagFramesToHide { get; set; } public int LagFramesToHide { get; set; }
private int[] lagFrames = new int[100]; // Large enough value that it shouldn't ever need resizing. private int[] lagFrames = new int[100]; // Large enough value that it shouldn't ever need resizing.
@ -563,6 +563,8 @@ namespace BizHawk.Client.EmuHawk
} }
} }
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
private int LastFullyVisibleRow private int LastFullyVisibleRow
{ {
get get
@ -573,6 +575,8 @@ namespace BizHawk.Client.EmuHawk
return FirstVisibleRow + VisibleRows - HalfRow + CountLagFramesDisplay(VisibleRows - HalfRow); return FirstVisibleRow + VisibleRows - HalfRow + CountLagFramesDisplay(VisibleRows - HalfRow);
} }
} }
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int LastVisibleRow public int LastVisibleRow
{ {
get get
@ -635,6 +639,44 @@ namespace BizHawk.Client.EmuHawk
} }
} }
/// <summary>
/// Gets the first visible column index, if scrolling is needed
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int FirstVisibleColumn
{
get
{
List<RollColumn> columnList = VisibleColumns.ToList();
if (HorizontalOrientation)
return VBar.Value / CellHeight;
else
return columnList.FindIndex(c => c.Right > 0);
}
}
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int LastVisibleColumnIndex
{
get
{
List<RollColumn> columnList = VisibleColumns.ToList();
int ret;
if (HorizontalOrientation)
{
ret = (VBar.Value + DrawHeight) / CellHeight;
if (ret >= columnList.Count)
ret = columnList.Count - 1;
}
else
ret = columnList.FindLastIndex(c => c.Left <= DrawWidth);
return ret;
}
}
[Browsable(false)] [Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public IEnumerable<int> SelectedRows public IEnumerable<int> SelectedRows
@ -800,7 +842,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++) for (int i = 0, f = 0; f < range; i++, f++)
{ {
f += lagFrames[i]; f += lagFrames[i];
for (int j = 0; j < columns.Count; j++) int LastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= LastVisible; j++)
{ {
Bitmap image = null; Bitmap image = null;
int x = 0; int x = 0;
@ -859,7 +902,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++) // Vertical for (int i = 0, f = 0; f < range; i++, f++) // Vertical
{ {
f += lagFrames[i]; f += lagFrames[i];
for (int j = 0; j < columns.Count; j++) // Horizontal int LastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= LastVisible; j++) // Horizontal
{ {
var col = columns[j]; var col = columns[j];
if (col.Left.Value < 0 || col.Left.Value > DrawWidth) if (col.Left.Value < 0 || col.Left.Value > DrawWidth)
@ -1173,7 +1217,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++) for (int i = 0, f = 0; f < range; i++, f++)
{ {
f += lagFrames[i]; f += lagFrames[i];
for (int j = 0; j < columns.Count; j++) // TODO: Don't query all columns int LastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= LastVisible; j++) // TODO: Don't query all columns
{ {
var color = Color.White; var color = Color.White;
QueryItemBkColor(f + startIndex, columns[j], ref color); QueryItemBkColor(f + startIndex, columns[j], ref color);
@ -1198,7 +1243,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++) // Vertical for (int i = 0, f = 0; f < range; i++, f++) // Vertical
{ {
f += lagFrames[i]; f += lagFrames[i];
for (int j = 0; j < columns.Count; j++) // Horizontal int LastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= LastVisible; j++) // Horizontal
{ {
var color = Color.White; var color = Color.White;
QueryItemBkColor(f + startRow, columns[j], ref color); QueryItemBkColor(f + startRow, columns[j], ref color);
@ -2078,7 +2124,7 @@ namespace BizHawk.Client.EmuHawk
} }
} }
else else
for (int i = 0; i < VisibleRows; i++) for (int i = 0; i <= VisibleRows; i++)
lagFrames[i] = 0; lagFrames[i] = 0;
} }
private void SetLagFramesFirst() private void SetLagFramesFirst()

View File

@ -30,7 +30,7 @@ namespace BizHawk.Client.EmuHawk
return; return;
} }
if (TasPlaybackBox.FollowCursor) // TODO: we already refreshed in RefreshDialog now we will do it again, make this more efficient if (TasPlaybackBox.FollowCursor)
{ {
SetVisibleIndex(); SetVisibleIndex();
} }
@ -73,7 +73,7 @@ namespace BizHawk.Client.EmuHawk
TasView.AllColumns.Clear(); TasView.AllColumns.Clear();
NewDefaultProject(); NewDefaultProject();
SetUpColumns(); SetUpColumns();
TasView.Refresh(); RefreshTasView();
} }
else else
{ {
@ -125,7 +125,7 @@ namespace BizHawk.Client.EmuHawk
{ {
indexThatMustBeVisible = CurrentTasMovie.IsRecording indexThatMustBeVisible = CurrentTasMovie.IsRecording
? CurrentTasMovie.InputLogLength ? CurrentTasMovie.InputLogLength
: Emulator.Frame + 1; : Emulator.Frame;
} }
if (!TasView.IsVisible(indexThatMustBeVisible.Value)) if (!TasView.IsVisible(indexThatMustBeVisible.Value))

View File

@ -233,7 +233,7 @@ namespace BizHawk.Client.EmuHawk
Global.StickyXORAdapter.SetSticky(e.Column.Name, e.Column.Emphasis); Global.StickyXORAdapter.SetSticky(e.Column.Name, e.Column.Emphasis);
TasView.Refresh(); RefreshTasView();
} }
private void TasView_ColumnReordered(object sender, InputRoll.ColumnReorderedEventArgs e) private void TasView_ColumnReordered(object sender, InputRoll.ColumnReorderedEventArgs e)
@ -270,7 +270,7 @@ namespace BizHawk.Client.EmuHawk
if (_floatEditColumn != buttonName || _floatEditRow != frame) if (_floatEditColumn != buttonName || _floatEditRow != frame)
{ {
_floatEditRow = -1; _floatEditRow = -1;
TasView.Refresh(); RefreshTasView();
} }
else else
{ {
@ -454,7 +454,7 @@ namespace BizHawk.Client.EmuHawk
TasView.SelectRow(i, _frameDragState); TasView.SelectRow(i, _frameDragState);
} }
TasView.Refresh(); RefreshTasView();
} }
} }
else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startBoolDrawColumn)) else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startBoolDrawColumn))
@ -468,7 +468,7 @@ namespace BizHawk.Client.EmuHawk
_triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value;
} }
TasView.Refresh(); RefreshTasView();
} }
} }
else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startFloatDrawColumn)) else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startFloatDrawColumn))
@ -485,7 +485,7 @@ namespace BizHawk.Client.EmuHawk
} }
} }
TasView.Refresh(); RefreshTasView();
} }
} }
} }

View File

@ -185,13 +185,13 @@ namespace BizHawk.Client.EmuHawk
private void DeselectMenuItem_Click(object sender, EventArgs e) private void DeselectMenuItem_Click(object sender, EventArgs e)
{ {
TasView.DeselectAll(); TasView.DeselectAll();
TasView.Refresh(); RefreshTasView();
} }
private void SelectAllMenuItem_Click(object sender, EventArgs e) private void SelectAllMenuItem_Click(object sender, EventArgs e)
{ {
TasView.SelectAll(); TasView.SelectAll();
TasView.Refresh(); RefreshTasView();
} }
private void SelectBetweenMarkersMenuItem_Click(object sender, EventArgs e) private void SelectBetweenMarkersMenuItem_Click(object sender, EventArgs e)
@ -705,7 +705,7 @@ namespace BizHawk.Client.EmuHawk
dummyColumnObject.Visible ^= true; dummyColumnObject.Visible ^= true;
TasView.AllColumns.ColumnsChanged(); TasView.AllColumns.ColumnsChanged();
CurrentTasMovie.FlagChanges(); CurrentTasMovie.FlagChanges();
TasView.Refresh(); RefreshTasView();
}; };
ColumnsSubMenu.DropDownItems.Add(menuItem); ColumnsSubMenu.DropDownItems.Add(menuItem);
@ -722,7 +722,7 @@ namespace BizHawk.Client.EmuHawk
{ {
TasView.AllColumns.Clear(); TasView.AllColumns.Clear();
SetUpColumns(); SetUpColumns();
TasView.Refresh(); RefreshTasView();
CurrentTasMovie.FlagChanges(); CurrentTasMovie.FlagChanges();
}; };
@ -760,7 +760,7 @@ namespace BizHawk.Client.EmuHawk
private void CancelSeekContextMenuItem_Click(object sender, EventArgs e) private void CancelSeekContextMenuItem_Click(object sender, EventArgs e)
{ {
GlobalWin.MainForm.PauseOnFrame = null; GlobalWin.MainForm.PauseOnFrame = null;
TasView.Refresh(); RefreshTasView();
} }
private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e) private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e)

View File

@ -226,7 +226,7 @@ namespace BizHawk.Client.EmuHawk
private void GetClientSettingsOnLoad(string settingsJson) private void GetClientSettingsOnLoad(string settingsJson)
{ {
TasView.LoadSettingsSerialized(settingsJson); TasView.LoadSettingsSerialized(settingsJson);
TasView.Refresh(); RefreshTasView();
} }
private void SetTextProperty() private void SetTextProperty()
@ -292,13 +292,7 @@ namespace BizHawk.Client.EmuHawk
public void RefreshDialog() public void RefreshDialog()
{ {
CurrentTasMovie.FlushInputCache(); RefreshTasView();
CurrentTasMovie.UseInputCache = true;
TasView.RowCount = CurrentTasMovie.InputLogLength + 1;
TasView.Refresh();
CurrentTasMovie.FlushInputCache();
CurrentTasMovie.UseInputCache = false;
if (MarkerControl != null) if (MarkerControl != null)
{ {
@ -306,6 +300,17 @@ namespace BizHawk.Client.EmuHawk
} }
} }
private void RefreshTasView()
{
CurrentTasMovie.UseInputCache = true;
TasView.RowCount = CurrentTasMovie.InputLogLength + 1;
TasView.Refresh();
CurrentTasMovie.FlushInputCache(TasView.VisibleRows);
CurrentTasMovie.UseInputCache = false;
}
private void DoAutoRestore() private void DoAutoRestore()
{ {
if (Settings.AutoRestoreLastPosition && _autoRestoreFrame.HasValue) if (Settings.AutoRestoreLastPosition && _autoRestoreFrame.HasValue)