1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-12-12 21:29:30 +00:00
6502bench/SourceGen/RenderAddressMap.cs

175 lines
6.7 KiB
C#
Raw Normal View History

/*
* Copyright 2021 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Asm65;
using CommonUtil;
using AddressChange = CommonUtil.AddressMap.AddressChange;
namespace SourceGen {
/// <summary>
/// Functions for generating a human-readable form of the address map.
/// </summary>
/// A graphical / interactive visualization would be nicer, but this can be pasted
/// into bug reports.
/// </remarks>
public static class RenderAddressMap {
private const string CRLF = "\r\n";
/// <summary>
/// Formats the address map for viewing.
/// </summary>
public static string GenerateString(DisasmProject project, Formatter formatter) {
AddressMap addrMap = project.AddrMap;
bool showBank = !project.CpuDef.HasAddr16;
StringBuilder sb = new StringBuilder();
int depth = 0;
int prevOffset = -1;
int prevAddr = 0;
int lastEndOffset = -1;
sb.AppendLine("Address region map for \"" + project.DataFileName + "\"");
ORG rework, part 6 Added support for non-addressable regions, which are useful for things like file headers stripped out by the system loader, or chunks that get loaded into non-addressable graphics RAM. Regions are specified with the "NA" address value. The code list displays the address field greyed out, starting from zero (which is kind of handy if you want to know the relative offset within the region). Putting labels in non-addressable regions doesn't make sense, but symbol resolution is complicated enough that we really only have two options: ignore the labels entirely, or allow them but warn of their presence. The problem isn't so much the label, which you could legitimately want to access from an extension script, but rather the references to them from code or data. So we keep the label and add a warning to the Messages list when we see a reference. Moved NON_ADDR constants to Address class. AddressMap now has a copy. This is awkward because Asm65 and CommonUtil don't share. Updated the asm code generators to understand NON_ADDR, and reworked the API so that Merlin and cc65 output is correct for nested regions. Address region changes are now noted in the anattribs array, which makes certain operations faster than checking the address map. It also fixes a failure to recognize mid-instruction region changes in the code analyzer. Tweaked handling of synthetic regions, which are non-addressable areas generated by the linear address map traversal to fill in any "holes". The address region editor now treats attempts to edit them as creation of a new region.
2021-10-01 01:07:21 +00:00
sb.Append(CRLF);
IEnumerator<AddressChange> iter = addrMap.AddressChangeIterator;
while (iter.MoveNext()) {
AddressChange change = iter.Current;
if (change.IsStart) {
//if (change.Offset == lastEndOffset) {
// // Extra vertical space for a START following an END at the same offset.
// PrintDepthLines(sb, depth, true);
// sb.Append(CRLF);
// lastEndOffset = -1;
//}
if (prevOffset >= 0 && change.Offset != prevOffset) {
// Start of region at new offset. Output address info for space
// between previous start or end.
PrintAddressInfo(sb, formatter, depth, prevAddr,
change.Offset - prevOffset, showBank);
}
// Start following end, or start following start after a gap.
sb.Append(formatter.FormatOffset24(change.Offset));
PrintDepthLines(sb, depth, false);
sb.Append("+- " + "start");
if (change.IsSynthetic) {
sb.Append(" (auto-generated)");
} else {
// If there's a label here, show it.
Anattrib attr = project.GetAnattrib(change.Offset);
if (attr.Symbol != null && !string.IsNullOrEmpty(attr.Symbol.Label)) {
sb.Append(" '");
sb.Append(attr.Symbol.GenerateDisplayLabel(formatter));
sb.Append("'");
}
}
if (change.Region.HasValidPreLabel) {
sb.Append(" pre='");
sb.Append(change.Region.PreLabel);
sb.Append("'");
}
sb.Append(CRLF);
prevOffset = change.Offset;
prevAddr = change.Address;
depth++;
} else {
Debug.Assert(prevOffset >= 0);
depth--;
if (change.Offset + 1 != prevOffset) {
// End of region at new offset. Output address info for space
// between previous start or end.
PrintAddressInfo(sb, formatter, depth + 1, prevAddr,
change.Offset + 1 - prevOffset, showBank);
}
sb.Append(formatter.FormatOffset24(change.Offset));
PrintDepthLines(sb, depth, false);
sb.Append("+- " + "end");
if (change.Region.IsFloating) {
sb.Append(" (floating)");
}
//PrintAddress(sb, formatter, change.Address, showBank);
//sb.Append(")");
sb.Append(CRLF);
ORG rework, part 6 Added support for non-addressable regions, which are useful for things like file headers stripped out by the system loader, or chunks that get loaded into non-addressable graphics RAM. Regions are specified with the "NA" address value. The code list displays the address field greyed out, starting from zero (which is kind of handy if you want to know the relative offset within the region). Putting labels in non-addressable regions doesn't make sense, but symbol resolution is complicated enough that we really only have two options: ignore the labels entirely, or allow them but warn of their presence. The problem isn't so much the label, which you could legitimately want to access from an extension script, but rather the references to them from code or data. So we keep the label and add a warning to the Messages list when we see a reference. Moved NON_ADDR constants to Address class. AddressMap now has a copy. This is awkward because Asm65 and CommonUtil don't share. Updated the asm code generators to understand NON_ADDR, and reworked the API so that Merlin and cc65 output is correct for nested regions. Address region changes are now noted in the anattribs array, which makes certain operations faster than checking the address map. It also fixes a failure to recognize mid-instruction region changes in the code analyzer. Tweaked handling of synthetic regions, which are non-addressable areas generated by the linear address map traversal to fill in any "holes". The address region editor now treats attempts to edit them as creation of a new region.
2021-10-01 01:07:21 +00:00
// Add a blank line, but with the depth lines.
if (depth > 0) {
PrintDepthLines(sb, depth, true);
}
sb.Append(CRLF);
// Use offset+1 here so it lines up with start records.
prevOffset = lastEndOffset = change.Offset + 1;
prevAddr = change.Address;
}
}
Debug.Assert(depth == 0);
return sb.ToString();
}
private static void PrintDepthLines(StringBuilder sb, int depth, bool doIndent) {
if (doIndent) {
sb.Append(" ");
}
sb.Append(" ");
while (depth-- > 0) {
sb.Append("| ");
}
}
private static void PrintAddressInfo(StringBuilder sb, Formatter formatter, int depth,
int startAddr, int length, bool showBank) {
//PrintDepthLines(sb, depth);
//sb.Append(CRLF);
PrintDepthLines(sb, depth, true);
sb.Append(' ');
ORG rework, part 6 Added support for non-addressable regions, which are useful for things like file headers stripped out by the system loader, or chunks that get loaded into non-addressable graphics RAM. Regions are specified with the "NA" address value. The code list displays the address field greyed out, starting from zero (which is kind of handy if you want to know the relative offset within the region). Putting labels in non-addressable regions doesn't make sense, but symbol resolution is complicated enough that we really only have two options: ignore the labels entirely, or allow them but warn of their presence. The problem isn't so much the label, which you could legitimately want to access from an extension script, but rather the references to them from code or data. So we keep the label and add a warning to the Messages list when we see a reference. Moved NON_ADDR constants to Address class. AddressMap now has a copy. This is awkward because Asm65 and CommonUtil don't share. Updated the asm code generators to understand NON_ADDR, and reworked the API so that Merlin and cc65 output is correct for nested regions. Address region changes are now noted in the anattribs array, which makes certain operations faster than checking the address map. It also fixes a failure to recognize mid-instruction region changes in the code analyzer. Tweaked handling of synthetic regions, which are non-addressable areas generated by the linear address map traversal to fill in any "holes". The address region editor now treats attempts to edit them as creation of a new region.
2021-10-01 01:07:21 +00:00
if (startAddr == Address.NON_ADDR) {
sb.Append("-" + Address.NON_ADDR_STR + "-");
} else {
PrintAddress(sb, formatter, startAddr, showBank);
sb.Append(" - ");
PrintAddress(sb, formatter, startAddr + length - 1, showBank);
}
sb.Append(" length=" + length + " ($" + length.ToString("x4") + ")");
sb.Append(CRLF);
//PrintDepthLines(sb, depth, true);
//sb.Append(CRLF);
}
private static void PrintAddress(StringBuilder sb, Formatter formatter, int addr,
bool showBank) {
ORG rework, part 6 Added support for non-addressable regions, which are useful for things like file headers stripped out by the system loader, or chunks that get loaded into non-addressable graphics RAM. Regions are specified with the "NA" address value. The code list displays the address field greyed out, starting from zero (which is kind of handy if you want to know the relative offset within the region). Putting labels in non-addressable regions doesn't make sense, but symbol resolution is complicated enough that we really only have two options: ignore the labels entirely, or allow them but warn of their presence. The problem isn't so much the label, which you could legitimately want to access from an extension script, but rather the references to them from code or data. So we keep the label and add a warning to the Messages list when we see a reference. Moved NON_ADDR constants to Address class. AddressMap now has a copy. This is awkward because Asm65 and CommonUtil don't share. Updated the asm code generators to understand NON_ADDR, and reworked the API so that Merlin and cc65 output is correct for nested regions. Address region changes are now noted in the anattribs array, which makes certain operations faster than checking the address map. It also fixes a failure to recognize mid-instruction region changes in the code analyzer. Tweaked handling of synthetic regions, which are non-addressable areas generated by the linear address map traversal to fill in any "holes". The address region editor now treats attempts to edit them as creation of a new region.
2021-10-01 01:07:21 +00:00
if (addr == Address.NON_ADDR) {
sb.Append("-" + Address.NON_ADDR_STR + "-");
} else {
sb.Append("$");
sb.Append(formatter.FormatAddress(addr, showBank));
}
}
}
}