clean up the binary save state api a bit
This commit is contained in:
parent
0582ef4c42
commit
8bd8af15fe
|
@ -1,24 +1,55 @@
|
|||
using System;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
||||
public class BinaryStateFileNames
|
||||
{
|
||||
/*
|
||||
public const string Versiontag = "BizState 1.0";
|
||||
public const string Corestate = "Core";
|
||||
public const string Framebuffer = "Framebuffer";
|
||||
public const string Input = "Input Log";
|
||||
public const string CorestateText = "CoreText";
|
||||
public const string Movieheader = "Header";
|
||||
*/
|
||||
|
||||
private static Dictionary<BinaryStateLump, string> LumpNames;
|
||||
|
||||
static BinaryStateFileNames()
|
||||
{
|
||||
LumpNames = new Dictionary<BinaryStateLump, string>();
|
||||
LumpNames[BinaryStateLump.Versiontag] = "BizState 1.0";
|
||||
LumpNames[BinaryStateLump.Corestate] = "Core";
|
||||
LumpNames[BinaryStateLump.Framebuffer] = "Framebuffer";
|
||||
LumpNames[BinaryStateLump.Input] = "Input Log";
|
||||
LumpNames[BinaryStateLump.CorestateText] = "CoreText";
|
||||
LumpNames[BinaryStateLump.Movieheader] = "Header";
|
||||
}
|
||||
|
||||
public static string Get(BinaryStateLump Lump) { return LumpNames[Lump]; }
|
||||
}
|
||||
|
||||
|
||||
public enum BinaryStateLump
|
||||
{
|
||||
Versiontag,
|
||||
Corestate,
|
||||
Framebuffer,
|
||||
Input,
|
||||
CorestateText,
|
||||
Movieheader
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// more accurately should be called ZipStateLoader, as it supports both text and binary core data
|
||||
/// </summary>
|
||||
public class BinaryStateLoader : IDisposable
|
||||
{
|
||||
|
||||
private bool isDisposed;
|
||||
public void Dispose()
|
||||
{
|
||||
|
@ -76,8 +107,7 @@ namespace BizHawk.Client.Common
|
|||
try
|
||||
{
|
||||
ret.zip = new ZipFile(Filename);
|
||||
var e = ret.zip.GetEntry(BinaryStateFileNames.Versiontag);
|
||||
if (!ret.GetFileByName(BinaryStateFileNames.Versiontag, false, ret.ReadVersion))
|
||||
if (!ret.GetLump(BinaryStateLump.Versiontag, false, ret.ReadVersion))
|
||||
{
|
||||
ret.zip.Close();
|
||||
return null;
|
||||
|
@ -90,8 +120,16 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
bool GetFileByName(string Name, bool abort, Action<Stream> callback)
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Lump">lump to retriever</param>
|
||||
/// <param name="abort">true to throw exception on failure</param>
|
||||
/// <param name="callback">function to call with the desired stream</param>
|
||||
/// <returns>true if callback was called and stream was loaded</returns>
|
||||
public bool GetLump(BinaryStateLump Lump, bool abort, Action<Stream> callback)
|
||||
{
|
||||
string Name = BinaryStateFileNames.Get(Lump);
|
||||
var e = zip.GetEntry(Name);
|
||||
if (e != null)
|
||||
{
|
||||
|
@ -111,13 +149,44 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
public bool GetLump(BinaryStateLump Lump, bool abort, Action<BinaryReader> callback)
|
||||
{
|
||||
return GetLump(Lump, abort, delegate(Stream s)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
callback(br);
|
||||
});
|
||||
}
|
||||
|
||||
public bool GetLump(BinaryStateLump Lump, bool abort, Action<TextReader> callback)
|
||||
{
|
||||
return GetLump(Lump, abort, delegate(Stream s)
|
||||
{
|
||||
TextReader tr = new StreamReader(s);
|
||||
callback(tr);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// load binary state, or text state if binary state lump doesn't exist
|
||||
/// </summary>
|
||||
/// <param name="callbackBinary"></param>
|
||||
/// <param name="callbackText"></param>
|
||||
public void GetCoreState(Action<Stream> callbackBinary, Action<Stream> callbackText)
|
||||
{
|
||||
if (!GetFileByName(BinaryStateFileNames.Corestate, false, callbackBinary)
|
||||
&& !GetFileByName(BinaryStateFileNames.CorestateText, false, callbackText))
|
||||
if (!GetLump(BinaryStateLump.Corestate, false, callbackBinary)
|
||||
&& !GetLump(BinaryStateLump.CorestateText, false, callbackText))
|
||||
throw new Exception("Couldn't find Binary or Text savestate");
|
||||
}
|
||||
|
||||
public void GetCoreState(Action<BinaryReader> callbackBinary, Action<TextReader> callbackText)
|
||||
{
|
||||
if (!GetLump(BinaryStateLump.Corestate, false, callbackBinary)
|
||||
&& !GetLump(BinaryStateLump.CorestateText, false, callbackText))
|
||||
throw new Exception("Couldn't find Binary or Text savestate");
|
||||
}
|
||||
|
||||
/*
|
||||
public bool GetFrameBuffer(Action<Stream> callback)
|
||||
{
|
||||
return GetFileByName(BinaryStateFileNames.Framebuffer, false, callback);
|
||||
|
@ -132,6 +201,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
GetFileByName(BinaryStateFileNames.Movieheader, true, callback);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public class BinaryStateSaver : IDisposable
|
||||
|
@ -158,17 +228,39 @@ namespace BizHawk.Client.Common
|
|||
};
|
||||
zip.SetLevel(0);
|
||||
|
||||
PutFileByName(BinaryStateFileNames.Versiontag, WriteVersion);
|
||||
PutLump(BinaryStateLump.Versiontag, WriteVersion);
|
||||
}
|
||||
|
||||
void PutFileByName(string Name, Action<Stream> callback)
|
||||
public void PutLump(BinaryStateLump Lump, Action<Stream> callback)
|
||||
{
|
||||
string Name = BinaryStateFileNames.Get(Lump);
|
||||
var e = new ZipEntry(Name) {CompressionMethod = CompressionMethod.Stored};
|
||||
zip.PutNextEntry(e);
|
||||
callback(zip);
|
||||
zip.CloseEntry();
|
||||
}
|
||||
|
||||
public void PutLump(BinaryStateLump Lump, Action<BinaryWriter> callback)
|
||||
{
|
||||
PutLump(Lump, delegate(Stream s)
|
||||
{
|
||||
BinaryWriter bw = new BinaryWriter(s);
|
||||
callback(bw);
|
||||
bw.Flush();
|
||||
});
|
||||
}
|
||||
|
||||
public void PutLump(BinaryStateLump Lump, Action<TextWriter> callback)
|
||||
{
|
||||
PutLump(Lump, delegate(Stream s)
|
||||
{
|
||||
TextWriter tw = new StreamWriter(s);
|
||||
callback(tw);
|
||||
tw.Flush();
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
public void PutCoreStateBinary(Action<Stream> callback)
|
||||
{
|
||||
PutFileByName(BinaryStateFileNames.Corestate, callback);
|
||||
|
@ -193,6 +285,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
PutFileByName(BinaryStateFileNames.Movieheader, callback);
|
||||
}
|
||||
*/
|
||||
|
||||
private bool isDisposed;
|
||||
public void Dispose()
|
||||
|
|
|
@ -30,44 +30,24 @@ namespace BizHawk.Client.Common
|
|||
using (BinaryStateSaver bs = new BinaryStateSaver(fs))
|
||||
{
|
||||
#if true
|
||||
bs.PutCoreStateBinary(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryWriter bw = new BinaryWriter(s);
|
||||
Global.Emulator.SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
});
|
||||
bs.PutLump(BinaryStateLump.Corestate, (bw) => Global.Emulator.SaveStateBinary(bw));
|
||||
#else
|
||||
// this would put text states inside the zipfile
|
||||
bs.PutCoreStateText(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
Global.Emulator.SaveStateText(sw);
|
||||
sw.Flush();
|
||||
});
|
||||
bs.PutLump(BinaryStateLump.CorestateText, (tw) => Global.Emulator.SaveStateText(tw));
|
||||
#endif
|
||||
if (Global.Config.SaveScreenshotWithStates)
|
||||
{
|
||||
bs.PutFrameBuffer(
|
||||
delegate(Stream s)
|
||||
{
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
BinaryWriter bw = new BinaryWriter(s);
|
||||
bw.Write(buff);
|
||||
bw.Flush();
|
||||
});
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
bs.PutLump(BinaryStateLump.Framebuffer, (BinaryWriter bw) => bw.Write(buff));
|
||||
}
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
bs.PutInputLog(
|
||||
delegate(Stream s)
|
||||
bs.PutLump(BinaryStateLump.Input,
|
||||
delegate(TextWriter tw)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
// this never should have been a core's responsibility
|
||||
sw.WriteLine("Frame {0}", Global.Emulator.Frame);
|
||||
Global.MovieSession.HandleMovieSaveState(sw);
|
||||
sw.Flush();
|
||||
tw.WriteLine("Frame {0}", Global.Emulator.Frame);
|
||||
Global.MovieSession.HandleMovieSaveState(tw);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +57,8 @@ namespace BizHawk.Client.Common
|
|||
public static bool LoadStateFile(string path, string name)
|
||||
{
|
||||
// try to detect binary first
|
||||
BinaryStateLoader bw = BinaryStateLoader.LoadAndDetect(path);
|
||||
if (bw != null)
|
||||
BinaryStateLoader bl = BinaryStateLoader.LoadAndDetect(path);
|
||||
if (bl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -86,34 +66,16 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
bw.GetInputLogRequired(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamReader sr = new StreamReader(s);
|
||||
succeed = Global.MovieSession.HandleMovieLoadState(sr);
|
||||
});
|
||||
bl.GetLump(BinaryStateLump.Input, true, (tr) => succeed = Global.MovieSession.HandleMovieLoadState(tr));
|
||||
if (!succeed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bw.GetCoreState(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
Global.Emulator.LoadStateBinary(br);
|
||||
},
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamReader sr = new StreamReader(s);
|
||||
Global.Emulator.LoadStateText(sr);
|
||||
});
|
||||
bl.GetCoreState((br) => Global.Emulator.LoadStateBinary(br), (tr) => Global.Emulator.LoadStateText(tr));
|
||||
|
||||
bw.GetFrameBuffer(
|
||||
delegate(Stream s)
|
||||
bl.GetLump(BinaryStateLump.Framebuffer, false,
|
||||
delegate(BinaryReader br)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
int i;
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
try
|
||||
|
@ -129,7 +91,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
finally
|
||||
{
|
||||
bw.Dispose();
|
||||
bl.Dispose();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
public void HandleMovieSaveState(StreamWriter writer)
|
||||
public void HandleMovieSaveState(TextWriter writer)
|
||||
{
|
||||
if (Movie.IsActive)
|
||||
{
|
||||
|
@ -185,7 +185,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
public bool HandleMovieLoadState(StreamReader reader)
|
||||
public bool HandleMovieLoadState(TextReader reader)
|
||||
{
|
||||
if (!Movie.IsActive)
|
||||
{
|
||||
|
@ -223,8 +223,9 @@ namespace BizHawk.Client.Common
|
|||
Movie.SwitchToRecord();
|
||||
}
|
||||
|
||||
reader.BaseStream.Position = 0;
|
||||
reader.DiscardBufferedData();
|
||||
// fixme: this is evil
|
||||
((StreamReader)reader).BaseStream.Position = 0;
|
||||
((StreamReader)reader).DiscardBufferedData();
|
||||
var result = Movie.ExtractInputLog(reader, out errorMsg);
|
||||
if (!result)
|
||||
{
|
||||
|
|
|
@ -314,31 +314,29 @@ namespace BizHawk.Client.Common
|
|||
return false;
|
||||
}
|
||||
// there's a lot of common code here with SavestateManager. refactor?
|
||||
using (BinaryStateLoader bw = BinaryStateLoader.LoadAndDetect(Filename))
|
||||
using (BinaryStateLoader bl = BinaryStateLoader.LoadAndDetect(Filename))
|
||||
{
|
||||
if (bw == null)
|
||||
if (bl == null)
|
||||
return false;
|
||||
|
||||
Header.Clear();
|
||||
_records.Clear();
|
||||
|
||||
bw.GetMovieHeaderRequired(
|
||||
delegate(Stream s)
|
||||
bl.GetLump(BinaryStateLump.Movieheader, true,
|
||||
delegate(TextReader tr)
|
||||
{
|
||||
StreamReader sr = new StreamReader(s);
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
while ((line = tr.ReadLine()) != null)
|
||||
if (!Header.ParseLineFromFile(line))
|
||||
Header.Comments.Add(line);
|
||||
});
|
||||
bw.GetInputLogRequired(
|
||||
delegate(Stream s)
|
||||
bl.GetLump(BinaryStateLump.Input, true,
|
||||
delegate(TextReader tr)
|
||||
{
|
||||
StreamReader sr = new StreamReader(s);
|
||||
string line = String.Empty;
|
||||
while (true)
|
||||
{
|
||||
line = sr.ReadLine();
|
||||
line = tr.ReadLine();
|
||||
if (line == null)
|
||||
{
|
||||
break;
|
||||
|
@ -354,7 +352,7 @@ namespace BizHawk.Client.Common
|
|||
if (Header.StartsFromSavestate)
|
||||
{
|
||||
// should we raise some sort of error if there's a savestate in the archive but Header.StartsFromSavestate is false?
|
||||
bw.GetCoreState(
|
||||
bl.GetCoreState(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
|
@ -366,10 +364,9 @@ namespace BizHawk.Client.Common
|
|||
Global.Emulator.LoadStateText(sr);
|
||||
});
|
||||
}
|
||||
bw.GetFrameBuffer(
|
||||
delegate(Stream s)
|
||||
bl.GetLump(BinaryStateLump.Framebuffer, false,
|
||||
delegate(BinaryReader br)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
int i;
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
try
|
||||
|
@ -395,38 +392,14 @@ namespace BizHawk.Client.Common
|
|||
using (FileStream fs = new FileStream(Filename, FileMode.Create, FileAccess.Write))
|
||||
using (BinaryStateSaver bs = new BinaryStateSaver(fs))
|
||||
{
|
||||
bs.PutMovieHeader(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
sw.WriteLine(Header.ToString());
|
||||
sw.Flush();
|
||||
});
|
||||
bs.PutInputLog(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
sw.WriteLine(GetInputLog());
|
||||
sw.Flush();
|
||||
});
|
||||
bs.PutLump(BinaryStateLump.Movieheader, (tw) => tw.WriteLine(Header.ToString()));
|
||||
bs.PutLump(BinaryStateLump.Input, (tw) => tw.WriteLine(GetInputLog()));
|
||||
if (Header.StartsFromSavestate)
|
||||
{
|
||||
#if true
|
||||
bs.PutCoreStateText(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
Global.Emulator.SaveStateText(sw);
|
||||
sw.Flush();
|
||||
});
|
||||
bs.PutLump(BinaryStateLump.CorestateText, (tw) => Global.Emulator.SaveStateText(tw));
|
||||
#else
|
||||
bs.PutCoreStateBinary(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryWriter bw = new BinaryWriter(s);
|
||||
Global.Emulator.SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
});
|
||||
bs.PutLump(BinaryStateLump.Corestate, (bw) => Global.Emulator.SaveStateBinary(bw));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue