lynx: savestates. should work pretty well, but format is subject to change

This commit is contained in:
goyuken 2014-09-29 20:13:26 +00:00
parent 6e1932c8bd
commit ee1f84bb4a
25 changed files with 697 additions and 9 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Common;
using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Cores.Atari.Lynx
@ -27,6 +28,18 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
[DllImport(dllname, CallingConvention = cc)]
public static extern bool GetSaveRamPtr(IntPtr s, out int size, out IntPtr data);
[DllImport(dllname, CallingConvention = cc)]
public static extern int BinStateSize(IntPtr s);
[DllImport(dllname, CallingConvention = cc)]
public static extern bool BinStateSave(IntPtr s, byte[] data, int length);
[DllImport(dllname, CallingConvention = cc)]
public static extern bool BinStateLoad(IntPtr s, byte[] data, int length);
[DllImport(dllname, CallingConvention = cc)]
public static extern void TxtStateSave(IntPtr s, [In]ref TextStateFPtrs ff);
[DllImport(dllname, CallingConvention = cc)]
public static extern void TxtStateLoad(IntPtr s, [In]ref TextStateFPtrs ff);
[Flags]
public enum Buttons : ushort
{

View File

@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using Newtonsoft.Json;
namespace BizHawk.Emulation.Cores.Atari.Lynx
{
@ -96,6 +97,9 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
{
CoreComm.VsyncNum = 16000000; // 16.00 mhz refclock
CoreComm.VsyncDen = 16 * 105 * 159;
savebuff = new byte[LibLynx.BinStateSize(Core)];
savebuff2 = new byte[savebuff.Length + 13];
}
catch
{
@ -189,25 +193,84 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
#region savestates
JsonSerializer ser = new JsonSerializer() { Formatting = Formatting.Indented };
byte[] savebuff;
byte[] savebuff2;
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.GetFunctionPointersSave();
LibLynx.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);
Console.WriteLine(BizHawk.Common.BufferExtensions.BufferExtensions.HashSHA1(SaveStateBinary()));
}
public void LoadStateText(TextReader reader)
{
var s = (TextState<TextStateData>)ser.Deserialize(reader, typeof(TextState<TextStateData>));
s.Prepare();
var ff = s.GetFunctionPointersLoad();
LibLynx.TxtStateLoad(Core, ref ff);
IsLagFrame = s.ExtraData.IsLagFrame;
LagCount = s.ExtraData.LagCount;
Frame = s.ExtraData.Frame;
}
public void SaveStateBinary(BinaryWriter writer)
{
if (!LibLynx.BinStateSave(Core, savebuff, savebuff.Length))
throw new InvalidOperationException("Core's 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 (!LibLynx.BinStateLoad(Core, savebuff, savebuff.Length))
throw new InvalidOperationException("Core's 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();
if (ms.Position != savebuff2.Length)
throw new InvalidOperationException();
ms.Close();
return savebuff2;
}
public bool BinarySaveStatesPreferred

View File

@ -73,6 +73,7 @@
<ClCompile Include="..\cinterface.cpp" />
<ClCompile Include="..\memmap.cpp" />
<ClCompile Include="..\mikie.cpp" />
<ClCompile Include="..\newstate.cpp" />
<ClCompile Include="..\ram.cpp" />
<ClCompile Include="..\rom.cpp" />
<ClCompile Include="..\sound\Blip_Buffer.cpp" />
@ -90,6 +91,7 @@
<ClInclude Include="..\mednafen.h" />
<ClInclude Include="..\memmap.h" />
<ClInclude Include="..\mikie.h" />
<ClInclude Include="..\newstate.h" />
<ClInclude Include="..\ram.h" />
<ClInclude Include="..\rom.h" />
<ClInclude Include="..\sound\Blip_Buffer.h" />

View File

@ -54,6 +54,9 @@
<ClCompile Include="..\cinterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\newstate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\c65c02.h">
@ -104,5 +107,8 @@
<ClInclude Include="..\sound\Stereo_Buffer.h">
<Filter>Header Files\sound</Filter>
</ClInclude>
<ClInclude Include="..\newstate.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -57,6 +57,31 @@ void C65C02::GetRegs(C6502_REGS &regs)
regs.IRQ=mSystem.gSystemIRQ;
}
SYNCFUNC(C65C02)
{
NSS(mA);
NSS(mX);
NSS(mY);
NSS(mSP);
NSS(mOpcode);
NSS(mOperand);
NSS(mPC);
NSS(mN);
NSS(mV);
NSS(mB);
NSS(mD);
NSS(mI);
NSS(mZ);
NSS(mC);
NSS(mIRQActive);
// don't need to save these:
// mRamPointer
// mBCDTable
}
void C65C02::Update(void)
{

View File

@ -161,6 +161,8 @@ public:
inline int GetPC() { return mPC; }
template<bool isReader>void SyncState(NewState *ns);
private:
CSystem &mSystem;

View File

@ -330,3 +330,36 @@ bool CCart::GetSaveRamPtr(int &size, uint8 *&data)
return false;
}
}
SYNCFUNC(CCart)
{
NSS(mWriteEnableBank0);
NSS(mWriteEnableBank1);
NSS(mCartRAM);
EBS(mBank, 0);
EVS(mBank, bank0, 0);
EVS(mBank, bank1, 1);
EVS(mBank, ram, 2);
EVS(mBank, cpu, 3);
EES(mBank, bank0);
NSS(mMaskBank0);
NSS(mMaskBank1);
if (false)
PSS(mCartBank0, mMaskBank0 + 1);
if (mCartRAM)
PSS(mCartBank1, mMaskBank1 + 1);
NSS(mCounter);
NSS(mShifter);
NSS(mAddrData);
NSS(mStrobe);
NSS(mShiftCount0);
NSS(mCountMask0);
NSS(mShiftCount1);
NSS(mCountMask1);
NSS(last_strobe);
}

View File

@ -109,6 +109,8 @@ public:
bool GetSaveRamPtr(int &size, uint8 *&data);
template<bool isReader>void SyncState(NewState *ns);
private:
EMMODE mBank;
uint32 mMaskBank0;

View File

@ -41,3 +41,38 @@ EXPORT int GetSaveRamPtr(CSystem *s, int *size, uint8 **data)
{
return s->GetSaveRamPtr(*size, *data);
}
EXPORT int BinStateSize(CSystem *s)
{
NewStateDummy dummy;
s->SyncState<false>(&dummy);
return dummy.GetLength();
}
EXPORT int BinStateSave(CSystem *s, char *data, int length)
{
NewStateExternalBuffer saver(data, length);
s->SyncState<false>(&saver);
return !saver.Overflow() && saver.GetLength() == length;
}
EXPORT int BinStateLoad(CSystem *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 TxtStateSave(CSystem *s, FPtrs *ff)
{
NewStateExternalFunctions saver(ff);
s->SyncState<false>(&saver);
}
EXPORT void TxtStateLoad(CSystem *s, FPtrs *ff)
{
NewStateExternalFunctions loader(ff);
s->SyncState<true>(&loader);
}

View File

@ -59,6 +59,7 @@
//
#include "lynxbase.h"
#include "newstate.h"
#endif

View File

@ -186,4 +186,18 @@ INLINE uint8 CMemMap::Peek(uint32 addr)
return retval;
}
//END OF FILE
SYNCFUNC(CMemMap)
{
NSS(mMikieEnabled);
NSS(mSusieEnabled);
NSS(mRomEnabled);
NSS(mVectorsEnabled);
if (isReader)
{
// force regenerate memory handlers
uint8 current = Peek(0);
Poke(0, ~current);
Poke(0, current);
}
}

View File

@ -80,6 +80,8 @@ class CMemMap : public CLynxBase
uint32 WriteCycle(void) {return 5;};
uint32 ObjectSize(void) {return MEMMAP_SIZE;};
template<bool isReader>void SyncState(NewState *ns);
// Data members
private:

View File

@ -2564,3 +2564,185 @@ void CMikie::Update()
// cannot be updated until this point otherwise it screws up the counters.
mSystem.gSystemCycleCount+=mikie_work_done;
}
SYNCFUNC(CMikie)
{
NSS(startTS);
// SSS(miksynth);
// SSS(mikbuf);
// mpDisplayCurrent;
NSS(mpDisplayCurrentLine);
NSS(framebuffer);
NSS(last_lsample);
NSS(last_rsample);
NSS(mDisplayAddress);
NSS(mAudioInputComparator);
NSS(mTimerStatusFlags);
NSS(mTimerInterruptMask);
NSS(mPalette);
NSS(mColourMap);
NSS(mIODAT);
NSS(mIODIR);
NSS(mIODAT_REST_SIGNAL);
NSS(mDISPCTL_DMAEnable);
NSS(mDISPCTL_Flip);
NSS(mDISPCTL_FourColour);
NSS(mDISPCTL_Colour);
NSS(mTIM_0_BKUP);
NSS(mTIM_0_ENABLE_RELOAD);
NSS(mTIM_0_ENABLE_COUNT);
NSS(mTIM_0_LINKING);
NSS(mTIM_0_CURRENT);
NSS(mTIM_0_TIMER_DONE);
NSS(mTIM_0_LAST_CLOCK);
NSS(mTIM_0_BORROW_IN);
NSS(mTIM_0_BORROW_OUT);
NSS(mTIM_0_LAST_LINK_CARRY);
NSS(mTIM_0_LAST_COUNT);
NSS(mTIM_1_BKUP);
NSS(mTIM_1_ENABLE_RELOAD);
NSS(mTIM_1_ENABLE_COUNT);
NSS(mTIM_1_LINKING);
NSS(mTIM_1_CURRENT);
NSS(mTIM_1_TIMER_DONE);
NSS(mTIM_1_LAST_CLOCK);
NSS(mTIM_1_BORROW_IN);
NSS(mTIM_1_BORROW_OUT);
NSS(mTIM_1_LAST_LINK_CARRY);
NSS(mTIM_1_LAST_COUNT);
NSS(mTIM_2_BKUP);
NSS(mTIM_2_ENABLE_RELOAD);
NSS(mTIM_2_ENABLE_COUNT);
NSS(mTIM_2_LINKING);
NSS(mTIM_2_CURRENT);
NSS(mTIM_2_TIMER_DONE);
NSS(mTIM_2_LAST_CLOCK);
NSS(mTIM_2_BORROW_IN);
NSS(mTIM_2_BORROW_OUT);
NSS(mTIM_2_LAST_LINK_CARRY);
NSS(mTIM_2_LAST_COUNT);
NSS(mTIM_3_BKUP);
NSS(mTIM_3_ENABLE_RELOAD);
NSS(mTIM_3_ENABLE_COUNT);
NSS(mTIM_3_LINKING);
NSS(mTIM_3_CURRENT);
NSS(mTIM_3_TIMER_DONE);
NSS(mTIM_3_LAST_CLOCK);
NSS(mTIM_3_BORROW_IN);
NSS(mTIM_3_BORROW_OUT);
NSS(mTIM_3_LAST_LINK_CARRY);
NSS(mTIM_3_LAST_COUNT);
NSS(mTIM_4_BKUP);
NSS(mTIM_4_ENABLE_RELOAD);
NSS(mTIM_4_ENABLE_COUNT);
NSS(mTIM_4_LINKING);
NSS(mTIM_4_CURRENT);
NSS(mTIM_4_TIMER_DONE);
NSS(mTIM_4_LAST_CLOCK);
NSS(mTIM_4_BORROW_IN);
NSS(mTIM_4_BORROW_OUT);
NSS(mTIM_4_LAST_LINK_CARRY);
NSS(mTIM_4_LAST_COUNT);
NSS(mTIM_5_BKUP);
NSS(mTIM_5_ENABLE_RELOAD);
NSS(mTIM_5_ENABLE_COUNT);
NSS(mTIM_5_LINKING);
NSS(mTIM_5_CURRENT);
NSS(mTIM_5_TIMER_DONE);
NSS(mTIM_5_LAST_CLOCK);
NSS(mTIM_5_BORROW_IN);
NSS(mTIM_5_BORROW_OUT);
NSS(mTIM_5_LAST_LINK_CARRY);
NSS(mTIM_5_LAST_COUNT);
NSS(mTIM_6_BKUP);
NSS(mTIM_6_ENABLE_RELOAD);
NSS(mTIM_6_ENABLE_COUNT);
NSS(mTIM_6_LINKING);
NSS(mTIM_6_CURRENT);
NSS(mTIM_6_TIMER_DONE);
NSS(mTIM_6_LAST_CLOCK);
NSS(mTIM_6_BORROW_IN);
NSS(mTIM_6_BORROW_OUT);
NSS(mTIM_6_LAST_LINK_CARRY);
NSS(mTIM_6_LAST_COUNT);
NSS(mTIM_7_BKUP);
NSS(mTIM_7_ENABLE_RELOAD);
NSS(mTIM_7_ENABLE_COUNT);
NSS(mTIM_7_LINKING);
NSS(mTIM_7_CURRENT);
NSS(mTIM_7_TIMER_DONE);
NSS(mTIM_7_LAST_CLOCK);
NSS(mTIM_7_BORROW_IN);
NSS(mTIM_7_BORROW_OUT);
NSS(mTIM_7_LAST_LINK_CARRY);
NSS(mTIM_7_LAST_COUNT);
NSS(mAUDIO_BKUP);
NSS(mAUDIO_ENABLE_RELOAD);
NSS(mAUDIO_ENABLE_COUNT);
NSS(mAUDIO_LINKING);
NSS(mAUDIO_CURRENT);
NSS(mAUDIO_TIMER_DONE);
NSS(mAUDIO_LAST_CLOCK);
NSS(mAUDIO_BORROW_IN);
NSS(mAUDIO_BORROW_OUT);
NSS(mAUDIO_LAST_LINK_CARRY);
NSS(mAUDIO_LAST_COUNT);
NSS(mAUDIO_VOLUME);
NSS(mAUDIO_INTEGRATE_ENABLE);
NSS(mAUDIO_WAVESHAPER);
NSS(mAUDIO_OUTPUT);
NSS(mAUDIO_ATTEN);
NSS(mSTEREO);
NSS(mPAN);
NSS(mUART_RX_IRQ_ENABLE);
NSS(mUART_TX_IRQ_ENABLE);
NSS(mUART_RX_COUNTDOWN);
NSS(mUART_TX_COUNTDOWN);
NSS(mUART_SENDBREAK);
NSS(mUART_TX_DATA);
NSS(mUART_RX_DATA);
NSS(mUART_RX_READY);
NSS(mUART_PARITY_ENABLE);
NSS(mUART_PARITY_EVEN);
NSS(mUART_CABLE_PRESENT);
// mpUART_TX_CALLBACK;
// mUART_TX_CALLBACK_OBJECT;
NSS(mUART_Rx_input_queue);
NSS(mUART_Rx_input_ptr);
NSS(mUART_Rx_output_ptr);
NSS(mUART_Rx_waiting);
NSS(mUART_Rx_framing_error);
NSS(mUART_Rx_overun_error);
// mpRamPointer;
NSS(mLynxLine);
NSS(mLynxLineDMACounter);
NSS(mLynxAddr);
}

