mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-01 07:50:37 +00:00
Two changes to "dense hex" bulk data formatting
(1) Added an option to limit the number of bytes per line. This is handy for things like bitmaps, where you might want to put (say) 3 or 8 bytes per line to reflect the structure. (2) Added an application setting that determines whether the screen listing shows Merlin/ACME dense hex (20edfd) or 64tass/cc65 hex bytes ($20,$ed,$fd). Made the setting part of the assembler-driven display definitions. Updated 64tass+cc65 to use ".byte" as their dense hex pseudo-op, and to use the updated formatter code. No changes to regression test output. (Changes were requested in issue #42.) Also, added a resize gripper to the bottom-right corner of the main window. (These seem to have generally fallen out of favor, but I like having it there.)
This commit is contained in:
parent
13f7ae4b70
commit
071adb8e95
@ -82,6 +82,7 @@ namespace Asm65 {
|
||||
|
||||
// miscellaneous
|
||||
public bool mSpacesBetweenBytes; // "20edfd" vs. "20 ed fd"
|
||||
public bool mCommaSeparatedDense; // "20edfd" vs. "$20,$ed,$fd"
|
||||
|
||||
// hex dumps
|
||||
public bool mHexDumpAsciiOnly; // disallow non-ASCII chars in hex dumps?
|
||||
@ -935,15 +936,47 @@ namespace Asm65 {
|
||||
/// <returns>Formatted data string.</returns>
|
||||
public string FormatDenseHex(byte[] data, int offset, int length) {
|
||||
char[] hexChars = mFormatConfig.mUpperHexDigits ? sHexCharsUpper : sHexCharsLower;
|
||||
char[] text = new char[length * 2];
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte val = data[offset + i];
|
||||
text[i * 2] = hexChars[val >> 4];
|
||||
text[i * 2 + 1] = hexChars[val & 0x0f];
|
||||
char[] text;
|
||||
if (mFormatConfig.mCommaSeparatedDense) {
|
||||
text = new char[length * 4 - 1];
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte val = data[offset + i];
|
||||
text[i * 4] = '$';
|
||||
text[i * 4 + 1] = hexChars[val >> 4];
|
||||
text[i * 4 + 2] = hexChars[val & 0x0f];
|
||||
if (i != length - 1) {
|
||||
text[i * 4 + 3] = ',';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = new char[length * 2];
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte val = data[offset + i];
|
||||
text[i * 2] = hexChars[val >> 4];
|
||||
text[i * 2 + 1] = hexChars[val & 0x0f];
|
||||
}
|
||||
}
|
||||
return new string(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of characters output for each byte when formatting dense hex.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This isn't quite right, because you don't need a comma after the very last element
|
||||
/// in the list for comma-separated values. Handling this correctly for multi-line
|
||||
/// items is more trouble than it's worth though.
|
||||
/// </remarks>
|
||||
public int CharsPerDenseByte {
|
||||
get {
|
||||
if (mFormatConfig.mCommaSeparatedDense) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats up to 16 bytes of data into a single line hex dump, in this format:
|
||||
/// <pre>012345: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef</pre>
|
||||
|
@ -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";
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -165,6 +165,7 @@ namespace SourceGen.AsmGen {
|
||||
config.mFullLineCommentDelimiterBase = ";";
|
||||
config.mBoxLineCommentDelimiter = string.Empty;
|
||||
config.mNonUniqueLabelPrefix = ":";
|
||||
config.mCommaSeparatedDense = false;
|
||||
config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Merlin;
|
||||
|
||||
Formatter.DelimiterSet charSet = new Formatter.DelimiterSet();
|
||||
@ -313,7 +314,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) {
|
||||
|
@ -131,7 +131,7 @@ namespace SourceGen.AsmGen {
|
||||
//DefineBigData3
|
||||
//DefineBigData4
|
||||
{ "Fill", ".fill" },
|
||||
//Dense // no equivalent, use .byte with comma-separated args
|
||||
{ "Dense", ".byte" }, // not really dense, just comma-separated bytes
|
||||
//Junk
|
||||
{ "Align", ".align" },
|
||||
{ "StrGeneric", ".text" },
|
||||
@ -199,6 +199,7 @@ namespace SourceGen.AsmGen {
|
||||
config.mFullLineCommentDelimiterBase = ";";
|
||||
config.mBoxLineCommentDelimiter = ";";
|
||||
config.mNonUniqueLabelPrefix = ""; // should be '_', but that's a valid label char
|
||||
config.mCommaSeparatedDense = true;
|
||||
config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Common;
|
||||
}
|
||||
|
||||
@ -520,25 +521,18 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,6 +471,8 @@ namespace SourceGen {
|
||||
settings.GetString(AppSettings.FMT_NON_UNIQUE_LABEL_PREFIX, string.Empty);
|
||||
mFormatterConfig.mLocalVariableLabelPrefix =
|
||||
settings.GetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, string.Empty);
|
||||
mFormatterConfig.mCommaSeparatedDense =
|
||||
settings.GetBool(AppSettings.FMT_COMMA_SEP_BULK_DATA, false);
|
||||
|
||||
string chrDelCereal = settings.GetString(AppSettings.FMT_CHAR_DELIM, null);
|
||||
if (chrDelCereal != null) {
|
||||
|
@ -276,7 +276,7 @@ namespace SourceGen {
|
||||
case FormatDescriptor.Type.Dense: {
|
||||
// no delimiter, two output bytes per input byte
|
||||
int maxLen = MAX_OPERAND_LEN;
|
||||
int textLen = dfd.Length * 2;
|
||||
int textLen = dfd.Length * formatter.CharsPerDenseByte;
|
||||
return (textLen + maxLen - 1) / maxLen;
|
||||
}
|
||||
default:
|
||||
@ -364,7 +364,7 @@ namespace SourceGen {
|
||||
}
|
||||
break;
|
||||
case FormatDescriptor.Type.Dense: {
|
||||
int maxPerLine = MAX_OPERAND_LEN / 2;
|
||||
int maxPerLine = MAX_OPERAND_LEN / formatter.CharsPerDenseByte;
|
||||
offset += subIndex * maxPerLine;
|
||||
length -= subIndex * maxPerLine;
|
||||
if (length > maxPerLine) {
|
||||
|
@ -161,9 +161,10 @@ select both bytes in the editor. (If you click on the first item, then
|
||||
Shift+double-click on the operand field of the last item, you can do
|
||||
this very quickly.) The selection does not need to be contiguous: you
|
||||
can use Control+click to select scattered items.</p>
|
||||
<p>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
|
||||
<p>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.</p>
|
||||
<p>(End-of-line comments do <i>not</i> split a region, and will
|
||||
@ -213,9 +214,10 @@ it requires that each individual string be entirely one or the other.</p>
|
||||
<p>Due to fundamental limitations of the character set, C64 screen code
|
||||
strings cannot be null terminated ($00 is '@').</p>
|
||||
|
||||
<p>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:</p>
|
||||
<p>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:</p>
|
||||
<pre>
|
||||
.DD1 $01
|
||||
.DD1 $ef
|
||||
@ -223,7 +225,7 @@ example, this can be formatted as two 16-bit words or one 32-bit word:</p>
|
||||
.DD1 $f0
|
||||
</pre>
|
||||
|
||||
<p>With a label in the middle, it be formatted as two 16-bit words, but
|
||||
<p>With a label in the middle, it can be formatted as two 16-bit words, but
|
||||
not as a 32-bit word:</p>
|
||||
<pre>
|
||||
.DD1 $01
|
||||
@ -233,7 +235,7 @@ LABEL .DD1 $01
|
||||
CODE LDA LABEL
|
||||
</pre>
|
||||
|
||||
<p>If this is inconvenient, you can add a label at a 32-bit boundary, and
|
||||
<p>If this is undesirable, you can add a label at a 32-bit boundary, and
|
||||
reference that instead:</p>
|
||||
<pre>
|
||||
LABEL .DD1 $01
|
||||
|
@ -584,6 +584,10 @@ limitations under the License.
|
||||
FontFamily="{StaticResource GeneralMonoFont}"/>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox DockPanel.Dock="Top" Margin="4,6,0,0"
|
||||
Content="Use comma-separated format for bulk data"
|
||||
IsChecked="{Binding CommaSeparatedBulkData}"/>
|
||||
|
||||
<GroupBox DockPanel.Dock="Bottom" Header="Quick Set"
|
||||
HorizontalAlignment="Right" Padding="2,4">
|
||||
<ComboBox Name="displayFmtQuickComboBox" DockPanel.Dock="Right"
|
||||
|
@ -889,6 +889,19 @@ namespace SourceGen.WpfGui {
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool mCommaSeparatedBulkData;
|
||||
public bool CommaSeparatedBulkData {
|
||||
get { return mCommaSeparatedBulkData; }
|
||||
set {
|
||||
if (mCommaSeparatedBulkData != value) {
|
||||
mCommaSeparatedBulkData = value;
|
||||
OnPropertyChanged();
|
||||
mSettings.SetBool(AppSettings.FMT_COMMA_SEP_BULK_DATA, value);
|
||||
UpdateDisplayFormatQuickCombo();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prevent recursion
|
||||
private bool mSettingDisplayFmtCombo;
|
||||
@ -935,11 +948,13 @@ namespace SourceGen.WpfGui {
|
||||
public string OperandPrefixLong { get; private set; }
|
||||
public string NonUniqueLabelPrefix { get; private set; }
|
||||
public string LocalVarPrefix { get; private set; }
|
||||
public bool CommaSeparatedBulkData { get; private set; }
|
||||
public ExpressionMode ExpressionStyle { get; private set; }
|
||||
|
||||
public DisplayFormatPreset(int id, string name, string opcSuffixAbs,
|
||||
string opcSuffixLong, string operPrefixAbs, string operPrefixLong,
|
||||
string nonUniqueLabelPrefix, string localVarPrefix, ExpressionMode expStyle) {
|
||||
string nonUniqueLabelPrefix, string localVarPrefix, bool commaSepBulkData,
|
||||
ExpressionMode expStyle) {
|
||||
Ident = id;
|
||||
Name = name;
|
||||
OpcodeSuffixAbs = opcSuffixAbs;
|
||||
@ -948,6 +963,7 @@ namespace SourceGen.WpfGui {
|
||||
OperandPrefixLong = operPrefixLong;
|
||||
NonUniqueLabelPrefix = nonUniqueLabelPrefix;
|
||||
LocalVarPrefix = localVarPrefix;
|
||||
CommaSeparatedBulkData = commaSepBulkData;
|
||||
ExpressionStyle = expStyle;
|
||||
}
|
||||
}
|
||||
@ -958,10 +974,11 @@ namespace SourceGen.WpfGui {
|
||||
DisplayPresets = new DisplayFormatPreset[AssemblerList.Count + 2];
|
||||
DisplayPresets[0] = new DisplayFormatPreset(DisplayFormatPreset.ID_CUSTOM,
|
||||
(string)FindResource("str_PresetCustom"), string.Empty, string.Empty,
|
||||
string.Empty, string.Empty, string.Empty, string.Empty, ExpressionMode.Unknown);
|
||||
string.Empty, string.Empty, string.Empty, string.Empty, false,
|
||||
ExpressionMode.Unknown);
|
||||
DisplayPresets[1] = new DisplayFormatPreset(DisplayFormatPreset.ID_DEFAULT,
|
||||
(string)FindResource("str_PresetDefault"), string.Empty, "l", "a:", "f:",
|
||||
string.Empty, string.Empty, ExpressionMode.Common);
|
||||
string.Empty, string.Empty, false, ExpressionMode.Common);
|
||||
for (int i = 0; i < AssemblerList.Count; i++) {
|
||||
AssemblerInfo asmInfo = AssemblerList[i];
|
||||
AsmGen.IGenerator gen = AssemblerInfo.GetGenerator(asmInfo.AssemblerId);
|
||||
@ -973,7 +990,8 @@ namespace SourceGen.WpfGui {
|
||||
asmInfo.Name, formatConfig.mForceAbsOpcodeSuffix,
|
||||
formatConfig.mForceLongOpcodeSuffix, formatConfig.mForceAbsOperandPrefix,
|
||||
formatConfig.mForceLongOperandPrefix, formatConfig.mNonUniqueLabelPrefix,
|
||||
formatConfig.mLocalVariableLabelPrefix, formatConfig.mExpressionMode);
|
||||
formatConfig.mLocalVariableLabelPrefix, formatConfig.mCommaSeparatedDense,
|
||||
formatConfig.mExpressionMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -996,6 +1014,8 @@ namespace SourceGen.WpfGui {
|
||||
mSettings.GetString(AppSettings.FMT_NON_UNIQUE_LABEL_PREFIX, string.Empty);
|
||||
LocalVarPrefix =
|
||||
mSettings.GetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, string.Empty);
|
||||
CommaSeparatedBulkData =
|
||||
mSettings.GetBool(AppSettings.FMT_COMMA_SEP_BULK_DATA, false);
|
||||
|
||||
string exprMode = mSettings.GetString(AppSettings.FMT_EXPRESSION_MODE, string.Empty);
|
||||
ExpressionMode mode;
|
||||
@ -1053,6 +1073,7 @@ namespace SourceGen.WpfGui {
|
||||
OperandPrefixLong = preset.OperandPrefixLong;
|
||||
NonUniqueLabelPrefix = preset.NonUniqueLabelPrefix;
|
||||
LocalVarPrefix = preset.LocalVarPrefix;
|
||||
CommaSeparatedBulkData = preset.CommaSeparatedBulkData;
|
||||
|
||||
SelectExpressionStyle(preset.ExpressionStyle);
|
||||
// dirty flag will be set by change watchers if one or more fields have changed
|
||||
@ -1078,6 +1099,7 @@ namespace SourceGen.WpfGui {
|
||||
OperandPrefixLong == preset.OperandPrefixLong &&
|
||||
NonUniqueLabelPrefix == preset.NonUniqueLabelPrefix &&
|
||||
LocalVarPrefix == preset.LocalVarPrefix &&
|
||||
CommaSeparatedBulkData == preset.CommaSeparatedBulkData &&
|
||||
expMode == preset.ExpressionStyle) {
|
||||
// match
|
||||
displayFmtQuickComboBox.SelectedIndex = i;
|
||||
|
@ -127,13 +127,20 @@ limitations under the License.
|
||||
<TextBlock Text="Bulk Data" Margin="0,12,0,0"/>
|
||||
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
|
||||
<RadioButton Name="radioDenseHex" GroupName="Main" Content="Densely-_packed bytes" Margin="0,4,0,0"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="20,4,0,0">
|
||||
<RadioButton Name="radioDenseHexLimited" GroupName="Main" Content="...with a limit of"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<TextBox Width="40" Margin="7,-3,0,0" MaxLength="2"
|
||||
Text="{Binding MaxDenseBytesPerLine, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<TextBlock Text="bytes per line" Margin="7,0,0,0"/>
|
||||
</StackPanel>
|
||||
<RadioButton Name="radioFill" GroupName="Main" Content="Area _filled with value" Margin="0,4,0,0"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<RadioButton Name="radioJunk" GroupName="Main" Content="_Junk bytes, end aligned to" Margin="0,4,0,0"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<ComboBox Name="junkAlignComboBox" Margin="8,-1,0,0" Width="200"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<RadioButton Name="radioJunk" GroupName="Main" Content="_Junk bytes, end aligned to"
|
||||
Checked="MainGroup_CheckedChanged"/>
|
||||
<ComboBox Name="junkAlignComboBox" Margin="8,-5,0,0" Width="200"
|
||||
ItemsSource="{Binding JunkAlignmentItems}" DisplayMemberPath="Description"/>
|
||||
</StackPanel>
|
||||
|
||||
|
@ -37,18 +37,6 @@ namespace SourceGen.WpfGui {
|
||||
/// </summary>
|
||||
public SortedList<int, FormatDescriptor> Results { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true when input is valid. Controls whether the OK button is enabled.
|
||||
/// </summary>
|
||||
public bool IsValid {
|
||||
get { return mIsValid; }
|
||||
set {
|
||||
mIsValid = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
private bool mIsValid;
|
||||
|
||||
/// <summary>
|
||||
/// 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 {
|
||||
/// </summary>
|
||||
private bool mPreferredFormatUnavailable;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true when input is valid. Controls whether the OK button is enabled.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="min">Minimum allowed format, or None.</param>
|
||||
/// <param name="max">Maximum allowed format, or None.</param>
|
||||
@ -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);
|
||||
|
@ -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.
|
||||
<TextBlock Grid.Column="0" Text="{Binding StatusBarText, FallbackValue=Ready}"/>
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Center"
|
||||
Text="{Binding ByteCountText, FallbackValue=30% code; 60% data; 10% junk}"/>
|
||||
<Button Grid.Column="2" Margin="4,0,6,0" Padding="4,0,4,0"
|
||||
<Button Grid.Column="2" Margin="4,0,20,0" Padding="4,0,4,0"
|
||||
Content="{Binding MessageStatusText, FallbackValue=3 messages (1 warning/error)}"
|
||||
Visibility="{Binding Path=CodeListVisibility}"
|
||||
Click="MessageStatusButton_Click"/>
|
||||
|
Loading…
Reference in New Issue
Block a user