Example #1
0
        public static DebugWorkspace GetWorkspace()
        {
            string romName = InteropEmu.GetRomInfo().GetRomName();

            if (_workspace != null)
            {
                SaveWorkspace();
            }

            if (_workspace == null || _romName != romName)
            {
                SymbolProvider = null;
                lock (_lock) {
                    if (_workspace == null || _romName != romName)
                    {
                        _romName   = InteropEmu.GetRomInfo().GetRomName();
                        _workspace = DebugWorkspace.GetWorkspace();

                        //Load watch entries
                        WatchManager.WatchEntries = _workspace.WatchValues;

                        //Setup labels
                        if (_workspace.Labels.Count == 0 && !ConfigManager.Config.DebugInfo.DisableDefaultLabels)
                        {
                            LabelManager.SetDefaultLabels(InteropEmu.GetRomInfo().MapperId);
                        }
                    }
                }
            }

            //Send breakpoints & labels to emulation core (even if the same game is running)
            BreakpointManager.SetBreakpoints(_workspace.Breakpoints);
            LabelManager.RefreshLabels();

            return(_workspace);
        }
Example #2
0
        public static void Export(string path)
        {
            List <CodeLabel> labels = LabelManager.GetAllLabels();

            labels.Sort((CodeLabel a, CodeLabel b) => {
                int result = a.MemoryType.CompareTo(b.MemoryType);
                if (result == 0)
                {
                    return(a.Address.CompareTo(b.Address));
                }
                else
                {
                    return(result);
                }
            });

            StringBuilder sb = new StringBuilder();

            foreach (CodeLabel label in labels)
            {
                sb.Append(label.ToString() + "\n");
            }
            File.WriteAllText(path, sb.ToString(), Encoding.UTF8);
        }
