diff --git a/Asm65/Formatter.cs b/Asm65/Formatter.cs index d676df2..6e28140 100644 --- a/Asm65/Formatter.cs +++ b/Asm65/Formatter.cs @@ -42,6 +42,10 @@ namespace Asm65 { /// fixed by keying off of the OpDef instead of OpDef.Opcode, but that's less convenient.) /// public class Formatter { + // Default wrap point for long operands. This potentially affects both on-screen + // display and source code generation. + private const int DEFAULT_OPERAND_WRAP_LEN = 64; + /// /// Various format configuration options. Fill one of these out and pass it to /// the Formatter constructor. @@ -80,6 +84,9 @@ namespace Asm65 { public DelimiterSet mCharDelimiters; public DelimiterSet mStringDelimiters; + // point at which we wrap long operands; zero uses default + public int mOperandWrapLen; + // miscellaneous public bool mSpacesBetweenBytes; // "20edfd" vs. "20 ed fd" public bool mCommaSeparatedDense; // "20edfd" vs. "$20,$ed,$fd" @@ -147,6 +154,10 @@ namespace Asm65 { if (mBoxLineCommentDelimiter == null) { mBoxLineCommentDelimiter = string.Empty; } + + if (mOperandWrapLen == 0) { + mOperandWrapLen = DEFAULT_OPERAND_WRAP_LEN; + } } } @@ -421,6 +432,13 @@ namespace Asm65 { get { return mFormatConfig.mExpressionMode; } } + /// + /// Point at which to wrap long operands, such as strings and dense hex. + /// + public int OperandWrapLen { + get { return mFormatConfig.mOperandWrapLen; } + } + /// /// Constructor. Initializes various fields based on the configuration. We want to diff --git a/Asm65/StringOpFormatter.cs b/Asm65/StringOpFormatter.cs index c32beae..36321c7 100644 --- a/Asm65/StringOpFormatter.cs +++ b/Asm65/StringOpFormatter.cs @@ -79,12 +79,11 @@ namespace Asm65 { /// Reference to text formatter. /// String delimiter values. /// How to format raw byte data. - /// Maximum line length. /// Character conversion delegate. public StringOpFormatter(Formatter formatter, Formatter.DelimiterDef delimiterDef, - RawOutputStyle byteStyle, int maxOperandLen, CharEncoding.Convert charConv) { + RawOutputStyle byteStyle, CharEncoding.Convert charConv) { mRawStyle = byteStyle; - mMaxOperandLen = maxOperandLen; + mMaxOperandLen = formatter.OperandWrapLen; CharConv = charConv; mDelimiterDef = delimiterDef; diff --git a/SourceGen/AppSettings.cs b/SourceGen/AppSettings.cs index 8ddbefc..f662b12 100644 --- a/SourceGen/AppSettings.cs +++ b/SourceGen/AppSettings.cs @@ -56,6 +56,7 @@ namespace SourceGen { public const string FMT_UPPER_OPERAND_XY = "fmt-upper-operand-xy"; public const string FMT_ADD_SPACE_FULL_COMMENT = "fmt-add-space-full-comment"; public const string FMT_SPACES_BETWEEN_BYTES = "fmt-spaces-between-bytes"; + public const string FMT_OPERAND_WRAP_LEN = "fmt-operand-wrap-len"; public const string FMT_OPCODE_SUFFIX_ABS = "fmt-opcode-suffix-abs"; public const string FMT_OPCODE_SUFFIX_LONG = "fmt-opcode-suffix-long"; diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs index 2248cbd..2224995 100644 --- a/SourceGen/AsmGen/AsmAcme.cs +++ b/SourceGen/AsmGen/AsmAcme.cs @@ -37,7 +37,6 @@ namespace SourceGen.AsmGen { // makefile rules. Since ".S" is pretty universal for assembly language sources, // I'm sticking with that. private const string ASM_FILE_SUFFIX = "_acme.S"; // must start with underscore - private const int MAX_OPERAND_LEN = 64; private const string CLOSE_PSEUDOPC = "} ;!pseudopc"; // IGenerator @@ -185,6 +184,7 @@ namespace SourceGen.AsmGen { private void SetFormatConfigValues(ref Formatter.FormatConfig config) { config.mSuppressImpliedAcc = true; + config.mOperandWrapLen = 64; config.mForceDirectOpcodeSuffix = "+1"; config.mForceAbsOpcodeSuffix = "+2"; config.mForceLongOpcodeSuffix = "+3"; @@ -455,7 +455,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 / formatter.CharsPerDenseByte; + int maxPerLine = formatter.OperandWrapLen / formatter.CharsPerDenseByte; string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense); for (int i = 0; i < length; i += maxPerLine) { @@ -648,8 +648,7 @@ namespace SourceGen.AsmGen { } StringOpFormatter stropf = new StringOpFormatter(SourceFormatter, - Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep, - MAX_OPERAND_LEN, charConv); + Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep, charConv); stropf.FeedBytes(data, offset, dfd.Length, leadingBytes, StringOpFormatter.ReverseMode.Forward); diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs index 8d625bf..3e85f1d 100644 --- a/SourceGen/AsmGen/AsmCc65.cs +++ b/SourceGen/AsmGen/AsmCc65.cs @@ -32,7 +32,6 @@ namespace SourceGen.AsmGen { public class GenCc65 : IGenerator { private const string ASM_FILE_SUFFIX = "_cc65.S"; // must start with underscore private const string CFG_FILE_SUFFIX = "_cc65.cfg"; // ditto - private const int MAX_OPERAND_LEN = 64; // IGenerator public DisasmProject Project { get; private set; } @@ -181,6 +180,7 @@ namespace SourceGen.AsmGen { /// Configures the assembler-specific format items. /// private void SetFormatConfigValues(ref Formatter.FormatConfig config) { + config.mOperandWrapLen = 64; config.mForceDirectOpcodeSuffix = string.Empty; config.mForceAbsOpcodeSuffix = string.Empty; config.mForceLongOpcodeSuffix = string.Empty; @@ -486,7 +486,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 / formatter.CharsPerDenseByte; + int maxPerLine = formatter.OperandWrapLen / formatter.CharsPerDenseByte; string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense); for (int i = 0; i < length; i += maxPerLine) { @@ -709,8 +709,7 @@ namespace SourceGen.AsmGen { } StringOpFormatter stropf = new StringOpFormatter(SourceFormatter, - Formatter.DOUBLE_QUOTE_DELIM, StringOpFormatter.RawOutputStyle.CommaSep, - MAX_OPERAND_LEN, charConv); + Formatter.DOUBLE_QUOTE_DELIM, StringOpFormatter.RawOutputStyle.CommaSep, charConv); stropf.FeedBytes(data, offset, dfd.Length - trailingBytes, leadingBytes, StringOpFormatter.ReverseMode.Forward); diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs index 735c1b3..90ff780 100644 --- a/SourceGen/AsmGen/AsmMerlin32.cs +++ b/SourceGen/AsmGen/AsmMerlin32.cs @@ -32,7 +32,6 @@ namespace SourceGen.AsmGen { /// public class GenMerlin32 : IGenerator { private const string ASM_FILE_SUFFIX = "_Merlin32.S"; // must start with underscore - private const int MAX_OPERAND_LEN = 64; // IGenerator public DisasmProject Project { get; private set; } @@ -155,6 +154,7 @@ namespace SourceGen.AsmGen { /// Configures the assembler-specific format items. /// private void SetFormatConfigValues(ref Formatter.FormatConfig config) { + config.mOperandWrapLen = 64; config.mForceDirectOpcodeSuffix = string.Empty; config.mForceAbsOpcodeSuffix = ":"; config.mForceLongOpcodeSuffix = "l"; @@ -333,7 +333,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 / formatter.CharsPerDenseByte; + int maxPerLine = formatter.OperandWrapLen / formatter.CharsPerDenseByte; string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense); for (int i = 0; i < length; i += maxPerLine) { @@ -607,7 +607,7 @@ namespace SourceGen.AsmGen { StringOpFormatter stropf = new StringOpFormatter(SourceFormatter, new Formatter.DelimiterDef(delim), - StringOpFormatter.RawOutputStyle.DenseHex, MAX_OPERAND_LEN, charConv); + StringOpFormatter.RawOutputStyle.DenseHex, charConv); if (dfd.FormatType == FormatDescriptor.Type.StringDci) { // DCI is awkward because the character encoding flips on the last byte. Rather // than clutter up StringOpFormatter for this rare item, we just accept low/high diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs index 87f01c9..3496782 100644 --- a/SourceGen/AsmGen/AsmTass64.cs +++ b/SourceGen/AsmGen/AsmTass64.cs @@ -45,7 +45,6 @@ namespace SourceGen.AsmGen { private const string ASM_FILE_SUFFIX = "_64tass.S"; // must start with underscore private const string ASCII_ENC_NAME = "sg_ascii"; private const string HIGH_ASCII_ENC_NAME = "sg_hiascii"; - private const int MAX_OPERAND_LEN = 64; // IGenerator public DisasmProject Project { get; private set; } @@ -188,6 +187,7 @@ namespace SourceGen.AsmGen { config.mUpperOperandA = false; config.mUpperOperandS = false; config.mUpperOperandXY = false; + config.mOperandWrapLen = 64; config.mBankSelectBackQuote = true; @@ -524,7 +524,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 / formatter.CharsPerDenseByte; + int maxPerLine = formatter.OperandWrapLen / formatter.CharsPerDenseByte; string opcodeStr = formatter.FormatPseudoOp(sDataOpNames.Dense); for (int i = 0; i < length; i += maxPerLine) { @@ -744,8 +744,7 @@ namespace SourceGen.AsmGen { } StringOpFormatter stropf = new StringOpFormatter(SourceFormatter, - Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep, - MAX_OPERAND_LEN, charConv); + Formatter.DOUBLE_QUOTE_DELIM,StringOpFormatter.RawOutputStyle.CommaSep, charConv); if (dfd.FormatType == FormatDescriptor.Type.StringDci) { // DCI is awkward because the character encoding flips on the last byte. Rather // than clutter up StringOpFormatter for this rare item, we just accept low/high diff --git a/SourceGen/AsmGen/GenCommon.cs b/SourceGen/AsmGen/GenCommon.cs index b622694..50e34fa 100644 --- a/SourceGen/AsmGen/GenCommon.cs +++ b/SourceGen/AsmGen/GenCommon.cs @@ -425,6 +425,8 @@ namespace SourceGen.AsmGen { settings.GetBool(AppSettings.FMT_SPACES_BETWEEN_BYTES, false); config.mAddSpaceLongComment = settings.GetBool(AppSettings.FMT_ADD_SPACE_FULL_COMMENT, true); + config.mOperandWrapLen = + settings.GetInt(AppSettings.FMT_OPERAND_WRAP_LEN, 0); config.mForceAbsOpcodeSuffix = settings.GetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, string.Empty); diff --git a/SourceGen/PseudoOp.cs b/SourceGen/PseudoOp.cs index 1b1b148..1101456 100644 --- a/SourceGen/PseudoOp.cs +++ b/SourceGen/PseudoOp.cs @@ -33,8 +33,6 @@ namespace SourceGen { /// multiple lines. /// public class PseudoOp { - private const int MAX_OPERAND_LEN = 64; - /// /// One piece of the pseudo-instruction. /// @@ -278,7 +276,7 @@ namespace SourceGen { return 1; case FormatDescriptor.Type.Dense: { // no delimiter, two output bytes per input byte - int maxLen = MAX_OPERAND_LEN; + int maxLen = formatter.OperandWrapLen; int textLen = dfd.Length * formatter.CharsPerDenseByte; return (textLen + maxLen - 1) / maxLen; } @@ -367,7 +365,7 @@ namespace SourceGen { } break; case FormatDescriptor.Type.Dense: { - int maxPerLine = MAX_OPERAND_LEN / formatter.CharsPerDenseByte; + int maxPerLine = formatter.OperandWrapLen / formatter.CharsPerDenseByte; offset += subIndex * maxPerLine; length -= subIndex * maxPerLine; if (length > maxPerLine) { @@ -547,7 +545,7 @@ namespace SourceGen { } StringOpFormatter stropf = new StringOpFormatter(formatter, delDef, - StringOpFormatter.RawOutputStyle.CommaSep, MAX_OPERAND_LEN, charConv); + StringOpFormatter.RawOutputStyle.CommaSep, charConv); stropf.FeedBytes(data, offset + hiddenLeadingBytes, dfd.Length - hiddenLeadingBytes - trailingBytes, 0, revMode); diff --git a/SourceGen/RuntimeData/Help/settings.html b/SourceGen/RuntimeData/Help/settings.html index 6669d26..2b30375 100644 --- a/SourceGen/RuntimeData/Help/settings.html +++ b/SourceGen/RuntimeData/Help/settings.html @@ -100,6 +100,65 @@ do not affect generated code, which must use the delimiter characters specified by the chosen assembler.

+

Display Format

+ +

These options change the way the code list looks on screen. They +do not affect generated code.

+ +

The +operand width disambiguator +strings are used when the width of an instruction operand is unclear. +You may specify values for all of them or none of them.

+ +

Different assemblers have different ways of forming expressions. +Sometimes the rules allow expressions to be written simply, other times +explicit grouping with parenthesis is required. Select whichever style +you are most comfortable with.

+ +

Non-unique labels are identified with a prefix character, typically +'@' or ':'. The default is '@', but you can configure it to any character +that isn't valid for the start of a label. (64tass uses '_' for locals, +but that's a valid label start character, and so isn't allowed here.) +The setting affects label editing as well as display.

+ +

If you would like your local variables to be shown with a prefix +character, you can set it in the "local variable prefix" box.

+ +

The "quick set" pop-up configures the fields on the left side of the +tab to match the conventions of the specified assembler. Select your +preferred assembler in the combo box to set the fields. The setting +automatically switches to "custom" when you edit a field. +(64tass and ACME use the "common" +expression style, cc65 and Merlin 32 have their own unique styles.)

+ +

The "comma-separated format for bulk data" determines whether large +blocks of hex look like ABC123 or +$AB,$C1,$23. The former reduces the number of lines +required, the latter is more readable.

+

Long operands, such as strings and bulk data, are wrapped to a new +line after a certain number of characters. Use the pop-up to configure +the value. Larger values can make the code easier to read, but smaller +values allow you to shrink the width of the operand column in the +on-screen listing, moving the comment field closer in.

+ + +

Pseudo-Op

+ +

These options change the way the code list looks on screen. Assembler +directives and data pseudo-opcodes will use these values. This does +not affect generated source code, which always matches the conventions +of the target assembler.

+ +

Enter the string you want to use for the various data formats. If +a field is left blank, a default value is used.

+ +

The "quick set" pop-up configures the fields on this tab to match +the conventions of the specified assembler. Select your preferred assembler +in the combo box to set the fields. The setting automatically switches to +"custom" when you edit a field.

+ + +

Asm Config

These settings configure cross-assemblers and modify assembly source @@ -150,53 +209,6 @@ the source file what the intended target assembler is, or what options are required to process the file correctly.

-

Display Format

- -

These options change the way the code list looks on screen. They -do not affect generated code.

- -

The -operand width disambiguator -strings are used when the width of an instruction operand is unclear. -You may specify values for all of them or none of them.

- -

Different assemblers have different ways of forming expressions. -Sometimes the rules allow expressions to be written simply, other times -explicit grouping with parenthesis is required. Select whichever style -you are most comfortable with.

- -

Non-unique labels are identified with a prefix character, typically -'@' or ':'. The default is '@', but you can configure it to any character -that isn't valid for the start of a label. (64tass uses '_' for locals, -but that's a valid label start character, and so isn't allowed here.) -The setting affects label editing as well as display.

- -

If you would like your local variables to be shown with a prefix -character, you can set it in the "local variable prefix" box.

- -

The "quick set" pop-up configures the fields on this tab to match -the conventions of the specified assembler. Select your preferred assembler -in the combo box to set the fields. The setting automatically switches to -"custom" when you edit a field. (64tass and ACME use the "common" -expression style, cc65 and Merlin 32 have their own unique styles.)

- - -

Pseudo-Op

- -

These options change the way the code list looks on screen. Assembler -directives and data pseudo-opcodes will use these values. This does -not affect generated source code, which always matches the conventions -of the target assembler.

- -

Enter the string you want to use for the various data formats. If -a field is left blank, a default value is used.

- -

The "quick set" pop-up configures the fields on this tab to match -the conventions of the specified assembler. Select your preferred assembler -in the combo box to set the fields. The setting automatically switches to -"custom" when you edit a field.

- -

Project Properties

Project properties are stored in the .dis65 project file. diff --git a/SourceGen/Tests/GenTest.cs b/SourceGen/Tests/GenTest.cs index d2fe0d7..7d8106e 100644 --- a/SourceGen/Tests/GenTest.cs +++ b/SourceGen/Tests/GenTest.cs @@ -389,6 +389,7 @@ namespace SourceGen.Tests { settings.SetBool(AppSettings.FMT_UPPER_OPERAND_S, true); settings.SetBool(AppSettings.FMT_UPPER_OPERAND_XY, false); settings.SetBool(AppSettings.FMT_ADD_SPACE_FULL_COMMENT, false); + settings.SetInt(AppSettings.FMT_OPERAND_WRAP_LEN, 64); // Don't show the assembler ident line. You can make a case for this being // mandatory, since the generated code is only guaranteed to work with the diff --git a/SourceGen/WpfGui/EditAppSettings.xaml b/SourceGen/WpfGui/EditAppSettings.xaml index 691f590..16f11b9 100644 --- a/SourceGen/WpfGui/EditAppSettings.xaml +++ b/SourceGen/WpfGui/EditAppSettings.xaml @@ -129,10 +129,10 @@ limitations under the License. - + @@ -422,180 +422,120 @@ limitations under the License. - - - - - - - - - - - - - - - - - - - -