mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-02-02 12:30:58 +00:00
Transition entirely to new symbols framework and wire profiler.
This commit is contained in:
parent
81e9068310
commit
93e1e903f6
@ -7,11 +7,11 @@ namespace EightBit
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
public class Disassembler(Bus bus, M6502 processor, Symbols symbols)
|
public class Disassembler(Bus bus, M6502 processor, Files.Symbols.Parser symbols)
|
||||||
{
|
{
|
||||||
private readonly Bus bus = bus;
|
private readonly Bus bus = bus;
|
||||||
private readonly M6502 processor = processor;
|
private readonly M6502 processor = processor;
|
||||||
private readonly Symbols symbols = symbols;
|
private readonly Files.Symbols.Parser symbols = symbols;
|
||||||
private ushort address;
|
private ushort address;
|
||||||
|
|
||||||
public static string DumpFlags(byte value)
|
public static string DumpFlags(byte value)
|
||||||
@ -59,55 +59,6 @@ namespace EightBit
|
|||||||
switch (bbb)
|
switch (bbb)
|
||||||
{
|
{
|
||||||
case 0b000: // BRK
|
case 0b000: // BRK
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.Append(this.Disassemble_Implied("BRK"));
|
output.Append(this.Disassemble_Implied("BRK"));
|
||||||
break;
|
break;
|
||||||
case 0b001: // DOP/NOP (0x04)
|
case 0b001: // DOP/NOP (0x04)
|
||||||
@ -552,23 +503,19 @@ namespace EightBit
|
|||||||
|
|
||||||
private string ConvertZPAddress(byte absolute) => this.TryGetLabel(absolute, out var label) ? label : "$" + DumpByteValue(absolute);
|
private string ConvertZPAddress(byte absolute) => this.TryGetLabel(absolute, out var label) ? label : "$" + DumpByteValue(absolute);
|
||||||
|
|
||||||
private bool TryGetLabel(ushort absolute, out string label)
|
private bool TryGetLabel(ushort absolute, out string name)
|
||||||
{
|
{
|
||||||
return this.symbols.Labels.TryGetValue(absolute, value: out label);
|
return this.symbols.TryGetQualifiedLabel(absolute, out name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MayeGetLabel(ushort absolute)
|
private string MaybeGetLabel(ushort absolute)
|
||||||
{
|
{
|
||||||
if (this.TryGetLabel(absolute, out var label))
|
return this.symbols.MaybeGetQualifiedLabel(absolute);
|
||||||
{
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MaybeGetCodeLabel(ushort absolute)
|
private string MaybeGetCodeLabel(ushort absolute)
|
||||||
{
|
{
|
||||||
var label = this.MayeGetLabel(absolute);
|
var label = this.MaybeGetLabel(absolute);
|
||||||
if (string.IsNullOrEmpty(label))
|
if (string.IsNullOrEmpty(label))
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
@ -578,20 +525,25 @@ namespace EightBit
|
|||||||
|
|
||||||
private string MaybeGetCodeLabel()
|
private string MaybeGetCodeLabel()
|
||||||
{
|
{
|
||||||
return Pad(this.MaybeGetCodeLabel(this.address), 20);
|
return Pad(this.MaybeGetCodeLabel(this.address), 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constants conversion
|
#region Constants conversion
|
||||||
|
|
||||||
|
private bool TryGetConstant(ushort value, out string name)
|
||||||
|
{
|
||||||
|
return this.symbols.TryGetQualifiedEquate(value, out name);
|
||||||
|
}
|
||||||
|
|
||||||
private string ConvertConstantWord(ushort address) => this.ConvertConstant(this.GetWord(address));
|
private string ConvertConstantWord(ushort address) => this.ConvertConstant(this.GetWord(address));
|
||||||
|
|
||||||
private string ConvertConstant(ushort constant) => this.symbols.Constants.TryGetValue(constant, out var label) ? label : this.Dump_DByte(constant);
|
private string ConvertConstant(ushort constant) => this.TryGetConstant(constant, out var label) ? label : this.Dump_DByte(constant);
|
||||||
|
|
||||||
private string ConvertConstantByte(ushort address) => this.ConvertConstant(this.GetByte(address));
|
private string ConvertConstantByte(ushort address) => this.ConvertConstant(this.GetByte(address));
|
||||||
|
|
||||||
private string ConvertConstant(byte constant) => this.symbols.Constants.TryGetValue(constant, out var label) ? label : "$" + DumpByteValue(constant);
|
private string ConvertConstant(byte constant) => this.TryGetConstant(constant, out var label) ? label : "$" + DumpByteValue(constant);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
private TestRunner Runner { get; }
|
private TestRunner Runner { get; }
|
||||||
|
|
||||||
private EightBit.Symbols Symbols { get; } = new();
|
private EightBit.Files.Symbols.Parser Symbols { get; } = new();
|
||||||
|
|
||||||
private EightBit.Disassembler Disassembler { get; }
|
private EightBit.Disassembler Disassembler { get; }
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace M6502.Test
|
namespace M6502.Test
|
||||||
{
|
{
|
||||||
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using EightBit;
|
using EightBit;
|
||||||
|
|
||||||
@ -11,8 +12,9 @@ namespace M6502.Test
|
|||||||
{
|
{
|
||||||
private readonly Configuration configuration;
|
private readonly Configuration configuration;
|
||||||
private readonly Ram ram;
|
private readonly Ram ram;
|
||||||
private readonly Symbols symbols;
|
private readonly EightBit.Files.Symbols.Parser symbols;
|
||||||
private readonly Disassembler disassembler;
|
private readonly Disassembler disassembler;
|
||||||
|
private readonly Profiler profiler;
|
||||||
private readonly MemoryMapping mapping;
|
private readonly MemoryMapping mapping;
|
||||||
|
|
||||||
private ushort oldPC;
|
private ushort oldPC;
|
||||||
@ -27,11 +29,26 @@ namespace M6502.Test
|
|||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.ram = new Ram(0x10000);
|
this.ram = new Ram(0x10000);
|
||||||
this.CPU = new M6502(this);
|
this.CPU = new M6502(this);
|
||||||
this.symbols = new Symbols(this.configuration.RomDirectory + "/" + this.configuration.Symbols);
|
this.symbols = new EightBit.Files.Symbols.Parser();
|
||||||
this.disassembler = new Disassembler(this, this.CPU, this.symbols);
|
this.disassembler = new Disassembler(this, this.CPU, this.symbols);
|
||||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
|
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
|
||||||
|
|
||||||
this.oldPC = (ushort)Mask.Sixteen;
|
this.oldPC = (ushort)Mask.Sixteen;
|
||||||
|
|
||||||
|
this.symbols.Parse(string.IsNullOrEmpty(this.configuration.Symbols) ? string.Empty : this.configuration.RomDirectory + "/" + this.configuration.Symbols);
|
||||||
|
|
||||||
|
this.profiler = new Profiler(this.CPU, this.disassembler, this.symbols, this.configuration.Profile, this.configuration.Profile);
|
||||||
|
if (this.configuration.Profile)
|
||||||
|
{
|
||||||
|
this.profiler.StartingOutput += this.Profiler_StartingOutput;
|
||||||
|
this.profiler.FinishedOutput += this.Profiler_FinishedOutput;
|
||||||
|
this.profiler.StartingLineOutput += this.Profiler_StartingLineOutput;
|
||||||
|
this.profiler.FinishedLineOutput += this.Profiler_FinishedLineOutput;
|
||||||
|
this.profiler.StartingScopeOutput += this.Profiler_StartingScopeOutput;
|
||||||
|
this.profiler.FinishedScopeOutput += this.Profiler_FinishedScopeOutput;
|
||||||
|
this.profiler.EmitLine += this.Profiler_EmitLine;
|
||||||
|
this.profiler.EmitScope += this.Profiler_EmitScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public M6502 CPU { get; }
|
public M6502 CPU { get; }
|
||||||
@ -51,6 +68,10 @@ namespace M6502.Test
|
|||||||
{
|
{
|
||||||
this.CPU.LowerPOWER();
|
this.CPU.LowerPOWER();
|
||||||
base.LowerPOWER();
|
base.LowerPOWER();
|
||||||
|
if (this.configuration.Profile)
|
||||||
|
{
|
||||||
|
this.profiler.Generate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@ -200,7 +221,49 @@ namespace M6502.Test
|
|||||||
|
|
||||||
output.Append(this.disassembler.Disassemble(address));
|
output.Append(this.disassembler.Disassemble(address));
|
||||||
|
|
||||||
System.Console.Out.WriteLine(output.ToString());
|
Console.Out.WriteLine(output.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_EmitScope(object? sender, ProfileScopeEventArgs e)
|
||||||
|
{
|
||||||
|
var proportion = (double)e.Cycles / this.CPU.Cycles;
|
||||||
|
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, e.Cycles, e.Count, e.Scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e)
|
||||||
|
{
|
||||||
|
var proportion = (double)e.Cycles / this.profiler.TotalCycleCount;
|
||||||
|
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}]\t{2}\n", proportion, e.Cycles, e.Source));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_FinishedScopeOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Finished profiler scope output...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_StartingScopeOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Starting profiler scope output...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_FinishedLineOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Finished profiler line output...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_StartingLineOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Starting profiler line output...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_FinishedOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Finished profiler output...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Profiler_StartingOutput(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.Out.Write("Starting profiler output...\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,6 @@
|
|||||||
{
|
{
|
||||||
public class ProfileEventArgs(string output) : EventArgs
|
public class ProfileEventArgs(string output) : EventArgs
|
||||||
{
|
{
|
||||||
private readonly string output = output;
|
public string Output { get; } = output;
|
||||||
|
|
||||||
public string Output
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,23 +2,8 @@
|
|||||||
{
|
{
|
||||||
public class ProfileLineEventArgs(string source, int cycles) : EventArgs
|
public class ProfileLineEventArgs(string source, int cycles) : EventArgs
|
||||||
{
|
{
|
||||||
private readonly string source = source;
|
public string Source { get; } = source;
|
||||||
private readonly int cycles = cycles;
|
|
||||||
|
|
||||||
public string Source
|
public int Cycles { get; } = cycles;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Cycles
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.cycles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,32 +2,10 @@
|
|||||||
{
|
{
|
||||||
public class ProfileScopeEventArgs(string scope, int cycles, int count) : EventArgs
|
public class ProfileScopeEventArgs(string scope, int cycles, int count) : EventArgs
|
||||||
{
|
{
|
||||||
private readonly string scope = scope;
|
public string Scope { get; } = scope;
|
||||||
private readonly int cycles = cycles;
|
|
||||||
private readonly int count = count;
|
|
||||||
|
|
||||||
public string Scope
|
public int Cycles { get; } = cycles;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.scope;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Cycles
|
public int Count { get; } = count;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.cycles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Count
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,32 +6,29 @@
|
|||||||
private readonly int[] addressProfiles;
|
private readonly int[] addressProfiles;
|
||||||
private readonly int[] addressCounts;
|
private readonly int[] addressCounts;
|
||||||
|
|
||||||
private readonly string[] addressScopes;
|
|
||||||
private readonly Dictionary<string, int> scopeCycles;
|
private readonly Dictionary<string, int> scopeCycles;
|
||||||
|
|
||||||
private readonly M6502 processor;
|
private readonly M6502 processor;
|
||||||
private readonly Disassembler disassembler;
|
private readonly Disassembler disassembler;
|
||||||
private readonly Symbols symbols;
|
private readonly Files.Symbols.Parser symbols;
|
||||||
|
|
||||||
private readonly bool countInstructions;
|
|
||||||
private readonly bool profileAddresses;
|
|
||||||
|
|
||||||
private int priorCycleCount;
|
private int priorCycleCount;
|
||||||
private ushort executingAddress;
|
private ushort executingAddress;
|
||||||
|
|
||||||
public Profiler(M6502 processor, Disassembler disassembler, Symbols symbols, bool countInstructions, bool profileAddresses)
|
public Profiler(M6502 processor, Disassembler disassembler, Files.Symbols.Parser symbols, bool countInstructions, bool profileAddresses)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(processor);
|
ArgumentNullException.ThrowIfNull(processor);
|
||||||
|
ArgumentNullException.ThrowIfNull(disassembler);
|
||||||
|
ArgumentNullException.ThrowIfNull(symbols);
|
||||||
|
|
||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
this.disassembler = disassembler;
|
this.disassembler = disassembler;
|
||||||
this.symbols = symbols;
|
this.symbols = symbols;
|
||||||
this.countInstructions = countInstructions;
|
|
||||||
this.profileAddresses = profileAddresses;
|
|
||||||
|
|
||||||
if (profileAddresses || countInstructions)
|
if (profileAddresses || countInstructions)
|
||||||
{
|
{
|
||||||
this.processor.ExecutingInstruction += this.Processor_ExecutingInstruction_Prequel;
|
this.processor.ExecutingInstruction += this.Processor_ExecutingInstruction_Prequel;
|
||||||
|
this.processor.ExecutedInstruction += this.Processor_ExecutedInstruction_Sequal;
|
||||||
}
|
}
|
||||||
if (profileAddresses)
|
if (profileAddresses)
|
||||||
{
|
{
|
||||||
@ -48,10 +45,7 @@
|
|||||||
this.addressProfiles = new int[0x10000];
|
this.addressProfiles = new int[0x10000];
|
||||||
this.addressCounts = new int[0x10000];
|
this.addressCounts = new int[0x10000];
|
||||||
|
|
||||||
this.addressScopes = new string[0x10000];
|
|
||||||
this.scopeCycles = [];
|
this.scopeCycles = [];
|
||||||
|
|
||||||
this.BuildAddressScopes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -71,6 +65,8 @@
|
|||||||
|
|
||||||
public event EventHandler<ProfileScopeEventArgs>? EmitScope;
|
public event EventHandler<ProfileScopeEventArgs>? EmitScope;
|
||||||
|
|
||||||
|
public long TotalCycleCount { get; private set; }
|
||||||
|
|
||||||
public void Generate()
|
public void Generate()
|
||||||
{
|
{
|
||||||
this.OnStartingOutput();
|
this.OnStartingOutput();
|
||||||
@ -116,7 +112,7 @@
|
|||||||
{
|
{
|
||||||
var name = scopeCycle.Key;
|
var name = scopeCycle.Key;
|
||||||
var cycles = scopeCycle.Value;
|
var cycles = scopeCycle.Value;
|
||||||
var count = this.addressCounts[this.symbols.Addresses[name]];
|
var count = this.addressCounts[this.symbols.LookupLabel(name).Value];
|
||||||
this.OnEmitScope(name, cycles, count);
|
this.OnEmitScope(name, cycles, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,6 +127,11 @@
|
|||||||
this.executingAddress = this.processor.PC.Word;
|
this.executingAddress = this.processor.PC.Word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Processor_ExecutedInstruction_Sequal(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.TotalCycleCount += this.processor.Cycles;
|
||||||
|
}
|
||||||
|
|
||||||
private void Processor_ExecutingInstruction_ProfileAddresses(object? sender, EventArgs e)
|
private void Processor_ExecutingInstruction_ProfileAddresses(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
this.priorCycleCount = this.processor.Cycles;
|
this.priorCycleCount = this.processor.Cycles;
|
||||||
@ -149,31 +150,15 @@
|
|||||||
|
|
||||||
this.addressProfiles[address] += cycles;
|
this.addressProfiles[address] += cycles;
|
||||||
|
|
||||||
var addressScope = this.addressScopes[address];
|
var addressScope = this.symbols.LookupScope(address);
|
||||||
if (addressScope != null)
|
if (addressScope != null)
|
||||||
{
|
{
|
||||||
if (!this.scopeCycles.ContainsKey(addressScope))
|
if (!this.scopeCycles.ContainsKey(addressScope.Name))
|
||||||
{
|
{
|
||||||
this.scopeCycles[addressScope] = 0;
|
this.scopeCycles[addressScope.Name] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scopeCycles[addressScope] += cycles;
|
this.scopeCycles[addressScope.Name] += cycles;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BuildAddressScopes()
|
|
||||||
{
|
|
||||||
foreach (var label in this.symbols.Labels)
|
|
||||||
{
|
|
||||||
var key = label.Value;
|
|
||||||
if (this.symbols.Scopes.TryGetValue(key, out var scope))
|
|
||||||
{
|
|
||||||
var address = label.Key;
|
|
||||||
for (ushort i = address; i < address + scope; ++i)
|
|
||||||
{
|
|
||||||
this.addressScopes[i] = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
111
M6502/Symbols.cs
111
M6502/Symbols.cs
@ -1,111 +0,0 @@
|
|||||||
// <copyright file="Symbols.cs" company="Adrian Conlon">
|
|
||||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace EightBit
|
|
||||||
{
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
public class Symbols
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, Dictionary<string, Dictionary<string, string>>> parsed = [];
|
|
||||||
|
|
||||||
public Symbols()
|
|
||||||
: this(string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Symbols(string? path)
|
|
||||||
{
|
|
||||||
ArgumentNullException.ThrowIfNull(path);
|
|
||||||
if (path.Length > 0)
|
|
||||||
{
|
|
||||||
this.Parse(path);
|
|
||||||
this.AssignSymbols();
|
|
||||||
this.AssignScopes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<ushort, string> Labels { get; } = [];
|
|
||||||
|
|
||||||
public Dictionary<ushort, string> Constants { get; } = [];
|
|
||||||
|
|
||||||
public Dictionary<string, ushort> Scopes { get; } = [];
|
|
||||||
|
|
||||||
public Dictionary<string, ushort> Addresses { get; } = [];
|
|
||||||
|
|
||||||
private void AssignScopes()
|
|
||||||
{
|
|
||||||
var parsedScopes = this.parsed["scope"];
|
|
||||||
foreach (var parsedScopeElement in parsedScopes)
|
|
||||||
{
|
|
||||||
var parsedScope = parsedScopeElement.Value;
|
|
||||||
var name = parsedScope["name"];
|
|
||||||
var trimmedName = name[1..^1];
|
|
||||||
var size = parsedScope["size"];
|
|
||||||
this.Scopes[trimmedName] = ushort.Parse(size, CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AssignSymbols()
|
|
||||||
{
|
|
||||||
var symbols = this.parsed["sym"];
|
|
||||||
foreach (var symbolElement in symbols)
|
|
||||||
{
|
|
||||||
var symbol = symbolElement.Value;
|
|
||||||
var name = symbol["name"];
|
|
||||||
var trimmedName = name[1..^1];
|
|
||||||
var value = symbol["val"][2..];
|
|
||||||
var number = Convert.ToUInt16(value, 16);
|
|
||||||
var symbolType = symbol["type"];
|
|
||||||
if (symbolType == "lab")
|
|
||||||
{
|
|
||||||
this.Labels[number] = trimmedName;
|
|
||||||
this.Addresses[trimmedName] = number;
|
|
||||||
}
|
|
||||||
else if (symbolType == "equ")
|
|
||||||
{
|
|
||||||
this.Constants[number] = trimmedName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Parse(string path)
|
|
||||||
{
|
|
||||||
using var reader = new StreamReader(path);
|
|
||||||
while (!reader.EndOfStream)
|
|
||||||
{
|
|
||||||
var line = reader.ReadLine();
|
|
||||||
if (line == null)
|
|
||||||
break;
|
|
||||||
var lineElements = line.Split(' ', '\t');
|
|
||||||
if (lineElements.Length == 2)
|
|
||||||
{
|
|
||||||
var type = lineElements[0];
|
|
||||||
var dataElements = lineElements[1].Split(',');
|
|
||||||
var data = new Dictionary<string, string>();
|
|
||||||
foreach (var dataElement in dataElements)
|
|
||||||
{
|
|
||||||
var definition = dataElement.Split('=');
|
|
||||||
if (definition.Length == 2)
|
|
||||||
{
|
|
||||||
data[definition[0]] = definition[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.ContainsKey("id"))
|
|
||||||
{
|
|
||||||
if (!this.parsed.ContainsKey(type))
|
|
||||||
{
|
|
||||||
this.parsed[type] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = data["id"];
|
|
||||||
data.Remove("id");
|
|
||||||
this.parsed[type][id] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user