diff --git a/PluginCommon/Interfaces.cs b/PluginCommon/Interfaces.cs
index 119767a..b78f6b7 100644
--- a/PluginCommon/Interfaces.cs
+++ b/PluginCommon/Interfaces.cs
@@ -126,7 +126,7 @@ namespace PluginCommon {
Unknown = 0,
NumericLE,
NumericBE,
- String,
+ StringGeneric,
Dense,
Fill
}
diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs
index 2f8b88e..bfcb8a9 100644
--- a/SourceGen/AsmGen/AsmAcme.cs
+++ b/SourceGen/AsmGen/AsmAcme.cs
@@ -122,7 +122,6 @@ namespace SourceGen.AsmGen {
//StrLen8
//StrLen16
//StrDci
- //StrDciReverse
};
@@ -388,7 +387,12 @@ namespace SourceGen.AsmGen {
opcodeStr = operandStr = null;
OutputDenseHex(offset, length, labelStr, commentStr);
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;
opcodeStr = operandStr = null;
OutputString(offset, labelStr, commentStr);
@@ -532,7 +536,7 @@ namespace SourceGen.AsmGen {
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
- Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
+ Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
bool highAscii = false;
@@ -541,36 +545,31 @@ namespace SourceGen.AsmGen {
bool showLeading = false;
bool showTrailing = false;
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.DciReverse:
- highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
- leadingBytes = 1;
- showLeading = true;
- break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (dfd.Length > 1) {
highAscii = (data[offset + 1] & 0x80) != 0;
}
leadingBytes = 1;
showLeading = true;
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
if (dfd.Length > 2) {
highAscii = (data[offset + 2] & 0x80) != 0;
}
@@ -598,18 +597,17 @@ namespace SourceGen.AsmGen {
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
// TODO(someday): something fancy with encodings to handle high-ASCII text?
break;
- case FormatDescriptor.SubType.Dci:
- case FormatDescriptor.SubType.Reverse:
- case FormatDescriptor.SubType.DciReverse:
+ case FormatDescriptor.Type.StringDci:
+ case FormatDescriptor.Type.StringReverse:
// Fully configured above.
break;
- case FormatDescriptor.SubType.CString:
- case FormatDescriptor.SubType.L8String:
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringNullTerm:
+ case FormatDescriptor.Type.StringL8:
+ case FormatDescriptor.Type.StringL16:
// Implement as macro?
break;
default:
diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs
index 09dcbfc..8db7b0b 100644
--- a/SourceGen/AsmGen/AsmCc65.cs
+++ b/SourceGen/AsmGen/AsmCc65.cs
@@ -119,7 +119,6 @@ namespace SourceGen.AsmGen {
//StrLen8 // macro with .strlen?
//StrLen16
//StrDci
- //StrDciReverse
};
@@ -414,7 +413,12 @@ namespace SourceGen.AsmGen {
opcodeStr = operandStr = null;
OutputDenseHex(offset, length, labelStr, commentStr);
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;
opcodeStr = operandStr = null;
OutputString(offset, labelStr, commentStr);
@@ -586,7 +590,7 @@ namespace SourceGen.AsmGen {
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
- Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
+ Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
bool highAscii = false;
@@ -595,36 +599,31 @@ namespace SourceGen.AsmGen {
bool showLeading = false;
bool showTrailing = false;
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.DciReverse:
- highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
- leadingBytes = 1;
- showLeading = true;
- break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (dfd.Length > 1) {
highAscii = (data[offset + 1] & 0x80) != 0;
}
leadingBytes = 1;
showLeading = true;
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
if (dfd.Length > 2) {
highAscii = (data[offset + 2] & 0x80) != 0;
}
@@ -652,8 +651,8 @@ namespace SourceGen.AsmGen {
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
// Special case for simple short high-ASCII strings. These have no
// leading or trailing bytes. We can improve this a bit by handling
// arbitrarily long strings by simply breaking them across lines.
@@ -673,19 +672,18 @@ namespace SourceGen.AsmGen {
highAscii = false;
}
break;
- case FormatDescriptor.SubType.Dci:
- case FormatDescriptor.SubType.Reverse:
- case FormatDescriptor.SubType.DciReverse:
+ case FormatDescriptor.Type.StringDci:
+ case FormatDescriptor.Type.StringReverse:
// Full configured above.
break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
opcodeStr = sDataOpNames.StrNullTerm;
showTrailing = false;
}
break;
- case FormatDescriptor.SubType.L8String:
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL8:
+ case FormatDescriptor.Type.StringL16:
// Implement macros?
break;
default:
diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs
index a785056..c308979 100644
--- a/SourceGen/AsmGen/AsmMerlin32.cs
+++ b/SourceGen/AsmGen/AsmMerlin32.cs
@@ -118,7 +118,6 @@ namespace SourceGen.AsmGen {
StrLen16Hi = "strl",
StrDci = "dci",
StrDciHi = "dci",
- //StrDciReverse
};
@@ -294,7 +293,12 @@ namespace SourceGen.AsmGen {
opcodeStr = operandStr = null;
OutputDenseHex(offset, length, labelStr, commentStr);
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;
opcodeStr = operandStr = null;
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
// 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
// should be output as DFB/DW zeroes rather than an empty string -- makes
// it easier to read.
@@ -472,7 +473,7 @@ namespace SourceGen.AsmGen {
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
- Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
+ Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
bool highAscii = false;
@@ -483,22 +484,18 @@ namespace SourceGen.AsmGen {
bool showTrailing = false;
RevMode revMode = RevMode.Forward;
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
highAscii = (data[offset] & 0x80) != 0;
revMode = RevMode.Reverse;
break;
- case FormatDescriptor.SubType.DciReverse:
- highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
- revMode = RevMode.Reverse;
- break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
highAscii = (data[offset] & 0x80) != 0;
if (dfd.Length == 1) {
showZeroes = 1; // empty null-terminated string
@@ -506,7 +503,7 @@ namespace SourceGen.AsmGen {
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (dfd.Length > 1) {
highAscii = (data[offset + 1] & 0x80) != 0;
} else {
@@ -514,7 +511,7 @@ namespace SourceGen.AsmGen {
}
leadingBytes = 1;
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
if (dfd.Length > 2) {
highAscii = (data[offset + 2] & 0x80) != 0;
} else {
@@ -555,11 +552,11 @@ namespace SourceGen.AsmGen {
string opcodeStr;
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
if (gath.NumLinesOutput == 1) {
opcodeStr = highAscii ? sDataOpNames.StrDciHi : sDataOpNames.StrDci;
} else {
@@ -568,7 +565,7 @@ namespace SourceGen.AsmGen {
showTrailing = true;
}
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
if (gath.HasDelimiter) {
// can't include escaped delimiters in REV
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
@@ -581,18 +578,11 @@ namespace SourceGen.AsmGen {
Debug.Assert(revMode == RevMode.Reverse);
}
break;
- case FormatDescriptor.SubType.DciReverse:
- // 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:
+ case FormatDescriptor.Type.StringNullTerm:
//opcodeStr = sDataOpNames.StrNullTerm[highAscii ? 1 : 0];
opcodeStr = highAscii ? sDataOpNames.StrGenericHi : sDataOpNames.StrGeneric;
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (gath.NumLinesOutput == 1) {
opcodeStr = highAscii ? sDataOpNames.StrLen8Hi : sDataOpNames.StrLen8;
} else {
@@ -601,7 +591,7 @@ namespace SourceGen.AsmGen {
showLeading = true;
}
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
if (gath.NumLinesOutput == 1) {
opcodeStr = highAscii ? sDataOpNames.StrLen16Hi : sDataOpNames.StrLen16;
} else {
diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs
index 9f671db..1bc7fe2 100644
--- a/SourceGen/AsmGen/AsmTass64.cs
+++ b/SourceGen/AsmGen/AsmTass64.cs
@@ -129,7 +129,6 @@ namespace SourceGen.AsmGen {
StrLen8 = ".ptext",
//StrLen16
//StrDci
- //StrDciReverse
};
private const string HERE_PSEUDO_OP = ".here";
@@ -360,7 +359,12 @@ namespace SourceGen.AsmGen {
opcodeStr = operandStr = null;
OutputDenseHex(offset, length, labelStr, commentStr);
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;
opcodeStr = operandStr = null;
OutputString(offset, labelStr, commentStr);
@@ -525,7 +529,7 @@ namespace SourceGen.AsmGen {
Anattrib attr = Project.GetAnattrib(offset);
FormatDescriptor dfd = attr.DataDescriptor;
Debug.Assert(dfd != null);
- Debug.Assert(dfd.FormatType == FormatDescriptor.Type.String);
+ Debug.Assert(dfd.IsString);
Debug.Assert(dfd.Length > 0);
bool highAscii = false;
@@ -534,36 +538,31 @@ namespace SourceGen.AsmGen {
bool showLeading = false;
bool showTrailing = false;
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
highAscii = (data[offset] & 0x80) != 0;
break;
- case FormatDescriptor.SubType.DciReverse:
- highAscii = (data[offset + dfd.Length - 1] & 0x80) != 0;
- leadingBytes = 1;
- showLeading = true;
- break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
highAscii = (data[offset] & 0x80) != 0;
trailingBytes = 1;
showTrailing = true;
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (dfd.Length > 1) {
highAscii = (data[offset + 1] & 0x80) != 0;
}
leadingBytes = 1;
showLeading = true;
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
if (dfd.Length > 2) {
highAscii = (data[offset + 2] & 0x80) != 0;
}
@@ -591,28 +590,27 @@ namespace SourceGen.AsmGen {
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.StrGeneric);
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.StringGeneric:
// TODO(someday): something fancy with encodings to handle high-ASCII text?
break;
- case FormatDescriptor.SubType.Dci:
- case FormatDescriptor.SubType.Reverse:
- case FormatDescriptor.SubType.DciReverse:
+ case FormatDescriptor.Type.StringDci:
+ case FormatDescriptor.Type.StringReverse:
// Fully configured above.
break;
- case FormatDescriptor.SubType.CString:
+ case FormatDescriptor.Type.StringNullTerm:
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
opcodeStr = sDataOpNames.StrNullTerm;
showTrailing = false;
}
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
if (gath.NumLinesOutput == 1 && !gath.HasDelimiter) {
opcodeStr = sDataOpNames.StrLen8;
showLeading = false;
}
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
// Implement as macro?
break;
default:
diff --git a/SourceGen/CodeAnalysis.cs b/SourceGen/CodeAnalysis.cs
index f83cd61..eec8f2b 100644
--- a/SourceGen/CodeAnalysis.cs
+++ b/SourceGen/CodeAnalysis.cs
@@ -1047,7 +1047,7 @@ namespace SourceGen {
return FormatDescriptor.Type.NumericBE;
case DataType.Dense:
return FormatDescriptor.Type.Dense;
- case DataType.String:
+ case DataType.StringGeneric:
case DataType.Fill:
default:
// not appropriate for operands, or inline data (?)
@@ -1068,8 +1068,6 @@ namespace SourceGen {
return FormatDescriptor.SubType.Decimal;
case DataSubType.Binary:
return FormatDescriptor.SubType.Binary;
- case DataSubType.Ascii:
- return FormatDescriptor.SubType.Ascii;
case DataSubType.Address:
return FormatDescriptor.SubType.Address;
case DataSubType.Symbol:
diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs
index f324b22..617169b 100644
--- a/SourceGen/DataAnalysis.cs
+++ b/SourceGen/DataAnalysis.cs
@@ -737,7 +737,7 @@ namespace SourceGen {
if (asciiLen >= minStringChars) {
LogV(start, "ASCII string, len=" + asciiLen + " bytes");
mAnattribs[start].DataDescriptor = FormatDescriptor.Create(asciiLen,
- FormatDescriptor.Type.String, FormatDescriptor.SubType.None);
+ FormatDescriptor.Type.StringGeneric, FormatDescriptor.SubType.Ascii);
start += asciiLen;
continue;
}
diff --git a/SourceGen/FormatDescriptor.cs b/SourceGen/FormatDescriptor.cs
index 61e2450..f7b6d63 100644
--- a/SourceGen/FormatDescriptor.cs
+++ b/SourceGen/FormatDescriptor.cs
@@ -34,27 +34,35 @@ namespace SourceGen {
///
public class FormatDescriptor {
///
- /// 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
/// to be orthogonal in case the policy changes.
///
public enum Type : byte {
Unknown = 0,
- REMOVE, // special type, only used by operand editor
- Default, // means "unformatted", same effect as not having a FormatDescriptor
- NumericLE, // 1-4 byte number, little-endian
- NumericBE, // 1-4 byte number, big-endian
- String, // character string
- Dense, // raw data, represented as compactly as possible
- Fill // fill memory with a value
+ REMOVE, // special type, only used by operand editor
+ Default, // means "unformatted", same as not having a FormatDescriptor
+
+ NumericLE, // 1-4 byte number, little-endian
+ NumericBE, // 1-4 byte number, big-endian
+
+ 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
}
///
- /// 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
- /// a string is high- or low-ASCII, or what value to use for Fill.
+ /// Some things are extracted from the data itself, e.g. we don't need to specify
+ /// what value to use for Fill.
///
public enum SubType : byte {
None = 0,
@@ -63,22 +71,18 @@ namespace SourceGen {
Hex,
Decimal,
Binary,
- Ascii, // aspirational; falls back on hex if data not suited
- Address, // wants to be an address, but no symbol defined
- Symbol, // symbolic ref; replace with Expression, someday?
+ Address, // wants to be an address, but no symbol defined
+ Symbol, // symbolic ref; replace with Expression, someday?
- // String; default is straight text
- Reverse, // plain ASCII in reverse order
- CString, // null-terminated
- L8String, // 8-bit length prefix
- L16String, // 16-bit length prefix
- Dci, // Dextral Character Inverted
- DciReverse, // DCI with string backwards [deprecated -- no asm supports this]
+ // Strings and NumericLE/BE (single character)
+ Ascii, // ASCII (with or without the high bit set)
+ C64Petscii, // C64 PETSCII
+ C64Screen, // C64 screen code
// Dense; no sub-types
// 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;
@@ -264,6 +268,25 @@ namespace SourceGen {
}
}
+ ///
+ /// True if the FormatDescriptor is a string type.
+ ///
+ 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;
+ }
+ }
+ }
+
///
/// True if the FormatDescriptor has a symbol or is Numeric/Address.
///
@@ -320,6 +343,48 @@ namespace SourceGen {
///
public string ToUiString() {
// 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) {
case SubType.None:
switch (FormatType) {
@@ -328,13 +393,12 @@ namespace SourceGen {
return "Numeric (little-endian)";
case Type.NumericBE:
return "Numeric (big-endian)";
- case Type.String:
- return "String (generic)";
case Type.Dense:
return "Dense";
case Type.Fill:
return "Fill";
default:
+ // strings handled earlier
return "???";
}
case SubType.Hex:
@@ -343,25 +407,16 @@ namespace SourceGen {
return "Numeric, Decimal";
case SubType.Binary:
return "Numeric, Binary";
- case SubType.Ascii:
- return "ASCII";
case SubType.Address:
return "Address";
case SubType.Symbol:
return "Symbol \"" + SymbolRef.Label + "\"";
-
- case SubType.Reverse:
- return "String (reverse)";
- case SubType.CString:
- return "String (null-term)";
- case SubType.L8String:
- 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)";
+ case SubType.Ascii:
+ return "ASCII";
+ case SubType.C64Petscii:
+ return "C64 PETSCII";
+ case SubType.C64Screen:
+ return "C64 Screen";
default:
return "???";
diff --git a/SourceGen/ProjectFile.cs b/SourceGen/ProjectFile.cs
index 2f3f4e1..aa7bcf1 100644
--- a/SourceGen/ProjectFile.cs
+++ b/SourceGen/ProjectFile.cs
@@ -52,7 +52,7 @@ namespace SourceGen {
// 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
// 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;
@@ -669,6 +669,33 @@ namespace SourceGen {
dfd = null;
FormatDescriptor.Type format;
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 {
format = (FormatDescriptor.Type)Enum.Parse(
typeof(FormatDescriptor.Type), sfd.Format);
diff --git a/SourceGen/PseudoOp.cs b/SourceGen/PseudoOp.cs
index 36d0c02..988dde1 100644
--- a/SourceGen/PseudoOp.cs
+++ b/SourceGen/PseudoOp.cs
@@ -87,8 +87,6 @@ namespace SourceGen {
public string StrNullTermHi { get; set; }
public string StrDci { get; set; }
public string StrDciHi { get; set; }
- public string StrDciReverse { get; set; }
- public string StrDciReverseHi { get; set; }
public string GetDefineData(int width) {
switch (width) {
@@ -180,8 +178,6 @@ namespace SourceGen {
StrNullTermHi = ".zstrh",
StrDci = ".dstr",
StrDciHi = ".dstrh",
- StrDciReverse = ".rdstr",
- StrDciReverseHi = ".rdstrh",
};
@@ -192,6 +188,37 @@ namespace SourceGen {
/// Data format descriptor.
/// Line count.
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) {
case FormatDescriptor.Type.Default:
case FormatDescriptor.Type.NumericLE:
@@ -204,37 +231,6 @@ namespace SourceGen {
int textLen = dfd.Length * 2;
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:
Debug.Assert(false);
return 1;
@@ -274,89 +270,94 @@ namespace SourceGen {
// multi-line items.
PseudoOut po = new PseudoOut();
- switch (dfd.FormatType) {
- case FormatDescriptor.Type.Default:
- if (length != 1) {
- // This shouldn't happen.
- Debug.Assert(false);
- length = 1;
+ if (dfd.IsString) {
+ // 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 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);
- 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 outList = new List();
- //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);
+ char[] ltext = BytesToChars(formatter, opNames, dfd.FormatType, 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.FormatType, data,
+ offset, length, out string popcode, out int showHexZeroes);
- if (showHexZeroes == 1) {
- po.Opcode = opNames.DefineData1;
- po.Operand = formatter.FormatHexValue(0, 2);
- } else if (showHexZeroes == 2) {
- po.Opcode = opNames.DefineData2;
- po.Operand = formatter.FormatHexValue(0, 4);
- } else {
- Debug.Assert(showHexZeroes == 0);
- po.Opcode = popcode;
- List outList = new List();
- GenerateTextLines(text, "\u201c", "\u201d", po, outList);
- po = outList[subIndex];
- }
+ if (showHexZeroes == 1) {
+ po.Opcode = opNames.DefineData1;
+ po.Operand = formatter.FormatHexValue(0, 2);
+ } else if (showHexZeroes == 2) {
+ po.Opcode = opNames.DefineData2;
+ po.Operand = formatter.FormatHexValue(0, 4);
+ } else {
+ Debug.Assert(showHexZeroes == 0);
+ po.Opcode = popcode;
+ List outList = new List();
+ GenerateTextLines(text, "\u201c", "\u201d", po, outList);
+ po = outList[subIndex];
}
- break;
- default:
- Debug.Assert(false);
- po.Opcode = ".???";
- po.Operand = "$" + data[offset].ToString("x2");
- break;
+ }
+ } else {
+ switch (dfd.FormatType) {
+ case FormatDescriptor.Type.Default:
+ if (length != 1) {
+ // 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 outList = new List();
+ //GenerateTextLines(text, "", "", po, outList);
+ //po = outList[subIndex];
+ }
+ break;
+ default:
+ Debug.Assert(false);
+ po.Opcode = ".???";
+ po.Operand = "$" + data[offset].ToString("x2");
+ break;
+ }
}
return po;
@@ -368,7 +369,7 @@ namespace SourceGen {
/// are not shown.
///
/// Formatter object.
- /// String sub-type.
+ /// String layout.
/// File data.
/// Offset, within data, of start of string.
/// Number of bytes to convert.
@@ -377,7 +378,7 @@ namespace SourceGen {
/// length or null-termination) instead of an empty string.
/// Array of characters with string data.
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) {
Debug.Assert(length > 0);
@@ -389,32 +390,25 @@ namespace SourceGen {
showHexZeroes = 0;
- switch (subType) {
- case FormatDescriptor.SubType.None:
+ switch (formatType) {
+ case FormatDescriptor.Type.StringGeneric:
// High or low ASCII, full width specified by formatter.
highAscii = (data[offset] & 0x80) != 0;
popcode = highAscii ? opNames.StrGenericHi : opNames.StrGeneric;
break;
- case FormatDescriptor.SubType.Dci:
+ case FormatDescriptor.Type.StringDci:
// High or low ASCII, full width specified by formatter.
highAscii = (data[offset] & 0x80) != 0;
popcode = highAscii ? opNames.StrDciHi : opNames.StrDci;
break;
- case FormatDescriptor.SubType.Reverse:
+ case FormatDescriptor.Type.StringReverse:
// High or low ASCII, full width specified by formatter. Show characters
// in reverse order.
highAscii = (data[offset + strLen - 1] & 0x80) != 0;
popcode = highAscii ? opNames.StrReverseHi : opNames.StrReverse;
reverse = true;
break;
- case FormatDescriptor.SubType.DciReverse:
- // 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:
+ case FormatDescriptor.Type.StringNullTerm:
// 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.
highAscii = (data[offset] & 0x80) != 0;
@@ -424,7 +418,7 @@ namespace SourceGen {
showHexZeroes = 1;
}
break;
- case FormatDescriptor.SubType.L8String:
+ case FormatDescriptor.Type.StringL8:
// 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.
strOffset++;
@@ -436,7 +430,7 @@ namespace SourceGen {
}
popcode = highAscii ? opNames.StrLen8Hi : opNames.StrLen8;
break;
- case FormatDescriptor.SubType.L16String:
+ case FormatDescriptor.Type.StringL16:
// 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.
Debug.Assert(strLen > 1);
@@ -455,6 +449,7 @@ namespace SourceGen {
break;
}
+ // TODO(petscii): convert character encoding
char[] text = new char[strLen];
if (!reverse) {
for (int i = 0; i < strLen; i++) {
@@ -547,6 +542,10 @@ namespace SourceGen {
case FormatDescriptor.SubType.Binary:
return formatter.FormatBinaryValue(operandValue, hexMinLen * 4);
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);
case FormatDescriptor.SubType.Symbol:
if (symbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
diff --git a/SourceGen/WpfGui/EditDataOperand.xaml.cs b/SourceGen/WpfGui/EditDataOperand.xaml.cs
index b377995..b368e11 100644
--- a/SourceGen/WpfGui/EditDataOperand.xaml.cs
+++ b/SourceGen/WpfGui/EditDataOperand.xaml.cs
@@ -528,6 +528,9 @@ namespace SourceGen.WpfGui {
radioSimpleDataBinary.IsChecked = true;
break;
case FormatDescriptor.SubType.Ascii:
+ case FormatDescriptor.SubType.C64Petscii:
+ case FormatDescriptor.SubType.C64Screen:
+ // TODO(petscii): update UI
radioSimpleDataAscii.IsChecked = true;
break;
case FormatDescriptor.SubType.Address:
@@ -560,34 +563,23 @@ namespace SourceGen.WpfGui {
// preferred format not enabled; leave Hex/Low checked
}
break;
- case FormatDescriptor.Type.String:
- switch (dfd.FormatSubType) {
- case FormatDescriptor.SubType.None:
- preferredFormat = radioStringMixed;
- break;
- case FormatDescriptor.SubType.Reverse:
- preferredFormat = radioStringMixedReverse;
- break;
- case FormatDescriptor.SubType.CString:
- preferredFormat = radioStringNullTerm;
- break;
- case FormatDescriptor.SubType.L8String:
- preferredFormat = radioStringLen8;
- break;
- case FormatDescriptor.SubType.L16String:
- preferredFormat = radioStringLen16;
- break;
- case FormatDescriptor.SubType.Dci:
- preferredFormat = radioStringDci;
- break;
- case FormatDescriptor.SubType.DciReverse:
- preferredFormat = radioDefaultFormat;
- break;
- default:
- Debug.Assert(false);
- preferredFormat = radioDefaultFormat;
- break;
- }
+ case FormatDescriptor.Type.StringGeneric:
+ preferredFormat = radioStringMixed;
+ break;
+ case FormatDescriptor.Type.StringReverse:
+ preferredFormat = radioStringMixedReverse;
+ break;
+ case FormatDescriptor.Type.StringNullTerm:
+ preferredFormat = radioStringNullTerm;
+ break;
+ case FormatDescriptor.Type.StringL8:
+ preferredFormat = radioStringLen8;
+ break;
+ case FormatDescriptor.Type.StringL16:
+ preferredFormat = radioStringLen16;
+ break;
+ case FormatDescriptor.Type.StringDci:
+ preferredFormat = radioStringDci;
break;
case FormatDescriptor.Type.Dense:
preferredFormat = radioDenseHex;
@@ -639,6 +631,7 @@ namespace SourceGen.WpfGui {
} else if (radioSimpleDataBinary.IsChecked == true) {
subType = FormatDescriptor.SubType.Binary;
} else if (radioSimpleDataAscii.IsChecked == true) {
+ // TODO(petscii): configure subType correctly
subType = FormatDescriptor.SubType.Ascii;
} else if (radioSimpleDataAddress.IsChecked == true) {
subType = FormatDescriptor.SubType.Address;
@@ -688,26 +681,25 @@ namespace SourceGen.WpfGui {
type = FormatDescriptor.Type.Dense;
} else if (radioFill.IsChecked == true) {
type = FormatDescriptor.Type.Fill;
+ subType = FormatDescriptor.SubType.Ascii; // TODO(petscii): set encoding
} else if (radioStringMixed.IsChecked == true) {
- type = FormatDescriptor.Type.String;
+ type = FormatDescriptor.Type.StringGeneric;
+ subType = FormatDescriptor.SubType.Ascii;
} else if (radioStringMixedReverse.IsChecked == true) {
- type = FormatDescriptor.Type.String;
- subType = FormatDescriptor.SubType.Reverse;
+ type = FormatDescriptor.Type.StringReverse;
+ subType = FormatDescriptor.SubType.Ascii;
} else if (radioStringNullTerm.IsChecked == true) {
- type = FormatDescriptor.Type.String;
- subType = FormatDescriptor.SubType.CString;
+ type = FormatDescriptor.Type.StringNullTerm;
+ subType = FormatDescriptor.SubType.Ascii;
} else if (radioStringLen8.IsChecked == true) {
- type = FormatDescriptor.Type.String;
- subType = FormatDescriptor.SubType.L8String;
+ type = FormatDescriptor.Type.StringL8;
+ subType = FormatDescriptor.SubType.Ascii;
} else if (radioStringLen16.IsChecked == true) {
- type = FormatDescriptor.Type.String;
- subType = FormatDescriptor.SubType.L16String;
+ type = FormatDescriptor.Type.StringL16;
+ subType = FormatDescriptor.SubType.Ascii;
} else if (radioStringDci.IsChecked == true) {
- type = FormatDescriptor.Type.String;
- subType = FormatDescriptor.SubType.Dci;
- //} else if (radioStringDciReverse.Checked) {
- // type = FormatDescriptor.Type.String;
- // subType = FormatDescriptor.SubType.DciReverse;
+ type = FormatDescriptor.Type.StringDci;
+ subType = FormatDescriptor.SubType.Ascii;
} else {
Debug.Assert(false);
// default/none
@@ -720,26 +712,26 @@ namespace SourceGen.WpfGui {
while (iter.MoveNext()) {
TypedRangeSet.TypedRange rng = iter.Current;
- if (type == FormatDescriptor.Type.String) {
- // We want to create one FormatDescriptor object per string. That way
- // each string gets its own line.
- if ((subType == FormatDescriptor.SubType.None ||
- subType == FormatDescriptor.SubType.Reverse)) {
- CreateMixedStringEntries(rng.Low, rng.High, subType);
- } else if (subType == FormatDescriptor.SubType.CString) {
- CreateCStringEntries(rng.Low, rng.High, subType);
- } else if (subType == FormatDescriptor.SubType.L8String ||
- subType == FormatDescriptor.SubType.L16String) {
- CreateLengthStringEntries(rng.Low, rng.High, subType);
- } else if (subType == FormatDescriptor.SubType.Dci ||
- subType == FormatDescriptor.SubType.DciReverse) {
- CreateDciStringEntries(rng.Low, rng.High, subType);
- } else {
- Debug.Assert(false);
- CreateMixedStringEntries(rng.Low, rng.High, subType); // shrug
- }
- } else {
- CreateSimpleEntries(type, subType, chunkLength, symbolRef, rng.Low, rng.High);
+ // TODO(petscii): handle encoding on all four calls
+ switch (type) {
+ case FormatDescriptor.Type.StringGeneric:
+ case FormatDescriptor.Type.StringReverse:
+ CreateMixedStringEntries(rng.Low, rng.High, type, subType);
+ break;
+ case FormatDescriptor.Type.StringNullTerm:
+ CreateCStringEntries(rng.Low, rng.High, type, subType);
+ break;
+ case FormatDescriptor.Type.StringL8:
+ case FormatDescriptor.Type.StringL16:
+ CreateLengthStringEntries(rng.Low, rng.High, type, subType);
+ break;
+ case FormatDescriptor.Type.StringDci:
+ CreateDciStringEntries(rng.Low, rng.High, type, subType);
+ break;
+ default:
+ CreateSimpleEntries(type, subType, chunkLength, symbolRef,
+ rng.Low, rng.High);
+ break;
}
}
}
@@ -793,7 +785,7 @@ namespace SourceGen.WpfGui {
/// Offset of first byte in range.
/// Offset of last byte in range.
/// String sub-type.
- private void CreateMixedStringEntries(int low, int high,
+ private void CreateMixedStringEntries(int low, int high, FormatDescriptor.Type type,
FormatDescriptor.SubType subType) {
int stringStart = -1;
int highBit = 0;
@@ -846,11 +838,12 @@ namespace SourceGen.WpfGui {
Debug.Assert(length > 0);
if (length == 1) {
// single byte, output as single ASCII char rather than 1-byte string
+ // TODO(petscii): low/high?
CreateByteFD(offset, FormatDescriptor.SubType.Ascii);
} else {
FormatDescriptor dfd;
dfd = FormatDescriptor.Create(length,
- FormatDescriptor.Type.String, subType);
+ FormatDescriptor.Type.StringGeneric, subType);
Results.Add(offset, dfd);
}
}
@@ -873,14 +866,14 @@ namespace SourceGen.WpfGui {
/// Offset of first byte in range.
/// Offset of last byte in range.
/// String sub-type.
- private void CreateCStringEntries(int low, int high,
+ private void CreateCStringEntries(int low, int high, FormatDescriptor.Type type,
FormatDescriptor.SubType subType) {
int startOffset = low;
for (int i = low; i <= high; i++) {
if (mFileData[i] == 0x00) {
// End of string. Zero-length strings are allowed.
FormatDescriptor dfd = FormatDescriptor.Create(
- i - startOffset + 1, FormatDescriptor.Type.String, subType);
+ i - startOffset + 1, type, subType);
Results.Add(startOffset, dfd);
startOffset = i + 1;
} else {
@@ -899,20 +892,19 @@ namespace SourceGen.WpfGui {
/// Offset of first byte in range.
/// Offset of last byte in range.
/// String sub-type.
- private void CreateLengthStringEntries(int low, int high,
+ private void CreateLengthStringEntries(int low, int high, FormatDescriptor.Type type,
FormatDescriptor.SubType subType) {
int i;
for (i = low; i <= high;) {
int length = mFileData[i];
- if (subType == FormatDescriptor.SubType.L16String) {
+ if (type == FormatDescriptor.Type.StringL16) {
length |= mFileData[i + 1] << 8;
length += 2;
} else {
length++;
}
// Zero-length strings are allowed.
- FormatDescriptor dfd = FormatDescriptor.Create(length,
- FormatDescriptor.Type.String, subType);
+ FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType);
Results.Add(i, dfd);
i += length;
}
@@ -927,36 +919,25 @@ namespace SourceGen.WpfGui {
/// Offset of first byte in range.
/// Offset of last byte in range.
/// String sub-type.
- private void CreateDciStringEntries(int low, int high,
+ private void CreateDciStringEntries(int low, int high, FormatDescriptor.Type type,
FormatDescriptor.SubType subType) {
- int start, end, adj, endMask;
- if (subType == FormatDescriptor.SubType.Dci) {
- start = low;
- end = high + 1;
- adj = 1;
- } else if (subType == FormatDescriptor.SubType.DciReverse) {
- start = high;
- end = low - 1;
- adj = -1;
- } else {
- Debug.Assert(false);
- return;
- }
+ int end, endMask;
+
+ end = high + 1;
// 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.
endMask = mFileData[end - 1] & 0x80;
- int stringStart = start;
- for (int i = start; i != end; i += adj) {
+ int stringStart = low;
+ for (int i = low; i != end; i++) {
byte val = mFileData[i];
if ((val & 0x80) == endMask) {
// found the end of a string
- int length = (i - stringStart) * adj + 1;
- FormatDescriptor dfd = FormatDescriptor.Create(length,
- FormatDescriptor.Type.String, subType);
+ int length = (i - stringStart) + 1;
+ FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType);
Results.Add(stringStart < i ? stringStart : i, dfd);
- stringStart = i + adj;
+ stringStart = i + 1;
}
}
diff --git a/SourceGen/WpfGui/EditInstructionOperand.xaml.cs b/SourceGen/WpfGui/EditInstructionOperand.xaml.cs
index 0ed0c38..33b2fdd 100644
--- a/SourceGen/WpfGui/EditInstructionOperand.xaml.cs
+++ b/SourceGen/WpfGui/EditInstructionOperand.xaml.cs
@@ -333,6 +333,7 @@ namespace SourceGen.WpfGui {
preview.Append(mFormatter.FormatBinaryValue(mOperandValue, 8));
break;
case FormatDescriptor.SubType.Ascii:
+ // TODO(petscii): encoding
preview.Append(mFormatter.FormatAsciiOrHex(mOperandValue));
break;
case FormatDescriptor.SubType.Symbol:
@@ -470,6 +471,7 @@ namespace SourceGen.WpfGui {
binaryButton.IsChecked = true;
break;
case FormatDescriptor.SubType.Ascii:
+ // TODO(petscii): encoding
asciiButton.IsChecked = true;
break;
case FormatDescriptor.SubType.Symbol:
@@ -499,7 +501,13 @@ namespace SourceGen.WpfGui {
}
break;
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:
default:
// Unexpected; used to be data?
@@ -543,6 +551,7 @@ namespace SourceGen.WpfGui {
} else if (binaryButton.IsChecked == true) {
subType = FormatDescriptor.SubType.Binary;
} else if (asciiButton.IsChecked == true) {
+ // TODO(petscii): encoding
subType = FormatDescriptor.SubType.Ascii;
} else if (symbolButton.IsChecked == true) {
subType = FormatDescriptor.SubType.Symbol;