gambatte savestates. slightly modifies some parts of the core and the pinvoke hookup to produce memory arrays instead of disk files as savestates.

does not work, for now.  (sorry about the exceptions!)
This commit is contained in:
goyuken 2012-09-09 18:47:00 +00:00
parent a277dfa1e5
commit 8cdcae462d
8 changed files with 134 additions and 72 deletions

View File

@ -158,27 +158,53 @@ namespace BizHawk.Emulation.Consoles.GB
public void SaveStateText(System.IO.TextWriter writer) public void SaveStateText(System.IO.TextWriter writer)
{ {
var temp = SaveStateBinary();
temp.SaveAsHex(writer);
} }
public void LoadStateText(System.IO.TextReader reader) public void LoadStateText(System.IO.TextReader reader)
{ {
string hex = reader.ReadLine();
byte[] state = new byte[hex.Length / 2];
state.ReadFromHex(hex);
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
} }
public void SaveStateBinary(System.IO.BinaryWriter writer) public void SaveStateBinary(System.IO.BinaryWriter writer)
{ {
uint nlen = 0;
IntPtr ndata = IntPtr.Zero;
if (!LibGambatte.gambatte_savestate(GambatteState, VideoBuffer, 160, ref ndata, ref nlen))
throw new Exception("Gambatte failed to save the savestate!");
if (nlen == 0)
throw new Exception("Gambatte returned a 0-length savestate?");
byte[] data = new byte[nlen];
System.Runtime.InteropServices.Marshal.Copy(ndata, data, 0, (int)nlen);
LibGambatte.gambatte_savestate_destroy(ndata);
writer.Write((int)nlen);
writer.Write(data);
} }
public void LoadStateBinary(System.IO.BinaryReader reader) public void LoadStateBinary(System.IO.BinaryReader reader)
{ {
int length = reader.ReadInt32();
byte[] data = reader.ReadBytes(length);
if (!LibGambatte.gambatte_loadstate(GambatteState, data, (uint)length))
throw new Exception("Gambatte failed to load the savestate!");
} }
public byte[] SaveStateBinary() public byte[] SaveStateBinary()
{ {
return new byte[0]; MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
} }

View File

@ -161,23 +161,33 @@ namespace BizHawk.Emulation.Consoles.GB
public static extern void gambatte_savesavedata(IntPtr core); public static extern void gambatte_savesavedata(IntPtr core);
/// <summary> /// <summary>
/// Saves emulator state to the state slot selected with gambatte_selectstate(). /// Saves emulator state to the state to a byte array
/// The data will be stored in the directory given by gambatte_setsavedir().
/// </summary> /// </summary>
/// <param name="core">opaque state pointer</param> /// <param name="core">opaque state pointer</param>
/// <param name="videobuf">160x144 RGB32 (native endian) video frame buffer or 0. Used for saving a thumbnail.</param> /// <param name="videobuf">160x144 RGB32 (native endian) video frame buffer or 0. Used for saving a thumbnail.</param>
/// <param name="pitch">distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.</param> /// <param name="pitch">distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.</param>
/// <returns></returns> /// <param name="data">private savestate data returned by the core</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] /// <param name="len">the length of the data in bytes</param>
public static extern bool gambatte_savestate(IntPtr core, int[] videobuf, int pitch);
/// <summary>
/// Loads emulator state from the state slot selected with selectState().
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <returns>success</returns> /// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_loadstate(IntPtr core); public static extern bool gambatte_savestate(IntPtr core, int[] videobuf, int pitch, ref IntPtr data, ref uint len);
/// <summary>
/// destroy data returned by gambatte_savestate() to avoid memory leaks
/// </summary>
/// <param name="data">pointer from gambatte_savestate()</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_savestate_destroy(IntPtr data);
/// <summary>
/// Loads emulator state from the byte array
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="data">savestate data</param>
/// <param name="len">length of the savestate data in bytes</param>
/// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_loadstate(IntPtr core, byte[] data, uint len);
/// <summary> /// <summary>
/// Saves emulator state to the file given by 'filepath'. /// Saves emulator state to the file given by 'filepath'.
@ -187,8 +197,8 @@ namespace BizHawk.Emulation.Consoles.GB
/// <param name="pitch">distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.</param> /// <param name="pitch">distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.</param>
/// <param name="filepath"></param> /// <param name="filepath"></param>
/// <returns>success</returns> /// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] //[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_savestate_file(IntPtr core, int[] videobuf, int pitch, string filepath); //public static extern bool gambatte_savestate_file(IntPtr core, int[] videobuf, int pitch, string filepath);
/// <summary> /// <summary>
/// Loads emulator state from the file given by 'filepath'. /// Loads emulator state from the file given by 'filepath'.
@ -196,8 +206,8 @@ namespace BizHawk.Emulation.Consoles.GB
/// <param name="core">opaque state pointer</param> /// <param name="core">opaque state pointer</param>
/// <param name="filepath"></param> /// <param name="filepath"></param>
/// <returns>success</returns> /// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] //[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_loadstate_file(IntPtr core, string filepath); //public static extern bool gambatte_loadstate_file(IntPtr core, string filepath);
/// <summary> /// <summary>
/// Selects which state slot to save state to or load state from. /// Selects which state slot to save state to or load state from.

