functioning saveram support for gambatte
This commit is contained in:
parent
efbe114e76
commit
4e35cb566f
|
@ -128,13 +128,39 @@ namespace BizHawk.Emulation.Consoles.GB
|
|||
|
||||
public byte[] ReadSaveRam
|
||||
{
|
||||
get { return new byte[0]; }
|
||||
get
|
||||
{
|
||||
int length = LibGambatte.gambatte_savesavedatalength(GambatteState);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
byte[] ret = new byte[length];
|
||||
LibGambatte.gambatte_savesavedata(GambatteState, ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (data.Length != LibGambatte.gambatte_savesavedatalength(GambatteState))
|
||||
throw new ArgumentException("Size of saveram data does not match expected!");
|
||||
LibGambatte.gambatte_loadsavedata(GambatteState, data);
|
||||
}
|
||||
|
||||
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get
|
||||
{
|
||||
if (LibGambatte.gambatte_savesavedatalength(GambatteState) == 0)
|
||||
return false;
|
||||
else
|
||||
return true; // need to wire more stuff into the core to actually know this
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public void ResetFrameCounter()
|
||||
|
|
|
@ -155,11 +155,28 @@ namespace BizHawk.Emulation.Consoles.GB
|
|||
public static extern bool gambatte_isloaded(IntPtr core);
|
||||
|
||||
/// <summary>
|
||||
/// Writes persistent cartridge data to disk. Done implicitly on ROM close.
|
||||
/// Get persistant cart memory.
|
||||
/// </summary>
|
||||
/// <param name="core">opaque state pointer</param>
|
||||
/// <param name="dest">byte buffer to write into. gambatte_savesavedatalength() bytes will be written</param>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_savesavedata(IntPtr core);
|
||||
public static extern void gambatte_savesavedata(IntPtr core, byte[] dest);
|
||||
|
||||
/// <summary>
|
||||
/// restore persistant cart memory.
|
||||
/// </summary>
|
||||
/// <param name="core">opaque state pointer</param>
|
||||
/// <param name="data">byte buffer to read from. gambatte_savesavedatalength() bytes will be read</param>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gambatte_loadsavedata(IntPtr core, byte[] data);
|
||||
|
||||
/// <summary>
|
||||
/// get the size of the persistant cart memory block. this value DEPENDS ON THE PARTICULAR CART LOADED
|
||||
/// </summary>
|
||||
/// <param name="core">opaque state pointer</param>
|
||||
/// <returns>length in bytes. 0 means no internal persistant cart memory</returns>
|
||||
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int gambatte_savesavedatalength(IntPtr core);
|
||||
|
||||
/// <summary>
|
||||
/// Saves emulator state to the state to a byte array
|
||||
|
|
|
@ -1560,7 +1560,10 @@ namespace BizHawk.MultiClient
|
|||
reader.Read(sram, 0, Global.Emulator.ReadSaveRam.Length);
|
||||
if (Global.Emulator is LibsnesCore)
|
||||
((LibsnesCore)Global.Emulator).StoreSaveRam(sram);
|
||||
else Array.Copy(sram, Global.Emulator.ReadSaveRam, Global.Emulator.ReadSaveRam.Length);
|
||||
else if (Global.Emulator is Gameboy)
|
||||
((Gameboy)Global.Emulator).StoreSaveRam(sram);
|
||||
else
|
||||
Array.Copy(sram, Global.Emulator.ReadSaveRam, Global.Emulator.ReadSaveRam.Length);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -92,8 +92,10 @@ public:
|
|||
/** Returns true if a ROM image is loaded. */
|
||||
bool isLoaded() const;
|
||||
|
||||
/** Writes persistent cartridge data to disk. Done implicitly on ROM close. */
|
||||
void saveSavedata();
|
||||
/** Writes persistent cartridge data to disk. NOT Done implicitly on ROM close. */
|
||||
void loadSavedata(const char *data);
|
||||
int saveSavedataLength();
|
||||
void saveSavedata(char *dest);
|
||||
|
||||
/** Saves emulator state to the state slot selected with selectState().
|
||||
* The data will be stored in the directory given by setSaveDir().
|
||||
|
|
|
@ -83,11 +83,31 @@ __declspec(dllexport) int gambatte_isloaded(void *core)
|
|||
return g->isLoaded();
|
||||
}
|
||||
|
||||
/*
|
||||
__declspec(dllexport) void gambatte_savesavedata(void *core)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
g->saveSavedata();
|
||||
}
|
||||
*/
|
||||
|
||||
__declspec(dllexport) void gambatte_savesavedata(void *core, char *dest)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
g->saveSavedata(dest);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void gambatte_loadsavedata(void *core, const char *data)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
g->loadSavedata(data);
|
||||
}
|
||||
|
||||
__declspec(dllexport) int gambatte_savesavedatalength(void *core)
|
||||
{
|
||||
GB *g = (GB *) core;
|
||||
return g->saveSavedataLength();
|
||||
}
|
||||
|
||||
/*
|
||||
__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch)
|
||||
|
|
|
@ -24,7 +24,9 @@ extern "C"
|
|||
|
||||
__declspec(dllexport) int gambatte_isloaded(void *core);
|
||||
|
||||
__declspec(dllexport) void gambatte_savesavedata(void *core);
|
||||
__declspec(dllexport) void gambatte_savesavedata(void *core, char *dest);
|
||||
__declspec(dllexport) void gambatte_loadsavedata(void *core, const char *data);
|
||||
__declspec(dllexport) int gambatte_savesavedatalength(void *core);
|
||||
|
||||
//__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch);
|
||||
|
||||
|
|
|
@ -51,8 +51,9 @@ public:
|
|||
void saveState(SaveState &state);
|
||||
void loadState(const SaveState &state);
|
||||
|
||||
void loadSavedata() { memory.loadSavedata(); }
|
||||
void saveSavedata() { memory.saveSavedata(); }
|
||||
void loadSavedata(const char *data) { memory.loadSavedata(data); }
|
||||
int saveSavedataLength() {return memory.saveSavedataLength(); }
|
||||
void saveSavedata(char *dest) { memory.saveSavedata(dest); }
|
||||
|
||||
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
|
||||
memory.setVideoBuffer(videoBuf, pitch);
|
||||
|
|
|
@ -47,8 +47,8 @@ struct GB::Priv {
|
|||
GB::GB() : p_(new Priv) {}
|
||||
|
||||
GB::~GB() {
|
||||
if (p_->cpu.loaded())
|
||||
p_->cpu.saveSavedata();
|
||||
//if (p_->cpu.loaded())
|
||||
// p_->cpu.saveSavedata();
|
||||
|
||||
delete p_;
|
||||
}
|
||||
|
@ -70,13 +70,24 @@ long GB::runFor(gambatte::uint_least32_t *const videoBuf, const int pitch,
|
|||
|
||||
void GB::reset() {
|
||||
if (p_->cpu.loaded()) {
|
||||
p_->cpu.saveSavedata();
|
||||
|
||||
int length = p_->cpu.saveSavedataLength();
|
||||
char *s;
|
||||
if (length > 0)
|
||||
{
|
||||
s = (char *) std::malloc(length);
|
||||
p_->cpu.saveSavedata(s);
|
||||
}
|
||||
|
||||
SaveState state;
|
||||
p_->cpu.setStatePtrs(state);
|
||||
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode);
|
||||
p_->cpu.loadState(state);
|
||||
p_->cpu.loadSavedata();
|
||||
if (length > 0)
|
||||
{
|
||||
p_->cpu.loadSavedata(s);
|
||||
std::free(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,8 +100,8 @@ void GB::setSaveDir(const std::string &sdir) {
|
|||
}
|
||||
|
||||
int GB::load(const char *romfiledata, unsigned romfilelength, const unsigned flags) {
|
||||
if (p_->cpu.loaded())
|
||||
p_->cpu.saveSavedata();
|
||||
//if (p_->cpu.loaded())
|
||||
// p_->cpu.saveSavedata();
|
||||
|
||||
const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
|
||||
|
||||
|
@ -99,7 +110,7 @@ int GB::load(const char *romfiledata, unsigned romfilelength, const unsigned fla
|
|||
p_->cpu.setStatePtrs(state);
|
||||
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode = flags & GBA_CGB);
|
||||
p_->cpu.loadState(state);
|
||||
p_->cpu.loadSavedata();
|
||||
//p_->cpu.loadSavedata();
|
||||
|
||||
p_->stateNo = 1;
|
||||
p_->cpu.setOsdElement(std::auto_ptr<OsdElement>());
|
||||
|
@ -116,9 +127,19 @@ bool GB::isLoaded() const {
|
|||
return p_->cpu.loaded();
|
||||
}
|
||||
|
||||
void GB::saveSavedata() {
|
||||
void GB::saveSavedata(char *dest) {
|
||||
if (p_->cpu.loaded())
|
||||
p_->cpu.saveSavedata();
|
||||
p_->cpu.saveSavedata(dest);
|
||||
}
|
||||
void GB::loadSavedata(const char *data) {
|
||||
if (p_->cpu.loaded())
|
||||
p_->cpu.loadSavedata(data);
|
||||
}
|
||||
int GB::saveSavedataLength() {
|
||||
if (p_->cpu.loaded())
|
||||
return p_->cpu.saveSavedataLength();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
|
||||
|
@ -127,7 +148,7 @@ void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32)
|
|||
|
||||
bool GB::loadState(std::istream &file) {
|
||||
if (p_->cpu.loaded()) {
|
||||
p_->cpu.saveSavedata();
|
||||
// p_->cpu.saveSavedata();
|
||||
|
||||
SaveState state;
|
||||
p_->cpu.setStatePtrs(state);
|
||||
|
|
|
@ -655,49 +655,42 @@ static bool hasBattery(const unsigned char headerByte0x147) {
|
|||
}
|
||||
}
|
||||
|
||||
void Cartridge::loadSavedata() {
|
||||
const std::string &sbp = saveBasePath();
|
||||
|
||||
void Cartridge::loadSavedata(const char *data) {
|
||||
if (hasBattery(memptrs.romdata()[0x147])) {
|
||||
std::ifstream file((sbp + ".sav").c_str(), std::ios::binary | std::ios::in);
|
||||
|
||||
if (file.is_open()) {
|
||||
file.read(reinterpret_cast<char*>(memptrs.rambankdata()), memptrs.rambankdataend() - memptrs.rambankdata());
|
||||
enforce8bit(memptrs.rambankdata(), memptrs.rambankdataend() - memptrs.rambankdata());
|
||||
}
|
||||
int length = memptrs.rambankdataend() - memptrs.rambankdata();
|
||||
std::memcpy(memptrs.rambankdata(), data, length);
|
||||
data += length;
|
||||
enforce8bit(memptrs.rambankdata(), length);
|
||||
}
|
||||
|
||||
if (hasRtc(memptrs.romdata()[0x147])) {
|
||||
std::ifstream file((sbp + ".rtc").c_str(), std::ios::binary | std::ios::in);
|
||||
|
||||
if (file.is_open()) {
|
||||
unsigned long basetime = file.get() & 0xFF;
|
||||
|
||||
basetime = basetime << 8 | (file.get() & 0xFF);
|
||||
basetime = basetime << 8 | (file.get() & 0xFF);
|
||||
basetime = basetime << 8 | (file.get() & 0xFF);
|
||||
|
||||
rtc.setBaseTime(basetime);
|
||||
}
|
||||
unsigned long basetime;
|
||||
std::memcpy(&basetime, data, 4);
|
||||
rtc.setBaseTime(basetime);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::saveSavedata() {
|
||||
const std::string &sbp = saveBasePath();
|
||||
|
||||
int Cartridge::saveSavedataLength() {
|
||||
int ret = 0;
|
||||
if (hasBattery(memptrs.romdata()[0x147])) {
|
||||
std::ofstream file((sbp + ".sav").c_str(), std::ios::binary | std::ios::out);
|
||||
file.write(reinterpret_cast<const char*>(memptrs.rambankdata()), memptrs.rambankdataend() - memptrs.rambankdata());
|
||||
ret = memptrs.rambankdataend() - memptrs.rambankdata();
|
||||
}
|
||||
if (hasRtc(memptrs.romdata()[0x147])) {
|
||||
ret += 4;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Cartridge::saveSavedata(char *dest) {
|
||||
if (hasBattery(memptrs.romdata()[0x147])) {
|
||||
int length = memptrs.rambankdataend() - memptrs.rambankdata();
|
||||
std::memcpy(dest, memptrs.rambankdata(), length);
|
||||
dest += length;
|
||||
}
|
||||
|
||||
if (hasRtc(memptrs.romdata()[0x147])) {
|
||||
std::ofstream file((sbp + ".rtc").c_str(), std::ios::binary | std::ios::out);
|
||||
const unsigned long basetime = rtc.getBaseTime();
|
||||
|
||||
file.put(basetime >> 24 & 0xFF);
|
||||
file.put(basetime >> 16 & 0xFF);
|
||||
file.put(basetime >> 8 & 0xFF);
|
||||
file.put(basetime & 0xFF);
|
||||
std::memcpy(dest, &basetime, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,8 +82,9 @@ public:
|
|||
void rtcWrite(unsigned data) { rtc.write(data); }
|
||||
unsigned char rtcRead() const { return *rtc.getActive(); }
|
||||
|
||||
void loadSavedata();
|
||||
void saveSavedata();
|
||||
void loadSavedata(const char *data);
|
||||
int saveSavedataLength();
|
||||
void saveSavedata(char *dest);
|
||||
const std::string saveBasePath() const;
|
||||
void setSaveDir(const std::string &dir);
|
||||
int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
|
||||
|
|
|
@ -78,8 +78,9 @@ public:
|
|||
void setStatePtrs(SaveState &state);
|
||||
unsigned long saveState(SaveState &state, unsigned long cc);
|
||||
void loadState(const SaveState &state/*, unsigned long oldCc*/);
|
||||
void loadSavedata() { cart.loadSavedata(); }
|
||||
void saveSavedata() { cart.saveSavedata(); }
|
||||
void loadSavedata(const char *data) { cart.loadSavedata(data); }
|
||||
int saveSavedataLength() {return cart.saveSavedataLength(); }
|
||||
void saveSavedata(char *dest) { cart.saveSavedata(dest); }
|
||||
const std::string saveBasePath() const { return cart.saveBasePath(); }
|
||||
|
||||
void setOsdElement(std::auto_ptr<OsdElement> osdElement) {
|
||||
|
|
Loading…
Reference in New Issue