1 using Mesen.GUI.Forms;
2 using System;
3 using System.Collections.Generic;
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 DebugWindowManager
12 	{
13 		private static HashSet<Form> _openedWindows = new HashSet<Form>();
14 
GetWindows()15 		public static List<Form> GetWindows()
16 		{
17 			return new List<Form>(_openedWindows);
18 		}
19 
20 		public static bool ScriptWindowOpened { get { return _openedWindows.Any(wnd => wnd is frmScript); } }
21 
OpenDebugWindow(DebugWindow window)22 		public static Form OpenDebugWindow(DebugWindow window)
23 		{
24 			Form existingWindow = GetExistingSingleInstanceWindow(window);
25 			if(existingWindow != null) {
26 				existingWindow.BringToFront();
27 				if(existingWindow.WindowState == FormWindowState.Minimized) {
28 					//Unminimize window if it was minimized
29 					existingWindow.WindowState = FormWindowState.Normal;
30 				}
31 				existingWindow.Focus();
32 				return existingWindow;
33 			} else {
34 				BaseForm frm = null;
35 				switch(window) {
36 					case DebugWindow.PpuViewer: frm = new frmPpuViewer(); frm.Icon = Properties.Resources.Video; break;
37 					case DebugWindow.TraceLogger: frm = new frmTraceLogger(); frm.Icon = Properties.Resources.LogWindow; break;
38 					case DebugWindow.MemoryViewer: frm = new frmMemoryViewer(); frm.Icon = Properties.Resources.CheatCode; break;
39 					case DebugWindow.Assembler: frm = new frmAssembler(); frm.Icon = Properties.Resources.Chip; break;
40 					case DebugWindow.Debugger: frm = new frmDebugger(); frm.Icon = Properties.Resources.Bug; break;
41 					case DebugWindow.ScriptWindow: frm = new frmScript(); frm.Icon = Properties.Resources.Script; break;
42 					case DebugWindow.ApuViewer: frm = new frmApuViewer(); frm.Icon = Properties.Resources.Audio; break;
43 					case DebugWindow.EventViewer: frm = new frmEventViewer(); frm.Icon = Properties.Resources.NesEventViewer; break;
44 					case DebugWindow.TextHooker: frm = new frmTextHooker(); frm.Icon = Properties.Resources.Font; break;
45 					case DebugWindow.Profiler: frm = new frmProfiler(); frm.Icon = Properties.Resources.Speed; break;
46 					case DebugWindow.WatchWindow: frm = new frmWatchWindow(); frm.Icon = Properties.Resources.Find; break;
47 				}
48 				_openedWindows.Add(frm);
49 				frm.FormClosed += Debugger_FormClosed;
50 				frm.Show();
51 				return frm;
52 			}
53 		}
54 
OpenAssembler(string code = R, UInt16 startAddress = 0, UInt16 blockLength = 0)55 		public static void OpenAssembler(string code = "", UInt16 startAddress = 0, UInt16 blockLength = 0)
56 		{
57 			frmAssembler frm = new frmAssembler(code, startAddress, blockLength);
58 			frm.Icon = Properties.Resources.Chip;
59 			_openedWindows.Add(frm);
60 			frm.FormClosed += Debugger_FormClosed;
61 			frm.Show();
62 		}
63 
OpenMemoryViewer()64 		private static frmMemoryViewer OpenMemoryViewer()
65 		{
66 			frmMemoryViewer frm = GetMemoryViewer();
67 			if(frm == null) {
68 				frm = new frmMemoryViewer();
69 				frm.Icon = Properties.Resources.CheatCode;
70 				frm.FormClosed += Debugger_FormClosed;
71 				_openedWindows.Add(frm);
72 			} else {
73 				if(frm.WindowState == FormWindowState.Minimized) {
74 					//Unminimize window if it was minimized
75 					frm.WindowState = FormWindowState.Normal;
76 				}
77 				frm.BringToFront();
78 			}
79 			frm.Show();
80 			return frm;
81 		}
82 
OpenMemoryViewer(int address, DebugMemoryType memoryType)83 		public static void OpenMemoryViewer(int address, DebugMemoryType memoryType)
84 		{
85 			frmMemoryViewer frm = OpenMemoryViewer();
86 			frm.ShowAddress(address, memoryType);
87 		}
88 
OpenMemoryViewer(GoToDestination dest)89 		public static void OpenMemoryViewer(GoToDestination dest)
90 		{
91 			frmMemoryViewer frm = OpenMemoryViewer();
92 			frm.GoToDestination(dest);
93 		}
94 
OpenPpuViewer(PpuViewerMode mode)95 		public static frmPpuViewer OpenPpuViewer(PpuViewerMode mode)
96 		{
97 			frmPpuViewer frm = new frmPpuViewer(mode);
98 			frm.Icon = Properties.Resources.Video;
99 			_openedWindows.Add(frm);
100 			frm.FormClosed += Debugger_FormClosed;
101 			frm.Show();
102 			return frm;
103 		}
104 
OpenScriptWindow(bool forceBlank)105 		public static frmScript OpenScriptWindow(bool forceBlank)
106 		{
107 			frmScript frm = new frmScript(forceBlank);
108 			frm.Icon = Properties.Resources.Script;
109 			_openedWindows.Add(frm);
110 			frm.FormClosed += Debugger_FormClosed;
111 			frm.Show();
112 			return frm;
113 		}
114 
GetDebugger()115 		public static frmDebugger GetDebugger()
116 		{
117 			return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger)) as frmDebugger;
118 		}
119 
GetMemoryViewer()120 		public static frmMemoryViewer GetMemoryViewer()
121 		{
122 			return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmMemoryViewer)) as frmMemoryViewer;
123 		}
124 
125 		public static bool HasOpenedWindow
126 		{
127 			get
128 			{
129 				return _openedWindows.Count > 0;
130 			}
131 		}
132 
CloseAll()133 		public static void CloseAll()
134 		{
135 			List<Form> openedWindows = new List<Form>(_openedWindows);
136 			foreach(Form frm in openedWindows) {
137 				frm.Close();
138 			}
139 		}
140 
GetExistingSingleInstanceWindow(DebugWindow window)141 		private static Form GetExistingSingleInstanceWindow(DebugWindow window)
142 		{
143 			//Only one of each of these windows can be opened at once, check if one is already opened
144 			switch(window) {
145 				case DebugWindow.TraceLogger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTraceLogger));
146 				case DebugWindow.Assembler: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmAssembler));
147 				case DebugWindow.Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger));
148 				case DebugWindow.ApuViewer: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmApuViewer));
149 				case DebugWindow.TextHooker: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTextHooker));
150 				case DebugWindow.Profiler: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmProfiler));
151 				case DebugWindow.WatchWindow: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmWatchWindow));
152 			}
153 
154 			return null;
155 		}
156 
CleanupDebugger()157 		public static void CleanupDebugger()
158 		{
159 			if(_openedWindows.Count == 0) {
160 				//All windows have been closed, disable debugger
161 				DebugWorkspaceManager.SaveWorkspace();
162 				DebugWorkspaceManager.Clear();
163 				InteropEmu.DebugRelease();
164 			}
165 		}
166 
Debugger_FormClosed(object sender, FormClosedEventArgs e)167 		private static void Debugger_FormClosed(object sender, FormClosedEventArgs e)
168 		{
169 			_openedWindows.Remove((Form)sender);
170 			CleanupDebugger();
171 		}
172 	}
173 
174 	public enum DebugWindow
175 	{
176 		PpuViewer,
177 		MemoryViewer,
178 		TraceLogger,
179 		Assembler,
180 		Debugger,
181 		ScriptWindow,
182 		ApuViewer,
183 		EventViewer,
184 		TextHooker,
185 		Profiler,
186 		WatchWindow,
187 	}
188 }
189