View File

@ -22,6 +22,7 @@
#include "inputgetter.h" #include "inputgetter.h"
#include "gbint.h" #include "gbint.h"
#include <string> #include <string>
#include <sstream>
namespace gambatte { namespace gambatte {
enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 }; enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 };
@ -101,12 +102,12 @@ public:
* @param pitch distance in number of pixels (not bytes) from the start of one line to the next in videoBuf. * @param pitch distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.
* @return success * @return success
*/ */
bool saveState(const gambatte::uint_least32_t *videoBuf, int pitch); //bool saveState(const gambatte::uint_least32_t *videoBuf, int pitch);
/** Loads emulator state from the state slot selected with selectState(). /** Loads emulator state from the state slot selected with selectState().
* @return success * @return success
*/ */
bool loadState(); //bool loadState();
/** Saves emulator state to the file given by 'filepath'. /** Saves emulator state to the file given by 'filepath'.
* *
@ -114,12 +115,12 @@ public:
* @param pitch distance in number of pixels (not bytes) from the start of one line to the next in videoBuf. * @param pitch distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.
* @return success * @return success
*/ */
bool saveState(const gambatte::uint_least32_t *videoBuf, int pitch, const std::string &filepath); bool saveState(const gambatte::uint_least32_t *videoBuf, int pitch, std::ostream &file);
/** Loads emulator state from the file given by 'filepath'. /** Loads emulator state from the file given by 'filepath'.
* @return success * @return success
*/ */
bool loadState(const std::string &filepath); bool loadState(std::istream &file);
/** Selects which state slot to save state to or load state from. /** Selects which state slot to save state to or load state from.
* There are 10 such slots, numbered from 0 to 9 (periodically extended for all n). * There are 10 such slots, numbered from 0 to 9 (periodically extended for all n).

View File

@ -1,5 +1,6 @@
#include "cinterface.h" #include "cinterface.h"
#include "gambatte.h" #include "gambatte.h"
#include <cstdlib>
using namespace gambatte; using namespace gambatte;
@ -88,6 +89,7 @@ __declspec(dllexport) void gambatte_savesavedata(void *core)
g->saveSavedata(); g->saveSavedata();
} }
/*
__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch) __declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch)
{ {
GB *g = (GB *) core; GB *g = (GB *) core;
@ -99,19 +101,37 @@ __declspec(dllexport) int gambatte_loadstate(void *core)
GB *g = (GB *) core; GB *g = (GB *) core;
return g->loadState(); return g->loadState();
} }
*/
__declspec(dllexport) int gambatte_savestate_file(void *core, const unsigned long *videobuf, int pitch, const char *filepath) __declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch, char **data, unsigned *len)
{ {
GB *g = (GB *) core; GB *g = (GB *) core;
return g->saveState(videobuf, pitch, std::string(filepath));
std::ostringstream os = std::ostringstream(std::ios_base::binary | std::ios_base::out);
if (!g->saveState(videobuf, pitch, os))
return 0;
os.flush();
std::string s = os.str();
char *ret = (char *) std::malloc(s.length());
std::memcpy(ret, s.data(), s.length());
*len = s.length();
*data = ret;
return 1;
} }
__declspec(dllexport) int gambatte_loadstate_file(void *core, const char *filepath) __declspec(dllexport) void gambatte_savestate_destroy(char *data)
{
std::free(data);
}
__declspec(dllexport) int gambatte_loadstate(void *core, const char *data, unsigned len)
{ {
GB *g = (GB *) core; GB *g = (GB *) core;
return g->loadState(std::string(filepath)); return g->loadState(std::istringstream(std::string(data, len), std::ios_base::binary | std::ios_base::in));
} }
/*
__declspec(dllexport) void gambatte_selectstate(void *core, int n) __declspec(dllexport) void gambatte_selectstate(void *core, int n)
{ {
GB *g = (GB *) core; GB *g = (GB *) core;
@ -123,6 +143,7 @@ __declspec(dllexport) int gambatte_currentstate(void *core)
GB *g = (GB *) core; GB *g = (GB *) core;
return g->currentState(); return g->currentState();
} }
*/
static char horriblebuff[64]; static char horriblebuff[64];
__declspec(dllexport) const char *gambatte_romtitle(void *core) __declspec(dllexport) const char *gambatte_romtitle(void *core)

