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