From 071adb8e95fd38cc297eff0586979e51098322ce Mon Sep 17 00:00:00 2001
From: Andy McFadden 012345: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
diff --git a/SourceGen/AppSettings.cs b/SourceGen/AppSettings.cs
index 919bead..d747182 100644
--- a/SourceGen/AppSettings.cs
+++ b/SourceGen/AppSettings.cs
@@ -68,6 +68,7 @@ namespace SourceGen {
public const string FMT_STRING_DELIM = "fmt-string-delim";
public const string FMT_NON_UNIQUE_LABEL_PREFIX = "fmt-non-unique-label-prefix";
public const string FMT_LOCAL_VARIABLE_PREFIX = "fmt-local-variable-prefix";
+ public const string FMT_COMMA_SEP_BULK_DATA = "fmt-comma-sep-bulk-data";
public const string CLIP_LINE_FORMAT = "clip-line-format";
@@ -101,6 +102,7 @@ namespace SourceGen {
// Operand edit settings.
public const string OPED_DEFAULT_STRING_ENCODING = "oped-default-string-encoding";
+ public const string OPED_DENSE_HEX_LIMIT = "oped-dense-hex-limit";
// Hex dump viewer settings.
public const string HEXD_ASCII_ONLY = "hexd-ascii-only";
diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs
index 4ae85fe..9eefc9e 100644
--- a/SourceGen/AsmGen/AsmAcme.cs
+++ b/SourceGen/AsmGen/AsmAcme.cs
@@ -195,6 +195,7 @@ namespace SourceGen.AsmGen {
config.mFullLineCommentDelimiterBase = ";";
config.mBoxLineCommentDelimiter = ";";
config.mNonUniqueLabelPrefix = "@";
+ config.mCommaSeparatedDense = false;
config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Common;
Formatter.DelimiterSet charSet = new Formatter.DelimiterSet();
@@ -453,7 +454,7 @@ namespace SourceGen.AsmGen {
private void OutputDenseHex(int offset, int length, string labelStr, string commentStr) {
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
- int maxPerLine = MAX_OPERAND_LEN / 2;
+ int maxPerLine = MAX_OPERAND_LEN / formatter.CharsPerDenseByte;
string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense);
for (int i = 0; i < length; i += maxPerLine) {
diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs
index 9b2f5ee..fc6a715 100644
--- a/SourceGen/AsmGen/AsmCc65.cs
+++ b/SourceGen/AsmGen/AsmCc65.cs
@@ -114,7 +114,7 @@ namespace SourceGen.AsmGen {
//DefineBigData3
//DefineBigData4
{ "Fill", ".res" },
- //Dense // no equivalent, use .byte with comma-separated args
+ { "Dense", ".byte" }, // not really dense, just comma-separated bytes
//Junk
{ "StrGeneric", ".byte" },
//StrReverse
@@ -190,6 +190,7 @@ namespace SourceGen.AsmGen {
config.mFullLineCommentDelimiterBase = ";";
config.mBoxLineCommentDelimiter = ";";
config.mNonUniqueLabelPrefix = "@";
+ config.mCommaSeparatedDense = true;
config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Cc65;
Formatter.DelimiterSet charSet = new Formatter.DelimiterSet();
@@ -484,26 +485,37 @@ namespace SourceGen.AsmGen {
private void OutputDenseHex(int offset, int length, string labelStr, string commentStr) {
Formatter formatter = SourceFormatter;
byte[] data = Project.FileData;
- StringBuilder sb = new StringBuilder(MAX_OPERAND_LEN);
+ int maxPerLine = MAX_OPERAND_LEN / formatter.CharsPerDenseByte;
- string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.DefineData1);
-
- int maxPerLine = MAX_OPERAND_LEN / 4;
- int numChunks = (length + maxPerLine - 1) / maxPerLine;
- for (int chunk = 0; chunk < numChunks; chunk++) {
- int chunkStart = chunk * maxPerLine;
- int chunkEnd = Math.Min((chunk + 1) * maxPerLine, length);
- for (int i = chunkStart; i < chunkEnd; i++) {
- if (i != chunkStart) {
- sb.Append(',');
- }
- sb.Append(formatter.FormatHexValue(data[offset + i], 2));
+ string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense);
+ for (int i = 0; i < length; i += maxPerLine) {
+ int subLen = length - i;
+ if (subLen > maxPerLine) {
+ subLen = maxPerLine;
}
+ string operandStr = formatter.FormatDenseHex(data, offset + i, subLen);
- OutputLine(labelStr, opcodeStr, sb.ToString(), commentStr);
+ OutputLine(labelStr, opcodeStr, operandStr, commentStr);
labelStr = commentStr = string.Empty;
- sb.Clear();
}
+
+ //StringBuilder sb = new StringBuilder(MAX_OPERAND_LEN);
+ //int maxPerLine = MAX_OPERAND_LEN / 4;
+ //int numChunks = (length + maxPerLine - 1) / maxPerLine;
+ //for (int chunk = 0; chunk < numChunks; chunk++) {
+ // int chunkStart = chunk * maxPerLine;
+ // int chunkEnd = Math.Min((chunk + 1) * maxPerLine, length);
+ // for (int i = chunkStart; i < chunkEnd; i++) {
+ // if (i != chunkStart) {
+ // sb.Append(',');
+ // }
+ // sb.Append(formatter.FormatHexValue(data[offset + i], 2));
+ // }
+
+ // OutputLine(labelStr, opcodeStr, sb.ToString(), commentStr);
+ // labelStr = commentStr = string.Empty;
+ // sb.Clear();
+ //}
}
///
If the range is discontiguous, or crosses a visual boundary -such as a change in address, a user-specified label, or a long comment -or note, the selection will be split into smaller regions. A message at the +
If the range is discontiguous, crosses a logical boundary +such as a change in address or a user-specified label, or crosses a +visual boundary like a long comment, note, or visualization, the selection +will be split into smaller regions. A message at the top of the dialog indicates how many bytes have been selected, and how many regions they have been divided into.
(End-of-line comments do not split a region, and will @@ -213,9 +214,10 @@ it requires that each individual string be entirely one or the other.
Due to fundamental limitations of the character set, C64 screen code strings cannot be null terminated ($00 is '@').
-To avoid burying a label in the middle of a data item, contiguous areas -are split at labels. This can sometimes have unexpected effects. For -example, this can be formatted as two 16-bit words or one 32-bit word:
+As noted earlier, to avoid burying elements such as labels in the middle +of a data item, contiguous areas may be split into smaller regions. This +can sometimes have unexpected effects. For example, this can be formatted +as two 16-bit words or one 32-bit word:
.DD1 $01 .DD1 $ef @@ -223,7 +225,7 @@ example, this can be formatted as two 16-bit words or one 32-bit word: .DD1 $f0-
With a label in the middle, it be formatted as two 16-bit words, but +
With a label in the middle, it can be formatted as two 16-bit words, but not as a 32-bit word:
.DD1 $01 @@ -233,7 +235,7 @@ LABEL .DD1 $01 CODE LDA LABEL-
If this is inconvenient, you can add a label at a 32-bit boundary, and +
If this is undesirable, you can add a label at a 32-bit boundary, and reference that instead:
LABEL .DD1 $01 diff --git a/SourceGen/WpfGui/EditAppSettings.xaml b/SourceGen/WpfGui/EditAppSettings.xaml index 89cbd1c..ba3fa58 100644 --- a/SourceGen/WpfGui/EditAppSettings.xaml +++ b/SourceGen/WpfGui/EditAppSettings.xaml @@ -584,6 +584,10 @@ limitations under the License. FontFamily="{StaticResource GeneralMonoFont}"/> ++ + Checked="MainGroup_CheckedChanged"/> + + + + + - - - + + diff --git a/SourceGen/WpfGui/EditDataOperand.xaml.cs b/SourceGen/WpfGui/EditDataOperand.xaml.cs index 30ab354..c633052 100644 --- a/SourceGen/WpfGui/EditDataOperand.xaml.cs +++ b/SourceGen/WpfGui/EditDataOperand.xaml.cs @@ -37,18 +37,6 @@ namespace SourceGen.WpfGui { /// public SortedList+ Results { get; private set; } - /// - /// Set to true when input is valid. Controls whether the OK button is enabled. - /// - public bool IsValid { - get { return mIsValid; } - set { - mIsValid = value; - OnPropertyChanged(); - } - } - private bool mIsValid; - ////// Selected offsets. An otherwise contiguous range of offsets can be broken up /// by user-specified labels and address discontinuities, so this needs to be @@ -95,6 +83,35 @@ namespace SourceGen.WpfGui { /// private bool mPreferredFormatUnavailable; + ///+ /// Set to true when input is valid. Controls whether the OK button is enabled. + /// + public bool IsValid { + get { return mIsValid; } + set { + mIsValid = value; + OnPropertyChanged(); + } + } + private bool mIsValid; + + public int MaxDenseBytesPerLine { + get { return mMaxDenseBytesPerLine; } + set { + if (mMaxDenseBytesPerLine != value) { + mMaxDenseBytesPerLine = value; + OnPropertyChanged(); + UpdateControls(); + + if (IsLoaded) { + // Set the radio button when text is typed. + radioDenseHexLimited.IsChecked = true; + } + } + } + } + private int mMaxDenseBytesPerLine; + ////// Text encoding combo box item. We use the same TextScanMode enum that the /// uncategorized data analyzer uses. @@ -142,6 +159,8 @@ namespace SourceGen.WpfGui { mSelection = trs; mFirstFormatDescriptor = firstDesc; + MaxDenseBytesPerLine = AppSettings.Global.GetInt(AppSettings.OPED_DENSE_HEX_LIMIT, 8); + StringEncodingItems = new StringEncodingItem[] { new StringEncodingItem(Res.Strings.SCAN_LOW_ASCII, TextScanMode.LowAscii), @@ -362,13 +381,23 @@ namespace SourceGen.WpfGui { } } IsValid = isOk; + + // If dense hex with a limit is selected, check the value. + if (radioDenseHexLimited.IsChecked == true) { + if (MaxDenseBytesPerLine > 0) { + AppSettings.Global.SetInt(AppSettings.OPED_DENSE_HEX_LIMIT, + MaxDenseBytesPerLine); + } else { + IsValid = false; + } + } } #region Setup /// /// Determines the minimum and maximum alignment values, based on the sizes of the - /// regions and the address they end on. + /// regions and the address they end on. Used for .align. /// /// Minimum allowed format, or None. /// Maximum allowed format, or None. @@ -918,7 +947,6 @@ namespace SourceGen.WpfGui { FormatDescriptor.Type type = FormatDescriptor.Type.Default; FormatDescriptor.SubType subType = FormatDescriptor.SubType.None; WeakSymbolRef symbolRef = null; - int chunkLength = -1; FormatDescriptor.SubType charSubType; CharEncoding.InclusionTest charTest; @@ -1013,6 +1041,7 @@ namespace SourceGen.WpfGui { } // Decode the main format. + int chunkLength = -1; if (radioDefaultFormat.IsChecked == true) { // Default/None; note this would create a multi-byte Default format, which isn't // really allowed. What we actually want to do is remove the explicit formatting @@ -1033,7 +1062,7 @@ namespace SourceGen.WpfGui { } else if (radio32BitLittle.IsChecked == true) { type = FormatDescriptor.Type.NumericLE; chunkLength = 4; - } else if (radioDenseHex.IsChecked == true) { + } else if (radioDenseHex.IsChecked == true || radioDenseHexLimited.IsChecked == true) { type = FormatDescriptor.Type.Dense; } else if (radioFill.IsChecked == true) { type = FormatDescriptor.Type.Fill; @@ -1088,6 +1117,21 @@ namespace SourceGen.WpfGui { case FormatDescriptor.Type.StringDci: CreateDciStringEntries(rng.Low, rng.High, type, subType); break; + case FormatDescriptor.Type.Dense: + if (radioDenseHexLimited.IsChecked == true) { + int low = rng.Low; + while (low <= rng.High) { + int remaining = rng.High - low + 1; + int subLen = Math.Min(remaining, MaxDenseBytesPerLine); + CreateSimpleEntries(type, subType, -1, null, low, low + subLen - 1); + low += subLen; + chunkLength -= subLen; + } + } else { + CreateSimpleEntries(type, subType, chunkLength, null, + rng.Low, rng.High); + } + break; default: CreateSimpleEntries(type, subType, chunkLength, symbolRef, rng.Low, rng.High); diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml index 313fc9e..b70e0b9 100644 --- a/SourceGen/WpfGui/MainWindow.xaml +++ b/SourceGen/WpfGui/MainWindow.xaml @@ -24,7 +24,7 @@ limitations under the License. mc:Ignorable="d" Title="6502bench SourceGen" Icon="/SourceGen;component/Res/SourceGenIcon.ico" - Width="1200" Height="700" MinWidth="800" MinHeight="500" + Width="1200" Height="700" MinWidth="800" MinHeight="500" ResizeMode="CanResizeWithGrip" SourceInitialized="Window_SourceInitialized" Loaded="Window_Loaded" LocationChanged="Window_LocationChanged" @@ -465,7 +465,7 @@ limitations under the License.-