diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index 043c38a8ab..1aaea2333d 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -130,8 +130,7 @@ public: void GetRegs(int *dest); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); private: struct Priv; diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index 56ddb5afab..8df32e33fb 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -178,7 +178,7 @@ GBEXPORT long gambatte_newstatelen(void *core) { GB *g = (GB *) core; NewStateDummy dummy; - g->SaveS(&dummy); + g->SyncState(&dummy); return dummy.GetLength(); } @@ -186,7 +186,7 @@ GBEXPORT int gambatte_newstatesave(void *core, char *data, long len) { GB *g = (GB *) core; NewStateExternalBuffer saver(data, len); - g->SaveS(&saver); + g->SyncState(&saver); return !saver.Overflow() && saver.GetLength() == len; } @@ -194,7 +194,7 @@ GBEXPORT int gambatte_newstateload(void *core, const char *data, long len) { GB *g = (GB *) core; NewStateExternalBuffer loader((char *)data, len); - g->LoadS(&loader); + g->SyncState(&loader); return !loader.Overflow() && loader.GetLength() == len; } @@ -205,7 +205,7 @@ GBEXPORT void gambatte_newstatesave_ex(void *core, { GB *g = (GB *) core; NewStateExternalFunctions saver(Save_, NULL, EnterSection_, ExitSection_); - g->SaveS(&saver); + g->SyncState(&saver); } GBEXPORT void gambatte_newstateload_ex(void *core, @@ -215,7 +215,7 @@ GBEXPORT void gambatte_newstateload_ex(void *core, { GB *g = (GB *) core; NewStateExternalFunctions loader(NULL, Load_, EnterSection_, ExitSection_); - g->LoadS(&loader); + g->SyncState(&loader); } static char horriblebuff[64]; diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp index 30e5190228..4a830ed411 100644 --- a/libgambatte/src/cpu.cpp +++ b/libgambatte/src/cpu.cpp @@ -2872,7 +2872,7 @@ void CPU::GetRegs(int *dest) dest[9] = L; } -void CPU::SaveS(NewState *ns) +SYNCFUNC(CPU) { SSS(memory); NSS(cycleCounter_); @@ -2892,25 +2892,4 @@ void CPU::SaveS(NewState *ns) NSS(skip); } -void CPU::LoadS(NewState *ns) -{ - SSL(memory); - NSL(cycleCounter_); - NSL(PC_); - NSL(SP); - NSL(HF1); - NSL(HF2); - NSL(ZF); - NSL(CF); - NSL(A_); - NSL(B); - NSL(C); - NSL(D); - NSL(E); - NSL(H); - NSL(L); - NSL(skip); -} - - } diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index 537b15a341..6b7fbd691d 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -120,8 +120,7 @@ public: void GetRegs(int *dest); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 88d91a30e1..46b3973c92 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -245,18 +245,11 @@ void GB::GetRegs(int *dest) { p_->cpu.GetRegs(dest); } -void GB::SaveS(NewState *ns) +SYNCFUNC(GB) { SSS(p_->cpu); NSS(p_->gbaCgbMode); NSS(p_->vbuff); } -void GB::LoadS(NewState *ns) -{ - SSL(p_->cpu); - NSL(p_->gbaCgbMode); - NSL(p_->vbuff); -} - } diff --git a/libgambatte/src/interrupter.cpp b/libgambatte/src/interrupter.cpp index 7b55d1ad22..9eac990516 100644 --- a/libgambatte/src/interrupter.cpp +++ b/libgambatte/src/interrupter.cpp @@ -39,6 +39,4 @@ unsigned long Interrupter::interrupt(const unsigned address, unsigned long cycle return cycleCounter; } - - } diff --git a/libgambatte/src/interruptrequester.cpp b/libgambatte/src/interruptrequester.cpp index eb6d7d0db9..32ab016da6 100644 --- a/libgambatte/src/interruptrequester.cpp +++ b/libgambatte/src/interruptrequester.cpp @@ -100,7 +100,7 @@ void InterruptRequester::setIfreg(const unsigned ifreg) { eventTimes.setValue(pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME)); } -void InterruptRequester::SaveS(NewState *ns) +SYNCFUNC(InterruptRequester) { SSS(eventTimes); NSS(minIntTime); @@ -108,14 +108,5 @@ void InterruptRequester::SaveS(NewState *ns) NSS(iereg_); NSS(intFlags.flags_); } - -void InterruptRequester::LoadS(NewState *ns) -{ - SSL(eventTimes); - NSL(minIntTime); - NSL(ifreg_); - NSL(iereg_); - NSL(intFlags.flags_); -} } diff --git a/libgambatte/src/interruptrequester.h b/libgambatte/src/interruptrequester.h index b8d0b2968c..54a0acd7e2 100644 --- a/libgambatte/src/interruptrequester.h +++ b/libgambatte/src/interruptrequester.h @@ -82,8 +82,7 @@ public: void setEventTime(const MemEventId id, unsigned long value) { eventTimes.setValue(id, value); } unsigned long eventTime(MemEventId id) const { return eventTimes.value(id); } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; inline void flagHdmaReq(InterruptRequester *const intreq) { intreq->setEventTime(0); } diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp index d9c9635ee3..9f649a0b84 100644 --- a/libgambatte/src/mem/cartridge.cpp +++ b/libgambatte/src/mem/cartridge.cpp @@ -35,12 +35,9 @@ public: virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const { return (addr< 0x4000) == (bank == 0); } - - virtual void SaveS(NewState *ns) + + virtual void SyncState(NewState *ns, bool isReader) { - } - virtual void LoadS(NewState *ns) - { } }; @@ -71,14 +68,10 @@ public: memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(enableRam); } - virtual void LoadS(NewState *ns) - { - NSL(enableRam); - } }; static inline unsigned rambanks(const MemPtrs &memptrs) { @@ -154,20 +147,13 @@ public: setRombank(); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); NSS(rambankMode); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(rambank); - NSL(enableRam); - NSL(rambankMode); - } }; class Mbc1Multi64 : public Mbc { @@ -237,18 +223,12 @@ public: return (addr < 0x4000) == ((bank & 0xF) == 0); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(enableRam); NSS(rombank0Mode); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(enableRam); - NSL(rombank0Mode); - } }; class Mbc2 : public DefaultMbc { @@ -289,16 +269,11 @@ public: memptrs.setRombank(rombank & (rombanks(memptrs) - 1)); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(enableRam); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(enableRam); - } }; class Mbc3 : public DefaultMbc { @@ -371,18 +346,12 @@ public: setRombank(); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(rambank); - NSL(enableRam); - } }; class HuC1 : public DefaultMbc { @@ -446,20 +415,14 @@ public: setRambank(); setRombank(); } - virtual void SaveS(NewState *ns) + + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); NSS(rambankMode); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(rambank); - NSL(enableRam); - NSL(rambankMode); - } }; class Mbc5 : public DefaultMbc { @@ -515,18 +478,12 @@ public: setRombank(); } - virtual void SaveS(NewState *ns) + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); } - virtual void LoadS(NewState *ns) - { - NSL(rombank); - NSL(rambank); - NSL(enableRam); - } }; static bool hasRtc(const unsigned headerByte0x147) { @@ -787,18 +744,11 @@ bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) { return false; } -void Cartridge::SaveS(NewState *ns) +SYNCFUNC(Cartridge) { SSS(memptrs); SSS(rtc); TSS(mbc); } - -void Cartridge::LoadS(NewState *ns) -{ - SSL(memptrs); - SSL(rtc); - TSL(mbc); -} } diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h index 2be9646e45..9de575f326 100644 --- a/libgambatte/src/mem/cartridge.h +++ b/libgambatte/src/mem/cartridge.h @@ -1,97 +1,100 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CARTRIDGE_H -#define CARTRIDGE_H - -#include "memptrs.h" -#include "rtc.h" -#include "savestate.h" -#include -#include -#include +/*************************************************************************** + * Copyright (C) 2007-2010 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CARTRIDGE_H +#define CARTRIDGE_H + +#include "memptrs.h" +#include "rtc.h" +#include "savestate.h" +#include +#include +#include #include "newstate.h" - -namespace gambatte { - -class Mbc { -public: - virtual ~Mbc() {} - virtual void romWrite(unsigned P, unsigned data) = 0; - virtual void saveState(SaveState::Mem &ss) const = 0; - virtual void loadState(const SaveState::Mem &ss) = 0; - virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0; - - virtual void SaveS(NewState *ns) = 0; - virtual void LoadS(NewState *ns) = 0; -}; - -class Cartridge { - MemPtrs memptrs; - Rtc rtc; - std::auto_ptr mbc; - -public: - void setStatePtrs(SaveState &); - void saveState(SaveState &) const; - void loadState(const SaveState &); - - bool loaded() const { return mbc.get(); } - - const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); } - unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); } - unsigned char * vramdata() const { return memptrs.vramdata(); } - unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); } - unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); } - const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); } - const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); } - unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); } - unsigned char * vrambankptr() const { return memptrs.vrambankptr(); } - OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); } - - void setVrambank(unsigned bank) { memptrs.setVrambank(bank); } - void setWrambank(unsigned bank) { memptrs.setWrambank(bank); } - void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); } - - void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); } - - bool isCgb() const { return gambatte::isCgb(memptrs); } - - void rtcWrite(unsigned data) { rtc.write(data); } - unsigned char rtcRead() const { return *rtc.getActive(); } - - void loadSavedata(const char *data); - int saveSavedataLength(); - void saveSavedata(char *dest); - - bool getMemoryArea(int which, unsigned char **data, int *length); - - int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat); - const char * romTitle() const { return reinterpret_cast(memptrs.romdata() + 0x134); } - - void setRTCCallback(std::uint32_t (*callback)()) { - rtc.setRTCCallback(callback); - } - - void SaveS(NewState *ns); - void LoadS(NewState *ns); -}; - -} - -#endif + +namespace gambatte { + +class Mbc { +public: + virtual ~Mbc() {} + virtual void romWrite(unsigned P, unsigned data) = 0; + virtual void saveState(SaveState::Mem &ss) const = 0; + virtual void loadState(const SaveState::Mem &ss) = 0; + virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0; + + templatevoid SyncState(NewState *ns) + { + // can't have virtual templates, so.. + SyncState(ns, isReader); + } + virtual void SyncState(NewState *ns, bool isReader) = 0; +}; + +class Cartridge { + MemPtrs memptrs; + Rtc rtc; + std::auto_ptr mbc; + +public: + void setStatePtrs(SaveState &); + void saveState(SaveState &) const; + void loadState(const SaveState &); + + bool loaded() const { return mbc.get(); } + + const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); } + unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); } + unsigned char * vramdata() const { return memptrs.vramdata(); } + unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); } + unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); } + const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); } + const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); } + unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); } + unsigned char * vrambankptr() const { return memptrs.vrambankptr(); } + OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); } + + void setVrambank(unsigned bank) { memptrs.setVrambank(bank); } + void setWrambank(unsigned bank) { memptrs.setWrambank(bank); } + void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); } + + void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); } + + bool isCgb() const { return gambatte::isCgb(memptrs); } + + void rtcWrite(unsigned data) { rtc.write(data); } + unsigned char rtcRead() const { return *rtc.getActive(); } + + void loadSavedata(const char *data); + int saveSavedataLength(); + void saveSavedata(char *dest); + + bool getMemoryArea(int which, unsigned char **data, int *length); + + int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat); + const char * romTitle() const { return reinterpret_cast(memptrs.romdata() + 0x134); } + + void setRTCCallback(std::uint32_t (*callback)()) { + rtc.setRTCCallback(callback); + } + + templatevoid SyncState(NewState *ns); +}; + +} + +#endif diff --git a/libgambatte/src/mem/memptrs.cpp b/libgambatte/src/mem/memptrs.cpp index b757456541..84c58e9de1 100644 --- a/libgambatte/src/mem/memptrs.cpp +++ b/libgambatte/src/mem/memptrs.cpp @@ -53,6 +53,10 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi setRambank(0, 0); setVrambank(0); setWrambank(1); + + // we save only the ram areas + memchunk_saveoffs = vramdata() - memchunk_; + memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs; } void MemPtrs::setRombank0(const unsigned bank) { @@ -142,8 +146,24 @@ void MemPtrs::disconnectOamDmaAreas() { #define MSS(a) RSS(a,memchunk_) #define MSL(a) RSL(a,memchunk_) -void MemPtrs::SaveS(NewState *ns) +SYNCFUNC(MemPtrs) { + int memchunk_len_old = memchunk_len; + int memchunk_saveoffs_old = memchunk_saveoffs; + int memchunk_savelen_old = memchunk_savelen; + + NSS(memchunk_len); + NSS(memchunk_saveoffs); + NSS(memchunk_savelen); + + if (isReader) + { + if (memchunk_len != memchunk_len_old || memchunk_saveoffs != memchunk_saveoffs_old || memchunk_savelen != memchunk_savelen_old) + __debugbreak(); + } + + PSS(memchunk_ + memchunk_saveoffs, memchunk_savelen); + MSS(rmem_[0x0]); MSS(wmem_[0x0]); MSS(rmem_[0x1]); @@ -188,67 +208,9 @@ void MemPtrs::SaveS(NewState *ns) MSS(vrambankptr_); MSS(rsrambankptr_); MSS(wsrambankptr_); - NSS(memchunk_len); - PSS(memchunk_, memchunk_len); MSS(rambankdata_); MSS(wramdataend_); NSS(oamDmaSrc_); } - -void MemPtrs::LoadS(NewState *ns) -{ - MSL(rmem_[0x0]); - MSL(wmem_[0x0]); - MSL(rmem_[0x1]); - MSL(wmem_[0x1]); - MSL(rmem_[0x2]); - MSL(wmem_[0x2]); - MSL(rmem_[0x3]); - MSL(wmem_[0x3]); - MSL(rmem_[0x4]); - MSL(wmem_[0x4]); - MSL(rmem_[0x5]); - MSL(wmem_[0x5]); - MSL(rmem_[0x6]); - MSL(wmem_[0x6]); - MSL(rmem_[0x7]); - MSL(wmem_[0x7]); - MSL(rmem_[0x8]); - MSL(wmem_[0x8]); - MSL(rmem_[0x9]); - MSL(wmem_[0x9]); - MSL(rmem_[0xa]); - MSL(wmem_[0xa]); - MSL(rmem_[0xb]); - MSL(wmem_[0xb]); - MSL(rmem_[0xc]); - MSL(wmem_[0xc]); - MSL(rmem_[0xd]); - MSL(wmem_[0xd]); - MSL(rmem_[0xe]); - MSL(wmem_[0xe]); - MSL(rmem_[0xf]); - MSL(wmem_[0xf]); - //for (int i = 0; i < 0x10; i++) - //{ - // MSL(rmem_[i]); - // MSL(wmem_[i]); - //} - MSL(romdata_[0]); - MSL(romdata_[1]); - MSL(wramdata_[0]); - MSL(wramdata_[1]); - MSL(vrambankptr_); - MSL(rsrambankptr_); - MSL(wsrambankptr_); - unsigned tmp = memchunk_len; - NSL(memchunk_len); - if (tmp != memchunk_len) // how graceful could we be here? not sure - __debugbreak(); - PSL(memchunk_, memchunk_len); - MSL(rambankdata_); - MSL(wramdataend_); - NSL(oamDmaSrc_); -} } diff --git a/libgambatte/src/mem/memptrs.h b/libgambatte/src/mem/memptrs.h index edf579959d..af21c02a15 100644 --- a/libgambatte/src/mem/memptrs.h +++ b/libgambatte/src/mem/memptrs.h @@ -41,7 +41,9 @@ class MemPtrs { OamDmaSrc oamDmaSrc_; - unsigned memchunk_len; + int memchunk_len; + int memchunk_saveoffs; + int memchunk_savelen; MemPtrs(const MemPtrs &); MemPtrs & operator=(const MemPtrs &); @@ -79,8 +81,7 @@ public: void setWrambank(unsigned bank); void setOamDmaSrc(OamDmaSrc oamDmaSrc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; inline bool isCgb(const MemPtrs &memptrs) { diff --git a/libgambatte/src/mem/rtc.cpp b/libgambatte/src/mem/rtc.cpp index df42338ddb..9e3f1c55dc 100644 --- a/libgambatte/src/mem/rtc.cpp +++ b/libgambatte/src/mem/rtc.cpp @@ -155,7 +155,7 @@ void Rtc::setS(const unsigned new_seconds) { baseTime -= new_seconds; } -void Rtc::SaveS(NewState *ns) +SYNCFUNC(Rtc) { EBS(activeData, 0); EVS(activeData, &dataS, 1); @@ -185,34 +185,4 @@ void Rtc::SaveS(NewState *ns) NSS(lastLatchData); } -void Rtc::LoadS(NewState *ns) -{ - EBL(activeData, 0); - EVL(activeData, &dataS, 1); - EVL(activeData, &dataM, 2); - EVL(activeData, &dataH, 3); - EVL(activeData, &dataDl, 4); - EVL(activeData, &dataDh, 5); - EEL(activeData, NULL); - - EBL(activeSet, 0); - EVL(activeSet, &Rtc::setS, 1); - EVL(activeSet, &Rtc::setM, 2); - EVL(activeSet, &Rtc::setH, 3); - EVL(activeSet, &Rtc::setDl, 4); - EVL(activeSet, &Rtc::setDh, 5); - EEL(activeSet, NULL); - - NSL(baseTime); - NSL(haltTime); - NSL(index); - NSL(dataDh); - NSL(dataDl); - NSL(dataH); - NSL(dataM); - NSL(dataS); - NSL(enabled); - NSL(lastLatchData); -} - } diff --git a/libgambatte/src/mem/rtc.h b/libgambatte/src/mem/rtc.h index 4eb93a6251..b71b4f88b4 100644 --- a/libgambatte/src/mem/rtc.h +++ b/libgambatte/src/mem/rtc.h @@ -91,8 +91,7 @@ public: timeCB = callback; } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp index 4aefc7c4d2..abef5d6878 100644 --- a/libgambatte/src/memory.cpp +++ b/libgambatte/src/memory.cpp @@ -1104,7 +1104,7 @@ int Memory::LinkStatus(int which) return -1; } -void Memory::SaveS(NewState *ns) +SYNCFUNC(Memory) { SSS(cart); NSS(ioamhram); @@ -1126,31 +1126,5 @@ void Memory::SaveS(NewState *ns) NSS(LINKCABLE); NSS(linkClockTrigger); } - -void Memory::LoadS(NewState *ns) -{ - SSL(cart); - NSL(ioamhram); - NSL(divLastUpdate); - NSL(lastOamDmaUpdate); - - SSL(intreq); - SSL(tima); - SSL(display); - SSL(sound); - //SSL(interrupter); // no state - - NSL(dmaSource); - NSL(dmaDestination); - NSL(oamDmaPos); - NSL(serialCnt); - NSL(blanklcd); - - NSL(LINKCABLE); - NSL(linkClockTrigger); -} - - - } diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h index f76f1b16b2..e83f521bfb 100644 --- a/libgambatte/src/memory.h +++ b/libgambatte/src/memory.h @@ -196,8 +196,7 @@ public: int LinkStatus(int which); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/minkeeper.h b/libgambatte/src/minkeeper.h index 54617d5d1c..0031adf098 100644 --- a/libgambatte/src/minkeeper.h +++ b/libgambatte/src/minkeeper.h @@ -108,17 +108,12 @@ public: unsigned long value(const int id) const { return values[id]; } // not sure if i understood everything in minkeeper correctly, so something might be missing here? - void SaveS(gambatte::NewState *ns) + template + void SyncState(gambatte::NewState *ns) { NSS(values); NSS(minValue_); NSS(a); - } - void LoadS(gambatte::NewState *ns) - { - NSL(values); - NSL(minValue_); - NSL(a); } }; diff --git a/libgambatte/src/newstate.h b/libgambatte/src/newstate.h index 0a65a1a1f2..8cf2deca33 100644 --- a/libgambatte/src/newstate.h +++ b/libgambatte/src/newstate.h @@ -61,6 +61,11 @@ public: 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 @@ -71,29 +76,22 @@ public: // 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 (0) -#define EVS(x,v,n) else if ((x) == (v)) _ttmp = (n) -#define EES(x,d) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0) +#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 EBL(x,d) do { int _ttmp = (d); ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0) -#define EVL(x,v,n) else if (_ttmp == (n)) (x) = (v) -#define EEL(x,d) else (x) = (d); } while (0) +#define RSS(x,b) do { if (isReader)\ +{ ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == 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 RSS(x,b) do { ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0) -#define RSL(x,b) do { ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == 0xdeadbeef ? 0 : (b) + _ttmp); } while (0) +#define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0) -#define PSS(x,s) ns->Save((x), (s), #x) -#define PSL(x,s) ns->Load((x), (s), #x) +#define SSS(x) do { ns->EnterSection(#x); (x).SyncState(ns); ns->ExitSection(#x); } while (0) -#define NSS(x) ns->Save(&(x), sizeof(x), #x) -#define NSL(x) ns->Load(&(x), sizeof(x), #x) - -#define SSS(x) do { ns->EnterSection(#x); (x).SaveS(ns); ns->ExitSection(#x); } while (0) -#define SSL(x) do { ns->EnterSection(#x); (x).LoadS(ns); ns->ExitSection(#x); } while (0) - -#define TSS(x) do { ns->EnterSection(#x); (x)->SaveS(ns); ns->ExitSection(#x); } while (0) -#define TSL(x) do { ns->EnterSection(#x); (x)->LoadS(ns); ns->ExitSection(#x); } while (0) +#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState(ns); ns->ExitSection(#x); } while (0) } diff --git a/libgambatte/src/sound.cpp b/libgambatte/src/sound.cpp index b0e307afd4..cf214486e3 100644 --- a/libgambatte/src/sound.cpp +++ b/libgambatte/src/sound.cpp @@ -180,7 +180,7 @@ unsigned PSG::getStatus() const { } // the buffer and position are not saved, as they're set and flushed on each runfor() call -void PSG::SaveS(NewState *ns) +SYNCFUNC(PSG) { SSS(ch1); SSS(ch2); @@ -191,17 +191,5 @@ void PSG::SaveS(NewState *ns) NSS(rsum); NSS(enabled); } - -void PSG::LoadS(NewState *ns) -{ - SSL(ch1); - SSL(ch2); - SSL(ch3); - SSL(ch4); - NSL(lastUpdate); - NSL(soVol); - NSL(rsum); - NSL(enabled); -} } diff --git a/libgambatte/src/sound.h b/libgambatte/src/sound.h index b2b1f81cca..602d2986a0 100644 --- a/libgambatte/src/sound.h +++ b/libgambatte/src/sound.h @@ -90,8 +90,7 @@ public: void map_so(unsigned nr51); unsigned getStatus() const; - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/sound/channel1.cpp b/libgambatte/src/sound/channel1.cpp index 84aa93c445..7e1322d0b2 100644 --- a/libgambatte/src/sound/channel1.cpp +++ b/libgambatte/src/sound/channel1.cpp @@ -104,21 +104,14 @@ void Channel1::SweepUnit::loadState(const SaveState &state) { negging = state.spu.ch1.sweep.negging; } -void Channel1::SweepUnit::SaveS(NewState *ns) +template +void Channel1::SweepUnit::SyncState(NewState *ns) { NSS(counter); NSS(shadow); NSS(nr0); NSS(negging); } - -void Channel1::SweepUnit::LoadS(NewState *ns) -{ - NSL(counter); - NSL(shadow); - NSL(nr0); - NSL(negging); -} Channel1::Channel1() : staticOutputTest(*this, dutyUnit), @@ -275,7 +268,7 @@ void Channel1::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign } } -void Channel1::SaveS(NewState *ns) +SYNCFUNC(Channel1) { SSS(lengthCounter); SSS(dutyUnit); @@ -296,27 +289,5 @@ void Channel1::SaveS(NewState *ns) NSS(nr4); NSS(master); } - -void Channel1::LoadS(NewState *ns) -{ - SSL(lengthCounter); - SSL(dutyUnit); - SSL(envelopeUnit); - SSL(sweepUnit); - - EBL(nextEventUnit, 0); - EVL(nextEventUnit, &dutyUnit, 1); - EVL(nextEventUnit, &sweepUnit, 2); - EVL(nextEventUnit, &envelopeUnit, 3); - EVL(nextEventUnit, &lengthCounter, 4); - EEL(nextEventUnit, NULL); - - NSL(cycleCounter); - NSL(soMask); - NSL(prevOut); - - NSL(nr4); - NSL(master); -} } diff --git a/libgambatte/src/sound/channel1.h b/libgambatte/src/sound/channel1.h index 086d36f124..d1afdefd51 100644 --- a/libgambatte/src/sound/channel1.h +++ b/libgambatte/src/sound/channel1.h @@ -1,101 +1,99 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL1_H -#define SOUND_CHANNEL1_H - -#include "gbint.h" -#include "master_disabler.h" -#include "length_counter.h" -#include "duty_unit.h" -#include "envelope_unit.h" -#include "static_output_tester.h" -#include "newstate.h" - -namespace gambatte { - -struct SaveState; - -class Channel1 { - class SweepUnit : public SoundUnit { - MasterDisabler &disableMaster; - DutyUnit &dutyUnit; - unsigned short shadow; - unsigned char nr0; - bool negging; - - unsigned calcFreq(); - - public: - SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit); - void event(); - void nr0Change(unsigned newNr0); - void nr4Init(unsigned long cycleCounter); - void reset(); - void saveState(SaveState &state) const; - void loadState(const SaveState &state); +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SOUND_CHANNEL1_H +#define SOUND_CHANNEL1_H - void SaveS(NewState *ns); - void LoadS(NewState *ns); - }; - - friend class StaticOutputTester; - - StaticOutputTester staticOutputTest; - DutyMasterDisabler disableMaster; - LengthCounter lengthCounter; - DutyUnit dutyUnit; - EnvelopeUnit envelopeUnit; - SweepUnit sweepUnit; - - SoundUnit *nextEventUnit; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - - unsigned char nr4; - bool master; - - void setEvent(); - -public: - Channel1(); - void setNr0(unsigned data); - void setNr1(unsigned data); - void setNr2(unsigned data); - void setNr3(unsigned data); - void setNr4(unsigned data); - - void setSo(unsigned long soMask); - bool isActive() const { return master; } - - void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - void reset(); - void init(bool cgb); - void saveState(SaveState &state); - void loadState(const SaveState &state); - - void SaveS(NewState *ns); - void LoadS(NewState *ns); -}; - -} - -#endif +#include "gbint.h" +#include "master_disabler.h" +#include "length_counter.h" +#include "duty_unit.h" +#include "envelope_unit.h" +#include "static_output_tester.h" +#include "newstate.h" + +namespace gambatte { + +struct SaveState; + +class Channel1 { + class SweepUnit : public SoundUnit { + MasterDisabler &disableMaster; + DutyUnit &dutyUnit; + unsigned short shadow; + unsigned char nr0; + bool negging; + + unsigned calcFreq(); + + public: + SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit); + void event(); + void nr0Change(unsigned newNr0); + void nr4Init(unsigned long cycleCounter); + void reset(); + void saveState(SaveState &state) const; + void loadState(const SaveState &state); + + templatevoid SyncState(NewState *ns); + }; + + friend class StaticOutputTester; + + StaticOutputTester staticOutputTest; + DutyMasterDisabler disableMaster; + LengthCounter lengthCounter; + DutyUnit dutyUnit; + EnvelopeUnit envelopeUnit; + SweepUnit sweepUnit; + + SoundUnit *nextEventUnit; + + unsigned long cycleCounter; + unsigned long soMask; + unsigned long prevOut; + + unsigned char nr4; + bool master; + + void setEvent(); + +public: + Channel1(); + void setNr0(unsigned data); + void setNr1(unsigned data); + void setNr2(unsigned data); + void setNr3(unsigned data); + void setNr4(unsigned data); + + void setSo(unsigned long soMask); + bool isActive() const { return master; } + + void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); + + void reset(); + void init(bool cgb); + void saveState(SaveState &state); + void loadState(const SaveState &state); + + templatevoid SyncState(NewState *ns); +}; + +} + +#endif diff --git a/libgambatte/src/sound/channel2.cpp b/libgambatte/src/sound/channel2.cpp index 34e074a4b0..567a5c7102 100644 --- a/libgambatte/src/sound/channel2.cpp +++ b/libgambatte/src/sound/channel2.cpp @@ -162,7 +162,7 @@ void Channel2::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign } } -void Channel2::SaveS(NewState *ns) +SYNCFUNC(Channel2) { SSS(lengthCounter); SSS(dutyUnit); @@ -181,26 +181,5 @@ void Channel2::SaveS(NewState *ns) NSS(nr4); NSS(master); } - -void Channel2::LoadS(NewState *ns) -{ - SSL(lengthCounter); - SSL(dutyUnit); - SSL(envelopeUnit); - - EBL(nextEventUnit, 0); - EVL(nextEventUnit, &dutyUnit, 1); - EVL(nextEventUnit, &envelopeUnit, 2); - EVL(nextEventUnit, &lengthCounter, 3); - EEL(nextEventUnit, NULL); - - NSL(cycleCounter); - NSL(soMask); - NSL(prevOut); - - NSL(nr4); - NSL(master); -} - } diff --git a/libgambatte/src/sound/channel2.h b/libgambatte/src/sound/channel2.h index 5e8bed630b..bb2ecb659e 100644 --- a/libgambatte/src/sound/channel2.h +++ b/libgambatte/src/sound/channel2.h @@ -1,77 +1,76 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL2_H -#define SOUND_CHANNEL2_H - -#include "gbint.h" -#include "length_counter.h" -#include "duty_unit.h" -#include "envelope_unit.h" -#include "static_output_tester.h" +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SOUND_CHANNEL2_H +#define SOUND_CHANNEL2_H + +#include "gbint.h" +#include "length_counter.h" +#include "duty_unit.h" +#include "envelope_unit.h" +#include "static_output_tester.h" #include "newstate.h" - -namespace gambatte { - -struct SaveState; - -class Channel2 { - friend class StaticOutputTester; - - StaticOutputTester staticOutputTest; - DutyMasterDisabler disableMaster; - LengthCounter lengthCounter; - DutyUnit dutyUnit; - EnvelopeUnit envelopeUnit; - - SoundUnit *nextEventUnit; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - - unsigned char nr4; - bool master; - - void setEvent(); - -public: - Channel2(); - void setNr1(unsigned data); - void setNr2(unsigned data); - void setNr3(unsigned data); - void setNr4(unsigned data); - - void setSo(unsigned long soMask); - // void deactivate() { disableMaster(); setEvent(); } - bool isActive() const { return master; } - - void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - void reset(); - void init(bool cgb); - void saveState(SaveState &state); - void loadState(const SaveState &state); - - void SaveS(NewState *ns); - void LoadS(NewState *ns); -}; - -} - -#endif + +namespace gambatte { + +struct SaveState; + +class Channel2 { + friend class StaticOutputTester; + + StaticOutputTester staticOutputTest; + DutyMasterDisabler disableMaster; + LengthCounter lengthCounter; + DutyUnit dutyUnit; + EnvelopeUnit envelopeUnit; + + SoundUnit *nextEventUnit; + + unsigned long cycleCounter; + unsigned long soMask; + unsigned long prevOut; + + unsigned char nr4; + bool master; + + void setEvent(); + +public: + Channel2(); + void setNr1(unsigned data); + void setNr2(unsigned data); + void setNr3(unsigned data); + void setNr4(unsigned data); + + void setSo(unsigned long soMask); + // void deactivate() { disableMaster(); setEvent(); } + bool isActive() const { return master; } + + void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); + + void reset(); + void init(bool cgb); + void saveState(SaveState &state); + void loadState(const SaveState &state); + + templatevoid SyncState(NewState *ns); +}; + +} + +#endif diff --git a/libgambatte/src/sound/channel3.cpp b/libgambatte/src/sound/channel3.cpp index d7fb3f760d..fe11399c3d 100644 --- a/libgambatte/src/sound/channel3.cpp +++ b/libgambatte/src/sound/channel3.cpp @@ -208,7 +208,7 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign } } -void Channel3::SaveS(NewState *ns) +SYNCFUNC(Channel3) { NSS(waveRam); @@ -230,28 +230,5 @@ void Channel3::SaveS(NewState *ns) NSS(master); NSS(cgb); } - -void Channel3::LoadS(NewState *ns) -{ - NSL(waveRam); - - SSL(lengthCounter); - - NSL(cycleCounter); - NSL(soMask); - NSL(prevOut); - NSL(waveCounter); - NSL(lastReadTime); - - NSL(nr0); - NSL(nr3); - NSL(nr4); - NSL(wavePos); - NSL(rShift); - NSL(sampleBuf); - - NSL(master); - NSL(cgb); -} } diff --git a/libgambatte/src/sound/channel3.h b/libgambatte/src/sound/channel3.h index 1d109a3ab8..fe62d91aad 100644 --- a/libgambatte/src/sound/channel3.h +++ b/libgambatte/src/sound/channel3.h @@ -1,107 +1,106 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL3_H -#define SOUND_CHANNEL3_H - -#include "gbint.h" -#include "master_disabler.h" -#include "length_counter.h" +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SOUND_CHANNEL3_H +#define SOUND_CHANNEL3_H + +#include "gbint.h" +#include "master_disabler.h" +#include "length_counter.h" #include "newstate.h" - -namespace gambatte { - -struct SaveState; - -class Channel3 { - class Ch3MasterDisabler : public MasterDisabler { - unsigned long &waveCounter; - - public: - Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {} - void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; } - }; - - unsigned char waveRam[0x10]; - - Ch3MasterDisabler disableMaster; - LengthCounter lengthCounter; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - unsigned long waveCounter; - unsigned long lastReadTime; - - unsigned char nr0; - unsigned char nr3; - unsigned char nr4; - unsigned char wavePos; - unsigned char rShift; - unsigned char sampleBuf; - - bool master; - bool cgb; - - void updateWaveCounter(unsigned long cc); - -public: - Channel3(); - bool isActive() const { return master; } - void reset(); - void init(bool cgb); - void setStatePtrs(SaveState &state); - void saveState(SaveState &state) const; - void loadState(const SaveState &state); - void setNr0(unsigned data); - void setNr1(unsigned data) { lengthCounter.nr1Change(data, nr4, cycleCounter); } - void setNr2(unsigned data); - void setNr3(unsigned data) { nr3 = data; } - void setNr4(unsigned data); - void setSo(unsigned long soMask); - void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - unsigned waveRamRead(unsigned index) const { - if (master) { - if (!cgb && cycleCounter != lastReadTime) - return 0xFF; - - index = wavePos >> 1; - } - - return waveRam[index]; - } - - void waveRamWrite(unsigned index, unsigned data) { - if (master) { - if (!cgb && cycleCounter != lastReadTime) - return; - - index = wavePos >> 1; - } - - waveRam[index] = data; - } - - void SaveS(NewState *ns); - void LoadS(NewState *ns); -}; - -} - -#endif + +namespace gambatte { + +struct SaveState; + +class Channel3 { + class Ch3MasterDisabler : public MasterDisabler { + unsigned long &waveCounter; + + public: + Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {} + void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; } + }; + + unsigned char waveRam[0x10]; + + Ch3MasterDisabler disableMaster; + LengthCounter lengthCounter; + + unsigned long cycleCounter; + unsigned long soMask; + unsigned long prevOut; + unsigned long waveCounter; + unsigned long lastReadTime; + + unsigned char nr0; + unsigned char nr3; + unsigned char nr4; + unsigned char wavePos; + unsigned char rShift; + unsigned char sampleBuf; + + bool master; + bool cgb; + + void updateWaveCounter(unsigned long cc); + +public: + Channel3(); + bool isActive() const { return master; } + void reset(); + void init(bool cgb); + void setStatePtrs(SaveState &state); + void saveState(SaveState &state) const; + void loadState(const SaveState &state); + void setNr0(unsigned data); + void setNr1(unsigned data) { lengthCounter.nr1Change(data, nr4, cycleCounter); } + void setNr2(unsigned data); + void setNr3(unsigned data) { nr3 = data; } + void setNr4(unsigned data); + void setSo(unsigned long soMask); + void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); + + unsigned waveRamRead(unsigned index) const { + if (master) { + if (!cgb && cycleCounter != lastReadTime) + return 0xFF; + + index = wavePos >> 1; + } + + return waveRam[index]; + } + + void waveRamWrite(unsigned index, unsigned data) { + if (master) { + if (!cgb && cycleCounter != lastReadTime) + return; + + index = wavePos >> 1; + } + + waveRam[index] = data; + } + + templatevoid SyncState(NewState *ns); +}; + +} + +#endif diff --git a/libgambatte/src/sound/channel4.cpp b/libgambatte/src/sound/channel4.cpp index c924ea9595..3fb6473868 100644 --- a/libgambatte/src/sound/channel4.cpp +++ b/libgambatte/src/sound/channel4.cpp @@ -163,7 +163,8 @@ void Channel4::Lfsr::loadState(const SaveState &state) { nr3 = state.mem.ioamhram.get()[0x122]; } -void Channel4::Lfsr::SaveS(NewState *ns) +template +void Channel4::Lfsr::SyncState(NewState *ns) { NSS(counter); NSS(backupCounter); @@ -171,15 +172,6 @@ void Channel4::Lfsr::SaveS(NewState *ns) NSS(nr3); NSS(master); } - -void Channel4::Lfsr::LoadS(NewState *ns) -{ - NSL(counter); - NSL(backupCounter); - NSL(reg); - NSL(nr3); - NSL(master); -} Channel4::Channel4() : staticOutputTest(*this, lfsr), @@ -319,7 +311,7 @@ void Channel4::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign } } -void Channel4::SaveS(NewState *ns) +SYNCFUNC(Channel4) { SSS(lengthCounter); SSS(envelopeUnit); @@ -338,25 +330,5 @@ void Channel4::SaveS(NewState *ns) NSS(nr4); NSS(master); } - -void Channel4::LoadS(NewState *ns) -{ - SSL(lengthCounter); - SSL(envelopeUnit); - SSL(lfsr); - - EBL(nextEventUnit, 0); - EVL(nextEventUnit, &lfsr, 1); - EVL(nextEventUnit, &envelopeUnit, 2); - EVL(nextEventUnit, &lengthCounter, 3); - EEL(nextEventUnit, NULL); - - NSL(cycleCounter); - NSL(soMask); - NSL(prevOut); - - NSL(nr4); - NSL(master); -} } diff --git a/libgambatte/src/sound/channel4.h b/libgambatte/src/sound/channel4.h index 85c3d05f22..fe8eb07f3d 100644 --- a/libgambatte/src/sound/channel4.h +++ b/libgambatte/src/sound/channel4.h @@ -53,8 +53,7 @@ class Channel4 { void killCounter() { counter = COUNTER_DISABLED; } void reviveCounter(unsigned long cc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; class Ch4MasterDisabler : public MasterDisabler { @@ -100,8 +99,7 @@ public: void saveState(SaveState &state); void loadState(const SaveState &state); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/sound/duty_unit.cpp b/libgambatte/src/sound/duty_unit.cpp index d737f3bff0..130fcbcaea 100644 --- a/libgambatte/src/sound/duty_unit.cpp +++ b/libgambatte/src/sound/duty_unit.cpp @@ -149,7 +149,7 @@ void DutyUnit::reviveCounter(const unsigned long cc) { setCounter(); } -void DutyUnit::SaveS(NewState *ns) +SYNCFUNC(DutyUnit) { NSS(counter); NSS(nextPosUpdate); @@ -159,17 +159,5 @@ void DutyUnit::SaveS(NewState *ns) NSS(high); NSS(enableEvents); } - -void DutyUnit::LoadS(NewState *ns) -{ - NSL(counter); - NSL(nextPosUpdate); - NSL(period); - NSL(pos); - NSL(duty); - NSL(high); - NSL(enableEvents); -} - } diff --git a/libgambatte/src/sound/duty_unit.h b/libgambatte/src/sound/duty_unit.h index 5006ccdbde..de44de30a1 100644 --- a/libgambatte/src/sound/duty_unit.h +++ b/libgambatte/src/sound/duty_unit.h @@ -56,8 +56,7 @@ public: unsigned getFreq() const { return 2048 - (period >> 1); } void setFreq(unsigned newFreq, unsigned long cc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; class DutyMasterDisabler : public MasterDisabler { diff --git a/libgambatte/src/sound/envelope_unit.cpp b/libgambatte/src/sound/envelope_unit.cpp index 9812b2cf76..37a1af5578 100644 --- a/libgambatte/src/sound/envelope_unit.cpp +++ b/libgambatte/src/sound/envelope_unit.cpp @@ -103,18 +103,11 @@ void EnvelopeUnit::loadState(const SaveState::SPU::Env &estate, const unsigned n this->nr2 = nr2; } -void EnvelopeUnit::SaveS(NewState *ns) +SYNCFUNC(EnvelopeUnit) { NSS(counter); NSS(nr2); NSS(volume); } - -void EnvelopeUnit::LoadS(NewState *ns) -{ - NSL(counter); - NSL(nr2); - NSL(volume); -} } diff --git a/libgambatte/src/sound/envelope_unit.h b/libgambatte/src/sound/envelope_unit.h index 46c360f7a5..d7d2eca0a0 100644 --- a/libgambatte/src/sound/envelope_unit.h +++ b/libgambatte/src/sound/envelope_unit.h @@ -49,8 +49,7 @@ public: void saveState(SaveState::SPU::Env &estate) const; void loadState(const SaveState::SPU::Env &estate, unsigned nr2, unsigned long cc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/sound/length_counter.cpp b/libgambatte/src/sound/length_counter.cpp index c9cc87c508..2846c85ba8 100644 --- a/libgambatte/src/sound/length_counter.cpp +++ b/libgambatte/src/sound/length_counter.cpp @@ -88,18 +88,11 @@ void LengthCounter::loadState(const SaveState::SPU::LCounter &lstate, const unsi lengthCounter = lstate.lengthCounter; } -void LengthCounter::SaveS(NewState *ns) +SYNCFUNC(LengthCounter) { NSS(counter); NSS(lengthCounter); NSS(cgb); } - -void LengthCounter::LoadS(NewState *ns) -{ - NSL(counter); - NSL(lengthCounter); - NSL(cgb); -} } diff --git a/libgambatte/src/sound/length_counter.h b/libgambatte/src/sound/length_counter.h index ebfd9f47bb..a50d643824 100644 --- a/libgambatte/src/sound/length_counter.h +++ b/libgambatte/src/sound/length_counter.h @@ -43,8 +43,7 @@ public: void saveState(SaveState::SPU::LCounter &lstate) const; void loadState(const SaveState::SPU::LCounter &lstate, unsigned long cc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/tima.cpp b/libgambatte/src/tima.cpp index 1a98764e43..5764afa6b8 100644 --- a/libgambatte/src/tima.cpp +++ b/libgambatte/src/tima.cpp @@ -168,7 +168,7 @@ void Tima::doIrqEvent(const TimaInterruptRequester timaIrq) { timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3])); } -void Tima::SaveS(NewState *ns) +SYNCFUNC(Tima) { NSS(lastUpdate_); NSS(tmatime_); @@ -176,14 +176,5 @@ void Tima::SaveS(NewState *ns) NSS(tma_); NSS(tac_); } - -void Tima::LoadS(NewState *ns) -{ - NSL(lastUpdate_); - NSL(tmatime_); - NSL(tima_); - NSL(tma_); - NSL(tac_); -} } diff --git a/libgambatte/src/tima.h b/libgambatte/src/tima.h index e617eb95ae..aece83b286 100644 --- a/libgambatte/src/tima.h +++ b/libgambatte/src/tima.h @@ -61,8 +61,7 @@ public: void doIrqEvent(TimaInterruptRequester timaIrq); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video.cpp b/libgambatte/src/video.cpp index 912727c985..e13a5acb25 100644 --- a/libgambatte/src/video.cpp +++ b/libgambatte/src/video.cpp @@ -744,7 +744,7 @@ void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, con // don't need to save or load rgb32 color data -void LCD::SaveS(NewState *ns) +SYNCFUNC(LCD) { SSS(ppu); NSS(bgpData); @@ -758,20 +758,5 @@ void LCD::SaveS(NewState *ns) NSS(m2IrqStatReg_); NSS(m1IrqStatReg_); } - -void LCD::LoadS(NewState *ns) -{ - SSL(ppu); - NSL(bgpData); - NSL(objpData); - SSL(eventTimes_); - SSL(m0Irq_); - SSL(lycIrq); - SSL(nextM0Time_); - - NSL(statReg); - NSL(m2IrqStatReg_); - NSL(m1IrqStatReg_); -} } diff --git a/libgambatte/src/video.h b/libgambatte/src/video.h index 9f6ea0c7c1..ffe14894e5 100644 --- a/libgambatte/src/video.h +++ b/libgambatte/src/video.h @@ -82,15 +82,11 @@ public: unsigned statReg() const { return statReg_; } - void SaveS(NewState *ns) + template + void SyncState(NewState *ns) { NSS(statReg_); NSS(lycReg_); - } - void LoadS(NewState *ns) - { - NSL(statReg_); - NSL(lycReg_); } }; @@ -128,17 +124,12 @@ class LCD { void flagIrq(const unsigned bit) { memEventRequester_.flagIrq(bit); } void flagHdmaReq() { memEventRequester_.flagHdmaReq(); } - void SaveS(NewState *ns) + template + void SyncState(NewState *ns) { SSS(eventMin_); SSS(memEventMin_); //SSS(memEventRequester_); // not needed - } - void LoadS(NewState *ns) - { - SSL(eventMin_); - SSL(memEventMin_); - //SSL(memEventRequester_); // not needed } }; @@ -284,8 +275,7 @@ public: void setScanlineCallback(void (*callback)(), int sl) { scanlinecallback = callback; scanlinecallbacksl = sl; } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video/ly_counter.cpp b/libgambatte/src/video/ly_counter.cpp index c6cf7ac118..01ae017132 100644 --- a/libgambatte/src/video/ly_counter.cpp +++ b/libgambatte/src/video/ly_counter.cpp @@ -65,20 +65,12 @@ void LyCounter::setDoubleSpeed(const bool ds_in) { lineTime_ = 456U << ds_in; } -void LyCounter::SaveS(NewState *ns) +SYNCFUNC(LyCounter) { NSS(time_); NSS(lineTime_); NSS(ly_); NSS(ds); } - -void LyCounter::LoadS(NewState *ns) -{ - NSL(time_); - NSL(lineTime_); - NSL(ly_); - NSL(ds); -} } diff --git a/libgambatte/src/video/ly_counter.h b/libgambatte/src/video/ly_counter.h index ff60d710f9..f65d9ef7dc 100644 --- a/libgambatte/src/video/ly_counter.h +++ b/libgambatte/src/video/ly_counter.h @@ -52,8 +52,7 @@ public: void setDoubleSpeed(bool ds_in); unsigned long time() const { return time_; } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video/lyc_irq.cpp b/libgambatte/src/video/lyc_irq.cpp index 4e8097a6ca..5f3a212bb9 100644 --- a/libgambatte/src/video/lyc_irq.cpp +++ b/libgambatte/src/video/lyc_irq.cpp @@ -99,7 +99,7 @@ void LycIrq::lcdReset() { lycReg_ = lycRegSrc_; } -void LycIrq::SaveS(NewState *ns) +SYNCFUNC(LycIrq) { NSS(time_); NSS(lycRegSrc_); @@ -108,15 +108,5 @@ void LycIrq::SaveS(NewState *ns) NSS(statReg_); NSS(cgb_); } - -void LycIrq::LoadS(NewState *ns) -{ - NSL(time_); - NSL(lycRegSrc_); - NSL(statRegSrc_); - NSL(lycReg_); - NSL(statReg_); - NSL(cgb_); -} } diff --git a/libgambatte/src/video/lyc_irq.h b/libgambatte/src/video/lyc_irq.h index 874a581d5a..96e0f7d8c2 100644 --- a/libgambatte/src/video/lyc_irq.h +++ b/libgambatte/src/video/lyc_irq.h @@ -55,8 +55,7 @@ public: regChange(statRegSrc_, lycReg, lyCounter, cc); } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video/next_m0_time.cpp b/libgambatte/src/video/next_m0_time.cpp index 3aae7bf0bd..15bf6441b6 100644 --- a/libgambatte/src/video/next_m0_time.cpp +++ b/libgambatte/src/video/next_m0_time.cpp @@ -7,15 +7,9 @@ void NextM0Time::predictNextM0Time(const PPU &ppu) { predictedNextM0Time_ = ppu.predictedNextXposTime(167); } - -void NextM0Time::SaveS(NewState *ns) +SYNCFUNC(NextM0Time) { NSS(predictedNextM0Time_); } -void NextM0Time::LoadS(NewState *ns) -{ - NSL(predictedNextM0Time_); -} - } diff --git a/libgambatte/src/video/next_m0_time.h b/libgambatte/src/video/next_m0_time.h index c74f33194f..a47f337118 100644 --- a/libgambatte/src/video/next_m0_time.h +++ b/libgambatte/src/video/next_m0_time.h @@ -14,8 +14,7 @@ public: void invalidatePredictedNextM0Time() { predictedNextM0Time_ = 0; } unsigned predictedNextM0Time() const { return predictedNextM0Time_; } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video/ppu.cpp b/libgambatte/src/video/ppu.cpp index 5dc678db44..cf32ebcb86 100644 --- a/libgambatte/src/video/ppu.cpp +++ b/libgambatte/src/video/ppu.cpp @@ -1745,7 +1745,7 @@ void PPU::update(const unsigned long cc) { } } -void PPU::SaveS(NewState *ns) +SYNCFUNC(PPU) { NSS(p_.bgPalette); NSS(p_.spPalette); @@ -1810,71 +1810,5 @@ void PPU::SaveS(NewState *ns) NSS(p_.cgb); NSS(p_.weMaster); } - -void PPU::LoadS(NewState *ns) -{ - NSL(p_.bgPalette); - NSL(p_.spPalette); - NSL(p_.spriteList); - NSL(p_.spwordList); - NSL(p_.nextSprite); - NSL(p_.currentSprite); - - EBL(p_.nextCallPtr, 0); - EVL(p_.nextCallPtr, &M2::Ly0::f0_, 1); - EVL(p_.nextCallPtr, &M2::LyNon0::f0_, 2); - EVL(p_.nextCallPtr, &M2::LyNon0::f1_, 3); - EVL(p_.nextCallPtr, &M3Start::f0_, 4); - EVL(p_.nextCallPtr, &M3Start::f1_, 5); - EVL(p_.nextCallPtr, &M3Loop::Tile::f0_, 6); - EVL(p_.nextCallPtr, &M3Loop::Tile::f1_, 7); - EVL(p_.nextCallPtr, &M3Loop::Tile::f2_, 8); - EVL(p_.nextCallPtr, &M3Loop::Tile::f3_, 9); - EVL(p_.nextCallPtr, &M3Loop::Tile::f4_, 10); - EVL(p_.nextCallPtr, &M3Loop::Tile::f5_, 11); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f0_, 12); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f1_, 13); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f2_, 14); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f3_, 15); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f4_, 16); - EVL(p_.nextCallPtr, &M3Loop::LoadSprites::f5_, 17); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f0_, 18); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f1_, 19); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f2_, 20); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f3_, 21); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f4_, 22); - EVL(p_.nextCallPtr, &M3Loop::StartWindowDraw::f5_, 23); - EEL(p_.nextCallPtr, NULL); - - NSL(p_.now); - NSL(p_.lastM0Time); - NSL(p_.cycles); - - NSL(p_.tileword); - NSL(p_.ntileword); - - SSL(p_.spriteMapper); - SSL(p_.lyCounter); - //SSL(p_.framebuf); // no state - - NSL(p_.lcdc); - NSL(p_.scy); - NSL(p_.scx); - NSL(p_.wy); - NSL(p_.wy2); - NSL(p_.wx); - NSL(p_.winDrawState); - NSL(p_.wscx); - NSL(p_.winYPos); - NSL(p_.reg0); - NSL(p_.reg1); - NSL(p_.attrib); - NSL(p_.nattrib); - NSL(p_.xpos); - NSL(p_.endx); - - NSL(p_.cgb); - NSL(p_.weMaster); -} } diff --git a/libgambatte/src/video/ppu.h b/libgambatte/src/video/ppu.h index fda7ee0bbd..8152f83376 100644 --- a/libgambatte/src/video/ppu.h +++ b/libgambatte/src/video/ppu.h @@ -131,8 +131,7 @@ public: unsigned long * spPalette() { return p_.spPalette; } void update(unsigned long cc); - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/libgambatte/src/video/sprite_mapper.cpp b/libgambatte/src/video/sprite_mapper.cpp index 7858cb6acc..80b588c088 100644 --- a/libgambatte/src/video/sprite_mapper.cpp +++ b/libgambatte/src/video/sprite_mapper.cpp @@ -117,7 +117,7 @@ void SpriteMapper::OamReader::loadState(const SaveState &ss, const unsigned char change(lu); } -void SpriteMapper::OamReader::SaveS(NewState *ns) +SYNCFUNC(SpriteMapper::OamReader) { NSS(buf); NSS(szbuf); @@ -127,17 +127,6 @@ void SpriteMapper::OamReader::SaveS(NewState *ns) NSS(largeSpritesSrc); NSS(cgb_); } - -void SpriteMapper::OamReader::LoadS(NewState *ns) -{ - NSL(buf); - NSL(szbuf); - - NSL(lu); - NSL(lastChange); - NSL(largeSpritesSrc); - NSL(cgb_); -} void SpriteMapper::OamReader::enableDisplay(const unsigned long cc) { std::memset(buf, 0x00, sizeof(buf)); @@ -201,7 +190,7 @@ unsigned long SpriteMapper::doEvent(const unsigned long time) { return oamReader.changed() ? time + oamReader.lyCounter.lineTime() : static_cast(DISABLED_TIME); } -void SpriteMapper::SaveS(NewState *ns) +SYNCFUNC(SpriteMapper) { NSS(spritemap); NSS(num); @@ -209,14 +198,5 @@ void SpriteMapper::SaveS(NewState *ns) SSS(nextM0Time_); SSS(oamReader); } - -void SpriteMapper::LoadS(NewState *ns) -{ - NSL(spritemap); - NSL(num); - - SSL(nextM0Time_); - SSL(oamReader); -} } diff --git a/libgambatte/src/video/sprite_mapper.h b/libgambatte/src/video/sprite_mapper.h index f02447e7fb..defc39d5cf 100644 --- a/libgambatte/src/video/sprite_mapper.h +++ b/libgambatte/src/video/sprite_mapper.h @@ -59,8 +59,7 @@ class SpriteMapper { void loadState(const SaveState &ss, const unsigned char *oamram); bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { return cc < lu; } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; enum { NEED_SORTING_MASK = 0x80 }; @@ -127,8 +126,7 @@ public: void loadState(const SaveState &state, const unsigned char *const oamram) { oamReader.loadState(state, oamram); mapSprites(); } bool inactivePeriodAfterDisplayEnable(unsigned long cc) const { return oamReader.inactivePeriodAfterDisplayEnable(cc); } - void SaveS(NewState *ns); - void LoadS(NewState *ns); + templatevoid SyncState(NewState *ns); }; } diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index 0af7301d60..30a1066e82 100644 Binary files a/output/dll/libgambatte.dll and b/output/dll/libgambatte.dll differ