clean up the binary save state api a bit

This commit is contained in:
goyuken 2013-12-17 21:26:15 +00:00
parent 0582ef4c42
commit 8bd8af15fe
4 changed files with 135 additions and 106 deletions

View File

@ -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()

View File

@ -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;

View File

@ -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)
{

View File

@ -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
}
}