diff --git a/SourceGen/RuntimeData/Help/codegen.html b/SourceGen/RuntimeData/Help/codegen.html
index 20b9f95..6f3949e 100644
--- a/SourceGen/RuntimeData/Help/codegen.html
+++ b/SourceGen/RuntimeData/Help/codegen.html
@@ -325,7 +325,8 @@ clipboard and pasting them into a text file, except that you have greater
control over which columns are included. The HTML version is augmented
with links.
-
Use File > Export to open the export dialog. You have several options:
+
Use File > Export to open the export dialog. You have several
+options:
Include only selected lines. This allows you to choose between
exporting all or part of a file. If no lines are selected, the entire
@@ -359,7 +360,8 @@ with links.
dialog. Any additional files generated, such as graphics for HTML pages,
will be written to the same directory.
-
All output uses UTF-8 encoding.
+
All output uses UTF-8 encoding. Filenames of HTML files will have '#'
+replaced with '_' to make linking easier.
diff --git a/SourceGen/RuntimeData/Help/settings.html b/SourceGen/RuntimeData/Help/settings.html
index 76a35bc..2922187 100644
--- a/SourceGen/RuntimeData/Help/settings.html
+++ b/SourceGen/RuntimeData/Help/settings.html
@@ -163,11 +163,11 @@ you are most comfortable with.
If you would like your local variables to be shown with a prefix
character, you can set one here.
-
The "quick set" buttons configure the fields on this tab to match
+
The "quick set" pop-up configures the fields on this tab to match
the conventions of the specified assembler. Select your preferred assembler
-with the combox box, then click "set" to set the fields. (64tass and
-ACME use the "common" expression style, cc65 and Merlin 32 have their
-own unique styles.)
+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.)
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" buttons configure the fields on this tab to match
+
The "quick set" pop-up configures the fields on this tab to match
the conventions of the specified assembler. Select your preferred assembler
-with the combox box, then click "set" to set the fields.
+in the combo box to set the fields. The setting automatically switches to
+"custom" when you edit a field.
diff --git a/SourceGen/RuntimeData/Help/tutorials.html b/SourceGen/RuntimeData/Help/tutorials.html
index 52d246a..ad3b608 100644
--- a/SourceGen/RuntimeData/Help/tutorials.html
+++ b/SourceGen/RuntimeData/Help/tutorials.html
@@ -19,8 +19,9 @@ difference between numeric and symbolic references, so reading the
manual is recommended.
@@ -345,81 +346,6 @@ on to the next tutorial to learn more.
can do. We assume you've already finished the Basic Features tutorial.
-
Address Table Formatting
-
-
Start a new project. Select the Apple //e platform, click Select File
-and navigate to the Examples directory. In A2-Amper-fdraw, select
-AMPERFDRAW#061d60. Click "OK" to create the project.
-
Not a lot to see here -- just half a dozen lines of loads and stores.
-This particular program interfaces with Applesoft BASIC, so we can make it
-a bit more meaningful by loading an additional platform
-symbol file. Select Edit > Project Properties, then the Symbol Files
-tab. Click Add Symbol Files. The file browser starts in the RuntimeData
-directory. In the Apple folder, select Applesoft.sym65, and
-click "Open". Click "OK" to close the project properties window.
-
The STA instructions now reference BAS_AMPERV,
-which is noted as a code vector. We can see the code setting up a jump
-(opcode $4c) to $1d70. As it happens, the start address of the code
-is $1d60 -- the last four digits of the filename -- so let's make that
-change. Double-click the initial .ORG statement, and change it from
-$2000 to $1d60. We can now see that $1d70 starts right after this
-initial chunk of code.
-
-
Select the line with address $1d70, then Actions > Hint As Code
-Entry Point.
-More code appears, but not much -- if you scroll down you'll see that most
-of the file is still data. The code at $1d70 searches through a table at
-$1d88 for a match with the contents of the accumulator. If it finds a match,
-it loads bytes from tables at $1da6 and $1d97, pushes them on the stack,
-and the JMPs away. This code is pushing a return address onto the stack.
-When the code at BAS_CHRGET returns, it'll return to that
-address. Because of a quirk of the 6502 architecture, the address pushed
-must be the desired address minus one.
-
The first byte in the first address table at $1d97 (which has the auto-label
-L1D97) is $b4. The first byte in the second table is $1d. So the first
-address we want is $1db4 + 1 = $1db5.
-
Select the line at $1db5, and use Actions > Hint As Code Entry Point.
-More code appears, but again it's only a few lines. Let's dress this one
-up a bit. Set a label on the code at $1db5 called "FUNC". At $1d97, edit
-the data item (double-click on "$b4"), click "Single bytes", then type "FUNC"
-(note the text field gets focus immediately, and the radio button
-automatically switches to "symbolic reference" when you start typing).
-Click "OK". The operand at $1d97 should now say <FUNC-1.
-Repeat the process at $1da6, this time clicking the "High" part radio button
-below the symbol entry text box,
-to make the operand there say >FUNC. (If it says
-<FUNC-152, you forgot to select the High part.)
-
-
We've now changed the first entry in the table to symbolic references.
-You could repeat these steps for the remaining items, but there's a faster
-way. Click on the line at address $1d97, then shift-click the line at
-address $1da9 (which should be .FILL 12,$1e). Select
-Actions > Format Address Table.
-
The message at the top should indicate that there are 30 bytes
-selected. In Address Characteristics, click the "Parts are split across
-sub-tables" checkbox and the "adjusted for RTS/RTL"
-checkbox. As soon as you do, the first line of the Generated Addresses
-list should show the symbol "FUNC". The rest of the addresses will look like
-(+) T1DD0. The "(+)" means that a label was not found at
-that location, so a label will be generated automatically.
-
Down near the bottom, check the "add code entry hint if needed" checkbox.
-Because we saw the table contents being pushed onto the stack for RTS,
-we know that they're all code entry points.
-
Click "OK". The table of address bytes at $1d97 should now all be
-references to symbols -- 15 low parts followed by 15 high parts. If you
-scroll down, you should see nothing but instructions until you get to the
-last dozen bytes at the end of the file. (If this isn't the case, use
-Edit > Undo, then work through the steps again.)
-
The formatter did the same steps you went through earlier -- set a
-label, apply the label to the low and high bytes in the table, add a
-code entry point hint -- but did several of them at once.
-
-
We don't want to save this project, so select File > Close. When
-SourceGen asks for confirmation, click Discard & Continue.
-
-
-
Going Deeper
-
Start a new project. Select "Generic 6502". For the data file, navigate
to the Examples directory, then from the Tutorial directory
select "Tutorial2".
@@ -585,7 +511,84 @@ extra symbol in the opcode field, you need to look closely at what's going
on.
-
Start a new project. Select the Apple //e platform, click Select File
+and navigate to the Examples directory. In A2-Amper-fdraw, select
+AMPERFDRAW#061d60. Click "OK" to create the project.
+
Not a lot to see here -- just half a dozen lines of loads and stores.
+This particular program interfaces with Applesoft BASIC, so we can make it
+a bit more meaningful by loading an additional platform
+symbol file. Select Edit > Project Properties, then the Symbol Files
+tab. Click Add Symbol Files. The file browser starts in the RuntimeData
+directory. In the Apple folder, select Applesoft.sym65, and
+click "Open". Click "OK" to close the project properties window.
+
The STA instructions now reference BAS_AMPERV,
+which is noted as a code vector. We can see the code setting up a jump
+(opcode $4c) to $1d70. As it happens, the start address of the code
+is $1d60 -- the last four digits of the filename -- so let's make that
+change. Double-click the initial .ORG statement, and change it from
+$2000 to $1d60. We can now see that $1d70 starts right after this
+initial chunk of code.
+
+
Select the line with address $1d70, then Actions > Hint As Code
+Entry Point.
+More code appears, but not much -- if you scroll down you'll see that most
+of the file is still data. The code at $1d70 searches through a table at
+$1d88 for a match with the contents of the accumulator. If it finds a match,
+it loads bytes from tables at $1da6 and $1d97, pushes them on the stack,
+and the JMPs away. This code is pushing a return address onto the stack.
+When the code at BAS_CHRGET returns, it'll return to that
+address. Because of a quirk of the 6502 architecture, the address pushed
+must be the desired address minus one.
+
The first byte in the first address table at $1d97 (which has the auto-label
+L1D97) is $b4. The first byte in the second table is $1d. So the first
+address we want is $1db4 + 1 = $1db5.
+
Select the line at $1db5, and use Actions > Hint As Code Entry Point.
+More code appears, but again it's only a few lines. Let's dress this one
+up a bit. Set a label on the code at $1db5 called "FUNC". At $1d97, edit
+the data item (double-click on "$b4"), click "Single bytes", then type "FUNC"
+(note the text field gets focus immediately, and the radio button
+automatically switches to "symbolic reference" when you start typing).
+Click "OK". The operand at $1d97 should now say <FUNC-1.
+Repeat the process at $1da6, this time clicking the "High" part radio button
+below the symbol entry text box,
+to make the operand there say >FUNC. (If it says
+<FUNC-152, you forgot to select the High part.)
+
+
We've now changed the first entry in the table to symbolic references.
+You could repeat these steps for the remaining items, but there's a faster
+way. Click on the line at address $1d97, then shift-click the line at
+address $1da9 (which should be .FILL 12,$1e). Select
+Actions > Format Address Table.
+
The message at the top should indicate that there are 30 bytes
+selected. In Address Characteristics, click the "Parts are split across
+sub-tables" checkbox and the "adjusted for RTS/RTL"
+checkbox. As soon as you do, the first line of the Generated Addresses
+list should show the symbol "FUNC". The rest of the addresses will look like
+(+) T1DD0. The "(+)" means that a label was not found at
+that location, so a label will be generated automatically.
+
Down near the bottom, check the "add code entry hint if needed" checkbox.
+Because we saw the table contents being pushed onto the stack for RTS,
+we know that they're all code entry points.
+
Click "OK". The table of address bytes at $1d97 should now all be
+references to symbols -- 15 low parts followed by 15 high parts. If you
+scroll down, you should see nothing but instructions until you get to the
+last dozen bytes at the end of the file. (If this isn't the case, use
+Edit > Undo, then work through the steps again.)
+
The formatter did the same steps you went through earlier -- set a
+label, apply the label to the low and high bytes in the table, add a
+code entry point hint -- but did several of them at once.
+
+
We don't want to save this project, so select File > Close. When
+SourceGen asks for confirmation, click Discard & Continue.
+
+
+
End of Tutorials
That's it for the tutorials. Significantly more detail on
all aspects of SourceGen can be found in the manual.
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml b/SourceGen/WpfGui/EditAppSettings.xaml
index db6e79c..ee40568 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml
+++ b/SourceGen/WpfGui/EditAppSettings.xaml
@@ -19,6 +19,7 @@ limitations under the License.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:SourceGen.WpfGui"
mc:Ignorable="d"
Title="Edit Application Settings"
@@ -26,6 +27,14 @@ limitations under the License.
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded">
+
+ Common
+ cc65
+ Merlin
+ Custom
+ Default
+
+
-
+ Text="{Binding OpcodeSuffixAbs, UpdateSourceTrigger=PropertyChanged,
+ FallbackValue=.placeho}"/>
-
+ Text="{Binding OperandPrefixAbs, UpdateSourceTrigger=PropertyChanged,
+ FallbackValue=.placeho}"/>
-
+ Text="{Binding OpcodeSuffixLong, UpdateSourceTrigger=PropertyChanged,
+ FallbackValue=.placeho}"/>
-
+ Text="{Binding OperandPrefixLong, UpdateSourceTrigger=PropertyChanged,
+ FallbackValue=.placeho}"/>
@@ -568,16 +577,11 @@ limitations under the License.
-
-
-
-
-
+ HorizontalAlignment="Right" Padding="2,4">
+
@@ -730,16 +734,11 @@ limitations under the License.
-
-
-
-
-
+ HorizontalAlignment="Right" Padding="2,4">
+
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml.cs b/SourceGen/WpfGui/EditAppSettings.xaml.cs
index 0be7aec..7eaf3f5 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml.cs
+++ b/SourceGen/WpfGui/EditAppSettings.xaml.cs
@@ -136,26 +136,8 @@ namespace SourceGen.WpfGui {
}
// Can't set the selected item yet.
- // Map text boxes to PseudoOpName fields.
- mPseudoNameMap = new TextBoxPropertyMap[] {
- new TextBoxPropertyMap(equDirectiveTextBox, "EquDirective"),
- new TextBoxPropertyMap(varDirectiveTextBox, "VarDirective"),
- new TextBoxPropertyMap(orgDirectiveTextBox, "OrgDirective"),
- new TextBoxPropertyMap(regWidthDirectiveTextBox, "RegWidthDirective"),
- new TextBoxPropertyMap(defineData1TextBox, "DefineData1"),
- new TextBoxPropertyMap(defineData2TextBox, "DefineData2"),
- new TextBoxPropertyMap(defineData3TextBox, "DefineData3"),
- new TextBoxPropertyMap(defineData4TextBox, "DefineData4"),
- new TextBoxPropertyMap(defineBigData2TextBox, "DefineBigData2"),
- new TextBoxPropertyMap(fillTextBox, "Fill"),
- new TextBoxPropertyMap(denseTextBox, "Dense"),
- new TextBoxPropertyMap(strGenericTextBox, "StrGeneric"),
- new TextBoxPropertyMap(strReverseTextBox, "StrReverse"),
- new TextBoxPropertyMap(strLen8TextBox, "StrLen8"),
- new TextBoxPropertyMap(strLen16TextBox, "StrLen16"),
- new TextBoxPropertyMap(strNullTermTextBox, "StrNullTerm"),
- new TextBoxPropertyMap(strDciTextBox, "StrDci"),
- };
+ Construct_PseudoOp();
+ Construct_DisplayFormat();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
@@ -815,6 +797,75 @@ namespace SourceGen.WpfGui {
#region Display Format
+ public string mOpcodeSuffixAbs;
+ public string OpcodeSuffixAbs {
+ get { return mOpcodeSuffixAbs; }
+ set {
+ if (mOpcodeSuffixAbs != value) {
+ mOpcodeSuffixAbs = value;
+ OnPropertyChanged();
+ mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, value);
+ UpdateDisplayFormatQuickCombo();
+ IsDirty = true;
+ }
+ }
+ }
+ public string mOpcodeSuffixLong;
+ public string OpcodeSuffixLong {
+ get { return mOpcodeSuffixLong; }
+ set {
+ if (mOpcodeSuffixLong != value) {
+ mOpcodeSuffixLong = value;
+ OnPropertyChanged();
+ mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_LONG, value);
+ UpdateDisplayFormatQuickCombo();
+ IsDirty = true;
+ }
+ }
+ }
+ public string mOperandPrefixAbs;
+ public string OperandPrefixAbs {
+ get { return mOperandPrefixAbs; }
+ set {
+ if (mOperandPrefixAbs != value) {
+ mOperandPrefixAbs = value;
+ OnPropertyChanged();
+ mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_ABS, value);
+ UpdateDisplayFormatQuickCombo();
+ IsDirty = true;
+ }
+ }
+ }
+ public string mOperandPrefixLong;
+ public string OperandPrefixLong {
+ get { return mOperandPrefixLong; }
+ set {
+ if (mOperandPrefixLong != value) {
+ mOperandPrefixLong = value;
+ OnPropertyChanged();
+ mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, value);
+ UpdateDisplayFormatQuickCombo();
+ IsDirty = true;
+ }
+ }
+ }
+ private string mLocalVarPrefix;
+ public string LocalVarPrefix {
+ get { return mLocalVarPrefix; }
+ set {
+ if (mLocalVarPrefix != value) {
+ mLocalVarPrefix = value;
+ OnPropertyChanged();
+ mSettings.SetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, value);
+ UpdateDisplayFormatQuickCombo();
+ IsDirty = true;
+ }
+ }
+ }
+
+ // prevent recursion
+ private bool mSettingDisplayFmtCombo;
+
///
/// Holds an item for the expression style selection combo box.
///
@@ -830,30 +881,90 @@ namespace SourceGen.WpfGui {
Name = name;
}
}
- private static ExpressionStyleItem[] sExpStyleItems = new ExpressionStyleItem[] {
- new ExpressionStyleItem(ExpressionMode.Common, "Common"),
- new ExpressionStyleItem(ExpressionMode.Cc65, "cc65"),
- new ExpressionStyleItem(ExpressionMode.Merlin, "Merlin"),
- };
+ private static ExpressionStyleItem[] sExpStyleItems;
public ExpressionStyleItem[] ExpressionStyleItems {
get { return sExpStyleItems; }
}
- public string LocalVarPrefix {
- get { return mLocalVarPrefix; }
- set {
- if (mLocalVarPrefix != value) {
- mLocalVarPrefix = value;
- OnPropertyChanged();
- mSettings.SetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, value);
- IsDirty = true;
- }
+ private void ConstructExpressionStyleItems() {
+ sExpStyleItems = new ExpressionStyleItem[] {
+ new ExpressionStyleItem(ExpressionMode.Common,
+ (string)FindResource("str_ExpStyleCommon")),
+ new ExpressionStyleItem(ExpressionMode.Cc65,
+ (string)FindResource("str_ExpStyleCc65")),
+ new ExpressionStyleItem(ExpressionMode.Merlin,
+ (string)FindResource("str_ExpStyleMerlin")),
+ };
+ }
+
+ public class DisplayFormatPreset {
+ public const int ID_CUSTOM = -2;
+ public const int ID_DEFAULT = -1;
+ public int Ident { get; private set; } // positive values are AssemblerInfo.Id
+ public string Name { get; private set; }
+ public string OpcodeSuffixAbs { get; private set; }
+ public string OpcodeSuffixLong { get; private set; }
+ public string OperandPrefixAbs { get; private set; }
+ public string OperandPrefixLong { get; private set; }
+ public string LocalVarPrefix { get; private set; }
+ public ExpressionMode ExpressionStyle { get; private set; }
+
+ public DisplayFormatPreset(int id, string name, string opcSuffixAbs,
+ string opcSuffixLong, string operPrefixAbs, string operPrefixLong,
+ string localVarPrefix, ExpressionMode expStyle) {
+ Ident = id;
+ Name = name;
+ OpcodeSuffixAbs = opcSuffixAbs;
+ OpcodeSuffixLong = opcSuffixLong;
+ OperandPrefixAbs = operPrefixAbs;
+ OperandPrefixLong = operPrefixLong;
+ LocalVarPrefix = localVarPrefix;
+ ExpressionStyle = expStyle;
}
}
- private string mLocalVarPrefix;
+ public DisplayFormatPreset[] DisplayPresets { get; private set; }
+
+ private void ConstructDisplayPresets() {
+ // "custom" must be in slot 0
+ 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, ExpressionMode.Unknown);
+ DisplayPresets[1] = new DisplayFormatPreset(DisplayFormatPreset.ID_DEFAULT,
+ (string)FindResource("str_PresetDefault"), string.Empty, "l", "a:", "f:",
+ string.Empty, ExpressionMode.Common);
+ for (int i = 0; i < AssemblerList.Count; i++) {
+ AssemblerInfo asmInfo = AssemblerList[i];
+ AsmGen.IGenerator gen = AssemblerInfo.GetGenerator(asmInfo.AssemblerId);
+
+ gen.GetDefaultDisplayFormat(out PseudoOp.PseudoOpNames unused,
+ out Asm65.Formatter.FormatConfig formatConfig);
+
+ DisplayPresets[i + 2] = new DisplayFormatPreset((int)asmInfo.AssemblerId,
+ asmInfo.Name, formatConfig.mForceAbsOpcodeSuffix,
+ formatConfig.mForceLongOpcodeSuffix, formatConfig.mForceAbsOperandPrefix,
+ formatConfig.mForceLongOperandPrefix, formatConfig.mLocalVariableLablePrefix,
+ formatConfig.mExpressionMode);
+ }
+ }
+
+ private void Construct_DisplayFormat() {
+ ConstructExpressionStyleItems();
+ ConstructDisplayPresets();
+ }
private void Loaded_DisplayFormat() {
- PopulateWidthDisamSettings();
+ // Set values from settings.
+ OpcodeSuffixAbs =
+ mSettings.GetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, string.Empty);
+ OpcodeSuffixLong =
+ mSettings.GetString(AppSettings.FMT_OPCODE_SUFFIX_LONG, string.Empty);
+ OperandPrefixAbs =
+ mSettings.GetString(AppSettings.FMT_OPERAND_PREFIX_ABS, string.Empty);
+ OperandPrefixLong =
+ mSettings.GetString(AppSettings.FMT_OPERAND_PREFIX_LONG, string.Empty);
+ LocalVarPrefix =
+ mSettings.GetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, string.Empty);
string exprMode = mSettings.GetString(AppSettings.FMT_EXPRESSION_MODE, string.Empty);
ExpressionMode mode;
@@ -863,60 +974,7 @@ namespace SourceGen.WpfGui {
SelectExpressionStyle(mode);
// No need to set this to anything specific.
- displayFmtQuickComboBox.SelectedIndex = 0;
-
- LocalVarPrefix = mSettings.GetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX,
- string.Empty);
- }
-
- ///
- /// Populates the width disambiguation text boxes.
- ///
- private void PopulateWidthDisamSettings() {
- // Operand width disambiguation. This is a little tricky -- we have to query all
- // settings then set all controls, or the field-updated callback may interfere
- // with us by changing AppSettings.
- string opcSuffixAbs = mSettings.GetString(AppSettings.FMT_OPCODE_SUFFIX_ABS,
- string.Empty);
- string opcSuffixLong = mSettings.GetString(AppSettings.FMT_OPCODE_SUFFIX_LONG,
- string.Empty);
- string opPrefixAbs = mSettings.GetString(AppSettings.FMT_OPERAND_PREFIX_ABS,
- string.Empty);
- string opPrefixLong = mSettings.GetString(AppSettings.FMT_OPERAND_PREFIX_LONG,
- string.Empty);
-
- disambSuffix16TextBox.Text = opcSuffixAbs;
- disambSuffix24TextBox.Text = opcSuffixLong;
- disambPrefix16TextBox.Text = opPrefixAbs;
- disambPrefix24TextBox.Text = opPrefixLong;
- }
-
- ///
- /// Sets all of the width disambiguation settings. Used for the quick-set feature.
- ///
- private void SetWidthDisamSettings(string opcodeSuffixAbs, string opcodeSuffixLong,
- string operandPrefixAbs, string operandPrefixLong) {
- mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, opcodeSuffixAbs);
- mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_LONG, opcodeSuffixLong);
- mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_ABS, operandPrefixAbs);
- mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, operandPrefixLong);
- PopulateWidthDisamSettings();
- }
-
- ///
- /// Exports the current state of the width controls to the settings object whenever
- /// text is typed.
- ///
- private void WidthDisamControlChanged(object sender, TextChangedEventArgs e) {
- if (mSettings == null) {
- // initialization
- return;
- }
- mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, disambSuffix16TextBox.Text);
- mSettings.SetString(AppSettings.FMT_OPCODE_SUFFIX_LONG, disambSuffix24TextBox.Text);
- mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_ABS, disambPrefix16TextBox.Text);
- mSettings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, disambPrefix24TextBox.Text);
- IsDirty = true;
+ UpdateDisplayFormatQuickCombo();
}
///
@@ -936,40 +994,74 @@ namespace SourceGen.WpfGui {
///
/// Handles a change to the expression style.
///
- private void ExpressionStyleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ private void ExpressionStyleComboBox_SelectionChanged(object sender,
+ SelectionChangedEventArgs e) {
ExpressionStyleItem esi = (ExpressionStyleItem)expressionStyleComboBox.SelectedItem;
mSettings.SetString(AppSettings.FMT_EXPRESSION_MODE, esi.ExpMode.ToString());
+ UpdateDisplayFormatQuickCombo();
IsDirty = true;
}
- private void DisplayFmtSetButton_Click(object sender, RoutedEventArgs e) {
- AssemblerInfo asmInfo = (AssemblerInfo)displayFmtQuickComboBox.SelectedItem;
- AsmGen.IGenerator gen = AssemblerInfo.GetGenerator(asmInfo.AssemblerId);
+ private void DisplayFmtQuickComboBox_SelectionChanged(object sender,
+ SelectionChangedEventArgs e) {
+ if (mSettingDisplayFmtCombo) {
+ // We shouldn't actually recurse indefinitely because we'll eventually
+ // decide that nothing is changing, but I feel better having this here.
+ return;
+ }
- PseudoOp.PseudoOpNames unused;
- Asm65.Formatter.FormatConfig formatConfig;
- gen.GetDefaultDisplayFormat(out unused, out formatConfig);
+ DisplayFormatPreset preset = (DisplayFormatPreset)displayFmtQuickComboBox.SelectedItem;
+ if (preset.Ident == DisplayFormatPreset.ID_CUSTOM) {
+ // Not an actual preset. Leave the combo box set to "Custom".
+ return;
+ }
- SetWidthDisamSettings(formatConfig.mForceAbsOpcodeSuffix,
- formatConfig.mForceLongOpcodeSuffix,
- formatConfig.mForceAbsOperandPrefix,
- formatConfig.mForceLongOperandPrefix);
- SelectExpressionStyle(formatConfig.mExpressionMode);
- LocalVarPrefix = formatConfig.mLocalVariableLablePrefix;
- // dirty flag set by change watchers if one or more fields have changed
+ OpcodeSuffixAbs = preset.OpcodeSuffixAbs;
+ OpcodeSuffixLong = preset.OpcodeSuffixLong;
+ OperandPrefixAbs = preset.OperandPrefixAbs;
+ OperandPrefixLong = preset.OperandPrefixLong;
+ LocalVarPrefix = preset.LocalVarPrefix;
+
+ SelectExpressionStyle(preset.ExpressionStyle);
+ // dirty flag will be set by change watchers if one or more fields have changed
}
- private void QuickFmtDefaultButton_Click(object sender, RoutedEventArgs e) {
- SetWidthDisamSettings(null, "l", "a:", "f:");
- SelectExpressionStyle(ExpressionMode.Common);
- LocalVarPrefix = string.Empty;
- // dirty flag set by change watchers if one or more fields have changed
+ private void UpdateDisplayFormatQuickCombo() {
+ mSettingDisplayFmtCombo = true;
+
+ ExpressionStyleItem esi = (ExpressionStyleItem)expressionStyleComboBox.SelectedItem;
+ ExpressionMode expMode = ExpressionMode.Unknown;
+ if (esi != null) {
+ expMode = esi.ExpMode;
+ }
+
+ // If the current settings match one of the quick sets, update the combo box to
+ // match. Otherwise, set it to "custom".
+ displayFmtQuickComboBox.SelectedIndex = 0;
+ for (int i = 1; i < DisplayPresets.Length; i++) {
+ DisplayFormatPreset preset = DisplayPresets[i];
+ if (OpcodeSuffixAbs == preset.OpcodeSuffixAbs &&
+ OpcodeSuffixLong == preset.OpcodeSuffixLong &&
+ OperandPrefixAbs == preset.OperandPrefixAbs &&
+ OperandPrefixLong == preset.OperandPrefixLong &&
+ LocalVarPrefix == preset.LocalVarPrefix &&
+ expMode == preset.ExpressionStyle) {
+ // match
+ displayFmtQuickComboBox.SelectedIndex = i;
+ break;
+ }
+ }
+
+ mSettingDisplayFmtCombo = false;
}
#endregion Display Format
#region PseudoOp
+ // recursion preventer
+ private bool mSettingPseudoOpCombo;
+
///
/// Map pseudo-op text entry fields to PseudoOpName properties.
///
@@ -984,6 +1076,68 @@ namespace SourceGen.WpfGui {
}
private TextBoxPropertyMap[] mPseudoNameMap;
+ private void ConstructPseudoOpMap() {
+ // Map text boxes to PseudoOpName fields.
+ mPseudoNameMap = new TextBoxPropertyMap[] {
+ new TextBoxPropertyMap(equDirectiveTextBox, "EquDirective"),
+ new TextBoxPropertyMap(varDirectiveTextBox, "VarDirective"),
+ new TextBoxPropertyMap(orgDirectiveTextBox, "OrgDirective"),
+ new TextBoxPropertyMap(regWidthDirectiveTextBox, "RegWidthDirective"),
+ new TextBoxPropertyMap(defineData1TextBox, "DefineData1"),
+ new TextBoxPropertyMap(defineData2TextBox, "DefineData2"),
+ new TextBoxPropertyMap(defineData3TextBox, "DefineData3"),
+ new TextBoxPropertyMap(defineData4TextBox, "DefineData4"),
+ new TextBoxPropertyMap(defineBigData2TextBox, "DefineBigData2"),
+ new TextBoxPropertyMap(fillTextBox, "Fill"),
+ new TextBoxPropertyMap(denseTextBox, "Dense"),
+ new TextBoxPropertyMap(strGenericTextBox, "StrGeneric"),
+ new TextBoxPropertyMap(strReverseTextBox, "StrReverse"),
+ new TextBoxPropertyMap(strLen8TextBox, "StrLen8"),
+ new TextBoxPropertyMap(strLen16TextBox, "StrLen16"),
+ new TextBoxPropertyMap(strNullTermTextBox, "StrNullTerm"),
+ new TextBoxPropertyMap(strDciTextBox, "StrDci"),
+ };
+ }
+
+ public class PseudoOpPreset {
+ public const int ID_CUSTOM = -2;
+ public const int ID_DEFAULT = -1;
+ public int Ident { get; private set; } // positive values are AssemblerInfo.Id
+ public string Name { get; private set; }
+ public PseudoOp.PseudoOpNames OpNames { get; private set; }
+
+ public PseudoOpPreset(int id, string name, PseudoOp.PseudoOpNames opNames) {
+ Ident = id;
+ Name = name;
+ OpNames = opNames;
+ }
+ }
+
+ public PseudoOpPreset[] PseudoOpPresets { get; private set; }
+
+ private void ConstructPseudoOpPresets() {
+ // "custom" must be in slot 0
+ PseudoOpPresets = new PseudoOpPreset[AssemblerList.Count + 2];
+ PseudoOpPresets[0] = new PseudoOpPreset(PseudoOpPreset.ID_CUSTOM,
+ (string)FindResource("str_PresetCustom"), new PseudoOp.PseudoOpNames());
+ PseudoOpPresets[1] = new PseudoOpPreset(PseudoOpPreset.ID_DEFAULT,
+ (string)FindResource("str_PresetDefault"), new PseudoOp.PseudoOpNames());
+ for (int i = 0; i < AssemblerList.Count; i++) {
+ AssemblerInfo asmInfo = AssemblerList[i];
+ AsmGen.IGenerator gen = AssemblerInfo.GetGenerator(asmInfo.AssemblerId);
+
+ gen.GetDefaultDisplayFormat(out PseudoOp.PseudoOpNames opNames,
+ out Asm65.Formatter.FormatConfig unused);
+ PseudoOpPresets[i + 2] = new PseudoOpPreset((int)asmInfo.AssemblerId,
+ asmInfo.Name, opNames);
+ }
+ }
+
+ private void Construct_PseudoOp() {
+ ConstructPseudoOpMap();
+ ConstructPseudoOpPresets();
+ }
+
private void Loaded_PseudoOp() {
string opStrCereal = mSettings.GetString(AppSettings.FMT_PSEUDO_OP_NAMES, null);
if (!string.IsNullOrEmpty(opStrCereal)) {
@@ -991,12 +1145,10 @@ namespace SourceGen.WpfGui {
ImportPseudoOpNames(opNames);
} else {
// no data available, populate with blanks
- //PseudoOp.PseudoOpNames opNames = PseudoOp.sDefaultPseudoOpNames;
ImportPseudoOpNames(new PseudoOp.PseudoOpNames());
}
- // No need to set this to anything specific.
- pseudoOpQuickComboBox.SelectedIndex = 0;
+ UpdatePseudoOpQuickCombo();
// Create text field listeners.
foreach (TextBoxPropertyMap pmap in mPseudoNameMap) {
@@ -1032,23 +1184,43 @@ namespace SourceGen.WpfGui {
private void PseudoOpTextChanged(object sender, EventArgs e) {
// Just set the dirty flag. The (somewhat expensive) export will happen
// on Apply/OK.
+ UpdatePseudoOpQuickCombo();
IsDirty = true;
}
- private void PseudoOpDefaultButton_Click(object sender, RoutedEventArgs e) {
- ImportPseudoOpNames(new PseudoOp.PseudoOpNames());
+ private void UpdatePseudoOpQuickCombo() {
+ mSettingPseudoOpCombo = true;
+
+ PseudoOp.PseudoOpNames curNames = ExportPseudoOpNames();
+
+ // If the current settings match one of the quick sets, update the combo box to
+ // match. Otherwise, set it to "custom".
+ pseudoOpQuickComboBox.SelectedIndex = 0;
+ for (int i = 1; i < PseudoOpPresets.Length; i++) {
+ PseudoOpPreset preset = PseudoOpPresets[i];
+ if (preset.OpNames == curNames) {
+ // match
+ pseudoOpQuickComboBox.SelectedIndex = i;
+ break;
+ }
+ }
+
+ mSettingPseudoOpCombo = false;
}
- private void PseudoOpSetButton_Click(object sender, RoutedEventArgs e) {
- AssemblerInfo asmInfo = (AssemblerInfo)pseudoOpQuickComboBox.SelectedItem;
- AsmGen.IGenerator gen = AssemblerInfo.GetGenerator(asmInfo.AssemblerId);
+ private void PseudoOpQuickComboBox_SelectionChanged(object sender,
+ SelectionChangedEventArgs e) {
+ if (mSettingPseudoOpCombo) {
+ return;
+ }
- PseudoOp.PseudoOpNames opNames;
- Asm65.Formatter.FormatConfig formatConfig;
- gen.GetDefaultDisplayFormat(out opNames, out formatConfig);
- ImportPseudoOpNames(opNames);
+ PseudoOpPreset preset = (PseudoOpPreset)pseudoOpQuickComboBox.SelectedItem;
+ if (preset.Ident == PseudoOpPreset.ID_CUSTOM) {
+ // Not an actual preset. Leave the combo box set to "Custom".
+ return;
+ }
- // dirty flag set by change watchers if one or more fields have changed
+ ImportPseudoOpNames(preset.OpNames);
}
#endregion PseudoOp