diff --git a/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs b/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs index 29787c0eb4..9f21571986 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs @@ -222,8 +222,61 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 public bool BinarySaveStatesPreferred { get { return true; } } + #region memorydomains + + MemoryDomain MakeMemoryDomain(string name, mupen64plusApi.N64_MEMORY id, Endian endian) + { + int size = api.get_memory_size(id); + + //if this type of memory isnt available, dont make the memory domain + if (size == 0) + return null; + + IntPtr memPtr = api.get_memory_ptr(id); + + MemoryDomain md = new MemoryDomain( + name, + size, + endian, + delegate(int addr) + { + if (addr < 0 || addr >= size) + throw new ArgumentOutOfRangeException(); + return Marshal.ReadByte(memPtr, addr); + }, + delegate(int addr, byte val) + { + if (addr < 0 || addr >= size) + throw new ArgumentOutOfRangeException(); + Marshal.WriteByte(memPtr + addr, val); + }); + + MemoryDomains.Add(md); + + return md; + } + + void InitMemoryDomains() + { + MemoryDomains = new List(); + MakeMemoryDomain("RDRAM", mupen64plusApi.N64_MEMORY.RDRAM, Endian.Little); + MakeMemoryDomain("PI Register", mupen64plusApi.N64_MEMORY.PI_REG, Endian.Little); + MakeMemoryDomain("SI Register", mupen64plusApi.N64_MEMORY.SI_REG, Endian.Little); + MakeMemoryDomain("VI Register", mupen64plusApi.N64_MEMORY.VI_REG, Endian.Little); + MakeMemoryDomain("RI Register", mupen64plusApi.N64_MEMORY.RI_REG, Endian.Little); + MakeMemoryDomain("AI Register", mupen64plusApi.N64_MEMORY.AI_REG, Endian.Little); + + MakeMemoryDomain("EEPROM", mupen64plusApi.N64_MEMORY.EEPROM, Endian.Little); + MakeMemoryDomain("Mempak 1", mupen64plusApi.N64_MEMORY.MEMPAK1, Endian.Little); + MakeMemoryDomain("Mempak 2", mupen64plusApi.N64_MEMORY.MEMPAK2, Endian.Little); + MakeMemoryDomain("Mempak 3", mupen64plusApi.N64_MEMORY.MEMPAK3, Endian.Little); + MakeMemoryDomain("Mempak 4", mupen64plusApi.N64_MEMORY.MEMPAK4, Endian.Little); + } + public IList MemoryDomains { get; private set; } - public MemoryDomain MainMemory { get; private set; } + public MemoryDomain MainMemory { get { return MemoryDomains[0]; } } + + #endregion public void Dispose() { @@ -241,9 +294,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 api = new mupen64plusApi(this, rom, video_settings); api.SetM64PInputCallback(new mupen64plusApi.InputCallback(setControllers)); - MemoryDomains = new List(); - MemoryDomains.Add(new MemoryDomain("RDRAM", 0x400000, Endian.Little, api.getRDRAMByte, api.setRDRAMByte)); - MainMemory = MemoryDomains[0]; + InitMemoryDomains(); } } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/N64/mupen64plusApi.cs b/BizHawk.Emulation/Consoles/Nintendo/N64/mupen64plusApi.cs index 38392edb99..35186eb03d 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/N64/mupen64plusApi.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/N64/mupen64plusApi.cs @@ -101,15 +101,21 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 M64TYPE_STRING }; - enum m64p_dbg_memptr_type + public enum N64_MEMORY : uint { - M64P_DBG_PTR_RDRAM = 1, - M64P_DBG_PTR_PI_REG, - M64P_DBG_PTR_SI_REG, - M64P_DBG_PTR_VI_REG, - M64P_DBG_PTR_RI_REG, - M64P_DBG_PTR_AI_REG - }; + RDRAM = 1, + PI_REG, + SI_REG, + VI_REG, + RI_REG, + AI_REG, + + EEPROM = 100, + MEMPAK1, + MEMPAK2, + MEMPAK3, + MEMPAK4 + } // Core Specifc functions @@ -201,9 +207,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 /// The section to get a pointer for /// A pointer to the section requested [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - delegate IntPtr DebugMemGetPointer(m64p_dbg_memptr_type mem_ptr_type); + delegate IntPtr DebugMemGetPointer(N64_MEMORY mem_ptr_type); DebugMemGetPointer m64pDebugMemGetPointer; + /// + /// Gets the size of the given memory area + /// + /// The section to get the size of + /// The size of the section requested + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + delegate int MemGetSize(N64_MEMORY mem_ptr_type); + MemGetSize m64pMemGetSize; + /// /// Initializes the saveram (eeprom and 4 mempacks) /// @@ -477,9 +492,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 m64pVICallback = new VICallback(VI); result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback); - // Get the pointer for RDRAM - rdram = m64pDebugMemGetPointer(m64p_dbg_memptr_type.M64P_DBG_PTR_RDRAM); - InitSaveram(); // Start the emulator in another thread @@ -526,6 +538,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 m64pCoreSaveState = (savestates_save_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_save_bkm"), typeof(savestates_save_bkm)); m64pCoreLoadState = (savestates_load_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_load_bkm"), typeof(savestates_load_bkm)); m64pDebugMemGetPointer = (DebugMemGetPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugMemGetPointer"), typeof(DebugMemGetPointer)); + m64pMemGetSize = (MemGetSize)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "MemGetSize"), typeof(MemGetSize)); m64pinit_saveram = (init_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "init_saveram"), typeof(init_saveram)); m64psave_saveram = (save_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "save_saveram"), typeof(save_saveram)); m64pload_saveram = (load_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "load_saveram"), typeof(load_saveram)); @@ -651,18 +664,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 m64pFrameComplete.Set(); } - IntPtr rdram; - public byte getRDRAMByte(int address) + public int get_memory_size(N64_MEMORY id) { - byte[] result = new byte[1]; - System.Runtime.InteropServices.Marshal.Copy(rdram + address, result, 0, 1); - return result[0]; + return m64pMemGetSize(id); } - public void setRDRAMByte(int address, byte data) + + public IntPtr get_memory_ptr(N64_MEMORY id) { - byte[] result = new byte[1]; - result[0] = data; - System.Runtime.InteropServices.Marshal.Copy(result, 0, rdram + address, 1); + return m64pDebugMemGetPointer(id); } public void set_buttons(int num, int keys, sbyte X, sbyte Y) diff --git a/BizHawk.MultiClient/output/dll/mupen64plus.dll b/BizHawk.MultiClient/output/dll/mupen64plus.dll index 5f58778377..0b8a9a97d8 100644 Binary files a/BizHawk.MultiClient/output/dll/mupen64plus.dll and b/BizHawk.MultiClient/output/dll/mupen64plus.dll differ diff --git a/libmupen64plus/mupen64plus-core/src/api/debugger.c b/libmupen64plus/mupen64plus-core/src/api/debugger.c index 89d19994ab..65b4079fdd 100644 --- a/libmupen64plus/mupen64plus-core/src/api/debugger.c +++ b/libmupen64plus/mupen64plus-core/src/api/debugger.c @@ -220,12 +220,56 @@ EXPORT void * CALL DebugMemGetPointer(m64p_dbg_memptr_type mem_ptr_type) return &ri_register; case M64P_DBG_PTR_AI_REG: return &ai_register; + + case EEPROM: + return eeprom; + case MEMPAK1: + return mempack[0]; + case MEMPAK2: + return mempack[1]; + case MEMPAK3: + return mempack[2]; + case MEMPAK4: + return mempack[3]; default: DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetPointer() called with invalid m64p_dbg_memptr_type"); return NULL; } } +EXPORT int CALL MemGetSize(m64p_dbg_memptr_type mem_ptr_type) +{ + switch (mem_ptr_type) + { + case M64P_DBG_PTR_RDRAM: + return 0x800000; + case M64P_DBG_PTR_PI_REG: + return sizeof(PI_register); + case M64P_DBG_PTR_SI_REG: + return sizeof(SI_register); + case M64P_DBG_PTR_VI_REG: + return sizeof(VI_register); + case M64P_DBG_PTR_RI_REG: + return sizeof(RI_register); + case M64P_DBG_PTR_AI_REG: + return sizeof(AI_register); + + case EEPROM: + return 0x800; + case MEMPAK1: + return 0x8000; + case MEMPAK2: + return 0x8000; + case MEMPAK3: + return 0x8000; + case MEMPAK4: + return 0x8000; + default: + DebugMessage(M64MSG_ERROR, "Bug: MemGetSize() called with invalid m64p_dbg_memptr_type"); + return NULL; + } +} + EXPORT unsigned long long CALL DebugMemRead64(unsigned int address) { #ifdef DBG diff --git a/libmupen64plus/mupen64plus-core/src/api/m64p_types.h b/libmupen64plus/mupen64plus-core/src/api/m64p_types.h index bb08162c44..4e72c5f12b 100644 --- a/libmupen64plus/mupen64plus-core/src/api/m64p_types.h +++ b/libmupen64plus/mupen64plus-core/src/api/m64p_types.h @@ -257,7 +257,13 @@ typedef enum { M64P_DBG_PTR_SI_REG, M64P_DBG_PTR_VI_REG, M64P_DBG_PTR_RI_REG, - M64P_DBG_PTR_AI_REG + M64P_DBG_PTR_AI_REG, + + EEPROM = 100, + MEMPAK1, + MEMPAK2, + MEMPAK3, + MEMPAK4 } m64p_dbg_memptr_type; typedef enum { diff --git a/libmupen64plus/mupen64plus-core/src/memory/memory.h b/libmupen64plus/mupen64plus-core/src/memory/memory.h index 2efeada159..a77094f6a2 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/memory.h +++ b/libmupen64plus/mupen64plus-core/src/memory/memory.h @@ -409,5 +409,8 @@ void update_vi_width(unsigned int word); * Useful for getting fast access to a zone with executable code. */ unsigned int *fast_mem_access(unsigned int address); +extern unsigned char eeprom[0x800]; +extern unsigned char mempack[4][0x8000]; + #endif diff --git a/libmupen64plus/mupen64plus-core/src/memory/pif.c b/libmupen64plus/mupen64plus-core/src/memory/pif.c index d33b883380..2b3319f8b4 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/pif.c +++ b/libmupen64plus/mupen64plus-core/src/memory/pif.c @@ -39,8 +39,8 @@ #include "main/util.h" #include "plugin/plugin.h" -static unsigned char eeprom[0x800]; -static unsigned char mempack[4][0x8000]; +unsigned char eeprom[0x800]; +unsigned char mempack[4][0x8000]; int saveramModified = 0; /*static char *get_eeprom_path(void)