Merge branch 'master' of https://github.com/TASVideos/BizHawk
This commit is contained in:
commit
19a1f6cbef
|
@ -9,6 +9,8 @@ using BizHawk.Common;
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||||
|
|
||||||
|
using stateKVP = System.Collections.Generic.KeyValuePair<int, int>;
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
class tsmState : IDisposable
|
class tsmState : IDisposable
|
||||||
|
@ -17,13 +19,14 @@ namespace BizHawk.Client.Common
|
||||||
TasStateManager _manager;
|
TasStateManager _manager;
|
||||||
|
|
||||||
byte[] _state;
|
byte[] _state;
|
||||||
int frame;
|
|
||||||
long ID;
|
long ID;
|
||||||
|
public int Frame;
|
||||||
|
|
||||||
public tsmState(TasStateManager manager, byte[] state)
|
public tsmState(TasStateManager manager, byte[] state, int frame)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
_state = state;
|
_state = state;
|
||||||
|
Frame = frame;
|
||||||
|
|
||||||
//I still think this is a bad idea. IDs may need scavenging somehow
|
//I still think this is a bad idea. IDs may need scavenging somehow
|
||||||
if (state_id > long.MaxValue - 100)
|
if (state_id > long.MaxValue - 100)
|
||||||
|
@ -109,40 +112,6 @@ namespace BizHawk.Client.Common
|
||||||
internal NDBDatabase ndbdatabase;
|
internal NDBDatabase ndbdatabase;
|
||||||
private Guid guid = Guid.NewGuid();
|
private Guid guid = Guid.NewGuid();
|
||||||
private SortedList<int, tsmState> States = new SortedList<int, tsmState>();
|
private SortedList<int, tsmState> States = new SortedList<int, tsmState>();
|
||||||
private SortedList<int, SortedList<int, tsmState>> BranchStates = new SortedList<int, SortedList<int, tsmState>>();
|
|
||||||
private int branches = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the state at frame in the given branch (-1 for current) has any duplicates.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Returns the ID of the branch (-1 for current) of the first match. If no match, returns -2.</returns>
|
|
||||||
private int stateHasDuplicate(int frame, int branch)
|
|
||||||
{
|
|
||||||
tsmState stateToMatch;
|
|
||||||
if (branch == -1)
|
|
||||||
stateToMatch = States[frame];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stateToMatch = BranchStates[frame][branch];
|
|
||||||
if (States.ContainsKey(frame) && States[frame] == stateToMatch)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < branches; i++)
|
|
||||||
{
|
|
||||||
if (i == branch)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (BranchStates.ContainsKey(frame))
|
|
||||||
{
|
|
||||||
SortedList<int, tsmState> stateList = BranchStates[frame];
|
|
||||||
if (stateList != null && stateList.ContainsKey(i) && stateList[i] == stateToMatch)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string statePath
|
private string statePath
|
||||||
{
|
{
|
||||||
|
@ -180,7 +149,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
private int maxStates
|
private int maxStates
|
||||||
{ get { return (int)(Settings.Cap / _expectedStateSize); } }
|
{ get { return (int)(Settings.Cap / _expectedStateSize) + (int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize); } }
|
||||||
|
|
||||||
public TasStateManager(TasMovie movie)
|
public TasStateManager(TasMovie movie)
|
||||||
{
|
{
|
||||||
|
@ -188,7 +157,7 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
Settings = new TasStateManagerSettings(Global.Config.DefaultTasProjSettings);
|
Settings = new TasStateManagerSettings(Global.Config.DefaultTasProjSettings);
|
||||||
|
|
||||||
accessed = new List<int>();
|
accessed = new List<tsmState>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -250,7 +219,7 @@ namespace BizHawk.Client.Common
|
||||||
return new KeyValuePair<int, byte[]>(-1, new byte[0]);
|
return new KeyValuePair<int, byte[]>(-1, new byte[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private List<int> accessed;
|
private List<tsmState> accessed;
|
||||||
|
|
||||||
public byte[] InitialState
|
public byte[] InitialState
|
||||||
{
|
{
|
||||||
|
@ -313,12 +282,9 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
if (Used > Settings.Cap)
|
if (Used > Settings.Cap)
|
||||||
{
|
{
|
||||||
if (DiskUsed > (ulong)Settings.DiskCapacitymb * 1024uL * 1024uL)
|
|
||||||
MaybeRemoveState();
|
|
||||||
|
|
||||||
int lastMemState = -1;
|
int lastMemState = -1;
|
||||||
do { lastMemState++; } while (States[accessed[lastMemState]] == null);
|
do { lastMemState++; } while (States[accessed[lastMemState].Frame] == null);
|
||||||
MoveStateToDisk(accessed[lastMemState]);
|
MoveStateToDisk(accessed[lastMemState].Frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int StateToRemove()
|
private int StateToRemove()
|
||||||
|
@ -326,35 +292,30 @@ namespace BizHawk.Client.Common
|
||||||
int markerSkips = maxStates / 3;
|
int markerSkips = maxStates / 3;
|
||||||
|
|
||||||
int shouldRemove = _movie.StartsFromSavestate ? -1 : 0;
|
int shouldRemove = _movie.StartsFromSavestate ? -1 : 0;
|
||||||
|
//int minFrames = 999;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
shouldRemove++;
|
shouldRemove++;
|
||||||
|
|
||||||
// No need to have two savestates with only lag frames between them:
|
//// No need to have two savestates with only lag frames between them:
|
||||||
// zero 05-aug-2015 - changed algorithm to iterate through States (a SortedList) instead of repeatedly call ElementAt (which is slow)
|
//for (int i = shouldRemove + 1; i < States.Count; i++)
|
||||||
// previously : for (int i = shouldRemove; i < States.Count - 1; i++) if (AllLag(States.ElementAt(i).Key, States.ElementAt(i + 1).Key)) { shouldRemove = i; break; } }
|
//{
|
||||||
int ctr = 0;
|
// if (AllLag(States.Keys[i - 1], States.Keys[i]))
|
||||||
KeyValuePair<int, tsmState>? prior = null;
|
// {
|
||||||
foreach (var kvp in States)
|
// shouldRemove = i - 1;
|
||||||
{
|
// break;
|
||||||
ctr++;
|
// }
|
||||||
if (ctr < shouldRemove)
|
//}
|
||||||
{
|
|
||||||
prior = kvp;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prior.HasValue)
|
//// Find states with the fewest frames between them
|
||||||
{
|
//for (int i = shouldRemove + 1; i < States.Count; i++)
|
||||||
if (AllLag(prior.Value.Key, kvp.Key))
|
//{
|
||||||
{
|
// if (States.Keys[i] - States.Keys[i - 1] < minFrames)
|
||||||
shouldRemove = ctr - 1;
|
// {
|
||||||
break;
|
// minFrames = States.Keys[i] - States.Keys[i - 1];
|
||||||
}
|
// shouldRemove = i;
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
prior = kvp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep marker states
|
// Keep marker states
|
||||||
markerSkips--;
|
markerSkips--;
|
||||||
|
@ -405,39 +366,50 @@ namespace BizHawk.Client.Common
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Used += (ulong)state.Length;
|
Used += (ulong)state.Length;
|
||||||
States.Add(frame, new tsmState(this, state));
|
States.Add(frame, new tsmState(this, state, frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
StateAccessed(frame);
|
StateAccessed(frame);
|
||||||
}
|
}
|
||||||
private void RemoveState(int frame)
|
private void RemoveState(int frame, int branch = -1)
|
||||||
|
{
|
||||||
|
if (branch == -1)
|
||||||
|
accessed.Remove(States[frame]);
|
||||||
|
else
|
||||||
|
accessed.Remove(BranchStates[frame][branch]);
|
||||||
|
|
||||||
|
if (branch == -1)
|
||||||
{
|
{
|
||||||
if (States[frame].IsOnDisk)
|
if (States[frame].IsOnDisk)
|
||||||
{
|
|
||||||
States[frame].Dispose();
|
States[frame].Dispose();
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Used -= (ulong)States[frame].Length;
|
Used -= (ulong)States[frame].Length;
|
||||||
|
|
||||||
States.RemoveAt(States.IndexOfKey(frame));
|
States.RemoveAt(States.IndexOfKey(frame));
|
||||||
accessed.Remove(frame);
|
|
||||||
}
|
}
|
||||||
private void StateAccessed(int index)
|
else
|
||||||
{
|
{
|
||||||
if (index == 0 && _movie.StartsFromSavestate)
|
if (BranchStates[frame][branch].IsOnDisk)
|
||||||
|
BranchStates[frame][branch].Dispose();
|
||||||
|
BranchStates[frame].RemoveAt(BranchStates[frame].IndexOfKey(branch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void StateAccessed(int frame)
|
||||||
|
{
|
||||||
|
if (frame == 0 && _movie.StartsFromSavestate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool removed = accessed.Remove(index);
|
tsmState state = States[frame];
|
||||||
accessed.Add(index);
|
bool removed = accessed.Remove(state);
|
||||||
|
accessed.Add(state);
|
||||||
|
|
||||||
if (States[index].IsOnDisk)
|
if (States[frame].IsOnDisk)
|
||||||
{
|
{
|
||||||
if (!States[accessed[0]].IsOnDisk)
|
if (!States[accessed[0].Frame].IsOnDisk)
|
||||||
MoveStateToDisk(accessed[0]);
|
MoveStateToDisk(accessed[0].Frame);
|
||||||
MoveStateToMemory(index);
|
MoveStateToMemory(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!removed && accessed.Count > (int)(Used / _expectedStateSize))
|
if (!removed && accessed.Count > maxStates)
|
||||||
accessed.RemoveAt(0);
|
accessed.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,24 +437,22 @@ namespace BizHawk.Client.Common
|
||||||
frame = 1;
|
frame = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var statesToRemove = States
|
List<KeyValuePair<int, tsmState>> statesToRemove =
|
||||||
.Where(x => x.Key >= frame)
|
States.Where(x => x.Key >= frame).ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
anyInvalidated = statesToRemove.Any();
|
anyInvalidated = statesToRemove.Any();
|
||||||
|
|
||||||
foreach (var state in statesToRemove)
|
foreach (KeyValuePair<int, tsmState> state in statesToRemove)
|
||||||
{
|
RemoveState(state.Key);
|
||||||
if (state.Value.IsOnDisk)
|
|
||||||
{
|
|
||||||
state.Value.Dispose();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Used -= (ulong)state.Value.Length;
|
|
||||||
|
|
||||||
accessed.Remove(state.Key);
|
// Why did I put this here? The branches aren't being edited/invalidated.
|
||||||
States.Remove(state.Key);
|
//var bStateLists = BranchStates.Where(x => x.Key >= frame).ToList();
|
||||||
}
|
//anyInvalidated = anyInvalidated | bStateLists.Any();
|
||||||
|
//foreach (KeyValuePair<int, SortedList<int, tsmState>> stateList in bStateLists)
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < stateList.Value.Count; i++)
|
||||||
|
// RemoveState(stateList.Key, stateList.Value.Keys[i]);
|
||||||
|
//}
|
||||||
|
|
||||||
CallInvalidateCallback(frame);
|
CallInvalidateCallback(frame);
|
||||||
}
|
}
|
||||||
|
@ -537,8 +507,23 @@ namespace BizHawk.Client.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void LimitStateCount()
|
public void LimitStateCount()
|
||||||
{
|
{
|
||||||
while (Used + DiskUsed > Settings.CapTotal)
|
//while (Used + DiskUsed > Settings.CapTotal)
|
||||||
MaybeRemoveState();
|
// RemoveState(States.ElementAt(StateToRemove()).Key);
|
||||||
|
|
||||||
|
//int index = -1;
|
||||||
|
//while (DiskUsed > (ulong)Settings.DiskCapacitymb * 1024uL * 1024uL)
|
||||||
|
//{
|
||||||
|
// do { index++; } while (!States[accessed[index]].IsOnDisk);
|
||||||
|
// States[
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (Used > Settings.Cap)
|
||||||
|
//{
|
||||||
|
// int lastMemState = -1;
|
||||||
|
// do { lastMemState++; } while (States[accessed[lastMemState]] == null);
|
||||||
|
// MoveStateToDisk(accessed[lastMemState]);
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: save/load BranchStates
|
// TODO: save/load BranchStates
|
||||||
|
@ -685,6 +670,42 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
#region "Branches"
|
#region "Branches"
|
||||||
|
|
||||||
|
private SortedList<int, SortedList<int, tsmState>> BranchStates = new SortedList<int, SortedList<int, tsmState>>();
|
||||||
|
private int branches = 0;
|
||||||
|
private int currentBranch = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the state at frame in the given branch (-1 for current) has any duplicates.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the ID of the branch (-1 for current) of the first match. If no match, returns -2.</returns>
|
||||||
|
private int stateHasDuplicate(int frame, int branch)
|
||||||
|
{
|
||||||
|
tsmState stateToMatch;
|
||||||
|
if (branch == -1)
|
||||||
|
stateToMatch = States[frame];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stateToMatch = BranchStates[frame][branch];
|
||||||
|
if (States.ContainsKey(frame) && States[frame] == stateToMatch)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < branches; i++)
|
||||||
|
{
|
||||||
|
if (i == branch)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (BranchStates.ContainsKey(frame))
|
||||||
|
{
|
||||||
|
SortedList<int, tsmState> stateList = BranchStates[frame];
|
||||||
|
if (stateList != null && stateList.ContainsKey(i) && stateList[i] == stateToMatch)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddBranch()
|
public void AddBranch()
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<int, tsmState> kvp in States)
|
foreach (KeyValuePair<int, tsmState> kvp in States)
|
||||||
|
@ -700,6 +721,7 @@ namespace BizHawk.Client.Common
|
||||||
stateList.Add(branches, kvp.Value);
|
stateList.Add(branches, kvp.Value);
|
||||||
}
|
}
|
||||||
branches++;
|
branches++;
|
||||||
|
currentBranch = branches;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveBranch(int index)
|
public void RemoveBranch(int index)
|
||||||
|
@ -723,6 +745,8 @@ namespace BizHawk.Client.Common
|
||||||
BranchStates[kvp.Key] = null;
|
BranchStates[kvp.Key] = null;
|
||||||
}
|
}
|
||||||
branches--;
|
branches--;
|
||||||
|
if (currentBranch <= branches)
|
||||||
|
currentBranch = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateBranch(int index)
|
public void UpdateBranch(int index)
|
||||||
|
@ -760,6 +784,8 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
stateList.Add(index, kvp.Value);
|
stateList.Add(index, kvp.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentBranch = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadBranch(int index)
|
public void LoadBranch(int index)
|
||||||
|
@ -773,6 +799,8 @@ namespace BizHawk.Client.Common
|
||||||
if (kvp.Value.ContainsKey(index))
|
if (kvp.Value.ContainsKey(index))
|
||||||
SetState(kvp.Key, kvp.Value[index].State);
|
SetState(kvp.Key, kvp.Value[index].State);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentBranch = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -747,7 +747,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
Owner = GlobalWin.MainForm,
|
Owner = GlobalWin.MainForm,
|
||||||
Location = this.ChildPointToScreen(TasView),
|
Location = this.ChildPointToScreen(TasView),
|
||||||
Statable = this.StatableEmulator
|
Statable = this.StatableEmulator
|
||||||
}.Show();
|
}.ShowDialog();
|
||||||
CurrentTasMovie.TasStateManager.LimitStateCount();
|
CurrentTasMovie.TasStateManager.LimitStateCount();
|
||||||
UpdateChangesIndicator();
|
UpdateChangesIndicator();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue