remove byte[] SavestateBinary() from IStatable, consolidate IBinaryStatable into IStatable now that they are the same

This commit is contained in:
adelikat 2020-08-05 21:07:30 -05:00
parent a93a94aead
commit ac139eabf2
32 changed files with 24 additions and 337 deletions

View File

@ -21,10 +21,10 @@ namespace BizHawk.Client.Common
/// Requests that the current emulator state be captured
/// Unless force is true, the state may or may not be captured depending on the logic employed by "green-zone" management
/// </summary>
void Capture(int frame, IBinaryStateable source, bool force = false);
void Capture(int frame, IStatable source, bool force = false);
// TODO: should this be used for markers?
//void CaptureHighPriority(int frame, IBinaryStateable source);
//void CaptureHighPriority(int frame, IStatable source);
bool HasState(int frame);

View File

@ -177,7 +177,7 @@ namespace BizHawk.Client.Common
public int Last => AllStates().First().Frame;
public void Capture(int frame, IBinaryStateable source, bool force = false)
public void Capture(int frame, IStatable source, bool force = false)
{
if (frame <= Last)
{
@ -206,7 +206,7 @@ namespace BizHawk.Client.Common
force);
}
public void CaptureHighPriority(int frame, IBinaryStateable source)
public void CaptureHighPriority(int frame, IStatable source)
{
_highPriority.Capture(frame, s => source.SaveStateBinary(new BinaryWriter(s)));
}

View File

@ -18,9 +18,9 @@ namespace BizHawk.Client.Common
*/
private readonly ZwinderBuffer _buffer;
private readonly IBinaryStateable _stateSource;
private readonly IStatable _stateSource;
public Zwinder(IBinaryStateable stateSource, IRewindSettings settings)
public Zwinder(IStatable stateSource, IRewindSettings settings)
{
_buffer = new ZwinderBuffer(settings);
_stateSource = stateSource;

View File

@ -11,21 +11,13 @@ namespace BizHawk.Emulation.Common
public class StateSerializer : ITextStatable
{
private readonly Action<Serializer> _syncState;
private readonly bool _bufferStates;
private byte[] _stateBuffer;
/// <summary>
/// Instantiates a new instance of the <see cref="StateSerializer" /> class
/// </summary>
/// <param name="syncState">The callback that will be called on save and load methods </param>
/// <param name="bufferStates">
/// Whether or not to keep an allocated array for
/// the byte array version of the SaveStateBinary method,
/// should be true unless a core can have savestates of varying sizes per instance
/// </param>
public StateSerializer(Action<Serializer> syncState, bool bufferStates = true)
public StateSerializer(Action<Serializer> syncState)
{
_bufferStates = bufferStates;
_syncState = syncState;
}
@ -55,26 +47,5 @@ namespace BizHawk.Emulation.Common
_syncState(Serializer.CreateBinaryReader(br));
LoadStateCallback?.Invoke();
}
public byte[] SaveStateBinary()
{
if (_bufferStates && _stateBuffer != null)
{
using var stream = new MemoryStream(_stateBuffer);
using var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
writer.Close();
return _stateBuffer;
}
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
_stateBuffer = ms.ToArray();
bw.Close();
return _stateBuffer;
}
}
}

View File

@ -3,28 +3,16 @@ using BizHawk.Common.BufferExtensions;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// Binary save and load state only without any trappings. At the moment, an emulator core should not implement this directly
/// </summary>
public interface IBinaryStateable
{
void SaveStateBinary(BinaryWriter writer);
void LoadStateBinary(BinaryReader reader);
}
/// <summary>
/// This service manages the logic of sending and receiving savestates from the core
/// If this service is available, client apps will expose features for making savestates and that utilize savestates (such as rewind))
/// If unavailable these options will not be exposed
/// Additionally many tools depend on savestates such as TAStudio, these will only be available if this service is implemented
/// </summary>
public interface IStatable : IBinaryStateable, IEmulatorService
public interface IStatable : IEmulatorService
{
/// <summary>
/// save state binary to a byte buffer
/// </summary>
/// <returns>you may NOT modify this. if you call SaveStateBinary() again with the same core, the old data MAY be overwritten.</returns>
byte[] SaveStateBinary();
void SaveStateBinary(BinaryWriter writer);
void LoadStateBinary(BinaryReader reader);
}
/// <summary>
@ -48,7 +36,7 @@ namespace BizHawk.Emulation.Common
textCore.SaveStateText(writer);
}
var temp = core.SaveStateBinary();
var temp = core.CloneSavestate();
temp.SaveAsHexFast(writer);
}