View File

@ -221,6 +221,8 @@ public:
uint32 mpDisplayCurrentLine;
uint32 framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
template<bool isReader>void SyncState(NewState *ns);
private:
CSystem &mSystem;

64
lynx/newstate.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "newstate.h"
#include <cstring>
#include <algorithm>
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);
}

98
lynx/newstate.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef NEWSTATE_H
#define NEWSTATE_H
#include <cstring>
#include <cstddef>
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

@ -62,3 +62,8 @@ void CRam::Reset(void)
//MDFNMP_AddRAM(65536, 0x0000, mRamData);
std::memset(mRamData, DEFAULT_RAM_CONTENTS, RAM_SIZE);
}
SYNCFUNC(CRam)
{
NSS(mRamData);
}

View File

@ -79,6 +79,8 @@ public:
uint32 ObjectSize(void) {return RAM_SIZE;};
uint8* GetRamPointer(void) { return mRamData; };
template<bool isReader>void SyncState(NewState *ns);
// Data members
private:

View File

@ -47,7 +47,7 @@
CRom::CRom(const uint8 *romfile, uint32 length)
{
mWriteEnable=FALSE;
//mWriteEnable = false;
Reset();
std::memset(mRomData, DEFAULT_ROM_CONTENTS, ROM_SIZE);
@ -58,3 +58,9 @@ CRom::CRom(const uint8 *romfile, uint32 length)
void CRom::Reset(void)
{
}
SYNCFUNC(CRom)
{
//NSS(mWriteEnable);
//NSS(mRomData);
}

View File

@ -61,16 +61,18 @@ public:
public:
void Reset(void) MDFN_COLD;
void Poke(uint32 addr,uint8 data) { if(mWriteEnable) mRomData[addr&ROM_ADDR_MASK]=data;};
uint8 Peek(uint32 addr) { return(mRomData[addr&ROM_ADDR_MASK]);};
uint32 ReadCycle(void) {return 5;};
uint32 WriteCycle(void) {return 5;};
uint32 ObjectSize(void) {return ROM_SIZE;};
void Poke(uint32 addr,uint8 data) { /*if(mWriteEnable) mRomData[addr&ROM_ADDR_MASK]=data;*/ }
uint8 Peek(uint32 addr) { return(mRomData[addr&ROM_ADDR_MASK]); }
uint32 ReadCycle(void) {return 5;}
uint32 WriteCycle(void) {return 5;}
uint32 ObjectSize(void) {return ROM_SIZE;}
template<bool isReader>void SyncState(NewState *ns);
// Data members
public:
bool mWriteEnable;
//bool mWriteEnable; // always false
private:
uint8 mRomData[ROM_SIZE];
};