View File

@ -1,6 +1,8 @@
#ifndef CINTERFACE_H #ifndef CINTERFACE_H
#define CINTERFACE_H #define CINTERFACE_H
// these are all documented on the C# side
extern "C" extern "C"
{ {
__declspec(dllexport) void *gambatte_create(); __declspec(dllexport) void *gambatte_create();
@ -24,17 +26,18 @@ extern "C"
__declspec(dllexport) void gambatte_savesavedata(void *core); __declspec(dllexport) void gambatte_savesavedata(void *core);
__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch); //__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch);
__declspec(dllexport) int gambatte_loadstate(void *core); //__declspec(dllexport) int gambatte_loadstate(void *core);
__declspec(dllexport) int gambatte_savestate_file(void *core, const unsigned long *videobuf, int pitch, const char *filepath); __declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch, char **data, unsigned *len);
__declspec(dllexport) void gambatte_savestate_destroy(char *data);
__declspec(dllexport) int gambatte_loadstate_file(void *core, const char *filepath); __declspec(dllexport) int gambatte_loadstate(void *core, const char *data, unsigned len);
__declspec(dllexport) void gambatte_selectstate(void *core, int n); //__declspec(dllexport) void gambatte_selectstate(void *core, int n);
__declspec(dllexport) int gambatte_currentstate(void *core); //__declspec(dllexport) int gambatte_currentstate(void *core);
__declspec(dllexport) const char *gambatte_romtitle(void *core); __declspec(dllexport) const char *gambatte_romtitle(void *core);

View File