View File

@ -333,22 +333,6 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME
IsLagFrame = reader.ReadBoolean();
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream(_hawkSaveBuffer);
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != _hawkSaveBuffer.Length)
{
throw new InvalidOperationException();
}
ms.Close();
return _hawkSaveBuffer;
}
public SyncSettings GetSyncSettings()
{
return _syncSettings.Clone();

View File

@ -27,16 +27,6 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
SyncState(new AppleSerializer(reader));
}
public byte[] SaveStateBinary()
{
// our savestate array can be of varying sizes, so this can't be too clever
using var stream = new MemoryStream();
using var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
return stream.ToArray();
}
private void SyncState(AppleSerializer ser)
{
int version = 2;

View File

@ -68,24 +68,8 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream(_saveBuff2, true);
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != _saveBuff2.Length)
{
throw new InvalidOperationException();
}
ms.Close();
return _saveBuff2;
}
private readonly JsonSerializer _ser = new JsonSerializer { Formatting = Formatting.Indented };
private readonly byte[] _saveBuff;
private readonly byte[] _saveBuff2;
private class TextStateData
{

View File

@ -92,7 +92,6 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
try
{
_saveBuff = new byte[LibLynx.BinStateSize(Core)];
_saveBuff2 = new byte[_saveBuff.Length + 13];
int rot = game.OptionPresent("rotate") ? int.Parse(game.OptionValue("rotate")) : 0;
LibLynx.SetRotation(Core, rot);

View File

@ -8,9 +8,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
public partial class MGBAHawk : IStatable
{
private byte[] _savebuff = new byte[0];
private byte[] _savebuff2 = new byte[13];
private void StartSaveStateBinaryInternal()
public void SaveStateBinary(BinaryWriter writer)
{
IntPtr p = IntPtr.Zero;
int size = 0;
@ -22,14 +21,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
if (size != _savebuff.Length)
{
_savebuff = new byte[size];
_savebuff2 = new byte[size + 13];
}
LibmGBA.BizFinishGetState(p, _savebuff, size);
}
private void FinishSaveStateBinaryInternal(BinaryWriter writer)
{
writer.Write(_savebuff.Length);
writer.Write(_savebuff, 0, _savebuff.Length);
@ -39,19 +34,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
writer.Write(Frame);
}
public void SaveStateBinary(BinaryWriter writer)
{
StartSaveStateBinaryInternal();
FinishSaveStateBinaryInternal(writer);
}
public void LoadStateBinary(BinaryReader reader)
{
int length = reader.ReadInt32();
if (length != _savebuff.Length)
{
_savebuff = new byte[length];
_savebuff2 = new byte[length + 13];
}
reader.Read(_savebuff, 0, length);
@ -65,16 +53,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
StartSaveStateBinaryInternal();
using var ms = new MemoryStream(_savebuff2, true);
using var bw = new BinaryWriter(ms);
FinishSaveStateBinaryInternal(bw);
bw.Flush();
ms.Close();
return _savebuff2;
}
}
}

View File

@ -199,7 +199,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
_tracer = new TraceBuffer { Header = cpu.TraceHeader };
ser.Register<ITraceable>(_tracer);
ser.Register<IStatable>(new StateSerializer(SyncState, false));
ser.Register<IStatable>(new StateSerializer(SyncState));
SetupMemoryDomains();
cpu.SetCallbacks(ReadMemory, PeekMemory, PeekMemory, WriteMemory);
HardReset();

View File

@ -26,15 +26,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagcount);

