bizswan: savestates

This commit is contained in:
goyuken 2014-05-31 05:57:18 +00:00
parent 8f87c2e854
commit 0ee073b71b
25 changed files with 495 additions and 24 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.WonderSwan
{
@ -105,6 +106,17 @@ namespace BizHawk.Emulation.Cores.WonderSwan
[DllImport(dd, CallingConvention = cc)]
public static extern bool bizswan_getmemoryarea(IntPtr core, int index, out IntPtr name, out int size, out IntPtr data);
[DllImport(dd, CallingConvention = cc)]
public static extern int bizswan_binstatesize(IntPtr core);
[DllImport(dd, CallingConvention = cc)]
public static extern bool bizswan_binstatesave(IntPtr core, byte[] data, int length);
[DllImport(dd, CallingConvention = cc)]
public static extern bool bizswan_binstateload(IntPtr core, byte[] data, int length);
[DllImport(dd, CallingConvention = cc)]
public static extern void bizswan_txtstatesave(IntPtr core, [In]ref TextStateFPtrs ff);
[DllImport(dd, CallingConvention = cc)]
public static extern void bizswan_txtstateload(IntPtr core, [In]ref TextStateFPtrs ff);
/// <summary>
/// return a CPU register

View File

@ -56,6 +56,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
try
{
var ss = _SyncSettings.GetNativeSettings();
if (deterministicEmulation)
ss.userealtime = false;
bool rotate = false;
@ -70,6 +72,9 @@ namespace BizHawk.Emulation.Cores.WonderSwan
InitVideo(rotate);
PutSettings(_Settings);
SetMemoryDomains();
savebuff = new byte[BizSwan.bizswan_binstatesize(Core)];
savebuff2 = new byte[savebuff.Length + 13];
}
catch
{
@ -157,25 +162,81 @@ namespace BizHawk.Emulation.Cores.WonderSwan
#region Savestates
JsonSerializer ser = new JsonSerializer() { Formatting = Formatting.Indented };
class TextStateData
{
public int Frame;
public int LagCount;
public bool IsLagFrame;
}
public void SaveStateText(TextWriter writer)
{
var s = new TextState<TextStateData>();
s.Prepare();
var ff = s.GetFunctionPointers();
BizSwan.bizswan_txtstatesave(Core, ref ff);
s.ExtraData.IsLagFrame = IsLagFrame;
s.ExtraData.LagCount = LagCount;
s.ExtraData.Frame = Frame;
ser.Serialize(writer, s);
// write extra copy of stuff we don't use
writer.WriteLine();
writer.WriteLine("Frame {0}", Frame);
}
public void LoadStateText(TextReader reader)
{
var s = (TextState<TextStateData>)ser.Deserialize(reader, typeof(TextState<TextStateData>));
s.Prepare();
var ff = s.GetFunctionPointers();
BizSwan.bizswan_txtstateload(Core, ref ff);
IsLagFrame = s.ExtraData.IsLagFrame;
LagCount = s.ExtraData.LagCount;
Frame = s.ExtraData.Frame;
}
byte[] savebuff;
byte[] savebuff2;
public void SaveStateBinary(BinaryWriter writer)
{
if (!BizSwan.bizswan_binstatesave(Core, savebuff, savebuff.Length))
throw new InvalidOperationException("bizswan_binstatesave() returned false!");
writer.Write(savebuff.Length);
writer.Write(savebuff);
// other variables
writer.Write(IsLagFrame);
writer.Write(LagCount);
writer.Write(Frame);
}
public void LoadStateBinary(BinaryReader reader)
{
int length = reader.ReadInt32();
if (length != savebuff.Length)
throw new InvalidOperationException("Save buffer size mismatch!");
reader.Read(savebuff, 0, length);
if (!BizSwan.bizswan_binstateload(Core, savebuff, savebuff.Length))
throw new InvalidOperationException("bizswan_binstateload() returned false!");
// other variables
IsLagFrame = reader.ReadBoolean();
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
return new byte[0];
var ms = new MemoryStream(savebuff2, true);
var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return savebuff2;
}
public bool BinarySaveStatesPreferred

Binary file not shown.

View File

@ -75,6 +75,7 @@
<ClCompile Include="..\gfx.cpp" />
<ClCompile Include="..\interrupt.cpp" />
<ClCompile Include="..\memory.cpp" />
<ClCompile Include="..\newstate.cpp" />
<ClCompile Include="..\rtc.cpp" />
<ClCompile Include="..\sound.cpp" />
<ClCompile Include="..\system.cpp" />
@ -90,6 +91,7 @@
<ClInclude Include="..\memory.h" />
<ClInclude Include="..\msvc\inttypes.h" />
<ClInclude Include="..\msvc\stdint.h" />
<ClInclude Include="..\newstate.h" />
<ClInclude Include="..\rtc.h" />
<ClInclude Include="..\sound.h" />
<ClInclude Include="..\system.h" />

View File

@ -57,6 +57,9 @@
<ClCompile Include="..\system.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\newstate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\eeprom.h">
@ -101,6 +104,9 @@
<ClInclude Include="..\system.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\newstate.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\start.inc">

View File

@ -114,9 +114,6 @@ namespace MDFN_IEN_WSWAN
255,255,255,255
};
//static uint8 iEEPROM_Command, EEPROM_Command;
//static uint16 iEEPROM_Address, EEPROM_Address;
uint8 EEPROM::Read(uint32 A)
{
switch(A)
@ -203,4 +200,15 @@ namespace MDFN_IEN_WSWAN
iEEPROM[0x375] = Blood;
}
SYNCFUNC(EEPROM)
{
NSS(iEEPROM_Command);
NSS(EEPROM_Command);
NSS(iEEPROM_Address);
NSS(EEPROM_Address);
NSS(eeprom_size);
NSS(iEEPROM);
NSS(wsEEPROM);
}
}