Example #3
0
        public void Import(string path, bool silent = false)
        {
            RomInfo romInfo = InteropEmu.GetRomInfo();

            _headerSize = (int)romInfo.FilePrgOffset;

            DebugState state = new DebugState();

            InteropEmu.DebugGetState(ref state);
            for (int i = 0; i < state.Cartridge.PrgMemoryType.Length; i++)
            {
                if (state.Cartridge.PrgMemoryType[i] == PrgMemoryType.WorkRam)
                {
                    _workRamStart = Math.Min(_workRamStart, i * 0x100);
                    _workRamEnd   = Math.Max(_workRamEnd, i * 0x100 + 0xFF);
                }
                else if (state.Cartridge.PrgMemoryType[i] == PrgMemoryType.SaveRam)
                {
                    _saveRamStart = Math.Min(_saveRamStart, i * 0x100);
                    _saveRamEnd   = Math.Max(_saveRamEnd, i * 0x100 + 0xFF);
                }
            }

            DbgFileStamp = File.GetLastWriteTime(path);
            string[] fileRows = File.ReadAllLines(path);

            string basePath = Path.GetDirectoryName(path);

            DbgPath = basePath;
            foreach (string row in fileRows)
            {
                try {
                    if (LoadLines(row) || LoadSpans(row) || LoadSymbols(row) || LoadCSymbols(row) || LoadScopes(row) || LoadFiles(row, basePath) || LoadSegments(row))
                    {
                        continue;
                    }
                } catch {
                    _errorCount++;
                }
            }

            LoadFileData(basePath);

            BuildCdlData();

            foreach (LineInfo line in _lines.Values)
            {
                foreach (int spanID in line.SpanIDs)
                {
                    SpanInfo span;
                    if (_spans.TryGetValue(spanID, out span))
                    {
                        SegmentInfo segment;
                        if (_segments.TryGetValue(span.SegmentID, out segment) && !segment.IsRam)
                        {
                            for (int i = 0; i < span.Size; i++)
                            {
                                int prgAddress = segment.FileOffset - _headerSize + span.Offset + i;
                                if (prgAddress >= state.Cartridge.PrgRomSize)
                                {
                                    //Address is outside PRG (probably CHR ROM)
                                    continue;
                                }

                                LineInfo existingLine;
                                if (_linesByPrgAddress.TryGetValue(prgAddress, out existingLine) && existingLine.Type == LineType.External)
                                {
                                    //Give priority to lines that come from C files
                                    continue;
                                }

                                _linesByPrgAddress[prgAddress] = line;
                                if (i == 0 && spanID == line.SpanIDs[0])
                                {
                                    //Mark the first byte of the first span representing this line as the PRG address for this line of code
                                    FileInfo file = _files[line.FileID];
                                    _prgAddressByLine[file.ID.ToString() + "_" + line.LineNumber.ToString()] = prgAddress;
                                }
                            }
                        }
                    }
                }
            }

            LoadLabels();

            int labelCount = 0;

            DebugImportConfig config = ConfigManager.Config.DebugInfo.ImportConfig;

            if (config.DbgImportComments)
            {
                LoadComments();
            }
            List <CodeLabel> labels = new List <CodeLabel>(_romLabels.Count + _ramLabels.Count + _workRamLabels.Count + _saveRamLabels.Count);

            if (config.DbgImportPrgRomLabels)
            {
                labels.AddRange(_romLabels.Values);
                labelCount += _romLabels.Count;
            }
            if (config.DbgImportRamLabels)
            {
                labels.AddRange(_ramLabels.Values);
                labelCount += _ramLabels.Count;
            }
            if (config.DbgImportWorkRamLabels)
            {
                labels.AddRange(_workRamLabels.Values);
                labelCount += _workRamLabels.Count;
            }
            if (config.DbgImportSaveRamLabels)
            {
                labels.AddRange(_saveRamLabels.Values);
                labelCount += _saveRamLabels.Count;
            }

            LabelManager.SetLabels(labels, true);

            if (!silent)
            {
                if (_errorCount > 0)
                {
                    _errorCount -= _filesNotFound.Count;
                    string message = $"Import completed with {labelCount} labels imported";
                    if (_errorCount > 0)
                    {
                        message += $"and {_errorCount} errors - please file a bug report and attach the DBG file you tried to import.";
                    }
                    if (_filesNotFound.Count > 0)
                    {
                        message += Environment.NewLine + Environment.NewLine + "The following files could not be found:";
                        foreach (string file in _filesNotFound)
                        {
                            message += Environment.NewLine + file;
                        }
                    }
                    MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else
                {
                    MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
Example #4
0
        private void UpdateResults()
        {
            string searchString = txtSearch.Text.Trim();

            List <string> searchStrings = new List <string>();

            searchStrings.Add(searchString.ToLower());
            searchStrings.AddRange(searchString.ToLower().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
            for (int i = 0; i < searchString.Length; i++)
            {
                char ch = searchString[i];
                if (ch >= 'A' && ch <= 'Z')
                {
                    searchString = searchString.Remove(i, 1).Insert(i, " " + (char)(ch + 'a' - 'A'));
                }
            }
            searchStrings.AddRange(searchString.ToLower().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
            searchStrings = searchStrings.Distinct().ToList();

            _resultCount = 0;

            HashSet <int> entryPoints = new HashSet <int>(InteropEmu.DebugGetFunctionEntryPoints());

            byte[] cdlData = InteropEmu.DebugGetPrgCdlData();

            List <SearchResultInfo> searchResults = new List <SearchResultInfo>();

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                if (_symbolProvider != null)
                {
                    if (_showFilesAndConstants)
                    {
                        foreach (Ld65DbgImporter.FileInfo file in _symbolProvider.Files.Values)
                        {
                            if (Contains(file.Name, searchStrings))
                            {
                                searchResults.Add(new SearchResultInfo()
                                {
                                    Caption          = Path.GetFileName(file.Name),
                                    AbsoluteAddress  = -1,
                                    MemoryType       = AddressType.InternalRam,
                                    SearchResultType = SearchResultType.File,
                                    Filename         = file.Name,
                                    FileLineNumber   = 0,
                                    RelativeAddress  = -1,
                                    CodeLabel        = null
                                });
                            }
                        }
                    }

                    foreach (Ld65DbgImporter.SymbolInfo symbol in _symbolProvider.GetSymbols())
                    {
                        if (Contains(symbol.Name, searchStrings))
                        {
                            Ld65DbgImporter.ReferenceInfo def = _symbolProvider.GetSymbolDefinition(symbol);
                            AddressTypeInfo addressInfo       = _symbolProvider.GetSymbolAddressInfo(symbol);
                            int             value             = 0;
                            int             relAddress        = -1;
                            bool            isConstant        = addressInfo == null;
                            if (!_showFilesAndConstants && isConstant)
                            {
                                continue;
                            }

                            if (addressInfo != null)
                            {
                                value      = InteropEmu.DebugGetMemoryValue(addressInfo.Type.ToMemoryType(), (uint)addressInfo.Address);
                                relAddress = InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type);
                            }
                            else
                            {
                                //For constants, the address field contains the constant's value
                                value = symbol.Address ?? 0;
                            }

                            SearchResultType resultType = SearchResultType.Data;
                            if (addressInfo?.Type == AddressType.PrgRom && entryPoints.Contains(addressInfo.Address))
                            {
                                resultType = SearchResultType.Function;
                            }
                            else if (addressInfo?.Type == AddressType.PrgRom && addressInfo.Address < cdlData.Length && (cdlData[addressInfo.Address] & (byte)CdlPrgFlags.JumpTarget) != 0)
                            {
                                resultType = SearchResultType.JumpTarget;
                            }
                            else if (isConstant)
                            {
                                resultType = SearchResultType.Constant;
                            }

                            searchResults.Add(new SearchResultInfo()
                            {
                                Caption          = symbol.Name,
                                AbsoluteAddress  = addressInfo?.Address ?? -1,
                                MemoryType       = addressInfo?.Type ?? AddressType.InternalRam,
                                SearchResultType = resultType,
                                Value            = value,
                                Filename         = def?.FileName ?? "",
                                FileLineNumber   = def?.LineNumber ?? 0,
                                RelativeAddress  = relAddress,
                                CodeLabel        = LabelManager.GetLabel(symbol.Name)
                            });
                        }
                    }
                }
                else
                {
                    foreach (CodeLabel label in LabelManager.GetLabels())
                    {
                        if (Contains(label.Label, searchStrings))
                        {
                            SearchResultType resultType = SearchResultType.Data;
                            if (label.AddressType == AddressType.PrgRom && entryPoints.Contains((int)label.Address))
                            {
                                resultType = SearchResultType.Function;
                            }
                            else if (label.AddressType == AddressType.PrgRom && label.Address < cdlData.Length && (cdlData[label.Address] & (byte)CdlPrgFlags.JumpTarget) != 0)
                            {
                                resultType = SearchResultType.JumpTarget;
                            }

                            int relativeAddress = label.GetRelativeAddress();

                            searchResults.Add(new SearchResultInfo()
                            {
                                Caption          = label.Label,
                                AbsoluteAddress  = (int)label.Address,
                                Value            = label.GetValue(),
                                MemoryType       = label.AddressType,
                                SearchResultType = resultType,
                                Filename         = "",
                                Disabled         = !_allowOutOfScope && relativeAddress < 0,
                                RelativeAddress  = relativeAddress,
                                CodeLabel        = label
                            });
                        }
                    }
                }
            }

            searchResults.Sort((SearchResultInfo a, SearchResultInfo b) => {
                int comparison = a.Disabled.CompareTo(b.Disabled);

                if (comparison == 0)
                {
                    bool aStartsWithSearch = a.Caption.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase);
                    bool bStartsWithSearch = b.Caption.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase);

                    comparison = bStartsWithSearch.CompareTo(aStartsWithSearch);
                    if (comparison == 0)
                    {
                        comparison = a.Caption.CompareTo(b.Caption);
                    }
                }
                return(comparison);
            });

            _resultCount   = Math.Min(searchResults.Count, MaxResultCount);
            SelectedResult = 0;

            if (searchResults.Count == 0)
            {
                searchResults.Add(new SearchResultInfo()
                {
                    Caption = "No results found.", AbsoluteAddress = -1
                });
                pnlResults.BackColor = SystemColors.ControlLight;
            }
            else
            {
                pnlResults.BackColor = SystemColors.ControlDarkDark;
            }

            if (Program.IsMono)
            {
                pnlResults.Visible = false;
            }
            else
            {
                //Suspend layout causes a crash on Mono
                tlpResults.SuspendLayout();
            }

            for (int i = 0; i < _resultCount; i++)
            {
                _results[i].Initialize(searchResults[i]);
                _results[i].Tag     = searchResults[i];
                _results[i].Visible = true;
            }

            for (int i = searchResults.Count; i < MaxResultCount; i++)
            {
                _results[i].Visible = false;
            }

            pnlResults.VerticalScroll.Value = 0;
            tlpResults.Height = (_results[0].Height + 1) * _resultCount;

            pnlResults.ResumeLayout();
            if (Program.IsMono)
            {
                pnlResults.Visible = true;
                tlpResults.Width   = pnlResults.ClientSize.Width - 17;
            }
            else
            {
                tlpResults.ResumeLayout();
                tlpResults.Width = pnlResults.ClientSize.Width - 1;
            }
        }
Example #5
0
        private void UpdateResults()
        {
            string searchString = txtSearch.Text.Trim();

            List <string> searchStrings = new List <string>();

            searchStrings.Add(searchString.ToLower());
            searchStrings.AddRange(searchString.ToLower().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
            for (int i = 0; i < searchString.Length; i++)
            {
                char ch = searchString[i];
                if (ch >= 'A' && ch <= 'Z')
                {
                    searchString = searchString.Remove(i, 1).Insert(i, " " + (char)(ch + 'a' - 'A'));
                }
            }
            searchStrings.AddRange(searchString.ToLower().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
            searchStrings = searchStrings.Distinct().ToList();

            _resultCount = 0;

            int size = DebugApi.GetMemorySize(SnesMemoryType.PrgRom);

            byte[] cdlData = DebugApi.GetCdlData(0, (uint)size, SnesMemoryType.PrgRom);

            List <SearchResultInfo> searchResults = new List <SearchResultInfo>();
            bool isEmptySearch = string.IsNullOrWhiteSpace(searchString);

            if (!isEmptySearch)
            {
                if (_symbolProvider != null)
                {
                    if (_showFilesAndConstants)
                    {
                        foreach (SourceFileInfo file in _symbolProvider.SourceFiles)
                        {
                            if (Contains(file.Name, searchStrings))
                            {
                                searchResults.Add(new SearchResultInfo()
                                {
                                    Caption          = Path.GetFileName(file.Name),
                                    AbsoluteAddress  = null,
                                    SearchResultType = SearchResultType.File,
                                    File             = file,
                                    SourceLocation   = null,
                                    RelativeAddress  = null,
                                    CodeLabel        = null
                                });
                            }
                        }
                    }

                    foreach (SourceSymbol symbol in _symbolProvider.GetSymbols())
                    {
                        if (Contains(symbol.Name, searchStrings))
                        {
                            SourceCodeLocation def         = _symbolProvider.GetSymbolDefinition(symbol);
                            AddressInfo?       addressInfo = _symbolProvider.GetSymbolAddressInfo(symbol);
                            int         value      = 0;
                            AddressInfo?relAddress = null;
                            bool        isConstant = addressInfo == null;
                            if (!_showFilesAndConstants && isConstant)
                            {
                                continue;
                            }

                            if (addressInfo != null)
                            {
                                value      = DebugApi.GetMemoryValue(addressInfo.Value.Type, (uint)addressInfo.Value.Address);
                                relAddress = DebugApi.GetRelativeAddress(addressInfo.Value, CpuType.Cpu);                                 //TODO
                            }
                            else
                            {
                                //For constants, the address field contains the constant's value
                                value = symbol.Address ?? 0;
                            }

                            SearchResultType resultType = SearchResultType.Data;
                            if (isConstant)
                            {
                                resultType = SearchResultType.Constant;
                            }
                            else if (addressInfo?.Type == SnesMemoryType.PrgRom && addressInfo.Value.Address < cdlData.Length)
                            {
                                if ((cdlData[addressInfo.Value.Address] & (byte)CdlFlags.JumpTarget) != 0)
                                {
                                    resultType = SearchResultType.JumpTarget;
                                }
                                else if ((cdlData[addressInfo.Value.Address] & (byte)CdlFlags.SubEntryPoint) != 0)
                                {
                                    resultType = SearchResultType.Function;
                                }
                            }

                            searchResults.Add(new SearchResultInfo()
                            {
                                Caption          = symbol.Name,
                                AbsoluteAddress  = addressInfo,
                                Length           = _symbolProvider.GetSymbolSize(symbol),
                                SearchResultType = resultType,
                                Value            = value,
                                File             = def?.File,
                                SourceLocation   = def,
                                RelativeAddress  = relAddress,
                                CodeLabel        = LabelManager.GetLabel(symbol.Name)
                            });
                        }
                    }
                }
                else
                {
                    foreach (CodeLabel label in LabelManager.GetLabels(CpuType.Cpu))                      //TODO
                    {
                        if (Contains(label.Label, searchStrings))
                        {
                            SearchResultType resultType  = SearchResultType.Data;
                            AddressInfo      addressInfo = label.GetAbsoluteAddress();
                            if (addressInfo.Type == SnesMemoryType.PrgRom && addressInfo.Address < cdlData.Length)
                            {
                                if ((cdlData[addressInfo.Address] & (byte)CdlFlags.JumpTarget) != 0)
                                {
                                    resultType = SearchResultType.JumpTarget;
                                }
                                else if ((cdlData[addressInfo.Address] & (byte)CdlFlags.SubEntryPoint) != 0)
                                {
                                    resultType = SearchResultType.Function;
                                }
                            }

                            AddressInfo relAddress = label.GetRelativeAddress(CpuType.Cpu);                             //TODO
                            searchResults.Add(new SearchResultInfo()
                            {
                                Caption          = label.Label,
                                AbsoluteAddress  = label.GetAbsoluteAddress(),
                                Length           = (int)label.Length,
                                Value            = label.GetValue(),
                                SearchResultType = resultType,
                                File             = null,
                                Disabled         = !_allowOutOfScope && relAddress.Address < 0,
                                RelativeAddress  = relAddress,
                                CodeLabel        = label
                            });
                        }
                    }
                }
            }

            searchResults.Sort((SearchResultInfo a, SearchResultInfo b) => {
                int comparison = a.Disabled.CompareTo(b.Disabled);

                if (comparison == 0)
                {
                    bool aStartsWithSearch = a.Caption.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase);
                    bool bStartsWithSearch = b.Caption.StartsWith(searchString, StringComparison.InvariantCultureIgnoreCase);

                    comparison = bStartsWithSearch.CompareTo(aStartsWithSearch);
                    if (comparison == 0)
                    {
                        comparison = a.Caption.CompareTo(b.Caption);
                    }
                }
                return(comparison);
            });

            _resultCount   = Math.Min(searchResults.Count, MaxResultCount);
            SelectedResult = 0;

            lblResultCount.Visible = !isEmptySearch;
            lblResultCount.Text    = searchResults.Count.ToString() + (searchResults.Count == 1 ? " result" : " results");
            if (searchResults.Count > MaxResultCount)
            {
                lblResultCount.Text += " (" + MaxResultCount.ToString() + " shown)";
            }

            if (searchResults.Count == 0 && !isEmptySearch)
            {
                _resultCount++;
                searchResults.Add(new SearchResultInfo()
                {
                    Caption = "No results found."
                });
                pnlResults.BackColor = SystemColors.ControlLight;
            }
            else
            {
                pnlResults.BackColor = SystemColors.ControlDarkDark;
            }

            if (Program.IsMono)
            {
                pnlResults.Visible = false;
            }
            else
            {
                //Suspend layout causes a crash on Mono
                tlpResults.SuspendLayout();
            }

            for (int i = 0; i < _resultCount; i++)
            {
                _results[i].Initialize(searchResults[i]);
                _results[i].Tag     = searchResults[i];
                _results[i].Visible = true;
            }

            for (int i = _resultCount; i < MaxResultCount; i++)
            {
                _results[i].Visible = false;
            }

            pnlResults.VerticalScroll.Value = 0;
            tlpResults.Height = (_results[0].Height + 1) * _resultCount;

            pnlResults.ResumeLayout();
            if (Program.IsMono)
            {
                pnlResults.Visible = true;
                tlpResults.Width   = pnlResults.ClientSize.Width - 17;
            }
            else
            {
                tlpResults.ResumeLayout();
                tlpResults.Width = pnlResults.ClientSize.Width - 1;
            }
        }
Example #6
0
        public void ProcessMouseMove(Point location)
        {
            if (_previousLocation != location)
            {
                bool closeExistingPopup = true;

                _previousLocation = location;

                string word = _codeViewer.GetWordUnderLocation(location);
                if (word.StartsWith("$"))
                {
                    try {
                        UInt32 address = UInt32.Parse(word.Substring(1), NumberStyles.AllowHexSpecifier);

                        AddressTypeInfo info = new AddressTypeInfo();
                        InteropEmu.DebugGetAbsoluteAddressAndType(address, info);

                        if (info.Address >= 0)
                        {
                            CodeLabel label = LabelManager.GetLabel((UInt32)info.Address, info.Type);
                            if (label == null)
                            {
                                DisplayAddressTooltip(word, address);
                                closeExistingPopup = false;
                            }
                            else
                            {
                                DisplayLabelTooltip(word, label, 0);
                                closeExistingPopup = false;
                            }
                        }
                        else
                        {
                            DisplayAddressTooltip(word, address);
                            closeExistingPopup = false;
                        }
                    } catch { }
                }
                else
                {
                    Match arrayMatch = LabelArrayFormat.Match(word);
                    int?  arrayIndex = null;
                    if (arrayMatch.Success)
                    {
                        word       = arrayMatch.Groups[1].Value;
                        arrayIndex = Int32.Parse(arrayMatch.Groups[2].Value);
                    }

                    int address = _codeViewer.GetLineNumberAtPosition(location.Y);
                    if (SymbolProvider != null)
                    {
                        int rangeStart, rangeEnd;
                        if (_codeViewer.GetNoteRangeAtLocation(location.Y, out rangeStart, out rangeEnd))
                        {
                            Ld65DbgImporter.SymbolInfo symbol = SymbolProvider.GetSymbol(word, rangeStart, rangeEnd);
                            if (symbol != null)
                            {
                                DisplaySymbolTooltip(symbol, arrayIndex);
                                return;
                            }
                        }
                    }
                    else
                    {
                        CodeLabel label = LabelManager.GetLabel(word);
                        if (label != null)
                        {
                            DisplayLabelTooltip(word, label, arrayIndex);
                            return;
                        }
                    }

                    if (ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word))
                    {
                        ShowTooltip(word, null, address, new AddressTypeInfo()
                        {
                            Address = address, Type = AddressType.Register
                        });
                        closeExistingPopup = false;
                    }
                }

                if (closeExistingPopup)
                {
                    this.Close();
                }
            }
        }
Example #7
0
        public void Import(string path, bool silent = false)
        {
            string[] fileRows = File.ReadAllLines(path);

            string basePath = Path.GetDirectoryName(path);

            foreach (string row in fileRows)
            {
                try {
                    if (LoadLines(row) || LoadSpans(row) || LoadSymbols(row) || LoadCSymbols(row) || LoadFiles(row, basePath) || LoadSegments(row))
                    {
                        continue;
                    }
                } catch {
                    _errorCount++;
                }
            }

            LoadFileData(basePath);

            int prgSize = InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom);

            if (prgSize > 0)
            {
                byte[] cdlFile = new byte[prgSize];
                foreach (KeyValuePair <int, SpanInfo> kvp in _spans)
                {
                    SegmentInfo segment;
                    if (_segments.TryGetValue(kvp.Value.SegmentID, out segment))
                    {
                        if (!segment.IsRam && kvp.Value.Size != segment.Size)
                        {
                            int prgAddress = kvp.Value.Offset + segment.FileOffset - iNesHeaderSize;

                            if (prgAddress >= 0 && prgAddress < prgSize)
                            {
                                for (int i = 0; i < kvp.Value.Size; i++)
                                {
                                    if (cdlFile[prgAddress + i] == 0 && !kvp.Value.IsData && kvp.Value.Size <= 3)
                                    {
                                        cdlFile[prgAddress + i] = (byte)0x01;
                                    }
                                    else if (kvp.Value.IsData)
                                    {
                                        cdlFile[prgAddress + i] = (byte)0x02;
                                    }
                                }
                            }
                        }
                    }
                }
                InteropEmu.DebugSetCdlData(cdlFile);
            }

            foreach (LineInfo line in _lines.Values)
            {
                if (line.SpanID == null)
                {
                    continue;
                }

                FileInfo    file    = _files[line.FileID];
                SpanInfo    span    = _spans[line.SpanID.Value];
                SegmentInfo segment = _segments[span.SegmentID];
                if (!segment.IsRam)
                {
                    for (int i = 0; i < span.Size; i++)
                    {
                        int prgAddress = segment.FileOffset - iNesHeaderSize + span.Offset + i;

                        LineInfo existingLine;
                        if (_linesByPrgAddress.TryGetValue(prgAddress, out existingLine) && existingLine.Type == LineType.External)
                        {
                            //Give priority to lines that come from C files
                            continue;
                        }

                        _linesByPrgAddress[prgAddress] = line;
                        if (i == 0)
                        {
                            _prgAddressByLine[file.ID.ToString() + "_" + line.LineNumber.ToString()] = prgAddress;
                        }
                    }
                }
            }

            LoadLabels();

            int labelCount = 0;

            DebugImportConfig config = ConfigManager.Config.DebugInfo.ImportConfig;

            if (config.DbgImportComments)
            {
                LoadComments();
            }
            if (config.DbgImportPrgRomLabels)
            {
                LabelManager.SetLabels(_romLabels.Values);
                labelCount += _romLabels.Count;
            }
            if (config.DbgImportRamLabels)
            {
                LabelManager.SetLabels(_ramLabels.Values);
                labelCount += _ramLabels.Count;
            }

            if (!silent)
            {
                if (_errorCount > 0)
                {
                    _errorCount -= _filesNotFound.Count;
                    string message = $"Import completed with {labelCount} labels imported";
                    if (_errorCount > 0)
                    {
                        message += $"and {_errorCount} errors - please file a bug report and attach the DBG file you tried to import.";
                    }
                    if (_filesNotFound.Count > 0)
                    {
                        message += Environment.NewLine + Environment.NewLine + "The following files could not be found:";
                        foreach (string file in _filesNotFound)
                        {
                            message += Environment.NewLine + file;
                        }
                    }
                    MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else
                {
                    MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
Example #8
0
        private void ctrlHexViewer_ByteMouseHover(int address, Point position)
        {
            if (address < 0 || !mnuShowLabelInfoOnMouseOver.Checked)
            {
                if (_tooltip != null)
                {
                    _tooltip.Close();
                    _lastLabelTooltip   = null;
                    _lastTooltipAddress = -1;
                }
                return;
            }

            if (_lastTooltipAddress == address)
            {
                return;
            }

            _lastTooltipAddress = address;

            CodeLabel label = null;

            switch (_memoryType)
            {
            case DebugMemoryType.CpuMemory:
                AddressTypeInfo info = new AddressTypeInfo();
                InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)address, info);
                if (info.Address >= 0)
                {
                    label = LabelManager.GetLabel((UInt32)info.Address, info.Type);
                }
                if (label == null)
                {
                    label = LabelManager.GetLabel((UInt32)address, AddressType.Register);
                }
                break;

            case DebugMemoryType.InternalRam:
                label = LabelManager.GetLabel((UInt32)address, AddressType.InternalRam);
                break;

            case DebugMemoryType.WorkRam:
                label = LabelManager.GetLabel((UInt32)address, AddressType.WorkRam);
                break;

            case DebugMemoryType.SaveRam:
                label = LabelManager.GetLabel((UInt32)address, AddressType.SaveRam);
                break;

            case DebugMemoryType.PrgRom:
                label = LabelManager.GetLabel((UInt32)address, AddressType.PrgRom);
                break;
            }

            if (label != null)
            {
                if (_lastLabelTooltip != label)
                {
                    if (_tooltip != null)
                    {
                        _tooltip.Close();
                    }

                    Dictionary <string, string> values = new Dictionary <string, string>();
                    if (!string.IsNullOrWhiteSpace(label.Label))
                    {
                        values["Label"] = label.Label;
                    }
                    values["Address"]      = "$" + label.Address.ToString("X4");
                    values["Address Type"] = label.AddressType.ToString();
                    if (!string.IsNullOrWhiteSpace(label.Comment))
                    {
                        values["Comment"] = label.Comment;
                    }

                    _tooltip             = new frmCodeTooltip(this, values);
                    _tooltip.FormClosed += (s, evt) => { _tooltip = null; };
                    _tooltip.SetFormLocation(new Point(position.X, position.Y), ctrlHexViewer);
                    _lastLabelTooltip = label;
                }
            }
            else
            {
                if (_tooltip != null)
                {
                    _tooltip.Close();
                    _lastLabelTooltip   = null;
                    _lastTooltipAddress = -1;
                }
            }
        }
Example #9
0
        public void Prepare(long firstByteIndex, long lastByteIndex)
        {
            int visibleByteCount = (int)(lastByteIndex - firstByteIndex + 1);

            if (_highlightBreakpoints)
            {
                Breakpoint[] breakpoints = BreakpointManager.Breakpoints.ToArray();
                _breakpointTypes = new BreakpointType[visibleByteCount];

                for (int i = 0; i < visibleByteCount; i++)
                {
                    int byteIndex = i + (int)firstByteIndex;
                    foreach (Breakpoint bp in breakpoints)
                    {
                        if (bp.Enabled && bp.IsCpuBreakpoint && bp.Matches(byteIndex, _memoryType))
                        {
                            _breakpointTypes[i] = bp.BreakOnExec ? BreakpointType.Execute : (bp.BreakOnWrite ? BreakpointType.WriteRam : BreakpointType.ReadRam);
                            break;
                        }
                    }
                }
            }
            else
            {
                _breakpointTypes = null;
            }

            _readStamps  = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
            _writeStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
            _execStamps  = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Exec);
            if (_memoryType == DebugMemoryType.CpuMemory)
            {
                _freezeState = InteropEmu.DebugGetFreezeState((UInt16)firstByteIndex, (UInt16)visibleByteCount);
            }

            _readCounts  = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
            _writeCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
            _execCounts  = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Exec);

            _cdlData = null;
            if (_highlightDmcDataBytes || _highlightDataBytes || _highlightCodeBytes)
            {
                switch (_memoryType)
                {
                case DebugMemoryType.ChrRom:
                case DebugMemoryType.PpuMemory:
                case DebugMemoryType.CpuMemory:
                case DebugMemoryType.PrgRom:
                    _cdlData = InteropEmu.DebugGetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
                    break;
                }
            }

            _hasLabel = new bool[visibleByteCount];
            if (_highlightLabelledBytes)
            {
                if (_memoryType == DebugMemoryType.CpuMemory)
                {
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        _hasLabel[i] = (
                            !string.IsNullOrWhiteSpace(LabelManager.GetLabel((UInt16)(i + firstByteIndex))?.Label) ||
                            !string.IsNullOrWhiteSpace(LabelManager.GetLabel((uint)(i + firstByteIndex), AddressType.Register)?.Label)
                            );
                    }
                }
                else if (_memoryType == DebugMemoryType.PrgRom || _memoryType == DebugMemoryType.WorkRam || _memoryType == DebugMemoryType.SaveRam)
                {
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        _hasLabel[i] = !string.IsNullOrWhiteSpace(LabelManager.GetLabel((uint)(firstByteIndex + i), _memoryType.ToAddressType())?.Label);
                    }
                }
            }

            InteropEmu.DebugGetState(ref _state);
        }
