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

View File

@ -8,16 +8,9 @@ namespace BizHawk.Client.Common
{
get
{
var key = button
.Replace("P1 ", "")
.Replace("P2 ", "")
.Replace("P3 ", "")
.Replace("P4 ", "")
.Replace("P5 ", "")
.Replace("P6 ", "")
.Replace("P7 ", "")
.Replace("P8 ", "")
.Replace("Key ", "");
var key = button.Replace("Key ", "");
if (key.StartsWith("P") && key[1] >= '0' && key[1] <= '9')
key = key.Substring(3);
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);
// TasProj extras
// Greenzone actually means StateHistory. Changing these two names would break previous save files, though.
bs.PutLump(BinaryStateLump.GreenzoneSettings, tw => tw.WriteLine(StateManager.Settings.ToString()));
bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(StateManager.Settings.ToString()));
ReportProgress(PROGRESS_STEP);
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);
@ -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.GreenzoneSettings, false, delegate(TextReader tr)
bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
{
StateManager.Settings.PopulateFromString(tr.ReadToEnd());
});
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);
});

View File

@ -185,9 +185,14 @@ namespace BizHawk.Client.Common
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)

View File

@ -31,7 +31,7 @@ namespace BizHawk.Client.Common
private int _expectedStateSize = 0;
private int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1;
private const int _maxFrequency = 16;
private const int _maxFrequency = 16;
private int StateFrequency
{
get
@ -51,6 +51,7 @@ namespace BizHawk.Client.Common
return freq;
}
}
private int _lastCapture = 0;
public TasStateManager(TasMovie movie)
{
@ -61,7 +62,7 @@ namespace BizHawk.Client.Common
var cap = Settings.Cap;
int limit = 0;
_expectedStateSize = Core.SaveStateBinary().Length;
if (_expectedStateSize > 0)
@ -85,15 +86,15 @@ namespace BizHawk.Client.Common
{
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))
{
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;
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;
}
@ -126,22 +128,21 @@ namespace BizHawk.Client.Common
{
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;
}
else if (_movie.Markers.IsMarker(Global.Emulator.Frame))
else if (_movie.Markers.IsMarker(frame))
{
shouldCapture = true; // Markers shoudl always get priority
}
else
{
shouldCapture = Global.Emulator.Frame % StateFrequency == 0;
shouldCapture = frame - _lastCapture >= StateFrequency;
}
if (shouldCapture)
{
var frame = Global.Emulator.Frame;
var state = (byte[])Core.SaveStateBinary().Clone();
if (States.ContainsKey(frame))
@ -150,18 +151,55 @@ namespace BizHawk.Client.Common
}
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);
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)
@ -170,7 +208,7 @@ namespace BizHawk.Client.Common
{
return true;
}
return States.ContainsKey(frame);
}
@ -194,6 +232,14 @@ namespace BizHawk.Client.Common
Used -= state.Value.Length;
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();
Used = 0;
_lastCapture = -1;
}
public void ClearStateHistory()
@ -218,10 +265,12 @@ namespace BizHawk.Client.Common
{
States.Add(0, power.Value);
Used = power.Value.Length;
_lastCapture = 0;
}
else
{
Used = 0;
_lastCapture = -1;
}
}
}
@ -301,14 +350,12 @@ namespace BizHawk.Client.Common
{
get
{
var kk = States.Keys;
int index = kk.Count;
if (index == 0)
if (States.Count == 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? _currentY;
// Hiding lag frames (Mainly intended for 30fps play.)
// Hiding lag frames (Mainly intended for < 60fps play.)
public int LagFramesToHide { get; set; }
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
{
get
@ -573,6 +575,8 @@ namespace BizHawk.Client.EmuHawk
return FirstVisibleRow + VisibleRows - HalfRow + CountLagFramesDisplay(VisibleRows - HalfRow);
}
}
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int LastVisibleRow
{
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)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public IEnumerable<int> SelectedRows
@ -800,7 +842,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++)
{
f += lagFrames[i];
for (int j = 0; j < columns.Count; j++)
int LastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= LastVisible; j++)
{
Bitmap image = null;
int x = 0;
@ -859,7 +902,8 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0, f = 0; f < range; i++, f++) // Vertical
{
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];
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++)
{
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;
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
{
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;
QueryItemBkColor(f + startRow, columns[j], ref color);
@ -2078,7 +2124,7 @@ namespace BizHawk.Client.EmuHawk
}
}
else
for (int i = 0; i < VisibleRows; i++)
for (int i = 0; i <= VisibleRows; i++)
lagFrames[i] = 0;
}
private void SetLagFramesFirst()

View File

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

View File

@ -233,7 +233,7 @@ namespace BizHawk.Client.EmuHawk
Global.StickyXORAdapter.SetSticky(e.Column.Name, e.Column.Emphasis);
TasView.Refresh();
RefreshTasView();
}
private void TasView_ColumnReordered(object sender, InputRoll.ColumnReorderedEventArgs e)
@ -270,7 +270,7 @@ namespace BizHawk.Client.EmuHawk
if (_floatEditColumn != buttonName || _floatEditRow != frame)
{
_floatEditRow = -1;
TasView.Refresh();
RefreshTasView();
}
else
{
@ -454,7 +454,7 @@ namespace BizHawk.Client.EmuHawk
TasView.SelectRow(i, _frameDragState);
}
TasView.Refresh();
RefreshTasView();
}
}
else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startBoolDrawColumn))
@ -468,7 +468,7 @@ namespace BizHawk.Client.EmuHawk
_triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value;
}
TasView.Refresh();
RefreshTasView();
}
}
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)
{
TasView.DeselectAll();
TasView.Refresh();
RefreshTasView();
}
private void SelectAllMenuItem_Click(object sender, EventArgs e)
{
TasView.SelectAll();
TasView.Refresh();
RefreshTasView();
}
private void SelectBetweenMarkersMenuItem_Click(object sender, EventArgs e)
@ -705,7 +705,7 @@ namespace BizHawk.Client.EmuHawk
dummyColumnObject.Visible ^= true;
TasView.AllColumns.ColumnsChanged();
CurrentTasMovie.FlagChanges();
TasView.Refresh();
RefreshTasView();
};
ColumnsSubMenu.DropDownItems.Add(menuItem);
@ -722,7 +722,7 @@ namespace BizHawk.Client.EmuHawk
{
TasView.AllColumns.Clear();
SetUpColumns();
TasView.Refresh();
RefreshTasView();
CurrentTasMovie.FlagChanges();
};
@ -760,7 +760,7 @@ namespace BizHawk.Client.EmuHawk
private void CancelSeekContextMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.MainForm.PauseOnFrame = null;
TasView.Refresh();
RefreshTasView();
}
private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e)

View File

@ -226,7 +226,7 @@ namespace BizHawk.Client.EmuHawk
private void GetClientSettingsOnLoad(string settingsJson)
{
TasView.LoadSettingsSerialized(settingsJson);
TasView.Refresh();
RefreshTasView();
}
private void SetTextProperty()
@ -292,13 +292,7 @@ namespace BizHawk.Client.EmuHawk
public void RefreshDialog()
{
CurrentTasMovie.FlushInputCache();
CurrentTasMovie.UseInputCache = true;
TasView.RowCount = CurrentTasMovie.InputLogLength + 1;
TasView.Refresh();
CurrentTasMovie.FlushInputCache();
CurrentTasMovie.UseInputCache = false;
RefreshTasView();
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()
{
if (Settings.AutoRestoreLastPosition && _autoRestoreFrame.HasValue)