1 using System;
2 using System.Collections.Generic;
3 using System.Drawing;
4 using System.Drawing.Imaging;
5 using System.IO;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Xml;
10 using System.Xml.Serialization;
11 using Mesen.GUI.Debugger;
12 using Mesen.GUI.Controls;
13 
14 namespace Mesen.GUI.Config
15 {
16 	public enum ByteCodePosition
17 	{
18 		Hidden,
19 		Left,
20 		Below
21 	}
22 
23 	public enum PrgAddressPosition
24 	{
25 		Hidden,
26 		Replace,
27 		Below,
28 		Inline
29 	}
30 
31 	public class DebugViewInfo
32 	{
33 		public bool ShowSourceAsComments = false;
34 		public ByteCodePosition ByteCodePosition = ByteCodePosition.Hidden;
35 		public PrgAddressPosition PrgAddressPosition = PrgAddressPosition.Hidden;
36 		public int TextZoom = 100;
37 		public bool UsingSourceView = false;
38 	}
39 
40 	public class DebugWorkspace
41 	{
42 		public List<Breakpoint> Breakpoints = new List<Breakpoint>();
43 		public List<string> WatchValues = new List<string>();
44 		public List<CodeLabel> Labels = new List<CodeLabel>();
45 		public List<string> TblMappings = null;
46 		private string _filePath;
47 
GetWorkspace()48 		public static DebugWorkspace GetWorkspace()
49 		{
50 			RomInfo info = InteropEmu.GetRomInfo();
51 			return Deserialize(Path.Combine(ConfigManager.DebuggerFolder, info.GetRomName() + ".Workspace.xml"));
52 		}
53 
Deserialize(string path)54 		private static DebugWorkspace Deserialize(string path)
55 		{
56 			DebugWorkspace config = new DebugWorkspace();
57 
58 			if(File.Exists(path)) {
59 				try {
60 					XmlSerializer xmlSerializer = new XmlSerializer(typeof(DebugWorkspace));
61 					using(TextReader textReader = new StreamReader(path)) {
62 						config = (DebugWorkspace)xmlSerializer.Deserialize(textReader);
63 					}
64 				} catch { }
65 			}
66 
67 			config._filePath = path;
68 
69 			return config;
70 		}
71 
Save()72 		public void Save()
73 		{
74 			try {
75 				XmlWriterSettings ws = new XmlWriterSettings();
76 				ws.NewLineHandling = NewLineHandling.Entitize;
77 				ws.Indent = true;
78 
79 				XmlSerializer xmlSerializer = new XmlSerializer(typeof(DebugWorkspace));
80 				using(XmlWriter xmlWriter = XmlWriter.Create(_filePath, ws)) {
81 					xmlSerializer.Serialize(xmlWriter, this);
82 				}
83 			} catch {
84 			}
85 		}
86 	}
87 
88 	public enum StatusFlagFormat
89 	{
90 		Hexadecimal = 0,
91 		Text = 1,
92 		CompactText = 2
93 	}
94 
95 	public class TraceLoggerOptions
96 	{
97 		public bool ShowByteCode;
98 		public bool ShowRegisters;
99 		public bool ShowCpuCycles;
100 		public bool ShowPpuCycles;
101 		public bool ShowPpuScanline;
102 		public bool ShowPpuFrames;
103 		public bool ShowExtraInfo;
104 		public bool IndentCode;
105 		public bool ShowEffectiveAddresses;
106 		public bool ShowMemoryValues;
107 		public bool UseLabels;
108 		public bool ExtendZeroPage;
109 		public bool UseWindowsEol = !Program.IsMono;
110 
111 		public StatusFlagFormat StatusFormat;
112 
113 		public bool OverrideFormat;
114 		public string Format;
115 	}
116 
117 	public class DebugInfo
118 	{
119 		private const int MaxRecentScripts = 10;
120 
121 		public DebugViewInfo LeftView;
122 		public DebugViewInfo RightView;
123 
124 		public InteropEmu.ConsoleId DebugConsoleId = InteropEmu.ConsoleId.Master;
125 
126 		public string FontFamily = BaseControl.MonospaceFontFamily;
127 		public FontStyle FontStyle = FontStyle.Regular;
128 		public float FontSize = BaseControl.DefaultFontSize;
129 
130 		public bool ShowOnlyDisassembledCode = true;
131 		public bool DisplayOpCodesInLowerCase = false;
132 		public bool ShowEffectiveAddresses = true;
133 
134 		public bool AutoCreateJumpLabels = false;
135 		public bool ShowJumpLabels = false;
136 
137 		public bool DisassembleVerifiedData = false;
138 		public bool DisassembleUnidentifiedData = false;
139 
140 		public bool ShowVerifiedData = false;
141 		public bool ShowUnidentifiedData = false;
142 
143 		public bool ShowCommentsInLabelList = false;
144 
145 		public bool ShowBreakNotifications = true;
146 		public bool ShowInstructionProgression = true;
147 		public bool ShowSelectionLength = false;
148 
149 		public bool AlwaysScrollToCenter = false;
150 		public bool SplitView = false;
151 		public bool VerticalLayout = false;
152 		public WatchFormatStyle WatchFormat = WatchFormatStyle.Hex;
153 		public bool ShowBreakpointLabels = true;
154 
155 		public Point EventViewerLocation;
156 		public bool EventViewerRefreshOnBreak = true;
157 		public bool EventViewerShowPpuRegisterWrites = true;
158 		public bool EventViewerShowPpuRegisterReads = true;
159 		public bool EventViewerShowMapperRegisterWrites = true;
160 		public bool EventViewerShowMapperRegisterReads = true;
161 		public bool EventViewerShowNmi = true;
162 		public bool EventViewerShowIrq = true;
163 		public bool EventViewerShowSpriteZeroHit = true;
164 		public bool EventViewerShowMarkedBreakpoints = true;
165 		public bool EventViewerShowPreviousFrameEvents = true;
166 
167 		public XmlColor EventViewerMapperRegisterWriteColor = ColorTranslator.FromHtml("#007597");
168 		public XmlColor EventViewerMapperRegisterReadColor = ColorTranslator.FromHtml("#C92929");
169 		public XmlColor EventViewerNmiColor = ColorTranslator.FromHtml("#ABADAC");
170 		public XmlColor EventViewerIrqColor = ColorTranslator.FromHtml("#F9FEAC");
171 		public XmlColor EventViewerSpriteZeroHitColor = ColorTranslator.FromHtml("#9F93C6");
172 		public XmlColor EventViewerBreakpointColor = ColorTranslator.FromHtml("#1898E4");
173 		public XmlColor[] EventViewerPpuRegisterWriteColors = new XmlColor[8] {
174 			ColorTranslator.FromHtml("#FF5E5E"), ColorTranslator.FromHtml("#8E33FF"), Color.Red, ColorTranslator.FromHtml("#FF84E0"),
175 			ColorTranslator.FromHtml("#FAFF39"), ColorTranslator.FromHtml("#2EFF28"), ColorTranslator.FromHtml("#3D2DFF"), ColorTranslator.FromHtml("#FF060D")
176 		};
177 		public XmlColor[] EventViewerPpuRegisterReadColors = new XmlColor[8] {
178 			Color.Red, Color.Red, ColorTranslator.FromHtml("#FF8224"), Color.Red, ColorTranslator.FromHtml("#24A672"), Color.Red, Color.Red, ColorTranslator.FromHtml("#6AF0FF")
179 		};
180 
181 		public bool CopyAddresses = false;
182 		public bool CopyByteCode = false;
183 		public bool CopyComments = false;
184 
185 		public Point? PpuWindowLocation = null;
186 
187 		public Point? PpuNametableViewerLocation = null;
188 		public Point? PpuChrViewerLocation = null;
189 		public Point? PpuSpriteViewerLocation = null;
190 		public Point? PpuPaletteViewerLocation = null;
191 
192 		public bool PpuAutoRefresh = true;
193 		public RefreshSpeed PpuAutoRefreshSpeed = RefreshSpeed.Normal;
194 		public bool PpuRefreshOnBreak = true;
195 		public bool PpuShowInformationOverlay = true;
196 		public bool PpuPartialDraw = false;
197 		public bool PpuShowPreviousFrame = false;
198 		public bool HidePauseIcon = false;
199 		public bool ShowPpuScrollOverlay = true;
200 		public bool ShowAttributeColorsOnly = false;
201 		public bool ShowTileGrid = false;
202 		public bool ShowAttributeGrid = false;
203 		public bool HighlightChrTile = false;
204 		public bool NtViewerUseGrayscalePalette = false;
205 		public bool NtViewerHighlightTileUpdates = false;
206 		public bool NtViewerHighlightAttributeUpdates = false;
207 		public bool NtViewerIgnoreRedundantWrites = false;
208 		public bool SpriteViewerDisplaySpriteOutlines = false;
209 
210 		public int ChrViewerSelectedPalette = 0;
211 		public CdlHighlightType ChrViewerHighlightType = CdlHighlightType.None;
212 		public bool ChrViewerUseAutoPalette = true;
213 		public bool ChrViewerUseLargeSprites = false;
214 		public bool ChrViewerShowSingleColorTilesInGrayscale = false;
215 
216 		public int PpuDisplayCycle = 0;
217 		public int PpuDisplayScanline = 241;
218 
219 		public bool ShowCodePreview = true;
220 		public bool ShowOpCodeTooltips = true;
221 		public bool OnlyShowTooltipsOnShift = false;
222 
223 		public bool ShowToolbar = true;
224 
225 		public bool ShowCpuMemoryMapping = true;
226 		public bool ShowPpuMemoryMapping = true;
227 
228 		public bool ShowRightPanel = true;
229 		public bool ShowBottomPanel = true;
230 		public int LeftPanelWidth = 930;
231 		public int TopPanelHeight = 450;
232 
233 		public XmlColor CodeVerifiedDataColor = Color.FromArgb(255, 252, 236);
234 		public XmlColor CodeUnidentifiedDataColor = Color.FromArgb(255, 242, 242);
235 		public XmlColor CodeUnexecutedCodeColor = Color.FromArgb(225, 244, 228);
236 
237 		public XmlColor CodeExecBreakpointColor = Color.FromArgb(140, 40, 40);
238 		public XmlColor CodeWriteBreakpointColor = Color.FromArgb(40, 120, 80);
239 		public XmlColor CodeReadBreakpointColor = Color.FromArgb(40, 40, 200);
240 		public XmlColor CodeActiveStatementColor = Color.Yellow;
241 		public XmlColor CodeEffectiveAddressColor = Color.SteelBlue;
242 
243 		public bool RamHighDensityTextMode = false;
244 		public bool RamEnablePerByteNavigation = false;
245 		public bool RamByteEditingMode = false;
246 		public bool RamAutoRefresh = true;
247 		public RefreshSpeed RamAutoRefreshSpeed = RefreshSpeed.Normal;
248 		public bool RamIgnoreRedundantWrites = false;
249 		public bool RamHighlightCurrentRowColumn = true;
250 		public int RamColumnCount = 2;
251 
252 		public string RamFontFamily = BaseControl.MonospaceFontFamily;
253 		public FontStyle RamFontStyle = FontStyle.Regular;
254 		public float RamFontSize = BaseControl.DefaultFontSize;
255 		public int RamTextZoom = 100;
256 
257 		public bool RamShowCharacters = true;
258 		public bool RamShowLabelInfo = true;
259 		public bool RamHighlightExecution = true;
260 		public bool RamHighlightWrites = true;
261 		public bool RamHighlightReads = true;
262 		public int RamFadeSpeed = 300;
263 		public bool RamHideUnusedBytes = false;
264 		public bool RamHideReadBytes = false;
265 		public bool RamHideWrittenBytes = false;
266 		public bool RamHideExecutedBytes = false;
267 		public bool RamHighlightBreakpoints = false;
268 		public bool RamHighlightLabelledBytes = false;
269 		public bool RamHighlightChrDrawnBytes = false;
270 		public bool RamHighlightChrReadBytes = false;
271 		public bool RamHighlightCodeBytes = false;
272 		public bool RamHighlightDataBytes = false;
273 		public bool RamHighlightDmcDataBytes = false;
274 		public XmlColor RamReadColor = Color.Blue;
275 		public XmlColor RamWriteColor = Color.Red;
276 		public XmlColor RamExecColor = Color.Green;
277 		public XmlColor RamLabelledByteColor = Color.LightPink;
278 		public XmlColor RamCodeByteColor = Color.DarkSeaGreen;
279 		public XmlColor RamDataByteColor = Color.LightSteelBlue;
280 		public XmlColor RamDmcDataByteColor = Color.Gold;
281 		public XmlColor RamChrDrawnByteColor = Color.DarkSeaGreen;
282 		public XmlColor RamChrReadByteColor = Color.LightSteelBlue;
283 		public DebugMemoryType RamMemoryType = DebugMemoryType.CpuMemory;
284 
285 		public Size MemoryViewerSize = new Size(0, 0);
286 		public Point MemoryViewerLocation;
287 		public Point? ApuViewerLocation;
288 
289 		public Size ProfilerSize = new Size(0, 0);
290 		public Point ProfilerLocation;
291 
292 		public Size WatchWindowSize = new Size(0, 0);
293 		public Point WatchWindowLocation;
294 
295 		public Point WindowLocation;
296 		public int WindowWidth = -1;
297 		public int WindowHeight = -1;
298 
299 		public int BreakInCount = 1;
300 		public BreakInMetric BreakInMetric = BreakInMetric.CpuCycles;
301 
302 		public int BreakOnValue = 241;
303 
304 		public bool FindOccurrencesMatchCase = false;
305 		public bool FindOccurrencesMatchWholeWord = false;
306 		public string FindOccurrencesLastSearch = string.Empty;
307 
308 		public bool AutoLoadDbgFiles = true;
309 		public bool AutoLoadCdlFiles = false;
310 		public bool DisableDefaultLabels = false;
311 
312 		public bool RefreshWhileRunning = false;
313 		public bool ShowMemoryValuesInCodeWindow = true;
314 
315 		public bool BreakOnOpen = true;
316 		public bool BreakOnReset = true;
317 		public bool BreakOnUnofficialOpcodes = true;
318 		public bool BreakOnBrk = false;
319 		public bool BreakOnDebuggerFocus = false;
320 		public bool BreakOnCrash = false;
321 		public bool BreakOnDecayedOamRead = false;
322 		public bool BreakOnUninitMemoryRead = false;
323 		public bool BreakOnInit = true;
324 		public bool BreakOnPlay = false;
325 		public bool BreakOnFirstCycle = true;
326 
327 		public bool BringToFrontOnPause = false;
328 		public bool BringToFrontOnBreak = true;
329 
330 		public TraceLoggerOptions TraceLoggerOptions;
331 		public bool TraceAutoRefresh = true;
332 		public int TraceLineCount = 1000;
333 		public Size TraceLoggerSize = new Size(0, 0);
334 		public Point TraceLoggerLocation;
335 
336 		public string TraceFontFamily = BaseControl.MonospaceFontFamily;
337 		public FontStyle TraceFontStyle = FontStyle.Regular;
338 		public float TraceFontSize = BaseControl.DefaultFontSize;
339 		public int TraceTextZoom = 100;
340 
341 		public Size ScriptWindowSize = new Size(0, 0);
342 		public Point ScriptWindowLocation;
343 		public int ScriptCodeWindowHeight = 0;
344 		public List<string> RecentScripts = new List<string>();
345 		public bool SaveScriptBeforeRun = true;
346 		public ScriptStartupBehavior ScriptStartupBehavior = ScriptStartupBehavior.ShowTutorial;
347 		public bool AutoLoadLastScript = true;
348 		public string ScriptFontFamily = BaseControl.MonospaceFontFamily;
349 		public FontStyle ScriptFontStyle = FontStyle.Regular;
350 		public float ScriptFontSize = BaseControl.DefaultFontSize;
351 		public int ScriptZoom = 100;
352 		public UInt32 ScriptTimeout = 1000;
353 
354 		public bool AssemblerCodeHighlighting = true;
355 		public XmlColor AssemblerOpcodeColor = Color.FromArgb(22, 37, 37);
356 		public XmlColor AssemblerLabelDefinitionColor = Color.Blue;
357 		public XmlColor AssemblerImmediateColor = Color.Chocolate;
358 		public XmlColor AssemblerAddressColor = Color.DarkRed;
359 		public XmlColor AssemblerCommentColor = Color.Green;
360 		public Size AssemblerSize = new Size(0, 0);
361 		public Point AssemblerLocation;
362 		public string AssemblerFontFamily = BaseControl.MonospaceFontFamily;
363 		public FontStyle AssemblerFontStyle = FontStyle.Regular;
364 		public float AssemblerFontSize = BaseControl.DefaultFontSize;
365 		public int AssemblerZoom = 100;
366 
367 		public Point? TextHookerWindowLocation = null;
368 		public bool TextHookerAutoRefresh = true;
369 		public bool TextHookerRefreshOnBreak = true;
370 		public int TextHookerDisplayCycle = 0;
371 		public int TextHookerDisplayScanline = 241;
372 		public List<CharMap> TextHookerCharMappings = new List<CharMap>();
373 		public bool TextHookerAdjustViewportScrolling = true;
374 		public bool TextHookerIgnoreMirroredNametables = true;
375 		public bool TextHookerAutoCopyToClipboard = false;
376 
377 		public string ExternalEditorPath;
378 		public string ExternalEditorArguments;
379 
380 		public DebuggerShortcutsConfig Shortcuts = new DebuggerShortcutsConfig();
381 		public DebugImportConfig ImportConfig = new DebugImportConfig();
382 
DebugInfo()383 		public DebugInfo()
384 		{
385 			LeftView = new DebugViewInfo();
386 			RightView = new DebugViewInfo();
387 			TraceLoggerOptions = new TraceLoggerOptions() {
388 				ShowByteCode = true,
389 				ShowCpuCycles = false,
390 				ShowEffectiveAddresses = true,
391 				ShowExtraInfo = true,
392 				ShowPpuFrames = false,
393 				ShowPpuCycles = true,
394 				ShowPpuScanline = true,
395 				ShowRegisters = true,
396 				UseLabels = false,
397 				StatusFormat = StatusFlagFormat.Hexadecimal
398 			};
399 
400 			if(ExternalEditorPath == null || ExternalEditorArguments == null) {
401 				ExternalEditorPath = "";
402 				ExternalEditorArguments = "";
403 
404 				//Setup a default editor when possible
405 				if(Program.IsMono) {
406 					string geditPath = "/usr/bin/gedit";
407 					string katePath = "/usr/bin/kate";
408 					if(File.Exists(geditPath)) {
409 						ExternalEditorPath = geditPath;
410 						ExternalEditorArguments = "+%L %F";
411 					} else if(File.Exists(katePath)) {
412 						ExternalEditorPath = katePath;
413 						ExternalEditorArguments = "%F -l %L";
414 					}
415 				} else {
416 					string notepadPath32 = "C:\\Program Files (x86)\\Notepad++\\notepad++.exe";
417 					string notepadPath64 = "C:\\Program Files\\Notepad++\\notepad++.exe";
418 					if(File.Exists(notepadPath32)) {
419 						ExternalEditorPath = notepadPath32;
420 						ExternalEditorArguments = "%F -n%L";
421 					} else if(File.Exists(notepadPath64)) {
422 						ExternalEditorPath = notepadPath64;
423 						ExternalEditorArguments = "%F -n%L";
424 					}
425 				}
426 			}
427 		}
428 
ApplyConfig()429 		static public void ApplyConfig()
430 		{
431 			InteropEmu.SetFlag(EmulationFlags.BreakOnCrash, ConfigManager.Config.DebugInfo.BreakOnCrash);
432 			InteropEmu.DebugSetScriptTimeout(ConfigManager.Config.DebugInfo.ScriptTimeout);
433 		}
434 
AddRecentScript(string scriptFile)435 		public void AddRecentScript(string scriptFile)
436 		{
437 			string existingItem = RecentScripts.Where((file) => file == scriptFile).FirstOrDefault();
438 			if(existingItem != null) {
439 				RecentScripts.Remove(existingItem);
440 			}
441 
442 			RecentScripts.Insert(0, scriptFile);
443 			if(RecentScripts.Count > DebugInfo.MaxRecentScripts) {
444 				RecentScripts.RemoveAt(DebugInfo.MaxRecentScripts);
445 			}
446 			ConfigManager.ApplyChanges();
447 		}
448 	}
449 
450 	public class DebugImportConfig
451 	{
452 		public bool ResetLabelsOnImport = true;
453 
454 		public bool DbgImportRamLabels = true;
455 		public bool DbgImportWorkRamLabels = true;
456 		public bool DbgImportSaveRamLabels = true;
457 		public bool DbgImportPrgRomLabels = true;
458 		public bool DbgImportComments = true;
459 
460 		public bool MlbImportInternalRamLabels = true;
461 		public bool MlbImportWorkRamLabels = true;
462 		public bool MlbImportSaveRamLabels = true;
463 		public bool MlbImportRegisterLabels = true;
464 		public bool MlbImportPrgRomLabels = true;
465 		public bool MlbImportComments = true;
466 	}
467 
468 	public enum ScriptStartupBehavior
469 	{
470 		ShowTutorial = 0,
471 		ShowBlankWindow = 1,
472 		LoadLastScript = 2
473 	}
474 
475 	public enum RefreshSpeed
476 	{
477 		Low = 0,
478 		Normal = 1,
479 		High = 2
480 	}
481 
482 	public enum BreakInMetric
483 	{
484 		CpuCycles,
485 		CpuInstructions,
486 		PpuCycles,
487 		Scanlines,
488 		Frames
489 	}
490 
491 	public class XmlColor
492 	{
493 		private Color _color = Color.Black;
494 
XmlColor()495 		public XmlColor() { }
XmlColor(Color c)496 		public XmlColor(Color c) { _color = c; }
497 
498 		[XmlIgnore]
499 		public Color Color
500 		{
501 			get { return _color; }
502 			set { _color = value; }
503 		}
504 
operator Color(XmlColor x)505 		public static implicit operator Color(XmlColor x)
506 		{
507 			return x.Color;
508 		}
509 
operator XmlColor(Color c)510 		public static implicit operator XmlColor(Color c)
511 		{
512 			return new XmlColor(c);
513 		}
514 
515 		[XmlAttribute]
516 		public string ColorString
517 		{
518 			get { return ColorTranslator.ToHtml(_color); }
519 			set
520 			{
521 				try {
522 					_color = ColorTranslator.FromHtml(value);
523 				} catch(Exception) {
524 					_color = Color.Black;
525 				}
526 			}
527 		}
528 	}
529 
530 	public class CharMap
531 	{
532 		[XmlAttribute]
533 		public string Key;
534 		[XmlAttribute]
535 		public string Value;
536 	}
537 }
538