Example #10
0
        private void ctrlHexViewer_ByteMouseHover(int address, Point position)
        {
            ctrlTooltip tooltip = BaseForm.GetPopupTooltip(this);

            if (address < 0 || !mnuShowLabelInfoOnMouseOver.Checked)
            {
                _lastTooltipAddress = -1;
                tooltip.Hide();
                return;
            }
            else if (_lastTooltipAddress == address)
            {
                return;
            }

            _lastTooltipAddress = address;

            CodeLabel label       = null;
            int       arrayOffset = 0;

            switch (_memoryType)
            {
            case SnesMemoryType.CpuMemory:
            case SnesMemoryType.SpcMemory:
                AddressInfo relAddress = new AddressInfo()
                {
                    Address = address,
                    Type    = _memoryType
                };
                AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
                if (absAddress.Address >= 0)
                {
                    label = LabelManager.GetLabel((uint)absAddress.Address, absAddress.Type);
                    if (label != null)
                    {
                        arrayOffset = relAddress.Address - (int)label.Address;
                    }
                }
                break;

            case SnesMemoryType.WorkRam:
            case SnesMemoryType.SaveRam:
            case SnesMemoryType.PrgRom:
            case SnesMemoryType.SpcRam:
            case SnesMemoryType.SpcRom:
                label = LabelManager.GetLabel((uint)address, _memoryType);
                if (label != null)
                {
                    arrayOffset = address - (int)label.Address;
                }
                break;
            }

            if (label != null && !string.IsNullOrWhiteSpace(label.Label))
            {
                Dictionary <string, string> values = new Dictionary <string, string>();
                if (!string.IsNullOrWhiteSpace(label.Label))
                {
                    values["Label"] = label.Label;
                    if (label.Length > 1)
                    {
                        values["Label"] += "+" + arrayOffset.ToString();
                    }
                }
                values["Address"] = "$" + (label.Address + arrayOffset).ToString("X4");
                values["Type"]    = ResourceHelper.GetEnumText(label.MemoryType);
                if (!string.IsNullOrWhiteSpace(label.Comment))
                {
                    values["Comment"] = label.Comment;
                }

                tooltip.SetTooltip(this.PointToClient(position), values);
            }
            else
            {
                tooltip.Hide();
            }
        }
Example #11
0
        private void OnNotificationReceived(NotificationEventArgs e)
        {
            switch (e.NotificationType)
            {
            case ConsoleNotificationType.GameLoaded: {
                if (_cpuType == CpuType.Sa1)
                {
                    CoprocessorType coprocessor = EmuApi.GetRomInfo().CoprocessorType;
                    if (coprocessor != CoprocessorType.SA1)
                    {
                        this.Invoke((MethodInvoker)(() => {
                                this.Close();
                            }));
                        return;
                    }
                }

                if (ConfigManager.Config.Debug.Debugger.BreakOnPowerCycleReset)
                {
                    DebugApi.Step(_cpuType, 1, StepType.PpuStep);
                }

                BreakpointManager.SetBreakpoints();

                DebugState state = DebugApi.GetState();
                this.BeginInvoke((MethodInvoker)(() => {
                        //Refresh workspace here as well as frmMain to ensure workspace
                        //is up-to-date no matter which form is notified first.
                        DebugWorkspaceManager.GetWorkspace();

                        bool isPowerCycle = e.Parameter.ToInt32() != 0;
                        if (!isPowerCycle)
                        {
                            DebugWorkspaceManager.AutoImportSymbols();
                        }
                        LabelManager.RefreshLabels();
                        DebugApi.RefreshDisassembly(_cpuType);
                        UpdateDebugger(state, null);
                    }));
                break;
            }

            case ConsoleNotificationType.GameReset:
                if (ConfigManager.Config.Debug.Debugger.BreakOnPowerCycleReset)
                {
                    DebugApi.Step(_cpuType, 1, StepType.PpuStep);
                }
                break;

            case ConsoleNotificationType.PpuFrameDone:
                this.BeginInvoke((MethodInvoker)(() => {
                    UpdateContinueAction();
                }));
                break;

            case ConsoleNotificationType.CodeBreak: {
                BreakEvent evt = (BreakEvent)Marshal.PtrToStructure(e.Parameter, typeof(BreakEvent));
                RefreshDebugger(evt);
                break;
            }
            }
        }
