1 using System; 2 using System.Collections.Generic; 3 using System.Collections.ObjectModel; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using System.Windows.Forms; 8 9 namespace Mesen.GUI.Debugger 10 { 11 public class BreakpointManager 12 { 13 private static object _lock = new object(); 14 private static List<Breakpoint> _breakpoints = new List<Breakpoint>(); 15 16 public static event EventHandler BreakpointsChanged; 17 public static ReadOnlyCollection<Breakpoint> Breakpoints { 18 get { 19 lock(_lock) { 20 return _breakpoints.ToList().AsReadOnly(); 21 } 22 } 23 } 24 RefreshBreakpoints(Breakpoint bp = null)25 public static void RefreshBreakpoints(Breakpoint bp = null) 26 { 27 if(BreakpointsChanged != null) { 28 BreakpointsChanged(bp, null); 29 } 30 31 SetBreakpoints(); 32 } 33 SetBreakpoints(List<Breakpoint> breakpoints)34 public static void SetBreakpoints(List<Breakpoint> breakpoints) 35 { 36 lock(_lock) { 37 _breakpoints = breakpoints.ToList(); 38 } 39 40 RefreshBreakpoints(); 41 } 42 EditBreakpoint(Breakpoint bp)43 public static void EditBreakpoint(Breakpoint bp) 44 { 45 if(new frmBreakpoint(bp).ShowDialog() == DialogResult.OK) { 46 lock(_lock) { 47 if(!_breakpoints.Contains(bp)) { 48 _breakpoints.Add(bp); 49 } 50 } 51 RefreshBreakpoints(bp); 52 } 53 } 54 RemoveBreakpoint(Breakpoint bp)55 public static void RemoveBreakpoint(Breakpoint bp) 56 { 57 lock(_lock) { 58 _breakpoints.Remove(bp); 59 } 60 RefreshBreakpoints(bp); 61 } 62 AddBreakpoint(Breakpoint bp)63 public static void AddBreakpoint(Breakpoint bp) 64 { 65 lock(_lock) { 66 _breakpoints.Add(bp); 67 } 68 RefreshBreakpoints(bp); 69 } 70 GetMatchingBreakpoint(int relativeAddress, AddressTypeInfo info)71 public static Breakpoint GetMatchingBreakpoint(int relativeAddress, AddressTypeInfo info) 72 { 73 return Breakpoints.Where((bp) => bp.Matches(relativeAddress, info)).FirstOrDefault(); 74 } 75 GetMatchingBreakpoint(UInt32 startAddress, UInt32 endAddress, DebugMemoryType memoryType)76 public static Breakpoint GetMatchingBreakpoint(UInt32 startAddress, UInt32 endAddress, DebugMemoryType memoryType) 77 { 78 bool isAddressRange = startAddress != endAddress; 79 return Breakpoints.Where((bp) => 80 bp.MemoryType == memoryType && 81 ((!isAddressRange && bp.Address == startAddress) || (isAddressRange && bp.StartAddress == startAddress && bp.EndAddress == endAddress)) 82 ).FirstOrDefault(); 83 } 84 ToggleBreakpoint(AddressTypeInfo info, bool toggleEnabled)85 public static void ToggleBreakpoint(AddressTypeInfo info, bool toggleEnabled) 86 { 87 if(info.Address >= 0) { 88 Breakpoint breakpoint = BreakpointManager.GetMatchingBreakpoint(InteropEmu.DebugGetRelativeAddress((uint)info.Address, info.Type), info); 89 if(breakpoint != null) { 90 if(toggleEnabled) { 91 breakpoint.SetEnabled(!breakpoint.Enabled); 92 } else { 93 BreakpointManager.RemoveBreakpoint(breakpoint); 94 } 95 } else { 96 if(info.Type == AddressType.InternalRam) { 97 breakpoint = new Breakpoint() { 98 MemoryType = DebugMemoryType.CpuMemory, 99 BreakOnExec = true, 100 BreakOnRead = true, 101 BreakOnWrite = true, 102 Address = (UInt32)info.Address, 103 Enabled = true 104 }; 105 } else { 106 breakpoint = new Breakpoint() { 107 Enabled = true, 108 BreakOnExec = true, 109 Address = (UInt32)info.Address 110 }; 111 112 if(info.Type != AddressType.PrgRom) { 113 breakpoint.BreakOnRead = true; 114 breakpoint.BreakOnWrite = true; 115 } 116 117 breakpoint.MemoryType = info.Type.ToMemoryType(); 118 } 119 BreakpointManager.AddBreakpoint(breakpoint); 120 } 121 } 122 } 123 SetBreakpoints()124 public static void SetBreakpoints() 125 { 126 List<InteropBreakpoint> breakpoints = new List<InteropBreakpoint>(); 127 for(int i = 0; i < Breakpoints.Count; i++) { 128 breakpoints.Add(Breakpoints[i].ToInteropBreakpoint(i)); 129 } 130 InteropEmu.DebugSetBreakpoints(breakpoints.ToArray(), (UInt32)breakpoints.Count); 131 } 132 } 133 } 134