Add an option to RewindConfig to specify if the rewinder should allow out-of-order states. Currently, the default rewinder should but TAStudio rewinders should not.

Previously, TAStudio's ZwinderStateManager had to handle this, which made the code somewhat confusing. (Especially when I was looking at ZwinderBuffer and forgetting about the default rewinder.)
This commit is contained in:
SuuperW 2022-01-19 13:18:49 -06:00
parent 014cd51ae4
commit 822cc53252
4 changed files with 24 additions and 15 deletions

View File

@ -34,6 +34,11 @@
/// </summary>
int TargetRewindInterval { get; }
/// <summary>
/// Specifies if the rewinder should accept states that are given out of order.
/// </summary>
bool AllowOutOfOrderStates { get; }
public enum BackingStoreType
{
Memory,
@ -52,6 +57,8 @@
public bool UseFixedRewindInterval { get; set; } = false;
public int TargetFrameLength { get; set; } = 600;
public int TargetRewindInterval { get; set; } = 5;
public bool AllowOutOfOrderStates { get; set; } = true;
public IRewindSettings.BackingStoreType BackingStore { get; set; } = IRewindSettings.BackingStoreType.Memory;
}
}

View File

@ -320,23 +320,12 @@ namespace BizHawk.Client.Common
}
// We use the gap buffer for forced capture to avoid crowding the "current" buffer and thus reducing it's actual span of covered frames.
if (force)
if (NeedsGap(frame) || force)
{
CaptureGap(frame, source);
return;
}
// We do not want to consider reserved states for a notion of Last
// reserved states can include future states in the case of branch states
if (frame <= LastRing)
{
if (NeedsGap(frame))
{
CaptureGap(frame, source);
}
return;
}
_current.Capture(frame,
s =>
{
@ -404,6 +393,12 @@ namespace BizHawk.Client.Common
private bool NeedsGap(int frame)
{
// We don't want to "fill gaps" if we are past the latest state in the current/recent buffers.
if (frame >= LastRing)
{
return false;
}
// When starting to fill gaps we won't actually know the true frequency, so fall back to current
// Current may very well not be the same as gap, but it's a reasonable behavior to have a current sized gap before seeing filler sized gaps
var frequency = _gapFiller.Count == 0 ? _current.RewindFrequency : _gapFiller.RewindFrequency;

View File

@ -109,6 +109,7 @@ namespace BizHawk.Client.Common
BufferSize = CurrentBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = CurrentTargetFrameLength,
AllowOutOfOrderStates = false,
BackingStore = CurrentStoreType
};
}
@ -120,6 +121,7 @@ namespace BizHawk.Client.Common
BufferSize = RecentBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = RecentTargetFrameLength,
AllowOutOfOrderStates = false,
BackingStore = RecentStoreType
};
}
@ -131,6 +133,7 @@ namespace BizHawk.Client.Common
BufferSize = GapsBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = GapsTargetFrameLength,
AllowOutOfOrderStates = false,
BackingStore = GapsStoreType
};
}

View File

@ -65,6 +65,7 @@ namespace BizHawk.Client.Common
_fixedRewindInterval = false;
_targetFrameLength = settings.TargetFrameLength;
}
_allowOutOfOrderStates = settings.AllowOutOfOrderStates;
_states = new StateInfo[STATEMASK + 1];
_useCompression = settings.UseCompression;
}
@ -111,6 +112,8 @@ namespace BizHawk.Client.Common
private readonly int _targetFrameLength;
private readonly int _targetRewindInterval;
private readonly bool _allowOutOfOrderStates;
private struct StateInfo
{
public long Start;
@ -162,6 +165,7 @@ namespace BizHawk.Client.Common
_useCompression == settings.UseCompression &&
_fixedRewindInterval == settings.UseFixedRewindInterval &&
(_fixedRewindInterval ? _targetRewindInterval == settings.TargetRewindInterval : _targetFrameLength == settings.TargetFrameLength) &&
_allowOutOfOrderStates == settings.AllowOutOfOrderStates &&
_backingStoreType == settings.BackingStore;
}
@ -173,9 +177,8 @@ namespace BizHawk.Client.Common
}
if (frameDiff < 1)
{
// non-linear time is from a combination of other state changing mechanisms and the rewinder
// not much we can say here, so just take a state
return true;
// Manually loading a savestate can cause this. The default rewinder should capture in this situation.
return _allowOutOfOrderStates;
}
return frameDiff >= ComputeIdealRewindInterval();
}
@ -369,6 +372,7 @@ namespace BizHawk.Client.Common
UseFixedRewindInterval = false,
TargetFrameLength = targetFrameLength,
TargetRewindInterval = 5,
AllowOutOfOrderStates = false,
UseCompression = useCompression
});
if (ret.Size != size || ret._sizeMask != sizeMask)