Add option to put labels on separate lines

We currently have two options for assembly code output, selected by
a checkbox in the application settings: always put labels on the same
lines as the instruction or data operand, or split the labels onto
their own line if they were wider than the label text field.

This change adds a third option, which puts labels on their own line
whenever possible.  Assemblers don't generally allow this for variable
assignment pseudo-ops like "foo = $1000", but it's accepted for most
other situations.  This is a cosmetic change to the output, and will
not affect the generated code.

The old true/false app setting will be disregarded.  "Split if too
long" will be used by default.

Added test 20280-label-placement to exercise the "split whenever
allowed" behavior.

The "export" function has a similar option that has not been updated
(for no particular reason other than laziness).

Also, simplified the app settings GetEnum / SetEnum calls, which
can infer the enumerated type from the arguments.  This should not
impact behavior.
This commit is contained in:
Andy McFadden 2024-04-21 15:30:11 -07:00
parent e425237783
commit 4322a0c231
28 changed files with 506 additions and 101 deletions

View File

@ -42,10 +42,10 @@ namespace CommonUtil {
/// </summary>
/// <remarks>
/// Usage:
/// AppDomain.CurrentDomain.UnhandledException +=
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
/// <code>AppDomain.CurrentDomain.UnhandledException +=
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);</code>
///
/// Thanks: https://stackoverflow.com/a/21308327/294248
/// Thanks: <see href="https://stackoverflow.com/a/21308327/294248"/>.
/// </remarks>
public static void CrashReporter(object sender, UnhandledExceptionEventArgs e) {
const string CRASH_PATH = @"CrashLog.txt";
@ -80,7 +80,7 @@ namespace CommonUtil {
/// faster than setting array elements individually.
/// </summary>
/// <remarks>
/// From https://stackoverflow.com/a/18659408/294248
/// From <see href="https://stackoverflow.com/a/18659408/294248"/>.
///
/// Invokes Array.Copy() on overlapping elements. Other approaches involve using
/// Buffer.BlockCopy or unsafe code. Apparently .NET Core has an Array.Fill(), but

View File

@ -124,7 +124,7 @@ namespace SourceGen {
// Source generation settings.
public const string SRCGEN_DEFAULT_ASM = "srcgen-default-asm";
public const string SRCGEN_ADD_IDENT_COMMENT = "srcgen-add-ident-comment";
public const string SRCGEN_LONG_LABEL_NEW_LINE = "srcgen-long-label-new-line";
public const string SRCGEN_LABEL_NEW_LINE = "srcgen-label-new-line";
public const string SRCGEN_SHOW_CYCLE_COUNTS = "srcgen-show-cycle-counts";
// Label file generation settings.
@ -291,21 +291,20 @@ namespace SourceGen {
/// <summary>
/// Retrieves an enumerated value setting.
/// </summary>
/// <typeparam name="T">Enumerated type.</typeparam>
/// <param name="name">Setting name.</param>
/// <param name="enumType">Enum type that the value is part of.</param>
/// <param name="defaultValue">Setting default value.</param>
/// <returns>The value found, or the default value if no setting with the specified
/// name exists, or the stored value is not a member of the specified enumerated
/// type.</returns>
public int GetEnum(string name, Type enumType, int defaultValue) {
/// name exists, or the stored value is not a member of the enumeration.</returns>
public T GetEnum<T>(string name, T defaultValue) {
if (!mSettings.TryGetValue(name, out string valueStr)) {
return defaultValue;
}
try {
object o = Enum.Parse(enumType, valueStr);
return (int)o;
object o = Enum.Parse(typeof(T), valueStr);
return (T)o;
} catch (ArgumentException ae) {
Debug.WriteLine("Failed to parse " + valueStr + " (enum " + enumType + "): " +
Debug.WriteLine("Failed to parse '" + valueStr + "' (enum " + typeof(T) + "): " +
ae.Message);
return defaultValue;
}
@ -314,14 +313,20 @@ namespace SourceGen {
/// <summary>
/// Sets an enumerated setting.
/// </summary>
/// <remarks>
/// The value is output to the settings file as a string, rather than an integer, allowing
/// the correct handling even if the enumerated values are renumbered.
/// </remarks>
/// <typeparam name="T">Enumerated type.</typeparam>
/// <param name="name">Setting name.</param>
/// <param name="enumType">Enum type.</param>
/// <param name="value">Setting value (integer enum index).</param>
public void SetEnum(string name, Type enumType, int value) {
string newVal = Enum.GetName(enumType, value);
public void SetEnum<T>(string name, T value) {
if (value == null) {
throw new NotImplementedException("Can't handle a null-valued enum type");
}
string newVal = Enum.GetName(typeof(T), value);
if (newVal == null) {
// Shouldn't be possible if an enum value of the correct type is passed in.
Debug.WriteLine("Unable to get enum name type=" + enumType + " value=" + value);
Debug.WriteLine("Unable to get enum name type=" + typeof(T) + " value=" + value);
return;
}
if (!mSettings.TryGetValue(name, out string oldValue) || oldValue != newVal) {

View File

@ -62,9 +62,9 @@ namespace SourceGen.AsmGen {
private string mWorkDirectory;
/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;
/// <summary>
/// Output column widths.
@ -198,7 +198,8 @@ namespace SourceGen.AsmGen {
mFileNameBase = fileNameBase;
Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Acme);
@ -667,7 +668,9 @@ namespace SourceGen.AsmGen {
!string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}

View File

@ -57,9 +57,9 @@ namespace SourceGen.AsmGen {
private string mWorkDirectory;
/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;
/// <summary>
/// Output column widths.
@ -188,7 +188,8 @@ namespace SourceGen.AsmGen {
mFileNameBase = fileNameBase;
Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Cc65);
@ -659,7 +660,9 @@ namespace SourceGen.AsmGen {
StringComparison.InvariantCultureIgnoreCase)) {
label += ':';
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}

View File

@ -57,9 +57,9 @@ namespace SourceGen.AsmGen {
private string mWorkDirectory;
/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;
/// <summary>
/// Output column widths.
@ -174,7 +174,8 @@ namespace SourceGen.AsmGen {
mFileNameBase = fileNameBase;
Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Merlin32);
@ -606,11 +607,14 @@ namespace SourceGen.AsmGen {
// IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) {
// Split long label, but not on EQU directives (confuses the assembler).
if (mLongLabelNewLine && label.Length >= mColumnWidths[0] &&
!string.Equals(opcode, sDataOpNames.EquDirective,
if (!string.IsNullOrEmpty(label) && !string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {
mOutStream.WriteLine(label);
label = string.Empty;
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}
}
mLineBuilder.Clear();

View File

@ -73,9 +73,9 @@ namespace SourceGen.AsmGen {
private string mWorkDirectory;
/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;
/// <summary>
/// Output column widths.
@ -201,7 +201,8 @@ namespace SourceGen.AsmGen {
mFileNameBase = fileNameBase;
Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Tass64);
@ -777,7 +778,9 @@ namespace SourceGen.AsmGen {
!string.Equals(opcode, sDataOpNames.VarDirective,
StringComparison.InvariantCultureIgnoreCase)) {
if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}

View File

@ -23,11 +23,19 @@ using Asm65;
using CommonUtil;
namespace SourceGen.AsmGen {
/// <summary>
/// Code common to all assembly source generators.
/// </summary>
public class GenCommon {
public enum LabelPlacement {
Unknown = 0,
PreferSameLine,
SplitIfTooLong,
PreferSeparateLine,
}
/// <summary>
/// Generates assembly source.
///
/// This code is common to all generators.
/// </summary>
/// <param name="gen">Reference to generator object (presumably the caller).</param>
/// <param name="sw">Text output sink.</param>

View File

@ -550,10 +550,8 @@ namespace SourceGen {
// but we're only doing this on the template file, which should be small.
tmplStr = tmplStr.Replace("$ProjectName$", mProject.DataFileName);
tmplStr = tmplStr.Replace("$AppVersion$", App.ProgramVersion.ToString());
string expModeStr = ((Formatter.FormatConfig.ExpressionMode)
AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
typeof(Formatter.FormatConfig.ExpressionMode),
(int)Formatter.FormatConfig.ExpressionMode.Unknown)).ToString();
string expModeStr = AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
Formatter.FormatConfig.ExpressionMode.Unknown).ToString();
tmplStr = tmplStr.Replace("$ExpressionStyle$", expModeStr);
string dateStr = DateTime.Now.ToString("yyyy/MM/dd");
string timeStr = DateTime.Now.ToString("HH:mm:ss zzz");

View File

@ -345,7 +345,8 @@ namespace SourceGen {
settings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, "f:");
settings.SetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, true);
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, true);
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
AsmGen.GenCommon.LabelPlacement.SplitIfTooLong);
#if DEBUG
settings.SetBool(AppSettings.DEBUG_MENU_ENABLED, true);
@ -1462,10 +1463,8 @@ namespace SourceGen {
return;
}
ClipLineFormat format = (ClipLineFormat)AppSettings.Global.GetEnum(
AppSettings.CLIP_LINE_FORMAT,
typeof(ClipLineFormat),
(int)ClipLineFormat.AssemblerSource);
ClipLineFormat format = AppSettings.Global.GetEnum(AppSettings.CLIP_LINE_FORMAT,
ClipLineFormat.AssemblerSource);
int[] rightWidths = new int[] { 16, 6, 16, 80 };

Binary file not shown.

View File

@ -0,0 +1,175 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":5,
"FileDataLength":25,
"FileDataCrc32":646072439,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
"TwoByteBrk":false,
"EntryFlags":32702671,
"AutoLabelStyle":"Simple",
"AnalysisParams":{
"AnalyzeUncategorizedData":true,
"DefaultTextScanMode":"LowHighAscii",
"MinCharsForString":4,
"SeekNearbyTargets":true,
"UseRelocData":false,
"SmartPlpHandling":false,
"SmartPlbHandling":true},
"PlatformSymbolFileIdentifiers":[],
"ExtensionScriptFileIdentifiers":[],
"ProjectSyms":{
"__ENABLE_ALL_LABEL_NEWLINE":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null},
"Comment":"",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"__ENABLE_ALL_LABEL_NEWLINE",
"Value":1,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"shortnm":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"short label",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"shortnm",
"Value":16384,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"SomewhatLongName":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"somewhat longer label",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"SomewhatLongName",
"Value":16385,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"}}},
"AddressMap":[{
"Offset":0,
"Addr":4096,
"Length":25,
"PreLabel":"",
"IsRelative":false}],
"TypeHints":[{
"Low":0,
"High":0,
"Hint":"Code"}],
"StatusFlagOverrides":{
},
"Comments":{
},
"LongComments":{
},
"Notes":{
},
"UserLabels":{
"9":{
"Label":"data",
"Value":4105,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"20":{
"Label":"shortb",
"Value":4116,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"10":{
"Label":"BranchTargetLongName",
"Value":4106,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"24":{
"Label":"done",
"Value":4120,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"}},
"OperandFormats":{
},
"LvTables":{
"10":{
"Variables":[{
"DataDescriptor":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"local var with short name",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"ptr",
"Value":0,
"Source":"Variable",
"Type":"ExternalAddr",
"LabelAnno":"None"},
{
"DataDescriptor":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"local var with longer name",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"PointerWithLongName",
"Value":2,
"Source":"Variable",
"Type":"ExternalAddr",
"LabelAnno":"None"}],
"ClearPrevious":false}},
"Visualizations":[],
"VisualizationAnimations":[],
"VisualizationSets":{
},
"RelocList":{
},
"DbrValues":{
}}

View File

@ -0,0 +1,28 @@
.cpu "6502"
shortnm = $4000 ;short label
SomewhatLongName = $4001 ;somewhat longer label
* = $1000
lda shortnm
ldx SomewhatLongName
clc
bcc BranchTargetLongName
data
.byte $cc
ptr .var $00 ;local var with short name
PointerWithLongName .var $02 ;local var with longer name
BranchTargetLongName
sta ptr
stx PointerWithLongName
ldy data
lsr a
bcc shortb
shortb
nop
jmp done
done
rts

View File

@ -0,0 +1,29 @@
!cpu 6502
shortnm = $4000 ;short label
SomewhatLongName = $4001 ;somewhat longer label
* = $1000
lda shortnm
ldx SomewhatLongName
clc
bcc BranchTargetLongName
data
!byte $cc
!zone Z00000a
.ptr = $00 ;local var with short name
.PointerWithLongName = $02 ;local var with longer name
BranchTargetLongName
sta .ptr
stx .PointerWithLongName
ldy data
lsr
bcc shortb
shortb
nop
jmp done
done
rts

View File

@ -0,0 +1,28 @@
.setcpu "6502"
shortnm = $4000 ;short label
SomewhatLongName = $4001 ;somewhat longer label
.org $1000
lda shortnm
ldx SomewhatLongName
clc
bcc BranchTargetLongName
data:
.byte $cc
ptr .set $00 ;local var with short name
PointerWithLongName .set $02 ;local var with longer name
BranchTargetLongName:
sta ptr
stx PointerWithLongName
ldy data
lsr A
bcc shortb
shortb:
nop
jmp done
done:
rts

View File

@ -0,0 +1,9 @@
# 6502bench SourceGen generated linker script for 20280-label-placement
MEMORY {
MAIN: file=%O, start=%S, size=65536;
}
SEGMENTS {
CODE: load=MAIN, type=rw;
}
FEATURES {}
SYMBOLS {}

View File

@ -0,0 +1,27 @@
shortnm equ $4000 ;short label
SomewhatLongName equ $4001 ;somewhat longer label
org $1000
lda shortnm
ldx SomewhatLongName
clc
bcc BranchTargetLongName
data
dfb $cc
]ptr equ $00 ;local var with short name
]PointerWithLongName equ $02 ;local var with longer name
BranchTargetLongName
sta ]ptr
stx ]PointerWithLongName
ldy data
lsr A
bcc shortb
shortb
nop
jmp done
done
rts

View File

@ -34,17 +34,19 @@ be opened as the project file.
### Overriding Settings ###
All tests are run with a fixed set of app settings, so that the tests look
the same regardless of how the assemblers are configured. For example,
upper-case conversion is disabled, and cycle counts are not shown.
the same regardless of how the assemblers are configured in the app settings
file. For example, upper-case conversion is disabled, and cycle counts are
not shown.
Sometimes a test will want to exercise one of these settings, so we need
a way to tell the test harness to override the default. We do this by
creating project symbols.
creating project symbols:
| Name | Value | Description
| ---------------------- | ----- | -------------------------------------------|
| __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line |
| __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments |
| Name | Value | Description
| -------------------------- | ----- | -------------------------------------------|
| __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line |
| __ENABLE_ALL_LABEL_NEWLINE | any | Puts all labels on their own line |
| __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments |
### Execution ###
@ -74,7 +76,7 @@ the "retain output" box in the test harness, the directory and its contents
will remain. This allows you to examine the outputs when investigating
failures.
As a safety measure, the directory will NOT be removed if it contains files
As a safety measure, a directory will NOT be removed if it contains files
that the test harness doesn't recognize.
### Updating Tests ###
@ -115,4 +117,3 @@ for a full explanation.
Some test projects and data files for exercising the visualization generators.
Not part of a formal test; load the projects and eyeball the results.

View File

@ -0,0 +1,32 @@
; Copyright 2024 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0).
;
; The symbol __ENABLE_ALL_LABEL_NEWLINE must be defined in the project
; symbols, so that labels are placed on their own lines whenever possible.
;
; Assembler: Merlin 32
org $1000
shortnm equ $4000
SomewhatLongName equ $4001
lda shortnm
ldx SomewhatLongName
clc
bcc BranchTargetLongName
data dfb $cc
]ptr equ $00
]PointerWithLongName equ $02
BranchTargetLongName
sta ]ptr
stx ]PointerWithLongName
ldy data
lsr A
bcc shortb
shortb nop
jmp done
done rts

View File

@ -430,7 +430,8 @@ namespace SourceGen.Tests {
// Don't break lines with long labels. That way we can redefine "long"
// without breaking our tests. (This is purely cosmetic.)
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.PreferSameLine);
// This could be on or off. Off seems less distracting.
settings.SetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS, false);
@ -455,17 +456,23 @@ namespace SourceGen.Tests {
}
/// <summary>
/// Applies app setting overrides that were specified in the project settings.
/// Applies app setting overrides that were specified in the project properties.
/// </summary>
private void ApplyProjectSettings(AppSettings settings, DisasmProject project) {
// We could probably make this a more general mechanism, but that would strain
// things a bit, since we need to know the settings name, bool/int/string, and
// desired value. Easier to just have a set of named features.
const string ENABLE_LABEL_NEWLINE = "__ENABLE_LABEL_NEWLINE";
const string ENABLE_ALL_LABEL_NEWLINE = "__ENABLE_ALL_LABEL_NEWLINE";
const string ENABLE_CYCLE_COUNTS = "__ENABLE_CYCLE_COUNTS";
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_LABEL_NEWLINE)) {
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, true);
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);
}
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_ALL_LABEL_NEWLINE)) {
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.PreferSeparateLine);
}
if (project.ProjectProps.ProjectSyms.ContainsKey(ENABLE_CYCLE_COUNTS)) {
settings.SetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS, true);

View File

@ -75,8 +75,7 @@ namespace SourceGen.Tools.WpfGui {
public void Window_Loaded(object sender, RoutedEventArgs e) {
// Restore chart mode setting.
ChartMode mode = (ChartMode)AppSettings.Global.GetEnum(
AppSettings.A2SC_MODE, typeof(ChartMode), (int)ChartMode.HiRes1_L);
ChartMode mode = AppSettings.Global.GetEnum(AppSettings.A2SC_MODE, ChartMode.HiRes1_L);
int index = 0;
for (int i = 0; i < ChartModeItems.Length; i++) {
if (ChartModeItems[i].Mode == mode) {
@ -107,7 +106,7 @@ namespace SourceGen.Tools.WpfGui {
return;
}
AppSettings.Global.SetEnum(AppSettings.A2SC_MODE, typeof(ChartMode), (int)item.Mode);
AppSettings.Global.SetEnum(AppSettings.A2SC_MODE, item.Mode);
string text;
switch (item.Mode) {

View File

@ -55,8 +55,7 @@ namespace SourceGen.Tools.WpfGui {
public void Window_Loaded(object sender, RoutedEventArgs e) {
// Restore chart mode setting.
ChartMode mode = (ChartMode)AppSettings.Global.GetEnum(
AppSettings.ASCCH_MODE, typeof(ChartMode), (int)ChartMode.Standard);
ChartMode mode = AppSettings.Global.GetEnum(AppSettings.ASCCH_MODE, ChartMode.Standard);
int index = 0;
for (int i = 0; i < ChartModeItems.Length; i++) {
if (ChartModeItems[i].Mode == mode) {
@ -87,7 +86,7 @@ namespace SourceGen.Tools.WpfGui {
return;
}
AppSettings.Global.SetEnum(AppSettings.ASCCH_MODE, typeof(ChartMode), (int)item.Mode);
AppSettings.Global.SetEnum(AppSettings.ASCCH_MODE, item.Mode);
//
// Draw box contents.

View File

@ -111,8 +111,8 @@ namespace SourceGen.Tools.WpfGui {
AsciiOnlyDump = AppSettings.Global.GetBool(AppSettings.HEXD_ASCII_ONLY, false);
// Restore conv mode setting.
CharConvMode mode = (CharConvMode)AppSettings.Global.GetEnum(
AppSettings.HEXD_CHAR_CONV, typeof(CharConvMode), (int)CharConvMode.Ascii);
CharConvMode mode =
AppSettings.Global.GetEnum(AppSettings.HEXD_CHAR_CONV, CharConvMode.Ascii);
int index = 0;
for (int i = 0; i < CharConvItems.Length; i++) {
if (CharConvItems[i].Mode == mode) {
@ -156,8 +156,7 @@ namespace SourceGen.Tools.WpfGui {
// Keep app settings up to date.
AppSettings.Global.SetBool(AppSettings.HEXD_ASCII_ONLY, mAsciiOnlyDump);
AppSettings.Global.SetEnum(AppSettings.HEXD_CHAR_CONV, typeof(CharConvMode),
(int)item.Mode);
AppSettings.Global.SetEnum(AppSettings.HEXD_CHAR_CONV, item.Mode);
mFormatter = new Formatter(config);
HexDumpLines.Reformat(mFormatter);

View File

@ -112,8 +112,8 @@ namespace SourceGen.Tools.WpfGui {
public void Window_Loaded(object sender, RoutedEventArgs e) {
// Restore chart settings.
CpuDef.CpuType type = (CpuDef.CpuType)AppSettings.Global.GetEnum(
AppSettings.INSTCH_MODE, typeof(CpuDef.CpuType), (int)CpuDef.CpuType.Cpu6502);
CpuDef.CpuType type =
AppSettings.Global.GetEnum(AppSettings.INSTCH_MODE, CpuDef.CpuType.Cpu6502);
ShowUndocumented = AppSettings.Global.GetBool(AppSettings.INSTCH_SHOW_UNDOC, true);
int index = 0;
@ -146,8 +146,7 @@ namespace SourceGen.Tools.WpfGui {
}
// Push current choice to settings.
AppSettings.Global.SetEnum(AppSettings.INSTCH_MODE, typeof(CpuDef.CpuType),
(int)item.Type);
AppSettings.Global.SetEnum(AppSettings.INSTCH_MODE, item.Type);
AppSettings.Global.SetBool(AppSettings.INSTCH_SHOW_UNDOC, mShowUndocumented);
// Populate the items source.

View File

@ -820,10 +820,20 @@ limitations under the License.
<TextBlock Text="General code generation:" Margin="4,16,0,0"/>
<CheckBox Content="Show cycle counts in comments" Margin="4,8,0,0"
IsChecked="{Binding ShowCycleCountsAsm}"/>
<CheckBox Content="Put long labels on separate line" Margin="4,8,0,0"
IsChecked="{Binding LongLabelNewLine}"/>
<CheckBox Content="Identify assembler in output" Margin="4,8,0,0"
<CheckBox Content="Identify assembler in output" Margin="4,6,0,0"
IsChecked="{Binding AddIdentComment}"/>
<StackPanel Orientation="Vertical" Margin="10,6,0,0">
<TextBlock Text="Put labels on their own line..."/>
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
Content="Only when required"
IsChecked="{Binding LabelPlacement_PreferSameLine}"/>
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
Content="When the label is wider than the field"
IsChecked="{Binding LabelPlacement_SplitIfTooLong}"/>
<RadioButton GroupName="labelLineGroup" Margin="0,4,0,0"
Content="Whenever possible"
IsChecked="{Binding LabelPlacement_PreferSeparateLine}"/>
</StackPanel>
</StackPanel>
</TabItem>

View File

@ -31,6 +31,7 @@ using CommonUtil;
using AssemblerInfo = SourceGen.AsmGen.AssemblerInfo;
using AssemblerConfig = SourceGen.AsmGen.AssemblerConfig;
using ExpressionMode = Asm65.Formatter.FormatConfig.ExpressionMode;
using LabelPlacement = SourceGen.AsmGen.GenCommon.LabelPlacement;
namespace SourceGen.WpfGui {
/// <summary>
@ -280,8 +281,8 @@ namespace SourceGen.WpfGui {
UpperOperandXY = mSettings.GetBool(AppSettings.FMT_UPPER_OPERAND_XY, false);
Debug.Assert(clipboardFormatComboBox.Items.Count == sClipboardFormatItems.Length);
int clipIndex = mSettings.GetEnum(AppSettings.CLIP_LINE_FORMAT,
typeof(MainController.ClipLineFormat), 0);
int clipIndex = (int)mSettings.GetEnum(AppSettings.CLIP_LINE_FORMAT,
MainController.ClipLineFormat.AssemblerSource);
if (clipIndex >= 0 && clipIndex < sClipboardFormatItems.Length) {
// require Value == clipIndex because we're lazy and don't want to search
Debug.Assert((int)sClipboardFormatItems[clipIndex].Value == clipIndex);
@ -414,8 +415,7 @@ namespace SourceGen.WpfGui {
private void ClipboardFormatComboBox_SelectionChanged(object sender,
SelectionChangedEventArgs e) {
ClipboardFormatItem item = (ClipboardFormatItem)clipboardFormatComboBox.SelectedItem;
mSettings.SetEnum(AppSettings.CLIP_LINE_FORMAT, typeof(MainController.ClipLineFormat),
(int)item.Value);
mSettings.SetEnum(AppSettings.CLIP_LINE_FORMAT, item.Value);
IsDirty = true;
}
@ -757,14 +757,6 @@ namespace SourceGen.WpfGui {
IsDirty = true;
}
}
public bool LongLabelNewLine {
get { return mSettings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false); }
set {
mSettings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, value);
OnPropertyChanged();
IsDirty = true;
}
}
public bool AddIdentComment {
get { return mSettings.GetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, false); }
set {
@ -774,6 +766,58 @@ namespace SourceGen.WpfGui {
}
}
// label placement radio buttons
public bool LabelPlacement_PreferSameLine {
get {
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.SplitIfTooLong);
return place == LabelPlacement.PreferSameLine;
}
set {
if (value) {
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.PreferSameLine);
LabelPlacementChanged();
IsDirty = true;
}
}
}
public bool LabelPlacement_SplitIfTooLong {
get {
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.SplitIfTooLong);
return place == LabelPlacement.SplitIfTooLong;
}
set {
if (value) {
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.SplitIfTooLong);
LabelPlacementChanged();
IsDirty = true;
}
}
}
public bool LabelPlacement_PreferSeparateLine {
get {
LabelPlacement place = mSettings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.SplitIfTooLong);
return place == LabelPlacement.PreferSeparateLine;
}
set {
if (value) {
mSettings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
LabelPlacement.PreferSeparateLine);
LabelPlacementChanged();
IsDirty = true;
}
}
}
private void LabelPlacementChanged() {
OnPropertyChanged(nameof(LabelPlacement_PreferSameLine));
OnPropertyChanged(nameof(LabelPlacement_SplitIfTooLong));
OnPropertyChanged(nameof(LabelPlacement_PreferSeparateLine));
}
private void Loaded_AsmConfig() {
asmConfigComboBox.SelectedItem = AssemblerInfo.GetAssemblerInfo(mInitialAsmId);
if (asmConfigComboBox.SelectedIndex < 0) {

View File

@ -293,8 +293,7 @@ namespace SourceGen.WpfGui {
AnalyzeStringRanges(item.Mode);
UpdateControls();
AppSettings.Global.SetEnum(AppSettings.OPED_DEFAULT_STRING_ENCODING,
typeof(TextScanMode), (int)item.Mode);
AppSettings.Global.SetEnum(AppSettings.OPED_DEFAULT_STRING_ENCODING, item.Mode);
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
@ -780,9 +779,8 @@ namespace SourceGen.WpfGui {
// 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);
TextScanMode textMode = AppSettings.Global.GetEnum(
AppSettings.OPED_DEFAULT_STRING_ENCODING, TextScanMode.LowHighAscii);
if (dfd == null) {
radioDefaultFormat.IsChecked = true;

View File

@ -235,8 +235,8 @@ namespace SourceGen.WpfGui {
AsmCommentColWidth = colWidths[3];
}
TextMode mode = (TextMode)AppSettings.Global.GetEnum(AppSettings.EXPORT_TEXT_MODE,
typeof(TextMode), (int)TextMode.PlainText);
TextMode mode = AppSettings.Global.GetEnum(AppSettings.EXPORT_TEXT_MODE,
TextMode.PlainText);
if (mode == TextMode.PlainText) {
TextModePlain = true;
} else {
@ -273,7 +273,7 @@ namespace SourceGen.WpfGui {
} else {
mode = TextMode.Csv;
}
AppSettings.Global.SetEnum(AppSettings.EXPORT_TEXT_MODE, typeof(TextMode), (int)mode);
AppSettings.Global.SetEnum(AppSettings.EXPORT_TEXT_MODE, mode);
}
/// <summary>

View File

@ -55,17 +55,15 @@ namespace SourceGen.WpfGui {
Owner = owner;
DataContext = this;
Format =
(LabelFileGenerator.LabelFmt)AppSettings.Global.GetEnum(AppSettings.LABGEN_FORMAT,
typeof(LabelFileGenerator.LabelFmt), (int)LabelFileGenerator.LabelFmt.VICE);
Format = AppSettings.Global.GetEnum(AppSettings.LABGEN_FORMAT,
LabelFileGenerator.LabelFmt.VICE);
UpdateFormats();
mIncludeAutoLabels = AppSettings.Global.GetBool(AppSettings.LABGEN_INCLUDE_AUTO, false);
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
// Save settings.
AppSettings.Global.SetEnum(AppSettings.LABGEN_FORMAT,
typeof(LabelFileGenerator.LabelFmt), (int)Format);
AppSettings.Global.SetEnum(AppSettings.LABGEN_FORMAT, Format);
AppSettings.Global.SetBool(AppSettings.LABGEN_INCLUDE_AUTO, mIncludeAutoLabels);
DialogResult = true;
}