View File

@ -27,6 +27,7 @@ public:
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -19,8 +19,6 @@
*/
#include "system.h"
//#include <mednafen/video.h>
//#include <trio/trio.h>
#include <cstring>
namespace MDFN_IEN_WSWAN
@ -602,4 +600,71 @@ namespace MDFN_IEN_WSWAN
std::memset(wsCols, 0, sizeof(wsCols));
}
SYNCFUNC(GFX)
{
// TCACHE stuff. we invalidate the cache instead of saving it
if (isReader)
{
std::memset(wsTCacheUpdate, 0, sizeof(wsTCacheUpdate));
std::memset(wsTCacheUpdate2, 0, sizeof(wsTCacheUpdate2));
}
/*
NSS(tiles);
NSS(wsTCache);
NSS(wsTCache2);
NSS(wsTCacheFlipped);
NSS(wsTCacheFlipped2);
NSS(wsTCacheUpdate);
NSS(wsTCacheUpdate2);
NSS(wsTileRow);
*/
NSS(wsVMode);
NSS(wsMonoPal);
NSS(wsColors);
NSS(wsCols);
NSS(ColorMapG);
NSS(ColorMap);
NSS(LayerEnabled);
NSS(wsLine);
NSS(SpriteTable);
NSS(SpriteCountCache);
NSS(DispControl);
NSS(BGColor);
NSS(LineCompare);
NSS(SPRBase);
NSS(SpriteStart);
NSS(SpriteCount);
NSS(FGBGLoc);
NSS(FGx0);
NSS(FGy0);
NSS(FGx1);
NSS(FGy1);
NSS(SPRx0);
NSS(SPRy0);
NSS(SPRx1);
NSS(SPRy1);
NSS(BGXScroll);
NSS(BGYScroll);
NSS(FGXScroll);
NSS(FGYScroll);
NSS(LCDControl);
NSS(LCDIcons);
NSS(BTimerControl);
NSS(HBTimerPeriod);
NSS(VBTimerPeriod);
NSS(HBCounter);
NSS(VBCounter);
NSS(VideoMode);
NSS(wsc); // mono / color
}
}

View File

@ -40,8 +40,9 @@ private:
uint8 wsTCacheUpdate[512];
uint8 wsTCacheUpdate2[512];
uint8 wsTileRow[8];
int wsVMode; // doesn't belong here?
// TCACHE/====================================
int wsVMode;
uint32 wsMonoPal[16][4];
uint32 wsColors[8];
uint32 wsCols[16][16];
@ -78,16 +79,9 @@ private:
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};
// ?
//extern uint32 dx_r,dx_g,dx_b,dx_sr,dx_sg,dx_sb;
//extern uint32 dx_bits,dx_pitch,cmov,dx_linewidth_blit,dx_buffer_line;
}
#endif

View File

@ -74,4 +74,14 @@ namespace MDFN_IEN_WSWAN
Recalc();
}
SYNCFUNC(Interrupt)
{
NSS(IStatus);
NSS(IEnable);
NSS(IVectorBase);
NSS(IOn_Cache);
NSS(IOn_Which);
NSS(IVector_Cache);
}
}

View File

@ -41,6 +41,7 @@ private:
void Recalc();
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};
}

View File

