diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs index f796d5272f..ca901f3b89 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs @@ -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 { diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs index 8ea08b84d5..d4efcb9f8f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs @@ -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(); + 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)ser.Deserialize(reader, typeof(TextState)); + 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 diff --git a/lynx/bizlynx/bizlynx.vcxproj b/lynx/bizlynx/bizlynx.vcxproj index d28b372eed..9953a1480d 100644 --- a/lynx/bizlynx/bizlynx.vcxproj +++ b/lynx/bizlynx/bizlynx.vcxproj @@ -73,6 +73,7 @@ + @@ -90,6 +91,7 @@ + diff --git a/lynx/bizlynx/bizlynx.vcxproj.filters b/lynx/bizlynx/bizlynx.vcxproj.filters index 5ce0f99bbb..0e61f577b7 100644 --- a/lynx/bizlynx/bizlynx.vcxproj.filters +++ b/lynx/bizlynx/bizlynx.vcxproj.filters @@ -54,6 +54,9 @@ Source Files + + Source Files + @@ -104,5 +107,8 @@ Header Files\sound + + Header Files + \ No newline at end of file diff --git a/lynx/c65c02.cpp b/lynx/c65c02.cpp index f63e088e26..761085ed5a 100644 --- a/lynx/c65c02.cpp +++ b/lynx/c65c02.cpp @@ -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) { diff --git a/lynx/c65c02.h b/lynx/c65c02.h index 6eed1dff44..1c19bf3370 100644 --- a/lynx/c65c02.h +++ b/lynx/c65c02.h @@ -161,6 +161,8 @@ public: inline int GetPC() { return mPC; } + templatevoid SyncState(NewState *ns); + private: CSystem &mSystem; diff --git a/lynx/cart.cpp b/lynx/cart.cpp index 430ec5db90..a4840465ef 100644 --- a/lynx/cart.cpp +++ b/lynx/cart.cpp @@ -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); +} diff --git a/lynx/cart.h b/lynx/cart.h index 558be11c6e..278799fea2 100644 --- a/lynx/cart.h +++ b/lynx/cart.h @@ -109,6 +109,8 @@ public: bool GetSaveRamPtr(int &size, uint8 *&data); + templatevoid SyncState(NewState *ns); + private: EMMODE mBank; uint32 mMaskBank0; diff --git a/lynx/cinterface.cpp b/lynx/cinterface.cpp index 9edf3d7699..cf589a73aa 100644 --- a/lynx/cinterface.cpp +++ b/lynx/cinterface.cpp @@ -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(&dummy); + return dummy.GetLength(); +} + +EXPORT int BinStateSave(CSystem *s, char *data, int length) +{ + NewStateExternalBuffer saver(data, length); + s->SyncState(&saver); + return !saver.Overflow() && saver.GetLength() == length; +} + +EXPORT int BinStateLoad(CSystem *s, const char *data, int length) +{ + NewStateExternalBuffer loader(const_cast(data), length); + s->SyncState(&loader); + return !loader.Overflow() && loader.GetLength() == length; +} + +EXPORT void TxtStateSave(CSystem *s, FPtrs *ff) +{ + NewStateExternalFunctions saver(ff); + s->SyncState(&saver); +} + +EXPORT void TxtStateLoad(CSystem *s, FPtrs *ff) +{ + NewStateExternalFunctions loader(ff); + s->SyncState(&loader); +} + diff --git a/lynx/machine.h b/lynx/machine.h index fd5c811629..3b464fb87a 100644 --- a/lynx/machine.h +++ b/lynx/machine.h @@ -59,6 +59,7 @@ // #include "lynxbase.h" +#include "newstate.h" #endif diff --git a/lynx/memmap.cpp b/lynx/memmap.cpp index 738e3e3eec..39d681614e 100644 --- a/lynx/memmap.cpp +++ b/lynx/memmap.cpp @@ -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); + } +} diff --git a/lynx/memmap.h b/lynx/memmap.h index 9ae36ed3a1..7436757b32 100644 --- a/lynx/memmap.h +++ b/lynx/memmap.h @@ -80,6 +80,8 @@ class CMemMap : public CLynxBase uint32 WriteCycle(void) {return 5;}; uint32 ObjectSize(void) {return MEMMAP_SIZE;}; + templatevoid SyncState(NewState *ns); + // Data members private: diff --git a/lynx/mikie.cpp b/lynx/mikie.cpp index 148b6c0a2c..676940efc5 100644 --- a/lynx/mikie.cpp +++ b/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); +} diff --git a/lynx/mikie.h b/lynx/mikie.h index ba3cfd0038..fa991e4e74 100644 --- a/lynx/mikie.h +++ b/lynx/mikie.h @@ -221,6 +221,8 @@ public: uint32 mpDisplayCurrentLine; uint32 framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT]; + templatevoid SyncState(NewState *ns); + private: CSystem &mSystem; diff --git a/lynx/newstate.cpp b/lynx/newstate.cpp new file mode 100644 index 0000000000..efc0d554d4 --- /dev/null +++ b/lynx/newstate.cpp @@ -0,0 +1,64 @@ +#include "newstate.h" +#include +#include + +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(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); +} diff --git a/lynx/newstate.h b/lynx/newstate.h new file mode 100644 index 0000000000..0c9230a373 --- /dev/null +++ b/lynx/newstate.h @@ -0,0 +1,98 @@ +#ifndef NEWSTATE_H +#define NEWSTATE_H + +#include +#include + +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(NewState *ns);\ + template void x::SyncState(NewState *ns);\ + templatevoid 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(ns); ns->ExitSection(#x); } while (0) + +#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState(ns); ns->ExitSection(#x); } while (0) + +#endif diff --git a/lynx/ram.cpp b/lynx/ram.cpp index 1ba8c77ff1..e782c0e16f 100644 --- a/lynx/ram.cpp +++ b/lynx/ram.cpp @@ -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); +} diff --git a/lynx/ram.h b/lynx/ram.h index 007c7ef8ea..0ce6b04d8f 100644 --- a/lynx/ram.h +++ b/lynx/ram.h @@ -79,6 +79,8 @@ public: uint32 ObjectSize(void) {return RAM_SIZE;}; uint8* GetRamPointer(void) { return mRamData; }; + templatevoid SyncState(NewState *ns); + // Data members private: diff --git a/lynx/rom.cpp b/lynx/rom.cpp index 67e50a4ff6..56d93b499e 100644 --- a/lynx/rom.cpp +++ b/lynx/rom.cpp @@ -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); +} diff --git a/lynx/rom.h b/lynx/rom.h index 5c4109c760..6f27be7529 100644 --- a/lynx/rom.h +++ b/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;} + + templatevoid SyncState(NewState *ns); // Data members public: - bool mWriteEnable; + //bool mWriteEnable; // always false private: uint8 mRomData[ROM_SIZE]; }; diff --git a/lynx/susie.cpp b/lynx/susie.cpp index 22ba6872da..2a03e99299 100644 --- a/lynx/susie.cpp +++ b/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); +} diff --git a/lynx/susie.h b/lynx/susie.h index 470b56e904..e8e9de327c 100644 --- a/lynx/susie.h +++ b/lynx/susie.h @@ -329,6 +329,8 @@ class CSusie : public CLynxBase uint32 PaintSprites(void); bool lagged; // set to false whenever joystick/switches are read + templatevoid SyncState(NewState *ns); + private: void DoMathDivide(void); void DoMathMultiply(void); diff --git a/lynx/system.cpp b/lynx/system.cpp index 9114fd29ec..2635c957fe 100644 --- a/lynx/system.cpp +++ b/lynx/system.cpp @@ -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[] = diff --git a/lynx/system.h b/lynx/system.h index bcaf6b8f36..9502baa5ad 100644 --- a/lynx/system.h +++ b/lynx/system.h @@ -216,6 +216,8 @@ public: // frame overflow detection int frameoverflow; + + templatevoid SyncState(NewState *ns); }; #endif diff --git a/output/dll/bizlynx.dll b/output/dll/bizlynx.dll index d60ab6abce..08214e2095 100644 Binary files a/output/dll/bizlynx.dll and b/output/dll/bizlynx.dll differ