diff --git a/BizHawk.Client.Common/BinarySaveStates.cs b/BizHawk.Client.Common/BinarySaveStates.cs index f69e55f9d7..a1b0c46777 100644 --- a/BizHawk.Client.Common/BinarySaveStates.cs +++ b/BizHawk.Client.Common/BinarySaveStates.cs @@ -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 LumpNames; + + static BinaryStateFileNames() + { + LumpNames = new Dictionary(); + 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 + }; + /// /// more accurately should be called ZipStateLoader, as it supports both text and binary core data /// 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 callback) + /// + /// + /// + /// lump to retriever + /// true to throw exception on failure + /// function to call with the desired stream + /// true if callback was called and stream was loaded + public bool GetLump(BinaryStateLump Lump, bool abort, Action 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 callback) + { + return GetLump(Lump, abort, delegate(Stream s) + { + BinaryReader br = new BinaryReader(s); + callback(br); + }); + } + + public bool GetLump(BinaryStateLump Lump, bool abort, Action callback) + { + return GetLump(Lump, abort, delegate(Stream s) + { + TextReader tr = new StreamReader(s); + callback(tr); + }); + } + + /// + /// load binary state, or text state if binary state lump doesn't exist + /// + /// + /// public void GetCoreState(Action callbackBinary, Action 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 callbackBinary, Action 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 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 callback) + public void PutLump(BinaryStateLump Lump, Action 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 callback) + { + PutLump(Lump, delegate(Stream s) + { + BinaryWriter bw = new BinaryWriter(s); + callback(bw); + bw.Flush(); + }); + } + + public void PutLump(BinaryStateLump Lump, Action callback) + { + PutLump(Lump, delegate(Stream s) + { + TextWriter tw = new StreamWriter(s); + callback(tw); + tw.Flush(); + }); + } + + /* public void PutCoreStateBinary(Action callback) { PutFileByName(BinaryStateFileNames.Corestate, callback); @@ -193,6 +285,7 @@ namespace BizHawk.Client.Common { PutFileByName(BinaryStateFileNames.Movieheader, callback); } + */ private bool isDisposed; public void Dispose() diff --git a/BizHawk.Client.Common/SavestateManager.cs b/BizHawk.Client.Common/SavestateManager.cs index bc7386afba..3cfb499f82 100644 --- a/BizHawk.Client.Common/SavestateManager.cs +++ b/BizHawk.Client.Common/SavestateManager.cs @@ -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; diff --git a/BizHawk.Client.Common/movie/MovieSession.cs b/BizHawk.Client.Common/movie/MovieSession.cs index 533e33c03a..075da317da 100644 --- a/BizHawk.Client.Common/movie/MovieSession.cs +++ b/BizHawk.Client.Common/movie/MovieSession.cs @@ -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) { diff --git a/BizHawk.Client.Common/movie/TasMovie.cs b/BizHawk.Client.Common/movie/TasMovie.cs index 49851a07eb..0d264890de 100644 --- a/BizHawk.Client.Common/movie/TasMovie.cs +++ b/BizHawk.Client.Common/movie/TasMovie.cs @@ -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 } }