rewind: work with variable length savestates without shitting a brick. this won't give good performance, though

This commit is contained in:
goyuken 2012-10-10 15:04:13 +00:00
parent b28b677be2
commit f32f74eb1d
1 changed files with 104 additions and 74 deletions

View File

@ -39,41 +39,48 @@ namespace BizHawk.MultiClient
void CaptureRewindState64K() void CaptureRewindState64K()
{ {
byte[] CurrentState = Global.Emulator.SaveStateBinary(); byte[] CurrentState = Global.Emulator.SaveStateBinary();
if (CurrentState.Length != LastState.Length)
throw new System.Exception(string.Format("Rewind error: Savestate size mismatch:{0} old {1} new", LastState.Length, CurrentState.Length));
int beginChangeSequence = -1; int beginChangeSequence = -1;
bool inChangeSequence = false; bool inChangeSequence = false;
var ms = new MemoryStream(); var ms = new MemoryStream();
var writer = new BinaryWriter(ms); var writer = new BinaryWriter(ms);
for (int i = 0; i < CurrentState.Length; i++) if (CurrentState.Length != LastState.Length)
{ {
if (inChangeSequence == false) writer.Write(true); // full state
writer.Write(CurrentState);
}
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; continue;
}
if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
{
writer.Write((byte)(i - beginChangeSequence + 1));
writer.Write((ushort)beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
inChangeSequence = false;
continue;
}
if (CurrentState[i] == LastState[i]) if (CurrentState[i] == LastState[i])
continue; {
writer.Write((byte)(i - beginChangeSequence));
inChangeSequence = true; writer.Write((ushort)beginChangeSequence);
beginChangeSequence = i; writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
continue; inChangeSequence = false;
} }
if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
{
writer.Write((byte)(i - beginChangeSequence + 1));
writer.Write((ushort)beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
inChangeSequence = false;
continue;
}
if (CurrentState[i] == LastState[i])
{
writer.Write((byte)(i - beginChangeSequence));
writer.Write((ushort)beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
inChangeSequence = false;
} }
} }
LastState = CurrentState; LastState = CurrentState;
@ -85,41 +92,48 @@ namespace BizHawk.MultiClient
void CaptureRewindStateLarge() void CaptureRewindStateLarge()
{ {
byte[] CurrentState = Global.Emulator.SaveStateBinary(); byte[] CurrentState = Global.Emulator.SaveStateBinary();
if (CurrentState.Length != LastState.Length)
throw new System.Exception(string.Format("Rewind error: Savestate size mismatch:{0} old {1} new", LastState.Length, CurrentState.Length));
int beginChangeSequence = -1; int beginChangeSequence = -1;
bool inChangeSequence = false; bool inChangeSequence = false;
var ms = new MemoryStream(); var ms = new MemoryStream();
var writer = new BinaryWriter(ms); var writer = new BinaryWriter(ms);
for (int i = 0; i < CurrentState.Length; i++) if (CurrentState.Length != LastState.Length)
{ {
if (inChangeSequence == false) writer.Write(true); // full state
writer.Write(CurrentState);
}
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; continue;
}
if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
{
writer.Write((byte)(i - beginChangeSequence + 1));
writer.Write(beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
inChangeSequence = false;
continue;
}
if (CurrentState[i] == LastState[i]) if (CurrentState[i] == LastState[i])
continue; {
writer.Write((byte)(i - beginChangeSequence));
inChangeSequence = true; writer.Write(beginChangeSequence);
beginChangeSequence = i; writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
continue; inChangeSequence = false;
} }
if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
{
writer.Write((byte)(i - beginChangeSequence + 1));
writer.Write(beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
inChangeSequence = false;
continue;
}
if (CurrentState[i] == LastState[i])
{
writer.Write((byte)(i - beginChangeSequence));
writer.Write(beginChangeSequence);
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
inChangeSequence = false;
} }
} }
LastState = CurrentState; LastState = CurrentState;
@ -131,36 +145,52 @@ namespace BizHawk.MultiClient
{ {
var ms = RewindBuf.Pop(); var ms = RewindBuf.Pop();
var reader = new BinaryReader(ms); var reader = new BinaryReader(ms);
var output = new MemoryStream(LastState); bool fullstate = reader.ReadBoolean();
while (ms.Position < ms.Length - 1) if (fullstate)
{ {
byte len = reader.ReadByte(); Global.Emulator.LoadStateBinary(reader);
ushort offset = reader.ReadUInt16(); }
output.Position = offset; else
output.Write(ms.GetBuffer(), (int)ms.Position, len); {
ms.Position += len; var output = new MemoryStream(LastState);
while (ms.Position < ms.Length - 1)
{
byte len = reader.ReadByte();
ushort offset = reader.ReadUInt16();
output.Position = offset;
output.Write(ms.GetBuffer(), (int)ms.Position, len);
ms.Position += len;
}
reader.Close();
output.Position = 0;
Global.Emulator.LoadStateBinary(new BinaryReader(output));
} }
reader.Close();
output.Position = 0;
Global.Emulator.LoadStateBinary(new BinaryReader(output));
} }
void RewindLarge() void RewindLarge()
{ {
var ms = RewindBuf.Pop(); var ms = RewindBuf.Pop();
var reader = new BinaryReader(ms); var reader = new BinaryReader(ms);
var output = new MemoryStream(LastState); bool fullstate = reader.ReadBoolean();
while (ms.Position < ms.Length - 1) if (fullstate)
{ {
byte len = reader.ReadByte(); Global.Emulator.LoadStateBinary(reader);
int offset = reader.ReadInt32(); }
output.Position = offset; else
output.Write(ms.GetBuffer(), (int)ms.Position, len); {
ms.Position += len; var output = new MemoryStream(LastState);
while (ms.Position < ms.Length - 1)
{
byte len = reader.ReadByte();
int offset = reader.ReadInt32();
output.Position = offset;
output.Write(ms.GetBuffer(), (int)ms.Position, len);
ms.Position += len;
}
reader.Close();
output.Position = 0;
Global.Emulator.LoadStateBinary(new BinaryReader(output));
} }
reader.Close();
output.Position = 0;
Global.Emulator.LoadStateBinary(new BinaryReader(output));
} }
public void Rewind(int frames) public void Rewind(int frames)