@ -27,9 +27,6 @@
namespace MDFN_IEN_WSWAN
{
//extern uint16 WSButtonStatus;
void Memory::Write20(uint32 A, uint8 V)
{
uint32 offset, bank;
@ -336,4 +333,34 @@ namespace MDFN_IEN_WSWAN
CommData = 0;
}
SYNCFUNC(Memory)
{
NSS(wsRAM);
//NSS(rom_size);
//PSS(wsCartROM, rom_size);
NSS(sram_size);
PSS(wsSRAM, sram_size);
NSS(WSButtonStatus);
NSS(Lagged);
NSS(ButtonWhich);
NSS(ButtonReadLatch);
NSS(DMASource);
NSS(DMADest);
NSS(DMALength);
NSS(DMAControl);
NSS(SoundDMASource);
NSS(SoundDMALength);
NSS(SoundDMAControl);
NSS(BankSelector);
NSS(CommControl);
NSS(CommData);
NSS(language);
}
}

View File

@ -53,6 +53,7 @@ private:
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
private:
void CheckDMA();
@ -66,8 +67,6 @@ enum
MEMORY_GSREG_BNK3SLCT,
};
}
#endif

View File

@ -16,6 +16,7 @@ SRCS = \
../system.cpp \
../tcache.cpp \
../v30mz.cpp \
../newstate.cpp \
../Blip/Blip_Buffer.cpp
OBJS = $(SRCS:.cpp=.o)

69
wonderswan/newstate.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "newstate.h"
#include <cstring>
#include <algorithm>
namespace MDFN_IEN_WSWAN {
NewStateDummy::NewStateDummy()
:length(0)
{
}
void NewStateDummy::Save(const void *ptr, size_t size, const char *name)
{
length += size;
}
void NewStateDummy::Load(void *ptr, size_t size, const char *name)
{
}
NewStateExternalBuffer::NewStateExternalBuffer(char *buffer, long maxlength)
:buffer(buffer), length(0), maxlength(maxlength)
{
}
void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name)
{
if (maxlength - length >= (long)size)
{
std::memcpy(buffer + length, ptr, size);
}
length += size;
}
void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name)
{
char *dst = static_cast<char *>(ptr);
if (maxlength - length >= (long)size)
{
std::memcpy(dst, buffer + length, size);
}
length += size;
}
NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff)
:Save_(ff->Save_),
Load_(ff->Load_),
EnterSection_(ff->EnterSection_),
ExitSection_(ff->ExitSection_)
{
}
void NewStateExternalFunctions::Save(const void *ptr, size_t size, const char *name)
{
Save_(ptr, size, name);
}
void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name)
{
Load_(ptr, size, name);
}
void NewStateExternalFunctions::EnterSection(const char *name)
{
EnterSection_(name);
}
void NewStateExternalFunctions::ExitSection(const char *name)
{
ExitSection_(name);
}
}

102
wonderswan/newstate.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef NEWSTATE_H
#define NEWSTATE_H
#include <cstring>
#include <cstddef>
namespace MDFN_IEN_WSWAN {
class NewState
{
public:
virtual void Save(const void *ptr, size_t size, const char *name) = 0;
virtual void Load(void *ptr, size_t size, const char *name) = 0;
virtual void EnterSection(const char *name) { }
virtual void ExitSection(const char *name) { }
};
class NewStateDummy : public NewState
{
private:
long length;
public:
NewStateDummy();
long GetLength() { return length; }
void Rewind() { length = 0; }
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
};
class NewStateExternalBuffer : public NewState
{
private:
char *const buffer;
long length;
const long maxlength;
public:
NewStateExternalBuffer(char *buffer, long maxlength);
long GetLength() { return length; }
void Rewind() { length = 0; }
bool Overflow() { return length > maxlength; }
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
};
struct FPtrs
{
void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name);
};
class NewStateExternalFunctions : public NewState
{
private:
void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name);
public:
NewStateExternalFunctions(const FPtrs *ff);
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
virtual void EnterSection(const char *name);
virtual void ExitSection(const char *name);
};
// defines and explicitly instantiates
#define SYNCFUNC(x)\
template void x::SyncState<false>(NewState *ns);\
template void x::SyncState<true>(NewState *ns);\
template<bool isReader>void x::SyncState(NewState *ns)
// N = normal variable
// P = pointer to fixed size data
// S = "sub object"
// T = "ptr to sub object"
// R = pointer, store its offset from some other pointer
// E = general purpose cased value "enum"
// first line is default value in converted enum; last line is default value in argument x
#define EBS(x,d) do { int _ttmp = (d); if (isReader) ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0)
#define EVS(x,v,n) else if (!isReader && (x) == (v)) _ttmp = (n); else if (isReader && _ttmp == (n)) (x) = (v)
#define EES(x,d) else if (isReader) (x) = (d); if (!isReader) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0)
#define RSS(x,b) do { if (isReader)\
{ ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == (ptrdiff_t)0xdeadbeef ? 0 : (b) + _ttmp); }\
else\
{ ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } } while (0)
#define PSS(x,s) do { if (isReader) ns->Load((x), (s), #x); else ns->Save((x), (s), #x); } while (0)
#define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0)
#define SSS(x) do { ns->EnterSection(#x); (x).SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
}
#endif

