ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* 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;
|
|
|
|
|
|
2021-10-07 19:39:08 +00:00
|
|
|
|
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);
|
|
|
|
|
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
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)) {
|
2021-10-07 19:39:08 +00:00
|
|
|
|
sb.Append(" '");
|
|
|
|
|
sb.Append(attr.Symbol.GenerateDisplayLabel(formatter));
|
|
|
|
|
sb.Append("'");
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-07 19:39:08 +00:00
|
|
|
|
if (change.Region.HasValidPreLabel) {
|
|
|
|
|
sb.Append(" pre='");
|
|
|
|
|
sb.Append(change.Region.PreLabel);
|
|
|
|
|
sb.Append("'");
|
|
|
|
|
}
|
2024-05-20 21:50:18 +00:00
|
|
|
|
if (change.Region.DisallowInward) {
|
|
|
|
|
sb.Append(" [!in]");
|
|
|
|
|
}
|
|
|
|
|
if (change.Region.DisallowOutward) {
|
|
|
|
|
sb.Append(" [!out]");
|
|
|
|
|
}
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
|
|
|
|
|
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");
|
2021-10-02 20:47:05 +00:00
|
|
|
|
if (change.Region.IsFloating) {
|
|
|
|
|
sb.Append(" (floating)");
|
|
|
|
|
}
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
//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);
|
|
|
|
|
}
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
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 + "-");
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
} 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 + "-");
|
ORG rework, part 5
Updated project file format to save the new map entries.
Tweaked appearance of .arend directives to show the .arstart address
in the operand field. This makes it easier to match them up on screen.
Also, add a synthetic comment on auto-generated .arstart entries.
Added .arstart/.arend to the things that respond to Jump to Operand
(Ctrl+J). Selecting one jumps to the other end. (Well, it jumps
to the code nearest the other, which will do for now.)
Added a menu item to display a text rendering of the address map.
Helpful when things get complicated.
Modified the linear map iterator to return .arend items with the offset
of the last byte in the region, rather than the first byte of the
following region. While the "exclusive end" approach is pretty
common, it caused problems when updating the line list, because it
meant that the .arend directives were outside the range of offsets
being updated (and, for directives at the end of the file, outside
the file itself). This was painful to deal with for partial updates.
Changing this required some relatively subtle changes and annoyed some
of the debug assertions, such as the one where all Line items have
offsets that match the start of a line, but it's the cleaner approach.
2021-09-28 00:02:18 +00:00
|
|
|
|
} else {
|
|
|
|
|
sb.Append("$");
|
|
|
|
|
sb.Append(formatter.FormatAddress(addr, showBank));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|