diff --git a/BizHawk.Emulation/Consoles/Atari/2600/Atari2600.cs b/BizHawk.Emulation/Consoles/Atari/2600/Atari2600.cs index 360915460d..2f1489d297 100644 --- a/BizHawk.Emulation/Consoles/Atari/2600/Atari2600.cs +++ b/BizHawk.Emulation/Consoles/Atari/2600/Atari2600.cs @@ -64,7 +64,7 @@ namespace BizHawk private int _lagcount = 0; private int _frame = 0; - public byte[] SaveRam { get { return new byte[0]; } } + public byte[] ReadSaveRam { get { return new byte[0]; } } public bool DeterministicEmulation { get; set; } public bool SaveRamModified { get; set; } public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); } diff --git a/BizHawk.Emulation/Consoles/Calculator/TI83.cs b/BizHawk.Emulation/Consoles/Calculator/TI83.cs index 8e4c8863f5..94824b8c89 100644 --- a/BizHawk.Emulation/Consoles/Calculator/TI83.cs +++ b/BizHawk.Emulation/Consoles/Calculator/TI83.cs @@ -478,7 +478,7 @@ namespace BizHawk.Emulation.Consoles.Calculator public bool DeterministicEmulation { get { return true; } set { } } - public byte[] SaveRam { get { return null; } } + public byte[] ReadSaveRam { get { return null; } } public bool SaveRamModified { get { return false; } diff --git a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs b/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs index fef10ea6e2..f50a12efb4 100644 --- a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs +++ b/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs @@ -70,7 +70,7 @@ namespace BizHawk.Emulation.Consoles.Coleco private int _lagcount = 0; private int _frame = 0; - public byte[] SaveRam { get { return new byte[0]; } } + public byte[] ReadSaveRam { get { return new byte[0]; } } public bool DeterministicEmulation { get; set; } public bool SaveRamModified { get; set; } public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); } diff --git a/BizHawk.Emulation/Consoles/GB/GB.cs b/BizHawk.Emulation/Consoles/GB/GB.cs index b997a490f2..16430d4172 100644 --- a/BizHawk.Emulation/Consoles/GB/GB.cs +++ b/BizHawk.Emulation/Consoles/GB/GB.cs @@ -68,7 +68,7 @@ namespace BizHawk.Emulation.Consoles.GB Frame = 0; } - public byte[] SaveRam { get { throw new NotImplementedException(); } } + public byte[] ReadSaveRam { get { throw new NotImplementedException(); } } public bool SaveRamModified { get { return false; } set { } } public void SaveStateBinary(System.IO.BinaryWriter writer) diff --git a/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs index 60d1f26e76..c04e93ffce 100644 --- a/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs +++ b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs @@ -775,7 +775,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy public int LagCount { get { return _lagcount; } set { _lagcount = value; } } public bool IsLagFrame { get { return islag; } } - public byte[] SaveRam + public byte[] ReadSaveRam { get { throw new NotImplementedException(); } } diff --git a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs index 50dc627ac5..bbf149a67e 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs @@ -122,7 +122,7 @@ namespace BizHawk.Emulation.Consoles.Intellivision public bool DeterministicEmulation { get; set; } - public byte[] SaveRam { get { return null; } } + public byte[] ReadSaveRam { get { return null; } } public bool SaveRamModified { diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index 90feffdd16..dcce7d69a6 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -303,7 +303,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo public bool DeterministicEmulation { get { return true; } set { } } - public byte[] SaveRam + public byte[] ReadSaveRam { get { diff --git a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs index 860612dc7b..6bb4cb6a8d 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -1,4 +1,9 @@ -using System; +//TODO +//libsnes needs to be modified to support multiple instances +//rename snes.dll so nobody thinks it's a stock snes.dll (we'll be editing it substantially at some point) +//wrap dll code around some kind of library-accessing interface so that it doesnt malfunction if the dll is unavailable + +using System; using System.Linq; using System.Diagnostics; using System.Globalization; @@ -8,7 +13,6 @@ using System.Runtime.InteropServices; namespace BizHawk.Emulation.Consoles.Nintendo.SNES { - //TODO - wrap around some kind of library-accessing interface so that it doesnt malfunction if the dll is unavailable public unsafe static class LibsnesDll { [DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] @@ -59,16 +63,49 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES [MarshalAs(UnmanagedType.LPArray)] byte[] rom_data, int rom_size); - public enum Device : uint + [DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.U1)] + public static extern SNES_REGION snes_get_region(); + + [DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern uint snes_get_memory_size(SNES_MEMORY id); + [DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint="snes_get_memory_data")] + public static extern IntPtr snes_get_memory_data(SNES_MEMORY id); + + public enum SNES_MEMORY : uint { - None, - Joypad, - Multitap, - Mouse, - SuperScope, - Justifier, - Justifiers, - USART, + CARTRIDGE_RAM = 0, + CARTRIDGE_RTC = 1, + BSX_RAM = 2, + BSX_PRAM = 3, + SUFAMI_TURBO_A_RAM = 4, + SUFAMI_TURBO_B_RAM = 5, + GAME_BOY_RAM = 6, + GAME_BOY_RTC = 7, + + WRAM = 100, + APURAM = 101, + VRAM = 102, + OAM = 103, + CGRAM = 104, + } + + public enum SNES_REGION : uint + { + NTSC = 0, + PAL = 1, + } + + public enum SNES_DEVICE : uint + { + NONE = 0, + JOYPAD = 1, + MULTITAP = 2, + MOUSE = 3, + SUPER_SCOPE = 4, + JUSTIFIER = 5, + JUSTIFIERS = 6, + SERIAL_CABLE = 7 } public enum SNES_DEVICE_ID : uint @@ -88,8 +125,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES } } - //TODO - libsnes needs to be modified to support multiple instances - //TODO - rename snes.dll so nobody thinks it's a stock snes.dll (we'll be editing it substantially at some point) public unsafe class LibsnesCore : IEmulator, IVideoProvider, ISoundProvider { static LibsnesCore() @@ -140,7 +175,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES //Console.WriteLine("{0} {1} {2} {3}", port, device, index, id); string key = "P" + (1 + port) + " "; - if ((LibsnesDll.Device)device == LibsnesDll.Device.Joypad) + if ((LibsnesDll.SNES_DEVICE)device == LibsnesDll.SNES_DEVICE.JOYPAD) { switch((LibsnesDll.SNES_DEVICE_ID)id) { @@ -236,8 +271,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES public bool IsLagFrame { get; private set; } public string SystemId { get { return "SNES"; } } public bool DeterministicEmulation { get; set; } - public byte[] SaveRam { get { return new byte[0]; } } - public bool SaveRamModified { get; set; } + public bool SaveRamModified + { + set { } + get + { + return LibsnesDll.snes_get_memory_size(LibsnesDll.SNES_MEMORY.CARTRIDGE_RAM) != 0; + } + } + + public byte[] ReadSaveRam { get { return snes_get_memory_data_read(LibsnesDll.SNES_MEMORY.CARTRIDGE_RAM); } } + public static byte[] snes_get_memory_data_read(LibsnesDll.SNES_MEMORY id) + { + var size = (int)LibsnesDll.snes_get_memory_size(id); + var data = LibsnesDll.snes_get_memory_data(id); + var ret = new byte[size]; + Marshal.Copy(data,ret,0,size); + return ret; + } + + public void StoreSaveRam(byte[] data) + { + var size = (int)LibsnesDll.snes_get_memory_size(LibsnesDll.SNES_MEMORY.CARTRIDGE_RAM); + var emudata = LibsnesDll.snes_get_memory_data(LibsnesDll.SNES_MEMORY.CARTRIDGE_RAM); + Marshal.Copy(data, 0, emudata, size); + } public void ResetFrameCounter() { } public void SaveStateText(TextWriter writer) { } diff --git a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs index b1ef10f795..432c660eec 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs @@ -277,7 +277,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx public string Region { get; set; } public bool DeterministicEmulation { get; set; } - public byte[] SaveRam + public byte[] ReadSaveRam { get { return BRAM; } } diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs index 77836d3397..7333cf4b5b 100644 --- a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs @@ -258,7 +258,7 @@ namespace BizHawk.Emulation.Consoles.Sega public bool DeterministicEmulation { get; set; } public string SystemId { get { return "GEN"; } } - public byte[] SaveRam + public byte[] ReadSaveRam { get { throw new NotImplementedException(); } } diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs index 945ae72dd1..056ce7b984 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs @@ -31,7 +31,7 @@ namespace BizHawk.Emulation.Consoles.Sega public byte[] SaveRAM = new byte[BankSize * 2]; public byte SaveRamBank; - public byte[] SaveRam { get { return SaveRAM; } } + public byte[] ReadSaveRam { get { return SaveRAM; } } public bool SaveRamModified { get; set; } // Machine resources diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs index 73e30f3d4e..72c0d3d4ac 100644 --- a/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs +++ b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs @@ -41,7 +41,7 @@ namespace BizHawk public int LagCount { get { return 0; } set { return; } } public bool IsLagFrame { get { return false; } } - public byte[] SaveRam { get { return new byte[0]; } } + public byte[] ReadSaveRam { get { return new byte[0]; } } public bool DeterministicEmulation { get; set; } public bool SaveRamModified { get; set; } public void SaveStateText(TextWriter writer) { } diff --git a/BizHawk.Emulation/Interfaces/IEmulator.cs b/BizHawk.Emulation/Interfaces/IEmulator.cs index 3359c9e5c8..2dd28feb44 100644 --- a/BizHawk.Emulation/Interfaces/IEmulator.cs +++ b/BizHawk.Emulation/Interfaces/IEmulator.cs @@ -20,7 +20,12 @@ namespace BizHawk string SystemId { get; } bool DeterministicEmulation { get; set; } - byte[] SaveRam { get; } + /// + /// Don't edit this data, it may be useless as it may be a copy or some compiled data. + /// use StoreSaveRam if you want to store sram into the core. + /// Well, this rule is being violated. This comment is just a reminder that this is a bad architecture + /// + byte[] ReadSaveRam { get; } bool SaveRamModified { get; set; } void ResetFrameCounter(); diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index c60c8e0e4d..11068d4770 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -1537,12 +1537,18 @@ namespace BizHawk.MultiClient DumpStatus.ToolTipText = annotation; } + private void LoadSaveRam() { + //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(Global.Emulator.SaveRam, 0, Global.Emulator.SaveRam.Length); + 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); } catch { } } @@ -1569,8 +1575,8 @@ namespace BizHawk.MultiClient f.Directory.Create(); var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write)); - int len = Util.SaveRamBytesUsed(Global.Emulator.SaveRam); - writer.Write(Global.Emulator.SaveRam, 0, len); + int len = Util.SaveRamBytesUsed(Global.Emulator.ReadSaveRam); + writer.Write(Global.Emulator.ReadSaveRam, 0, len); writer.Close(); }