1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Drawing.Text;
7 using System.IO;
8 using System.Linq;
9 using System.Text;
10 using System.Threading.Tasks;
11 using System.Windows.Forms;
12 using Mesen.GUI.Config;
13 using Mesen.GUI.Debugger.Controls;
14 using Mesen.GUI.Forms;
15 using Mesen.GUI.Controls;
16 using System.Collections.ObjectModel;
17 
18 namespace Mesen.GUI.Debugger
19 {
20 	public partial class frmDebugger : BaseForm
21 	{
22 		private bool _debuggerInitialized = false;
23 		private bool _firstBreak = true;
24 		private bool _wasPaused = false;
25 		private bool _executionIsStopped = false; //Flag used to break on the first instruction after power cycle/reset if execution was stopped before the reset
26 		private UInt64 _previousCycle = 0;
27 
28 		private InteropEmu.NotificationListener _notifListener;
29 		private ICodeViewer _lastCodeWindow;
30 		private Size _minimumSize;
31 		private int _topPanelMinSize;
32 
33 		public ICodeViewer LastCodeWindow
34 		{
35 			get { return _lastCodeWindow; }
36 			set
37 			{
38 				_lastCodeWindow = value;
39 				UpdateCodeMenu();
40 			}
41 		}
42 
frmDebugger()43 		public frmDebugger()
44 		{
45 			InitializeComponent();
46 		}
47 
OnLoad(EventArgs e)48 		protected override void OnLoad(EventArgs e)
49 		{
50 			this.InitShortcuts();
51 			this.InitToolbar();
52 
53 			base.OnLoad(e);
54 
55 			_minimumSize = this.MinimumSize;
56 			_topPanelMinSize = splitContainer.Panel1MinSize;
57 
58 			_wasPaused = InteropEmu.IsPaused();
59 			bool debuggerAlreadyRunning = InteropEmu.DebugIsDebuggerRunning();
60 
61 			ctrlConsoleStatus.OnStateChanged += ctrlConsoleStatus_OnStateChanged;
62 			LabelManager.OnLabelUpdated += LabelManager_OnLabelUpdated;
63 			BreakpointManager.BreakpointsChanged += BreakpointManager_BreakpointsChanged;
64 			ctrlProfiler.OnFunctionSelected += ctrlProfiler_OnFunctionSelected;
65 
66 			Font font = new Font(ConfigManager.Config.DebugInfo.FontFamily, ConfigManager.Config.DebugInfo.FontSize, ConfigManager.Config.DebugInfo.FontStyle);
67 			ctrlDebuggerCode.CodeViewer.BaseFont = font;
68 			ctrlDebuggerCodeSplit.CodeViewer.BaseFont = font;
69 			ctrlSourceViewer.CodeViewer.BaseFont = font;
70 			ctrlSourceViewerSplit.CodeViewer.BaseFont = font;
71 
72 			this.UpdateWorkspace();
73 			this.AutoLoadCdlFiles();
74 			DebugWorkspaceManager.AutoLoadDbgFiles(true);
75 
76 			if(!Program.IsMono) {
77 				this.mnuSplitView.Checked = ConfigManager.Config.DebugInfo.SplitView;
78 			} else {
79 				Task.Run(() => {
80 					//Wait 2 seconds before we turn split view on (otherwise Mono tends to cause GDI-related crashes)
81 					System.Threading.Thread.Sleep(500);
82 					this.BeginInvoke((Action)(() => {
83 						this.mnuSplitView.Checked = ConfigManager.Config.DebugInfo.SplitView;
84 						if(this.mnuSplitView.Checked) {
85 							this.UpdateDebugger(false, false);
86 						}
87 					}));
88 				});
89 			}
90 			this.mnuAutoCreateJumpLabels.Checked = ConfigManager.Config.DebugInfo.AutoCreateJumpLabels;
91 			this.mnuCopyAddresses.Checked = ConfigManager.Config.DebugInfo.CopyAddresses;
92 			this.mnuCopyByteCode.Checked = ConfigManager.Config.DebugInfo.CopyByteCode;
93 			this.mnuCopyComments.Checked = ConfigManager.Config.DebugInfo.CopyComments;
94 			this.mnuPpuPartialDraw.Checked = ConfigManager.Config.DebugInfo.PpuPartialDraw;
95 			this.mnuPpuShowPreviousFrame.Checked = ConfigManager.Config.DebugInfo.PpuShowPreviousFrame;
96 			this.mnuHidePauseIcon.Checked = ConfigManager.Config.DebugInfo.HidePauseIcon;
97 			this.mnuShowEffectiveAddresses.Checked = ConfigManager.Config.DebugInfo.ShowEffectiveAddresses;
98 			this.mnuShowCodePreview.Checked = ConfigManager.Config.DebugInfo.ShowCodePreview;
99 			this.mnuShowOpCodeTooltips.Checked = ConfigManager.Config.DebugInfo.ShowOpCodeTooltips;
100 			this.mnuOnlyShowTooltipOnShift.Checked = ConfigManager.Config.DebugInfo.OnlyShowTooltipsOnShift;
101 			this.mnuShowToolbar.Checked = ConfigManager.Config.DebugInfo.ShowToolbar;
102 			this.mnuShowCpuMemoryMapping.Checked = ConfigManager.Config.DebugInfo.ShowCpuMemoryMapping;
103 			this.mnuShowPpuMemoryMapping.Checked = ConfigManager.Config.DebugInfo.ShowPpuMemoryMapping;
104 			this.mnuAutoLoadDbgFiles.Checked = ConfigManager.Config.DebugInfo.AutoLoadDbgFiles;
105 			this.mnuAutoLoadCdlFiles.Checked = ConfigManager.Config.DebugInfo.AutoLoadCdlFiles;
106 			this.mnuEnableSubInstructionBreakpoints.Checked = !ConfigManager.Config.DebugInfo.BreakOnFirstCycle;
107 			this.mnuBreakOnReset.Checked = ConfigManager.Config.DebugInfo.BreakOnReset;
108 			this.mnuBreakOnInit.Checked = ConfigManager.Config.DebugInfo.BreakOnInit;
109 			this.mnuBreakOnPlay.Checked = ConfigManager.Config.DebugInfo.BreakOnPlay;
110 			this.mnuBreakOnOpen.Checked = ConfigManager.Config.DebugInfo.BreakOnOpen;
111 			this.mnuBreakOnUnofficialOpcodes.Checked = ConfigManager.Config.DebugInfo.BreakOnUnofficialOpcodes;
112 			this.mnuBreakOnBrk.Checked = ConfigManager.Config.DebugInfo.BreakOnBrk;
113 			this.mnuBreakOnUninitMemoryRead.Checked = ConfigManager.Config.DebugInfo.BreakOnUninitMemoryRead;
114 			this.mnuBreakOnDecayedOamRead.Checked = ConfigManager.Config.DebugInfo.BreakOnDecayedOamRead;
115 			this.mnuBreakOnCrash.Checked = ConfigManager.Config.DebugInfo.BreakOnCrash;
116 			this.mnuBreakOnDebuggerFocus.Checked = ConfigManager.Config.DebugInfo.BreakOnDebuggerFocus;
117 			this.mnuBringToFrontOnBreak.Checked = ConfigManager.Config.DebugInfo.BringToFrontOnBreak;
118 			this.mnuBringToFrontOnPause.Checked = ConfigManager.Config.DebugInfo.BringToFrontOnPause;
119 			this.mnuDisplayOpCodesInLowerCase.Checked = ConfigManager.Config.DebugInfo.DisplayOpCodesInLowerCase;
120 
121 			this.mnuDisassembleVerifiedData.Checked = ConfigManager.Config.DebugInfo.DisassembleVerifiedData;
122 			this.mnuDisassembleUnidentifiedData.Checked = ConfigManager.Config.DebugInfo.DisassembleUnidentifiedData;
123 
124 			this.mnuShowVerifiedData.Checked = ConfigManager.Config.DebugInfo.ShowVerifiedData;
125 			this.mnuShowUnidentifiedData.Checked = ConfigManager.Config.DebugInfo.ShowUnidentifiedData;
126 
127 			this.mnuShowBreakNotifications.Checked = ConfigManager.Config.DebugInfo.ShowBreakNotifications;
128 			this.mnuShowInstructionProgression.Checked = ConfigManager.Config.DebugInfo.ShowInstructionProgression;
129 			this.mnuShowSelectionLength.Checked = ConfigManager.Config.DebugInfo.ShowSelectionLength;
130 			this.mnuAlwaysScrollToCenter.Checked = ConfigManager.Config.DebugInfo.AlwaysScrollToCenter;
131 			this.mnuRefreshWhileRunning.Checked = ConfigManager.Config.DebugInfo.RefreshWhileRunning;
132 			this.mnuShowMemoryValues.Checked = ConfigManager.Config.DebugInfo.ShowMemoryValuesInCodeWindow;
133 			ctrlDebuggerCode.ShowMemoryValues = mnuShowMemoryValues.Checked;
134 			ctrlDebuggerCodeSplit.ShowMemoryValues = mnuShowMemoryValues.Checked;
135 
136 			if(ConfigManager.Config.DebugInfo.WindowWidth > -1) {
137 				this.StartPosition = FormStartPosition.Manual;
138 				this.Width = ConfigManager.Config.DebugInfo.WindowWidth;
139 				this.Height = ConfigManager.Config.DebugInfo.WindowHeight;
140 				this.Location = ConfigManager.Config.DebugInfo.WindowLocation;
141 			}
142 
143 			tsToolbar.Visible = mnuShowToolbar.Checked;
144 			ctrlCpuMemoryMapping.Visible = mnuShowCpuMemoryMapping.Checked;
145 			ctrlPpuMemoryMapping.Visible = mnuShowPpuMemoryMapping.Checked;
146 
147 			if(ConfigManager.Config.DebugInfo.LeftPanelWidth > 0) {
148 				this.ctrlSplitContainerTop.SplitterDistance = ConfigManager.Config.DebugInfo.LeftPanelWidth;
149 			}
150 			if(ConfigManager.Config.DebugInfo.TopPanelHeight > 0) {
151 				this.splitContainer.SplitterDistance = ConfigManager.Config.DebugInfo.TopPanelHeight;
152 			}
153 
154 			if(!ConfigManager.Config.DebugInfo.ShowRightPanel) {
155 				ctrlSplitContainerTop.CollapsePanel();
156 			} else {
157 				mnuShowFunctionLabelLists.Checked = true;
158 			}
159 
160 			if(!ConfigManager.Config.DebugInfo.ShowBottomPanel) {
161 				splitContainer.CollapsePanel();
162 			} else {
163 				mnuShowBottomPanel.Checked = true;
164 			}
165 
166 			this.mnuUseVerticalLayout.Checked = ConfigManager.Config.DebugInfo.VerticalLayout;
167 
168 			LastCodeWindow = ctrlDebuggerCode;
169 
170 			this.toolTip.SetToolTip(this.picWatchHelp, ctrlWatch.GetTooltipText());
171 
172 			_notifListener = new InteropEmu.NotificationListener(ConfigManager.Config.DebugInfo.DebugConsoleId);
173 			_notifListener.OnNotification += _notifListener_OnNotification;
174 
175 			InteropEmu.DebugInitialize();
176 
177 			_debuggerInitialized = true;
178 
179 			DebugState state = new DebugState();
180 			InteropEmu.DebugGetState(ref state);
181 			_previousCycle = state.CPU.CycleCount;
182 
183 			//Pause a few frames later to give the debugger a chance to disassemble some code
184 			_firstBreak = true;
185 			if(!debuggerAlreadyRunning) {
186 				InteropEmu.SetFlag(EmulationFlags.ForceMaxSpeed, true);
187 				InteropEmu.DebugStep((uint)(_wasPaused ? 1 : 5000));
188 			} else {
189 				//Break once to show code and then resume execution
190 				InteropEmu.DebugStep(1);
191 			}
192 			InteropEmu.Resume();
193 
194 			UpdateDebuggerFlags();
195 			UpdateCdlRatios();
196 			UpdateFileOptions();
197 		}
198 
OnShown(EventArgs e)199 		protected override void OnShown(EventArgs e)
200 		{
201 			base.OnShown(e);
202 
203 			ctrlDebuggerCode.Visible = true;
204 			ctrlDebuggerCodeSplit.Visible = true;
205 			ctrlSourceViewer.Visible = true;
206 			ctrlSourceViewerSplit.Visible = true;
207 
208 			ctrlDebuggerCode.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
209 			ctrlDebuggerCode.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
210 			ctrlDebuggerCode.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
211 			ctrlDebuggerCode.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
212 
213 			ctrlDebuggerCodeSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
214 			ctrlDebuggerCodeSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
215 			ctrlDebuggerCodeSplit.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
216 			ctrlDebuggerCodeSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
217 
218 			ctrlSourceViewer.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
219 			ctrlSourceViewer.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
220 			ctrlSourceViewer.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
221 			ctrlSourceViewer.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
222 
223 			ctrlSourceViewerSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
224 			ctrlSourceViewerSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
225 			ctrlSourceViewerSplit.CodeViewerActions.OnGoToDestination += ctrlDebuggerCode_OnGoToDestination;
226 			ctrlSourceViewerSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
227 
228 			ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
229 			ctrlSourceViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
230 			ctrlDebuggerCodeSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
231 			ctrlSourceViewerSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
232 
233 			ctrlSourceViewer.Visible = false;
234 			ctrlSourceViewerSplit.Visible = false;
235 		}
236 
InitShortcuts()237 		private void InitShortcuts()
238 		{
239 			mnuIncreaseFontSize.InitShortcut(this, nameof(DebuggerShortcutsConfig.IncreaseFontSize));
240 			mnuDecreaseFontSize.InitShortcut(this, nameof(DebuggerShortcutsConfig.DecreaseFontSize));
241 			mnuResetFontSize.InitShortcut(this, nameof(DebuggerShortcutsConfig.ResetFontSize));
242 
243 			mnuSaveRom.InitShortcut(this, nameof(DebuggerShortcutsConfig.SaveRom));
244 			mnuSaveRomAs.InitShortcut(this, nameof(DebuggerShortcutsConfig.SaveRomAs));
245 			mnuSaveAsIps.InitShortcut(this, nameof(DebuggerShortcutsConfig.SaveEditAsIps));
246 			mnuRevertChanges.InitShortcut(this, nameof(DebuggerShortcutsConfig.RevertPrgChrChanges));
247 
248 			mnuReset.InitShortcut(this, nameof(DebuggerShortcutsConfig.Reset));
249 			mnuPowerCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.PowerCycle));
250 
251 			mnuContinue.InitShortcut(this, nameof(DebuggerShortcutsConfig.Continue));
252 			mnuBreak.InitShortcut(this, nameof(DebuggerShortcutsConfig.Break));
253 			mnuBreakIn.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakIn));
254 			mnuBreakOn.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakOn));
255 
256 			mnuStepBack.InitShortcut(this, nameof(DebuggerShortcutsConfig.StepBack));
257 			mnuStepOut.InitShortcut(this, nameof(DebuggerShortcutsConfig.StepOut));
258 			mnuStepInto.InitShortcut(this, nameof(DebuggerShortcutsConfig.StepInto));
259 			mnuStepOver.InitShortcut(this, nameof(DebuggerShortcutsConfig.StepOver));
260 
261 			mnuRunCpuCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunCpuCycle));
262 			mnuRunPpuCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuCycle));
263 			mnuRunScanline.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuScanline));
264 			mnuRunOneFrame.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuFrame));
265 
266 			mnuGoToAll.InitShortcut(this, nameof(DebuggerShortcutsConfig.GoToAll));
267 			mnuGoToAddress.InitShortcut(this, nameof(DebuggerShortcutsConfig.GoTo));
268 			mnuFind.InitShortcut(this, nameof(DebuggerShortcutsConfig.Find));
269 			mnuFindNext.InitShortcut(this, nameof(DebuggerShortcutsConfig.FindNext));
270 			mnuFindPrev.InitShortcut(this, nameof(DebuggerShortcutsConfig.FindPrev));
271 			mnuFindAllOccurrences.InitShortcut(this, nameof(DebuggerShortcutsConfig.FindOccurrences));
272 
273 			mnuShowVerifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.ToggleVerifiedData));
274 			mnuShowUnidentifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.ToggleUnidentifiedCodeData));
275 
276 			mnuApuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenApuViewer));
277 			mnuAssembler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenAssembler));
278 			mnuEventViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenEventViewer));
279 			mnuMemoryViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenMemoryTools));
280 			mnuPpuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPpuViewer));
281 			mnuScriptWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenScriptWindow));
282 			mnuTraceLogger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTraceLogger));
283 			mnuTextHooker.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTextHooker));
284 			mnuProfiler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenProfiler));
285 			mnuWatchWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenWatchWindow));
286 
287 			mnuOpenNametableViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenNametableViewer));
288 			mnuOpenChrViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenChrViewer));
289 			mnuOpenSpriteViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSpriteViewer));
290 			mnuOpenPaletteViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPaletteViewer));
291 		}
292 
InitToolbar()293 		private void InitToolbar()
294 		{
295 			tsToolbar.AddItemsToToolbar(
296 				mnuSaveRom, mnuRevertChanges, null,
297 				mnuImportLabels, mnuExportLabels, null,
298 				mnuContinue, mnuBreak, null,
299 				mnuStepInto, mnuStepOver, mnuStepOut, mnuStepBack, null,
300 				mnuRunCpuCycle, null,
301 				mnuRunPpuCycle, mnuRunScanline, mnuRunOneFrame, null,
302 				mnuToggleBreakpoint, mnuDisableEnableBreakpoint, null,
303 				mnuFind, mnuFindPrev, mnuFindNext, null,
304 				mnuApuViewer, mnuAssembler, mnuEventViewer, mnuMemoryViewer, mnuPpuViewer, mnuScriptWindow, mnuTextHooker, mnuTraceLogger, null,
305 				mnuEditHeader, null,
306 				mnuSplitView, mnuUseVerticalLayout, null
307 			);
308 			tsToolbar.AddItemToToolbar(mnuShowVerifiedData, "Show Verified Data");
309 			tsToolbar.AddItemToToolbar(mnuShowUnidentifiedData, "Show Unidentified Code/Data");
310 			tsToolbar.AddItemsToToolbar(null, mnuBreakIn, null, mnuBreakOn);
311 		}
312 
ProcessCmdKey(ref Message msg, Keys keyData)313 		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
314 		{
315 			if(!((UserControl)LastCodeWindow).ContainsFocus) {
316 				//Allow Ctrl+C, etc to work normally while editing watch, or other fields
317 				CleanupMenu(mnuCode.DropDownItems);
318 				mnuCode.DropDownItems.Clear();
319 			} else {
320 				UpdateCodeMenu();
321 			}
322 
323 			if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.ToggleBreakContinue) {
324 				if(mnuBreak.Enabled) {
325 					ctrlConsoleStatus.ApplyChanges();
326 					InteropEmu.DebugStep(1);
327 				} else {
328 					ResumeExecution();
329 				}
330 				return true;
331 			}
332 
333 			return base.ProcessCmdKey(ref msg, keyData);
334 		}
335 
OnActivated(EventArgs e)336 		protected override void OnActivated(EventArgs e)
337 		{
338 			base.OnActivated(e);
339 			if(ConfigManager.Config.DebugInfo.BreakOnDebuggerFocus && !InteropEmu.DebugIsExecutionStopped()) {
340 				InteropEmu.DebugStep(1, BreakSource.BreakOnFocus);
341 			}
342 		}
343 
ctrlProfiler_OnFunctionSelected(object sender, EventArgs e)344 		private void ctrlProfiler_OnFunctionSelected(object sender, EventArgs e)
345 		{
346 			int relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)sender, AddressType.PrgRom);
347 			if(relativeAddress >= 0) {
348 				BringToFront();
349 				LastCodeWindow.ScrollToLineNumber(relativeAddress);
350 			}
351 		}
352 
mnuFile_DropDownOpening(object sender, EventArgs e)353 		private void mnuFile_DropDownOpening(object sender, EventArgs e)
354 		{
355 			UpdateFileOptions();
356 		}
357 
UpdateFileOptions()358 		private void UpdateFileOptions()
359 		{
360 			bool hasChanges = InteropEmu.DebugHasPrgChrChanges();
361 			RomInfo romInfo = InteropEmu.GetRomInfo();
362 			mnuSaveRom.Enabled = romInfo.Format == RomFormat.iNes && hasChanges && !romInfo.RomFile.Compressed;
363 			mnuSaveAsIps.Enabled = romInfo.Format == RomFormat.iNes && hasChanges;
364 			mnuRevertChanges.Enabled = hasChanges;
365 			mnuSaveRomAs.Enabled = romInfo.Format == RomFormat.iNes;
366 			mnuEditHeader.Enabled = romInfo.Format == RomFormat.iNes;
367 
368 			mnuCdlStripUnusedData.Enabled = romInfo.Format == RomFormat.iNes;
369 			mnuCdlStripUsedData.Enabled = romInfo.Format == RomFormat.iNes;
370 		}
371 
AutoLoadCdlFiles()372 		private void AutoLoadCdlFiles()
373 		{
374 			if(ConfigManager.Config.DebugInfo.AutoLoadCdlFiles) {
375 				//This loads CDL files that are next to the rom - useful when developing with a compiler that can produce a CDL file
376 				RomInfo info = InteropEmu.GetRomInfo();
377 				string cdlPath = Path.Combine(info.RomFile.Folder, info.GetRomName() + ".cdl");
378 				if(File.Exists(cdlPath)) {
379 					if(InteropEmu.DebugLoadCdlFile(cdlPath)) {
380 						UpdateDebugger(false, false);
381 					}
382 				}
383 			}
384 		}
385 
UpdateWorkspace()386 		private void UpdateWorkspace()
387 		{
388 			DebugWorkspaceManager.SaveWorkspace();
389 			DebugWorkspaceManager.GetWorkspace();
390 
391 			ctrlLabelList.UpdateLabelList();
392 			ctrlFunctionList.UpdateFunctionList(true);
393 			ctrlBreakpoints.RefreshList();
394 		}
395 
UpdateCdlRatios()396 		private void UpdateCdlRatios()
397 		{
398 			CdlRatios ratios = new CdlRatios();
399 			InteropEmu.DebugGetCdlRatios(ref ratios);
400 
401 			lblPrgAnalysisResult.Text = string.Format("{0:0.00}% (Code: {1:0.00}%, Data: {2:0.00}%, Unknown: {3:0.00}%)", ratios.PrgRatio * 100, ratios.CodeRatio * 100, ratios.DataRatio * 100, (1 - ratios.PrgRatio) * 100);
402 			if(ratios.ChrRatio >= 0) {
403 				lblChrAnalysisResult.Text = string.Format("{0:0.00}% (Drawn: {1:0.00}%, Read: {2:0.00}%, Unknown: {3:0.00}%)", ratios.ChrRatio * 100, ratios.ChrDrawnRatio * 100, ratios.ChrReadRatio * 100, (1 - ratios.ChrRatio) * 100);
404 			} else {
405 				lblChrAnalysisResult.Text = "N/A (CHR RAM)";
406 			}
407 		}
408 
SetFlag(DebuggerFlags flag, bool enabled)409 		private void SetFlag(DebuggerFlags flag, bool enabled)
410 		{
411 			if(enabled) {
412 				DebugWorkspaceManager.SetFlags(flag);
413 			} else {
414 				DebugWorkspaceManager.ClearFlags(flag);
415 			}
416 		}
417 
UpdateDebuggerFlags()418 		private void UpdateDebuggerFlags()
419 		{
420 			DebugInfo config = ConfigManager.Config.DebugInfo;
421 			SetFlag(DebuggerFlags.PpuPartialDraw, config.PpuPartialDraw);
422 			SetFlag(DebuggerFlags.PpuShowPreviousFrame, config.PpuShowPreviousFrame);
423 			SetFlag(DebuggerFlags.ShowEffectiveAddresses, config.ShowEffectiveAddresses);
424 			SetFlag(DebuggerFlags.DisplayOpCodesInLowerCase, config.DisplayOpCodesInLowerCase);
425 			SetFlag(DebuggerFlags.DisassembleVerifiedData, config.DisassembleVerifiedData);
426 			SetFlag(DebuggerFlags.DisassembleUnidentifiedData, config.DisassembleUnidentifiedData);
427 			SetFlag(DebuggerFlags.ShowVerifiedData, config.ShowVerifiedData);
428 			SetFlag(DebuggerFlags.ShowUnidentifiedData, config.ShowUnidentifiedData);
429 			SetFlag(DebuggerFlags.BreakOnUnofficialOpCode, config.BreakOnUnofficialOpcodes);
430 			SetFlag(DebuggerFlags.BreakOnBrk, config.BreakOnBrk);
431 			SetFlag(DebuggerFlags.BreakOnUninitMemoryRead, config.BreakOnUninitMemoryRead);
432 			SetFlag(DebuggerFlags.BreakOnDecayedOamRead, config.BreakOnDecayedOamRead);
433 			SetFlag(DebuggerFlags.BreakOnInit, config.BreakOnInit);
434 			SetFlag(DebuggerFlags.BreakOnPlay, config.BreakOnPlay);
435 			SetFlag(DebuggerFlags.BreakOnFirstCycle, config.BreakOnFirstCycle);
436 			SetFlag(DebuggerFlags.HidePauseIcon, config.HidePauseIcon);
437 			InteropEmu.SetFlag(EmulationFlags.DebuggerWindowEnabled, true);
438 		}
439 
GetBreakNotification(Int64 param)440 		private string GetBreakNotification(Int64 param)
441 		{
442 			BreakSource source = (BreakSource)(byte)param;
443 
444 			string message = null;
445 			if(ConfigManager.Config.DebugInfo.ShowBreakNotifications) {
446 				message = ResourceHelper.GetEnumText(source);
447 				if(source == BreakSource.Breakpoint) {
448 					int breakpointId = (int)(param >> 40);
449 					byte bpValue = (byte)((param >> 32) & 0xFF);
450 					BreakpointType bpType = (BreakpointType)(byte)((param >> 8) & 0x0F);
451 					UInt16 bpAddress = (UInt16)(param >> 16);
452 
453 					ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
454 					if(breakpointId >= 0 && breakpointId < breakpoints.Count) {
455 						Breakpoint bp = breakpoints[breakpointId];
456 						if(bpType != BreakpointType.Global) {
457 							message += ": " + ResourceHelper.GetEnumText(bpType) + " ($" + bpAddress.ToString("X4") + ":$" + bpValue.ToString("X2") + ")";
458 						}
459 						if(!string.IsNullOrWhiteSpace(bp.Condition)) {
460 							string cond = bp.Condition.Trim();
461 							if(cond.Length > 27) {
462 								message += Environment.NewLine + cond.Substring(0, 24) + "...";
463 							} else {
464 								message += Environment.NewLine + cond;
465 							}
466 						}
467 					}
468 				} else if(source == BreakSource.BreakOnUninitMemoryRead) {
469 					UInt16 address = (UInt16)(param >> 16);
470 					byte value = (byte)((param >> 32) & 0xFF);
471 					message += " ($" + address.ToString("X4") + ":$" + value.ToString("X2") + ")";
472 				} else if(source == BreakSource.CpuStep || source == BreakSource.PpuStep) {
473 					//Don't display anything when breaking due to stepping
474 					message = null;
475 				}
476 			}
477 
478 			return message;
479 		}
480 
_notifListener_OnNotification(InteropEmu.NotificationEventArgs e)481 		private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
482 		{
483 			switch(e.NotificationType) {
484 				case InteropEmu.ConsoleNotificationType.PpuFrameDone:
485 					if(ConfigManager.Config.DebugInfo.RefreshWhileRunning) {
486 						DebugState state = new DebugState();
487 						InteropEmu.DebugGetState(ref state);
488 
489 						this.BeginInvoke((MethodInvoker)(() => {
490 							if(state.PPU.FrameCount % 30 == 0) {
491 								//Update UI every 30 frames, since this is a relatively slow operation
492 								ctrlCpuMemoryMapping.UpdateCpuRegions(state.Cartridge);
493 								ctrlPpuMemoryMapping.UpdatePpuRegions(state.Cartridge);
494 								ctrlConsoleStatus.UpdateStatus(ref state);
495 								UpdateCdlRatios();
496 							}
497 							ctrlWatch.UpdateWatch(false);
498 						}));
499 					}
500 					break;
501 
502 				case InteropEmu.ConsoleNotificationType.CodeBreak:
503 					this._executionIsStopped = true;
504 
505 					this.BeginInvoke((MethodInvoker)(() => {
506 						BreakSource source = (BreakSource)(byte)e.Parameter.ToInt64();
507 
508 						bool bringToFront = (
509 							source < BreakSource.Pause && ConfigManager.Config.DebugInfo.BringToFrontOnBreak ||
510 							source == BreakSource.Pause && ConfigManager.Config.DebugInfo.BringToFrontOnPause
511 						);
512 						UpdateDebugger(true, bringToFront);
513 
514 						_lastCodeWindow.SetMessage(new TextboxMessageInfo() { Message = GetBreakNotification(e.Parameter.ToInt64()) });
515 
516 						mnuContinue.Enabled = true;
517 						mnuBreak.Enabled = false;
518 					}));
519 					BreakpointManager.SetBreakpoints();
520 					break;
521 
522 				case InteropEmu.ConsoleNotificationType.GameReset:
523 				case InteropEmu.ConsoleNotificationType.GameLoaded:
524 					UpdateDebuggerFlags();
525 					BreakpointManager.SetBreakpoints();
526 
527 					bool breakOnReset = ConfigManager.Config.DebugInfo.BreakOnReset && !InteropEmu.IsNsf();
528 					this.BeginInvoke((MethodInvoker)(() => {
529 						this.UpdateWorkspace();
530 						LabelManager.RefreshLabels();
531 						this.AutoLoadCdlFiles();
532 						DebugWorkspaceManager.AutoLoadDbgFiles(true);
533 						UpdateDebugger(true, false);
534 
535 						if(!breakOnReset) {
536 							ClearActiveStatement();
537 						}
538 					}));
539 
540 					if(breakOnReset || _executionIsStopped) {
541 						InteropEmu.DebugStep(1, BreakSource.BreakOnReset);
542 					}
543 					break;
544 			}
545 		}
546 
UpdateSplitView()547 		private bool UpdateSplitView()
548 		{
549 			if(mnuSplitView.Checked) {
550 				tlpTop.ColumnStyles[1].SizeType = SizeType.Percent;
551 				tlpTop.ColumnStyles[0].Width = 50f;
552 				tlpTop.ColumnStyles[1].Width = 50f;
553 				this.UpdateMinimumSize();
554 			} else {
555 				tlpTop.ColumnStyles[1].SizeType = SizeType.Absolute;
556 				tlpTop.ColumnStyles[1].Width = 0f;
557 				this.UpdateMinimumSize();
558 			}
559 			ctrlDebuggerCodeSplit.Visible = mnuSplitView.Checked;
560 			return mnuSplitView.Checked;
561 		}
562 
UpdateMinimumSize()563 		private void UpdateMinimumSize()
564 		{
565 			int minWidth, minHeight;
566 			if(mnuSplitView.Checked) {
567 				minWidth = _minimumSize.Width + 250;
568 			} else {
569 				minWidth = _minimumSize.Width;
570 			}
571 
572 			if(mnuUseVerticalLayout.Checked) {
573 				minHeight = _minimumSize.Height + 150;
574 				splitContainer.Panel1MinSize = _topPanelMinSize + 100;
575 			} else {
576 				minHeight = _minimumSize.Height;
577 				splitContainer.Panel1MinSize = _topPanelMinSize;
578 			}
579 
580 			this.MinimumSize = new Size(minWidth, minHeight);
581 		}
582 
UpdateVectorAddresses()583 		private void UpdateVectorAddresses()
584 		{
585 			int nmiHandler = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFA) | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFB) << 8);
586 			int resetHandler = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFC) | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFD) << 8);
587 			int irqHandler = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFE) | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFF) << 8);
588 
589 			mnuGoToNmiHandler.Text = "NMI Handler ($" + nmiHandler.ToString("X4") + ")";
590 			mnuGoToResetHandler.Text = "Reset Handler ($" + resetHandler.ToString("X4") + ")";
591 			mnuGoToIrqHandler.Text = "IRQ Handler ($" + irqHandler.ToString("X4") + ")";
592 		}
593 
UpdateDebugger(bool updateActiveAddress = true, bool bringToFront = true)594 		public void UpdateDebugger(bool updateActiveAddress = true, bool bringToFront = true)
595 		{
596 			if(!_debuggerInitialized) {
597 				return;
598 			}
599 
600 			if(ConfigManager.Config.DebugInfo.AutoCreateJumpLabels) {
601 				LabelManager.CreateAutomaticJumpLabels();
602 			}
603 
604 			ctrlBreakpoints.RefreshListAddresses();
605 			ctrlLabelList.UpdateLabelListAddresses();
606 			ctrlFunctionList.UpdateFunctionList(false);
607 			UpdateDebuggerFlags();
608 			UpdateVectorAddresses();
609 
610 			string newCode = InteropEmu.DebugGetCode(_firstBreak);
611 			if(newCode != null) {
612 				ctrlDebuggerCode.Code = new CodeInfo(newCode);
613 			}
614 
615 			DebugState state = new DebugState();
616 			InteropEmu.DebugGetState(ref state);
617 
618 			lblCyclesElapsedCount.Text = (state.CPU.CycleCount - _previousCycle).ToString();
619 			_previousCycle = state.CPU.CycleCount;
620 
621 			if(UpdateSplitView()) {
622 				if(ctrlDebuggerCodeSplit.Code != ctrlDebuggerCode.Code) {
623 					ctrlDebuggerCodeSplit.Code = ctrlDebuggerCode.Code;
624 				}
625 			} else {
626 				LastCodeWindow = ctrlSourceViewer.Visible ? (ICodeViewer)ctrlSourceViewer : (ICodeViewer)ctrlDebuggerCode;
627 			}
628 
629 			if(updateActiveAddress) {
630 				LastCodeWindow.SelectActiveAddress(state.CPU.DebugPC);
631 			}
632 
633 			ctrlDebuggerCode.SetActiveAddress(state.CPU.DebugPC);
634 			ctrlSourceViewer.SetActiveAddress(state.CPU.DebugPC);
635 			ctrlDebuggerCode.UpdateLineColors();
636 
637 			if(UpdateSplitView()) {
638 				ctrlDebuggerCodeSplit.SetActiveAddress(state.CPU.DebugPC);
639 				ctrlSourceViewerSplit.SetActiveAddress(state.CPU.DebugPC);
640 				ctrlDebuggerCodeSplit.UpdateLineColors();
641 			}
642 
643 			ctrlConsoleStatus.UpdateStatus(ref state);
644 			ctrlWatch.UpdateWatch();
645 			ctrlCallstack.UpdateCallstack();
646 			UpdateCdlRatios();
647 
648 			ctrlCpuMemoryMapping.UpdateCpuRegions(state.Cartridge);
649 			ctrlPpuMemoryMapping.UpdatePpuRegions(state.Cartridge);
650 
651 			if(bringToFront) {
652 				this.BringToFront();
653 			}
654 
655 			if(_firstBreak) {
656 				InteropEmu.SetFlag(EmulationFlags.ForceMaxSpeed, false);
657 				if(!_wasPaused && !ConfigManager.Config.DebugInfo.BreakOnOpen) {
658 					ResumeExecution();
659 				}
660 				_firstBreak = false;
661 
662 				//Switch to source viewer after reopening debugger if we were in source viewer when we closed it
663 				if(ctrlSourceViewer.CurrentFile != null && ConfigManager.Config.DebugInfo.LeftView.UsingSourceView) {
664 					ctrlDebuggerCode_OnSwitchView(this.ctrlDebuggerCode);
665 				}
666 				if(ctrlSourceViewerSplit.CurrentFile != null && ConfigManager.Config.DebugInfo.RightView.UsingSourceView) {
667 					ctrlDebuggerCode_OnSwitchView(this.ctrlDebuggerCodeSplit);
668 				}
669 			}
670 		}
671 
ClearActiveStatement()672 		private void ClearActiveStatement()
673 		{
674 			ctrlDebuggerCode.ClearActiveAddress();
675 			ctrlDebuggerCode.UpdateLineColors();
676 			ctrlDebuggerCodeSplit.ClearActiveAddress();
677 			ctrlDebuggerCodeSplit.UpdateLineColors();
678 
679 			ctrlSourceViewer.ClearActiveAddress();
680 			ctrlSourceViewerSplit.ClearActiveAddress();
681 
682 			ctrlDebuggerCode.SetMessage(null);
683 			ctrlDebuggerCodeSplit.SetMessage(null);
684 			ctrlSourceViewer.SetMessage(null);
685 			ctrlSourceViewerSplit.SetMessage(null);
686 		}
687 
TogglePause()688 		public void TogglePause()
689 		{
690 			if(mnuBreak.Enabled) {
691 				ctrlConsoleStatus.ApplyChanges();
692 				InteropEmu.DebugBreakOnScanline(241);
693 			} else {
694 				ResumeExecution();
695 			}
696 		}
697 
ToggleBreakpoint(bool toggleEnabled)698 		private void ToggleBreakpoint(bool toggleEnabled)
699 		{
700 			LastCodeWindow.CodeViewerActions.ToggleBreakpoint(toggleEnabled);
701 		}
702 
ResumeExecution()703 		private void ResumeExecution()
704 		{
705 			_executionIsStopped = false;
706 			mnuContinue.Enabled = false;
707 			mnuBreak.Enabled = true;
708 
709 			ctrlConsoleStatus.ApplyChanges();
710 			ClearActiveStatement();
711 			UpdateDebuggerFlags();
712 			InteropEmu.DebugRun();
713 		}
714 
mnuContinue_Click(object sender, EventArgs e)715 		private void mnuContinue_Click(object sender, EventArgs e)
716 		{
717 			ResumeExecution();
718 		}
719 
mnuToggleBreakpoint_Click(object sender, EventArgs e)720 		private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
721 		{
722 			ToggleBreakpoint(false);
723 		}
724 
mnuDisableEnableBreakpoint_Click(object sender, EventArgs e)725 		private void mnuDisableEnableBreakpoint_Click(object sender, EventArgs e)
726 		{
727 			ToggleBreakpoint(true);
728 		}
729 
mnuBreak_Click(object sender, EventArgs e)730 		private void mnuBreak_Click(object sender, EventArgs e)
731 		{
732 			ctrlConsoleStatus.ApplyChanges();
733 			InteropEmu.DebugStep(1);
734 		}
735 
mnuStepInto_Click(object sender, EventArgs e)736 		private void mnuStepInto_Click(object sender, EventArgs e)
737 		{
738 			ctrlConsoleStatus.ApplyChanges();
739 			InteropEmu.DebugStep(1);
740 		}
741 
mnuStepOut_Click(object sender, EventArgs e)742 		private void mnuStepOut_Click(object sender, EventArgs e)
743 		{
744 			ctrlConsoleStatus.ApplyChanges();
745 			InteropEmu.DebugStepOut();
746 		}
747 
mnuStepOver_Click(object sender, EventArgs e)748 		private void mnuStepOver_Click(object sender, EventArgs e)
749 		{
750 			ctrlConsoleStatus.ApplyChanges();
751 			InteropEmu.DebugStepOver();
752 		}
753 
mnuStepBack_Click(object sender, EventArgs e)754 		private void mnuStepBack_Click(object sender, EventArgs e)
755 		{
756 			ctrlConsoleStatus.ApplyChanges();
757 			InteropEmu.DebugStepBack();
758 		}
759 
mnuRunCpuCycle_Click(object sender, EventArgs e)760 		private void mnuRunCpuCycle_Click(object sender, EventArgs e)
761 		{
762 			ctrlConsoleStatus.ApplyChanges();
763 			InteropEmu.DebugStepCycles(1);
764 		}
765 
mnuRunPpuCycle_Click(object sender, EventArgs e)766 		private void mnuRunPpuCycle_Click(object sender, EventArgs e)
767 		{
768 			ctrlConsoleStatus.ApplyChanges();
769 			InteropEmu.DebugPpuStep(1);
770 		}
771 
mnuRunScanline_Click(object sender, EventArgs e)772 		private void mnuRunScanline_Click(object sender, EventArgs e)
773 		{
774 			ctrlConsoleStatus.ApplyChanges();
775 			InteropEmu.DebugPpuStep(341);
776 		}
777 
mnuRunOneFrame_Click(object sender, EventArgs e)778 		private void mnuRunOneFrame_Click(object sender, EventArgs e)
779 		{
780 			ctrlConsoleStatus.ApplyChanges();
781 			NesModel model = InteropEmu.GetNesModel();
782 			int extraScanlines = (int)(ConfigManager.Config.EmulationInfo.PpuExtraScanlinesAfterNmi + ConfigManager.Config.EmulationInfo.PpuExtraScanlinesBeforeNmi);
783 			int cycleCount = ((model == NesModel.NTSC ? 262 : 312) + extraScanlines) * 341;
784 			InteropEmu.DebugPpuStep((UInt32)cycleCount);
785 		}
786 
ctrlDebuggerCode_OnGoToDestination(ICodeViewer sender, GoToDestination dest)787 		private void ctrlDebuggerCode_OnGoToDestination(ICodeViewer sender, GoToDestination dest)
788 		{
789 			GoToDestination(sender, dest);
790 		}
791 
ctrlDebuggerCode_OnShowInSplitView(ICodeViewer sender, GoToDestination dest)792 		private void ctrlDebuggerCode_OnShowInSplitView(ICodeViewer sender, GoToDestination dest)
793 		{
794 			if(!ConfigManager.Config.DebugInfo.SplitView) {
795 				mnuSplitView.Checked = true;
796 				ConfigManager.Config.DebugInfo.SplitView = true;
797 				ConfigManager.ApplyChanges();
798 				UpdateDebugger(false);
799 			}
800 
801 			if(sender == ctrlDebuggerCode || sender == ctrlSourceViewer) {
802 				if(ctrlSourceViewerSplit.Visible) {
803 					GoToDestination(ctrlSourceViewerSplit, dest);
804 				} else {
805 					GoToDestination(ctrlDebuggerCodeSplit, dest);
806 				}
807 			} else {
808 				if(ctrlSourceViewer.Visible) {
809 					GoToDestination(ctrlSourceViewer, dest);
810 				} else {
811 					GoToDestination(ctrlDebuggerCode, dest);
812 				}
813 			}
814 		}
815 
ctrlDebuggerCode_OnSetNextStatement(AddressEventArgs args)816 		private void ctrlDebuggerCode_OnSetNextStatement(AddressEventArgs args)
817 		{
818 			UInt16 addr = (UInt16)args.Address;
819 			InteropEmu.DebugSetNextStatement(addr);
820 			this.UpdateDebugger();
821 		}
822 
ctrlDebuggerCode_OnSwitchView(ICodeViewer sender)823 		private void ctrlDebuggerCode_OnSwitchView(ICodeViewer sender)
824 		{
825 			if(ctrlDebuggerCode == sender) {
826 				if(ctrlSourceViewer.CurrentFile != null) {
827 					ctrlDebuggerCode.Visible = false;
828 					ctrlSourceViewer.Visible = true;
829 					if(ctrlDebuggerCode.CodeViewer.CurrentLine >= 0) {
830 						ctrlSourceViewer.ScrollToLineNumber(ctrlDebuggerCode.CodeViewer.CurrentLine);
831 					}
832 					ctrlSourceViewer.Focus();
833 					ctrlSourceViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
834 				} else {
835 					MessageBox.Show("Source files could not be found/loaded", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
836 				}
837 			} else if(ctrlSourceViewer == sender) {
838 				ctrlSourceViewer.Visible = false;
839 				ctrlDebuggerCode.Visible = true;
840 				if(ctrlDebuggerCode.CodeViewer.CurrentLine >= 0) {
841 					ctrlDebuggerCode.ScrollToLineNumber(ctrlDebuggerCode.CodeViewer.CurrentLine);
842 				}
843 				ctrlDebuggerCode.Focus();
844 				ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
845 			} else if(ctrlSourceViewerSplit == sender) {
846 				if(ctrlSourceViewerSplit.CurrentFile != null) {
847 					ctrlSourceViewerSplit.Visible = false;
848 					ctrlDebuggerCodeSplit.Visible = true;
849 					if(ctrlSourceViewerSplit.CodeViewer.CurrentLine >= 0) {
850 						ctrlDebuggerCodeSplit.ScrollToLineNumber(ctrlSourceViewerSplit.CodeViewer.CurrentLine);
851 					}
852 					ctrlDebuggerCodeSplit.Focus();
853 					ctrlDebuggerCodeSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
854 				} else {
855 					MessageBox.Show("Source files could not be found/loaded", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
856 				}
857 			} else {
858 				ctrlDebuggerCodeSplit.Visible = false;
859 				ctrlSourceViewerSplit.Visible = true;
860 				if(ctrlDebuggerCodeSplit.CodeViewer.CurrentLine >= 0) {
861 					ctrlSourceViewerSplit.ScrollToLineNumber(ctrlDebuggerCodeSplit.CodeViewer.CurrentLine);
862 				}
863 				ctrlSourceViewerSplit.Focus();
864 				ctrlSourceViewerSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
865 			}
866 		}
867 
mnuFind_Click(object sender, EventArgs e)868 		private void mnuFind_Click(object sender, EventArgs e)
869 		{
870 			LastCodeWindow.CodeViewer.OpenSearchBox();
871 		}
872 
mnuFindNext_Click(object sender, EventArgs e)873 		private void mnuFindNext_Click(object sender, EventArgs e)
874 		{
875 			LastCodeWindow.CodeViewer.FindNext();
876 		}
877 
mnuFindPrev_Click(object sender, EventArgs e)878 		private void mnuFindPrev_Click(object sender, EventArgs e)
879 		{
880 			LastCodeWindow.CodeViewer.FindPrevious();
881 		}
882 
mnuSplitView_Click(object sender, EventArgs e)883 		private void mnuSplitView_Click(object sender, EventArgs e)
884 		{
885 			ConfigManager.Config.DebugInfo.SplitView = this.mnuSplitView.Checked;
886 			ConfigManager.ApplyChanges();
887 
888 			ctrlDebuggerCodeSplit.Code = ctrlDebuggerCode.Code;
889 			UpdateDebugger(false);
890 		}
891 
mnuMemoryViewer_Click(object sender, EventArgs e)892 		private void mnuMemoryViewer_Click(object sender, EventArgs e)
893 		{
894 			DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryViewer);
895 		}
896 
mnuEventViewer_Click(object sender, EventArgs e)897 		private void mnuEventViewer_Click(object sender, EventArgs e)
898 		{
899 			DebugWindowManager.OpenDebugWindow(DebugWindow.EventViewer);
900 		}
901 
BreakpointManager_BreakpointsChanged(object sender, EventArgs e)902 		private void BreakpointManager_BreakpointsChanged(object sender, EventArgs e)
903 		{
904 			ctrlDebuggerCodeSplit.UpdateLineColors();
905 			ctrlDebuggerCode.UpdateLineColors();
906 
907 			ctrlSourceViewer.RefreshViewer();
908 			ctrlSourceViewerSplit.RefreshViewer();
909 		}
910 
ScrollToAddress(int address)911 		public void ScrollToAddress(int address)
912 		{
913 			LastCodeWindow.ScrollToLineNumber(address);
914 			if(WindowState == FormWindowState.Minimized) {
915 				//Unminimize window if it was minimized
916 				WindowState = FormWindowState.Normal;
917 			}
918 			BringToFront();
919 		}
920 
ctrlDebuggerCode_Enter(object sender, EventArgs e)921 		private void ctrlDebuggerCode_Enter(object sender, EventArgs e)
922 		{
923 			LastCodeWindow = (ICodeViewer)sender;
924 		}
925 
mnuGoToAddress_Click(object sender, EventArgs e)926 		private void mnuGoToAddress_Click(object sender, EventArgs e)
927 		{
928 			LastCodeWindow.CodeViewer.GoToAddress();
929 		}
930 
mnuGoToIrqHandler_Click(object sender, EventArgs e)931 		private void mnuGoToIrqHandler_Click(object sender, EventArgs e)
932 		{
933 			int address = (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFF) << 8) | InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFE);
934 			LastCodeWindow.ScrollToLineNumber(address);
935 		}
936 
mnuGoToNmiHandler_Click(object sender, EventArgs e)937 		private void mnuGoToNmiHandler_Click(object sender, EventArgs e)
938 		{
939 			int address = (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFB) << 8) | InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFA);
940 			LastCodeWindow.ScrollToLineNumber(address);
941 		}
942 
mnuGoToResetHandler_Click(object sender, EventArgs e)943 		private void mnuGoToResetHandler_Click(object sender, EventArgs e)
944 		{
945 			int address = (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFD) << 8) | InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFC);
946 			LastCodeWindow.ScrollToLineNumber(address);
947 		}
948 
mnuGoToProgramCount_Click(object sender, EventArgs e)949 		private void mnuGoToProgramCount_Click(object sender, EventArgs e)
950 		{
951 			LastCodeWindow.CodeViewerActions.ScrollToActiveAddress();
952 		}
953 
mnuIncreaseFontSize_Click(object sender, EventArgs e)954 		private void mnuIncreaseFontSize_Click(object sender, EventArgs e)
955 		{
956 			LastCodeWindow.CodeViewer.TextZoom += 10;
957 		}
958 
mnuDecreaseFontSize_Click(object sender, EventArgs e)959 		private void mnuDecreaseFontSize_Click(object sender, EventArgs e)
960 		{
961 			LastCodeWindow.CodeViewer.TextZoom -= 10;
962 		}
963 
mnuResetFontSize_Click(object sender, EventArgs e)964 		private void mnuResetFontSize_Click(object sender, EventArgs e)
965 		{
966 			LastCodeWindow.CodeViewer.TextZoom = 100;
967 		}
968 
mnuClose_Click(object sender, EventArgs e)969 		private void mnuClose_Click(object sender, EventArgs e)
970 		{
971 			this.Close();
972 		}
973 
OnFormClosing(FormClosingEventArgs e)974 		protected override void OnFormClosing(FormClosingEventArgs e)
975 		{
976 			LabelManager.OnLabelUpdated -= LabelManager_OnLabelUpdated;
977 			BreakpointManager.BreakpointsChanged -= BreakpointManager_BreakpointsChanged;
978 			ctrlConsoleStatus.OnStateChanged -= ctrlConsoleStatus_OnStateChanged;
979 			ctrlProfiler.OnFunctionSelected -= ctrlProfiler_OnFunctionSelected;
980 
981 			if(_notifListener != null) {
982 				_notifListener.Dispose();
983 				_notifListener = null;
984 			}
985 
986 			InteropEmu.DebugSetFlags(0);
987 			InteropEmu.SetFlag(EmulationFlags.DebuggerWindowEnabled, false);
988 			BreakpointManager.SetBreakpoints();
989 			if(_wasPaused) {
990 				InteropEmu.Pause();
991 			}
992 			InteropEmu.DebugRun();
993 
994 			ConfigManager.Config.DebugInfo.FontFamily = ctrlDebuggerCode.CodeViewer.BaseFont.FontFamily.Name;
995 			ConfigManager.Config.DebugInfo.FontStyle = ctrlDebuggerCode.CodeViewer.BaseFont.Style;
996 			ConfigManager.Config.DebugInfo.FontSize = ctrlDebuggerCode.CodeViewer.BaseFont.Size;
997 			ConfigManager.Config.DebugInfo.WindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
998 			ConfigManager.Config.DebugInfo.WindowWidth = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Width : this.Width;
999 			ConfigManager.Config.DebugInfo.WindowHeight = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Height : this.Height;
1000 			ConfigManager.Config.DebugInfo.TopPanelHeight = this.splitContainer.GetSplitterDistance();
1001 			ConfigManager.Config.DebugInfo.LeftPanelWidth = this.ctrlSplitContainerTop.GetSplitterDistance();
1002 
1003 			ConfigManager.Config.DebugInfo.LeftView.UsingSourceView = this.ctrlSourceViewer.Visible;
1004 			ConfigManager.Config.DebugInfo.RightView.UsingSourceView = this.ctrlSourceViewerSplit.Visible;
1005 
1006 			ConfigManager.ApplyChanges();
1007 
1008 			DebugWorkspaceManager.SaveWorkspace();
1009 		}
1010 
mnuNametableViewer_Click(object sender, EventArgs e)1011 		private void mnuNametableViewer_Click(object sender, EventArgs e)
1012 		{
1013 			DebugWindowManager.OpenDebugWindow(DebugWindow.PpuViewer);
1014 		}
1015 
mnuApuViewer_Click(object sender, EventArgs e)1016 		private void mnuApuViewer_Click(object sender, EventArgs e)
1017 		{
1018 			DebugWindowManager.OpenDebugWindow(DebugWindow.ApuViewer);
1019 		}
1020 
ctrlCallstack_FunctionSelected(object sender, EventArgs e)1021 		private void ctrlCallstack_FunctionSelected(object sender, EventArgs e)
1022 		{
1023 			LastCodeWindow.ScrollToLineNumber((int)sender);
1024 		}
1025 
ctrlConsoleStatus_OnStateChanged(object sender, EventArgs e)1026 		private void ctrlConsoleStatus_OnStateChanged(object sender, EventArgs e)
1027 		{
1028 			UpdateDebugger(true, false);
1029 		}
1030 
mnuLoadCdlFile_Click(object sender, EventArgs e)1031 		private void mnuLoadCdlFile_Click(object sender, EventArgs e)
1032 		{
1033 			OpenFileDialog ofd = new OpenFileDialog();
1034 			ofd.SetFilter("CDL files (*.cdl)|*.cdl");
1035 			if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
1036 				if(!InteropEmu.DebugLoadCdlFile(ofd.FileName)) {
1037 					MessageBox.Show("Could not load CDL file.  The file selected file is invalid.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
1038 				}
1039 			}
1040 		}
1041 
mnuSaveAsCdlFile_Click(object sender, EventArgs e)1042 		private void mnuSaveAsCdlFile_Click(object sender, EventArgs e)
1043 		{
1044 			SaveFileDialog sfd = new SaveFileDialog();
1045 			sfd.SetFilter("CDL files (*.cdl)|*.cdl");
1046 			sfd.AddExtension = true;
1047 			if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
1048 				if(!InteropEmu.DebugSaveCdlFile(sfd.FileName)) {
1049 					MessageBox.Show("Error while trying to save CDL file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
1050 				}
1051 			}
1052 		}
1053 
mnuResetCdlLog_Click(object sender, EventArgs e)1054 		private void mnuResetCdlLog_Click(object sender, EventArgs e)
1055 		{
1056 			InteropEmu.DebugResetCdlLog();
1057 			UpdateDebugger(false);
1058 		}
1059 
ctrlBreakpoints_BreakpointNavigation(object sender, EventArgs e)1060 		private void ctrlBreakpoints_BreakpointNavigation(object sender, EventArgs e)
1061 		{
1062 			Breakpoint bp = (Breakpoint)sender;
1063 			if(bp.IsCpuBreakpoint) {
1064 				int relAddress = bp.GetRelativeAddress();
1065 				if(relAddress >= 0) {
1066 					LastCodeWindow.ScrollToLineNumber(relAddress);
1067 				}
1068 			}
1069 		}
1070 
mnuTextHooker_Click(object sender, EventArgs e)1071 		private void mnuTextHooker_Click(object sender, EventArgs e)
1072 		{
1073 			DebugWindowManager.OpenDebugWindow(DebugWindow.TextHooker);
1074 		}
1075 
mnuTraceLogger_Click(object sender, EventArgs e)1076 		private void mnuTraceLogger_Click(object sender, EventArgs e)
1077 		{
1078 			DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
1079 		}
1080 
mnuAutoCreateJumpLabels_Click(object sender, EventArgs e)1081 		private void mnuAutoCreateJumpLabels_Click(object sender, EventArgs e)
1082 		{
1083 			ConfigManager.Config.DebugInfo.AutoCreateJumpLabels = mnuAutoCreateJumpLabels.Checked;
1084 			ConfigManager.ApplyChanges();
1085 		}
1086 
mnuCopyAddresses_Click(object sender, EventArgs e)1087 		private void mnuCopyAddresses_Click(object sender, EventArgs e)
1088 		{
1089 			ConfigManager.Config.DebugInfo.CopyAddresses = mnuCopyAddresses.Checked;
1090 			ConfigManager.ApplyChanges();
1091 		}
1092 
mnuCopyByteCode_Click(object sender, EventArgs e)1093 		private void mnuCopyByteCode_Click(object sender, EventArgs e)
1094 		{
1095 			ConfigManager.Config.DebugInfo.CopyByteCode = mnuCopyByteCode.Checked;
1096 			ConfigManager.ApplyChanges();
1097 		}
1098 
mnuCopyComments_Click(object sender, EventArgs e)1099 		private void mnuCopyComments_Click(object sender, EventArgs e)
1100 		{
1101 			ConfigManager.Config.DebugInfo.CopyComments = mnuCopyComments.Checked;
1102 			ConfigManager.ApplyChanges();
1103 		}
1104 
mnuHidePauseIcon_Click(object sender, EventArgs e)1105 		private void mnuHidePauseIcon_Click(object sender, EventArgs e)
1106 		{
1107 			ConfigManager.Config.DebugInfo.HidePauseIcon = mnuHidePauseIcon.Checked;
1108 			ConfigManager.ApplyChanges();
1109 		}
1110 
mnuPpuPartialDraw_Click(object sender, EventArgs e)1111 		private void mnuPpuPartialDraw_Click(object sender, EventArgs e)
1112 		{
1113 			ConfigManager.Config.DebugInfo.PpuPartialDraw = mnuPpuPartialDraw.Checked;
1114 			ConfigManager.ApplyChanges();
1115 			mnuPpuShowPreviousFrame.Enabled = mnuPpuPartialDraw.Checked;
1116 		}
1117 
mnuShowPreviousFrame_Click(object sender, EventArgs e)1118 		private void mnuShowPreviousFrame_Click(object sender, EventArgs e)
1119 		{
1120 			ConfigManager.Config.DebugInfo.PpuShowPreviousFrame = mnuPpuShowPreviousFrame.Checked;
1121 			ConfigManager.ApplyChanges();
1122 		}
1123 
mnuShowEffectiveAddresses_Click(object sender, EventArgs e)1124 		private void mnuShowEffectiveAddresses_Click(object sender, EventArgs e)
1125 		{
1126 			ConfigManager.Config.DebugInfo.ShowEffectiveAddresses = mnuShowEffectiveAddresses.Checked;
1127 			ConfigManager.ApplyChanges();
1128 			UpdateDebugger(false);
1129 		}
1130 
mnuShowToolbar_Click(object sender, EventArgs e)1131 		private void mnuShowToolbar_Click(object sender, EventArgs e)
1132 		{
1133 			tsToolbar.Visible = mnuShowToolbar.Checked;
1134 			ConfigManager.Config.DebugInfo.ShowToolbar = mnuShowToolbar.Checked;
1135 			ConfigManager.ApplyChanges();
1136 		}
1137 
mnuShowCpuMemoryMapping_Click(object sender, EventArgs e)1138 		private void mnuShowCpuMemoryMapping_Click(object sender, EventArgs e)
1139 		{
1140 			ctrlCpuMemoryMapping.Visible = mnuShowCpuMemoryMapping.Checked;
1141 			ConfigManager.Config.DebugInfo.ShowCpuMemoryMapping = mnuShowCpuMemoryMapping.Checked;
1142 			ConfigManager.ApplyChanges();
1143 		}
1144 
mnuShowPpuMemoryMapping_Click(object sender, EventArgs e)1145 		private void mnuShowPpuMemoryMapping_Click(object sender, EventArgs e)
1146 		{
1147 			ctrlPpuMemoryMapping.Visible = mnuShowPpuMemoryMapping.Checked;
1148 			ConfigManager.Config.DebugInfo.ShowPpuMemoryMapping = mnuShowPpuMemoryMapping.Checked;
1149 			ConfigManager.ApplyChanges();
1150 		}
1151 
mnuShowCodePreview_CheckedChanged(object sender, EventArgs e)1152 		private void mnuShowCodePreview_CheckedChanged(object sender, EventArgs e)
1153 		{
1154 			ConfigManager.Config.DebugInfo.ShowCodePreview = mnuShowCodePreview.Checked;
1155 			ConfigManager.ApplyChanges();
1156 		}
1157 
mnuShowOpCodeTooltips_CheckedChanged(object sender, EventArgs e)1158 		private void mnuShowOpCodeTooltips_CheckedChanged(object sender, EventArgs e)
1159 		{
1160 			ConfigManager.Config.DebugInfo.ShowOpCodeTooltips = mnuShowOpCodeTooltips.Checked;
1161 			ConfigManager.ApplyChanges();
1162 		}
1163 
mnuTooltipShowOnShift_CheckedChanged(object sender, EventArgs e)1164 		private void mnuTooltipShowOnShift_CheckedChanged(object sender, EventArgs e)
1165 		{
1166 			ConfigManager.Config.DebugInfo.OnlyShowTooltipsOnShift = mnuOnlyShowTooltipOnShift.Checked;
1167 			ConfigManager.ApplyChanges();
1168 		}
1169 
mnuBreakOnFirstCycle_Click(object sender, EventArgs e)1170 		private void mnuBreakOnFirstCycle_Click(object sender, EventArgs e)
1171 		{
1172 			ConfigManager.Config.DebugInfo.BreakOnFirstCycle = !mnuEnableSubInstructionBreakpoints.Checked;
1173 			ConfigManager.ApplyChanges();
1174 			UpdateDebuggerFlags();
1175 		}
1176 
mnuBreakOnReset_Click(object sender, EventArgs e)1177 		private void mnuBreakOnReset_Click(object sender, EventArgs e)
1178 		{
1179 			ConfigManager.Config.DebugInfo.BreakOnReset = mnuBreakOnReset.Checked;
1180 			ConfigManager.ApplyChanges();
1181 		}
1182 
mnuBreakOnInit_Click(object sender, EventArgs e)1183 		private void mnuBreakOnInit_Click(object sender, EventArgs e)
1184 		{
1185 			ConfigManager.Config.DebugInfo.BreakOnInit = mnuBreakOnInit.Checked;
1186 			ConfigManager.ApplyChanges();
1187 			UpdateDebuggerFlags();
1188 		}
1189 
mnuBreakOnPlay_Click(object sender, EventArgs e)1190 		private void mnuBreakOnPlay_Click(object sender, EventArgs e)
1191 		{
1192 			ConfigManager.Config.DebugInfo.BreakOnPlay = mnuBreakOnPlay.Checked;
1193 			ConfigManager.ApplyChanges();
1194 			UpdateDebuggerFlags();
1195 		}
1196 
mnuBreakOnOpen_Click(object sender, EventArgs e)1197 		private void mnuBreakOnOpen_Click(object sender, EventArgs e)
1198 		{
1199 			ConfigManager.Config.DebugInfo.BreakOnOpen = mnuBreakOnOpen.Checked;
1200 			ConfigManager.ApplyChanges();
1201 		}
1202 
mnuBreakOnUnofficialOpcodes_Click(object sender, EventArgs e)1203 		private void mnuBreakOnUnofficialOpcodes_Click(object sender, EventArgs e)
1204 		{
1205 			ConfigManager.Config.DebugInfo.BreakOnUnofficialOpcodes = mnuBreakOnUnofficialOpcodes.Checked;
1206 			ConfigManager.ApplyChanges();
1207 			UpdateDebuggerFlags();
1208 		}
1209 
mnuBreakOnBrk_Click(object sender, EventArgs e)1210 		private void mnuBreakOnBrk_Click(object sender, EventArgs e)
1211 		{
1212 			ConfigManager.Config.DebugInfo.BreakOnBrk = mnuBreakOnBrk.Checked;
1213 			ConfigManager.ApplyChanges();
1214 			UpdateDebuggerFlags();
1215 		}
1216 
mnuBreakOnUninitMemoryRead_Click(object sender, EventArgs e)1217 		private void mnuBreakOnUninitMemoryRead_Click(object sender, EventArgs e)
1218 		{
1219 			ConfigManager.Config.DebugInfo.BreakOnUninitMemoryRead = mnuBreakOnUninitMemoryRead.Checked;
1220 			ConfigManager.ApplyChanges();
1221 			UpdateDebuggerFlags();
1222 		}
1223 
mnuBreakOnDecayedOamRead_Click(object sender, EventArgs e)1224 		private void mnuBreakOnDecayedOamRead_Click(object sender, EventArgs e)
1225 		{
1226 			ConfigManager.Config.DebugInfo.BreakOnDecayedOamRead = mnuBreakOnDecayedOamRead.Checked;
1227 			ConfigManager.ApplyChanges();
1228 			UpdateDebuggerFlags();
1229 		}
1230 
mnuBreakOnCrash_Click(object sender, EventArgs e)1231 		private void mnuBreakOnCrash_Click(object sender, EventArgs e)
1232 		{
1233 			ConfigManager.Config.DebugInfo.BreakOnCrash = mnuBreakOnCrash.Checked;
1234 			ConfigManager.ApplyChanges();
1235 			DebugInfo.ApplyConfig();
1236 		}
1237 
mnuBreakOnDebuggerFocus_Click(object sender, EventArgs e)1238 		private void mnuBreakOnDebuggerFocus_Click(object sender, EventArgs e)
1239 		{
1240 			ConfigManager.Config.DebugInfo.BreakOnDebuggerFocus = mnuBreakOnDebuggerFocus.Checked;
1241 			ConfigManager.ApplyChanges();
1242 		}
1243 
mnuBringToFrontOnPause_Click(object sender, EventArgs e)1244 		private void mnuBringToFrontOnPause_Click(object sender, EventArgs e)
1245 		{
1246 			ConfigManager.Config.DebugInfo.BringToFrontOnPause = mnuBringToFrontOnPause.Checked;
1247 			ConfigManager.ApplyChanges();
1248 		}
1249 
mnuBringToFrontOnBreak_Click(object sender, EventArgs e)1250 		private void mnuBringToFrontOnBreak_Click(object sender, EventArgs e)
1251 		{
1252 			ConfigManager.Config.DebugInfo.BringToFrontOnBreak = mnuBringToFrontOnBreak.Checked;
1253 			ConfigManager.ApplyChanges();
1254 		}
1255 
mnuShowBreakNotifications_Click(object sender, EventArgs e)1256 		private void mnuShowBreakNotifications_Click(object sender, EventArgs e)
1257 		{
1258 			ConfigManager.Config.DebugInfo.ShowBreakNotifications = mnuShowBreakNotifications.Checked;
1259 			ConfigManager.ApplyChanges();
1260 		}
1261 
mnuShowInstructionProgression_Click(object sender, EventArgs e)1262 		private void mnuShowInstructionProgression_Click(object sender, EventArgs e)
1263 		{
1264 			ConfigManager.Config.DebugInfo.ShowInstructionProgression = mnuShowInstructionProgression.Checked;
1265 			ConfigManager.ApplyChanges();
1266 
1267 			UpdateDebugger(false, false);
1268 		}
1269 
mnuShowSelectionLength_Click(object sender, EventArgs e)1270 		private void mnuShowSelectionLength_Click(object sender, EventArgs e)
1271 		{
1272 			ConfigManager.Config.DebugInfo.ShowSelectionLength = mnuShowSelectionLength.Checked;
1273 			ConfigManager.ApplyChanges();
1274 
1275 			UpdateDebugger(false, false);
1276 		}
1277 
mnuAlwaysScrollToCenter_Click(object sender, EventArgs e)1278 		private void mnuAlwaysScrollToCenter_Click(object sender, EventArgs e)
1279 		{
1280 			ConfigManager.Config.DebugInfo.AlwaysScrollToCenter = mnuAlwaysScrollToCenter.Checked;
1281 			ConfigManager.ApplyChanges();
1282 		}
1283 
mnuRefreshWhileRunning_Click(object sender, EventArgs e)1284 		private void mnuRefreshWhileRunning_Click(object sender, EventArgs e)
1285 		{
1286 			ConfigManager.Config.DebugInfo.RefreshWhileRunning = mnuRefreshWhileRunning.Checked;
1287 			ConfigManager.ApplyChanges();
1288 		}
1289 
mnuShowMemoryValues_Click(object sender, EventArgs e)1290 		private void mnuShowMemoryValues_Click(object sender, EventArgs e)
1291 		{
1292 			ConfigManager.Config.DebugInfo.ShowMemoryValuesInCodeWindow = mnuShowMemoryValues.Checked;
1293 			ConfigManager.ApplyChanges();
1294 
1295 			ctrlDebuggerCode.ShowMemoryValues = mnuShowMemoryValues.Checked;
1296 			ctrlDebuggerCodeSplit.ShowMemoryValues = mnuShowMemoryValues.Checked;
1297 		}
1298 
mnuDisableDefaultLabels_Click(object sender, EventArgs e)1299 		private void mnuDisableDefaultLabels_Click(object sender, EventArgs e)
1300 		{
1301 			ConfigManager.Config.DebugInfo.DisableDefaultLabels = mnuDisableDefaultLabels.Checked;
1302 			ConfigManager.ApplyChanges();
1303 		}
1304 
mnuDisplayOpCodesInLowerCase_Click(object sender, EventArgs e)1305 		private void mnuDisplayOpCodesInLowerCase_Click(object sender, EventArgs e)
1306 		{
1307 			ConfigManager.Config.DebugInfo.DisplayOpCodesInLowerCase = mnuDisplayOpCodesInLowerCase.Checked;
1308 			ConfigManager.ApplyChanges();
1309 			this.UpdateDebuggerFlags();
1310 			this.UpdateDebugger(false);
1311 		}
1312 
ctrlFunctionList_OnFunctionSelected(GoToDestination dest)1313 		private void ctrlFunctionList_OnFunctionSelected(GoToDestination dest)
1314 		{
1315 			GoToDestination(LastCodeWindow, dest);
1316 		}
1317 
ctrlLabelList_OnLabelSelected(GoToDestination dest)1318 		private void ctrlLabelList_OnLabelSelected(GoToDestination dest)
1319 		{
1320 			GoToDestination(LastCodeWindow, dest);
1321 		}
1322 
LabelManager_OnLabelUpdated(object sender, EventArgs e)1323 		private void LabelManager_OnLabelUpdated(object sender, EventArgs e)
1324 		{
1325 			DebugWorkspaceManager.SaveWorkspace();
1326 			ctrlLabelList.UpdateLabelList();
1327 			ctrlFunctionList.UpdateFunctionList(true);
1328 			UpdateDebugger(false, false);
1329 		}
1330 
mnuResetWorkspace_Click(object sender, EventArgs e)1331 		private void mnuResetWorkspace_Click(object sender, EventArgs e)
1332 		{
1333 			if(MessageBox.Show("This operation will empty the watch window, remove all breakpoints, and reset labels to their default state." + Environment.NewLine + "Are you sure?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) {
1334 				DebugWorkspaceManager.ResetWorkspace();
1335 				UpdateWorkspace();
1336 				UpdateDebugger(false);
1337 			}
1338 		}
1339 
mnuResetLabels_Click(object sender, EventArgs e)1340 		private void mnuResetLabels_Click(object sender, EventArgs e)
1341 		{
1342 			if(MessageBox.Show("This operation will reset labels to their default state." + Environment.NewLine + "Are you sure?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) {
1343 				DebugWorkspaceManager.ResetLabels();
1344 				UpdateWorkspace();
1345 				UpdateDebugger(false);
1346 			}
1347 		}
1348 
ImportLabelFile(string path)1349 		private void ImportLabelFile(string path)
1350 		{
1351 			string ext = Path.GetExtension(path).ToLower();
1352 			if(ext == ".mlb") {
1353 				DebugWorkspaceManager.ImportMlbFile(path);
1354 			} else if(ext == ".fns") {
1355 				DebugWorkspaceManager.ImportNesasmFnsFile(path);
1356 			} else {
1357 				DebugWorkspaceManager.ImportDbgFile(path, false);
1358 			}
1359 		}
1360 
mnuImportLabels_Click(object sender, EventArgs e)1361 		private void mnuImportLabels_Click(object sender, EventArgs e)
1362 		{
1363 			OpenFileDialog ofd = new OpenFileDialog();
1364 			ofd.SetFilter("All supported files (*.dbg, *.mlb, *.fns)|*.dbg;*.mlb;*.fns");
1365 			if(ofd.ShowDialog() == DialogResult.OK) {
1366 				ImportLabelFile(ofd.FileName);
1367 			}
1368 		}
1369 
mnuExportLabels_Click(object sender, EventArgs e)1370 		private void mnuExportLabels_Click(object sender, EventArgs e)
1371 		{
1372 			SaveFileDialog sfd = new SaveFileDialog();
1373 			sfd.SetFilter("All supported files (*.mlb)|*.mlb");
1374 			if(sfd.ShowDialog() == DialogResult.OK) {
1375 				MesenLabelFile.Export(sfd.FileName);
1376 			}
1377 		}
1378 
ctrlLabelList_OnFindOccurrence(object sender, EventArgs e)1379 		private void ctrlLabelList_OnFindOccurrence(object sender, EventArgs e)
1380 		{
1381 			CodeLabel label = sender as CodeLabel;
1382 			LastCodeWindow.FindAllOccurrences(label.Label, true, true);
1383 		}
1384 
ctrlFunctionList_OnFindOccurrence(object sender, EventArgs e)1385 		private void ctrlFunctionList_OnFindOccurrence(object sender, EventArgs e)
1386 		{
1387 			LastCodeWindow.FindAllOccurrences(sender as string, true, true);
1388 		}
1389 
mnuBreakIn_Click(object sender, EventArgs e)1390 		private void mnuBreakIn_Click(object sender, EventArgs e)
1391 		{
1392 			using(frmBreakIn frm = new frmBreakIn()) {
1393 				frm.ShowDialog();
1394 			}
1395 		}
1396 
mnuBreakOn_Click(object sender, EventArgs e)1397 		private void mnuBreakOn_Click(object sender, EventArgs e)
1398 		{
1399 			using(frmBreakOn frm = new frmBreakOn()) {
1400 				frm.ShowDialog();
1401 			}
1402 		}
1403 
mnuFindAllOccurrences_Click(object sender, EventArgs e)1404 		private void mnuFindAllOccurrences_Click(object sender, EventArgs e)
1405 		{
1406 			frmFindOccurrences frm = new Debugger.frmFindOccurrences();
1407 			if(frm.ShowDialog() == DialogResult.OK) {
1408 				LastCodeWindow.FindAllOccurrences(frm.SearchString, frm.MatchWholeWord, frm.MatchCase);
1409 			}
1410 		}
1411 
mnuAutoLoadDbgFiles_Click(object sender, EventArgs e)1412 		private void mnuAutoLoadDbgFiles_Click(object sender, EventArgs e)
1413 		{
1414 			if(_debuggerInitialized) {
1415 				ConfigManager.Config.DebugInfo.AutoLoadDbgFiles = mnuAutoLoadDbgFiles.Checked;
1416 				ConfigManager.ApplyChanges();
1417 				DebugWorkspaceManager.AutoLoadDbgFiles(false);
1418 			}
1419 		}
1420 
mnuAutoLoadCdlFiles_Click(object sender, EventArgs e)1421 		private void mnuAutoLoadCdlFiles_Click(object sender, EventArgs e)
1422 		{
1423 			if(_debuggerInitialized) {
1424 				ConfigManager.Config.DebugInfo.AutoLoadCdlFiles = mnuAutoLoadCdlFiles.Checked;
1425 				ConfigManager.ApplyChanges();
1426 				AutoLoadCdlFiles();
1427 			}
1428 		}
1429 
ctrlConsoleStatus_OnGotoLocation(object sender, EventArgs e)1430 		private void ctrlConsoleStatus_OnGotoLocation(object sender, EventArgs e)
1431 		{
1432 			LastCodeWindow.ScrollToLineNumber((int)sender);
1433 		}
1434 
UpdateDisassembleFlags()1435 		private void UpdateDisassembleFlags()
1436 		{
1437 			ConfigManager.ApplyChanges();
1438 			UpdateDebuggerFlags();
1439 			UpdateDebugger(false);
1440 		}
1441 
mnuDisassembleVerifiedData_Click(object sender, EventArgs e)1442 		private void mnuDisassembleVerifiedData_Click(object sender, EventArgs e)
1443 		{
1444 			ConfigManager.Config.DebugInfo.DisassembleVerifiedData = mnuDisassembleVerifiedData.Checked;
1445 			UpdateDisassembleFlags();
1446 		}
1447 
mnuDisassembleUnidentifiedData_Click(object sender, EventArgs e)1448 		private void mnuDisassembleUnidentifiedData_Click(object sender, EventArgs e)
1449 		{
1450 			ConfigManager.Config.DebugInfo.DisassembleUnidentifiedData = mnuDisassembleUnidentifiedData.Checked;
1451 			UpdateDisassembleFlags();
1452 		}
1453 
mnuShowVerifiedData_Click(object sender, EventArgs e)1454 		private void mnuShowVerifiedData_Click(object sender, EventArgs e)
1455 		{
1456 			ConfigManager.Config.DebugInfo.ShowVerifiedData = mnuShowVerifiedData.Checked;
1457 			UpdateDisassembleFlags();
1458 		}
1459 
mnuShowUnidentifiedData_Click(object sender, EventArgs e)1460 		private void mnuShowUnidentifiedData_Click(object sender, EventArgs e)
1461 		{
1462 			ConfigManager.Config.DebugInfo.ShowUnidentifiedData = mnuShowUnidentifiedData.Checked;
1463 			UpdateDisassembleFlags();
1464 		}
1465 
ctrlSplitContainerTop_PanelCollapsed(object sender, EventArgs e)1466 		private void ctrlSplitContainerTop_PanelCollapsed(object sender, EventArgs e)
1467 		{
1468 			mnuShowFunctionLabelLists.Checked = false;
1469 			ConfigManager.Config.DebugInfo.ShowRightPanel = mnuShowFunctionLabelLists.Checked;
1470 			ConfigManager.ApplyChanges();
1471 		}
1472 
ctrlSplitContainerTop_PanelExpanded(object sender, EventArgs e)1473 		private void ctrlSplitContainerTop_PanelExpanded(object sender, EventArgs e)
1474 		{
1475 			mnuShowFunctionLabelLists.Checked = true;
1476 			ConfigManager.Config.DebugInfo.ShowRightPanel = mnuShowFunctionLabelLists.Checked;
1477 			ConfigManager.ApplyChanges();
1478 		}
1479 
mnuShowFunctionLabelLists_Click(object sender, EventArgs e)1480 		private void mnuShowFunctionLabelLists_Click(object sender, EventArgs e)
1481 		{
1482 			if(mnuShowFunctionLabelLists.Checked) {
1483 				this.ctrlSplitContainerTop.ExpandPanel();
1484 			} else {
1485 				this.ctrlSplitContainerTop.CollapsePanel();
1486 			}
1487 		}
1488 
splitContainer_PanelCollapsed(object sender, EventArgs e)1489 		private void splitContainer_PanelCollapsed(object sender, EventArgs e)
1490 		{
1491 			mnuShowBottomPanel.Checked = false;
1492 			ConfigManager.Config.DebugInfo.ShowBottomPanel = mnuShowBottomPanel.Checked;
1493 			ConfigManager.ApplyChanges();
1494 		}
1495 
splitContainer_PanelExpanded(object sender, EventArgs e)1496 		private void splitContainer_PanelExpanded(object sender, EventArgs e)
1497 		{
1498 			mnuShowBottomPanel.Checked = true;
1499 			ConfigManager.Config.DebugInfo.ShowBottomPanel = mnuShowBottomPanel.Checked;
1500 			ConfigManager.ApplyChanges();
1501 		}
1502 
mnuShowBottomPanel_Click(object sender, EventArgs e)1503 		private void mnuShowBottomPanel_Click(object sender, EventArgs e)
1504 		{
1505 			if(mnuShowBottomPanel.Checked) {
1506 				splitContainer.ExpandPanel();
1507 			} else {
1508 				splitContainer.CollapsePanel();
1509 			}
1510 		}
1511 
mnuSaveRom_Click(object sender, EventArgs e)1512 		private void mnuSaveRom_Click(object sender, EventArgs e)
1513 		{
1514 			InteropEmu.DebugSaveRomToDisk(InteropEmu.GetRomInfo().RomFile.Path);
1515 		}
1516 
mnuSaveRomAs_Click(object sender, EventArgs e)1517 		private void mnuSaveRomAs_Click(object sender, EventArgs e)
1518 		{
1519 			using(SaveFileDialog sfd = new SaveFileDialog()) {
1520 				sfd.SetFilter("NES roms (*.nes)|*.nes");
1521 				sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + "_Modified.nes";
1522 				sfd.InitialDirectory = ConfigManager.DebuggerFolder;
1523 				if(sfd.ShowDialog() == DialogResult.OK) {
1524 					InteropEmu.DebugSaveRomToDisk(sfd.FileName);
1525 				}
1526 			}
1527 		}
1528 
mnuSaveAsIps_Click(object sender, EventArgs e)1529 		private void mnuSaveAsIps_Click(object sender, EventArgs e)
1530 		{
1531 			using(SaveFileDialog sfd = new SaveFileDialog()) {
1532 				sfd.SetFilter("IPS patch files (*.ips)|*.ips");
1533 				sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".ips";
1534 				sfd.InitialDirectory = ConfigManager.DebuggerFolder;
1535 				if(sfd.ShowDialog() == DialogResult.OK) {
1536 					InteropEmu.DebugSaveRomToDisk(sfd.FileName, true);
1537 				}
1538 			}
1539 		}
1540 
SaveRomWithCdlStripping(CdlStripFlag cdlStripFlag)1541 		private void SaveRomWithCdlStripping(CdlStripFlag cdlStripFlag)
1542 		{
1543 			using(SaveFileDialog sfd = new SaveFileDialog()) {
1544 				sfd.SetFilter("NES roms (*.nes)|*.nes");
1545 				sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + (cdlStripFlag == CdlStripFlag.StripUnused ? "_StripUnusedData.nes" : "_StripUsedData.nes");
1546 				sfd.InitialDirectory = ConfigManager.DebuggerFolder;
1547 				if(sfd.ShowDialog() == DialogResult.OK) {
1548 					InteropEmu.DebugSaveRomToDisk(sfd.FileName, false, null, cdlStripFlag);
1549 				}
1550 			}
1551 		}
1552 
mnuRevertChanges_Click(object sender, EventArgs e)1553 		private void mnuRevertChanges_Click(object sender, EventArgs e)
1554 		{
1555 			InteropEmu.DebugRevertPrgChrChanges();
1556 			UpdateDebugger(false);
1557 		}
1558 
mnuEditHeader_Click(object sender, EventArgs e)1559 		private void mnuEditHeader_Click(object sender, EventArgs e)
1560 		{
1561 			using(frmEditHeader frm = new frmEditHeader()) {
1562 				frm.ShowDialog(sender, this);
1563 			}
1564 		}
1565 
mnuScriptWindow_Click(object sender, EventArgs e)1566 		private void mnuScriptWindow_Click(object sender, EventArgs e)
1567 		{
1568 			DebugWindowManager.OpenDebugWindow(DebugWindow.ScriptWindow);
1569 		}
1570 
mnuProfiler_Click(object sender, EventArgs e)1571 		private void mnuProfiler_Click(object sender, EventArgs e)
1572 		{
1573 			DebugWindowManager.OpenDebugWindow(DebugWindow.Profiler);
1574 		}
1575 
mnuAssembler_Click(object sender, EventArgs e)1576 		private void mnuAssembler_Click(object sender, EventArgs e)
1577 		{
1578 			DebugWindowManager.OpenDebugWindow(DebugWindow.Assembler);
1579 		}
1580 
ctrlDebuggerCode_OnEditCode(AssemblerEventArgs args)1581 		private void ctrlDebuggerCode_OnEditCode(AssemblerEventArgs args)
1582 		{
1583 			DebugWindowManager.OpenAssembler(args.Code, args.StartAddress, args.BlockLength);
1584 		}
1585 
CopyMenu(ToolStripItemCollection source, ToolStripItemCollection dest)1586 		private void CopyMenu(ToolStripItemCollection source, ToolStripItemCollection dest)
1587 		{
1588 			List<ToolStripItem> items = new List<ToolStripItem>();
1589 			foreach(ToolStripItem item in source) {
1590 				if(item is ToolStripSeparator) {
1591 					ToolStripSeparator sep = new ToolStripSeparator();
1592 					sep.Name = item.Name;
1593 					sep.Visible = true;
1594 					items.Add(sep);
1595 				} else if(item is ToolStripMenuItem) {
1596 					ToolStripMenuItem copy = new ToolStripMenuItem(item.Text, item.Image);
1597 					copy.Name = item.Name;
1598 					copy.Enabled = item.Enabled;
1599 					copy.CheckOnClick = ((ToolStripMenuItem)item).CheckOnClick;
1600 					copy.Checked = ((ToolStripMenuItem)item).Checked;
1601 					copy.Visible = true;
1602 					copy.Click += (s, e) => {
1603 						item.PerformClick();
1604 					};
1605 
1606 					if(((ToolStripMenuItem)item).DropDownItems.Count > 0) {
1607 						CopyMenu(((ToolStripMenuItem)item).DropDownItems, copy.DropDownItems);
1608 					}
1609 
1610 					if(item.Tag is ShortcutInfo) {
1611 						copy.InitShortcut(this, ((ShortcutInfo)item.Tag).ShortcutKey);
1612 					}
1613 
1614 					items.Add(copy);
1615 				} else {
1616 					//Not used
1617 				}
1618 			}
1619 			dest.AddRange(items.ToArray());
1620 		}
1621 
CleanupMenu(ToolStripItemCollection items)1622 		private void CleanupMenu(ToolStripItemCollection items)
1623 		{
1624 			foreach(ToolStripItem item in items) {
1625 				if(item.Tag is ShortcutInfo && ((ShortcutInfo)item.Tag).KeyHandler != null) {
1626 					DebuggerShortcutsConfig.ClearProcessCmdKeyHandler((ToolStripMenuItem)item, this);
1627 				}
1628 
1629 				if(item is ToolStripMenuItem && ((ToolStripMenuItem)item).HasDropDownItems) {
1630 					CleanupMenu(((ToolStripMenuItem)item).DropDownItems);
1631 				}
1632 			}
1633 		}
1634 
UpdateCodeMenu()1635 		private void UpdateCodeMenu()
1636 		{
1637 			CleanupMenu(mnuCode.DropDownItems);
1638 			mnuCode.DropDownItems.Clear();
1639 			CopyMenu(this.LastCodeWindow.CodeViewerActions.contextMenu.Items, mnuCode.DropDownItems);
1640 			this.LastCodeWindow.CodeViewerActions.UpdateContextMenuItemVisibility(mnuCode.DropDownItems);
1641 		}
1642 
mnuCode_DropDownOpening(object sender, EventArgs e)1643 		private void mnuCode_DropDownOpening(object sender, EventArgs e)
1644 		{
1645 			UpdateCodeMenu();
1646 		}
1647 
mnuCdlStripUsedData_Click(object sender, EventArgs e)1648 		private void mnuCdlStripUsedData_Click(object sender, EventArgs e)
1649 		{
1650 			SaveRomWithCdlStripping(CdlStripFlag.StripUsed);
1651 		}
1652 
mnuCdlStripUnusedData_Click(object sender, EventArgs e)1653 		private void mnuCdlStripUnusedData_Click(object sender, EventArgs e)
1654 		{
1655 			SaveRomWithCdlStripping(CdlStripFlag.StripUnused);
1656 		}
1657 
mnuConfigureColors_Click(object sender, EventArgs e)1658 		private void mnuConfigureColors_Click(object sender, EventArgs e)
1659 		{
1660 			using(frmDebuggerColors frm = new frmDebuggerColors()) {
1661 				if(frm.ShowDialog(this, this) == DialogResult.OK) {
1662 					this.UpdateDebugger(false, true);
1663 				}
1664 			}
1665 		}
1666 
mnuSelectFont_Click(object sender, EventArgs e)1667 		private void mnuSelectFont_Click(object sender, EventArgs e)
1668 		{
1669 			Font newFont = FontDialogHelper.SelectFont(ctrlDebuggerCode.CodeViewer.BaseFont);
1670 
1671 			ConfigManager.Config.DebugInfo.FontFamily = newFont.FontFamily.Name;
1672 			ConfigManager.Config.DebugInfo.FontStyle = newFont.Style;
1673 			ConfigManager.Config.DebugInfo.FontSize = newFont.Size;
1674 			ConfigManager.ApplyChanges();
1675 
1676 			ctrlDebuggerCode.CodeViewer.BaseFont = newFont;
1677 			ctrlDebuggerCodeSplit.CodeViewer.BaseFont = newFont;
1678 			ctrlSourceViewer.CodeViewer.BaseFont = newFont;
1679 			ctrlSourceViewerSplit.CodeViewer.BaseFont = newFont;
1680 		}
1681 
mnuPreferences_Click(object sender, EventArgs e)1682 		private void mnuPreferences_Click(object sender, EventArgs e)
1683 		{
1684 			using(frmDbgPreferences frm = new frmDbgPreferences()) {
1685 				frm.ShowDialog(sender, this);
1686 			}
1687 		}
1688 
mnuImportSettings_Click(object sender, EventArgs e)1689 		private void mnuImportSettings_Click(object sender, EventArgs e)
1690 		{
1691 			using(frmImportSettings frm = new frmImportSettings()) {
1692 				frm.ShowDialog(sender, this);
1693 			}
1694 		}
1695 
mnuReset_Click(object sender, EventArgs e)1696 		private void mnuReset_Click(object sender, EventArgs e)
1697 		{
1698 			InteropEmu.Reset();
1699 		}
1700 
mnuPowerCycle_Click(object sender, EventArgs e)1701 		private void mnuPowerCycle_Click(object sender, EventArgs e)
1702 		{
1703 			InteropEmu.PowerCycle();
1704 		}
1705 
OnResize(EventArgs e)1706 		protected override void OnResize(EventArgs e)
1707 		{
1708 			base.OnResize(e);
1709 
1710 			if(lblPrgAnalysis != null) {
1711 				if(this.Width - this._minimumSize.Width < 100) {
1712 					if(lblPrgAnalysis.Text != "PRG:") {
1713 						lblPrgAnalysis.Text = "PRG:";
1714 						lblChrAnalysis.Text = "CHR:";
1715 					}
1716 				} else if(lblPrgAnalysis.Text == "PRG:") {
1717 					lblPrgAnalysis.Text = "PRG analysis:";
1718 					lblChrAnalysis.Text = "CHR analysis:";
1719 				}
1720 			}
1721 		}
1722 
mnuUseVerticalLayout_CheckedChanged(object sender, EventArgs e)1723 		private void mnuUseVerticalLayout_CheckedChanged(object sender, EventArgs e)
1724 		{
1725 			ConfigManager.Config.DebugInfo.VerticalLayout = this.mnuUseVerticalLayout.Checked;
1726 			ConfigManager.ApplyChanges();
1727 
1728 			if(mnuUseVerticalLayout.Checked) {
1729 				this.ctrlSplitContainerTop.HidePanel2 = true;
1730 				this.ctrlSplitContainerTop.CollapsePanel();
1731 				this.tlpVerticalLayout.Controls.Add(this.grpLabels, 0, 0);
1732 				this.tlpVerticalLayout.Controls.Add(this.grpFunctions, 1, 0);
1733 			} else {
1734 				this.tlpFunctionLabelLists.Controls.Add(this.grpLabels, 0, 1);
1735 				this.tlpFunctionLabelLists.Controls.Add(this.grpFunctions, 0, 0);
1736 				this.ctrlSplitContainerTop.HidePanel2 = false;
1737 				this.ctrlSplitContainerTop.ExpandPanel();
1738 			}
1739 
1740 			mnuShowFunctionLabelLists.Enabled = !mnuUseVerticalLayout.Checked;
1741 			this.UpdateMinimumSize();
1742 		}
1743 
mnuBreakOptions_DropDownOpening(object sender, EventArgs e)1744 		private void mnuBreakOptions_DropDownOpening(object sender, EventArgs e)
1745 		{
1746 			this.mnuBreakOnDecayedOamRead.Enabled = ConfigManager.Config.EmulationInfo.EnableOamDecay;
1747 
1748 			bool isNsf = InteropEmu.IsNsf();
1749 			mnuBreakOnInit.Visible = isNsf;
1750 			mnuBreakOnPlay.Visible = isNsf;
1751 			sepBreakNsfOptions.Visible = isNsf;
1752 
1753 			mnuBreakOnReset.Enabled = !isNsf;
1754 		}
1755 
frmDebugger_DragDrop(object sender, DragEventArgs e)1756 		private void frmDebugger_DragDrop(object sender, DragEventArgs e)
1757 		{
1758 			try {
1759 				string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
1760 				if(files != null && File.Exists(files[0])) {
1761 					ImportLabelFile(files[0]);
1762 				}
1763 			} catch(Exception ex) {
1764 				MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString());
1765 			}
1766 		}
1767 
frmDebugger_DragEnter(object sender, DragEventArgs e)1768 		private void frmDebugger_DragEnter(object sender, DragEventArgs e)
1769 		{
1770 			try {
1771 				if(e.Data != null && e.Data.GetDataPresent(DataFormats.FileDrop)) {
1772 					string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
1773 					if(files != null && files.Length > 0) {
1774 						string ext = Path.GetExtension(files[0]).ToLower();
1775 						if(ext == ".dbg" || ext == ".mlb" || ext == ".fns") {
1776 							e.Effect = DragDropEffects.Copy;
1777 						}
1778 					}
1779 				}
1780 			} catch(Exception ex) {
1781 				MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString());
1782 			}
1783 		}
1784 
GetAlternateView(ICodeViewer viewer)1785 		private ICodeViewer GetAlternateView(ICodeViewer viewer)
1786 		{
1787 			if(viewer == ctrlDebuggerCode) {
1788 				return ctrlSourceViewer;
1789 			} else if(viewer == ctrlSourceViewer) {
1790 				return ctrlDebuggerCode;
1791 			} else if(viewer == ctrlDebuggerCodeSplit) {
1792 				return ctrlSourceViewerSplit;
1793 			} else if(viewer == ctrlSourceViewerSplit) {
1794 				return ctrlDebuggerCodeSplit;
1795 			}
1796 			return null;
1797 		}
1798 
GoToDestination(ICodeViewer target, GoToDestination dest)1799 		private void GoToDestination(ICodeViewer target, GoToDestination dest)
1800 		{
1801 			if(target is ctrlSourceViewer && !string.IsNullOrWhiteSpace(dest.File)) {
1802 				((ctrlSourceViewer)target).ScrollToFileLine(dest.File, dest.Line);
1803 			} else if(dest.CpuAddress >= 0) {
1804 				target.ScrollToLineNumber(dest.CpuAddress);
1805 			} else if(!string.IsNullOrWhiteSpace(dest.File)) {
1806 				if(!(target is ctrlSourceViewer)) {
1807 					ctrlDebuggerCode_OnSwitchView(target);
1808 					target = GetAlternateView(target);
1809 				}
1810 				if(target is ctrlSourceViewer) {
1811 					((ctrlSourceViewer)target).ScrollToFileLine(dest.File, dest.Line);
1812 				}
1813 			} else {
1814 				AddressTypeInfo addressInfo = dest.AddressInfo;
1815 				if(addressInfo == null && dest.Label != null) {
1816 					addressInfo = new AddressTypeInfo() { Address = (int)dest.Label.Address, Type = dest.Label.AddressType };
1817 				}
1818 
1819 				if(InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type) < 0) {
1820 					//Try to display the label in the source view if possible (when code is out of scope)
1821 					if(ctrlSourceViewer.CurrentFile != null && !(target is ctrlSourceViewer)) {
1822 						ctrlDebuggerCode_OnSwitchView(target);
1823 						target = GetAlternateView(target);
1824 					}
1825 				}
1826 				target.ScrollToAddress(addressInfo);
1827 			}
1828 
1829 			if(WindowState == FormWindowState.Minimized) {
1830 				//Unminimize window if it was minimized
1831 				WindowState = FormWindowState.Normal;
1832 			}
1833 			BringToFront();
1834 		}
1835 
GoToDestination(GoToDestination dest)1836 		public void GoToDestination(GoToDestination dest)
1837 		{
1838 			GoToDestination(LastCodeWindow, dest);
1839 		}
1840 
mnuGoToAll_Click(object sender, EventArgs e)1841 		private void mnuGoToAll_Click(object sender, EventArgs e)
1842 		{
1843 			using(frmGoToAll frm = new frmGoToAll(false, true)) {
1844 				if(frm.ShowDialog() == DialogResult.OK) {
1845 					GoToDestination(_lastCodeWindow, frm.Destination);
1846 
1847 					if(Program.IsMono) {
1848 						//Delay by 150ms before giving focus when running on Mono
1849 						//Otherwise this doesn't work (presumably because Mono sets the debugger form to disabled while the popup is opened)
1850 						Task.Run(() => {
1851 							System.Threading.Thread.Sleep(150);
1852 							this.BeginInvoke((Action)(() => {
1853 								_lastCodeWindow.CodeViewer.Focus();
1854 							}));
1855 						});
1856 					} else {
1857 						_lastCodeWindow.CodeViewer.Focus();
1858 					}
1859 				}
1860 			}
1861 		}
1862 
mnuConfigureExternalEditor_Click(object sender, EventArgs e)1863 		private void mnuConfigureExternalEditor_Click(object sender, EventArgs e)
1864 		{
1865 			using(frmExternalEditorConfig frm = new frmExternalEditorConfig()) {
1866 				frm.ShowDialog(mnuConfigureExternalEditor, this);
1867 			}
1868 		}
1869 
mnuOpenChrViewer_Click(object sender, EventArgs e)1870 		private void mnuOpenChrViewer_Click(object sender, EventArgs e)
1871 		{
1872 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.ChrViewer);
1873 		}
1874 
mnuOpenNametableViewer_Click(object sender, EventArgs e)1875 		private void mnuOpenNametableViewer_Click(object sender, EventArgs e)
1876 		{
1877 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.NametableViewer);
1878 		}
1879 
mnuOpenSpriteViewer_Click(object sender, EventArgs e)1880 		private void mnuOpenSpriteViewer_Click(object sender, EventArgs e)
1881 		{
1882 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.SpriteViewer);
1883 		}
1884 
mnuOpenPaletteViewer_Click(object sender, EventArgs e)1885 		private void mnuOpenPaletteViewer_Click(object sender, EventArgs e)
1886 		{
1887 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.PaletteViewer);
1888 		}
1889 
mnuWatchWindow_Click(object sender, EventArgs e)1890 		private void mnuWatchWindow_Click(object sender, EventArgs e)
1891 		{
1892 			DebugWindowManager.OpenDebugWindow(DebugWindow.WatchWindow);
1893 		}
1894 	}
1895 }
1896