mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-20 06:29:04 +00:00
Change the way string formats are defined
We used to use type="String", with the sub-type indicating whether the string was null-terminated, prefixed with a length, or whatever. This didn't leave much room for specifying a character encoding, which is orthogonal to the sub-type. What we actually want is to have the type specify the string type, and then have the sub-type determine the character encoding. These sub-types can also be used with the Numeric type to specify the encoding of character operands. This change updates the enum definitions and the various bits of code that use them, but does not add any code for working with non-ASCII character encodings. The project file version number was incremented to 2, since the new FormatDescriptor serialization is mildly incompatible with the old. (Won't explode, but it'll post a complaint and ignore the stuff it doesn't recognize.) While I was at it, I finished removing DciReverse. It's still part of the 2005-string-types regression test, which currently fails because the generated source doesn't match.
This commit is contained in:
parent
89288c4d8c
commit
0d0854bda7
@ -126,7 +126,7 @@ namespace PluginCommon {
|
|||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
NumericLE,
|
NumericLE,
|
||||||
NumericBE,
|
NumericBE,
|
||||||
String,
|
StringGeneric,
|
||||||
Dense,
|
Dense,
|
||||||
Fill
|
Fill
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,6 @@ namespace SourceGen.AsmGen {
|
|||||||
//StrLen8
|
//StrLen8
|
||||||
//StrLen16
|
//StrLen16
|
||||||
//StrDci
|
//StrDci
|
||||||
//StrDciReverse
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -388,7 +387,12 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputDenseHex(offset, length, labelStr, commentStr);
|
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
multiLine = true;
|
multiLine = true;
|
||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputString(offset, labelStr, commentStr);
|
OutputString(offset, labelStr, commentStr);
|
||||||
@ -532,7 +536,7 @@ namespace SourceGen.AsmGen {
|
|||||||
Anattrib attr = Project.GetAnattrib(offset);
|
Anattrib attr = Project.GetAnattrib(offset);
|
||||||
FormatDescriptor dfd = attr.DataDescriptor;
|
FormatDescriptor dfd = attr.DataDescriptor;
|
||||||
Debug.Assert(dfd != null);
|
Debug.Assert(dfd != null);
|
||||||
Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
|
Debug.Assert(dfd.IsString);
|
||||||
Debug.Assert(dfd.Length > 0);
|
Debug.Assert(dfd.Length > 0);
|
||||||
|
|
||||||
bool highAscii = false;
|
bool highAscii = false;
|
||||||
@ -541,36 +545,31 @@ namespace SourceGen.AsmGen {
|
|||||||
bool showLeading = false;
|
bool showLeading = false;
|
||||||
bool showTrailing = false;
|
bool showTrailing = false;
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
|
|
||||||
leadingBytes = 1;
|
|
||||||
showLeading = true;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (dfd.Length > 1) {
|
if (dfd.Length > 1) {
|
||||||
highAscii = (data[offset + 1] & 0x80) != 0;
|
highAscii = (data[offset + 1] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
leadingBytes = 1;
|
leadingBytes = 1;
|
||||||
showLeading = true;
|
showLeading = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
if (dfd.Length > 2) {
|
if (dfd.Length > 2) {
|
||||||
highAscii = (data[offset + 2] & 0x80) != 0;
|
highAscii = (data[offset + 2] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
@ -598,18 +597,17 @@ namespace SourceGen.AsmGen {
|
|||||||
|
|
||||||
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
// TODO(someday): something fancy with encodings to handle high-ASCII text?
|
// TODO(someday): something fancy with encodings to handle high-ASCII text?
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
|
||||||
// Fully configured above.
|
// Fully configured above.
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.CString:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
// Implement as macro?
|
// Implement as macro?
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -119,7 +119,6 @@ namespace SourceGen.AsmGen {
|
|||||||
//StrLen8 // macro with .strlen?
|
//StrLen8 // macro with .strlen?
|
||||||
//StrLen16
|
//StrLen16
|
||||||
//StrDci
|
//StrDci
|
||||||
//StrDciReverse
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -414,7 +413,12 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputDenseHex(offset, length, labelStr, commentStr);
|
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
multiLine = true;
|
multiLine = true;
|
||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputString(offset, labelStr, commentStr);
|
OutputString(offset, labelStr, commentStr);
|
||||||
@ -586,7 +590,7 @@ namespace SourceGen.AsmGen {
|
|||||||
Anattrib attr = Project.GetAnattrib(offset);
|
Anattrib attr = Project.GetAnattrib(offset);
|
||||||
FormatDescriptor dfd = attr.DataDescriptor;
|
FormatDescriptor dfd = attr.DataDescriptor;
|
||||||
Debug.Assert(dfd != null);
|
Debug.Assert(dfd != null);
|
||||||
Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
|
Debug.Assert(dfd.IsString);
|
||||||
Debug.Assert(dfd.Length > 0);
|
Debug.Assert(dfd.Length > 0);
|
||||||
|
|
||||||
bool highAscii = false;
|
bool highAscii = false;
|
||||||
@ -595,36 +599,31 @@ namespace SourceGen.AsmGen {
|
|||||||
bool showLeading = false;
|
bool showLeading = false;
|
||||||
bool showTrailing = false;
|
bool showTrailing = false;
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
|
|
||||||
leadingBytes = 1;
|
|
||||||
showLeading = true;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (dfd.Length > 1) {
|
if (dfd.Length > 1) {
|
||||||
highAscii = (data[offset + 1] & 0x80) != 0;
|
highAscii = (data[offset + 1] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
leadingBytes = 1;
|
leadingBytes = 1;
|
||||||
showLeading = true;
|
showLeading = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
if (dfd.Length > 2) {
|
if (dfd.Length > 2) {
|
||||||
highAscii = (data[offset + 2] & 0x80) != 0;
|
highAscii = (data[offset + 2] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
@ -652,8 +651,8 @@ namespace SourceGen.AsmGen {
|
|||||||
|
|
||||||
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
// Special case for simple short high-ASCII strings. These have no
|
// Special case for simple short high-ASCII strings. These have no
|
||||||
// leading or trailing bytes. We can improve this a bit by handling
|
// leading or trailing bytes. We can improve this a bit by handling
|
||||||
// arbitrarily long strings by simply breaking them across lines.
|
// arbitrarily long strings by simply breaking them across lines.
|
||||||
@ -673,19 +672,18 @@ namespace SourceGen.AsmGen {
|
|||||||
highAscii = false;
|
highAscii = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
|
||||||
// Full configured above.
|
// Full configured above.
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.CString:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
||||||
opcodeStr = sDataOpNames.StrNullTerm;
|
opcodeStr = sDataOpNames.StrNullTerm;
|
||||||
showTrailing = false;
|
showTrailing = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
// Implement macros?
|
// Implement macros?
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -118,7 +118,6 @@ namespace SourceGen.AsmGen {
|
|||||||
StrLen16Hi = "strl",
|
StrLen16Hi = "strl",
|
||||||
StrDci = "dci",
|
StrDci = "dci",
|
||||||
StrDciHi = "dci",
|
StrDciHi = "dci",
|
||||||
//StrDciReverse
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -294,7 +293,12 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputDenseHex(offset, length, labelStr, commentStr);
|
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
multiLine = true;
|
multiLine = true;
|
||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputString(offset, labelStr, commentStr);
|
OutputString(offset, labelStr, commentStr);
|
||||||
@ -460,9 +464,6 @@ namespace SourceGen.AsmGen {
|
|||||||
// backward order. Also, Merlin doesn't allow hex to be embedded in a REV
|
// backward order. Also, Merlin doesn't allow hex to be embedded in a REV
|
||||||
// operation, so we can't use REV if the string contains a delimiter.
|
// operation, so we can't use REV if the string contains a delimiter.
|
||||||
//
|
//
|
||||||
// DciReverse is deprecated, but we can handle it as a Reverse string with a
|
|
||||||
// trailing byte on a following line.
|
|
||||||
//
|
|
||||||
// For aesthetic purposes, zero-length CString, L8String, and L16String
|
// For aesthetic purposes, zero-length CString, L8String, and L16String
|
||||||
// should be output as DFB/DW zeroes rather than an empty string -- makes
|
// should be output as DFB/DW zeroes rather than an empty string -- makes
|
||||||
// it easier to read.
|
// it easier to read.
|
||||||
@ -472,7 +473,7 @@ namespace SourceGen.AsmGen {
|
|||||||
Anattrib attr = Project.GetAnattrib(offset);
|
Anattrib attr = Project.GetAnattrib(offset);
|
||||||
FormatDescriptor dfd = attr.DataDescriptor;
|
FormatDescriptor dfd = attr.DataDescriptor;
|
||||||
Debug.Assert(dfd != null);
|
Debug.Assert(dfd != null);
|
||||||
Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
|
Debug.Assert(dfd.IsString);
|
||||||
Debug.Assert(dfd.Length > 0);
|
Debug.Assert(dfd.Length > 0);
|
||||||
|
|
||||||
bool highAscii = false;
|
bool highAscii = false;
|
||||||
@ -483,22 +484,18 @@ namespace SourceGen.AsmGen {
|
|||||||
bool showTrailing = false;
|
bool showTrailing = false;
|
||||||
RevMode revMode = RevMode.Forward;
|
RevMode revMode = RevMode.Forward;
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
revMode = RevMode.Reverse;
|
revMode = RevMode.Reverse;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
|
|
||||||
revMode = RevMode.Reverse;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
if (dfd.Length == 1) {
|
if (dfd.Length == 1) {
|
||||||
showZeroes = 1; // empty null-terminated string
|
showZeroes = 1; // empty null-terminated string
|
||||||
@ -506,7 +503,7 @@ namespace SourceGen.AsmGen {
|
|||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (dfd.Length > 1) {
|
if (dfd.Length > 1) {
|
||||||
highAscii = (data[offset + 1] & 0x80) != 0;
|
highAscii = (data[offset + 1] & 0x80) != 0;
|
||||||
} else {
|
} else {
|
||||||
@ -514,7 +511,7 @@ namespace SourceGen.AsmGen {
|
|||||||
}
|
}
|
||||||
leadingBytes = 1;
|
leadingBytes = 1;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
if (dfd.Length > 2) {
|
if (dfd.Length > 2) {
|
||||||
highAscii = (data[offset + 2] & 0x80) != 0;
|
highAscii = (data[offset + 2] & 0x80) != 0;
|
||||||
} else {
|
} else {
|
||||||
@ -555,11 +552,11 @@ namespace SourceGen.AsmGen {
|
|||||||
|
|
||||||
string opcodeStr;
|
string opcodeStr;
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
if (gath.NumLinesOutput == 1) {
|
if (gath.NumLinesOutput == 1) {
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrDciHi : sDataOpNames.StrDci;
|
opcodeStr = highAscii ? sDataOpNames.StrDciHi : sDataOpNames.StrDci;
|
||||||
} else {
|
} else {
|
||||||
@ -568,7 +565,7 @@ namespace SourceGen.AsmGen {
|
|||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
if (gath.HasDelimiter) {
|
if (gath.HasDelimiter) {
|
||||||
// can't include escaped delimiters in REV
|
// can't include escaped delimiters in REV
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
||||||
@ -581,18 +578,11 @@ namespace SourceGen.AsmGen {
|
|||||||
Debug.Assert(revMode == RevMode.Reverse);
|
Debug.Assert(revMode == RevMode.Reverse);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
// Mostly punt -- output as ASCII with special handling for first byte.
|
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
|
||||||
revMode = RevMode.Forward;
|
|
||||||
leadingBytes = 1;
|
|
||||||
showLeading = true;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
//opcodeStr = sDataOpNames.StrNullTerm[highAscii ? 1 : 0];
|
//opcodeStr = sDataOpNames.StrNullTerm[highAscii ? 1 : 0];
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (gath.NumLinesOutput == 1) {
|
if (gath.NumLinesOutput == 1) {
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrLen8Hi : sDataOpNames.StrLen8;
|
opcodeStr = highAscii ? sDataOpNames.StrLen8Hi : sDataOpNames.StrLen8;
|
||||||
} else {
|
} else {
|
||||||
@ -601,7 +591,7 @@ namespace SourceGen.AsmGen {
|
|||||||
showLeading = true;
|
showLeading = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
if (gath.NumLinesOutput == 1) {
|
if (gath.NumLinesOutput == 1) {
|
||||||
opcodeStr = highAscii ? sDataOpNames.StrLen16Hi : sDataOpNames.StrLen16;
|
opcodeStr = highAscii ? sDataOpNames.StrLen16Hi : sDataOpNames.StrLen16;
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,7 +129,6 @@ namespace SourceGen.AsmGen {
|
|||||||
StrLen8 = ".ptext",
|
StrLen8 = ".ptext",
|
||||||
//StrLen16
|
//StrLen16
|
||||||
//StrDci
|
//StrDci
|
||||||
//StrDciReverse
|
|
||||||
};
|
};
|
||||||
private const string HERE_PSEUDO_OP = ".here";
|
private const string HERE_PSEUDO_OP = ".here";
|
||||||
|
|
||||||
@ -360,7 +359,12 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputDenseHex(offset, length, labelStr, commentStr);
|
OutputDenseHex(offset, length, labelStr, commentStr);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
multiLine = true;
|
multiLine = true;
|
||||||
opcodeStr = operandStr = null;
|
opcodeStr = operandStr = null;
|
||||||
OutputString(offset, labelStr, commentStr);
|
OutputString(offset, labelStr, commentStr);
|
||||||
@ -525,7 +529,7 @@ namespace SourceGen.AsmGen {
|
|||||||
Anattrib attr = Project.GetAnattrib(offset);
|
Anattrib attr = Project.GetAnattrib(offset);
|
||||||
FormatDescriptor dfd = attr.DataDescriptor;
|
FormatDescriptor dfd = attr.DataDescriptor;
|
||||||
Debug.Assert(dfd != null);
|
Debug.Assert(dfd != null);
|
||||||
Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
|
Debug.Assert(dfd.IsString);
|
||||||
Debug.Assert(dfd.Length > 0);
|
Debug.Assert(dfd.Length > 0);
|
||||||
|
|
||||||
bool highAscii = false;
|
bool highAscii = false;
|
||||||
@ -534,36 +538,31 @@ namespace SourceGen.AsmGen {
|
|||||||
bool showLeading = false;
|
bool showLeading = false;
|
||||||
bool showTrailing = false;
|
bool showTrailing = false;
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
|
|
||||||
leadingBytes = 1;
|
|
||||||
showLeading = true;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
trailingBytes = 1;
|
trailingBytes = 1;
|
||||||
showTrailing = true;
|
showTrailing = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (dfd.Length > 1) {
|
if (dfd.Length > 1) {
|
||||||
highAscii = (data[offset + 1] & 0x80) != 0;
|
highAscii = (data[offset + 1] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
leadingBytes = 1;
|
leadingBytes = 1;
|
||||||
showLeading = true;
|
showLeading = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
if (dfd.Length > 2) {
|
if (dfd.Length > 2) {
|
||||||
highAscii = (data[offset + 2] & 0x80) != 0;
|
highAscii = (data[offset + 2] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
@ -591,28 +590,27 @@ namespace SourceGen.AsmGen {
|
|||||||
|
|
||||||
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
|
||||||
|
|
||||||
switch (dfd.FormatSubType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
// TODO(someday): something fancy with encodings to handle high-ASCII text?
|
// TODO(someday): something fancy with encodings to handle high-ASCII text?
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
|
||||||
// Fully configured above.
|
// Fully configured above.
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.CString:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
||||||
opcodeStr = sDataOpNames.StrNullTerm;
|
opcodeStr = sDataOpNames.StrNullTerm;
|
||||||
showTrailing = false;
|
showTrailing = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
|
||||||
opcodeStr = sDataOpNames.StrLen8;
|
opcodeStr = sDataOpNames.StrLen8;
|
||||||
showLeading = false;
|
showLeading = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
// Implement as macro?
|
// Implement as macro?
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1047,7 +1047,7 @@ namespace SourceGen {
|
|||||||
return FormatDescriptor.Type.NumericBE;
|
return FormatDescriptor.Type.NumericBE;
|
||||||
case DataType.Dense:
|
case DataType.Dense:
|
||||||
return FormatDescriptor.Type.Dense;
|
return FormatDescriptor.Type.Dense;
|
||||||
case DataType.String:
|
case DataType.StringGeneric:
|
||||||
case DataType.Fill:
|
case DataType.Fill:
|
||||||
default:
|
default:
|
||||||
// not appropriate for operands, or inline data (?)
|
// not appropriate for operands, or inline data (?)
|
||||||
@ -1068,8 +1068,6 @@ namespace SourceGen {
|
|||||||
return FormatDescriptor.SubType.Decimal;
|
return FormatDescriptor.SubType.Decimal;
|
||||||
case DataSubType.Binary:
|
case DataSubType.Binary:
|
||||||
return FormatDescriptor.SubType.Binary;
|
return FormatDescriptor.SubType.Binary;
|
||||||
case DataSubType.Ascii:
|
|
||||||
return FormatDescriptor.SubType.Ascii;
|
|
||||||
case DataSubType.Address:
|
case DataSubType.Address:
|
||||||
return FormatDescriptor.SubType.Address;
|
return FormatDescriptor.SubType.Address;
|
||||||
case DataSubType.Symbol:
|
case DataSubType.Symbol:
|
||||||
|
@ -737,7 +737,7 @@ namespace SourceGen {
|
|||||||
if (asciiLen >= minStringChars) {
|
if (asciiLen >= minStringChars) {
|
||||||
LogV(start, "ASCII string, len=" + asciiLen + " bytes");
|
LogV(start, "ASCII string, len=" + asciiLen + " bytes");
|
||||||
mAnattribs[start].DataDescriptor = FormatDescriptor.Create(asciiLen,
|
mAnattribs[start].DataDescriptor = FormatDescriptor.Create(asciiLen,
|
||||||
FormatDescriptor.Type.String, FormatDescriptor.SubType.None);
|
FormatDescriptor.Type.StringGeneric, FormatDescriptor.SubType.Ascii);
|
||||||
start += asciiLen;
|
start += asciiLen;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -34,27 +34,35 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class FormatDescriptor {
|
public class FormatDescriptor {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General data type.
|
/// General data type. Generally corresponds to the pseudo-opcode.
|
||||||
///
|
///
|
||||||
/// The UI only allows big-endian values in certain situations. Internally we want
|
/// The UI only allows big-endian values in certain situations. Internally we want
|
||||||
/// to be orthogonal in case the policy changes.
|
/// to be orthogonal in case the policy changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum Type : byte {
|
public enum Type : byte {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
REMOVE, // special type, only used by operand editor
|
REMOVE, // special type, only used by operand editor
|
||||||
Default, // means "unformatted", same effect as not having a FormatDescriptor
|
Default, // means "unformatted", same as not having a FormatDescriptor
|
||||||
NumericLE, // 1-4 byte number, little-endian
|
|
||||||
NumericBE, // 1-4 byte number, big-endian
|
NumericLE, // 1-4 byte number, little-endian
|
||||||
String, // character string
|
NumericBE, // 1-4 byte number, big-endian
|
||||||
Dense, // raw data, represented as compactly as possible
|
|
||||||
Fill // fill memory with a value
|
StringGeneric, // character string
|
||||||
|
StringReverse, // character string, in reverse order
|
||||||
|
StringNullTerm, // C-style null-terminated string
|
||||||
|
StringL8, // string with 8-bit length prefix
|
||||||
|
StringL16, // string with 16-bit length prefix
|
||||||
|
StringDci, // string terminated by flipped high bit (Dextral Char Inverted)
|
||||||
|
|
||||||
|
Dense, // raw data, represented as compactly as possible
|
||||||
|
Fill // fill memory with a value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Additional data type detail.
|
/// Additional data type detail. Generally affects the operand.
|
||||||
///
|
///
|
||||||
/// Some things are extracted from the data itself, e.g. we don't need to specify if
|
/// Some things are extracted from the data itself, e.g. we don't need to specify
|
||||||
/// a string is high- or low-ASCII, or what value to use for Fill.
|
/// what value to use for Fill.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum SubType : byte {
|
public enum SubType : byte {
|
||||||
None = 0,
|
None = 0,
|
||||||
@ -63,22 +71,18 @@ namespace SourceGen {
|
|||||||
Hex,
|
Hex,
|
||||||
Decimal,
|
Decimal,
|
||||||
Binary,
|
Binary,
|
||||||
Ascii, // aspirational; falls back on hex if data not suited
|
Address, // wants to be an address, but no symbol defined
|
||||||
Address, // wants to be an address, but no symbol defined
|
Symbol, // symbolic ref; replace with Expression, someday?
|
||||||
Symbol, // symbolic ref; replace with Expression, someday?
|
|
||||||
|
|
||||||
// String; default is straight text
|
// Strings and NumericLE/BE (single character)
|
||||||
Reverse, // plain ASCII in reverse order
|
Ascii, // ASCII (with or without the high bit set)
|
||||||
CString, // null-terminated
|
C64Petscii, // C64 PETSCII
|
||||||
L8String, // 8-bit length prefix
|
C64Screen, // C64 screen code
|
||||||
L16String, // 16-bit length prefix
|
|
||||||
Dci, // Dextral Character Inverted
|
|
||||||
DciReverse, // DCI with string backwards [deprecated -- no asm supports this]
|
|
||||||
|
|
||||||
// Dense; no sub-types
|
// Dense; no sub-types
|
||||||
|
|
||||||
// Fill; default is non-ignore
|
// Fill; default is non-ignore
|
||||||
Ignore // TODO(someday): use this for "don't care" sections
|
Ignore // TODO(someday): use this for "don't care" sections
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int MAX_NUMERIC_LEN = 4;
|
private const int MAX_NUMERIC_LEN = 4;
|
||||||
@ -264,6 +268,25 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the FormatDescriptor is a string type.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsString {
|
||||||
|
get {
|
||||||
|
switch (FormatType) {
|
||||||
|
case Type.StringGeneric:
|
||||||
|
case Type.StringReverse:
|
||||||
|
case Type.StringNullTerm:
|
||||||
|
case Type.StringL8:
|
||||||
|
case Type.StringL16:
|
||||||
|
case Type.StringDci:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the FormatDescriptor has a symbol or is Numeric/Address.
|
/// True if the FormatDescriptor has a symbol or is Numeric/Address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -320,6 +343,48 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string ToUiString() {
|
public string ToUiString() {
|
||||||
// NOTE: this should be made easier to localize
|
// NOTE: this should be made easier to localize
|
||||||
|
|
||||||
|
if (IsString) {
|
||||||
|
string descr;
|
||||||
|
switch (FormatSubType) {
|
||||||
|
case SubType.Ascii:
|
||||||
|
descr = "ASCII";
|
||||||
|
break;
|
||||||
|
case SubType.C64Petscii:
|
||||||
|
descr = "C64 PETSCII";
|
||||||
|
break;
|
||||||
|
case SubType.C64Screen:
|
||||||
|
descr = "C64 Screen";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
descr = "???";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (FormatType) {
|
||||||
|
case Type.StringGeneric:
|
||||||
|
descr += " string";
|
||||||
|
break;
|
||||||
|
case Type.StringReverse:
|
||||||
|
descr += " string (reverse)";
|
||||||
|
break;
|
||||||
|
case Type.StringNullTerm:
|
||||||
|
descr += " string (null term)";
|
||||||
|
break;
|
||||||
|
case Type.StringL8:
|
||||||
|
descr += " string (1-byte len)";
|
||||||
|
break;
|
||||||
|
case Type.StringL16:
|
||||||
|
descr += " string (2-byte len)";
|
||||||
|
break;
|
||||||
|
case Type.StringDci:
|
||||||
|
descr += " string (DCI)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
descr += " ???";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (FormatSubType) {
|
switch (FormatSubType) {
|
||||||
case SubType.None:
|
case SubType.None:
|
||||||
switch (FormatType) {
|
switch (FormatType) {
|
||||||
@ -328,13 +393,12 @@ namespace SourceGen {
|
|||||||
return "Numeric (little-endian)";
|
return "Numeric (little-endian)";
|
||||||
case Type.NumericBE:
|
case Type.NumericBE:
|
||||||
return "Numeric (big-endian)";
|
return "Numeric (big-endian)";
|
||||||
case Type.String:
|
|
||||||
return "String (generic)";
|
|
||||||
case Type.Dense:
|
case Type.Dense:
|
||||||
return "Dense";
|
return "Dense";
|
||||||
case Type.Fill:
|
case Type.Fill:
|
||||||
return "Fill";
|
return "Fill";
|
||||||
default:
|
default:
|
||||||
|
// strings handled earlier
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
case SubType.Hex:
|
case SubType.Hex:
|
||||||
@ -343,25 +407,16 @@ namespace SourceGen {
|
|||||||
return "Numeric, Decimal";
|
return "Numeric, Decimal";
|
||||||
case SubType.Binary:
|
case SubType.Binary:
|
||||||
return "Numeric, Binary";
|
return "Numeric, Binary";
|
||||||
case SubType.Ascii:
|
|
||||||
return "ASCII";
|
|
||||||
case SubType.Address:
|
case SubType.Address:
|
||||||
return "Address";
|
return "Address";
|
||||||
case SubType.Symbol:
|
case SubType.Symbol:
|
||||||
return "Symbol \"" + SymbolRef.Label + "\"";
|
return "Symbol \"" + SymbolRef.Label + "\"";
|
||||||
|
case SubType.Ascii:
|
||||||
case SubType.Reverse:
|
return "ASCII";
|
||||||
return "String (reverse)";
|
case SubType.C64Petscii:
|
||||||
case SubType.CString:
|
return "C64 PETSCII";
|
||||||
return "String (null-term)";
|
case SubType.C64Screen:
|
||||||
case SubType.L8String:
|
return "C64 Screen";
|
||||||
return "String (1-byte len)";
|
|
||||||
case SubType.L16String:
|
|
||||||
return "String (2-byte len)";
|
|
||||||
case SubType.Dci:
|
|
||||||
return "String (DCI)";
|
|
||||||
case SubType.DciReverse:
|
|
||||||
return "String (RevDCI)";
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "???";
|
return "???";
|
||||||
|
@ -52,7 +52,7 @@ namespace SourceGen {
|
|||||||
// ignore stuff that's in one side but not the other. However, if we're opening a
|
// ignore stuff that's in one side but not the other. However, if we're opening a
|
||||||
// newer file in an older program, it's worth letting the user know that some stuff
|
// newer file in an older program, it's worth letting the user know that some stuff
|
||||||
// may get lost as soon as they save the file.
|
// may get lost as soon as they save the file.
|
||||||
public const int CONTENT_VERSION = 1;
|
public const int CONTENT_VERSION = 2;
|
||||||
|
|
||||||
private static readonly bool ADD_CRLF = true;
|
private static readonly bool ADD_CRLF = true;
|
||||||
|
|
||||||
@ -669,6 +669,33 @@ namespace SourceGen {
|
|||||||
dfd = null;
|
dfd = null;
|
||||||
FormatDescriptor.Type format;
|
FormatDescriptor.Type format;
|
||||||
FormatDescriptor.SubType subFormat;
|
FormatDescriptor.SubType subFormat;
|
||||||
|
|
||||||
|
// File version 1 used a different set of enumerated values for defining strings.
|
||||||
|
// Parse it out here.
|
||||||
|
if ("String".Equals(sfd.Format)) {
|
||||||
|
subFormat = FormatDescriptor.SubType.Ascii;
|
||||||
|
if ("None".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringGeneric;
|
||||||
|
} else if ("Reverse".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringReverse;
|
||||||
|
} else if ("CString".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringNullTerm;
|
||||||
|
} else if ("L8String".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringL8;
|
||||||
|
} else if ("L16String".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringL16;
|
||||||
|
} else if ("Dci".Equals(sfd.SubFormat)) {
|
||||||
|
format = FormatDescriptor.Type.StringDci;
|
||||||
|
} else {
|
||||||
|
// DciReverse no longer supported; output as dense hex
|
||||||
|
format = FormatDescriptor.Type.Dense;
|
||||||
|
subFormat = FormatDescriptor.SubType.None;
|
||||||
|
}
|
||||||
|
Debug.WriteLine("Found v1 string, fmt=" + format + ", sub=" + subFormat);
|
||||||
|
dfd = FormatDescriptor.Create(sfd.Length, format, subFormat);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
format = (FormatDescriptor.Type)Enum.Parse(
|
format = (FormatDescriptor.Type)Enum.Parse(
|
||||||
typeof(FormatDescriptor.Type), sfd.Format);
|
typeof(FormatDescriptor.Type), sfd.Format);
|
||||||
|
@ -87,8 +87,6 @@ namespace SourceGen {
|
|||||||
public string StrNullTermHi { get; set; }
|
public string StrNullTermHi { get; set; }
|
||||||
public string StrDci { get; set; }
|
public string StrDci { get; set; }
|
||||||
public string StrDciHi { get; set; }
|
public string StrDciHi { get; set; }
|
||||||
public string StrDciReverse { get; set; }
|
|
||||||
public string StrDciReverseHi { get; set; }
|
|
||||||
|
|
||||||
public string GetDefineData(int width) {
|
public string GetDefineData(int width) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
@ -180,8 +178,6 @@ namespace SourceGen {
|
|||||||
StrNullTermHi = ".zstrh",
|
StrNullTermHi = ".zstrh",
|
||||||
StrDci = ".dstr",
|
StrDci = ".dstr",
|
||||||
StrDciHi = ".dstrh",
|
StrDciHi = ".dstrh",
|
||||||
StrDciReverse = ".rdstr",
|
|
||||||
StrDciReverseHi = ".rdstrh",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -192,6 +188,37 @@ namespace SourceGen {
|
|||||||
/// <param name="dfd">Data format descriptor.</param>
|
/// <param name="dfd">Data format descriptor.</param>
|
||||||
/// <returns>Line count.</returns>
|
/// <returns>Line count.</returns>
|
||||||
public static int ComputeRequiredLineCount(Formatter formatter, FormatDescriptor dfd) {
|
public static int ComputeRequiredLineCount(Formatter formatter, FormatDescriptor dfd) {
|
||||||
|
if (dfd.IsString) {
|
||||||
|
// Subtract two chars, to leave room for start/end delimiter. We use
|
||||||
|
// non-ASCII delimiters on-screen, so there's nothing to escape there.
|
||||||
|
int maxLen = MAX_OPERAND_LEN - 2;
|
||||||
|
|
||||||
|
// Remove leading length or trailing null byte from string length.
|
||||||
|
int textLen = dfd.Length;
|
||||||
|
switch (dfd.FormatType) {
|
||||||
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
textLen--;
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
textLen -= 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int strLen = (textLen + maxLen - 1) / maxLen;
|
||||||
|
if (strLen == 0) {
|
||||||
|
// Empty string, but we still need to output a line.
|
||||||
|
strLen = 1;
|
||||||
|
}
|
||||||
|
return strLen;
|
||||||
|
}
|
||||||
|
|
||||||
switch (dfd.FormatType) {
|
switch (dfd.FormatType) {
|
||||||
case FormatDescriptor.Type.Default:
|
case FormatDescriptor.Type.Default:
|
||||||
case FormatDescriptor.Type.NumericLE:
|
case FormatDescriptor.Type.NumericLE:
|
||||||
@ -204,37 +231,6 @@ namespace SourceGen {
|
|||||||
int textLen = dfd.Length * 2;
|
int textLen = dfd.Length * 2;
|
||||||
return (textLen + maxLen - 1) / maxLen;
|
return (textLen + maxLen - 1) / maxLen;
|
||||||
}
|
}
|
||||||
case FormatDescriptor.Type.String: {
|
|
||||||
// Subtract two chars, to leave room for start/end delimiter. We use
|
|
||||||
// non-ASCII delimiters on-screen, so there's nothing to escape there.
|
|
||||||
int maxLen = MAX_OPERAND_LEN - 2;
|
|
||||||
|
|
||||||
// Remove leading length or trailing null byte from string length.
|
|
||||||
int textLen = dfd.Length;
|
|
||||||
switch (dfd.FormatSubType) {
|
|
||||||
case FormatDescriptor.SubType.None:
|
|
||||||
case FormatDescriptor.SubType.Dci:
|
|
||||||
case FormatDescriptor.SubType.Reverse:
|
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
case FormatDescriptor.SubType.L8String:
|
|
||||||
textLen--;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.L16String:
|
|
||||||
textLen -= 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug.Assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int strLen = (textLen + maxLen - 1) / maxLen;
|
|
||||||
if (strLen == 0) {
|
|
||||||
// Empty string, but we still need to output a line.
|
|
||||||
strLen = 1;
|
|
||||||
}
|
|
||||||
return strLen;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false);
|
Debug.Assert(false);
|
||||||
return 1;
|
return 1;
|
||||||
@ -274,89 +270,94 @@ namespace SourceGen {
|
|||||||
// multi-line items.
|
// multi-line items.
|
||||||
PseudoOut po = new PseudoOut();
|
PseudoOut po = new PseudoOut();
|
||||||
|
|
||||||
switch (dfd.FormatType) {
|
if (dfd.IsString) {
|
||||||
case FormatDescriptor.Type.Default:
|
// It's hard to do strings in single-line pieces because of prefix lengths,
|
||||||
if (length != 1) {
|
// terminating nulls, DCI polarity, and reverse-order strings. We
|
||||||
// This shouldn't happen.
|
// really just want to convert the whole thing to a run of chars
|
||||||
Debug.Assert(false);
|
// and then pull out a chunk. As an optimization we can handle
|
||||||
length = 1;
|
// generic strings more efficiently, which should help if auto-analysis is
|
||||||
|
// creating massive strings (at least until auto-analysis learns how to do
|
||||||
|
// more complex things).
|
||||||
|
//
|
||||||
|
// TODO: consider storing the full string on the first line, then each
|
||||||
|
// subsequent line has a reference to it with offset+length
|
||||||
|
if (dfd.FormatType == FormatDescriptor.Type.StringGeneric) {
|
||||||
|
int maxPerLine = MAX_OPERAND_LEN - 2;
|
||||||
|
offset += subIndex * maxPerLine;
|
||||||
|
length -= subIndex * maxPerLine;
|
||||||
|
if (length > maxPerLine) {
|
||||||
|
length = maxPerLine;
|
||||||
}
|
}
|
||||||
po.Opcode = opNames.GetDefineData(length);
|
char[] ltext = BytesToChars(formatter, opNames, dfd.FormatType, data,
|
||||||
int operand = RawData.GetWord(data, offset, length, false);
|
offset, length, out string lpopcode, out int unused);
|
||||||
po.Operand = formatter.FormatHexValue(operand, length * 2);
|
po.Opcode = lpopcode;
|
||||||
break;
|
po.Operand = "\u201c" + new string(ltext) + "\u201d";
|
||||||
case FormatDescriptor.Type.NumericLE:
|
} else {
|
||||||
po.Opcode = opNames.GetDefineData(length);
|
char[] text = BytesToChars(formatter, opNames, dfd.FormatType, data,
|
||||||
operand = RawData.GetWord(data, offset, length, false);
|
offset, length, out string popcode, out int showHexZeroes);
|
||||||
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
|
||||||
operand, length, FormatNumericOpFlags.None);
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.Type.NumericBE:
|
|
||||||
po.Opcode = opNames.GetDefineBigData(length);
|
|
||||||
operand = RawData.GetWord(data, offset, length, true);
|
|
||||||
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
|
||||||
operand, length, FormatNumericOpFlags.None);
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.Type.Fill:
|
|
||||||
po.Opcode = opNames.Fill;
|
|
||||||
po.Operand = length + "," + formatter.FormatHexValue(data[offset], 2);
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.Type.Dense: {
|
|
||||||
int maxPerLine = MAX_OPERAND_LEN / 2;
|
|
||||||
offset += subIndex * maxPerLine;
|
|
||||||
length -= subIndex * maxPerLine;
|
|
||||||
if (length > maxPerLine) {
|
|
||||||
length = maxPerLine;
|
|
||||||
}
|
|
||||||
po.Opcode = opNames.Dense;
|
|
||||||
po.Operand = formatter.FormatDenseHex(data, offset, length);
|
|
||||||
//List<PseudoOut> outList = new List<PseudoOut>();
|
|
||||||
//GenerateTextLines(text, "", "", po, outList);
|
|
||||||
//po = outList[subIndex];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.Type.String:
|
|
||||||
// It's hard to do strings in single-line pieces because of prefix lengths,
|
|
||||||
// terminating nulls, DCI polarity, and reverse-order strings. We
|
|
||||||
// really just want to convert the whole thing to a run of chars
|
|
||||||
// and then pull out a chunk. As an optimization we can handle
|
|
||||||
// generic strings (subtype=None) more efficiently, which should solve
|
|
||||||
// the problem of massive strings created by auto-analysis.
|
|
||||||
if (dfd.FormatSubType == FormatDescriptor.SubType.None) {
|
|
||||||
int maxPerLine = MAX_OPERAND_LEN - 2;
|
|
||||||
offset += subIndex * maxPerLine;
|
|
||||||
length -= subIndex * maxPerLine;
|
|
||||||
if (length > maxPerLine) {
|
|
||||||
length = maxPerLine;
|
|
||||||
}
|
|
||||||
char[] ltext = BytesToChars(formatter, opNames, dfd.FormatSubType, data,
|
|
||||||
offset, length, out string lpopcode, out int unused);
|
|
||||||
po.Opcode = lpopcode;
|
|
||||||
po.Operand = "\u201c" + new string(ltext) + "\u201d";
|
|
||||||
} else {
|
|
||||||
char[] text = BytesToChars(formatter, opNames, dfd.FormatSubType, data,
|
|
||||||
offset, length, out string popcode, out int showHexZeroes);
|
|
||||||
|
|
||||||
if (showHexZeroes == 1) {
|
if (showHexZeroes == 1) {
|
||||||
po.Opcode = opNames.DefineData1;
|
po.Opcode = opNames.DefineData1;
|
||||||
po.Operand = formatter.FormatHexValue(0, 2);
|
po.Operand = formatter.FormatHexValue(0, 2);
|
||||||
} else if (showHexZeroes == 2) {
|
} else if (showHexZeroes == 2) {
|
||||||
po.Opcode = opNames.DefineData2;
|
po.Opcode = opNames.DefineData2;
|
||||||
po.Operand = formatter.FormatHexValue(0, 4);
|
po.Operand = formatter.FormatHexValue(0, 4);
|
||||||
} else {
|
} else {
|
||||||
Debug.Assert(showHexZeroes == 0);
|
Debug.Assert(showHexZeroes == 0);
|
||||||
po.Opcode = popcode;
|
po.Opcode = popcode;
|
||||||
List<PseudoOut> outList = new List<PseudoOut>();
|
List<PseudoOut> outList = new List<PseudoOut>();
|
||||||
GenerateTextLines(text, "\u201c", "\u201d", po, outList);
|
GenerateTextLines(text, "\u201c", "\u201d", po, outList);
|
||||||
po = outList[subIndex];
|
po = outList[subIndex];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
} else {
|
||||||
Debug.Assert(false);
|
switch (dfd.FormatType) {
|
||||||
po.Opcode = ".???";
|
case FormatDescriptor.Type.Default:
|
||||||
po.Operand = "$" + data[offset].ToString("x2");
|
if (length != 1) {
|
||||||
break;
|
// This shouldn't happen.
|
||||||
|
Debug.Assert(false);
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
po.Opcode = opNames.GetDefineData(length);
|
||||||
|
int operand = RawData.GetWord(data, offset, length, false);
|
||||||
|
po.Operand = formatter.FormatHexValue(operand, length * 2);
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.NumericLE:
|
||||||
|
po.Opcode = opNames.GetDefineData(length);
|
||||||
|
operand = RawData.GetWord(data, offset, length, false);
|
||||||
|
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
||||||
|
operand, length, FormatNumericOpFlags.None);
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.NumericBE:
|
||||||
|
po.Opcode = opNames.GetDefineBigData(length);
|
||||||
|
operand = RawData.GetWord(data, offset, length, true);
|
||||||
|
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
||||||
|
operand, length, FormatNumericOpFlags.None);
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.Fill:
|
||||||
|
po.Opcode = opNames.Fill;
|
||||||
|
po.Operand = length + "," + formatter.FormatHexValue(data[offset], 2);
|
||||||
|
break;
|
||||||
|
case FormatDescriptor.Type.Dense: {
|
||||||
|
int maxPerLine = MAX_OPERAND_LEN / 2;
|
||||||
|
offset += subIndex * maxPerLine;
|
||||||
|
length -= subIndex * maxPerLine;
|
||||||
|
if (length > maxPerLine) {
|
||||||
|
length = maxPerLine;
|
||||||
|
}
|
||||||
|
po.Opcode = opNames.Dense;
|
||||||
|
po.Operand = formatter.FormatDenseHex(data, offset, length);
|
||||||
|
//List<PseudoOut> outList = new List<PseudoOut>();
|
||||||
|
//GenerateTextLines(text, "", "", po, outList);
|
||||||
|
//po = outList[subIndex];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false);
|
||||||
|
po.Opcode = ".???";
|
||||||
|
po.Operand = "$" + data[offset].ToString("x2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return po;
|
return po;
|
||||||
@ -368,7 +369,7 @@ namespace SourceGen {
|
|||||||
/// are not shown.
|
/// are not shown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="formatter">Formatter object.</param>
|
/// <param name="formatter">Formatter object.</param>
|
||||||
/// <param name="subType">String sub-type.</param>
|
/// <param name="formatType">String layout.</param>
|
||||||
/// <param name="data">File data.</param>
|
/// <param name="data">File data.</param>
|
||||||
/// <param name="offset">Offset, within data, of start of string.</param>
|
/// <param name="offset">Offset, within data, of start of string.</param>
|
||||||
/// <param name="length">Number of bytes to convert.</param>
|
/// <param name="length">Number of bytes to convert.</param>
|
||||||
@ -377,7 +378,7 @@ namespace SourceGen {
|
|||||||
/// length or null-termination) instead of an empty string.</param>
|
/// length or null-termination) instead of an empty string.</param>
|
||||||
/// <returns>Array of characters with string data.</returns>
|
/// <returns>Array of characters with string data.</returns>
|
||||||
private static char[] BytesToChars(Formatter formatter, PseudoOpNames opNames,
|
private static char[] BytesToChars(Formatter formatter, PseudoOpNames opNames,
|
||||||
FormatDescriptor.SubType subType, byte[] data, int offset, int length,
|
FormatDescriptor.Type formatType, byte[] data, int offset, int length,
|
||||||
out string popcode, out int showHexZeroes) {
|
out string popcode, out int showHexZeroes) {
|
||||||
Debug.Assert(length > 0);
|
Debug.Assert(length > 0);
|
||||||
|
|
||||||
@ -389,32 +390,25 @@ namespace SourceGen {
|
|||||||
|
|
||||||
showHexZeroes = 0;
|
showHexZeroes = 0;
|
||||||
|
|
||||||
switch (subType) {
|
switch (formatType) {
|
||||||
case FormatDescriptor.SubType.None:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
// High or low ASCII, full width specified by formatter.
|
// High or low ASCII, full width specified by formatter.
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
popcode = highAscii ? opNames.StrGenericHi : opNames.StrGeneric;
|
popcode = highAscii ? opNames.StrGenericHi : opNames.StrGeneric;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Dci:
|
case FormatDescriptor.Type.StringDci:
|
||||||
// High or low ASCII, full width specified by formatter.
|
// High or low ASCII, full width specified by formatter.
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
popcode = highAscii ? opNames.StrDciHi : opNames.StrDci;
|
popcode = highAscii ? opNames.StrDciHi : opNames.StrDci;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
case FormatDescriptor.Type.StringReverse:
|
||||||
// High or low ASCII, full width specified by formatter. Show characters
|
// High or low ASCII, full width specified by formatter. Show characters
|
||||||
// in reverse order.
|
// in reverse order.
|
||||||
highAscii = (data[offset + strLen - 1] & 0x80) != 0;
|
highAscii = (data[offset + strLen - 1] & 0x80) != 0;
|
||||||
popcode = highAscii ? opNames.StrReverseHi : opNames.StrReverse;
|
popcode = highAscii ? opNames.StrReverseHi : opNames.StrReverse;
|
||||||
reverse = true;
|
reverse = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
// High or low ASCII, full width specified by formatter. Show characters
|
|
||||||
// in reverse order.
|
|
||||||
highAscii = (data[offset + strLen - 1] & 0x80) != 0;
|
|
||||||
popcode = highAscii ? opNames.StrDciReverseHi : opNames.StrDciReverse;
|
|
||||||
reverse = true;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.CString:
|
|
||||||
// High or low ASCII, with a terminating null. Don't show the null. If
|
// High or low ASCII, with a terminating null. Don't show the null. If
|
||||||
// it's an empty string, just show the null byte as hex.
|
// it's an empty string, just show the null byte as hex.
|
||||||
highAscii = (data[offset] & 0x80) != 0;
|
highAscii = (data[offset] & 0x80) != 0;
|
||||||
@ -424,7 +418,7 @@ namespace SourceGen {
|
|||||||
showHexZeroes = 1;
|
showHexZeroes = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L8String:
|
case FormatDescriptor.Type.StringL8:
|
||||||
// High or low ASCII, with a leading length byte. Don't show the null.
|
// High or low ASCII, with a leading length byte. Don't show the null.
|
||||||
// If it's an empty string, just show the length byte as hex.
|
// If it's an empty string, just show the length byte as hex.
|
||||||
strOffset++;
|
strOffset++;
|
||||||
@ -436,7 +430,7 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
popcode = highAscii ? opNames.StrLen8Hi : opNames.StrLen8;
|
popcode = highAscii ? opNames.StrLen8Hi : opNames.StrLen8;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.L16String:
|
case FormatDescriptor.Type.StringL16:
|
||||||
// High or low ASCII, with a leading length word. Don't show the null.
|
// High or low ASCII, with a leading length word. Don't show the null.
|
||||||
// If it's an empty string, just show the length word as hex.
|
// If it's an empty string, just show the length word as hex.
|
||||||
Debug.Assert(strLen > 1);
|
Debug.Assert(strLen > 1);
|
||||||
@ -455,6 +449,7 @@ namespace SourceGen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(petscii): convert character encoding
|
||||||
char[] text = new char[strLen];
|
char[] text = new char[strLen];
|
||||||
if (!reverse) {
|
if (!reverse) {
|
||||||
for (int i = 0; i < strLen; i++) {
|
for (int i = 0; i < strLen; i++) {
|
||||||
@ -547,6 +542,10 @@ namespace SourceGen {
|
|||||||
case FormatDescriptor.SubType.Binary:
|
case FormatDescriptor.SubType.Binary:
|
||||||
return formatter.FormatBinaryValue(operandValue, hexMinLen * 4);
|
return formatter.FormatBinaryValue(operandValue, hexMinLen * 4);
|
||||||
case FormatDescriptor.SubType.Ascii:
|
case FormatDescriptor.SubType.Ascii:
|
||||||
|
case FormatDescriptor.SubType.C64Petscii:
|
||||||
|
case FormatDescriptor.SubType.C64Screen:
|
||||||
|
// TODO(petscii): convert encoding; use a helper function *not* in
|
||||||
|
// formatter -- pass converted char value in along with operandValue
|
||||||
return formatter.FormatAsciiOrHex(operandValue);
|
return formatter.FormatAsciiOrHex(operandValue);
|
||||||
case FormatDescriptor.SubType.Symbol:
|
case FormatDescriptor.SubType.Symbol:
|
||||||
if (symbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
|
if (symbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
|
||||||
|
@ -528,6 +528,9 @@ namespace SourceGen.WpfGui {
|
|||||||
radioSimpleDataBinary.IsChecked = true;
|
radioSimpleDataBinary.IsChecked = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Ascii:
|
case FormatDescriptor.SubType.Ascii:
|
||||||
|
case FormatDescriptor.SubType.C64Petscii:
|
||||||
|
case FormatDescriptor.SubType.C64Screen:
|
||||||
|
// TODO(petscii): update UI
|
||||||
radioSimpleDataAscii.IsChecked = true;
|
radioSimpleDataAscii.IsChecked = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Address:
|
case FormatDescriptor.SubType.Address:
|
||||||
@ -560,34 +563,23 @@ namespace SourceGen.WpfGui {
|
|||||||
// preferred format not enabled; leave Hex/Low checked
|
// preferred format not enabled; leave Hex/Low checked
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
switch (dfd.FormatSubType) {
|
preferredFormat = radioStringMixed;
|
||||||
case FormatDescriptor.SubType.None:
|
break;
|
||||||
preferredFormat = radioStringMixed;
|
case FormatDescriptor.Type.StringReverse:
|
||||||
break;
|
preferredFormat = radioStringMixedReverse;
|
||||||
case FormatDescriptor.SubType.Reverse:
|
break;
|
||||||
preferredFormat = radioStringMixedReverse;
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
break;
|
preferredFormat = radioStringNullTerm;
|
||||||
case FormatDescriptor.SubType.CString:
|
break;
|
||||||
preferredFormat = radioStringNullTerm;
|
case FormatDescriptor.Type.StringL8:
|
||||||
break;
|
preferredFormat = radioStringLen8;
|
||||||
case FormatDescriptor.SubType.L8String:
|
break;
|
||||||
preferredFormat = radioStringLen8;
|
case FormatDescriptor.Type.StringL16:
|
||||||
break;
|
preferredFormat = radioStringLen16;
|
||||||
case FormatDescriptor.SubType.L16String:
|
break;
|
||||||
preferredFormat = radioStringLen16;
|
case FormatDescriptor.Type.StringDci:
|
||||||
break;
|
preferredFormat = radioStringDci;
|
||||||
case FormatDescriptor.SubType.Dci:
|
|
||||||
preferredFormat = radioStringDci;
|
|
||||||
break;
|
|
||||||
case FormatDescriptor.SubType.DciReverse:
|
|
||||||
preferredFormat = radioDefaultFormat;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug.Assert(false);
|
|
||||||
preferredFormat = radioDefaultFormat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.Dense:
|
case FormatDescriptor.Type.Dense:
|
||||||
preferredFormat = radioDenseHex;
|
preferredFormat = radioDenseHex;
|
||||||
@ -639,6 +631,7 @@ namespace SourceGen.WpfGui {
|
|||||||
} else if (radioSimpleDataBinary.IsChecked == true) {
|
} else if (radioSimpleDataBinary.IsChecked == true) {
|
||||||
subType = FormatDescriptor.SubType.Binary;
|
subType = FormatDescriptor.SubType.Binary;
|
||||||
} else if (radioSimpleDataAscii.IsChecked == true) {
|
} else if (radioSimpleDataAscii.IsChecked == true) {
|
||||||
|
// TODO(petscii): configure subType correctly
|
||||||
subType = FormatDescriptor.SubType.Ascii;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioSimpleDataAddress.IsChecked == true) {
|
} else if (radioSimpleDataAddress.IsChecked == true) {
|
||||||
subType = FormatDescriptor.SubType.Address;
|
subType = FormatDescriptor.SubType.Address;
|
||||||
@ -688,26 +681,25 @@ namespace SourceGen.WpfGui {
|
|||||||
type = FormatDescriptor.Type.Dense;
|
type = FormatDescriptor.Type.Dense;
|
||||||
} else if (radioFill.IsChecked == true) {
|
} else if (radioFill.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.Fill;
|
type = FormatDescriptor.Type.Fill;
|
||||||
|
subType = FormatDescriptor.SubType.Ascii; // TODO(petscii): set encoding
|
||||||
} else if (radioStringMixed.IsChecked == true) {
|
} else if (radioStringMixed.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringGeneric;
|
||||||
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioStringMixedReverse.IsChecked == true) {
|
} else if (radioStringMixedReverse.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringReverse;
|
||||||
subType = FormatDescriptor.SubType.Reverse;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioStringNullTerm.IsChecked == true) {
|
} else if (radioStringNullTerm.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringNullTerm;
|
||||||
subType = FormatDescriptor.SubType.CString;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioStringLen8.IsChecked == true) {
|
} else if (radioStringLen8.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringL8;
|
||||||
subType = FormatDescriptor.SubType.L8String;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioStringLen16.IsChecked == true) {
|
} else if (radioStringLen16.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringL16;
|
||||||
subType = FormatDescriptor.SubType.L16String;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (radioStringDci.IsChecked == true) {
|
} else if (radioStringDci.IsChecked == true) {
|
||||||
type = FormatDescriptor.Type.String;
|
type = FormatDescriptor.Type.StringDci;
|
||||||
subType = FormatDescriptor.SubType.Dci;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
//} else if (radioStringDciReverse.Checked) {
|
|
||||||
// type = FormatDescriptor.Type.String;
|
|
||||||
// subType = FormatDescriptor.SubType.DciReverse;
|
|
||||||
} else {
|
} else {
|
||||||
Debug.Assert(false);
|
Debug.Assert(false);
|
||||||
// default/none
|
// default/none
|
||||||
@ -720,26 +712,26 @@ namespace SourceGen.WpfGui {
|
|||||||
while (iter.MoveNext()) {
|
while (iter.MoveNext()) {
|
||||||
TypedRangeSet.TypedRange rng = iter.Current;
|
TypedRangeSet.TypedRange rng = iter.Current;
|
||||||
|
|
||||||
if (type == FormatDescriptor.Type.String) {
|
// TODO(petscii): handle encoding on all four calls
|
||||||
// We want to create one FormatDescriptor object per string. That way
|
switch (type) {
|
||||||
// each string gets its own line.
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
if ((subType == FormatDescriptor.SubType.None ||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
subType == FormatDescriptor.SubType.Reverse)) {
|
CreateMixedStringEntries(rng.Low, rng.High, type, subType);
|
||||||
CreateMixedStringEntries(rng.Low, rng.High, subType);
|
break;
|
||||||
} else if (subType == FormatDescriptor.SubType.CString) {
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
CreateCStringEntries(rng.Low, rng.High, subType);
|
CreateCStringEntries(rng.Low, rng.High, type, subType);
|
||||||
} else if (subType == FormatDescriptor.SubType.L8String ||
|
break;
|
||||||
subType == FormatDescriptor.SubType.L16String) {
|
case FormatDescriptor.Type.StringL8:
|
||||||
CreateLengthStringEntries(rng.Low, rng.High, subType);
|
case FormatDescriptor.Type.StringL16:
|
||||||
} else if (subType == FormatDescriptor.SubType.Dci ||
|
CreateLengthStringEntries(rng.Low, rng.High, type, subType);
|
||||||
subType == FormatDescriptor.SubType.DciReverse) {
|
break;
|
||||||
CreateDciStringEntries(rng.Low, rng.High, subType);
|
case FormatDescriptor.Type.StringDci:
|
||||||
} else {
|
CreateDciStringEntries(rng.Low, rng.High, type, subType);
|
||||||
Debug.Assert(false);
|
break;
|
||||||
CreateMixedStringEntries(rng.Low, rng.High, subType); // shrug
|
default:
|
||||||
}
|
CreateSimpleEntries(type, subType, chunkLength, symbolRef,
|
||||||
} else {
|
rng.Low, rng.High);
|
||||||
CreateSimpleEntries(type, subType, chunkLength, symbolRef, rng.Low, rng.High);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -793,7 +785,7 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <param name="low">Offset of first byte in range.</param>
|
/// <param name="low">Offset of first byte in range.</param>
|
||||||
/// <param name="high">Offset of last byte in range.</param>
|
/// <param name="high">Offset of last byte in range.</param>
|
||||||
/// <param name="subType">String sub-type.</param>
|
/// <param name="subType">String sub-type.</param>
|
||||||
private void CreateMixedStringEntries(int low, int high,
|
private void CreateMixedStringEntries(int low, int high, FormatDescriptor.Type type,
|
||||||
FormatDescriptor.SubType subType) {
|
FormatDescriptor.SubType subType) {
|
||||||
int stringStart = -1;
|
int stringStart = -1;
|
||||||
int highBit = 0;
|
int highBit = 0;
|
||||||
@ -846,11 +838,12 @@ namespace SourceGen.WpfGui {
|
|||||||
Debug.Assert(length > 0);
|
Debug.Assert(length > 0);
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
// single byte, output as single ASCII char rather than 1-byte string
|
// single byte, output as single ASCII char rather than 1-byte string
|
||||||
|
// TODO(petscii): low/high?
|
||||||
CreateByteFD(offset, FormatDescriptor.SubType.Ascii);
|
CreateByteFD(offset, FormatDescriptor.SubType.Ascii);
|
||||||
} else {
|
} else {
|
||||||
FormatDescriptor dfd;
|
FormatDescriptor dfd;
|
||||||
dfd = FormatDescriptor.Create(length,
|
dfd = FormatDescriptor.Create(length,
|
||||||
FormatDescriptor.Type.String, subType);
|
FormatDescriptor.Type.StringGeneric, subType);
|
||||||
Results.Add(offset, dfd);
|
Results.Add(offset, dfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -873,14 +866,14 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <param name="low">Offset of first byte in range.</param>
|
/// <param name="low">Offset of first byte in range.</param>
|
||||||
/// <param name="high">Offset of last byte in range.</param>
|
/// <param name="high">Offset of last byte in range.</param>
|
||||||
/// <param name="subType">String sub-type.</param>
|
/// <param name="subType">String sub-type.</param>
|
||||||
private void CreateCStringEntries(int low, int high,
|
private void CreateCStringEntries(int low, int high, FormatDescriptor.Type type,
|
||||||
FormatDescriptor.SubType subType) {
|
FormatDescriptor.SubType subType) {
|
||||||
int startOffset = low;
|
int startOffset = low;
|
||||||
for (int i = low; i <= high; i++) {
|
for (int i = low; i <= high; i++) {
|
||||||
if (mFileData[i] == 0x00) {
|
if (mFileData[i] == 0x00) {
|
||||||
// End of string. Zero-length strings are allowed.
|
// End of string. Zero-length strings are allowed.
|
||||||
FormatDescriptor dfd = FormatDescriptor.Create(
|
FormatDescriptor dfd = FormatDescriptor.Create(
|
||||||
i - startOffset + 1, FormatDescriptor.Type.String, subType);
|
i - startOffset + 1, type, subType);
|
||||||
Results.Add(startOffset, dfd);
|
Results.Add(startOffset, dfd);
|
||||||
startOffset = i + 1;
|
startOffset = i + 1;
|
||||||
} else {
|
} else {
|
||||||
@ -899,20 +892,19 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <param name="low">Offset of first byte in range.</param>
|
/// <param name="low">Offset of first byte in range.</param>
|
||||||
/// <param name="high">Offset of last byte in range.</param>
|
/// <param name="high">Offset of last byte in range.</param>
|
||||||
/// <param name="subType">String sub-type.</param>
|
/// <param name="subType">String sub-type.</param>
|
||||||
private void CreateLengthStringEntries(int low, int high,
|
private void CreateLengthStringEntries(int low, int high, FormatDescriptor.Type type,
|
||||||
FormatDescriptor.SubType subType) {
|
FormatDescriptor.SubType subType) {
|
||||||
int i;
|
int i;
|
||||||
for (i = low; i <= high;) {
|
for (i = low; i <= high;) {
|
||||||
int length = mFileData[i];
|
int length = mFileData[i];
|
||||||
if (subType == FormatDescriptor.SubType.L16String) {
|
if (type == FormatDescriptor.Type.StringL16) {
|
||||||
length |= mFileData[i + 1] << 8;
|
length |= mFileData[i + 1] << 8;
|
||||||
length += 2;
|
length += 2;
|
||||||
} else {
|
} else {
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
// Zero-length strings are allowed.
|
// Zero-length strings are allowed.
|
||||||
FormatDescriptor dfd = FormatDescriptor.Create(length,
|
FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType);
|
||||||
FormatDescriptor.Type.String, subType);
|
|
||||||
Results.Add(i, dfd);
|
Results.Add(i, dfd);
|
||||||
i += length;
|
i += length;
|
||||||
}
|
}
|
||||||
@ -927,36 +919,25 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <param name="low">Offset of first byte in range.</param>
|
/// <param name="low">Offset of first byte in range.</param>
|
||||||
/// <param name="high">Offset of last byte in range.</param>
|
/// <param name="high">Offset of last byte in range.</param>
|
||||||
/// <param name="subType">String sub-type.</param>
|
/// <param name="subType">String sub-type.</param>
|
||||||
private void CreateDciStringEntries(int low, int high,
|
private void CreateDciStringEntries(int low, int high, FormatDescriptor.Type type,
|
||||||
FormatDescriptor.SubType subType) {
|
FormatDescriptor.SubType subType) {
|
||||||
int start, end, adj, endMask;
|
int end, endMask;
|
||||||
if (subType == FormatDescriptor.SubType.Dci) {
|
|
||||||
start = low;
|
end = high + 1;
|
||||||
end = high + 1;
|
|
||||||
adj = 1;
|
|
||||||
} else if (subType == FormatDescriptor.SubType.DciReverse) {
|
|
||||||
start = high;
|
|
||||||
end = low - 1;
|
|
||||||
adj = -1;
|
|
||||||
} else {
|
|
||||||
Debug.Assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero-length strings aren't a thing for DCI. The analyzer requires that all
|
// Zero-length strings aren't a thing for DCI. The analyzer requires that all
|
||||||
// strings in a region have the same polarity, so just grab the last byte.
|
// strings in a region have the same polarity, so just grab the last byte.
|
||||||
endMask = mFileData[end - 1] & 0x80;
|
endMask = mFileData[end - 1] & 0x80;
|
||||||
|
|
||||||
int stringStart = start;
|
int stringStart = low;
|
||||||
for (int i = start; i != end; i += adj) {
|
for (int i = low; i != end; i++) {
|
||||||
byte val = mFileData[i];
|
byte val = mFileData[i];
|
||||||
if ((val & 0x80) == endMask) {
|
if ((val & 0x80) == endMask) {
|
||||||
// found the end of a string
|
// found the end of a string
|
||||||
int length = (i - stringStart) * adj + 1;
|
int length = (i - stringStart) + 1;
|
||||||
FormatDescriptor dfd = FormatDescriptor.Create(length,
|
FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType);
|
||||||
FormatDescriptor.Type.String, subType);
|
|
||||||
Results.Add(stringStart < i ? stringStart : i, dfd);
|
Results.Add(stringStart < i ? stringStart : i, dfd);
|
||||||
stringStart = i + adj;
|
stringStart = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +333,7 @@ namespace SourceGen.WpfGui {
|
|||||||
preview.Append(mFormatter.FormatBinaryValue(mOperandValue, 8));
|
preview.Append(mFormatter.FormatBinaryValue(mOperandValue, 8));
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Ascii:
|
case FormatDescriptor.SubType.Ascii:
|
||||||
|
// TODO(petscii): encoding
|
||||||
preview.Append(mFormatter.FormatAsciiOrHex(mOperandValue));
|
preview.Append(mFormatter.FormatAsciiOrHex(mOperandValue));
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Symbol:
|
case FormatDescriptor.SubType.Symbol:
|
||||||
@ -470,6 +471,7 @@ namespace SourceGen.WpfGui {
|
|||||||
binaryButton.IsChecked = true;
|
binaryButton.IsChecked = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Ascii:
|
case FormatDescriptor.SubType.Ascii:
|
||||||
|
// TODO(petscii): encoding
|
||||||
asciiButton.IsChecked = true;
|
asciiButton.IsChecked = true;
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.SubType.Symbol:
|
case FormatDescriptor.SubType.Symbol:
|
||||||
@ -499,7 +501,13 @@ namespace SourceGen.WpfGui {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.NumericBE:
|
case FormatDescriptor.Type.NumericBE:
|
||||||
case FormatDescriptor.Type.String:
|
case FormatDescriptor.Type.StringGeneric:
|
||||||
|
case FormatDescriptor.Type.StringReverse:
|
||||||
|
case FormatDescriptor.Type.StringNullTerm:
|
||||||
|
case FormatDescriptor.Type.StringL8:
|
||||||
|
case FormatDescriptor.Type.StringL16:
|
||||||
|
case FormatDescriptor.Type.StringDci:
|
||||||
|
case FormatDescriptor.Type.Dense:
|
||||||
case FormatDescriptor.Type.Fill:
|
case FormatDescriptor.Type.Fill:
|
||||||
default:
|
default:
|
||||||
// Unexpected; used to be data?
|
// Unexpected; used to be data?
|
||||||
@ -543,6 +551,7 @@ namespace SourceGen.WpfGui {
|
|||||||
} else if (binaryButton.IsChecked == true) {
|
} else if (binaryButton.IsChecked == true) {
|
||||||
subType = FormatDescriptor.SubType.Binary;
|
subType = FormatDescriptor.SubType.Binary;
|
||||||
} else if (asciiButton.IsChecked == true) {
|
} else if (asciiButton.IsChecked == true) {
|
||||||
|
// TODO(petscii): encoding
|
||||||
subType = FormatDescriptor.SubType.Ascii;
|
subType = FormatDescriptor.SubType.Ascii;
|
||||||
} else if (symbolButton.IsChecked == true) {
|
} else if (symbolButton.IsChecked == true) {
|
||||||
subType = FormatDescriptor.SubType.Symbol;
|
subType = FormatDescriptor.SubType.Symbol;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user