lynx: savestates. should work pretty well, but format is subject to change
This commit is contained in:
parent
6e1932c8bd
commit
ee1f84bb4a
BizHawk.Emulation.Cores/Consoles/Atari/lynx
lynx
bizlynx
c65c02.cppc65c02.hcart.cppcart.hcinterface.cppmachine.hmemmap.cppmemmap.hmikie.cppmikie.hnewstate.cppnewstate.hram.cppram.hrom.cpprom.hsusie.cppsusie.hsystem.cppsystem.houtput/dll
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -57,6 +57,31 @@ void C65C02::GetRegs(C6502_REGS ®s)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -161,6 +161,8 @@ public:
|
|||
|
||||
inline int GetPC() { return mPC; }
|
||||
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
|
||||
private:
|
||||
CSystem &mSystem;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,8 @@ public:
|
|||
|
||||
bool GetSaveRamPtr(int &size, uint8 *&data);
|
||||
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
|
||||
private:
|
||||
EMMODE mBank;
|
||||
uint32 mMaskBank0;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
//
|
||||
|
||||
#include "lynxbase.h"
|
||||
#include "newstate.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
182
lynx/mikie.cpp
182
lynx/mikie.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -221,6 +221,8 @@ public:
|
|||
uint32 mpDisplayCurrentLine;
|
||||
uint32 framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
|
||||
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
|
||||
private:
|
||||
CSystem &mSystem;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
14
lynx/rom.h
14
lynx/rom.h
|
@ -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];
|
||||
};
|
||||
|
|
103
lynx/susie.cpp
103
lynx/susie.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[] =
|
||||
|
|
|
@ -216,6 +216,8 @@ public:
|
|||
|
||||
// frame overflow detection
|
||||
int frameoverflow;
|
||||
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue