diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs index 783e185b03..999a402920 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs @@ -369,6 +369,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo ret = sysbus_watch[addr].ApplyGameGenie(ret); } + if (CoreInputComm.MemoryCallbackSystem.ReadCallback != null) + { + CoreInputComm.MemoryCallbackSystem.TriggerRead(addr); + } + DB = ret; return ret; @@ -420,6 +425,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo { board.WritePRG(addr - 0x8000, value); } + + if (CoreInputComm.MemoryCallbackSystem.WriteCallback != null) + { + CoreInputComm.MemoryCallbackSystem.WriteCallback(); + } } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index e372e03497..ba7cc4f52f 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo { CoreOutputComm = new CoreOutputComm(); CoreOutputComm.CpuTraceAvailable = true; + CoreInputComm = new BizHawk.CoreInputComm(); BootGodDB.Initialize(); SetPalette(Palettes.FCEUX_Standard); videoProvider = new MyVideoProvider(this); diff --git a/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs index ca3a2163a1..c0a661674e 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs @@ -1,73 +1,83 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx { - public partial class PCEngine - { - byte IOBuffer; + public partial class PCEngine + { + byte IOBuffer; - byte ReadMemory(int addr) - { - if (addr < 0xFFFFF) // read ROM - return RomData[addr % RomLength]; + byte ReadMemory(int addr) + { + if (addr < 0xFFFFF) // read ROM + return RomData[addr % RomLength]; - if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM - return Ram[addr & 0x1FFF]; + if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM + return Ram[addr & 0x1FFF]; - if (addr >= 0x1FE000) // hardware page. - { - if (addr < 0x1FE400) return VDC1.ReadVDC(addr); - if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); } - if (addr < 0x1FEC00) return IOBuffer; - if (addr < 0x1FF000) { IOBuffer = (byte) (Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; } - if (addr >= 0x1FF000 && - addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; } - if ((addr & ~1) == 0x1FF400) return IOBuffer; - if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; } - if (addr == 0x1FF403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; } - if (addr >= 0x1FF800) return ReadCD(addr); - } + if (addr >= 0x1FE000) // hardware page. + { + if (addr < 0x1FE400) return VDC1.ReadVDC(addr); + if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); } + if (addr < 0x1FEC00) return IOBuffer; + if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; } + if (addr >= 0x1FF000 && + addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; } + if ((addr & ~1) == 0x1FF400) return IOBuffer; + if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; } + if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; } + if (addr >= 0x1FF800) return ReadCD(addr); + } - if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM - { - if (BramEnabled && BramLocked == false) - return BRAM[addr & 0x7FF]; - return 0xFF; - } + if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM + { + if (BramEnabled && BramLocked == false) + return BRAM[addr & 0x7FF]; + return 0xFF; + } - Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr); - return 0xFF; - } + if (CoreInputComm.MemoryCallbackSystem.ReadCallback != null) + { + CoreInputComm.MemoryCallbackSystem.TriggerRead(addr); + } - void WriteMemory(int addr, byte value) - { - if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. - Ram[addr & 0x1FFF] = value; + Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr); + return 0xFF; + } - else if (addr >= 0x1FE000) // hardware page. - { - if (addr < 0x1FE400) VDC1.WriteVDC(addr, value); - else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); } - else if (addr < 0x1FEC00) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); } - else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); } - else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } - else if (addr >= 0x1FF000 && - addr < 0x1FF400) { IOBuffer = value; WriteInput(value); } - else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); } - else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); } - else if (addr >= 0x1FF800) { WriteCD(addr, value); } - else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value); - } + void WriteMemory(int addr, byte value) + { + if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. + Ram[addr & 0x1FFF] = value; - else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM - { - if (BramEnabled && BramLocked == false) - { - BRAM[addr & 0x7FF] = value; - SaveRamModified = true; - } - } + else if (addr >= 0x1FE000) // hardware page. + { + if (addr < 0x1FE400) VDC1.WriteVDC(addr, value); + else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); } + else if (addr < 0x1FEC00) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); } + else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); } + else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } + else if (addr >= 0x1FF000 && + addr < 0x1FF400) { IOBuffer = value; WriteInput(value); } + else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); } + else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); } + else if (addr >= 0x1FF800) { WriteCD(addr, value); } + else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value); + } - else - Log.Error("MEM","UNHANDLED WRITE: {0:X6}:{1:X2}",addr,value); - } - } + else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM + { + if (BramEnabled && BramLocked == false) + { + BRAM[addr & 0x7FF] = value; + SaveRamModified = true; + } + } + + else + Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value); + + if (CoreInputComm.MemoryCallbackSystem.WriteCallback != null) + { + CoreInputComm.MemoryCallbackSystem.WriteCallback(); + } + } + } } \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/CoreComms.cs b/BizHawk.Emulation/Interfaces/CoreComms.cs index 8a130dfb69..fc0b6d58ac 100644 --- a/BizHawk.Emulation/Interfaces/CoreComms.cs +++ b/BizHawk.Emulation/Interfaces/CoreComms.cs @@ -25,6 +25,8 @@ namespace BizHawk /// for emu.on_snoop() /// public System.Action InputCallback; + + public MemoryCallbackSystem MemoryCallbackSystem = new MemoryCallbackSystem(); } public class CoreOutputComm @@ -93,4 +95,49 @@ namespace BizHawk private StringBuilder buffer; private bool logging = false; } + + public class MemoryCallbackSystem + { + public int? ReadAddr = null; + public System.Action ReadCallback = null; + + public void TriggerRead(int addr) + { + if (ReadCallback != null) + { + if (ReadAddr != null) + { + if (ReadAddr == addr) + { + ReadCallback(); + } + } + else + { + ReadCallback(); + } + } + } + + public int? WriteAddr = null; + public System.Action WriteCallback = null; + + public void TriggerWrite(int addr) + { + if (WriteCallback != null) + { + if (WriteAddr != null) + { + if (WriteAddr == addr) + { + WriteCallback(); + } + } + else + { + WriteCallback(); + } + } + } + } } diff --git a/BizHawk.MultiClient/LuaImplementation.cs b/BizHawk.MultiClient/LuaImplementation.cs index aca9a8f2f8..3771e47ec1 100644 --- a/BizHawk.MultiClient/LuaImplementation.cs +++ b/BizHawk.MultiClient/LuaImplementation.cs @@ -457,8 +457,6 @@ namespace BizHawk.MultiClient "write_u32_be", "readbyterange", "writebyterange", - //"registerwrite", - //"registerread", }; public static string[] SaveStateFunctions = new string[] @@ -568,8 +566,8 @@ namespace BizHawk.MultiClient "onsavestate", "onframestart", "onframeend", - //"onmemoryread", - //"onmemorywrite", + "onmemoryread", + "onmemorywrite", "oninputpoll", }; /****************************************************/ @@ -2683,5 +2681,79 @@ namespace BizHawk.MultiClient { emu_on_snoop(luaf); } + + public void event_onmemoryread(LuaFunction luaf, object address = null) + { + //TODO: allow a list of addresses + if (luaf != null) + { + int? _addr; + if (address == null) + { + _addr = null; + } + else + { + _addr = LuaInt(address); + } + + Global.Emulator.CoreInputComm.MemoryCallbackSystem.ReadAddr = _addr; + Global.Emulator.CoreInputComm.MemoryCallbackSystem.ReadCallback = delegate() + { + try + { + luaf.Call(); + } + catch (SystemException e) + { + Global.MainForm.LuaConsole1.WriteToOutputWindow( + "error running function attached by lua function event.onmemoryread" + + "\nError message: " + e.Message); + } + }; + + } + else + { + Global.Emulator.CoreInputComm.MemoryCallbackSystem.ReadCallback = null; + } + } + + + public void event_onmemorywrite(LuaFunction luaf, object address = null) + { + //TODO: allow a list of addresses + if (luaf != null) + { + int? _addr; + if (address == null) + { + _addr = null; + } + else + { + _addr = LuaInt(address); + } + + Global.Emulator.CoreInputComm.MemoryCallbackSystem.WriteAddr = _addr; + Global.Emulator.CoreInputComm.MemoryCallbackSystem.WriteCallback = delegate() + { + try + { + luaf.Call(); + } + catch (SystemException e) + { + Global.MainForm.LuaConsole1.WriteToOutputWindow( + "error running function attached by lua function event.onmemoryread" + + "\nError message: " + e.Message); + } + }; + } + else + { + Global.Emulator.CoreInputComm.MemoryCallbackSystem.WriteCallback = null; + } + } } }