View File

@ -28,15 +28,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagcount);

View File

@ -32,15 +32,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagcount);

View File

@ -63,28 +63,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
IsCgb = reader.ReadBoolean();
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream(_savebuff2);
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != _savebuff2.Length)
{
throw new InvalidOperationException();
}
ms.Close();
return _savebuff2;
}
private byte[] _savebuff;
private byte[] _savebuff2;
private void NewSaveCoreSetBuff()
{
_savebuff = new byte[LibGambatte.gambatte_newstatelen(GambatteState)];
_savebuff2 = new byte[_savebuff.Length + 4 + 21 + 1];
}
private readonly JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };

View File

@ -74,15 +74,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
_cablediscosignal = reader.ReadBoolean();
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };
private class DGBSerialized

View File

@ -51,32 +51,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
// WELCOME TO THE HACK ZONE
byte[] saveram = api.SaveSaveram();
int lenwant = 4 + SaveStatePrivateBuff.Length + saveram.Length + 1 + 4 + 4;
if (SaveStateBinaryPrivateBuff.Length != lenwant)
{
Console.WriteLine("Allocating new N64 private buffer size {0}", lenwant);
SaveStateBinaryPrivateBuff = new byte[lenwant];
}
using var ms = new MemoryStream(SaveStateBinaryPrivateBuff);
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Length != SaveStateBinaryPrivateBuff.Length)
{
throw new Exception("Unexpected Length");
}
return SaveStateBinaryPrivateBuff;
}
private byte[] SaveStatePrivateBuff = new byte[16788288 + 1024];
private byte[] SaveStateBinaryPrivateBuff = new byte[0];
}
}

View File

@ -25,21 +25,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
}
}
public byte[] SaveStateBinary()
public void SaveStateBinary(BinaryWriter writer)
{
// TODO: can we do this without a making a copy of the byte buffer?
int len = GetSavestateSize();
byte[] ret = new byte[len];
fixed (byte* ptr = ret)
byte[] data = new byte[len];
fixed (byte* ptr = data)
{
GetSavestateData(ptr, len);
}
return ret;
}
public void SaveStateBinary(BinaryWriter writer)
{
byte[] data = SaveStateBinary();
writer.Write(data);
}

View File

@ -36,31 +36,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
CheckDisposed();
var ms = new MemoryStream(_saveStateBuff2, true);
var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != _saveStateBuff2.Length)
{
throw new InvalidOperationException("Unexpected savestate length!");
}
bw.Close();
return _saveStateBuff2;
}
private byte[] _saveStateBuff;
private byte[] _saveStateBuff2;
private void InitSaveStateBuff()
{
int size = 0;
LibQuickNES.ThrowStringError(QN.qn_state_size(Context, ref size));
_saveStateBuff = new byte[size];
_saveStateBuff2 = new byte[size + 13];
}
}
}

View File

@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
public abstract void PostLoadState();
}
public unsafe partial class LibsnesApi : IDisposable, IMonitor, IBinaryStateable
public unsafe partial class LibsnesApi : IDisposable, IMonitor, IStatable
{
static LibsnesApi()
{

View File

@ -20,14 +20,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
}
}

View File

@ -23,15 +23,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagCount);

View File

@ -23,15 +23,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagCount);

View File

@ -26,15 +26,6 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagCount);

View File

@ -34,15 +34,5 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
writer.Write(_prevDiskPressed);
writer.Write(_nextDiskPressed);
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return ms.ToArray();
}
}
}

View File

