mirror of
https://github.com/fadden/6502bench.git
synced 2024-06-12 23:29:32 +00:00
Compare commits
57 Commits
v1.8.3-dev
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
967d468c58 | ||
|
c05b5b3a28 | ||
|
7ca11b0889 | ||
|
4e5c34f457 | ||
|
fa5d9ba890 | ||
|
3b20566b10 | ||
|
7a7ff44d3a | ||
|
e137db2b5c | ||
|
ea4ddc1071 | ||
|
d6cfc83368 | ||
|
17bd80e39f | ||
|
ca38b7751c | ||
|
948e4a2bf2 | ||
|
aa05aa7a80 | ||
|
47b11b6797 | ||
|
9e82ff8b88 | ||
|
4322a0c231 | ||
|
e425237783 | ||
|
da91d9fc0e | ||
|
8532cfb433 | ||
|
89df3278bc | ||
|
9e9b12564e | ||
|
2f836d77a2 | ||
|
110a9ae818 | ||
|
c637d6549c | ||
|
1c79cddb47 | ||
|
cee8fa3cbf | ||
|
a8aa871109 | ||
|
2f603b69c3 | ||
|
7ebf976279 | ||
|
72d8498fe0 | ||
|
ca50730611 | ||
|
08243bf19c | ||
|
74cc55de29 | ||
|
f46d8f4920 | ||
|
d22d35c4df | ||
|
31d4bf8bfa | ||
|
3ffca60066 | ||
|
edc92cf5d6 | ||
|
a83b0e73da | ||
|
7adec9f725 | ||
|
58d794f535 | ||
|
4f64a936ed | ||
|
426db27b5a | ||
|
5d7503686c | ||
|
c1a8ce519e | ||
|
0e2d190d28 | ||
|
f3d255c1a9 | ||
|
dcab984f3b | ||
|
072c66bc8c | ||
|
80ffd5f534 | ||
|
4c60f329c7 | ||
|
ce1a6d0109 | ||
|
b8314b7f30 | ||
|
8b1e70fa58 | ||
|
663a3d0230 | ||
|
0878854759 |
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
|
|
@ -1121,8 +1121,17 @@ namespace Asm65 {
|
|||
sb.Append(mHexDumpBuffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats up to 16 bytes of data and appends it to the StringBuilder.
|
||||
/// </summary>
|
||||
/// <param name="data">Reference to data.</param>
|
||||
/// <param name="offset">Start offset.</param>
|
||||
/// <param name="addr">Address to put at start of line.</param>
|
||||
/// <param name="length">Number of bytes to format.</param>
|
||||
/// <param name="sb">StringBuilder to append the data to.</param>
|
||||
public void FormatHexDump(byte[] data, int offset, int addr, int length,
|
||||
StringBuilder sb) {
|
||||
Debug.Assert(length <= 16);
|
||||
FormatHexDumpCommon(data, offset, addr, length);
|
||||
sb.Append(mHexDumpBuffer);
|
||||
}
|
||||
|
|
|
@ -750,13 +750,13 @@ namespace Asm65 {
|
|||
{ OpName.SMB7, SMB_DESC },
|
||||
};
|
||||
|
||||
private static string BBR_DESC =
|
||||
private const string BBR_DESC =
|
||||
"Branches to a relative address if the specified bit in memory is zero.";
|
||||
private static string BBS_DESC =
|
||||
private const string BBS_DESC =
|
||||
"Branches to a relative address if the specified bit in memory is one.";
|
||||
private static string RMB_DESC =
|
||||
private const string RMB_DESC =
|
||||
"Clears a bit in memory.";
|
||||
private static string SMB_DESC =
|
||||
private const string SMB_DESC =
|
||||
"Sets a bit in memory.";
|
||||
|
||||
|
||||
|
|
|
@ -39,18 +39,19 @@ namespace CommonUtil {
|
|||
/// There are three basic API modes:
|
||||
/// (1) Structural. Add, modify, and remove regions. Needed by the "edit region" dialog.
|
||||
/// This matches exactly with the contents of the project file.
|
||||
/// (2) Hierarchical. Used when converting an offset to an address, which can't be
|
||||
/// (2) Hierarchical. Used when converting an address to an offset, which can't be
|
||||
/// accomplished with a simple map because we need to take into account the offset of
|
||||
/// the reference. The tree best represents the relationship between regions.
|
||||
/// the reference, and when determining the address of an offset. The tree best
|
||||
/// represents the relationship between regions.
|
||||
/// (3) Linear. When generating assembly sources or the display list, we need to identify
|
||||
/// the lines that have an address change event (even if the address doesn't change).
|
||||
/// This will be done as we walk through the code. For easy interaction with an
|
||||
/// iterator, we flatten it out.
|
||||
///
|
||||
/// These are different enough that it's best to use three different data structures. The
|
||||
/// list of regions is the primary structure, and the other two are generated from it. Changes
|
||||
/// to the map are very infrequent, and analyzing the file contents may hit the map
|
||||
/// frequently, so we want to optimize for "read" accesses.
|
||||
/// structural list of regions is the primary structure, and the other two are generated from
|
||||
/// it. Changes to the map are very infrequent, and analyzing the file contents may hit
|
||||
/// the map frequently, so we want to optimize for "read" accesses.
|
||||
///
|
||||
/// A region can be uniquely identified by {offset,length}. There can be multiple regions
|
||||
/// starting at a given offset, or ending at a given offset, but we disallow regions that
|
||||
|
@ -120,6 +121,16 @@ namespace CommonUtil {
|
|||
/// </summary>
|
||||
public string PreLabel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we prevent address resolution from entering this region?
|
||||
/// </summary>
|
||||
public bool DisallowInward { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we prevent address resolution from traversing outside this region?
|
||||
/// </summary>
|
||||
public bool DisallowOutward { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we try to generate the directive with an operand that is relative to
|
||||
/// the current PC?
|
||||
|
@ -130,20 +141,31 @@ namespace CommonUtil {
|
|||
public bool IsRelative { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// Simple constructor.
|
||||
/// </summary>
|
||||
public AddressMapEntry(int offset, int len, int addr, string preLabel, bool isRelative) {
|
||||
public AddressMapEntry(int offset, int len, int addr)
|
||||
: this(offset, len, addr, string.Empty, false, false, false)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Full constructor.
|
||||
/// </summary>
|
||||
public AddressMapEntry(int offset, int len, int addr, string preLabel,
|
||||
bool disallowInward, bool disallowOutward, bool isRelative) {
|
||||
Offset = offset;
|
||||
Length = len;
|
||||
Address = addr;
|
||||
PreLabel = preLabel;
|
||||
DisallowInward = disallowInward;
|
||||
DisallowOutward = disallowOutward;
|
||||
IsRelative = isRelative;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "[AddrMapEnt: +" + Offset.ToString("x6") + " len=$" + Length.ToString("x4") +
|
||||
" addr=$" + Address.ToString("x4") + " preLab='" + PreLabel +
|
||||
"' isRel=" + IsRelative + "]";
|
||||
"' disIn=" + DisallowInward + " disOut=" + DisallowOutward +
|
||||
" isRel=" + IsRelative + "]";
|
||||
}
|
||||
|
||||
public static bool operator ==(AddressMapEntry a, AddressMapEntry b) {
|
||||
|
@ -155,7 +177,8 @@ namespace CommonUtil {
|
|||
}
|
||||
// All fields must be equal.
|
||||
return a.Offset == b.Offset && a.Length == b.Length && a.Address == b.Address &&
|
||||
a.PreLabel == b.PreLabel && a.IsRelative == b.IsRelative;
|
||||
a.PreLabel == b.PreLabel && a.DisallowInward == b.DisallowInward &&
|
||||
a.DisallowOutward == b.DisallowOutward && a.IsRelative == b.IsRelative;
|
||||
}
|
||||
public static bool operator !=(AddressMapEntry a, AddressMapEntry b) {
|
||||
return !(a == b);
|
||||
|
@ -164,7 +187,8 @@ namespace CommonUtil {
|
|||
return obj is AddressMapEntry && this == (AddressMapEntry)obj;
|
||||
}
|
||||
public override int GetHashCode() {
|
||||
return Offset ^ Length ^ Address ^ PreLabel.GetHashCode() ^ (IsRelative ? 1 : 0);
|
||||
return Offset ^ Length ^ Address ^ PreLabel.GetHashCode() ^
|
||||
(DisallowInward ? 1 : 0) ^ (DisallowOutward ? 2 : 0) ^ (IsRelative ? 4 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,9 +249,11 @@ namespace CommonUtil {
|
|||
/// <summary>
|
||||
/// Full constructor.
|
||||
/// </summary>
|
||||
public AddressRegion(int offset, int len, int addr, string preLabel, bool isRelative,
|
||||
public AddressRegion(int offset, int len, int addr, string preLabel,
|
||||
bool disallowInward, bool disallowOutward, bool isRelative,
|
||||
int actualLen, int preLabelAddr)
|
||||
: base(offset, len, addr, preLabel, isRelative) {
|
||||
: base(offset, len, addr, preLabel, disallowInward, disallowOutward, isRelative)
|
||||
{
|
||||
ActualLength = actualLen;
|
||||
PreLabelAddress = preLabelAddr;
|
||||
|
||||
|
@ -238,14 +264,17 @@ namespace CommonUtil {
|
|||
/// Basic constructor. Not for use when len==FLOATING_LEN.
|
||||
/// </summary>
|
||||
public AddressRegion(int offset, int len, int addr)
|
||||
: this(offset, len, addr, string.Empty, false, len, NON_ADDR) {
|
||||
: this(offset, len, addr, string.Empty, false, false, false, len, NON_ADDR) {
|
||||
Debug.Assert(len != FLOATING_LEN);
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "[AddrRegion: +" + Offset.ToString("x6") + " len=$" +
|
||||
Length.ToString("x4") + " addr=$" + Address.ToString("x4") +
|
||||
" actualLen=$" + ActualLength.ToString("x4") + " isRel=" + IsRelative + "]";
|
||||
return "[AddrRegion: +" + Offset.ToString("x6") +
|
||||
" len=" + (Length == FLOATING_LEN ? "float" : "$" + Length.ToString("x4")) +
|
||||
" addr=" + (Address == NON_ADDR ? "NA" : "$" + Address.ToString("x4")) +
|
||||
" actualLen=$" + ActualLength.ToString("x4") +
|
||||
" disIn=" + DisallowInward + " disOut=" + DisallowOutward + " isRel=" +
|
||||
IsRelative + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +312,7 @@ namespace CommonUtil {
|
|||
foreach (AddressMapEntry ent in entries) {
|
||||
// TODO(maybe): suppress Regenerate() call in AddEntry while we work
|
||||
AddResult result = AddEntry(ent.Offset, ent.Length, ent.Address, ent.PreLabel,
|
||||
ent.IsRelative);
|
||||
ent.DisallowInward, ent.DisallowOutward, ent.IsRelative);
|
||||
if (result != AddResult.Okay) {
|
||||
throw new Exception("Unable to add entry (" + result + "): " + ent);
|
||||
}
|
||||
|
@ -360,16 +389,20 @@ namespace CommonUtil {
|
|||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We need to verify:
|
||||
/// - offset >= 0
|
||||
/// - offset < total length of file
|
||||
/// - either length is floating, or:
|
||||
/// - length > 0
|
||||
/// - length < total length of file
|
||||
/// - offset + length < total length of file
|
||||
/// - either address is NON_ADDR, or:
|
||||
/// - addr > 0
|
||||
/// - addr <= ADDR_MAX
|
||||
/// - preLabel is not null
|
||||
/// <list type="bullet">
|
||||
/// <item>offset >= 0</item>
|
||||
/// <item>offset < total length of file</item>
|
||||
/// <item>either length is floating, or:<list type="bullet">
|
||||
/// <item>length > 0</item>
|
||||
/// <item>length < total length of file</item>
|
||||
/// <item>offset + length < total length of file</item>
|
||||
/// </list></item>
|
||||
/// <item>either address is NON_ADDR, or:<list type="bullet">
|
||||
/// <item>addr > 0</item>
|
||||
/// <item>addr <= ADDR_MAX</item>
|
||||
/// </list></item>
|
||||
/// <item>preLabel is not null</item>
|
||||
/// </list>
|
||||
///
|
||||
/// We might want to limit the length to fit within a single 64K bank, unless it's
|
||||
/// a non-addressable region. That would probably be better as a warning than an error.
|
||||
|
@ -390,7 +423,7 @@ namespace CommonUtil {
|
|||
/// <param name="addr">Address of region start.</param>
|
||||
/// <returns>Failure code.</returns>
|
||||
public AddResult AddEntry(int offset, int length, int addr) {
|
||||
return AddEntry(offset, length, addr, string.Empty, false);
|
||||
return AddEntry(offset, length, addr, string.Empty, false, false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -402,7 +435,7 @@ namespace CommonUtil {
|
|||
// Slightly inefficient to extract the fields and reassemble them, which we can
|
||||
// avoid since instances are immutable, but it's not worth coding around.
|
||||
return AddEntry(entry.Offset, entry.Length, entry.Address, entry.PreLabel,
|
||||
entry.IsRelative);
|
||||
entry.DisallowInward, entry.DisallowOutward, entry.IsRelative);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -412,11 +445,15 @@ namespace CommonUtil {
|
|||
/// <param name="length">Length of region, or FLOATING_LEN for a floating end point.</param>
|
||||
/// <param name="addr">Address of region start.</param>
|
||||
/// <param name="preLabel">Pre-region label.</param>
|
||||
/// <param name="disallowInward">True if address resolution should not enter this
|
||||
/// region.</param>
|
||||
/// <param name="disallowOutward">True if address resolution should not traverse outside
|
||||
/// of this region.</param>
|
||||
/// <param name="isRelative">True if code generator should output relative
|
||||
/// assembler directive operand.</param>
|
||||
/// <returns>Failure code.</returns>
|
||||
public AddResult AddEntry(int offset, int length, int addr, string preLabel,
|
||||
bool isRelative) {
|
||||
bool disallowInward, bool disallowOutward, bool isRelative) {
|
||||
if (!ValidateArgs(offset, length, addr, preLabel)) {
|
||||
Debug.WriteLine("AddEntry: invalid arg");
|
||||
return AddResult.InvalidValue;
|
||||
|
@ -425,7 +462,7 @@ namespace CommonUtil {
|
|||
AddResult result = FindAddIndex(offset, length, out insIdx);
|
||||
if (result == AddResult.Okay) {
|
||||
AddressMapEntry newEntry = new AddressMapEntry(offset, length, addr,
|
||||
preLabel, isRelative);
|
||||
preLabel, disallowInward, disallowOutward, isRelative);
|
||||
mMapEntries.Insert(insIdx, newEntry);
|
||||
Regenerate();
|
||||
}
|
||||
|
@ -678,6 +715,11 @@ namespace CommonUtil {
|
|||
Parent = parent;
|
||||
// all other fields null/false
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "[TreeNode children=" + Children.Count +
|
||||
", Region=" + Region.ToString() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -696,7 +738,7 @@ namespace CommonUtil {
|
|||
// explicitly is caught here. It also avoids the need to special-case the top
|
||||
// part of the file.
|
||||
AddressRegion globalReg = new AddressRegion(0, mSpanLength, NON_ADDR, string.Empty,
|
||||
false, mSpanLength, NON_ADDR);
|
||||
false, false, false, mSpanLength, NON_ADDR);
|
||||
TreeNode topNode = new TreeNode(globalReg, null);
|
||||
|
||||
// Generate the children of this node.
|
||||
|
@ -753,7 +795,8 @@ namespace CommonUtil {
|
|||
}
|
||||
}
|
||||
AddressRegion fixedReg = new AddressRegion(childEnt.Offset,
|
||||
FLOATING_LEN, childEnt.Address, childEnt.PreLabel, childEnt.IsRelative,
|
||||
FLOATING_LEN, childEnt.Address, childEnt.PreLabel,
|
||||
childEnt.DisallowInward, childEnt.DisallowOutward, childEnt.IsRelative,
|
||||
nextStart - childEnt.Offset, preLabelAddr);
|
||||
children.Add(new TreeNode(fixedReg, parent));
|
||||
|
||||
|
@ -762,7 +805,8 @@ namespace CommonUtil {
|
|||
// Add this region to the list, and check for descendants.
|
||||
AddressRegion newReg = new AddressRegion(childEnt.Offset,
|
||||
childEnt.Length, childEnt.Address, childEnt.PreLabel,
|
||||
childEnt.IsRelative, childEnt.Length, preLabelAddr);
|
||||
childEnt.DisallowInward, childEnt.DisallowOutward, childEnt.IsRelative,
|
||||
childEnt.Length, preLabelAddr);
|
||||
TreeNode thisNode = new TreeNode(newReg, parent);
|
||||
children.Add(thisNode);
|
||||
|
||||
|
@ -833,7 +877,12 @@ namespace CommonUtil {
|
|||
return offset;
|
||||
}
|
||||
|
||||
// Didn't find it. Move up one level, but ignore the branch we've already checked.
|
||||
if (startNode.Region.DisallowOutward) {
|
||||
return -1; // can't look at parent or siblings of this node
|
||||
}
|
||||
|
||||
// Didn't find it. Move up one level, but ignore the branch we've already checked
|
||||
// (for efficiency). We need to start checking the "disallow inward" flag.
|
||||
ignoreNode = startNode;
|
||||
startNode = startNode.Parent;
|
||||
if (startNode == null) {
|
||||
|
@ -851,11 +900,18 @@ namespace CommonUtil {
|
|||
/// <param name="targetAddr">Address to find.</param>
|
||||
/// <returns>Offset, or -1 if not found.</returns>
|
||||
private int FindAddress(TreeNode node, TreeNode ignore, int targetAddr) {
|
||||
// We can ignore the DisallowInward flag on the current node, because we're already
|
||||
// in it. We don't want to descend into a child with the flag set. (It's okay to
|
||||
// ascend into a parent that has it set, but that's not handled here.)
|
||||
|
||||
if (node.Children != null) {
|
||||
foreach (TreeNode childNode in node.Children) {
|
||||
if (childNode == ignore) {
|
||||
continue;
|
||||
}
|
||||
if (childNode.Region.DisallowInward) {
|
||||
continue; // can't look at siblings with DisallowInward set
|
||||
}
|
||||
int offset = FindAddress(childNode, null, targetAddr);
|
||||
if (offset >= 0) {
|
||||
// Found match in child, return that.
|
||||
|
@ -876,7 +932,8 @@ namespace CommonUtil {
|
|||
}
|
||||
|
||||
// We span the correct range of addresses. See if the requested address
|
||||
// falls into a hole spanned by a child.
|
||||
// falls into a hole spanned by a child. (This is independent of DisallowInward,
|
||||
// since it's a hole in the address space whether we look at it or not.)
|
||||
if (node.Children != null) {
|
||||
int subPosn = targetAddr - region.Address; // position of target inside node
|
||||
foreach (TreeNode childNode in node.Children) {
|
||||
|
@ -923,7 +980,8 @@ namespace CommonUtil {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursively descends into the tree to find the node that contains the offset.
|
||||
/// Recursively descends into the tree to find the node that contains the offset. The
|
||||
/// deepest child node that spans the offset will be returned.
|
||||
/// </summary>
|
||||
/// <param name="offset">File offset.</param>
|
||||
/// <param name="node">Node to examine.</param>
|
||||
|
@ -1260,6 +1318,12 @@ namespace CommonUtil {
|
|||
if (change.IsSynthetic) {
|
||||
sb.Append(" (auto-generated)");
|
||||
}
|
||||
if (change.Region.DisallowInward) {
|
||||
sb.Append(" [!in]");
|
||||
}
|
||||
if (change.Region.DisallowOutward) {
|
||||
sb.Append(" [!out]");
|
||||
}
|
||||
sb.Append(CRLF);
|
||||
|
||||
prevOffset = change.Offset;
|
||||
|
@ -1330,6 +1394,9 @@ namespace CommonUtil {
|
|||
|
||||
#region Unit tests
|
||||
|
||||
// Unit test primitives. Set "result" to true at start of test; these will set it to
|
||||
// false on failure.
|
||||
|
||||
private static void Test_Expect(AddResult expected, ref bool result, AddResult actual) {
|
||||
if (expected != actual) {
|
||||
Debug.WriteLine("test failed (expected=" + expected + ", actual=" + actual + ")");
|
||||
|
@ -1342,7 +1409,6 @@ namespace CommonUtil {
|
|||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Test_Expect(int expected, ref bool result, int actual) {
|
||||
if (expected != actual) {
|
||||
Debug.WriteLine("test failed (expected=$" + expected.ToString("x4") + "/" +
|
||||
|
@ -1351,12 +1417,14 @@ namespace CommonUtil {
|
|||
}
|
||||
}
|
||||
|
||||
// Test equality and hashcode ops on AddressMapEntry.
|
||||
private static bool Test_Primitives() {
|
||||
bool result = true;
|
||||
|
||||
AddressMapEntry ent1 = new AddressMapEntry(0, 1, 2, "three", true);
|
||||
AddressMapEntry ent2 = new AddressMapEntry(0, 1, 2, "three", true);
|
||||
AddressMapEntry ent3 = new AddressMapEntry(0, 1, 2, "three-A", true);
|
||||
AddressMapEntry ent1 = new AddressMapEntry(0, 1, 2, "three", false, false, true);
|
||||
AddressMapEntry ent2 = new AddressMapEntry(0, 1, 2, "three", false, false, true);
|
||||
AddressMapEntry ent3 = new AddressMapEntry(0, 1, 2, "three-A", false, false, true);
|
||||
AddressMapEntry ent4 = new AddressMapEntry(0, 1, 2, "three-A", false, true, true);
|
||||
|
||||
result &= ent1 == ent2;
|
||||
result &= ent1 != ent3;
|
||||
|
@ -1364,11 +1432,14 @@ namespace CommonUtil {
|
|||
Test_Expect(true, ref result, result);
|
||||
|
||||
AddressRegion reg1 = new AddressRegion(ent1.Offset, ent1.Length, ent1.Address,
|
||||
ent1.PreLabel, ent1.IsRelative, ent1.Length, 0);
|
||||
ent1.PreLabel, ent1.DisallowInward, ent1.DisallowOutward, ent1.IsRelative,
|
||||
ent1.Length, 0);
|
||||
AddressRegion reg2 = new AddressRegion(ent2.Offset, ent2.Length, ent2.Address,
|
||||
ent2.PreLabel, ent2.IsRelative, ent2.Length, 0);
|
||||
ent2.PreLabel, ent2.DisallowInward, ent2.DisallowOutward, ent2.IsRelative,
|
||||
ent2.Length, 0);
|
||||
AddressRegion reg3 = new AddressRegion(ent3.Offset, ent3.Length, ent3.Address,
|
||||
ent3.PreLabel, ent3.IsRelative, ent3.Length, 0);
|
||||
ent3.PreLabel, ent3.DisallowInward, ent3.DisallowOutward, ent3.IsRelative,
|
||||
ent3.Length, 0);
|
||||
|
||||
result &= reg1 == reg2;
|
||||
result &= reg1 == ent1;
|
||||
|
@ -1377,33 +1448,37 @@ namespace CommonUtil {
|
|||
result &= reg3 != ent1;
|
||||
result &= reg1.Equals(ent2);
|
||||
result &= ent3 != reg1;
|
||||
result &= ent3 != ent4;
|
||||
Test_Expect(true, ref result, result);
|
||||
|
||||
result &= ent1.GetHashCode() == ent2.GetHashCode();
|
||||
result &= ent2.GetHashCode() != ent3.GetHashCode();
|
||||
result &= ent3.GetHashCode() != ent4.GetHashCode();
|
||||
Test_Expect(true, ref result, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Test the AddressMap FindRegion() method.
|
||||
private static bool Test_Find() {
|
||||
const int mapLen = 0x1000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
const int off0 = 0x000100;
|
||||
// Map with three nested regions.
|
||||
const int off0 = 0x000100; // region 0: +000100-000fff $2100-$2fff
|
||||
const int len0 = 0x0f00;
|
||||
const int adr0 = 0x2100;
|
||||
const int off1 = 0x000200;
|
||||
const int off1 = 0x000200; // region 1: +000200-0005ff $2200-$25ff
|
||||
const int len1 = 0x0400;
|
||||
const int adr1 = 0x2200;
|
||||
const int off2 = 0x000400;
|
||||
const int off2 = 0x000400; // region 2: +000400-0005ff* $2400-25ff
|
||||
const int len2 = FLOATING_LEN;
|
||||
const int adr2 = 0x2400;
|
||||
|
||||
AddressMapEntry ent0 = new AddressMapEntry(off0, len0, adr0, string.Empty, false);
|
||||
AddressMapEntry ent1 = new AddressMapEntry(off1, len1, adr1, string.Empty, false);
|
||||
AddressMapEntry ent2 = new AddressMapEntry(off2, len2, adr2, string.Empty, false);
|
||||
AddressMapEntry ent0 = new AddressMapEntry(off0, len0, adr0);
|
||||
AddressMapEntry ent1 = new AddressMapEntry(off1, len1, adr1);
|
||||
AddressMapEntry ent2 = new AddressMapEntry(off2, len2, adr2);
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent0));
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent1));
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent2));
|
||||
|
@ -1425,18 +1500,20 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test basic behavior in a simple linear map.
|
||||
private static bool Test_SimpleLinear() {
|
||||
const int mapLen = 0x8000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
const int off0 = 0x000000;
|
||||
// Simple map with no gaps at start or between.
|
||||
const int off0 = 0x000000; // region 0: +000000-0001ff $1000-$11ff
|
||||
const int len0 = 0x0200;
|
||||
const int adr0 = 0x1000;
|
||||
const int off1 = 0x000200;
|
||||
const int off1 = 0x000200; // region 1: +000200-0006ff $1200-$16ff
|
||||
const int len1 = 0x0500;
|
||||
const int adr1 = 0x1200;
|
||||
const int off2 = 0x000700;
|
||||
const int off2 = 0x000700; // region 3: +000700-0009ff $1700-$19ff
|
||||
const int len2 = 0x0300;
|
||||
const int adr2 = 0x1700;
|
||||
|
||||
|
@ -1465,6 +1542,7 @@ namespace CommonUtil {
|
|||
Test_Expect(true, ref result, map.RemoveEntry(off0, mapLen));
|
||||
Test_Expect(false, ref result, map.RemoveEntry(off0, mapLen));
|
||||
|
||||
// Check some address mappings.
|
||||
Test_Expect(adr0, ref result, map.OffsetToAddress(off0));
|
||||
Test_Expect(adr1, ref result, map.OffsetToAddress(off1));
|
||||
Test_Expect(adr2, ref result, map.OffsetToAddress(off2));
|
||||
|
@ -1487,25 +1565,26 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test with floating region, and region with non-addressable gap.
|
||||
private static bool Test_SimpleFloatGap() {
|
||||
const int mapLen = 0x8000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
const int off0 = 0x001000;
|
||||
// Map has a non-addressable gap at the start; region #2 is nested non-addr.
|
||||
// Regions 0 and 1 have overlapping address spaces.
|
||||
const int off0 = 0x001000; // region 0: +001000-003fff* $1000-$3fff
|
||||
const int len0 = FLOATING_LEN;
|
||||
const int adr0 = 0x1000;
|
||||
const int off1 = 0x004000;
|
||||
const int off1 = 0x004000; // region 1: +004000-006fff $1200-51ff
|
||||
const int len1 = 0x3000;
|
||||
const int adr1 = 0x1200;
|
||||
const int off2 = 0x005000;
|
||||
const int off2 = 0x005000; // region 2: +005000-0050ff N/A
|
||||
const int len2 = 0x0100;
|
||||
const int adr2 = NON_ADDR;
|
||||
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1));
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(off0, len0, adr0));
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(off1, len1, adr1));
|
||||
|
||||
// Try to remove the implicit no-address zone.
|
||||
Test_Expect(false, ref result, map.RemoveEntry(0, off0));
|
||||
|
@ -1534,42 +1613,43 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test construction with various nesting scenarios.
|
||||
private static bool Test_Nested() {
|
||||
AddressMap map = new AddressMap(0x8000);
|
||||
bool result = true;
|
||||
// Nested with shared start offset.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000100, 0x0400, 0x4000, "preA0", false));
|
||||
map.AddEntry(0x000100, 0x0400, 0x4000, "preA0", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000100, 0x0100, 0x7000, "preA1", false));
|
||||
map.AddEntry(0x000100, 0x0100, 0x7000, "preA1", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000100, 0x0300, 0x5000, "preA2", false));
|
||||
map.AddEntry(0x000100, 0x0300, 0x5000, "preA2", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000100, 0x0200, 0x6000, "preA3", false));
|
||||
map.AddEntry(0x000100, 0x0200, 0x6000, "preA3", false, false, false));
|
||||
// Add a couple of floaters.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x0000ff, FLOATING_LEN, 0x30ff, "preA4", false));
|
||||
map.AddEntry(0x0000ff, FLOATING_LEN, 0x30ff, "preA4", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000101, FLOATING_LEN, 0x3101, "preA5", false));
|
||||
map.AddEntry(0x000101, FLOATING_LEN, 0x3101, "preA5", false, false, false));
|
||||
Test_Expect(AddResult.OverlapFloating, ref result,
|
||||
map.AddEntry(0x000100, FLOATING_LEN, 0x3100, "preA6", false));
|
||||
map.AddEntry(0x000100, FLOATING_LEN, 0x3100, "preA6", false, false, false));
|
||||
|
||||
// Nested with shared end offset.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000fff, FLOATING_LEN, 0x3fff, "preB0", false));
|
||||
map.AddEntry(0x000fff, FLOATING_LEN, 0x3fff, "preB0", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001200, 0x0200, 0x6000, "preB1", false));
|
||||
map.AddEntry(0x001200, 0x0200, 0x6000, "preB1", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001000, 0x0400, 0x4000, "preB2", false));
|
||||
map.AddEntry(0x001000, 0x0400, 0x4000, "preB2", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001100, 0x0300, 0x5000, "preB3", false));
|
||||
map.AddEntry(0x001100, 0x0300, 0x5000, "preB3", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001300, 0x0100, 0x7000, "preB4", false));
|
||||
map.AddEntry(0x001300, 0x0100, 0x7000, "preB4", false, false, false));
|
||||
// Single-byte region at start and end.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001200, 1, 0x8200, "preB5", false));
|
||||
map.AddEntry(0x001200, 1, 0x8200, "preB5", false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x0013ff, 1, 0x83ff, "preB6", false));
|
||||
map.AddEntry(0x0013ff, 1, 0x83ff, "preB6", false, false, false));
|
||||
|
||||
// Nested with no common edge, building from outside-in.
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x0800, 0x4000));
|
||||
|
@ -1607,20 +1687,27 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Look up addresses from different initial regions.
|
||||
private static bool Test_Cross() {
|
||||
const int mapLen = 0x4000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
// Region 0: +000000-001fff $8000-9fff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x2000, 0x8000));
|
||||
// Region 1: +002000-003fff $8000-9fff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x2000, 0x8000));
|
||||
// Region 2: +002100-0022ff $e100-e2ff (overlaps with region 1).
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002100, 0x0200, 0xe100));
|
||||
// Region 3: +003100-0032ff $f100-f2ff (overlaps with region 1).
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x003100, 0x0200, 0xf100));
|
||||
|
||||
// Look up address in region 3, from different regions.
|
||||
Test_Expect(0x003105, ref result, map.AddressToOffset(0x000000, 0xf105));
|
||||
Test_Expect(0x003105, ref result, map.AddressToOffset(0x002100, 0xf105));
|
||||
Test_Expect(0x003105, ref result, map.AddressToOffset(0x003100, 0xf105));
|
||||
|
||||
// Look up address in region 2, from different regions.
|
||||
Test_Expect(0x002105, ref result, map.AddressToOffset(0x000000, 0xe105));
|
||||
Test_Expect(0x002105, ref result, map.AddressToOffset(0x002100, 0xe105));
|
||||
Test_Expect(0x002105, ref result, map.AddressToOffset(0x003100, 0xe105));
|
||||
|
@ -1643,28 +1730,29 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test resolution across nested regions with no shared start/end.
|
||||
private static bool Test_Pyramids() {
|
||||
const int mapLen = 0xc000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
// Pyramid shape, all regions start at same address except last.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x000000, 0x6000, 0x8000));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x001000, 0x4000, 0x8000));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x002000, 0x2000, 0x7fff));
|
||||
// Nested pyramid shape, all regions start at same address except last.
|
||||
// Region 0: +000000-005fff $8000-dfff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x6000, 0x8000));
|
||||
// Region 1: +001000-005fff $8000-bfff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x001000, 0x4000, 0x8000));
|
||||
// Region 2: +002000-003fff $7fff-9ffe
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x2000, 0x7fff));
|
||||
|
||||
// Second pyramid.
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x006000, 0x6000, 0x8000));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x007000, 0x4000, 0x8000));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(0x008000, 0x2000, 0x8000));
|
||||
// Region 3: +006000-00bfff $8000-dfff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x006000, 0x6000, 0x8000));
|
||||
// Region 4: +007000-00afff $8000-bfff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x007000, 0x4000, 0x8000));
|
||||
// Region 5: +008000-009fff $8000-9fff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x008000, 0x2000, 0x8000));
|
||||
|
||||
// Children take priority over the start node.
|
||||
// Children take priority over the start node. These all resolve in region 2.
|
||||
Test_Expect(0x002001, ref result, map.AddressToOffset(0x000000, 0x8000));
|
||||
Test_Expect(0x003000, ref result, map.AddressToOffset(0x000000, 0x8fff));
|
||||
Test_Expect(0x002001, ref result, map.AddressToOffset(0x001000, 0x8000));
|
||||
|
@ -1672,19 +1760,26 @@ namespace CommonUtil {
|
|||
Test_Expect(0x002001, ref result, map.AddressToOffset(0x002000, 0x8000));
|
||||
Test_Expect(0x002000, ref result, map.AddressToOffset(0x000000, 0x7fff));
|
||||
|
||||
// These resolve in region 0.
|
||||
Test_Expect(0x005000, ref result, map.AddressToOffset(0x000000, 0xd000));
|
||||
Test_Expect(0x005000, ref result, map.AddressToOffset(0x003000, 0xd000));
|
||||
|
||||
// These fail because $c000-cfff only exists in region 0, and maps to
|
||||
// offsets +004000-004fff, but region 1 (its child) spans the same range
|
||||
// of offsets with different addresses.
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0xc000));
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0xcfff));
|
||||
|
||||
// These resolve in region 5.
|
||||
Test_Expect(0x008000, ref result, map.AddressToOffset(0x006000, 0x8000));
|
||||
Test_Expect(0x008000, ref result, map.AddressToOffset(0x007000, 0x8000));
|
||||
Test_Expect(0x008000, ref result, map.AddressToOffset(0x008000, 0x8000));
|
||||
Test_Expect(0x008000, ref result, map.AddressToOffset(0x00bfff, 0x8000));
|
||||
|
||||
// $7fff doesn't exist in second chunk, so we have to go back to first to find it.
|
||||
// $7fff doesn't exist in second pyramid, so we have to go back to first to find it.
|
||||
Test_Expect(0x002000, ref result, map.AddressToOffset(0x008000, 0x7fff));
|
||||
// Address $a000 exists in region 4, at offset +009000, but that's overlapped
|
||||
// by region 5 (its child) with a different address.
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x008000, 0xa000));
|
||||
|
||||
// inside
|
||||
|
@ -1703,28 +1798,38 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test some region overlap edge cases.
|
||||
private static bool Test_OddOverlap() {
|
||||
const int mapLen = 0x1000;
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
bool result = true;
|
||||
|
||||
// Top region spans full map.
|
||||
// Top region spans full map. +000000-000fff $1000-1fff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, mapLen, 0x1000));
|
||||
// Parent region covers next two.
|
||||
// Parent region covers next two. +000000-0003ff $1000-13ff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x0400, 0x1000));
|
||||
// Floating region.
|
||||
// Floating region. +000100-0001ff* $2000-20ff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000100, FLOATING_LEN, 0x2000));
|
||||
// Fixed region follows.
|
||||
// Fixed region follows. +000200-0002ff $3000-30ff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000200, 0x0100, 0x3000));
|
||||
|
||||
//string mapStr = map.FormatAddressMap(); // DEBUG - format the map and
|
||||
//Debug.WriteLine(mapStr); // DEBUG - print it to the console
|
||||
|
||||
Test_Expect(0x00017f, ref result, map.AddressToOffset(0x000000, 0x207f));
|
||||
Test_Expect(0x00027f, ref result, map.AddressToOffset(0x000000, 0x307f));
|
||||
Test_Expect(0x000180, ref result, map.AddressToOffset(0x000000, 0x2080));
|
||||
|
||||
// Add a region that starts in the middle of the floating region (becoming
|
||||
// a sibling), and ends after the fixed region (becoming its parent).
|
||||
// +000180-00037f $4000-41ff
|
||||
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000180, 0x0200, 0x4000));
|
||||
// Remove it.
|
||||
|
||||
Test_Expect(0x00017f, ref result, map.AddressToOffset(0x000000, 0x207f));
|
||||
Test_Expect(0x00027f, ref result, map.AddressToOffset(0x000000, 0x307f));
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0x2080));
|
||||
|
||||
// Remove the region we just added. The float region should flex back out.
|
||||
Test_Expect(true, ref result, map.RemoveEntry(0x000180, 0x0200));
|
||||
Test_Expect(0x000180, ref result, map.AddressToOffset(0x000000, 0x2080));
|
||||
|
||||
// Add a region that starts in the middle of the floating region and ends after
|
||||
// the parent. Since this crosses the parent's end boundary and doesn't share
|
||||
|
@ -1736,6 +1841,151 @@ namespace CommonUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Test interaction between isolated regions.
|
||||
private static bool Test_Isolation() {
|
||||
const int mapLen = 0x8000;
|
||||
bool result = true;
|
||||
|
||||
const int off0 = 0x001000; // region 0: +001000-003fff $1000-$3fff
|
||||
const int len0 = 0x3000;
|
||||
const int adr0 = 0x1000;
|
||||
const int off1 = 0x002000; // region 1: +002000-002fff $2000-$2fff
|
||||
const int len1 = 0x1000;
|
||||
const int adr1 = 0x2000;
|
||||
const int off2 = 0x004000; // region 2: +004000-006fff $4000-$6fff
|
||||
const int len2 = 0x3000;
|
||||
const int adr2 = 0x4000;
|
||||
const int off3 = 0x005000; // region 3: +005000-005fff $8000-$8fff
|
||||
const int len3 = 0x1000;
|
||||
const int adr3 = 0x8000;
|
||||
|
||||
// Map: all open
|
||||
AddressMap map = new AddressMap(mapLen);
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off3, len3, adr3, string.Empty, false, false, false));
|
||||
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x5005)); // hole
|
||||
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
|
||||
|
||||
// Map: inner regions 1 and 3 disallow inward
|
||||
map = new AddressMap(mapLen);
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1, string.Empty, true, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off3, len3, adr3, string.Empty, true, false, false));
|
||||
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
|
||||
|
||||
// Map: inner regions 1 and 3 disallow outward
|
||||
map = new AddressMap(mapLen);
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1, string.Empty, false, true, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off3, len3, adr3, string.Empty, false, true, false));
|
||||
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
|
||||
|
||||
// Map: region 0 disallows inward and outward
|
||||
map = new AddressMap(mapLen);
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0, string.Empty, true, true, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off3, len3, adr3, string.Empty, false, false, false));
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x001000, 0x1005)); // 0 -> 0
|
||||
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
|
||||
|
||||
// Map: region 3 disallows inward and outward
|
||||
map = new AddressMap(mapLen);
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
|
||||
Test_Expect(AddResult.Okay, ref result,
|
||||
map.AddEntry(off3, len3, adr3, string.Empty, true, true, false));
|
||||
Test_Expect(0x005005, ref result, map.AddressToOffset(0x005000, 0x8005)); // 3 -> 3
|
||||
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
|
||||
Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
|
||||
Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
|
||||
Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
|
||||
Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool Test() {
|
||||
bool ok = true;
|
||||
ok &= Test_Primitives();
|
||||
|
@ -1746,6 +1996,11 @@ namespace CommonUtil {
|
|||
ok &= Test_Cross();
|
||||
ok &= Test_Pyramids();
|
||||
ok &= Test_OddOverlap();
|
||||
ok &= Test_Isolation();
|
||||
|
||||
// Do this to get a visualization:
|
||||
//string mapStr = map.FormatAddressMap(); // DEBUG - format the map and
|
||||
//Debug.WriteLine(mapStr); // DEBUG - print it to the console
|
||||
|
||||
Debug.WriteLine("AddressMap: test complete (ok=" + ok + ")");
|
||||
return ok;
|
||||
|
|
|
@ -42,10 +42,10 @@ namespace CommonUtil {
|
|||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Usage:
|
||||
/// AppDomain.CurrentDomain.UnhandledException +=
|
||||
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
|
||||
/// <code>AppDomain.CurrentDomain.UnhandledException +=
|
||||
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);</code>
|
||||
///
|
||||
/// Thanks: https://stackoverflow.com/a/21308327/294248
|
||||
/// Thanks: <see href="https://stackoverflow.com/a/21308327/294248"/>.
|
||||
/// </remarks>
|
||||
public static void CrashReporter(object sender, UnhandledExceptionEventArgs e) {
|
||||
const string CRASH_PATH = @"CrashLog.txt";
|
||||
|
@ -80,7 +80,7 @@ namespace CommonUtil {
|
|||
/// faster than setting array elements individually.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// From https://stackoverflow.com/a/18659408/294248
|
||||
/// From <see href="https://stackoverflow.com/a/18659408/294248"/>.
|
||||
///
|
||||
/// Invokes Array.Copy() on overlapping elements. Other approaches involve using
|
||||
/// Buffer.BlockCopy or unsafe code. Apparently .NET Core has an Array.Fill(), but
|
||||
|
|
|
@ -346,6 +346,12 @@ namespace CommonUtil {
|
|||
" height=" + grb.ImageHeight);
|
||||
Debug.WriteLine(" localCT=" + grb.LocalColorTableFlag + " size=" +
|
||||
grb.LocalColorTableSize + " itrl=" + grb.InterlaceFlag);
|
||||
for (int i = 0; i < grb.LocalColorTable.Length; i += 3) {
|
||||
Debug.WriteLine(" " + (i / 3) + ": $" +
|
||||
grb.LocalColorTable[i].ToString("x2") + " $" +
|
||||
grb.LocalColorTable[i + 1].ToString("x2") + " $" +
|
||||
grb.LocalColorTable[i + 2].ToString("x2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,5 @@ license. The text below must be included in Derivative Works per the terms.]
|
|||
----------
|
||||
|
||||
This product contains source code or data files from 6502bench. You can
|
||||
visit the project web page at https://6502bench.com/ .
|
||||
visit the project web page at https://6502bench.com/ or
|
||||
https://fadden.github.io/6502bench .
|
||||
|
|
|
@ -323,7 +323,8 @@ namespace PluginCommon {
|
|||
/// Will be null for direct-color images. Do not modify.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's possible, but weird, for the array to have a length of zero.
|
||||
/// It's possible, but weird, for the array to have a length of zero. For best results
|
||||
/// with GIF images, only one palette entry should be transparent.
|
||||
/// </remarks>
|
||||
int[] GetPalette();
|
||||
|
||||
|
@ -453,7 +454,8 @@ namespace PluginCommon {
|
|||
Dense,
|
||||
Fill,
|
||||
Uninit,
|
||||
Junk
|
||||
Junk,
|
||||
BinaryInclude
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -64,6 +64,12 @@ namespace PluginCommon {
|
|||
return mPalette[pix];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color index for a single pixel.
|
||||
/// </summary>
|
||||
/// <param name="x">X coordinate.</param>
|
||||
/// <param name="y">Y coordinate.</param>
|
||||
/// <returns>Color index.</returns>
|
||||
public byte GetPixelIndex(int x, int y) {
|
||||
return mData[x + y * Width];
|
||||
}
|
||||
|
@ -180,7 +186,7 @@ namespace PluginCommon {
|
|||
/// <remarks>
|
||||
/// Might want a way to specify that the background shouldn't be drawn at all.
|
||||
/// </remarks>
|
||||
/// <param name="vb">Bitma to draw on.</param>
|
||||
/// <param name="vb">Bitmap to draw on.</param>
|
||||
/// <param name="ch">Character to draw.</param>
|
||||
/// <param name="xc">X coord of upper-left pixel.</param>
|
||||
/// <param name="yc">Y coord of upper-left pixel.</param>
|
||||
|
|
15
README.md
15
README.md
|
@ -122,8 +122,8 @@ The zero-page argument for the Rockwell BBR/BBS instructions cannot be
|
|||
formatted.
|
||||
|
||||
To learn about other areas for potential future development, visit the
|
||||
wiki section for the
|
||||
[current "TO DO" list](https://github.com/fadden/6502bench/wiki/TO-DO-List).
|
||||
wiki section for the current
|
||||
["TO DO" list](https://github.com/fadden/6502bench/wiki/TO-DO-List).
|
||||
|
||||
To learn about the past, check the
|
||||
[change log](https://github.com/fadden/6502bench/wiki/Change-Log).
|
||||
|
@ -139,13 +139,12 @@ You need to have Microsoft .NET Framework v4.6.2 or later installed. Most
|
|||
people will already have this. If SourceGen doesn't seem to want to start,
|
||||
download the latest version (currently v4.8)
|
||||
[directly from Microsoft](https://dotnet.microsoft.com/download/dotnet-framework/net48).
|
||||
The framework requires Win7 SP1, Win8.1, or Win10 updated through at least
|
||||
the Anniversary Update (1607). (One user who had trouble with the 4.7.2
|
||||
installer was able to get the 4.6.2 installer to work.)
|
||||
The framework requires Win7 SP1, Win8.1, Win10 updated through at least the
|
||||
Anniversary Update (1607), or Win11. (One user who had trouble with the
|
||||
4.7.2 installer was able to get the 4.6.2 installer to work.)
|
||||
|
||||
SourceGen does not currently run on Linux or Mac OS X. My understanding is
|
||||
that .NET apps don't work under WINE, so it can only be run on a full
|
||||
Windows system emulation.
|
||||
SourceGen does not run natively on Linux or Mac OS. It is reported
|
||||
to work with recent versions (v9+) of the [Wine emulation layer](https://winehq.org/).
|
||||
|
||||
(SourceGen versions 1.0 and 1.1 used the WinForms API, which has been
|
||||
implemented for [Mono](https://www.mono-project.com/), but after
|
||||
|
|
|
@ -25,6 +25,6 @@ namespace SourceGen {
|
|||
/// SourceGen version number.
|
||||
/// </summary>
|
||||
public static readonly CommonUtil.Version ProgramVersion =
|
||||
new CommonUtil.Version(1, 8, 3, CommonUtil.Version.PreRelType.Dev, 1);
|
||||
new CommonUtil.Version(1, 9, 0, CommonUtil.Version.PreRelType.Dev, 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,9 +124,13 @@ namespace SourceGen {
|
|||
// Source generation settings.
|
||||
public const string SRCGEN_DEFAULT_ASM = "srcgen-default-asm";
|
||||
public const string SRCGEN_ADD_IDENT_COMMENT = "srcgen-add-ident-comment";
|
||||
public const string SRCGEN_LONG_LABEL_NEW_LINE = "srcgen-long-label-new-line";
|
||||
public const string SRCGEN_LABEL_NEW_LINE = "srcgen-label-new-line";
|
||||
public const string SRCGEN_SHOW_CYCLE_COUNTS = "srcgen-show-cycle-counts";
|
||||
|
||||
// Label file generation settings.
|
||||
public const string LABGEN_FORMAT = "labgen-format";
|
||||
public const string LABGEN_INCLUDE_AUTO = "labgen-include-auto";
|
||||
|
||||
// Assembler settings prefix
|
||||
public const string ASM_CONFIG_PREFIX = "asm-config-";
|
||||
|
||||
|
@ -187,6 +191,7 @@ namespace SourceGen {
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public AppSettings GetCopy() {
|
||||
// TODO: make this a copy constructor?
|
||||
AppSettings copy = new AppSettings();
|
||||
//copy.mSettings.EnsureCapacity(mSettings.Count);
|
||||
foreach (KeyValuePair<string, string> kvp in mSettings) {
|
||||
|
@ -202,7 +207,7 @@ namespace SourceGen {
|
|||
/// discarding the object itself, which is useful in case something has cached a
|
||||
/// reference to the singleton.
|
||||
/// </summary>
|
||||
/// <param name="newSettings"></param>
|
||||
/// <param name="newSettings">Object with new settings.</param>
|
||||
public void ReplaceSettings(AppSettings newSettings) {
|
||||
// Clone the new list, and stuff it into the old object. This way the
|
||||
// objects aren't sharing lists.
|
||||
|
@ -213,8 +218,7 @@ namespace SourceGen {
|
|||
/// <summary>
|
||||
/// Merges settings from another settings object into this one.
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="newSettings"></param>
|
||||
/// <param name="newSettings">Object with new settings.</param>
|
||||
public void MergeSettings(AppSettings newSettings) {
|
||||
foreach (KeyValuePair<string, string> kvp in newSettings.mSettings) {
|
||||
mSettings[kvp.Key] = kvp.Value;
|
||||
|
@ -287,21 +291,20 @@ namespace SourceGen {
|
|||
/// <summary>
|
||||
/// Retrieves an enumerated value setting.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Enumerated type.</typeparam>
|
||||
/// <param name="name">Setting name.</param>
|
||||
/// <param name="enumType">Enum type that the value is part of.</param>
|
||||
/// <param name="defaultValue">Setting default value.</param>
|
||||
/// <returns>The value found, or the default value if no setting with the specified
|
||||
/// name exists, or the stored value is not a member of the specified enumerated
|
||||
/// type.</returns>
|
||||
public int GetEnum(string name, Type enumType, int defaultValue) {
|
||||
/// name exists, or the stored value is not a member of the enumeration.</returns>
|
||||
public T GetEnum<T>(string name, T defaultValue) {
|
||||
if (!mSettings.TryGetValue(name, out string valueStr)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
object o = Enum.Parse(enumType, valueStr);
|
||||
return (int)o;
|
||||
object o = Enum.Parse(typeof(T), valueStr);
|
||||
return (T)o;
|
||||
} catch (ArgumentException ae) {
|
||||
Debug.WriteLine("Failed to parse " + valueStr + " (enum " + enumType + "): " +
|
||||
Debug.WriteLine("Failed to parse '" + valueStr + "' (enum " + typeof(T) + "): " +
|
||||
ae.Message);
|
||||
return defaultValue;
|
||||
}
|
||||
|
@ -310,11 +313,22 @@ namespace SourceGen {
|
|||
/// <summary>
|
||||
/// Sets an enumerated setting.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The value is output to the settings file as a string, rather than an integer, allowing
|
||||
/// the correct handling even if the enumerated values are renumbered.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">Enumerated type.</typeparam>
|
||||
/// <param name="name">Setting name.</param>
|
||||
/// <param name="enumType">Enum type.</param>
|
||||
/// <param name="value">Setting value (integer enum index).</param>
|
||||
public void SetEnum(string name, Type enumType, int value) {
|
||||
string newVal = Enum.GetName(enumType, value);
|
||||
public void SetEnum<T>(string name, T value) {
|
||||
if (value == null) {
|
||||
throw new NotImplementedException("Can't handle a null-valued enum type");
|
||||
}
|
||||
string newVal = Enum.GetName(typeof(T), value);
|
||||
if (newVal == null) {
|
||||
Debug.WriteLine("Unable to get enum name type=" + typeof(T) + " value=" + value);
|
||||
return;
|
||||
}
|
||||
if (!mSettings.TryGetValue(name, out string oldValue) || oldValue != newVal) {
|
||||
mSettings[name] = newVal;
|
||||
Dirty = true;
|
||||
|
|
|
@ -56,15 +56,20 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public int StartOffset { get { return 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// List of binary include sections found in the project.
|
||||
/// </summary>
|
||||
private List<BinaryInclude.Excision> mBinaryIncludes = new List<BinaryInclude.Excision>();
|
||||
|
||||
/// <summary>
|
||||
/// Working directory, i.e. where we write our output file(s).
|
||||
/// </summary>
|
||||
private string mWorkDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// If set, long labels get their own line.
|
||||
/// Influences whether labels are put on their own line.
|
||||
/// </summary>
|
||||
private bool mLongLabelNewLine;
|
||||
private GenCommon.LabelPlacement mLabelNewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Output column widths.
|
||||
|
@ -139,6 +144,7 @@ namespace SourceGen.AsmGen {
|
|||
{ "Uninit", "!skip" },
|
||||
//Junk
|
||||
{ "Align", "!align" },
|
||||
{ "BinaryInclude", "!binary" },
|
||||
{ "StrGeneric", "!text" }, // can use !xor for high ASCII
|
||||
//StrReverse
|
||||
//StrNullTerm
|
||||
|
@ -198,7 +204,8 @@ namespace SourceGen.AsmGen {
|
|||
mFileNameBase = fileNameBase;
|
||||
Settings = settings;
|
||||
|
||||
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
|
||||
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
|
||||
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
|
||||
AssemblerInfo.Id.Acme);
|
||||
|
@ -302,7 +309,7 @@ namespace SourceGen.AsmGen {
|
|||
}
|
||||
mOutStream = null;
|
||||
|
||||
return new GenerationResults(pathNames, string.Empty);
|
||||
return new GenerationResults(pathNames, string.Empty, mBinaryIncludes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -482,6 +489,12 @@ namespace SourceGen.AsmGen {
|
|||
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
opcodeStr = sDataOpNames.BinaryInclude;
|
||||
string biPath = BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
operandStr = '"' + biPath + '"';
|
||||
mBinaryIncludes.Add(new BinaryInclude.Excision(offset, length, biPath));
|
||||
break;
|
||||
case FormatDescriptor.Type.StringGeneric:
|
||||
case FormatDescriptor.Type.StringReverse:
|
||||
case FormatDescriptor.Type.StringNullTerm:
|
||||
|
@ -663,11 +676,13 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public void OutputLine(string label, string opcode, string operand, string comment) {
|
||||
// Break the line if the label is long and it's not a .EQ directive.
|
||||
if (!string.IsNullOrEmpty(label) &&
|
||||
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
|
||||
!string.Equals(opcode, sDataOpNames.EquDirective,
|
||||
StringComparison.InvariantCultureIgnoreCase)) {
|
||||
|
||||
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
|
||||
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
|
||||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
|
||||
label.Length >= mColumnWidths[0])) {
|
||||
mOutStream.WriteLine(label);
|
||||
label = string.Empty;
|
||||
}
|
||||
|
|
|
@ -51,15 +51,20 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public int StartOffset { get { return 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// List of binary include sections found in the project.
|
||||
/// </summary>
|
||||
private List<BinaryInclude.Excision> mBinaryIncludes = new List<BinaryInclude.Excision>();
|
||||
|
||||
/// <summary>
|
||||
/// Working directory, i.e. where we write our output file(s).
|
||||
/// </summary>
|
||||
private string mWorkDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// If set, long labels get their own line.
|
||||
/// Influences whether labels are put on their own line.
|
||||
/// </summary>
|
||||
private bool mLongLabelNewLine;
|
||||
private GenCommon.LabelPlacement mLabelNewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Output column widths.
|
||||
|
@ -138,6 +143,8 @@ namespace SourceGen.AsmGen {
|
|||
{ "Dense", ".byte" }, // really just just comma-separated bytes
|
||||
{ "Uninit", ".res" },
|
||||
//Junk
|
||||
//Align
|
||||
{ "BinaryInclude", ".incbin" },
|
||||
{ "StrGeneric", ".byte" },
|
||||
//StrReverse
|
||||
{ "StrNullTerm", ".asciiz" },
|
||||
|
@ -188,7 +195,8 @@ namespace SourceGen.AsmGen {
|
|||
mFileNameBase = fileNameBase;
|
||||
Settings = settings;
|
||||
|
||||
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
|
||||
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
|
||||
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
|
||||
AssemblerInfo.Id.Cc65);
|
||||
|
@ -261,7 +269,7 @@ namespace SourceGen.AsmGen {
|
|||
}
|
||||
mOutStream = null;
|
||||
|
||||
return new GenerationResults(pathNames, string.Empty);
|
||||
return new GenerationResults(pathNames, string.Empty, mBinaryIncludes);
|
||||
}
|
||||
|
||||
private void GenerateLinkerScript(StreamWriter sw) {
|
||||
|
@ -469,6 +477,12 @@ namespace SourceGen.AsmGen {
|
|||
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
opcodeStr = sDataOpNames.BinaryInclude;
|
||||
string biPath = BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
operandStr = '"' + biPath + '"';
|
||||
mBinaryIncludes.Add(new BinaryInclude.Excision(offset, length, biPath));
|
||||
break;
|
||||
case FormatDescriptor.Type.StringGeneric:
|
||||
case FormatDescriptor.Type.StringReverse:
|
||||
case FormatDescriptor.Type.StringNullTerm:
|
||||
|
@ -659,7 +673,10 @@ namespace SourceGen.AsmGen {
|
|||
StringComparison.InvariantCultureIgnoreCase)) {
|
||||
label += ':';
|
||||
|
||||
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
|
||||
if (!string.IsNullOrEmpty(opcode) &&
|
||||
(mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
|
||||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
|
||||
label.Length >= mColumnWidths[0]))) {
|
||||
mOutStream.WriteLine(label);
|
||||
label = string.Empty;
|
||||
}
|
||||
|
|
|
@ -51,15 +51,20 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public int StartOffset { get { return 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// List of binary include sections found in the project.
|
||||
/// </summary>
|
||||
private List<BinaryInclude.Excision> mBinaryIncludes = new List<BinaryInclude.Excision>();
|
||||
|
||||
/// <summary>
|
||||
/// Working directory, i.e. where we write our output file(s).
|
||||
/// </summary>
|
||||
private string mWorkDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// If set, long labels get their own line.
|
||||
/// Influences whether labels are put on their own line.
|
||||
/// </summary>
|
||||
private bool mLongLabelNewLine;
|
||||
private GenCommon.LabelPlacement mLabelNewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Output column widths.
|
||||
|
@ -133,6 +138,7 @@ namespace SourceGen.AsmGen {
|
|||
{ "Uninit", "ds" },
|
||||
//Junk
|
||||
//Align
|
||||
{ "BinaryInclude", "putbin" },
|
||||
{ "StrGeneric", "asc" },
|
||||
{ "StrReverse", "rev" },
|
||||
//StrNullTerm
|
||||
|
@ -174,7 +180,8 @@ namespace SourceGen.AsmGen {
|
|||
mFileNameBase = fileNameBase;
|
||||
Settings = settings;
|
||||
|
||||
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
|
||||
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
|
||||
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
|
||||
AssemblerInfo.Id.Merlin32);
|
||||
|
@ -242,7 +249,7 @@ namespace SourceGen.AsmGen {
|
|||
}
|
||||
mOutStream = null;
|
||||
|
||||
return new GenerationResults(pathNames, string.Empty);
|
||||
return new GenerationResults(pathNames, string.Empty, mBinaryIncludes);
|
||||
}
|
||||
|
||||
// IGenerator
|
||||
|
@ -346,6 +353,12 @@ namespace SourceGen.AsmGen {
|
|||
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
opcodeStr = sDataOpNames.BinaryInclude;
|
||||
string biPath = BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
operandStr = biPath; // no quotes
|
||||
mBinaryIncludes.Add(new BinaryInclude.Excision(offset, length, biPath));
|
||||
break;
|
||||
case FormatDescriptor.Type.StringGeneric:
|
||||
case FormatDescriptor.Type.StringReverse:
|
||||
case FormatDescriptor.Type.StringNullTerm:
|
||||
|
@ -606,11 +619,15 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public void OutputLine(string label, string opcode, string operand, string comment) {
|
||||
// Split long label, but not on EQU directives (confuses the assembler).
|
||||
if (mLongLabelNewLine && label.Length >= mColumnWidths[0] &&
|
||||
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
|
||||
!string.Equals(opcode, sDataOpNames.EquDirective,
|
||||
StringComparison.InvariantCultureIgnoreCase)) {
|
||||
mOutStream.WriteLine(label);
|
||||
label = string.Empty;
|
||||
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
|
||||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
|
||||
label.Length >= mColumnWidths[0])) {
|
||||
mOutStream.WriteLine(label);
|
||||
label = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
mLineBuilder.Clear();
|
||||
|
|
|
@ -61,21 +61,27 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public LabelLocalizer Localizer { get { return mLocalizer; } }
|
||||
|
||||
// IGenerator
|
||||
public int StartOffset {
|
||||
get {
|
||||
return mHasPrgHeader ? 2 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of binary include sections found in the project.
|
||||
/// </summary>
|
||||
private List<BinaryInclude.Excision> mBinaryIncludes = new List<BinaryInclude.Excision>();
|
||||
|
||||
/// <summary>
|
||||
/// Working directory, i.e. where we write our output file(s).
|
||||
/// </summary>
|
||||
private string mWorkDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// If set, long labels get their own line.
|
||||
/// Influences whether labels are put on their own line.
|
||||
/// </summary>
|
||||
private bool mLongLabelNewLine;
|
||||
private GenCommon.LabelPlacement mLabelNewLine;
|
||||
|
||||
/// <summary>
|
||||
/// Output column widths.
|
||||
|
@ -158,6 +164,7 @@ namespace SourceGen.AsmGen {
|
|||
{ "Uninit", ".fill" },
|
||||
//Junk
|
||||
{ "Align", ".align" },
|
||||
{ "BinaryInclude", ".binary" },
|
||||
{ "StrGeneric", ".text" },
|
||||
//StrReverse
|
||||
{ "StrNullTerm", ".null" },
|
||||
|
@ -201,7 +208,8 @@ namespace SourceGen.AsmGen {
|
|||
mFileNameBase = fileNameBase;
|
||||
Settings = settings;
|
||||
|
||||
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
|
||||
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
|
||||
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
|
||||
AssemblerInfo.Id.Tass64);
|
||||
|
@ -322,7 +330,7 @@ namespace SourceGen.AsmGen {
|
|||
}
|
||||
mOutStream = null;
|
||||
|
||||
return new GenerationResults(pathNames, extraOptions);
|
||||
return new GenerationResults(pathNames, extraOptions, mBinaryIncludes);
|
||||
}
|
||||
|
||||
// IGenerator
|
||||
|
@ -576,6 +584,12 @@ namespace SourceGen.AsmGen {
|
|||
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
opcodeStr = sDataOpNames.BinaryInclude;
|
||||
string biPath = BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
operandStr = '"' + biPath + '"';
|
||||
mBinaryIncludes.Add(new BinaryInclude.Excision(offset, length, biPath));
|
||||
break;
|
||||
case FormatDescriptor.Type.StringGeneric:
|
||||
case FormatDescriptor.Type.StringReverse:
|
||||
case FormatDescriptor.Type.StringNullTerm:
|
||||
|
@ -771,13 +785,15 @@ namespace SourceGen.AsmGen {
|
|||
// IGenerator
|
||||
public void OutputLine(string label, string opcode, string operand, string comment) {
|
||||
// Break the line if the label is long and it's not a .EQ/.VAR directive.
|
||||
if (!string.IsNullOrEmpty(label) &&
|
||||
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
|
||||
!string.Equals(opcode, sDataOpNames.EquDirective,
|
||||
StringComparison.InvariantCultureIgnoreCase) &&
|
||||
!string.Equals(opcode, sDataOpNames.VarDirective,
|
||||
StringComparison.InvariantCultureIgnoreCase)) {
|
||||
|
||||
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
|
||||
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
|
||||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
|
||||
label.Length >= mColumnWidths[0])) {
|
||||
mOutStream.WriteLine(label);
|
||||
label = string.Empty;
|
||||
}
|
||||
|
|
225
SourceGen/AsmGen/BinaryInclude.cs
Normal file
225
SourceGen/AsmGen/BinaryInclude.cs
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Copyright 2024 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.IO;
|
||||
|
||||
namespace SourceGen.AsmGen {
|
||||
/// <summary>
|
||||
/// Helper functions for working with binary includes.
|
||||
/// </summary>
|
||||
public static class BinaryInclude {
|
||||
// Character placed at the start of a path as a check that the field holds what we
|
||||
// expect. If we want to modify the structure of the string, e.g. to add or remove
|
||||
// additional fields, we can change the character to something else.
|
||||
private static char PATH_PREFIX_CHAR = '\u2191'; // UPWARDS ARROW
|
||||
|
||||
/// <summary>
|
||||
/// Class to help when gathering up binary includes during asm gen.
|
||||
/// </summary>
|
||||
public class Excision {
|
||||
// Offset of start of region to excise.
|
||||
public int Offset { get; private set; }
|
||||
|
||||
// Length of region to excise.
|
||||
public int Length { get; private set; }
|
||||
|
||||
// Partial pathname of output file, as stored in the project.
|
||||
public string PathName { get; private set; }
|
||||
|
||||
// Full output file path, initially null, set by PrepareList().
|
||||
public string FullPath { get; set; }
|
||||
|
||||
public Excision(int offset, int length, string pathName) {
|
||||
Offset = offset;
|
||||
Length = length;
|
||||
PathName = pathName;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "[Exc: offset=+" + Offset.ToString("x6") + " len=" + Length +
|
||||
"path=\"" + PathName + "\" fullPath=\"" + FullPath + "\"]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the full path of each binary include output file. Checks for duplicates.
|
||||
/// Sorts the list by case-insensitive pathname.
|
||||
/// </summary>
|
||||
/// <param name="list">List of binary include excisions.</param>
|
||||
/// <param name="workDir">Working directory.</param>
|
||||
/// <param name="failMsg">On failure, a human-readable error message.</param>
|
||||
/// <returns>True on success.</returns>
|
||||
public static bool PrepareList(List<Excision> list, string workDir, out string failMsg) {
|
||||
// Normalize the pathname. This is not expected to fail.
|
||||
string fullWorkDir = Path.GetFullPath(workDir);
|
||||
|
||||
string oldCurrentDir = Environment.CurrentDirectory;
|
||||
try {
|
||||
Environment.CurrentDirectory = workDir;
|
||||
|
||||
foreach (Excision exc in list) {
|
||||
try {
|
||||
exc.FullPath = Path.GetFullPath(exc.PathName);
|
||||
} catch (Exception ex) {
|
||||
failMsg = "unable to get full path for binary include \"" +
|
||||
exc.PathName + "\": " + ex.Message;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!exc.FullPath.StartsWith(fullWorkDir)) {
|
||||
failMsg = "binary include path for \"" + exc.PathName +
|
||||
"\" resolved to parent directory";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Environment.CurrentDirectory = oldCurrentDir;
|
||||
}
|
||||
|
||||
// Check for duplicates. Assume filenames are case-insensitive.
|
||||
list.Sort(delegate (Excision a, Excision b) {
|
||||
return string.Compare(a.PathName, b.PathName,
|
||||
StringComparison.InvariantCultureIgnoreCase);
|
||||
});
|
||||
string prev = null;
|
||||
foreach (Excision exc in list) {
|
||||
if (prev != null && exc.FullPath == prev) {
|
||||
failMsg = "found multiple binary includes that output to \"" + prev + "\"";
|
||||
return false;
|
||||
}
|
||||
prev = exc.FullPath;
|
||||
}
|
||||
|
||||
failMsg = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the output file with the binary include data.
|
||||
/// </summary>
|
||||
/// <param name="exc">Binary include object, with full pathname computed.</param>
|
||||
/// <param name="data">Project data array.</param>
|
||||
/// <param name="failMsg">On failure, a human-readable error message.</param>
|
||||
/// <returns>True on success.</returns>
|
||||
public static bool GenerateOutputFile(Excision exc, byte[] data, out string failMsg) {
|
||||
if (exc.FullPath == null) {
|
||||
failMsg = "internal error";
|
||||
return false;
|
||||
}
|
||||
if (File.Exists(exc.FullPath)) {
|
||||
// Test the file length. If it's different, don't overwrite the existing file.
|
||||
// Make an exception if it's zero bytes long?
|
||||
long fileLen = new FileInfo(exc.FullPath).Length;
|
||||
if (exc.Length != fileLen) {
|
||||
failMsg = "output file \"" + exc.PathName + "\" exists and " +
|
||||
"has a different length (" + fileLen + " vs. " + exc.Length + ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Create any directories in the path.
|
||||
string dirName = Path.GetDirectoryName(exc.FullPath);
|
||||
Directory.CreateDirectory(dirName);
|
||||
// Create the file and copy the data into it.
|
||||
Debug.Assert(exc.Offset < data.Length && exc.Offset + exc.Length <= data.Length);
|
||||
using (Stream stream = new FileStream(exc.FullPath, FileMode.OpenOrCreate,
|
||||
FileAccess.ReadWrite, FileShare.None)) {
|
||||
stream.SetLength(0);
|
||||
stream.Write(data, exc.Offset, exc.Length);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
failMsg = "unable to create '" + exc.PathName + "': " + ex.Message;
|
||||
return false;
|
||||
}
|
||||
failMsg = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates a binary-include filename. We allow partial paths, but they're not allowed
|
||||
/// to ascend above the current directory. Does not access the filesystem.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The Path.GetFullPath() call hits the filesystem, which is undesirable for
|
||||
/// a check-as-you-type test. We just want to avoid having a "rooted" path or something
|
||||
/// with a ".." directory reference.</para>
|
||||
/// <para>This is intended as a simple measure to avoid having important files
|
||||
/// overwritten by an asm generation command. The file generator could employ other
|
||||
/// measures, e.g. checking to see if an existing output file has the same size. (Note
|
||||
/// some malicious individual could hand-edit the filename in the project file.)</para>
|
||||
/// <para>We screen the filename for illegal characters, though what works on one
|
||||
/// platform might not on another. We can't guarantee validity.</para>
|
||||
/// </remarks>
|
||||
/// <param name="pathName">Partial path to verify.</param>
|
||||
/// <returns>True if the path looks correct.</returns>
|
||||
public static bool ValidatePathName(string pathName) {
|
||||
if (string.IsNullOrEmpty(pathName)) {
|
||||
return false;
|
||||
}
|
||||
// In .NET Framework, IsPathRooted() will throw if invalid chars are found. This is
|
||||
// not a full syntax check, just a char test. The behavior changed in .NET Core 2.1.
|
||||
try {
|
||||
if (Path.IsPathRooted(pathName)) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Debug.WriteLine("GetFileName rejected pathname: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to screen out "../foo", "x/../y", "bar/..", without rejecting "..my..stuff..".
|
||||
// Normalize to forward-slash and split into components.
|
||||
string normal = pathName.Replace('\\', '/');
|
||||
string[] parts = normal.Split('/');
|
||||
foreach (string part in parts) {
|
||||
if ("..".Equals(part)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reject names with a double quote, so we don't have to figure out the quote-quoting
|
||||
// mechanism for every assembler.
|
||||
if (normal.Contains("\"")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a binary include pathname to a format suited for storage.
|
||||
/// </summary>
|
||||
/// <param name="pathName">Partial pathname.</param>
|
||||
/// <returns>String to store.</returns>
|
||||
public static string ConvertPathNameToStorage(string pathName) {
|
||||
return PATH_PREFIX_CHAR + pathName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the stored name back to a path prefix string.
|
||||
/// </summary>
|
||||
/// <param name="storageStr">Stored string.</param>
|
||||
/// <returns>Path prefix.</returns>
|
||||
public static string ConvertPathNameFromStorage(string storageStr) {
|
||||
if (string.IsNullOrEmpty(storageStr) || storageStr[0] != PATH_PREFIX_CHAR) {
|
||||
return "!BAD STORED NAME!";
|
||||
}
|
||||
return storageStr.Substring(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,11 +23,19 @@ using Asm65;
|
|||
using CommonUtil;
|
||||
|
||||
namespace SourceGen.AsmGen {
|
||||
/// <summary>
|
||||
/// Code common to all assembly source generators.
|
||||
/// </summary>
|
||||
public class GenCommon {
|
||||
public enum LabelPlacement {
|
||||
Unknown = 0,
|
||||
PreferSameLine,
|
||||
SplitIfTooLong,
|
||||
PreferSeparateLine,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates assembly source.
|
||||
///
|
||||
/// This code is common to all generators.
|
||||
/// </summary>
|
||||
/// <param name="gen">Reference to generator object (presumably the caller).</param>
|
||||
/// <param name="sw">Text output sink.</param>
|
||||
|
|
|
@ -288,10 +288,13 @@ namespace SourceGen.AsmGen {
|
|||
public class GenerationResults {
|
||||
public List<string> PathNames { get; private set; }
|
||||
public string ExtraOptions { get; private set; }
|
||||
public List<BinaryInclude.Excision> BinaryIncludes { get; private set; }
|
||||
|
||||
public GenerationResults(List<string> pathNames, string extraOptions) {
|
||||
public GenerationResults(List<string> pathNames, string extraOptions,
|
||||
List<BinaryInclude.Excision> binaryIncludes) {
|
||||
PathNames = CommonUtil.Container.CopyStringList(pathNames);
|
||||
ExtraOptions = extraOptions;
|
||||
BinaryIncludes = binaryIncludes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ limitations under the License.
|
|||
<DockPanel Grid.Column="3" Grid.Row="2">
|
||||
<TextBlock DockPanel.Dock="Left" Margin="0,1,0,0">Work directory:</TextBlock>
|
||||
<TextBox DockPanel.Dock="Right" Name="workDirectoryTextBox" Margin="8,0,0,0"
|
||||
Text="C:\this\that\theother"/>
|
||||
IsReadOnly="True" Text="C:\this\that\theother"/>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
|
||||
|
|
|
@ -285,6 +285,24 @@ namespace SourceGen.AsmGen.WpfGui {
|
|||
return;
|
||||
}
|
||||
|
||||
// Generate binary includes.
|
||||
if (!BinaryInclude.PrepareList(res.BinaryIncludes, mWorkDirectory,
|
||||
out string failMsg)) {
|
||||
MessageBox.Show(this, "Failed processing binary includes: " + failMsg,
|
||||
Res.Strings.ERR_FILE_GENERIC_CAPTION,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
} else {
|
||||
foreach (BinaryInclude.Excision exc in res.BinaryIncludes) {
|
||||
if (!BinaryInclude.GenerateOutputFile(exc, mProject.FileData,
|
||||
out string failMsg2)) {
|
||||
MessageBox.Show(this, "Failed processing binary include at +" +
|
||||
exc.Offset.ToString("x6") + ": " + failMsg2,
|
||||
Res.Strings.ERR_FILE_GENERIC_CAPTION,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResetElements();
|
||||
mGenerationResults = res;
|
||||
previewFileComboBox.Items.Clear();
|
||||
|
|
|
@ -1171,7 +1171,7 @@ namespace SourceGen {
|
|||
" (" + mAnalyzerTags[i] + ")");
|
||||
return false;
|
||||
}
|
||||
if (mAnattribs[offset].IsInstruction) {
|
||||
if (mAnattribs[i].IsInstruction) {
|
||||
LogW(offset, "SIDF rej: not for use with instructions");
|
||||
return false;
|
||||
}
|
||||
|
@ -1189,6 +1189,9 @@ namespace SourceGen {
|
|||
if (type == DataType.Fill && subType != DataSubType.None) {
|
||||
throw new PluginException("SIDF rej: fill data must use subType=None");
|
||||
}
|
||||
if (type == DataType.BinaryInclude && subType != DataSubType.None) {
|
||||
throw new PluginException("SIDF rej: binary-include data must use subType=None");
|
||||
}
|
||||
|
||||
if (isStringType && !isStringSub) {
|
||||
throw new PluginException("SIDF rej: bad type/subType combo: type=" +
|
||||
|
@ -1275,6 +1278,8 @@ namespace SourceGen {
|
|||
return FormatDescriptor.Type.Uninit;
|
||||
case DataType.Dense:
|
||||
return FormatDescriptor.Type.Dense;
|
||||
case DataType.BinaryInclude:
|
||||
return FormatDescriptor.Type.BinaryInclude;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
throw new PluginException("Instr format rej: unknown format type " + pluginType);
|
||||
|
|
|
@ -152,7 +152,7 @@ namespace SourceGen {
|
|||
|
||||
|
||||
/// <summary>
|
||||
/// The contents of the 65xx data file.
|
||||
/// The contents of the 65xx data file. Do not modify.
|
||||
/// </summary>
|
||||
public byte[] FileData { get { return mFileData; } }
|
||||
private byte[] mFileData;
|
||||
|
@ -1438,17 +1438,19 @@ namespace SourceGen {
|
|||
attr.OperandAddress >= 0 && attr.OperandOffset < 0) {
|
||||
// This is an instruction that hasn't been explicitly formatted. It
|
||||
// has an operand address, but not an offset, meaning it's a reference
|
||||
// to an address outside the scope of the file. See if it has a
|
||||
// platform symbol definition.
|
||||
// to an address outside the scope of the file -or- a reference to an address
|
||||
// region that we're not supposed to interact with (DisallowInbound on it
|
||||
// or DisallowOutbound on us). See if it has a platform symbol definition,
|
||||
// or perhaps an address region pre-label.
|
||||
//
|
||||
// It might seem unwise to examine the full symbol table, because it has
|
||||
// non-project non-platform symbols in it. However, any matching user
|
||||
// labels would have been applied already. Also, we want to ensure that
|
||||
// conflicting user labels take precedence, e.g. creating a user label "COUT"
|
||||
// will prevent a platform symbol with the same name from being visible.
|
||||
// Using the full symbol table is potentially a tad less efficient than
|
||||
// looking for a match exclusively in project/platform symbols, but it's
|
||||
// the correct thing to do.
|
||||
// labels would have been applied already (unless blocked by address region
|
||||
// isolation). Also, we want to ensure that conflicting user labels take
|
||||
// precedence, e.g. creating a user label "COUT" will prevent a platform
|
||||
// symbol with the same name from being visible. Using the full symbol
|
||||
// table is potentially a tad less efficient than looking for a match
|
||||
// exclusively in project/platform symbols, but it's the correct thing to do.
|
||||
OpDef op = CpuDef.GetOpDef(FileData[offset]);
|
||||
accType = op.MemEffect;
|
||||
address = attr.OperandAddress;
|
||||
|
@ -1493,10 +1495,24 @@ namespace SourceGen {
|
|||
if (sym == null && checkNearby && (address & 0xffff) < 0xffff &&
|
||||
address > 0x0000ff) {
|
||||
sym = SymbolTable.FindNonVariableByAddress(address + 1, accType);
|
||||
if (sym != null && sym.SymbolSource != Symbol.Source.Project &&
|
||||
sym.SymbolSource != Symbol.Source.Platform) {
|
||||
Debug.WriteLine("Applying non-platform in GeneratePlatform: " + sym);
|
||||
// should be okay to do this
|
||||
}
|
||||
if (sym != null && sym.SymbolSource != Symbol.Source.Project &&
|
||||
sym.SymbolSource != Symbol.Source.Platform &&
|
||||
sym.SymbolSource != Symbol.Source.AddrPreLabel) {
|
||||
// If we matched to something other than a project/platform symbol or
|
||||
// pre-label (which are expected to be outside the file area), make sure
|
||||
// we're not doing an invalid cross-region reference.
|
||||
if (AddrMap.AddressToOffset(offset, sym.Value) >= 0) {
|
||||
Debug.WriteLine("GeneratePlatform applying non-platform at +" +
|
||||
offset.ToString("x6") + ": " + sym);
|
||||
} else {
|
||||
Debug.WriteLine("GeneratePlatform not applying at +" +
|
||||
offset.ToString("x6") + ": " + sym);
|
||||
// Do a secondary scan, looking only at project/platform/pre-labels.
|
||||
sym = SymbolTable.FindProjPlatPreByAddress(address, accType);
|
||||
if (sym != null) {
|
||||
Debug.WriteLine(" ...found matching proj/plat: " + sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1534,7 +1550,7 @@ namespace SourceGen {
|
|||
//
|
||||
// We want to tag both. So if "LDA $1000" becomes "LDA label-2", we want to
|
||||
// add a numeric reference to the code at $1000, and a symbolic reference to the
|
||||
// labe at $1002, that point back to the LDA instruction. These are presented
|
||||
// label at $1002, that point back to the LDA instruction. These are presented
|
||||
// slightly differently to the user. For a symbolic reference with no adjustment,
|
||||
// we don't add the (redundant) numeric reference.
|
||||
//
|
||||
|
@ -1632,6 +1648,12 @@ namespace SourceGen {
|
|||
mAnattribs[operandOffset].Address;
|
||||
}
|
||||
|
||||
// TODO: to handle pre-labels correctly, we need to associate an
|
||||
// XrefSet with an address region, and add the reference there. We
|
||||
// currently attach it to the offset of the first byte in the region,
|
||||
// which means you don't see anything in the references window when
|
||||
// the pre-label line is selected.
|
||||
|
||||
AddXref(symOffset, new XrefSet.Xref(offset, true, xrefType, accType,
|
||||
accessFlags, adj));
|
||||
if (adj == 0) {
|
||||
|
|
|
@ -550,10 +550,8 @@ namespace SourceGen {
|
|||
// but we're only doing this on the template file, which should be small.
|
||||
tmplStr = tmplStr.Replace("$ProjectName$", mProject.DataFileName);
|
||||
tmplStr = tmplStr.Replace("$AppVersion$", App.ProgramVersion.ToString());
|
||||
string expModeStr = ((Formatter.FormatConfig.ExpressionMode)
|
||||
AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
|
||||
typeof(Formatter.FormatConfig.ExpressionMode),
|
||||
(int)Formatter.FormatConfig.ExpressionMode.Unknown)).ToString();
|
||||
string expModeStr = AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
|
||||
Formatter.FormatConfig.ExpressionMode.Unknown).ToString();
|
||||
tmplStr = tmplStr.Replace("$ExpressionStyle$", expModeStr);
|
||||
string dateStr = DateTime.Now.ToString("yyyy/MM/dd");
|
||||
string timeStr = DateTime.Now.ToString("HH:mm:ss zzz");
|
||||
|
|
|
@ -62,7 +62,8 @@ namespace SourceGen {
|
|||
Dense, // raw data, represented as compactly as possible
|
||||
Fill, // fill memory with a value
|
||||
Uninit, // uninitialized data storage area
|
||||
Junk // contents of memory are not interesting
|
||||
Junk, // contents of memory are not interesting
|
||||
BinaryInclude // file contents will be loaded from external file during asm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -171,6 +172,19 @@ namespace SourceGen {
|
|||
/// </summary>
|
||||
public WeakSymbolRef SymbolRef { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional extra data, used for special cases like BinaryInclude. May be null.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's unfortunate that we have this field for every object, even though very few
|
||||
/// will actually make use of it. The SymbolRef field has a very specific purpose
|
||||
/// and shouldn't be used to hold it (asserts and other logic gets upset). Storing
|
||||
/// the filenames in a separate table has some advantages, but requires integrating
|
||||
/// changes with the undo/redo mechanism, and the space savings doesn't justify the
|
||||
/// complexity cost.
|
||||
/// </remarks>
|
||||
public string Extra { get; private set; }
|
||||
|
||||
// Crude attempt to see how effective the prefab object creation is. Note we create
|
||||
// these for DefSymbols, so there will be one prefab for every platform symbol entry.
|
||||
public static int DebugCreateCount { get; private set; }
|
||||
|
@ -191,6 +205,7 @@ namespace SourceGen {
|
|||
Debug.Assert(length > 0);
|
||||
Debug.Assert(length <= MAX_NUMERIC_LEN || !IsNumeric);
|
||||
Debug.Assert(fmt != Type.Default || length == 1);
|
||||
Debug.Assert(fmt != Type.BinaryInclude);
|
||||
Debug.Assert(subFmt == SubType.None || (fmt != Type.Junk) ^ IsJunkSubType(subFmt));
|
||||
|
||||
Length = length;
|
||||
|
@ -213,6 +228,22 @@ namespace SourceGen {
|
|||
SymbolRef = sym;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for item with arbitrary string data.
|
||||
/// </summary>
|
||||
/// <param name="length">Length, in bytes.</param>
|
||||
/// <param name="fmt">Format type.</param>
|
||||
/// <param name="str">String data.</param>
|
||||
private FormatDescriptor(int length, Type fmt, string stringData) {
|
||||
Debug.Assert(length > 0);
|
||||
Debug.Assert(fmt == Type.BinaryInclude);
|
||||
Debug.Assert(!string.IsNullOrEmpty(stringData));
|
||||
Length = length;
|
||||
FormatType = fmt;
|
||||
FormatSubType = SubType.None;
|
||||
Extra = stringData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a descriptor with the requested characteristics. For common cases this
|
||||
/// returns a pre-allocated object, for less-common cases this allocates a new object.
|
||||
|
@ -267,6 +298,18 @@ namespace SourceGen {
|
|||
return new FormatDescriptor(length, sym, isBigEndian);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a descriptor with arbitrary string data.
|
||||
/// </summary>
|
||||
/// <param name="length">Length, in bytes.</param>
|
||||
/// <param name="fmt">Format type.</param>
|
||||
/// <param name="str">String data.</param>
|
||||
/// <returns>New or pre-allocated descriptor.</returns>
|
||||
public static FormatDescriptor Create(int length, Type fmt, string str) {
|
||||
DebugCreateCount++;
|
||||
return new FormatDescriptor(length, fmt, str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the descriptor is okay to use on an instruction operand. The CPU only
|
||||
/// understands little-endian numeric values, so that's all we allow.
|
||||
|
@ -276,8 +319,8 @@ namespace SourceGen {
|
|||
switch (FormatType) {
|
||||
case Type.Default:
|
||||
case Type.NumericLE:
|
||||
//case Type.NumericBE:
|
||||
return true;
|
||||
//case Type.NumericBE:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -506,6 +549,9 @@ namespace SourceGen {
|
|||
case Type.Junk:
|
||||
retstr += "unaligned junk";
|
||||
break;
|
||||
case Type.BinaryInclude:
|
||||
retstr += "binary include";
|
||||
break;
|
||||
default:
|
||||
// strings handled earlier
|
||||
retstr += "???";
|
||||
|
@ -571,7 +617,7 @@ namespace SourceGen {
|
|||
|
||||
public override string ToString() {
|
||||
return "[FmtDesc: len=" + Length + " fmt=" + FormatType + " sub=" + FormatSubType +
|
||||
" sym=" + SymbolRef + "]";
|
||||
" sym=" + SymbolRef + " xtra=" + Extra + "]";
|
||||
}
|
||||
|
||||
|
||||
|
@ -583,7 +629,8 @@ namespace SourceGen {
|
|||
return false; // one is null
|
||||
}
|
||||
return a.Length == b.Length && a.FormatType == b.FormatType &&
|
||||
a.FormatSubType == b.FormatSubType && a.SymbolRef == b.SymbolRef;
|
||||
a.FormatSubType == b.FormatSubType && a.SymbolRef == b.SymbolRef &&
|
||||
a.Extra == b.Extra;
|
||||
}
|
||||
public static bool operator !=(FormatDescriptor a, FormatDescriptor b) {
|
||||
return !(a == b);
|
||||
|
@ -599,6 +646,9 @@ namespace SourceGen {
|
|||
hashCode ^= Length;
|
||||
hashCode ^= (int)FormatType;
|
||||
hashCode ^= (int)FormatSubType;
|
||||
if (Extra != null) {
|
||||
hashCode ^= Extra.GetHashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
|
90
SourceGen/LabelFileGenerator.cs
Normal file
90
SourceGen/LabelFileGenerator.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2019 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.IO;
|
||||
|
||||
namespace SourceGen {
|
||||
/// <summary>
|
||||
/// Label file generator.
|
||||
/// </summary>
|
||||
public class LabelFileGenerator {
|
||||
public enum LabelFmt {
|
||||
Unknown = 0,
|
||||
VICE,
|
||||
}
|
||||
|
||||
private DisasmProject mProject;
|
||||
private LabelFmt mFormat;
|
||||
private bool mIncludeAutoLabels;
|
||||
|
||||
public LabelFileGenerator(DisasmProject project, LabelFmt format, bool includeAutoLabels) {
|
||||
mProject = project;
|
||||
mFormat = format;
|
||||
mIncludeAutoLabels = includeAutoLabels;
|
||||
}
|
||||
|
||||
public void Generate(StreamWriter outStream) {
|
||||
List<Symbol> symList = new List<Symbol>();
|
||||
|
||||
foreach (Symbol sym in mProject.SymbolTable) {
|
||||
bool include;
|
||||
switch (sym.SymbolSource) {
|
||||
case Symbol.Source.User:
|
||||
case Symbol.Source.AddrPreLabel:
|
||||
include = true;
|
||||
break;
|
||||
case Symbol.Source.Auto:
|
||||
include = mIncludeAutoLabels;
|
||||
break;
|
||||
case Symbol.Source.Project:
|
||||
case Symbol.Source.Platform:
|
||||
case Symbol.Source.Variable:
|
||||
default:
|
||||
include = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (include) {
|
||||
symList.Add(sym);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort alphabetically. Not necessary, but it could make a "diff" easier to read.
|
||||
symList.Sort((a, b) => Symbol.Compare(Symbol.SymbolSortField.Name, true, a, b));
|
||||
|
||||
Debug.Assert(mFormat == LabelFmt.VICE);
|
||||
|
||||
// VICE format is "add_label <address> <label>", but may be abbreviated "al".
|
||||
// We could also use ACME format ("labelname = $1234 ; Maybe a comment").
|
||||
foreach (Symbol sym in symList) {
|
||||
// VICE only keeps one copy of each label, so local labels need to include the
|
||||
// uniquifier. The UNIQUE_TAG_CHAR may not be accepted, so replace it with '_'.
|
||||
string label = sym.Label;
|
||||
label = label.Replace(Symbol.UNIQUE_TAG_CHAR, '_');
|
||||
if (sym.IsNonUnique) {
|
||||
// Add the cc65 prefix convention for local labels.
|
||||
label = '@' + label;
|
||||
}
|
||||
// The cc65 docs (https://www.cc65.org/doc/debugging-4.html) say all labels
|
||||
// must be prefaced with '.'. VICE rejects labels that start with a letter.
|
||||
label = '.' + label;
|
||||
outStream.WriteLine("al " + sym.Value.ToString("x6") + " " + label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1122,9 +1122,19 @@ namespace SourceGen {
|
|||
comment += " (auto-generated)";
|
||||
}
|
||||
#else
|
||||
string comment = string.Empty;
|
||||
string cstr = string.Empty;
|
||||
if (change.IsSynthetic) {
|
||||
comment = mFormatter.FormatEolComment("(auto-generated)");
|
||||
cstr += " (auto-generated)";
|
||||
}
|
||||
if (region.DisallowInward) {
|
||||
cstr += " [!in]";
|
||||
}
|
||||
if (region.DisallowOutward) {
|
||||
cstr += " [!out]";
|
||||
}
|
||||
string comment = string.Empty;
|
||||
if (cstr.Length > 0) {
|
||||
comment = mFormatter.FormatEolComment(cstr.Substring(1));
|
||||
}
|
||||
#endif
|
||||
newLine.Parts = FormattedParts.CreateFullDirective(string.Empty,
|
||||
|
|
|
@ -256,7 +256,7 @@ namespace SourceGen {
|
|||
// Load the settings from the file. If this fails we have no way to tell the user,
|
||||
// so just keep going.
|
||||
LoadAppSettings();
|
||||
SetAppWindowLocation();
|
||||
SetAppWindowLocation(); // <-- this causes WindowLoaded to fire
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -345,7 +345,8 @@ namespace SourceGen {
|
|||
settings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, "f:");
|
||||
|
||||
settings.SetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, true);
|
||||
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, true);
|
||||
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
AsmGen.GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
|
||||
#if DEBUG
|
||||
settings.SetBool(AppSettings.DEBUG_MENU_ENABLED, true);
|
||||
|
@ -453,20 +454,6 @@ namespace SourceGen {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the contents of the global settings object with the new settings,
|
||||
/// then applies them to the project.
|
||||
/// </summary>
|
||||
/// <param name="settings">New settings.</param>
|
||||
public void SetAppSettings(AppSettings settings) {
|
||||
AppSettings.Global.ReplaceSettings(settings);
|
||||
ApplyAppSettings();
|
||||
|
||||
// We get called whenever Apply or OK is hit in the settings editor, so it's
|
||||
// a pretty good time to save the settings out.
|
||||
SaveAppSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the app window's location and size. This should be called before the window has
|
||||
/// finished initialization.
|
||||
|
@ -1476,10 +1463,8 @@ namespace SourceGen {
|
|||
return;
|
||||
}
|
||||
|
||||
ClipLineFormat format = (ClipLineFormat)AppSettings.Global.GetEnum(
|
||||
AppSettings.CLIP_LINE_FORMAT,
|
||||
typeof(ClipLineFormat),
|
||||
(int)ClipLineFormat.AssemblerSource);
|
||||
ClipLineFormat format = AppSettings.Global.GetEnum(AppSettings.CLIP_LINE_FORMAT,
|
||||
ClipLineFormat.AssemblerSource);
|
||||
|
||||
int[] rightWidths = new int[] { 16, 6, 16, 80 };
|
||||
|
||||
|
@ -1519,21 +1504,30 @@ namespace SourceGen {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the application settings dialog. All changes to settings are made directly
|
||||
/// to the AppSettings.Global object.
|
||||
/// Handles Edit > App Settings.
|
||||
/// </summary>
|
||||
public void EditAppSettings() {
|
||||
ShowAppSettings(mMainWin, WpfGui.EditAppSettings.Tab.Unknown,
|
||||
AsmGen.AssemblerInfo.Id.Unknown);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the application settings dialog. All changes to settings are made directly
|
||||
/// to the AppSettings.Global object.
|
||||
/// </summary>
|
||||
public void ShowAppSettings(Window owner, EditAppSettings.Tab initialTab,
|
||||
AsmGen.AssemblerInfo.Id initialAsmId) {
|
||||
EditAppSettings dlg = new EditAppSettings(owner, mMainWin, this,
|
||||
initialTab, initialAsmId);
|
||||
EditAppSettings dlg = new EditAppSettings(owner, mMainWin, initialTab, initialAsmId);
|
||||
dlg.SettingsApplied += SetAppSettings; // called when "Apply" is clicked
|
||||
dlg.ShowDialog();
|
||||
}
|
||||
|
||||
// The settings code calls SetAppSettings() directly whenever "Apply" is hit.
|
||||
/// <summary>
|
||||
/// Applies settings to the project, and saves them to the settings files.
|
||||
/// </summary>
|
||||
private void SetAppSettings() {
|
||||
ApplyAppSettings();
|
||||
SaveAppSettings();
|
||||
}
|
||||
|
||||
public void HandleCodeListDoubleClick(int row, int col) {
|
||||
|
@ -1930,8 +1924,7 @@ namespace SourceGen {
|
|||
}
|
||||
|
||||
// Create a prototype entry with the various values.
|
||||
newEntry = new AddressMap.AddressMapEntry(firstOffset,
|
||||
selectedLen, addr, string.Empty, false);
|
||||
newEntry = new AddressMap.AddressMapEntry(firstOffset, selectedLen, addr);
|
||||
Debug.WriteLine("New entry prototype: " + newEntry);
|
||||
}
|
||||
|
||||
|
@ -2359,6 +2352,7 @@ namespace SourceGen {
|
|||
Debug.WriteLine("No change to data formats");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void EditProjectProperties(WpfGui.EditProjectProperties.Tab initialTab) {
|
||||
|
@ -2562,6 +2556,47 @@ namespace SourceGen {
|
|||
}
|
||||
}
|
||||
|
||||
public void GenerateLabels() {
|
||||
GenerateLabels dlg = new GenerateLabels(mMainWin);
|
||||
if (dlg.ShowDialog() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
string ext;
|
||||
string filter;
|
||||
switch (dlg.Format) {
|
||||
case LabelFileGenerator.LabelFmt.VICE:
|
||||
ext = ".lbl";
|
||||
filter = "VICE labels (*.lbl)|*.lbl";
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false, "bad format");
|
||||
return;
|
||||
}
|
||||
|
||||
SaveFileDialog fileDlg = new SaveFileDialog() {
|
||||
Filter = filter,
|
||||
FilterIndex = 1,
|
||||
ValidateNames = true,
|
||||
AddExtension = true, // doesn't add extension if non-ext file exists
|
||||
FileName = "labels" + ext
|
||||
};
|
||||
if (fileDlg.ShowDialog() != true) {
|
||||
return;
|
||||
}
|
||||
string pathName = Path.GetFullPath(fileDlg.FileName);
|
||||
try {
|
||||
using (StreamWriter writer = new StreamWriter(pathName, false)) {
|
||||
LabelFileGenerator gen = new LabelFileGenerator(mProject,
|
||||
dlg.Format, dlg.IncludeAutoLabels);
|
||||
gen.Generate(writer);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
MessageBox.Show("Error: " + ex.Message, "Failed", MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public void Find() {
|
||||
FindBox dlg = new FindBox(mMainWin, mFindString);
|
||||
if (dlg.ShowDialog() == true) {
|
||||
|
@ -3913,7 +3948,8 @@ namespace SourceGen {
|
|||
return;
|
||||
}
|
||||
int lineIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
LineListGen.Line.Type type = CodeLineList[lineIndex].LineType;
|
||||
LineListGen.Line line = CodeLineList[lineIndex];
|
||||
LineListGen.Line.Type type = line.LineType;
|
||||
if (type != LineListGen.Line.Type.Code &&
|
||||
type != LineListGen.Line.Type.Data &&
|
||||
type != LineListGen.Line.Type.EquDirective &&
|
||||
|
@ -3926,10 +3962,10 @@ namespace SourceGen {
|
|||
|
||||
// Find the appropriate xref set.
|
||||
if (type == LineListGen.Line.Type.LocalVariableTable) {
|
||||
DefSymbol defSym = CodeLineList.GetLocalVariableFromLine(CodeLineList[lineIndex]);
|
||||
DefSymbol defSym = CodeLineList.GetLocalVariableFromLine(line);
|
||||
xrefs = (defSym == null) ? null : defSym.Xrefs;
|
||||
} else {
|
||||
int offset = CodeLineList[lineIndex].FileOffset;
|
||||
int offset = line.FileOffset;
|
||||
if (offset < 0) {
|
||||
// EQU in header
|
||||
int index = LineListGen.DefSymIndexFromOffset(offset);
|
||||
|
|
|
@ -23,6 +23,10 @@ using System.Web.Script.Serialization;
|
|||
|
||||
using CommonUtil;
|
||||
|
||||
// TODO: experiment with serialization options that exclude default values, such as null
|
||||
// strings, from the serialized output
|
||||
// TODO: switch to System.Text.Json.JsonSerializer (with WriteIndented=true).
|
||||
|
||||
namespace SourceGen {
|
||||
/// <summary>
|
||||
/// Load and save project data from/to a ".dis65" file.
|
||||
|
@ -52,7 +56,10 @@ namespace SourceGen {
|
|||
// ignore stuff that's in one side but not the other. However, if we're opening a
|
||||
// newer file in an older program, it's worth letting the user know that some stuff
|
||||
// may get lost as soon as they save the file.
|
||||
public const int CONTENT_VERSION = 5;
|
||||
public const int CONTENT_VERSION = 6;
|
||||
|
||||
// Max JSON file length.
|
||||
internal const int MAX_JSON_LENGTH = 64 * 1024 * 1024;
|
||||
|
||||
private static readonly bool ADD_CRLF = true;
|
||||
|
||||
|
@ -242,6 +249,8 @@ namespace SourceGen {
|
|||
public int Addr { get; set; }
|
||||
public int Length { get; set; }
|
||||
public string PreLabel { get; set; }
|
||||
public bool DisallowInward { get; set; }
|
||||
public bool DisallowOutward { get; set; }
|
||||
public bool IsRelative { get; set; }
|
||||
|
||||
public SerAddressMapEntry() {
|
||||
|
@ -254,6 +263,8 @@ namespace SourceGen {
|
|||
Addr = ent.Address;
|
||||
Length = ent.Length;
|
||||
PreLabel = ent.PreLabel;
|
||||
DisallowInward = ent.DisallowInward;
|
||||
DisallowOutward = ent.DisallowOutward;
|
||||
IsRelative = ent.IsRelative;
|
||||
}
|
||||
}
|
||||
|
@ -305,6 +316,7 @@ namespace SourceGen {
|
|||
public string Format { get; set; }
|
||||
public string SubFormat { get; set; }
|
||||
public SerWeakSymbolRef SymbolRef { get; set; }
|
||||
public string Extra { get; set; }
|
||||
|
||||
public SerFormatDescriptor() { }
|
||||
public SerFormatDescriptor(FormatDescriptor dfd) {
|
||||
|
@ -314,6 +326,9 @@ namespace SourceGen {
|
|||
if (dfd.SymbolRef != null) {
|
||||
SymbolRef = new SerWeakSymbolRef(dfd.SymbolRef);
|
||||
}
|
||||
if (dfd.Extra != null) {
|
||||
Extra = dfd.Extra;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class SerWeakSymbolRef {
|
||||
|
@ -567,6 +582,7 @@ namespace SourceGen {
|
|||
}
|
||||
|
||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||
ser.MaxJsonLength = ProjectFile.MAX_JSON_LENGTH; // increase max len beyond 2MB
|
||||
string cereal = ser.Serialize(spf);
|
||||
sb.Append(cereal);
|
||||
|
||||
|
@ -586,6 +602,10 @@ namespace SourceGen {
|
|||
public static bool DeserializeProject(string cereal, DisasmProject proj,
|
||||
FileLoadReport report) {
|
||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||
// Increase max size of JSON data. We need to make the deserialization limit larger
|
||||
// than the serialization limit because we insert additional newlines to make the
|
||||
// file more readable. 1/64th of max is probably about right. TODO: fix this properly.
|
||||
ser.MaxJsonLength = ProjectFile.MAX_JSON_LENGTH + (ProjectFile.MAX_JSON_LENGTH / 64);
|
||||
SerializableProjectFile1 spf;
|
||||
try {
|
||||
spf = ser.Deserialize<SerializableProjectFile1>(cereal);
|
||||
|
@ -681,7 +701,8 @@ namespace SourceGen {
|
|||
proj.AddrMap.Clear();
|
||||
foreach (SerAddressMapEntry addr in spf.AddressMap) {
|
||||
AddressMap.AddResult addResult = proj.AddrMap.AddEntry(addr.Offset,
|
||||
addr.Length, addr.Addr, addr.PreLabel, addr.IsRelative);
|
||||
addr.Length, addr.Addr, addr.PreLabel,
|
||||
addr.DisallowInward, addr.DisallowOutward, addr.IsRelative);
|
||||
if (addResult != CommonUtil.AddressMap.AddResult.Okay) {
|
||||
string msg = "off=+" + addr.Offset.ToString("x6") + " len=" +
|
||||
(addr.Length == CommonUtil.AddressMap.FLOATING_LEN ?
|
||||
|
@ -1074,9 +1095,14 @@ namespace SourceGen {
|
|||
": " + sfd.Format + "/" + sfd.SubFormat);
|
||||
return false;
|
||||
}
|
||||
if (sfd.SymbolRef == null) {
|
||||
if (sfd.Extra != null) {
|
||||
// Descriptor with extra data.
|
||||
dfd = FormatDescriptor.Create(sfd.Length, format, sfd.Extra);
|
||||
} else if (sfd.SymbolRef == null) {
|
||||
// Simple descriptor.
|
||||
dfd = FormatDescriptor.Create(sfd.Length, format, subFormat);
|
||||
} else {
|
||||
// Descriptor with symbolic reference.
|
||||
WeakSymbolRef.Part part;
|
||||
try {
|
||||
part = (WeakSymbolRef.Part)Enum.Parse(
|
||||
|
|
|
@ -81,6 +81,7 @@ namespace SourceGen {
|
|||
public string Uninit { get; private set; }
|
||||
public string Junk { get; private set; }
|
||||
public string Align { get; private set; }
|
||||
public string BinaryInclude { get; private set; }
|
||||
public string StrGeneric { get; private set; }
|
||||
public string StrReverse { get; private set; }
|
||||
public string StrLen8 { get; private set; }
|
||||
|
@ -133,6 +134,7 @@ namespace SourceGen {
|
|||
a.Uninit == b.Uninit &&
|
||||
a.Junk == b.Junk &&
|
||||
a.Align == b.Align &&
|
||||
a.BinaryInclude == b.BinaryInclude &&
|
||||
a.StrGeneric == b.StrGeneric &&
|
||||
a.StrReverse == b.StrReverse &&
|
||||
a.StrLen8 == b.StrLen8 &&
|
||||
|
@ -247,6 +249,7 @@ namespace SourceGen {
|
|||
{ "Uninit", ".ds" },
|
||||
{ "Junk", ".junk" },
|
||||
{ "Align", ".align" },
|
||||
{ "BinaryInclude", ".incbin" },
|
||||
|
||||
{ "StrGeneric", ".str" },
|
||||
{ "StrReverse", ".rstr" },
|
||||
|
@ -280,6 +283,7 @@ namespace SourceGen {
|
|||
case FormatDescriptor.Type.Fill:
|
||||
case FormatDescriptor.Type.Uninit:
|
||||
case FormatDescriptor.Type.Junk:
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
return 1;
|
||||
case FormatDescriptor.Type.Dense: {
|
||||
// no delimiter, two output bytes per input byte
|
||||
|
@ -389,6 +393,11 @@ namespace SourceGen {
|
|||
//po = outList[subIndex];
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
po.Opcode = opNames.BinaryInclude;
|
||||
string biPath = AsmGen.BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
po.Operand = '"' + biPath + "'";
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
po.Opcode = ".???";
|
||||
|
|
|
@ -87,6 +87,12 @@ namespace SourceGen {
|
|||
sb.Append(change.Region.PreLabel);
|
||||
sb.Append("'");
|
||||
}
|
||||
if (change.Region.DisallowInward) {
|
||||
sb.Append(" [!in]");
|
||||
}
|
||||
if (change.Region.DisallowOutward) {
|
||||
sb.Append(" [!out]");
|
||||
}
|
||||
|
||||
sb.Append(CRLF);
|
||||
|
||||
|
|
203
SourceGen/RuntimeData/Commodore/1541-RAM-use.sym65
Normal file
203
SourceGen/RuntimeData/Commodore/1541-RAM-use.sym65
Normal file
|
@ -0,0 +1,203 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Commodore 1541 / OC-118 Disk Drive Memory Map (v1.3, Jan 18, 1995)
|
||||
; https://ist.uwaterloo.ca/~schepers/MJK/ascii/1541map.txt
|
||||
;
|
||||
; - Commodore 1541 drive memory map
|
||||
; https://sta.c64.org/cbm1541mem.html
|
||||
;
|
||||
; - DOS 2.6 ROM LISTINGS (v1.0, Feb 11, 2000)
|
||||
; http://www.ffd2.com/fridge/docs/1541dis.html
|
||||
;
|
||||
; - CBM DOS ROM disassembly and memory variables for Commodore 1541 drive
|
||||
; https://g3sl.github.io/c1541rom.html
|
||||
|
||||
*SYNOPSIS 1541 RAM locations used by the 1541 ROM
|
||||
|
||||
cmdCodeBuf0 @ $0000 ;Command code for buffer 0
|
||||
cmdCodeBuf1 @ $0001 ;Command code for buffer 1
|
||||
cmdCodeBuf2 @ $0002 ;Command code for buffer 2
|
||||
cmdCodeBuf3 @ $0003 ;Command code for buffer 3
|
||||
cmdCodeBuf4 @ $0004 ;Command code for buffer 4
|
||||
trkBuf0 @ $0006 ;Track buffer 0
|
||||
secBuf0 @ $0007 ;Sector buffer 0
|
||||
trkBuf1 @ $0008 ;Track buffer 1
|
||||
secBuf1 @ $0009 ;Sector buffer 1
|
||||
trkBuf2 @ $000a ;Track buffer 2
|
||||
secBuf2 @ $000b ;Sector buffer 2
|
||||
trkBuf3 @ $000c ;Track buffer 3
|
||||
secBuf3 @ $000d ;Sector buffer 3
|
||||
trkBuf4 @ $000e ;Track buffer 4
|
||||
secBuf4 @ $000f ;Sector buffer 4
|
||||
d0DiskID @ $0012 ;Disk ID, drive 0
|
||||
d1DiskID @ $0014 ;Disk ID, drive 1
|
||||
hbID @ $0016 ;Header block: ID
|
||||
hbTrk @ $0018 ;Header block: Track
|
||||
hbSec @ $0019 ;Header block: Sector
|
||||
hbParity @ $001a ;Header block: Parity
|
||||
diskChgD0 @ $001c ;Flag for disk change, drive 0 01
|
||||
diskChgD1 @ $001d ;Flag for disk change, drive 1 01
|
||||
writeProtD0 @ $001e ;Flag for write protect sense, drive 0 01
|
||||
writeProtD1 @ $001f ;Flag for write protect sense, drive 1
|
||||
d0Status @ $0020 ;Drive 0 status (disk and step motor)
|
||||
d1Status @ $0021 ;Drive 1 status (disk and step motor)
|
||||
d0CurTrk @ $0022 ;Current track for drive 0
|
||||
driveType @ $0023 ;Flag for 1541 (0), 1540 (not 0)
|
||||
gcrWorkArea @ $0024 ;Scratch pad of GCR conversion
|
||||
ptrTmpMem @ $002e 2 ;Pointer for temporary storage
|
||||
bufPtrCtrl @ $0030 2 ;Buffer pointer for disk controller
|
||||
ptrCurTrk @ $0032 2 ;Pointer: active track
|
||||
ptrCurSec @ $0033 2 ;Pointer: active sector
|
||||
ptrLastConvByte @ $0034 2 ;Pointer to last converted byte
|
||||
convByteCnt @ $0036 ;Byte counter for GCR/BIN conversion
|
||||
byteStartBlk @ $0038 ;Constant 7, ID mark for start of data block
|
||||
byteStartBlkHdr @ $0039 ;Constant 8, ID mark for start of block header
|
||||
dataBufParity @ $003a ;Parity for data buffer
|
||||
motorFlag @ $003d ;Motor flag
|
||||
curDrive @ $003e ;Active drive (FF, if not active)
|
||||
ctrlBufNum @ $003f ;Buffer number for disk controller
|
||||
gcrConvByteCnt @ $0040 ;Byte counter for GCR conversion
|
||||
workCnt @ $0041 ;Number of next work in queue (0 - 5)
|
||||
destTrk @ $0042 ;Destination track (to move R/W head to)
|
||||
secPerTrk @ $0043 ;Number of sectors per track for formatting
|
||||
tmpArea @ $0044 ;Temp. work area; Scratch pad
|
||||
tmpArea2 @ $0045 ;Work code temp. storage
|
||||
byteBlkID @ $0047 ;Data block ID char, default 07.
|
||||
headMoveCnt @ $0048 ;Counter for head movement
|
||||
headStepCnt @ $004a ;Step counter for head transport
|
||||
lastReadSec @ $004c ;Last read sector
|
||||
nextSec @ $004d ;Next sector
|
||||
gcrConvBufPtr @ $004e 2 ;Pointer to buffer for GCR->BIN conversion
|
||||
gcrFormatFlag @ $0050 ;Flag for GCR format (0=BIN, 1=GCR)
|
||||
curFormatTrk @ $0051 ;Current track number for formatting FF
|
||||
gcrConvBytesBuf @ $0052 4 ;Storage for 4 BIN bytes for GCR coding
|
||||
gcrConvStore @ $0056 5 ;Storage for 5 GCR bytes
|
||||
headAccSteps @ $005e ;Number of steps for head motor accel/decl
|
||||
headAccFactor @ $005f ;accelerating/decl. factor 04
|
||||
headMoveVec @ $0062 2 ;Pointer to routine for head movement $fa05
|
||||
headStepsMin @ $0064 ;Minimum number of steps C8
|
||||
nmiVec @ $0065 2 ;Pointer to start of NMI routine ($eb2e)
|
||||
nmiInProc @ $0067 ;Flag: NMI in process
|
||||
diskInitInProc @ $0068 ;Flag for disk initialisation
|
||||
secDivStepSize @ $0069 ;Step size for sector division $0a
|
||||
numReadAttempts @ $006a ;Number of read attempts 5
|
||||
ptrStartJumpTbl @ $006b 2 ;Pointer: Start of Jump table for U commands $ffea
|
||||
ptrStartBitmap @ $006d 2 ;Pointer: Start of bitmap $0400
|
||||
ptrMBcmds @ $006f 2 ;Pointer to address for M & B commands
|
||||
tmpArea3 @ $0071 4 ;Temp work area
|
||||
indPtrVar @ $0075 2 ;Indirect pointer variable ($0100)
|
||||
listenAddr @ $0077 ;Listener address (Device number + $20)
|
||||
talkAddr @ $0078 ;Talker address (Device number + $40)
|
||||
curListenFlag @ $0079 ;Flag: Active listener
|
||||
curTalkFlag @ $007a ;Flag: Active talker
|
||||
atnRecevFlag @ $007c ;Flag for ATN from serial bus receiving
|
||||
atnActiveFlag @ $007d ;Flag for ATN on serial bus active
|
||||
lastPrg @ $007e ;Last handled program
|
||||
driveNum @ $007f ;Drive number (on 1541 always 00)
|
||||
curTrk @ $0080 ;Current Track number
|
||||
curSec @ $0081 ;Current Sector number
|
||||
chnlNum @ $0082 ;Channel number (Logical index)
|
||||
scndAddr @ $0083 ;Secondary address
|
||||
scndAddrOrig @ $0084 ;Original Secondary address $6f
|
||||
curDataByte @ $0085 ;Current Data byte $3f
|
||||
tmpArea4 @ $0086 9 ;Temp Results area
|
||||
curBufPtr @ $0094 2 ;Current dir buffer pointer
|
||||
ptrNxtByteBuf0 @ $0099 2 ;Pointer: Next byte in buffer 0 $0300
|
||||
ptrNxtByteBuf1 @ $009b 2 ;Pointer: Next byte in buffer 1 $0400
|
||||
ptrNxtByteBuf2 @ $009d 2 ;Pointer: Next byte in buffer 2 $0500
|
||||
ptrNxtByteBuf3 @ $009f 2 ;Pointer: Next byte in buffer 3 $0600
|
||||
ptrNxtByteBuf4 @ $00a1 2 ;Pointer: Next byte in buffer 4 $0700
|
||||
ptrNxtByteCmdBf @ $00a3 2 ;Pointer: Next byte in command buffer $0200
|
||||
prtNxtByteErrBf @ $00a5 2 ;Pointer: Next byte in error message buffer $02d6
|
||||
tblBufChnls @ $00a7 ;Table: buffer channel assignments
|
||||
tblLoBufRecNum @ $00b5 6 ;Table: lo bytes of record numbers for each buffer
|
||||
tblHiBufRecNum @ $00bb 6 ;Table: hi bytes of record numbers for each buffer
|
||||
relWritePtr @ $00c1 ;Write pointer for REL file
|
||||
relRecLen @ $00c7 ;Table: Record length for REL file
|
||||
tblSideSecs @ $00cd 6 ;Table: Side sectors
|
||||
relInRecPtr @ $00d4 ;Pointer in record for REL file
|
||||
sideSecNum @ $00d5 ;Side sector number
|
||||
blkPrtSideSec @ $00d6 ;Pointer to data block in side sector
|
||||
relToRecPtr2 @ $00d7 ;Pointer to record in REL file
|
||||
dirSectors @ $00d8 ;Directory sectors
|
||||
indexDir @ $00dd ;Index: Directory
|
||||
defaultDrive @ $00e2 ;Default disk drive 00
|
||||
chnlStatus @ $00f2 ;Channel status
|
||||
flatEOI @ $00f8 ;Flag for EOI
|
||||
currWorkBufNum @ $00f9 ;Current work (Buffer number)
|
||||
lruTable @ $00fa 5 ;Least recently used table
|
||||
d0ReadyFlag @ $00ff ;Flag: FF = drive 0 not ready (No disk), 00 = ready
|
||||
d1ReadyFlag @ $0100 ;Flag: FF = drive 1 not ready (No disk), 00 = ready
|
||||
d0FormatMarker @ $0101 ;DOS version from t18 for drive 0
|
||||
d1FormatMarker @ $0102 ;DOS version from t18 for drive 1
|
||||
cmdStrBuf @ $0200 42 ;Buffer for command string
|
||||
cmdCode @ $022a ;Command code
|
||||
chnl1Index @ $022b ;Logical index, channel 0
|
||||
chnl2Index @ $022c ;Logical index, channel 1
|
||||
chnl3Index @ $022d ;Logical index, channel 2
|
||||
chnlsLastRWbyte @ $022e 6 ;Last read/written byte for each channel
|
||||
chnlsLastChar @ $0244 6 ;Pointer: Last char on channel
|
||||
curFileType @ $024a ;Type of active file
|
||||
strLen @ $024b ;String length
|
||||
tmpChnlNum @ $024c ;Temp. channel number (secondary address)
|
||||
curWork @ $024d ;Current work with drive number
|
||||
workAreaForSec @ $024e ;Work area to find the best sector
|
||||
bufAlloc @ $024f ;Buffer allocated
|
||||
d0BamChangFlag @ $0251 ;Flag: BAM changed, drive 0
|
||||
d1BamChangFlag @ $0252 ;Flag: BAM changed, drive 1
|
||||
dirEntryFndFlag @ $0253 ;Flag for directory entry found
|
||||
dirOutputFlag @ $0254 ;Flag for directory output
|
||||
cmdWaitFlag @ $0255 ;Flag: Waiting for command
|
||||
lastUsedBuf @ $0257 ;Last used buffer
|
||||
recordLen @ $0258 ;Record length
|
||||
sideSecTrk @ $0259 ;Track of side sector
|
||||
sideSecSec @ $025a ;Sector of side sector
|
||||
lastWorkBufs @ $025b 5 ;Last work (buffers)
|
||||
dirSecBufs @ $0260 5 ;Directory sector (buffers)
|
||||
fileDirIdxBufs @ $0266 5 ;File's index in directory (buffers)
|
||||
ledFlashCnt @ $026c ;Counter for LED flash
|
||||
ledFlashMask @ $026d ;Error LED mask for flashing
|
||||
driveForLastPrg @ $026e ;Drive for last program
|
||||
secForLastPrg @ $026f ;sector for last program
|
||||
writeLindx @ $0270 ;Write LINDX
|
||||
readLindx @ $0271 ;Read LINDX
|
||||
inputLineLen @ $0274 ;Length of input line
|
||||
charToProcess @ $0275 ;Char to interpret
|
||||
endOfCmdBufFN @ $0276 ;Index: End of filename in command buffer
|
||||
numOfFNs @ $0278 ;Number of filenames
|
||||
tblPtrFNs @ $027a 6 ;Pointer table: filenames
|
||||
fileTrk @ $0280 ;Track of a file
|
||||
fileSec @ $0285 ;Sector of a file
|
||||
patternFlag @ $028a ;Flag: wild cards
|
||||
fileStrmImage @ $028b ;File stream image
|
||||
numDriveSrches @ $028c ;Number of drives to look for
|
||||
driveSearchFlag @ $028d ;Flag: Looking for drive
|
||||
driveWthLastErr @ $028e ;drive with last write/open error, used as default drive
|
||||
foundInDirFlag @ $028f ;Flag: Found in directory
|
||||
dirSec @ $0290 ;Directory sector
|
||||
sec1stAvailFile @ $0291 ;Sector for first available file
|
||||
idx1stAvailFile @ $0292 ;Index (in directory) for first available file
|
||||
zeroIfLastBlk @ $0293 ;=0 if last block
|
||||
curBufIndex @ $0294 ;Current buffer-index
|
||||
filesCnt @ $0295 ;Counter: Files
|
||||
typeFlag @ $0296 ;Flag: Name matching wild cards
|
||||
fileMode @ $0297 ;Active file mode (R or W)
|
||||
jobReturnFlag @ $0298 ;Flag: job return
|
||||
recoveryPtr @ $0299 2 ;Pointer for recovery
|
||||
totalTrkOffset @ $029a ;Total tracks offset
|
||||
lastBamUpdtPtr @ $029b 2 ;Pointer: BAM last update
|
||||
bamImgTrackNum @ $029d 2 ;Track # of BAM image (drive 0/1)
|
||||
bamImg @ $02a1 16 ;BAM image
|
||||
dirOutputBuf @ $02b1 36 ;Buffer for directory output
|
||||
errMsgBuf @ $02d5 36 ;Buffer for error message
|
||||
noWriteBamFlag @ $02f9 ;Flag: Don't write BAM
|
||||
numFreeBlksLo @ $02fa 2 ;Number of free blocks, lo for drives 0 and 1
|
||||
numFreeBlksHi @ $02fc 2 ;Number of free blocks, hi for drives 0 and 1
|
||||
stepperPhase @ $02fe 2 ;Current phase of head stepper motor
|
||||
buffer0 @ $0300 256 ;Buffer 0
|
||||
buffer1 @ $0400 256 ;Buffer 1
|
||||
buffer2 @ $0500 256 ;Buffer 2
|
||||
buffer3 @ $0600 256 ;Buffer 3
|
||||
buffer4 @ $0700 256 ;Buffer 4
|
309
SourceGen/RuntimeData/Commodore/1541-ROM.sym65
Normal file
309
SourceGen/RuntimeData/Commodore/1541-ROM.sym65
Normal file
|
@ -0,0 +1,309 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Commodore 1541 / OC-118 Disk Drive Memory Map (v1.3, Jan 18, 1995)
|
||||
; https://ist.uwaterloo.ca/~schepers/MJK/ascii/1541map.txt
|
||||
;
|
||||
; - Commodore 1541 drive memory map
|
||||
; https://sta.c64.org/cbm1541mem.html
|
||||
;
|
||||
; - DOS 2.6 ROM LISTINGS (v1.0, Feb 11, 2000)
|
||||
; http://www.ffd2.com/fridge/docs/1541dis.html
|
||||
;
|
||||
; - CBM DOS ROM disassembly and memory variables for Commodore 1541 drive
|
||||
; https://g3sl.github.io/c1541rom.html
|
||||
|
||||
*SYNOPSIS 1541 ROM and memory-mapped I/O labels
|
||||
|
||||
via1PortB @ $1800 ;VIA1: port B serial bus
|
||||
via1PortA @ $1801 ;VIA1: port A. Read to ack interrupt from ATN IN going high
|
||||
via1PortBddr @ $1802 ;VIA1: port B data direction reg
|
||||
via1PortAddr @ $1803 ;VIA1: port A data direction reg
|
||||
via1Timer @ $1805 ;VIA1: Timer
|
||||
via2PortB @ $1c00 ;VIA2: PB, control port B
|
||||
via2PortA @ $1c01 ;VIA2: PA, port A (data to and from read/write head)
|
||||
via2PortBddr @ $1c02 ;VIA2: CB, data direction port B
|
||||
via2PortAddr @ $1c03 ;VIA2: A, data direction port A
|
||||
timerLo @ $1c04 ;Timer low byte
|
||||
timerHi @ $1c05 ;Timer high byte, write to start timer
|
||||
timerStartValLo @ $1c06 ;Timer starting value low byte
|
||||
timerStartValHi @ $1c07 ;Timer starting value high byte
|
||||
timerCtrl @ $1c0b ;Timer control register
|
||||
auxCtrl @ $1c0c ;Auxiliary control register
|
||||
interruptStatus @ $1c0d ;Interrupt status register
|
||||
interruptCtrl @ $1c0e ;Interrupt control register
|
||||
ledOnCurrDrive @ $c100 ;Turn LED on for current drive
|
||||
ledOn @ $c118 ;Turn LED on
|
||||
clrErrors @ $c123 ;Clear error flags
|
||||
prepLedFlash @ $c12c ;Prepare for LED flash after error
|
||||
interpretCmd @ $c146 ;Interpret command from computer
|
||||
prepError @ $c194 ;Prepare error msg after executing command
|
||||
clrInputBuf @ $c1bd ;Erase input buffer
|
||||
outErrorMsg @ $c1c8 ;Output error msg (track and sector 0)
|
||||
chkInputLine @ $c1d1 ;Check input line
|
||||
srchInputBuf @ $c268 ;Search character in input buffer
|
||||
chkLineLen @ $c2b3 ;Check line length
|
||||
clrInputFlags @ $c2dc ;Clear flags for command input
|
||||
prsrvDriveNum @ $c312 ;Preserve drive number
|
||||
searchDriveNum @ $c33c ;Search for drive number
|
||||
getDriveNum @ $c368 ;Get drive number
|
||||
reserveDriveNum @ $c38f ;Reverse drive number
|
||||
chkFileType @ $c398 ;Check given file type
|
||||
chkDriveNum @ $c3bd ;Check given drive number
|
||||
verifyDriveNum @ $c3ca ;Verify drive number
|
||||
searchDir @ $c44f ;Search for file in directory
|
||||
testInitDrive @ $c63d ;Test and initalise drive
|
||||
fnInDirBuf @ $c66e ;Name of file in directory buffer
|
||||
putFnInWorkBuf @ $c688 ;Copy filename to work buffer
|
||||
searchEndOfName @ $c6a6 ;Search for end of name in command
|
||||
clrDirOutputBuf @ $c7ac ;Clear Directory Output Buffer
|
||||
hdrWithDiskName @ $c7b7 ;Create header with disk name
|
||||
printBlocksFree @ $c806 ;Print 'blocks free.'
|
||||
deleteCmd @ $c823 ;Perform S - Scratch command
|
||||
deleteFile @ $c87d ;Erase file
|
||||
deleteEntry @ $c8b6 ;Erase dir entry
|
||||
formatCmd @ $c8c6 ;Format disk
|
||||
copyCmd @ $c8f0 ;Perform C - Copy command
|
||||
renameCmd @ $ca88 ;Perform R - Rename command
|
||||
presentCmd @ $cacc ;Check if file present
|
||||
memoryCmd @ $caf8 ;Perform M - Memory command
|
||||
memReadCmd @ $cb20 ;M-R memory read
|
||||
memWriteCmd @ $cb50 ;M-W memory write
|
||||
userCmd @ $cb5c ;Perform U - User command
|
||||
openDirAccChnl @ $cb84 ;Open direct access channel, number
|
||||
blockCmd @ $cc1b ;Perform B - Block/Buffer command
|
||||
parseBlkParams @ $cc6f ;Get parameters from block commands
|
||||
blockFreeCmd @ $ccf5 ;B-F block free
|
||||
blockAllocCmd @ $cd03 ;B-A block allocate
|
||||
readBlockToBuf @ $cd36 ;Read block to buffer
|
||||
getBufByte @ $cd3c ;Get byte from buffer
|
||||
readBlock @ $cd42 ;Read block from disk
|
||||
blkReadCmd @ $cd56 ;B-R block read
|
||||
blkReadInPlace @ $cd5f ;U1, Block read without changing buffer pointer
|
||||
blkWriteCmd @ $cd73 ;B-W block write
|
||||
blkWriteInPlace @ $cd97 ;U2, Block write without changing buffer pointer
|
||||
blkExecCmd @ $cda3 ;B-E block execute
|
||||
blkPtrCmd @ $cdbd ;B-P block pointer
|
||||
openChnl @ $cdd2 ;Open channel
|
||||
chkBufNum @ $cdf2 ;Check buffer number and open channel
|
||||
setRelFilePtr @ $ce0e ;Set pointer for REL file
|
||||
div254 @ $ce6e ;Divide by 254
|
||||
div120 @ $ce71 ;Divide by 120
|
||||
eraseWrkMem @ $ced9 ;Erase work storage
|
||||
chgBuf @ $cf8c ;Change buffer
|
||||
writeInBuf @ $cf9b ;Write data in buffer
|
||||
writeByteInBuf @ $cff1 ;Write data byte in buffer
|
||||
initCmd @ $d005 ;Perform I - Initalise command
|
||||
readBam @ $d00e ;Read BAM from disk
|
||||
loadBam @ $d042 ;Load BAM
|
||||
calcFree @ $d075 ;Calculate blocks free
|
||||
readBlock @ $d0c3 ;Read block
|
||||
writeBlock @ $d0c7 ;Write block
|
||||
openReadChnl @ $d0eb ;Open channel for reading
|
||||
openWriteChnl @ $d107 ;Open channel for writing
|
||||
checkForRel @ $d125 ;Check for file type REL
|
||||
getBufChnlNums @ $d12f ;Get buffer and channel numbers
|
||||
getByteFromBuf @ $d137 ;Get a byte from buffer
|
||||
getByteNextBlk @ $d156 ;Get byte and read next block
|
||||
writeToBufBlk @ $d19d ;Write byte in buffer and block
|
||||
incBufPtrs @ $d1c6 ;Increment buffer pointer
|
||||
getDriveNum @ $d1d3 ;Get drive number
|
||||
findWChnlBuf @ $d1df ;Find write channel and buffer
|
||||
findRChnlBuf @ $d1e2 ;Find read channel and buffer
|
||||
closeChnl @ $d227 ;Close channel
|
||||
freeBuf @ $d25a ;Free buffer
|
||||
findBuf @ $d28e ;Find buffer
|
||||
closeAllChnls @ $d307 ;Close all channels
|
||||
closeAllDChnls @ $d313 ;Close all channels of other drives
|
||||
findChnlAlloc @ $d37f ;Find channel and allocate
|
||||
getByteOutput @ $d39b ;Get byte for output
|
||||
readNextBlk @ $d44d ;Read next block
|
||||
readBlk @ $d460 ;Read block
|
||||
writeBlk @ $d464 ;Write block
|
||||
allocBufandRead @ $d475 ;Allocate buffer and read block
|
||||
allocBlk @ $d486 ;Allocate new block
|
||||
writeDirBlk @ $d48d ;Write dir block
|
||||
setBufPtr @ $d4c8 ;Set buffer pointer
|
||||
closeIntChnl @ $d4da ;Close internal channel
|
||||
setBufPtr2 @ $d4e8 ;Set buffer pointer
|
||||
getByteFromBuf2 @ $d4f6 ;Get byte from buffer
|
||||
chkTSnums @ $d506 ;Check track and sector numbers
|
||||
getTSForJob @ $d552 ;Get track and sector numbers for current job
|
||||
chkValidTSNums @ $d55f ;Check for vaild track and sector numbers
|
||||
errorDosMismtch @ $d572 ;DOS mismatch error
|
||||
readBlk2 @ $d586 ;Read block
|
||||
writeBlk2 @ $d58a ;Write block
|
||||
verifyExe @ $d599 ;Verify execution
|
||||
verifyExeNoWait @ $d5a6 ;Verify execution (without wait)
|
||||
attempts @ $d5c6 ;Additional attempts for read errors
|
||||
moveHeadHalfTrk @ $d676 ;Move head by half a track
|
||||
moveHeadOneTrk @ $d693 ;Move head one track in or out
|
||||
multiAttemptCmd @ $d6a6 ;Attempt command execution multiple times
|
||||
parmsToCtrl @ $d6d0 ;Transmit param to disk controller
|
||||
enterFileInDir @ $d6e4 ;Enter file in dir
|
||||
open @ $d7b4 ;OPEN command, secondary addr 15
|
||||
checkAstr @ $d7c7 ;Check '*' Last file
|
||||
checkDolr @ $d7f3 ;Check '$' Directory
|
||||
checkHash @ $d815 ;Check '#' Channel
|
||||
openOverwrite @ $d8f5 ;Open a file with overwriting (@)
|
||||
openRead @ $d9a0 ;Open file for reading
|
||||
openWrite @ $d9e3 ;Open file for writing
|
||||
chkTypetrl @ $da09 ;Check file type and control mode
|
||||
prepAppend @ $da2a ;Preparation for append
|
||||
openDir @ $da55 ;Open directory
|
||||
closeRoutine @ $dac0 ;Close routine
|
||||
closeFile @ $db02 ;Close file
|
||||
writeLastBlk @ $db62 ;Write last block
|
||||
dirEntry @ $dba5 ;Directory entry
|
||||
readBlkAllocBuf @ $dc46 ;Read block, allocate buffer
|
||||
resetPtr @ $dcb6 ;Reset pointer
|
||||
makeNewBlk @ $dcda ;Construct a new block
|
||||
writeSideSecBlk @ $dd8d ;Write byte in side-sector block
|
||||
verifyWriteCmd @ $ddab ;Verify command code for writing
|
||||
writeRelBlk @ $ddf1 ;Write a block of a REL file
|
||||
writeForNextTrk @ $ddfd ;Write bytes for following track
|
||||
getTSnums @ $de0c ;Get following track and sector numbers
|
||||
folTrkLastBlk @ $de19 ;Following track for last block
|
||||
zeroBufPtr @ $de2b ;buffer pointer to zero
|
||||
getTSnums2 @ $de3b ;Get track and sector
|
||||
getTSfromBuf @ $de95 ;Get following track and sector from buffer
|
||||
copyBuf @ $dea5 ;Copy buffer contents
|
||||
eraseBuf @ $dec1 ;Erase buffer Y
|
||||
getSideSecNum @ $ded2 ;Get side-sector number
|
||||
setBufPtrToSS @ $dedc ;Set buffer pointer to side-sector
|
||||
getSSandBufPtr @ $def8 ;Get side sector and buffer pointer
|
||||
readSS @ $df1b ;Read side-sector
|
||||
writeSS @ $df21 ;Write side-sector
|
||||
setBufInSS @ $df45 ;Set buffer pointer in side-sector
|
||||
blocksInRelFile @ $df4c ;Calculate number of blocks in a REL file
|
||||
verifySSinBuf @ $df66 ;Verify side-sector in buffer
|
||||
getBufNum @ $df93 ;Get buffer number
|
||||
nextRecInRel @ $dfd0 ;Get next record in REL file
|
||||
writeBlkGetNext @ $e03c ;Write block and read next block
|
||||
writeByteInRec @ $e07c ;Write a byte in a record
|
||||
writeByteInRel @ $e0ab ;Write byte in REL file
|
||||
zeroFillRec @ $e0f3 ;Fill record with 0s
|
||||
writeBufNumTbl @ $e105 ;Write buffer number in table
|
||||
getByteFromRel @ $e120 ;Get byte from REL file
|
||||
getLastSS @ $e1cb ;Get last side-sector
|
||||
positionCmd @ $e207 ;Perform P - Position command
|
||||
blksToRecords @ $e2e2 ;Divide data blocks into records
|
||||
prtToNextRec @ $e304 ;Set pointer to next record
|
||||
expandSS @ $e31c ;Expand side-sector
|
||||
writeSSallocNxt @ $e44e ;Write side-sector and allocate new
|
||||
prepErrNumMsg @ $e60a ;Prepare error number and message
|
||||
errorMsgToBuf @ $e645 ;Print error message into error buffer
|
||||
talk3 @ $e680 ;TALK
|
||||
listen @ $e688 ;LISTEN
|
||||
binToPetscii @ $e69b ;Convert BIN to petscii (error message buffer)
|
||||
bcdToPetscii @ $e6ab ;Convert BCD to petscii (error message buffer)
|
||||
writeOK @ $e6bc ;Write OK in buffer
|
||||
trk0ErrorToBuf @ $e6c1 ;Print error on track 00,00 to error buffer
|
||||
curTrkErrToBuf @ $e6c7 ;Print error on current track to error buffer
|
||||
errMsgToBuf @ $e706 ;Write error message string to buffer
|
||||
tokenIntoBuf @ $e754 ;Get character and in buffer
|
||||
getErrMsgChar @ $e767 ;Get a char of the error message
|
||||
incPtr @ $e775 ;Increment pointer
|
||||
usrExecCmd @ $e7a3 ;Perform & - USR file execute command
|
||||
genChecksum @ $e84b ;Generate checksum
|
||||
serialIrq @ $e853 ;IRQ routine for serial bus
|
||||
serialService @ $e85b ;Service the serial bus
|
||||
serialSend @ $e909 ;Send data
|
||||
serialDataOutLo @ $e99c ;DATA OUT lo
|
||||
serialDataOutHi @ $e9a5 ;DATA OUT hi
|
||||
serialClkOutHi @ $e9ae ;CLOCK OUT hi
|
||||
serialClkOutLo @ $e9b7 ;CLOCK OUT lo
|
||||
readIEEE @ $e9c0 ;Read IEEE port
|
||||
getByteFromBus @ $e9c9 ;Get data byte from bus
|
||||
getByteWithEOI @ $e9f2 ;Accept byte with EOI
|
||||
acceptData @ $ea2e ;Accept data from serial bus
|
||||
testATN @ $ea59 ;Test for ATN
|
||||
ledFlash @ $ea6e ;Flash LED for hardware defects, self-test
|
||||
reset @ $eaa0 ;Power-up RESET routine
|
||||
wait @ $ebff ;Wait loop
|
||||
loadDir @ $ec9e ;Load dir
|
||||
transmitDirLine @ $ed59 ;Transmit dir line
|
||||
getByteFromBuf3 @ $ed67 ;Get byte from buffer
|
||||
validateCmd @ $ed84 ;Perform V - Validate command
|
||||
bamAlloc @ $ede5 ;Allocate file blocks in BAM
|
||||
formatCmd2 @ $ee0d ;Perform N - New (Format) command
|
||||
createBAM @ $eeb7 ;Create BAM
|
||||
writeBAM @ $eef4 ;Write BAM if needed
|
||||
setBAMptr @ $ef3a ;Set buffer pointer for BAM
|
||||
getDirBlksFree @ $ef4d ;Get number of free blocks for dir
|
||||
markBlkFree @ $ef5c ;Mark block as free
|
||||
markBAMchanges @ $ef88 ;Set flag for BAM changed
|
||||
markBlkAlloc @ $ef90 ;Mark block as allocated
|
||||
delBAMsecBit @ $efcf ;Erase bit for sector in BAM entry
|
||||
updateBAM @ $eff1 ;Write BAM after change
|
||||
delBAMbuf @ $f005 ;Erase BAM buffer
|
||||
clearBAM @ $f0d1 ;Crear BAM
|
||||
getBAMbufNum @ $f10f ;Get buffer number for BAM
|
||||
bamBufNum @ $f119 ;Buffer number for BAM
|
||||
findFreeBlkAloc @ $f11e ;Find and allocate free block
|
||||
findFreeSecAloc @ $f1a9 ;Find free sector and allocate
|
||||
findFreeSectors @ $f1fa ;Find free sectors in current track
|
||||
verFreeBAMblks @ $f220 ;Verify number of free blocks in BAM
|
||||
numSecsPerTrk @ $f24b ;Establish number of sectors per track
|
||||
initCtrl @ $f259 ;Initialise disk controller
|
||||
irqCtrl @ $f2b0 ;IRQ routine for disk controller
|
||||
headTransport @ $f2f9 ;Head transport
|
||||
execInBuf @ $f36e ;Execute program in buffer
|
||||
bump @ $f37c ;Bump, find track 1 (head at stop)
|
||||
initPtrInBuf @ $f393 ;Initialise pointer in buffer
|
||||
readBlkHdr @ $f3b1 ;Read block header, verify ID
|
||||
prsrvBlkHdr @ $f410 ;Preserve block header
|
||||
okInQueue @ $f418 ;Work Return value $01 (OK) into queue
|
||||
error0bInQueue @ $f41b ;Work Return value $0b (READ ERROR) into queue
|
||||
error09InQueue @ $f41e ;Work Return value $09 (READ ERROR) into queue
|
||||
optimizeJob @ $f423 ;Job optimisation
|
||||
readSec @ $f4d1 ;Read sector
|
||||
findBlkStart @ $f50a ;Find start of data block
|
||||
readBlkHdr2 @ $f510 ;Read block header
|
||||
waitSync @ $f556 ;Wait for SYNC
|
||||
writeBlk3 @ $f575 ;Write data block to disk
|
||||
calcBufParity @ $f5e9 ;Calculate parity for data buffer
|
||||
gcrToBin @ $f5f2 ;Convert buffer of GCR data into binary
|
||||
findSec @ $f6ca ;Command code for find sector
|
||||
bytesToGcrBytes @ $f6d0 ;Convert 4 binary bytes to 5 GCR bytes
|
||||
gcrTable @ $f77f 16 ;GCR (5-bit) nybble table
|
||||
gcrBytesToBytes @ $f7e6 ;Convert 5 GCR bytes to 4 binary bytes
|
||||
tblGCRToBinHi @ $f8a0 64 ;Conversion table GCR to binary - high nybble
|
||||
tblGCRToBinLo @ $f8c0 64 ;Conversion table GCR to binary - low nybble
|
||||
decod69GcrBytes @ $f8e0 ;Decode 69 GCR bytes
|
||||
blkHdrToGcr @ $f934 ;Convert block header to GCR code
|
||||
errEntry @ $f969 ;Error entry disk controller
|
||||
motorOn @ $f97e ;Turn drive motor on
|
||||
motorOff @ $f98f ;Turn drive motor off
|
||||
jobLoop @ $f99c ;Job loop disk controller
|
||||
moveHeadNextTrk @ $fa05 ;Move head to next track
|
||||
calNumSteps @ $fa1c ;Calculate number of head steps
|
||||
nudgeStepper @ $fa3b ;Move stepper motor short distance
|
||||
loadHead @ $fa4e ;Load head
|
||||
prepFastHeadMov @ $fa7b ;Prepare fast head movement
|
||||
fastHeadMov @ $fa97 ;Fast head movement
|
||||
prepSlowHeadMov @ $faa5 ;Prepare slow head movement
|
||||
formatRoutine @ $fac7 ;Formatting
|
||||
writeSyncs @ $fda3 ;Write SYNC 10240 times, erase track
|
||||
writeByteFill @ $fdc3 ;Read/write ($621/$622) times
|
||||
formatErrRetry @ $fdd3 ;Attempt counter for formatting
|
||||
cpyOvflwDataBuf @ $fdf5 ;Copy data from overflow buffer
|
||||
switchToRead @ $fe00 ;Switch to reading
|
||||
write55Fill @ $fe0e ;Write $55 10240 times
|
||||
buf0HdrToGcr @ $fe30 ;Convert header in buffer 0 to GCR code
|
||||
irdMainSystem @ $fe67 ;Interrupt routine
|
||||
jmpToVNMI @ $fee7 ;From UI command $eb22, to reset
|
||||
diagPatch @ $feea ;Patch for diagnostic routine from $ea7a
|
||||
serialBusDelay @ $fef3 ;Delay loop for serial bus in 1541 mode, from $e97d
|
||||
serialOutPatch @ $fefb ;Patch for data output to serial bus, from $e980
|
||||
switch1540_1541 @ $ff01 2 ;U9 vector, switch 1540/1541
|
||||
resetPatch @ $ff10 ;Patch for reset routine, from $eaa4
|
||||
listenPatch @ $ff20 ;Patch for listen to serial bus, from $e9dc
|
||||
vecFormat @ $ffe6 2 ;vector for format
|
||||
vecOff @ $ffe8 2 ;vector for $f98f
|
||||
vecUblkkrd @ $ffea 2 ;vector for $cd5f
|
||||
vecUblkwt @ $ffec 2 ;vector for $cd97
|
||||
vecNMI @ $fffa 2 ;vector to $ff01
|
||||
vecInit @ $fffc 2 ;vector to $eaa0
|
||||
vecIrq @ $fffe 2 ;vector to $fe67
|
88
SourceGen/RuntimeData/Commodore/C64-BASIC-RAM-use.sym65
Normal file
88
SourceGen/RuntimeData/Commodore/C64-BASIC-RAM-use.sym65
Normal file
|
@ -0,0 +1,88 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Project 64, 64MAP10.TXT, June 1996, etext #41
|
||||
; http://unusedino.de/ec64/technical/project64/memory_maps.html
|
||||
;
|
||||
; - "Mapping the Commodore 64", by Sheldon Leemon
|
||||
; Compute! Publications Inc. (1984), ISBN 0-942386-23-X
|
||||
; https://archive.org/details/Compute_s_Mapping_the_Commodore_64
|
||||
|
||||
*SYNOPSIS RAM locations used by BASIC
|
||||
|
||||
ADRAY1 @ $0003 2 ;Vector: Convert FAC to Integer in (A/Y) ($b1aa)
|
||||
ADRAY2 @ $0005 2 ;Vector: Convert int in (A/Y) to float in (FAC) ($b391)
|
||||
CHARAC @ $0007 ;Search Character/Temporary Integer during INT
|
||||
ENDCHR @ $0008 ;Flag: Scan for Quote at end of String
|
||||
INTEGR @ $0007 ;Temporary Integer during OR/AND
|
||||
TRMPOS @ $0009 ;Screen Column for last TAB
|
||||
VERCK @ $000a ;Flag: 0 = Load, 1 = Verify
|
||||
COUNT @ $000b ;Input Buffer Pointer/Number of Subscripts
|
||||
DIMFLG @ $000c ;Flag: Default Array dimension
|
||||
VALTYP @ $000d ;Data type Flag: $00 = Numeric, $FF = String
|
||||
INTFLG @ $000e ;Data type Flag: $00 = Floating point, $80 = Integer
|
||||
GARBFL @ $000f ;Flag: DATA scan/List Quote/Garbage collection
|
||||
SUBFLG @ $0010 ;Flag: Subscript reference/User Function call
|
||||
INPFLG @ $0011 ;Input Flag: $00 = INPUT, $40 = GET, $98 = READ
|
||||
TANSGN @ $0012 ;Flag: TAN sign/Comparative result
|
||||
CHANNL @ $0013 ;File number of current Input Device
|
||||
LINNUM @ $0014 2 ;Temporary: Integer value
|
||||
TEMPPT @ $0016 ;Pointer: Temporary String Stack
|
||||
LASTPT @ $0017 2 ;Last temporary String Address
|
||||
TEMPST @ $0019 9 ;Stack for temporary Strings
|
||||
INDEX1 @ $0022 2 ;First Utility Pointer
|
||||
INDEX2 @ $0024 2 ;Second Utility Pointer
|
||||
RESHO @ $0026 5 ;Floating point product of Multiply and Divide
|
||||
TXTTAB @ $002b 2 ;Pointer: Start of BASIC Text Area ($0801)
|
||||
VARTAB @ $002d 2 ;Pointer: Start of BASIC Variables
|
||||
ARYTAB @ $002f 2 ;Pointer: Start of BASIC Arrays
|
||||
STREND @ $0031 2 ;Pointer: End of BASIC Arrays + 1
|
||||
FRETOP @ $0033 2 ;Pointer: Bottom of String space
|
||||
FRESPC @ $0035 2 ;Utility String Pointer
|
||||
MEMSIZ @ $0037 2 ;Pointer: Highest Address available to BASIC ($a000)
|
||||
CURLIN @ $0039 2 ;Current BASIC Line number
|
||||
OLDLIN @ $003b 2 ;Previous BASIC Line number
|
||||
OLDTXT @ $003d 2 ;Pointer: BASIC Statement for CONT
|
||||
DATLIN @ $003f 2 ;Current DATA Line number
|
||||
DATPTR @ $0041 2 ;Pointer: Used by READ - current DATA Item Address
|
||||
INPPTR @ $0043 2 ;Pointer: Temporary storage of Pointer during INPUT Routine
|
||||
VARNAM @ $0045 2 ;Name of Variable being sought in Variable Table
|
||||
VARPNT @ $0047 2 ;Pointer: to value of (VARNAM) if Int, to descriptor if Str
|
||||
FORPNT @ $0049 2 ;Pointer: Index Variable for FOR/NEXT loop
|
||||
VARTXT @ $004b 2 ;Temporary storage for TXTPTR during READ, INPUT and GET
|
||||
OPMASK @ $004d ;Mask used during FRMEVL
|
||||
TEMPF3 @ $004e 2 ;Temporary storage for FLPT value
|
||||
FOUR6 @ $0053 ;Length of String Variable during Garbage collection
|
||||
JMPER @ $0054 3 ;jmp used in Function Evaluation
|
||||
TEMPF1 @ $0057 10 ;Temporary storage for FLPT value
|
||||
TEMPF2 @ $005c ;Temporary storage for FLPT value
|
||||
FACEXP @ $0061 ;FAC Exponent
|
||||
FACHO @ $0062 4 ;FAC Mantissa
|
||||
FACSGN @ $0066 ;FAC Sign
|
||||
SGNFLG @ $0067 ;Pointer: Series Evaluation Constant
|
||||
BITS @ $0068 ;Bit Overflow Area during normalisation Routine
|
||||
ARGEXP @ $0069 ;AFAC Exponent
|
||||
ARGHO @ $006a 4 ;AFAC Mantissa
|
||||
ARGSGN @ $006e ;AFAC Sign
|
||||
ARISGN @ $006f ;Sign of result of Arithmetic Evaluation
|
||||
FACOV @ $0070 ;FAC low-order rounding
|
||||
FBUFPT @ $0071 2 ;Pointer: Used during CRUNCH/ASCII conversion
|
||||
CHRGET @ $0073 ;Subroutine: Get next Byte of BASIC Text
|
||||
CHRGOT @ $0079 ;Entry to Get same Byte again
|
||||
TXTPTR @ $007a 2 ;Pointer: Current Byte of BASIC Text
|
||||
RNDX @ $008b 5 ;Floating RND Function Seed Value
|
||||
BSTACK @ $013f ;BASIC Stack Area
|
||||
BUF @ $0200 ;BASIC Input Buffer (Input Line from Screen)
|
||||
IERROR @ $0300 2 ;Vector: BASIC Error ($e38b)
|
||||
IMAIN @ $0302 2 ;Vector: BASIC Input Line ($a483)
|
||||
ICRNCH @ $0304 2 ;Vector: BASIC Tokenise ($a57c)
|
||||
IQPLOP @ $0306 2 ;Vector: BASIC LIST ($a71a)
|
||||
IGONE @ $0308 2 ;Vector: BASIC Character ($a7e4)
|
||||
IEVAL @ $030a 2 ;Vector: BASIC Token ($ae86)
|
||||
SAREG @ $030c ;Storage for 6510 Accumulator during SYS
|
||||
SXREG @ $030d ;Storage for 6510 X-Register during SYS
|
||||
SYREG @ $030e ;Storage for 6510 Y-Register during SYS
|
||||
SPREG @ $030f ;Storage for 6510 Status Register during SYS
|
||||
USRPOK @ $0310 ;USR Function JMP Instruction ($4c)
|
||||
USRADD @ $0311 ;USR Address ($LB,$MB)
|
183
SourceGen/RuntimeData/Commodore/C64-BASIC-ROM.sym65
Normal file
183
SourceGen/RuntimeData/Commodore/C64-BASIC-ROM.sym65
Normal file
|
@ -0,0 +1,183 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Project 64, 64MAP10.TXT, June 1996, etext #41
|
||||
; http://unusedino.de/ec64/technical/project64/memory_maps.html
|
||||
;
|
||||
; - PageTable's C64 BASIC & KERNAL ROM Disassembly
|
||||
; https://www.pagetable.com/c64ref/c64disasm/
|
||||
;
|
||||
; - "Mapping the Commodore 64", by Sheldon Leemon
|
||||
; Compute! Publications Inc. (1984), ISBN 0-942386-23-X
|
||||
; https://archive.org/details/Compute_s_Mapping_the_Commodore_64
|
||||
|
||||
*SYNOPSIS BASIC ROM ($a000-$bfff) labels (functions and vectors)
|
||||
|
||||
coldStartVec @ $a000 2 ;Cold Start Vector
|
||||
warmStartVec @ $a002 2 ;Warm Start Vector
|
||||
fndfor @ $a38a ;Find FOR/GOSUB Entry on Stack
|
||||
bltu @ $a3b8 ;Open Space in Memory
|
||||
getstk @ $a3fb ;Check Stack Depth
|
||||
reason @ $a408 ;Check Memory Overlap
|
||||
omerr @ $a435 ;Output ?OUT OF MEMORY Error
|
||||
error @ $a437 ;Error Routine
|
||||
errfin @ $a469 ;Break Entry
|
||||
ready @ $a474 ;Restart BASIC
|
||||
main @ $a480 ;Input & Identify BASIC Line
|
||||
main1 @ $a49c ;Get Line Number & Tokenise Text
|
||||
inslin @ $a4a2 ;Insert BASIC Text
|
||||
linkprg @ $a533 ;Rechain Lines
|
||||
inlin @ $a560 ;Input Line Into Buffer
|
||||
crunch @ $a579 ;Tokenise Input Buffer
|
||||
fndlin @ $a613 ;Search for Line Number
|
||||
scrtch @ $a642 ;Perform new
|
||||
clear @ $a65e ;Perform clr
|
||||
stxpt @ $a68e ;Reset TXTPTR
|
||||
list @ $a69c ;Perform list
|
||||
qplop @ $a717 ;Handle LIST Character
|
||||
for @ $a742 ;Perform for
|
||||
newstt @ $a7ae ;BASIC Warm Start
|
||||
ckeol @ $a7c4 ;Check End of Program
|
||||
gone @ $a7e1 ;Prepare to execute statement
|
||||
gone3 @ $a7ed ;Perform BASIC Keyword
|
||||
restor3 @ $a81d ;Perform restore
|
||||
stop @ $a82c ;Perform stop, end, break
|
||||
cont @ $a857 ;Perform cont
|
||||
run @ $a871 ;Perform run
|
||||
gosub @ $a883 ;Perform gosub
|
||||
goto @ $a8a0 ;Perform goto
|
||||
return @ $a8d2 ;Perform return
|
||||
data @ $a8f8 ;Perform data
|
||||
datan @ $a906 ;Search for Next Statement / Line
|
||||
if @ $a928 ;Perform if
|
||||
rem @ $a93b ;Perform rem
|
||||
ongoto @ $a94b ;Perform on
|
||||
linget @ $a96b ;Fetch linnum From BASIC
|
||||
let @ $a9a5 ;Perform let
|
||||
putint @ $a9c4 ;Assign Integer
|
||||
ptflpt @ $a9d6 ;Assign Floating Point
|
||||
putstr @ $a9d9 ;Assign String
|
||||
puttim @ $a9e3 ;Assign TI$
|
||||
getspt @ $aa2c ;Add Digit to FAC#1
|
||||
printn @ $aa80 ;Perform print#
|
||||
cmd @ $aa86 ;Perform cmd
|
||||
strdon @ $aa9a ;Print String From Memory
|
||||
print @ $aaa0 ;Perform print
|
||||
varop @ $aab8 ;Output Variable
|
||||
crdo @ $aad7 ;Output CR/LF
|
||||
comprt @ $aae8 ;Handle comma, TAB(, SPC(
|
||||
strout @ $ab1e ;Output String
|
||||
outspc @ $ab3b ;Output Format Character
|
||||
doagin @ $ab4d ;Handle Bad Data
|
||||
get @ $ab7b ;Perform get
|
||||
inputn @ $aba5 ;Perform input#
|
||||
input @ $abbf ;Perform input
|
||||
bufful @ $abea ;Read Input Buffer
|
||||
qinlin @ $abf9 ;Do Input Prompt
|
||||
read @ $ac06 ;Perform read
|
||||
rdget @ $ac35 ;General Purpose Read Routine
|
||||
next @ $ad1e ;Perform next
|
||||
donext @ $ad61 ;Check Valid Loop
|
||||
frmnum @ $ad8a ;Confirm Result
|
||||
frmevl @ $ad9e ;Evaluate Expression in Text
|
||||
eval @ $ae83 ;Evaluate Single Term
|
||||
qdot @ $aead ;Continue Expression
|
||||
parchk @ $aef1 ;Expression in Brackets
|
||||
chkcls @ $aef7 ;Confirm Character
|
||||
synerr @ $af08 ;Output ?SYNTAX Error
|
||||
domin @ $af0d ;Set up NOT Function
|
||||
rsvvar @ $af14 ;Identify Reserved Variable
|
||||
isvar @ $af28 ;Search for Variable
|
||||
tisasc @ $af48 ;Convert TI to ASCII String
|
||||
isfun @ $afa7 ;Identify Function Type
|
||||
strfun @ $afb1 ;Evaluate String Function
|
||||
numfun @ $afd1 ;Evaluate Numeric Function
|
||||
orop @ $afe6 ;Perform or, and
|
||||
dorel @ $b016 ;Perform <, =, >
|
||||
numrel @ $b01b ;Numeric Comparison
|
||||
strrel @ $b02e ;String Comparison
|
||||
dim @ $b07e ;Perform dim
|
||||
ptrget @ $b08b ;Identify Variable
|
||||
ordvar @ $b0e7 ;Locate Ordinary Variable
|
||||
notfns @ $b11d ;Create New Variable
|
||||
notevl @ $b128 ;Create Variable
|
||||
aryget @ $b194 ;Allocate Array Pointer Space
|
||||
facinx @ $b1aa ;FAC#1 to Integer in (AC/YR)
|
||||
intidx @ $b1b2 ;Evaluate Text for Integer
|
||||
ayint @ $b1bf ;FAC#1 to Positive Integer
|
||||
isary @ $b1d1 ;Get Array Parameters
|
||||
fndary @ $b218 ;Find Array
|
||||
bserr @ $b245 ;?BAD SUBSCRIPT/?ILLEGAL QUANTITY
|
||||
notfdd @ $b261 ;Create Array
|
||||
inlpn2 @ $b30e ;Locate Element in Array
|
||||
umult @ $b34c ;Number of Bytes in Subscript
|
||||
fre @ $b37d ;Perform fre
|
||||
givayf @ $b391 ;Convert Integer in (AC/YR) to Flpt
|
||||
pos @ $b39e ;Perform pos
|
||||
errdir @ $b3a6 ;Confirm Program Mode
|
||||
getfnm @ $b3e1 ;Check Syntax of FN
|
||||
fndoer @ $b3f4 ;Perform fn
|
||||
strd @ $b465 ;Perform str$
|
||||
strlit @ $b487 ;Set Up String
|
||||
putnw1 @ $b4d5 ;Save String Descriptor
|
||||
getspa @ $b4f4 ;Allocate Space for String
|
||||
garbag @ $b526 ;Garbage Collection
|
||||
dvars @ $b5bd ;Search for Next String
|
||||
grbpas @ $b606 ;Collect a String
|
||||
cat @ $b63d ;Concatenate Two Strings
|
||||
movins @ $b67a ;Store String in High RAM
|
||||
frestr @ $b6a3 ;Perform String Housekeeping
|
||||
frefac @ $b6db ;Clean Descriptor Stack
|
||||
chrd @ $b6ec ;Perform chr$
|
||||
leftd @ $b700 ;Perform left$
|
||||
rightd @ $b72c ;Perform right$
|
||||
midd @ $b737 ;Perform mid$
|
||||
pream @ $b761 ;Pull sTring Parameters
|
||||
len @ $b77c ;Perform len
|
||||
len1 @ $b782 ;Exit String Mode
|
||||
asc @ $b78b ;Perform asc
|
||||
gtbytc @ $b79b ;Evaluate Text to 1 Byte in XR
|
||||
val @ $b7ad ;Perform val
|
||||
strval @ $b7b5 ;Convert ASCII String to Flpt
|
||||
getnum @ $b7eb ;Get parameters for POKE/WAIT
|
||||
getadr @ $b7f7 ;Convert FAC#1 to Integer in LINNUM
|
||||
peek @ $b80d ;Perform peek
|
||||
poke @ $b824 ;Perform poke
|
||||
wait @ $b82d ;Perform wait
|
||||
faddh @ $b849 ;Add 0.5 to FAC#1
|
||||
fsub @ $b850 ;Perform Subtraction
|
||||
fadd5 @ $b862 ;Normalise Addition
|
||||
fadd @ $b867 ;Perform Addition
|
||||
negfac @ $b947 ;2's Complement FAC#1
|
||||
overr @ $b97e ;Output ?OVERFLOW Error
|
||||
mulshf @ $b983 ;Multiply by Zero Byte
|
||||
log @ $b9ea ;Perform log
|
||||
fmult @ $ba28 ;Perform Multiply
|
||||
mulply @ $ba59 ;Multiply by a Byte
|
||||
conupk @ $ba8c ;Load FAC#2 From Memory
|
||||
muldiv @ $bab7 ;Test Both Accumulators
|
||||
mldvex @ $bad4 ;Overflow / Underflow
|
||||
mul10 @ $bae2 ;Multiply FAC#1 by 10
|
||||
div10 @ $bafe ;Divide FAC#1 by 10
|
||||
fdiv @ $bb07 ;Divide FAC#2 by Flpt at (AC/YR)
|
||||
fdivt @ $bb0f ;Divide FAC#2 by FAC#1
|
||||
movfm @ $bba2 ;Load FAC#1 From Memory
|
||||
mov2f @ $bbc7 ;Store FAC#1 in Memory
|
||||
movfa @ $bbfc ;Copy FAC#2 into FAC#1
|
||||
movaf @ $bc0c ;Copy FAC#1 into FAC#2
|
||||
round @ $bc1b ;Round FAC#1
|
||||
sign @ $bc2b ;Check Sign of FAC#1
|
||||
sgn @ $bc39 ;Perform sgn
|
||||
abs @ $bc58 ;Perform abs
|
||||
fcomp @ $bc5b ;Compare FAC#1 With Memory
|
||||
qint @ $bc9b ;Convert FAC#1 to Integer
|
||||
int @ $bccc ;Perform int
|
||||
fin @ $bcf3 ;Convert ASCII String to a Number in FAC#1
|
||||
inprt @ $bdc2 ;Output 'IN' and Line Number
|
||||
fout @ $bddd ;Convert FAC#1 to ASCII String
|
||||
foutim @ $be68 ;Convert TI to String
|
||||
sqr @ $bf71 ;Perform sqr
|
||||
fpwrt @ $bf7b ;Perform power ($)
|
||||
negop @ $bfb4 ;Negate FAC#1
|
||||
exp @ $bfed ;Perform exp (continued in KERNAL)
|
124
SourceGen/RuntimeData/Commodore/C64-IO.sym65
Normal file
124
SourceGen/RuntimeData/Commodore/C64-IO.sym65
Normal file
|
@ -0,0 +1,124 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Project 64, 64MAP10.TXT, June 1996, etext #41
|
||||
; http://unusedino.de/ec64/technical/project64/memory_maps.html
|
||||
;
|
||||
; - "Mapping the Commodore 64", by Sheldon Leemon
|
||||
; Compute! Publications Inc. (1984), ISBN 0-942386-23-X
|
||||
; https://archive.org/details/Compute_s_Mapping_the_Commodore_64
|
||||
|
||||
*SYNOPSIS Commodore 64 memory-mapped I/O addresses (and color ram)
|
||||
|
||||
D6510 @ $0000 ;6510 I/O Data Direction Register
|
||||
R6510 @ $0001 ;ROM/IO Banking and Cassette I/O
|
||||
SPOX @ $D000 ;Sprite 0 X Pos
|
||||
SPOY @ $D001 ;Sprite 0 Y Pos
|
||||
SP1X @ $D002 ;Sprite 1 X Pos
|
||||
SP1Y @ $D003 ;Sprite 1 Y Pos
|
||||
SP2X @ $D004 ;Sprite 2 X Pos
|
||||
SP2Y @ $D005 ;Sprite 2 Y Pos
|
||||
SP3X @ $D006 ;Sprite 3 X Pos
|
||||
SP3Y @ $D007 ;Sprite 3 Y Pos
|
||||
SP4X @ $D008 ;Sprite 4 X Pos
|
||||
SP4Y @ $D009 ;Sprite 4 Y Pos
|
||||
SP5X @ $D00A ;Sprite 5 X Pos
|
||||
SP5Y @ $D00B ;Sprite 5 Y Pos
|
||||
SP6X @ $D00C ;Sprite 6 X Pos
|
||||
SP6Y @ $D00D ;Sprite 6 Y Pos
|
||||
SP7X @ $D00E ;Sprite 7 X Pos
|
||||
SP7Y @ $D00F ;Sprite 7 Y Pos
|
||||
MSIGX @ $D010 ;Sprites 0-7 X Pos 9th bit
|
||||
SCROLY @ $D011 ;VIC Control Register
|
||||
RASTER @ $D012 ;Read Raster / Write Raster Value for Compare
|
||||
LPENX @ $D013 ;Light Pen/Gun Latch X Pos (divided by 2)
|
||||
LPENY @ $D014 ;Light Pen/Gun Latch Y Pos
|
||||
SPENA @ $D015 ;Sprites 0-7 display Enable (1 = enable)
|
||||
SCROLX @ $D016 ;VIC Control Register
|
||||
YXPAND @ $D017 ;Sprites 0-7 Expand 2x Vertical
|
||||
VMCSB @ $D018 ;VIC Memory Control Register
|
||||
VICIRQ @ $D019 ;VIC Interrupt Flag Register
|
||||
IRQMSK @ $D01A ;IRQ Mask Register (1 = Interrupt Enable)
|
||||
SPBGPR @ $D01B ;Sprite to Background Display Priority
|
||||
SPMC @ $D01C ;Sprites 0-7 Multi-Color Mode Select
|
||||
XXPAND @ $D01D ;Sprites 0-7 Expand 2x Horizontal
|
||||
SPSPCL @ $D01E ;Sprite to Sprite Collision Detect
|
||||
SPBGCL @ $D01F ;Sprite to Background Collision Detect
|
||||
EXTCOL @ $D020 ;Border Color
|
||||
BGCOL0 @ $D021 ;Background Color 0 (screen color)
|
||||
BGCOL1 @ $D022 ;Background Color 1
|
||||
BGCOL2 @ $D023 ;Background Color 2
|
||||
BGCOL3 @ $D024 ;Background Color 3
|
||||
SPMC0 @ $D025 ;Sprite Multi-Color Register 0
|
||||
SPMC1 @ $D026 ;Sprite Multi-Color Register 1
|
||||
SP0CL @ $D027 ;Sprite 0 Color
|
||||
SP1CL @ $D028 ;Sprite 1 Color
|
||||
SP2CL @ $D029 ;Sprite 2 Color
|
||||
SP3CL @ $D02A ;Sprite 3 Color
|
||||
SP4CL @ $D02B ;Sprite 4 Color
|
||||
SP5CL @ $D02C ;Sprite 5 Color
|
||||
SP6CL @ $D02D ;Sprite 6 Color
|
||||
SP7CL @ $D02E ;Sprite 7 Color
|
||||
FRELO1 > $D400 ;Voice 1 Frequency - Low-Byte
|
||||
FREHI1 > $D401 ;Voice 1 Frequency - High-Byte
|
||||
PWLO1 > $D402 ;Voice 1 Pulse Waveform Width - Low-Byte
|
||||
PWHI1 > $D403 ;Voice 1 Pulse Waveform Width - High-Nybble
|
||||
VCREG1 > $D404 ;Voice 1 Control Register
|
||||
ATDCY1 > $D405 ;Voice 1 Attack / Decay
|
||||
SUREL1 > $D406 ;Voice 1 Sustain / Release
|
||||
FRELO2 > $D407 ;Voice 2 Frequency - Low-Byte
|
||||
FREHI2 > $D408 ;Voice 2 Frequency - High-Byte
|
||||
PWLO2 > $D409 ;Voice 2 Pulse Waveform Width - Low-Byte
|
||||
PWHI2 > $D40A ;Voice 2 Pulse Waveform Width - High-Nybble
|
||||
VCREG2 > $D40B ;Voice 2 Control Register
|
||||
ATDCY2 > $D40C ;Voice 2 Attack / Decay
|
||||
SUREL2 > $D40D ;Voice 2 Sustain / Release
|
||||
FRELO3 > $D40E ;Voice 3 Frequency - Low-Byte
|
||||
FREHI3 > $D40F ;Voice 3 Frequency - High-Byte
|
||||
PWLO3 > $D410 ;Voice 3 Pulse Waveform Width - Low-Byte
|
||||
PWHI3 > $D411 ;Voice 3 Pulse Waveform Width - High-Nybble
|
||||
VCREG3 > $D412 ;Voice 3 Control Register
|
||||
ATDCY3 > $D413 ;Voice 3 Attack/Decay
|
||||
SUREL3 > $D414 ;Voice 3 Sustain / Release
|
||||
CUTLO > $D415 ;Filter Cutoff Frequency Low-Nybble
|
||||
CUTHI > $D416 ;Filter Cutoff Frequency High-Byte
|
||||
RESON > $D417 ;Filter Resonance / Voice Input
|
||||
SIGVOL > $D418 ;Select Filter Mode and Volume
|
||||
POTX > $D419 ;Analog/Digital Converter Game Paddle 1
|
||||
POTY > $D41A ;Analog/Digital Converter Game Paddle 2
|
||||
RANDOM < $D41B ;Voice 3 Oscillator output
|
||||
ENV3 < $D41C ;Voice 3 Envelope output
|
||||
colorRam @ $D800 1024 ;Color RAM nybbles ($d800-$dbff)
|
||||
CIAPRA @ $DC00 ;CIA1 Data Port A (Keyboard, Joystick, Paddles, Light-Pen)
|
||||
CIAPRB @ $DC01 ;CIA1 Data Port B (Keyboard, Joysticks, Paddles)
|
||||
CIDDRA @ $DC02 ;CIA1 Data Direction Register - Port A
|
||||
CIDDRB @ $DC03 ;CIA1 Data Direction Register - Port B
|
||||
TIMALO @ $DC04 ;CIA1 Timer A Low-Byte
|
||||
TIMAHI @ $DC05 ;CIA1 Timer A High-Byte
|
||||
TIMBLO @ $DC06 ;CIA1 Timer B Low-Byte
|
||||
TIMBHI @ $DC07 ;CIA1 Timer B High-Byte
|
||||
TODTEN @ $DC08 ;CIA1 Time-of-Day Clock 1/10 Seconds
|
||||
TODSEC @ $DC09 ;CIA1 Time-of-Day Clock Seconds
|
||||
TODMIN @ $DC0A ;CIA1 Time-of-Day Clock Minutes
|
||||
TODHRS @ $DC0B ;CIA1 Time-of-Day Clock Hours + AM/PM Flag (Bit 7)
|
||||
CIASDR @ $DC0C ;CIA1 Synchronous Serial I/O Data Buffer
|
||||
CIAICR @ $DC0D ;CIA1 CIA Interrupt Control Register
|
||||
CIACRA @ $DC0E ;CIA1 CIA Control Register A
|
||||
CIACRB @ $DC0F ;CIA1 CIA Control Register B
|
||||
CI2PRA @ $DD00 ;CIA2 Data Port A (Serial Bus RS-232, VIC Memory Control)
|
||||
CI2PRB @ $DD01 ;CIA2 Data Port B (User Port, RS-232)
|
||||
C2DDRA @ $DD02 ;CIA2 Data Direction Register - Port A
|
||||
C2DDRB @ $DD03 ;CIA2 Data Direction Register - Port B
|
||||
TI2ALO @ $DD04 ;CIA2 Timer A Low-Byte
|
||||
TI2AHI @ $DD05 ;CIA2 Timer A High-Byte
|
||||
TI2BLO @ $DD06 ;CIA2 Timer B Low-Byte
|
||||
TI2BHI @ $DD07 ;CIA2 Timer B High-Byte
|
||||
TO2TEN @ $DD08 ;CIA2 Time-of-Day Clock 1/10 Seconds
|
||||
TO2SEC @ $DD09 ;CIA2 Time-of-Day Clock Seconds
|
||||
TO2MIN @ $DD0A ;CIA2 Time-of-Day Clock Minutes
|
||||
TO2HRS @ $DD0B ;CIA2 Time-of-Day Clock Hours + AM/PM Flag (Bit 7)
|
||||
CI2SDR @ $DD0C ;CIA2 Synchronous Serial I/O Data Buffer
|
||||
CI2ICR @ $DD0D ;CIA2 CIA Interrupt Control Register
|
||||
CI2CRA @ $DD0E ;CIA2 CIA Control Register A
|
||||
CI2CRB @ $DD0F ;CIA2 CIA Control Register B
|
139
SourceGen/RuntimeData/Commodore/C64-Kernal-RAM-use.sym65
Normal file
139
SourceGen/RuntimeData/Commodore/C64-Kernal-RAM-use.sym65
Normal file
|
@ -0,0 +1,139 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Project 64, 64MAP10.TXT, June 1996, etext #41
|
||||
; http://unusedino.de/ec64/technical/project64/memory_maps.html
|
||||
;
|
||||
; - "Mapping the Commodore 64", by Sheldon Leemon
|
||||
; Compute! Publications Inc. (1984), ISBN 0-942386-23-X
|
||||
; https://archive.org/details/Compute_s_Mapping_the_Commodore_64
|
||||
|
||||
*SYNOPSIS RAM locations used by the KERNAL
|
||||
|
||||
STATUS @ $0090 ;Kernal I/O Status Word ST
|
||||
STKEY @ $0091 ;Flag: $7f = STOP key
|
||||
SVXT @ $0092 ;Timing Constant for Tape
|
||||
VERCKK @ $0093 ;Flag: 0 = Load, 1 = Verify
|
||||
C3PO @ $0094 ;Flag: Serial Bus - Output Character buffered
|
||||
BSOUR @ $0095 ;Buffered Character for Serial Bus
|
||||
SYNO @ $0096 ;Cassette Sync. number
|
||||
TEMPX @ $0097 ;Temporary storage of X Register during CHRIN
|
||||
TEMPY @ $0097 ;Temporary storage of Y Register during RS232 fetch
|
||||
LDTND @ $0098 ;Number of Open Files/Index to File Table
|
||||
DFLTN @ $0099 ;Default Input Device (0)
|
||||
DFLTO @ $009a ;Default Output Device (3)
|
||||
PRTY @ $009b ;Parity of Byte Output to Tape
|
||||
DPSW @ $009c ;Flag: Byte received from Tape
|
||||
MSGFLG @ $009d ;Set error message mode
|
||||
FNMIDX @ $009e ;Index to Cassette File name/Header ID for Tape write
|
||||
PTR1 @ $009e ;Tape Error log pass 1
|
||||
PTR2 @ $009f ;Tape Error log pass 2
|
||||
TIME @ $00a0 ;Real-time jiffy Clock, Update Routine: UDTIMK ($f69b)
|
||||
TSFCNT @ $00a3 ;Bit Counter Tape Read or Write/Serial Bus
|
||||
TBTCNT @ $00a4 ;Pulse Counter Tape Read or Write/Serial Bus shift Counter
|
||||
CNTDN @ $00a5 ;Tape Synchronising count down
|
||||
BUFPNT @ $00a6 2 ;Pointer: Tape I/O buffer
|
||||
INBIT @ $00a7 ;RS232 temporary for received Bit/Tape
|
||||
BITC1 @ $00a8 ;RS232 Input Bit count/Tape temporary
|
||||
RINONE @ $00a9 ;RS232 Flag: Start Bit check/Tape temporary
|
||||
RIDATA @ $00aa ;RS232 Input Byte Buffer/Tape temporary
|
||||
RIPRTY @ $00ab ;RS232 Input parity/Tape temporary
|
||||
SAL @ $00ac 2 ;Pointer: Tape Buffer/Screen scrolling
|
||||
EAL @ $00ae ;Tape End Address/End of Program
|
||||
CMPO @ $00b0 ;Tape timing Constants
|
||||
TAPE1 @ $00b2 2 ;Pointer: Start Address of Tape Buffer ($033c)
|
||||
BITTS @ $00b4 ;RS232 Write bit count/Tape Read timing Flag
|
||||
NXTBIT @ $00b5 ;RS232 Next Bit to send/Tape Read - End of Tape
|
||||
RODATA @ $00b6 ;RS232 Output Byte Buffer/Tape Read Error Flag
|
||||
FNLEN @ $00b7 ;Number of Characters in Filename
|
||||
LA @ $00b8 ;Current File - Logical File number
|
||||
SA @ $00b9 ;Current File - Secondary Address
|
||||
FA @ $00ba ;Current File - First Address (Device number)
|
||||
FNADR @ $00bb 2 ;Pointer: Current File name Address
|
||||
ROPRTY @ $00bd ;RS232 Output Parity/Tape Byte to be Input or Output
|
||||
FSBLK @ $00be ;Tape Input/Output Block count
|
||||
MYCH @ $00bf ;Serial Word Buffer
|
||||
CAS1 @ $00c0 ;Tape Motor Switch
|
||||
STAL @ $00c1 ;Start Address for LOAD and Cassette Write
|
||||
MEMUSS @ $00c3 2 ;Pointer: Type 3 Tape LOAD and general use
|
||||
LSTX @ $00c5 ;Matrix value of last Key pressed; No Key = $40
|
||||
NDX @ $00c6 ;Number of Characters in Keyboard Buffer queue
|
||||
RVS @ $00c7 ;Flag: Reverse On/Off; On = $01, Off = $00
|
||||
INDX @ $00c8 2 ;Pointer: End of Line for Input
|
||||
LXSP @ $00c9 ;Cursor X/Y (Line/Column) position at start of Input
|
||||
SFDX @ $00cb ;Flag: Print shifted Characters
|
||||
BLNSW @ $00cc ;Flag: Cursor blink; $00 = Enabled, $01 = Disabled
|
||||
BLNCT @ $00cd ;Timer: Count down for Cursor blink toggle
|
||||
GDBLN @ $00ce ;Character under Cursor while Cursor Inverted
|
||||
BLNON @ $00cf ;Flag: Cursor Status; $00 = Off, $01 = On
|
||||
CRSW @ $00d0 ;Flag: Input from Screen = $03, or Keyboard = $00
|
||||
PNT @ $00d1 2 ;Pointer: Current Screen Line Address
|
||||
PNTR @ $00d3 ;Cursor Column on current Line, including Wrap-round Line, if any
|
||||
QTSW @ $00d4 ;Flag: Editor in Quote Mode; $00 = Not
|
||||
LNMX @ $00d5 ;Current logical Line length: 39 or 79
|
||||
TBLX @ $00d6 ;Current Screen Line number of Cursor
|
||||
SCHAR @ $00d7 ;Screen value of current Input Character/Last Character Output
|
||||
INSRT @ $00d8 ;Count of number of inserts outstanding
|
||||
LDTB1 @ $00d9 ;Screen Line link Table/Editor temporaries
|
||||
USER @ $00f3 2 ;Pointer: Current Colour RAM Location
|
||||
KEYTAB @ $00f5 2 ;Vector: Current Keyboard decoding Table ($eb81)
|
||||
RIBUF @ $00f7 2 ;RS232 Input Buffer Pointer
|
||||
ROBUF @ $00f9 2 ;RS232 Output Buffer Pointer
|
||||
FREKZP @ $00fb ;Free Zero Page space for User Programs
|
||||
BASZPT @ $00ff ;BASIC temporary Data Area
|
||||
ASCWRK @ $00ff ;Assembly Area for Floating point to ASCII conversion
|
||||
LAT @ $0259 10 ;Kernal Table: Active logical File numbers
|
||||
FAT @ $0263 10 ;Kernal Table: Active File First Addresses
|
||||
SAT @ $026d 10 ;Kernal Table: Active File Secondary Addresses
|
||||
KEYD @ $0277 10 ;Keyboard Buffer Queue (FIFO)
|
||||
MEMSTR @ $0281 2 ;Pointer: Bottom of Memory for Operating System ($0800)
|
||||
MEMSIZ2 @ $0283 2 ;Pointer: Top of Memory for Operating System ($a000)
|
||||
TIMOUT @ $0285 ;Serial IEEE Bus timeout defeat Flag
|
||||
COLOR @ $0286 ;Current Character Colour code
|
||||
GDCOL @ $0287 ;Background Colour under Cursor
|
||||
HIBASE @ $0288 ;High Byte of Screen Memory Address ($04)
|
||||
XMAX @ $0289 ;Maximum number of Bytes in Keyboard Buffer ($0a)
|
||||
RPTFLG @ $028a ;Flag: Repeat keys setting
|
||||
KOUNT @ $028b ;Repeat Key: Speed Counter ($04)
|
||||
DELAY @ $028c ;Repeat Key: First repeat delay Counter ($10)
|
||||
SHFLAG @ $028d ;flags for shift, CBM, CTRL
|
||||
LSTSHF @ $028e ;Last Shift Key used for debouncing
|
||||
KEYLOG @ $028f 2 ;Vector: Routine to determine Keyboard table to use
|
||||
MODE @ $0291 ;Flag: Upper/Lower Case change
|
||||
AUTODN @ $0292 ;Flag: Auto scroll down: $00 = Disabled ($00)
|
||||
M51CTR @ $0293 ;RS232 Pseudo 6551 control Register Image
|
||||
M51CDR @ $0294 ;RS232 Pseudo 6551 command Register Image
|
||||
M51AJB @ $0295 ;RS232 Non-standard Bits/Second
|
||||
RSSTAT @ $0297 ;RS232 Pseudo 6551 Status Register Image
|
||||
BITNUM @ $0298 ;RS232 Number of Bits left to send
|
||||
BAUDOF @ $0299 ;RS232 Baud Rate; Full Bit time microseconds
|
||||
RIDBE @ $029b ;RS232 Index to End of Input Buffer
|
||||
RIDBS @ $029c 2 ;RS232 Pointer: High Byte of Address of Input Buffer
|
||||
RODBS @ $029d 2 ;RS232 Pointer: High Byte of Address of Output Buffer
|
||||
RODBE @ $029e ;RS232 Index to End of Output Buffer
|
||||
IRQTMP @ $029f 2 ;Temporary store for IRQ Vector during Tape operations
|
||||
ENABL @ $02a1 ;RS232 Enables
|
||||
TODSNS @ $02a2 ;TOD sense during Tape I/O
|
||||
TRDTMP @ $02a3 ;Temporary storage during Tape READ
|
||||
TD1IRQ @ $02a4 ;Temporary D1IRQ Indicator during Tape READ
|
||||
TLNIDX @ $02a5 ;Temporary for Line Index
|
||||
TVSFLG @ $02a6 ;Flag: TV Standard: $00 = NTSC, $01 = PAL
|
||||
CINV @ $0314 2 ;Vector: Hardware IRQ Interrupt ($ea31)
|
||||
CNBINV @ $0316 2 ;Vector: BRK Instruction Interrupt ($fe66)
|
||||
NMINV @ $0318 2 ;Vector: Hardware NMI Interrupt ($fe47)
|
||||
IOPEN2 @ $031a 2 ;Vector: Kernal OPEN Routine ($f34a)
|
||||
ICLOSE2 @ $031c 2 ;Vector: Kernal CLOSE Routine ($f291)
|
||||
ICHKIN2 @ $031e 2 ;Vector: Kernal CHKIN Routine ($f20e)
|
||||
ICKOUT2 @ $0320 2 ;Vector: Kernal CHKOUT Routine ($f250)
|
||||
ICLRCH2 @ $0322 2 ;Vector: Kernal CLRCHN Routine ($f333)
|
||||
IBASIN2 @ $0324 2 ;Vector: Kernal CHRIN Routine ($f157)
|
||||
IBSOUT2 @ $0326 2 ;Vector: Kernal CHROUT Routine ($f1ca)
|
||||
ISTOP2 @ $0328 2 ;Vector: Kernal STOP Routine ($f6ed)
|
||||
IGETIN2 @ $032a 2 ;Vector: Kernal GETIN Routine ($f13e)
|
||||
ICLALL2 @ $032c 2 ;Vector: Kernal CLALL Routine ($f32f)
|
||||
USRCMD2 @ $032e 2 ;User Defined Vector ($fe66)
|
||||
ILOAD2 @ $0330 2 ;Vector: Kernal LOAD Routine ($f4a5)
|
||||
ISAVE2 @ $0332 2 ;Vector: Kernal SAVE Routine ($f5ed)
|
||||
TBUFFR @ $033c 192 ;start of Tape I/O Buffer
|
||||
VICSCN @ $0400 1024 ;start of Default Screen Video Matrix
|
251
SourceGen/RuntimeData/Commodore/C64-Kernal-ROM.sym65
Normal file
251
SourceGen/RuntimeData/Commodore/C64-Kernal-ROM.sym65
Normal file
|
@ -0,0 +1,251 @@
|
|||
; See the LICENSE file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Parts adapted from multiple sources:
|
||||
;
|
||||
; - Project 64, 64MAP10.TXT, June 1996, etext #41
|
||||
; http://unusedino.de/ec64/technical/project64/memory_maps.html
|
||||
;
|
||||
; - PageTable's C64 BASIC & KERNAL ROM Disassembly
|
||||
; https://www.pagetable.com/c64ref/c64disasm/
|
||||
;
|
||||
; - "Mapping the Commodore 64", by Sheldon Leemon
|
||||
; Compute! Publications Inc. (1984), ISBN 0-942386-23-X
|
||||
; https://archive.org/details/Compute_s_Mapping_the_Commodore_64
|
||||
|
||||
*SYNOPSIS KERNAL ROM ($e000-$ffff) labels (functions and some of the vectors)
|
||||
|
||||
; Note: BASIC too big to fit into $a000-$bfff, so some additional BASIC support
|
||||
; spills over into the start of the KERNAL ROM.
|
||||
|
||||
expCont @ $e000 ;EXP continued From BASIC ROM
|
||||
polyx @ $e043 ;Series Evaluation
|
||||
rmulc @ $e08d ;Constants for RND
|
||||
rnd @ $e097 ;Perform rnd
|
||||
bioerr @ $e0f9 ;Handle I/O Error in BASIC
|
||||
bchout @ $e10c ;Output Character
|
||||
bchin @ $e112 ;Input Character
|
||||
bckout @ $e118 ;Set Up For Output
|
||||
bckin @ $e11e ;Set Up For Input
|
||||
bgetin @ $e124 ;Get One Character
|
||||
sys @ $e12a ;Perform sys
|
||||
savet @ $e156 ;Perform save
|
||||
verfyt @ $e165 ;Perform verify / load
|
||||
opent @ $e1be ;Perform open
|
||||
closet @ $e1c7 ;Perform close
|
||||
slpara @ $e1d4 ;Get Parameters For LOAD/SAVE
|
||||
combyt @ $e200 ;Get Next One Byte Parameter
|
||||
deflt @ $e206 ;Check Default Parameters
|
||||
cmmerr @ $e20e ;Check For Comma
|
||||
ocpara @ $e219 ;Get Parameters For OPEN/CLOSE
|
||||
cos @ $e264 ;Perform cos
|
||||
sin @ $e26b ;Perform sin
|
||||
tan @ $e2b4 ;Perform tan
|
||||
atn @ $e30e ;Perform atn
|
||||
bassft @ $e37b ;BASIC Warm Start RUNSTOP-RESTORE
|
||||
init @ $e394 ;BASIC Cold Start
|
||||
initat @ $e3a2 ;CHRGET For Zero-page
|
||||
initcz @ $e3bf ;Initialize BASIC RAM
|
||||
initms @ $e422 ;Output Power-Up Message
|
||||
bvtrs @ $e447 12 ;Table of BASIC Vectors (for $300)
|
||||
initv @ $e453 ;Initialize Vectors
|
||||
words @ $e45f ;Power-Up Message
|
||||
chkoutCallPatch @ $e4ad ;Patch for BASIC Call to CHKOUT
|
||||
rstCharColor @ $e4da ;Reset Character Colour
|
||||
pauseTapeFind @ $e4e0 ;Pause After Finding Tape File
|
||||
rs232Timing @ $e4ec 20 ;RS-232 Timing Table
|
||||
iobase2 @ $e500 ;Get I/O Address
|
||||
screen2 @ $e505 ;Get Screen Size
|
||||
plot2 @ $e50a ;Put / Get Row And Column
|
||||
cint1 @ $e518 ;Initialize I/O
|
||||
clrScrn @ $e544 ;Clear Screen
|
||||
homeCur @ $e566 ;Home Cursor
|
||||
setScrnPtrs @ $e56c ;Set Screen Pointers
|
||||
ioDefaultsAlt @ $e59a ;Set I/O Defaults (Unused Entry)
|
||||
ioDefaults @ $e5a0 ;Set I/O Defaults
|
||||
lp2 @ $e5b4 ;Get Character From Keyboard Buffer
|
||||
keyInput @ $e5ca ;Input From Keyboard
|
||||
keyScrnInput @ $e632 ;Input From Screen or Keyboard
|
||||
quotesTest @ $e684 ;Quotes Test
|
||||
scrnPrntInit @ $e691 ;Set Up Screen Print
|
||||
advanceCur @ $e6b6 ;Advance Cursor
|
||||
retreatCur @ $e6ed ;Retreat Cursor
|
||||
backPrevLine @ $e701 ;Back on to Previous Line
|
||||
outputToScrn @ $e716 ;Output to Screen
|
||||
unshiftChars @ $e72a ;unshifted characters
|
||||
shiftedChars @ $e7d4 ;shifted characters
|
||||
nextLine @ $e87c ;Go to Next Line
|
||||
outputCR @ $e891 ;Output <CR>
|
||||
chkLineDec @ $e8a1 ;Check Line Decrement
|
||||
chkLineInc @ $e8b3 ;Check Line Increment
|
||||
setColorCode @ $e8cb ;Set Colour Code
|
||||
colorCodeTbl @ $e8da 16 ;Colour Code Table
|
||||
scrnScroll @ $e8ea ;Scroll Screen
|
||||
openSpace @ $e965 ;Open A Space On The Screen
|
||||
moveLine @ $e9c8 ;Move A Screen Line
|
||||
syncColorXfer @ $e9e0 ;Syncronise Colour Transfer
|
||||
setSOL @ $e9f0 ;Set Start of Line
|
||||
clearLine @ $e9ff ;Clear Screen Line
|
||||
printToScrn @ $ea13 ;Print To Screen
|
||||
syncColPntr @ $ea24 ;Syncronise Colour Pointer
|
||||
defaultIrqEntry @ $ea31 ;Main IRQ Entry Point
|
||||
scnkey2 @ $ea87 ;Scan Keyboard
|
||||
processKey @ $eadd ;Process Key Image
|
||||
graphTextCntrl @ $ec44 ;Graphics/Text Control
|
||||
shiftRunEq @ $ece7 ;Shift-Run Equivalent
|
||||
loScrnLineAddr @ $ecf0 ;Low Byte Screen Line Addresses
|
||||
talk2 @ $ed09 ;Send TALK Command on Serial Bus
|
||||
listn2 @ $ed0c ;Send LISTEN Command on Serial Bus
|
||||
serialSend @ $ed40 ;Send Data On Serial Bus
|
||||
flagErrors @ $edad ;Flag Errors
|
||||
flagDevNotPres @ $edad ;Status #80 - device not present
|
||||
flagWriteTout @ $edb0 ;Status #03 - write timeout
|
||||
secnd2 @ $edb9 ;Send LISTEN Secondary Address
|
||||
clrAtn @ $edbe ;Clear ATN
|
||||
tksa2 @ $edc7 ;Send TALK Secondary Address
|
||||
waitForClock @ $edcc ;Wait For Clock
|
||||
ciout2 @ $eddd ;Send Serial Deferred
|
||||
untalk2 @ $edef ;Send UNTALK / UNLISTEN
|
||||
unlsn2 @ $edfe ;Unlisten
|
||||
acptr2 @ $ee13 ;Receive From Serial Bus
|
||||
serialClkOn @ $ee85 ;Serial Clock On
|
||||
serialClkOff @ $ee8e ;Serial Clock Off
|
||||
serialOutput1 @ $ee97 ;Serial Output 1
|
||||
serialOutput0 @ $eea0 ;Serial Output 0
|
||||
serialGet @ $eea9 ;Get Serial Data And Clock In
|
||||
delay1ms @ $eeb3 ;Delay 1 ms
|
||||
rs232Send @ $eebb ;RS-232 Send
|
||||
rs232SendByte @ $ef06 ;Send New RS-232 Byte
|
||||
noDataSetRdy @ $ef2e ;No DSR / No CTS Error
|
||||
disableTimer @ $ef39 ;Disable Timer
|
||||
bitCount @ $ef4a ;Compute Bit Count
|
||||
rs232Recv @ $ef59 ;RS-232 Receive
|
||||
rs232RecvInit @ $ef7e ;Set Up To Receive
|
||||
rs232ProcByte @ $ef90 ;Process RS-232 Byte
|
||||
rs232Submit @ $efe1 ;Submit to RS-232
|
||||
noDsrError @ $f00d ;No DSR (Data Set Ready) Error
|
||||
rs232SendToBuf @ $f017 ;Send to RS-232 Buffer
|
||||
rs232Input @ $f04d ;Input From RS-232
|
||||
rs232Get @ $f086 ;Get From RS-232
|
||||
serialBusIdle @ $f0a4 ;Serial Bus Idle
|
||||
prtMsgIfDirect @ $f12b ;Print Message if Direct
|
||||
prtMsg @ $f12f ;Print Message
|
||||
getin3 @ $f13e ;Get a byte
|
||||
chrin3 @ $f157 ;Input a byte
|
||||
getFromIO @ $f199 ;Get From Tape / Serial / RS-232
|
||||
chrout3 @ $f1ca ;Output One Character
|
||||
chkin3 @ $f20e ;Set Input Device
|
||||
chkout3 @ $f250 ;Set Output Device
|
||||
close3 @ $f291 ;Close File
|
||||
findFile @ $f30f ;Find File
|
||||
setFileParms @ $f31f ;Set File values
|
||||
clall3 @ $f32f ;Abort All Files
|
||||
clrchn3 @ $f333 ;Restore Default I/O
|
||||
open3 @ $f34a ;Open File
|
||||
setSecondary @ $f3d5 ;Send Secondary Address
|
||||
rs232Open @ $f409 ;Open RS-232
|
||||
load2 @ $f49e ;Load RAM
|
||||
serialLoadFile @ $f4b8 ;Load File From Serial Bus
|
||||
tapeLoadFile @ $f533 ;Load File From Tape
|
||||
printSearching @ $f5af ;Print SEARCHING
|
||||
printFilename @ $f5c1 ;Print Filename
|
||||
printLoading @ $f5d2 ;Print LOADING / VERIFYING
|
||||
save @ $f5dd ;Save RAM
|
||||
serialSave @ $f5fa ;Save to Serial Bus
|
||||
tapeSave @ $f659 ;Save to Tape
|
||||
printSaving @ $f68f ;Print SAVING
|
||||
udtim2 @ $f69b ;Bump Clock
|
||||
rdtim2 @ $f6dd ;Get Time
|
||||
settim2 @ $f6e4 ;Set Time
|
||||
stop @ $f6ed ;Check STOP Key
|
||||
findTapeHdr @ $f72c ;Find Any Tape Header
|
||||
writeTapeHdr @ $f76a ;Write Tape Header
|
||||
getBufAddr @ $f7d0 ;Get Buffer Address
|
||||
headerStartEnd @ $f7d7 ;Set Buffer Stat / End Pointers
|
||||
findSpecTapeHdr @ $f7ea ;Find Specific Tape Header
|
||||
bumpTapePtr @ $f80d ;Bump Tape Pointer
|
||||
printPressPlay @ $f817 ;Print PRESS PLAY ON TAPE
|
||||
chkTapeStatus @ $f82e ;Check Tape Status
|
||||
printPressRecrd @ $f838 ;Print PRESS RECORD...
|
||||
initTapeRead @ $f841 ;Initiate Tape Read
|
||||
initTapeWrite @ $f864 ;Initiate Tape Write
|
||||
tapeOperEntry @ $f875 ;Common Tape Code
|
||||
chkTapeStop @ $f8d0 ;Check Tape Stop
|
||||
setReadTiming @ $f8e2 ;Set Read Timing
|
||||
readTapeBits @ $f92c ;Read Tape Bits
|
||||
storeTapeChars @ $fa60 ;Store Tape Characters
|
||||
rstTapePtr @ $fb8e ;Reset Tape Pointer
|
||||
newCharSetup @ $fb97 ;New Character Setup
|
||||
sendTapeTone @ $fba6 ;Send Tone to Tape
|
||||
writeTapeData @ $fbc8 ;Write Data to Tape
|
||||
tapeIrqEntry @ $fbcd ;IRQ Entry Point
|
||||
writeTapeLeader @ $fc57 ;Write Tape Leader
|
||||
restoreIrq @ $fc93 ;Restore Normal IRQ
|
||||
setIrqVec @ $fcb8 ;Set IRQ Vector
|
||||
stopTapeMotor @ $fcca ;Kill Tape Motor
|
||||
chkRwPtr @ $fcd1 ;Check Read / Write Pointer
|
||||
bumpRwPtr @ $fcdb ;Bump Read / Write Pointer
|
||||
resetEntry @ $fce2 ;Power-Up RESET Entry
|
||||
cartridgeCheck @ $fd02 ;Check For 8-ROM
|
||||
restor2 @ $fd15 ;Restore Kernal Vectors (at $0314)
|
||||
vector2 @ $fd1a ;Change Vectors For User
|
||||
ramtas2 @ $fd50 ;Initialise System Constants
|
||||
ioinit2 @ $fda3 ;Initialise I/O
|
||||
enableTimer @ $fddd ;Enable Timer
|
||||
setnam2 @ $fdf9 ;Set Filename
|
||||
setlfs2 @ $fe00 ;Set Logical File Parameters
|
||||
readst2 @ $fe07 ;Get I/O Status Word
|
||||
setmsg2 @ $fe18 ;Control OS Messages
|
||||
settmo2 @ $fe21 ;Set IEEE Timeout
|
||||
memtop2 @ $fe25 ;Read / Set Top of Memory
|
||||
membot2 @ $fe34 ;Read / Set Bottom of Memory
|
||||
nmiHandler @ $fe43 ;NMI Transfer Entry
|
||||
basicWarmStart @ $fe66 ;Warm Start Basic BRK
|
||||
exitInterrupt @ $febc ;Exit Interrupt
|
||||
rs232NmiIn @ $fed6 ;NMI RS-232 In
|
||||
rs232NmiOut @ $ff07 ;NMI RS-232 Out
|
||||
irqEntryAlt @ $ff43 ;Fake IRQ Entry
|
||||
irqEntry @ $ff48 ;IRQ Entry
|
||||
cint2 @ $ff5b ;Initialize screen editor
|
||||
kernalVer @ $ff80 ;Kernal Version Number 03
|
||||
cint @ $ff81 ;Init Editor & Video Chips ($ff5b)
|
||||
ioinit @ $ff84 ;Init I/O Devices Ports & Timers ($fda3)
|
||||
ramtas @ $ff87 ;Init Ram & Buffers ($fd50)
|
||||
restor @ $ff8a ;Restore Vectors ($fd15)
|
||||
vector @ $ff8d ;Change Vectors For User ($fd1a)
|
||||
setmsg @ $ff90 ;Control OS Messages ($fe18)
|
||||
secnd @ $ff93 ;Send SA After Listen ($edb9)
|
||||
tksa @ $ff96 ;Send SA After Talk ($edc7)
|
||||
memtop @ $ff99 ;Set/Read System RAM Top ($fe25)
|
||||
membot @ $ff9c ;Set/Read System RAM Bottom ($fe34)
|
||||
scnkey @ $ff9f ;Scan Keyboard ($ea87)
|
||||
settmo @ $ffa2 ;Set Timeout In IEEE ($fe21)
|
||||
acptr @ $ffa5 ;Handshake Serial Byte In ($ee13)
|
||||
ciout @ $ffa8 ;Handshake Serial Byte Out ($eddd)
|
||||
untalk @ $ffab ;Command Serial Bus UNTALK ($edef)
|
||||
unlsn @ $ffae ;Command Serial Bus UNLISTEN ($edfe)
|
||||
listn @ $ffb1 ;Command Serial Bus LISTEN ($ed0c)
|
||||
talk @ $ffb4 ;Command Serial Bus TALK ($ed09)
|
||||
readst @ $ffb7 ;Read I/O Status Word ($fe07)
|
||||
setlfs @ $ffba ;Set Logical File Parameters ($fe00)
|
||||
setnam @ $ffbd ;Set Filename ($fdf9)
|
||||
iopen @ $ffc0 ;Open Vector $f34a ($031a->$f34a)
|
||||
iclose @ $ffc3 ;Close Vector $f291 ($031c->$f291)
|
||||
ichkin @ $ffc6 ;Set Input $f20e ($031e->$f20e)
|
||||
ichkout @ $ffc9 ;Set Output $f250 ($0320->$f250)
|
||||
iclrch @ $ffcc ;Restore I/O Vector $f333 ($0322->$f333)
|
||||
ichrin @ $ffcf ;Input Vector chrin $f157 ($0324->$f157)
|
||||
ichrout @ $ffd2 ;Output Vector chrout $f1ca ($0326->$f1ca)
|
||||
load @ $ffd5 ;Load RAM From Device ($f49e)
|
||||
save2 @ $ffd8 ;Save RAM To Device ($f5dd)
|
||||
settim @ $ffdb ;Set Real-Time Clock ($f6e4)
|
||||
rdtim @ $ffde ;Read Real-Time Clock ($f6dd)
|
||||
istop3 @ $ffe1 ;Test-Stop Vector $f6ed ($0328->$f6ed)
|
||||
igetin @ $ffe4 ;Get From Keyboad $f13e ($032a->$f13e)
|
||||
iclall @ $ffe7 ;Close All Channels And Files $f32f ($032c->$f32f)
|
||||
udtim @ $ffea ;Increment Real-Time Clock ($f69b)
|
||||
screen @ $ffed ;Return Screen Organization ($e505)
|
||||
plot @ $fff0 ;Read / Set Cursor X/Y Position ($e50a)
|
||||
iobase @ $fff3 ;Return I/O Base Address ($e500)
|
||||
nmiVector @ $fffa 2 ;Non-Maskable Interrupt Hardware Vector ($fe43)
|
||||
resetVector @ $fffc 2 ;System Rest (RES) Hardware Vector ($fce2)
|
||||
irqVector @ $fffe 2 ;Maskable Interrupt Request and Break Hardware Vectors ($ff48)
|
|
@ -13,12 +13,23 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//#define SHOW_BORDER
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
using PluginCommon;
|
||||
|
||||
|
||||
namespace RuntimeData.Commodore {
|
||||
/// <summary>
|
||||
/// Visualizer for C64 sprites and fonts.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// References:
|
||||
/// https://www.c64-wiki.com/wiki/Sprite
|
||||
/// http://sta.c64.org/cbm64disp.html
|
||||
/// http://unusedino.de/ec64/technical/misc/vic656x/colors/
|
||||
/// </remarks>
|
||||
public class VisC64 : MarshalByRefObject, IPlugin, IPlugin_Visualizer {
|
||||
// IPlugin
|
||||
public string Identifier {
|
||||
|
@ -30,9 +41,14 @@ namespace RuntimeData.Commodore {
|
|||
|
||||
// Visualization identifiers; DO NOT change or projects that use them will break.
|
||||
private const string VIS_GEN_HI_RES_SPRITE = "c64-hi-res-sprite";
|
||||
private const string VIS_GEN_HI_RES_SPRITE_GRID = "c64-hi-res-sprite-grid";
|
||||
private const string VIS_GEN_MULTI_COLOR_SPRITE = "c64-multi-color-sprite";
|
||||
private const string VIS_GEN_MULTI_COLOR_SPRITE_GRID = "c64-multi-color-sprite-grid";
|
||||
private const string VIS_GEN_HI_RES_FONT = "c64-hi-res-font";
|
||||
private const string VIS_GEN_MULTI_COLOR_FONT = "c64-multi-color-font";
|
||||
|
||||
private const string P_OFFSET = "offset";
|
||||
private const string P_COUNT = "count";
|
||||
private const string P_DOUBLE_WIDE = "doubleWide";
|
||||
private const string P_DOUBLE_HIGH = "doubleHigh";
|
||||
private const string P_COLOR = "color"; // sprite color (hi-res or multi-color)
|
||||
|
@ -40,9 +56,10 @@ namespace RuntimeData.Commodore {
|
|||
private const string P_COLOR_11 = "color11"; // multi-color 2
|
||||
|
||||
private const int MAX_COLOR = 15;
|
||||
private const int BYTE_WIDTH = 3;
|
||||
private const int HEIGHT = 21;
|
||||
private const int SPRITE_SIZE = BYTE_WIDTH * HEIGHT; // 63
|
||||
private const int SPRITE_BYTE_WIDTH = 3;
|
||||
private const int SPRITE_HEIGHT = 21;
|
||||
private const int SPRITE_SIZE = SPRITE_BYTE_WIDTH * SPRITE_HEIGHT; // 63
|
||||
private const int SPRITE_STRIDE = 64; // hardware sprites are 64-byte aligned
|
||||
|
||||
// Visualization descriptors.
|
||||
private VisDescr[] mDescriptors = new VisDescr[] {
|
||||
|
@ -72,6 +89,50 @@ namespace RuntimeData.Commodore {
|
|||
new VisParamDescr("Double high",
|
||||
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_HI_RES_SPRITE_GRID, "C64 Hi-Res Sprite Sheet", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Number of items",
|
||||
P_COUNT, typeof(int), 1, 1024, 0, 16),
|
||||
new VisParamDescr("Sprite color",
|
||||
P_COLOR, typeof(int), 0, 15, 0, 0),
|
||||
new VisParamDescr("Double wide",
|
||||
P_DOUBLE_WIDE, typeof(bool), 0, 0, 0, false),
|
||||
new VisParamDescr("Double high",
|
||||
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_MULTI_COLOR_SPRITE_GRID, "C64 Multi-Color Sprite Sheet", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Number of items",
|
||||
P_COUNT, typeof(int), 1, 1024, 0, 16),
|
||||
new VisParamDescr("Sprite color",
|
||||
P_COLOR, typeof(int), 0, 15, 0, 1),
|
||||
new VisParamDescr("Multi-color 1",
|
||||
P_COLOR_01, typeof(int), 0, 15, 0, 0),
|
||||
new VisParamDescr("Multi-color 2",
|
||||
P_COLOR_11, typeof(int), 0, 15, 0, 2),
|
||||
new VisParamDescr("Double wide",
|
||||
P_DOUBLE_WIDE, typeof(bool), 0, 0, 0, false),
|
||||
new VisParamDescr("Double high",
|
||||
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_HI_RES_FONT, "C64 Hi-Res Font", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Number of items",
|
||||
P_COUNT, typeof(int), 1, 512, 0, 96),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_MULTI_COLOR_FONT, "C64 Multi-Color Font", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Number of items",
|
||||
P_COUNT, typeof(int), 1, 512, 0, 96),
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
|
@ -104,74 +165,36 @@ namespace RuntimeData.Commodore {
|
|||
ReadOnlyDictionary<string, object> parms) {
|
||||
switch (descr.Ident) {
|
||||
case VIS_GEN_HI_RES_SPRITE:
|
||||
return GenerateHiResSprite(parms);
|
||||
return GenerateSprite(parms, false);
|
||||
case VIS_GEN_MULTI_COLOR_SPRITE:
|
||||
return GenerateMultiColorSprite(parms);
|
||||
return GenerateSprite(parms, true);
|
||||
case VIS_GEN_HI_RES_SPRITE_GRID:
|
||||
return GenerateSpriteGrid(parms, false);
|
||||
case VIS_GEN_MULTI_COLOR_SPRITE_GRID:
|
||||
return GenerateSpriteGrid(parms, true);
|
||||
case VIS_GEN_HI_RES_FONT:
|
||||
return GenerateFont(parms, false);
|
||||
case VIS_GEN_MULTI_COLOR_FONT:
|
||||
return GenerateFont(parms, true);
|
||||
default:
|
||||
mAppRef.ReportError("Unknown ident " + descr.Ident);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateHiResSprite(ReadOnlyDictionary<string, object> parms) {
|
||||
private IVisualization2d GenerateSprite(ReadOnlyDictionary<string, object> parms,
|
||||
bool isMultiColor) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
|
||||
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
|
||||
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
|
||||
|
||||
if (offset < 0 || offset >= mFileData.Length || color < 0 || color > MAX_COLOR) {
|
||||
// the UI should flag these based on range (and ideally wouldn't have called us)
|
||||
mAppRef.ReportError("Invalid parameter");
|
||||
return null;
|
||||
byte color01 = 0;
|
||||
byte color11 = 0;
|
||||
if (isMultiColor) {
|
||||
color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
|
||||
color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
|
||||
}
|
||||
|
||||
int lastOffset = offset + SPRITE_SIZE - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Sprite runs off end of file (last offset +" +
|
||||
lastOffset.ToString("x6") + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
int xwide = isDoubleWide ? 2 : 1;
|
||||
int xhigh = isDoubleHigh ? 2 : 1;
|
||||
|
||||
VisBitmap8 vb = new VisBitmap8(BYTE_WIDTH * 8 * xwide, HEIGHT * xhigh);
|
||||
SetPalette(vb);
|
||||
|
||||
// Clear all pixels to transparent, then just draw the non-transparent ones.
|
||||
vb.SetAllPixelIndices(TRANSPARENT);
|
||||
|
||||
for (int row = 0; row < HEIGHT; row++) {
|
||||
for (int col = 0; col < BYTE_WIDTH; col++) {
|
||||
byte val = mFileData[offset + row * BYTE_WIDTH + col];
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
if ((val & 0x80) != 0) {
|
||||
int xc = (col * 8 + bit) * xwide;
|
||||
int yc = row * xhigh;
|
||||
vb.SetPixelIndex(xc, yc, color);
|
||||
if (isDoubleWide || isDoubleHigh) {
|
||||
// Draw doubled pixels. If we're only doubled in one dimension
|
||||
// this will draw pixels twice.
|
||||
vb.SetPixelIndex(xc + xwide - 1, yc, color);
|
||||
vb.SetPixelIndex(xc, yc + xhigh - 1, color);
|
||||
vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, color);
|
||||
}
|
||||
}
|
||||
val <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateMultiColorSprite(ReadOnlyDictionary<string, object> parms) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
|
||||
byte color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
|
||||
byte color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
|
||||
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
|
||||
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
|
||||
|
||||
if (offset < 0 || offset >= mFileData.Length ||
|
||||
color < 0 || color > MAX_COLOR ||
|
||||
color01 < 0 || color01 > MAX_COLOR ||
|
||||
|
@ -180,7 +203,6 @@ namespace RuntimeData.Commodore {
|
|||
mAppRef.ReportError("Invalid parameter");
|
||||
return null;
|
||||
}
|
||||
|
||||
int lastOffset = offset + SPRITE_SIZE - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Sprite runs off end of file (last offset +" +
|
||||
|
@ -191,13 +213,196 @@ namespace RuntimeData.Commodore {
|
|||
int xwide = isDoubleWide ? 2 : 1;
|
||||
int xhigh = isDoubleHigh ? 2 : 1;
|
||||
|
||||
VisBitmap8 vb = new VisBitmap8(BYTE_WIDTH * 8 * xwide, HEIGHT * xhigh);
|
||||
VisBitmap8 vb = new VisBitmap8(SPRITE_BYTE_WIDTH * 8 * xwide, SPRITE_HEIGHT * xhigh);
|
||||
SetPalette(vb);
|
||||
vb.SetAllPixelIndices(TRANSPARENT);
|
||||
|
||||
for (int row = 0; row < HEIGHT; row++) {
|
||||
for (int col = 0; col < BYTE_WIDTH; col++) {
|
||||
byte val = mFileData[offset + row * BYTE_WIDTH + col];
|
||||
if (isMultiColor) {
|
||||
RenderMultiColorBitmap(offset, SPRITE_BYTE_WIDTH, SPRITE_HEIGHT,
|
||||
isDoubleWide, isDoubleHigh, color, color01, color11, vb, 0, 0);
|
||||
} else {
|
||||
RenderHiResBitmap(offset, SPRITE_BYTE_WIDTH, SPRITE_HEIGHT,
|
||||
isDoubleWide, isDoubleHigh, color, vb, 0, 0);
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateSpriteGrid(ReadOnlyDictionary<string, object> parms,
|
||||
bool isMultiColor) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
int count = Util.GetFromObjDict(parms, P_COUNT, 16);
|
||||
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
|
||||
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
|
||||
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
|
||||
byte color01 = 0;
|
||||
byte color11 = 0;
|
||||
if (isMultiColor) {
|
||||
color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
|
||||
color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
|
||||
}
|
||||
|
||||
if (offset < 0 || offset >= mFileData.Length ||
|
||||
color < 0 || color > MAX_COLOR ||
|
||||
color01 < 0 || color01 > MAX_COLOR ||
|
||||
color11 < 0 || color11 > MAX_COLOR) {
|
||||
// the UI should flag these based on range (and ideally wouldn't have called us)
|
||||
mAppRef.ReportError("Invalid parameter");
|
||||
return null;
|
||||
}
|
||||
int lastOffset = offset + SPRITE_STRIDE * count - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Sprite set runs off end of file (last offset +" +
|
||||
lastOffset.ToString("x6") + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
int xwide = isDoubleWide ? 2 : 1;
|
||||
int xhigh = isDoubleHigh ? 2 : 1;
|
||||
|
||||
// Try to make it square, unless there's a large number of them. Limit the width
|
||||
// to 16 sprites (384 pixels + padding).
|
||||
int hcells;
|
||||
if (count * xwide > 64) {
|
||||
hcells = 16 / xwide;
|
||||
} else if (count * xwide >= 32) {
|
||||
hcells = 8 / xwide;
|
||||
} else {
|
||||
hcells = (int)Math.Sqrt(count * xwide + 1);
|
||||
}
|
||||
|
||||
int vcells = (count + hcells - 1) / hcells;
|
||||
|
||||
VisBitmap8 vb = new VisBitmap8(1 + hcells * SPRITE_BYTE_WIDTH * 8 * xwide + hcells,
|
||||
1 + vcells * SPRITE_HEIGHT * xhigh + vcells);
|
||||
SetPalette(vb);
|
||||
vb.SetAllPixelIndices(BORDER_COLOR);
|
||||
|
||||
int cellX = 1;
|
||||
int cellY = 1;
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
if (isMultiColor) {
|
||||
RenderMultiColorBitmap(offset + idx * SPRITE_STRIDE,
|
||||
SPRITE_BYTE_WIDTH, SPRITE_HEIGHT, isDoubleWide, isDoubleHigh,
|
||||
color, color01, color11, vb, cellX, cellY);
|
||||
} else {
|
||||
RenderHiResBitmap(offset + idx * SPRITE_STRIDE,
|
||||
SPRITE_BYTE_WIDTH, SPRITE_HEIGHT, isDoubleWide, isDoubleHigh,
|
||||
color, vb, cellX, cellY);
|
||||
}
|
||||
|
||||
cellX += SPRITE_BYTE_WIDTH * 8 * xwide + 1;
|
||||
if (cellX == vb.Width) {
|
||||
cellX = 1;
|
||||
cellY += SPRITE_HEIGHT * xhigh + 1;
|
||||
}
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateFont(ReadOnlyDictionary<string, object> parms,
|
||||
bool isMultiColor) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
int count = Util.GetFromObjDict(parms, P_COUNT, 96);
|
||||
|
||||
if (offset < 0 || offset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Invalid parameter");
|
||||
return null;
|
||||
}
|
||||
int lastOffset = offset + count - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Font runs off end of file (last offset +" +
|
||||
lastOffset.ToString("x6") + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set the number of horizontal cells. For small counts we try to make it square,
|
||||
// for larger counts we use a reasonable power of 2.
|
||||
int hcells;
|
||||
if (count > 128) {
|
||||
hcells = 32;
|
||||
} else if (count > 64) {
|
||||
hcells = 16;
|
||||
} else if (count >= 32) {
|
||||
hcells = 8;
|
||||
} else {
|
||||
hcells = (int)Math.Sqrt(count + 1);
|
||||
}
|
||||
|
||||
int vcells = (count + hcells - 1) / hcells;
|
||||
|
||||
const int FONT_BYTE_WIDTH = 1;
|
||||
const int FONT_HEIGHT = 8;
|
||||
const int CELL_STRIDE = FONT_BYTE_WIDTH * FONT_HEIGHT;
|
||||
|
||||
// Create a bitmap with room for each cell, plus a 1-pixel boundary
|
||||
// between them and around the edges.
|
||||
VisBitmap8 vb = new VisBitmap8(1 + hcells * FONT_BYTE_WIDTH * 8 + hcells,
|
||||
1 + vcells * FONT_HEIGHT + vcells);
|
||||
SetPalette(vb);
|
||||
vb.SetAllPixelIndices(BORDER_COLOR);
|
||||
|
||||
int cellX = 1;
|
||||
int cellY = 1;
|
||||
byte color = 0; /* black */
|
||||
byte color01 = 11; /* dark grey */
|
||||
byte color11 = 15; /* light grey */
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
if (isMultiColor) {
|
||||
RenderMultiColorBitmap(offset + idx * CELL_STRIDE, FONT_BYTE_WIDTH, FONT_HEIGHT,
|
||||
false, false, color, color01, color11, vb, cellX, cellY);
|
||||
} else {
|
||||
RenderHiResBitmap(offset + idx * CELL_STRIDE, FONT_BYTE_WIDTH, FONT_HEIGHT,
|
||||
false, false, color, vb, cellX, cellY);
|
||||
}
|
||||
|
||||
cellX += FONT_BYTE_WIDTH * 8 + 1;
|
||||
if (cellX == vb.Width) {
|
||||
cellX = 1;
|
||||
cellY += FONT_HEIGHT + 1;
|
||||
}
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
private void RenderHiResBitmap(int offset, int byteWidth, int height,
|
||||
bool isDoubleWide, bool isDoubleHigh,
|
||||
byte color, VisBitmap8 vb, int startx, int starty) {
|
||||
int xwide = isDoubleWide ? 2 : 1;
|
||||
int xhigh = isDoubleHigh ? 2 : 1;
|
||||
for (int row = 0; row < height; row++) {
|
||||
for (int col = 0; col < byteWidth; col++) {
|
||||
byte val = mFileData[offset + row * byteWidth + col];
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
byte pixColor;
|
||||
if ((val & 0x80) == 0) {
|
||||
pixColor = TRANSPARENT;
|
||||
} else {
|
||||
pixColor = color;
|
||||
}
|
||||
int xc = startx + (col * 8 + bit) * xwide;
|
||||
int yc = starty + row * xhigh;
|
||||
vb.SetPixelIndex(xc, yc, pixColor);
|
||||
if (isDoubleWide || isDoubleHigh) {
|
||||
// Draw doubled pixels. If we're only doubled in one dimension
|
||||
// this will draw some pixels twice.
|
||||
vb.SetPixelIndex(xc + xwide - 1, yc, pixColor);
|
||||
vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
|
||||
vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, pixColor);
|
||||
}
|
||||
val <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderMultiColorBitmap(int offset, int byteWidth, int height,
|
||||
bool isDoubleWide, bool isDoubleHigh,
|
||||
byte color, byte color01, byte color11, VisBitmap8 vb, int startx, int starty) {
|
||||
int xwide = isDoubleWide ? 2 : 1;
|
||||
int xhigh = isDoubleHigh ? 2 : 1;
|
||||
for (int row = 0; row < height; row++) {
|
||||
for (int col = 0; col < byteWidth; col++) {
|
||||
byte val = mFileData[offset + row * byteWidth + col];
|
||||
for (int bit = 0; bit < 8; bit += 2) {
|
||||
byte pixColor = 0;
|
||||
switch (val & 0xc0) {
|
||||
|
@ -206,13 +411,14 @@ namespace RuntimeData.Commodore {
|
|||
case 0x40: pixColor = color01; break;
|
||||
case 0xc0: pixColor = color11; break;
|
||||
}
|
||||
int xc = (col * 8 + bit) * xwide;
|
||||
int yc = row * xhigh;
|
||||
int xc = startx + (col * 8 + bit) * xwide;
|
||||
int yc = starty + row * xhigh;
|
||||
// Set two adjacent pixels.
|
||||
vb.SetPixelIndex(xc, yc, pixColor);
|
||||
vb.SetPixelIndex(xc+1, yc, pixColor);
|
||||
if (isDoubleWide || isDoubleHigh) {
|
||||
// Draw doubled pixels. If we're only doubled in one dimension
|
||||
// this will draw pixels twice.
|
||||
// this will draw some pixels twice.
|
||||
vb.SetPixelIndex(xc + xwide*2 - 2, yc, pixColor);
|
||||
vb.SetPixelIndex(xc + xwide*2 - 1, yc, pixColor);
|
||||
vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
|
||||
|
@ -224,31 +430,38 @@ namespace RuntimeData.Commodore {
|
|||
}
|
||||
}
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
private const byte TRANSPARENT = 16;
|
||||
#if SHOW_BORDER
|
||||
private const byte BORDER_COLOR = 17;
|
||||
#else
|
||||
private const byte BORDER_COLOR = TRANSPARENT;
|
||||
#endif
|
||||
|
||||
// C64 colors, from http://unusedino.de/ec64/technical/misc/vic656x/colors/
|
||||
// (the ones on https://www.c64-wiki.com/wiki/Color looked wrong)
|
||||
private void SetPalette(VisBitmap8 vb) {
|
||||
vb.AddColor(0xff, 0x00, 0x00, 0x00); // 0=black
|
||||
vb.AddColor(0xff, 0xff, 0xff, 0xff); // 1=white
|
||||
vb.AddColor(0xff, 0x68, 0x37, 0x2b); // 2=red
|
||||
vb.AddColor(0xff, 0x70, 0xa4, 0xb2); // 3=cyan
|
||||
vb.AddColor(0xff, 0x6f, 0x3d, 0x86); // 4=purple
|
||||
vb.AddColor(0xff, 0x58, 0x8d, 0x43); // 5=green
|
||||
vb.AddColor(0xff, 0x35, 0x28, 0x79); // 6=blue
|
||||
vb.AddColor(0xff, 0xb8, 0xc7, 0x6f); // 7=yellow
|
||||
vb.AddColor(0xff, 0x6f, 0x4f, 0x25); // 8=orange
|
||||
vb.AddColor(0xff, 0x43, 0x39, 0x00); // 9-brown
|
||||
vb.AddColor(0xff, 0x9a, 0x67, 0x59); // 10=light red
|
||||
vb.AddColor(0xff, 0x44, 0x44, 0x44); // 11=dark grey
|
||||
vb.AddColor(0xff, 0x6c, 0x6c, 0x6c); // 12=grey
|
||||
vb.AddColor(0xff, 0x9a, 0xd2, 0x84); // 13=light green
|
||||
vb.AddColor(0xff, 0x6c, 0x5e, 0xb5); // 14=light blue
|
||||
vb.AddColor(0xff, 0x95, 0x95, 0x95); // 15=light grey
|
||||
vb.AddColor(0, 0, 0, 0); // 16=transparent
|
||||
vb.SetColor(0, 0xff, 0x00, 0x00, 0x00); // 0=black
|
||||
vb.SetColor(1, 0xff, 0xff, 0xff, 0xff); // 1=white
|
||||
vb.SetColor(2, 0xff, 0x68, 0x37, 0x2b); // 2=red
|
||||
vb.SetColor(3, 0xff, 0x70, 0xa4, 0xb2); // 3=cyan
|
||||
vb.SetColor(4, 0xff, 0x6f, 0x3d, 0x86); // 4=purple
|
||||
vb.SetColor(5, 0xff, 0x58, 0x8d, 0x43); // 5=green
|
||||
vb.SetColor(6, 0xff, 0x35, 0x28, 0x79); // 6=blue
|
||||
vb.SetColor(7, 0xff, 0xb8, 0xc7, 0x6f); // 7=yellow
|
||||
vb.SetColor(8, 0xff, 0x6f, 0x4f, 0x25); // 8=orange
|
||||
vb.SetColor(9, 0xff, 0x43, 0x39, 0x00); // 9-brown
|
||||
vb.SetColor(10, 0xff, 0x9a, 0x67, 0x59); // 10=light red
|
||||
vb.SetColor(11, 0xff, 0x44, 0x44, 0x44); // 11=dark grey
|
||||
vb.SetColor(12, 0xff, 0x6c, 0x6c, 0x6c); // 12=grey
|
||||
vb.SetColor(13, 0xff, 0x9a, 0xd2, 0x84); // 13=light green
|
||||
vb.SetColor(14, 0xff, 0x6c, 0x5e, 0xb5); // 14=light blue
|
||||
vb.SetColor(15, 0xff, 0x95, 0x95, 0x95); // 15=light grey
|
||||
vb.SetColor(16, 0, 0, 0, 0); // 16=transparent
|
||||
#if SHOW_BORDER
|
||||
vb.SetColor(17, 0xff, 0x00, 0xd6, 0xff); // 17=grid border
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
113
SourceGen/RuntimeData/Nintendo/SNES-SA-1.sym65
Normal file
113
SourceGen/RuntimeData/Nintendo/SNES-SA-1.sym65
Normal file
|
@ -0,0 +1,113 @@
|
|||
; 6502bench SNES SA-1 registers symbol
|
||||
; Reference:
|
||||
; Super Nintendo Entertainment System Development Manual
|
||||
; Registers | Super Famicom Development Wiki
|
||||
; https://wiki.superfamicom.org/sa-1-registers
|
||||
; Copyright 2022 absindx
|
||||
; Follow the original license. (Apache 2.0)
|
||||
|
||||
*SYNOPSIS Super NES SA-1 registers
|
||||
|
||||
; SA-1 internal registers
|
||||
; bank = $00-$3F, $80-$BF
|
||||
; %?0??????xxxxxxxxxxxxxxxx
|
||||
; %010000000000000000000000 CompareMask (0/1)
|
||||
; %000000000000000000000000 CompareValue (1)
|
||||
; %000000001111111111111111 AddressMask (x)
|
||||
*MULTI_MASK %010000000000000000000000 %000000000000000000000000 %000000001111111111111111
|
||||
|
||||
; Write registers $xx2200
|
||||
|
||||
SA1_CCNT > $2200 ;W IRrN mmmm SA-1 CPU control
|
||||
SA1_SIE > $2201 ;W I-C- ---- Super NES CPU int enable
|
||||
SA1_SIC > $2202 ;W I-C- ---- Super NES CPU int clear
|
||||
SA1_CRVL > $2203 ;W aaaa aaaa SA-1 CPU reset vector (Low)
|
||||
SA1_CRVH > $2204 ;W aaaa aaaa SA-1 CPU reset vector (High)
|
||||
SA1_CNVL > $2205 ;W aaaa aaaa SA-1 CPU NMI vector (Low)
|
||||
SA1_CNVH > $2206 ;W aaaa aaaa SA-1 CPU NMI vector (High)
|
||||
SA1_CIVL > $2207 ;W aaaa aaaa SA-1 CPU IRQ vector (Low)
|
||||
SA1_CIVH > $2208 ;W aaaa aaaa SA-1 CPU IRQ vector (High)
|
||||
SA1_SCNT > $2209 ;W IS-N mmmm Super NES CPU control
|
||||
SA1_CIE > $220A ;W ITDN ---- SA-1 CPU int enable
|
||||
SA1_CIC > $220B ;W ITDN ---- SA-1 CPU int clear
|
||||
SA1_SNVL > $220C ;W aaaa aaaa Super NES CPU NMI vector (Low)
|
||||
SA1_SNVH > $220D ;W aaaa aaaa Super NES CPU NMI vector (High)
|
||||
SA1_SIVL > $220E ;W aaaa aaaa Super NES CPU IRQ vector (Low)
|
||||
SA1_SIVH > $220F ;W aaaa aaaa Super NES CPU IRQ vector (High)
|
||||
SA1_TMC > $2210 ;W T--- --VH H/V timer control
|
||||
SA1_CTR > $2211 ;W ---- ---- SA-1 CPU timer restart
|
||||
SA1_HCNTL > $2212 ;W HHHH HHHH Set H-Count (Low)
|
||||
SA1_HCNTH > $2213 ;W ---- ---H Set H-Count (High)
|
||||
SA1_VCNTL > $2214 ;W VVVV VVVV Set V-Count (Low)
|
||||
SA1_VCNTH > $2215 ;W ---- ---V Set V-Count (High)
|
||||
|
||||
SA1_CXB > $2220 ;W B--- -AAA Set Super MMC bank C
|
||||
SA1_DXB > $2221 ;W B--- -AAA Set Super MMC bank D
|
||||
SA1_EXB > $2222 ;W B--- -AAA Set Super MMC bank E
|
||||
SA1_FXB > $2223 ;W B--- -AAA Set Super MMC bank F
|
||||
SA1_BMAPS > $2224 ;W ---B BBBB Super NES CPU BW-RAM address mapping
|
||||
SA1_BMAP > $2225 ;W SBBB BBBB SA-1 CPU BW-RAM address mapping
|
||||
SA1_SBWE > $2226 ;W P--- ---- Super NES CPU BW-RAM write enable
|
||||
SA1_CBWE > $2227 ;W P--- ---- SA-1 CPU BW-RAM write enable
|
||||
SA1_BWPA > $2228 ;W ---- AAAA BW-RAM Write-Protected area
|
||||
SA1_SIWP > $2229 ;W 7654 3210 Super NES I-RAM wirte protection
|
||||
SA1_CIWP > $222A ;W 7654 3210 SA-1 I-RAM wirte protection
|
||||
|
||||
SA1_DCNT > $2230 ;W CPMT -DSS DMA control
|
||||
SA1_CDMA > $2231 ;W E--S SSCC Character conversion DMA parameters
|
||||
SA1_SDAL > $2232 ;W AAAA AAAA DMA source device start address (Low)
|
||||
SA1_SDAH > $2233 ;W AAAA AAAA DMA source device start address (Middle)
|
||||
SA1_SDAB > $2234 ;W AAAA AAAA DMA source device start address (High)
|
||||
SA1_DDAL > $2235 ;W AAAA AAAA DMA destination start address (Low)
|
||||
SA1_DDAH > $2236 ;W AAAA AAAA DMA destination start address (Middle)
|
||||
SA1_DDAB > $2237 ;W AAAA AAAA DMA destination start address (High)
|
||||
SA1_DTCL > $2238 ;W CCCC CCCC DMA terminal counter (Low)
|
||||
SA1_DTCH > $2239 ;W CCCC CCCC DMA terminal counter (High)
|
||||
|
||||
SA1_BBF > $223F ;W C--- ---- BW-RAM bit map format
|
||||
SA1_BRF0 > $2240 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF1 > $2241 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF2 > $2242 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF3 > $2243 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF4 > $2244 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF5 > $2245 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF6 > $2246 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF7 > $2247 ;W BBBB BBBB Bit map register file (Buffer 1)
|
||||
SA1_BRF8 > $2248 ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRF9 > $2249 ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFA > $224A ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFB > $224B ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFC > $224C ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFD > $224D ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFE > $224E ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_BRFF > $224F ;W BBBB BBBB Bit map register file (Buffer 2)
|
||||
SA1_MCNT > $2250 ;W ---- --OO Arithmetic control
|
||||
SA1_MAL > $2251 ;W NNNN NNNN Arithmetic parameters: Multiplicand / Dividend (Low)
|
||||
SA1_MAH > $2252 ;W NNNN NNNN Arithmetic parameters: Multiplicand / Dividend (High)
|
||||
SA1_MBL > $2253 ;W NNNN NNNN Arithmetic parameters: Multiplier / Divisor (Low)
|
||||
SA1_MBH > $2254 ;W NNNN NNNN Arithmetic parameters: Multiplier / Divisor (High)
|
||||
|
||||
SA1_VBD > $2258 ;W H--- VVVV Variable-Length bit processing
|
||||
SA1_VDAL > $2259 ;W AAAA AAAA Variable-Length bit game pak ROM start address (Low)
|
||||
SA1_VDAH > $225A ;W AAAA AAAA Variable-Length bit game pak ROM start address (Middle)
|
||||
SA1_VDAB > $225B ;W AAAA AAAA Variable-Length bit game pak ROM start address (High)
|
||||
|
||||
; Read registers $xx2300
|
||||
|
||||
SA1_SFR < $2300 ;R IVDN mmmm Super NES CPU flag read
|
||||
SA1_CFR < $2301 ;R ITDN mmmm SA-1 CPU flag read
|
||||
SA1_HCRL < $2302 ;R HHHH HHHH H-Count read (Low)
|
||||
SA1_HCRH < $2303 ;R ---- ---H H-Count read (High)
|
||||
SA1_VCRL < $2304 ;R VVVV VVVV V-Count read (Low)
|
||||
SA1_VCRH < $2305 ;R ---- ---V V-Count read (High)
|
||||
SA1_MR1 < $2306 ;R DDDD DDDD Arithmetic result (product/quotient/cumulative sum)
|
||||
SA1_MR2 < $2307 ;R DDDD DDDD Arithmetic result (product/quotient/cumulative sum)
|
||||
SA1_MR3 < $2308 ;R DDDD DDDD Arithmetic result (product/remainder/cumulative sum)
|
||||
SA1_MR4 < $2309 ;R DDDD DDDD Arithmetic result (product/remainder/cumulative sum)
|
||||
SA1_MR5 < $230A ;R DDDD DDDD Arithmetic result (cumulative sum)
|
||||
SA1_OF < $230B ;R O--- ---- Arithmetic overflow flag
|
||||
SA1_VDPL < $230C ;R DDDD DDDD Variable-Length data read port (Low)
|
||||
SA1_VDPH < $230D ;R DDDD DDDD Variable-Length data read port (High)
|
||||
SA1_VC < $230E ;R VVVV VVVV Version code register
|
||||
|
||||
|
70
SourceGen/RuntimeData/Nintendo/SNES-SuperFX.sym65
Normal file
70
SourceGen/RuntimeData/Nintendo/SNES-SuperFX.sym65
Normal file
|
@ -0,0 +1,70 @@
|
|||
; 6502bench SNES Super FX registers symbol
|
||||
; Reference:
|
||||
; Super Nintendo Entertainment System Development Manual
|
||||
; Copyright 2022 absindx
|
||||
; Follow the original license. (Apache 2.0)
|
||||
|
||||
*SYNOPSIS Super NES Super FX registers
|
||||
|
||||
; GSU internal registers $xx3000
|
||||
; bank = $00-$3F, $80-$BF
|
||||
; %?0??????xxxxxxxxxxxxxxxx
|
||||
; %010000000000000000000000 CompareMask (0/1)
|
||||
; %000000000000000000000000 CompareValue (1)
|
||||
; %000000001111111111111111 AddressMask (x)
|
||||
*MULTI_MASK %010000000000000000000000 %000000000000000000000000 %000000001111111111111111
|
||||
|
||||
; General registers
|
||||
|
||||
GSU_R0L @ $3000 ;RW DDDD DDDD Default source/destination register (Low)
|
||||
GSU_R0H @ $3001 ;RW DDDD DDDD Default source/destination register (High)
|
||||
GSU_R1L @ $3002 ;RW DDDD DDDD PLOT instruction, X coordinate (Low)
|
||||
GSU_R1H @ $3003 ;RW DDDD DDDD PLOT instruction, X coordinate (High)
|
||||
GSU_R2L @ $3004 ;RW DDDD DDDD PLOT instruction, Y coordinate (Low)
|
||||
GSU_R2H @ $3005 ;RW DDDD DDDD PLOT instruction, Y coordinate (High)
|
||||
GSU_R3L @ $3006 ;RW DDDD DDDD General register (Low)
|
||||
GSU_R3H @ $3007 ;RW DDDD DDDD General register (High)
|
||||
GSU_R4L @ $3008 ;RW DDDD DDDD LMULT instruction, lower 16 bits (Low)
|
||||
GSU_R4H @ $3009 ;RW DDDD DDDD LMULT instruction, lower 16 bits (High)
|
||||
GSU_R5L @ $300A ;RW DDDD DDDD General register (Low)
|
||||
GSU_R5H @ $300B ;RW DDDD DDDD General register (High)
|
||||
GSU_R6L @ $300C ;RW DDDD DDDD FMULT and LMULT instructions, multiplication (Low)
|
||||
GSU_R6H @ $300D ;RW DDDD DDDD FMULT and LMULT instructions, multiplication (High)
|
||||
GSU_R7L @ $300E ;RW DDDD DDDD MERGE instruction, source1 (Low)
|
||||
GSU_R7H @ $300F ;RW DDDD DDDD MERGE instruction, source1 (High)
|
||||
GSU_R8L @ $3010 ;RW DDDD DDDD MERGE instruction, source2 (Low)
|
||||
GSU_R8H @ $3011 ;RW DDDD DDDD MERGE instruction, source2 (High)
|
||||
GSU_R9L @ $3012 ;RW DDDD DDDD General register (Low)
|
||||
GSU_R9H @ $3013 ;RW DDDD DDDD General register (High)
|
||||
GSU_R10L @ $3014 ;RW DDDD DDDD General register (Low)
|
||||
GSU_R10H @ $3015 ;RW DDDD DDDD General register (High)
|
||||
GSU_R11L @ $3016 ;RW DDDD DDDD LINK instruction destination register (Low)
|
||||
GSU_R11H @ $3017 ;RW DDDD DDDD LINK instruction destination register (High)
|
||||
GSU_R12L @ $3018 ;RW DDDD DDDD LOOP instruction counter (Low)
|
||||
GSU_R12H @ $3019 ;RW DDDD DDDD LOOP instruction counter (High)
|
||||
GSU_R13L @ $301A ;RW DDDD DDDD LOOP instruction branch (Low)
|
||||
GSU_R13H @ $301B ;RW DDDD DDDD LOOP instruction branch (High)
|
||||
GSU_R14L @ $301C ;RW AAAA AAAA Game pak ROM address pointer (Low)
|
||||
GSU_R14H @ $301D ;RW AAAA AAAA Game pak ROM address pointer (High)
|
||||
GSU_R15L @ $301E ;RW PPPP PPPP Program counter (Low)
|
||||
GSU_R15H @ $301F ;RW PPPP PPPP Program counter (High)
|
||||
|
||||
; Other registers
|
||||
|
||||
GSU_SFRL @ $3030 ;RW -RGO SCZ- Flag register
|
||||
GSU_SFRH @ $3031 ;RW I--B HL21 Status register
|
||||
GSU_PBR @ $3034 ;RW AAAA AAAA Program bank register
|
||||
GSU_ROMBR < $3036 ;R AAAA AAAA Game pak ROM bank register
|
||||
GSU_RAMBR < $303C ;RW ---- ---A Game pak RAM bank register
|
||||
GSU_CBRL < $303E ;RW AAAA ---- Cache base register (Low)
|
||||
GSU_CBRH < $303F ;RW AAAA AAAA Cache base register (High)
|
||||
GSU_SCBR > $3038 ;W AAAA AAAA Screen base register
|
||||
GSU_SCMR > $303A ;W --HE EHGG Screen mode register
|
||||
;GSU_COLR - $30xx ;- CCCC CCCC Color register (Not accessible from Super NES)
|
||||
;GSU_POR - $30xx ;- ---O FNDT Plot option register (Not accessible from Super NES)
|
||||
GSU_BRAMR > $3033 ;W ---- ---B Back-up RAM register
|
||||
GSU_VCR < $303B ;R VVVV VVVV Version code register
|
||||
GSU_CFGR > $3037 ;W I-S- ---- Config register
|
||||
GSU_CLSR > $3039 ;W ---- ---C Clock select register
|
||||
|
||||
|
|
@ -3,127 +3,138 @@
|
|||
; Super Nintendo Entertainment System Development Manual
|
||||
; Registers | Super Famicom Development Wiki
|
||||
; https://wiki.superfamicom.org/registers
|
||||
; Copyright 2021 absindx
|
||||
; Memory map - SNESdev Wiki
|
||||
; https://snes.nesdev.org/wiki/Memory_map
|
||||
; Copyright 2021-2022 absindx
|
||||
; Follow the original license. (Apache 2.0)
|
||||
|
||||
*SYNOPSIS Super NES registers
|
||||
|
||||
*MULTI_MASK
|
||||
; I/O registers $xx2000
|
||||
; bank = $00-$3F, $80-$BF
|
||||
; page = $2000-$6F00
|
||||
; %?0??????xxxxxxxxxxxxxxxx
|
||||
; %010000000000000000000000 CompareMask (0/1)
|
||||
; %000000000000000000000000 CompareValue (1)
|
||||
; %000000001111111111111111 AddressMask (x)
|
||||
*MULTI_MASK %010000000000000000000000 %000000000000000000000000 %000000001111111111111111
|
||||
|
||||
; PPU registers (Address Bus B)
|
||||
|
||||
INIDISP @ $2100 ;W B--- FFFF Initial settings for screen
|
||||
OBJSEL @ $2101 ;W SSSN NAAA Object size & Object data area designation
|
||||
OAMADDL @ $2102 ;W AAAA AAAA Address for accessing OAM (Low)
|
||||
OAMADDH @ $2103 ;W P--- ---A Address for accessing OAM (High)
|
||||
OAMDATA @ $2104 ;W DDDD DDDD Data for OAM write
|
||||
BGMODE @ $2105 ;W SSSS PMMM BG mode & Character size settings
|
||||
MOSAIC @ $2106 ;W MMMM EEEE Size & Screen designation for mosaic display
|
||||
BG1SC @ $2107 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-1)
|
||||
BG2SC @ $2108 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-2)
|
||||
BG3SC @ $2109 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-3)
|
||||
BG4SC @ $210A ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-4)
|
||||
BG12NBA @ $210B ;W 2222 1111 BG character data area designation (BG-1, 2)
|
||||
BG34NBA @ $210C ;W 4444 3333 BG character data area designation (BG-3, 4)
|
||||
BG1HOFS @ $210D ;WW XXXX XXXX, ---X XXXX H scroll value designation for BG-1
|
||||
BG1VOFS @ $210E ;WW XXXX XXXX, ---X XXXX V scroll value designation for BG-1
|
||||
BG2HOFS @ $210F ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-2
|
||||
BG2VOFS @ $2110 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-2
|
||||
BG3HOFS @ $2111 ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-3
|
||||
BG3VOFS @ $2112 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-3
|
||||
BG4HOFS @ $2113 ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-4
|
||||
BG4VOFS @ $2114 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-4
|
||||
VMAINC @ $2115 ;W T--- GGII VRAM address increment value designation
|
||||
VMADDL @ $2116 ;W AAAA AAAA Address for VRAM read and write (Low)
|
||||
VMADDH @ $2117 ;W AAAA AAAA Address for VRAM read and write (High)
|
||||
VMDATAL @ $2118 ;W AAAA AAAA Data for VRAM write (Low)
|
||||
VMDATAH @ $2119 ;W AAAA AAAA Data for VRAM write (High)
|
||||
M7SEL @ $211A ;W SS-- --VH Initial setting in screen Mode-7
|
||||
M7A @ $211B ;WW AAAA AAAA, AAAA AAAA Rotation/Enlargement/Reduction in Mode-7, Matrix parameter A (Low, High)
|
||||
M7B @ $211C ;WW BBBB BBBB, BBBB BBBB Rotation/Enlargement/Reduction in Mode-7, Matrix parameter B (Low, High)
|
||||
M7C @ $211D ;WW CCCC CCCC, CCCC CCCC Rotation/Enlargement/Reduction in Mode-7, Matrix parameter C (Low, High)
|
||||
M7D @ $211E ;WW DDDD DDDD, DDDD DDDD Rotation/Enlargement/Reduction in Mode-7, Matrix parameter D (Low, High)
|
||||
M7X @ $211F ;WW XXXX XXXX, ---X XXXX Rotation/Enlargement/Reduction in Mode-7, Center position X0 (Low, High)
|
||||
M7Y @ $2120 ;WW YYYY YYYY, ---Y YYYY Rotation/Enlargement/Reduction in Mode-7, Center position Y0 (Low, High)
|
||||
CGADD @ $2121 ;W AAAA AAAA Address for CG-RAM read and write
|
||||
CGDATA @ $2122 ;WW DDDD DDDD, -DDD DDDD Data for CG-RAM write
|
||||
W12SEL @ $2123 ;W EIEI EIEI Window mask settings (BG-1, 2)
|
||||
W34SEL @ $2124 ;W EIEI EIEI Window mask settings (BG-3, 4)
|
||||
WOBJSEL @ $2125 ;W EIEI EIEI Window mask settings (OBJ, Color)
|
||||
WH0 @ $2126 ;W PPPP PPPP Window position designation (Window-1 left position)
|
||||
WH1 @ $2127 ;W PPPP PPPP Window position designation (Window-1 right position)
|
||||
WH2 @ $2128 ;W PPPP PPPP Window position designation (Window-2 left position)
|
||||
WH3 @ $2129 ;W PPPP PPPP Window position designation (Window-2 right position)
|
||||
WBGLOG @ $212A ;W 4433 2211 Mask logic settings for Window-1 & 2 on each screen
|
||||
WOBJLOG @ $212B ;W ---- CCOO Mask logic settings for Window-1 & 2 on each screen
|
||||
TM @ $212C ;W ---O 4321 Main screen designation
|
||||
TS @ $212D ;W ---O 4321 Sub screen designation
|
||||
TMW @ $212E ;W ---O 4321 Window mask designation for main screen
|
||||
TSW @ $212F ;W ---O 4321 Window mask designation for sub screen
|
||||
CGSWSEL @ $2130 ;W MMSS --CD Initial settings for fixed color addition on screen addition
|
||||
CGADSUB @ $2131 ;W SEBO 4321 Addition/Subtraction & Subtraction designation for each BG screen OBJ & Background color
|
||||
COLDATA @ $2132 ;W BGRD DDDD Fixed color data for fixed color addition/subtraction
|
||||
SETINI @ $2133 ;W SI-- PBOI Screen initial setting
|
||||
MPYL @ $2134 ;R MMMM MMMM Multiplication result (Low)
|
||||
MPYM @ $2135 ;R MMMM MMMM Multiplication result (Middle)
|
||||
MPYH @ $2136 ;R MMMM MMMM Multiplication result (High)
|
||||
SLHV @ $2137 ;- SSSS SSSS Software latch for H/V counter
|
||||
OAMDATA @ $2138 ;RR DDDD DDDD, DDDD DDDD Read data from OAM
|
||||
VMDATAL @ $2139 ;R DDDD DDDD Read data from VRAM (Low)
|
||||
VMDATAH @ $213A ;R DDDD DDDD Read data from VRAM (High)
|
||||
CGDATA @ $213B ;RR DDDD DDDD, -DDD DDDD Read data from CG-RAM
|
||||
OPHCT @ $213C ;RR HHHH HHHH, ---- ---H H counter data by external or software latch
|
||||
OPVCT @ $213D ;RR VVVV VVVV, ---- ---V V counter data by external or software latch
|
||||
STAT77 @ $213E ;R TRM- VVVV PPU status flag & Version number (5C77)
|
||||
STAT78 @ $213F ;R FL-D VVVV PPU status flag & Version number (5C78)
|
||||
INIDISP > $2100 ;W B--- FFFF Initial settings for screen
|
||||
OBJSEL > $2101 ;W SSSN NAAA Object size & Object data area designation
|
||||
OAMADDL > $2102 ;W AAAA AAAA Address for accessing OAM (Low)
|
||||
OAMADDH > $2103 ;W P--- ---A Address for accessing OAM (High)
|
||||
OAMDATA > $2104 ;W DDDD DDDD Data for OAM write
|
||||
BGMODE > $2105 ;W SSSS PMMM BG mode & Character size settings
|
||||
MOSAIC > $2106 ;W MMMM EEEE Size & Screen designation for mosaic display
|
||||
BG1SC > $2107 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-1)
|
||||
BG2SC > $2108 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-2)
|
||||
BG3SC > $2109 ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-3)
|
||||
BG4SC > $210A ;W AAAA AASS Address for storing SC-data of each BG & SC size designation (Mode 0-6) (BG-4)
|
||||
BG12NBA > $210B ;W 2222 1111 BG character data area designation (BG-1, 2)
|
||||
BG34NBA > $210C ;W 4444 3333 BG character data area designation (BG-3, 4)
|
||||
BG1HOFS > $210D ;WW XXXX XXXX, ---X XXXX H scroll value designation for BG-1
|
||||
BG1VOFS > $210E ;WW XXXX XXXX, ---X XXXX V scroll value designation for BG-1
|
||||
BG2HOFS > $210F ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-2
|
||||
BG2VOFS > $2110 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-2
|
||||
BG3HOFS > $2111 ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-3
|
||||
BG3VOFS > $2112 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-3
|
||||
BG4HOFS > $2113 ;WW XXXX XXXX, ---- --XX H scroll value designation for BG-4
|
||||
BG4VOFS > $2114 ;WW XXXX XXXX, ---- --XX V scroll value designation for BG-4
|
||||
VMAINC > $2115 ;W T--- GGII VRAM address increment value designation
|
||||
VMADDL > $2116 ;W AAAA AAAA Address for VRAM read and write (Low)
|
||||
VMADDH > $2117 ;W AAAA AAAA Address for VRAM read and write (High)
|
||||
VMDATAL > $2118 ;W AAAA AAAA Data for VRAM write (Low)
|
||||
VMDATAH > $2119 ;W AAAA AAAA Data for VRAM write (High)
|
||||
M7SEL > $211A ;W SS-- --VH Initial setting in screen Mode-7
|
||||
M7A > $211B ;WW AAAA AAAA, AAAA AAAA Rotation/Enlargement/Reduction in Mode-7, Matrix parameter A (Low, High)
|
||||
M7B > $211C ;WW BBBB BBBB, BBBB BBBB Rotation/Enlargement/Reduction in Mode-7, Matrix parameter B (Low, High)
|
||||
M7C > $211D ;WW CCCC CCCC, CCCC CCCC Rotation/Enlargement/Reduction in Mode-7, Matrix parameter C (Low, High)
|
||||
M7D > $211E ;WW DDDD DDDD, DDDD DDDD Rotation/Enlargement/Reduction in Mode-7, Matrix parameter D (Low, High)
|
||||
M7X > $211F ;WW XXXX XXXX, ---X XXXX Rotation/Enlargement/Reduction in Mode-7, Center position X0 (Low, High)
|
||||
M7Y > $2120 ;WW YYYY YYYY, ---Y YYYY Rotation/Enlargement/Reduction in Mode-7, Center position Y0 (Low, High)
|
||||
CGADD > $2121 ;W AAAA AAAA Address for CG-RAM read and write
|
||||
CGDATA > $2122 ;WW DDDD DDDD, -DDD DDDD Data for CG-RAM write
|
||||
W12SEL > $2123 ;W EIEI EIEI Window mask settings (BG-1, 2)
|
||||
W34SEL > $2124 ;W EIEI EIEI Window mask settings (BG-3, 4)
|
||||
WOBJSEL > $2125 ;W EIEI EIEI Window mask settings (OBJ, Color)
|
||||
WH0 > $2126 ;W PPPP PPPP Window position designation (Window-1 left position)
|
||||
WH1 > $2127 ;W PPPP PPPP Window position designation (Window-1 right position)
|
||||
WH2 > $2128 ;W PPPP PPPP Window position designation (Window-2 left position)
|
||||
WH3 > $2129 ;W PPPP PPPP Window position designation (Window-2 right position)
|
||||
WBGLOG > $212A ;W 4433 2211 Mask logic settings for Window-1 & 2 on each screen
|
||||
WOBJLOG > $212B ;W ---- CCOO Mask logic settings for Window-1 & 2 on each screen
|
||||
TM > $212C ;W ---O 4321 Main screen designation
|
||||
TS > $212D ;W ---O 4321 Sub screen designation
|
||||
TMW > $212E ;W ---O 4321 Window mask designation for main screen
|
||||
TSW > $212F ;W ---O 4321 Window mask designation for sub screen
|
||||
CGSWSEL > $2130 ;W MMSS --CD Initial settings for fixed color addition on screen addition
|
||||
CGADSUB > $2131 ;W SEBO 4321 Addition/Subtraction & Subtraction designation for each BG screen OBJ & Background color
|
||||
COLDATA > $2132 ;W BGRD DDDD Fixed color data for fixed color addition/subtraction
|
||||
SETINI > $2133 ;W SI-- PBOI Screen initial setting
|
||||
MPYL < $2134 ;R MMMM MMMM Multiplication result (Low)
|
||||
MPYM < $2135 ;R MMMM MMMM Multiplication result (Middle)
|
||||
MPYH < $2136 ;R MMMM MMMM Multiplication result (High)
|
||||
SLHV < $2137 ;R ---- ---- Software latch for H/V counter
|
||||
OAMDATAREAD < $2138 ;RR DDDD DDDD, DDDD DDDD Read data from OAM
|
||||
VMDATALREAD < $2139 ;R DDDD DDDD Read data from VRAM (Low)
|
||||
VMDATAHREAD < $213A ;R DDDD DDDD Read data from VRAM (High)
|
||||
CGDATAREAD < $213B ;RR DDDD DDDD, -DDD DDDD Read data from CG-RAM
|
||||
OPHCT < $213C ;RR HHHH HHHH, ---- ---H H counter data by external or software latch
|
||||
OPVCT < $213D ;RR VVVV VVVV, ---- ---V V counter data by external or software latch
|
||||
STAT77 < $213E ;R TRM- VVVV PPU status flag & Version number (5C77)
|
||||
STAT78 < $213F ;R FL-D VVVV PPU status flag & Version number (5C78)
|
||||
APUIO0 @ $2140 ;RW DDDD DDDD Communication port with APU
|
||||
APUIO1 @ $2141 ;RW DDDD DDDD Communication port with APU
|
||||
APUIO2 @ $2142 ;RW DDDD DDDD Communication port with APU
|
||||
APUIO3 @ $2143 ;RW DDDD DDDD Communication port with APU
|
||||
WMDATA @ $2180 ;RW DDDD DDDD DATA to consecutively read from and write to WRAM
|
||||
WMADDL @ $2181 ;W AAAA AAAA Address to consecutively read and write WRAM (Low)
|
||||
WMADDM @ $2182 ;W AAAA AAAA Address to consecutively read and write WRAM (Middle)
|
||||
WMADDH @ $2183 ;W ---- ---A Address to consecutively read and write WRAM (High)
|
||||
WMADDL > $2181 ;W AAAA AAAA Address to consecutively read and write WRAM (Low)
|
||||
WMADDM > $2182 ;W AAAA AAAA Address to consecutively read and write WRAM (Middle)
|
||||
WMADDH > $2183 ;W ---- ---A Address to consecutively read and write WRAM (High)
|
||||
|
||||
|
||||
|
||||
; CPU registers (Internal)
|
||||
|
||||
NMITIMEN @ $4200 ;W N-VH ---C Enable flag for V-Blank, Timer interrupt & Standard controller read
|
||||
WRIO @ $4201 ;W DDDD DDDD Programmable I/O port (Out port)
|
||||
WRMPYA @ $4202 ;W AAAA AAAA Multiplicand by multiplication
|
||||
WRMPYB @ $4203 ;W BBBB BBBB Multiplier by multiplication
|
||||
WRDIVL @ $4204 ;W CCCC CCCC Dividend by divide (Low)
|
||||
WRDIVH @ $4205 ;W CCCC CCCC Dividend by divide (High)
|
||||
WRDIVB @ $4206 ;W BBBB BBBB Divisor by divide
|
||||
HTIMEL @ $4207 ;W HHHH HHHH H-count timer settings (Low)
|
||||
HTIMEH @ $4208 ;W ---- ---H H-count timer settings (High)
|
||||
VTIMEL @ $4209 ;W VVVV VVVV V-count timer settings (Low)
|
||||
VTIMEH @ $420A ;W ---- ---V V-count timer settings (High)
|
||||
MDMAEN @ $420B ;W 7654 3210 Channel designation for general purpose DMA & Trigger (start)
|
||||
HDMAEN @ $420C ;W 7654 3210 Channel designation for H-DMA
|
||||
MEMSEL @ $420D ;W ---- ---A Access cycle designation in memory [2] area
|
||||
RDNMI @ $4210 ;R N--- VVVV NMI flag by V-Blank & Version number
|
||||
TIMEUP @ $4211 ;R T--- ---- IRQ flag by H/V count timer
|
||||
HVBJOY @ $4212 ;R VH-- ---C H/V Blank flag & Standard controller enable flag
|
||||
RDIO @ $4213 ;R DDDD DDDD Programmable I/O port (In port)
|
||||
RDDIVL @ $4214 ;R AAAA AAAA Quotient of divide result (Low)
|
||||
RDDIVH @ $4215 ;R AAAA AAAA Quotient of divide result (High)
|
||||
RDMPYL @ $4216 ;R CCCC CCCC Product of multiplication result or remainder of divide result (Low)
|
||||
RDMPYH @ $4217 ;R CCCC CCCC Product of multiplication result or remainder of divide result (High)
|
||||
STDCNTRL1L @ $4218 ;R AXLR ---- Data for standard controller 1 (Low)
|
||||
STDCNTRL1H @ $4219 ;R BYST UDLR Data for standard controller 1 (High)
|
||||
STDCNTRL2L @ $421A ;R AXLR ---- Data for standard controller 2 (Low)
|
||||
STDCNTRL2H @ $421B ;R BYST UDLR Data for standard controller 2 (High)
|
||||
STDCNTRL3L @ $421C ;R AXLR ---- Data for standard controller 3 (Low)
|
||||
STDCNTRL3H @ $421D ;R BYST UDLR Data for standard controller 3 (High)
|
||||
STDCNTRL4L @ $421E ;R AXLR ---- Data for standard controller 4 (Low)
|
||||
STDCNTRL4H @ $421F ;R BYST UDLR Data for standard controller 4 (High)
|
||||
NMITIMEN > $4200 ;W N-VH ---C Enable flag for V-Blank, Timer interrupt & Standard controller read
|
||||
WRIO > $4201 ;W DDDD DDDD Programmable I/O port (Out port)
|
||||
WRMPYA > $4202 ;W AAAA AAAA Multiplicand by multiplication
|
||||
WRMPYB > $4203 ;W BBBB BBBB Multiplier by multiplication
|
||||
WRDIVL > $4204 ;W CCCC CCCC Dividend by divide (Low)
|
||||
WRDIVH > $4205 ;W CCCC CCCC Dividend by divide (High)
|
||||
WRDIVB > $4206 ;W BBBB BBBB Divisor by divide
|
||||
HTIMEL > $4207 ;W HHHH HHHH H-count timer settings (Low)
|
||||
HTIMEH > $4208 ;W ---- ---H H-count timer settings (High)
|
||||
VTIMEL > $4209 ;W VVVV VVVV V-count timer settings (Low)
|
||||
VTIMEH > $420A ;W ---- ---V V-count timer settings (High)
|
||||
MDMAEN > $420B ;W 7654 3210 Channel designation for general purpose DMA & Trigger (start)
|
||||
HDMAEN > $420C ;W 7654 3210 Channel designation for H-DMA
|
||||
MEMSEL > $420D ;W ---- ---A Access cycle designation in memory [2] area
|
||||
RDNMI < $4210 ;R N--- VVVV NMI flag by V-Blank & Version number
|
||||
TIMEUP < $4211 ;R T--- ---- IRQ flag by H/V count timer
|
||||
HVBJOY < $4212 ;R VH-- ---C H/V Blank flag & Standard controller enable flag
|
||||
RDIO < $4213 ;R DDDD DDDD Programmable I/O port (In port)
|
||||
RDDIVL < $4214 ;R AAAA AAAA Quotient of divide result (Low)
|
||||
RDDIVH < $4215 ;R AAAA AAAA Quotient of divide result (High)
|
||||
RDMPYL < $4216 ;R CCCC CCCC Product of multiplication result or remainder of divide result (Low)
|
||||
RDMPYH < $4217 ;R CCCC CCCC Product of multiplication result or remainder of divide result (High)
|
||||
STDCNTRL1L < $4218 ;R AXLR ---- Data for standard controller 1 (Low)
|
||||
STDCNTRL1H < $4219 ;R BYST UDLR Data for standard controller 1 (High)
|
||||
STDCNTRL2L < $421A ;R AXLR ---- Data for standard controller 2 (Low)
|
||||
STDCNTRL2H < $421B ;R BYST UDLR Data for standard controller 2 (High)
|
||||
STDCNTRL3L < $421C ;R AXLR ---- Data for standard controller 3 (Low)
|
||||
STDCNTRL3H < $421D ;R BYST UDLR Data for standard controller 3 (High)
|
||||
STDCNTRL4L < $421E ;R AXLR ---- Data for standard controller 4 (Low)
|
||||
STDCNTRL4H < $421F ;R BYST UDLR Data for standard controller 4 (High)
|
||||
|
||||
|
||||
|
||||
; Old Style Joypad Registers
|
||||
|
||||
JOYSER0 @ $4016 ;R:---- --31 W:---- -xxL
|
||||
JOYSER1 @ $4017 ;R ---- --42
|
||||
JOYSER1 < $4017 ;R ---- --42
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
# Runtime Data #
|
||||
|
||||
Symbol files and analyzer scripts are split into directories by
|
||||
platform manufacturer.
|
||||
Symbol files and extension scripts are split into directories by
|
||||
platform manufacturer. General-purpose scripts are in the `Common`
|
||||
directory.
|
||||
|
||||
The Visual Studio project (RuntimeData.csproj) exists so you can edit
|
||||
scripts with IntelliSense and error highlighting. Everything here is
|
||||
distributed as source, not in compiled form; all compilation occurs at
|
||||
run time.
|
||||
A Visual Studio project (`RuntimeData.csproj`) exists in the source tree
|
||||
so you can edit platform-specific scripts with IntelliSense and error
|
||||
highlighting. Everything in this directory is distributed as source,
|
||||
not in compiled form; all compilation occurs at run time.
|
||||
|
||||
The `Tips` directory holds the files used by the "daily tips" feature,
|
||||
and `TestData` has some files used by the regression tests.
|
||||
|
||||
## SystemDefs.json ##
|
||||
|
||||
|
@ -16,7 +20,7 @@ The following fields are mandatory:
|
|||
* Name - Short name that identifies the system.
|
||||
* GroupName - Short string used to group common items together in the UI.
|
||||
* CPU - Type of CPU used. The string must be part of the known set
|
||||
(see CpuDef.cs)
|
||||
(see CpuDef.cs).
|
||||
* Speed - Clock rate, in MHz, of the CPU on the system. When multiple
|
||||
speeds are possible, use the most common, favoring NTSC over PAL.
|
||||
* SymbolFiles - List of platform symbol file identifiers (see below).
|
||||
|
@ -25,42 +29,40 @@ The following fields are mandatory:
|
|||
|
||||
The currently-supported parameters are:
|
||||
|
||||
* load-address=<addr> - Specify the initial load address. The default
|
||||
* `load-address=<addr>` - Specify the initial load address. The default
|
||||
is 0x1000.
|
||||
* entry-flags=<flag-set> - Specify the processor status flag values to
|
||||
* `entry-flags=<flag-set>` - Specify the processor status flag values to
|
||||
use at entry points. This is intended for use on the 65802/65816, and
|
||||
may be one of "emulation", "native-short", and "native-long". The
|
||||
default is "emulation".
|
||||
* undocumented-opcodes={true|false} - Enable or disable undocumented
|
||||
may be one of `emulation`, `native-short`, and `native-long`. The
|
||||
default is `emulation`.
|
||||
* `undocumented-opcodes={true|false}` - Enable or disable undocumented
|
||||
opcodes. They are disabled by default.
|
||||
* first-word-is-load-addr={true|false} - If true, the first two bytes of
|
||||
* `first-word-is-load-addr={true|false}` - If true, the first two bytes of
|
||||
the file contain the load address.
|
||||
* default-text-encoding=<mode> - Specify default character encoding.
|
||||
Use "c64-petscii" for PETSCII. The default is low/high ASCII.
|
||||
* `default-text-encoding=<mode>` - Specify default character encoding.
|
||||
Use `c64-petscii` for PETSCII. The default is low/high ASCII.
|
||||
|
||||
All of these things can be changed after the project has begun, but it's
|
||||
nice to have them configured in advance.
|
||||
|
||||
SymbolFiles and ExtensionScripts use file identifiers, which look like
|
||||
"RT:Apple/ProDOS8.sym65". The "RT:" means that the file lives in the
|
||||
"`RT:Apple/ProDOS8.sym65`". The "RT:" means that the file lives in the
|
||||
RuntimeData directory, and the rest is a partial pathname. Files that
|
||||
live in the same directory as the project file are prefixed with "PROJ:".
|
||||
All symbol files and extension scripts must live in the RuntimeData
|
||||
directory or project file directory, or they will not be loaded.
|
||||
|
||||
All "RT:" identifier paths are relative to the RuntimeData directory. The
|
||||
Group Name is not automatically added.
|
||||
|
||||
GroupName string is not automatically added.
|
||||
|
||||
## Platform Symbol Files and Extension Scripts ##
|
||||
|
||||
These are described in the "Advanced Topics" section of the manual
|
||||
([here](Help/advanced.html)).
|
||||
|
||||
The format of these files is described in detail in the "Advanced Topics"
|
||||
section of the manual ([here](../../docs/sgmanual/advanced.html)).
|
||||
|
||||
## Misc Files ##
|
||||
|
||||
ExportTemplate.html and SGStyle.css are used by SourceGen's HTML export
|
||||
`ExportTemplate.html` and `SGStyle.css` are used by SourceGen's HTML export
|
||||
feature.
|
||||
|
||||
LegalStuff.txt is displayed in the About box.
|
||||
`LegalStuff.txt` is displayed in the About box.
|
||||
|
|
BIN
SourceGen/SGTestData/20280-label-placement
Normal file
BIN
SourceGen/SGTestData/20280-label-placement
Normal file
Binary file not shown.
175
SourceGen/SGTestData/20280-label-placement.dis65
Normal file
175
SourceGen/SGTestData/20280-label-placement.dis65
Normal file
|
@ -0,0 +1,175 @@
|
|||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":5,
|
||||
"FileDataLength":25,
|
||||
"FileDataCrc32":646072439,
|
||||
"ProjectProps":{
|
||||
"CpuName":"6502",
|
||||
"IncludeUndocumentedInstr":false,
|
||||
"TwoByteBrk":false,
|
||||
"EntryFlags":32702671,
|
||||
"AutoLabelStyle":"Simple",
|
||||
"AnalysisParams":{
|
||||
"AnalyzeUncategorizedData":true,
|
||||
"DefaultTextScanMode":"LowHighAscii",
|
||||
"MinCharsForString":4,
|
||||
"SeekNearbyTargets":true,
|
||||
"UseRelocData":false,
|
||||
"SmartPlpHandling":false,
|
||||
"SmartPlbHandling":true},
|
||||
|
||||
"PlatformSymbolFileIdentifiers":[],
|
||||
"ExtensionScriptFileIdentifiers":[],
|
||||
"ProjectSyms":{
|
||||
"__ENABLE_ALL_LABEL_NEWLINE":{
|
||||
"DataDescriptor":{
|
||||
"Length":1,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Decimal",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"",
|
||||
"HasWidth":false,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"__ENABLE_ALL_LABEL_NEWLINE",
|
||||
"Value":1,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"shortnm":{
|
||||
"DataDescriptor":{
|
||||
"Length":1,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"short label",
|
||||
"HasWidth":false,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"shortnm",
|
||||
"Value":16384,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"SomewhatLongName":{
|
||||
"DataDescriptor":{
|
||||
"Length":1,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"somewhat longer label",
|
||||
"HasWidth":false,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"SomewhatLongName",
|
||||
"Value":16385,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"}}},
|
||||
|
||||
"AddressMap":[{
|
||||
"Offset":0,
|
||||
"Addr":4096,
|
||||
"Length":25,
|
||||
"PreLabel":"",
|
||||
"IsRelative":false}],
|
||||
"TypeHints":[{
|
||||
"Low":0,
|
||||
"High":0,
|
||||
"Hint":"Code"}],
|
||||
"StatusFlagOverrides":{
|
||||
},
|
||||
|
||||
"Comments":{
|
||||
},
|
||||
|
||||
"LongComments":{
|
||||
},
|
||||
|
||||
"Notes":{
|
||||
},
|
||||
|
||||
"UserLabels":{
|
||||
"9":{
|
||||
"Label":"data",
|
||||
"Value":4105,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"20":{
|
||||
"Label":"shortb",
|
||||
"Value":4116,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"10":{
|
||||
"Label":"BranchTargetLongName",
|
||||
"Value":4106,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"24":{
|
||||
"Label":"done",
|
||||
"Value":4120,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"}},
|
||||
|
||||
"OperandFormats":{
|
||||
},
|
||||
|
||||
"LvTables":{
|
||||
"10":{
|
||||
"Variables":[{
|
||||
"DataDescriptor":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"local var with short name",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"ptr",
|
||||
"Value":0,
|
||||
"Source":"Variable",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
{
|
||||
"DataDescriptor":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"local var with longer name",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"PointerWithLongName",
|
||||
"Value":2,
|
||||
"Source":"Variable",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"}],
|
||||
"ClearPrevious":false}},
|
||||
|
||||
"Visualizations":[],
|
||||
"VisualizationAnimations":[],
|
||||
"VisualizationSets":{
|
||||
},
|
||||
|
||||
"RelocList":{
|
||||
},
|
||||
|
||||
"DbrValues":{
|
||||
}}
|
BIN
SourceGen/SGTestData/20290-region-isolation
Normal file
BIN
SourceGen/SGTestData/20290-region-isolation
Normal file
Binary file not shown.
419
SourceGen/SGTestData/20290-region-isolation.dis65
Normal file
419
SourceGen/SGTestData/20290-region-isolation.dis65
Normal file
|
@ -0,0 +1,419 @@
|
|||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":6,
|
||||
"FileDataLength":1537,
|
||||
"FileDataCrc32":-1543685807,
|
||||
"ProjectProps":{
|
||||
"CpuName":"6502",
|
||||
"IncludeUndocumentedInstr":false,
|
||||
"TwoByteBrk":false,
|
||||
"EntryFlags":32702671,
|
||||
"AutoLabelStyle":"Simple",
|
||||
"AnalysisParams":{
|
||||
"AnalyzeUncategorizedData":true,
|
||||
"DefaultTextScanMode":"LowHighAscii",
|
||||
"MinCharsForString":4,
|
||||
"SeekNearbyTargets":true,
|
||||
"UseRelocData":false,
|
||||
"SmartPlpHandling":false,
|
||||
"SmartPlbHandling":true},
|
||||
|
||||
"PlatformSymbolFileIdentifiers":[],
|
||||
"ExtensionScriptFileIdentifiers":[],
|
||||
"ProjectSyms":{
|
||||
"IN_1":{
|
||||
"DataDescriptor":{
|
||||
"Length":256,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"IN_1",
|
||||
"Value":36864,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"IN_2":{
|
||||
"DataDescriptor":{
|
||||
"Length":256,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"IN_2",
|
||||
"Value":40960,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"IN_3":{
|
||||
"DataDescriptor":{
|
||||
"Length":256,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"IN_3",
|
||||
"Value":45056,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"IN_4":{
|
||||
"DataDescriptor":{
|
||||
"Length":256,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"",
|
||||
"HasWidth":true,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"IN_4",
|
||||
"Value":49152,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"THREE_K":{
|
||||
"DataDescriptor":{
|
||||
"Length":1,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Hex",
|
||||
"SymbolRef":null},
|
||||
|
||||
"Comment":"project symbol test",
|
||||
"HasWidth":false,
|
||||
"Direction":"ReadWrite",
|
||||
"MultiMask":null,
|
||||
"Label":"THREE_K",
|
||||
"Value":12288,
|
||||
"Source":"Project",
|
||||
"Type":"ExternalAddr",
|
||||
"LabelAnno":"None"}}},
|
||||
|
||||
"AddressMap":[{
|
||||
"Offset":0,
|
||||
"Addr":2048,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":45,
|
||||
"Addr":2093,
|
||||
"Length":12,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":true,
|
||||
"IsRelative":true},
|
||||
|
||||
{
|
||||
"Offset":256,
|
||||
"Addr":4096,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":true,
|
||||
"DisallowOutward":true,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":512,
|
||||
"Addr":4096,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":537,
|
||||
"Addr":36864,
|
||||
"Length":18,
|
||||
"PreLabel":"inner1_pre",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":768,
|
||||
"Addr":8192,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":true,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":793,
|
||||
"Addr":40960,
|
||||
"Length":18,
|
||||
"PreLabel":"inner2_pre",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":1024,
|
||||
"Addr":12288,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":true,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":1049,
|
||||
"Addr":45056,
|
||||
"Length":18,
|
||||
"PreLabel":"inner3_pre",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":1280,
|
||||
"Addr":16384,
|
||||
"Length":256,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":true,
|
||||
"DisallowOutward":true,
|
||||
"IsRelative":false},
|
||||
|
||||
{
|
||||
"Offset":1305,
|
||||
"Addr":49152,
|
||||
"Length":18,
|
||||
"PreLabel":"inner4_pre",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false}],
|
||||
"TypeHints":[{
|
||||
"Low":0,
|
||||
"High":0,
|
||||
"Hint":"Code"},
|
||||
|
||||
{
|
||||
"Low":256,
|
||||
"High":256,
|
||||
"Hint":"Code"},
|
||||
|
||||
{
|
||||
"Low":512,
|
||||
"High":512,
|
||||
"Hint":"Code"},
|
||||
|
||||
{
|
||||
"Low":1024,
|
||||
"High":1024,
|
||||
"Hint":"Code"},
|
||||
|
||||
{
|
||||
"Low":1280,
|
||||
"High":1280,
|
||||
"Hint":"Code"}],
|
||||
"StatusFlagOverrides":{
|
||||
},
|
||||
|
||||
"Comments":{
|
||||
"9":"operand label set manually"},
|
||||
|
||||
"LongComments":{
|
||||
},
|
||||
|
||||
"Notes":{
|
||||
},
|
||||
|
||||
"UserLabels":{
|
||||
"256":{
|
||||
"Label":"region1x",
|
||||
"Value":4096,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"36":{
|
||||
"Label":"altbnk1",
|
||||
"Value":2084,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"45":{
|
||||
"Label":"altbnk2",
|
||||
"Value":2093,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"57":{
|
||||
"Label":"done",
|
||||
"Value":2105,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"512":{
|
||||
"Label":"region1",
|
||||
"Value":4096,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"537":{
|
||||
"Label":"inner1",
|
||||
"Value":36864,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"555":{
|
||||
"Label":"finish1",
|
||||
"Value":4139,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"768":{
|
||||
"Label":"region2",
|
||||
"Value":8192,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"793":{
|
||||
"Label":"inner2",
|
||||
"Value":40960,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"811":{
|
||||
"Label":"finish2",
|
||||
"Value":8235,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1024":{
|
||||
"Label":"region3",
|
||||
"Value":12288,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1049":{
|
||||
"Label":"inner3",
|
||||
"Value":45056,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1067":{
|
||||
"Label":"finish3",
|
||||
"Value":12331,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1280":{
|
||||
"Label":"region4",
|
||||
"Value":16384,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1305":{
|
||||
"Label":"inner4",
|
||||
"Value":49152,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1323":{
|
||||
"Label":"finish4",
|
||||
"Value":16427,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1287":{
|
||||
"Label":"copy",
|
||||
"Value":16391,
|
||||
"Source":"User",
|
||||
"Type":"NonUniqueLocalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1031":{
|
||||
"Label":"copy",
|
||||
"Value":12295,
|
||||
"Source":"User",
|
||||
"Type":"NonUniqueLocalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"775":{
|
||||
"Label":"copy",
|
||||
"Value":8199,
|
||||
"Source":"User",
|
||||
"Type":"NonUniqueLocalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"519":{
|
||||
"Label":"copy",
|
||||
"Value":4103,
|
||||
"Source":"User",
|
||||
"Type":"NonUniqueLocalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"24":{
|
||||
"Label":"self",
|
||||
"Value":2072,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"1319":{
|
||||
"Label":"_checkit",
|
||||
"Value":49166,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"}},
|
||||
|
||||
"OperandFormats":{
|
||||
"9":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"region4",
|
||||
"Part":"Low"}}},
|
||||
|
||||
"LvTables":{
|
||||
},
|
||||
|
||||
"Visualizations":[],
|
||||
"VisualizationAnimations":[],
|
||||
"VisualizationSets":{
|
||||
},
|
||||
|
||||
"RelocList":{
|
||||
},
|
||||
|
||||
"DbrValues":{
|
||||
}}
|
BIN
SourceGen/SGTestData/20300-binary-include
Normal file
BIN
SourceGen/SGTestData/20300-binary-include
Normal file
Binary file not shown.
85
SourceGen/SGTestData/20300-binary-include.dis65
Normal file
85
SourceGen/SGTestData/20300-binary-include.dis65
Normal file
|
@ -0,0 +1,85 @@
|
|||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":6,
|
||||
"FileDataLength":96,
|
||||
"FileDataCrc32":1316780246,
|
||||
"ProjectProps":{
|
||||
"CpuName":"6502",
|
||||
"IncludeUndocumentedInstr":false,
|
||||
"TwoByteBrk":false,
|
||||
"EntryFlags":32702671,
|
||||
"AutoLabelStyle":"Simple",
|
||||
"AnalysisParams":{
|
||||
"AnalyzeUncategorizedData":true,
|
||||
"DefaultTextScanMode":"LowHighAscii",
|
||||
"MinCharsForString":4,
|
||||
"SeekNearbyTargets":true,
|
||||
"UseRelocData":false,
|
||||
"SmartPlpHandling":false,
|
||||
"SmartPlbHandling":true},
|
||||
|
||||
"PlatformSymbolFileIdentifiers":[],
|
||||
"ExtensionScriptFileIdentifiers":[],
|
||||
"ProjectSyms":{
|
||||
}},
|
||||
|
||||
"AddressMap":[{
|
||||
"Offset":0,
|
||||
"Addr":4096,
|
||||
"Length":96,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
"IsRelative":false}],
|
||||
"TypeHints":[{
|
||||
"Low":0,
|
||||
"High":0,
|
||||
"Hint":"Code"}],
|
||||
"StatusFlagOverrides":{
|
||||
},
|
||||
|
||||
"Comments":{
|
||||
},
|
||||
|
||||
"LongComments":{
|
||||
},
|
||||
|
||||
"Notes":{
|
||||
},
|
||||
|
||||
"UserLabels":{
|
||||
"95":{
|
||||
"Label":"done",
|
||||
"Value":4191,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"}},
|
||||
|
||||
"OperandFormats":{
|
||||
"23":{
|
||||
"Length":40,
|
||||
"Format":"BinaryInclude",
|
||||
"SubFormat":"None",
|
||||
"SymbolRef":null,
|
||||
"Extra":"↑20300-1.bin"},
|
||||
|
||||
"63":{
|
||||
"Length":32,
|
||||
"Format":"BinaryInclude",
|
||||
"SubFormat":"None",
|
||||
"SymbolRef":null,
|
||||
"Extra":"↑20300sub/20300-2.bin"}},
|
||||
|
||||
"LvTables":{
|
||||
},
|
||||
|
||||
"Visualizations":[],
|
||||
"VisualizationAnimations":[],
|
||||
"VisualizationSets":{
|
||||
},
|
||||
|
||||
"RelocList":{
|
||||
},
|
||||
|
||||
"DbrValues":{
|
||||
}}
|
28
SourceGen/SGTestData/Expected/20280-label-placement_64tass.S
Normal file
28
SourceGen/SGTestData/Expected/20280-label-placement_64tass.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
.cpu "6502"
|
||||
shortnm = $4000 ;short label
|
||||
SomewhatLongName = $4001 ;somewhat longer label
|
||||
|
||||
* = $1000
|
||||
lda shortnm
|
||||
ldx SomewhatLongName
|
||||
clc
|
||||
bcc BranchTargetLongName
|
||||
|
||||
data
|
||||
.byte $cc
|
||||
|
||||
ptr .var $00 ;local var with short name
|
||||
PointerWithLongName .var $02 ;local var with longer name
|
||||
BranchTargetLongName
|
||||
sta ptr
|
||||
stx PointerWithLongName
|
||||
ldy data
|
||||
lsr a
|
||||
bcc shortb
|
||||
shortb
|
||||
nop
|
||||
jmp done
|
||||
|
||||
done
|
||||
rts
|
||||
|
29
SourceGen/SGTestData/Expected/20280-label-placement_acme.S
Normal file
29
SourceGen/SGTestData/Expected/20280-label-placement_acme.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
!cpu 6502
|
||||
shortnm = $4000 ;short label
|
||||
SomewhatLongName = $4001 ;somewhat longer label
|
||||
|
||||
* = $1000
|
||||
lda shortnm
|
||||
ldx SomewhatLongName
|
||||
clc
|
||||
bcc BranchTargetLongName
|
||||
|
||||
data
|
||||
!byte $cc
|
||||
|
||||
!zone Z00000a
|
||||
.ptr = $00 ;local var with short name
|
||||
.PointerWithLongName = $02 ;local var with longer name
|
||||
BranchTargetLongName
|
||||
sta .ptr
|
||||
stx .PointerWithLongName
|
||||
ldy data
|
||||
lsr
|
||||
bcc shortb
|
||||
shortb
|
||||
nop
|
||||
jmp done
|
||||
|
||||
done
|
||||
rts
|
||||
|
28
SourceGen/SGTestData/Expected/20280-label-placement_cc65.S
Normal file
28
SourceGen/SGTestData/Expected/20280-label-placement_cc65.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
.setcpu "6502"
|
||||
shortnm = $4000 ;short label
|
||||
SomewhatLongName = $4001 ;somewhat longer label
|
||||
|
||||
.org $1000
|
||||
lda shortnm
|
||||
ldx SomewhatLongName
|
||||
clc
|
||||
bcc BranchTargetLongName
|
||||
|
||||
data:
|
||||
.byte $cc
|
||||
|
||||
ptr .set $00 ;local var with short name
|
||||
PointerWithLongName .set $02 ;local var with longer name
|
||||
BranchTargetLongName:
|
||||
sta ptr
|
||||
stx PointerWithLongName
|
||||
ldy data
|
||||
lsr A
|
||||
bcc shortb
|
||||
shortb:
|
||||
nop
|
||||
jmp done
|
||||
|
||||
done:
|
||||
rts
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# 6502bench SourceGen generated linker script for 20280-label-placement
|
||||
MEMORY {
|
||||
MAIN: file=%O, start=%S, size=65536;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load=MAIN, type=rw;
|
||||
}
|
||||
FEATURES {}
|
||||
SYMBOLS {}
|
|
@ -0,0 +1,27 @@
|
|||
shortnm equ $4000 ;short label
|
||||
SomewhatLongName equ $4001 ;somewhat longer label
|
||||
|
||||
org $1000
|
||||
lda shortnm
|
||||
ldx SomewhatLongName
|
||||
clc
|
||||
bcc BranchTargetLongName
|
||||
|
||||
data
|
||||
dfb $cc
|
||||
|
||||
]ptr equ $00 ;local var with short name
|
||||
]PointerWithLongName equ $02 ;local var with longer name
|
||||
BranchTargetLongName
|
||||
sta ]ptr
|
||||
stx ]PointerWithLongName
|
||||
ldy data
|
||||
lsr A
|
||||
bcc shortb
|
||||
shortb
|
||||
nop
|
||||
jmp done
|
||||
|
||||
done
|
||||
rts
|
||||
|
255
SourceGen/SGTestData/Expected/20290-region-isolation_64tass.S
Normal file
255
SourceGen/SGTestData/Expected/20290-region-isolation_64tass.S
Normal file
|
@ -0,0 +1,255 @@
|
|||
.cpu "6502"
|
||||
THREE_K = $3000 ;project symbol test
|
||||
IN_1 = $9000
|
||||
IN_2 = $a000
|
||||
IN_3 = $b000
|
||||
IN_4 = $c000
|
||||
|
||||
* = $0800
|
||||
jsr region1
|
||||
jsr region2
|
||||
jsr THREE_K
|
||||
jsr region4 ;operand label set manually
|
||||
lda L9005
|
||||
lda LA008
|
||||
lda IN_3+11
|
||||
lda IN_4+14
|
||||
self .byte $ad,$ea
|
||||
L081A nop
|
||||
jsr altbnk1
|
||||
jsr altbnk2
|
||||
jmp done
|
||||
|
||||
altbnk1 bit $ffc0
|
||||
lda self+1
|
||||
bne L081A
|
||||
rts
|
||||
|
||||
.logical *+$0000
|
||||
altbnk2 bit $ffc0
|
||||
lda $0819
|
||||
bne $081a
|
||||
ldx $081b
|
||||
rts
|
||||
|
||||
.here
|
||||
done nop
|
||||
rts
|
||||
|
||||
.fill 197,$00
|
||||
|
||||
.logical $1000
|
||||
region1x lda region1x
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
|
||||
.fill 202,$00
|
||||
.here
|
||||
|
||||
.logical $1000
|
||||
region1 lda region1
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
_copy lda inner1_pre,y
|
||||
sta inner1,y
|
||||
dey
|
||||
bpl _copy
|
||||
bit $101d
|
||||
jsr inner1
|
||||
jmp finish1
|
||||
|
||||
inner1_pre
|
||||
.logical $9000
|
||||
inner1 ldx inner1
|
||||
ldy #$aa
|
||||
L9005 ldy finish1
|
||||
ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.here
|
||||
finish1 ldy finish1
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.fill 184,$00
|
||||
.here
|
||||
|
||||
.logical $2000
|
||||
region2 lda region2
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
_copy lda inner2_pre,y
|
||||
sta inner2,y
|
||||
dey
|
||||
bpl _copy
|
||||
bit $201d
|
||||
jsr inner2
|
||||
jmp finish2
|
||||
|
||||
inner2_pre
|
||||
.logical $a000
|
||||
inner2 ldx inner2
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
LA008 ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.here
|
||||
finish2 ldy finish2
|
||||
ldx $1000
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda IN_1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.fill 184,$00
|
||||
.here
|
||||
|
||||
.logical $3000
|
||||
region3 lda region3
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
_copy lda inner3_pre,y
|
||||
sta inner3,y
|
||||
dey
|
||||
bpl _copy
|
||||
bit $301d
|
||||
jsr inner3
|
||||
jmp finish3
|
||||
|
||||
inner3_pre
|
||||
.logical $b000
|
||||
inner3 ldx inner3
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.here
|
||||
finish3 ldy finish3
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.fill 184,$00
|
||||
.here
|
||||
|
||||
.logical $4000
|
||||
region4 lda region4
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
_copy lda inner4_pre,y
|
||||
sta inner4,y
|
||||
dey
|
||||
bpl _copy
|
||||
bit $401d
|
||||
jsr inner4
|
||||
jmp finish4
|
||||
|
||||
inner4_pre
|
||||
.logical $c000
|
||||
inner4 ldx inner4
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
ldy $202b
|
||||
ldy $302b
|
||||
X_checkit ldy finish4
|
||||
rts
|
||||
|
||||
.here
|
||||
finish4 ldy finish4
|
||||
ldx $1000
|
||||
ldx $2000
|
||||
ldx THREE_K
|
||||
ldx region4
|
||||
lda IN_1
|
||||
lda IN_2
|
||||
lda IN_3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.fill 184,$00
|
||||
.here
|
||||
.logical $0000
|
||||
.byte $ff
|
||||
.here
|
255
SourceGen/SGTestData/Expected/20290-region-isolation_acme.S
Normal file
255
SourceGen/SGTestData/Expected/20290-region-isolation_acme.S
Normal file
|
@ -0,0 +1,255 @@
|
|||
!cpu 6502
|
||||
THREE_K = $3000 ;project symbol test
|
||||
IN_1 = $9000
|
||||
IN_2 = $a000
|
||||
IN_3 = $b000
|
||||
IN_4 = $c000
|
||||
|
||||
* = $0800
|
||||
jsr region1
|
||||
jsr region2
|
||||
jsr THREE_K
|
||||
jsr region4 ;operand label set manually
|
||||
lda L9005
|
||||
lda LA008
|
||||
lda IN_3+11
|
||||
lda IN_4+14
|
||||
self !byte $ad,$ea
|
||||
L081A nop
|
||||
jsr altbnk1
|
||||
jsr altbnk2
|
||||
jmp done
|
||||
|
||||
altbnk1 bit $ffc0
|
||||
lda self+1
|
||||
bne L081A
|
||||
rts
|
||||
|
||||
!pseudopc *+$0000 {
|
||||
altbnk2 bit $ffc0
|
||||
lda $0819
|
||||
bne $081a
|
||||
ldx $081b
|
||||
rts
|
||||
|
||||
}
|
||||
done nop
|
||||
rts
|
||||
|
||||
!fill 197,$00
|
||||
|
||||
!pseudopc $1000 {
|
||||
region1x lda region1x
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
|
||||
!fill 202,$00
|
||||
}
|
||||
|
||||
!pseudopc $1000 {
|
||||
region1 lda region1
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy lda inner1_pre,y
|
||||
sta inner1,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $101d
|
||||
jsr inner1
|
||||
jmp finish1
|
||||
|
||||
inner1_pre
|
||||
!pseudopc $9000 {
|
||||
inner1 ldx inner1
|
||||
ldy #$aa
|
||||
L9005 ldy finish1
|
||||
ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
}
|
||||
finish1 ldy finish1
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
!fill 184,$00
|
||||
}
|
||||
|
||||
!pseudopc $2000 {
|
||||
region2 lda region2
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy lda inner2_pre,y
|
||||
sta inner2,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $201d
|
||||
jsr inner2
|
||||
jmp finish2
|
||||
|
||||
inner2_pre
|
||||
!pseudopc $a000 {
|
||||
inner2 ldx inner2
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
LA008 ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
}
|
||||
finish2 ldy finish2
|
||||
ldx $1000
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda IN_1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
!fill 184,$00
|
||||
}
|
||||
|
||||
!pseudopc $3000 {
|
||||
region3 lda region3
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy lda inner3_pre,y
|
||||
sta inner3,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $301d
|
||||
jsr inner3
|
||||
jmp finish3
|
||||
|
||||
inner3_pre
|
||||
!pseudopc $b000 {
|
||||
inner3 ldx inner3
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
}
|
||||
finish3 ldy finish3
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
!fill 184,$00
|
||||
}
|
||||
|
||||
!pseudopc $4000 {
|
||||
region4 lda region4
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy lda inner4_pre,y
|
||||
sta inner4,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $401d
|
||||
jsr inner4
|
||||
jmp finish4
|
||||
|
||||
inner4_pre
|
||||
!pseudopc $c000 {
|
||||
inner4 ldx inner4
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
ldy $202b
|
||||
ldy $302b
|
||||
_checkit ldy finish4
|
||||
rts
|
||||
|
||||
}
|
||||
finish4 ldy finish4
|
||||
ldx $1000
|
||||
ldx $2000
|
||||
ldx THREE_K
|
||||
ldx region4
|
||||
lda IN_1
|
||||
lda IN_2
|
||||
lda IN_3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
!fill 184,$00
|
||||
}
|
||||
!pseudopc $0000 {
|
||||
!byte $ff
|
||||
}
|
249
SourceGen/SGTestData/Expected/20290-region-isolation_cc65.S
Normal file
249
SourceGen/SGTestData/Expected/20290-region-isolation_cc65.S
Normal file
|
@ -0,0 +1,249 @@
|
|||
.setcpu "6502"
|
||||
THREE_K = $3000 ;project symbol test
|
||||
IN_1 = $9000
|
||||
IN_2 = $a000
|
||||
IN_3 = $b000
|
||||
IN_4 = $c000
|
||||
|
||||
.org $0800
|
||||
jsr region1
|
||||
jsr region2
|
||||
jsr THREE_K
|
||||
jsr region4 ;operand label set manually
|
||||
lda L9005
|
||||
lda LA008
|
||||
lda IN_3+11
|
||||
lda IN_4+14
|
||||
self: .byte $ad,$ea
|
||||
L081A: nop
|
||||
jsr altbnk1
|
||||
jsr altbnk2
|
||||
jmp done
|
||||
|
||||
altbnk1: bit $ffc0
|
||||
lda self+1
|
||||
bne L081A
|
||||
rts
|
||||
|
||||
.org *+$0000
|
||||
altbnk2: bit $ffc0
|
||||
lda $0819
|
||||
bne $081a
|
||||
ldx $081b
|
||||
rts
|
||||
|
||||
.org $0839
|
||||
done: nop
|
||||
rts
|
||||
|
||||
.res 197,$00
|
||||
|
||||
.org $1000
|
||||
region1x: lda region1x
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
|
||||
.res 202,$00
|
||||
|
||||
.org $1000
|
||||
region1: lda region1
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy: lda inner1_pre,y
|
||||
sta inner1,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $101d
|
||||
jsr inner1
|
||||
jmp finish1
|
||||
|
||||
inner1_pre:
|
||||
.org $9000
|
||||
inner1: ldx inner1
|
||||
ldy #$aa
|
||||
L9005: ldy finish1
|
||||
ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.org $102b
|
||||
finish1: ldy finish1
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.res 184,$00
|
||||
|
||||
.org $2000
|
||||
region2: lda region2
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy: lda inner2_pre,y
|
||||
sta inner2,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $201d
|
||||
jsr inner2
|
||||
jmp finish2
|
||||
|
||||
inner2_pre:
|
||||
.org $a000
|
||||
inner2: ldx inner2
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
LA008: ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.org $202b
|
||||
finish2: ldy finish2
|
||||
ldx $1000
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda IN_1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.res 184,$00
|
||||
|
||||
.org $3000
|
||||
region3: lda region3
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy: lda inner3_pre,y
|
||||
sta inner3,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $301d
|
||||
jsr inner3
|
||||
jmp finish3
|
||||
|
||||
inner3_pre:
|
||||
.org $b000
|
||||
inner3: ldx inner3
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
.org $302b
|
||||
finish3: ldy finish3
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
.res 184,$00
|
||||
|
||||
.org $4000
|
||||
region4: lda region4
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
@copy: lda inner4_pre,y
|
||||
sta inner4,y
|
||||
dey
|
||||
bpl @copy
|
||||
bit $401d
|
||||
jsr inner4
|
||||
jmp finish4
|
||||
|
||||
inner4_pre:
|
||||
.org $c000
|
||||
inner4: ldx inner4
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
ldy $202b
|
||||
ldy $302b
|
||||
_checkit: ldy finish4
|
||||
rts
|
||||
|
||||
.org $402b
|
||||
finish4: ldy finish4
|
||||
ldx $1000
|
||||
ldx $2000
|
||||
ldx THREE_K
|
||||
ldx region4
|
||||
lda IN_1
|
||||
lda IN_2
|
||||
lda IN_3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.res 184,$00
|
||||
.org $0000
|
||||
.byte $ff
|
|
@ -0,0 +1,9 @@
|
|||
# 6502bench SourceGen generated linker script for 20290-region-isolation
|
||||
MEMORY {
|
||||
MAIN: file=%O, start=%S, size=65536;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load=MAIN, type=rw;
|
||||
}
|
||||
FEATURES {}
|
||||
SYMBOLS {}
|
248
SourceGen/SGTestData/Expected/20290-region-isolation_merlin32.S
Normal file
248
SourceGen/SGTestData/Expected/20290-region-isolation_merlin32.S
Normal file
|
@ -0,0 +1,248 @@
|
|||
THREE_K equ $3000 ;project symbol test
|
||||
IN_1 equ $9000
|
||||
IN_2 equ $a000
|
||||
IN_3 equ $b000
|
||||
IN_4 equ $c000
|
||||
|
||||
org $0800
|
||||
jsr region1
|
||||
jsr region2
|
||||
jsr THREE_K
|
||||
jsr region4 ;operand label set manually
|
||||
lda L9005
|
||||
lda LA008
|
||||
lda IN_3+11
|
||||
lda IN_4+14
|
||||
self dfb $ad,$ea
|
||||
L081A nop
|
||||
jsr altbnk1
|
||||
jsr altbnk2
|
||||
jmp done
|
||||
|
||||
altbnk1 bit $ffc0
|
||||
lda self+1
|
||||
bne L081A
|
||||
rts
|
||||
|
||||
org *+$0000
|
||||
altbnk2 bit $ffc0
|
||||
lda $0819
|
||||
bne $081a
|
||||
ldx $081b
|
||||
rts
|
||||
|
||||
org $0839
|
||||
done nop
|
||||
rts
|
||||
|
||||
ds 197
|
||||
|
||||
org $1000
|
||||
region1x lda region1x
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
|
||||
ds 202
|
||||
|
||||
org $1000
|
||||
region1 lda region1
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
:copy lda inner1_pre,y
|
||||
sta inner1,y
|
||||
dey
|
||||
bpl :copy
|
||||
bit $101d
|
||||
jsr inner1
|
||||
jmp finish1
|
||||
|
||||
inner1_pre
|
||||
org $9000
|
||||
inner1 ldx inner1
|
||||
ldy #$aa
|
||||
L9005 ldy finish1
|
||||
ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
org $102b
|
||||
finish1 ldy finish1
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
ds 184
|
||||
|
||||
org $2000
|
||||
region2 lda region2
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
:copy lda inner2_pre,y
|
||||
sta inner2,y
|
||||
dey
|
||||
bpl :copy
|
||||
bit $201d
|
||||
jsr inner2
|
||||
jmp finish2
|
||||
|
||||
inner2_pre
|
||||
org $a000
|
||||
inner2 ldx inner2
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
LA008 ldy finish2
|
||||
ldy $302b
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
org $202b
|
||||
finish2 ldy finish2
|
||||
ldx $1000
|
||||
ldx region2
|
||||
ldx THREE_K
|
||||
ldx $4000
|
||||
lda IN_1
|
||||
lda inner2
|
||||
lda IN_3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
ds 184
|
||||
|
||||
org $3000
|
||||
region3 lda region3
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
:copy lda inner3_pre,y
|
||||
sta inner3,y
|
||||
dey
|
||||
bpl :copy
|
||||
bit $301d
|
||||
jsr inner3
|
||||
jmp finish3
|
||||
|
||||
inner3_pre
|
||||
org $b000
|
||||
inner3 ldx inner3
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
ldy $402b
|
||||
rts
|
||||
|
||||
org $302b
|
||||
finish3 ldy finish3
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx $4000
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda IN_4
|
||||
pla
|
||||
rts
|
||||
|
||||
ds 184
|
||||
|
||||
org $4000
|
||||
region4 lda region4
|
||||
pha
|
||||
ldy #$11
|
||||
nop
|
||||
:copy lda inner4_pre,y
|
||||
sta inner4,y
|
||||
dey
|
||||
bpl :copy
|
||||
bit $401d
|
||||
jsr inner4
|
||||
jmp finish4
|
||||
|
||||
inner4_pre
|
||||
org $c000
|
||||
inner4 ldx inner4
|
||||
ldy #$aa
|
||||
ldy $102b
|
||||
ldy $202b
|
||||
ldy $302b
|
||||
_checkit ldy finish4
|
||||
rts
|
||||
|
||||
org $402b
|
||||
finish4 ldy finish4
|
||||
ldx $1000
|
||||
ldx $2000
|
||||
ldx THREE_K
|
||||
ldx region4
|
||||
lda IN_1
|
||||
lda IN_2
|
||||
lda IN_3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
ds 184
|
||||
org $0000
|
||||
dfb $ff
|
17
SourceGen/SGTestData/Expected/20300-binary-include_64tass.S
Normal file
17
SourceGen/SGTestData/Expected/20300-binary-include_64tass.S
Normal file
|
@ -0,0 +1,17 @@
|
|||
.cpu "6502"
|
||||
* = $1000
|
||||
L1000 ldy #$28
|
||||
lda _L1017,y
|
||||
sta $2000,y
|
||||
dey
|
||||
bpl L1000
|
||||
lda _L103F
|
||||
lda _L103F+1
|
||||
lda done-1
|
||||
jmp done
|
||||
|
||||
_L1017 .binary "20300-1.bin"
|
||||
_L103F .binary "20300sub/20300-2.bin"
|
||||
|
||||
done rts
|
||||
|
17
SourceGen/SGTestData/Expected/20300-binary-include_acme.S
Normal file
17
SourceGen/SGTestData/Expected/20300-binary-include_acme.S
Normal file
|
@ -0,0 +1,17 @@
|
|||
!cpu 6502
|
||||
* = $1000
|
||||
L1000 ldy #$28
|
||||
lda @L1017,y
|
||||
sta $2000,y
|
||||
dey
|
||||
bpl L1000
|
||||
lda @L103F
|
||||
lda @L103F+1
|
||||
lda done-1
|
||||
jmp done
|
||||
|
||||
@L1017 !binary "20300-1.bin"
|
||||
@L103F !binary "20300sub/20300-2.bin"
|
||||
|
||||
done rts
|
||||
|
17
SourceGen/SGTestData/Expected/20300-binary-include_cc65.S
Normal file
17
SourceGen/SGTestData/Expected/20300-binary-include_cc65.S
Normal file
|
@ -0,0 +1,17 @@
|
|||
.setcpu "6502"
|
||||
.org $1000
|
||||
L1000: ldy #$28
|
||||
lda @L1017,y
|
||||
sta $2000,y
|
||||
dey
|
||||
bpl L1000
|
||||
lda @L103F
|
||||
lda @L103F+1
|
||||
lda done-1
|
||||
jmp done
|
||||
|
||||
@L1017: .incbin "20300-1.bin"
|
||||
@L103F: .incbin "20300sub/20300-2.bin"
|
||||
|
||||
done: rts
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# 6502bench SourceGen generated linker script for 20300-binary-include
|
||||
MEMORY {
|
||||
MAIN: file=%O, start=%S, size=65536;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load=MAIN, type=rw;
|
||||
}
|
||||
FEATURES {}
|
||||
SYMBOLS {}
|
|
@ -0,0 +1,16 @@
|
|||
org $1000
|
||||
L1000 ldy #$28
|
||||
lda :L1017,y
|
||||
sta $2000,y
|
||||
dey
|
||||
bpl L1000
|
||||
lda :L103F
|
||||
lda :L103F+1
|
||||
lda done-1
|
||||
jmp done
|
||||
|
||||
:L1017 putbin 20300-1.bin
|
||||
:L103F putbin 20300sub/20300-2.bin
|
||||
|
||||
done rts
|
||||
|
|
@ -34,17 +34,19 @@ be opened as the project file.
|
|||
### Overriding Settings ###
|
||||
|
||||
All tests are run with a fixed set of app settings, so that the tests look
|
||||
the same regardless of how the assemblers are configured. For example,
|
||||
upper-case conversion is disabled, and cycle counts are not shown.
|
||||
the same regardless of how the assemblers are configured in the app settings
|
||||
file. For example, upper-case conversion is disabled, and cycle counts are
|
||||
not shown.
|
||||
|
||||
Sometimes a test will want to exercise one of these settings, so we need
|
||||
a way to tell the test harness to override the default. We do this by
|
||||
creating project symbols.
|
||||
creating project symbols:
|
||||
|
||||
| Name | Value | Description
|
||||
| ---------------------- | ----- | -------------------------------------------|
|
||||
| __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line |
|
||||
| __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments |
|
||||
| Name | Value | Description
|
||||
| -------------------------- | ----- | -----------------------------------------|
|
||||
| __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line |
|
||||
| __ENABLE_ALL_LABEL_NEWLINE | any | Puts all labels on their own line |
|
||||
| __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments |
|
||||
|
||||
### Execution ###
|
||||
|
||||
|
@ -74,7 +76,7 @@ the "retain output" box in the test harness, the directory and its contents
|
|||
will remain. This allows you to examine the outputs when investigating
|
||||
failures.
|
||||
|
||||
As a safety measure, the directory will NOT be removed if it contains files
|
||||
As a safety measure, a directory will NOT be removed if it contains files
|
||||
that the test harness doesn't recognize.
|
||||
|
||||
### Updating Tests ###
|
||||
|
@ -88,6 +90,7 @@ If you want to add or update a test, follow these steps:
|
|||
into the Expected directory, replacing any existing copies.
|
||||
4. Run the test harness. This should now report success, and will
|
||||
remove the tmpNNNNN directory.
|
||||
5. Run "git diff" to verify that the changes match your expectations.
|
||||
|
||||
Be sure to have the version of the cross-assembler identified at the top
|
||||
of this document configured.
|
||||
|
@ -115,4 +118,3 @@ for a full explanation.
|
|||
|
||||
Some test projects and data files for exercising the visualization generators.
|
||||
Not part of a formal test; load the projects and eyeball the results.
|
||||
|
||||
|
|
32
SourceGen/SGTestData/Source/20280-label-placement.S
Normal file
32
SourceGen/SGTestData/Source/20280-label-placement.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
; Copyright 2024 faddenSoft. All Rights Reserved.
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; The symbol __ENABLE_ALL_LABEL_NEWLINE must be defined in the project
|
||||
; symbols, so that labels are placed on their own lines whenever possible.
|
||||
;
|
||||
; Assembler: Merlin 32
|
||||
|
||||
org $1000
|
||||
shortnm equ $4000
|
||||
SomewhatLongName equ $4001
|
||||
|
||||
lda shortnm
|
||||
ldx SomewhatLongName
|
||||
clc
|
||||
bcc BranchTargetLongName
|
||||
data dfb $cc
|
||||
|
||||
]ptr equ $00
|
||||
]PointerWithLongName equ $02
|
||||
|
||||
BranchTargetLongName
|
||||
sta ]ptr
|
||||
stx ]PointerWithLongName
|
||||
ldy data
|
||||
lsr A
|
||||
bcc shortb
|
||||
shortb nop
|
||||
|
||||
jmp done
|
||||
|
||||
done rts
|
259
SourceGen/SGTestData/Source/20290-region-isolation.S
Normal file
259
SourceGen/SGTestData/Source/20290-region-isolation.S
Normal file
|
@ -0,0 +1,259 @@
|
|||
; Copyright 2024 faddenSoft. All Rights Reserved.
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Assembler: 64tass
|
||||
; % tass64 --ascii --case-sensitive --nostart 20290-region-isolation.S
|
||||
;
|
||||
; This is pretending to be a multi-bank ROM, with 256 bytes per bank.
|
||||
|
||||
.cpu "6502"
|
||||
|
||||
;
|
||||
; Initial region. This should end before region1, rather than span
|
||||
; all sub-regions, so that we're exercising top-level regions for
|
||||
; regions 1-4.
|
||||
;
|
||||
* = $0800
|
||||
BANK = $ffc0
|
||||
; EDIT: create project symbol THREE_K for $3000
|
||||
jsr region1
|
||||
jsr region2
|
||||
jsr region3
|
||||
jsr region4
|
||||
|
||||
; EDIT: create project symbols for $8000/9000/a000/b000, len=256
|
||||
; These should resolve to the user labels (for 1/2) or the project
|
||||
; symbols (for 3/4). We use an offset from the base address to ensure
|
||||
; that the range is being taken into account.
|
||||
lda inner1a
|
||||
lda inner2a
|
||||
lda inner3a
|
||||
lda inner4a
|
||||
|
||||
; Local reference, can use "do not follow" to avoid mid-instruction branch.
|
||||
self lda $eaea
|
||||
|
||||
call jsr altbnk1
|
||||
jsr altbnk2
|
||||
|
||||
jmp done
|
||||
|
||||
; These pretend to be code that switches the ROM bank, so the code
|
||||
; after the BIT instruction is actually in a different ROM, and the
|
||||
; BNE goes to something else.
|
||||
|
||||
; EDIT: mark individual BNE as "do not follow"
|
||||
altbnk1 bit BANK ;e.g. trigger a ROM bank switch
|
||||
lda self+1
|
||||
bne self+2
|
||||
rts
|
||||
|
||||
; EDIT: put this in a separate region, mark "disallow outbound"
|
||||
altbnk2 bit BANK
|
||||
lda self+1
|
||||
bne self+2
|
||||
ldx call ;EDIT: set symbol explicitly, should work
|
||||
rts
|
||||
|
||||
done nop
|
||||
rts
|
||||
|
||||
.align 256
|
||||
|
||||
;
|
||||
; region 1x: fully closed
|
||||
;
|
||||
; This overlaps with region 1. By closing it we should prevent any
|
||||
; of the external references from resolving here.
|
||||
;
|
||||
.logical $1000
|
||||
region1x lda region1x
|
||||
.fill 50,$ea
|
||||
rts
|
||||
|
||||
.align 256
|
||||
.endlogical
|
||||
|
||||
;
|
||||
; region 1: fully open
|
||||
;
|
||||
.logical $1000 ;*
|
||||
region1 lda region1 ;*
|
||||
pha
|
||||
|
||||
ldy #inner1_end-inner1-1 ;*
|
||||
nop
|
||||
_copy lda inner1_pre,y ;*
|
||||
sta inner1,y ;*
|
||||
dey
|
||||
bpl _copy
|
||||
bit inner1_pre+4 ;* should be an unresolved hole
|
||||
jsr inner1 ;*
|
||||
jmp finish1 ;*
|
||||
|
||||
; relocated inner chunk
|
||||
inner1_pre ;*
|
||||
.logical region1+$8000 ;*
|
||||
inner1 ldx inner1 ;*
|
||||
ldy #$aa
|
||||
inner1a ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
ldy finish4
|
||||
rts
|
||||
inner1_end ;*
|
||||
.endlogical
|
||||
|
||||
finish1 ldy finish1 ;*
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx region4
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.align 256 ;pad chunk to 256 bytes
|
||||
.endlogical
|
||||
|
||||
;
|
||||
; region 2: disallow outbound
|
||||
;
|
||||
.logical $2000
|
||||
region2 lda region2
|
||||
pha
|
||||
|
||||
ldy #inner2_end-inner2-1 ;*
|
||||
nop
|
||||
_copy lda inner2_pre,y ;*
|
||||
sta inner2,y ;*
|
||||
dey
|
||||
bpl _copy
|
||||
bit inner2_pre+4 ;* should be an unresolved hole
|
||||
jsr inner2 ;*
|
||||
jmp finish2 ;*
|
||||
|
||||
; relocated inner chunk
|
||||
inner2_pre ;*
|
||||
.logical region2+$8000 ;*
|
||||
inner2 ldx inner2 ;*
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
inner2a ldy finish2
|
||||
ldy finish3
|
||||
ldy finish4
|
||||
rts
|
||||
inner2_end ;*
|
||||
.endlogical
|
||||
|
||||
finish2 ldy finish2 ;*
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx region4
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.align 256 ;pad chunk to 256 bytes
|
||||
.endlogical
|
||||
|
||||
;
|
||||
; region 3: disallow inbound
|
||||
;
|
||||
.logical $3000
|
||||
region3 lda region3
|
||||
pha
|
||||
|
||||
ldy #inner3_end-inner3-1 ;*
|
||||
nop
|
||||
_copy lda inner3_pre,y ;*
|
||||
sta inner3,y ;*
|
||||
dey
|
||||
bpl _copy
|
||||
bit inner3_pre+4 ;* should be an unresolved hole
|
||||
jsr inner3 ;*
|
||||
jmp finish3 ;*
|
||||
|
||||
; relocated inner chunk
|
||||
inner3_pre ;*
|
||||
.logical region3+$8000 ;*
|
||||
inner3 ldx inner3 ;*
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
inner3a ldy finish3
|
||||
ldy finish4
|
||||
rts
|
||||
inner3_end ;*
|
||||
.endlogical
|
||||
|
||||
finish3 ldy finish3 ;*
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx region4
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.align 256 ;pad chunk to 256 bytes
|
||||
.endlogical
|
||||
|
||||
;
|
||||
; region 4: disallow both
|
||||
;
|
||||
.logical $4000
|
||||
region4 lda region4
|
||||
pha
|
||||
|
||||
ldy #inner4_end-inner4-1 ;*
|
||||
nop
|
||||
_copy lda inner4_pre,y ;*
|
||||
sta inner4,y ;*
|
||||
dey
|
||||
bpl _copy
|
||||
bit inner4_pre+4 ;* should be an unresolved hole
|
||||
jsr inner4 ;*
|
||||
jmp finish4 ;*
|
||||
|
||||
; relocated inner chunk
|
||||
inner4_pre ;*
|
||||
.logical region4+$8000 ;*
|
||||
inner4 ldx inner4 ;*
|
||||
ldy #$aa
|
||||
ldy finish1
|
||||
ldy finish2
|
||||
ldy finish3
|
||||
inner4a ldy finish4
|
||||
rts
|
||||
inner4_end ;*
|
||||
.endlogical
|
||||
|
||||
finish4 ldy finish4 ;*
|
||||
ldx region1
|
||||
ldx region2
|
||||
ldx region3
|
||||
ldx region4
|
||||
lda inner1
|
||||
lda inner2
|
||||
lda inner3
|
||||
lda inner4
|
||||
pla
|
||||
rts
|
||||
|
||||
.align 256 ;pad chunk to 256 bytes
|
||||
.endlogical
|
||||
|
||||
; Not sure how to force asm to output alignment padding at end of file.
|
||||
; Leave this marked as non-addressable.
|
||||
.byte $ff
|
31
SourceGen/SGTestData/Source/20300-binary-include.S
Normal file
31
SourceGen/SGTestData/Source/20300-binary-include.S
Normal file
|
@ -0,0 +1,31 @@
|
|||
; Copyright 2024 faddenSoft. All Rights Reserved.
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Assembler: Merlin 32
|
||||
;
|
||||
|
||||
org $1000
|
||||
start ldy #40
|
||||
lda blob1,Y
|
||||
sta $2000,Y
|
||||
dey
|
||||
bpl start
|
||||
|
||||
lda blob2
|
||||
lda blob2+1
|
||||
lda blob2+31
|
||||
|
||||
jmp done
|
||||
|
||||
; EDIT: set blob as binary include, current dir
|
||||
blob1
|
||||
asc ' !"#$%&',27,'()'
|
||||
asc '0123456789'
|
||||
asc 'ABCDEFGHIJ'
|
||||
asc 'PQRSTUVWXY'
|
||||
|
||||
; EDIT: set blob as binary include, file in subdir
|
||||
blob2
|
||||
ds 32,$ff
|
||||
|
||||
done rts
|
|
@ -24,6 +24,7 @@
|
|||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
@ -33,6 +34,7 @@
|
|||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Res\SourceGenIcon.ico</ApplicationIcon>
|
||||
|
@ -72,6 +74,7 @@
|
|||
<Compile Include="AsmGen\AssemblerConfig.cs" />
|
||||
<Compile Include="AsmGen\AssemblerInfo.cs" />
|
||||
<Compile Include="AsmGen\AssemblerVersion.cs" />
|
||||
<Compile Include="AsmGen\BinaryInclude.cs" />
|
||||
<Compile Include="AsmGen\GenCommon.cs" />
|
||||
<Compile Include="AsmGen\IAssembler.cs" />
|
||||
<Compile Include="AsmGen\IGenerator.cs" />
|
||||
|
@ -79,6 +82,7 @@
|
|||
<Compile Include="DailyTips.cs" />
|
||||
<Compile Include="Exporter.cs" />
|
||||
<Compile Include="FormattedOperandCache.cs" />
|
||||
<Compile Include="LabelFileGenerator.cs" />
|
||||
<Compile Include="LocalVariableLookup.cs" />
|
||||
<Compile Include="MessageList.cs" />
|
||||
<Compile Include="Sgec.cs" />
|
||||
|
@ -188,6 +192,9 @@
|
|||
<Compile Include="WpfGui\FormatAddressTable.xaml.cs">
|
||||
<DependentUpon>FormatAddressTable.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\GenerateLabels.xaml.cs">
|
||||
<DependentUpon>GenerateLabels.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\GotoBox.xaml.cs">
|
||||
<DependentUpon>GotoBox.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -413,6 +420,10 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\GenerateLabels.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\GotoBox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
@ -491,9 +502,6 @@
|
|||
<ItemGroup>
|
||||
<Resource Include="Res\SourceGenIcon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Res\AboutImage.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Res\RedX.png" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace SourceGen {
|
|||
/// </summary>
|
||||
public class Symbol {
|
||||
public const char UNCERTAIN_CHAR = '?';
|
||||
public const char UNIQUE_TAG_CHAR = '\u00a7'; // SECTION SIGN
|
||||
private const char NO_ANNO_CHAR = '\ufffd'; // REPLACEMENT CHARACTER '<27>'
|
||||
private const char UNIQUE_TAG_CHAR = '\u00a7'; // SECTION SIGN
|
||||
private const int NON_UNIQUE_LEN = 7; // NON_UNIQUE_CHAR + 6 hex digits
|
||||
|
||||
/// <summary>
|
||||
|
@ -84,6 +84,7 @@ namespace SourceGen {
|
|||
/// <remarks>
|
||||
/// Non-unique labels have extra stuff at the end to make them unique. That is
|
||||
/// included here, so that the Label field is still viable as a unique identifier.
|
||||
/// Use <see cref="LabelWithoutTag"/> to get just the label.
|
||||
/// </remarks>
|
||||
public string Label { get; private set; }
|
||||
|
||||
|
|
|
@ -523,6 +523,7 @@ namespace SourceGen {
|
|||
/// variables.
|
||||
/// </summary>
|
||||
/// <param name="addr">Address to find.</param>
|
||||
/// <param name="effect">Memory effect type to match against.</param>
|
||||
/// <returns>First matching symbol found, or null if nothing matched.</returns>
|
||||
public Symbol FindNonVariableByAddress(int addr, OpDef.MemoryEffect effect) {
|
||||
bool tryRead, tryWrite;
|
||||
|
@ -540,6 +541,7 @@ namespace SourceGen {
|
|||
return null;
|
||||
}
|
||||
|
||||
// The mSymbolsBy{Read,Write}Address tables don't include local vars or constants.
|
||||
Symbol sym = null;
|
||||
if (tryRead) {
|
||||
mSymbolsByReadAddress.TryGetValue(addr, out sym);
|
||||
|
@ -549,11 +551,10 @@ namespace SourceGen {
|
|||
}
|
||||
|
||||
if (sym == null) {
|
||||
// Nothing matched, check the match groups.
|
||||
// Nothing matched, check the mask groups.
|
||||
foreach (KeyValuePair<DefSymbol.MultiAddressMask, MaskGroup> kvp in mMaskGroups) {
|
||||
DefSymbol.MultiAddressMask multiMask = kvp.Key;
|
||||
if ((addr & multiMask.CompareMask) == multiMask.CompareValue) {
|
||||
MaskGroup group = kvp.Value;
|
||||
DefSymbol defSym = kvp.Value.Find(addr, tryRead, tryWrite);
|
||||
if (defSym != null) {
|
||||
sym = defSym;
|
||||
|
@ -565,6 +566,53 @@ namespace SourceGen {
|
|||
return sym;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches the table for project/platform symbols with matching address values. Ignores
|
||||
/// constants and variables.
|
||||
/// </summary>
|
||||
/// <param name="addr">Address to find.</param>
|
||||
/// <param name="effect">Memory effect type to match against.</param>
|
||||
/// <returns>First matching symbol found, or null if nothing matched.</returns>
|
||||
public Symbol FindProjPlatPreByAddress(int addr, OpDef.MemoryEffect effect) {
|
||||
bool tryRead, tryWrite;
|
||||
if (effect == OpDef.MemoryEffect.Read) {
|
||||
tryRead = true;
|
||||
tryWrite = false;
|
||||
} else if (effect == OpDef.MemoryEffect.Write) {
|
||||
tryRead = false;
|
||||
tryWrite = true;
|
||||
} else if (effect == OpDef.MemoryEffect.ReadModifyWrite ||
|
||||
effect == OpDef.MemoryEffect.None) {
|
||||
tryRead = tryWrite = true;
|
||||
} else {
|
||||
Debug.Assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// We don't have a pair of tables for this, so just do a linear walk through
|
||||
// the symbol table. This is inefficient, but the current use case is very rare.
|
||||
foreach (KeyValuePair<string,Symbol> kvp in mSymbols) {
|
||||
if (!(kvp.Value is DefSymbol)) {
|
||||
continue;
|
||||
}
|
||||
DefSymbol defSym = (DefSymbol)kvp.Value;
|
||||
if (defSym.SymbolSource != Symbol.Source.Project &&
|
||||
defSym.SymbolSource != Symbol.Source.Platform &&
|
||||
defSym.SymbolSource != Symbol.Source.AddrPreLabel) {
|
||||
continue;
|
||||
}
|
||||
if (addr >= defSym.Value && addr < defSym.Value + defSym.DataDescriptor.Length) {
|
||||
if ((tryRead && (defSym.Direction & DefSymbol.DirectionFlags.Read) != 0) ||
|
||||
(tryWrite && (defSym.Direction & DefSymbol.DirectionFlags.Write) != 0))
|
||||
{
|
||||
return defSym;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do we need to check the mask groups?
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "SymbolTable: " + mSymbols.Count + " by label, " +
|
||||
mSymbolsByReadAddress.Count + " by addr(r), " +
|
||||
|
|
|
@ -309,6 +309,26 @@ namespace SourceGen.Tests {
|
|||
//continue;
|
||||
}
|
||||
|
||||
// Generate binary includes. These are not verified in the "expected source"
|
||||
// section because we'll do the necessary check in the binary diff.
|
||||
if (!BinaryInclude.PrepareList(genResults.BinaryIncludes, workDir,
|
||||
out string failMsg)) {
|
||||
ReportErrMsg("Failed processing binary includes: " + failMsg);
|
||||
ReportProgress("\r\n");
|
||||
didFail = true;
|
||||
} else {
|
||||
foreach (BinaryInclude.Excision exc in genResults.BinaryIncludes) {
|
||||
if (!BinaryInclude.GenerateOutputFile(exc, project.FileData,
|
||||
out string failMsg2)) {
|
||||
ReportErrMsg("Failed processing binary include at +" +
|
||||
exc.Offset.ToString("x6") + ": " + failMsg2);
|
||||
ReportProgress("\r\n");
|
||||
didFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assemble code.
|
||||
ReportProgress(" " + asmId.ToString() + " assemble...");
|
||||
IAssembler asm = AssemblerInfo.GetAssembler(asmId);
|
||||
|
@ -430,7 +450,8 @@ namespace SourceGen.Tests {
|
|||
|
||||
// Don't break lines with long labels. That way we can redefine "long"
|
||||
// without breaking our tests. (This is purely cosmetic.)
|
||||
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
|
||||
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.PreferSameLine);
|
||||
|
||||
// This could be on or off. Off seems less distracting.
|
||||
settings.SetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS, false);
|
||||
|
@ -455,17 +476,23 @@ namespace SourceGen.Tests {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies app setting overrides that were specified in the project settings.
|
||||
/// Applies app setting overrides that were specified in the project properties.
|
||||
/// </summary>
|
||||
private void ApplyProjectSettings(AppSettings settings, DisasmProject project) {
|
||||
// We could probably make this a more general mechanism, but that would strain
|
||||
// things a bit, since we need to know the settings name, bool/int/string, and
|
||||
// desired value. Easier to just have a set of named features.
|
||||
const string ENABLE_LABEL_NEWLINE = "__ENABLE_LABEL_NEWLINE";
|
||||
const string ENABLE_ALL_LABEL_NEWLINE = "__ENABLE_ALL_LABEL_NEWLINE";
|
||||
const string ENABLE_CYCLE_COUNTS = "__ENABLE_CYCLE_COUNTS";
|
||||
|
||||
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_LABEL_NEWLINE)) {
|
||||
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, true);
|
||||
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.SplitIfTooLong);
|
||||
}
|
||||
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_ALL_LABEL_NEWLINE)) {
|
||||
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
GenCommon.LabelPlacement.PreferSeparateLine);
|
||||
}
|
||||
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_CYCLE_COUNTS)) {
|
||||
settings.SetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS, true);
|
||||
|
@ -597,8 +624,8 @@ namespace SourceGen.Tests {
|
|||
/// Removes the contents of a temporary work directory. Only files that we believe
|
||||
/// to be products of the generator or assembler are removed.
|
||||
/// </summary>
|
||||
/// <param name="workDir"></param>
|
||||
/// <param name="testNum"></param>
|
||||
/// <param name="workDir">Full pathname of work directory.</param>
|
||||
/// <param name="testNum">Test number, used to evaluate files for removal.</param>
|
||||
private void ScrubWorkDirectory(string workDir, int testNum) {
|
||||
string checkString = testNum.ToString();
|
||||
if (checkString.Length != 5) {
|
||||
|
@ -606,6 +633,20 @@ namespace SourceGen.Tests {
|
|||
return;
|
||||
}
|
||||
|
||||
// Remove any subdirectories that match the pattern, e.g. for binary includes.
|
||||
foreach (string pathName in Directory.EnumerateDirectories(workDir)) {
|
||||
string fileName = Path.GetFileName(pathName);
|
||||
if (fileName.Contains(checkString)) {
|
||||
ScrubWorkDirectory(pathName, testNum);
|
||||
try {
|
||||
Directory.Delete(pathName);
|
||||
} catch (Exception ex) {
|
||||
ReportErrMsg("unable to remove dir '" + fileName + "': " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all matching files.
|
||||
foreach (string pathName in Directory.EnumerateFiles(workDir)) {
|
||||
bool doRemove = false;
|
||||
string fileName = Path.GetFileName(pathName);
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace SourceGen.Tests.WpfGui {
|
|||
/// Source generation test runner.
|
||||
/// </summary>
|
||||
public partial class GenTestRunner : Window, INotifyPropertyChanged {
|
||||
// Full set of results from last run.
|
||||
private List<GenTest.GenTestResults> mLastResults;
|
||||
|
||||
private BackgroundWorker mWorker;
|
||||
|
@ -208,7 +209,7 @@ namespace SourceGen.Tests.WpfGui {
|
|||
outputTextBox.Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
if (mLastResults == null && mLastResults.Count <= sel) {
|
||||
if (mLastResults == null || mLastResults.Count <= sel) {
|
||||
Debug.WriteLine("SelIndexChanged to " + sel + ", not available");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -610,7 +610,7 @@ namespace SourceGen.Tools.Omf {
|
|||
// Generate an ORG directive.
|
||||
//int origAddr = proj.AddrMap.OffsetToAddress(bufOffset);
|
||||
AddressMap.AddressMapEntry addrEnt = new AddressMap.AddressMapEntry(bufOffset,
|
||||
AddressMap.FLOATING_LEN, addr, string.Empty, false);
|
||||
AddressMap.FLOATING_LEN, addr);
|
||||
UndoableChange uc = UndoableChange.CreateAddressChange(null, addrEnt);
|
||||
cs.Add(uc);
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace SourceGen.Tools.Omf {
|
|||
}
|
||||
first = false;
|
||||
|
||||
Debug.Assert(seg.FileLength > 0);
|
||||
Debug.Assert(seg != null && seg.FileLength > 0);
|
||||
|
||||
SegmentList.Add(seg);
|
||||
offset += seg.FileLength;
|
||||
|
|
|
@ -35,8 +35,8 @@ limitations under the License.
|
|||
<system:String x:Key="str_OmfFileLibraryStr">a Library file</system:String>
|
||||
<system:String x:Key="str_OmfFileIndeterminateStr">a file of indeterminate type</system:String>
|
||||
|
||||
<system:String x:Key="str_OmfFileSummaryFmt">This is {0}, with {1} segment</system:String>
|
||||
<system:String x:Key="str_OmfFileSummaryPlFmt">This is {0}, with {1} segments</system:String>
|
||||
<system:String x:Key="str_OmfFileSummaryFmt">This is {0}, with {1} segment (double-click to examine):</system:String>
|
||||
<system:String x:Key="str_OmfFileSummaryPlFmt">This is {0}, with {1} segments (double-click to examine):</system:String>
|
||||
<system:String x:Key="str_OmfFileNot">This is not an Apple II OMF file</system:String>
|
||||
|
||||
<system:String x:Key="str_OmfLoaderFail">Unable to prepare data file for project.</system:String>
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace SourceGen.Tools {
|
|||
/// demand and retain the results indefinitely.
|
||||
/// </remarks>
|
||||
public class VirtualHexDump : IList, INotifyCollectionChanged, INotifyPropertyChanged {
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Data to display. We currently require that the entire file fit in memory,
|
||||
/// which is reasonable because we impose a 2^24 (16MB) limit.
|
||||
|
|
|
@ -75,8 +75,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
|
||||
public void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
// Restore chart mode setting.
|
||||
ChartMode mode = (ChartMode)AppSettings.Global.GetEnum(
|
||||
AppSettings.A2SC_MODE, typeof(ChartMode), (int)ChartMode.HiRes1_L);
|
||||
ChartMode mode = AppSettings.Global.GetEnum(AppSettings.A2SC_MODE, ChartMode.HiRes1_L);
|
||||
int index = 0;
|
||||
for (int i = 0; i < ChartModeItems.Length; i++) {
|
||||
if (ChartModeItems[i].Mode == mode) {
|
||||
|
@ -107,7 +106,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
return;
|
||||
}
|
||||
|
||||
AppSettings.Global.SetEnum(AppSettings.A2SC_MODE, typeof(ChartMode), (int)item.Mode);
|
||||
AppSettings.Global.SetEnum(AppSettings.A2SC_MODE, item.Mode);
|
||||
|
||||
string text;
|
||||
switch (item.Mode) {
|
||||
|
|
|
@ -55,8 +55,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
|
||||
public void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
// Restore chart mode setting.
|
||||
ChartMode mode = (ChartMode)AppSettings.Global.GetEnum(
|
||||
AppSettings.ASCCH_MODE, typeof(ChartMode), (int)ChartMode.Standard);
|
||||
ChartMode mode = AppSettings.Global.GetEnum(AppSettings.ASCCH_MODE, ChartMode.Standard);
|
||||
int index = 0;
|
||||
for (int i = 0; i < ChartModeItems.Length; i++) {
|
||||
if (ChartModeItems[i].Mode == mode) {
|
||||
|
@ -87,7 +86,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
return;
|
||||
}
|
||||
|
||||
AppSettings.Global.SetEnum(AppSettings.ASCCH_MODE, typeof(ChartMode), (int)item.Mode);
|
||||
AppSettings.Global.SetEnum(AppSettings.ASCCH_MODE, item.Mode);
|
||||
|
||||
//
|
||||
// Draw box contents.
|
||||
|
|
|
@ -42,7 +42,7 @@ limitations under the License.
|
|||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- DataGrid gives us Ctrl+A select-all and Ctrl+C text-copy built in. -->
|
||||
<!-- DataGrid gives us Ctrl+A (select-all) and Ctrl+C (text-copy) built in. -->
|
||||
<DataGrid Name="hexDumpData" Grid.Row="0"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding HexDumpLines}"
|
||||
|
@ -58,6 +58,8 @@ limitations under the License.
|
|||
ScrollViewer.CanContentScroll="True"
|
||||
VerticalScrollBarVisibility="Visible">
|
||||
<DataGrid.Columns>
|
||||
<!-- Unqualified {Binding} creates a Binding object with default values.
|
||||
This is how we reference the strings we get from the virtualized IList. -->
|
||||
<DataGridTextColumn Header="Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F Text"
|
||||
Width="491" Binding="{Binding}"/>
|
||||
</DataGrid.Columns>
|
||||
|
|
|
@ -111,8 +111,8 @@ namespace SourceGen.Tools.WpfGui {
|
|||
AsciiOnlyDump = AppSettings.Global.GetBool(AppSettings.HEXD_ASCII_ONLY, false);
|
||||
|
||||
// Restore conv mode setting.
|
||||
CharConvMode mode = (CharConvMode)AppSettings.Global.GetEnum(
|
||||
AppSettings.HEXD_CHAR_CONV, typeof(CharConvMode), (int)CharConvMode.Ascii);
|
||||
CharConvMode mode =
|
||||
AppSettings.Global.GetEnum(AppSettings.HEXD_CHAR_CONV, CharConvMode.Ascii);
|
||||
int index = 0;
|
||||
for (int i = 0; i < CharConvItems.Length; i++) {
|
||||
if (CharConvItems[i].Mode == mode) {
|
||||
|
@ -156,8 +156,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
|
||||
// Keep app settings up to date.
|
||||
AppSettings.Global.SetBool(AppSettings.HEXD_ASCII_ONLY, mAsciiOnlyDump);
|
||||
AppSettings.Global.SetEnum(AppSettings.HEXD_CHAR_CONV, typeof(CharConvMode),
|
||||
(int)item.Mode);
|
||||
AppSettings.Global.SetEnum(AppSettings.HEXD_CHAR_CONV, item.Mode);
|
||||
|
||||
mFormatter = new Formatter(config);
|
||||
HexDumpLines.Reformat(mFormatter);
|
||||
|
|
|
@ -112,8 +112,8 @@ namespace SourceGen.Tools.WpfGui {
|
|||
|
||||
public void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
// Restore chart settings.
|
||||
CpuDef.CpuType type = (CpuDef.CpuType)AppSettings.Global.GetEnum(
|
||||
AppSettings.INSTCH_MODE, typeof(CpuDef.CpuType), (int)CpuDef.CpuType.Cpu6502);
|
||||
CpuDef.CpuType type =
|
||||
AppSettings.Global.GetEnum(AppSettings.INSTCH_MODE, CpuDef.CpuType.Cpu6502);
|
||||
ShowUndocumented = AppSettings.Global.GetBool(AppSettings.INSTCH_SHOW_UNDOC, true);
|
||||
|
||||
int index = 0;
|
||||
|
@ -146,8 +146,7 @@ namespace SourceGen.Tools.WpfGui {
|
|||
}
|
||||
|
||||
// Push current choice to settings.
|
||||
AppSettings.Global.SetEnum(AppSettings.INSTCH_MODE, typeof(CpuDef.CpuType),
|
||||
(int)item.Type);
|
||||
AppSettings.Global.SetEnum(AppSettings.INSTCH_MODE, item.Type);
|
||||
AppSettings.Global.SetBool(AppSettings.INSTCH_SHOW_UNDOC, mShowUndocumented);
|
||||
|
||||
// Populate the items source.
|
||||
|
|
|
@ -79,13 +79,13 @@ namespace SourceGen {
|
|||
public bool IsVariable { get { return VarType != LocalVariableType.NotVar; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// Standard constructor.
|
||||
/// </summary>
|
||||
public WeakSymbolRef(string label, Part part) :
|
||||
this(label, part, LocalVariableType.NotVar) { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// Constructor for local variable table references.
|
||||
/// </summary>
|
||||
public WeakSymbolRef(string label, Part part, LocalVariableType varType) {
|
||||
Debug.Assert(label != null);
|
||||
|
|
|
@ -49,12 +49,13 @@ limitations under the License.
|
|||
BorderThickness="0" HorizontalAlignment="Left"
|
||||
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
|
||||
Click="WebSiteButton_Click"/>
|
||||
<TextBlock Text="Copyright 2022 faddenSoft" Margin="0,0,0,0"/>
|
||||
<TextBlock Text="Copyright 2024 faddenSoft" Margin="0,0,0,0"/>
|
||||
<TextBlock Text="Created by Andy McFadden"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="0,8,0,0">
|
||||
<TextBlock Text="{Binding OsPlatform, FallbackValue=OS: blah blah blah}"/>
|
||||
<TextBlock Text="{Binding RuntimeInfo, FallbackValue=RunTime: blah blah}"/>
|
||||
<TextBlock Text="Assertions and extended validation are enabled"
|
||||
Visibility="{Binding DebugMessageVisibility}"/>
|
||||
<TextBlock Text="Legal stuff:" Margin="0,8,0,0"/>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
|
@ -40,6 +41,17 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runtime information, for display.
|
||||
/// </summary>
|
||||
public string RuntimeInfo {
|
||||
get {
|
||||
return "Runtime: " + RuntimeInformation.FrameworkDescription + ", " +
|
||||
"OS-arch " + RuntimeInformation.OSArchitecture + ", proc-arch " +
|
||||
RuntimeInformation.ProcessArchitecture;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a message about assertions is visible.
|
||||
/// </summary>
|
||||
|
|
|
@ -187,6 +187,10 @@ limitations under the License.
|
|||
<StackPanel>
|
||||
<CheckBox Content="Use relative addressing"
|
||||
IsChecked="{Binding UseRelativeAddressing}"/>
|
||||
<CheckBox Content="Disallow inbound address resolution" Margin="0,8,0,0"
|
||||
IsChecked="{Binding DisallowInwardRes}"/>
|
||||
<CheckBox Content="Disallow outbound address resolution" Margin="0,4,0,0"
|
||||
IsChecked="{Binding DisallowOutwardRes}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,16,0,0">
|
||||
<TextBlock Text="Pre-label:"/>
|
||||
|
|
|
@ -162,6 +162,18 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
private bool mUseRelativeAddressing;
|
||||
|
||||
public bool DisallowInwardRes {
|
||||
get { return mDisallowInwardRes; }
|
||||
set { mDisallowInwardRes = value; OnPropertyChanged(); UpdateControls(); }
|
||||
}
|
||||
private bool mDisallowInwardRes;
|
||||
|
||||
public bool DisallowOutwardRes {
|
||||
get { return mDisallowOutwardRes; }
|
||||
set { mDisallowOutwardRes = value; OnPropertyChanged(); UpdateControls(); }
|
||||
}
|
||||
private bool mDisallowOutwardRes;
|
||||
|
||||
/// <summary>
|
||||
/// Pre-label input TextBox.
|
||||
/// </summary>
|
||||
|
@ -309,6 +321,8 @@ namespace SourceGen.WpfGui {
|
|||
AddressText = Asm65.Address.AddressToString(curRegion.Address, false);
|
||||
}
|
||||
PreLabelText = curRegion.PreLabel;
|
||||
DisallowInwardRes = curRegion.DisallowInward;
|
||||
DisallowOutwardRes = curRegion.DisallowOutward;
|
||||
UseRelativeAddressing = curRegion.IsRelative;
|
||||
|
||||
OperationStr = (string)FindResource("str_HdrEdit");
|
||||
|
@ -323,6 +337,7 @@ namespace SourceGen.WpfGui {
|
|||
// to fixed.
|
||||
mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
|
||||
curRegion.Length, curRegion.Address, curRegion.PreLabel,
|
||||
curRegion.DisallowInward, curRegion.DisallowOutward,
|
||||
curRegion.IsRelative);
|
||||
option1Summ = (string)FindResource("str_OptEditAsIsSummary");
|
||||
option1Msg = (string)FindResource("str_OptEditAsIs");
|
||||
|
@ -332,6 +347,7 @@ namespace SourceGen.WpfGui {
|
|||
option2Msg = (string)FindResource("str_OptEditAndFix");
|
||||
mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
|
||||
curRegion.ActualLength, curRegion.Address, curRegion.PreLabel,
|
||||
curRegion.DisallowInward, curRegion.DisallowOutward,
|
||||
curRegion.IsRelative);
|
||||
} else {
|
||||
option2Summ = string.Empty;
|
||||
|
@ -347,10 +363,10 @@ namespace SourceGen.WpfGui {
|
|||
// first action is disabled.
|
||||
mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
|
||||
selectionLen, curRegion.Address, curRegion.PreLabel,
|
||||
curRegion.IsRelative);
|
||||
curRegion.DisallowInward, curRegion.DisallowOutward, curRegion.IsRelative);
|
||||
mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
|
||||
curRegion.Length, curRegion.Address, curRegion.PreLabel,
|
||||
curRegion.IsRelative);
|
||||
curRegion.DisallowInward, curRegion.DisallowOutward, curRegion.IsRelative);
|
||||
|
||||
option1Summ = (string)FindResource("str_OptResizeSummary");
|
||||
string fmt = (string)FindResource("str_OptResize");
|
||||
|
@ -396,6 +412,8 @@ namespace SourceGen.WpfGui {
|
|||
AddressText = Asm65.Address.AddressToString(newEntry.Address, false);
|
||||
}
|
||||
PreLabelText = string.Empty;
|
||||
DisallowInwardRes = false;
|
||||
DisallowOutwardRes = false;
|
||||
UseRelativeAddressing = false;
|
||||
|
||||
OperationStr = (string)FindResource("str_HdrCreate");
|
||||
|
@ -417,7 +435,8 @@ namespace SourceGen.WpfGui {
|
|||
// a fixed region with the same start offset, but can't create a float there.
|
||||
if (ares1 == AddressMap.AddResult.Okay) {
|
||||
mResultEntry1 = new AddressMap.AddressMapEntry(newEntry.Offset,
|
||||
newRegion1.ActualLength, newEntry.Address, string.Empty, false);
|
||||
newRegion1.ActualLength, newEntry.Address,
|
||||
string.Empty, false, false, false);
|
||||
|
||||
option1Summ = (string)FindResource("str_CreateFixedSummary");
|
||||
string fmt = (string)FindResource("str_CreateFixed");
|
||||
|
@ -439,7 +458,8 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
if (ares2 == AddressMap.AddResult.Okay) {
|
||||
mResultEntry2 = new AddressMap.AddressMapEntry(newEntry.Offset,
|
||||
AddressMap.FLOATING_LEN, newEntry.Address, string.Empty, false);
|
||||
AddressMap.FLOATING_LEN, newEntry.Address,
|
||||
string.Empty, false, false, false);
|
||||
|
||||
option2Summ = (string)FindResource("str_CreateFloatingSummary");
|
||||
string fmt = (string)FindResource("str_CreateFloating");
|
||||
|
@ -615,7 +635,8 @@ namespace SourceGen.WpfGui {
|
|||
|
||||
// Combine base entry with pre-label string and relative addressing checkbox.
|
||||
ResultEntry = new AddressMap.AddressMapEntry(baseEntry.Offset,
|
||||
baseEntry.Length, addr, PreLabelText, UseRelativeAddressing);
|
||||
baseEntry.Length, addr, PreLabelText,
|
||||
DisallowInwardRes, DisallowOutwardRes, UseRelativeAddressing);
|
||||
Debug.WriteLine("Dialog result: " + ResultEntry);
|
||||
DialogResult = true;
|
||||
}
|
||||
|
|
|
@ -653,6 +653,12 @@ limitations under the License.
|
|||
VerticalAlignment="Center" Margin="{StaticResource TBS}"
|
||||
Text=".placeho" MaxLength="12"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
<TextBlock Grid.Column="4" Grid.Row="3" Text="Binary include:"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||
<TextBox Name="binaryIncludeTextBox" Grid.Column="5" Grid.Row="3"
|
||||
VerticalAlignment="Center" Margin="{StaticResource TBS}"
|
||||
Text=".placeho" MaxLength="12"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
<TextBlock Grid.Column="6" Grid.Row="3" Text="Bulk data:"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||
<TextBox Name="denseTextBox" Grid.Column="7" Grid.Row="3"
|
||||
|
@ -820,10 +826,20 @@ limitations under the License.
|
|||
<TextBlock Text="General code generation:" Margin="4,16,0,0"/>
|
||||
<CheckBox Content="Show cycle counts in comments" Margin="4,8,0,0"
|
||||
IsChecked="{Binding ShowCycleCountsAsm}"/>
|
||||
<CheckBox Content="Put long labels on separate line" Margin="4,8,0,0"
|
||||
IsChecked="{Binding LongLabelNewLine}"/>
|
||||
<CheckBox Content="Identify assembler in output" Margin="4,8,0,0"
|
||||
<CheckBox Content="Identify assembler in output" Margin="4,6,0,0"
|
||||
IsChecked="{Binding AddIdentComment}"/>
|
||||
<StackPanel Orientation="Vertical" Margin="10,6,0,0">
|
||||
<TextBlock Text="Put labels on their own line..."/>
|
||||
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
|
||||
Content="Only when required"
|
||||
IsChecked="{Binding LabelPlacement_PreferSameLine}"/>
|
||||
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
|
||||
Content="When the label is wider than the field"
|
||||
IsChecked="{Binding LabelPlacement_SplitIfTooLong}"/>
|
||||
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
|
||||
Content="Whenever possible"
|
||||
IsChecked="{Binding LabelPlacement_PreferSeparateLine}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ using System.Reflection;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Asm65;
|
||||
|
@ -30,24 +31,26 @@ using CommonUtil;
|
|||
using AssemblerInfo = SourceGen.AsmGen.AssemblerInfo;
|
||||
using AssemblerConfig = SourceGen.AsmGen.AssemblerConfig;
|
||||
using ExpressionMode = Asm65.Formatter.FormatConfig.ExpressionMode;
|
||||
using System.Windows.Input;
|
||||
using LabelPlacement = SourceGen.AsmGen.GenCommon.LabelPlacement;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
/// Application settings dialog.
|
||||
/// </summary>
|
||||
public partial class EditAppSettings : Window, INotifyPropertyChanged {
|
||||
/// <summary>
|
||||
/// Event that the controller can subscribe to if it wants to be notified when the
|
||||
/// "Apply" or "OK" button is hit.
|
||||
/// </summary>
|
||||
public event SettingsAppliedHandler SettingsApplied;
|
||||
public delegate void SettingsAppliedHandler();
|
||||
|
||||
/// <summary>
|
||||
/// Reference to main window. Needed for examination of the code list font and
|
||||
/// column widths.
|
||||
/// </summary>
|
||||
private MainWindow mMainWin;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to main controller. Needed to push settings out when Apply/OK is clicked.
|
||||
/// </summary>
|
||||
private MainController mMainCtrl;
|
||||
|
||||
/// <summary>
|
||||
/// Copy of settings that we make changes to. On "Apply" or "OK", this is pushed
|
||||
/// into the global settings object, and applied to the ProjectView.
|
||||
|
@ -102,14 +105,13 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
|
||||
|
||||
public EditAppSettings(Window owner, MainWindow mainWin, MainController mainCtrl,
|
||||
Tab initialTab, AssemblerInfo.Id initialAsmId) {
|
||||
public EditAppSettings(Window owner, MainWindow mainWin, Tab initialTab,
|
||||
AssemblerInfo.Id initialAsmId) {
|
||||
InitializeComponent();
|
||||
Owner = owner;
|
||||
DataContext = this;
|
||||
|
||||
mMainWin = mainWin;
|
||||
mMainCtrl = mainCtrl;
|
||||
mInitialTab = initialTab;
|
||||
mInitialAsmId = initialAsmId;
|
||||
|
||||
|
@ -203,7 +205,8 @@ namespace SourceGen.WpfGui {
|
|||
// QueryVersions() can sometimes be slow under Win10 (mid 2019), possibly
|
||||
// because of the built-in malware detection, so pop up a wait cursor.
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
mMainCtrl.SetAppSettings(mSettings);
|
||||
AppSettings.Global.ReplaceSettings(mSettings);
|
||||
OnSettingsApplied();
|
||||
AsmGen.AssemblerVersionCache.QueryVersions();
|
||||
} finally {
|
||||
Mouse.OverrideCursor = null;
|
||||
|
@ -212,6 +215,16 @@ namespace SourceGen.WpfGui {
|
|||
IsDirty = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the "settings applied" event.
|
||||
/// </summary>
|
||||
private void OnSettingsApplied() {
|
||||
SettingsAppliedHandler handler = SettingsApplied;
|
||||
if (handler != null) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Code View
|
||||
|
||||
|
@ -268,8 +281,8 @@ namespace SourceGen.WpfGui {
|
|||
UpperOperandXY = mSettings.GetBool(AppSettings.FMT_UPPER_OPERAND_XY, false);
|
||||
|
||||
Debug.Assert(clipboardFormatComboBox.Items.Count == sClipboardFormatItems.Length);
|
||||
int clipIndex = mSettings.GetEnum(AppSettings.CLIP_LINE_FORMAT,
|
||||
typeof(MainController.ClipLineFormat), 0);
|
||||
int clipIndex = (int)mSettings.GetEnum(AppSettings.CLIP_LINE_FORMAT,
|
||||
MainController.ClipLineFormat.AssemblerSource);
|
||||
if (clipIndex >= 0 && clipIndex < sClipboardFormatItems.Length) {
|
||||
// require Value == clipIndex because we're lazy and don't want to search
|
||||
Debug.Assert((int)sClipboardFormatItems[clipIndex].Value == clipIndex);
|
||||
|
@ -402,8 +415,7 @@ namespace SourceGen.WpfGui {
|
|||
private void ClipboardFormatComboBox_SelectionChanged(object sender,
|
||||
SelectionChangedEventArgs e) {
|
||||
ClipboardFormatItem item = (ClipboardFormatItem)clipboardFormatComboBox.SelectedItem;
|
||||
mSettings.SetEnum(AppSettings.CLIP_LINE_FORMAT, typeof(MainController.ClipLineFormat),
|
||||
(int)item.Value);
|
||||
mSettings.SetEnum(AppSettings.CLIP_LINE_FORMAT, item.Value);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
|
@ -745,14 +757,6 @@ namespace SourceGen.WpfGui {
|
|||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool LongLabelNewLine {
|
||||
get { return mSettings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false); }
|
||||
set {
|
||||
mSettings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, value);
|
||||
OnPropertyChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool AddIdentComment {
|
||||
get { return mSettings.GetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, false); }
|
||||
set {
|
||||
|
@ -762,6 +766,58 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
}
|
||||
|
||||
// label placement radio buttons
|
||||
public bool LabelPlacement_PreferSameLine {
|
||||
get {
|
||||
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.SplitIfTooLong);
|
||||
return place == LabelPlacement.PreferSameLine;
|
||||
}
|
||||
set {
|
||||
if (value) {
|
||||
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.PreferSameLine);
|
||||
LabelPlacementChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool LabelPlacement_SplitIfTooLong {
|
||||
get {
|
||||
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.SplitIfTooLong);
|
||||
return place == LabelPlacement.SplitIfTooLong;
|
||||
}
|
||||
set {
|
||||
if (value) {
|
||||
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.SplitIfTooLong);
|
||||
LabelPlacementChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool LabelPlacement_PreferSeparateLine {
|
||||
get {
|
||||
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.SplitIfTooLong);
|
||||
return place == LabelPlacement.PreferSeparateLine;
|
||||
}
|
||||
set {
|
||||
if (value) {
|
||||
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
|
||||
LabelPlacement.PreferSeparateLine);
|
||||
LabelPlacementChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void LabelPlacementChanged() {
|
||||
OnPropertyChanged(nameof(LabelPlacement_PreferSameLine));
|
||||
OnPropertyChanged(nameof(LabelPlacement_SplitIfTooLong));
|
||||
OnPropertyChanged(nameof(LabelPlacement_PreferSeparateLine));
|
||||
}
|
||||
|
||||
private void Loaded_AsmConfig() {
|
||||
asmConfigComboBox.SelectedItem = AssemblerInfo.GetAssemblerInfo(mInitialAsmId);
|
||||
if (asmConfigComboBox.SelectedIndex < 0) {
|
||||
|
@ -1309,6 +1365,7 @@ namespace SourceGen.WpfGui {
|
|||
new TextBoxPropertyMap(uninitTextBox, "Uninit"),
|
||||
new TextBoxPropertyMap(junkTextBox, "Junk"),
|
||||
new TextBoxPropertyMap(alignTextBox, "Align"),
|
||||
new TextBoxPropertyMap(binaryIncludeTextBox, "BinaryInclude"),
|
||||
new TextBoxPropertyMap(strGenericTextBox, "StrGeneric"),
|
||||
new TextBoxPropertyMap(strReverseTextBox, "StrReverse"),
|
||||
new TextBoxPropertyMap(strLen8TextBox, "StrLen8"),
|
||||
|
|
|
@ -148,9 +148,17 @@ limitations under the License.
|
|||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<RadioButton Name="radioJunk" GroupName="Main" Content="_Junk bytes, end aligned to"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<ComboBox Name="junkAlignComboBox" Margin="8,-5,0,0" Width="200"
|
||||
<ComboBox Name="junkAlignComboBox" Margin="6,-4,0,0" Width="200"
|
||||
ItemsSource="{Binding JunkAlignmentItems}" DisplayMemberPath="Description"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<RadioButton Name="radioBinaryInclude" GroupName="Main" Content="Binary include, filename:"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<TextBox Name="binaryIncludeTextBox" Margin="6,-2,0,0" Width="240"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"
|
||||
TextChanged="BinaryIncludeTextBox_TextChanged"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="String" Margin="0,12,0,0"/>
|
||||
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
|
||||
|
|
|
@ -266,6 +266,12 @@ namespace SourceGen.WpfGui {
|
|||
UpdateControls();
|
||||
}
|
||||
|
||||
private void BinaryIncludeTextBox_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
radioBinaryInclude.IsChecked = true;
|
||||
// Update OK button based on filename validity.
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the string encoding combo box to an item that matches the specified mode. If
|
||||
/// the mode can't be found, an arbitrary entry will be chosen.
|
||||
|
@ -293,8 +299,7 @@ namespace SourceGen.WpfGui {
|
|||
AnalyzeStringRanges(item.Mode);
|
||||
UpdateControls();
|
||||
|
||||
AppSettings.Global.SetEnum(AppSettings.OPED_DEFAULT_STRING_ENCODING,
|
||||
typeof(TextScanMode), (int)item.Mode);
|
||||
AppSettings.Global.SetEnum(AppSettings.OPED_DEFAULT_STRING_ENCODING, item.Mode);
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
|
@ -378,6 +383,10 @@ namespace SourceGen.WpfGui {
|
|||
}
|
||||
IsValid = isOk;
|
||||
|
||||
if (radioBinaryInclude.IsChecked == true) {
|
||||
IsValid &= AsmGen.BinaryInclude.ValidatePathName(binaryIncludeTextBox.Text);
|
||||
}
|
||||
|
||||
// If dense hex with a limit is selected, check the value.
|
||||
if (radioDenseHexLimited.IsChecked == true) {
|
||||
if (MaxDenseBytesPerLine > 0) {
|
||||
|
@ -515,6 +524,9 @@ namespace SourceGen.WpfGui {
|
|||
radioFill.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// We can't handle multiple ranges because we need to set the filename.
|
||||
radioBinaryInclude.IsEnabled = (mSelection.RangeCount == 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -780,9 +792,8 @@ namespace SourceGen.WpfGui {
|
|||
|
||||
// Get the previous mode selected in the combo box. If the format descriptor
|
||||
// doesn't specify a string, we'll use this.
|
||||
TextScanMode textMode = (TextScanMode)AppSettings.Global.GetEnum(
|
||||
AppSettings.OPED_DEFAULT_STRING_ENCODING, typeof(TextScanMode),
|
||||
(int)TextScanMode.LowHighAscii);
|
||||
TextScanMode textMode = AppSettings.Global.GetEnum(
|
||||
AppSettings.OPED_DEFAULT_STRING_ENCODING, TextScanMode.LowHighAscii);
|
||||
|
||||
if (dfd == null) {
|
||||
radioDefaultFormat.IsChecked = true;
|
||||
|
@ -903,6 +914,11 @@ namespace SourceGen.WpfGui {
|
|||
case FormatDescriptor.Type.Junk:
|
||||
preferredFormat = radioJunk;
|
||||
break;
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
preferredFormat = radioBinaryInclude;
|
||||
binaryIncludeTextBox.Text =
|
||||
AsmGen.BinaryInclude.ConvertPathNameFromStorage(dfd.Extra);
|
||||
break;
|
||||
default:
|
||||
// Should not be here.
|
||||
Debug.Assert(false);
|
||||
|
@ -1079,6 +1095,10 @@ namespace SourceGen.WpfGui {
|
|||
type = FormatDescriptor.Type.Junk;
|
||||
JunkAlignmentItem comboItem = (JunkAlignmentItem)junkAlignComboBox.SelectedItem;
|
||||
subType = comboItem.FormatSubType;
|
||||
} else if (radioBinaryInclude.IsChecked == true) {
|
||||
type = FormatDescriptor.Type.BinaryInclude;
|
||||
// path will be extracted directly by subroutine
|
||||
Debug.Assert(mSelection.RangeCount == 1);
|
||||
} else if (radioStringMixed.IsChecked == true) {
|
||||
type = FormatDescriptor.Type.StringGeneric;
|
||||
subType = charSubType;
|
||||
|
@ -1178,7 +1198,13 @@ namespace SourceGen.WpfGui {
|
|||
// The one exception to this is ASCII values for non-string data, because we have
|
||||
// to dig the low vs. high value out of the data itself.
|
||||
FormatDescriptor dfd;
|
||||
if (subType == FormatDescriptor.SubType.Symbol) {
|
||||
if (type == FormatDescriptor.Type.BinaryInclude) {
|
||||
// Special case. We know there can be only one of these, so just grab the
|
||||
// filename directly instead of passing it in as a rare argument.
|
||||
string storePath =
|
||||
AsmGen.BinaryInclude.ConvertPathNameToStorage(binaryIncludeTextBox.Text);
|
||||
dfd = FormatDescriptor.Create(chunkLength, type, storePath);
|
||||
} else if (subType == FormatDescriptor.SubType.Symbol) {
|
||||
dfd = FormatDescriptor.Create(chunkLength, symbolRef,
|
||||
type == FormatDescriptor.Type.NumericBE);
|
||||
} else {
|
||||
|
|
|
@ -695,6 +695,7 @@ namespace SourceGen.WpfGui {
|
|||
case FormatDescriptor.Type.Fill:
|
||||
case FormatDescriptor.Type.Uninit:
|
||||
case FormatDescriptor.Type.Junk:
|
||||
case FormatDescriptor.Type.BinaryInclude:
|
||||
default:
|
||||
// Unexpected; used to be data?
|
||||
break;
|
||||
|
|
|
@ -20,9 +20,9 @@ using System.IO;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using CommonUtil;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
|
@ -235,8 +235,8 @@ namespace SourceGen.WpfGui {
|
|||
AsmCommentColWidth = colWidths[3];
|
||||
}
|
||||
|
||||
TextMode mode = (TextMode)AppSettings.Global.GetEnum(AppSettings.EXPORT_TEXT_MODE,
|
||||
typeof(TextMode), (int)TextMode.PlainText);
|
||||
TextMode mode = AppSettings.Global.GetEnum(AppSettings.EXPORT_TEXT_MODE,
|
||||
TextMode.PlainText);
|
||||
if (mode == TextMode.PlainText) {
|
||||
TextModePlain = true;
|
||||
} else {
|
||||
|
@ -273,7 +273,7 @@ namespace SourceGen.WpfGui {
|
|||
} else {
|
||||
mode = TextMode.Csv;
|
||||
}
|
||||
AppSettings.Global.SetEnum(AppSettings.EXPORT_TEXT_MODE, typeof(TextMode), (int)mode);
|
||||
AppSettings.Global.SetEnum(AppSettings.EXPORT_TEXT_MODE, mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -56,15 +56,20 @@ limitations under the License.
|
|||
</ListBox>
|
||||
|
||||
<TextBlock Text="Font size:" Margin="0,8,0,0"/>
|
||||
<ComboBox Name="sizeComboBox" IsReadOnly="True" Margin="0,4,0,0" Width="75"
|
||||
HorizontalAlignment="Left">
|
||||
<!-- these are parsed directly, so only use numeric values -->
|
||||
<ComboBoxItem>8</ComboBoxItem>
|
||||
<ComboBoxItem>10</ComboBoxItem>
|
||||
<ComboBoxItem>12</ComboBoxItem>
|
||||
<ComboBoxItem>16</ComboBoxItem>
|
||||
<ComboBoxItem>20</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ComboBox Name="sizeComboBox" Margin="0,4,0,0" Width="75"
|
||||
HorizontalAlignment="Left" IsEditable="True">
|
||||
<!-- these are parsed directly, so only use numeric values -->
|
||||
<ComboBoxItem>8</ComboBoxItem>
|
||||
<ComboBoxItem>10</ComboBoxItem>
|
||||
<ComboBoxItem>12</ComboBoxItem>
|
||||
<ComboBoxItem>14</ComboBoxItem>
|
||||
<ComboBoxItem>16</ComboBoxItem>
|
||||
<ComboBoxItem>20</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<TextBlock Name="sizeErrMsg" Margin="8,6,0,0" Text="Must be an integer from 3 to 64."
|
||||
Foreground="Red" Visibility="Hidden"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
|
||||
<Button Name="okButton" Content="OK" IsDefault="True"
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace SourceGen.WpfGui {
|
|||
|
||||
GenerateMonoFontList(initialFamily);
|
||||
|
||||
int selIndex = 0;
|
||||
int selIndex = -1;
|
||||
string sizeStr = initialSize.ToString();
|
||||
for (int i = 0; i < sizeComboBox.Items.Count; i++) {
|
||||
ComboBoxItem item = (ComboBoxItem)sizeComboBox.Items[i];
|
||||
|
@ -53,6 +53,10 @@ namespace SourceGen.WpfGui {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (selIndex < 0) {
|
||||
// Size is not one of the standard combo box items.
|
||||
sizeComboBox.Text = initialSize.ToString();
|
||||
}
|
||||
sizeComboBox.SelectedIndex = selIndex;
|
||||
}
|
||||
|
||||
|
@ -90,7 +94,7 @@ namespace SourceGen.WpfGui {
|
|||
continue;
|
||||
}
|
||||
|
||||
tmpList.Add(familyName, typ.FontFamily);
|
||||
tmpList[familyName] = typ.FontFamily;
|
||||
|
||||
if (familyName.Equals(initialFamily)) {
|
||||
SelectedFamily = typ.FontFamily;
|
||||
|
@ -114,7 +118,21 @@ namespace SourceGen.WpfGui {
|
|||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
ComboBoxItem item = (ComboBoxItem)sizeComboBox.SelectedItem;
|
||||
SelectedSize = int.Parse((string)item.Content);
|
||||
if (item != null) {
|
||||
SelectedSize = int.Parse((string)item.Content);
|
||||
} else {
|
||||
// Catch bad font sizes when "OK" is hit. Not as nice as disabling the OK
|
||||
// button on bad input, but much simpler.
|
||||
try {
|
||||
SelectedSize = int.Parse(sizeComboBox.Text);
|
||||
} catch (FormatException) {
|
||||
SelectedSize = -1; // trigger next test
|
||||
}
|
||||
if (SelectedSize < 3 || SelectedSize > 64) {
|
||||
sizeErrMsg.Visibility = Visibility.Visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
DialogResult = true;
|
||||
}
|
||||
}
|
||||
|
|
52
SourceGen/WpfGui/GenerateLabels.xaml
Normal file
52
SourceGen/WpfGui/GenerateLabels.xaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<!--
|
||||
Copyright 2024 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.
|
||||
-->
|
||||
|
||||
<Window x:Class="SourceGen.WpfGui.GenerateLabels"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SourceGen.WpfGui"
|
||||
mc:Ignorable="d"
|
||||
Title="Generate Label File"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Grid.Row="0" Header="Output Format" Padding="2,4">
|
||||
<StackPanel>
|
||||
<RadioButton Content="VICE label commands"
|
||||
ToolTip="Load in VICE monitor with 'll' command."
|
||||
IsChecked="{Binding Format_VICE}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<CheckBox Grid.Row="1" Margin="0,4,0,0" Content="Include auto-generated labels"
|
||||
IsChecked="{Binding IncludeAutoLabels}"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal"
|
||||
HorizontalAlignment="Right" Margin="0,8,0,0">
|
||||
<Button Content="Generate" IsDefault="True" Width="70" Click="OkButton_Click"/>
|
||||
<Button Content="Cancel" IsCancel="True" Width="70" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
71
SourceGen/WpfGui/GenerateLabels.xaml.cs
Normal file
71
SourceGen/WpfGui/GenerateLabels.xaml.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2019 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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
/// Select parameters for label file generation.
|
||||
/// </summary>
|
||||
public partial class GenerateLabels : Window, INotifyPropertyChanged {
|
||||
// INotifyPropertyChanged implementation
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public bool IncludeAutoLabels {
|
||||
get { return mIncludeAutoLabels; }
|
||||
set { mIncludeAutoLabels = value; OnPropertyChanged(); }
|
||||
}
|
||||
private bool mIncludeAutoLabels;
|
||||
|
||||
public LabelFileGenerator.LabelFmt Format { get; private set; }
|
||||
|
||||
public bool Format_VICE {
|
||||
get { return Format == LabelFileGenerator.LabelFmt.VICE;}
|
||||
set { Format = LabelFileGenerator.LabelFmt.VICE; UpdateFormats(); }
|
||||
}
|
||||
|
||||
private void UpdateFormats() {
|
||||
OnPropertyChanged(nameof(Format_VICE));
|
||||
}
|
||||
|
||||
|
||||
public GenerateLabels(Window owner) {
|
||||
InitializeComponent();
|
||||
Owner = owner;
|
||||
DataContext = this;
|
||||
|
||||
Format = AppSettings.Global.GetEnum(AppSettings.LABGEN_FORMAT,
|
||||
LabelFileGenerator.LabelFmt.VICE);
|
||||
UpdateFormats();
|
||||
mIncludeAutoLabels = AppSettings.Global.GetBool(AppSettings.LABGEN_INCLUDE_AUTO, false);
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
// Save settings.
|
||||
AppSettings.Global.SetEnum(AppSettings.LABGEN_FORMAT, Format);
|
||||
AppSettings.Global.SetBool(AppSettings.LABGEN_INCLUDE_AUTO, mIncludeAutoLabels);
|
||||
DialogResult = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ limitations under the License.
|
|||
</Style>
|
||||
|
||||
<RoutedUICommand x:Key="AboutCmd" Text="About..."/>
|
||||
<RoutedUICommand x:Key="AssembleCmd" Text="Assemble...">
|
||||
<RoutedUICommand x:Key="AssembleCmd" Text="Generate Assembly...">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>Ctrl+Shift+A</KeyGesture>
|
||||
</RoutedUICommand.InputGestures>
|
||||
|
@ -136,6 +136,7 @@ limitations under the License.
|
|||
</RoutedUICommand.InputGestures>
|
||||
</RoutedUICommand>
|
||||
<RoutedUICommand x:Key="FormatAddressTableCmd" Text="Format Address Table..."/>
|
||||
<RoutedUICommand x:Key="GenerateLabelsCmd" Text="Generate Label File..."/>
|
||||
<RoutedUICommand x:Key="GotoCmd" Text="Go To...">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>Ctrl+G</KeyGesture>
|
||||
|
@ -284,6 +285,8 @@ limitations under the License.
|
|||
CanExecute="CanFormatAsWord" Executed="FormatAsWordCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource FormatAddressTableCmd}"
|
||||
CanExecute="CanFormatAddressTable" Executed="FormatAddressTableCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource GenerateLabelsCmd}"
|
||||
CanExecute="IsProjectOpen" Executed="GenerateLabelsCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource GotoCmd}"
|
||||
CanExecute="IsProjectOpen" Executed="GotoCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource GotoLastChangeCmd}"
|
||||
|
@ -392,8 +395,8 @@ limitations under the License.
|
|||
</MenuItem>
|
||||
<Separator/>
|
||||
<MenuItem Command="{StaticResource AssembleCmd}"/>
|
||||
<!--<MenuItem Command="Print"/>-->
|
||||
<MenuItem Command="{StaticResource ExportCmd}"/>
|
||||
<MenuItem Command="{StaticResource GenerateLabelsCmd}"/>
|
||||
<Separator/>
|
||||
<MenuItem Command="{StaticResource ReloadExternalFilesCmd}"/>
|
||||
<Separator/>
|
||||
|
|
|
@ -1332,6 +1332,10 @@ namespace SourceGen.WpfGui {
|
|||
mMainCtrl.FormatAddressTable();
|
||||
}
|
||||
|
||||
private void GenerateLabelsCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.GenerateLabels();
|
||||
}
|
||||
|
||||
private void GotoCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.Goto();
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace SourceGen {
|
|||
|
||||
public override string ToString() {
|
||||
return "Xref off=+" + Offset.ToString("x6") + " sym=" + IsByName +
|
||||
" type=" + Type + " accType= " + AccType + " flags=" + Flags +
|
||||
" type=" + Type + " accType=" + AccType + " flags=" + Flags +
|
||||
" adj=" + Adjustment;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user