diff --git a/Core/Disassembler.cpp b/Core/Disassembler.cpp index a6b81bcc..771752cb 100644 --- a/Core/Disassembler.cpp +++ b/Core/Disassembler.cpp @@ -497,6 +497,7 @@ string Disassembler::GetCode(AddressTypeInfo &addressInfo, uint32_t endAddr, uin string label; string commentString; string commentLines; + shared_ptr tmpInfo(new DisassemblyInfo()); shared_ptr info; DataType dataType = DataType::UnidentifiedData; string spaces = " "; @@ -542,7 +543,8 @@ string Disassembler::GetCode(AddressTypeInfo &addressInfo, uint32_t endAddr, uin isVerifiedData = addressInfo.Type == AddressType::PrgRom && cdl->IsData(addr&mask); if(!info && ((disassembleUnidentifiedData && !isVerifiedData) || (disassembleVerifiedData && isVerifiedData))) { dataType = isVerifiedData ? DataType::VerifiedData : (addressInfo.Type == AddressType::PrgRom ? DataType::UnidentifiedData : DataType::VerifiedCode); - info.reset(new DisassemblyInfo(source + (addr & mask), false)); + tmpInfo->Initialize(source + (addr & mask), false); + info = tmpInfo; } else if(info) { dataType = DataType::VerifiedCode; } diff --git a/Core/DisassemblyInfo.cpp b/Core/DisassemblyInfo.cpp index 43083596..47a1e726 100644 --- a/Core/DisassemblyInfo.cpp +++ b/Core/DisassemblyInfo.cpp @@ -33,6 +33,11 @@ DisassemblyInfo::DisassemblyInfo() { } +DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint) +{ + Initialize(opPointer, isSubEntryPoint); +} + void DisassemblyInfo::ToString(string &out, uint32_t memoryAddr, MemoryManager* memoryManager, LabelManager* labelManager, bool extendZeroPage) { char buffer[500]; @@ -143,7 +148,7 @@ uint16_t DisassemblyInfo::GetOpAddr(uint16_t memoryAddr) return opAddr; } -DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint) +void DisassemblyInfo::Initialize(uint8_t* opPointer, bool isSubEntryPoint) { _isSubEntryPoint = isSubEntryPoint; diff --git a/Core/DisassemblyInfo.h b/Core/DisassemblyInfo.h index fc0bea7c..ee37f745 100644 --- a/Core/DisassemblyInfo.h +++ b/Core/DisassemblyInfo.h @@ -26,6 +26,8 @@ public: DisassemblyInfo(); DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint); + void Initialize(uint8_t * opPointer, bool isSubEntryPoint); + void SetSubEntryPoint(); int32_t GetEffectiveAddress(State& cpuState, MemoryManager* memoryManager); diff --git a/GUI.NET/Debugger/Breakpoint.cs b/GUI.NET/Debugger/Breakpoint.cs index 5fca9409..d017b19d 100644 --- a/GUI.NET/Debugger/Breakpoint.cs +++ b/GUI.NET/Debugger/Breakpoint.cs @@ -174,7 +174,7 @@ namespace Mesen.GUI.Debugger } } - public bool Matches(int relativeAddress, ref AddressTypeInfo info) + public bool Matches(int relativeAddress, AddressTypeInfo info) { if(this.IsCpuBreakpoint && this.AddressType == BreakpointAddressType.SingleAddress) { if(this.MemoryType == DebugMemoryType.CpuMemory) { diff --git a/GUI.NET/Debugger/BreakpointManager.cs b/GUI.NET/Debugger/BreakpointManager.cs index c2e8957e..6e96ee42 100644 --- a/GUI.NET/Debugger/BreakpointManager.cs +++ b/GUI.NET/Debugger/BreakpointManager.cs @@ -70,7 +70,7 @@ namespace Mesen.GUI.Debugger public static Breakpoint GetMatchingBreakpoint(int relativeAddress, AddressTypeInfo info) { - return Breakpoints.Where((bp) => bp.Matches(relativeAddress, ref info)).FirstOrDefault(); + return Breakpoints.Where((bp) => bp.Matches(relativeAddress, info)).FirstOrDefault(); } public static Breakpoint GetMatchingBreakpoint(UInt32 startAddress, UInt32 endAddress, DebugMemoryType memoryType) diff --git a/GUI.NET/Debugger/CodeInfo.cs b/GUI.NET/Debugger/CodeInfo.cs new file mode 100644 index 00000000..807489f2 --- /dev/null +++ b/GUI.NET/Debugger/CodeInfo.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mesen.GUI.Debugger +{ + public class CodeInfo + { + public int[] LineNumbers { get; private set; } + public string[] LineNumberNotes { get; private set; } + public char[] LineMemoryType { get; private set; } + public int[] AbsoluteLineNumbers { get; private set; } + public string[] CodeNotes { get; private set; } + public string[] CodeLines { get; private set; } + public HashSet UnexecutedAddresses { get; private set; } + public HashSet VerifiedDataAddresses { get; private set; } + public HashSet SpeculativeCodeAddreses { get; private set; } + public Dictionary CodeContent { get; private set; } + public Dictionary CodeByteCode { get; private set; } + public string[] Addressing { get; private set; } + public string[] Comments { get; private set; } + public int[] LineIndentations { get; private set; } + + public CodeInfo(string code) + { + string[] token = code.Split('\x1'); + + int lineCount = token.Length / 8; + LineNumbers = new int[lineCount]; + LineNumberNotes = new string[lineCount]; + LineMemoryType = new char[lineCount]; + AbsoluteLineNumbers = new int[lineCount]; + CodeNotes = new string[lineCount]; + CodeLines = new string[lineCount]; + Addressing = new string[lineCount]; + Comments = new string[lineCount]; + LineIndentations = new int[lineCount]; + + UnexecutedAddresses = new HashSet(); + VerifiedDataAddresses = new HashSet(); + SpeculativeCodeAddreses = new HashSet(); + + int tokenIndex = 0; + int lineNumber = 0; + + while(tokenIndex < token.Length - 8) { + int relativeAddress = ParseHexAddress(token[tokenIndex + 1]); + + //Flags: + //1: Executed code + //2: Speculative Code + //4: Indented line + switch(token[tokenIndex][0]) { + case '2': + SpeculativeCodeAddreses.Add(lineNumber); + LineIndentations[lineNumber] = 0; + break; + + case '4': + UnexecutedAddresses.Add(lineNumber); + LineIndentations[lineNumber] = 20; + break; + + case '6': + SpeculativeCodeAddreses.Add(lineNumber); + LineIndentations[lineNumber] = 20; + break; + + case '5': + LineIndentations[lineNumber] = 20; + break; + + case '8': + VerifiedDataAddresses.Add(lineNumber); + LineIndentations[lineNumber] = 0; + break; + + case '9': + VerifiedDataAddresses.Add(lineNumber); + LineIndentations[lineNumber] = 20; + break; + + default: + LineIndentations[lineNumber] = 0; + break; + } + + LineNumbers[lineNumber] = relativeAddress; + LineMemoryType[lineNumber] = token[tokenIndex + 2][0]; + LineNumberNotes[lineNumber] = token[tokenIndex + 3]; + AbsoluteLineNumbers[lineNumber] = this.ParseHexAddress(token[tokenIndex + 3]); + CodeNotes[lineNumber] = token[tokenIndex + 4]; + CodeLines[lineNumber] = token[tokenIndex + 5]; + + Addressing[lineNumber] = token[tokenIndex + 6]; + Comments[lineNumber] = token[tokenIndex + 7]; + + + lineNumber++; + tokenIndex += 8; + } + } + + public void InitAssemblerValues() + { + if(CodeContent == null) { + CodeContent = new Dictionary(LineNumbers.Length); + CodeByteCode = new Dictionary(LineNumbers.Length); + + for(int i = 0; i < LineNumbers.Length; i++) { + //Used by assembler + int relativeAddress = LineNumbers[i]; + CodeByteCode[relativeAddress] = CodeNotes[i]; + CodeContent[relativeAddress] = CodeLines[i]; + } + } + } + + private int ParseHexAddress(string hexAddress) + { + if(string.IsNullOrWhiteSpace(hexAddress)) { + return -1; + } else { + return HexConverter.FromHex(hexAddress); + } + } + } +} diff --git a/GUI.NET/Debugger/CodeTooltipManager.cs b/GUI.NET/Debugger/CodeTooltipManager.cs index d9578544..c8af8698 100644 --- a/GUI.NET/Debugger/CodeTooltipManager.cs +++ b/GUI.NET/Debugger/CodeTooltipManager.cs @@ -20,7 +20,7 @@ namespace Mesen.GUI.Debugger private Control _owner = null; private ctrlScrollableTextbox _codeViewer = null; - public string Code { get; set; } + public CodeInfo Code { get; set; } public Ld65DbgImporter SymbolProvider { get; set; } public CodeTooltipManager(Control owner, ctrlScrollableTextbox codeViewer) @@ -29,7 +29,7 @@ namespace Mesen.GUI.Debugger _codeViewer = codeViewer; } - public void ShowTooltip(string word, Dictionary values, int lineAddress, AddressTypeInfo? previewAddress) + public void ShowTooltip(string word, Dictionary values, int lineAddress, AddressTypeInfo previewAddress) { if(ConfigManager.Config.DebugInfo.OnlyShowTooltipsOnShift && Control.ModifierKeys != Keys.Shift) { return; @@ -46,7 +46,7 @@ namespace Mesen.GUI.Debugger if(ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word)) { _codeTooltip = new frmOpCodeTooltip(parentForm, word, lineAddress); } else { - _codeTooltip = new frmCodeTooltip(parentForm, values, previewAddress.HasValue && previewAddress.Value.Type == AddressType.PrgRom ? previewAddress : null, Code, SymbolProvider); + _codeTooltip = new frmCodeTooltip(parentForm, values, previewAddress != null && previewAddress.Type == AddressType.PrgRom ? previewAddress : null, Code, SymbolProvider); } _codeTooltip.FormClosed += (s, e) => { _codeTooltip = null; }; } @@ -79,7 +79,7 @@ namespace Mesen.GUI.Debugger }; AddressTypeInfo addressInfo = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType(address, ref addressInfo); + InteropEmu.DebugGetAbsoluteAddressAndType(address, addressInfo); this.ShowTooltip(word, values, -1, addressInfo); } @@ -108,7 +108,7 @@ namespace Mesen.GUI.Debugger byte byteValue = relativeAddress >= 0 ? InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress) : (byte)0; UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0; - AddressTypeInfo? addressInfo = SymbolProvider.GetSymbolAddressInfo(symbol); + AddressTypeInfo addressInfo = SymbolProvider.GetSymbolAddressInfo(symbol); if(addressInfo != null) { var values = new Dictionary() { @@ -119,8 +119,8 @@ namespace Mesen.GUI.Debugger values["CPU Address"] = "$" + relativeAddress.ToString("X4"); }; - if(addressInfo.Value.Type == AddressType.PrgRom) { - values["PRG Offset"] = "$" + addressInfo.Value.Address.ToString("X4"); + if(addressInfo.Type == AddressType.PrgRom) { + values["PRG Offset"] = "$" + addressInfo.Address.ToString("X4"); } values["Value"] = (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a"); @@ -148,7 +148,7 @@ namespace Mesen.GUI.Debugger UInt32 address = UInt32.Parse(word.Substring(1), NumberStyles.AllowHexSpecifier); AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType(address, info); if(info.Address >= 0) { CodeLabel label = LabelManager.GetLabel((UInt32)info.Address, info.Type); diff --git a/GUI.NET/Debugger/Controls/CodeViewerActions.cs b/GUI.NET/Debugger/Controls/CodeViewerActions.cs index e78c486b..e85e9d37 100644 --- a/GUI.NET/Debugger/Controls/CodeViewerActions.cs +++ b/GUI.NET/Debugger/Controls/CodeViewerActions.cs @@ -239,7 +239,7 @@ namespace Mesen.GUI.Debugger.Controls { if(UpdateContextMenu(_lastLocation)) { AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)_lastClickedAddress, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)_lastClickedAddress, info); if(info.Address >= 0) { ctrlLabelList.EditLabel((UInt32)info.Address, info.Type); } diff --git a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs index 1934141c..fabbd6e5 100644 --- a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs +++ b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs @@ -18,22 +18,6 @@ namespace Mesen.GUI.Debugger public delegate void AssemblerEventHandler(AssemblerEventArgs args); public event AssemblerEventHandler OnEditCode; - private List _lineNumbers = new List(10000); - private List _lineNumberNotes = new List(10000); - private List _lineMemoryType = new List(10000); - private List _absoluteLineNumbers = new List(10000); - private List _codeNotes = new List(10000); - private List _codeLines = new List(10000); - private HashSet _unexecutedAddresses = new HashSet(); - private HashSet _verifiedDataAddresses = new HashSet(); - private HashSet _speculativeCodeAddreses = new HashSet(); - private Dictionary _codeContent = new Dictionary(10000); - private Dictionary _codeComments = new Dictionary(10000); - private Dictionary _codeByteCode = new Dictionary(10000); - private List _addressing = new List(10000); - private List _comments = new List(10000); - private List _lineIndentations = new List(10000); - private UInt32? _currentActiveAddress { get; set; } = null; private DebugViewInfo _config; @@ -81,19 +65,19 @@ namespace Mesen.GUI.Debugger set { _symbolProvider = value; } } - private string _code; + private CodeInfo _code = new CodeInfo(""); private bool _codeChanged; - public string Code + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public CodeInfo Code { get { return _code; } set { - if(value != null) { - _codeChanged = true; - _code = value; - _tooltipManager.Code = value; - UpdateCode(); - } + _codeChanged = true; + _code = value; + _tooltipManager.Code = value; + UpdateCode(); } } @@ -141,6 +125,8 @@ namespace Mesen.GUI.Debugger public List GetCode(out int byteLength, ref int startAddress, int endAddress = -1) { + _code.InitAssemblerValues(); + List result = new List(); byteLength = 0; @@ -154,7 +140,7 @@ namespace Mesen.GUI.Debugger for(int i = startAddress; (i <= endAddress || endAddress == -1) && endAddress < 65536; ) { string code; - if(_codeContent.TryGetValue(i, out code)) { + if(_code.CodeContent.TryGetValue(i, out code)) { code = code.Split('\x2')[0].Trim(); if(code.StartsWith("--") || code.StartsWith("__")) { @@ -163,7 +149,7 @@ namespace Mesen.GUI.Debugger } AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)i, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)i, info); CodeLabel codeLabel = info.Address >= 0 ? LabelManager.GetLabel((UInt32)info.Address, AddressType.PrgRom) : null; string comment = codeLabel?.Comment; string label = codeLabel?.Label; @@ -176,7 +162,7 @@ namespace Mesen.GUI.Debugger } else { comment = code; } - code = ".byte " + string.Join(",", _codeByteCode[i].Split(' ')); + code = ".byte " + string.Join(",", _code.CodeByteCode[i].Split(' ')); addPadding = false; } @@ -189,7 +175,7 @@ namespace Mesen.GUI.Debugger } result.Add((addPadding ? " " : "") + code + (!string.IsNullOrWhiteSpace(comment) ? (" ;" + comment) : "")); - int length = _codeByteCode[i].Count(c => c == ' ') + 1; + int length = _code.CodeByteCode[i].Count(c => c == ' ') + 1; byteLength += length; i += length; @@ -218,101 +204,15 @@ namespace Mesen.GUI.Debugger scrollOffset++; } while(centerLineAddress < 0 && centerLineIndex > 0); - _lineNumbers.Clear(); - _codeContent.Clear(); - _codeComments.Clear(); - _codeByteCode.Clear(); - _unexecutedAddresses.Clear(); - _speculativeCodeAddreses.Clear(); - _verifiedDataAddresses.Clear(); - _lineMemoryType.Clear(); - _absoluteLineNumbers.Clear(); - string[] token = new string[8]; - int tokenIndex = 0; - int startPos = 0; - int endPos = 0; - int lineNumber = 0; + ctrlCodeViewer.LineIndentations = _code.LineIndentations; + ctrlCodeViewer.Addressing = _code.Addressing; + ctrlCodeViewer.Comments = _code.Comments; - Action readToken = () => { - endPos = _code.IndexOf('\x1', endPos) + 1; - token[tokenIndex++] = _code.Substring(startPos, endPos - startPos - 1); - startPos = endPos; - }; - - Action readLine = () => { - tokenIndex = 0; - readToken(); readToken(); readToken(); readToken(); readToken(); readToken(); readToken(); readToken(); - }; - - Func processLine = () => { - readLine(); - - int relativeAddress = ParseHexAddress(token[1]); - - //Flags: - //1: Executed code - //2: Speculative Code - //4: Indented line - if(token[0] == "2") { - _speculativeCodeAddreses.Add(lineNumber); - _lineIndentations.Add(0); - } else if(token[0] == "4") { - _unexecutedAddresses.Add(lineNumber); - _lineIndentations.Add(20); - } else if(token[0] == "6") { - _speculativeCodeAddreses.Add(lineNumber); - _lineIndentations.Add(20); - } else if(token[0] == "5") { - _lineIndentations.Add(20); - } else if(token[0] == "8") { - _verifiedDataAddresses.Add(lineNumber); - _lineIndentations.Add(0); - } else if(token[0] == "9") { - _verifiedDataAddresses.Add(lineNumber); - _lineIndentations.Add(20); - } else { - _lineIndentations.Add(0); - } - - _lineNumbers.Add(relativeAddress); - _lineMemoryType.Add(token[2][0]); - _lineNumberNotes.Add(string.IsNullOrWhiteSpace(token[3]) ? "" : (token[3].Length > 5 ? token[3].TrimStart('0').PadLeft(4, '0') : token[3])); - _absoluteLineNumbers.Add(this.ParseHexAddress(token[3])); - _codeNotes.Add(token[4]); - _codeLines.Add(token[5]); - - _addressing.Add(token[6]); - _comments.Add(token[7]); - - //Used by assembler - _codeByteCode[relativeAddress] = token[4]; - _codeContent[relativeAddress] = token[5]; - _codeComments[relativeAddress] = token[7]; - - lineNumber++; - - return endPos < _code.Length; - }; - - while(processLine()); - - ctrlCodeViewer.LineIndentations = _lineIndentations.ToArray(); - ctrlCodeViewer.Addressing = _addressing.ToArray(); - ctrlCodeViewer.Comments = _comments.ToArray(); - - ctrlCodeViewer.LineNumbers = _lineNumbers.ToArray(); - ctrlCodeViewer.TextLineNotes = _codeNotes.ToArray(); - ctrlCodeViewer.LineNumberNotes = _lineNumberNotes.ToArray(); - ctrlCodeViewer.TextLines = _codeLines.ToArray(); - - //These are all temporary and can be cleared right away - _lineNumberNotes.Clear(); - _codeNotes.Clear(); - _codeLines.Clear(); - _addressing.Clear(); - _comments.Clear(); - _lineIndentations.Clear(); + ctrlCodeViewer.LineNumbers = _code.LineNumbers; + ctrlCodeViewer.TextLineNotes = _code.CodeNotes; + ctrlCodeViewer.LineNumberNotes = _code.LineNumberNotes; + ctrlCodeViewer.TextLines = _code.CodeLines; _codeChanged = false; UpdateLineColors(); @@ -328,16 +228,7 @@ namespace Mesen.GUI.Debugger UpdateLineColors(); return false; } - - private int ParseHexAddress(string hexAddress) - { - if(string.IsNullOrWhiteSpace(hexAddress)) { - return -1; - } else { - return (int)UInt32.Parse(hexAddress, System.Globalization.NumberStyles.AllowHexSpecifier); - } - } - + private void ctrlCodeViewer_MouseLeave(object sender, EventArgs e) { _tooltipManager.Close(); @@ -389,9 +280,9 @@ namespace Mesen.GUI.Debugger public AddressTypeInfo GetAddressInfo(int lineNumber) { AddressTypeInfo info = new AddressTypeInfo(); - if(lineNumber < this._absoluteLineNumbers.Count) { - info.Address = this._absoluteLineNumbers[lineNumber]; - switch(this._lineMemoryType[lineNumber]) { + if(lineNumber < this._code.AbsoluteLineNumbers.Length) { + info.Address = this._code.AbsoluteLineNumbers[lineNumber]; + switch(this._code.LineMemoryType[lineNumber]) { case 'P': info.Type = AddressType.PrgRom; break; case 'W': info.Type = AddressType.WorkRam; break; case 'S': info.Type = AddressType.SaveRam; break; @@ -514,15 +405,15 @@ namespace Mesen.GUI.Debugger props.FgColor = Color.Black; props.TextBgColor = info.CodeActiveStatementColor; props.Symbol |= LineSymbol.Arrow; - } else if(_code._unexecutedAddresses.Contains(lineNumber)) { + } else if(_code._code.UnexecutedAddresses.Contains(lineNumber)) { props.LineBgColor = info.CodeUnexecutedCodeColor; - } else if(_code._speculativeCodeAddreses.Contains(lineNumber)) { + } else if(_code._code.SpeculativeCodeAddreses.Contains(lineNumber)) { props.LineBgColor = info.CodeUnidentifiedDataColor; - } else if(_code._verifiedDataAddresses.Contains(lineNumber)) { + } else if(_code._code.VerifiedDataAddresses.Contains(lineNumber)) { props.LineBgColor = info.CodeVerifiedDataColor; } - switch(_code._lineMemoryType[lineNumber]) { + switch(_code._code.LineMemoryType[lineNumber]) { case 'P': props.AddressColor = Color.Gray; break; case 'W': props.AddressColor = Color.DarkBlue; break; case 'S': props.AddressColor = Color.DarkRed; break; @@ -536,7 +427,7 @@ namespace Mesen.GUI.Debugger { DebugInfo info = ConfigManager.Config.DebugInfo; foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) { - if(breakpoint.Matches(cpuAddress, ref addressInfo)) { + if(breakpoint.Matches(cpuAddress, addressInfo)) { Color fgColor = Color.White; Color? bgColor = null; Color bpColor = breakpoint.BreakOnExec ? info.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? info.CodeWriteBreakpointColor : info.CodeReadBreakpointColor); @@ -578,7 +469,7 @@ namespace Mesen.GUI.Debugger { _code = code; DebugInfo info = ConfigManager.Config.DebugInfo; - int len = _code._absoluteLineNumbers.Count; + int len = _code._code.AbsoluteLineNumbers.Length; AddressTypeInfo[] addressInfo = new AddressTypeInfo[len]; for(int i = 0; i < len; i++) { @@ -587,7 +478,7 @@ namespace Mesen.GUI.Debugger foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) { for(int i = 0; i < len; i++) { - if(breakpoint.Matches(_code._lineNumbers[i], ref addressInfo[i])) { + if(breakpoint.Matches(_code._code.LineNumbers[i], addressInfo[i])) { Color bpColor = breakpoint.BreakOnExec ? info.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? info.CodeWriteBreakpointColor : info.CodeReadBreakpointColor); _breakpointColors[i] = bpColor; } @@ -598,17 +489,17 @@ namespace Mesen.GUI.Debugger public Color GetBackgroundColor(float position) { DebugInfo info = ConfigManager.Config.DebugInfo; - int lineIndex = (int)((_code._lineMemoryType.Count - 1) * position); + int lineIndex = (int)((_code._code.LineMemoryType.Length - 1) * position); - if(lineIndex < _code._lineMemoryType.Count) { - switch(_code._lineMemoryType[lineIndex]) { + if(lineIndex < _code._code.LineMemoryType.Length) { + switch(_code._code.LineMemoryType[lineIndex]) { case 'N': return _nesRamColor; case 'P': - if(_code._unexecutedAddresses.Contains(lineIndex)) { + if(_code._code.UnexecutedAddresses.Contains(lineIndex)) { return info.CodeUnexecutedCodeColor; - } else if(_code._verifiedDataAddresses.Contains(lineIndex)) { + } else if(_code._code.VerifiedDataAddresses.Contains(lineIndex)) { return info.CodeVerifiedDataColor; - } else if(_code._speculativeCodeAddreses.Contains(lineIndex)) { + } else if(_code._code.SpeculativeCodeAddreses.Contains(lineIndex)) { return info.CodeUnidentifiedDataColor; } return Color.White; @@ -622,8 +513,8 @@ namespace Mesen.GUI.Debugger public frmCodePreviewTooltip GetPreview(int lineIndex) { - if(lineIndex < _code._lineNumbers.Count) { - while(lineIndex > 0 && _code._lineNumbers[lineIndex] < 0) { + if(lineIndex < _code._code.LineNumbers.Length) { + while(lineIndex > 0 && _code._code.LineNumbers[lineIndex] < 0) { lineIndex--; } return new frmCodePreviewTooltip(_code.FindForm(), lineIndex, _code._code); @@ -648,7 +539,7 @@ namespace Mesen.GUI.Debugger public Color GetMarkerColor(float position, int linesPerPixel) { - int lineIndex = (int)((_code._lineMemoryType.Count - 1) * position); + int lineIndex = (int)((_code._code.LineMemoryType.Length - 1) * position); Color bpColor; for(int i = 0; i < linesPerPixel; i++) { diff --git a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs index e66c2ce5..5ba4b7bf 100644 --- a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs +++ b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs @@ -504,7 +504,7 @@ namespace Mesen.GUI.Debugger.Controls UInt32 address = (UInt32)ctrlHexBox.SelectionStart; if(this._memoryType == DebugMemoryType.CpuMemory) { AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType(address, info); ctrlLabelList.EditLabel((UInt32)info.Address, info.Type); } else { ctrlLabelList.EditLabel(address, GetAddressType().Value); @@ -594,7 +594,7 @@ namespace Mesen.GUI.Debugger.Controls bool disableEditLabel = false; if(this._memoryType == DebugMemoryType.CpuMemory) { AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType(startAddress, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType(startAddress, info); disableEditLabel = info.Address == -1; } diff --git a/GUI.NET/Debugger/Controls/ctrlLabelList.cs b/GUI.NET/Debugger/Controls/ctrlLabelList.cs index b6513aa3..034327e5 100644 --- a/GUI.NET/Debugger/Controls/ctrlLabelList.cs +++ b/GUI.NET/Debugger/Controls/ctrlLabelList.cs @@ -254,7 +254,7 @@ namespace Mesen.GUI.Debugger.Controls CodeLabel label = (CodeLabel)GetSelectedItem().SubItems[1].Tag; if(label.AddressType == AddressType.InternalRam || label.AddressType == AddressType.Register) { AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType(label.Address, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType(label.Address, info); if(BreakpointManager.GetMatchingBreakpoint((Int32)label.Address, info) == null) { BreakpointManager.AddBreakpoint(new Breakpoint() { MemoryType = DebugMemoryType.CpuMemory, diff --git a/GUI.NET/Debugger/Controls/ctrlSourceViewer.cs b/GUI.NET/Debugger/Controls/ctrlSourceViewer.cs index d9dc65e6..9c15613b 100644 --- a/GUI.NET/Debugger/Controls/ctrlSourceViewer.cs +++ b/GUI.NET/Debugger/Controls/ctrlSourceViewer.cs @@ -334,7 +334,7 @@ namespace Mesen.GUI.Debugger.Controls } AddressTypeInfo addressInfo = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((uint)cpuAddress, ref addressInfo); + InteropEmu.DebugGetAbsoluteAddressAndType((uint)cpuAddress, addressInfo); if(addressInfo.Address >= 0 && addressInfo.Type == AddressType.PrgRom) { LineInfo line = _symbolProvider.GetSourceCodeLineInfo(addressInfo.Address); return CurrentFile.ID == line?.FileID; @@ -345,7 +345,7 @@ namespace Mesen.GUI.Debugger.Controls public void ScrollToLineNumber(int lineNumber, bool scrollToTop = false) { AddressTypeInfo addressInfo = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((uint)lineNumber, ref addressInfo); + InteropEmu.DebugGetAbsoluteAddressAndType((uint)lineNumber, addressInfo); ScrollToAddress(addressInfo, scrollToTop); } @@ -445,7 +445,7 @@ namespace Mesen.GUI.Debugger.Controls foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) { for(int i = 0; i < len; i++) { - if(breakpoint.Matches(relativeAddresses[i], ref addressInfo[i])) { + if(breakpoint.Matches(relativeAddresses[i], addressInfo[i])) { Color bpColor = breakpoint.BreakOnExec ? info.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? info.CodeWriteBreakpointColor : info.CodeReadBreakpointColor); _breakpointColors[i] = bpColor; } diff --git a/GUI.NET/Debugger/DbgImporter.cs b/GUI.NET/Debugger/DbgImporter.cs index 7990c1df..b62e83b7 100644 --- a/GUI.NET/Debugger/DbgImporter.cs +++ b/GUI.NET/Debugger/DbgImporter.cs @@ -137,7 +137,7 @@ namespace Mesen.GUI.Debugger return null; } - public AddressTypeInfo? GetSymbolAddressInfo(SymbolInfo symbol) + public AddressTypeInfo GetSymbolAddressInfo(SymbolInfo symbol) { if(symbol.SegmentID == null || symbol.Address == null) { return null; @@ -310,7 +310,7 @@ namespace Mesen.GUI.Debugger count++; } - int address = GetSymbolAddressInfo(symbol).Value.Address; + int address = GetSymbolAddressInfo(symbol).Address; if(segment.IsRam) { _ramLabels[address] = new CodeLabel() { Label = newName, Address = (UInt32)address, AddressType = AddressType.InternalRam, Comment = string.Empty }; } else { diff --git a/GUI.NET/Debugger/HexConverter.cs b/GUI.NET/Debugger/HexConverter.cs new file mode 100644 index 00000000..e187f300 --- /dev/null +++ b/GUI.NET/Debugger/HexConverter.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mesen.GUI.Debugger +{ + class HexConverter + { + private static byte[] _hexLookup = new byte[256]; + + static HexConverter() + { + _hexLookup['0'] = 0; + _hexLookup['1'] = 1; + _hexLookup['2'] = 2; + _hexLookup['3'] = 3; + _hexLookup['4'] = 4; + _hexLookup['5'] = 5; + _hexLookup['6'] = 6; + _hexLookup['7'] = 7; + _hexLookup['8'] = 8; + _hexLookup['9'] = 9; + _hexLookup['a'] = 10; + _hexLookup['b'] = 11; + _hexLookup['c'] = 12; + _hexLookup['d'] = 13; + _hexLookup['e'] = 14; + _hexLookup['f'] = 15; + _hexLookup['A'] = 10; + _hexLookup['B'] = 11; + _hexLookup['C'] = 12; + _hexLookup['D'] = 13; + _hexLookup['E'] = 14; + _hexLookup['F'] = 15; + } + + public static int FromHex(string hex) + { + int value = 0; + for(int i = 0; i < hex.Length; i++) { + value <<= 4; + value |= _hexLookup[hex[i]]; + } + return value; + } + } +} diff --git a/GUI.NET/Debugger/LabelManager.cs b/GUI.NET/Debugger/LabelManager.cs index f189b666..c88252c4 100644 --- a/GUI.NET/Debugger/LabelManager.cs +++ b/GUI.NET/Debugger/LabelManager.cs @@ -65,7 +65,7 @@ namespace Mesen.GUI.Debugger public static CodeLabel GetLabel(UInt16 relativeAddress) { AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)relativeAddress, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)relativeAddress, info); if(info.Address >= 0) { return GetLabel((UInt32)info.Address, info.Type); } diff --git a/GUI.NET/Debugger/frmCodePreviewTooltip.cs b/GUI.NET/Debugger/frmCodePreviewTooltip.cs index e64ffe80..b32a2c92 100644 --- a/GUI.NET/Debugger/frmCodePreviewTooltip.cs +++ b/GUI.NET/Debugger/frmCodePreviewTooltip.cs @@ -18,7 +18,7 @@ namespace Mesen.GUI.Debugger private ICodeViewer _codeViewer; private int _lineIndex; - private string _code; + private CodeInfo _code; private Ld65DbgImporter _symbolProvider; private Ld65DbgImporter.FileInfo _selectedFile; @@ -27,7 +27,7 @@ namespace Mesen.GUI.Debugger get { return true; } } - public frmCodePreviewTooltip(Form parent, int lineIndex, string code = null, Ld65DbgImporter symbolProvider = null, Ld65DbgImporter.FileInfo selectedFile = null) + public frmCodePreviewTooltip(Form parent, int lineIndex, CodeInfo code = null, Ld65DbgImporter symbolProvider = null, Ld65DbgImporter.FileInfo selectedFile = null) { _parentForm = parent; _code = code; diff --git a/GUI.NET/Debugger/frmCodeTooltip.cs b/GUI.NET/Debugger/frmCodeTooltip.cs index 7fd5de96..6191a7e2 100644 --- a/GUI.NET/Debugger/frmCodeTooltip.cs +++ b/GUI.NET/Debugger/frmCodeTooltip.cs @@ -17,8 +17,8 @@ namespace Mesen.GUI.Debugger { private ICodeViewer _codeViewer; private Dictionary _values; - private AddressTypeInfo? _previewAddress; - private string _code; + private AddressTypeInfo _previewAddress; + private CodeInfo _code; private Ld65DbgImporter _symbolProvider; protected override bool ShowWithoutActivation @@ -26,7 +26,7 @@ namespace Mesen.GUI.Debugger get { return true; } } - public frmCodeTooltip(Form parent, Dictionary values, AddressTypeInfo? previewAddress = null, string code = null, Ld65DbgImporter symbolProvider = null) + public frmCodeTooltip(Form parent, Dictionary values, AddressTypeInfo previewAddress = null, CodeInfo code = null, Ld65DbgImporter symbolProvider = null) { _parentForm = parent; _values = values; @@ -66,7 +66,7 @@ namespace Mesen.GUI.Debugger i++; } - if(_previewAddress.HasValue) { + if(_previewAddress != null) { tlpMain.RowStyles.Insert(1, new RowStyle()); if(_code != null) { @@ -81,7 +81,7 @@ namespace Mesen.GUI.Debugger _codeViewer.CodeViewer.BaseFont = new Font(ConfigManager.Config.DebugInfo.FontFamily, ConfigManager.Config.DebugInfo.FontSize, ConfigManager.Config.DebugInfo.FontStyle); _codeViewer.CodeViewer.HideSelection = true; _codeViewer.CodeViewer.ShowScrollbars = false; - _codeViewer.ScrollToAddress(_previewAddress.Value, true); + _codeViewer.ScrollToAddress(_previewAddress, true); _codeViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView, true); Control control = _codeViewer as Control; diff --git a/GUI.NET/Debugger/frmDebugger.Designer.cs b/GUI.NET/Debugger/frmDebugger.Designer.cs index 54d076c8..c61ef7fe 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -322,7 +322,6 @@ namespace Mesen.GUI.Debugger // // ctrlDebuggerCode // - this.ctrlDebuggerCode.Code = null; this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlDebuggerCode.HideSelection = false; this.ctrlDebuggerCode.Location = new System.Drawing.Point(0, 0); @@ -359,7 +358,6 @@ namespace Mesen.GUI.Debugger // // ctrlDebuggerCodeSplit // - this.ctrlDebuggerCodeSplit.Code = null; this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlDebuggerCodeSplit.HideSelection = false; this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(0, 0); diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index 4d6656f3..ef6b7598 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -557,7 +557,7 @@ namespace Mesen.GUI.Debugger string newCode = InteropEmu.DebugGetCode(_firstBreak); if(newCode != null) { - ctrlDebuggerCode.Code = newCode; + ctrlDebuggerCode.Code = new CodeInfo(newCode); } DebugState state = new DebugState(); diff --git a/GUI.NET/Debugger/frmMemoryViewer.cs b/GUI.NET/Debugger/frmMemoryViewer.cs index 032a6ece..60d916c6 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.cs @@ -582,7 +582,7 @@ namespace Mesen.GUI.Debugger switch(_memoryType) { case DebugMemoryType.CpuMemory: AddressTypeInfo info = new AddressTypeInfo(); - InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)address, ref info); + InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)address, info); if(info.Address >= 0) { label = LabelManager.GetLabel((UInt32)info.Address, info.Type); } diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index 1fe21cdc..67b2fee7 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -326,6 +326,7 @@ + UserControl @@ -825,6 +826,7 @@ + diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 8a472d15..c3ee4fa7 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -278,7 +278,7 @@ namespace Mesen.GUI } } - [DllImport(DLLPath)] public static extern void DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, ref AddressTypeInfo addressTypeInfo); + [DllImport(DLLPath)] public static extern void DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, AddressTypeInfo addressTypeInfo); [DllImport(DLLPath)] public static extern void DebugSetPpuViewerScanlineCycle(Int32 ppuViewerId, Int32 scanline, Int32 cycle); [DllImport(DLLPath)] public static extern void DebugClearPpuViewerSettings(Int32 ppuViewerId); @@ -2251,12 +2251,13 @@ namespace Mesen.GUI IgnoreOverscan = 8, } - public struct AddressTypeInfo + [StructLayout(LayoutKind.Sequential)] + public class AddressTypeInfo { public Int32 Address; public AddressType Type; } - + public class MD5Helper { public static string GetMD5Hash(string filename)