@ -1093,7 +1093,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
//THIS IS STILL AWFUL
byte[] savebuff;
byte[] savebuff2;
void StudySaveBufferSize()
{
@ -1101,7 +1100,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
transaction.transaction = OctoshockDll.eShockStateTransaction.BinarySize;
int size = OctoshockDll.shock_StateTransaction(psx, ref transaction);
savebuff = new byte[size];
savebuff2 = new byte[savebuff.Length + 4 + 4 + 4 + 1 + 1 + 4];
}
public void SaveStateBinary(BinaryWriter writer)
@ -1159,19 +1157,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
}
}
public byte[] SaveStateBinary()
{
//this are objectionable shenanigans, but theyre required to get the extra info in the stream. we need a better approach.
using var ms = new MemoryStream(savebuff2, true);
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != savebuff2.Length)
throw new InvalidOperationException();
ms.Close();
return savebuff2;
}
Settings _Settings = new Settings();
SyncSettings _SyncSettings;

View File

@ -13,7 +13,6 @@ namespace BizHawk.Emulation.Cores.WonderSwan
private void InitIStatable()
{
savebuff = new byte[BizSwan.bizswan_binstatesize(Core)];
savebuff2 = new byte[savebuff.Length + 13];
}
JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };
@ -59,7 +58,6 @@ namespace BizHawk.Emulation.Cores.WonderSwan
}
byte[] savebuff;
byte[] savebuff2;
public void SaveStateBinary(BinaryWriter writer)
{
@ -85,17 +83,5 @@ namespace BizHawk.Emulation.Cores.WonderSwan
var d = BinaryQuickSerializer.Create<TextStateData>(reader);
LoadTextStateData(d);
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream(savebuff2, true);
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
if (ms.Position != savebuff2.Length)
throw new InvalidOperationException();
ms.Close();
return savebuff2;
}
}
}

View File

@ -342,7 +342,7 @@ namespace BizHawk.Emulation.Cores.Libretro
IsLagFrame = false;
}
private byte[] savebuff, savebuff2;
private byte[] savebuff;
public void SaveStateBinary(BinaryWriter writer)
{
@ -350,7 +350,6 @@ namespace BizHawk.Emulation.Cores.Libretro
if (savebuff == null || savebuff.Length != (int)api.comm->env.retro_serialize_size)
{
savebuff = new byte[api.comm->env.retro_serialize_size];
savebuff2 = new byte[savebuff.Length + 13];
}
api.CMD_Serialize(savebuff);
@ -374,24 +373,6 @@ namespace BizHawk.Emulation.Cores.Libretro
LagCount = reader.ReadInt32();
IsLagFrame = reader.ReadBoolean();
}
public byte[] SaveStateBinary()
{
api.CMD_UpdateSerializeSize();
if (savebuff == null || savebuff.Length != (int)api.comm->env.retro_serialize_size)
{
savebuff = new byte[api.comm->env.retro_serialize_size];
savebuff2 = new byte[savebuff.Length + 13];
}
var ms = new MemoryStream(savebuff2, true);
var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return savebuff2;
}
} //class
} //namespace
}
}

View File

@ -29,7 +29,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
protected delegate void ControllerThunk(IController c, byte[] b);
protected class ControllerAdapter : IBinaryStateable
protected class ControllerAdapter : IStatable
{
/// <summary>
/// Device list suitable to pass back to the core

View File

@ -298,16 +298,6 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return ms.ToArray();
}
/// <summary>
/// called after the base core saves state. the core must save any other
/// variables that it needs to.

View File

@ -68,7 +68,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
public bool SkipMemoryConsistencyCheck { get; set; } = false;
}
public unsafe class WaterboxHost : IMonitor, IImportResolver, IBinaryStateable, IDisposable, ICallbackAdjuster
public unsafe class WaterboxHost : IMonitor, IImportResolver, IStatable, IDisposable, ICallbackAdjuster
{
private IntPtr _nativeHost;
private int _enterCount;

View File

@ -57,7 +57,7 @@ namespace BizHawk.Common.Tests.Client.Common.Movie
Assert.IsTrue(actual < 10440);
}
private class StateSource : IBinaryStateable
private class StateSource : IStatable
{
public int Frame { get; set; }
public byte[] PaddingData { get; set; } = new byte[0];