@ -125,14 +125,14 @@ void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32)
p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32); p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
} }
bool GB::loadState(const std::string &filepath) { bool GB::loadState(std::istream &file) {
if (p_->cpu.loaded()) { if (p_->cpu.loaded()) {
p_->cpu.saveSavedata(); p_->cpu.saveSavedata();
SaveState state; SaveState state;
p_->cpu.setStatePtrs(state); p_->cpu.setStatePtrs(state);
if (StateSaver::loadState(state, filepath)) { if (StateSaver::loadState(state, file)) {
p_->cpu.loadState(state); p_->cpu.loadState(state);
return true; return true;
} }
@ -140,7 +140,7 @@ bool GB::loadState(const std::string &filepath) {
return false; return false;
} }
/*
bool GB::saveState(const gambatte::uint_least32_t *const videoBuf, const int pitch) { bool GB::saveState(const gambatte::uint_least32_t *const videoBuf, const int pitch) {
if (saveState(videoBuf, pitch, statePath(p_->cpu.saveBasePath(), p_->stateNo))) { if (saveState(videoBuf, pitch, statePath(p_->cpu.saveBasePath(), p_->stateNo))) {
p_->cpu.setOsdElement(newStateSavedOsdElement(p_->stateNo)); p_->cpu.setOsdElement(newStateSavedOsdElement(p_->stateNo));
@ -158,13 +158,13 @@ bool GB::loadState() {
return false; return false;
} }
*/
bool GB::saveState(const gambatte::uint_least32_t *const videoBuf, const int pitch, const std::string &filepath) { bool GB::saveState(const gambatte::uint_least32_t *const videoBuf, const int pitch, std::ostream &file) {
if (p_->cpu.loaded()) { if (p_->cpu.loaded()) {
SaveState state; SaveState state;
p_->cpu.setStatePtrs(state); p_->cpu.setStatePtrs(state);
p_->cpu.saveState(state); p_->cpu.saveState(state);
return StateSaver::saveState(state, videoBuf, pitch, filepath); return StateSaver::saveState(state, videoBuf, pitch, file);
} }
return false; return false;

View File

@ -22,7 +22,8 @@
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
#include <fstream> #include <ostream>
#include <istream>
namespace { namespace {
@ -41,8 +42,8 @@ enum AsciiChar {
struct Saver { struct Saver {
const char *label; const char *label;
void (*save)(std::ofstream &file, const SaveState &state); void (*save)(std::ostream &file, const SaveState &state);
void (*load)(std::ifstream &file, SaveState &state); void (*load)(std::istream &file, SaveState &state);
unsigned char labelsize; unsigned char labelsize;
}; };
@ -50,27 +51,27 @@ static inline bool operator<(const Saver &l, const Saver &r) {
return std::strcmp(l.label, r.label) < 0; return std::strcmp(l.label, r.label) < 0;
} }
static void put24(std::ofstream &file, const unsigned long data) { static void put24(std::ostream &file, const unsigned long data) {
file.put(data >> 16 & 0xFF); file.put(data >> 16 & 0xFF);
file.put(data >> 8 & 0xFF); file.put(data >> 8 & 0xFF);
file.put(data & 0xFF); file.put(data & 0xFF);
} }
static void put32(std::ofstream &file, const unsigned long data) { static void put32(std::ostream &file, const unsigned long data) {
file.put(data >> 24 & 0xFF); file.put(data >> 24 & 0xFF);
file.put(data >> 16 & 0xFF); file.put(data >> 16 & 0xFF);
file.put(data >> 8 & 0xFF); file.put(data >> 8 & 0xFF);
file.put(data & 0xFF); file.put(data & 0xFF);
} }
static void write(std::ofstream &file, const unsigned char data) { static void write(std::ostream &file, const unsigned char data) {
static const char inf[] = { 0x00, 0x00, 0x01 }; static const char inf[] = { 0x00, 0x00, 0x01 };
file.write(inf, sizeof(inf)); file.write(inf, sizeof(inf));
file.put(data & 0xFF); file.put(data & 0xFF);
} }
static void write(std::ofstream &file, const unsigned short data) { static void write(std::ostream &file, const unsigned short data) {
static const char inf[] = { 0x00, 0x00, 0x02 }; static const char inf[] = { 0x00, 0x00, 0x02 };
file.write(inf, sizeof(inf)); file.write(inf, sizeof(inf));
@ -78,30 +79,30 @@ static void write(std::ofstream &file, const unsigned short data) {
file.put(data & 0xFF); file.put(data & 0xFF);
} }
static void write(std::ofstream &file, const unsigned long data) { static void write(std::ostream &file, const unsigned long data) {
static const char inf[] = { 0x00, 0x00, 0x04 }; static const char inf[] = { 0x00, 0x00, 0x04 };
file.write(inf, sizeof(inf)); file.write(inf, sizeof(inf));
put32(file, data); put32(file, data);
} }
static inline void write(std::ofstream &file, const bool data) { static inline void write(std::ostream &file, const bool data) {
write(file, static_cast<unsigned char>(data)); write(file, static_cast<unsigned char>(data));
} }
static void write(std::ofstream &file, const unsigned char *data, const unsigned long sz) { static void write(std::ostream &file, const unsigned char *data, const unsigned long sz) {
put24(file, sz); put24(file, sz);
file.write(reinterpret_cast<const char*>(data), sz); file.write(reinterpret_cast<const char*>(data), sz);
} }
static void write(std::ofstream &file, const bool *data, const unsigned long sz) { static void write(std::ostream &file, const bool *data, const unsigned long sz) {
put24(file, sz); put24(file, sz);
for (unsigned long i = 0; i < sz; ++i) for (unsigned long i = 0; i < sz; ++i)
file.put(data[i]); file.put(data[i]);
} }
static unsigned long get24(std::ifstream &file) { static unsigned long get24(std::istream &file) {
unsigned long tmp = file.get() & 0xFF; unsigned long tmp = file.get() & 0xFF;
tmp = tmp << 8 | (file.get() & 0xFF); tmp = tmp << 8 | (file.get() & 0xFF);
@ -109,7 +110,7 @@ static unsigned long get24(std::ifstream &file) {
return tmp << 8 | (file.get() & 0xFF); return tmp << 8 | (file.get() & 0xFF);
} }
static unsigned long read(std::ifstream &file) { static unsigned long read(std::istream &file) {
unsigned long size = get24(file); unsigned long size = get24(file);
if (size > 4) { if (size > 4) {
@ -129,23 +130,23 @@ static unsigned long read(std::ifstream &file) {
return out; return out;
} }
static inline void read(std::ifstream &file, unsigned char &data) { static inline void read(std::istream &file, unsigned char &data) {
data = read(file) & 0xFF; data = read(file) & 0xFF;
} }
static inline void read(std::ifstream &file, unsigned short &data) { static inline void read(std::istream &file, unsigned short &data) {
data = read(file) & 0xFFFF; data = read(file) & 0xFFFF;
} }
static inline void read(std::ifstream &file, unsigned long &data) { static inline void read(std::istream &file, unsigned long &data) {
data = read(file); data = read(file);
} }
static inline void read(std::ifstream &file, bool &data) { static inline void read(std::istream &file, bool &data) {
data = read(file); data = read(file);
} }
static void read(std::ifstream &file, unsigned char *data, unsigned long sz) { static void read(std::istream &file, unsigned char *data, unsigned long sz) {
const unsigned long size = get24(file); const unsigned long size = get24(file);
if (size < sz) if (size < sz)
@ -160,7 +161,7 @@ static void read(std::ifstream &file, unsigned char *data, unsigned long sz) {
} }
} }
static void read(std::ifstream &file, bool *data, unsigned long sz) { static void read(std::istream &file, bool *data, unsigned long sz) {
const unsigned long size = get24(file); const unsigned long size = get24(file);
if (size < sz) if (size < sz)
@ -193,8 +194,8 @@ public:
}; };
static void pushSaver(SaverList::list_t &list, const char *label, static void pushSaver(SaverList::list_t &list, const char *label,
void (*save)(std::ofstream &file, const SaveState &state), void (*save)(std::ostream &file, const SaveState &state),
void (*load)(std::ifstream &file, SaveState &state), unsigned labelsize) { void (*load)(std::istream &file, SaveState &state), unsigned labelsize) {
const Saver saver = { label, save, load, labelsize }; const Saver saver = { label, save, load, labelsize };
list.push_back(saver); list.push_back(saver);
} }
@ -202,8 +203,8 @@ static void pushSaver(SaverList::list_t &list, const char *label,
SaverList::SaverList() { SaverList::SaverList() {
#define ADD(arg) do { \ #define ADD(arg) do { \
struct Func { \ struct Func { \
static void save(std::ofstream &file, const SaveState &state) { write(file, state.arg); } \ static void save(std::ostream &file, const SaveState &state) { write(file, state.arg); } \
static void load(std::ifstream &file, SaveState &state) { read(file, state.arg); } \ static void load(std::istream &file, SaveState &state) { read(file, state.arg); } \
}; \ }; \
\ \
pushSaver(list, label, Func::save, Func::load, sizeof label); \ pushSaver(list, label, Func::save, Func::load, sizeof label); \
@ -211,8 +212,8 @@ SaverList::SaverList() {
#define ADDPTR(arg) do { \ #define ADDPTR(arg) do { \
struct Func { \ struct Func { \
static void save(std::ofstream &file, const SaveState &state) { write(file, state.arg.get(), state.arg.getSz()); } \ static void save(std::ostream &file, const SaveState &state) { write(file, state.arg.get(), state.arg.getSz()); } \
static void load(std::ifstream &file, SaveState &state) { read(file, state.arg.ptr, state.arg.getSz()); } \ static void load(std::istream &file, SaveState &state) { read(file, state.arg.ptr, state.arg.getSz()); } \
}; \ }; \
\ \
pushSaver(list, label, Func::save, Func::load, sizeof label); \ pushSaver(list, label, Func::save, Func::load, sizeof label); \
@ -220,8 +221,8 @@ SaverList::SaverList() {
#define ADDARRAY(arg) do { \ #define ADDARRAY(arg) do { \
struct Func { \ struct Func { \
static void save(std::ofstream &file, const SaveState &state) { write(file, state.arg, sizeof(state.arg)); } \ static void save(std::ostream &file, const SaveState &state) { write(file, state.arg, sizeof(state.arg)); } \
static void load(std::ifstream &file, SaveState &state) { read(file, state.arg, sizeof(state.arg)); } \ static void load(std::istream &file, SaveState &state) { read(file, state.arg, sizeof(state.arg)); } \
}; \ }; \
\ \
pushSaver(list, label, Func::save, Func::load, sizeof label); \ pushSaver(list, label, Func::save, Func::load, sizeof label); \
@ -373,7 +374,7 @@ static void blendPxlPairs(PxlSum *const dst, const PxlSum *const sums) {
dst->g = sums[1].g * 8 + (sums[0].g - sums[1].g ) * 3; dst->g = sums[1].g * 8 + (sums[0].g - sums[1].g ) * 3;
} }
static void writeSnapShot(std::ofstream &file, const uint_least32_t *pixels, const int pitch) { static void writeSnapShot(std::ostream &file, const uint_least32_t *pixels, const int pitch) {
put24(file, pixels ? StateSaver::SS_WIDTH * StateSaver::SS_HEIGHT * sizeof(uint_least32_t) : 0); put24(file, pixels ? StateSaver::SS_WIDTH * StateSaver::SS_HEIGHT * sizeof(uint_least32_t) : 0);
if (pixels) { if (pixels) {
@ -411,8 +412,8 @@ namespace gambatte {
bool StateSaver::saveState(const SaveState &state, bool StateSaver::saveState(const SaveState &state,
const uint_least32_t *const videoBuf, const uint_least32_t *const videoBuf,
const int pitch, const std::string &filename) { const int pitch, std::ostream &file) {
std::ofstream file(filename.c_str(), std::ios_base::binary); //std::ostream file(filename.c_str(), std::ios_base::binary);
if (file.fail()) if (file.fail())
return false; return false;
@ -429,8 +430,8 @@ bool StateSaver::saveState(const SaveState &state,
return !file.fail(); return !file.fail();
} }
bool StateSaver::loadState(SaveState &state, const std::string &filename) { bool StateSaver::loadState(SaveState &state, std::istream &file) {
std::ifstream file(filename.c_str(), std::ios_base::binary); //std::istream file(filename.c_str(), std::ios_base::binary);
if (file.fail() || file.get() != 0) if (file.fail() || file.get() != 0)
return false; return false;

View File

@ -36,8 +36,8 @@ public:
enum { SS_HEIGHT = 144 >> SS_SHIFT }; enum { SS_HEIGHT = 144 >> SS_SHIFT };
static bool saveState(const SaveState &state, static bool saveState(const SaveState &state,
const uint_least32_t *videoBuf, int pitch, const std::string &filename); const uint_least32_t *videoBuf, int pitch, std::ostream &file);
static bool loadState(SaveState &state, const std::string &filename); static bool loadState(SaveState &state, std::istream &file);
}; };
} }