1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-12 23:29:32 +00:00

Add C64 encodings to instruction and data operand editors

Both dialogs got a couple extra radio buttons for selection of
single character operands.  The data operand editor got a combo box
that lets you specify how it scans for viable strings.

Various string scanning methods were made more generic.  This got a
little strange with auto-detection of low/high ASCII, but that was
mostly a matter of keeping the previous code around as a special
case.

Made C64 Screen Code DCI strings a thing that works.
This commit is contained in:
Andy McFadden 2019-08-15 17:53:12 -07:00
parent 176e1ad6af
commit 7bbe5692bd
18 changed files with 560 additions and 211 deletions

View File

@ -106,11 +106,12 @@ namespace Asm65 {
return IsExtendedAscii((byte)(val & 0x7f)); return IsExtendedAscii((byte)(val & 0x7f));
} }
public static char ConvertLowAndHighAscii(byte val) { public static char ConvertLowAndHighAscii(byte val) {
if (IsPrintableAscii(val) || IsPrintableHighAscii(val)) { //if (IsPrintableAscii(val) || IsPrintableHighAscii(val)) {
return (char)(val & 0x7f); // return (char)(val & 0x7f);
} else { //} else {
return UNPRINTABLE_CHAR; // return UNPRINTABLE_CHAR;
} //}
return ConvertAscii((byte)(val & 0x7f));
} }
// //
@ -256,5 +257,8 @@ namespace Asm65 {
return UNPRINTABLE_CHAR; return UNPRINTABLE_CHAR;
} }
} }
public static char ConvertLowAndHighC64ScreenCode(byte val) {
return ConvertC64ScreenCode((byte)(val & 0x7f));
}
} }
} }

View File

