Tweak the rewinder. (#2668)
MainForm intentionally frame advances right after rewinding; this is so it can capture a new framebuffer. The old rewinder sort-of understood this, the new one does not. Tweak the logic so the new rewinder behaves like the old one, but only when the interval is 1. When the interval is greater than 1, don't go farther back than we have to. No particular behavior is guaranteed when nonlinear time exists (ie, rewinding through manual loadstates). Fixes #2667.
This commit is contained in:
parent
359cb0d17b
commit
62ddd6495e
|
@ -13,9 +13,9 @@ namespace BizHawk.Client.Common
|
|||
|
||||
void Capture(int frame);
|
||||
/// <summary>
|
||||
/// Rewind 1 saved frame, if possible
|
||||
/// Rewind 1 or 2 saved frames, avoiding frameToAvoid if possible.
|
||||
/// </summary>
|
||||
bool Rewind();
|
||||
bool Rewind(int frameToAvoid);
|
||||
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
|
|
@ -60,12 +60,18 @@ namespace BizHawk.Client.Common
|
|||
_buffer.Capture(frame, s => _stateSource.SaveStateBinary(new BinaryWriter(s)));
|
||||
}
|
||||
|
||||
public bool Rewind()
|
||||
public bool Rewind(int frameToAvoid)
|
||||
{
|
||||
if (!Active || Count == 0)
|
||||
return false;
|
||||
var index = Count - 1;
|
||||
var state = _buffer.GetState(index);
|
||||
if (state.Frame == frameToAvoid && Count > 1)
|
||||
{
|
||||
// Do not decrement index again. We will "head" this state and not pop it since it will be advanced past
|
||||
// without an opportunity to capture. This is a bit hackish.
|
||||
state = _buffer.GetState(index - 1);
|
||||
}
|
||||
_stateSource.LoadStateBinary(new BinaryReader(state.GetReadStream()));
|
||||
_buffer.InvalidateEnd(index);
|
||||
return true;
|
||||
|
|
|
@ -4517,7 +4517,16 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
if (isRewinding)
|
||||
{
|
||||
runFrame = Rewinder.Rewind() && Emulator.Frame > 1;
|
||||
// Try to avoid the previous frame: We want to frame advance right after rewinding so we can give a useful
|
||||
// framebuffer.
|
||||
var frameToAvoid = Emulator.Frame - 1;
|
||||
runFrame = Rewinder.Rewind(frameToAvoid);
|
||||
if (Emulator.Frame == frameToAvoid)
|
||||
{
|
||||
// The rewinder was unable to satisfy our request. Prefer showing a stale framebuffer to
|
||||
// advancing in a way that essentially no-ops the entire rewind.
|
||||
runFrame = false;
|
||||
}
|
||||
|
||||
if (runFrame && MovieSession.Movie.IsRecording())
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue