diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index d4d84c445c..9a6c529b43 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -1255,6 +1255,7 @@
+
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs
index 501ebc962c..dd60e92de3 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
{
- public abstract class LibPizza : LibWaterboxCore
+ public abstract class LibPizza : LibWaterboxCore, ICustomSaveram
{
[Flags]
public enum Buttons : uint
@@ -32,5 +32,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
public abstract bool Init(byte[] rom, int romlen, bool sgb, byte[] spc, int spclen);
[BizImport(CC)]
public abstract bool IsCGB();
+ [BizImport(CC)]
+ public abstract int GetSaveramSize();
+ [BizImport(CC)]
+ public abstract void PutSaveram(byte[] data, int size);
+ [BizImport(CC)]
+ public abstract void GetSaveram(byte[] data, int size);
}
}
diff --git a/BizHawk.Emulation.Cores/Waterbox/CustomSaverammer.cs b/BizHawk.Emulation.Cores/Waterbox/CustomSaverammer.cs
new file mode 100644
index 0000000000..ae1834f235
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Waterbox/CustomSaverammer.cs
@@ -0,0 +1,38 @@
+using BizHawk.Emulation.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Waterbox
+{
+ internal class CustomSaverammer : ISaveRam
+ {
+ private readonly ICustomSaveram _s;
+ private readonly int _size;
+
+
+ public CustomSaverammer(ICustomSaveram s)
+ {
+ _s = s;
+ _size = s.GetSaveramSize();
+ }
+
+ public bool SaveRamModified => _size > 0;
+
+ public byte[] CloneSaveRam()
+ {
+ var ret = new byte[_size];
+ _s.GetSaveram(ret, ret.Length);
+ return ret;
+ }
+
+ public void StoreSaveRam(byte[] data)
+ {
+ if (data.Length != _size)
+ throw new InvalidOperationException("Wrong size saveram");
+ _s.PutSaveram(data, data.Length);
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs b/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs
index 9e1973a8f3..b1fd9ee0d6 100644
--- a/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs
@@ -48,7 +48,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
[Flags]
- public enum MemoryDomainFlags: int
+ public enum MemoryDomainFlags : int
{
None = 0,
///
@@ -166,11 +166,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
Writable = (m.Flags & MemoryDomainFlags.Writable) != 0;
if ((m.Flags & MemoryDomainFlags.WordSize1) != 0)
WordSize = 1;
- else if((m.Flags & MemoryDomainFlags.WordSize2) != 0)
+ else if ((m.Flags & MemoryDomainFlags.WordSize2) != 0)
WordSize = 2;
- else if((m.Flags & MemoryDomainFlags.WordSize4) != 0)
+ else if ((m.Flags & MemoryDomainFlags.WordSize4) != 0)
WordSize = 4;
- else if((m.Flags & MemoryDomainFlags.WordSize8) != 0)
+ else if ((m.Flags & MemoryDomainFlags.WordSize8) != 0)
WordSize = 8;
else
throw new InvalidOperationException("Unknown word size for memory domain");
@@ -195,4 +195,14 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizImport(CC)]
public abstract void SetInputCallback(EmptyCallback callback);
}
+
+ ///
+ /// if a core implements this, it will be used for saveramming instead of memory domains
+ ///
+ interface ICustomSaveram
+ {
+ int GetSaveramSize();
+ void PutSaveram(byte[] data, int size);
+ void GetSaveram(byte[] data, int size);
+ }
}
diff --git a/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
index bf4d53b29c..29181e2530 100644
--- a/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs
@@ -79,6 +79,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
var mdl = new MemoryDomainList(memoryDomains.Cast().ToList());
mdl.MainMemory = mdl[primaryIndex];
_serviceProvider.Register(mdl);
+
+ var sr = _core as ICustomSaveram;
+ if (sr != null)
+ _serviceProvider.Register(new CustomSaverammer(sr)); // override the default implementation
+
_exe.Seal();
}
}
diff --git a/output/dll/pizza.wbx.gz b/output/dll/pizza.wbx.gz
index dfa7e96b27..66eb3a5fb3 100644
Binary files a/output/dll/pizza.wbx.gz and b/output/dll/pizza.wbx.gz differ
diff --git a/waterbox/pizza/lib/cartridge.h b/waterbox/pizza/lib/cartridge.h
index 4c6c372ad6..ebc95de13c 100644
--- a/waterbox/pizza/lib/cartridge.h
+++ b/waterbox/pizza/lib/cartridge.h
@@ -24,6 +24,5 @@
/* prototypes */
char cartridge_load(const void* data, size_t sz);
-void cartridge_term();
#endif
diff --git a/waterbox/pizza/lib/mmu.c b/waterbox/pizza/lib/mmu.c
index f749ca55b0..4fe931f3f2 100644
--- a/waterbox/pizza/lib/mmu.c
+++ b/waterbox/pizza/lib/mmu.c
@@ -303,10 +303,9 @@ uint8_t mmu_read_no_cyc(uint16_t a)
return mmu.memory[a];
}
-void mmu_restore_ram(char *fn)
-{
- /* save only if cartridge got a battery */
- if (mmu.carttype == 0x03 ||
+static int has_saveram(void)
+{
+ return mmu.carttype == 0x03 ||
mmu.carttype == 0x06 ||
mmu.carttype == 0x09 ||
mmu.carttype == 0x0D ||
@@ -317,31 +316,46 @@ void mmu_restore_ram(char *fn)
mmu.carttype == 0x1B ||
mmu.carttype == 0x1E ||
mmu.carttype == 0x22 ||
- mmu.carttype == 0xFF)
- {
- FILE *fp = fopen(fn, "r+");
+ mmu.carttype == 0xFF;
+}
- /* it could be not present */
- if (fp == NULL)
- return;
+int mmu_saveram_size(void)
+{
+ return has_saveram() ? ram_sz : 0;
+}
- if (ram_sz <= 0x2000)
- {
- /* no need to put togheter pieces of ram banks */
- fread(&mmu.memory[0xA000], ram_sz, 1, fp);
- }
- else
- {
- /* read entire file into ram buffer */
- fread(mmu.ram_internal, 0x2000, 1, fp);
- fread(ram, ram_sz, 1, fp);
+void mmu_restore_saveram(const uint8_t* data, int sz)
+{
+ if (sz == mmu_saveram_size())
+ {
+ if (ram_sz <= 0x2000)
+ {
+ memcpy(&mmu.memory[0xa000], data, ram_sz);
+ }
+ else
+ {
+ memcpy(ram, data, ram_sz);
+ if (mmu.ram_external_enabled)
+ memcpy(&mmu.memory[0xa000], &ram[0x2000 * mmu.ram_current_bank], 0x2000);
+ }
+ }
+}
- /* copy internal RAM to 0xA000 address */
- memcpy(&mmu.memory[0xA000], mmu.ram_internal, 0x2000);
- }
-
- fclose(fp);
- }
+void mmu_save_saveram(uint8_t* dest, int sz)
+{
+ if (sz == mmu_saveram_size())
+ {
+ if (ram_sz <= 0x2000)
+ {
+ memcpy(dest, &mmu.memory[0xa000], ram_sz);
+ }
+ else
+ {
+ memcpy(dest, ram, ram_sz);
+ if (mmu.ram_external_enabled)
+ memcpy(&dest[0x2000 * mmu.ram_current_bank], &mmu.memory[0xa000], 0x2000);
+ }
+ }
}
void mmu_restore_rtc(char *fn)
@@ -367,56 +381,6 @@ void mmu_restore_rtc(char *fn)
}
}
-void mmu_save_ram(char *fn)
-{
- /* save only if cartridge got a battery */
- if (mmu.carttype == 0x03 ||
- mmu.carttype == 0x06 ||
- mmu.carttype == 0x09 ||
- mmu.carttype == 0x0d ||
- mmu.carttype == 0x0f ||
- mmu.carttype == 0x10 ||
- mmu.carttype == 0x13 ||
- mmu.carttype == 0x17 ||
- mmu.carttype == 0x1b ||
- mmu.carttype == 0x1e ||
- mmu.carttype == 0x22 ||
- mmu.carttype == 0xff)
- {
- FILE *fp = fopen(fn, "w+");
-
- if (fp == NULL)
- {
- printf("Error dumping RAM\n");
- return;
- }
-
- if (ram_sz <= 0x2000)
- {
- /* no need to put togheter pieces of ram banks */
- fwrite(&mmu.memory[0xA000], ram_sz, 1, fp);
- }
- else
- {
- /* yes, i need to put togheter pieces */
-
- /* save current used bank */
- if (mmu.ram_external_enabled)
- memcpy(&ram[0x2000 * mmu.ram_current_bank],
- &mmu.memory[0xA000], 0x2000);
- else
- memcpy(mmu.ram_internal,
- &mmu.memory[0xA000], 0x2000);
-
- /* dump the entire internal + external RAM */
- fwrite(mmu.ram_internal, 0x2000, 1, fp);
- fwrite(ram, ram_sz, 1, fp);
- }
-
- fclose(fp);
- }
-}
-
void mmu_save_rtc(char *fn)
{
/* save only if cartridge got a battery */
@@ -440,15 +404,6 @@ void mmu_set_rumble_cb(mmu_rumble_cb_t cb)
mmu_rumble_cb = cb;
}
-void mmu_term()
-{
- if (ram)
- {
- free(ram);
- ram = NULL;
- }
-}
-
/* write 16 bit block on a memory address */
void mmu_write(uint16_t a, uint8_t v)
{
@@ -699,10 +654,6 @@ void mmu_write(uint16_t a, uint8_t v)
if (mmu.ram_external_enabled)
return;
- /* save current bank */
- memcpy(mmu.ram_internal,
- &mmu.memory[0xA000], 0x2000);
-
/* restore external ram bank */
memcpy(&mmu.memory[0xA000],
&ram[0x2000 * mmu.ram_current_bank],
@@ -724,10 +675,6 @@ void mmu_write(uint16_t a, uint8_t v)
memcpy(&ram[0x2000 * mmu.ram_current_bank],
&mmu.memory[0xA000], 0x2000);
- /* restore external ram bank */
- memcpy(&mmu.memory[0xA000],
- mmu.ram_internal, 0x2000);
-
/* clear external RAM eanbled flag */
mmu.ram_external_enabled = 0;
}
@@ -807,10 +754,6 @@ void mmu_write(uint16_t a, uint8_t v)
if (mmu.ram_external_enabled)
return;
- /* save current bank */
- memcpy(mmu.ram_internal,
- &mmu.memory[0xA000], 0x2000);
-
/* restore external ram bank */
memcpy(&mmu.memory[0xA000],
&ram[0x2000 * mmu.ram_current_bank],
@@ -836,10 +779,6 @@ void mmu_write(uint16_t a, uint8_t v)
memcpy(&ram[0x2000 * mmu.ram_current_bank],
&mmu.memory[0xA000], 0x2000);
- /* restore external ram bank */
- memcpy(&mmu.memory[0xA000],
- mmu.ram_internal, 0x2000);
-
/* clear external RAM eanbled flag */
mmu.ram_external_enabled = 0;
}
@@ -921,9 +860,6 @@ void mmu_write(uint16_t a, uint8_t v)
/* save new current bank */
mmu.rom_current_bank = b;
-
- /* re-apply cheats */
-// mmu_apply_gg();
}
return;
@@ -1135,8 +1071,3 @@ void mmu_write_no_cyc(uint16_t a, uint8_t v)
{
mmu.memory[a] = v;
}
-
-
-
-
-
diff --git a/waterbox/pizza/lib/mmu.h b/waterbox/pizza/lib/mmu.h
index 58fb8285d4..4fda013058 100644
--- a/waterbox/pizza/lib/mmu.h
+++ b/waterbox/pizza/lib/mmu.h
@@ -37,8 +37,7 @@ typedef struct mmu_s {
uint8_t spare;
uint16_t spare2;
- /* internal RAM */
- uint8_t ram_internal[0x2000];
+ // cartridge RAM
uint8_t ram_external_enabled;
uint8_t ram_current_bank;
@@ -101,13 +100,13 @@ void mmu_move(uint16_t d, uint16_t s);
uint8_t mmu_read_no_cyc(uint16_t a);
uint8_t mmu_read(uint16_t a);
unsigned int mmu_read_16(uint16_t a);
-void mmu_restore_ram(char *fn);
+int mmu_saveram_size(void);
+void mmu_restore_saveram(const uint8_t* data, int sz);
+void mmu_save_saveram(uint8_t* dest, int sz);
void mmu_restore_rtc(char *fn);
-void mmu_save_ram(char *fn);
void mmu_save_rtc(char *fn);
void mmu_set_rumble_cb(mmu_rumble_cb_t cb);
void mmu_step();
-void mmu_term();
void mmu_write_no_cyc(uint16_t a, uint8_t v);
void mmu_write(uint16_t a, uint8_t v);
void mmu_write_16(uint16_t a, uint16_t v);
diff --git a/waterbox/pizza/pizza.c b/waterbox/pizza/pizza.c
index d4cfe0b62e..0736f7ef89 100644
--- a/waterbox/pizza/pizza.c
+++ b/waterbox/pizza/pizza.c
@@ -148,6 +148,21 @@ EXPORT void GetMemoryAreas(MemoryArea *m)
m[0].Flags = MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1;
}
+EXPORT int GetSaveramSize(void)
+{
+ return mmu_saveram_size();
+}
+
+EXPORT void PutSaveram(const uint8_t* data, int size)
+{
+ mmu_restore_saveram(data, size);
+}
+
+EXPORT void GetSaveram(uint8_t* data, int size)
+{
+ mmu_save_saveram(data, size);
+}
+
void frame_cb()
{
if (global_sgb)