Example #12
0
        private bool UpdateContextMenu(Point mouseLocation)
        {
            UpdateContextMenuItemVisibility(true);

            string word = GetWordUnderLocation(mouseLocation);

            if (word.StartsWith("$") || LabelManager.GetLabel(word) != null)
            {
                //Cursor is on a numeric value or label
                _lastWord = word;

                if (word.StartsWith("$"))
                {
                    _lastClickedAddress = Int32.Parse(word.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier);
                    _newWatchValue      = "[$" + _lastClickedAddress.ToString("X") + "]";
                }
                else
                {
                    _lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress(LabelManager.GetLabel(word).Address, LabelManager.GetLabel(word).AddressType);
                    _newWatchValue      = "[" + word + "]";
                }

                mnuGoToLocation.Enabled = true;
                mnuGoToLocation.Text    = $"Go to Location ({word})";

                mnuAddToWatch.Enabled = true;
                mnuAddToWatch.Text    = $"Add to Watch ({word})";

                mnuFindOccurrences.Enabled = true;
                mnuFindOccurrences.Text    = $"Find Occurrences ({word})";

                mnuEditLabel.Enabled = true;
                mnuEditLabel.Text    = $"Edit Label ({word})";

                return(true);
            }
            else
            {
                mnuGoToLocation.Enabled    = false;
                mnuGoToLocation.Text       = "Go to Location";
                mnuAddToWatch.Enabled      = false;
                mnuAddToWatch.Text         = "Add to Watch";
                mnuFindOccurrences.Enabled = false;
                mnuFindOccurrences.Text    = "Find Occurrences";
                mnuEditLabel.Enabled       = false;
                mnuEditLabel.Text          = "Edit Label";

                _lastClickedAddress = ctrlCodeViewer.GetLineNumberAtPosition(mouseLocation.Y);
                if (mouseLocation.X < this.ctrlCodeViewer.CodeMargin && _lastClickedAddress >= 0)
                {
                    //Cursor is in the margin, over an address label
                    string address = $"${_lastClickedAddress.ToString("X4")}";
                    _newWatchValue = $"[{address}]";
                    _lastWord      = address;

                    mnuAddToWatch.Enabled      = true;
                    mnuAddToWatch.Text         = $"Add to Watch ({address})";
                    mnuFindOccurrences.Enabled = true;
                    mnuFindOccurrences.Text    = $"Find Occurrences ({address})";
                    mnuEditLabel.Enabled       = true;
                    mnuEditLabel.Text          = $"Edit Label ({address})";

                    return(true);
                }

                return(false);
            }
        }
Example #13
0
        private void ctrlCodeViewer_MouseMove(object sender, MouseEventArgs e)
        {
            //Always enable to allow F2 shortcut
            mnuEditLabel.Enabled = true;

            if (e.Location.X < this.ctrlCodeViewer.CodeMargin / 4)
            {
                this.ctrlCodeViewer.ContextMenuStrip = contextMenuMargin;
            }
            else
            {
                this.ctrlCodeViewer.ContextMenuStrip = contextMenuCode;
            }

            if (_previousLocation != e.Location)
            {
                if (!_preventCloseTooltip && _codeTooltip != null)
                {
                    _codeTooltip.Close();
                    _codeTooltip = null;
                }
                _preventCloseTooltip = false;

                string word = GetWordUnderLocation(e.Location);
                if (word.StartsWith("$"))
                {
                    try {
                        UInt32 address = UInt32.Parse(word.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier);

                        AddressTypeInfo info = new AddressTypeInfo();
                        InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);

                        if (info.Address >= 0)
                        {
                            CodeLabel label = LabelManager.GetLabel((UInt32)info.Address, info.Type);
                            if (label == null)
                            {
                                DisplayAddressTooltip(word, address);
                            }
                            else
                            {
                                DisplayLabelTooltip(word, label);
                            }
                        }
                        else
                        {
                            DisplayAddressTooltip(word, address);
                        }
                    } catch { }
                }
                else
                {
                    CodeLabel label = LabelManager.GetLabel(word);

                    if (label != null)
                    {
                        DisplayLabelTooltip(word, label);
                    }
                }
                _previousLocation = e.Location;
            }
        }
