Fix DCI string edge case

If a DCI string ended with a string delimiter or non-ASCII character
(e.g. a PETSCII char with no ASCII equivalent), the code generator
output the last byte as a hex value.  This caused an error because it
was outputting the raw hex value, with the high bit already set, which
the assembler did not expect.

This change corrects the behavior for code generation and on-screen
display, and adds a few samples to the regression test suite.

(see issue #102)
This commit is contained in:
Andy McFadden 2021-08-10 14:08:39 -07:00
parent fa1b0af932
commit 635084db9d
27 changed files with 617 additions and 89 deletions

View File

@ -31,8 +31,17 @@ namespace Asm65 {
/// </summary>
public enum ReverseMode { Forward, LineReverse, FullReverse };
/// <summary>
/// Character encoding conversion delegate. This function converts a raw byte value
/// to a printable value, or CharEncoding.UNPRINTABLE_CHAR.
/// </summary>
public CharEncoding.Convert CharConv { get; set; }
/// <summary>
/// True if the input bytes are a DCI string. Only compatible with ReverseMode==Forward.
/// </summary>
public bool IsDciString { get; set; } = false;
// Output format for raw (non-printable) characters. Most assemblers use comma-separated
// hex values, some allow dense hex strings.
public enum RawOutputStyle { DenseHex, CommaSep };
@ -252,6 +261,8 @@ namespace Asm65 {
/// </summary>
public void FeedBytes(byte[] data, int offset, int length, int leadingBytes,
ReverseMode revMode) {
Debug.Assert(!IsDciString || revMode == ReverseMode.Forward);
int startOffset = offset;
int strEndOffset = offset + length;
@ -288,7 +299,11 @@ namespace Asm65 {
} else {
Debug.Assert(revMode == ReverseMode.Forward);
for (; offset < strEndOffset; offset++) {
WriteChar(data[offset]);
byte val = data[offset];
if (IsDciString && offset == strEndOffset - 1) {
val ^= 0x80;
}
WriteChar(val);
}
}

View File

@ -626,12 +626,7 @@ namespace SourceGen.AsmGen {
StringOpFormatter stropf = new StringOpFormatter(SourceFormatter,
new Formatter.DelimiterDef(delim),
StringOpFormatter.RawOutputStyle.DenseHex, charConv, false);
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
// DCI is awkward because the character encoding flips on the last byte. Rather
// than clutter up StringOpFormatter for this rare item, we just accept low/high
// throughout.
stropf.CharConv = CharEncoding.ConvertLowAndHighAscii;
}
stropf.IsDciString = (dfd.FormatType == FormatDescriptor.Type.StringDci);
// Feed bytes in, skipping over the leading length bytes.
stropf.FeedBytes(data, offset + leadingBytes,
@ -672,7 +667,7 @@ namespace SourceGen.AsmGen {
if (stropf.Lines.Count != 1) {
// single-line only
opcodeStr = sDataOpNames.StrGeneric;
stropf.CharConv = charConv;
stropf.IsDciString = false;
redo = true;
}
break;

View File

@ -750,23 +750,18 @@ namespace SourceGen.AsmGen {
Debug.Assert(dfd.Length > 0);
CharEncoding.Convert charConv = null;
CharEncoding.Convert dciConv = null;
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
charConv = CharEncoding.ConvertAscii;
dciConv = CharEncoding.ConvertLowAndHighAscii;
break;
case FormatDescriptor.SubType.HighAscii:
charConv = CharEncoding.ConvertHighAscii;
dciConv = CharEncoding.ConvertLowAndHighAscii;
break;
case FormatDescriptor.SubType.C64Petscii:
charConv = CharEncoding.ConvertC64Petscii;
dciConv = CharEncoding.ConvertLowAndHighC64Petscii;
break;
case FormatDescriptor.SubType.C64Screen:
charConv = CharEncoding.ConvertC64ScreenCode;
dciConv = CharEncoding.ConvertLowAndHighC64ScreenCode;
break;
default:
break;
@ -808,6 +803,7 @@ namespace SourceGen.AsmGen {
if ((Project.FileData[offset + dfd.Length - 1] & 0x80) == 0) {
// ".shift" directive only works for strings where the low bit starts
// clear and ends high.
// TODO(maybe): this is sub-optimal for high-ASCII DCI strings.
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
@ -820,12 +816,7 @@ namespace SourceGen.AsmGen {
StringOpFormatter stropf = new StringOpFormatter(SourceFormatter,
Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep, charConv,
false);
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
// DCI is awkward because the character encoding flips on the last byte. Rather
// than clutter up StringOpFormatter for this rare item, we just accept low/high
// throughout.
stropf.CharConv = dciConv;
}
stropf.IsDciString = (dfd.FormatType == FormatDescriptor.Type.StringDci);
// Feed bytes in, skipping over hidden bytes (leading L8, trailing null).
stropf.FeedBytes(data, offset + hiddenLeadingBytes,
@ -847,7 +838,7 @@ namespace SourceGen.AsmGen {
if (stropf.Lines.Count != 1) {
// Must be single-line.
opcodeStr = sDataOpNames.StrGeneric;
stropf.CharConv = charConv; // undo DCI hack
stropf.IsDciString = false;
redo = true;
}
break;

View File

@ -442,13 +442,11 @@ namespace SourceGen {
/// <param name="dfd">Format descriptor.</param>
/// <param name="data">File data.</param>
/// <param name="offset">Offset, within data, of start of string.</param>
/// <param name="popcode">Pseudo-opcode string.</param>
/// <param name="popcode">Receives the pseudo-opcode string.</param>
/// <returns>Array of operand strings.</returns>
public static List<string> FormatStringOp(Formatter formatter, PseudoOpNames opNames,
FormatDescriptor dfd, byte[] data, int offset, out string popcode) {
int hiddenLeadingBytes = 0;
int trailingBytes = 0;
StringOpFormatter.ReverseMode revMode = StringOpFormatter.ReverseMode.Forward;
Formatter.DelimiterSet delSet = formatter.Config.mStringDelimiters;
Formatter.DelimiterDef delDef;
@ -456,35 +454,19 @@ namespace SourceGen {
CharEncoding.Convert charConv;
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighAscii;
} else {
charConv = CharEncoding.ConvertAscii;
}
charConv = CharEncoding.ConvertAscii;
delDef = delSet.Get(CharEncoding.Encoding.Ascii);
break;
case FormatDescriptor.SubType.HighAscii:
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighAscii;
} else {
charConv = CharEncoding.ConvertHighAscii;
}
charConv = CharEncoding.ConvertHighAscii;
delDef = delSet.Get(CharEncoding.Encoding.HighAscii);
break;
case FormatDescriptor.SubType.C64Petscii:
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighC64Petscii;
} else {
charConv = CharEncoding.ConvertC64Petscii;
}
charConv = CharEncoding.ConvertC64Petscii;
delDef = delSet.Get(CharEncoding.Encoding.C64Petscii);
break;
case FormatDescriptor.SubType.C64Screen:
if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighC64ScreenCode;
} else {
charConv = CharEncoding.ConvertC64ScreenCode;
}
charConv = CharEncoding.ConvertC64ScreenCode;
delDef = delSet.Get(CharEncoding.Encoding.C64ScreenCode);
break;
default:
@ -498,6 +480,11 @@ namespace SourceGen {
delDef = Formatter.DOUBLE_QUOTE_DELIM;
}
StringOpFormatter stropf = new StringOpFormatter(formatter, delDef,
StringOpFormatter.RawOutputStyle.CommaSep, charConv, false);
int hiddenLeadingBytes = 0;
int trailingBytes = 0;
switch (dfd.FormatType) {
case FormatDescriptor.Type.StringGeneric:
// Generic character data.
@ -513,30 +500,22 @@ namespace SourceGen {
// Character data with a terminating null. Don't show the null byte.
popcode = opNames.StrNullTerm;
trailingBytes = 1;
//if (strLen == 0) {
// showHexZeroes = 1;
//}
break;
case FormatDescriptor.Type.StringL8:
// Character data with a leading length byte. Don't show the length.
hiddenLeadingBytes = 1;
//if (strLen == 0) {
// showHexZeroes = 1;
//}
popcode = opNames.StrLen8;
break;
case FormatDescriptor.Type.StringL16:
// Character data with a leading length word. Don't show the length.
Debug.Assert(dfd.Length > 1);
hiddenLeadingBytes = 2;
//if (strLen == 0) {
// showHexZeroes = 2;
//}
popcode = opNames.StrLen16;
break;
case FormatDescriptor.Type.StringDci:
// High bit on last byte is flipped.
popcode = opNames.StrDci;
stropf.IsDciString = true;
break;
default:
Debug.Assert(false);
@ -544,8 +523,6 @@ namespace SourceGen {
break;
}
StringOpFormatter stropf = new StringOpFormatter(formatter, delDef,
StringOpFormatter.RawOutputStyle.CommaSep, charConv, false);
stropf.FeedBytes(data, offset + hiddenLeadingBytes,
dfd.Length - hiddenLeadingBytes - trailingBytes, 0, revMode);

View File

@ -1,8 +1,8 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":4,
"FileDataLength":1299,
"FileDataCrc32":-371479809,
"FileDataLength":1417,
"FileDataCrc32":212868891,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
@ -786,6 +786,84 @@
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1297":{
"Length":6,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1304":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1314":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1325":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1336":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1348":{
"Length":8,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1357":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1367":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1378":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1380":{
"Length":11,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1392":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1402":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1413":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null}},
"LvTables":{

View File

@ -1,8 +1,8 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":4,
"FileDataLength":1299,
"FileDataCrc32":-371479809,
"FileDataLength":1417,
"FileDataCrc32":212868891,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
@ -786,6 +786,84 @@
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1297":{
"Length":6,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1304":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1314":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1325":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1336":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1348":{
"Length":8,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1357":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1367":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1378":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1380":{
"Length":11,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1392":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1402":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1413":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null}},
"LvTables":{

View File

@ -1,8 +1,8 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":4,
"FileDataLength":1299,
"FileDataCrc32":-371479809,
"FileDataLength":1417,
"FileDataCrc32":212868891,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
@ -786,6 +786,84 @@
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1297":{
"Length":6,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1304":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1314":{
"Length":10,
"Format":"StringDci",
"SubFormat":"Ascii",
"SymbolRef":null},
"1325":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1336":{
"Length":11,
"Format":"StringDci",
"SubFormat":"HighAscii",
"SymbolRef":null},
"1348":{
"Length":8,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1357":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1367":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1378":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Petscii",
"SymbolRef":null},
"1380":{
"Length":11,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1392":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1402":{
"Length":10,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null},
"1413":{
"Length":1,
"Format":"StringDci",
"SubFormat":"C64Screen",
"SymbolRef":null}},
"LvTables":{

View File

@ -251,7 +251,7 @@ L144B nop
.byte $80
_L14DA nop
jmp _L1511
jmp _L1587
.byte $86
.enc "sg_ascii"
@ -284,7 +284,33 @@ _L14DA nop
.shift "X"
.shift "!"
.byte $86
.enc "sg_ascii"
.shift "ascii",$7f
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.enc "sg_hiascii"
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.enc "none"
.shift "petscii",$5e
.byte $86
.shift $22,"a quote1",$22
.shift "'a quote2'"
.byte $86
.shift $5c
.byte $86
.enc "screen"
.shift "ScreenCode",$1e
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.shift $1c
.byte $86
_L1511 nop
_L1587 nop
rts

View File

@ -220,7 +220,7 @@ L144B nop
!byte $80
@L14DA nop
jmp @L1511
jmp @L1587
!byte $86
!text "Hell",$ef
@ -248,7 +248,29 @@ L144B nop
!scr $d8
!scr $a1
!byte $86
!text "ascii",$ff
!byte $86
!text $22,"A quote1",$a2
!text "'A quote2",$a7
!byte $86
!hex a2c8c1a0f1f5eff4e5b122
!hex a7c8c1a0f1f5eff4e5b227
!byte $86
!pet "petscii",$de
!byte $86
!pet $22,"a quote1",$a2
!pet "'a quote2",$a7
!byte $86
!pet $dc
!byte $86
!scr "ScreenCode",$9e
!byte $86
!scr $22,"A quote1",$a2
!scr "'A quote2",$a7
!byte $86
!scr $9c
!byte $86
@L1511 nop
@L1587 nop
rts

View File

@ -247,7 +247,7 @@ L144B: nop
.byte $80
@L14DA: nop
jmp @L1511
jmp @L1587
.byte $86
.byte "Hell",$ef
@ -275,7 +275,29 @@ L144B: nop
.byte $d8
.byte $a1
.byte $86
.byte "ascii",$ff
.byte $86
.byte $22,"A quote1",$a2
.byte "'A quote2",$a7
.byte $86
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.byte $50,$45,$54,$53,$43,$49,$49,$de
.byte $86
.byte $22,$41,$20,$51,$55,$4f,$54,$45,$31,$a2
.byte $27,$41,$20,$51,$55,$4f,$54,$45,$32,$a7
.byte $86
.byte $dc
.byte $86
.byte $53,$03,$12,$05,$05,$0e,$43,$0f,$04,$05,$9e
.byte $86
.byte $22,$41,$20,$11,$15,$0f,$14,$05,$31,$a2
.byte $27,$41,$20,$11,$15,$0f,$14,$05,$32,$a7
.byte $86
.byte $9c
.byte $86
@L1511: nop
@L1587: nop
rts

View File

@ -1,7 +1,7 @@
# 6502bench SourceGen generated linker script for 20120-char-encoding-a
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=1299;
# MEM000: file=%O, start=$1000, size=1417;
}
SEGMENTS {
CODE: load=MAIN, type=rw;

View File

@ -214,7 +214,7 @@ L144B nop
dfb $80
:L14DA nop
jmp :L1511
jmp :L1587
dfb $86
dci 'Hello'
@ -242,7 +242,29 @@ L144B nop
hex d8
hex a1
dfb $86
dci 'ascii',7f
dfb $86
dci '"A quote1"'
dci 27,'A quote2',27
dfb $86
dci a2,"HA quote1",a2
dci "'HA quote2'"
dfb $86
hex 50455453434949de
dfb $86
hex 22412051554f544531a2
hex 27412051554f544532a7
dfb $86
hex dc
dfb $86
hex 53031205050e430f04059e
dfb $86
hex 22412011150f140531a2
hex 27412011150f140532a7
dfb $86
hex 9c
dfb $86
:L1511 nop
:L1587 nop
rts

View File

@ -344,7 +344,7 @@ L144B nop
.byte $80
_L14DA nop
jmp _L1511
jmp _L1587
.byte $86
.enc "sg_ascii"
@ -377,7 +377,33 @@ _L14DA nop
.shift "X"
.shift "!"
.byte $86
.enc "sg_ascii"
.shift "ascii",$7f
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.enc "sg_hiascii"
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.enc "none"
.shift "petscii",$5e
.byte $86
.shift $22,"a quote1",$22
.shift "'a quote2'"
.byte $86
.shift $5c
.byte $86
.enc "screen"
.shift "ScreenCode",$1e
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.shift $1c
.byte $86
_L1511 nop
_L1587 nop
rts

View File

@ -313,7 +313,7 @@ L144B nop
!byte $80
@L14DA nop
jmp @L1511
jmp @L1587
!byte $86
!text "Hell",$ef
@ -341,7 +341,29 @@ L144B nop
!scr $d8
!scr $a1
!byte $86
!text "ascii",$ff
!byte $86
!text $22,"A quote1",$a2
!text "'A quote2",$a7
!byte $86
!hex a2c8c1a0f1f5eff4e5b122
!hex a7c8c1a0f1f5eff4e5b227
!byte $86
!pet "petscii",$de
!byte $86
!pet $22,"a quote1",$a2
!pet "'a quote2",$a7
!byte $86
!pet $dc
!byte $86
!scr "ScreenCode",$9e
!byte $86
!scr $22,"A quote1",$a2
!scr "'A quote2",$a7
!byte $86
!scr $9c
!byte $86
@L1511 nop
@L1587 nop
rts

View File

@ -340,7 +340,7 @@ L144B: nop
.byte $80
@L14DA: nop
jmp @L1511
jmp @L1587
.byte $86
.byte "Hell",$ef
@ -368,7 +368,29 @@ L144B: nop
.byte $d8
.byte $a1
.byte $86
.byte "ascii",$ff
.byte $86
.byte $22,"A quote1",$a2
.byte "'A quote2",$a7
.byte $86
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.byte $50,$45,$54,$53,$43,$49,$49,$de
.byte $86
.byte $22,$41,$20,$51,$55,$4f,$54,$45,$31,$a2
.byte $27,$41,$20,$51,$55,$4f,$54,$45,$32,$a7
.byte $86
.byte $dc
.byte $86
.byte $53,$03,$12,$05,$05,$0e,$43,$0f,$04,$05,$9e
.byte $86
.byte $22,$41,$20,$11,$15,$0f,$14,$05,$31,$a2
.byte $27,$41,$20,$11,$15,$0f,$14,$05,$32,$a7
.byte $86
.byte $9c
.byte $86
@L1511: nop
@L1587: nop
rts

View File

@ -1,7 +1,7 @@
# 6502bench SourceGen generated linker script for 20130-char-encoding-p
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=1299;
# MEM000: file=%O, start=$1000, size=1417;
}
SEGMENTS {
CODE: load=MAIN, type=rw;

View File

@ -308,7 +308,7 @@ L144B nop
dfb $80
:L14DA nop
jmp :L1511
jmp :L1587
dfb $86
dci 'Hello'
@ -336,7 +336,29 @@ L144B nop
hex d8
hex a1
dfb $86
dci 'ascii',7f
dfb $86
dci '"A quote1"'
dci 27,'A quote2',27
dfb $86
dci a2,"HA quote1",a2
dci "'HA quote2'"
dfb $86
hex 50455453434949de
dfb $86
hex 22412051554f544531a2
hex 27412051554f544532a7
dfb $86
hex dc
dfb $86
hex 53031205050e430f04059e
dfb $86
hex 22412011150f140531a2
hex 27412011150f140532a7
dfb $86
hex 9c
dfb $86
:L1511 nop
:L1587 nop
rts

View File

@ -352,7 +352,7 @@ L144B nop
.byte $80
_L14DA nop
jmp _L1511
jmp _L1587
.byte $86
.enc "sg_ascii"
@ -385,7 +385,33 @@ _L14DA nop
.shift "X"
.shift "!"
.byte $86
.enc "sg_ascii"
.shift "ascii",$7f
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.enc "sg_hiascii"
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.enc "none"
.shift "petscii",$5e
.byte $86
.shift $22,"a quote1",$22
.shift "'a quote2'"
.byte $86
.shift $5c
.byte $86
.enc "screen"
.shift "ScreenCode",$1e
.byte $86
.shift $22,"A quote1",$22
.shift "'A quote2'"
.byte $86
.shift $1c
.byte $86
_L1511 nop
_L1587 nop
rts

View File

@ -322,7 +322,7 @@ L144B nop
!byte $80
@L14DA nop
jmp @L1511
jmp @L1587
!byte $86
!text "Hell",$ef
@ -350,7 +350,29 @@ L144B nop
!scr $d8
!scr $a1
!byte $86
!text "ascii",$ff
!byte $86
!text $22,"A quote1",$a2
!text "'A quote2",$a7
!byte $86
!hex a2c8c1a0f1f5eff4e5b122
!hex a7c8c1a0f1f5eff4e5b227
!byte $86
!pet "petscii",$de
!byte $86
!pet $22,"a quote1",$a2
!pet "'a quote2",$a7
!byte $86
!pet $dc
!byte $86
!scr "ScreenCode",$9e
!byte $86
!scr $22,"A quote1",$a2
!scr "'A quote2",$a7
!byte $86
!scr $9c
!byte $86
@L1511 nop
@L1587 nop
rts

View File

@ -349,7 +349,7 @@ L144B: nop
.byte $80
@L14DA: nop
jmp @L1511
jmp @L1587
.byte $86
.byte "Hell",$ef
@ -377,7 +377,29 @@ L144B: nop
.byte $d8
.byte $a1
.byte $86
.byte "ascii",$ff
.byte $86
.byte $22,"A quote1",$a2
.byte "'A quote2",$a7
.byte $86
.byte $a2,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b1,$22
.byte $a7,$c8,$c1,$a0,$f1,$f5,$ef,$f4,$e5,$b2,$27
.byte $86
.byte $50,$45,$54,$53,$43,$49,$49,$de
.byte $86
.byte $22,$41,$20,$51,$55,$4f,$54,$45,$31,$a2
.byte $27,$41,$20,$51,$55,$4f,$54,$45,$32,$a7
.byte $86
.byte $dc
.byte $86
.byte $53,$03,$12,$05,$05,$0e,$43,$0f,$04,$05,$9e
.byte $86
.byte $22,$41,$20,$11,$15,$0f,$14,$05,$31,$a2
.byte $27,$41,$20,$11,$15,$0f,$14,$05,$32,$a7
.byte $86
.byte $9c
.byte $86
@L1511: nop
@L1587: nop
rts

View File

@ -1,7 +1,7 @@
# 6502bench SourceGen generated linker script for 20140-char-encoding-s
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=1299;
# MEM000: file=%O, start=$1000, size=1417;
}
SEGMENTS {
CODE: load=MAIN, type=rw;

View File

@ -317,7 +317,7 @@ L144B nop
dfb $80
:L14DA nop
jmp :L1511
jmp :L1587
dfb $86
dci 'Hello'
@ -345,7 +345,29 @@ L144B nop
hex d8
hex a1
dfb $86
dci 'ascii',7f
dfb $86
dci '"A quote1"'
dci 27,'A quote2',27
dfb $86
dci a2,"HA quote1",a2
dci "'HA quote2'"
dfb $86
hex 50455453434949de
dfb $86
hex 22412051554f544531a2
hex 27412051554f544532a7
dfb $86
hex dc
dfb $86
hex 53031205050e430f04059e
dfb $86
hex 22412011150f140531a2
hex 27412011150f140532a7
dfb $86
hex 9c
dfb $86
:L1511 nop
:L1587 nop
rts

View File

@ -45,13 +45,13 @@
dfb $81
* 62 high-ASCII underscores. Should be one line.
* 62 high-ASCII asterisks. Should be one line.
asc "********************************"
asc "******************************"
dfb $80
* 96 high-ASCII underscores. Might be converted to "fill".
* 96 high-ASCII asterisks. Might be converted to "fill".
asc "********************************"
asc "********************************"
asc "********************************"

View File

@ -204,5 +204,45 @@ skip_esc nop
!byte $a1
!byte $86
; Test edge case: last character of DCI string is delimiter or invalid
; character, e.g. PETSCII with no ASCII equivalent.
;
; EDIT: format all of these as DCI strings
!text "ascii",$ff ;invalid end
!byte $86
!text $22,"A quote1",$a2
!text $27,"A quote2",$a7
!byte $86
!xor $80 {
!text $22,"HA quote1",$a2
!text $27,"HA quote2",$a7
}
!byte $86
; PETSCII stuff
!pet "petscii",$de ;ends with upward arrow ($5e)
!byte $86
!pet $22,"a quote1",$a2
!pet $27,"a quote2",$a7
!byte $86
!byte $dc ;$5c pound sign (UK currency)
!byte $86
; ScreenCode stuff
!scr "ScreenCode",$9e ;ends with upward arrow
!byte $86
!scr $22,"A quote1",$a2
!scr $27,"A quote2",$a7
!byte $86
!byte $9c ;$1c pound sign (UK currency)
!byte $86
skip_dci nop
rts