View File

@ -2129,3 +2129,106 @@ uint8 CSusie::Peek(uint32 addr)
return 0xff;
}
SYNCFUNC(CSusie)
{
NSS(lagged);
NSS(cycles_used);
NSS(mTMPADR);
NSS(mTILTACUM);
NSS(mHOFF);
NSS(mVOFF);
NSS(mVIDBAS);
NSS(mCOLLBAS);
NSS(mVIDADR);
NSS(mCOLLADR);
NSS(mSCBNEXT);
NSS(mSPRDLINE);
NSS(mHPOSSTRT);
NSS(mVPOSSTRT);
NSS(mSPRHSIZ);
NSS(mSPRVSIZ);
NSS(mSTRETCH);
NSS(mTILT);
NSS(mSPRDOFF);
NSS(mSPRVPOS);
NSS(mCOLLOFF);
NSS(mVSIZACUM);
NSS(mHSIZACUM);
NSS(mHSIZOFF);
NSS(mVSIZOFF);
NSS(mSCBADR);
NSS(mPROCADR);
NSS(mMATHABCD);
NSS(mMATHEFGH);
NSS(mMATHJKLM);
NSS(mMATHNP);
NSS(mMATHAB_sign);
NSS(mMATHCD_sign);
NSS(mMATHEFGH_sign);
NSS(mSPRCTL0_Type);
NSS(mSPRCTL0_Vflip);
NSS(mSPRCTL0_Hflip);
NSS(mSPRCTL0_PixelBits);
NSS(mSPRCTL1_StartLeft);
NSS(mSPRCTL1_StartUp);
NSS(mSPRCTL1_SkipSprite);
NSS(mSPRCTL1_ReloadPalette);
NSS(mSPRCTL1_ReloadDepth);
NSS(mSPRCTL1_Sizing);
NSS(mSPRCTL1_Literal);
NSS(mSPRCOLL_Number);
NSS(mSPRCOLL_Collide);
NSS(mSPRSYS_StopOnCurrent);
NSS(mSPRSYS_LeftHand);
NSS(mSPRSYS_VStretch);
NSS(mSPRSYS_NoCollide);
NSS(mSPRSYS_Accumulate);
NSS(mSPRSYS_SignedMath);
NSS(mSPRSYS_Status);
NSS(mSPRSYS_UnsafeAccess);
NSS(mSPRSYS_LastCarry);
NSS(mSPRSYS_Mathbit);
NSS(mSPRSYS_MathInProgress);
NSS(mSUZYBUSEN);
NSS(mSPRINIT);
NSS(mSPRGO);
NSS(mEVERON);
NSS(mPenIndex);
NSS(mLineType);
NSS(mLineShiftRegCount);
NSS(mLineShiftReg);
NSS(mLineRepeatCount);
NSS(mLinePixel);
NSS(mLinePacketBitsLeft);
NSS(mCollision);
// mRamPointer;
NSS(mLineBaseAddress);
NSS(mLineCollisionAddress);
NSS(hquadoff);
NSS(vquadoff);
NSS(mJOYSTICK);
NSS(mSWITCHES);
}

