gambatte: break stuff. don't use
This commit is contained in:
parent
64e3ff520d
commit
975ced7e38
|
@ -237,6 +237,7 @@
|
|||
<Compile Include="Consoles\Nintendo\Gameboy\GambatteLink.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\StateDebug.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBA\LibMeteor.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />
|
||||
<Compile Include="Consoles\Nintendo\N64\N64Input.cs" />
|
||||
|
|
|
@ -106,6 +106,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
TimeCallback = new LibGambatte.RTCCallback(GetCurrentTime);
|
||||
LibGambatte.gambatte_setrtccallback(GambatteState, TimeCallback);
|
||||
|
||||
NewSaveCoreSetBuff();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -253,6 +255,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
ProcessSoundEnd();
|
||||
|
||||
FrameAdvancePost();
|
||||
|
||||
//DebugStates(); // for maximum fun only
|
||||
}
|
||||
|
||||
static string MapperName(byte[] romdata)
|
||||
|
@ -414,6 +418,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
#region savestates
|
||||
|
||||
byte[] newsavebuff;
|
||||
|
||||
void NewSaveCoreSetBuff()
|
||||
{
|
||||
newsavebuff = new byte[LibGambatte.gambatte_newstatelen(GambatteState)];
|
||||
}
|
||||
|
||||
byte[] NewSaveCoreBinary()
|
||||
{
|
||||
if (!LibGambatte.gambatte_newstatesave(GambatteState, newsavebuff, newsavebuff.Length))
|
||||
throw new Exception("gambatte_newstatesave() returned false");
|
||||
return newsavebuff;
|
||||
}
|
||||
|
||||
void NewLoadCoreBinary(byte[] data)
|
||||
{
|
||||
if (!LibGambatte.gambatte_newstateload(GambatteState, data, data.Length))
|
||||
throw new Exception("gambatte_newstateload() returned false");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// handles the core-portion of savestating
|
||||
/// </summary>
|
||||
|
@ -464,7 +488,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
public void SaveStateBinary(System.IO.BinaryWriter writer)
|
||||
{
|
||||
byte[] data = SaveCoreBinary();
|
||||
//byte[] data = SaveCoreBinary();
|
||||
byte[] data = NewSaveCoreBinary();
|
||||
|
||||
writer.Write(data.Length);
|
||||
writer.Write(data);
|
||||
|
@ -482,7 +507,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
int length = reader.ReadInt32();
|
||||
byte[] data = reader.ReadBytes(length);
|
||||
|
||||
LoadCoreBinary(data);
|
||||
//LoadCoreBinary(data);
|
||||
NewLoadCoreBinary(data);
|
||||
|
||||
// other variables
|
||||
IsLagFrame = reader.ReadBoolean();
|
||||
|
@ -503,6 +529,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
public bool BinarySaveStatesPreferred { get { return true; } }
|
||||
|
||||
void DebugStates()
|
||||
{
|
||||
var sd = new StateDebug();
|
||||
var Save = new LibGambatte.DataFunction(sd.Save);
|
||||
var Load = new LibGambatte.DataFunction(sd.Load);
|
||||
var EnterSection = new LibGambatte.SectionFunction(sd.EnterSection);
|
||||
var ExitSection = new LibGambatte.SectionFunction(sd.ExitSection);
|
||||
|
||||
LibGambatte.gambatte_newstatesave_ex(GambatteState, Save, EnterSection, ExitSection);
|
||||
LibGambatte.gambatte_newstateload_ex(GambatteState, Load, EnterSection, ExitSection);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region memorycallback
|
||||
|
|
|
@ -298,6 +298,46 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gambatte_loadstate(IntPtr core, byte[] data, uint len);
|
||||
|
||||
/// <summary>
|
||||
/// new savestate method
|
||||
/// </summary>
|
||||
/// <param name="core"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int gambatte_newstatelen(IntPtr core);
|
||||
|
||||
/// <summary>
|
||||
/// new savestate method
|
||||
/// </summary>
|
||||
/// <param name="core"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="len"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gambatte_newstatesave(IntPtr core, byte[] data, int len);
|
||||
|
||||
/// <summary>
|
||||
/// new savestate method
|
||||
/// </summary>
|
||||
/// <param name="core"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="len"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gambatte_newstateload(IntPtr core, byte[] data, int len);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DataFunction(IntPtr data, int length, string name);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void SectionFunction(string name);
|
||||
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_newstatesave_ex(IntPtr core, DataFunction Save, SectionFunction EnterSection, SectionFunction ExitSection);
|
||||
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_newstateload_ex(IntPtr core, DataFunction Load, SectionFunction EnterSection, SectionFunction ExitSection);
|
||||
|
||||
/// <summary>
|
||||
/// ROM header title of currently loaded ROM image.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
/*
|
||||
* the new gambatte savestater includes functionality that
|
||||
* could be used to make structured text mode savestates. this module just does a bit of
|
||||
* sanity checking using that capability
|
||||
*/
|
||||
|
||||
public class StateDebug
|
||||
{
|
||||
Dictionary<string, byte[]> Data = new Dictionary<string, byte[]>();
|
||||
|
||||
string Path = "/";
|
||||
|
||||
List<string> SaveHistory = new List<string>();
|
||||
int LoadHistoryPos = 0;
|
||||
|
||||
public void Save(IntPtr data, int length, string name)
|
||||
{
|
||||
byte[] d = new byte[length];
|
||||
Marshal.Copy(data, d, 0, length);
|
||||
string s = Path + name;
|
||||
SaveHistory.Add(s);
|
||||
if (Data.ContainsKey(s))
|
||||
throw new Exception("Already stored");
|
||||
Data[s] = d;
|
||||
}
|
||||
|
||||
public void Load(IntPtr data, int length, string name)
|
||||
{
|
||||
string s = Path + name;
|
||||
byte[] d = Data[s];
|
||||
if (SaveHistory[LoadHistoryPos++] != s)
|
||||
throw new Exception("Loading out of order!");
|
||||
Marshal.Copy(d, 0, data, length);
|
||||
}
|
||||
|
||||
public void EnterSection(string name)
|
||||
{
|
||||
Path = Path + name + '/';
|
||||
}
|
||||
|
||||
public void ExitSection(string name)
|
||||
{
|
||||
int i = Path.Substring(0, Path.Length - 1).LastIndexOf('/');
|
||||
if (i < 0)
|
||||
throw new Exception("Couldn't unwind stack!");
|
||||
string newPath = Path.Substring(0, i + 1);
|
||||
string unwind = Path.Substring(0, Path.Length - 1).Substring(i + 1);
|
||||
if (unwind != name)
|
||||
throw new Exception("Left wrong section!");
|
||||
Path = newPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstdint>
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 };
|
||||
|
@ -129,6 +130,9 @@ public:
|
|||
|
||||
void GetRegs(int *dest);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
|
||||
private:
|
||||
struct Priv;
|
||||
Priv *const p_;
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
<ClInclude Include="src\mem\memptrs.h" />
|
||||
<ClInclude Include="src\mem\rtc.h" />
|
||||
<ClInclude Include="src\minkeeper.h" />
|
||||
<ClInclude Include="src\newstate.h" />
|
||||
<ClInclude Include="src\savestate.h" />
|
||||
<ClInclude Include="src\sound.h" />
|
||||
<ClInclude Include="src\sound\channel1.h" />
|
||||
|
@ -134,6 +135,7 @@
|
|||
<ClCompile Include="src\mem\cartridge.cpp" />
|
||||
<ClCompile Include="src\mem\memptrs.cpp" />
|
||||
<ClCompile Include="src\mem\rtc.cpp" />
|
||||
<ClCompile Include="src\newstate.cpp" />
|
||||
<ClCompile Include="src\sound.cpp" />
|
||||
<ClCompile Include="src\sound\channel1.cpp" />
|
||||
<ClCompile Include="src\sound\channel2.cpp" />
|
||||
|
|
|
@ -120,15 +120,18 @@
|
|||
<ClInclude Include="src\video\sprite_mapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\sound\static_output_tester.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\common\uncopyable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\insertion_sort.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\newstate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\sound\static_output_tester.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\cinterface.cpp">
|
||||
|
@ -209,5 +212,8 @@
|
|||
<ClCompile Include="src\tima.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\newstate.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,6 +1,7 @@
|
|||
#include "cinterface.h"
|
||||
#include "gambatte.h"
|
||||
#include <cstdlib>
|
||||
#include "newstate.h"
|
||||
|
||||
using namespace gambatte;
|
||||
|
||||
|
@ -168,7 +169,53 @@ GBEXPORT void gambatte_savestate_destroy(char *data)
|
|||
GBEXPORT int gambatte_loadstate(void *core, const char *data, unsigned len)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
return g->loadState(std::istringstream(std::string(data, len), std::ios_base::binary | std::ios_base::in));
|
||||
// msvc allows using an Rvalue directly where an Lvalue is need, which is kind of cool and sort of makes sense, but no
|
||||
std::istringstream iss(std::string(data, len), std::ios_base::binary | std::ios_base::in);
|
||||
return g->loadState(iss);
|
||||
}
|
||||
|
||||
GBEXPORT long gambatte_newstatelen(void *core)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateDummy dummy;
|
||||
g->SaveS(&dummy);
|
||||
return dummy.GetLength();
|
||||
}
|
||||
|
||||
GBEXPORT int gambatte_newstatesave(void *core, char *data, long len)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalBuffer saver(data, len);
|
||||
g->SaveS(&saver);
|
||||
return !saver.Overflow() && saver.GetLength() == len;
|
||||
}
|
||||
|
||||
GBEXPORT int gambatte_newstateload(void *core, const char *data, long len)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalBuffer loader((char *)data, len);
|
||||
g->LoadS(&loader);
|
||||
return !loader.Overflow() && loader.GetLength() == len;
|
||||
}
|
||||
|
||||
GBEXPORT void gambatte_newstatesave_ex(void *core,
|
||||
void (*Save_)(const void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name))
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalFunctions saver(Save_, NULL, EnterSection_, ExitSection_);
|
||||
g->SaveS(&saver);
|
||||
}
|
||||
|
||||
GBEXPORT void gambatte_newstateload_ex(void *core,
|
||||
void (*Load_)(void *ptr, size_t size, const char *name),
|
||||
void (*EnterSection_)(const char *name),
|
||||
void (*ExitSection_)(const char *name))
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
NewStateExternalFunctions loader(NULL, Load_, EnterSection_, ExitSection_);
|
||||
g->LoadS(&loader);
|
||||
}
|
||||
|
||||
static char horriblebuff[64];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@
|
|||
#define CPU_H
|
||||
|
||||
#include "memory.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -118,6 +119,9 @@ public:
|
|||
int LinkStatus(int which) { return memory.LinkStatus(which); }
|
||||
|
||||
void GetRegs(int *dest);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -245,4 +245,18 @@ void GB::GetRegs(int *dest) {
|
|||
p_->cpu.GetRegs(dest);
|
||||
}
|
||||
|
||||
void GB::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(p_->cpu);
|
||||
NSS(p_->gbaCgbMode);
|
||||
NSS(p_->vbuff);
|
||||
}
|
||||
|
||||
void GB::LoadS(NewState *ns)
|
||||
{
|
||||
SSL(p_->cpu);
|
||||
NSL(p_->gbaCgbMode);
|
||||
NSL(p_->vbuff);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,4 +100,22 @@ void InterruptRequester::setIfreg(const unsigned ifreg) {
|
|||
eventTimes.setValue<INTERRUPTS>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME));
|
||||
}
|
||||
|
||||
void InterruptRequester::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(eventTimes);
|
||||
NSS(minIntTime);
|
||||
NSS(ifreg_);
|
||||
NSS(iereg_);
|
||||
NSS(intFlags.flags_);
|
||||
}
|
||||
|
||||
void InterruptRequester::LoadS(NewState *ns)
|
||||
{
|
||||
SSL(eventTimes);
|
||||
NSL(minIntTime);
|
||||
NSL(ifreg_);
|
||||
NSL(iereg_);
|
||||
NSL(intFlags.flags_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "counterdef.h"
|
||||
#include "minkeeper.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
struct SaveState;
|
||||
|
@ -33,6 +34,7 @@ class InterruptRequester {
|
|||
unsigned iereg_;
|
||||
|
||||
class IntFlags {
|
||||
friend class InterruptRequester;
|
||||
unsigned char flags_;
|
||||
enum { IME_MASK = 1, HALTED_MASK = 2 };
|
||||
|
||||
|
@ -79,6 +81,9 @@ public:
|
|||
template<MemEventId id> void setEventTime(unsigned long value) { eventTimes.setValue<id>(value); }
|
||||
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);
|
||||
};
|
||||
|
||||
inline void flagHdmaReq(InterruptRequester *const intreq) { intreq->setEventTime<DMA>(0); }
|
||||
|
|
|
@ -35,6 +35,13 @@ public:
|
|||
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const {
|
||||
return (addr< 0x4000) == (bank == 0);
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Mbc0 : public DefaultMbc {
|
||||
|
@ -63,6 +70,15 @@ public:
|
|||
enableRam = ss.enableRam;
|
||||
memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(enableRam);
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(enableRam);
|
||||
}
|
||||
};
|
||||
|
||||
static inline unsigned rambanks(const MemPtrs &memptrs) {
|
||||
|
@ -137,6 +153,21 @@ public:
|
|||
setRambank();
|
||||
setRombank();
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
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 {
|
||||
|
@ -205,6 +236,19 @@ public:
|
|||
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const {
|
||||
return (addr < 0x4000) == ((bank & 0xF) == 0);
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(rombank);
|
||||
NSS(enableRam);
|
||||
NSS(rombank0Mode);
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(rombank);
|
||||
NSL(enableRam);
|
||||
NSL(rombank0Mode);
|
||||
}
|
||||
};
|
||||
|
||||
class Mbc2 : public DefaultMbc {
|
||||
|
@ -244,6 +288,17 @@ public:
|
|||
memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
|
||||
memptrs.setRombank(rombank & (rombanks(memptrs) - 1));
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(rombank);
|
||||
NSS(enableRam);
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(rombank);
|
||||
NSL(enableRam);
|
||||
}
|
||||
};
|
||||
|
||||
class Mbc3 : public DefaultMbc {
|
||||
|
@ -315,6 +370,19 @@ public:
|
|||
setRambank();
|
||||
setRombank();
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(rombank);
|
||||
NSS(rambank);
|
||||
NSS(enableRam);
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(rombank);
|
||||
NSL(rambank);
|
||||
NSL(enableRam);
|
||||
}
|
||||
};
|
||||
|
||||
class HuC1 : public DefaultMbc {
|
||||
|
@ -378,6 +446,20 @@ public:
|
|||
setRambank();
|
||||
setRombank();
|
||||
}
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
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 {
|
||||
|
@ -432,6 +514,19 @@ public:
|
|||
setRambank();
|
||||
setRombank();
|
||||
}
|
||||
|
||||
virtual void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(rombank);
|
||||
NSS(rambank);
|
||||
NSS(enableRam);
|
||||
}
|
||||
virtual void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(rombank);
|
||||
NSL(rambank);
|
||||
NSL(enableRam);
|
||||
}
|
||||
};
|
||||
|
||||
static bool hasRtc(const unsigned headerByte0x147) {
|
||||
|
@ -692,4 +787,18 @@ bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Cartridge::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(memptrs);
|
||||
SSS(rtc);
|
||||
TSS(mbc);
|
||||
}
|
||||
|
||||
void Cartridge::LoadS(NewState *ns)
|
||||
{
|
||||
SSL(memptrs);
|
||||
SSL(rtc);
|
||||
TSL(mbc);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -35,6 +36,9 @@ public:
|
|||
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 {
|
||||
|
@ -83,6 +87,9 @@ public:
|
|||
void setRTCCallback(std::uint32_t (*callback)()) {
|
||||
rtc.setRTCCallback(callback);
|
||||
}
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace gambatte {
|
|||
|
||||
MemPtrs::MemPtrs()
|
||||
: rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0),
|
||||
wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF)
|
||||
wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF),
|
||||
memchunk_len(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,7 +35,8 @@ MemPtrs::~MemPtrs() {
|
|||
|
||||
void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) {
|
||||
delete []memchunk_;
|
||||
memchunk_ = new unsigned char[0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000];
|
||||
memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000;
|
||||
memchunk_ = new unsigned char[memchunk_len];
|
||||
|
||||
romdata_[0] = romdata();
|
||||
rambankdata_ = romdata_[0] + rombanks * 0x4000ul + 0x4000;
|
||||
|
@ -136,4 +138,117 @@ void MemPtrs::disconnectOamDmaAreas() {
|
|||
}
|
||||
}
|
||||
|
||||
// all pointers here are relative to memchunk_
|
||||
#define MSS(a) RSS(a,memchunk_)
|
||||
#define MSL(a) RSL(a,memchunk_)
|
||||
|
||||
void MemPtrs::SaveS(NewState *ns)
|
||||
{
|
||||
MSS(rmem_[0x0]);
|
||||
MSS(wmem_[0x0]);
|
||||
MSS(rmem_[0x1]);
|
||||
MSS(wmem_[0x1]);
|
||||
MSS(rmem_[0x2]);
|
||||
MSS(wmem_[0x2]);
|
||||
MSS(rmem_[0x3]);
|
||||
MSS(wmem_[0x3]);
|
||||
MSS(rmem_[0x4]);
|
||||
MSS(wmem_[0x4]);
|
||||
MSS(rmem_[0x5]);
|
||||
MSS(wmem_[0x5]);
|
||||
MSS(rmem_[0x6]);
|
||||
MSS(wmem_[0x6]);
|
||||
MSS(rmem_[0x7]);
|
||||
MSS(wmem_[0x7]);
|
||||
MSS(rmem_[0x8]);
|
||||
MSS(wmem_[0x8]);
|
||||
MSS(rmem_[0x9]);
|
||||
MSS(wmem_[0x9]);
|
||||
MSS(rmem_[0xa]);
|
||||
MSS(wmem_[0xa]);
|
||||
MSS(rmem_[0xb]);
|
||||
MSS(wmem_[0xb]);
|
||||
MSS(rmem_[0xc]);
|
||||
MSS(wmem_[0xc]);
|
||||
MSS(rmem_[0xd]);
|
||||
MSS(wmem_[0xd]);
|
||||
MSS(rmem_[0xe]);
|
||||
MSS(wmem_[0xe]);
|
||||
MSS(rmem_[0xf]);
|
||||
MSS(wmem_[0xf]);
|
||||
//for (int i = 0; i < 0x10; i++)
|
||||
//{
|
||||
// MSS(rmem_[i]);
|
||||
// MSS(wmem_[i]);
|
||||
//}
|
||||
MSS(romdata_[0]);
|
||||
MSS(romdata_[1]);
|
||||
MSS(wramdata_[0]);
|
||||
MSS(wramdata_[1]);
|
||||
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_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef MEMPTRS_H
|
||||
#define MEMPTRS_H
|
||||
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM,
|
||||
|
@ -38,7 +40,9 @@ class MemPtrs {
|
|||
unsigned char *wramdataend_;
|
||||
|
||||
OamDmaSrc oamDmaSrc_;
|
||||
|
||||
|
||||
unsigned memchunk_len;
|
||||
|
||||
MemPtrs(const MemPtrs &);
|
||||
MemPtrs & operator=(const MemPtrs &);
|
||||
void disconnectOamDmaAreas();
|
||||
|
@ -74,6 +78,9 @@ public:
|
|||
void setVrambank(unsigned bank) { vrambankptr_ = vramdata() + bank * 0x2000ul - 0x8000; }
|
||||
void setWrambank(unsigned bank);
|
||||
void setOamDmaSrc(OamDmaSrc oamDmaSrc);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
inline bool isCgb(const MemPtrs &memptrs) {
|
||||
|
|
|
@ -1,158 +1,218 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include "rtc.h"
|
||||
#include "../savestate.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
Rtc::Rtc()
|
||||
: activeData(NULL),
|
||||
activeSet(NULL),
|
||||
baseTime(0),
|
||||
haltTime(0),
|
||||
index(5),
|
||||
dataDh(0),
|
||||
dataDl(0),
|
||||
dataH(0),
|
||||
dataM(0),
|
||||
dataS(0),
|
||||
enabled(false),
|
||||
lastLatchData(false),
|
||||
timeCB(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Rtc::doLatch() {
|
||||
std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
|
||||
|
||||
while (tmp > 0x1FF * 86400) {
|
||||
baseTime += 0x1FF * 86400;
|
||||
tmp -= 0x1FF * 86400;
|
||||
dataDh |= 0x80;
|
||||
}
|
||||
|
||||
dataDl = (tmp / 86400) & 0xFF;
|
||||
dataDh &= 0xFE;
|
||||
dataDh |= ((tmp / 86400) & 0x100) >> 8;
|
||||
tmp %= 86400;
|
||||
|
||||
dataH = tmp / 3600;
|
||||
tmp %= 3600;
|
||||
|
||||
dataM = tmp / 60;
|
||||
tmp %= 60;
|
||||
|
||||
dataS = tmp;
|
||||
}
|
||||
|
||||
void Rtc::doSwapActive() {
|
||||
if (!enabled || index > 4) {
|
||||
activeData = NULL;
|
||||
activeSet = NULL;
|
||||
} else switch (index) {
|
||||
case 0x00:
|
||||
activeData = &dataS;
|
||||
activeSet = &Rtc::setS;
|
||||
break;
|
||||
case 0x01:
|
||||
activeData = &dataM;
|
||||
activeSet = &Rtc::setM;
|
||||
break;
|
||||
case 0x02:
|
||||
activeData = &dataH;
|
||||
activeSet = &Rtc::setH;
|
||||
break;
|
||||
case 0x03:
|
||||
activeData = &dataDl;
|
||||
activeSet = &Rtc::setDl;
|
||||
break;
|
||||
case 0x04:
|
||||
activeData = &dataDh;
|
||||
activeSet = &Rtc::setDh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Rtc::saveState(SaveState &state) const {
|
||||
state.rtc.baseTime = baseTime;
|
||||
state.rtc.haltTime = haltTime;
|
||||
state.rtc.dataDh = dataDh;
|
||||
state.rtc.dataDl = dataDl;
|
||||
state.rtc.dataH = dataH;
|
||||
state.rtc.dataM = dataM;
|
||||
state.rtc.dataS = dataS;
|
||||
state.rtc.lastLatchData = lastLatchData;
|
||||
}
|
||||
|
||||
void Rtc::loadState(const SaveState &state) {
|
||||
baseTime = state.rtc.baseTime;
|
||||
haltTime = state.rtc.haltTime;
|
||||
dataDh = state.rtc.dataDh;
|
||||
dataDl = state.rtc.dataDl;
|
||||
dataH = state.rtc.dataH;
|
||||
dataM = state.rtc.dataM;
|
||||
dataS = state.rtc.dataS;
|
||||
lastLatchData = state.rtc.lastLatchData;
|
||||
|
||||
doSwapActive();
|
||||
}
|
||||
|
||||
void Rtc::setDh(const unsigned new_dh) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
|
||||
baseTime += old_highdays * 86400;
|
||||
baseTime -= ((new_dh & 0x1) << 8) * 86400;
|
||||
|
||||
if ((dataDh ^ new_dh) & 0x40) {
|
||||
if (new_dh & 0x40)
|
||||
haltTime = timeCB();
|
||||
else
|
||||
baseTime += timeCB() - haltTime;
|
||||
}
|
||||
}
|
||||
|
||||
void Rtc::setDl(const unsigned new_lowdays) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF;
|
||||
baseTime += old_lowdays * 86400;
|
||||
baseTime -= new_lowdays * 86400;
|
||||
}
|
||||
|
||||
void Rtc::setH(const unsigned new_hours) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24;
|
||||
baseTime += old_hours * 3600;
|
||||
baseTime -= new_hours * 3600;
|
||||
}
|
||||
|
||||
void Rtc::setM(const unsigned new_minutes) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60;
|
||||
baseTime += old_minutes * 60;
|
||||
baseTime -= new_minutes * 60;
|
||||
}
|
||||
|
||||
void Rtc::setS(const unsigned new_seconds) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
baseTime += (unixtime - baseTime) % 60;
|
||||
baseTime -= new_seconds;
|
||||
}
|
||||
|
||||
}
|
||||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include "rtc.h"
|
||||
#include "../savestate.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
Rtc::Rtc()
|
||||
: activeData(NULL),
|
||||
activeSet(NULL),
|
||||
baseTime(0),
|
||||
haltTime(0),
|
||||
index(5),
|
||||
dataDh(0),
|
||||
dataDl(0),
|
||||
dataH(0),
|
||||
dataM(0),
|
||||
dataS(0),
|
||||
enabled(false),
|
||||
lastLatchData(false),
|
||||
timeCB(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Rtc::doLatch() {
|
||||
std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
|
||||
|
||||
while (tmp > 0x1FF * 86400) {
|
||||
baseTime += 0x1FF * 86400;
|
||||
tmp -= 0x1FF * 86400;
|
||||
dataDh |= 0x80;
|
||||
}
|
||||
|
||||
dataDl = (tmp / 86400) & 0xFF;
|
||||
dataDh &= 0xFE;
|
||||
dataDh |= ((tmp / 86400) & 0x100) >> 8;
|
||||
tmp %= 86400;
|
||||
|
||||
dataH = tmp / 3600;
|
||||
tmp %= 3600;
|
||||
|
||||
dataM = tmp / 60;
|
||||
tmp %= 60;
|
||||
|
||||
dataS = tmp;
|
||||
}
|
||||
|
||||
void Rtc::doSwapActive() {
|
||||
if (!enabled || index > 4) {
|
||||
activeData = NULL;
|
||||
activeSet = NULL;
|
||||
} else switch (index) {
|
||||
case 0x00:
|
||||
activeData = &dataS;
|
||||
activeSet = &Rtc::setS;
|
||||
break;
|
||||
case 0x01:
|
||||
activeData = &dataM;
|
||||
activeSet = &Rtc::setM;
|
||||
break;
|
||||
case 0x02:
|
||||
activeData = &dataH;
|
||||
activeSet = &Rtc::setH;
|
||||
break;
|
||||
case 0x03:
|
||||
activeData = &dataDl;
|
||||
activeSet = &Rtc::setDl;
|
||||
break;
|
||||
case 0x04:
|
||||
activeData = &dataDh;
|
||||
activeSet = &Rtc::setDh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Rtc::saveState(SaveState &state) const {
|
||||
state.rtc.baseTime = baseTime;
|
||||
state.rtc.haltTime = haltTime;
|
||||
state.rtc.dataDh = dataDh;
|
||||
state.rtc.dataDl = dataDl;
|
||||
state.rtc.dataH = dataH;
|
||||
state.rtc.dataM = dataM;
|
||||
state.rtc.dataS = dataS;
|
||||
state.rtc.lastLatchData = lastLatchData;
|
||||
}
|
||||
|
||||
void Rtc::loadState(const SaveState &state) {
|
||||
baseTime = state.rtc.baseTime;
|
||||
haltTime = state.rtc.haltTime;
|
||||
dataDh = state.rtc.dataDh;
|
||||
dataDl = state.rtc.dataDl;
|
||||
dataH = state.rtc.dataH;
|
||||
dataM = state.rtc.dataM;
|
||||
dataS = state.rtc.dataS;
|
||||
lastLatchData = state.rtc.lastLatchData;
|
||||
|
||||
doSwapActive();
|
||||
}
|
||||
|
||||
void Rtc::setDh(const unsigned new_dh) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
|
||||
baseTime += old_highdays * 86400;
|
||||
baseTime -= ((new_dh & 0x1) << 8) * 86400;
|
||||
|
||||
if ((dataDh ^ new_dh) & 0x40) {
|
||||
if (new_dh & 0x40)
|
||||
haltTime = timeCB();
|
||||
else
|
||||
baseTime += timeCB() - haltTime;
|
||||
}
|
||||
}
|
||||
|
||||
void Rtc::setDl(const unsigned new_lowdays) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF;
|
||||
baseTime += old_lowdays * 86400;
|
||||
baseTime -= new_lowdays * 86400;
|
||||
}
|
||||
|
||||
void Rtc::setH(const unsigned new_hours) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24;
|
||||
baseTime += old_hours * 3600;
|
||||
baseTime -= new_hours * 3600;
|
||||
}
|
||||
|
||||
void Rtc::setM(const unsigned new_minutes) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60;
|
||||
baseTime += old_minutes * 60;
|
||||
baseTime -= new_minutes * 60;
|
||||
}
|
||||
|
||||
void Rtc::setS(const unsigned new_seconds) {
|
||||
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
|
||||
baseTime += (unixtime - baseTime) % 60;
|
||||
baseTime -= new_seconds;
|
||||
}
|
||||
|
||||
void Rtc::SaveS(NewState *ns)
|
||||
{
|
||||
EBS(activeData, 0);
|
||||
EVS(activeData, &dataS, 1);
|
||||
EVS(activeData, &dataM, 2);
|
||||
EVS(activeData, &dataH, 3);
|
||||
EVS(activeData, &dataDl, 4);
|
||||
EVS(activeData, &dataDh, 5);
|
||||
EES(activeData, NULL);
|
||||
|
||||
EBS(activeSet, 0);
|
||||
EVS(activeSet, &Rtc::setS, 1);
|
||||
EVS(activeSet, &Rtc::setM, 2);
|
||||
EVS(activeSet, &Rtc::setH, 3);
|
||||
EVS(activeSet, &Rtc::setDl, 4);
|
||||
EVS(activeSet, &Rtc::setDh, 5);
|
||||
EES(activeSet, NULL);
|
||||
|
||||
NSS(baseTime);
|
||||
NSS(haltTime);
|
||||
NSS(index);
|
||||
NSS(dataDh);
|
||||
NSS(dataDl);
|
||||
NSS(dataH);
|
||||
NSS(dataM);
|
||||
NSS(dataS);
|
||||
NSS(enabled);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,96 +1,100 @@
|
|||
/***************************************************************************
|
||||
* 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 RTC_H
|
||||
#define RTC_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
|
||||
class Rtc {
|
||||
private:
|
||||
unsigned char *activeData;
|
||||
void (Rtc::*activeSet)(unsigned);
|
||||
std::uint32_t baseTime;
|
||||
std::uint32_t haltTime;
|
||||
unsigned char index;
|
||||
unsigned char dataDh;
|
||||
unsigned char dataDl;
|
||||
unsigned char dataH;
|
||||
unsigned char dataM;
|
||||
unsigned char dataS;
|
||||
bool enabled;
|
||||
bool lastLatchData;
|
||||
std::uint32_t (*timeCB)();
|
||||
|
||||
void doLatch();
|
||||
void doSwapActive();
|
||||
void setDh(unsigned new_dh);
|
||||
void setDl(unsigned new_lowdays);
|
||||
void setH(unsigned new_hours);
|
||||
void setM(unsigned new_minutes);
|
||||
void setS(unsigned new_seconds);
|
||||
|
||||
public:
|
||||
Rtc();
|
||||
|
||||
const unsigned char* getActive() const { return activeData; }
|
||||
std::uint32_t getBaseTime() const { return baseTime; }
|
||||
|
||||
void setBaseTime(const std::uint32_t baseTime) {
|
||||
this->baseTime = baseTime;
|
||||
// doLatch();
|
||||
}
|
||||
|
||||
void latch(const unsigned data) {
|
||||
if (!lastLatchData && data == 1)
|
||||
doLatch();
|
||||
|
||||
lastLatchData = data;
|
||||
}
|
||||
|
||||
void saveState(SaveState &state) const;
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void set(const bool enabled, unsigned bank) {
|
||||
bank &= 0xF;
|
||||
bank -= 8;
|
||||
|
||||
this->enabled = enabled;
|
||||
this->index = bank;
|
||||
|
||||
doSwapActive();
|
||||
}
|
||||
|
||||
void write(const unsigned data) {
|
||||
// if (activeSet)
|
||||
(this->*activeSet)(data);
|
||||
*activeData = data;
|
||||
}
|
||||
|
||||
void setRTCCallback(std::uint32_t (*callback)()) {
|
||||
timeCB = callback;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/***************************************************************************
|
||||
* 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 RTC_H
|
||||
#define RTC_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
|
||||
class Rtc {
|
||||
private:
|
||||
unsigned char *activeData;
|
||||
void (Rtc::*activeSet)(unsigned);
|
||||
std::uint32_t baseTime;
|
||||
std::uint32_t haltTime;
|
||||
unsigned char index;
|
||||
unsigned char dataDh;
|
||||
unsigned char dataDl;
|
||||
unsigned char dataH;
|
||||
unsigned char dataM;
|
||||
unsigned char dataS;
|
||||
bool enabled;
|
||||
bool lastLatchData;
|
||||
std::uint32_t (*timeCB)();
|
||||
|
||||
void doLatch();
|
||||
void doSwapActive();
|
||||
void setDh(unsigned new_dh);
|
||||
void setDl(unsigned new_lowdays);
|
||||
void setH(unsigned new_hours);
|
||||
void setM(unsigned new_minutes);
|
||||
void setS(unsigned new_seconds);
|
||||
|
||||
public:
|
||||
Rtc();
|
||||
|
||||
const unsigned char* getActive() const { return activeData; }
|
||||
std::uint32_t getBaseTime() const { return baseTime; }
|
||||
|
||||
void setBaseTime(const std::uint32_t baseTime) {
|
||||
this->baseTime = baseTime;
|
||||
// doLatch();
|
||||
}
|
||||
|
||||
void latch(const unsigned data) {
|
||||
if (!lastLatchData && data == 1)
|
||||
doLatch();
|
||||
|
||||
lastLatchData = data;
|
||||
}
|
||||
|
||||
void saveState(SaveState &state) const;
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void set(const bool enabled, unsigned bank) {
|
||||
bank &= 0xF;
|
||||
bank -= 8;
|
||||
|
||||
this->enabled = enabled;
|
||||
this->index = bank;
|
||||
|
||||
doSwapActive();
|
||||
}
|
||||
|
||||
void write(const unsigned data) {
|
||||
// if (activeSet)
|
||||
(this->*activeSet)(data);
|
||||
*activeData = data;
|
||||
}
|
||||
|
||||
void setRTCCallback(std::uint32_t (*callback)()) {
|
||||
timeCB = callback;
|
||||
}
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1104,4 +1104,53 @@ int Memory::LinkStatus(int which)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void Memory::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(cart);
|
||||
NSS(ioamhram);
|
||||
NSS(divLastUpdate);
|
||||
NSS(lastOamDmaUpdate);
|
||||
|
||||
SSS(intreq);
|
||||
SSS(tima);
|
||||
SSS(display);
|
||||
SSS(sound);
|
||||
//SSS(interrupter); // no state
|
||||
|
||||
NSS(dmaSource);
|
||||
NSS(dmaDestination);
|
||||
NSS(oamDmaPos);
|
||||
NSS(serialCnt);
|
||||
NSS(blanklcd);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "sound.h"
|
||||
#include "interrupter.h"
|
||||
#include "tima.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
class InputGetter;
|
||||
|
@ -194,6 +195,9 @@ public:
|
|||
void setCgbPalette(unsigned *lut);
|
||||
|
||||
int LinkStatus(int which);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define MINKEEPER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "newstate.h"
|
||||
|
||||
namespace MinKeeperUtil {
|
||||
template<int n> struct CeiledLog2 { enum { R = 1 + CeiledLog2<(n + 1) / 2>::R }; };
|
||||
|
@ -105,6 +106,20 @@ 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)
|
||||
{
|
||||
NSS(values);
|
||||
NSS(minValue_);
|
||||
NSS(a);
|
||||
}
|
||||
void LoadS(gambatte::NewState *ns)
|
||||
{
|
||||
NSL(values);
|
||||
NSL(minValue_);
|
||||
NSL(a);
|
||||
}
|
||||
};
|
||||
|
||||
template<int ids> typename MinKeeper<ids>::UpdateValueLut MinKeeper<ids>::updateValueLut;
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
#include "newstate.h"
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
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), maxlength(maxlength), length(0)
|
||||
{
|
||||
}
|
||||
|
||||
void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name)
|
||||
{
|
||||
const char *src = static_cast<const char *>(ptr);
|
||||
if (maxlength - length >= 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 >= size)
|
||||
{
|
||||
std::memcpy(dst, buffer + length, size);
|
||||
}
|
||||
length += size;
|
||||
}
|
||||
|
||||
NewStateExternalFunctions::NewStateExternalFunctions(
|
||||
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))
|
||||
:Save_(Save_),
|
||||
Load_(Load_),
|
||||
EnterSection_(EnterSection_),
|
||||
ExitSection_(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,100 @@
|
|||
#ifndef NEWSTATE_H
|
||||
#define NEWSTATE_H
|
||||
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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(
|
||||
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));
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
// 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 (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 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 { 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 PSS(x,s) ns->Save((x), (s), #x)
|
||||
#define PSL(x,s) ns->Load((x), (s), #x)
|
||||
|
||||
#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)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -179,4 +179,29 @@ unsigned PSG::getStatus() const {
|
|||
return ch1.isActive() | ch2.isActive() << 1 | ch3.isActive() << 2 | ch4.isActive() << 3;
|
||||
}
|
||||
|
||||
// the buffer and position are not saved, as they're set and flushed on each runfor() call
|
||||
void PSG::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(ch1);
|
||||
SSS(ch2);
|
||||
SSS(ch3);
|
||||
SSS(ch4);
|
||||
NSS(lastUpdate);
|
||||
NSS(soVol);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "sound/channel2.h"
|
||||
#include "sound/channel3.h"
|
||||
#include "sound/channel4.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -88,6 +89,9 @@ public:
|
|||
void set_so_volume(unsigned nr50);
|
||||
void map_so(unsigned nr51);
|
||||
unsigned getStatus() const;
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -104,6 +104,22 @@ void Channel1::SweepUnit::loadState(const SaveState &state) {
|
|||
negging = state.spu.ch1.sweep.negging;
|
||||
}
|
||||
|
||||
void Channel1::SweepUnit::SaveS(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),
|
||||
disableMaster(master, dutyUnit),
|
||||
|
@ -259,4 +275,48 @@ void Channel1::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
|
|||
}
|
||||
}
|
||||
|
||||
void Channel1::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(lengthCounter);
|
||||
SSS(dutyUnit);
|
||||
SSS(envelopeUnit);
|
||||
SSS(sweepUnit);
|
||||
|
||||
EBS(nextEventUnit, 0);
|
||||
EVS(nextEventUnit, &dutyUnit, 1);
|
||||
EVS(nextEventUnit, &sweepUnit, 2);
|
||||
EVS(nextEventUnit, &envelopeUnit, 3);
|
||||
EVS(nextEventUnit, &lengthCounter, 4);
|
||||
EES(nextEventUnit, NULL);
|
||||
|
||||
NSS(cycleCounter);
|
||||
NSS(soMask);
|
||||
NSS(prevOut);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "duty_unit.h"
|
||||
#include "envelope_unit.h"
|
||||
#include "static_output_tester.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -48,6 +49,9 @@ class Channel1 {
|
|||
void reset();
|
||||
void saveState(SaveState &state) const;
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
friend class StaticOutputTester<Channel1,DutyUnit>;
|
||||
|
@ -87,6 +91,9 @@ public:
|
|||
void init(bool cgb);
|
||||
void saveState(SaveState &state);
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -162,4 +162,45 @@ void Channel2::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
|
|||
}
|
||||
}
|
||||
|
||||
void Channel2::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(lengthCounter);
|
||||
SSS(dutyUnit);
|
||||
SSS(envelopeUnit);
|
||||
|
||||
EBS(nextEventUnit, 0);
|
||||
EVS(nextEventUnit, &dutyUnit, 1);
|
||||
EVS(nextEventUnit, &envelopeUnit, 2);
|
||||
EVS(nextEventUnit, &lengthCounter, 3);
|
||||
EES(nextEventUnit, NULL);
|
||||
|
||||
NSS(cycleCounter);
|
||||
NSS(soMask);
|
||||
NSS(prevOut);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "duty_unit.h"
|
||||
#include "envelope_unit.h"
|
||||
#include "static_output_tester.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -66,6 +67,9 @@ public:
|
|||
void init(bool cgb);
|
||||
void saveState(SaveState &state);
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -208,4 +208,50 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
|
|||
}
|
||||
}
|
||||
|
||||
void Channel3::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(waveRam);
|
||||
|
||||
SSS(lengthCounter);
|
||||
|
||||
NSS(cycleCounter);
|
||||
NSS(soMask);
|
||||
NSS(prevOut);
|
||||
NSS(waveCounter);
|
||||
NSS(lastReadTime);
|
||||
|
||||
NSS(nr0);
|
||||
NSS(nr3);
|
||||
NSS(nr4);
|
||||
NSS(wavePos);
|
||||
NSS(rShift);
|
||||
NSS(sampleBuf);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "gbint.h"
|
||||
#include "master_disabler.h"
|
||||
#include "length_counter.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -96,6 +97,9 @@ public:
|
|||
|
||||
waveRam[index] = data;
|
||||
}
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -163,6 +163,24 @@ void Channel4::Lfsr::loadState(const SaveState &state) {
|
|||
nr3 = state.mem.ioamhram.get()[0x122];
|
||||
}
|
||||
|
||||
void Channel4::Lfsr::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(counter);
|
||||
NSS(backupCounter);
|
||||
NSS(reg);
|
||||
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),
|
||||
disableMaster(master, lfsr),
|
||||
|
@ -300,5 +318,45 @@ void Channel4::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
|
|||
cycleCounter -= SoundUnit::COUNTER_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void Channel4::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(lengthCounter);
|
||||
SSS(envelopeUnit);
|
||||
SSS(lfsr);
|
||||
|
||||
EBS(nextEventUnit, 0);
|
||||
EVS(nextEventUnit, &lfsr, 1);
|
||||
EVS(nextEventUnit, &envelopeUnit, 2);
|
||||
EVS(nextEventUnit, &lengthCounter, 3);
|
||||
EES(nextEventUnit, NULL);
|
||||
|
||||
NSS(cycleCounter);
|
||||
NSS(soMask);
|
||||
NSS(prevOut);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "length_counter.h"
|
||||
#include "envelope_unit.h"
|
||||
#include "static_output_tester.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -51,6 +52,9 @@ class Channel4 {
|
|||
void disableMaster() { killCounter(); master = false; reg = 0x7FFF; }
|
||||
void killCounter() { counter = COUNTER_DISABLED; }
|
||||
void reviveCounter(unsigned long cc);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
class Ch4MasterDisabler : public MasterDisabler {
|
||||
|
@ -95,6 +99,9 @@ public:
|
|||
void init(bool cgb);
|
||||
void saveState(SaveState &state);
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -149,4 +149,27 @@ void DutyUnit::reviveCounter(const unsigned long cc) {
|
|||
setCounter();
|
||||
}
|
||||
|
||||
void DutyUnit::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(counter);
|
||||
NSS(nextPosUpdate);
|
||||
NSS(period);
|
||||
NSS(pos);
|
||||
NSS(duty);
|
||||
NSS(high);
|
||||
NSS(enableEvents);
|
||||
}
|
||||
|
||||
void DutyUnit::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(counter);
|
||||
NSL(nextPosUpdate);
|
||||
NSL(period);
|
||||
NSL(pos);
|
||||
NSL(duty);
|
||||
NSL(high);
|
||||
NSL(enableEvents);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "sound_unit.h"
|
||||
#include "master_disabler.h"
|
||||
#include "../savestate.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -54,6 +55,9 @@ public:
|
|||
//intended for use by SweepUnit only.
|
||||
unsigned getFreq() const { return 2048 - (period >> 1); }
|
||||
void setFreq(unsigned newFreq, unsigned long cc);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
class DutyMasterDisabler : public MasterDisabler {
|
||||
|
|
|
@ -103,4 +103,18 @@ void EnvelopeUnit::loadState(const SaveState::SPU::Env &estate, const unsigned n
|
|||
this->nr2 = nr2;
|
||||
}
|
||||
|
||||
void EnvelopeUnit::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(counter);
|
||||
NSS(nr2);
|
||||
NSS(volume);
|
||||
}
|
||||
|
||||
void EnvelopeUnit::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(counter);
|
||||
NSL(nr2);
|
||||
NSL(volume);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "sound_unit.h"
|
||||
#include "../savestate.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -47,6 +48,9 @@ public:
|
|||
void reset();
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -88,4 +88,18 @@ void LengthCounter::loadState(const SaveState::SPU::LCounter &lstate, const unsi
|
|||
lengthCounter = lstate.lengthCounter;
|
||||
}
|
||||
|
||||
void LengthCounter::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(counter);
|
||||
NSS(lengthCounter);
|
||||
NSS(cgb);
|
||||
}
|
||||
|
||||
void LengthCounter::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(counter);
|
||||
NSL(lengthCounter);
|
||||
NSL(cgb);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "sound_unit.h"
|
||||
#include "../savestate.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -41,6 +42,9 @@ public:
|
|||
void init(bool cgb);
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -168,4 +168,22 @@ void Tima::doIrqEvent(const TimaInterruptRequester timaIrq) {
|
|||
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3]));
|
||||
}
|
||||
|
||||
void Tima::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(lastUpdate_);
|
||||
NSS(tmatime_);
|
||||
NSS(tima_);
|
||||
NSS(tma_);
|
||||
NSS(tac_);
|
||||
}
|
||||
|
||||
void Tima::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(lastUpdate_);
|
||||
NSL(tmatime_);
|
||||
NSL(tima_);
|
||||
NSL(tma_);
|
||||
NSL(tac_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ public:
|
|||
unsigned tima(unsigned long cc);
|
||||
|
||||
void doIrqEvent(TimaInterruptRequester timaIrq);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,43 +37,9 @@ void LCD::setCgbPalette(unsigned *lut) {
|
|||
}
|
||||
|
||||
unsigned long LCD::gbcToRgb32(const unsigned bgr15) {
|
||||
/*
|
||||
const unsigned long r = bgr15 & 0x1F;
|
||||
const unsigned long g = bgr15 >> 5 & 0x1F;
|
||||
const unsigned long b = bgr15 >> 10 & 0x1F;
|
||||
|
||||
return ((r * 13 + g * 2 + b) >> 1) << 16 | (g * 3 + b) << 9 | (r * 3 + g * 2 + b * 11) >> 1;
|
||||
*/
|
||||
return cgbColorsRgb32[bgr15 & 0x7FFF];
|
||||
}
|
||||
|
||||
/*static unsigned long gbcToRgb16(const unsigned bgr15) {
|
||||
const unsigned r = bgr15 & 0x1F;
|
||||
const unsigned g = bgr15 >> 5 & 0x1F;
|
||||
const unsigned b = bgr15 >> 10 & 0x1F;
|
||||
|
||||
return (((r * 13 + g * 2 + b + 8) << 7) & 0xF800) | ((g * 3 + b + 1) >> 1) << 5 | ((r * 3 + g * 2 + b * 11 + 8) >> 4);
|
||||
}
|
||||
|
||||
static unsigned long gbcToUyvy(const unsigned bgr15) {
|
||||
const unsigned r5 = bgr15 & 0x1F;
|
||||
const unsigned g5 = bgr15 >> 5 & 0x1F;
|
||||
const unsigned b5 = bgr15 >> 10 & 0x1F;
|
||||
|
||||
// y = (r5 * 926151 + g5 * 1723530 + b5 * 854319) / 510000 + 16;
|
||||
// u = (b5 * 397544 - r5 * 68824 - g5 * 328720) / 225930 + 128;
|
||||
// v = (r5 * 491176 - g5 * 328720 - b5 * 162456) / 178755 + 128;
|
||||
|
||||
const unsigned long y = (r5 * 116 + g5 * 216 + b5 * 107 + 16 * 64 + 32) >> 6;
|
||||
const unsigned long u = (b5 * 225 - r5 * 39 - g5 * 186 + 128 * 128 + 64) >> 7;
|
||||
const unsigned long v = (r5 * 176 - g5 * 118 - b5 * 58 + 128 * 64 + 32) >> 6;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return u << 24 | y << 16 | v << 8 | y;
|
||||
#else
|
||||
return y << 24 | v << 16 | y << 8 | u;
|
||||
#endif
|
||||
}*/
|
||||
|
||||
LCD::LCD(const unsigned char *const oamram, const unsigned char *const vram, const VideoInterruptRequester memEventRequester) :
|
||||
ppu(nextM0Time_, oamram, vram),
|
||||
|
@ -196,32 +162,6 @@ void LCD::refreshPalettes() {
|
|||
|
||||
namespace {
|
||||
|
||||
template<class Blend>
|
||||
static void blitOsdElement(uint_least32_t *d,
|
||||
const uint_least32_t *s, const unsigned width, unsigned h, const int dpitch, Blend blend)
|
||||
{
|
||||
while (h--) {
|
||||
for (unsigned w = width; w--;) {
|
||||
if (*s != 0xFFFFFFFF)
|
||||
*d = blend(*s, *d);
|
||||
|
||||
++d;
|
||||
++s;
|
||||
}
|
||||
|
||||
d += dpitch - static_cast<int>(width);
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned weight>
|
||||
struct Blend {
|
||||
enum { SW = weight - 1 };
|
||||
enum { LOWMASK = SW * 0x010101ul };
|
||||
uint_least32_t operator()(const uint_least32_t s, const uint_least32_t d) const {
|
||||
return (s * SW + d - (((s & LOWMASK) * SW + (d & LOWMASK)) & LOWMASK)) / weight;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void clear(T *buf, const unsigned long color, const int dpitch) {
|
||||
unsigned lines = 144;
|
||||
|
@ -802,4 +742,36 @@ void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, con
|
|||
refreshPalettes();
|
||||
}
|
||||
|
||||
// don't need to save or load rgb32 color data
|
||||
|
||||
void LCD::SaveS(NewState *ns)
|
||||
{
|
||||
SSS(ppu);
|
||||
NSS(bgpData);
|
||||
NSS(objpData);
|
||||
SSS(eventTimes_);
|
||||
SSS(m0Irq_);
|
||||
SSS(lycIrq);
|
||||
SSS(nextM0Time_);
|
||||
|
||||
NSS(statReg);
|
||||
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_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "interruptrequester.h"
|
||||
#include "minkeeper.h"
|
||||
#include <memory>
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
|
@ -80,6 +81,17 @@ public:
|
|||
}
|
||||
|
||||
unsigned statReg() const { return statReg_; }
|
||||
|
||||
void SaveS(NewState *ns)
|
||||
{
|
||||
NSS(statReg_);
|
||||
NSS(lycReg_);
|
||||
}
|
||||
void LoadS(NewState *ns)
|
||||
{
|
||||
NSL(statReg_);
|
||||
NSL(lycReg_);
|
||||
}
|
||||
};
|
||||
|
||||
class LCD {
|
||||
|
@ -115,6 +127,19 @@ class LCD {
|
|||
|
||||
void flagIrq(const unsigned bit) { memEventRequester_.flagIrq(bit); }
|
||||
void flagHdmaReq() { memEventRequester_.flagHdmaReq(); }
|
||||
|
||||
void SaveS(NewState *ns)
|
||||
{
|
||||
SSS(eventMin_);
|
||||
SSS(memEventMin_);
|
||||
//SSS(memEventRequester_); // not needed
|
||||
}
|
||||
void LoadS(NewState *ns)
|
||||
{
|
||||
SSL(eventMin_);
|
||||
SSL(memEventMin_);
|
||||
//SSL(memEventRequester_); // not needed
|
||||
}
|
||||
};
|
||||
|
||||
PPU ppu;
|
||||
|
@ -258,6 +283,9 @@ public:
|
|||
unsigned long *spPalette() { return ppu.spPalette(); }
|
||||
|
||||
void setScanlineCallback(void (*callback)(), int sl) { scanlinecallback = callback; scanlinecallbacksl = sl; }
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -64,5 +64,21 @@ void LyCounter::setDoubleSpeed(const bool ds_in) {
|
|||
ds = ds_in;
|
||||
lineTime_ = 456U << ds_in;
|
||||
}
|
||||
|
||||
void LyCounter::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(time_);
|
||||
NSS(lineTime_);
|
||||
NSS(ly_);
|
||||
NSS(ds);
|
||||
}
|
||||
|
||||
void LyCounter::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(time_);
|
||||
NSL(lineTime_);
|
||||
NSL(ly_);
|
||||
NSL(ds);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef LY_COUNTER_H
|
||||
#define LY_COUNTER_H
|
||||
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
|
@ -49,6 +51,9 @@ public:
|
|||
void reset(unsigned long videoCycles, unsigned long lastUpdate);
|
||||
void setDoubleSpeed(bool ds_in);
|
||||
unsigned long time() const { return time_; }
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -99,4 +99,24 @@ void LycIrq::lcdReset() {
|
|||
lycReg_ = lycRegSrc_;
|
||||
}
|
||||
|
||||
void LycIrq::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(time_);
|
||||
NSS(lycRegSrc_);
|
||||
NSS(statRegSrc_);
|
||||
NSS(lycReg_);
|
||||
NSS(statReg_);
|
||||
NSS(cgb_);
|
||||
}
|
||||
|
||||
void LycIrq::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(time_);
|
||||
NSL(lycRegSrc_);
|
||||
NSL(statRegSrc_);
|
||||
NSL(lycReg_);
|
||||
NSL(statReg_);
|
||||
NSL(cgb_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef VIDEO_LYC_IRQ_H
|
||||
#define VIDEO_LYC_IRQ_H
|
||||
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
|
@ -52,6 +54,9 @@ public:
|
|||
void lycRegChange(unsigned lycReg, const LyCounter &lyCounter, unsigned long cc) {
|
||||
regChange(statRegSrc_, lycReg, lyCounter, cc);
|
||||
}
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
#include "next_m0_time.h"
|
||||
#include "ppu.h"
|
||||
|
||||
void gambatte::NextM0Time::predictNextM0Time(const PPU &ppu) {
|
||||
namespace gambatte {
|
||||
|
||||
void NextM0Time::predictNextM0Time(const PPU &ppu) {
|
||||
predictedNextM0Time_ = ppu.predictedNextXposTime(167);
|
||||
}
|
||||
|
||||
|
||||
void NextM0Time::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(predictedNextM0Time_);
|
||||
}
|
||||
|
||||
void NextM0Time::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(predictedNextM0Time_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef NEXT_M0_TIME_H_
|
||||
#define NEXT_M0_TIME_H_
|
||||
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class NextM0Time {
|
||||
|
@ -11,6 +13,9 @@ public:
|
|||
void predictNextM0Time(const class PPU &v);
|
||||
void invalidatePredictedNextM0Time() { predictedNextM0Time_ = 0; }
|
||||
unsigned predictedNextM0Time() const { return predictedNextM0Time_; }
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1745,4 +1745,136 @@ void PPU::update(const unsigned long cc) {
|
|||
}
|
||||
}
|
||||
|
||||
void PPU::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(p_.bgPalette);
|
||||
NSS(p_.spPalette);
|
||||
NSS(p_.spriteList);
|
||||
NSS(p_.spwordList);
|
||||
NSS(p_.nextSprite);
|
||||
NSS(p_.currentSprite);
|
||||
|
||||
EBS(p_.nextCallPtr, 0);
|
||||
EVS(p_.nextCallPtr, &M2::Ly0::f0_, 1);
|
||||
EVS(p_.nextCallPtr, &M2::LyNon0::f0_, 2);
|
||||
EVS(p_.nextCallPtr, &M2::LyNon0::f1_, 3);
|
||||
EVS(p_.nextCallPtr, &M3Start::f0_, 4);
|
||||
EVS(p_.nextCallPtr, &M3Start::f1_, 5);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f0_, 6);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f1_, 7);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f2_, 8);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f3_, 9);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f4_, 10);
|
||||
EVS(p_.nextCallPtr, &M3Loop::Tile::f5_, 11);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f0_, 12);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f1_, 13);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f2_, 14);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f3_, 15);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f4_, 16);
|
||||
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f5_, 17);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f0_, 18);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f1_, 19);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f2_, 20);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f3_, 21);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f4_, 22);
|
||||
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f5_, 23);
|
||||
EES(p_.nextCallPtr, NULL);
|
||||
|
||||
NSS(p_.now);
|
||||
NSS(p_.lastM0Time);
|
||||
NSS(p_.cycles);
|
||||
|
||||
NSS(p_.tileword);
|
||||
NSS(p_.ntileword);
|
||||
|
||||
SSS(p_.spriteMapper);
|
||||
SSS(p_.lyCounter);
|
||||
//SSS(p_.framebuf); // no state
|
||||
|
||||
NSS(p_.lcdc);
|
||||
NSS(p_.scy);
|
||||
NSS(p_.scx);
|
||||
NSS(p_.wy);
|
||||
NSS(p_.wy2);
|
||||
NSS(p_.wx);
|
||||
NSS(p_.winDrawState);
|
||||
NSS(p_.wscx);
|
||||
NSS(p_.winYPos);
|
||||
NSS(p_.reg0);
|
||||
NSS(p_.reg1);
|
||||
NSS(p_.attrib);
|
||||
NSS(p_.nattrib);
|
||||
NSS(p_.xpos);
|
||||
NSS(p_.endx);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "video/sprite_mapper.h"
|
||||
#include "gbint.h"
|
||||
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class PPUFrameBuf {
|
||||
|
@ -128,6 +130,9 @@ public:
|
|||
void speedChange(unsigned long cycleCounter);
|
||||
unsigned long * spPalette() { return p_.spPalette; }
|
||||
void update(unsigned long cc);
|
||||
|
||||
void SaveS(NewState *ns);
|
||||
void LoadS(NewState *ns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -117,6 +117,28 @@ void SpriteMapper::OamReader::loadState(const SaveState &ss, const unsigned char
|
|||
change(lu);
|
||||
}
|
||||
|
||||
void SpriteMapper::OamReader::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(buf);
|
||||
NSS(szbuf);
|
||||
|
||||
NSS(lu);
|
||||
NSS(lastChange);
|
||||
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));
|
||||
std::fill(szbuf, szbuf + 40, false);
|
||||
|
@ -179,4 +201,22 @@ unsigned long SpriteMapper::doEvent(const unsigned long time) {
|
|||
return oamReader.changed() ? time + oamReader.lyCounter.lineTime() : static_cast<unsigned long>(DISABLED_TIME);
|
||||
}
|
||||
|
||||
void SpriteMapper::SaveS(NewState *ns)
|
||||
{
|
||||
NSS(spritemap);
|
||||
NSS(num);
|
||||
|
||||
SSS(nextM0Time_);
|
||||
SSS(oamReader);
|
||||
}
|
||||
|
||||
void SpriteMapper::LoadS(NewState *ns)
|
||||
{
|
||||
NSL(spritemap);
|
||||
NSL(num);
|
||||
|
||||
SSL(nextM0Time_);
|
||||
SSL(oamReader);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "ly_counter.h"
|
||||
#include "../savestate.h"
|
||||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
class NextM0Time;
|
||||
|
@ -57,6 +58,9 @@ class SpriteMapper {
|
|||
void saveState(SaveState &state) const { state.ppu.enableDisplayM0Time = lu; }
|
||||
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);
|
||||
};
|
||||
|
||||
enum { NEED_SORTING_MASK = 0x80 };
|
||||
|
@ -122,6 +126,9 @@ public:
|
|||
void saveState(SaveState &state) const { oamReader.saveState(state); }
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue