diff --git a/Z80/Disassembler.cs b/Z80/Disassembler.cs index e233f2b..2a619ae 100644 --- a/Z80/Disassembler.cs +++ b/Z80/Disassembler.cs @@ -6,9 +6,12 @@ namespace Z80 { using EightBit; using System.Globalization; + using System.Diagnostics; - public class Disassembler(Bus bus) + public class Disassembler(Bus bus, Labels labels) { + private readonly Labels _labels = labels; + private bool _prefixCB; private bool _prefixDD; private bool _prefixED; @@ -69,6 +72,11 @@ namespace Z80 + $"{(cpu.INT.Lowered() ? "I" : "-")}"; } + public Disassembler(Bus bus) + : this(bus, new Labels()) + { + } + public string Disassemble(Z80 cpu) { ArgumentNullException.ThrowIfNull(cpu); @@ -158,6 +166,13 @@ namespace Z80 if (outputFormatSpecification) { output += '\t'; + + if (this._labels.Lookup(pc, out var label)) + { + Debug.Assert(label is not null); + output += $"{label}: "; + } + output += string.Format(CultureInfo.InvariantCulture, specification, (int)immediate, (int)absolute, relative, (int)displacement, indexedImmediate); } diff --git a/Z80/Labels.cs b/Z80/Labels.cs new file mode 100644 index 0000000..99c0786 --- /dev/null +++ b/Z80/Labels.cs @@ -0,0 +1,60 @@ +namespace Z80 +{ + using System.Diagnostics; + using System.Globalization; + using System.Collections.Generic; + + public class Labels(EightBit.ILogger logger) + { + private readonly EightBit.ILogger _logger = logger; + private readonly Dictionary _symbols = []; // Address to symbol lookup + + public Dictionary Symbols => this._symbols; + + public Labels() + : this(new EightBit.ConsoleLogger()) + {} + + public bool Lookup(ushort address, out string? label) => this.Symbols.TryGetValue(address, out label); + + public void Parse(string path) + { + this._logger.Inform($"Labels: reading {path}"); + using var reader = new StreamReader(path); + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + this.ParseLine(line); + } + } + + private void ParseLine(string? line) + { + if (string.IsNullOrEmpty(line)) + { + this._logger.Debug($"Ignoring empty line"); + return; + } + this._logger.Debug($"Parsing: {line}"); + var elements = line.Split(' ', '\t'); + Debug.Assert(elements is not null); + if (elements.Length != 2) + { + this._logger.Debug("Ignoring invalid line"); + return; + } + + if (!ushort.TryParse(elements[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var address)) + { + this._logger.Debug($"First element ({elements[0]}), cannot be parsed as a hexadecimal number"); + return; + } + + var label = elements[1]; + if (!this.Symbols.TryAdd(address, label)) + { + this._logger.Debug($"Label {label}, has already been used"); + } + } + } +}