@ -152,12 +152,10 @@ namespace Asm65 {
new Dictionary<CharEncoding.Encoding, DelimiterDef>(); new Dictionary<CharEncoding.Encoding, DelimiterDef>();
/// <summary> /// <summary>
/// Returns the specified DelimiterDef, or a default if not found. /// Returns the specified DelimiterDef, or null if not found.
/// </summary> /// </summary>
public DelimiterDef Get(CharEncoding.Encoding enc) { public DelimiterDef Get(CharEncoding.Encoding enc) {
if (!mDelimiters.TryGetValue(enc, out DelimiterDef def)) { mDelimiters.TryGetValue(enc, out DelimiterDef def);
return DOUBLE_QUOTE_DELIM;
}
return def; return def;
} }
public void Set(CharEncoding.Encoding enc, DelimiterDef def) { public void Set(CharEncoding.Encoding enc, DelimiterDef def) {
@ -528,6 +526,10 @@ namespace Asm65 {
} }
DelimiterDef delimDef = mFormatConfig.mCharDelimiters.Get(enc); DelimiterDef delimDef = mFormatConfig.mCharDelimiters.Get(enc);
if (delimDef == null) {
return FormatHexValue(value, 2);
}
string fmt = delimDef.FormatStr; string fmt = delimDef.FormatStr;
Debug.Assert(fmt != null); Debug.Assert(fmt != null);

View File

@ -68,6 +68,9 @@ namespace SourceGen {
public const string CLIP_LINE_FORMAT = "clip-line-format"; public const string CLIP_LINE_FORMAT = "clip-line-format";
// Main project view settings.
public const string PRVW_RECENT_PROJECT_LIST = "prvw-recent-project-list";
// Symbol-list window options. // Symbol-list window options.
public const string SYMWIN_SHOW_USER = "symwin-show-user"; public const string SYMWIN_SHOW_USER = "symwin-show-user";
public const string SYMWIN_SHOW_AUTO = "symwin-show-auto"; public const string SYMWIN_SHOW_AUTO = "symwin-show-auto";
@ -91,6 +94,9 @@ namespace SourceGen {
public const string CDLV_FONT_FAMILY = "cdlv-font-family"; public const string CDLV_FONT_FAMILY = "cdlv-font-family";
public const string CDLV_FONT_SIZE = "cdlv-font-size"; public const string CDLV_FONT_SIZE = "cdlv-font-size";
// Operand edit settings.
public const string OPED_DEFAULT_STRING_ENCODING = "oped-default-string-encoding";
// Hex dump viewer settings. // Hex dump viewer settings.
public const string HEXD_ASCII_ONLY = "hexd-ascii-only"; public const string HEXD_ASCII_ONLY = "hexd-ascii-only";
public const string HEXD_CHAR_CONV = "hexd-char-conv1"; public const string HEXD_CHAR_CONV = "hexd-char-conv1";
@ -105,9 +111,6 @@ namespace SourceGen {
public const string SRCGEN_LONG_LABEL_NEW_LINE = "srcgen-long-label-new-line"; public const string SRCGEN_LONG_LABEL_NEW_LINE = "srcgen-long-label-new-line";
public const string SRCGEN_SHOW_CYCLE_COUNTS = "srcgen-show-cycle-counts"; public const string SRCGEN_SHOW_CYCLE_COUNTS = "srcgen-show-cycle-counts";
// Main project view settings.
public const string PRVW_RECENT_PROJECT_LIST = "prvw-recent-project-list";
// Assembler settings prefix // Assembler settings prefix
public const string ASM_CONFIG_PREFIX = "asm-config-"; public const string ASM_CONFIG_PREFIX = "asm-config-";

View File

@ -810,7 +810,7 @@ namespace SourceGen {
#endif #endif
} }
#region Static analyzer methods #region Static analyzer methods
/// <summary> /// <summary>
/// Checks for a repeated run of the same byte. /// Checks for a repeated run of the same byte.
@ -837,43 +837,63 @@ namespace SourceGen {
/// <param name="fileData">Raw data.</param> /// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param> /// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range</param> /// <param name="end">Offset of last byte in range</param>
/// <param name="lowAscii">Set to the number of low-ASCII bytes found.</param> /// <param name="charTest">Character test delegate. Must match on both high and
/// <param name="highAscii">Set to the number of high-ASCII bytes found.</param> /// low characters.</param>
/// <param name="nonAscii">Set to the number of non-ASCII bytes found.</param> /// <param name="lowVal">Set to the number of low-range characters found.</param>
public static void CountAsciiBytes(byte[] fileData, int start, int end, /// <param name="highVal">Set to the number of high-range characters found.</param>
out int lowAscii, out int highAscii, out int nonAscii) { /// <param name="nonChar">Set to the number of non-character bytes found.</param>
lowAscii = highAscii = nonAscii = 0; public static void CountHighLowBytes(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest,
out int lowVal, out int highVal, out int nonChar) {
lowVal = highVal = nonChar = 0;
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
byte val = fileData[i]; byte val = fileData[i];
if (val < 0x20) { if (!charTest(val)) {
nonAscii++; nonChar++;
} else if (val < 0x7f) { } else if ((val & 0x80) == 0) {
lowAscii++; lowVal++;
} else if (val < 0xa0) {
nonAscii++;
} else if (val < 0xff) {
highAscii++;
} else { } else {
nonAscii++; highVal++;
} }
} }
} }
/// <summary>
/// Counts the number of bytes that match the character test.
/// </summary>
/// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range.</param>
/// <param name="charTest">Character test delegate.</param>
/// <returns>Number of matching characters.</returns>
public static int CountCharacterBytes(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest) {
int count = 0;
for (int i = start; i <= end; i++) {
if (charTest(fileData[i])) {
count++;
}
}
return count;
}
/// <summary> /// <summary>
/// Counts the number of null-terminated strings in the buffer. /// Counts the number of null-terminated strings in the buffer.
/// ///
/// Zero-length strings are allowed but not included in the count. /// Zero-length strings are allowed but not included in the count.
/// ///
/// Each string must be either high-ASCII or low-ASCII, not a mix.
///
/// If any bad data is found, the scan aborts and returns -1. /// If any bad data is found, the scan aborts and returns -1.
/// </summary> /// </summary>
/// <param name="fileData">Raw data.</param> /// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param> /// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range.</param> /// <param name="end">Offset of last byte in range.</param>
/// <param name="charTest">Character test delegate.</param>
/// <param name="limitHiBit">If set, the high bit in all character must be the
/// same. Used to enforce a single encoding when "low or high ASCII" is used.</param>
/// <returns>Number of strings found, or -1 if bad data identified.</returns> /// <returns>Number of strings found, or -1 if bad data identified.</returns>
public static int RecognizeNullTerminatedStrings(byte[] fileData, int start, int end) { public static int RecognizeNullTerminatedStrings(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest, bool limitHiBit) {
// Quick test. // Quick test.
if (fileData[end] != 0x00) { if (fileData[end] != 0x00) {
return -1; return -1;
@ -892,16 +912,17 @@ namespace SourceGen {
stringLen = 0; stringLen = 0;
expectedHiBit = -1; expectedHiBit = -1;
} else { } else {
if (expectedHiBit == -1) { if (limitHiBit) {
// First byte in string, set hi/lo expectation. if (expectedHiBit == -1) {
expectedHiBit = val & 0x80; // First byte in string, set hi/lo expectation.
} else if ((val & 0x80) != expectedHiBit) { expectedHiBit = val & 0x80;
// Mixed ASCII or non-ASCII, fail. } else if ((val & 0x80) != expectedHiBit) {
return -1; // Mixed ASCII or non-ASCII, fail.
return -1;
}
} }
val &= 0x7f; if (!charTest(val)) {
if (val < 0x20 || val == 0x7f) { // Not a matching character, fail.
// Non-ASCII, fail.
return -1; return -1;
} }
stringLen++; stringLen++;
@ -913,16 +934,18 @@ namespace SourceGen {
/// <summary> /// <summary>
/// Counts strings prefixed with an 8-bit length. /// Counts strings prefixed with an 8-bit length.
///
/// Each string must be either high-ASCII or low-ASCII, not a mix.
/// ///
/// Zero-length strings are allowed but not counted. /// Zero-length strings are allowed but not counted.
/// </summary> /// </summary>
/// <param name="fileData">Raw data.</param> /// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param> /// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range.</param> /// <param name="end">Offset of last byte in range.</param>
/// <param name="charTest">Character test delegate.</param>
/// <param name="limitHiBit">If set, the high bit in all character must be the
/// same. Used to enforce a single encoding when "low or high ASCII" is used.</param>
/// <returns>Number of strings found, or -1 if bad data identified.</returns> /// <returns>Number of strings found, or -1 if bad data identified.</returns>
public static int RecognizeLen8Strings(byte[] fileData, int start, int end) { public static int RecognizeLen8Strings(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest, bool limitHiBit) {
int posn = start; int posn = start;
int remaining = end - start + 1; int remaining = end - start + 1;
int stringCount = 0; int stringCount = 0;
@ -944,13 +967,12 @@ namespace SourceGen {
while (strLen-- != 0) { while (strLen-- != 0) {
byte val = fileData[posn++]; byte val = fileData[posn++];
if ((val & 0x80) != expectedHiBit) { if (limitHiBit && (val & 0x80) != expectedHiBit) {
// Mixed ASCII, fail. // Mixed ASCII, fail.
return -1; return -1;
} }
val &= 0x7f; if (!charTest(val)) {
if (val < 0x20 || val == 0x7f) { // Not a matching character, fail.
// Non-ASCII, fail.
return -1; return -1;
} }
} }
@ -961,16 +983,18 @@ namespace SourceGen {
/// <summary> /// <summary>
/// Counts strings prefixed with a 16-bit length. /// Counts strings prefixed with a 16-bit length.
///
/// Each string must be either high-ASCII or low-ASCII, not a mix.
/// ///
/// Zero-length strings are allowed but not counted. /// Zero-length strings are allowed but not counted.
/// </summary> /// </summary>
/// <param name="fileData">Raw data.</param> /// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param> /// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range.</param> /// <param name="end">Offset of last byte in range.</param>
/// <param name="charTest">Character test delegate.</param>
/// <param name="limitHiBit">If set, the high bit in all character must be the
/// same. Used to enforce a single encoding when "low or high ASCII" is used.</param>
/// <returns>Number of strings found, or -1 if bad data identified.</returns> /// <returns>Number of strings found, or -1 if bad data identified.</returns>
public static int RecognizeLen16Strings(byte[] fileData, int start, int end) { public static int RecognizeLen16Strings(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest, bool limitHiBit) {
int posn = start; int posn = start;
int remaining = end - start + 1; int remaining = end - start + 1;
int stringCount = 0; int stringCount = 0;
@ -998,13 +1022,12 @@ namespace SourceGen {
while (strLen-- != 0) { while (strLen-- != 0) {
byte val = fileData[posn++]; byte val = fileData[posn++];
if ((val & 0x80) != expectedHiBit) { if (limitHiBit && (val & 0x80) != expectedHiBit) {
// Mixed ASCII, fail. // Mixed ASCII, fail.
return -1; return -1;
} }
val &= 0x7f; if (!charTest(val)) {
if (val < 0x20 || val == 0x7f) { // Not a matching character, fail.
// Non-ASCII, fail.
return -1; return -1;
} }
} }
@ -1020,11 +1043,16 @@ namespace SourceGen {
/// Each string must be at least two bytes. To reduce false-positives, we require /// Each string must be at least two bytes. To reduce false-positives, we require
/// that all strings have the same hi/lo pattern. /// that all strings have the same hi/lo pattern.
/// </summary> /// </summary>
/// <remarks>
/// Not useful for C64Petscii, which mixes high/low characters.
/// </remarks>
/// <param name="fileData">Raw data.</param> /// <param name="fileData">Raw data.</param>
/// <param name="start">Offset of first byte in range.</param> /// <param name="start">Offset of first byte in range.</param>
/// <param name="end">Offset of last byte in range.</param> /// <param name="end">Offset of last byte in range.</param>
/// <param name="charTest">Character test delegate.</param>
/// <returns>Number of strings found, or -1 if bad data identified.</returns> /// <returns>Number of strings found, or -1 if bad data identified.</returns>
public static int RecognizeDciStrings(byte[] fileData, int start, int end) { public static int RecognizeDciStrings(byte[] fileData, int start, int end,
CharEncoding.InclusionTest charTest) {
int expectedHiBit = fileData[start] & 0x80; int expectedHiBit = fileData[start] & 0x80;
int stringCount = 0; int stringCount = 0;
int stringLen = 0; int stringLen = 0;
@ -1048,9 +1076,8 @@ namespace SourceGen {
stringLen++; stringLen++;
} }
val &= 0x7f; if (!charTest((byte)(val & 0x7f))) {
if (val < 0x20 || val == 0x7f) { // Not a matching character, fail.
// Non-ASCII, fail.
return -1; return -1;
} }
} }
@ -1104,7 +1131,7 @@ namespace SourceGen {
return stringCount; return stringCount;
} }
#endregion // Static analyzers #endregion // Static analyzers
} }
} }

View File

@ -106,8 +106,8 @@ namespace SourceGen {
/// </summary> /// </summary>
/// <param name="e">Argument from SelectionChanged event.</param> /// <param name="e">Argument from SelectionChanged event.</param>
public void SelectionChanged(SelectionChangedEventArgs e) { public void SelectionChanged(SelectionChangedEventArgs e) {
Debug.WriteLine("SelectionChanged event: Add=" + e.AddedItems.Count + //Debug.WriteLine("SelectionChanged event: Add=" + e.AddedItems.Count +
" Rem=" + e.RemovedItems.Count); // " Rem=" + e.RemovedItems.Count);
foreach (DisplayList.FormattedParts parts in e.AddedItems) { foreach (DisplayList.FormattedParts parts in e.AddedItems) {
Debug.Assert(parts.ListIndex >= 0 && parts.ListIndex < mSelection.Length); Debug.Assert(parts.ListIndex >= 0 && parts.ListIndex < mSelection.Length);
this[parts.ListIndex] = true; this[parts.ListIndex] = true;

View File

@ -393,6 +393,7 @@ namespace SourceGen {
descr += " ???"; descr += " ???";
break; break;
} }
return descr;
} }
switch (FormatSubType) { switch (FormatSubType) {

View File

@ -2359,7 +2359,7 @@ namespace SourceGen {
/// is selected.</param> /// is selected.</param>
public SelectionState UpdateSelectionState() { public SelectionState UpdateSelectionState() {
int selCount = mMainWin.CodeListView_GetSelectionCount(); int selCount = mMainWin.CodeListView_GetSelectionCount();
Debug.WriteLine("UpdateSelectionState: selCount=" + selCount); //Debug.WriteLine("UpdateSelectionState: selCount=" + selCount);
SelectionState state = new SelectionState(); SelectionState state = new SelectionState();

View File

@ -318,11 +318,19 @@ namespace SourceGen {
CharEncoding.Convert charConv; CharEncoding.Convert charConv;
switch (dfd.FormatSubType) { switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii: case FormatDescriptor.SubType.Ascii:
charConv = CharEncoding.ConvertAscii; if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighAscii;
} else {
charConv = CharEncoding.ConvertAscii;
}
delDef = delSet.Get(CharEncoding.Encoding.Ascii); delDef = delSet.Get(CharEncoding.Encoding.Ascii);
break; break;
case FormatDescriptor.SubType.HighAscii: case FormatDescriptor.SubType.HighAscii:
charConv = CharEncoding.ConvertHighAscii; if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighAscii;
} else {
charConv = CharEncoding.ConvertHighAscii;
}
delDef = delSet.Get(CharEncoding.Encoding.HighAscii); delDef = delSet.Get(CharEncoding.Encoding.HighAscii);
break; break;
case FormatDescriptor.SubType.C64Petscii: case FormatDescriptor.SubType.C64Petscii:
@ -330,7 +338,11 @@ namespace SourceGen {
delDef = delSet.Get(CharEncoding.Encoding.C64Petscii); delDef = delSet.Get(CharEncoding.Encoding.C64Petscii);
break; break;
case FormatDescriptor.SubType.C64Screen: case FormatDescriptor.SubType.C64Screen:
charConv = CharEncoding.ConvertC64ScreenCode; if (dfd.FormatType == FormatDescriptor.Type.StringDci) {
charConv = CharEncoding.ConvertLowAndHighC64ScreenCode;
} else {
charConv = CharEncoding.ConvertC64ScreenCode;
}
delDef = delSet.Get(CharEncoding.Encoding.C64ScreenCode); delDef = delSet.Get(CharEncoding.Encoding.C64ScreenCode);
break; break;
default: default:
@ -340,13 +352,17 @@ namespace SourceGen {
break; break;
} }
if (delDef == null) {
delDef = Formatter.DOUBLE_QUOTE_DELIM;
}
switch (dfd.FormatType) { switch (dfd.FormatType) {
case FormatDescriptor.Type.StringGeneric: case FormatDescriptor.Type.StringGeneric:
// Generic character data. // Generic character data.
popcode = opNames.StrGeneric; popcode = opNames.StrGeneric;
break; break;
case FormatDescriptor.Type.StringReverse: case FormatDescriptor.Type.StringReverse:
// High or low ASCII, full width specified by formatter. Show characters // Character data, full width specified by formatter. Show characters
// in reverse order. // in reverse order.
popcode = opNames.StrReverse; popcode = opNames.StrReverse;
revMode = StringOpFormatter.ReverseMode.FullReverse; revMode = StringOpFormatter.ReverseMode.FullReverse;
@ -377,10 +393,8 @@ namespace SourceGen {
popcode = opNames.StrLen16; popcode = opNames.StrLen16;
break; break;
case FormatDescriptor.Type.StringDci: case FormatDescriptor.Type.StringDci:
// High or low ASCII, with high bit on last byte flipped. Only useful // High bit on last byte is flipped.
// for ASCII strings.
popcode = opNames.StrDci; popcode = opNames.StrDci;
charConv = CharEncoding.ConvertLowAndHighAscii;
break; break;
default: default:
Debug.Assert(false); Debug.Assert(false);

View File

@ -112,6 +112,10 @@ limitations under the License.
<system:String x:Key="str_RuntimeDirNotFoundCaption">RuntimeData Not Found</system:String> <system:String x:Key="str_RuntimeDirNotFoundCaption">RuntimeData Not Found</system:String>
<system:String x:Key="str_SaveBeforeAsm">Please save your project before assembling. The generated source code will be placed in the same directory as the project file.</system:String> <system:String x:Key="str_SaveBeforeAsm">Please save your project before assembling. The generated source code will be placed in the same directory as the project file.</system:String>
<system:String x:Key="str_SaveBeforeAsmCaption">Save Project First</system:String> <system:String x:Key="str_SaveBeforeAsmCaption">Save Project First</system:String>
<system:String x:Key="str_ScanLowAscii">Plain ASCII</system:String>
<system:String x:Key="str_ScanLowHighAscii">Low or High ASCII</system:String>
<system:String x:Key="str_ScanC64Petscii">C64 PETSCII</system:String>
<system:String x:Key="str_ScanC64ScreenCode">C64 Screen Code</system:String>
<system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String> <system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String>
<system:String x:Key="str_ShowCol">Show</system:String> <system:String x:Key="str_ShowCol">Show</system:String>
<system:String x:Key="str_StatusReady">Ready</system:String> <system:String x:Key="str_StatusReady">Ready</system:String>

View File

@ -205,6 +205,14 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_SaveBeforeAsm"); (string)Application.Current.FindResource("str_SaveBeforeAsm");
public static string SAVE_BEFORE_ASM_CAPTION = public static string SAVE_BEFORE_ASM_CAPTION =
(string)Application.Current.FindResource("str_SaveBeforeAsmCaption"); (string)Application.Current.FindResource("str_SaveBeforeAsmCaption");
public static string SCAN_LOW_ASCII =
(string)Application.Current.FindResource("str_ScanLowAscii");
public static string SCAN_LOW_HIGH_ASCII =
(string)Application.Current.FindResource("str_ScanLowHighAscii");
public static string SCAN_C64_PETSCII =
(string)Application.Current.FindResource("str_ScanC64Petscii");
public static string SCAN_C64_SCREEN_CODE =
(string)Application.Current.FindResource("str_ScanC64ScreenCode");
public static string SETUP_SYSTEM_SUMMARY_FMT = public static string SETUP_SYSTEM_SUMMARY_FMT =
(string)Application.Current.FindResource("str_SetupSystemSummaryFmt"); (string)Application.Current.FindResource("str_SetupSystemSummaryFmt");
public static string SHOW_COL = public static string SHOW_COL =

View File

@ -1,7 +1,7 @@
; Copyright 2019 faddenSoft. All Rights Reserved. ; Copyright 2019 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: ACME (good PETSCII/screen code support) ; Assembler: ACME (for the PETSCII/screen code support)
!cpu 65816 !cpu 65816
* = $1000 * = $1000
@ -28,6 +28,8 @@
lda #$7f ;EDIT: force to PETSCII lda #$7f ;EDIT: force to PETSCII
lda #$7f ;EDIT: force to screen code lda #$7f ;EDIT: force to screen code
lda #$0d ;verify the instruction operand editor only allows C64SC
; Single letter in a 16-bit immediate ; Single letter in a 16-bit immediate
rep #$30 rep #$30
!al !al
@ -63,7 +65,7 @@
; Start with the basics ; Start with the basics
!byte $80 !byte $80
!text "low ASCII str" !text "low ASCII str"
!byte $80 ; !byte $80 ; let them run together to test scan / dialog behavior
!xor $80 { !xor $80 {
!text "high ASCII str" !text "high ASCII str"
} }

View File

@ -512,6 +512,9 @@ namespace SourceGen.WpfGui {
private void ImportDelimiters(Formatter.DelimiterSet delSet, DelimiterTextBoxes[] boxarr) { private void ImportDelimiters(Formatter.DelimiterSet delSet, DelimiterTextBoxes[] boxarr) {
foreach (DelimiterTextBoxes boxes in boxarr) { foreach (DelimiterTextBoxes boxes in boxarr) {
Formatter.DelimiterDef def = delSet.Get(boxes.mEncoding); Formatter.DelimiterDef def = delSet.Get(boxes.mEncoding);
if (def == null) {
def = Formatter.DOUBLE_QUOTE_DELIM;
}
boxes.mPrefix.Text = def.Prefix; boxes.mPrefix.Text = def.Prefix;
boxes.mOpen.Text = "" + def.OpenDelim; boxes.mOpen.Text = "" + def.OpenDelim;
boxes.mClose.Text = "" + def.CloseDelim; boxes.mClose.Text = "" + def.CloseDelim;

View File

@ -33,8 +33,8 @@ limitations under the License.
<system:String x:Key="str_SingleGroup">Select data format ({0} bytes selected):</system:String> <system:String x:Key="str_SingleGroup">Select data format ({0} bytes selected):</system:String>
<system:String x:Key="str_MultiGroup">Select data format ({0} bytes selected in {1} groups):</system:String> <system:String x:Key="str_MultiGroup">Select data format ({0} bytes selected in {1} groups):</system:String>
<system:String x:Key="str_StringMixed">Mixed ASCII ({0} bytes) and non-ASCII ({1} bytes)</system:String> <system:String x:Key="str_StringMixed">Mixed character ({0} bytes) and non-character ({1} bytes)</system:String>
<system:String x:Key="str_StringMixedReverse">Reversed ASCII ({0} bytes) and non-ASCII ({1} bytes)</system:String> <system:String x:Key="str_StringMixedReverse">Reversed character ({0} bytes) and non-character ({1} bytes)</system:String>
<system:String x:Key="str_StringNullTerm">Null-terminated strings ({0})</system:String> <system:String x:Key="str_StringNullTerm">Null-terminated strings ({0})</system:String>
<system:String x:Key="str_StringLen8">Strings prefixed with 8-bit length ({0})</system:String> <system:String x:Key="str_StringLen8">Strings prefixed with 8-bit length ({0})</system:String>
<system:String x:Key="str_StringLen16">Strings prefixed with 16-bit length ({0})</system:String> <system:String x:Key="str_StringLen16">Strings prefixed with 16-bit length ({0})</system:String>
@ -64,29 +64,44 @@ limitations under the License.
<RadioButton Name="radio32BitLittle" GroupName="Main" Content="32-bit words, little-endian" Margin="0,4,0,0" <RadioButton Name="radio32BitLittle" GroupName="Main" Content="32-bit words, little-endian" Margin="0,4,0,0"
Checked="MainGroup_CheckedChanged"/> Checked="MainGroup_CheckedChanged"/>
</StackPanel> </StackPanel>
<GroupBox Name="simpleDisplayAsGroupBox" Grid.Column="1" Header="Display As..." Margin="16,0,0,0"> <GroupBox Name="simpleDisplayAsGroupBox" Grid.Column="1" Header="Display As..." Margin="16,0,0,0"
Padding="2,4">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<RadioButton Name="radioSimpleDataHex" GroupName="Display" Content="Hex" <RadioButton Name="radioSimpleDataHex" GroupName="Display" Content="Hex"
Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Checked="SimpleDisplay_CheckedChanged"/>
<RadioButton Name="radioSimpleDataDecimal" GroupName="Display" Content="Decimal" <RadioButton Name="radioSimpleDataDecimal" GroupName="Display" Content="Decimal"
Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Margin="0,4,18,0" Checked="SimpleDisplay_CheckedChanged"/>
<RadioButton Name="radioSimpleDataBinary" GroupName="Display" Content="Binary" <RadioButton Name="radioSimpleDataBinary" GroupName="Display" Content="Binary"
Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/>
<RadioButton Name="radioSimpleDataAscii" GroupName="Display" Content="ASCII" <RadioButton Name="radioSimpleDataAddress" GroupName="Display" Content="_Address"
Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/>
</StackPanel> </StackPanel>
<StackPanel Grid.Column="1"> <StackPanel Grid.Column="1" Grid.Row="0">
<RadioButton Name="radioSimpleDataAddress" GroupName="Display" Content="_Address" <RadioButton Name="radioSimpleDataAscii" GroupName="Display"
Margin="12,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Content="ASCII (low or high) character"
Checked="SimpleDisplay_CheckedChanged"/>
<RadioButton Name="radioSimpleDataPetscii" GroupName="Display"
Content="C64 PETSCII character"
Checked="SimpleDisplay_CheckedChanged"/>
<RadioButton Name="radioSimpleDataScreenCode" GroupName="Display"
Content="C64 Screen character"
Checked="SimpleDisplay_CheckedChanged"/>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2">
<RadioButton Name="radioSimpleDataSymbolic" GroupName="Display" Content="_Symbolic reference" <RadioButton Name="radioSimpleDataSymbolic" GroupName="Display" Content="_Symbolic reference"
Margin="12,4,0,0" Checked="SimpleDisplay_CheckedChanged"/> Margin="0,4,0,0" Checked="SimpleDisplay_CheckedChanged"/>
<TextBox Name="symbolEntryTextBox" Margin="32,4,0,0" TextChanged="SymbolEntryTextBox_TextChanged"/> <TextBox Name="symbolEntryTextBox" Margin="20,4,0,0" TextChanged="SymbolEntryTextBox_TextChanged"/>
<StackPanel Orientation="Horizontal" Margin="32,4,0,0"
<StackPanel Orientation="Horizontal" Margin="20,4,0,0"
IsEnabled="{Binding ElementName=radioSimpleDataSymbolic, Path=IsChecked}"> IsEnabled="{Binding ElementName=radioSimpleDataSymbolic, Path=IsChecked}">
<RadioButton Name="radioSymbolPartLow" GroupName="Part" Content="Low"/> <RadioButton Name="radioSymbolPartLow" GroupName="Part" Content="Low"/>
<RadioButton Name="radioSymbolPartHigh" GroupName="Part" Content="High" Margin="8,0,0,0"/> <RadioButton Name="radioSymbolPartHigh" GroupName="Part" Content="High" Margin="8,0,0,0"/>
@ -106,6 +121,12 @@ limitations under the License.
<TextBlock Text="String" Margin="0,12,0,0"/> <TextBlock Text="String" Margin="0,12,0,0"/>
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/> <Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Character encoding:" Margin="0,7,0,0"/>
<ComboBox Name="stringEncodingComboBox" Width="150" Margin="8,4,0,4"
ItemsSource="{Binding StringEncodingItems}" DisplayMemberPath="Name"
SelectionChanged="StringEncodingComboBox_SelectionChanged"/>
</StackPanel>
<RadioButton Name="radioStringMixed" GroupName="Main" Margin="0,4,0,0" <RadioButton Name="radioStringMixed" GroupName="Main" Margin="0,4,0,0"
Content="{StaticResource str_StringMixed}" Content="{StaticResource str_StringMixed}"
Checked="MainGroup_CheckedChanged"/> Checked="MainGroup_CheckedChanged"/>

View File

@ -21,7 +21,9 @@ using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using Asm65;
using CommonUtil; using CommonUtil;
using TextScanMode = SourceGen.ProjectProperties.AnalysisParameters.TextScanMode;
namespace SourceGen.WpfGui { namespace SourceGen.WpfGui {
/// <summary> /// <summary>
@ -77,18 +79,27 @@ namespace SourceGen.WpfGui {
/// </summary> /// </summary>
private Asm65.Formatter mFormatter; private Asm65.Formatter mFormatter;
///// <summary>
///// Set this during initial control configuration, so we know to ignore the CheckedChanged
///// events.
///// </summary>
//private bool mIsInitialSetup;
/// <summary> /// <summary>
/// Set to true if, during the initial setup, the format defined by FirstFormatDescriptor /// Set to true if, during the initial setup, the format defined by FirstFormatDescriptor
/// was unavailable. /// was unavailable.
/// </summary> /// </summary>
private bool mPreferredFormatUnavailable; private bool mPreferredFormatUnavailable;
/// <summary>
/// Text encoding combo box item. We use the same TextScanMode enum that the
/// uncategorized data analyzer uses.
/// </summary>
public class StringEncodingItem {
public string Name { get; private set; }
public TextScanMode Mode { get; private set; }
public StringEncodingItem(string name, TextScanMode mode) {
Name = name;
Mode = mode;
}
}
public StringEncodingItem[] StringEncodingItems { get; private set; }
// INotifyPropertyChanged implementation // INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") { private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
@ -107,6 +118,17 @@ namespace SourceGen.WpfGui {
mFormatter = formatter; mFormatter = formatter;
mSelection = trs; mSelection = trs;
mFirstFormatDescriptor = firstDesc; mFirstFormatDescriptor = firstDesc;
StringEncodingItems = new StringEncodingItem[] {
new StringEncodingItem(Res.Strings.SCAN_LOW_ASCII,
TextScanMode.LowAscii),
new StringEncodingItem(Res.Strings.SCAN_LOW_HIGH_ASCII,
TextScanMode.LowHighAscii),
new StringEncodingItem(Res.Strings.SCAN_C64_PETSCII,
TextScanMode.C64Petscii),
new StringEncodingItem(Res.Strings.SCAN_C64_SCREEN_CODE,
TextScanMode.C64ScreenCode),
};
} }
private void Window_Loaded(object sender, RoutedEventArgs e) { private void Window_Loaded(object sender, RoutedEventArgs e) {
@ -116,6 +138,9 @@ namespace SourceGen.WpfGui {
// Disable any radio buttons that won't work. // Disable any radio buttons that won't work.
AnalyzeRanges(); AnalyzeRanges();
// This gets invoked a bit later, from the "selection changed" callback.
//AnalyzeStringRanges(TextScanMode.LowHighAscii);
// Configure the dialog from the FormatDescriptor, if one is available. // Configure the dialog from the FormatDescriptor, if one is available.
Debug.WriteLine("First FD: " + mFirstFormatDescriptor); Debug.WriteLine("First FD: " + mFirstFormatDescriptor);
SetControlsFromDescriptor(mFirstFormatDescriptor); SetControlsFromDescriptor(mFirstFormatDescriptor);
@ -169,6 +194,36 @@ namespace SourceGen.WpfGui {
UpdateControls(); UpdateControls();
} }
/// <summary>
/// Sets the string encoding combo box to an item that matches the specified mode. If
/// the mode can't be found, an arbitrary entry will be chosen.
/// </summary>
private void SetStringEncoding(TextScanMode mode) {
StringEncodingItem choice = null;
foreach (StringEncodingItem item in StringEncodingItems) {
if (item.Mode == mode) {
choice = item;
break;
}
}
if (choice == null) {
choice = StringEncodingItems[1];
}
stringEncodingComboBox.SelectedItem = choice;
}
private void StringEncodingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
if (!IsLoaded) {
return;
}
StringEncodingItem item = (StringEncodingItem)stringEncodingComboBox.SelectedItem;
AnalyzeStringRanges(item.Mode);
UpdateControls();
AppSettings.Global.SetEnum(AppSettings.OPED_DEFAULT_STRING_ENCODING,
typeof(TextScanMode), (int)item.Mode);
}
private void OkButton_Click(object sender, RoutedEventArgs e) { private void OkButton_Click(object sender, RoutedEventArgs e) {
CreateDescriptorListFromControls(); CreateDescriptorListFromControls();
FormatDescriptor.DebugDumpSortedList(Results); FormatDescriptor.DebugDumpSortedList(Results);
@ -207,7 +262,14 @@ namespace SourceGen.WpfGui {
bool focusOnSymbol = !simpleDisplayAsGroupBox.IsEnabled && wantStyle; bool focusOnSymbol = !simpleDisplayAsGroupBox.IsEnabled && wantStyle;
simpleDisplayAsGroupBox.IsEnabled = wantStyle; simpleDisplayAsGroupBox.IsEnabled = wantStyle;
if (wantStyle) { if (wantStyle) {
radioSimpleDataAscii.IsEnabled = IsRawAsciiCompatible(simpleWidth, isBigEndian); // Because this covers multiple items in a data area, we allow the
// "extended" set, which includes some control characters.
radioSimpleDataAscii.IsEnabled = IsCompatibleWithCharSet(simpleWidth,
isBigEndian, CharEncoding.IsExtendedLowOrHighAscii);
radioSimpleDataPetscii.IsEnabled = IsCompatibleWithCharSet(simpleWidth,
isBigEndian, CharEncoding.IsExtendedC64Petscii);
radioSimpleDataScreenCode.IsEnabled = IsCompatibleWithCharSet(simpleWidth,
isBigEndian, CharEncoding.IsExtendedC64ScreenCode);
} }
// Enable the symbolic reference entry box if the "display as" group is enabled. // Enable the symbolic reference entry box if the "display as" group is enabled.
@ -263,13 +325,6 @@ namespace SourceGen.WpfGui {
IEnumerator<TypedRangeSet.TypedRange> iter = mSelection.RangeListIterator; IEnumerator<TypedRangeSet.TypedRange> iter = mSelection.RangeListIterator;
int mixedAsciiOkCount = 0;
int mixedAsciiNotCount = 0;
int nullTermStringCount = 0;
int len8StringCount = 0;
int len16StringCount = 0;
int dciStringCount = 0;
// For each range, check to see if the data within qualifies for the various // For each range, check to see if the data within qualifies for the various
// options. If any of them fail to meet the criteria, the option is disabled // options. If any of them fail to meet the criteria, the option is disabled
// for all ranges. // for all ranges.
@ -277,7 +332,7 @@ namespace SourceGen.WpfGui {
TypedRangeSet.TypedRange rng = iter.Current; TypedRangeSet.TypedRange rng = iter.Current;
Debug.WriteLine("Testing [" + rng.Low + ", " + rng.High + "]"); Debug.WriteLine("Testing [" + rng.Low + ", " + rng.High + "]");
// Start with the easy ones. Single-byte and dense are always enabled. // Note single-byte and dense are always enabled.
int count = rng.High - rng.Low + 1; int count = rng.High - rng.Low + 1;
Debug.Assert(count > 0); Debug.Assert(count > 0);
@ -305,46 +360,110 @@ namespace SourceGen.WpfGui {
} else { } else {
radioFill.IsEnabled = false; radioFill.IsEnabled = false;
} }
}
}
/// <summary>
/// Analyzes the selection to see which string formatting options are suitable.
/// Disables radio buttons and updates labels.
///
/// Call this when the character encoding selection changes.
/// </summary>
private void AnalyzeStringRanges(TextScanMode scanMode) {
Debug.WriteLine("Analyzing string ranges");
Debug.Assert(IsLoaded);
int mixedCharOkCount = 0;
int mixedCharNotCount = 0;
int nullTermStringCount = 0;
int len8StringCount = 0;
int len16StringCount = 0;
int dciStringCount = 0;
CharEncoding.InclusionTest charTest;
switch (scanMode) {
case TextScanMode.LowAscii:
charTest = CharEncoding.IsExtendedAscii;
break;
case TextScanMode.LowHighAscii:
charTest = CharEncoding.IsExtendedLowOrHighAscii;
break;
case TextScanMode.C64Petscii:
charTest = CharEncoding.IsExtendedC64Petscii;
break;
case TextScanMode.C64ScreenCode:
charTest = CharEncoding.IsExtendedC64ScreenCode;
break;
default:
Debug.Assert(false);
charTest = CharEncoding.IsExtendedAscii;
break;
}
radioStringMixed.IsEnabled = true;
radioStringMixedReverse.IsEnabled = true;
radioStringNullTerm.IsEnabled = (scanMode != TextScanMode.C64ScreenCode);
radioStringLen8.IsEnabled = true;
radioStringLen16.IsEnabled = true;
radioStringDci.IsEnabled = (scanMode != TextScanMode.C64Petscii);
IEnumerator<TypedRangeSet.TypedRange> iter = mSelection.RangeListIterator;
while (iter.MoveNext()) {
TypedRangeSet.TypedRange rng = iter.Current;
Debug.WriteLine("Testing [" + rng.Low + ", " + rng.High + "]");
// See if there's enough string data to make it worthwhile. We use an // See if there's enough string data to make it worthwhile. We use an
// arbitrary threshold of 2+ ASCII characters, and require twice as many // arbitrary threshold of 2+ printable characters, and require twice as many
// ASCII as non-ASCII. We arbitrarily require the strings to be either // printable as non-printable.
// high or low ASCII, and treat the other as non-ASCII. (We could relax
// this -- we generate separate items for each string and non-ASCII chunk --
// but I'm trying to hide the option when the buffer doesn't really seem
// to be holding strings. Could replace with some sort of minimum string
// length requirement?)
if (radioStringMixed.IsEnabled) { if (radioStringMixed.IsEnabled) {
int asciiCount; if (scanMode == TextScanMode.LowHighAscii) {
DataAnalysis.CountAsciiBytes(mFileData, rng.Low, rng.High, // We use a special test that counts low, high, and non-ASCII.
out int lowAscii, out int highAscii, out int nonAscii); // Whichever form of ASCII has the highest count is the winner, and
if (highAscii > lowAscii) { // the loser is counted as non-ASCII.
asciiCount = highAscii; int asciiCount;
nonAscii += lowAscii; DataAnalysis.CountHighLowBytes(mFileData, rng.Low, rng.High, charTest,
} else { out int lowAscii, out int highAscii, out int nonAscii);
asciiCount = lowAscii; if (highAscii > lowAscii) {
nonAscii += highAscii; asciiCount = highAscii;
} nonAscii += lowAscii;
} else {
asciiCount = lowAscii;
nonAscii += highAscii;
}
if (asciiCount >= 2 && asciiCount >= nonAscii * 2) { if (asciiCount >= 2 && asciiCount >= nonAscii * 2) {
// Looks good // Looks good
mixedAsciiOkCount += asciiCount; mixedCharOkCount += asciiCount;
mixedAsciiNotCount += nonAscii; mixedCharNotCount += nonAscii;
} else {
// Fail
radioStringMixed.IsEnabled = false;
radioStringMixedReverse.IsEnabled = false;
mixedCharOkCount = mixedCharNotCount = -1;
}
} else { } else {
// Fail int matchCount = DataAnalysis.CountCharacterBytes(mFileData,
radioStringMixed.IsEnabled = false; rng.Low, rng.High, charTest);
radioStringMixedReverse.IsEnabled = false; int missCount = (rng.High - rng.Low + 1) - matchCount;
mixedAsciiOkCount = mixedAsciiNotCount = -1; if (matchCount >= 2 && matchCount >= missCount * 2) {
mixedCharOkCount += matchCount;
mixedCharNotCount += missCount;
} else {
// Fail
radioStringMixed.IsEnabled = false;
radioStringMixedReverse.IsEnabled = false;
mixedCharOkCount = mixedCharNotCount = -1;
}
} }
} }
// Check for null-terminated strings. Zero-length strings are allowed, but // Check for null-terminated strings. Zero-length strings are allowed, but
// not counted -- we want to have some actual character data. Individual // not counted -- we want to have some actual character data. Individual
// strings need to be entirely high-ASCII or low-ASCII, but not all strings // ASCII strings need to be entirely high-ASCII or low-ASCII, but not all strings
// in a region have to be the same. // in a region have to be the same.
if (radioStringNullTerm.IsEnabled) { if (radioStringNullTerm.IsEnabled) {
int strCount = DataAnalysis.RecognizeNullTerminatedStrings(mFileData, int strCount = DataAnalysis.RecognizeNullTerminatedStrings(mFileData,
rng.Low, rng.High); rng.Low, rng.High, charTest, scanMode == TextScanMode.LowHighAscii);
if (strCount > 0) { if (strCount > 0) {
nullTermStringCount += strCount; nullTermStringCount += strCount;
} else { } else {
@ -355,7 +474,8 @@ namespace SourceGen.WpfGui {
// Check for strings prefixed with an 8-bit length. // Check for strings prefixed with an 8-bit length.
if (radioStringLen8.IsEnabled) { if (radioStringLen8.IsEnabled) {
int strCount = DataAnalysis.RecognizeLen8Strings(mFileData, rng.Low, rng.High); int strCount = DataAnalysis.RecognizeLen8Strings(mFileData, rng.Low, rng.High,
charTest, scanMode == TextScanMode.LowHighAscii);
if (strCount > 0) { if (strCount > 0) {
len8StringCount += strCount; len8StringCount += strCount;
} else { } else {
@ -366,7 +486,8 @@ namespace SourceGen.WpfGui {
// Check for strings prefixed with a 16-bit length. // Check for strings prefixed with a 16-bit length.
if (radioStringLen16.IsEnabled) { if (radioStringLen16.IsEnabled) {
int strCount = DataAnalysis.RecognizeLen16Strings(mFileData, rng.Low, rng.High); int strCount = DataAnalysis.RecognizeLen16Strings(mFileData, rng.Low, rng.High,
charTest, scanMode == TextScanMode.LowHighAscii);
if (strCount > 0) { if (strCount > 0) {
len16StringCount += strCount; len16StringCount += strCount;
} else { } else {
@ -375,10 +496,11 @@ namespace SourceGen.WpfGui {
} }
} }
// Check for DCI strings. All strings within a single range must have the // Check for DCI strings. All strings within the entire range must have the
// same "polarity", e.g. low ASCII terminated by high ASCII. // same "polarity", e.g. low ASCII terminated by high ASCII.
if (radioStringDci.IsEnabled) { if (radioStringDci.IsEnabled) {
int strCount = DataAnalysis.RecognizeDciStrings(mFileData, rng.Low, rng.High); int strCount = DataAnalysis.RecognizeDciStrings(mFileData, rng.Low, rng.High,
charTest);
if (strCount > 0) { if (strCount > 0) {
dciStringCount += strCount; dciStringCount += strCount;
} else { } else {
@ -390,15 +512,16 @@ namespace SourceGen.WpfGui {
// Update the dialog with string and character counts, summed across all regions. // Update the dialog with string and character counts, summed across all regions.
string fmt;
const string UNSUP_STR = "xx"; const string UNSUP_STR = "xx";
fmt = (string)FindResource("str_StringMixed"); fmt = (string)FindResource("str_StringMixed");
string revfmt = (string)FindResource("str_StringMixedReverse"); string revfmt = (string)FindResource("str_StringMixedReverse");
if (mixedAsciiOkCount > 0) { if (mixedCharOkCount > 0) {
Debug.Assert(radioStringMixed.IsEnabled); Debug.Assert(radioStringMixed.IsEnabled);
radioStringMixed.Content = string.Format(fmt, radioStringMixed.Content = string.Format(fmt,
mixedAsciiOkCount, mixedAsciiNotCount); mixedCharOkCount, mixedCharNotCount);
radioStringMixedReverse.Content = string.Format(revfmt, radioStringMixedReverse.Content = string.Format(revfmt,
mixedAsciiOkCount, mixedAsciiNotCount); mixedCharOkCount, mixedCharNotCount);
} else { } else {
Debug.Assert(!radioStringMixed.IsEnabled); Debug.Assert(!radioStringMixed.IsEnabled);
radioStringMixed.Content = string.Format(fmt, UNSUP_STR, UNSUP_STR); radioStringMixed.Content = string.Format(fmt, UNSUP_STR, UNSUP_STR);
@ -440,32 +563,40 @@ namespace SourceGen.WpfGui {
Debug.Assert(!radioStringDci.IsEnabled); Debug.Assert(!radioStringDci.IsEnabled);
radioStringDci.Content = string.Format(fmt, UNSUP_STR); radioStringDci.Content = string.Format(fmt, UNSUP_STR);
} }
// If this invalidated the selected item, reset to Default.
if ((radioStringMixed.IsChecked == true && !radioStringMixed.IsEnabled) ||
(radioStringMixedReverse.IsChecked == true && !radioStringMixedReverse.IsEnabled) ||
(radioStringNullTerm.IsChecked == true && !radioStringNullTerm.IsEnabled) ||
(radioStringLen8.IsChecked == true && !radioStringLen8.IsEnabled) ||
(radioStringLen8.IsChecked == true && !radioStringLen8.IsEnabled) ||
(radioStringDci.IsChecked == true && !radioStringDci.IsEnabled)) {
Debug.WriteLine("Previous selection invalidated");
radioDefaultFormat.IsChecked = true;
}
} }
/// <summary> /// <summary>
/// Determines whether the data in the buffer can be represented as ASCII values. /// Determines whether the data in the buffer can be represented as character values.
/// Using ".DD1 'A'" for 0x41 is obvious, but we also allow ".DD2 'A'" for /// Using ".DD1 'A'" for 0x41 is obvious, but we also allow ".DD2 'A'" for
/// 0x41 0x00. 16-bit character constants are more likely as intermediate /// 0x41 0x00. 16-bit character constants are more likely as intermediate
/// operands, but could be found in data areas. /// operands, but could be found in data areas.
///
/// High and low ASCII are allowed, and may be freely mixed.
///
/// Testing explicitly is probably excessive, and possibly counter-productive if
/// the user is trying to flag an area that is a mix of ASCII and non-ASCII and
/// just wants hex for the rest, but we'll give it a try.
/// </summary> /// </summary>
/// <param name="wordWidth">Number of bytes per character.</param> /// <param name="wordWidth">Number of bytes per character.</param>
/// <param name="isBigEndian">Word endian-ness.</param> /// <param name="isBigEndian">Word endian-ness.</param>
/// <returns>True if data in all regions can be represented as high or low ASCII.</returns> /// <param name="charTest">Character test delegate.</param>
private bool IsRawAsciiCompatible(int wordWidth, bool isBigEndian) { /// <returns>True if data in all regions can be represented as a character.</returns>
private bool IsCompatibleWithCharSet(int wordWidth, bool isBigEndian,
CharEncoding.InclusionTest charTest) {
IEnumerator<TypedRangeSet.TypedRange> iter = mSelection.RangeListIterator; IEnumerator<TypedRangeSet.TypedRange> iter = mSelection.RangeListIterator;
while (iter.MoveNext()) { while (iter.MoveNext()) {
TypedRangeSet.TypedRange rng = iter.Current; TypedRangeSet.TypedRange rng = iter.Current;
Debug.Assert(((rng.High - rng.Low + 1) / wordWidth) * wordWidth == Debug.Assert(((rng.High - rng.Low + 1) / wordWidth) * wordWidth ==
rng.High - rng.Low + 1); rng.High - rng.Low + 1);
for (int i = rng.Low; i <= rng.High; i += wordWidth) { for (int i = rng.Low; i <= rng.High; i += wordWidth) {
int val = RawData.GetWord(mFileData, rng.Low, wordWidth, isBigEndian); int val = RawData.GetWord(mFileData, i, wordWidth, isBigEndian);
if (val < 0x20 || (val >= 0x7f && val < 0xa0) || val >= 0xff) { if (val != (byte)val || !charTest((byte)val)) {
// bad value, fail // bad value, fail
return false; return false;
} }
@ -485,11 +616,22 @@ namespace SourceGen.WpfGui {
radioSimpleDataHex.IsChecked = true; radioSimpleDataHex.IsChecked = true;
radioSymbolPartLow.IsChecked = true; radioSymbolPartLow.IsChecked = true;
// Get the previous mode selected in the combo box. If the format descriptor
// doesn't specify a string, we'll use this.
TextScanMode textMode = (TextScanMode)AppSettings.Global.GetEnum(
AppSettings.OPED_DEFAULT_STRING_ENCODING, typeof(TextScanMode),
(int)TextScanMode.LowHighAscii);
if (dfd == null) { if (dfd == null) {
radioDefaultFormat.IsChecked = true; radioDefaultFormat.IsChecked = true;
SetStringEncoding(textMode);
return; return;
} }
if (dfd.IsString) {
textMode = TextScanModeFromDescriptor(dfd);
}
RadioButton preferredFormat; RadioButton preferredFormat;
switch (dfd.FormatType) { switch (dfd.FormatType) {
@ -529,11 +671,14 @@ namespace SourceGen.WpfGui {
break; break;
case FormatDescriptor.SubType.Ascii: case FormatDescriptor.SubType.Ascii:
case FormatDescriptor.SubType.HighAscii: case FormatDescriptor.SubType.HighAscii:
case FormatDescriptor.SubType.C64Petscii:
case FormatDescriptor.SubType.C64Screen:
// TODO(petscii): update UI
radioSimpleDataAscii.IsChecked = true; radioSimpleDataAscii.IsChecked = true;
break; break;
case FormatDescriptor.SubType.C64Petscii:
radioSimpleDataPetscii.IsChecked = true;
break;
case FormatDescriptor.SubType.C64Screen:
radioSimpleDataScreenCode.IsChecked = true;
break;
case FormatDescriptor.SubType.Address: case FormatDescriptor.SubType.Address:
radioSimpleDataAddress.IsChecked = true; radioSimpleDataAddress.IsChecked = true;
break; break;
@ -601,6 +746,24 @@ namespace SourceGen.WpfGui {
mPreferredFormatUnavailable = true; mPreferredFormatUnavailable = true;
radioDefaultFormat.IsChecked = true; radioDefaultFormat.IsChecked = true;
} }
SetStringEncoding(textMode);
}
private TextScanMode TextScanModeFromDescriptor(FormatDescriptor dfd) {
Debug.Assert(dfd.IsString);
switch (dfd.FormatSubType) {
case FormatDescriptor.SubType.Ascii:
case FormatDescriptor.SubType.HighAscii:
return TextScanMode.LowHighAscii;
case FormatDescriptor.SubType.C64Petscii:
return TextScanMode.C64Petscii;
case FormatDescriptor.SubType.C64Screen:
return TextScanMode.C64ScreenCode;
default:
Debug.Assert(false);
return TextScanMode.LowHighAscii;
}
} }
#endregion Setup #endregion Setup
@ -623,6 +786,33 @@ namespace SourceGen.WpfGui {
WeakSymbolRef symbolRef = null; WeakSymbolRef symbolRef = null;
int chunkLength = -1; int chunkLength = -1;
FormatDescriptor.SubType charSubType;
CharEncoding.InclusionTest charTest;
StringEncodingItem item = (StringEncodingItem)stringEncodingComboBox.SelectedItem;
switch (item.Mode) {
case TextScanMode.LowAscii:
charSubType = FormatDescriptor.SubType.Ascii;
charTest = CharEncoding.IsExtendedAscii;
break;
case TextScanMode.LowHighAscii:
charSubType = FormatDescriptor.SubType.ASCII_GENERIC;
charTest = CharEncoding.IsExtendedLowOrHighAscii;
break;
case TextScanMode.C64Petscii:
charSubType = FormatDescriptor.SubType.C64Petscii;
charTest = CharEncoding.IsExtendedC64Petscii;
break;
case TextScanMode.C64ScreenCode:
charSubType = FormatDescriptor.SubType.C64Screen;
charTest = CharEncoding.IsExtendedC64ScreenCode;
break;
default:
Debug.Assert(false);
charSubType = FormatDescriptor.SubType.ASCII_GENERIC;
charTest = CharEncoding.IsExtendedLowOrHighAscii;
break;
}
// Decode the "display as" panel, if it's relevant. // Decode the "display as" panel, if it's relevant.
if (radioSimpleDataHex.IsEnabled) { if (radioSimpleDataHex.IsEnabled) {
if (radioSimpleDataHex.IsChecked == true) { if (radioSimpleDataHex.IsChecked == true) {
@ -632,8 +822,11 @@ 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): add PETSCII buttons
subType = FormatDescriptor.SubType.ASCII_GENERIC; subType = FormatDescriptor.SubType.ASCII_GENERIC;
} else if (radioSimpleDataPetscii.IsChecked == true) {
subType = FormatDescriptor.SubType.C64Petscii;
} else if (radioSimpleDataScreenCode.IsChecked == true) {
subType = FormatDescriptor.SubType.C64Screen;
} else if (radioSimpleDataAddress.IsChecked == true) { } else if (radioSimpleDataAddress.IsChecked == true) {
subType = FormatDescriptor.SubType.Address; subType = FormatDescriptor.SubType.Address;
} else if (radioSimpleDataSymbolic.IsChecked == true) { } else if (radioSimpleDataSymbolic.IsChecked == true) {
@ -683,26 +876,23 @@ namespace SourceGen.WpfGui {
} else if (radioFill.IsChecked == true) { } else if (radioFill.IsChecked == true) {
type = FormatDescriptor.Type.Fill; type = FormatDescriptor.Type.Fill;
} else if (radioStringMixed.IsChecked == true) { } else if (radioStringMixed.IsChecked == true) {
// TODO(petscii): encoding format will come from a combo box; that determines
// the subType and the arg to the string-creation functions, which use the
// appropriate char encoding methods to break up the strings
type = FormatDescriptor.Type.StringGeneric; type = FormatDescriptor.Type.StringGeneric;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else if (radioStringMixedReverse.IsChecked == true) { } else if (radioStringMixedReverse.IsChecked == true) {
type = FormatDescriptor.Type.StringReverse; type = FormatDescriptor.Type.StringReverse;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else if (radioStringNullTerm.IsChecked == true) { } else if (radioStringNullTerm.IsChecked == true) {
type = FormatDescriptor.Type.StringNullTerm; type = FormatDescriptor.Type.StringNullTerm;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else if (radioStringLen8.IsChecked == true) { } else if (radioStringLen8.IsChecked == true) {
type = FormatDescriptor.Type.StringL8; type = FormatDescriptor.Type.StringL8;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else if (radioStringLen16.IsChecked == true) { } else if (radioStringLen16.IsChecked == true) {
type = FormatDescriptor.Type.StringL16; type = FormatDescriptor.Type.StringL16;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else if (radioStringDci.IsChecked == true) { } else if (radioStringDci.IsChecked == true) {
type = FormatDescriptor.Type.StringDci; type = FormatDescriptor.Type.StringDci;
subType = FormatDescriptor.SubType.Ascii; subType = charSubType;
} else { } else {
Debug.Assert(false); Debug.Assert(false);
// default/none // default/none
@ -715,11 +905,12 @@ namespace SourceGen.WpfGui {
while (iter.MoveNext()) { while (iter.MoveNext()) {
TypedRangeSet.TypedRange rng = iter.Current; TypedRangeSet.TypedRange rng = iter.Current;
// TODO(petscii): handle encoding on all four calls
switch (type) { switch (type) {
case FormatDescriptor.Type.StringGeneric: case FormatDescriptor.Type.StringGeneric:
CreateMixedStringEntries(rng.Low, rng.High, type, subType, charTest);
break;
case FormatDescriptor.Type.StringReverse: case FormatDescriptor.Type.StringReverse:
CreateMixedStringEntries(rng.Low, rng.High, type, subType); CreateMixedStringEntries(rng.Low, rng.High, type, subType, charTest);
break; break;
case FormatDescriptor.Type.StringNullTerm: case FormatDescriptor.Type.StringNullTerm:
CreateCStringEntries(rng.Low, rng.High, type, subType); CreateCStringEntries(rng.Low, rng.High, type, subType);
@ -794,69 +985,118 @@ namespace SourceGen.WpfGui {
/// <summary> /// <summary>
/// Creates one or more FormatDescriptor entries for the specified range, adding them /// Creates one or more FormatDescriptor entries for the specified range, adding them
/// to the Results list. /// to the Results list. Runs of character data are output as generic strings, while any
/// non-character data is output as individual bytes.
/// </summary> /// </summary>
/// <remarks>
/// This is the only string create function that accepts a mix of valid and invalid
/// characters.
/// </remarks>
/// <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="type">String type (Generic or Reverse).</param>
/// <param name="subType">String sub-type.</param> /// <param name="subType">String sub-type.</param>
/// <param name="charTest">Character test delegate.</param>
private void CreateMixedStringEntries(int low, int high, FormatDescriptor.Type type, private void CreateMixedStringEntries(int low, int high, FormatDescriptor.Type type,
FormatDescriptor.SubType subType) { FormatDescriptor.SubType subType, CharEncoding.InclusionTest charTest) {
int stringStart = -1; int stringStart = -1;
int highBit = 0;
int cur; int cur;
for (cur = low; cur <= high; cur++) {
byte val = mFileData[cur]; if (subType == FormatDescriptor.SubType.ASCII_GENERIC) {
if (CommonUtil.TextUtil.IsHiLoAscii(val)) { int highBit = 0;
// is ASCII for (cur = low; cur <= high; cur++) {
if (stringStart >= 0) { byte val = mFileData[cur];
// was in a string if (charTest(val)) {
if (highBit != (val & 0x80)) { // is ASCII
// end of string due to high bit flip, output if (stringStart >= 0) {
CreateStringOrByte(stringStart, cur - stringStart, subType); // was in a string
// start a new string if (highBit != (val & 0x80)) {
stringStart = cur; // end of string due to high bit flip, output
CreateGenericStringOrByte(stringStart, cur - stringStart,
type, subType);
// start a new string
stringStart = cur;
} else {
// still in string, keep going
}
} else { } else {
// still in string, keep going // wasn't in a string, start one
stringStart = cur;
}
highBit = val & 0x80;
} else {
// not ASCII
if (stringStart >= 0) {
// was in a string, output it
CreateGenericStringOrByte(stringStart, cur - stringStart,
type, subType);
stringStart = -1;
}
// output as single byte
CreateByteFD(cur, FormatDescriptor.SubType.Hex);
}
}
} else {
for (cur = low; cur <= high; cur++) {
byte val = mFileData[cur];
if (charTest(val)) {
// is character
if (stringStart < 0) {
// mark this as the start of the string
stringStart = cur;
} }
} else { } else {
// wasn't in a string, start one // not character
stringStart = cur; if (stringStart >= 0) {
// was in a string, output it
CreateGenericStringOrByte(stringStart, cur - stringStart,
type, subType);
stringStart = -1;
}
// output as single byte
CreateByteFD(cur, FormatDescriptor.SubType.Hex);
} }
highBit = val & 0x80;
} else {
// not ASCII
if (stringStart >= 0) {
// was in a string, output it
CreateStringOrByte(stringStart, cur - stringStart, subType);
stringStart = -1;
}
// output as single byte
CreateByteFD(cur, FormatDescriptor.SubType.Hex);
} }
} }
if (stringStart >= 0) { if (stringStart >= 0) {
// close out the string // close out the string
CreateStringOrByte(stringStart, cur - stringStart, subType); CreateGenericStringOrByte(stringStart, cur - stringStart, type, subType);
} }
} }
private FormatDescriptor.SubType ResolveAsciiGeneric(int offset,
FormatDescriptor.SubType subType) {
if (subType == FormatDescriptor.SubType.ASCII_GENERIC) {
if ((mFileData[offset] & 0x80) != 0) {
subType = FormatDescriptor.SubType.HighAscii;
} else {
subType = FormatDescriptor.SubType.Ascii;
}
}
return subType;
}
/// <summary> /// <summary>
/// Creates a format descriptor for ASCII data. If the data is only one byte long, /// Creates a format descriptor for character data. If the data is only one byte long,
/// a single-byte ASCII char item is emitted instead. /// a single-byte character item is emitted instead.
/// </summary> /// </summary>
/// <param name="offset">Offset of first byte.</param> /// <param name="offset">Offset of first byte.</param>
/// <param name="length">Length of string.</param> /// <param name="length">Length of string.</param>
/// <param name="subType">String sub-type.</param> /// <param name="type">String type (Generic or Reverse).</param>
private void CreateStringOrByte(int offset, int length, FormatDescriptor.SubType subType) { /// <param name="subType">String sub-type. If set to ASCII_GENERIC, this will
/// refine the sub-type.</param>
private void CreateGenericStringOrByte(int offset, int length,
FormatDescriptor.Type type, FormatDescriptor.SubType subType) {
Debug.Assert(length > 0); Debug.Assert(length > 0);
subType = ResolveAsciiGeneric(offset, subType);
if (length == 1) { if (length == 1) {
// Single byte, output as single char rather than 1-byte string. We use the // Single byte, output as single char rather than 1-byte string. We use the
// same encoding as the rest of the string. // same encoding as the rest of the string.
CreateByteFD(offset, subType); CreateByteFD(offset, subType);
} else { } else {
FormatDescriptor dfd; FormatDescriptor dfd;
dfd = FormatDescriptor.Create(length, dfd = FormatDescriptor.Create(length, type, subType);
FormatDescriptor.Type.StringGeneric, subType);
Results.Add(offset, dfd); Results.Add(offset, dfd);
} }
} }
@ -886,7 +1126,7 @@ namespace SourceGen.WpfGui {
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, type, subType); i - startOffset + 1, type, ResolveAsciiGeneric(startOffset, subType));
Results.Add(startOffset, dfd); Results.Add(startOffset, dfd);
startOffset = i + 1; startOffset = i + 1;
} else { } else {
@ -917,7 +1157,8 @@ namespace SourceGen.WpfGui {
length++; length++;
} }
// Zero-length strings are allowed. // Zero-length strings are allowed.
FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType); FormatDescriptor dfd = FormatDescriptor.Create(length, type,
ResolveAsciiGeneric(i, subType));
Results.Add(i, dfd); Results.Add(i, dfd);
i += length; i += length;
} }
@ -948,8 +1189,9 @@ namespace SourceGen.WpfGui {
if ((val & 0x80) == endMask) { if ((val & 0x80) == endMask) {
// found the end of a string // found the end of a string
int length = (i - stringStart) + 1; int length = (i - stringStart) + 1;
FormatDescriptor dfd = FormatDescriptor.Create(length, type, subType); FormatDescriptor dfd = FormatDescriptor.Create(length, type,
Results.Add(stringStart < i ? stringStart : i, dfd); ResolveAsciiGeneric(stringStart, subType));
Results.Add(stringStart, dfd);
stringStart = i + 1; stringStart = i + 1;
} }
} }

View File

@ -36,7 +36,11 @@ limitations under the License.
Checked="MainGroup_CheckedChanged"/> Checked="MainGroup_CheckedChanged"/>
<RadioButton Name="binaryButton" GroupName="Format" Content="Binary" Margin="0,2,0,0" <RadioButton Name="binaryButton" GroupName="Format" Content="Binary" Margin="0,2,0,0"
Checked="MainGroup_CheckedChanged"/> Checked="MainGroup_CheckedChanged"/>
<RadioButton Name="asciiButton" GroupName="Format" Content="ASCII character" Margin="0,2,0,0" <RadioButton Name="asciiButton" GroupName="Format" Content="ASCII (low or high) character" Margin="0,2,0,0"
Checked="MainGroup_CheckedChanged"/>
<RadioButton Name="petsciiButton" GroupName="Format" Content="C64 PETSCII character" Margin="0,2,0,0"
Checked="MainGroup_CheckedChanged"/>
<RadioButton Name="screenCodeButton" GroupName="Format" Content="C64 Screen character" Margin="0,2,0,0"
Checked="MainGroup_CheckedChanged"/> Checked="MainGroup_CheckedChanged"/>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>

View File

@ -171,8 +171,19 @@ namespace SourceGen.WpfGui {
private void Window_Loaded(object sender, RoutedEventArgs e) { private void Window_Loaded(object sender, RoutedEventArgs e) {
mIsInitialSetup = true; mIsInitialSetup = true;
// Can this be represented as high or low ASCII? // Can this be represented as a character? We only allow the printable set
asciiButton.IsEnabled = CommonUtil.TextUtil.IsHiLoAscii(mOperandValue); // here, not the extended set (which includes control characters).
if (mOperandValue == (byte) mOperandValue) {
asciiButton.IsEnabled =
CharEncoding.IsPrintableLowOrHighAscii((byte)mOperandValue);
petsciiButton.IsEnabled =
CharEncoding.IsPrintableC64Petscii((byte)mOperandValue);
screenCodeButton.IsEnabled =
CharEncoding.IsPrintableC64ScreenCode((byte)mOperandValue);
} else {
asciiButton.IsEnabled = petsciiButton.IsEnabled = screenCodeButton.IsEnabled =
false;
}
// Configure the dialog from the FormatDescriptor, if one is available. // Configure the dialog from the FormatDescriptor, if one is available.
SetControlsFromDescriptor(FormatDescriptor); SetControlsFromDescriptor(FormatDescriptor);
@ -475,9 +486,14 @@ namespace SourceGen.WpfGui {
break; break;
case FormatDescriptor.SubType.Ascii: case FormatDescriptor.SubType.Ascii:
case FormatDescriptor.SubType.HighAscii: case FormatDescriptor.SubType.HighAscii:
// TODO(petscii): encoding
asciiButton.IsChecked = true; asciiButton.IsChecked = true;
break; break;
case FormatDescriptor.SubType.C64Petscii:
petsciiButton.IsChecked = true;
break;
case FormatDescriptor.SubType.C64Screen:
screenCodeButton.IsChecked = true;
break;
case FormatDescriptor.SubType.Symbol: case FormatDescriptor.SubType.Symbol:
Debug.Assert(dfd.HasSymbol); Debug.Assert(dfd.HasSymbol);
symbolButton.IsChecked = true; symbolButton.IsChecked = true;
@ -555,12 +571,15 @@ 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
if (mOperandValue > 0x7f) { if (mOperandValue > 0x7f) {
subType = FormatDescriptor.SubType.HighAscii; subType = FormatDescriptor.SubType.HighAscii;
} else { } else {
subType = FormatDescriptor.SubType.Ascii; subType = FormatDescriptor.SubType.Ascii;
} }
} else if (petsciiButton.IsChecked == true) {
subType = FormatDescriptor.SubType.C64Petscii;
} else if (screenCodeButton.IsChecked == true) {
subType = FormatDescriptor.SubType.C64Screen;
} else if (symbolButton.IsChecked == true) { } else if (symbolButton.IsChecked == true) {
subType = FormatDescriptor.SubType.Symbol; subType = FormatDescriptor.SubType.Symbol;
} else { } else {

View File

@ -38,11 +38,6 @@ limitations under the License.
<system:String x:Key="str_65C02">WDC W65C02S</system:String> <system:String x:Key="str_65C02">WDC W65C02S</system:String>
<system:String x:Key="str_65816">WDC W65C816S</system:String> <system:String x:Key="str_65816">WDC W65C816S</system:String>
<system:String x:Key="str_LowAscii">Plain ASCII</system:String>
<system:String x:Key="str_LowHighAscii">Plain or High ASCII</system:String>
<system:String x:Key="str_C64Petscii">C64 PETSCII</system:String>
<system:String x:Key="str_C64ScreenCode">C64 Screen Code</system:String>
<system:String x:Key="str_DisableStringScan">None (disabled)</system:String> <system:String x:Key="str_DisableStringScan">None (disabled)</system:String>
<system:String x:Key="str_AutoLabelSimple">Simple ("L1234")</system:String> <system:String x:Key="str_AutoLabelSimple">Simple ("L1234")</system:String>

View File

@ -97,13 +97,13 @@ namespace SourceGen.WpfGui {
new CpuItem((string)FindResource("str_65816"), CpuDef.CpuType.Cpu65816), new CpuItem((string)FindResource("str_65816"), CpuDef.CpuType.Cpu65816),
}; };
DefaultTextScanModeItems = new DefaultTextScanMode[] { DefaultTextScanModeItems = new DefaultTextScanMode[] {
new DefaultTextScanMode((string)FindResource("str_LowAscii"), new DefaultTextScanMode(Res.Strings.SCAN_LOW_ASCII,
TextScanMode.LowAscii), TextScanMode.LowAscii),
new DefaultTextScanMode((string)FindResource("str_LowHighAscii"), new DefaultTextScanMode(Res.Strings.SCAN_LOW_HIGH_ASCII,
TextScanMode.LowHighAscii), TextScanMode.LowHighAscii),
new DefaultTextScanMode((string)FindResource("str_C64Petscii"), new DefaultTextScanMode(Res.Strings.SCAN_C64_PETSCII,
TextScanMode.C64Petscii), TextScanMode.C64Petscii),
new DefaultTextScanMode((string)FindResource("str_C64ScreenCode"), new DefaultTextScanMode(Res.Strings.SCAN_C64_SCREEN_CODE,
TextScanMode.C64ScreenCode), TextScanMode.C64ScreenCode),
}; };
MinCharsItems = new MinCharsItem[] { MinCharsItems = new MinCharsItem[] {