diff --git a/BizHawk.MultiClient/Rewind.cs b/BizHawk.MultiClient/Rewind.cs
index 7fcedfd16c..bad190bcdf 100644
--- a/BizHawk.MultiClient/Rewind.cs
+++ b/BizHawk.MultiClient/Rewind.cs
@@ -85,17 +85,20 @@ namespace BizHawk.MultiClient
}
///
- /// The push and pop semantics are for historical reasons and not resemblence
+ /// The push and pop semantics are for historical reasons and not resemblence to normal definitions
///
- public void PushMemoryStream(MemoryStream ms)
+ public void Push(ArraySegment seg)
{
- var buf = ms.GetBuffer();
- int len = (int)ms.Length;
+ var buf = seg.Array;
+ int len = seg.Count;
long offset = Enqueue(0, len);
mStream.Position = offset;
- mStream.Write(buf, 0, len);
+ mStream.Write(buf, seg.Offset, len);
}
+ ///
+ /// The push and pop semantics are for historical reasons and not resemblence to normal definitions
+ ///
public MemoryStream PopMemoryStream()
{
var item = Pop();
@@ -289,58 +292,77 @@ namespace BizHawk.MultiClient
// Builds a delta for states that are <= 64K in size.
void CaptureRewindState64K() { CaptureRewindStateDelta(true); }
+ byte[] TempBuf = new byte[0];
void CaptureRewindStateDelta(bool isSmall)
{
byte[] CurrentState = Global.Emulator.SaveStateBinary();
int beginChangeSequence = -1;
bool inChangeSequence = false;
- var ms = new MemoryStream();
- var writer = new BinaryWriter(ms);
- if (CurrentState.Length != LastState.Length)
+ MemoryStream ms;
+
+ //try to set up the buffer in advance so we dont ever have exceptions in here
+ if(TempBuf.Length < CurrentState.Length)
+ TempBuf = new byte[CurrentState.Length*2];
+
+ ms = new MemoryStream(TempBuf, 0, TempBuf.Length, true, true);
+ RETRY:
+ try
{
- writer.Write(true); // full state
- writer.Write(LastState);
- }
- else
- {
- writer.Write(false); // delta state
- for (int i = 0; i < CurrentState.Length; i++)
+ var writer = new BinaryWriter(ms);
+ if (CurrentState.Length != LastState.Length)
{
- if (inChangeSequence == false)
+ writer.Write(true); // full state
+ writer.Write(LastState);
+ }
+ else
+ {
+ writer.Write(false); // delta state
+ for (int i = 0; i < CurrentState.Length; i++)
{
- if (i >= LastState.Length)
+ if (inChangeSequence == false)
+ {
+ if (i >= LastState.Length)
+ continue;
+ if (CurrentState[i] == LastState[i])
+ continue;
+
+ inChangeSequence = true;
+ beginChangeSequence = i;
continue;
+ }
+
+ if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
+ {
+ writer.Write((byte)(i - beginChangeSequence + 1));
+ if (isSmall) writer.Write((ushort)beginChangeSequence);
+ else writer.Write(beginChangeSequence);
+ writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
+ inChangeSequence = false;
+ continue;
+ }
+
if (CurrentState[i] == LastState[i])
- continue;
-
- inChangeSequence = true;
- beginChangeSequence = i;
- continue;
- }
-
- if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
- {
- writer.Write((byte)(i - beginChangeSequence + 1));
- if(isSmall) writer.Write((ushort)beginChangeSequence);
- else writer.Write(beginChangeSequence);
- writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
- inChangeSequence = false;
- continue;
- }
-
- if (CurrentState[i] == LastState[i])
- {
- writer.Write((byte)(i - beginChangeSequence));
- if(isSmall) writer.Write((ushort)beginChangeSequence);
- else writer.Write(beginChangeSequence);
- writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
- inChangeSequence = false;
+ {
+ writer.Write((byte)(i - beginChangeSequence));
+ if (isSmall) writer.Write((ushort)beginChangeSequence);
+ else writer.Write(beginChangeSequence);
+ writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
+ inChangeSequence = false;
+ }
}
}
}
+ catch (NotSupportedException)
+ {
+ //ok... we had an exception after all
+ //if we did actually run out of room in the memorystream, then try it again with a bigger buffer
+ TempBuf = new byte[TempBuf.Length * 2];
+ goto RETRY;
+ }
+
LastState = CurrentState;
- ms.Position = 0;
- RewindBuf.PushMemoryStream(ms);
+ var seg = new ArraySegment(TempBuf, 0, (int)ms.Position);
+ RewindBuf.Push(seg);
}
void RewindLarge() { RewindDelta(false); }