From 4e35cb566fc83c0ae60ad0dc534989e66ec2f4f3 Mon Sep 17 00:00:00 2001 From: goyuken Date: Mon, 10 Sep 2012 23:40:53 +0000 Subject: [PATCH] functioning saveram support for gambatte --- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 32 +++++++++- .../Consoles/Nintendo/Gameboy/LibGambatte.cs | 21 ++++++- BizHawk.MultiClient/MainForm.cs | 5 +- BizHawk.MultiClient/output/libgambatte.dll | Bin 182272 -> 171520 bytes libgambatte/include/gambatte.h | 6 +- libgambatte/src/cinterface.cpp | 20 +++++++ libgambatte/src/cinterface.h | 4 +- libgambatte/src/cpu.h | 5 +- libgambatte/src/gambatte.cpp | 41 +++++++++---- libgambatte/src/mem/cartridge.cpp | 55 ++++++++---------- libgambatte/src/mem/cartridge.h | 5 +- libgambatte/src/memory.h | 5 +- 12 files changed, 143 insertions(+), 56 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs index e0b894e333..db24d2f677 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -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() diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs index 8414b2a9bb..d184ed78f2 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -155,11 +155,28 @@ namespace BizHawk.Emulation.Consoles.GB public static extern bool gambatte_isloaded(IntPtr core); /// - /// Writes persistent cartridge data to disk. Done implicitly on ROM close. + /// Get persistant cart memory. /// /// opaque state pointer + /// byte buffer to write into. gambatte_savesavedatalength() bytes will be written [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void gambatte_savesavedata(IntPtr core); + public static extern void gambatte_savesavedata(IntPtr core, byte[] dest); + + /// + /// restore persistant cart memory. + /// + /// opaque state pointer + /// byte buffer to read from. gambatte_savesavedatalength() bytes will be read + [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void gambatte_loadsavedata(IntPtr core, byte[] data); + + /// + /// get the size of the persistant cart memory block. this value DEPENDS ON THE PARTICULAR CART LOADED + /// + /// opaque state pointer + /// length in bytes. 0 means no internal persistant cart memory + [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int gambatte_savesavedatalength(IntPtr core); /// /// Saves emulator state to the state to a byte array diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index 4cf252994f..5d437d898e 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -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 { } } diff --git a/BizHawk.MultiClient/output/libgambatte.dll b/BizHawk.MultiClient/output/libgambatte.dll index ad71e22badca9eddf3474ae733d0ffab76452a7d..08d529cca3504f81964abd163dec48d005811e0d 100644 GIT binary patch delta 41876 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%0DAXDZ3qjBgqnU`h0s^>~a)22E z(+{*E?~4UM*n_kOPwE9>EWC=n2Frq4B<@^mNVLXvb$v$uFGmceEHZeT<9p3tf{Q;=inrmVPdL zVqTx{LV7wG!SO;`Bk7PLdKyXR7tv#W)@gQeR(3(rqI_qk{j5`Bo|{eJcGR^_K_9i{uq@vwVZ{ztj@- zEp4ZMS~rZF%ye^wxjJA5%|Ds@%@@r9)=*2fW?I?SQfs&MvUS`#Z;iCCwIw^>-i9wo zr+nCZND`PEm}cgEri=N48Nd!@6S()nc_;ZC1N=!s@U(tuCwEI%D-%XEEqri?XBaXgkLC z+Oc+=J<|5s@pgh8Ok7PDcuE^~uBLD77q~}K)R}6wx=#J0x=%f>eyk4AVzlctQ%lxn zYV);R?NRMz?U;5(o1j~Il0H}8pzqN4>ihL^hGslsykU$s-!XHnW$672Yn0t=U$Cii zoES06*~|)NHB-s_omt4PW{1xD~ZIyn48#UwuNnF&v8F+ z!Nd|e&PxWhT3#nporp0&6~uSO7X^aiE^(%uE#IkZQ}!w!VXo4RSToKXY5L3#^CR93dta@j;rSyxkKFTLX*%evnuHIIE%-mpT**v= zWk_WfF%L42Gfm7p%r^|f-onm@Zf#)?vPWPkdf2n+&dN zwsM!UQdzH5DMyqyFp+WUNOhbhXfw2>+P#`;CYv+OJFEw-lh$SSUc13QZg-H8dp&{B zCb*P|W5$Kd+G1uKvxj+wIfa4K?6d51>^U}?yOz6=E8_NY?{VM3#0})f@gjeZutnG_ zd@adxfm|dP%d6xPtZ=DZCYQ?<^7HbO%6{bq45mZ*MCny1HA;@EV+e*~7{(N1ma)Xx zYCLW{XS`~>hy8F(027mI{vOM{9?SiRxx=h6|7N~qwwcGU;HOO58flGzrJZBV!}L97 zJz@P5M&y(gWnW@nZjZ39hSg>4OgqQkVgJG2W4~{IWK(_*m4egeaAp(}A5w^0m~`e2 zW+AhL*~RR}c6*okkhzK-%ihig=0Z10*!$Uy*zk|Cd$8#{*nhFZxGTBQ+#GHmc0DoI zhq-3%Rj!?Thx?HGlpDeO_%v9j41PQR2mT-Y3I094m#2ka2}6V{gwaBRkS^Sbiq;%)FhIpQ|4N^BF41;l@1cV8*p8nR=>(i&;4v`N}3?UZ&) z?b1oJ#eI>VCCFeFMuGIIVuAey0x7hG@gJ z>orbOwVSo++AM7`H1{5Dqqarcu05sg)1K3gYHw-pz{Y>AUC=JoWA!Wb3A&)``Yn2z zK1W}oFVk1)4`c0j>VMG>=+EnI`rFWfFZJ{KPx=sJxZyKyG$g}>L6~J^Lf=*z_ZnLR z#t!2#<5}aNam4tCanks}_}aK&cwiE)G{=}CjKXio)-e~r0k46M1kGLM9yY)L^_ulAT;FNyN2@>F z-PQIudxCA-ftz5DGwp@;61&8Hz}{rT9U%n_!Ad4u_Y>4wXv*@3JVYIYsVvPtaC z>~wYkyO>?du7kF1VRy4nvHJqB)koR4*e>=o`xP6-4dRAy@!a(s$4%x^xEWjycQlP?w4u3aa#6Q4q;veB__`mQ6 z_!bzn<9s*&1%Hl@7A}V;O%QGrBq3S2RhTIRa)o^C@lxSoVVm%zP$x79uL^C@+E0WY zL`(xkuXu%coydv`BB$wyo$|y&ai#c>SRp7fkxmnbHN8NrNY7BG3tN@guWyH@5T zOvyFu1Xg92!N)wvzQn!`|2>qu3Pw8{i+2yVpL-s*BZeQrkL7RVSMeM8t*{zr_zQeL z;qrixA>54xC=*`Cqxq(aZD`dZ&IyR}4Q~ccoEn)Eegv%8Wq-oN4A^<29MB zW}M}-60KsZ#41DR`yQgn3s$r}*q&+MY3JE1?NWQQ{WeVTXZATVdj%e1ktv1oGbwOy zyO>($Aa=={OdRVAu!#tJ*05y=;%nGv;Fu{chMURV$>nh?xl(R3_cr%Fbp0Hs@P0l8 zF>^Iv%OlJcVqj!5g*@Saa2PSjNugW#Qcz%GQ(#(miM0sJTEsWSILRj^{^Go)%b9YX z9B7oAU{2!{pOUEDr<5z(l|9Nin0lyMtO<$LNG^@19$4Mxm+Cnj&D zR;q2*PH3I5iHh#mQ}jx`8Y+2Sr;HdQ9X2k{H~>X#g<0!1zBFXhHgAD3+XfR>YaTRP z%s0)rKxitLTWc_tJFFV(8S7i?C+kvsn4J!@lxH`>6t&t^iHGXKOb&xbOJp>dp5I+O zk(kF~II=SK1l!4;VHM5~`%wwkRm+{{C_aXt%HIpctLArNL!OnQ<-zhbvLXj^aNc=T zu9F)PHoq^QmA{tudFm`peL&b9%4tF@9x?ffrD*Rc|%s8@a}k zfUyC#{}`s|BZDgUP$Th_r_?>#Q+kmx3SnWXxyif}K@(N&3B6gYV~2{k*9zrz68AQF zLP4?tW8W^IraPNcvevcI#fHfS#$MK{1c>X$`;U(VSC-KSr zG+6!Fd?ue0ygfiq2)rVGq?}g@;>BHsQT&ko^k+&R%u^+>n7gZ~)5<_ckyFgE0A4B-~xE@1^6%)f-o#oNV)#Yf;e9uuDs z|18#ve-&R4UxfpCTYL}4r_W*SXlan-m4;#8UMmTbUz#l4h7(?*RRUi?V@Kn-ya|EM4j8;=)aTVV)w8NcyHp#hU4`@W zbZxelgZ;ZyE7sOPdpBt1+BU4r<64dOv{tV@uYI6>rG2jr(nlh~vEXWQu(NmRyY*}Y zs*l5o97WJE27$&>Ym0Tz`WMd8m)VLv*`8)E2*CI~V(+r+VF0mkc*O_ov+c&1}|7f5+h0mQA6)=8yOIea(S4`esgON~+! zPCczS^_-A8;L*FK9+;3`iISt`7&%sslYMf$oG3H0(hrB;V0}4#)32lT7~P97F%Hw{ z)8q97Ju&!QIeksPYJGQb!e;u)xDM>kF1;J>rbj;uv)QXh!*IqK!PL!kTyV)|IzEOf zps7YY%2{}!VDo0$7f8ZcD#c7S)8LWj!Y3`j@gWZ<#v-%WT!mxAy8qa%HL$jIW<7k@ zA$YH5*xgnfFWSu$IOKMkU1qm=#_TcAn&-`4ld_@^OvYGVE7pp`(ZgrOTM1UGm1dm8^7kf7fdp902nu6_; z!lz=#rt@?81qcSp_;S7iTc?WOjiYBP-^O?HU5M7s@I5$&_VTepJa$o{zzBk1;82<_ z6bMBDgbP(dwXj>LLB!S~oDe#MPS_p_(ON7{8UmuVR51;)+A6U`EJv(XDOQV(aEPs9 zyLd+I6)9}7Scy1C#nFL0tbB>H?)6yh7H6${r5M@ktZ$N>hK-jiUz&##XPI0jSHp4C z2l=hE9XJcCLynozs!wI$F_P3|gdC}Ax>|snv~}2xm9R&<)kE+iZEC05rFO%gp2dlA zq~_BYoRt;Lz!k?_?92kKNL!^lpay5kvMxK>B)LJZksao z+yH`?a=ikZv<5D?UT@Wjc7^qdf=(qEi8z4zjUVC2ZK-pW8Q+Rln%QW_g*v=hh6E#kw1|UaFgi|-B^&AvVbXON|)Oebt~ z3>(L$;?z(8=U&cMvF+H$XJMfeL+(8dK~gc-#Ivss<;3 z_K+?`30~-tfqS%E1pF1aNjn7P=@!lkv7#>&IpvAPAyugn>)^yX;KZV#C~;D}loT=) zbEVvnaj3%0WJ|~l^hzT`TmQETG-ClSAj+W_(?O==MB1ZkYH8oe=$BT77@c diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index 467b22d094..00028d3afd 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -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(). diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index 7995e03f0d..f808d35cf9 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -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) diff --git a/libgambatte/src/cinterface.h b/libgambatte/src/cinterface.h index 4fbbb44b95..ee2a39a301 100644 --- a/libgambatte/src/cinterface.h +++ b/libgambatte/src/cinterface.h @@ -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); diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index 6b3208a209..a84fd723cb 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -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); diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index b2fbfd1ae4..a6deec0f80 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -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()); @@ -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); diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp index 05252e28d2..0c4bf5c972 100644 --- a/libgambatte/src/mem/cartridge.cpp +++ b/libgambatte/src/mem/cartridge.cpp @@ -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(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(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); } } diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h index b7a8a41b37..ee036f6077 100644 --- a/libgambatte/src/mem/cartridge.h +++ b/libgambatte/src/mem/cartridge.h @@ -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); diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h index 00bcfdbc14..70d9fd6308 100644 --- a/libgambatte/src/memory.h +++ b/libgambatte/src/memory.h @@ -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) {