diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
index 2080b0f72d..5919b0b8f5 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
@@ -55,7 +55,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// length of data in bytes
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_loadrom(byte[] data, uint datalen);
-
+
///
/// load a bios image
///
@@ -85,16 +85,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
[Flags]
public enum Buttons : ushort
{
- BTN_A = 0x001,
- BTN_B = 0x002,
+ BTN_A = 0x001,
+ BTN_B = 0x002,
BTN_SELECT = 0x004,
- BTN_START = 0x008,
- BTN_RIGHT = 0x010,
- BTN_LEFT = 0x020,
- BTN_UP = 0x040,
- BTN_DOWN = 0x080,
- BTN_R = 0x100,
- BTN_L = 0x200
+ BTN_START = 0x008,
+ BTN_RIGHT = 0x010,
+ BTN_LEFT = 0x020,
+ BTN_UP = 0x040,
+ BTN_DOWN = 0x080,
+ BTN_R = 0x100,
+ BTN_L = 0x200
}
///
@@ -146,5 +146,43 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// null to clear
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_settracecallback(TraceCallback callback);
+
+ ///
+ /// load saveram from a byte buffer
+ ///
+ ///
+ ///
+ /// success
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool libmeteor_loadsaveram(byte[] data, uint size);
+
+ ///
+ /// save saveram to a byte buffer
+ ///
+ /// buffer generated by core. coyp from, but do not modify
+ /// length of buffer
+ /// success
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool libmeteor_savesaveram(ref IntPtr data, ref uint size);
+
+ ///
+ /// destroy a buffer previously returned by libmeteor_savesaveram() to avoid leakage
+ ///
+ ///
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void libmeteor_savesaveram_destroy(IntPtr data);
+
+ ///
+ /// return true if there is saveram installed on currently loaded cart
+ ///
+ ///
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool libmeteor_hassaveram();
+
+ ///
+ /// resets the current cart's saveram
+ ///
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void libmeteor_clearsaveram();
}
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
index dc4b56fe7c..a04ee143b4 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
@@ -64,18 +64,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
public byte[] ReadSaveRam()
{
- return new byte[0];
+ if (!LibMeteor.libmeteor_hassaveram())
+ return null;
+ IntPtr data = IntPtr.Zero;
+ uint size = 0;
+ if (!LibMeteor.libmeteor_savesaveram(ref data, ref size))
+ throw new Exception("libmeteor_savesaveram() returned false!");
+ byte[] ret = new byte[size];
+ Marshal.Copy(data, ret, 0, (int)size);
+ LibMeteor.libmeteor_savesaveram_destroy(data);
+ return ret;
}
public void StoreSaveRam(byte[] data)
{
+ if (!LibMeteor.libmeteor_loadsaveram(data, (uint)data.Length))
+ throw new Exception("libmeteor_loadsaveram() returned false!");
}
public void ClearSaveRam()
{
+ LibMeteor.libmeteor_clearsaveram();
}
- public bool SaveRamModified { get { return false; } set { } }
+ public bool SaveRamModified
+ { get { return LibMeteor.libmeteor_hassaveram(); } set { } }
#endregion
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index e3ef6d3d29..3b3ed74f63 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -2041,20 +2041,18 @@ namespace BizHawk.MultiClient
//zero says: this is sort of sketchy... but this is no time for rearchitecting
try
{
- /*
- var sram = new byte[Global.Emulator.ReadSaveRam.Length];
- using (var reader = new BinaryReader(new FileStream(PathManager.SaveRamPath(Global.Game), FileMode.Open, FileAccess.Read)))
- reader.Read(sram, 0, Global.Emulator.ReadSaveRam.Length);
- if (Global.Emulator is LibsnesCore)
- ((LibsnesCore)Global.Emulator).StoreSaveRam(sram);
- else if (Global.Emulator is Gameboy)
- ((Gameboy)Global.Emulator).StoreSaveRam(sram);
+ byte[] sram;
+ // GBA core might not know how big the saveram ought to be, so just send it the whole file
+ if (Global.Emulator is GBA)
+ {
+ sram = File.ReadAllBytes(PathManager.SaveRamPath(Global.Game));
+ }
else
- Array.Copy(sram, Global.Emulator.ReadSaveRam, Global.Emulator.ReadSaveRam.Length);
- */
- var sram = new byte[Global.Emulator.ReadSaveRam().Length];
- using (var reader = new BinaryReader(new FileStream(PathManager.SaveRamPath(Global.Game), FileMode.Open, FileAccess.Read)))
+ {
+ sram = new byte[Global.Emulator.ReadSaveRam().Length];
+ using (var reader = new BinaryReader(new FileStream(PathManager.SaveRamPath(Global.Game), FileMode.Open, FileAccess.Read)))
reader.Read(sram, 0, sram.Length);
+ }
Global.Emulator.StoreSaveRam(sram);
}
catch (IOException) { }
diff --git a/BizHawk.MultiClient/output/dll/libmeteor.dll b/BizHawk.MultiClient/output/dll/libmeteor.dll
index dcf3915798..3e03b60010 100644
Binary files a/BizHawk.MultiClient/output/dll/libmeteor.dll and b/BizHawk.MultiClient/output/dll/libmeteor.dll differ
diff --git a/libmeteor/Makefile b/libmeteor/Makefile
index a66f82a441..2029f11b3d 100644
--- a/libmeteor/Makefile
+++ b/libmeteor/Makefile
@@ -30,8 +30,9 @@ else
CXXFLAGS += -DNO_MEMMEM
endif
+#__LIBRETRO__ enables a slightly different saveram mechanism that doesn't seem to serve any useful purpose?
#CXXFLAGS += -Wall -pedantic -I. -I../ameteor/include -pipe -D__LIBRETRO__ -Wno-parentheses -fno-exceptions -fno-rtti
-CXXFLAGS += -Wall -pedantic -I. -Iinclude -pipe -D__LIBRETRO__ -DX86_ASM -Wno-parentheses -fno-exceptions -fno-rtti
+CXXFLAGS += -Wall -pedantic -I. -Iinclude -pipe -DX86_ASM -Wno-parentheses -fno-exceptions -fno-rtti
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -g
diff --git a/libmeteor/cinterface.cpp b/libmeteor/cinterface.cpp
index 36ec943370..98f5f79144 100644
--- a/libmeteor/cinterface.cpp
+++ b/libmeteor/cinterface.cpp
@@ -120,8 +120,6 @@ EXPORT void libmeteor_init()
static bool first = true;
if (first)
{
- // TODO: saveram stuff
- //AMeteor::_memory.LoadCartInferred();
AMeteor::_lcd.GetScreen().GetRenderer().SetFrameSlot(syg::ptr_fun(videocb));
AMeteor::_sound.GetSpeaker().SetFrameSlot(syg::ptr_fun(soundcb));
first = false;
@@ -150,5 +148,30 @@ EXPORT uint8_t *libmeteor_getmemoryarea(int which)
return AMeteor::_memory.GetMemoryArea(which);
}
+EXPORT int libmeteor_loadsaveram(const void *data, unsigned size)
+{
+ return AMeteor::_memory.LoadCart((const uint8_t*)data, size);
+}
+
+EXPORT int libmeteor_savesaveram(void **data, unsigned *size)
+{
+ return AMeteor::_memory.SaveCart((uint8_t **)data, size);
+}
+
+EXPORT void libmeteor_savesaveram_destroy(void *data)
+{
+ AMeteor::_memory.SaveCartDestroy((uint8_t *)data);
+}
+
+EXPORT int libmeteor_hassaveram()
+{
+ return AMeteor::_memory.HasCart();
+}
+
+EXPORT void libmeteor_clearsaveram()
+{
+ AMeteor::_memory.DeleteCart();
+}
+
// TODO: cartram and system bus memory domains
diff --git a/libmeteor/include/ameteor/clock.hpp b/libmeteor/include/ameteor/clock.hpp
index 8d001f962b..b711080538 100644
--- a/libmeteor/include/ameteor/clock.hpp
+++ b/libmeteor/include/ameteor/clock.hpp
@@ -81,15 +81,15 @@ namespace AMeteor
return m_timer[num];
}
- void SetBattery (uint32_t cycles)
- {
- m_battery = cycles;
- }
- void DisableBattery ()
- {
- m_battery = INT_MAX;
+ //void SetBattery (uint32_t cycles)
+ //{
+ // m_battery = cycles;
+ //}
+ //void DisableBattery ()
+ //{
+ // m_battery = INT_MAX;
// no need to SetFirst since battery will be disabled only in TimeEvent
- }
+ //}
bool SaveState (std::ostream& stream);
bool LoadState (std::istream& stream);
@@ -100,7 +100,7 @@ namespace AMeteor
unsigned short m_cycles;
unsigned short m_first;
- int m_lcd, m_timer[4], m_sound, m_battery;
+ int m_lcd, m_timer[4], m_sound;//, m_battery;
unsigned int m_count;
diff --git a/libmeteor/include/ameteor/memory.hpp b/libmeteor/include/ameteor/memory.hpp
index 0b167cfe8c..d55cb7ff27 100644
--- a/libmeteor/include/ameteor/memory.hpp
+++ b/libmeteor/include/ameteor/memory.hpp
@@ -60,10 +60,10 @@ namespace AMeteor
// erases cartridge memory
void SetCartTypeFromSize (uint32_t size);
void SetCartType (uint8_t type);
- void SetCartFile (const char* filename)
- {
- m_cartfile = filename;
- }
+ //void SetCartFile (const char* filename)
+ //{
+ // m_cartfile = filename;
+ //}
void Reset (uint32_t params = ~0);
void ClearWbram ();
@@ -85,10 +85,23 @@ namespace AMeteor
}
bool LoadRom (const char* filename);
void LoadRom (const uint8_t* data, uint32_t size);
- CartError LoadCart ();
+ //CartError LoadCart ();
+ bool LoadCart (const uint8_t* data, uint32_t size);
+ bool SaveCart (uint8_t** data, uint32_t* size);
+ void SaveCartDestroy(uint8_t* data);
#ifdef __LIBRETRO__
bool LoadCartInferred ();
#endif
+ bool HasCart () const
+ {
+ return m_cart;
+ }
+
+ void DeleteCart()
+ {
+ if (m_cart)
+ delete m_cart;
+ }
bool HasBios () const
{
@@ -141,7 +154,7 @@ namespace AMeteor
uint8_t m_carttype;
CartMem* m_cart;
- std::string m_cartfile;
+ //std::string m_cartfile;
uint8_t ReadCart (uint16_t add);
void WriteCart (uint16_t add, uint8_t val);
diff --git a/libmeteor/libmeteor.vcxproj b/libmeteor/libmeteor.vcxproj
index 7a9a1207b5..89cb51c975 100644
--- a/libmeteor/libmeteor.vcxproj
+++ b/libmeteor/libmeteor.vcxproj
@@ -51,7 +51,7 @@
Level3
Disabled
- WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions);METDEBUG;METDEBUGLOG;_ITERATOR_DEBUG_LEVEL=0
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions);METDEBUG;METDEBUGLOG;_ITERATOR_DEBUG_LEVEL=0;NO_MEMMEM
4396;4800
@@ -67,7 +67,7 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions);NO_MEMMEM
4396;4800
diff --git a/libmeteor/source/clock.cpp b/libmeteor/source/clock.cpp
index 7f21980ed3..4600a7250e 100644
--- a/libmeteor/source/clock.cpp
+++ b/libmeteor/source/clock.cpp
@@ -27,7 +27,7 @@ namespace AMeteor
// lcd is enabled by default
m_first = m_count = m_cycles = m_lcd = m_sound = 0;
// timers and battery are disabled by default
- m_battery = m_timer[0] = m_timer[1] = m_timer[2] = m_timer[3] =
+ /*m_battery =*/ m_timer[0] = m_timer[1] = m_timer[2] = m_timer[3] =
INT_MAX;
}
@@ -67,7 +67,7 @@ namespace AMeteor
COMMIT(timer[1], TIMER1)
COMMIT(timer[2], TIMER2)
COMMIT(timer[3], TIMER3)
- COMMIT(battery, MEM)
+ //COMMIT(battery, MEM)
#undef COMMIT
SetFirst();
@@ -91,7 +91,7 @@ namespace AMeteor
SETFIRST(timer[2]);
SETFIRST(timer[3]);
SETFIRST(sound);
- SETFIRST(battery);
+ //SETFIRST(battery);
}
#undef SETFIRST
@@ -101,7 +101,7 @@ namespace AMeteor
SS_WRITE_VAR(m_first);
SS_WRITE_VAR(m_lcd);
SS_WRITE_VAR(m_sound);
- SS_WRITE_VAR(m_battery);
+ //SS_WRITE_VAR(m_battery);
SS_WRITE_ARRAY(m_timer);
@@ -114,7 +114,7 @@ namespace AMeteor
SS_READ_VAR(m_first);
SS_READ_VAR(m_lcd);
SS_READ_VAR(m_sound);
- SS_READ_VAR(m_battery);
+ //SS_READ_VAR(m_battery);
SS_READ_ARRAY(m_timer);
diff --git a/libmeteor/source/memory.cpp b/libmeteor/source/memory.cpp
index 5532ea2f53..f82ac18aec 100644
--- a/libmeteor/source/memory.cpp
+++ b/libmeteor/source/memory.cpp
@@ -99,29 +99,39 @@ namespace AMeteor
void Memory::SetCartType (uint8_t type)
{
if (m_cart)
+ {
delete m_cart;
+ print_bizhawk("Cart Memory unloaded.\n");
+ }
switch (type)
{
case CTYPE_UNKNOWN:
m_cart = NULL;
+ print_bizhawk("Cart Memory set to .\n");
break;
case CTYPE_FLASH64:
m_cart = new Flash(false);
+ print_bizhawk("Cart Memory set to FLASH64\n");
break;
case CTYPE_FLASH128:
m_cart = new Flash(true);
+ print_bizhawk("Cart Memory set to FLASH128\n");
break;
case CTYPE_EEPROM512:
m_cart = new Eeprom(false);
+ print_bizhawk("Cart Memory set to EEPROM512\n");
break;
case CTYPE_EEPROM8192:
m_cart = new Eeprom(true);
+ print_bizhawk("Cart Memory set to EEPROM8192\n");
break;
case CTYPE_SRAM:
m_cart = new Sram();
+ print_bizhawk("Cart Memory set to SRAM\n");
break;
default:
met_abort("Unknown cartridge memory type");
+ print_bizhawk("Problem setting Cart Memory. This is bad.\n");
break;
}
m_carttype = type;
@@ -168,7 +178,7 @@ namespace AMeteor
if (params & UNIT_MEMORY_ROM)
std::memset(m_rom , 0, 0x02000000);
SetCartType(CTYPE_UNKNOWN);
- m_cartfile.clear();
+ //m_cartfile.clear();
}
void Memory::ClearWbram ()
@@ -204,6 +214,7 @@ namespace AMeteor
void Memory::TimeEvent ()
{
+ /*
if (!m_cartfile.empty())
{
// FIXME, this may fail, we should do something to inform user
@@ -211,6 +222,7 @@ namespace AMeteor
m_cart->Save(f);
}
CLOCK.DisableBattery();
+ */
}
bool Memory::LoadBios (const char* filename)
@@ -251,6 +263,38 @@ namespace AMeteor
std::memset(m_rom+until, 0, 0x02000000-until);
}
+ bool Memory::LoadCart(const uint8_t* data, uint32_t size)
+ {
+ SetCartTypeFromSize(size);
+ if (!m_cart)
+ return false;
+ std::stringstream ss = std::stringstream(std::string((const char*)data, size), std::ios_base::in | std::ios_base::binary);
+ return m_cart->Load(ss);
+ }
+
+ bool Memory::SaveCart(uint8_t** data, uint32_t* size)
+ {
+ if (!m_cart)
+ return false;
+ if (!data || !size)
+ return false;
+ std::stringstream ss = std::stringstream(std::ios_base::out | std::ios_base::binary);
+ if (!m_cart->Save(ss))
+ return false;
+ std::string s = ss.str();
+ uint8_t *ret = (uint8_t *)std::malloc(s.length());
+ std::memcpy(ret, s.data(), s.length());
+ *data = ret;
+ *size = s.length();
+ return true;
+ }
+
+ void Memory::SaveCartDestroy(uint8_t* data)
+ {
+ std::free(data);
+ }
+
+ /*
Memory::CartError Memory::LoadCart ()
{
struct stat buf;
@@ -262,6 +306,7 @@ namespace AMeteor
return CERR_FAIL;
return CERR_NO_ERROR;
}
+ */
#ifdef __LIBRETRO__
bool Memory::LoadCartInferred ()
@@ -761,8 +806,9 @@ namespace AMeteor
else
met_abort("Unknown size for EEPROM DMA");
- if (eeprom->Write((uint16_t*)GetRealAddress(src), size))
- CLOCK.SetBattery(CART_SAVE_TIME);
+ //if (eeprom->Write((uint16_t*)GetRealAddress(src), size))
+ // CLOCK.SetBattery(CART_SAVE_TIME);
+ eeprom->Write((uint16_t*)GetRealAddress(src), size);
}
#if 0
@@ -777,7 +823,6 @@ namespace AMeteor
}
#endif
-#define NO_MEMMEM
#ifdef NO_MEMMEM // memmem() is a GNU extension, and does not exist in at least MinGW.
#define memmem memmem_compat
// Implementation from Git.
@@ -817,8 +862,9 @@ namespace AMeteor
}
else
SetCartType(CTYPE_SRAM);
- if (m_cart->Write(add, val))
- CLOCK.SetBattery(CART_SAVE_TIME);
+ //if (m_cart->Write(add, val))
+ // CLOCK.SetBattery(CART_SAVE_TIME);
+ m_cart->Write(add, val);
}
uint8_t *Memory::GetMemoryArea(int which)