rework the binary savestates. not done yet. don't load any binary savestates from before this revision, you will cause death and destruction
This commit is contained in:
parent
fa8cbf650d
commit
4de024e570
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.MultiClient
|
||||
{
|
||||
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 class BinaryStateLoader : IDisposable
|
||||
{
|
||||
bool disposed = false;
|
||||
public void Dispose()
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
zip.Close();
|
||||
}
|
||||
}
|
||||
|
||||
ZipFile zip;
|
||||
|
||||
private BinaryStateLoader()
|
||||
{
|
||||
}
|
||||
|
||||
public static BinaryStateLoader LoadAndDetect(string Filename)
|
||||
{
|
||||
BinaryStateLoader ret = new BinaryStateLoader();
|
||||
try
|
||||
{
|
||||
ret.zip = new ZipFile(Filename);
|
||||
var e = ret.zip.GetEntry(BinaryStateFileNames.versiontag);
|
||||
if (e == null)
|
||||
{
|
||||
ret.zip.Close();
|
||||
return null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch (ZipException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetFileByName(string Name, bool abort, Action<Stream> callback)
|
||||
{
|
||||
var e = zip.GetEntry(Name);
|
||||
if (e != null)
|
||||
{
|
||||
using (Stream zs = zip.GetInputStream(e))
|
||||
{
|
||||
callback(zs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (abort)
|
||||
{
|
||||
throw new Exception("Essential zip section not found: " + Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetCoreState(Action<Stream> callback)
|
||||
{
|
||||
GetFileByName(BinaryStateFileNames.corestate, true, callback);
|
||||
}
|
||||
|
||||
public bool GetFrameBuffer(Action<Stream> callback)
|
||||
{
|
||||
return GetFileByName(BinaryStateFileNames.framebuffer, false, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public class BinaryStateSaver : IDisposable
|
||||
{
|
||||
ZipOutputStream zip;
|
||||
|
||||
bool disposed = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="s">not closed when finished!</param>
|
||||
public BinaryStateSaver(Stream s)
|
||||
{
|
||||
zip = new ZipOutputStream(s);
|
||||
zip.IsStreamOwner = false;
|
||||
zip.SetLevel(0);
|
||||
zip.UseZip64 = UseZip64.Off;
|
||||
|
||||
PutFileByName(BinaryStateFileNames.versiontag, (ss) => { });
|
||||
}
|
||||
|
||||
void PutFileByName(string Name, Action<Stream> callback)
|
||||
{
|
||||
var e = new ZipEntry(Name);
|
||||
e.CompressionMethod = CompressionMethod.Stored;
|
||||
zip.PutNextEntry(e);
|
||||
callback(zip);
|
||||
zip.CloseEntry();
|
||||
}
|
||||
|
||||
public void PutCoreState(Action<Stream> callback)
|
||||
{
|
||||
PutFileByName(BinaryStateFileNames.corestate, callback);
|
||||
}
|
||||
|
||||
public void PutFrameBuffer(Action<Stream> callback)
|
||||
{
|
||||
PutFileByName(BinaryStateFileNames.framebuffer, callback);
|
||||
}
|
||||
|
||||
public void PutInputLog(Action<Stream> callback)
|
||||
{
|
||||
PutFileByName(BinaryStateFileNames.input, callback);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
zip.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -152,6 +152,7 @@
|
|||
<DependentUpon>VideoWriterChooserForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="AVOut\WavWriter.cs" />
|
||||
<Compile Include="BinarySaveStates.cs" />
|
||||
<Compile Include="BizBox.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
|
|
@ -2395,12 +2395,10 @@ namespace BizHawk.MultiClient
|
|||
|
||||
public void SaveStateFile(string filename, string name, bool fromLua)
|
||||
{
|
||||
// since movie mode requires input log, always save text in that case
|
||||
if (Global.MovieSession.Movie.IsActive ||
|
||||
Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
|
||||
if (Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
|
||||
(Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred))
|
||||
{
|
||||
//DateTime start = DateTime.UtcNow;
|
||||
// text mode savestates
|
||||
var writer = new StreamWriter(filename);
|
||||
Global.Emulator.SaveStateText(writer);
|
||||
HandleMovieSaveState(writer);
|
||||
|
@ -2415,18 +2413,40 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
else
|
||||
{
|
||||
// binary savestate
|
||||
//DateTime start = DateTime.UtcNow;
|
||||
var writer = new BinaryWriter(new FileStream(filename, FileMode.Create));
|
||||
Global.Emulator.SaveStateBinary(writer);
|
||||
if (Global.Config.SaveScreenshotWithStates)
|
||||
// binary savestates
|
||||
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
|
||||
using (BinaryStateSaver bs = new BinaryStateSaver(fs))
|
||||
{
|
||||
writer.Write("FRAMEBUFFA");
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
writer.Write(buff.Length);
|
||||
writer.Write(buff);
|
||||
bs.PutCoreState(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryWriter bw = new BinaryWriter(s);
|
||||
Global.Emulator.SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
});
|
||||
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();
|
||||
});
|
||||
}
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
bs.PutInputLog(
|
||||
delegate(Stream s)
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
HandleMovieSaveState(sw);
|
||||
sw.WriteLine("Frame: {0}", Global.Emulator.Frame);
|
||||
sw.Flush();
|
||||
});
|
||||
}
|
||||
}
|
||||
writer.Close();
|
||||
//DateTime end = DateTime.UtcNow;
|
||||
//Console.WriteLine("n64 savestate TEXT time: {0}", (end - start).TotalMilliseconds);
|
||||
}
|
||||
|
@ -2459,74 +2479,77 @@ namespace BizHawk.MultiClient
|
|||
|
||||
public void LoadStateFile(string path, string name, bool fromLua = false)
|
||||
{
|
||||
if (!Global.MovieSession.Movie.IsActive)
|
||||
// try to detect binary first
|
||||
BinaryStateLoader bw = BinaryStateLoader.LoadAndDetect(path);
|
||||
if (bw != null)
|
||||
{
|
||||
// only when movies are not playing can we possibly load binary savestates
|
||||
bool binary = false;
|
||||
using (var s = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
try
|
||||
{
|
||||
int i;
|
||||
while ((i = s.ReadByte()) != -1)
|
||||
{
|
||||
// unicode support will need something better here
|
||||
if (i < 0x9 || (i > 0x7f))
|
||||
{
|
||||
binary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// binary mode
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
throw new Exception("NOT DONE YET BRO");
|
||||
|
||||
if (binary)
|
||||
{
|
||||
using (var reader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
Global.Emulator.LoadStateBinary(reader);
|
||||
try
|
||||
bw.GetCoreState(
|
||||
delegate(Stream s)
|
||||
{
|
||||
string s = reader.ReadString();
|
||||
if (s.Equals("FRAMEBUFFA"))
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
Global.Emulator.LoadStateBinary(br);
|
||||
});
|
||||
|
||||
bw.GetFrameBuffer(
|
||||
delegate(Stream s)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(s);
|
||||
int i;
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
try
|
||||
{
|
||||
int len = reader.ReadInt32();
|
||||
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
||||
for (int i = 0; i < len; i++)
|
||||
buff[i] = reader.ReadInt32();
|
||||
for (i = 0; i < buff.Length; i++)
|
||||
{
|
||||
int j = br.ReadInt32();
|
||||
buff[i] = j;
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
bw.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// text mode
|
||||
|
||||
if (HandleMovieLoadState(path))
|
||||
{
|
||||
using (var reader = new StreamReader(path))
|
||||
{
|
||||
Global.Emulator.LoadStateText(reader);
|
||||
|
||||
while (true)
|
||||
{
|
||||
string str = reader.ReadLine();
|
||||
if (str == null) break;
|
||||
if (str.Trim() == "") continue;
|
||||
|
||||
string[] args = str.Split(' ');
|
||||
if (args[0] == "Framebuffer")
|
||||
{
|
||||
Global.Emulator.VideoProvider.GetVideoBuffer().ReadFromHex(args[1]);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fall through to text situation
|
||||
}
|
||||
Global.OSD.AddMessage("Loadstate error!");
|
||||
}
|
||||
|
||||
|
||||
if (HandleMovieLoadState(path))
|
||||
{
|
||||
var reader = new StreamReader(path);
|
||||
Global.Emulator.LoadStateText(reader);
|
||||
|
||||
while (true)
|
||||
{
|
||||
string str = reader.ReadLine();
|
||||
if (str == null) break;
|
||||
if (str.Trim() == "") continue;
|
||||
|
||||
string[] args = str.Split(' ');
|
||||
if (args[0] == "Framebuffer")
|
||||
{
|
||||
Global.Emulator.VideoProvider.GetVideoBuffer().ReadFromHex(args[1]);
|
||||
}
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
}
|
||||
else
|
||||
Global.OSD.AddMessage("Loadstate error!");
|
||||
|
||||
cleanup:
|
||||
Global.OSD.ClearGUIText();
|
||||
UpdateToolsBefore(fromLua);
|
||||
|
|
|
@ -654,7 +654,14 @@ namespace BizHawk.MultiClient
|
|||
|
||||
public void LoadLogFromSavestateText(string path)
|
||||
{
|
||||
var reader = new StreamReader(path);
|
||||
using (var reader = new StreamReader(path))
|
||||
{
|
||||
LoadLogFromSavestateText(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadLogFromSavestateText(TextReader reader)
|
||||
{
|
||||
int? stateFrame = null;
|
||||
//We are in record mode so replace the movie log with the one from the savestate
|
||||
if (!Global.MovieSession.MultiTrack.IsActive)
|
||||
|
@ -754,7 +761,6 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
if (IsCountingRerecords)
|
||||
Rerecords++;
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
public string GetTime(bool preLoad)
|
||||
|
|
Loading…
Reference in New Issue