From 12830bab4e0b20a37f1d3d42fb63e3cf36c676ad Mon Sep 17 00:00:00 2001
From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date: Fri, 28 Jul 2023 22:07:31 -0700
Subject: [PATCH] Add in flag to IStatable to hint to the frontend that it
should avoid rewind (not entire sure with the name, maybe SlowStates would
have been better? trivial to mass-rename anyways) Add in logic to not create
the main rewinder if this flag is true, and add in logic to tastudio to avoid
the main greenzone captures (instead only capture on branch save/load)
---
.../config/RewindConfig.cs | 7 ++--
.../movie/tasproj/TasMovie.cs | 2 +-
.../movie/tasproj/ZwinderStateManager.cs | 9 +++--
src/BizHawk.Client.EmuHawk/MainForm.cs | 2 +-
.../tools/TAStudio/BookmarksBranchesBox.cs | 34 ++++++++++++++++---
.../Base Implementations/StateSerializer.cs | 2 ++
.../Interfaces/Services/IStatable.cs | 1 +
.../Arcades/MAME/MAME.IStatable.cs | 2 ++
.../Calculators/Emu83/Emu83.IStatable.cs | 2 ++
.../Computers/AppleII/AppleII.IStatable.cs | 2 ++
.../Consoles/Atari/lynx/Lynx.IStatable.cs | 2 ++
.../Consoles/Nintendo/3DS/Citra.IStatable.cs | 2 ++
.../Consoles/Nintendo/3DS/Citra.cs | 3 ++
.../Consoles/Nintendo/BSNES/BsnesApi.cs | 2 ++
.../Nintendo/BSNES/BsnesCore.IStatable.cs | 2 ++
.../Nintendo/GBA/MGBAHawk.IStatable.cs | 2 ++
.../GBHawkLink/GBHawkLink.IStatable.cs | 2 ++
.../GBHawkLink3x/GBHawkLink3x.IStatable.cs | 2 ++
.../GBHawkLink4x/GBHawkLink4x.IStatable.cs | 2 ++
.../Nintendo/Gameboy/Gambatte.IStatable.cs | 2 ++
.../Gameboy/GambatteLink.IStatable.cs | 14 ++++++++
.../Consoles/Nintendo/N64/N64.IStatable.cs | 2 ++
.../Nintendo/QuickNES/QuickNES.IStatable.cs | 2 ++
.../Consoles/Nintendo/SNES/LibsnesApi.cs | 2 ++
.../Nintendo/SNES/LibsnesCore.IStatable.cs | 2 ++
.../Nintendo/SameBoy/SameBoy.IStatable.cs | 2 ++
.../Nintendo/SubGBHawk/SubGBHawk.IStatable.cs | 2 ++
.../SubNESHawk/SubNESHawk.IStatable.cs | 2 ++
.../Sega/GGHawkLink/GGHawkLink.IStatable.cs | 2 ++
.../Consoles/Sega/gpgx64/GPGX.IStatable.cs | 2 ++
.../Consoles/Sony/PSX/Octoshock.cs | 2 ++
.../WonderSwan/WonderSwan.IStatable.cs | 2 ++
.../Libretro/Libretro.IStatable.cs | 2 ++
.../Waterbox/NymaCore.Controller.cs | 2 ++
.../Waterbox/WaterboxCore.cs | 2 ++
.../Waterbox/WaterboxHost.cs | 2 ++
.../Movie/ZwinderStateManagerTests.cs | 3 ++
37 files changed, 119 insertions(+), 12 deletions(-)
diff --git a/src/BizHawk.Client.Common/config/RewindConfig.cs b/src/BizHawk.Client.Common/config/RewindConfig.cs
index 2f67c0f6c1..992253cb40 100644
--- a/src/BizHawk.Client.Common/config/RewindConfig.cs
+++ b/src/BizHawk.Client.Common/config/RewindConfig.cs
@@ -5,13 +5,13 @@
///
/// Gets a value indicating whether or not to compress savestates before storing them
///
- bool UseCompression { get; }
-
+ bool UseCompression { get; }
+
///
/// Gets a value indicating whether or not to delta compress savestates before storing them
///
///
- // TODO: This is in here for frontend reasons, but the buffer itself doesn't interact with this.
+ // TODO: This is in here for frontend reasons, but the buffer itself doesn't interact with this.
bool UseDelta { get; }
///
@@ -53,6 +53,7 @@
public bool UseCompression { get; set; } = false;
public bool UseDelta { get; set; } = false;
public bool Enabled { get; set; } = true;
+ public bool AllowSlowStates { get; set; } = false; // TODO: Hook up in UI
public long BufferSize { get; set; } = 512; // in mb
public bool UseFixedRewindInterval { get; set; } = false;
public int TargetFrameLength { get; set; } = 600;
diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
index 8f591884ed..6f1be955dc 100644
--- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
+++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
@@ -196,7 +196,7 @@ namespace BizHawk.Client.Common
LagLog[Emulator.Frame] = _inputPollable.IsLagFrame;
// We will forbibly capture a state for the last edited frame (requested by #916 for case of "platforms with analog stick")
- TasStateManager.Capture(Emulator.Frame, Emulator.AsStatable(), Emulator.Frame == LastEditedFrame - 1);
+ TasStateManager.Capture(Emulator.Frame, Emulator.AsStatable(), !Emulator.AsStatable().AvoidRewind && Emulator.Frame == LastEditedFrame - 1);
}
diff --git a/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs b/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs
index 73683157da..66d954a49c 100644
--- a/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs
+++ b/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs
@@ -334,6 +334,12 @@ namespace BizHawk.Client.Common
return;
}
+ // avoid capturing in this case
+ if (source.AvoidRewind)
+ {
+ return;
+ }
+
_current.Capture(frame,
s =>
{
@@ -372,8 +378,7 @@ namespace BizHawk.Client.Common
AddToReserved(state2);
}
});
- },
- force);
+ });
}
// Returns whether or not a frame has a reserved state within the frame interval on either side of it
diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs
index dd55cb31b9..40a4f08036 100644
--- a/src/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/src/BizHawk.Client.EmuHawk/MainForm.cs
@@ -1064,7 +1064,7 @@ namespace BizHawk.Client.EmuHawk
public void CreateRewinder()
{
Rewinder?.Dispose();
- Rewinder = Emulator.HasSavestates() && Config.Rewind.Enabled
+ Rewinder = Emulator.HasSavestates() && Config.Rewind.Enabled && (!Emulator.AsStatable().AvoidRewind || Config.Rewind.AllowSlowStates)
? Config.Rewind.UseDelta
? new ZeldaWinder(Emulator.AsStatable(), Config.Rewind)
: new Zwinder(Emulator.AsStatable(), Config.Rewind)
diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
index 88285752d9..68d055931f 100644
--- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
+++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs
@@ -174,16 +174,40 @@ namespace BizHawk.Client.EmuHawk
public TasBranch SelectedBranch
=> BranchView.AnyRowsSelected ? Branches[BranchView.FirstSelectedRowIndex] : null;
+ // to avoid a double (potentially slow) state
+ private class BufferedStatable : IStatable
+ {
+ private readonly Lazy _bufferedState;
+ public byte[] BufferedState => _bufferedState.Value;
+
+ public BufferedStatable(IStatable statable)
+ {
+ _bufferedState = new(statable.CloneSavestate);
+ AvoidRewind = statable.AvoidRewind;
+ }
+
+ public bool AvoidRewind { get; }
+
+ public void SaveStateBinary(BinaryWriter writer)
+ => writer.Write(BufferedState);
+
+ public void LoadStateBinary(BinaryReader reader)
+ => throw new NotImplementedException();
+ }
+
private TasBranch CreateBranch()
{
- return new TasBranch
+ var bufferedStatable = new BufferedStatable(Tastudio.Emulator.AsStatable());
+ Movie.TasStateManager.Capture(Tastudio.Emulator.Frame, bufferedStatable, bufferedStatable.AvoidRewind);
+
+ return new()
{
Frame = Tastudio.Emulator.Frame,
- CoreData = Tastudio.StatableEmulator.CloneSavestate(),
+ CoreData = bufferedStatable.BufferedState,
InputLog = Movie.GetLogEntries().Clone(),
CoreFrameBuffer = MainForm.MakeScreenshotImage(),
OSDFrameBuffer = MainForm.CaptureOSD(),
- ChangeLog = new TasMovieChangeLog(Movie),
+ ChangeLog = new(Movie),
TimeStamp = DateTime.Now,
Markers = Movie.Markers.DeepClone(),
UserText = Movie.Branches.NewBranchText
@@ -199,8 +223,8 @@ namespace BizHawk.Client.EmuHawk
}
Movie.LoadBranch(branch);
- Tastudio.LoadState(new KeyValuePair(branch.Frame, new MemoryStream(branch.CoreData, false)));
- Movie.TasStateManager.Capture(Tastudio.Emulator.Frame, Tastudio.Emulator.AsStatable());
+ Tastudio.LoadState(new(branch.Frame, new MemoryStream(branch.CoreData, false)));
+ Movie.TasStateManager.Capture(Tastudio.Emulator.Frame, Tastudio.Emulator.AsStatable(), Tastudio.Emulator.AsStatable().AvoidRewind);
Tastudio.MainForm.QuickBmpFile.Copy(new BitmapBufferVideoProvider(branch.CoreFrameBuffer), Tastudio.VideoProvider);
if (Tastudio.Settings.OldControlSchemeForBranches && Tastudio.TasPlaybackBox.RecordingMode)
diff --git a/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs b/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs
index 31fb789258..b864951020 100644
--- a/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs
+++ b/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs
@@ -28,6 +28,8 @@ namespace BizHawk.Emulation.Common
///
public Action LoadStateCallback { get; set; }
+ public bool AvoidRewind => false;
+
public void SaveStateText(TextWriter writer)
{
_syncState(Serializer.CreateTextWriter(writer));
diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/IStatable.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/IStatable.cs
index c3bee6be7a..2e5e380d1b 100644
--- a/src/BizHawk.Emulation.Common/Interfaces/Services/IStatable.cs
+++ b/src/BizHawk.Emulation.Common/Interfaces/Services/IStatable.cs
@@ -13,6 +13,7 @@ namespace BizHawk.Emulation.Common
///
public interface IStatable : IEmulatorService
{
+ bool AvoidRewind { get; }
void SaveStateBinary(BinaryWriter writer);
void LoadStateBinary(BinaryReader reader);
}
diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IStatable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IStatable.cs
index a996f9604a..f04e813604 100644
--- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IStatable.cs
@@ -7,6 +7,8 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME
{
public partial class MAME : IStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
using (_exe.EnterExit())
diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs
index e81aae3d87..1e9b25707e 100644
--- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Calculators.Emu83
{
private readonly byte[] _stateBuf = new byte[LibEmu83.TI83_GetStateSize()];
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
if (!LibEmu83.TI83_SaveState(Context, _stateBuf))
diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IStatable.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IStatable.cs
index 5540d2163b..5ad404baed 100644
--- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IStatable.cs
@@ -7,6 +7,8 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
{
public partial class AppleII : ITextStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateText(TextWriter writer)
{
SyncState(new AppleSerializer(writer));
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs
index b9fb7f1012..adfff45478 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs
@@ -8,6 +8,8 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
{
public partial class Lynx : ITextStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateText(TextWriter writer)
{
var s = new TextState();
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.IStatable.cs
index a00ef69524..b3561e3707 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS
{
private byte[] _stateBuf = Array.Empty();
+ public bool AvoidRewind => true;
+
public void SaveStateBinary(BinaryWriter writer)
{
var stateLen = _core.Citra_StartSaveState(_context);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.cs
index 6a46050fe8..cffeec390b 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.cs
@@ -151,6 +151,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS
}
InitMemoryDomains();
+ // for some reason, if a savestate is created on frame 0, Citra will crash if another savestate is made after loading that state
+ // advance one frame to avoid that issue
+ _core.Citra_RunFrame(_context);
OnVideoRefresh();
}
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs
index ca1a7e8730..513cf2b0f6 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs
@@ -294,6 +294,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
// private int serializedSize;
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
// commented code left for debug purposes; created savestates are native bsnes savestates
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IStatable.cs
index cc207e655e..8e10d70d50 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IStatable.cs
@@ -5,6 +5,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
{
public partial class BsnesCore : IStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
Api.SaveStateBinary(writer);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs
index 43e4e98757..8257bdfe78 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
private byte[] _savebuff = Array.Empty();
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
if (!LibmGBA.BizStartGetState(Core, out var p, out var size))
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IStatable.cs
index 23416fa421..568db13653 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IStatable.cs
@@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
private readonly IStatable _lStates;
private readonly IStatable _rStates;
+ public bool AvoidRewind => _lStates.AvoidRewind || _rStates.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_lStates.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IStatable.cs
index cca9cf3e0e..d44344da67 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IStatable.cs
@@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x
private readonly IStatable _cStates;
private readonly IStatable _rStates;
+ public bool AvoidRewind => _lStates.AvoidRewind || _cStates.AvoidRewind || _rStates.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_lStates.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs
index 01484cd411..c9cbfbf205 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs
@@ -12,6 +12,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
private readonly IStatable _cStates;
private readonly IStatable _dStates;
+ public bool AvoidRewind => _aStates.AvoidRewind || _bStates.AvoidRewind || _cStates.AvoidRewind || _dStates.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_aStates.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs
index 139f2dcc21..9b08cfdc95 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs
@@ -11,6 +11,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
public partial class Gameboy : IStatable, ITextStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateText(TextWriter writer)
{
var s = SaveState();
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs
index bf850d5382..437370815d 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs
@@ -9,6 +9,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
public partial class GambatteLink : ITextStatable
{
+ public bool AvoidRewind
+ {
+ get
+ {
+ var ret = false;
+ for (var i = 0; i < _numCores; i++)
+ {
+ ret |= _linkedCores[i].AvoidRewind;
+ }
+
+ return ret;
+ }
+ }
+
public void SaveStateText(TextWriter writer)
{
ser.Serialize(writer, new GBLSerialized(this));
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs
index 7902308646..2f57f58862 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs
@@ -8,6 +8,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
{
public partial class N64 : IStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
byte[] data = SaveStatePrivateBuff;
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs
index 0b753c0c2e..6c334f1ba3 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs
@@ -6,6 +6,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
{
public partial class QuickNES : IStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
CheckDisposed();
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs
index 8537e09bfc..ac125797b9 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs
@@ -428,6 +428,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
_readonlyFiles.Clear();
}
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
_exe.SaveStateBinary(writer);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IStatable.cs
index b081d696b6..a08667c075 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IStatable.cs
@@ -5,6 +5,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
{
public partial class LibsnesCore : IStatable
{
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
Api.SaveStateBinary(writer);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs
index 82b61828a5..d22b984efd 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
{
private readonly byte[] _stateBuf;
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
LibSameboy.sameboy_savestate(SameboyState, _stateBuf);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs
index 3c81d27c53..b8683d811b 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk
{
private readonly IStatable _GBStatable;
+ public bool AvoidRewind => _GBStatable.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_GBStatable.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs
index 7299789fef..a4d19635c5 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs
@@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
private readonly IStatable _nesStatable;
+ public bool AvoidRewind => _nesStatable.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_nesStatable.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs
index 6c82a214ed..366c57828e 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs
@@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
private readonly IStatable _lStates;
private readonly IStatable _rStates;
+ public bool AvoidRewind => _lStates.AvoidRewind || _rStates.AvoidRewind;
+
public void SaveStateBinary(BinaryWriter bw)
{
_lStates.SaveStateBinary(bw);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs
index 5adc9f293f..9b851efefd 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs
@@ -5,6 +5,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IStatable
{
+ public bool AvoidRewind => false;
+
public void LoadStateBinary(BinaryReader reader)
{
_elf.LoadStateBinary(reader);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
index 43d525169d..e6f14d1fba 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs
@@ -1038,6 +1038,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
savebuff = new byte[size];
}
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
fixed (byte* psavebuff = savebuff)
diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs
index 74854f77ea..377491cb64 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs
@@ -59,6 +59,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
private byte[] savebuff;
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
if (!BizSwan.bizswan_binstatesave(Core, savebuff, savebuff.Length))
diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs
index b1bda8c231..eb19dfe6c9 100644
--- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs
@@ -21,6 +21,8 @@ namespace BizHawk.Emulation.Cores.Libretro
_stateBuf = new byte[maxSize];
}
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
var len = checked((int)_api.retro_serialize_size());
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs
index d3e2c49b60..1a272af833 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs
@@ -328,6 +328,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
private const ulong MAGIC = 9569546739673486731;
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter writer)
{
writer.Write(MAGIC);
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
index 49587912c5..63c16fb3f5 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
@@ -263,6 +263,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
public virtual ControllerDefinition ControllerDefinition { get; protected set; } = NullController.Instance.Definition;
+ public bool AvoidRewind => false;
+
public void LoadStateBinary(BinaryReader reader)
{
using (_exe.EnterExit())
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
index deaeb7e515..956c86da75 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
@@ -342,6 +342,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
}
+ public bool AvoidRewind => false;
+
public void SaveStateBinary(BinaryWriter bw)
{
using var writer = new ReadWriteWrapper(bw.BaseStream, false);
diff --git a/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs b/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs
index 4901f2f1ab..5965b1bb29 100644
--- a/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs
+++ b/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs
@@ -575,6 +575,9 @@ namespace BizHawk.Tests.Client.Common.Movie
{
public int Frame { get; set; }
public byte[] PaddingData { get; set; } = Array.Empty();
+
+ public bool AvoidRewind => false;
+
public void LoadStateBinary(BinaryReader reader)
{
Frame = reader.ReadInt32();