diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs index 9aae5fc2f7..6e0544a298 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs @@ -17,6 +17,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo public APU apu; byte[] ram; MemoryDomain.FreezeData[] sysbus_freeze = new MemoryDomain.FreezeData[65536]; + NESWatch[] sysbus_watch = new NESWatch[65536]; protected byte[] CIRAM; //AKA nametables string game_name; //friendly name exposed to user and used as filename base CartInfo cart; //the current cart prototype. should be moved into the board, perhaps @@ -214,9 +215,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo //handle breakpoints and stuff. //the idea is that each core can implement its own watch class on an address which will track all the different kinds of monitors and breakpoints and etc. //but since freeze is a common case, it was implemented through its own mechanisms - if (sysbus_freeze[addr].HasWatch) + if (sysbus_watch[addr] != null) { - (sysbus_freeze[addr].watch as NESWatch).Read(); + sysbus_watch[addr].Sync(); + ret = sysbus_watch[addr].ApplyGameGenie(ret); } return ret; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index 322e54ade7..44b2c32f1e 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -34,14 +34,76 @@ namespace BizHawk.Emulation.Consoles.Nintendo SetPalette(Palettes.FCEUX_Standard); } + NESWatch GetWatch(NESWatch.EDomain domain, int address) + { + if (domain == NESWatch.EDomain.Sysbus) + { + NESWatch ret = sysbus_watch[address] ?? new NESWatch(this,domain,address); + sysbus_watch[address] = ret; + return ret; + } + return null; + } + class NESWatch { - public Action OnRead; - - public void Read() + public enum EDomain { - if (OnRead != null) OnRead(); + Sysbus } + public NESWatch(NES nes, EDomain domain, int address) + { + Address = address; + Domain = domain; + if (domain == EDomain.Sysbus) + { + watches = nes.sysbus_watch; + } + } + public int Address; + public EDomain Domain; + + public enum EFlags + { + None = 0, + GameGenie = 1, + ReadPrint = 2 + } + EFlags flags; + + public void Sync() + { + if (flags == EFlags.None) + watches[Address] = null; + else watches[Address] = this; + } + + public void SetGameGenie(int check, int replace) + { + flags |= EFlags.GameGenie; + gg_check = check; + gg_replace = replace; + Sync(); + } + + public bool HasGameGenie { get { return (flags & EFlags.GameGenie) != 0; } } + public byte ApplyGameGenie(byte curr) + { + if (!HasGameGenie) return curr; + if (curr == gg_check || gg_check == -1) { Console.WriteLine("applied game genie"); return (byte)gg_replace; } + else return curr; + } + + public void RemoveGameGenie() + { + flags &= ~EFlags.GameGenie; + Sync(); + } + + int gg_check, gg_replace; + + + NESWatch[] watches; } public enum EMirrorType @@ -194,12 +256,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo SystemBus.GetFreeze = addr => sysbus_freeze[addr]; SystemBus.SetFreeze = (addr,value) => sysbus_freeze[addr] = value; - //demo a watchpoint - var test = new NESWatch(); - test.OnRead = () => Console.WriteLine("0x8000 was read!"); - MemoryDomain.FreezeData temp = SystemBus.GetFreeze(0x8000); - temp.SetWatch(test); - SystemBus.SetFreeze(0x8000,temp); + //demo a game genie code + GetWatch(NESWatch.EDomain.Sysbus, 0xB424).SetGameGenie(-1, 0x10); + GetWatch(NESWatch.EDomain.Sysbus, 0xB424).RemoveGameGenie(); domains.Add(RAM); domains.Add(SystemBus); diff --git a/BizHawk.Emulation/Interfaces/IEmulator.cs b/BizHawk.Emulation/Interfaces/IEmulator.cs index c06fb96135..29c8e95901 100644 --- a/BizHawk.Emulation/Interfaces/IEmulator.cs +++ b/BizHawk.Emulation/Interfaces/IEmulator.cs @@ -56,24 +56,17 @@ namespace BizHawk { this.flags = flags; this.value = value; - watch = null; } public byte value; public Flag flags; - public object watch; - public void SetWatch(object watch) - { - this.watch = watch; - } public enum Flag : byte { None = 0, - Frozen = 1 + Frozen = 1, } public bool IsFrozen { get { return (flags & Flag.Frozen) != 0; } } - public bool HasWatch { get { return watch != null; } } - public static FreezeData Unfrozen { get { return new FreezeData(); } } + public static FreezeData Empty { get { return new FreezeData(); } } } public readonly Func PeekByte;