Example #14
0
        public static void Import(string path, bool silent = false)
        {
            List <CodeLabel>  labels      = new List <CodeLabel>(1000);
            List <Breakpoint> breakpoints = new List <Breakpoint>(1000);

            int errorCount = 0;

            foreach (string row in File.ReadAllLines(path, Encoding.UTF8))
            {
                string lineData = row.Trim();
                if (lineData.StartsWith("<"))
                {
                    continue;                                           //this is a <command line>: operation and we don't want it
                }
                if (lineData.Contains(":="))
                {
                    continue;                                          //this is a "variable" we dont' want it
                }
                int splitIndex = lineData.IndexOf(' ');

                string[] parts = lineData.Substring(splitIndex + 1).Split('=');

                UInt32       address;
                string       value = parts[1].Trim();
                NumberStyles type  = NumberStyles.Integer;
                if (value.StartsWith("$"))
                {
                    type  = NumberStyles.HexNumber;
                    value = value.Substring(1);                     //remove the $
                }
                else if (value.StartsWith("%"))
                {
                    continue;                     // Binary values are not labels 99.99999999999999% of the time
                }

                if (!UInt32.TryParse(value, type, null, out address))
                {
                    errorCount++;
                    continue;
                }

                AddressInfo absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo()
                {
                    Address = (int)address, Type = SnesMemoryType.CpuMemory
                });

                if (absAddress.Address >= 0)
                {
                    if (parts[0].Contains("BREAK"))
                    {
                        //we have a break point
                        Breakpoint breakpoint = new Breakpoint();
                        breakpoint.Address     = address;
                        breakpoint.AddressType = BreakpointAddressType.SingleAddress;
                        breakpoint.BreakOnExec = true;
                        breakpoint.CpuType     = CpuType.Cpu;
                        breakpoints.Add(breakpoint);
                    }
                    else if (parts[0].Contains("ASSERT_"))
                    {
                        string assert_field = parts[0].Trim().ToLower().Substring(parts[0].IndexOf("ASSERT_") + 7);
                        string cond         = string.Empty;
                        if (assert_field == "a8")
                        {
                            cond = "(PS & 32) == 32";
                        }
                        else if (assert_field == "a16")
                        {
                            cond = "(PS & 32) == 0";
                        }
                        else if (assert_field == "xy8")
                        {
                            cond = "(PS & 16) == 16";
                        }
                        else if (assert_field == "xy16")
                        {
                            cond = "(PS & 16) == 0";
                        }
                        else if (assert_field == "axy8")
                        {
                            cond = "(PS & 48) == 48";
                        }
                        else if (assert_field == "axy16")
                        {
                            cond = "(PS & 48) == 32";
                        }
                        else if (assert_field == "jsl")
                        {
                            cond = "jslf == 1";
                        }
                        else if (assert_field == "jsr")
                        {
                            cond = "jslf == 0";
                        }
                        else
                        {
                            cond = assert_field.Replace("_0x", "_$");
                            cond = cond.Replace("_eq_", "==");
                            cond = cond.Replace("_lt_", "<");
                            cond = cond.Replace("_lte_", "<=");
                            cond = cond.Replace("_gt_", ">");
                            cond = cond.Replace("_gte_", ">=");
                            cond = cond.Replace("_ne_", "!=");
                            cond = cond.Replace("_and_", "&&");
                            cond = cond.Replace("_or_", "||");
                            cond = cond.Replace("_not_", "!");
                            cond = cond.Replace("_lbrac_", "(");
                            cond = cond.Replace("_rbrac_", ")");
                            cond = cond.Replace("_", " ");
                        }

                        Breakpoint breakpoint = new Breakpoint();
                        breakpoint.Address     = address;
                        breakpoint.AddressType = BreakpointAddressType.SingleAddress;
                        breakpoint.BreakOnExec = true;
                        breakpoint.CpuType     = CpuType.Cpu;
                        breakpoint.IsAssert    = true;
                        breakpoint.Condition   = "!(" + cond + ")";
                        breakpoints.Add(breakpoint);
                    }
                    else if (parts[0].Contains("WATCH_"))
                    {
                        string[]   watchParts = parts[0].Trim().ToLower().Split('_');
                        Breakpoint breakpoint = new Breakpoint();
                        breakpoint.CpuType     = CpuType.Cpu;
                        breakpoint.IsAssert    = false;
                        breakpoint.Condition   = String.Empty;
                        breakpoint.BreakOnExec = false;
                        int range = 1;
                        for (int i = 1; i < watchParts.Length; ++i)
                        {
                            switch (watchParts[i])
                            {
                            case "load":
                            case "read":
                                breakpoint.BreakOnRead = true;
                                break;

                            case "store":
                            case "write":
                                breakpoint.BreakOnWrite = true;
                                break;

                            case "readwrite":
                            case "writeread":
                            case "loadstore":
                            case "storeload":
                                breakpoint.BreakOnRead  = true;
                                breakpoint.BreakOnWrite = true;
                                break;

                            case "word":
                                range = 2;
                                break;

                            case "long":
                                range = 3;
                                break;
                            }
                        }
                        breakpoint.EndAddress = address - 1;
                        switch (range)
                        {
                        case 1:
                            breakpoint.StartAddress = address - 1;
                            breakpoint.AddressType  = BreakpointAddressType.SingleAddress;
                            break;

                        case 2:
                            breakpoint.StartAddress = address - 2;
                            breakpoint.AddressType  = BreakpointAddressType.AddressRange;
                            break;

                        case 3:
                            breakpoint.StartAddress = address - 3;
                            breakpoint.AddressType  = BreakpointAddressType.AddressRange;
                            break;
                        }
                        breakpoint.Address = breakpoint.StartAddress;
                        breakpoints.Add(breakpoint);
                    }
                    else
                    {
                        CodeLabel label = new CodeLabel();
                        label.Address    = (UInt32)absAddress.Address;
                        label.MemoryType = absAddress.Type;
                        label.Comment    = "";
                        string labelName = parts[0].Trim();
                        if (string.IsNullOrEmpty(labelName) || !LabelManager.LabelRegex.IsMatch(labelName))
                        {
                            errorCount++;
                        }
                        else
                        {
                            label.Label = labelName;
                            labels.Add(label);
                        }
                    }
                }
            }

            LabelManager.SetLabels(labels);
            BreakpointManager.SetBreakpoints(breakpoints);

            if (!silent)
            {
                string message = $"Import completed with {labels.Count} labels imported";
                if (errorCount > 0)
                {
                    message += $" and {errorCount} error(s)";
                }
                MessageBox.Show(message, "Mesen-S", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        private void picPicture_MouseMove(object sender, MouseEventArgs e)
        {
            Point pos = GetCycleScanline(e.Location);

            if (_lastPos == pos)
            {
                return;
            }

            EventViewerDisplayOptions options = ConfigManager.Config.Debug.EventViewer.GetInteropOptions();
            DebugEventInfo            evt     = DebugApi.GetEventViewerEvent((UInt16)pos.Y, (UInt16)pos.X, options);

            if (evt.ProgramCounter == 0xFFFFFFFF)
            {
                ResetTooltip();
                UpdateOverlay(e.Location);
                return;
            }

            Dictionary <string, string> values = new Dictionary <string, string>()
            {
                { "Type", ResourceHelper.GetEnumText(evt.Type) },
                { "Scanline", evt.Scanline.ToString() },
                { "Cycle", evt.Cycle.ToString() },
                { "PC", "$" + evt.ProgramCounter.ToString("X6") },
            };

            switch (evt.Type)
            {
            case DebugEventType.Register:
                bool isWrite = evt.Operation.Type == MemoryOperationType.Write || evt.Operation.Type == MemoryOperationType.DmaWrite;
                bool isDma   = evt.Operation.Type == MemoryOperationType.DmaWrite || evt.Operation.Type == MemoryOperationType.DmaRead;

                CodeLabel label = LabelManager.GetLabel(new AddressInfo()
                {
                    Address = (int)evt.Operation.Address, Type = SnesMemoryType.CpuMemory
                });
                string registerText = "$" + evt.Operation.Address.ToString("X4");
                if (label != null)
                {
                    registerText = label.Label + " (" + registerText + ")";
                }

                values["Register"] = registerText + (isWrite ? " (Write)" : " (Read)") + (isDma ? " (DMA)" : "");
                values["Value"]    = "$" + evt.Operation.Value.ToString("X2");

                if (isDma)
                {
                    bool indirectHdma = false;
                    values["Channel"] = evt.DmaChannel.ToString();
                    if (evt.DmaChannelInfo.InterruptedByHdma != 0)
                    {
                        indirectHdma           = evt.DmaChannelInfo.HdmaIndirectAddressing != 0;
                        values["Channel"]     += indirectHdma ? " (Indirect HDMA)" : " (HDMA)";
                        values["Line Counter"] = "$" + evt.DmaChannelInfo.HdmaLineCounterAndRepeat.ToString("X2");
                    }
                    values["Mode"] = evt.DmaChannelInfo.TransferMode.ToString();

                    int aBusAddress;
                    if (indirectHdma)
                    {
                        aBusAddress = (evt.DmaChannelInfo.SrcBank << 16) | evt.DmaChannelInfo.TransferSize;
                    }
                    else
                    {
                        aBusAddress = (evt.DmaChannelInfo.SrcBank << 16) | evt.DmaChannelInfo.SrcAddress;
                    }

                    if (evt.DmaChannelInfo.InvertDirection == 0)
                    {
                        values["Transfer"] = "$" + aBusAddress.ToString("X4") + " -> $" + evt.DmaChannelInfo.DestAddress.ToString("X2");
                    }
                    else
                    {
                        values["Transfer"] = "$" + aBusAddress.ToString("X4") + " <- $" + evt.DmaChannelInfo.DestAddress.ToString("X2");
                    }
                }
                break;

            case DebugEventType.Breakpoint:
                //TODO

                /*ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
                 * if(debugEvent.BreakpointId >= 0 && debugEvent.BreakpointId < breakpoints.Count) {
                 *      Breakpoint bp = breakpoints[debugEvent.BreakpointId];
                 *      values["BP Type"] = bp.ToReadableType();
                 *      values["BP Addresses"] = bp.GetAddressString(true);
                 *      if(bp.Condition.Length > 0) {
                 *              values["BP Condition"] = bp.Condition;
                 *      }
                 * }*/
                break;
            }

            UpdateOverlay(new Point((int)(evt.Cycle * 2 * this.ImageScale), (int)(evt.Scanline * 2 * this.ImageScale)));

            Form  parentForm = this.FindForm();
            Point location   = parentForm.PointToClient(this.PointToScreen(new Point(e.Location.X - picViewer.ScrollOffsets.X, e.Location.Y - picViewer.ScrollOffsets.Y)));

            BaseForm.GetPopupTooltip(parentForm).SetTooltip(location, values);
        }
Example #16
0
        public static void Import(string path, bool silent = false)
        {
            const int prgBankSize  = 0x4000;
            const int wramBankSize = 0x1000;
            const int sramBankSize = 0x2000;

            List <CodeLabel> labels = new List <CodeLabel>(1000);

            int errorCount = 0;

            foreach (string row in File.ReadAllLines(path, Encoding.UTF8))
            {
                UInt32 address;
                UInt32 bank;
                string labelName;

                if (!GetBankAddressLabel(row, out address, out bank, out labelName))
                {
                    errorCount++;
                    continue;
                }
                else if (labelName == null)
                {
                    //Empty line/comment
                    continue;
                }

                UInt32      fullAddress = 0;
                AddressInfo absAddress;
                if (address <= 0x7FFF)
                {
                    fullAddress = bank * prgBankSize + (address & (prgBankSize - 1));
                    absAddress  = new AddressInfo()
                    {
                        Address = (int)fullAddress, Type = SnesMemoryType.GbPrgRom
                    };
                }
                else if (address >= 0xA000 && address <= 0xCFFF)
                {
                    fullAddress = bank * sramBankSize + (address & (sramBankSize - 1));
                    absAddress  = new AddressInfo()
                    {
                        Address = (int)fullAddress, Type = SnesMemoryType.GbCartRam
                    };
                }
                else if (address >= 0xC000 && address <= 0xDFFF)
                {
                    fullAddress = bank * wramBankSize + (address & (wramBankSize - 1));
                    absAddress  = new AddressInfo()
                    {
                        Address = (int)fullAddress, Type = SnesMemoryType.GbWorkRam
                    };
                }
                else
                {
                    absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo()
                    {
                        Address = (int)address, Type = SnesMemoryType.GameboyMemory
                    });
                }

                if (absAddress.Address >= 0)
                {
                    CodeLabel label = new CodeLabel();
                    label.Address    = (UInt32)absAddress.Address;
                    label.MemoryType = absAddress.Type;
                    label.Comment    = "";
                    label.Label      = labelName;
                    labels.Add(label);
                }
                else
                {
                    errorCount++;
                }
            }

            LabelManager.SetLabels(labels);

            if (!silent)
            {
                string message = $"Import completed with {labels.Count} labels imported";
                if (errorCount > 0)
                {
                    message += $" and {errorCount} error(s)";
                }
                MessageBox.Show(message, "Mesen-S", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Example #17
0
        public static void Import(string path, bool silent = false)
        {
            //This only works reliably for NROM games with 32kb PRG
            DebugState state = new DebugState();

            InteropEmu.DebugGetState(ref state);
            int errorCount = 0;

            bool hasLargePrg = state.Cartridge.PrgRomSize != 0x8000;

            if (!silent && hasLargePrg)
            {
                if (MessageBox.Show($"Warning: Due to .fns file format limitations, imported labels are not reliable for games that have more than 32kb of PRG ROM.\n\nAre you sure you want to import these labels?", "Mesen", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
                {
                    return;
                }
            }
            Dictionary <UInt32, CodeLabel> labels = new Dictionary <uint, CodeLabel>();

            char[] separator = new char[1] {
                '='
            };
            foreach (string row in File.ReadAllLines(path, Encoding.UTF8))
            {
                string[] rowData = row.Split(separator);
                if (rowData.Length < 2)
                {
                    //Invalid row
                    continue;
                }

                uint address;
                if (UInt32.TryParse(rowData[1].Trim().Substring(1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address))
                {
                    string labelName = rowData[0].Trim();
                    if (!LabelManager.LabelRegex.IsMatch(labelName))
                    {
                        //Reject labels that don't respect the label naming restrictions
                        errorCount++;
                        continue;
                    }

                    CodeLabel codeLabel;
                    if (!labels.TryGetValue(address, out codeLabel))
                    {
                        codeLabel             = new CodeLabel();
                        codeLabel.Address     = hasLargePrg ? address : (address - 0x8000);
                        codeLabel.AddressType = hasLargePrg ? AddressType.Register : AddressType.PrgRom;
                        codeLabel.Label       = "";
                        codeLabel.Comment     = "";
                        labels[address]       = codeLabel;
                    }

                    codeLabel.Label = labelName;
                }
                else
                {
                    errorCount++;
                }
            }

            LabelManager.SetLabels(labels.Values);

            if (!silent)
            {
                string message = $"Import completed with {labels.Values.Count} labels imported";
                if (errorCount > 0)
                {
                    message += $" and {errorCount} error(s)";
                }
                MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
 public static void RefreshLabels()
 {
     InteropEmu.DebugDeleteLabels();
     LabelManager.SetLabels(GetLabels(), true);
 }
Example #19
0
        private void OnNotificationReceived(NotificationEventArgs e)
        {
            switch (e.NotificationType)
            {
            case ConsoleNotificationType.GameLoaded: {
                if (_cpuType == CpuType.Sa1)
                {
                    CoprocessorType coprocessor = EmuApi.GetRomInfo().CoprocessorType;
                    if (coprocessor != CoprocessorType.SA1)
                    {
                        this.Invoke((MethodInvoker)(() => {
                                this.Close();
                            }));
                        return;
                    }
                }

                if (ConfigManager.Config.Debug.Debugger.BreakOnPowerCycleReset)
                {
                    DebugApi.Step(_cpuType, 1, StepType.PpuStep);
                }

                BreakpointManager.SetBreakpoints();

                DebugState state = DebugApi.GetState();
                this.BeginInvoke((MethodInvoker)(() => {
                        DebugWorkspaceManager.ImportDbgFile();
                        LabelManager.RefreshLabels();
                        DebugApi.RefreshDisassembly(_cpuType);
                        UpdateDebugger(state, null);
                    }));
                break;
            }

            case ConsoleNotificationType.GameReset:
                if (ConfigManager.Config.Debug.Debugger.BreakOnPowerCycleReset)
                {
                    DebugApi.Step(_cpuType, 1, StepType.PpuStep);
                }
                break;

            case ConsoleNotificationType.PpuFrameDone:
                this.BeginInvoke((MethodInvoker)(() => {
                    UpdateContinueAction();
                }));
                break;

            case ConsoleNotificationType.CodeBreak: {
                BreakEvent evt   = (BreakEvent)Marshal.PtrToStructure(e.Parameter, typeof(BreakEvent));
                DebugState state = DebugApi.GetState();
                int        activeAddress;
                switch (_cpuType)
                {
                case CpuType.Cpu: activeAddress = (int)((state.Cpu.K << 16) | state.Cpu.PC); break;

                case CpuType.Spc: activeAddress = (int)state.Spc.PC; break;

                case CpuType.Sa1: activeAddress = (int)((state.Sa1.K << 16) | state.Sa1.PC); break;

                case CpuType.Gsu: activeAddress = (int)((state.Gsu.ProgramBank << 16) | state.Gsu.R[15]); break;

                default: throw new Exception("Unsupported cpu type");
                }

                this.BeginInvoke((MethodInvoker)(() => {
                        ProcessBreakEvent(evt, state, activeAddress);

                        if (_firstBreak && !ConfigManager.Config.Debug.Debugger.BreakOnOpen)
                        {
                            DebugApi.ResumeExecution();
                        }
                        _firstBreak = false;
                    }));
                break;
            }
            }
        }
Example #20
0
        public static void Import(string path, bool silent = false)
        {
            Dictionary <AddressType, Dictionary <UInt32, CodeLabel> > labels = new Dictionary <AddressType, Dictionary <UInt32, CodeLabel> >()
            {
                { AddressType.InternalRam, new Dictionary <uint, CodeLabel>() },
                { AddressType.PrgRom, new Dictionary <uint, CodeLabel>() },
                { AddressType.Register, new Dictionary <uint, CodeLabel>() },
                { AddressType.SaveRam, new Dictionary <uint, CodeLabel>() },
                { AddressType.WorkRam, new Dictionary <uint, CodeLabel>() }
            };

            DebugImportConfig config = ConfigManager.Config.DebugInfo.ImportConfig;

            int errorCount = 0;

            char[] separator = new char[1] {
                ':'
            };
            foreach (string row in File.ReadAllLines(path, Encoding.UTF8))
            {
                string[] rowData = row.Split(separator, 4);
                if (rowData.Length < 3)
                {
                    //Invalid row
                    continue;
                }
                AddressType type;
                bool        importLabel = false;
                switch (rowData[0][0])
                {
                case 'G': type = AddressType.Register; importLabel = config.MlbImportRegisterLabels; break;

                case 'R': type = AddressType.InternalRam; importLabel = config.MlbImportInternalRamLabels; break;

                case 'P': type = AddressType.PrgRom; importLabel = config.MlbImportPrgRomLabels; break;

                case 'S': type = AddressType.SaveRam; importLabel = config.MlbImportSaveRamLabels; break;

                case 'W': type = AddressType.WorkRam; importLabel = config.MlbImportWorkRamLabels; break;

                default: continue;
                }

                if (importLabel)
                {
                    string addressString = rowData[1];
                    uint   address       = 0;
                    uint   length        = 1;
                    if (addressString.Contains("-"))
                    {
                        uint     addressEnd;
                        string[] addressStartEnd = addressString.Split('-');
                        if (UInt32.TryParse(addressStartEnd[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address) &&
                            UInt32.TryParse(addressStartEnd[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out addressEnd))
                        {
                            if (addressEnd > address)
                            {
                                length = addressEnd - address;
                            }
                            else
                            {
                                //Invalid label (start < end)
                                errorCount++;
                                continue;
                            }
                        }
                        else
                        {
                            //Invalid label (can't parse)
                            errorCount++;
                            continue;
                        }
                    }
                    else
                    {
                        if (!UInt32.TryParse(rowData[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address))
                        {
                            //Invalid label (can't parse)
                            errorCount++;
                            continue;
                        }
                        length = 1;
                    }

                    string labelName = rowData[2];
                    if (!string.IsNullOrEmpty(labelName) && !LabelManager.LabelRegex.IsMatch(labelName))
                    {
                        //Reject labels that don't respect the label naming restrictions
                        errorCount++;
                        continue;
                    }

                    CodeLabel codeLabel;
                    if (!labels[type].TryGetValue(address, out codeLabel))
                    {
                        codeLabel             = new CodeLabel();
                        codeLabel.Address     = address;
                        codeLabel.AddressType = type;
                        codeLabel.Label       = "";
                        codeLabel.Comment     = "";
                        labels[type][address] = codeLabel;
                    }

                    if (rowData.Length > 3 && config.MlbImportComments)
                    {
                        codeLabel.Comment = rowData[3].Replace("\\n", "\n");
                    }
                    codeLabel.Label  = labelName;
                    codeLabel.Length = length;
                }
            }

            int labelCount = 0;

            foreach (KeyValuePair <AddressType, Dictionary <UInt32, CodeLabel> > kvp in labels)
            {
                labelCount += kvp.Value.Values.Count;
            }
            List <CodeLabel> codeLabels = new List <CodeLabel>();

            foreach (KeyValuePair <AddressType, Dictionary <UInt32, CodeLabel> > kvp in labels)
            {
                codeLabels.AddRange(kvp.Value.Values);
            }
            LabelManager.SetLabels(codeLabels);

            if (!silent)
            {
                string message = $"Import completed with {labelCount} labels imported";
                if (errorCount > 0)
                {
                    message += $" and {errorCount} error(s)";
                }
                MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Example #21
0
        public List <string> GetCode(out int byteLength, ref int startAddress, int endAddress = -1)
        {
            _code.InitAssemblerValues();

            List <string> result = new List <string>();

            byteLength = 0;

            if (endAddress == -1)
            {
                //When no end address is specified, find the start of the function based on startAddress
                int address = InteropEmu.DebugFindSubEntryPoint((UInt16)startAddress);
                if (address != -1)
                {
                    startAddress = address;
                }
            }

            for (int i = startAddress; (i <= endAddress || endAddress == -1) && endAddress < 65536;)
            {
                string code;
                if (_code.CodeContent.TryGetValue(i, out code))
                {
                    code = code.Split('\x2')[0].Trim();

                    if (code.StartsWith("--") || code.StartsWith("__"))
                    {
                        //Stop adding code when we find a new section (new function, data blocks, etc.)
                        break;
                    }

                    AddressTypeInfo info = new AddressTypeInfo();
                    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;

                    bool addPadding = true;
                    if (code.StartsWith("STP*") || code.StartsWith("NOP*"))
                    {
                        //Transform unofficial opcodes that can't be reassembled properly into .byte statements
                        if (comment != null)
                        {
                            comment.Insert(0, code + " - ");
                        }
                        else
                        {
                            comment = code;
                        }
                        code       = ".byte " + string.Join(",", _code.CodeByteCode[i].Split(' '));
                        addPadding = false;
                    }

                    if (!string.IsNullOrWhiteSpace(comment) && comment.Contains("\n"))
                    {
                        result.AddRange(comment.Replace("\r", "").Split('\n').Select(cmt => ";" + cmt));
                        comment = null;
                    }
                    if (!string.IsNullOrWhiteSpace(label))
                    {
                        result.Add(label + ":");
                    }
                    result.Add((addPadding ? "  " : "") + code + (!string.IsNullOrWhiteSpace(comment) ? (" ;" + comment) : ""));

                    int length = _code.CodeByteCode[i].Count(c => c == ' ') + 1;
                    byteLength += length;
                    i          += length;

                    if (endAddress == -1 && (string.Compare(code, "RTI", true) == 0 || string.Compare(code, "RTS", true) == 0))
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            result.Add("");
            return(result);
        }
Example #22
0
        public static void Import(string path, bool silent = false)
        {
            Dictionary <AddressType, Dictionary <UInt32, CodeLabel> > labels = new Dictionary <AddressType, Dictionary <UInt32, CodeLabel> >()
            {
                { AddressType.InternalRam, new Dictionary <uint, CodeLabel>() },
                { AddressType.PrgRom, new Dictionary <uint, CodeLabel>() },
                { AddressType.Register, new Dictionary <uint, CodeLabel>() },
                { AddressType.SaveRam, new Dictionary <uint, CodeLabel>() },
                { AddressType.WorkRam, new Dictionary <uint, CodeLabel>() }
            };

            char[] separator = new char[1] {
                ':'
            };
            foreach (string row in File.ReadAllLines(path, Encoding.UTF8))
            {
                string[] rowData = row.Split(separator, 4);
                if (rowData.Length < 3)
                {
                    //Invalid row
                    continue;
                }
                AddressType type;
                switch (rowData[0][0])
                {
                case 'G': type = AddressType.Register; break;

                case 'R': type = AddressType.InternalRam; break;

                case 'P': type = AddressType.PrgRom; break;

                case 'S': type = AddressType.SaveRam; break;

                case 'W': type = AddressType.WorkRam; break;

                default: continue;
                }

                uint address;
                if (UInt32.TryParse(rowData[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address))
                {
                    CodeLabel codeLabel;
                    if (!labels[type].TryGetValue(address, out codeLabel))
                    {
                        codeLabel             = new CodeLabel();
                        codeLabel.Address     = address;
                        codeLabel.AddressType = type;
                        codeLabel.Label       = "";
                        codeLabel.Comment     = "";
                        labels[type][address] = codeLabel;
                    }

                    if (rowData.Length > 3)
                    {
                        codeLabel.Comment = rowData[3].Replace("\\n", "\n");
                    }
                    codeLabel.Label = rowData[2].Replace("\\n", "\n").Replace("\n", "");
                }
            }

            int labelCount = 0;

            foreach (KeyValuePair <AddressType, Dictionary <UInt32, CodeLabel> > kvp in labels)
            {
                LabelManager.SetLabels(kvp.Value.Values);
                labelCount += kvp.Value.Values.Count;
            }

            if (!silent)
            {
                MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Example #23
0
        public static void SetDefaultLabels(int mapperId)
        {
            bool   disableBuiltInWorkspace       = false;
            bool   disableBuiltInMapperWorkspace = false;
            string prefix = "DefaultLabels.";
            string defaultWorkspaceMlbFile = Path.Combine(ConfigManager.DebuggerFolder, prefix + "Global.mlb");

            if (File.Exists(defaultWorkspaceMlbFile))
            {
                MesenLabelFile.Import(defaultWorkspaceMlbFile, true);
                disableBuiltInWorkspace = true;
            }

            string mapperName = mapperId.ToString();

            if (mapperId == FdsMapperID)
            {
                mapperName = "FDS";
            }
            else if (mapperId == NsfMapperID)
            {
                mapperName = "NSF";
            }

            string defaultWorkspaceMapperMlbFile = Path.Combine(ConfigManager.DebuggerFolder, prefix + mapperName + ".mlb");

            if (File.Exists(defaultWorkspaceMapperMlbFile))
            {
                MesenLabelFile.Import(defaultWorkspaceMapperMlbFile, true);
                disableBuiltInMapperWorkspace = true;
            }

            if (!disableBuiltInWorkspace)
            {
                LabelManager.SetLabel(0x2000, AddressType.Register, "PpuControl_2000", $"7  bit  0{Environment.NewLine}---- ----{Environment.NewLine}VPHB SINN{Environment.NewLine}|||| ||||{Environment.NewLine}|||| ||++- Base nametable address{Environment.NewLine}|||| ||    (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00){Environment.NewLine}|||| |+--- VRAM address increment per CPU read/write of PPUDATA{Environment.NewLine}|||| |     (0: add 1, going across; 1: add 32, going down){Environment.NewLine}|||| +---- Sprite pattern table address for 8x8 sprites{Environment.NewLine}||||       (0: $0000; 1: $1000; ignored in 8x16 mode){Environment.NewLine}|||+------ Background pattern table address (0: $0000; 1: $1000){Environment.NewLine}||+------- Sprite size (0: 8x8; 1: 8x16){Environment.NewLine}|+-------- PPU master/slave select{Environment.NewLine}|          (0: read backdrop from EXT pins; 1: output color on EXT pins){Environment.NewLine}+--------- Generate an NMI at the start of the{Environment.NewLine}           vertical blanking interval (0: off; 1: on)", false);
                LabelManager.SetLabel(0x2001, AddressType.Register, "PpuMask_2001", $"7  bit  0{Environment.NewLine}---- ----{Environment.NewLine}BGRs bMmG{Environment.NewLine}|||| ||||{Environment.NewLine}|||| |||+- Display type: (0: color, 1: grayscale){Environment.NewLine}|||| ||+-- 1: Show background in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| |+--- 1: Show sprites in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| +---- 1: Show background{Environment.NewLine}|||+------ 1: Show sprites{Environment.NewLine}||+------- Emphasize red{Environment.NewLine}|+-------- Emphasize green{Environment.NewLine}+--------- Emphasize blue", false);
                LabelManager.SetLabel(0x2002, AddressType.Register, "PpuStatus_2002", $"7  bit  0{Environment.NewLine}---- ----{Environment.NewLine}VSO. ....{Environment.NewLine}|||| ||||{Environment.NewLine}|||+-++++- Least significant bits previously written into a PPU register{Environment.NewLine}|||        (due to register not being updated for this address){Environment.NewLine}||+------- Sprite overflow. The intent was for this flag to be set{Environment.NewLine}||         whenever more than eight sprites appear on a scanline, but a{Environment.NewLine}||         hardware bug causes the actual behavior to be more complicated{Environment.NewLine}||         and generate false positives as well as false negatives; see{Environment.NewLine}||         PPU sprite evaluation. This flag is set during sprite{Environment.NewLine}||         evaluation and cleared at dot 1 (the second dot) of the{Environment.NewLine}||         pre-render line.{Environment.NewLine}|+-------- Sprite 0 Hit.  Set when a nonzero pixel of sprite 0 overlaps{Environment.NewLine}|          a nonzero background pixel; cleared at dot 1 of the pre-render{Environment.NewLine}|          line.  Used for raster timing.{Environment.NewLine}+--------- Vertical blank has started (0: not in vblank; 1: in vblank).{Environment.NewLine}           Set at dot 1 of line 241 (the line *after* the post-render{Environment.NewLine}           line, false); cleared after reading $2002 and at dot 1 of the{Environment.NewLine}           pre-render line.", false);
                LabelManager.SetLabel(0x2003, AddressType.Register, "OamAddr_2003", "Set OAM address - Write only", false);
                LabelManager.SetLabel(0x2004, AddressType.Register, "OamData_2004", "Read/Write OAM data", false);
                LabelManager.SetLabel(0x2005, AddressType.Register, "PpuScroll_2005", "Set PPU scroll, write twice - Write only", false);
                LabelManager.SetLabel(0x2006, AddressType.Register, "PpuAddr_2006", "Set PPU address, write twice - Write only", false);
                LabelManager.SetLabel(0x2007, AddressType.Register, "PpuData_2007", "Read/Write VRAM", false);

                LabelManager.SetLabel(0x4000, AddressType.Register, "Sq0Duty_4000", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
                LabelManager.SetLabel(0x4001, AddressType.Register, "Sq0Sweep_4001", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)", false);
                LabelManager.SetLabel(0x4002, AddressType.Register, "Sq0Timer_4002", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
                LabelManager.SetLabel(0x4003, AddressType.Register, "Sq0Length_4003", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);

                LabelManager.SetLabel(0x4004, AddressType.Register, "Sq1Duty_4004", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
                LabelManager.SetLabel(0x4005, AddressType.Register, "Sq1Sweep_4005", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)", false);
                LabelManager.SetLabel(0x4006, AddressType.Register, "Sq1Timer_4006", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
                LabelManager.SetLabel(0x4007, AddressType.Register, "Sq1Length_4007", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);

                LabelManager.SetLabel(0x4008, AddressType.Register, "TrgLinear_4008", $"CRRR RRRR{Environment.NewLine}Length counter halt / linear counter control (C), linear counter load (R)", false);
                LabelManager.SetLabel(0x400A, AddressType.Register, "TrgTimer_400A", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
                LabelManager.SetLabel(0x400B, AddressType.Register, "TrgLength_400B", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);

                LabelManager.SetLabel(0x400C, AddressType.Register, "NoiseVolume_400C", $"--LC VVVV{Environment.NewLine}Envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
                LabelManager.SetLabel(0x400E, AddressType.Register, "NoisePeriod_400E", $"L--- PPPP{Environment.NewLine}Loop noise (L), noise period (P)", false);
                LabelManager.SetLabel(0x400F, AddressType.Register, "NoiseLength_400F", $"LLLL L---{Environment.NewLine}Length counter load (L)", false);

                LabelManager.SetLabel(0x4010, AddressType.Register, "DmcFreq_4010", $"IL-- RRRR{Environment.NewLine}IRQ enable (I), loop (L), frequency (R)", false);
                LabelManager.SetLabel(0x4011, AddressType.Register, "DmcCounter_4011", $"-DDD DDDD{Environment.NewLine}Load counter (D)", false);
                LabelManager.SetLabel(0x4012, AddressType.Register, "DmcAddress_4012", $"AAAA AAAA{Environment.NewLine}Sample address (A)", false);
                LabelManager.SetLabel(0x4013, AddressType.Register, "DmcLength_4013", $"LLLL LLLL{Environment.NewLine}Sample length (L)", false);

                LabelManager.SetLabel(0x4014, AddressType.Register, "SpriteDma_4014", "Writing $XX will upload 256 bytes of data from CPU page $XX00-$XXFF to the internal PPU OAM.", false);

                LabelManager.SetLabel(0x4015, AddressType.Register, "ApuStatus_4015", $"Read:{Environment.NewLine}IF-D NT21{Environment.NewLine}DMC interrupt (I), frame interrupt (F), DMC active (D), length counter > 0 (N/T/2/1){Environment.NewLine + Environment.NewLine}Write:{Environment.NewLine}---D NT21{Environment.NewLine}Enable DMC (D), noise (N), triangle (T), and pulse channels (2/1)", false);

                LabelManager.SetLabel(0x4016, AddressType.Register, "Ctrl1_4016", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #1.{Environment.NewLine}{Environment.NewLine}Write:{Environment.NewLine}---- ---A{Environment.NewLine}Output data (strobe) to both controllers.", false);
                LabelManager.SetLabel(0x4017, AddressType.Register, "Ctrl2_FrameCtr_4017", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #2.{Environment.NewLine}{Environment.NewLine}Write (Frame counter): MI-- ----{Environment.NewLine}Mode (M, 0 = 4-step, 1 = 5-step), IRQ inhibit flag (I)", false);
            }

            if (!disableBuiltInMapperWorkspace && mapperId == FdsMapperID)
            {
                LabelManager.SetLabel(0x01F8, AddressType.PrgRom, "LoadFiles", "Input: Pointer to Disk ID, Pointer to File List" + Environment.NewLine + "Output: A = error #, Y = # of files loaded" + Environment.NewLine + "Desc: Loads files specified by DiskID into memory from disk. Load addresses are decided by the file's header.", false);
                LabelManager.SetLabel(0x0237, AddressType.PrgRom, "AppendFile", "Input: Pointer to Disk ID, Pointer to File Header" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Appends the file data given by DiskID to the disk. This means that the file is tacked onto the end of the disk, and the disk file count is incremented. The file is then read back to verify the write. If an error occurs during verification, the disk's file count is decremented (logically hiding the written file).", false);
                LabelManager.SetLabel(0x0239, AddressType.PrgRom, "WriteFile", "Input: Pointer to Disk ID, Pointer to File Header, A = file #" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Same as \"Append File\", but instead of writing the file to the end of the disk, A specifies the sequential position on the disk to write the file (0 is the first). This also has the effect of setting the disk's file count to the A value, therefore logically hiding any other files that may reside after the written one.", false);
                LabelManager.SetLabel(0x02B7, AddressType.PrgRom, "CheckFileCount", "Input: Pointer to Disk ID, A = # to set file count to" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, compares it to A, then sets the disk's file count to A.", false);
                LabelManager.SetLabel(0x02BB, AddressType.PrgRom, "AdjustFileCount", "Input: Pointer to Disk ID, A = number to reduce current file count by" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, decrements it by A, then writes the new value back.", false);
                LabelManager.SetLabel(0x0301, AddressType.PrgRom, "SetFileCount1", "Input: Pointer to Disk ID, A = file count minus one = # of the last file" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A + 1", false);
                LabelManager.SetLabel(0x0305, AddressType.PrgRom, "SetFileCount", "Input: Pointer to Disk ID, A = file count" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A", false);
                LabelManager.SetLabel(0x032A, AddressType.PrgRom, "GetDiskInfo", "Input: Pointer to Disk Info" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Fills DiskInfo up with data read off the current disk.", false);

                LabelManager.SetLabel(0x0445, AddressType.PrgRom, "CheckDiskHeader", "Input: Pointer to 10 byte string at $00 " + Environment.NewLine + "Output:  " + Environment.NewLine + "Desc: Compares the first 10 bytes on the disk coming after the FDS string, to 10 bytes pointed to by Ptr($00). To bypass the checking of any byte, a -1 can be placed in the equivelant place in the compare string.  Otherwise, if the comparison fails, an appropriate error will be generated.", false);
                LabelManager.SetLabel(0x0484, AddressType.PrgRom, "GetNumFiles", "Input:  " + Environment.NewLine + "Output:  " + Environment.NewLine + "Desc: Reads number of files stored on disk, stores the result in $06", false);
                LabelManager.SetLabel(0x0492, AddressType.PrgRom, "SetNumFiles", "Input:  " + Environment.NewLine + "Output: A = number of files " + Environment.NewLine + "Desc: Writes new number of files to disk header.", false);
                LabelManager.SetLabel(0x04A0, AddressType.PrgRom, "FileMatchTest", "Input: Pointer to FileID list at $02 " + Environment.NewLine + "Output:   " + Environment.NewLine + "Desc: Uses a byte string pointed at by Ptr($02) to tell the disk system which files to load.  The file ID's number is searched for in the string.  If an exact match is found, [$09] is 0'd, and [$0E] is incremented.  If no matches are found after 20 bytes, or a -1 entry is encountered, [$09] is set to -1.  If the first byte in the string is -1, the BootID number is used for matching files (any FileID that is not greater than the BootID qualifies as a match).", false);
                LabelManager.SetLabel(0x04DA, AddressType.PrgRom, "SkipFiles", "Input: Number of files to skip in $06 " + Environment.NewLine + "Output:  " + Environment.NewLine + "Desc: Skips over specified number of files.", false);

                LabelManager.SetLabel(0x0149, AddressType.PrgRom, "Delay132", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: 132 clock cycle delay", false);
                LabelManager.SetLabel(0x0153, AddressType.PrgRom, "Delayms", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: X, Y " + Environment.NewLine + "Desc: Delay routine, Y = delay in ms (approximate)", false);
                LabelManager.SetLabel(0x0161, AddressType.PrgRom, "DisPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites and background", false);
                LabelManager.SetLabel(0x016B, AddressType.PrgRom, "EnPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites and background", false);
                LabelManager.SetLabel(0x0171, AddressType.PrgRom, "DisObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites", false);
                LabelManager.SetLabel(0x0178, AddressType.PrgRom, "EnObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites", false);
                LabelManager.SetLabel(0x017E, AddressType.PrgRom, "DisPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable background", false);
                LabelManager.SetLabel(0x0185, AddressType.PrgRom, "EnPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable background", false);
                LabelManager.SetLabel(0x01B2, AddressType.PrgRom, "VINTWait", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: $ff " + Environment.NewLine + "Desc: Wait until next VBlank NMI fires, and return (for programs that does it the \"everything in main\" way). NMI vector selection at $100 is preserved, but further VBlanks are disabled.", false);
                LabelManager.SetLabel(0x07BB, AddressType.PrgRom, "VRAMStructWrite", "Input: Pointer to VRAM buffer to be written " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $ff " + Environment.NewLine + "Desc: Set VRAM increment to 1 (clear [[PPUCTRL]]/$ff bit 2), and write a VRAM buffer to VRAM. Read below for information on the structure.", false);
                LabelManager.SetLabel(0x0844, AddressType.PrgRom, "FetchDirectPtr", "Input: " + Environment.NewLine + "Output: $00, $01 = pointer fetched " + Environment.NewLine + "Affects: A, X, Y, $05, $06 " + Environment.NewLine + "Desc: Fetch a direct pointer from the stack (the pointer should be placed after the return address of the routine that calls this one (see \"important notes\" above)), save the pointer at ($00) and fix the return address.", false);
                LabelManager.SetLabel(0x086A, AddressType.PrgRom, "WriteVRAMBuffer", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $301, $302 " + Environment.NewLine + "Desc: Write the VRAM Buffer at $302 to VRAM. Read below for information on the structure.", false);
                LabelManager.SetLabel(0x08B3, AddressType.PrgRom, "ReadVRAMBuffer", "Input: X = start address of read buffer, Y = # of bytes to read " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: Read individual bytes from VRAM to the VRAMBuffer. (see notes below)", false);
                LabelManager.SetLabel(0x08D2, AddressType.PrgRom, "PrepareVRAMString", "Input: A = High VRAM address, X = Low VRAM address, Y = string length, Direct Pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : string didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies pointed data into the VRAM buffer.", false);
                LabelManager.SetLabel(0x08E1, AddressType.PrgRom, "PrepareVRAMStrings", "Input: A = High VRAM address, X = Low VRAM address, Direct pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : data didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies a 2D string into the VRAM buffer. The first byte of the data determines the width and height of the following string (in tiles): Upper nybble = height, lower nybble = width.", false);
                LabelManager.SetLabel(0x094F, AddressType.PrgRom, "GetVRAMBufferByte", "Input: X = starting index of read buffer, Y = # of address to compare (starting at 1), $00, $01 = address to read from " + Environment.NewLine + "Output: carry clear : a previously read byte was returned, carry set : no byte was read, should wait next call to ReadVRAMBuffer " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: This routine was likely planned to be used in order to avoid useless latency on a VRAM reads (see notes below). It compares the VRAM address in ($00) with the Yth (starting at 1) address of the read buffer. If both addresses match, the corresponding data byte is returned exit with c clear. If the addresses are different, the buffer address is overwritten by the address in ($00) and the routine exit with c set.", false);
                LabelManager.SetLabel(0x097D, AddressType.PrgRom, "Pixel2NamConv", "Input: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Output: $00 = High nametable address, $01 = Low nametable address " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert pixel screen coordinates to corresponding nametable address (assumes no scrolling, and points to first nametable at $2000-$23ff).", false);
                LabelManager.SetLabel(0x0997, AddressType.PrgRom, "Nam2PixelConv", "Input: $00 = High nametable address, $01 = low nametable address " + Environment.NewLine + "Output: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert a nametable address to corresponding pixel coordinates (assume no scrolling).", false);
                LabelManager.SetLabel(0x09B1, AddressType.PrgRom, "Random", "Input: X = Zero Page address where the random bytes are placed, Y = # of shift register bytes (normally $02) " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00 " + Environment.NewLine + "Desc: This is a shift-register based random number generator, normally takes 2 bytes (using more won't affect random sequence). On reset you are supposed to write some non-zero values here (BIOS uses writes $d0, $d0), and call this routine several times before the data is actually random. Each call of this routine will shift the bytes ''right''.", false);
                LabelManager.SetLabel(0x09C8, AddressType.PrgRom, "SpriteDMA", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine does sprite DMA from RAM $200-$2ff", false);
                LabelManager.SetLabel(0x09D3, AddressType.PrgRom, "CounterLogic", "Input: A, Y = end Zeropage address of counters, X = start zeropage address of counters " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00 " + Environment.NewLine + "Desc: This decrements several counters in Zeropage. The first counter is a decimal counter 9 -> 8 -> 7 -> ... -> 1 -> 0 -> 9 -> ... Counters 1...A are simply decremented and stays at 0. Counters A+1...Y are decremented when the first counter does a 0 -> 9 transition, and stays at 0.", false);
                LabelManager.SetLabel(0x09EB, AddressType.PrgRom, "ReadPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 data, $f6 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01, " + Environment.NewLine + "Desc: This read hardwired famicom joypads.", false);
                LabelManager.SetLabel(0x0A1A, AddressType.PrgRom, "ReadDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired famicom joypads, and detect up->down button transitions", false);
                LabelManager.SetLabel(0x0A1F, AddressType.PrgRom, "ReadOrDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions.", false);
                LabelManager.SetLabel(0x0A36, AddressType.PrgRom, "ReadDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired Famicom joypads, and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.", false);
                LabelManager.SetLabel(0x0A4C, AddressType.PrgRom, "ReadOrDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.", false);
                LabelManager.SetLabel(0x0A68, AddressType.PrgRom, "ReadDownExpPads", "Input: $f1-$f4 = up->down transitions, $f5-$f8 = Joypad data in the order : Pad1, Pad2, Expansion1, Expansion2 " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypad, but stores their data separately instead of ORing them together like the other routines does. This routine is NOT DMC fortified.", false);
                LabelManager.SetLabel(0x0A84, AddressType.PrgRom, "VRAMFill", "Input: A = High VRAM Address (aka tile row #), X = Fill value, Y = # of tile rows OR attribute fill data " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02 " + Environment.NewLine + "Desc: This routine does 2 things : If A < $20, it fills pattern table data with the value in X for 16 * Y tiles. If A >= $20, it fills the corresponding nametable with the value in X and attribute table with the value in Y.", false);
                LabelManager.SetLabel(0x0Ad2, AddressType.PrgRom, "MemFill", "Input: A = fill value, X = first page #, Y = last page # " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: This routines fills RAM pages with specified value.", false);
                LabelManager.SetLabel(0x0AEA, AddressType.PrgRom, "SetScroll", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine set scroll registers according to values in $fc, $fd and $ff. Should typically be called in VBlank after VRAM updates", false);
                LabelManager.SetLabel(0x0AFD, AddressType.PrgRom, "JumpEngine", "Input: A = Jump table entry " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: The instruction calling this is supposed to be followed by a jump table (16-bit pointers little endian, up to 128 pointers). A is the entry # to jump to, return address on stack is used to get jump table entries.", false);
                LabelManager.SetLabel(0x0B13, AddressType.PrgRom, "ReadKeyboard", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: Read Family Basic Keyboard expansion (detail is under analysis)", false);
                LabelManager.SetLabel(0x0B66, AddressType.PrgRom, "LoadTileset", "Input: A = Low VRAM Address & Flags, Y = Hi VRAM Address, X = # of tiles to transfer to/from VRAM " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04 " + Environment.NewLine + "Desc: This routine can read and write 2BP and 1BP tilesets to/from VRAM. See appendix below about the flags.", false);
                LabelManager.SetLabel(0x0C22, AddressType.PrgRom, "unk_EC22", "Some kind of logic that some games use. (detail is under analysis)", false);
            }
        }
        private void picPicture_MouseMove(object sender, MouseEventArgs e)
        {
            DebugEventInfo?result = GetEventAtPosition(e.Location);

            if (result == null)
            {
                ResetTooltip();
                UpdateOverlay(e.Location);
                return;
            }

            DebugEventInfo evt    = result.Value;
            Point          newPos = new Point(evt.Cycle, evt.Scanline);

            if (_lastPos == newPos)
            {
                return;
            }

            Dictionary <string, string> values;

            if (this.CpuType == CpuType.Gameboy)
            {
                values = new Dictionary <string, string>()
                {
                    { "Type", ResourceHelper.GetEnumText(evt.Type) },
                    { "Scanline", evt.Scanline.ToString() },
                    { "Cycle", evt.Cycle.ToString() },
                    { "PC", "$" + evt.ProgramCounter.ToString("X4") },
                };
            }
            else
            {
                values = new Dictionary <string, string>()
                {
                    { "Type", ResourceHelper.GetEnumText(evt.Type) },
                    { "Scanline", evt.Scanline.ToString() },
                    { "H-Clock", evt.Cycle.ToString() + " (" + GetCycle(evt.Cycle) + ")" },
                    { "PC", "$" + evt.ProgramCounter.ToString("X6") },
                };
            }

            switch (evt.Type)
            {
            case DebugEventType.Register:
                bool isWrite = evt.Operation.Type == MemoryOperationType.Write || evt.Operation.Type == MemoryOperationType.DmaWrite;
                bool isDma   = evt.Operation.Type == MemoryOperationType.DmaWrite || evt.Operation.Type == MemoryOperationType.DmaRead;

                CodeLabel label = LabelManager.GetLabel(new AddressInfo()
                {
                    Address = (int)evt.Operation.Address, Type = SnesMemoryType.CpuMemory
                });
                string registerText = "$" + evt.Operation.Address.ToString("X4");
                if (label != null)
                {
                    registerText = label.Label + " (" + registerText + ")";
                }

                values["Register"] = registerText + (isWrite ? " (Write)" : " (Read)") + (isDma ? " (DMA)" : "");
                values["Value"]    = "$" + evt.Operation.Value.ToString("X2");

                if (isDma && this.CpuType != CpuType.Gameboy)
                {
                    bool indirectHdma = false;
                    values["Channel"] = (evt.DmaChannel & 0x07).ToString();

                    if ((evt.DmaChannel & ctrlEventViewerPpuView.HdmaChannelFlag) != 0)
                    {
                        indirectHdma           = evt.DmaChannelInfo.HdmaIndirectAddressing;
                        values["Channel"]     += indirectHdma ? " (Indirect HDMA)" : " (HDMA)";
                        values["Line Counter"] = "$" + evt.DmaChannelInfo.HdmaLineCounterAndRepeat.ToString("X2");
                    }

                    values["Mode"] = evt.DmaChannelInfo.TransferMode.ToString();

                    int aBusAddress;
                    if (indirectHdma)
                    {
                        aBusAddress = (evt.DmaChannelInfo.SrcBank << 16) | evt.DmaChannelInfo.TransferSize;
                    }
                    else
                    {
                        aBusAddress = (evt.DmaChannelInfo.SrcBank << 16) | evt.DmaChannelInfo.SrcAddress;
                    }

                    if (!evt.DmaChannelInfo.InvertDirection)
                    {
                        values["Transfer"] = "$" + aBusAddress.ToString("X4") + " -> $" + evt.DmaChannelInfo.DestAddress.ToString("X2");
                    }
                    else
                    {
                        values["Transfer"] = "$" + aBusAddress.ToString("X4") + " <- $" + evt.DmaChannelInfo.DestAddress.ToString("X2");
                    }
                }
                break;

            case DebugEventType.Breakpoint:
                ReadOnlyCollection <Breakpoint> breakpoints = BreakpointManager.Breakpoints;
                if (evt.BreakpointId >= 0 && evt.BreakpointId < breakpoints.Count)
                {
                    Breakpoint bp = breakpoints[evt.BreakpointId];
                    values["CPU Type"]     = ResourceHelper.GetEnumText(bp.CpuType);
                    values["BP Type"]      = bp.ToReadableType();
                    values["BP Addresses"] = bp.GetAddressString(true);
                    if (bp.Condition.Length > 0)
                    {
                        values["BP Condition"] = bp.Condition;
                    }
                }
                break;
            }

            UpdateOverlay(new Point((int)(evt.Cycle / _xRatio * this.ImageScale), (int)(evt.Scanline * 2 * this.ImageScale)));

            Form  parentForm = this.FindForm();
            Point location   = parentForm.PointToClient(Control.MousePosition);

            BaseForm.GetPopupTooltip(parentForm).SetTooltip(location, values);
        }
Example #25
0
        public void Prepare(long firstByteIndex, long lastByteIndex)
        {
            int visibleByteCount = (int)(lastByteIndex - firstByteIndex + 1);

            if (_highlightBreakpoints)
            {
                Breakpoint[] breakpoints = BreakpointManager.Breakpoints.ToArray();
                _breakpointTypes = new BreakpointTypeFlags[visibleByteCount];

                for (int i = 0; i < visibleByteCount; i++)
                {
                    int byteIndex = i + (int)firstByteIndex;
                    foreach (Breakpoint bp in breakpoints)
                    {
                        if (bp.Enabled && bp.Matches((uint)byteIndex, _memoryType, null))
                        {
                            _breakpointTypes[i] = bp.BreakOnExec ? BreakpointTypeFlags.Execute : (bp.BreakOnWrite ? BreakpointTypeFlags.Write : BreakpointTypeFlags.Read);
                            break;
                        }
                    }
                }
            }
            else
            {
                _breakpointTypes = null;
            }

            _counters = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);

            _cdlData = null;
            if (_highlightDataBytes || _highlightCodeBytes)
            {
                switch (_memoryType)
                {
                case SnesMemoryType.CpuMemory:
                case SnesMemoryType.Sa1Memory:
                case SnesMemoryType.Cx4Memory:
                case SnesMemoryType.GsuMemory:
                case SnesMemoryType.GameboyMemory:
                case SnesMemoryType.PrgRom:
                case SnesMemoryType.GbPrgRom:
                    _cdlData = DebugApi.GetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
                    break;
                }
            }

            _hasLabel = new bool[visibleByteCount];
            if (_highlightLabelledBytes)
            {
                if (_memoryType <= SnesMemoryType.SpcMemory)
                {
                    AddressInfo addr = new AddressInfo();
                    addr.Type = _memoryType;
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        addr.Address = (int)(firstByteIndex + i);
                        _hasLabel[i] = !string.IsNullOrWhiteSpace(LabelManager.GetLabel(addr)?.Label);
                    }
                }
                else if (_memoryType == SnesMemoryType.PrgRom || _memoryType == SnesMemoryType.WorkRam || _memoryType == SnesMemoryType.SaveRam)
                {
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        _hasLabel[i] = !string.IsNullOrWhiteSpace(LabelManager.GetLabel((uint)(firstByteIndex + i), _memoryType)?.Label);
                    }
                }
            }

            _state = DebugApi.GetState();
        }
Example #26
0
        public void Prepare(long firstByteIndex, long lastByteIndex)
        {
            int visibleByteCount = (int)(lastByteIndex - firstByteIndex + 1);

            if (_highlightBreakpoints)
            {
                Breakpoint[] breakpoints = BreakpointManager.Breakpoints.ToArray();
                _breakpointTypes = new BreakpointType[visibleByteCount];

                for (int i = 0; i < visibleByteCount; i++)
                {
                    int byteIndex = i + (int)firstByteIndex;
                    foreach (Breakpoint bp in breakpoints)
                    {
                        if (bp.Enabled && bp.IsCpuBreakpoint && bp.Matches(byteIndex, _memoryType))
                        {
                            _breakpointTypes[i] = bp.BreakOnExec ? BreakpointType.Execute : (bp.BreakOnWrite ? BreakpointType.WriteRam : BreakpointType.ReadRam);
                            break;
                        }
                    }
                }
            }
            else
            {
                _breakpointTypes = null;
            }

            _counts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
            if (_memoryType == DebugMemoryType.CpuMemory)
            {
                _freezeState = InteropEmu.DebugGetFreezeState((UInt16)firstByteIndex, (UInt16)visibleByteCount);
            }

            _cdlData = null;
            if (_highlightDmcDataBytes || _highlightDataBytes || _highlightCodeBytes)
            {
                switch (_memoryType)
                {
                case DebugMemoryType.ChrRom:
                case DebugMemoryType.PpuMemory:
                case DebugMemoryType.CpuMemory:
                case DebugMemoryType.PrgRom:
                    _cdlData = InteropEmu.DebugGetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
                    break;
                }
            }

            _hasLabel = new ByteLabelState[visibleByteCount];
            if (_highlightLabelledBytes)
            {
                if (_memoryType == DebugMemoryType.CpuMemory)
                {
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        UInt16    addr  = (UInt16)(i + firstByteIndex);
                        CodeLabel label = LabelManager.GetLabel(addr);
                        if (label == null)
                        {
                            label = LabelManager.GetLabel(addr, AddressType.Register);
                        }

                        if (label != null && !string.IsNullOrWhiteSpace(label.Label))
                        {
                            if (label.Length > 1)
                            {
                                int relAddress = label.GetRelativeAddress();
                                _hasLabel[i] = relAddress == addr ? ByteLabelState.LabelFirstByte : ByteLabelState.LabelExtraByte;
                            }
                            else
                            {
                                _hasLabel[i] = ByteLabelState.LabelFirstByte;
                            }
                        }
                    }
                }
                else if (_memoryType == DebugMemoryType.PrgRom || _memoryType == DebugMemoryType.WorkRam || _memoryType == DebugMemoryType.SaveRam)
                {
                    for (long i = 0; i < _hasLabel.Length; i++)
                    {
                        UInt32    addr  = (UInt32)(i + firstByteIndex);
                        CodeLabel label = LabelManager.GetLabel(addr, _memoryType.ToAddressType());
                        if (label != null && !string.IsNullOrWhiteSpace(label.Label))
                        {
                            _hasLabel[i] = label.Length == 1 || label.Address == addr ? ByteLabelState.LabelFirstByte : ByteLabelState.LabelExtraByte;
                        }
                    }
                }
            }

            InteropEmu.DebugGetState(ref _state);
        }