Add config option for rewinds every fixed number of frames. (#2893)

* wip consistent rewind intervals.

    In Bizhawk 2.3, rewinds were always made in fixed intervals.
    With the new rewinder, the rewind intervals vary depending on the
    save state size. (This is especially pronounced with delta compression.)
    While this is good for TAStudio, it is awful for regular playing / TASing.

* clean up rewind config gui a bit.

Use radio buttons to make it clear that only the numeric input field of the selected option is being used.

* use more precise variable names.

* minor whitespace cleanup

* don't use fixed rewind intervals by default.

This avoid suddenly changing the rewind behaviour when updating from previous recent versions of Bizhawk.
This commit is contained in:
Daniel Peter Rutschmann 2021-09-18 10:08:43 +02:00 committed by GitHub
parent 158451a68e
commit 94f9016c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 197 deletions

View File

@ -19,11 +19,21 @@
/// </summary>
long BufferSize { get; }
/// <summary>
/// Specifies whether TargetFrameLength or TargetRewindInterval is used.
/// </summary>
public bool UseFixedRewindInterval { get; }
/// <summary>
/// Desired frame length (number of emulated frames you can go back before running out of buffer)
/// </summary>
int TargetFrameLength { get; }
/// <summary>
/// Desired rewind interval (number of emulated frames you can go back per rewind)
/// </summary>
int TargetRewindInterval { get; }
public enum BackingStoreType
{
Memory,
@ -39,7 +49,9 @@
public bool UseDelta { get; set; }
public bool Enabled { get; set; } = true;
public long BufferSize { get; set; } = 512; // in mb
public bool UseFixedRewindInterval { get; set; } = false;
public int TargetFrameLength { get; set; } = 600;
public int TargetRewindInterval { get; set; } = 5;
public IRewindSettings.BackingStoreType BackingStore { get; set; } = IRewindSettings.BackingStoreType.Memory;
}
}

View File

@ -107,6 +107,7 @@ namespace BizHawk.Client.Common
{
UseCompression = CurrentUseCompression,
BufferSize = CurrentBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = CurrentTargetFrameLength,
BackingStore = CurrentStoreType
};
@ -117,6 +118,7 @@ namespace BizHawk.Client.Common
{
UseCompression = RecentUseCompression,
BufferSize = RecentBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = RecentTargetFrameLength,
BackingStore = RecentStoreType
};
@ -127,6 +129,7 @@ namespace BizHawk.Client.Common
{
UseCompression = GapsUseCompression,
BufferSize = GapsBufferSize,
UseFixedRewindInterval = false,
TargetFrameLength = GapsTargetFrameLength,
BackingStore = GapsStoreType
};

View File

@ -55,7 +55,16 @@ namespace BizHawk.Client.Common
default:
throw new ArgumentException("Unsupported store type for ZwinderBuffer.");
}
if (settings.UseFixedRewindInterval)
{
_fixedRewindInterval = true;
_targetRewindInterval = settings.TargetRewindInterval;
}
else
{
_fixedRewindInterval = false;
_targetFrameLength = settings.TargetFrameLength;
}
_states = new StateInfo[STATEMASK + 1];
_useCompression = settings.UseCompression;
}
@ -98,7 +107,9 @@ namespace BizHawk.Client.Common
private readonly long _sizeMask;
private readonly bool _fixedRewindInterval;
private readonly int _targetFrameLength;
private readonly int _targetRewindInterval;
private struct StateInfo
{
@ -130,6 +141,11 @@ namespace BizHawk.Client.Common
return 1; // shrug
}
if (_fixedRewindInterval)
{
return _targetRewindInterval;
}
// assume that the most recent state size is representative of stuff
var sizeRatio = Size / (float)_states[HeadStateIndex].Size;
var frameRatio = _targetFrameLength / sizeRatio;
@ -144,7 +160,8 @@ namespace BizHawk.Client.Common
long size = 1L << (int)Math.Floor(Math.Log(targetSize, 2));
return Size == size &&
_useCompression == settings.UseCompression &&
_targetFrameLength == settings.TargetFrameLength &&
_fixedRewindInterval == settings.UseFixedRewindInterval &&
(_fixedRewindInterval ? _targetRewindInterval == settings.TargetRewindInterval : _targetFrameLength == settings.TargetFrameLength) &&
_backingStoreType == settings.BackingStore;
}
@ -349,7 +366,9 @@ namespace BizHawk.Client.Common
ret = new ZwinderBuffer(new RewindConfig
{
BufferSize = (int)(size >> 20),
UseFixedRewindInterval = false,
TargetFrameLength = targetFrameLength,
TargetRewindInterval = 5,
UseCompression = useCompression
});
if (ret.Size != size || ret._sizeMask != sizeMask)

