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)