diff --git a/CommonUtil/AddressMap.cs b/CommonUtil/AddressMap.cs index fb96db9..db7d85e 100644 --- a/CommonUtil/AddressMap.cs +++ b/CommonUtil/AddressMap.cs @@ -24,13 +24,13 @@ namespace CommonUtil { /// multiple ORG directives. /// /// It's possible to generate code that would overlap once relocated at run time, - /// which means a given address could map to multiple offsets. For this reason - /// it's useful to know the offset of the referring code when evaluating a - /// reference, so that a "local" match can take priority. + /// which means a given address can map to multiple offsets (overlays, bank-switched + /// RAM, etc). For this reason it's useful to know the offset of the referring code + /// when evaluating a reference, so that "local" matches take priority. /// /// /// This was part of the main SourceGen application, but I want to share it with - /// script extensions. + /// the extension script mechanism. /// public class AddressMap : IEnumerable { public const int NO_ENTRY_ADDR = -1; // address value indicating no entry @@ -44,31 +44,19 @@ namespace CommonUtil { /// entry in the list. It's convenient to maintain it explicitly however, as /// the list is read far more often than it is updated. /// - /// Entries are mutable, but must only be altered by AddressMap. Don't retain - /// instances of this across other activity. + /// Instances are immutable. /// - /// - /// TODO: make this immutable. That should allow us to eliminate the copy constructor, - /// since we won't need to make copies of things. - /// [Serializable] public class AddressMapEntry { - public int Offset { get; set; } - public int Addr { get; set; } - public int Length { get; set; } + public int Offset { get; private set; } + public int Addr { get; private set; } + public int Length { get; private set; } public AddressMapEntry(int offset, int addr, int len) { Offset = offset; Addr = addr; Length = len; } - - // Copy constructor. - public AddressMapEntry(AddressMapEntry src) { - Offset = src.Offset; - Addr = src.Addr; - Length = src.Length; - } } /// @@ -99,7 +87,7 @@ namespace CommonUtil { public AddressMap(List entries) { mTotalLength = entries[entries.Count - 1].Offset + entries[entries.Count - 1].Length; foreach (AddressMapEntry ent in entries) { - mAddrList.Add(new AddressMapEntry(ent)); + mAddrList.Add(ent); } DebugValidate(); } @@ -111,7 +99,7 @@ namespace CommonUtil { public List GetEntryList() { List newList = new List(mAddrList.Count); foreach (AddressMapEntry ent in mAddrList) { - newList.Add(new AddressMapEntry(ent)); + newList.Add(ent); } return newList; } @@ -186,8 +174,7 @@ namespace CommonUtil { AddressMapEntry ad = mAddrList[i]; if (ad.Offset == offset) { // update existing - ad.Addr = addr; - mAddrList[i] = ad; + mAddrList[i] = new AddressMapEntry(ad.Offset, addr, ad.Length); return; } else if (ad.Offset > offset) { // The i'th entry is one past the interesting part. @@ -199,8 +186,7 @@ namespace CommonUtil { AddressMapEntry prev = mAddrList[i - 1]; int prevOldLen = prev.Length; int prevNewLen = offset - prev.Offset; - prev.Length = prevNewLen; - mAddrList[i - 1] = prev; + mAddrList[i - 1] = new AddressMapEntry(prev.Offset, prev.Addr, prevNewLen); mAddrList.Insert(i, new AddressMapEntry(offset, addr, prevOldLen - prevNewLen)); @@ -223,8 +209,8 @@ namespace CommonUtil { if (mAddrList[i].Offset == offset) { // Add the length to the previous entry. AddressMapEntry prev = mAddrList[i - 1]; - prev.Length += mAddrList[i].Length; - mAddrList[i - 1] = prev; + mAddrList[i - 1] = new AddressMapEntry(prev.Offset, prev.Addr, + prev.Length + mAddrList[i].Length); mAddrList.RemoveAt(i); DebugValidate(); @@ -297,13 +283,14 @@ namespace CommonUtil { } /// - /// Checks to see if the specified range of offsets is in a contiguous range of - /// addresses. Use this to see if something crosses an address-change boundary. + /// Checks to see if the specified range of offsets is in a single address range. Use + /// this to see if something crosses an address-change boundary. This does not + /// handle no-op address changes specially. /// /// Start offset. /// Length of region. /// True if the data area is unbroken. - public bool IsContiguous(int offset, int length) { + public bool IsSingleAddrRange(int offset, int length) { Debug.Assert(offset >= 0 && offset < mTotalLength); Debug.Assert(length > 0 && offset + length <= mTotalLength); return (IndexForOffset(offset) == IndexForOffset(offset + length - 1)); diff --git a/SourceGen/CodeAnalysis.cs b/SourceGen/CodeAnalysis.cs index c677321..112c523 100644 --- a/SourceGen/CodeAnalysis.cs +++ b/SourceGen/CodeAnalysis.cs @@ -1044,7 +1044,7 @@ namespace SourceGen { " label='" + label + "'; file length is" + mFileData.Length); } - if (!mAddrMap.IsContiguous(offset, length)) { + if (!mAddrMap.IsSingleAddrRange(offset, length)) { LogW(offset, "SIDF: format crosses address map boundary (len=" + length + ")"); return false; } diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs index affec10..ebe0932 100644 --- a/SourceGen/DataAnalysis.cs +++ b/SourceGen/DataAnalysis.cs @@ -533,8 +533,8 @@ namespace SourceGen { int startOffset = -1; for (int offset = 0; offset < mAnattribs.Length; ) { // We want to find a contiguous series of offsets which are not known - // to hold code or data. We stop if we encounter a user-defined label - // or format descriptor. + // to hold code or data. We stop if we encounter a user-defined label, + // format descriptor, or address override. Anattrib attr = mAnattribs[offset]; if (attr.IsInstruction || attr.IsInlineData || attr.IsDataStart) { @@ -572,19 +572,17 @@ namespace SourceGen { } offset++; - // Check to see if the address has changed from the previous entry. - // TODO(BUG): this test is insufficient -- they might have a .ORG that - // doesn't change the address. It's currently harmless because the - // .ORG is a no-op and gets swallowed up by the asm generator, but it - // looks wrong and could break things. + // Check to see if we just crossed an address change. if (offset < mAnattribs.Length && - mAnattribs[offset-1].Address + 1 != mAnattribs[offset].Address) { - // Must be an ORG here. Scan previous region. + !mProject.AddrMap.IsSingleAddrRange(offset - 1, 2)) { + // Must be an ORG here. End region and scan. AnalyzeRange(startOffset, offset - 1); startOffset = -1; } } } + + // Do the last bit. if (startOffset >= 0) { AnalyzeRange(startOffset, mAnattribs.Length - 1); } diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs index b4e4c82..527c1c2 100644 --- a/SourceGen/DisasmProject.cs +++ b/SourceGen/DisasmProject.cs @@ -969,7 +969,7 @@ namespace SourceGen { continue; } - if (!AddrMap.IsContiguous(offset, dfd.Length)) { + if (!AddrMap.IsSingleAddrRange(offset, dfd.Length)) { string msg = "descriptor straddles address change; len=" + dfd.Length; genLog.LogE("+" + offset.ToString("x6") + ": " + msg); Messages.Add(new MessageList.MessageEntry( diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index f3ea691..04c853a 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -2479,7 +2479,7 @@ namespace SourceGen { // This must match what GroupedOffsetSetFromSelected() does. if (!mProject.UserLabels.ContainsKey(nextOffset) && !mProject.HasCommentNoteOrVis(nextOffset) && - thisAttr.Address == nextAttr.Address - 1) { + mProject.AddrMap.IsSingleAddrRange(nextOffset - 1, 2)) { // Good to go. Debug.WriteLine("Grabbing second byte from +" + nextOffset.ToString("x6")); trs.Add(nextOffset, rng.Type); @@ -3362,6 +3362,9 @@ namespace SourceGen { /// or a string. It should not be possible to select part of a formatted section, /// unless the user has been playing weird games with type hints to get overlapping /// format descriptors. + /// + /// The type values used in the TypedRangeSet may not be contiguous. They're only + /// there to create group separation from otherwise contiguous address ranges. /// /// TypedRangeSet with all offsets. private TypedRangeSet GroupedOffsetSetFromSelected() { @@ -3394,12 +3397,18 @@ namespace SourceGen { if (attr.Address != expectedAddr) { // For a contiguous selection, this should only happen if there's a .ORG // address change. For non-contiguous selection this is expected. In the - // latter case, incrementing the group number is unnecessary but harmless. - Debug.WriteLine("Address break: " + attr.Address + " vs. " + expectedAddr); - //Debug.Assert(mProject.AddrMap.Get(offset) >= 0); - + // latter case, incrementing the group number is unnecessary but harmless + // (the TypedRangeSet splits at the gap). + //Debug.WriteLine("Address break: $" + attr.Address.ToString("x4") + " vs. $" + // + expectedAddr.ToString("x4")); expectedAddr = attr.Address; groupNum++; + } else if (offset > 0 && !mProject.AddrMap.IsSingleAddrRange(offset - 1, 2)) { + // Was the previous byte in a different address range? This is only + // strictly necessary if the previous byte was in the selection set (which + // it won't be if the selection starts at the beginning of an address + // range), but bumping the group number is harmless if it wasn't. + groupNum++; } else if (mProject.UserLabels.ContainsKey(offset)) { //if (mProject.GetAnattrib(offset).Symbol != null) { // We consider auto labels when splitting regions for the data analysis, diff --git a/SourceGen/SGTestData/2004-numeric-types.dis65 b/SourceGen/SGTestData/2004-numeric-types.dis65 index eb025a3..6d9a8ac 100644 --- a/SourceGen/SGTestData/2004-numeric-types.dis65 +++ b/SourceGen/SGTestData/2004-numeric-types.dis65 @@ -1,89 +1,248 @@ ### 6502bench SourceGen dis65 v1.0 ### { -"_ContentVersion":3,"FileDataLength":1200,"FileDataCrc32":1114187983,"ProjectProps":{ -"CpuName":"6502","IncludeUndocumentedInstr":false,"TwoByteBrk":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{ -"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true}, -"PlatformSymbolFileIdentifiers":[],"ExtensionScriptFileIdentifiers":["PROJ:2004-numeric-types.cs"],"ProjectSyms":{ +"_ContentVersion":3, +"FileDataLength":1200, +"FileDataCrc32":1114187983, +"ProjectProps":{ +"CpuName":"6502", +"IncludeUndocumentedInstr":false, +"TwoByteBrk":false, +"EntryFlags":32702671, +"AutoLabelStyle":"Simple", +"AnalysisParams":{ +"AnalyzeUncategorizedData":true, +"DefaultTextScanMode":"LowHighAscii", +"MinCharsForString":4, +"SeekNearbyTargets":true, +"SmartPlpHandling":true}, + +"PlatformSymbolFileIdentifiers":[], +"ExtensionScriptFileIdentifiers":["PROJ:2004-numeric-types.cs"], +"ProjectSyms":{ }}, + "AddressMap":[{ -"Offset":0,"Addr":4096}, +"Offset":0, +"Addr":4096}, + { -"Offset":1032,"Addr":5128}, +"Offset":1032, +"Addr":5128}, + { -"Offset":1048,"Addr":5160}],"TypeHints":[{ -"Low":0,"High":0,"Hint":"Code"}],"StatusFlagOverrides":{ +"Offset":1048, +"Addr":5160}], +"TypeHints":[{ +"Low":0, +"High":0, +"Hint":"Code"}], +"StatusFlagOverrides":{ }, + "Comments":{ -"588":"comment on bulk","882":"incorrect alignment","1128":"end-of-line comment"}, +"588":"comment on bulk", +"882":"incorrect alignment", +"1032":"note no-op .ORG", +"1048":"meaningful .ORG", +"1128":"end-of-line comment"}, + "LongComments":{ "-2147483647":{ -"Text":"Project file was edited to get all big-endian data types, and to have an incorrect .junk alignment directive.","BoxMode":false,"MaxWidth":80,"BackgroundColor":0}, +"Text":"Project file was edited to get all big-endian data types, and to have an incorrect .junk alignment directive.", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + "1112":{ -"Text":"long comment\r\n","BoxMode":false,"MaxWidth":80,"BackgroundColor":0}}, +"Text":"long comment\r\n", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}}, + "Notes":{ "1144":{ -"Text":":ETON","BoxMode":false,"MaxWidth":80,"BackgroundColor":0}}, +"Text":":ETON", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}}, + "UserLabels":{ "588":{ -"Label":"LABEL","Value":4684,"Source":"User","Type":"GlobalAddr","LabelAnno":"None"}, +"Label":"LABEL", +"Value":4684, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}, + "1064":{ -"Label":"UserLabel","Value":5176,"Source":"User","Type":"GlobalAddr","LabelAnno":"None"}}, +"Label":"UserLabel", +"Value":5176, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}}, + "OperandFormats":{ "23":{ -"Length":1,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null}, +"Length":1, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + "24":{ -"Length":2,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null}, +"Length":2, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + "26":{ -"Length":3,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null}, +"Length":3, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + "29":{ -"Length":4,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null}, +"Length":4, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + "33":{ -"Length":1,"Format":"NumericBE","SubFormat":"Hex","SymbolRef":null}, +"Length":1, +"Format":"NumericBE", +"SubFormat":"Hex", +"SymbolRef":null}, + "34":{ -"Length":2,"Format":"NumericBE","SubFormat":"Hex","SymbolRef":null}, +"Length":2, +"Format":"NumericBE", +"SubFormat":"Hex", +"SymbolRef":null}, + "36":{ -"Length":3,"Format":"NumericBE","SubFormat":"Hex","SymbolRef":null}, +"Length":3, +"Format":"NumericBE", +"SubFormat":"Hex", +"SymbolRef":null}, + "39":{ -"Length":4,"Format":"NumericBE","SubFormat":"Hex","SymbolRef":null}, +"Length":4, +"Format":"NumericBE", +"SubFormat":"Hex", +"SymbolRef":null}, + "43":{ -"Length":2,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":2, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "46":{ -"Length":3,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":3, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "50":{ -"Length":4,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":4, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "55":{ -"Length":5,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":5, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "61":{ -"Length":256,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":256, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "318":{ -"Length":257,"Format":"Fill","SubFormat":"None","SymbolRef":null}, +"Length":257, +"Format":"Fill", +"SubFormat":"None", +"SymbolRef":null}, + "575":{ -"Length":1,"Format":"Dense","SubFormat":"None","SymbolRef":null}, +"Length":1, +"Format":"Dense", +"SubFormat":"None", +"SymbolRef":null}, + "577":{ -"Length":10,"Format":"Dense","SubFormat":"None","SymbolRef":null}, +"Length":10, +"Format":"Dense", +"SubFormat":"None", +"SymbolRef":null}, + "588":{ -"Length":64,"Format":"Dense","SubFormat":"None","SymbolRef":null}, +"Length":64, +"Format":"Dense", +"SubFormat":"None", +"SymbolRef":null}, + "653":{ -"Length":115,"Format":"Junk","SubFormat":"Align256","SymbolRef":null}, +"Length":115, +"Format":"Junk", +"SubFormat":"Align256", +"SymbolRef":null}, + "769":{ -"Length":63,"Format":"Junk","SubFormat":"Align64","SymbolRef":null}, +"Length":63, +"Format":"Junk", +"SubFormat":"Align64", +"SymbolRef":null}, + "833":{ -"Length":31,"Format":"Junk","SubFormat":"Align32","SymbolRef":null}, +"Length":31, +"Format":"Junk", +"SubFormat":"Align32", +"SymbolRef":null}, + "864":{ -"Length":8,"Format":"Junk","SubFormat":"None","SymbolRef":null}, +"Length":8, +"Format":"Junk", +"SubFormat":"None", +"SymbolRef":null}, + "873":{ -"Length":8,"Format":"Junk","SubFormat":"None","SymbolRef":null}, +"Length":8, +"Format":"Junk", +"SubFormat":"None", +"SymbolRef":null}, + "882":{ -"Length":2,"Format":"Junk","SubFormat":"Align128","SymbolRef":null}, +"Length":2, +"Format":"Junk", +"SubFormat":"Align128", +"SymbolRef":null}, + "884":{ -"Length":140,"Format":"Junk","SubFormat":"Align256","SymbolRef":null}, +"Length":140, +"Format":"Junk", +"SubFormat":"Align256", +"SymbolRef":null}, + "1192":{ -"Length":1,"Format":"NumericLE","SubFormat":"Binary","SymbolRef":null}}, +"Length":1, +"Format":"NumericLE", +"SubFormat":"Binary", +"SymbolRef":null}}, + "LvTables":{ "1096":{ -"Variables":[],"ClearPrevious":true}}, +"Variables":[], +"ClearPrevious":true}}, + "Visualizations":[{ -"Tag":"vis000488","VisGenIdent":"dummy","VisGenParams":{ -}}],"VisualizationAnimations":[],"VisualizationSets":{ +"Tag":"vis000488", +"VisGenIdent":"dummy", +"VisGenParams":{ +}}], +"VisualizationAnimations":[], +"VisualizationSets":{ "1160":{ "Tags":["vis000488"]}}} diff --git a/SourceGen/SGTestData/2024-ui-edge-cases b/SourceGen/SGTestData/2024-ui-edge-cases new file mode 100644 index 0000000..bdcf36f Binary files /dev/null and b/SourceGen/SGTestData/2024-ui-edge-cases differ diff --git a/SourceGen/SGTestData/2024-ui-edge-cases.dis65 b/SourceGen/SGTestData/2024-ui-edge-cases.dis65 new file mode 100644 index 0000000..6f1e970 --- /dev/null +++ b/SourceGen/SGTestData/2024-ui-edge-cases.dis65 @@ -0,0 +1,71 @@ +### 6502bench SourceGen dis65 v1.0 ### +{ +"_ContentVersion":3, +"FileDataLength":50, +"FileDataCrc32":-1443914879, +"ProjectProps":{ +"CpuName":"6502", +"IncludeUndocumentedInstr":false, +"TwoByteBrk":false, +"EntryFlags":32702671, +"AutoLabelStyle":"Simple", +"AnalysisParams":{ +"AnalyzeUncategorizedData":true, +"DefaultTextScanMode":"LowHighAscii", +"MinCharsForString":4, +"SeekNearbyTargets":true, +"SmartPlpHandling":true}, + +"PlatformSymbolFileIdentifiers":["RT:Apple/F8-ROM.sym65", +"RT:Apple/Cxxx-IO.sym65", +"RT:Apple/DOS33.sym65"], +"ExtensionScriptFileIdentifiers":["RT:Apple/VisHiRes.cs"], +"ProjectSyms":{ +}}, + +"AddressMap":[{ +"Offset":0, +"Addr":8192}, + +{ +"Offset":10, +"Addr":8202}, + +{ +"Offset":16, +"Addr":8448}], +"TypeHints":[{ +"Low":0, +"High":0, +"Hint":"Code"}], +"StatusFlagOverrides":{ +}, + +"Comments":{ +"3":"string should be split by no-op addr change", +"18":"edit this operand"}, + +"LongComments":{ +}, + +"Notes":{ +}, + +"UserLabels":{ +"44":{ +"Label":"addr1", +"Value":8476, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}}, + +"OperandFormats":{ +}, + +"LvTables":{ +}, + +"Visualizations":[], +"VisualizationAnimations":[], +"VisualizationSets":{ +}} diff --git a/SourceGen/SGTestData/Expected/2004-numeric-types_64tass.S b/SourceGen/SGTestData/Expected/2004-numeric-types_64tass.S index 9784107..8d3daea 100644 --- a/SourceGen/SGTestData/Expected/2004-numeric-types_64tass.S +++ b/SourceGen/SGTestData/Expected/2004-numeric-types_64tass.S @@ -63,10 +63,13 @@ LABEL .byte $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff .byte $81 .fill 2,$dd ;incorrect alignment .align 256,$00 - .fill 16,$82 + .fill 8,$82 + .logical $1408 + .fill 8,$82 ;note no-op .ORG .fill 8,$83 + .here .logical $1428 - .fill 8,$83 + .fill 8,$83 ;meaningful .ORG .fill 8,$84 UserLabel .fill 8,$84 .fill 8,$85 diff --git a/SourceGen/SGTestData/Expected/2004-numeric-types_Merlin32.S b/SourceGen/SGTestData/Expected/2004-numeric-types_Merlin32.S index ef6bf4d..c103745 100644 --- a/SourceGen/SGTestData/Expected/2004-numeric-types_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2004-numeric-types_Merlin32.S @@ -58,10 +58,12 @@ LABEL hex 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff dfb $81 ds 2,$dd ;incorrect alignment ds \ - ds 16,$82 + ds 8,$82 + org $1408 + ds 8,$82 ;note no-op .ORG ds 8,$83 org $1428 - ds 8,$83 + ds 8,$83 ;meaningful .ORG ds 8,$84 UserLabel ds 8,$84 ds 8,$85 diff --git a/SourceGen/SGTestData/Expected/2004-numeric-types_acme.S b/SourceGen/SGTestData/Expected/2004-numeric-types_acme.S index 0324208..69ed4b0 100644 --- a/SourceGen/SGTestData/Expected/2004-numeric-types_acme.S +++ b/SourceGen/SGTestData/Expected/2004-numeric-types_acme.S @@ -59,10 +59,13 @@ LABEL !hex 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff !byte $81 !fill 2,$dd ;incorrect alignment !align 255,0,$00 - !fill 16,$82 + !fill 8,$82 + !pseudopc $1408 { + !fill 8,$82 ;note no-op .ORG !fill 8,$83 + } ;!pseudopc !pseudopc $1428 { - !fill 8,$83 + !fill 8,$83 ;meaningful .ORG !fill 8,$84 UserLabel !fill 8,$84 !fill 8,$85 diff --git a/SourceGen/SGTestData/Expected/2004-numeric-types_cc65.S b/SourceGen/SGTestData/Expected/2004-numeric-types_cc65.S index 5f21c6a..32edd7f 100644 --- a/SourceGen/SGTestData/Expected/2004-numeric-types_cc65.S +++ b/SourceGen/SGTestData/Expected/2004-numeric-types_cc65.S @@ -62,11 +62,14 @@ LABEL: .byte $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff .byte $81 .res 2,$dd ;incorrect alignment .res 140,$00 - .res 16,$82 + .res 8,$82 +; .segment "SEG001" + .org $1408 + .res 8,$82 ;note no-op .ORG .res 8,$83 ; .segment "SEG002" .org $1428 - .res 8,$83 + .res 8,$83 ;meaningful .ORG .res 8,$84 UserLabel: .res 8,$84 .res 8,$85 diff --git a/SourceGen/SGTestData/Expected/2024-ui-edge-cases_64tass.S b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_64tass.S new file mode 100644 index 0000000..38d3533 --- /dev/null +++ b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_64tass.S @@ -0,0 +1,25 @@ + .cpu "6502" + .enc sg_ascii + .cdef $20,$7e,$20 +* = $2000 + jmp L2100 + + .text "hello, " ;string should be split by no-op addr change + .logical $200a + .text "world" + .byte $80 + + .here + .logical $2100 +L2100 lda #$00 + sta addr1-1 ;edit this operand + sta addr1 + sta addr1+1 + jmp L2121 + + .text "testing stuff." +addr1 .text "!?---" + +L2121 rts + + .here diff --git a/SourceGen/SGTestData/Expected/2024-ui-edge-cases_Merlin32.S b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_Merlin32.S new file mode 100644 index 0000000..532cea4 --- /dev/null +++ b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_Merlin32.S @@ -0,0 +1,20 @@ + org $2000 + jmp L2100 + + asc 'hello, ' ;string should be split by no-op addr change + org $200a + asc 'world' + dfb $80 + + org $2100 +L2100 lda #$00 + sta addr1-1 ;edit this operand + sta addr1 + sta addr1+1 + jmp L2121 + + asc 'testing stuff.' +addr1 asc '!?---' + +L2121 rts + diff --git a/SourceGen/SGTestData/Expected/2024-ui-edge-cases_acme.S b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_acme.S new file mode 100644 index 0000000..b714551 --- /dev/null +++ b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_acme.S @@ -0,0 +1,23 @@ + !cpu 6502 +* = $2000 + jmp L2100 + + !text "hello, " ;string should be split by no-op addr change + !pseudopc $200a { + !text "world" + !byte $80 + + } ;!pseudopc + !pseudopc $2100 { +L2100 lda #$00 + sta addr1-1 ;edit this operand + sta addr1 + sta addr1+1 + jmp L2121 + + !text "testing stuff." +addr1 !text "!?---" + +L2121 rts + + } ;!pseudopc diff --git a/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.S b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.S new file mode 100644 index 0000000..aff9ea9 --- /dev/null +++ b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.S @@ -0,0 +1,24 @@ + .setcpu "6502" +; .segment "SEG000" + .org $2000 + jmp L2100 + + .byte "hello, " ;string should be split by no-op addr change +; .segment "SEG001" + .org $200a + .byte "world" + .byte $80 + +; .segment "SEG002" + .org $2100 +L2100: lda #$00 + sta addr1-1 ;edit this operand + sta addr1 + sta addr1+1 + jmp L2121 + + .byte "testing stuff." +addr1: .byte "!?---" + +L2121: rts + diff --git a/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.cfg b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.cfg new file mode 100644 index 0000000..114145f --- /dev/null +++ b/SourceGen/SGTestData/Expected/2024-ui-edge-cases_cc65.cfg @@ -0,0 +1,15 @@ +# 6502bench SourceGen generated linker script for 2024-ui-edge-cases +MEMORY { + MAIN: file=%O, start=%S, size=65536; +# MEM000: file=%O, start=$2000, size=10; +# MEM001: file=%O, start=$200a, size=6; +# MEM002: file=%O, start=$2100, size=34; +} +SEGMENTS { + CODE: load=MAIN, type=rw; +# SEG000: load=MEM000, type=rw; +# SEG001: load=MEM001, type=rw; +# SEG002: load=MEM002, type=rw; +} +FEATURES {} +SYMBOLS {} diff --git a/SourceGen/SGTestData/Source/2024-ui-edge-cases.S b/SourceGen/SGTestData/Source/2024-ui-edge-cases.S new file mode 100644 index 0000000..4da7d23 --- /dev/null +++ b/SourceGen/SGTestData/Source/2024-ui-edge-cases.S @@ -0,0 +1,33 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; These tests are for exercising UI edge cases. They're not necessarily +; meaningful for the generate/assemble regression test. +; +; Assembler: Merlin 32 + + ORG $2000 + + jmp skip + + asc 'hello, ' + ORG $200a ;EDIT: add this no-op ORG statement + asc 'world' ;(string finder should split the string) + dfb $80 + + org $2100 ;EDIT: add this +skip + lda #$00 + sta addr0 ;TEST: edit this operand ("addr1-1") + sta addr1 + sta addr2 + jmp done + +L1 asc 'testing stuff' +addr0 asc '.' +addr1 asc '!' ;EDIT: place label here +addr2 asc '?' + asc '---' + + +done rts