View File

@ -47,7 +47,7 @@
this.labelEx1 = new BizHawk.WinForms.Controls.LabelEx();
this.cbDeltaCompression = new System.Windows.Forms.CheckBox();
this.TargetFrameLengthNumeric = new System.Windows.Forms.NumericUpDown();
this.label2 = new BizHawk.WinForms.Controls.LocLabelEx();
this.TargetRewindIntervalNumeric = new System.Windows.Forms.NumericUpDown();
this.EstTimeLabel = new BizHawk.WinForms.Controls.LocLabelEx();
this.label11 = new BizHawk.WinForms.Controls.LocLabelEx();
this.ApproxFramesLabel = new BizHawk.WinForms.Controls.LocLabelEx();
@ -73,10 +73,13 @@
this.label16 = new BizHawk.WinForms.Controls.LocLabelEx();
this.BackupSavestatesCheckbox = new System.Windows.Forms.CheckBox();
this.label12 = new BizHawk.WinForms.Controls.LocLabelEx();
this.TargetFrameLengthRadioButton = new System.Windows.Forms.RadioButton();
this.TargetRewindIntervalRadioButton = new System.Windows.Forms.RadioButton();
((System.ComponentModel.ISupportInitialize)(this.BufferSizeUpDown)).BeginInit();
this.groupBox4.SuspendLayout();
this.locSingleRowFLP1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.TargetFrameLengthNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.TargetRewindIntervalNumeric)).BeginInit();
this.groupBox6.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarCompression)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudCompression)).BeginInit();
@ -120,9 +123,9 @@
// UseCompression
//
this.UseCompression.AutoSize = true;
this.UseCompression.Location = new System.Drawing.Point(15, 170);
this.UseCompression.Location = new System.Drawing.Point(15, 194);
this.UseCompression.Name = "UseCompression";
this.UseCompression.Size = new System.Drawing.Size(306, 17);
this.UseCompression.Size = new System.Drawing.Size(324, 17);
this.UseCompression.TabIndex = 5;
this.UseCompression.Text = "Use zlib compression (economizes buffer usage at cost of CPU)";
this.UseCompression.UseVisualStyleBackColor = true;
@ -136,7 +139,7 @@
//
// BufferSizeUpDown
//
this.BufferSizeUpDown.Location = new System.Drawing.Point(0, 0);
this.BufferSizeUpDown.Location = new System.Drawing.Point(25, 3);
this.BufferSizeUpDown.Maximum = new decimal(new int[] {
15,
0,
@ -189,10 +192,12 @@
//
// groupBox4
//
this.groupBox4.Controls.Add(this.TargetRewindIntervalRadioButton);
this.groupBox4.Controls.Add(this.TargetFrameLengthRadioButton);
this.groupBox4.Controls.Add(this.locSingleRowFLP1);
this.groupBox4.Controls.Add(this.cbDeltaCompression);
this.groupBox4.Controls.Add(this.TargetFrameLengthNumeric);
this.groupBox4.Controls.Add(this.label2);
this.groupBox4.Controls.Add(this.TargetRewindIntervalNumeric);
this.groupBox4.Controls.Add(this.UseCompression);
this.groupBox4.Controls.Add(this.RewindEnabledBox);
this.groupBox4.Controls.Add(this.label3);
@ -208,7 +213,7 @@
this.groupBox4.Controls.Add(this.StateSizeLabel);
this.groupBox4.Location = new System.Drawing.Point(12, 12);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(371, 218);
this.groupBox4.Size = new System.Drawing.Size(371, 248);
this.groupBox4.TabIndex = 2;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "RewindSettings";
@ -244,16 +249,16 @@
// cbDeltaCompression
//
this.cbDeltaCompression.AutoSize = true;
this.cbDeltaCompression.Location = new System.Drawing.Point(15, 193);
this.cbDeltaCompression.Location = new System.Drawing.Point(15, 217);
this.cbDeltaCompression.Name = "cbDeltaCompression";
this.cbDeltaCompression.Size = new System.Drawing.Size(149, 17);
this.cbDeltaCompression.Size = new System.Drawing.Size(332, 17);
this.cbDeltaCompression.TabIndex = 35;
this.cbDeltaCompression.Text = "Use delta compression (economizes buffer usage at cost of CPU)";
this.cbDeltaCompression.UseVisualStyleBackColor = true;
//
// TargetFrameLengthNumeric
//
this.TargetFrameLengthNumeric.Location = new System.Drawing.Point(125, 135);
this.TargetFrameLengthNumeric.Location = new System.Drawing.Point(146, 138);
this.TargetFrameLengthNumeric.Maximum = new decimal(new int[] {
500000,
0,
@ -273,11 +278,27 @@
0,
0});
//
// label2
// TargetRewindIntervalNumeric
//
this.label2.Location = new System.Drawing.Point(12, 138);
this.label2.Name = "label2";
this.label2.Text = "Desired frame length:";
this.TargetRewindIntervalNumeric.Location = new System.Drawing.Point(231, 162);
this.TargetRewindIntervalNumeric.Maximum = new decimal(new int[] {
500000,
0,
0,
0});
this.TargetRewindIntervalNumeric.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.TargetRewindIntervalNumeric.Name = "TargetRewindIntervalNumeric";
this.TargetRewindIntervalNumeric.Size = new System.Drawing.Size(52, 20);
this.TargetRewindIntervalNumeric.TabIndex = 21;
this.TargetRewindIntervalNumeric.Value = new decimal(new int[] {
5,
0,
0,
0});
//
// EstTimeLabel
//
@ -365,7 +386,7 @@
this.trackBarCompression.Location = new System.Drawing.Point(22, 37);
this.trackBarCompression.Maximum = 9;
this.trackBarCompression.Name = "trackBarCompression";
this.trackBarCompression.Size = new System.Drawing.Size(157, 42);
this.trackBarCompression.Size = new System.Drawing.Size(157, 45);
this.trackBarCompression.TabIndex = 1;
this.toolTip1.SetToolTip(this.trackBarCompression, "0 = None; 9 = Maximum");
this.trackBarCompression.Value = 1;
@ -508,6 +529,28 @@
this.label12.Name = "label12";
this.label12.Text = "Compression Level";
//
// TargetFrameLengthRadioButton
//
this.TargetFrameLengthRadioButton.AutoSize = true;
this.TargetFrameLengthRadioButton.Location = new System.Drawing.Point(15, 138);
this.TargetFrameLengthRadioButton.Name = "TargetFrameLengthRadioButton";
this.TargetFrameLengthRadioButton.Size = new System.Drawing.Size(125, 17);
this.TargetFrameLengthRadioButton.TabIndex = 48;
this.TargetFrameLengthRadioButton.TabStop = true;
this.TargetFrameLengthRadioButton.Text = "Desired frame length:";
this.TargetFrameLengthRadioButton.UseVisualStyleBackColor = true;
//
// TargetRewindIntervalRadioButton
//
this.TargetRewindIntervalRadioButton.AutoSize = true;
this.TargetRewindIntervalRadioButton.Location = new System.Drawing.Point(15, 162);
this.TargetRewindIntervalRadioButton.Name = "TargetRewindIntervalRadioButton";
this.TargetRewindIntervalRadioButton.Size = new System.Drawing.Size(210, 17);
this.TargetRewindIntervalRadioButton.TabIndex = 49;
this.TargetRewindIntervalRadioButton.TabStop = true;
this.TargetRewindIntervalRadioButton.Text = "Rewinds every fixed number of frames: ";
this.TargetRewindIntervalRadioButton.UseVisualStyleBackColor = true;
//
// RewindConfig
//
this.AcceptButton = this.OK;
@ -532,6 +575,7 @@
this.locSingleRowFLP1.ResumeLayout(false);
this.locSingleRowFLP1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.TargetFrameLengthNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.TargetRewindIntervalNumeric)).EndInit();
this.groupBox6.ResumeLayout(false);
this.groupBox6.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarCompression)).EndInit();
@ -583,11 +627,13 @@
private System.Windows.Forms.CheckBox BackupSavestatesCheckbox;
private BizHawk.WinForms.Controls.LocLabelEx label20;
private System.Windows.Forms.NumericUpDown TargetFrameLengthNumeric;
private BizHawk.WinForms.Controls.LocLabelEx label2;
private System.Windows.Forms.NumericUpDown TargetRewindIntervalNumeric;
private System.Windows.Forms.CheckBox cbDeltaCompression;
private WinForms.Controls.LocSingleRowFLP locSingleRowFLP1;
private WinForms.Controls.LabelEx labelEx3;
private WinForms.Controls.LabelEx labelEx2;
private WinForms.Controls.LabelEx labelEx1;
private System.Windows.Forms.RadioButton TargetFrameLengthRadioButton;
private System.Windows.Forms.RadioButton TargetRewindIntervalRadioButton;
}
}

