1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-29 10:50:28 +00:00

Update source generators to recognize C64 strings

For the most part this means explicitly dumping them as hex, though
ACME gets to exercise its !pet and !scr operators.
This commit is contained in:
Andy McFadden 2019-08-15 21:33:10 -07:00
parent 7bbe5692bd
commit 84d3146903
4 changed files with 124 additions and 43 deletions

View File

@ -451,7 +451,7 @@ namespace SourceGen.AsmGen {
}
}
if (singleValue) {
if (singleValue && length > 1) {
string opcodeStr = SourceFormatter.FormatPseudoOp(sDataOpNames.Fill);
string operandStr = length + "," + SourceFormatter.FormatHexValue(val, 2);
OutputLine(labelStr, opcodeStr, operandStr, commentStr);
@ -532,11 +532,6 @@ namespace SourceGen.AsmGen {
}
private void OutputString(int offset, string labelStr, string commentStr) {
// Normal ASCII strings are handled with a simple !text directive.
//
// We could probably do something fancy with !xor to
// make high-ASCII work nicely.
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
Anattrib attr = Project.GetAnattrib(offset);
@ -545,9 +540,30 @@ namespace SourceGen.AsmGen {
Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
if (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii) {
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
string opcodeStr;
CharEncoding.Convert charConv;
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
opcodeStr = sDataOpNames.StrGeneric;
charConv = CharEncoding.ConvertAscii;
break;
case FormatDescriptor.SubType.HighAscii:
// Can't !xor the output, because while it works for string data it
// also flips the high bits on unprintable bytes output as raw hex.
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
case FormatDescriptor.SubType.C64Petscii:
opcodeStr = "!pet";
charConv = CharEncoding.ConvertC64Petscii;
break;
case FormatDescriptor.SubType.C64Screen:
opcodeStr = "!scr";
charConv = CharEncoding.ConvertC64ScreenCode;
break;
default:
Debug.Assert(false);
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
int leadingBytes = 0;
@ -557,11 +573,14 @@ namespace SourceGen.AsmGen {
case FormatDescriptor.Type.StringReverse:
case FormatDescriptor.Type.StringNullTerm:
case FormatDescriptor.Type.StringDci:
// Last byte will be output as hex.
break;
case FormatDescriptor.Type.StringL8:
// Length byte will be output as hex.
leadingBytes = 1;
break;
case FormatDescriptor.Type.StringL16:
// Length byte will be output as hex.
leadingBytes = 2;
break;
default:
@ -570,17 +589,21 @@ namespace SourceGen.AsmGen {
}
StringOpFormatter stropf = new StringOpFormatter(SourceFormatter,
Formatter.DOUBLE_QUOTE_DELIM,
StringOpFormatter.RawOutputStyle.CommaSep, MAX_OPERAND_LEN,
CharEncoding.ConvertAscii);
Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep,
MAX_OPERAND_LEN, charConv);
stropf.FeedBytes(data, offset, dfd.Length, leadingBytes,
StringOpFormatter.ReverseMode.Forward);
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
//if (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii) {
// OutputLine(string.Empty, "!xor", "$80 {", string.Empty);
//}
foreach (string str in stropf.Lines) {
OutputLine(labelStr, opcodeStr, str, commentStr);
labelStr = commentStr = string.Empty; // only show on first
}
//if (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii) {
// OutputLine(string.Empty, "}", string.Empty, string.Empty);
//}
}
}

View File

@ -485,7 +485,7 @@ namespace SourceGen.AsmGen {
}
}
if (singleValue) {
if (singleValue && length > 1) {
string opcodeStr = SourceFormatter.FormatPseudoOp(sDataOpNames.Fill);
string operandStr = length + "," + SourceFormatter.FormatHexValue(val, 2);
OutputLine(labelStr, opcodeStr, operandStr, commentStr);
@ -592,14 +592,35 @@ namespace SourceGen.AsmGen {
// Some ideas here:
// https://groups.google.com/forum/#!topic/comp.sys.apple2.programmer/5Wkw8mUPcU0
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
CharEncoding.Convert charConv;
bool isHighAscii = false;
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
charConv = CharEncoding.ConvertAscii;
break;
case FormatDescriptor.SubType.HighAscii:
if (dfd.FormatType != FormatDescriptor.Type.StringGeneric) {
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
charConv = CharEncoding.ConvertHighAscii;
isHighAscii = true;
break;
case FormatDescriptor.SubType.C64Petscii:
case FormatDescriptor.SubType.C64Screen:
default:
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
int leadingBytes = 0;
int trailingBytes = 0;
@ -622,19 +643,6 @@ namespace SourceGen.AsmGen {
return;
}
bool highAscii = (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii);
if (highAscii && dfd.FormatType != FormatDescriptor.Type.StringGeneric) {
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
CharEncoding.Convert charConv;
if (highAscii) {
charConv = CharEncoding.ConvertHighAscii;
} else {
charConv = CharEncoding.ConvertAscii;
}
StringOpFormatter stropf = new StringOpFormatter(SourceFormatter,
Formatter.DOUBLE_QUOTE_DELIM, StringOpFormatter.RawOutputStyle.CommaSep,
MAX_OPERAND_LEN, charConv);
@ -643,7 +651,7 @@ namespace SourceGen.AsmGen {
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
if (highAscii) {
if (isHighAscii) {
// Does this fit the narrow definition of what we can do with a macro?
Debug.Assert(dfd.FormatType == FormatDescriptor.Type.StringGeneric);
if (stropf.Lines.Count == 1 && !stropf.HasEscapedText) {

View File

@ -308,6 +308,33 @@ namespace SourceGen.AsmGen {
}
}
/// <summary>
/// Outputs formatted data in an unformatted way, because the code generator couldn't
/// figure out how to do something better.
/// </summary>
private void OutputNoJoy(int offset, int length, string labelStr, string commentStr) {
byte[] data = Project.FileData;
Debug.Assert(length > 0);
Debug.Assert(offset >= 0 && offset < data.Length);
bool singleValue = true;
byte val = data[offset];
for (int i = 1; i < length; i++) {
if (data[offset + i] != val) {
singleValue = false;
break;
}
}
if (singleValue && length > 1) {
string opcodeStr = SourceFormatter.FormatPseudoOp(sDataOpNames.Fill);
string operandStr = length + "," + SourceFormatter.FormatHexValue(val, 2);
OutputLine(labelStr, opcodeStr, operandStr, commentStr);
} else {
OutputDenseHex(offset, length, labelStr, commentStr);
}
}
// IGenerator
public string ModifyOpcode(int offset, OpDef op) {
if (op.IsUndocumented) {
@ -446,14 +473,27 @@ namespace SourceGen.AsmGen {
// have the right pattern. If not, we will generate bad output. This would need
// to be scanned and corrected at a higher level.
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
// We can sort of do parts of C64 stuff, but it's probably more readable to just
// output a commented blob than something where only the capital letters are readable.
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
case FormatDescriptor.SubType.HighAscii:
break;
case FormatDescriptor.SubType.C64Petscii:
case FormatDescriptor.SubType.C64Screen:
default:
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
StringOpFormatter.ReverseMode revMode = StringOpFormatter.ReverseMode.Forward;
int leadingBytes = 0;
string opcodeStr;

View File

@ -428,7 +428,7 @@ namespace SourceGen.AsmGen {
}
}
if (singleValue) {
if (singleValue && length > 1) {
string opcodeStr = SourceFormatter.FormatPseudoOp(sDataOpNames.Fill);
string operandStr = length + "," + SourceFormatter.FormatHexValue(val, 2);
OutputLine(labelStr, opcodeStr, operandStr, commentStr);
@ -528,24 +528,34 @@ namespace SourceGen.AsmGen {
//
// We might be able to define a macro for Reverse.
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
CharEncoding.Convert charConv;
CharEncoding.Convert dciConv;
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
charConv = CharEncoding.ConvertAscii;
dciConv = CharEncoding.ConvertLowAndHighAscii;
break;
case FormatDescriptor.SubType.HighAscii:
case FormatDescriptor.SubType.C64Petscii:
case FormatDescriptor.SubType.C64Screen:
default:
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
int hiddenLeadingBytes = 0;
int shownLeadingBytes = 0;
int trailingBytes = 0;
string opcodeStr;
if (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii) {
OutputNoJoy(offset, dfd.Length, labelStr, commentStr);
return;
}
switch (dfd.FormatType) {
case FormatDescriptor.Type.StringGeneric:
case FormatDescriptor.Type.StringReverse:
@ -573,12 +583,12 @@ namespace SourceGen.AsmGen {
StringOpFormatter stropf = new StringOpFormatter(SourceFormatter,
Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep,
MAX_OPERAND_LEN, CharEncoding.ConvertAscii);
MAX_OPERAND_LEN, charConv);
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.CharConv = dciConv;
}
// Feed bytes in, skipping over hidden bytes (leading L8, trailing null).
@ -601,7 +611,7 @@ namespace SourceGen.AsmGen {
if (stropf.Lines.Count != 1) {
// Must be single-line.
opcodeStr = sDataOpNames.StrGeneric;
stropf.CharConv = CharEncoding.ConvertAscii; // undo DCI hack
stropf.CharConv = charConv; // undo DCI hack
redo = true;
}
break;