From e8608770b93356cc0ffa7b5405a813059209bdbf Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sat, 2 Oct 2021 13:47:05 -0700 Subject: [PATCH] ORG rework, part 7 Implemented "is relative" flag. This only affects source code generation, replacing ".arstart " with ".arstart *+". Only output by 64tass and ACME generators. Added a bold-text summary to radio buttons in address region edit dialog. This makes it much easier to see what you're doing. Added a warning to the label edit dialog when a label is being placed in a non-addressable region. Modified double-click behavior for .arstart/.arend to jump to the other end when the opcode is clicked on. This matches the behavior of instructions with address operands. Reordered Actions menu, putting "edit operand" at the top. Fixed AddressMap entry collision testing. Fixed PRG issue with multiple address regions at offset +000002. Added regression tests. Most of the complicated stuff with regions is tested by unit tests inside AddressMap, but we still need to exercise nested region code generation. --- CommonUtil/AddressMap.cs | 110 ++++++------ SourceGen/AsmGen/AsmAcme.cs | 17 +- SourceGen/AsmGen/AsmCc65.cs | 1 + SourceGen/AsmGen/AsmMerlin32.cs | 1 + SourceGen/AsmGen/AsmTass64.cs | 18 +- SourceGen/AsmGen/GenCommon.cs | 9 +- SourceGen/LineListGen.cs | 11 ++ SourceGen/MainController.cs | 27 +-- SourceGen/RenderAddressMap.cs | 3 + SourceGen/SGTestData/20250-nested-regions | Bin 0 -> 156 bytes .../SGTestData/20250-nested-regions.dis65 | 161 ++++++++++++++++++ SourceGen/SGTestData/20252-nested-regions | Bin 0 -> 40 bytes .../SGTestData/20252-nested-regions.dis65 | 96 +++++++++++ .../Expected/20250-nested-regions_64tass.S | 97 +++++++++++ .../Expected/20250-nested-regions_acme.S | 97 +++++++++++ .../Expected/20250-nested-regions_cc65.S | 90 ++++++++++ .../Expected/20250-nested-regions_cc65.cfg | 9 + .../Expected/20250-nested-regions_merlin32.S | 88 ++++++++++ .../Expected/20252-nested-regions_64tass.S | 30 ++++ .../Expected/20252-nested-regions_acme.S | 6 + .../Expected/20252-nested-regions_cc65.S | 27 +++ .../Expected/20252-nested-regions_cc65.cfg | 9 + .../Expected/20252-nested-regions_merlin32.S | 24 +++ .../SGTestData/Source/20250-nested-regions.S | 137 +++++++++++++++ .../SGTestData/Source/20252-nested-regions.S | 47 +++++ SourceGen/WpfGui/EditAddress.xaml | 46 +++-- SourceGen/WpfGui/EditAddress.xaml.cs | 77 ++++++--- SourceGen/WpfGui/EditLabel.xaml | 2 + SourceGen/WpfGui/EditLabel.xaml.cs | 8 + SourceGen/WpfGui/MainWindow.xaml | 6 +- 30 files changed, 1149 insertions(+), 105 deletions(-) create mode 100644 SourceGen/SGTestData/20250-nested-regions create mode 100644 SourceGen/SGTestData/20250-nested-regions.dis65 create mode 100644 SourceGen/SGTestData/20252-nested-regions create mode 100644 SourceGen/SGTestData/20252-nested-regions.dis65 create mode 100644 SourceGen/SGTestData/Expected/20250-nested-regions_64tass.S create mode 100644 SourceGen/SGTestData/Expected/20250-nested-regions_acme.S create mode 100644 SourceGen/SGTestData/Expected/20250-nested-regions_cc65.S create mode 100644 SourceGen/SGTestData/Expected/20250-nested-regions_cc65.cfg create mode 100644 SourceGen/SGTestData/Expected/20250-nested-regions_merlin32.S create mode 100644 SourceGen/SGTestData/Expected/20252-nested-regions_64tass.S create mode 100644 SourceGen/SGTestData/Expected/20252-nested-regions_acme.S create mode 100644 SourceGen/SGTestData/Expected/20252-nested-regions_cc65.S create mode 100644 SourceGen/SGTestData/Expected/20252-nested-regions_cc65.cfg create mode 100644 SourceGen/SGTestData/Expected/20252-nested-regions_merlin32.S create mode 100644 SourceGen/SGTestData/Source/20250-nested-regions.S create mode 100644 SourceGen/SGTestData/Source/20252-nested-regions.S diff --git a/CommonUtil/AddressMap.cs b/CommonUtil/AddressMap.cs index ef50165..cfb55c9 100644 --- a/CommonUtil/AddressMap.cs +++ b/CommonUtil/AddressMap.cs @@ -256,6 +256,7 @@ namespace CommonUtil { // (Shouldn't be necessary since we're only doing this to pass the address map to // plugins, but... better safe.) 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); if (result != AddResult.Okay) { @@ -357,7 +358,7 @@ namespace CommonUtil { } /// - /// Adds a new entry to the map. + /// Adds a new entry to the map. Uses defaults for PreLabel and IsRelative. /// /// File offset of region start. /// Length of region, or FLOATING_LEN for a floating end point. @@ -423,14 +424,16 @@ namespace CommonUtil { return AddResult.Okay; } - // Find insertion point. - int insIdx; - for (insIdx = 0; insIdx < mMapEntries.Count; insIdx++) { - AddressMapEntry ent = mMapEntries[insIdx]; - if (ent.Offset > offset) { - // Insert before this one. - break; - } else if (ent.Offset == offset) { + // Find the insertion point, and check for conflicts. + // + // If we know where to insert the new entry, we only need to check the previous + // node, following node, and parents. However, we may not have regenerated the + // tree structure since the previous add, so we can't rely on that. We're expecting + // the list to be short, so checking all entries shouldn't be prohibitive. + int insIdx = -1; + for (int i = 0; i < mMapEntries.Count; i++) { + AddressMapEntry ent = mMapEntries[i]; + if (ent.Offset == offset) { // We share a start point with this entry. See if we fit inside it or // wrap around it. if (length == FLOATING_LEN || ent.Length == FLOATING_LEN) { @@ -441,33 +444,18 @@ namespace CommonUtil { return AddResult.OverlapExisting; } else if (ent.Length < length) { // New region is larger, would become parent, so insert before this. - break; + if (insIdx < 0) { + insIdx = i; + } } else { // New region is smaller and will be a child of this entry, so we want // to insert *after* this point. Loop again to see if the following // entry is also a parent for this new one. Debug.Assert(ent.Length > length); } - } - } - - // The insertion index indicates the entry we want to insert before. We need to - // confirm that the new block doesn't straddle the blocks on either side. If we're - // inserting into a bunch of blocks with coincident start points, it's possible for - // the blocks appearing before and after to share the same start offset. - - if (insIdx > 0) { - // Check previous block. We know that its offset is <= the new offset, so - // either its a parent or a sibling. - AddressMapEntry ent = mMapEntries[insIdx - 1]; - if (ent.Offset == offset) { - // Previous is our parent. These things were checked earlier. - Debug.Assert(length != FLOATING_LEN && ent.Length != FLOATING_LEN); - Debug.Assert(ent.Length > length); - } else { + } else if (ent.Offset < offset) { // Existing block starts before this new one. The existing block must either // be floating, be completely before this, or completely envelop this. - Debug.Assert(ent.Offset < offset); if (ent.Length == FLOATING_LEN) { // sibling -- must end before us } else if (ent.Offset + ent.Length <= offset) { @@ -480,20 +468,12 @@ namespace CommonUtil { // whoops return AddResult.StraddleExisting; } - } - } - if (insIdx < mMapEntries.Count) { - // Check following block. We know that its offset is >= the new offset, so it's - // either a child or a sibling. - AddressMapEntry ent = mMapEntries[insIdx]; - if (ent.Offset == offset) { - // Following block is our child. These things were checked earlier. - Debug.Assert(length != FLOATING_LEN && ent.Length != FLOATING_LEN); - Debug.Assert(ent.Length < length); } else { // Existing block starts after this new one. The existing block must either // be floating, be completely after this, or be completely enveloped by this. - Debug.Assert(ent.Offset > offset); + if (insIdx < 0) { + insIdx = i; + } if (ent.Length == FLOATING_LEN) { // child or sibling, depending on start offset } else if (offset + length <= ent.Offset) { @@ -509,6 +489,10 @@ namespace CommonUtil { } } + if (insIdx < 0) { + insIdx = mMapEntries.Count; + } + outInsIdx = insIdx; return AddResult.Okay; } @@ -549,13 +533,6 @@ namespace CommonUtil { return -1; } - // Returns true if adding the specified region is a valid action. - // ??? do we want to do this, or just ask "does region exist"? Depends on - // flow in edit dialog. - //public bool CanAddRegion(int offset, int length) { - // return false; - //} - /// /// Gets a list of the entries with the specified offset value. /// @@ -1097,7 +1074,7 @@ namespace CommonUtil { /// /// We use inclusive Offset values for both start and end. If we don't do this, the /// offset for end records will be outside the file bounds. It also gets a bit painful - /// when the display list tries to update [M,N] if put the end at N+1. + /// when the display list tries to update [M,N] if the end is actually held at N+1. /// public class AddressChange { // True if this is a region start, false if a region end. @@ -1451,6 +1428,8 @@ namespace CommonUtil { map.AddEntry(off0 + 1, len0, 0x1000)); Test_Expect(AddResult.InvalidValue, ref result, map.AddEntry(off0, mapLen + 1, 0x1000)); + Test_Expect(AddResult.StraddleExisting, ref result, + map.AddEntry(off0 + 1, off2 - off0, 0x1000)); // One region to wrap them all. Add then remove. Test_Expect(AddResult.Okay, ref result, @@ -1596,9 +1575,6 @@ namespace CommonUtil { Test_Expect(0x002100, ref result, map.AddressToOffset(0x002300, 0x5000)); Test_Expect(0x003100, ref result, map.AddressToOffset(0x003000, 0x5000)); - string mapStr = map.FormatAddressMap(); // DEBUG - format the map and - Debug.WriteLine(mapStr); // DEBUG - print it to the console - result &= map.DebugValidate(); return result; } @@ -1699,6 +1675,39 @@ namespace CommonUtil { return result; } + private static bool Test_OddOverlap() { + const int mapLen = 0x1000; + AddressMap map = new AddressMap(mapLen); + bool result = true; + + // Top region spans full map. + Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, mapLen, 0x1000)); + // Parent region covers next two. + Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x0400, 0x1000)); + // Floating region. + Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000100, FLOATING_LEN, 0x2000)); + // Fixed region follows. + 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 + + // Add a region that starts in the middle of the floating region (becoming + // a sibling), and ends after the fixed region (becoming its parent). + Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000180, 0x0200, 0x4000)); + // Remove it. + Test_Expect(true, ref result, map.RemoveEntry(0x000180, 0x0200)); + + // 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 + // the parent's start offset, this is invalid. + Test_Expect(AddResult.StraddleExisting, ref result, + map.AddEntry(0x000180, 0x0400, 0x4000)); + + result &= map.DebugValidate(); + return result; + } + public static bool Test() { bool ok = true; ok &= Test_Primitives(); @@ -1708,6 +1717,7 @@ namespace CommonUtil { ok &= Test_Nested(); ok &= Test_Cross(); ok &= Test_Pyramids(); + ok &= Test_OddOverlap(); Debug.WriteLine("AddressMap: test complete (ok=" + ok + ")"); return ok; diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs index 6c7a81f..b8d0248 100644 --- a/SourceGen/AsmGen/AsmAcme.cs +++ b/SourceGen/AsmGen/AsmAcme.cs @@ -594,9 +594,24 @@ namespace SourceGen.AsmGen { OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty); } } + AddressMap.AddressRegion region = change.Region; + string addrStr; + if (region.IsRelative && region.PreLabelAddress != Address.NON_ADDR) { + int diff = nextAddress - region.PreLabelAddress; + string pfxStr; + if (diff >= 0) { + pfxStr = "*+"; + } else { + pfxStr = "*-"; + diff = -diff; + } + addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4); + } else { + addrStr = SourceFormatter.FormatHexValue(nextAddress, 4); + } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), - SourceFormatter.FormatHexValue(nextAddress, 4) + " {", + addrStr + " {", string.Empty); mPcDepth++; } else { diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs index e344690..239561c 100644 --- a/SourceGen/AsmGen/AsmCc65.cs +++ b/SourceGen/AsmGen/AsmCc65.cs @@ -550,6 +550,7 @@ namespace SourceGen.AsmGen { // IGenerator public void FlushArDirectives() { + // TODO(someday): handle IsRelative OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), SourceFormatter.FormatHexValue(mNextAddress, 4), diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs index aa7e12f..83a7f0c 100644 --- a/SourceGen/AsmGen/AsmMerlin32.cs +++ b/SourceGen/AsmGen/AsmMerlin32.cs @@ -501,6 +501,7 @@ namespace SourceGen.AsmGen { // IGenerator public void FlushArDirectives() { + // TODO(someday): handle IsRelative OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), SourceFormatter.FormatHexValue(mNextAddress, 4), diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs index a781286..75fd6aa 100644 --- a/SourceGen/AsmGen/AsmTass64.cs +++ b/SourceGen/AsmGen/AsmTass64.cs @@ -697,9 +697,25 @@ namespace SourceGen.AsmGen { //OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty); } } + + AddressMap.AddressRegion region = change.Region; + string addrStr; + if (region.IsRelative && region.PreLabelAddress != Address.NON_ADDR) { + int diff = nextAddress - region.PreLabelAddress; + string pfxStr; + if (diff >= 0) { + pfxStr = "*+"; + } else { + pfxStr = "*-"; + diff = -diff; + } + addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4); + } else { + addrStr = SourceFormatter.FormatHexValue(nextAddress, 4); + } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), - SourceFormatter.FormatHexValue(nextAddress, 4), + addrStr, string.Empty); mPcDepth++; } else { diff --git a/SourceGen/AsmGen/GenCommon.cs b/SourceGen/AsmGen/GenCommon.cs index 16741ee..2a41b25 100644 --- a/SourceGen/AsmGen/GenCommon.cs +++ b/SourceGen/AsmGen/GenCommon.cs @@ -584,9 +584,12 @@ namespace SourceGen.AsmGen { if (change.Region.ActualLength != 2) { Debug.WriteLine("PRG test: first entry is not a two-byte region"); } - // Confirm there's an address map entry at offset 2. - if (project.AddrMap.GetEntries(0x000002).Count == 0) { - //Debug.WriteLine("PRG test: no ORG at +2"); + // Confirm there's a single address map entry at offset 2. If there's more than + // one we likely have a situation where the first one is a "full-file" region, and + // the second determines the address. This weird scenario causes problems with + // code generation, so we just don't support it. + if (project.AddrMap.GetEntries(0x000002).Count != 1) { + //Debug.WriteLine("PRG test: wrong #of entries at +000002"); return false; } // See if the address at offset 2 matches the value at 0/1. diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs index 5c0d572..37e7b48 100644 --- a/SourceGen/LineListGen.cs +++ b/SourceGen/LineListGen.cs @@ -1086,6 +1086,17 @@ namespace SourceGen { string addrStr; if (region.Address == Address.NON_ADDR) { addrStr = Address.NON_ADDR_STR; + } else if (change.Region.IsRelative && + change.Region.PreLabelAddress != Address.NON_ADDR) { + int diff = region.Address - change.Region.PreLabelAddress; + string pfxStr; + if (diff >= 0) { + pfxStr = "*+"; + } else { + pfxStr = "*-"; + diff = -diff; + } + addrStr = pfxStr + mFormatter.FormatHexValue(diff, 4); } else { addrStr = mFormatter.FormatHexValue(region.Address, 4); } diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index c8fbfd2..3a1fe61 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -1532,7 +1532,9 @@ namespace SourceGen { break; case LineListGen.Line.Type.ArStartDirective: case LineListGen.Line.Type.ArEndDirective: - if (CanEditAddress()) { + if ((CodeListColumn)col == CodeListColumn.Opcode) { + JumpToOperandTarget(line, false); + } else if (CanEditAddress()) { EditAddress(); } break; @@ -1807,9 +1809,10 @@ namespace SourceGen { return false; } - // If multiple lines with code/data are selected, there must not be an address change + // If multiple lines with code/data are selected, there must not be a .arstart // between them unless we're resizing a region. Determining whether or not a resize - // is valid is left to the edit dialog. + // is valid is left to the edit dialog. It's okay for a .arend to be in the middle + // so long as the corresponding .arstart is at the current offset. if (selLine.LineType == LineListGen.Line.Type.ArStartDirective) { // Skip overlapping region check. return true; @@ -1821,14 +1824,18 @@ namespace SourceGen { return true; } - // Compute exclusive end point of selected range. - int nextOffset = lastOffset + CodeLineList[lastIndex].OffsetSpan; + // Anything else is too complicated to be worth messing with here. We could do + // the work, but we have no good way of telling the user what went wrong. + // Let the dialog explain it. - if (!mProject.AddrMap.IsRangeUnbroken(firstOffset, nextOffset - firstOffset)) { - Debug.WriteLine("Found mid-selection AddressMap entry (len=" + - (nextOffset - firstOffset) + ")"); - return false; - } + //// Compute exclusive end point of selected range. + //int nextOffset = lastOffset + CodeLineList[lastIndex].OffsetSpan; + + //if (!mProject.AddrMap.IsRangeUnbroken(firstOffset, nextOffset - firstOffset)) { + // Debug.WriteLine("Found mid-selection AddressMap entry (len=" + + // (nextOffset - firstOffset) + ")"); + // return false; + //} //Debug.WriteLine("First +" + firstOffset.ToString("x6") + // ", last +" + lastOffset.ToString("x6") + ",next +" + nextOffset.ToString("x6")); diff --git a/SourceGen/RenderAddressMap.cs b/SourceGen/RenderAddressMap.cs index bb77bf7..001b7db 100644 --- a/SourceGen/RenderAddressMap.cs +++ b/SourceGen/RenderAddressMap.cs @@ -107,6 +107,9 @@ namespace SourceGen { sb.Append(formatter.FormatOffset24(change.Offset)); PrintDepthLines(sb, depth, false); sb.Append("+- " + "end"); + if (change.Region.IsFloating) { + sb.Append(" (floating)"); + } //PrintAddress(sb, formatter, change.Address, showBank); //sb.Append(")"); sb.Append(CRLF); diff --git a/SourceGen/SGTestData/20250-nested-regions b/SourceGen/SGTestData/20250-nested-regions new file mode 100644 index 0000000000000000000000000000000000000000..9fd3fb4318e385effa8a23c15a68b1defdf100d8 GIT binary patch literal 156 zcmZQD&|xrG%WR;_e8GoDL5D}dM@T?NNI-$Xf#F=JkB@GMYml$Pg`-z4A3k|fAvh$+ z)6bouf!TohLW2&2gAPN04nGLJ@=*YD7#v=`(%}fu5f6BkpaT>F%0PgRg9AvMA>b8E hEI|h-1XSn4Z~g006RwHOT+~ literal 0 HcmV?d00001 diff --git a/SourceGen/SGTestData/20250-nested-regions.dis65 b/SourceGen/SGTestData/20250-nested-regions.dis65 new file mode 100644 index 0000000..9e9e35e --- /dev/null +++ b/SourceGen/SGTestData/20250-nested-regions.dis65 @@ -0,0 +1,161 @@ +### 6502bench SourceGen dis65 v1.0 ### +{ +"_ContentVersion":5, +"FileDataLength":156, +"FileDataCrc32":1681364707, +"ProjectProps":{ +"CpuName":"6502", +"IncludeUndocumentedInstr":false, +"TwoByteBrk":false, +"EntryFlags":32702671, +"AutoLabelStyle":"Simple", +"AnalysisParams":{ +"AnalyzeUncategorizedData":true, +"DefaultTextScanMode":"C64Petscii", +"MinCharsForString":4, +"SeekNearbyTargets":true, +"UseRelocData":false, +"SmartPlpHandling":false, +"SmartPlbHandling":true}, + +"PlatformSymbolFileIdentifiers":["RT:Commodore/C64-Kernal.sym65"], +"ExtensionScriptFileIdentifiers":["RT:Commodore/VisC64.cs"], +"ProjectSyms":{ +}}, + +"AddressMap":[{ +"Offset":2, +"Addr":4096, +"Length":154, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":2, +"Addr":8192, +"Length":18, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":2, +"Addr":12288, +"Length":12, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":26, +"Addr":-1025, +"Length":-1024, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":58, +"Addr":16384, +"Length":74, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":74, +"Addr":20480, +"Length":16, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":106, +"Addr":20488, +"Length":16, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":132, +"Addr":53248, +"Length":24, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":139, +"Addr":57344, +"Length":17, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":145, +"Addr":61440, +"Length":-1024, +"PreLabel":"", +"IsRelative":false}], +"TypeHints":[{ +"Low":2, +"High":2, +"Hint":"Code"}, + +{ +"Low":74, +"High":74, +"Hint":"Code"}, + +{ +"Low":106, +"High":106, +"Hint":"Code"}], +"StatusFlagOverrides":{ +}, + +"Comments":{ +"0":"load address"}, + +"LongComments":{ +}, + +"Notes":{ +}, + +"UserLabels":{ +}, + +"OperandFormats":{ +"0":{ +"Length":2, +"Format":"NumericLE", +"SubFormat":"None", +"SymbolRef":null}, + +"27":{ +"Length":25, +"Format":"StringNullTerm", +"SubFormat":"C64Petscii", +"SymbolRef":null}, + +"53":{ +"Length":2, +"Format":"NumericLE", +"SubFormat":"Address", +"SymbolRef":null}, + +"55":{ +"Length":2, +"Format":"NumericLE", +"SubFormat":"Address", +"SymbolRef":null}}, + +"LvTables":{ +}, + +"Visualizations":[], +"VisualizationAnimations":[], +"VisualizationSets":{ +}, + +"RelocList":{ +}, + +"DbrValues":{ +}} diff --git a/SourceGen/SGTestData/20252-nested-regions b/SourceGen/SGTestData/20252-nested-regions new file mode 100644 index 0000000000000000000000000000000000000000..92ff6d391329bede11e49d3bef666e9ba499f431 GIT binary patch literal 40 rcmZ3_Ai%tyMSxjfUVt%1K!9mI5XVReFs=t;A2or7R|!B#hF1vyl;j9O literal 0 HcmV?d00001 diff --git a/SourceGen/SGTestData/20252-nested-regions.dis65 b/SourceGen/SGTestData/20252-nested-regions.dis65 new file mode 100644 index 0000000..cee85a4 --- /dev/null +++ b/SourceGen/SGTestData/20252-nested-regions.dis65 @@ -0,0 +1,96 @@ +### 6502bench SourceGen dis65 v1.0 ### +{ +"_ContentVersion":5, +"FileDataLength":40, +"FileDataCrc32":-539266680, +"ProjectProps":{ +"CpuName":"65816", +"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":69632, +"Length":40, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":0, +"Addr":135168, +"Length":24, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":0, +"Addr":200704, +"Length":16, +"PreLabel":"", +"IsRelative":true}, + +{ +"Offset":32, +"Addr":-1025, +"Length":6, +"PreLabel":"", +"IsRelative":true}], +"TypeHints":[{ +"Low":0, +"High":0, +"Hint":"Code"}, + +{ +"Low":32, +"High":32, +"Hint":"Code"}], +"StatusFlagOverrides":{ +}, + +"Comments":{ +}, + +"LongComments":{ +}, + +"Notes":{ +}, + +"UserLabels":{ +}, + +"OperandFormats":{ +"34":{ +"Length":4, +"Format":"NumericLE", +"SubFormat":"Address", +"SymbolRef":null}}, + +"LvTables":{ +}, + +"Visualizations":[], +"VisualizationAnimations":[], +"VisualizationSets":{ +}, + +"RelocList":{ +}, + +"DbrValues":{ +}} diff --git a/SourceGen/SGTestData/Expected/20250-nested-regions_64tass.S b/SourceGen/SGTestData/Expected/20250-nested-regions_64tass.S new file mode 100644 index 0000000..7aeb89a --- /dev/null +++ b/SourceGen/SGTestData/Expected/20250-nested-regions_64tass.S @@ -0,0 +1,97 @@ + .cpu "6502" +* = $0000 + .word $3000 ;load address + + .logical $1000 + .logical *+$1000 + .logical *+$1000 +L3000 bit L3000 +_L3003 lda _L3003 + and _LD003 + jmp _L200C + + .here +_L200C bit _L200C + jmp _L1012 + + .here +_L1012 bit _L1012 + jsr _L4000 + .logical $0000 + .byte $00 + .null "Null-term PETSCII string" + .byte $80 + .word _L3003 + .word _LD003 + .byte $80 + .here + + .logical $4000 +_L4000 bit _L4000 + bit _L5000 + bit _L500F + bit _L500F + nop + jmp _L4020 + + .logical $5000 +_L5000 bit _L5000 + bit _L4000 + nop + nop +_L5008 bit _L5008 + bit _L5017 + nop +_L500F rts + + .here +_L4020 bit _L4020 + bit _L500F + nop + nop + nop + nop + nop + nop + nop + jmp _L4040 + + .logical $5008 +_L5008_0 bit _L5008_0 + bit _L5000 + nop +_L500F_0 bit _L500F_0 + nop + nop + nop + nop + nop +_L5017 rts + + .here +_L4040 bit _L4040 + bit _L5017 + nop + jmp _LD000 + + .here + .logical *+$bf7e +_LD000 bit _L200C +_LD003 nop + jmp _LE000 + + .logical $e000 +_LE000 bit _LE000 + jmp _LF000 + + .logical $f000 +_LF000 bit _LF000 + lda _L3003 + and _LD003 + nop + rts + + .here + .here + .here + .here diff --git a/SourceGen/SGTestData/Expected/20250-nested-regions_acme.S b/SourceGen/SGTestData/Expected/20250-nested-regions_acme.S new file mode 100644 index 0000000..c8bb315 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20250-nested-regions_acme.S @@ -0,0 +1,97 @@ + !cpu 6502 +* = $0000 + !word $3000 ;load address + + !pseudopc $1000 { + !pseudopc *+$1000 { + !pseudopc *+$1000 { +L3000 bit L3000 +@L3003 lda @L3003 + and @LD003 + jmp @L200C + + } +@L200C bit @L200C + jmp @L1012 + + } +@L1012 bit @L1012 + jsr @L4000 + !pseudopc $0000 { + !byte $00 + !pet "Null-term PETSCII string",$00 + !byte $80 + !word @L3003 + !word @LD003 + !byte $80 + } + + !pseudopc $4000 { +@L4000 bit @L4000 + bit @L5000 + bit @L500F + bit @L500F + nop + jmp @L4020 + + !pseudopc $5000 { +@L5000 bit @L5000 + bit @L4000 + nop + nop +@L5008 bit @L5008 + bit @L5017 + nop +@L500F rts + + } +@L4020 bit @L4020 + bit @L500F + nop + nop + nop + nop + nop + nop + nop + jmp @L4040 + + !pseudopc $5008 { +@L5008_0 bit @L5008_0 + bit @L5000 + nop +@L500F_0 bit @L500F_0 + nop + nop + nop + nop + nop +@L5017 rts + + } +@L4040 bit @L4040 + bit @L5017 + nop + jmp @LD000 + + } + !pseudopc *+$bf7e { +@LD000 bit @L200C +@LD003 nop + jmp @LE000 + + !pseudopc $e000 { +@LE000 bit @LE000 + jmp @LF000 + + !pseudopc $f000 { +@LF000 bit @LF000 + lda @L3003 + and @LD003 + nop + rts + + } + } + } + } diff --git a/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.S b/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.S new file mode 100644 index 0000000..3f14590 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.S @@ -0,0 +1,90 @@ + .setcpu "6502" + .org $0000 + .word $3000 ;load address + + .org $3000 +L3000: bit L3000 +@L3003: lda @L3003 + and @LD003 + jmp @L200C + + .org $200c +@L200C: bit @L200C + jmp @L1012 + + .org $1012 +@L1012: bit @L1012 + jsr @L4000 + .org $0000 + .byte $00 + .byte $ce,$55,$4c,$4c,$2d,$54,$45,$52,$4d,$20,$d0,$c5,$d4,$d3,$c3,$c9 + .byte $c9,$20,$53,$54,$52,$49,$4e,$47,$00 + .byte $80 + .word @L3003 + .word @LD003 + .byte $80 + + .org $4000 +@L4000: bit @L4000 + bit @L5000 + bit @L500F + bit @L500F + nop + jmp @L4020 + + .org $5000 +@L5000: bit @L5000 + bit @L4000 + nop + nop +@L5008: bit @L5008 + bit @L5017 + nop +@L500F: rts + + .org $4020 +@L4020: bit @L4020 + bit @L500F + nop + nop + nop + nop + nop + nop + nop + jmp @L4040 + + .org $5008 +@L5008_0: bit @L5008_0 + bit @L5000 + nop +@L500F_0: bit @L500F_0 + nop + nop + nop + nop + nop +@L5017: rts + + .org $4040 +@L4040: bit @L4040 + bit @L5017 + nop + jmp @LD000 + + .org $d000 +@LD000: bit @L200C +@LD003: nop + jmp @LE000 + + .org $e000 +@LE000: bit @LE000 + jmp @LF000 + + .org $f000 +@LF000: bit @LF000 + lda @L3003 + and @LD003 + nop + rts + diff --git a/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.cfg b/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.cfg new file mode 100644 index 0000000..c4db7e4 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20250-nested-regions_cc65.cfg @@ -0,0 +1,9 @@ +# 6502bench SourceGen generated linker script for 20250-nested-regions +MEMORY { + MAIN: file=%O, start=%S, size=65536; +} +SEGMENTS { + CODE: load=MAIN, type=rw; +} +FEATURES {} +SYMBOLS {} diff --git a/SourceGen/SGTestData/Expected/20250-nested-regions_merlin32.S b/SourceGen/SGTestData/Expected/20250-nested-regions_merlin32.S new file mode 100644 index 0000000..5986f41 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20250-nested-regions_merlin32.S @@ -0,0 +1,88 @@ + org $0000 + dw $3000 ;load address + + org $3000 +L3000 bit L3000 +:L3003 lda :L3003 + and :LD003 + jmp :L200C + + org $200c +:L200C bit :L200C + jmp :L1012 + + org $1012 +:L1012 bit :L1012 + jsr :L4000 + org $0000 + dfb $00 + hex ce554c4c2d5445524d20d0c5d4d3c3c9c920535452494e4700 + dfb $80 + dw :L3003 + dw :LD003 + dfb $80 + + org $4000 +:L4000 bit :L4000 + bit :L5000 + bit :L500F + bit :L500F + nop + jmp :L4020 + + org $5000 +:L5000 bit :L5000 + bit :L4000 + nop + nop +:L5008 bit :L5008 + bit :L5017 + nop +:L500F rts + + org $4020 +:L4020 bit :L4020 + bit :L500F + nop + nop + nop + nop + nop + nop + nop + jmp :L4040 + + org $5008 +:L5008_0 bit :L5008_0 + bit :L5000 + nop +:L500F_0 bit :L500F_0 + nop + nop + nop + nop + nop +:L5017 rts + + org $4040 +:L4040 bit :L4040 + bit :L5017 + nop + jmp :LD000 + + org $d000 +:LD000 bit :L200C +:LD003 nop + jmp :LE000 + + org $e000 +:LE000 bit :LE000 + jmp :LF000 + + org $f000 +:LF000 bit :LF000 + lda :L3003 + and :LD003 + nop + rts + diff --git a/SourceGen/SGTestData/Expected/20252-nested-regions_64tass.S b/SourceGen/SGTestData/Expected/20252-nested-regions_64tass.S new file mode 100644 index 0000000..f8d7751 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20252-nested-regions_64tass.S @@ -0,0 +1,30 @@ + .cpu "65816" + .logical $011000 + .logical *+$010000 + .logical *+$010000 + .as + .xs +L31000 lda L31000 +_L31004 lda _L31004 + and _L1101F + jml _L21010 + + .here +_L21010 lda _L21010 + jml _L11018 + + .here +_L11018 lda _L11018 + jmp _L11026 + +_L1101F .byte $80 + .logical *-$011020 + .byte $ea + .byte $60 + .dword _L31004 + .here + +_L11026 nop + rts + + .here diff --git a/SourceGen/SGTestData/Expected/20252-nested-regions_acme.S b/SourceGen/SGTestData/Expected/20252-nested-regions_acme.S new file mode 100644 index 0000000..040588e --- /dev/null +++ b/SourceGen/SGTestData/Expected/20252-nested-regions_acme.S @@ -0,0 +1,6 @@ +;ACME can't handle 65816 code that lives outside bank zero +* = $0000 + !pseudopc $031000 { + !hex af001003af0410032f1f10015c101002af1010025c181001af1810014c261080 + !hex ea6004100300ea60 + } diff --git a/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.S b/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.S new file mode 100644 index 0000000..58eb4c2 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.S @@ -0,0 +1,27 @@ + .setcpu "65816" + .org $031000 + .a8 + .i8 +L31000: lda L31000 +@L31004: lda @L31004 + and f:@L1101F + jml @L21010 + + .org $021010 +@L21010: lda @L21010 + jml @L11018 + + .org $011018 +@L11018: lda @L11018 + jmp @L11026 & $ffff + +@L1101F: .byte $80 + .org $0000 + .byte $ea + .byte $60 + .dword @L31004 + + .org $011026 +@L11026: nop + rts + diff --git a/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.cfg b/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.cfg new file mode 100644 index 0000000..5e65efc --- /dev/null +++ b/SourceGen/SGTestData/Expected/20252-nested-regions_cc65.cfg @@ -0,0 +1,9 @@ +# 6502bench SourceGen generated linker script for 20252-nested-regions +MEMORY { + MAIN: file=%O, start=%S, size=65536; +} +SEGMENTS { + CODE: load=MAIN, type=rw; +} +FEATURES {} +SYMBOLS {} diff --git a/SourceGen/SGTestData/Expected/20252-nested-regions_merlin32.S b/SourceGen/SGTestData/Expected/20252-nested-regions_merlin32.S new file mode 100644 index 0000000..a03da82 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20252-nested-regions_merlin32.S @@ -0,0 +1,24 @@ + org $031000 +L31000 ldal L31000 +:L31004 ldal :L31004 + andl :L1101F + jml :L21010 + + org $021010 +:L21010 ldal :L21010 + jml :L11018 + + org $011018 +:L11018 ldal :L11018 + jmp :L11026 + +:L1101F dfb $80 + org $0000 + dfb $ea + dfb $60 + adrl :L31004 + + org $011026 +:L11026 nop + rts + diff --git a/SourceGen/SGTestData/Source/20250-nested-regions.S b/SourceGen/SGTestData/Source/20250-nested-regions.S new file mode 100644 index 0000000..57a1567 --- /dev/null +++ b/SourceGen/SGTestData/Source/20250-nested-regions.S @@ -0,0 +1,137 @@ +; Copyright 2021 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Test nested address regions. +; +; Assembler: 64tass +; % tass64 --ascii --case-sensitive --nostart 20250-nested-regions.S + + .cpu "6502" +* = $1000 +START + .word $3000 + +; NOTE: leave PRG header as a 2-byte hole with no explicit region + +; Start with 3 nested regions that share a starting address. + +; EDIT: create region starting at $1000, ending at REGION_END +; EDIT: make all 3 of these relative (especially the first one, which follows non-addr) + + +; EDIT: create these as fixed-end regions; first one spans full file + .logical $1000 + .logical $2000 + .logical $3000 + +part3k bit part3k +early lda early + and late + jmp part2k + + .here ;$3000; now $20xx + +part2k bit part2k + jmp part1k + + .here ;$2000; now $10xx + +part1k bit part1k + jsr overhole ;let execution try to fall into non-addr + +REGION1_END + +; EDIT: next chunk is a *floating* non-addr region + + brk + .null "Null-term PETSCII string" + .byte $80 + .word early + .word late + .byte $80 + +; 4000-40xx, with two overlapping regions in the $5000 area. Tests order +; of resolution and descent into children. (This is mostly tested internally +; by the AddressMap unit tests, so we don't need to go crazy here.) + + .logical $4000 +overhole +a4000 bit a4000 + bit b5000 + bit b500f ;CHECK: resolves to b500f + bit c500f ;CHECK: also resolves to b500f + nop + jmp a4020 + +; EDIT: set region, add code start tag + .logical $5000 +b5000 bit b5000 +b5003 bit a4000 + nop + nop +b5008 bit b5008 ;CHECK: resolves locally + bit c5017 ;CHECK: resolves to other segment + nop +b500f rts + .here ;$5000, now at $4010 + +a4020 bit a4020 + bit c500f + nop + nop + nop + nop + nop + nop + nop + jmp a4040 + +; EDIT: set region, add code start tag + .logical $5008 +c5008 bit c5008 ;CHECK: resolves locally + bit b5000 ;CHECK: resolves to other segment + nop +c500f bit c500f + nop + nop + nop + nop + nop +c5017 rts + .here ;$5008 + +a4040 bit a4040 + bit c5017 + nop + jmp tailend + .here ;$4000 + + +; EDIT: create region starting at $d000, ending at REGION2_END; relative + .logical $d000 +tailend +partdk bit part2k +late nop + jmp partek + +; EDIT: create + .logical $e000 + +partek bit partek + jmp partfk + +; EDIT: create, make it floating + .logical $f000 + +partfk bit partfk + lda early + and late + +end + nop + rts +REGION2_END + .here ;$f000 + .here ;$e000 + .here ;$d000 + .here ;$1000 diff --git a/SourceGen/SGTestData/Source/20252-nested-regions.S b/SourceGen/SGTestData/Source/20252-nested-regions.S new file mode 100644 index 0000000..ea57fa7 --- /dev/null +++ b/SourceGen/SGTestData/Source/20252-nested-regions.S @@ -0,0 +1,47 @@ +; Copyright 2021 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Test nested address regions. +; +; Assembler: 64tass +; % tass64 --ascii --case-sensitive --nostart 20252-nested-regions.S + + .cpu "65816" +* = $081000 +START + +; Start with 3 nested regions that share a starting address. + +; EDIT: create these as fixed-end regions; first one spans full file + .logical $011000 + .logical $021000 + .logical $031000 + +part3k lda @lpart3k +early lda early + and late + jmp part2k + + .here ;031000 + +part2k lda @lpart2k + jmp part1k + + .here ;021000 + +part1k lda @lpart1k + jmp end + +late .byte $80 + +; EIDT: make this a non-addressable region +; EDIT: put a code start tag here +tag nop + rts + .dword early + +end + nop + rts +REGION2_END + .here ;$011000 diff --git a/SourceGen/WpfGui/EditAddress.xaml b/SourceGen/WpfGui/EditAddress.xaml index 8f9c692..19c95ea 100644 --- a/SourceGen/WpfGui/EditAddress.xaml +++ b/SourceGen/WpfGui/EditAddress.xaml @@ -33,25 +33,47 @@ limitations under the License. Creating new address region Editing existing address region: + + Edit only. + Edit the region's attributes. Region length will not be changed. + + Set fixed size. + Edit the region's attributes, and convert the floating end to a fixed end. + + Resize. + Edit the region's attributes, and resize it to the selection. The new end offset will be {0}, for a length of {1}. - Cannot resize to the selection. + Resize not available: cannot resize to the selection. {0} + + + Create fixed. Create a new region, with a fixed end point. The region will start at {0} and have a length of {1}. + + Create fixed not available: can't convert to fixed end point because it's already fixed. + - Unable to create a new region with a fixed end point here. + Create fixed not available: unable to create a new region with a fixed end point here. + + + Create fixed not available: unable to create a new region with a fixed end point + here, because it would straddle an existing region. + + + Create floating. Create a new region, with a floating end point. The region will start at {0} @@ -59,13 +81,13 @@ limitations under the License. may change as other regions are added and removed. - Unable to create a new region with a floating end point here. + Create floating not available: unable to create a new region with a floating end point here. Internal error. Internal error (invalid value). - The new region has the same start offset and length as an existing region. + The new region would have the same start offset and length as an existing region. The start offset of the new region is the same as the start offset of an existing @@ -77,7 +99,7 @@ limitations under the License. - + @@ -114,7 +136,7 @@ limitations under the License. IsEnabled="{Binding EnableOption1}" IsChecked="{Binding CheckOption1}"> - + - + @@ -151,8 +173,8 @@ limitations under the License. - - + + @@ -173,9 +195,9 @@ limitations under the License. - - - + + + diff --git a/SourceGen/WpfGui/EditAddress.xaml.cs b/SourceGen/WpfGui/EditAddress.xaml.cs index 7b15e4c..0b7b780 100644 --- a/SourceGen/WpfGui/EditAddress.xaml.cs +++ b/SourceGen/WpfGui/EditAddress.xaml.cs @@ -18,7 +18,8 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Windows; - +using System.Windows.Controls; +using System.Windows.Documents; using Asm65; using CommonUtil; @@ -109,18 +110,6 @@ namespace SourceGen.WpfGui { } private bool mCheckOption2; - public string Option1Str { - get { return mOption1Str; } - set { mOption1Str = value; OnPropertyChanged(); } - } - private string mOption1Str; - - public string Option2Str { - get { return mOption2Str; } - set { mOption2Str = value; OnPropertyChanged(); } - } - private string mOption2Str; - /// /// Address at which a pre-label would be placed. This is determined by the parent /// region, so its value is fixed. @@ -279,6 +268,11 @@ namespace SourceGen.WpfGui { CheckOption1 = true; EnableAttributeControls = true; + string option1Summ; + string option1Msg; + string option2Summ; + string option2Msg; + if (curRegion != null) { // Editing an existing region. CanDeleteRegion = true; @@ -304,14 +298,18 @@ namespace SourceGen.WpfGui { mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset, curRegion.Length, curRegion.Address, curRegion.PreLabel, curRegion.IsRelative); - Option1Str = (string)FindResource("str_OptEditAsIs"); - Option2Str = (string)FindResource("str_OptEditAndFix"); + option1Summ = (string)FindResource("str_OptEditAsIsSummary"); + option1Msg = (string)FindResource("str_OptEditAsIs"); if (curRegion.IsFloating) { + option2Summ = (string)FindResource("str_OptEditAndFixSummary"); + option2Msg = (string)FindResource("str_OptEditAndFix"); mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset, curRegion.ActualLength, curRegion.Address, curRegion.PreLabel, curRegion.IsRelative); } else { + option2Summ = string.Empty; + option2Msg = (string)FindResource("str_CreateFixedAlreadyFixed"); mResultEntry2 = null; EnableOption2 = false; // show it, but disabled } @@ -328,11 +326,13 @@ namespace SourceGen.WpfGui { curRegion.Length, curRegion.Address, curRegion.PreLabel, curRegion.IsRelative); + option1Summ = (string)FindResource("str_OptResizeSummary"); string fmt = (string)FindResource("str_OptResize"); - Option1Str = string.Format(fmt, + option1Msg = string.Format(fmt, mFormatter.FormatOffset24(curRegion.Offset + selectionLen - 1), FormatLength(selectionLen)); - Option2Str = (string)FindResource("str_OptEditAsIs"); + option2Summ = (string)FindResource("str_OptEditAsIsSummary"); + option2Msg = (string)FindResource("str_OptEditAsIs"); Debug.Assert(selectionLen > 0); AddressMap.AddResult ares; @@ -340,7 +340,9 @@ namespace SourceGen.WpfGui { curRegion.Address, out ares); if (ares != AddressMap.AddResult.Okay) { // Can't resize the new region, so disable that option (still visible). - Option1Str = (string)FindResource("str_OptResizeFail"); + option1Summ = string.Empty; + string fmta = (string)FindResource("str_OptResizeFail"); + option1Msg = string.Format(fmta, GetErrorString(ares)); EnableOption1 = false; CheckOption2 = true; } @@ -378,13 +380,19 @@ namespace SourceGen.WpfGui { mResultEntry1 = new AddressMap.AddressMapEntry(newEntry.Offset, newRegion1.ActualLength, newEntry.Address, string.Empty, false); + option1Summ = (string)FindResource("str_CreateFixedSummary"); string fmt = (string)FindResource("str_CreateFixed"); - Option1Str = string.Format(fmt, + option1Msg = string.Format(fmt, mFormatter.FormatOffset24(newEntry.Offset), FormatLength(newRegion1.ActualLength)); mPreLabelAddress = newRegion1.PreLabelAddress; } else { - Option1Str = (string)FindResource("str_CreateFixedFail"); + option1Summ = string.Empty; + if (ares1 == AddressMap.AddResult.StraddleExisting) { + option1Msg = (string)FindResource("str_CreateFixedFailStraddle"); + } else { + option1Msg = (string)FindResource("str_CreateFixedFail"); + } CheckOption2 = true; EnableOption1 = false; } @@ -392,13 +400,15 @@ namespace SourceGen.WpfGui { mResultEntry2 = new AddressMap.AddressMapEntry(newEntry.Offset, AddressMap.FLOATING_LEN, newEntry.Address, string.Empty, false); + option2Summ = (string)FindResource("str_CreateFloatingSummary"); string fmt = (string)FindResource("str_CreateFloating"); - Option2Str = string.Format(fmt, + option2Msg = string.Format(fmt, mFormatter.FormatOffset24(newEntry.Offset), FormatLength(newRegion2.ActualLength)); mPreLabelAddress = newRegion2.PreLabelAddress; } else { - Option2Str = (string)FindResource("str_CreateFloatingFail"); + option2Summ = string.Empty; + option2Msg = (string)FindResource("str_CreateFloatingFail"); CheckOption1 = true; CheckOption2 = false; // required for some reason EnableOption2 = false; @@ -412,6 +422,20 @@ namespace SourceGen.WpfGui { SetErrorString(ares1); } } + + TextBlock tb1 = option1TextBlock; + tb1.Inlines.Clear(); + if (!string.IsNullOrEmpty(option1Summ)) { + tb1.Inlines.Add(new Run(option1Summ + " ") { FontWeight = FontWeights.Bold }); + } + tb1.Inlines.Add(option1Msg); + + TextBlock tb2 = option2TextBlock; + tb2.Inlines.Clear(); + if (!string.IsNullOrEmpty(option2Summ)) { + tb2.Inlines.Add(new Run(option2Summ + " ") { FontWeight = FontWeights.Bold }); + } + tb2.Inlines.Add(option2Msg); } private string FormatLength(int len) { @@ -442,7 +466,7 @@ namespace SourceGen.WpfGui { return newRegion; } - private void SetErrorString(AddressMap.AddResult result) { + private string GetErrorString(AddressMap.AddResult result) { string rsrc; switch (result) { case AddressMap.AddResult.InternalError: @@ -458,15 +482,18 @@ namespace SourceGen.WpfGui { rsrc = "str_ErrOverlapFloating"; break; case AddressMap.AddResult.StraddleExisting: - rsrc = "str_ErrStraddelExisting"; + rsrc = "str_ErrStraddleExisting"; break; default: Debug.Assert(false); rsrc = "str_ErrInternal"; break; } + return(string)FindResource(rsrc); // throws exception on failure + } - ErrorMessageStr = (string)FindResource(rsrc); // throws exception on failure + private void SetErrorString(AddressMap.AddResult result) { + ErrorMessageStr = GetErrorString(result); ShowErrorMessage = true; } diff --git a/SourceGen/WpfGui/EditLabel.xaml b/SourceGen/WpfGui/EditLabel.xaml index a198968..83e7090 100644 --- a/SourceGen/WpfGui/EditLabel.xaml +++ b/SourceGen/WpfGui/EditLabel.xaml @@ -51,6 +51,8 @@ limitations under the License. + diff --git a/SourceGen/WpfGui/EditLabel.xaml.cs b/SourceGen/WpfGui/EditLabel.xaml.cs index 7ead04c..c82ce70 100644 --- a/SourceGen/WpfGui/EditLabel.xaml.cs +++ b/SourceGen/WpfGui/EditLabel.xaml.cs @@ -121,6 +121,8 @@ namespace SourceGen.WpfGui { set { mIsExportedEnabled = value; OnPropertyChanged(); } } + public Visibility NonAddrWarningVis { get; private set; } + // INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = "") { @@ -142,6 +144,12 @@ namespace SourceGen.WpfGui { string fmt = (string)FindResource("str_NonUniqueLocalFmt"); NonUniqueButtonLabel = string.Format(fmt, mFormatter.NonUniqueLabelPrefix); + + if (mAddress == Address.NON_ADDR) { + NonAddrWarningVis = Visibility.Visible; + } else { + NonAddrWarningVis = Visibility.Collapsed; + } } private void Window_Loaded(object sender, RoutedEventArgs e) { diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml index 1c45e54..ba1a156 100644 --- a/SourceGen/WpfGui/MainWindow.xaml +++ b/SourceGen/WpfGui/MainWindow.xaml @@ -425,12 +425,12 @@ limitations under the License. - - - + + +