functioning saveram support for gambatte

This commit is contained in:
goyuken 2012-09-10 23:40:53 +00:00
parent efbe114e76
commit 4e35cb566f
12 changed files with 143 additions and 56 deletions

View File

@ -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()

View File

@ -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

View File

@ -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 { }
}

View File

@ -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().

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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) {