diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index df61e1988d..c0500a49a9 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -31,6 +31,7 @@ using BizHawk.Client.EmuHawk.CoreExtensions; using BizHawk.Client.ApiHawk; using BizHawk.Emulation.Common.Base_Implementations; using BizHawk.Emulation.Cores.Nintendo.SNES9X; +using BizHawk.Emulation.Cores.Consoles.SNK; namespace BizHawk.Client.EmuHawk { @@ -1686,7 +1687,7 @@ namespace BizHawk.Client.EmuHawk // GBA meteor core might not know how big the saveram ought to be, so just send it the whole file // GBA vba-next core will try to eat anything, regardless of size - if (Emulator is VBANext || Emulator is MGBAHawk) + if (Emulator is VBANext || Emulator is MGBAHawk || Emulator is NeoGeoPort) { sram = File.ReadAllBytes(PathManager.SaveRamPath(Global.Game)); } diff --git a/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeoPort.cs b/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeoPort.cs index 08214a89f5..d28126d328 100644 --- a/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeoPort.cs +++ b/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeoPort.cs @@ -31,6 +31,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK { Japanese, English } + [UnmanagedFunctionPointer(CC)] + public delegate void SaveRamCallback(IntPtr data, int length); [BizImport(CC)] public abstract bool LoadSystem(byte[] rom, int romlength, Language language); @@ -46,5 +48,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK public abstract void GetMemoryArea(int which, ref IntPtr ptr, ref int size, ref bool writable); [BizImport(CC)] public abstract void SetCommsCallbacks(IntPtr readcb, IntPtr pollcb, IntPtr writecb); + [BizImport(CC)] + public abstract bool HasSaveRam(); + [BizImport(CC)] + public abstract bool PutSaveRam(byte[] data, int length); + [BizImport(CC)] + public abstract void GetSaveRam(SaveRamCallback callback); } } diff --git a/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs b/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs index e21d97e4d3..7e8fb5c287 100644 --- a/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs +++ b/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK [CoreAttributes("NeoPop", "Thomas Klausner", true, false, "0.9.44.1", "https://mednafen.github.io/releases/", false)] public class NeoGeoPort : IEmulator, IVideoProvider, ISoundProvider, IStatable, IInputPollable, - ISettable + ISettable, ISaveRam { private PeRunner _exe; internal LibNeoGeoPort _neopop; @@ -34,6 +34,9 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK internal NeoGeoPort(CoreComm comm, byte[] rom, SyncSettings syncSettings, bool deterministic, ulong startAddress) { + if (rom.Length > 4 * 1024 * 1024) + throw new InvalidOperationException("ROM too big!"); + ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; _syncSettings = syncSettings ?? new SyncSettings(); @@ -43,9 +46,9 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK Path = comm.CoreFileProvider.DllPath(), Filename = "ngp.wbx", SbrkHeapSizeKB = 256, - SealedHeapSizeKB = 10 * 1024, // must be a bit larger than twice the ROM size + SealedHeapSizeKB = 5 * 1024, // must be a bit larger than the ROM size InvisibleHeapSizeKB = 4, - PlainHeapSizeKB = 4, + PlainHeapSizeKB = 5 * 1024, // must be a bit larger than the ROM size StartAddress = startAddress }); @@ -374,5 +377,28 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK } #endregion + + #region ISaveram + + public bool SaveRamModified => _neopop.HasSaveRam(); + + public byte[] CloneSaveRam() + { + byte[] ret = null; + _neopop.GetSaveRam((data, size) => + { + ret = new byte[size]; + Marshal.Copy(data, ret, 0, size); + }); + return ret; + } + + public void StoreSaveRam(byte[] data) + { + if (!_neopop.PutSaveRam(data, data.Length)) + throw new InvalidOperationException("Core rejected the saveram"); + } + + #endregion } } diff --git a/output64/dll/ngp.wbx b/output64/dll/ngp.wbx index ebd418af10..f5111c35d8 100644 Binary files a/output64/dll/ngp.wbx and b/output64/dll/ngp.wbx differ diff --git a/waterbox/ngp/Makefile b/waterbox/ngp/Makefile index 67181161a6..fe067ba74b 100644 --- a/waterbox/ngp/Makefile +++ b/waterbox/ngp/Makefile @@ -29,8 +29,8 @@ $(TARGET).in: $(OBJS) @$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so $(TARGET): $(TARGET).in -# strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104 - cp $< $@ + strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104 +# cp $< $@ clean: rm -rf $(OBJ_DIR) diff --git a/waterbox/ngp/flash.cpp b/waterbox/ngp/flash.cpp index 20c5da9bbb..7f03d788ca 100644 --- a/waterbox/ngp/flash.cpp +++ b/waterbox/ngp/flash.cpp @@ -202,11 +202,11 @@ bool FLASH_LoadNV(const uint8* data, uint32 size) //throw MDFN_Error(0, _("FLASH header total_file_length is bad!")); } - if (size < sizeof(FlashFileHeader) + header.total_file_length) + if (size < header.total_file_length) return false; flashdata.resize(header.total_file_length); - memcpy(&flashdata[0], data + sizeof(FlashFileHeader), flashdata.size()); + memcpy(&flashdata[0], data, flashdata.size()); if (!do_flash_read(&flashdata[0])) return false; @@ -219,7 +219,7 @@ bool FLASH_LoadNV(const uint8* data, uint32 size) //----------------------------------------------------------------------------- void flash_write(uint32 start_address, uint16 length) { - /*uint16 i; + uint16 i; //Now we need a new flash command before the next flash write will work! memory_flash_command = FALSE; @@ -255,7 +255,7 @@ void flash_write(uint32 start_address, uint16 length) blocks[block_count].start_address = start_address; blocks[block_count].data_length = length; block_count++; - }*/ + } } static void make_flash_commit(std::vector &flashdata) @@ -304,6 +304,11 @@ static void make_flash_commit(std::vector &flashdata) } } +bool FLASH_IsModified() +{ + return block_count > 0; +} + void FLASH_SaveNV(void (*callback)(const uint8* data, uint32 size)) { std::vector flashdata; diff --git a/waterbox/ngp/flash.h b/waterbox/ngp/flash.h index eebe6d312c..c463c8df3e 100644 --- a/waterbox/ngp/flash.h +++ b/waterbox/ngp/flash.h @@ -24,6 +24,7 @@ void flash_write(uint32 start_address, uint16 length); bool FLASH_LoadNV(const uint8* data, uint32 size); void FLASH_SaveNV(void (*callback)(const uint8* data, uint32 size)); +bool FLASH_IsModified(); } //============================================================================= diff --git a/waterbox/ngp/neopop.cpp b/waterbox/ngp/neopop.cpp index f6b1b3186e..ee8d225009 100644 --- a/waterbox/ngp/neopop.cpp +++ b/waterbox/ngp/neopop.cpp @@ -143,7 +143,7 @@ static MDFN_COLD bool Load(const uint8* romdata, int32 romlength) //throw MDFN_Error(0, _("NGP/NGPC ROM image is too large.")); ngpc_rom.length = fp_size; - ngpc_rom.data = (uint8*)alloc_sealed(ngpc_rom.length); + ngpc_rom.data = (uint8*)alloc_plain(ngpc_rom.length); memcpy(ngpc_rom.data, romdata, romlength); rom_loaded(); @@ -240,3 +240,18 @@ EXPORT void GetMemoryArea(int which, void **ptr, int *size, int *writable) } } +EXPORT bool HasSaveRam() +{ + return FLASH_IsModified(); +} + +EXPORT bool PutSaveRam(const uint8* data, uint32 length) +{ + return FLASH_LoadNV(data, length); +} + +EXPORT void GetSaveRam(void (*callback)(const uint8* data, uint32 length)) +{ + FLASH_SaveNV(callback); +} +