2013-11-01 20:53:47 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
2014-07-03 18:54:53 +00:00
|
|
|
|
using BizHawk.Common.BufferExtensions;
|
2014-07-03 17:13:09 +00:00
|
|
|
|
using BizHawk.Common.IOExtensions;
|
2014-10-09 01:49:44 +00:00
|
|
|
|
using BizHawk.Common;
|
2013-11-01 20:53:47 +00:00
|
|
|
|
|
|
|
|
|
namespace BizHawk.Client.Common
|
|
|
|
|
{
|
|
|
|
|
public static class SavestateManager
|
|
|
|
|
{
|
|
|
|
|
public static void SaveStateFile(string filename, string name)
|
|
|
|
|
{
|
2014-06-16 21:19:48 +00:00
|
|
|
|
// the old method of text savestate save is now gone.
|
|
|
|
|
// a text savestate is just like a binary savestate, but with a different core lump
|
2014-10-12 04:24:31 +00:00
|
|
|
|
using (var bs = new BinaryStateSaver(filename))
|
2013-11-01 20:53:47 +00:00
|
|
|
|
{
|
2014-06-16 21:19:48 +00:00
|
|
|
|
if (Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
|
|
|
|
|
(Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred))
|
|
|
|
|
{
|
|
|
|
|
// text savestate format
|
2014-10-09 01:49:44 +00:00
|
|
|
|
using (new SimpleTime("Save Core"))
|
|
|
|
|
bs.PutLump(BinaryStateLump.CorestateText, (tw) => Global.Emulator.SaveStateText(tw));
|
2014-06-16 21:19:48 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// binary core lump format
|
2014-10-09 01:49:44 +00:00
|
|
|
|
using (new SimpleTime("Save Core"))
|
|
|
|
|
bs.PutLump(BinaryStateLump.Corestate, bw => Global.Emulator.SaveStateBinary(bw));
|
2014-06-16 21:19:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-01 20:53:47 +00:00
|
|
|
|
if (Global.Config.SaveScreenshotWithStates)
|
|
|
|
|
{
|
2014-05-07 01:36:19 +00:00
|
|
|
|
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
|
|
|
|
|
|
|
|
|
// If user wants large screenshots, or screenshot is small enough
|
|
|
|
|
if (Global.Config.SaveLargeScreenshotWithStates || buff.Length < Global.Config.BigScreenshotSize)
|
|
|
|
|
{
|
2014-10-09 01:49:44 +00:00
|
|
|
|
using (new SimpleTime("Save Framebuffer"))
|
2014-10-27 01:14:47 +00:00
|
|
|
|
bs.PutLump(BinaryStateLump.Framebuffer, DumpFramebuffer);
|
2014-05-07 01:36:19 +00:00
|
|
|
|
}
|
2013-11-01 20:53:47 +00:00
|
|
|
|
}
|
2014-01-08 03:53:53 +00:00
|
|
|
|
|
2014-06-16 21:19:48 +00:00
|
|
|
|
if (Global.MovieSession.Movie.IsActive)
|
2013-11-01 20:53:47 +00:00
|
|
|
|
{
|
2014-06-16 21:19:48 +00:00
|
|
|
|
bs.PutLump(BinaryStateLump.Input,
|
|
|
|
|
delegate(TextWriter tw)
|
2014-05-07 01:36:19 +00:00
|
|
|
|
{
|
2014-06-16 21:19:48 +00:00
|
|
|
|
// this never should have been a core's responsibility
|
|
|
|
|
tw.WriteLine("Frame {0}", Global.Emulator.Frame);
|
|
|
|
|
Global.MovieSession.HandleMovieSaveState(tw);
|
|
|
|
|
});
|
2013-11-01 20:53:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-27 01:14:47 +00:00
|
|
|
|
public static void PopulateFramebuffer(BinaryReader br)
|
|
|
|
|
{
|
|
|
|
|
var buff = Global.Emulator.VideoProvider.GetVideoBuffer();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < buff.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
int j = br.ReadInt32();
|
|
|
|
|
buff[i] = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (EndOfStreamException) { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DumpFramebuffer(BinaryWriter bw)
|
|
|
|
|
{
|
|
|
|
|
bw.Write(Global.Emulator.VideoProvider.GetVideoBuffer());
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-01 20:53:47 +00:00
|
|
|
|
public static bool LoadStateFile(string path, string name)
|
|
|
|
|
{
|
|
|
|
|
// try to detect binary first
|
2014-01-08 03:53:53 +00:00
|
|
|
|
var bl = BinaryStateLoader.LoadAndDetect(path);
|
2013-12-17 21:26:15 +00:00
|
|
|
|
if (bl != null)
|
2013-11-01 20:53:47 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2014-01-08 03:53:53 +00:00
|
|
|
|
var succeed = false;
|
2013-11-01 20:53:47 +00:00
|
|
|
|
|
|
|
|
|
if (Global.MovieSession.Movie.IsActive)
|
|
|
|
|
{
|
2014-04-18 17:41:14 +00:00
|
|
|
|
bl.GetLump(BinaryStateLump.Input, true, tr => succeed = Global.MovieSession.HandleMovieLoadState_HackyStep1(tr));
|
2014-11-09 15:48:06 +00:00
|
|
|
|
if (!succeed)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-18 17:41:14 +00:00
|
|
|
|
bl.GetLump(BinaryStateLump.Input, true, tr => succeed = Global.MovieSession.HandleMovieLoadState_HackyStep2(tr));
|
2013-11-01 20:53:47 +00:00
|
|
|
|
if (!succeed)
|
2014-01-08 03:53:53 +00:00
|
|
|
|
{
|
2013-11-01 20:53:47 +00:00
|
|
|
|
return false;
|
2014-01-08 03:53:53 +00:00
|
|
|
|
}
|
2013-11-01 20:53:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-09 01:49:44 +00:00
|
|
|
|
using (new SimpleTime("Load Core"))
|
|
|
|
|
bl.GetCoreState(br => Global.Emulator.LoadStateBinary(br), tr => Global.Emulator.LoadStateText(tr));
|
2013-11-01 20:53:47 +00:00
|
|
|
|
|
2014-10-27 01:14:47 +00:00
|
|
|
|
bl.GetLump(BinaryStateLump.Framebuffer, false, PopulateFramebuffer);
|
2013-11-01 20:53:47 +00:00
|
|
|
|
}
|
2014-09-07 15:17:47 +00:00
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2013-11-01 20:53:47 +00:00
|
|
|
|
finally
|
|
|
|
|
{
|
2013-12-17 21:26:15 +00:00
|
|
|
|
bl.Dispose();
|
2013-11-01 20:53:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else // text mode
|
|
|
|
|
{
|
|
|
|
|
if (Global.MovieSession.HandleMovieLoadState(path))
|
|
|
|
|
{
|
|
|
|
|
using (var reader = new StreamReader(path))
|
|
|
|
|
{
|
|
|
|
|
Global.Emulator.LoadStateText(reader);
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
2014-01-08 03:53:53 +00:00
|
|
|
|
var str = reader.ReadLine();
|
|
|
|
|
if (str == null)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-22 23:59:52 +00:00
|
|
|
|
if (str.Trim() == string.Empty)
|
2014-01-08 03:53:53 +00:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-11-01 20:53:47 +00:00
|
|
|
|
|
2014-01-08 03:53:53 +00:00
|
|
|
|
var args = str.Split(' ');
|
2013-11-01 20:53:47 +00:00
|
|
|
|
if (args[0] == "Framebuffer")
|
|
|
|
|
{
|
|
|
|
|
Global.Emulator.VideoProvider.GetVideoBuffer().ReadFromHex(args[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-08 03:53:53 +00:00
|
|
|
|
|
2013-11-01 20:53:47 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|