saturn: savestates. rather unwieldly, taking ~11MiB in text form and causing a noticable pause to save or load. core changes to support savestating: savestates reverted to version 1 (no movie info and no framebuffer, both of which are handled in bizhawk), and parts dealing with verifiying size through liberal use of fseek() (which doesn't work here) removed
This commit is contained in:
parent
99ff09555e
commit
b399e87ffe
|
@ -38,6 +38,39 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
|
|||
PipeName = "BizHawk-" + Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public void Get(Stream s)
|
||||
{
|
||||
if (thr != null)
|
||||
throw new Exception("Can only serve one thing at a time!");
|
||||
if (e != null)
|
||||
throw new Exception("Previous attempt failed!", e);
|
||||
if (!s.CanWrite)
|
||||
throw new ArgumentException("Stream must be readable!");
|
||||
|
||||
using (var evt = new ManualResetEventSlim())
|
||||
{
|
||||
thr = new Thread(delegate()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var srv = new NamedPipeServerStream(PipeName, PipeDirection.In))
|
||||
{
|
||||
evt.Set();
|
||||
srv.WaitForConnection();
|
||||
srv.CopyTo(s);
|
||||
//srv.Flush();
|
||||
}
|
||||
}
|
||||
catch (Exception ee)
|
||||
{
|
||||
e = ee;
|
||||
}
|
||||
});
|
||||
thr.Start();
|
||||
evt.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
public void Offer(Stream s)
|
||||
{
|
||||
if (thr != null)
|
||||
|
@ -47,23 +80,28 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
|
|||
if (!s.CanRead)
|
||||
throw new ArgumentException("Stream must be readable!");
|
||||
|
||||
thr = new Thread(delegate()
|
||||
{
|
||||
try
|
||||
using (var evt = new ManualResetEventSlim())
|
||||
{
|
||||
thr = new Thread(delegate()
|
||||
{
|
||||
using (var srv = new NamedPipeServerStream(PipeName, PipeDirection.Out))
|
||||
try
|
||||
{
|
||||
srv.WaitForConnection();
|
||||
s.CopyTo(srv);
|
||||
srv.WaitForPipeDrain();
|
||||
using (var srv = new NamedPipeServerStream(PipeName, PipeDirection.Out))
|
||||
{
|
||||
evt.Set();
|
||||
srv.WaitForConnection();
|
||||
s.CopyTo(srv);
|
||||
srv.WaitForPipeDrain();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ee)// might want to do something about this...
|
||||
{
|
||||
e = ee;
|
||||
}
|
||||
});
|
||||
thr.Start();
|
||||
catch (Exception ee)
|
||||
{
|
||||
e = ee;
|
||||
}
|
||||
});
|
||||
thr.Start();
|
||||
evt.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
public Exception GetResults()
|
||||
|
|
|
@ -66,6 +66,28 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
|
|||
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void libyabause_softreset();
|
||||
|
||||
/// <summary>
|
||||
/// hard reset, or something like that
|
||||
/// </summary>
|
||||
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void libyabause_hardreset();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fn"></param>
|
||||
/// <returns>success</returns>
|
||||
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool libyabause_loadstate(string fn);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fn"></param>
|
||||
/// <returns>success</returns>
|
||||
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool libyabause_savestate(string fn);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Sega.Saturn
|
||||
{
|
||||
|
@ -202,27 +203,100 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
|
|||
IsLagFrame = false;
|
||||
}
|
||||
|
||||
public void SaveStateText(System.IO.TextWriter writer)
|
||||
#region savestates
|
||||
|
||||
void LoadCoreBinary(byte[] data)
|
||||
{
|
||||
var fp = new FilePiping();
|
||||
fp.Offer(data);
|
||||
bool succeed = LibYabause.libyabause_loadstate(fp.GetPipeNameNative());
|
||||
var e = fp.GetResults();
|
||||
if (e != null)
|
||||
throw e;
|
||||
if (!succeed)
|
||||
throw new Exception("libyabause_loadstate() failed");
|
||||
}
|
||||
|
||||
public void LoadStateText(System.IO.TextReader reader)
|
||||
byte[] SaveCoreBinary()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
var fp = new FilePiping();
|
||||
fp.Get(ms);
|
||||
bool succeed = LibYabause.libyabause_savestate(fp.GetPipeNameNative());
|
||||
var e = fp.GetResults();
|
||||
if (e != null)
|
||||
throw e;
|
||||
var ret = ms.ToArray();
|
||||
ms.Close();
|
||||
if (!succeed)
|
||||
throw new Exception("libyabause_savestate() failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void SaveStateBinary(System.IO.BinaryWriter writer)
|
||||
// these next 5 functions are all exact copy paste from gambatte.
|
||||
// if something's wrong here, it's probably wrong there too
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
var temp = SaveStateBinary();
|
||||
temp.SaveAsHex(writer);
|
||||
// write extra copy of stuff we don't use
|
||||
writer.WriteLine("Frame {0}", Frame);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(System.IO.BinaryReader reader)
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
string hex = reader.ReadLine();
|
||||
if (hex.StartsWith("emuVersion")) // movie save
|
||||
{
|
||||
do // theoretically, our portion should start right after StartsFromSavestate, maybe...
|
||||
{
|
||||
hex = reader.ReadLine();
|
||||
} while (!hex.StartsWith("StartsFromSavestate"));
|
||||
hex = reader.ReadLine();
|
||||
}
|
||||
byte[] state = new byte[hex.Length / 2];
|
||||
state.ReadFromHex(hex);
|
||||
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
byte[] data = SaveCoreBinary();
|
||||
|
||||
writer.Write(data.Length);
|
||||
writer.Write(data);
|
||||
|
||||
// other variables
|
||||
writer.Write(IsLagFrame);
|
||||
writer.Write(LagCount);
|
||||
writer.Write(Frame);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
int length = reader.ReadInt32();
|
||||
byte[] data = reader.ReadBytes(length);
|
||||
|
||||
LoadCoreBinary(data);
|
||||
|
||||
// other variables
|
||||
IsLagFrame = reader.ReadBoolean();
|
||||
LagCount = reader.ReadInt32();
|
||||
Frame = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
return new byte[0];
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
public IList<MemoryDomain> MemoryDomains
|
||||
|
|
Binary file not shown.
|
@ -160,6 +160,7 @@ static INLINE int StateWriteHeader(FILE *fp, const char *name, int version) {
|
|||
}
|
||||
|
||||
static INLINE int StateFinishHeader(FILE *fp, int offset) {
|
||||
/*
|
||||
IOCheck_struct check;
|
||||
int size = 0;
|
||||
size = ftell(fp) - offset;
|
||||
|
@ -169,6 +170,8 @@ static INLINE int StateFinishHeader(FILE *fp, int offset) {
|
|||
ywrite(&check, (void *)&size, sizeof(size), 1, fp); // write true size
|
||||
fseek(fp, 0, SEEK_END);
|
||||
return (check.done == check.size) ? (size + 12) : -1;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INLINE int StateCheckRetrieveHeader(FILE *fp, const char *name, int *version, int *size) {
|
||||
|
|
|
@ -177,6 +177,21 @@ extern "C" __declspec(dllexport) void libyabause_softreset()
|
|||
YabauseResetButton();
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) void libyabause_hardreset()
|
||||
{
|
||||
YabauseReset();
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int libyabause_loadstate(const char *fn)
|
||||
{
|
||||
return !YabLoadState(fn);
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int libyabause_savestate(const char *fn)
|
||||
{
|
||||
return !YabSaveState(fn);
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int libyabause_frameadvance(int *w, int *h, int *nsamp)
|
||||
{
|
||||
LagFrameFlag = 1;
|
||||
|
|
|
@ -1028,7 +1028,7 @@ int YabSaveState(const char *filename)
|
|||
#endif
|
||||
|
||||
// Write version(fix me)
|
||||
i = 2;
|
||||
i = 1;//2;
|
||||
ywrite(&check, (void *)&i, sizeof(i), 1, fp);
|
||||
|
||||
// Skip the next 4 bytes for now
|
||||
|
@ -1036,10 +1036,10 @@ int YabSaveState(const char *filename)
|
|||
ywrite(&check, (void *)&i, sizeof(i), 1, fp);
|
||||
|
||||
//write frame number
|
||||
ywrite(&check, (void *)&framecounter, 4, 1, fp);
|
||||
//ywrite(&check, (void *)&framecounter, 4, 1, fp);
|
||||
|
||||
//this will be updated with the movie position later
|
||||
ywrite(&check, (void *)&framecounter, 4, 1, fp);
|
||||
//ywrite(&check, (void *)&framecounter, 4, 1, fp);
|
||||
|
||||
// Go through each area and write each state
|
||||
i += CartSaveState(fp);
|
||||
|
@ -1071,7 +1071,7 @@ int YabSaveState(const char *filename)
|
|||
ywrite(&check, (void *)&temp32, sizeof(u32), 1, fp);
|
||||
ywrite(&check, (void *)&yabsys.CurSH2FreqType, sizeof(int), 1, fp);
|
||||
ywrite(&check, (void *)&yabsys.IsPal, sizeof(int), 1, fp);
|
||||
|
||||
/*
|
||||
VIDCore->GetGlSize(&outputwidth, &outputheight);
|
||||
|
||||
totalsize=outputwidth * outputheight * sizeof(u32);
|
||||
|
@ -1097,15 +1097,15 @@ int YabSaveState(const char *filename)
|
|||
movieposition=ftell(fp);
|
||||
//write the movie to the end of the savestate
|
||||
SaveMovieInState(fp, check);
|
||||
|
||||
*/
|
||||
i += StateFinishHeader(fp, offset);
|
||||
|
||||
/*
|
||||
// Go back and update size
|
||||
fseek(fp, 8, SEEK_SET);
|
||||
ywrite(&check, (void *)&i, sizeof(i), 1, fp);
|
||||
fseek(fp, 16, SEEK_SET);
|
||||
ywrite(&check, (void *)&movieposition, sizeof(movieposition), 1, fp);
|
||||
|
||||
*/
|
||||
fclose(fp);
|
||||
|
||||
OSDPushMessage(OSDMSG_STATUS, 150, "STATE SAVED");
|
||||
|
@ -1187,14 +1187,14 @@ int YabLoadState(const char *filename)
|
|||
}
|
||||
|
||||
// Make sure size variable matches actual size minus header
|
||||
fseek(fp, 0, SEEK_END);
|
||||
//fseek(fp, 0, SEEK_END);
|
||||
|
||||
if (size != (ftell(fp) - headersize))
|
||||
{
|
||||
fclose(fp);
|
||||
return -2;
|
||||
}
|
||||
fseek(fp, headersize, SEEK_SET);
|
||||
//if (size != (ftell(fp) - headersize))
|
||||
//{
|
||||
// fclose(fp);
|
||||
// return -2;
|
||||
//}
|
||||
//fseek(fp, headersize, SEEK_SET);
|
||||
|
||||
// Verify version here
|
||||
|
||||
|
|
Loading…
Reference in New Issue