View File

@ -49,7 +49,10 @@ namespace BizHawk.Client.EmuHawk
UseCompression.Checked = _config.Rewind.UseCompression;
cbDeltaCompression.Checked = _config.Rewind.UseDelta;
BufferSizeUpDown.Value = Math.Max((decimal) Math.Log(_config.Rewind.BufferSize, 2), BufferSizeUpDown.Minimum);
TargetFrameLengthRadioButton.Checked = !_config.Rewind.UseFixedRewindInterval;
TargetRewindIntervalRadioButton.Checked = _config.Rewind.UseFixedRewindInterval;
TargetFrameLengthNumeric.Value = Math.Max(_config.Rewind.TargetFrameLength, TargetFrameLengthNumeric.Minimum);
TargetRewindIntervalNumeric.Value = Math.Max(_config.Rewind.TargetRewindInterval, TargetRewindIntervalNumeric.Minimum);
StateSizeLabel.Text = FormatKB(_avgStateSize);
CalculateEstimates();
@ -111,7 +114,9 @@ namespace BizHawk.Client.EmuHawk
_config.Rewind.UseCompression = PutRewindSetting(_config.Rewind.UseCompression, UseCompression.Checked);
_config.Rewind.Enabled = PutRewindSetting(_config.Rewind.Enabled, RewindEnabledBox.Checked);
_config.Rewind.BufferSize = PutRewindSetting(_config.Rewind.BufferSize, 1L << (int) BufferSizeUpDown.Value);
_config.Rewind.UseFixedRewindInterval = PutRewindSetting(_config.Rewind.UseFixedRewindInterval, TargetRewindIntervalRadioButton.Checked);
_config.Rewind.TargetFrameLength = PutRewindSetting(_config.Rewind.TargetFrameLength, (int)TargetFrameLengthNumeric.Value);
_config.Rewind.TargetRewindInterval = PutRewindSetting(_config.Rewind.TargetRewindInterval, (int)TargetRewindIntervalNumeric.Value);
_config.Rewind.UseDelta = PutRewindSetting(_config.Rewind.UseDelta, cbDeltaCompression.Checked);
// These settings are not used by DoRewindSettings