View File

@ -112,4 +112,14 @@ namespace MDFN_IEN_WSWAN
}
}
SYNCFUNC(RTC)
{
NSS(CurrentTime);
NSS(userealtime);
NSS(ClockCycleCounter);
NSS(wsCA15);
NSS(Command);
NSS(Data);
}
}

View File

@ -22,6 +22,7 @@ private:
uint8 Command, Data;
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -379,4 +379,35 @@ namespace MDFN_IEN_WSWAN
sbuf[y]->clear();
}
SYNCFUNC(Sound)
{
// don't need to save any of the blip stuff
NSS(period[4]);
NSS(volume[4]);
NSS(voice_volume);
NSS(sweep_step);
NSS(sweep_value);
NSS(noise_control);
NSS(control);
NSS(output_control);
NSS(sweep_8192_divider);
NSS(sweep_counter);
NSS(SampleRAMPos);
NSS(sample_cache);
NSS(last_v_val);
NSS(HyperVoice);
NSS(last_hv_val);
NSS(period_counter);
NSS(last_val);
NSS(sample_pos);
NSS(nreg);
NSS(last_ts);
}
}

View File

@ -61,6 +61,7 @@ private:
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -237,6 +237,7 @@ namespace MDFN_IEN_WSWAN
{
return eeprom.ieeprom_size + eeprom.eeprom_size + memory.sram_size;
}
bool System::SaveRamLoad(const uint8 *data, int size)
{
if (size != SaveRamSize())
@ -294,6 +295,18 @@ namespace MDFN_IEN_WSWAN
return ret;
}
SYNCFUNC(System)
{
SSS(gfx);
SSS(memory);
SSS(eeprom);
SSS(rtc);
SSS(sound);
SSS(cpu);
SSS(interrupt);
NSS(rotate);
}
EXPORT System *bizswan_new()
{
@ -352,4 +365,36 @@ namespace MDFN_IEN_WSWAN
return s->GetMemoryArea(index, *name, *size, *data);
}
EXPORT int bizswan_binstatesize(System *s)
{
NewStateDummy dummy;
s->SyncState<false>(&dummy);
return dummy.GetLength();
}
EXPORT int bizswan_binstatesave(System *s, char *data, int length)
{
NewStateExternalBuffer saver(data, length);
s->SyncState<false>(&saver);
return !saver.Overflow() && saver.GetLength() == length;
}
EXPORT int bizswan_binstateload(System *s, const char *data, int length)
{
NewStateExternalBuffer loader(const_cast<char *>(data), length);
s->SyncState<true>(&loader);
return !loader.Overflow() && loader.GetLength() == length;
}
EXPORT void bizswan_txtstatesave(System *s, FPtrs *ff)
{
NewStateExternalFunctions saver(ff);
s->SyncState<false>(&saver);
}
EXPORT void bizswan_txtstateload(System *s, FPtrs *ff)
{
NewStateExternalFunctions loader(ff);
s->SyncState<true>(&loader);
}
}

View File

@ -7,8 +7,11 @@ class System;
struct SyncSettings;
struct Settings;
}
#include "wswan.h"
#include "newstate.h"
#include "gfx.h"
#include "memory.h"
#include "eeprom.h"
@ -18,7 +21,7 @@ struct Settings;
#include "interrupt.h"
#include <cstddef>
namespace MDFN_IEN_WSWAN
{
class System
@ -52,6 +55,8 @@ public:
Interrupt interrupt;
bool rotate; // rotate screen and controls left 90
template<bool isReader>void SyncState(NewState *ns);
};
struct SyncSettings

View File

@ -1027,4 +1027,25 @@ namespace MDFN_IEN_WSWAN
}
SYNCFUNC(V30MZ)
{
NSS(old_CS);
NSS(old_IP);
NSS(timestamp);
NSS(ICount);
NSS(I);
NSS(InHLT);
NSS(prefix_base);
NSS(seg_prefix);
NSS(parity_table);
NSS(EA);
NSS(EO);
NSS(E16);
NSS(Mod_RM);
}
}

View File

@ -141,6 +141,7 @@ private:
public:
System *sys;
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -3,8 +3,6 @@
#include <mednafen/types.h>
#include "interrupt.h"
namespace MDFN_IEN_WSWAN
{