View File

@ -329,6 +329,8 @@ class CSusie : public CLynxBase
uint32 PaintSprites(void);
bool lagged; // set to false whenever joystick/switches are read
template<bool isReader>void SyncState(NewState *ns);
private:
void DoMathDivide(void);
void DoMathMultiply(void);

View File

@ -188,6 +188,28 @@ bool CSystem::Advance(int buttons, uint32 *vbuff, int16 *sbuff, int &sbuffsize)
return mSusie->lagged;
}
SYNCFUNC(CSystem)
{
// mMemMap regenerates the mMemoryHandlers directly on load
TSS(mCart);
TSS(mRom);
TSS(mMemMap);
TSS(mRam);
TSS(mCpu);
TSS(mMikie);
TSS(mSusie);
NSS(gSuzieDoneTime);
NSS(gSystemCycleCount);
NSS(gNextTimerEvent);
NSS(gSystemIRQ);
NSS(gSystemNMI);
NSS(gSystemCPUSleep);
NSS(gSystemHalt);
NSS(frameoverflow);
}
/*
static MDFNSetting LynxSettings[] =

View File

@ -216,6 +216,8 @@ public:
// frame overflow detection
int frameoverflow;
template<bool isReader>void SyncState(NewState *ns);
};
#endif

Binary file not shown.