1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-25 05:29:31 +00:00

Instruction operand editor rework, part 3

Implemented editing of labels and project symbols.

Also, cleaned up the local variable edit code.
This commit is contained in:
Andy McFadden 2019-09-08 16:41:54 -07:00
parent e8ae534879
commit 4d9d5e2ecf
6 changed files with 456 additions and 206 deletions

View File

@ -246,7 +246,7 @@ namespace SourceGen {
/// </summary>
/// <param name="proj">Project reference.</param>
/// <param name="offset">Start offset.</param>
/// <returns></returns>
/// <returns>Base offset.</returns>
public static int GetBaseOperandOffset(DisasmProject proj, int offset) {
Debug.Assert(offset >= 0 && offset < proj.FileDataLength);
while (!proj.GetAnattrib(offset).IsStart) {
@ -302,6 +302,8 @@ namespace SourceGen {
// descriptor includes this offset, we set the target offset to that.
// (Note the uncategorized data pass hasn't run yet, so only instructions
// and offsets identified by users or scripts have been categorized.)
//
// ?? Can we use GetBaseOperandOffset(), which searches for IsStart?
int scanOffset = targetOffset;
while (--scanOffset >= 0) {
FormatDescriptor dfd = mAnattribs[scanOffset].DataDescriptor;

View File

@ -1214,8 +1214,7 @@ namespace SourceGen {
new XrefSet.Xref(offset, true, xrefType, accType, adj));
}
} else if (SymbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
// Is this a reference to a project/platform symbol? We also handle
// local variables here.
// Is this a reference to a project/platform symbol?
if (sym.SymbolSource == Symbol.Source.Project ||
sym.SymbolSource == Symbol.Source.Platform) {
DefSymbol defSym = sym as DefSymbol;
@ -1226,8 +1225,10 @@ namespace SourceGen {
defSym.Xrefs.Add(
new XrefSet.Xref(offset, true, xrefType, accType, adj));
} else {
Debug.WriteLine("NOTE: not xrefing '" + sym.Label + "'");
Debug.Assert(false); // not possible?
// Can get here if somebody creates an address operand symbol
// that refers to a local variable.
Debug.WriteLine("NOTE: not xrefing +" + offset.ToString("x6") +
" " + sym);
}
}
} else if (dfd.FormatSubType == FormatDescriptor.SubType.Address) {

View File

@ -1849,75 +1849,6 @@ namespace SourceGen {
}
private void EditInstructionOperand(int offset) {
#if false
EditInstructionOperand dlg = new EditInstructionOperand(mMainWin, offset,
mProject, mOutputFormatter);
// We'd really like to pass in an indication of what the "default" format actually
// resolved to, but we don't always know. If this offset has a FormatDescriptor,
// we might not have auto-generated the label that would have been used otherwise.
// We're editing the FormatDescriptor from OperandFormats, not Anattribs;
// the latter may have auto-generated stuff.
if (mProject.OperandFormats.TryGetValue(offset, out FormatDescriptor dfd)) {
dlg.FormatDescriptor = dfd;
}
dlg.ShowDialog();
if (dlg.DialogResult != true) {
return;
}
ChangeSet cs = new ChangeSet(1);
// Handle shortcut actions.
if (dlg.FormatDescriptor != dfd && dlg.ShortcutAction !=
WpfGui.EditInstructionOperand.SymbolShortcutAction.CreateLabelInstead) {
// Note EditOperand returns a null descriptor when the user selects Default.
// This is different from how EditData works, since that has to deal with
// multiple regions.
Debug.WriteLine("Changing " + dfd + " to " + dlg.FormatDescriptor);
UndoableChange uc = UndoableChange.CreateOperandFormatChange(offset,
dfd, dlg.FormatDescriptor);
cs.Add(uc);
} else if (dfd != null && dlg.ShortcutAction ==
WpfGui.EditInstructionOperand.SymbolShortcutAction.CreateLabelInstead) {
Debug.WriteLine("Removing existing label for CreateLabelInstead");
UndoableChange uc = UndoableChange.CreateOperandFormatChange(offset,
dfd, null);
cs.Add(uc);
} else {
Debug.WriteLine("No change to format descriptor");
}
switch (dlg.ShortcutAction) {
case WpfGui.EditInstructionOperand.SymbolShortcutAction.CreateLabelInstead:
case WpfGui.EditInstructionOperand.SymbolShortcutAction.CreateLabelAlso:
Debug.Assert(!mProject.UserLabels.ContainsKey(dlg.ShortcutArg));
Anattrib targetAttr = mProject.GetAnattrib(dlg.ShortcutArg);
Symbol newLabel = new Symbol(dlg.FormatDescriptor.SymbolRef.Label,
targetAttr.Address, Symbol.Source.User, Symbol.Type.LocalOrGlobalAddr);
UndoableChange uc = UndoableChange.CreateLabelChange(dlg.ShortcutArg,
null, newLabel);
cs.Add(uc);
break;
case WpfGui.EditInstructionOperand.SymbolShortcutAction.CreateProjectSymbolAlso:
Debug.Assert(!mProject.ProjectProps.ProjectSyms.ContainsKey(
dlg.FormatDescriptor.SymbolRef.Label));
DefSymbol defSym = new DefSymbol(dlg.FormatDescriptor.SymbolRef.Label,
dlg.ShortcutArg, Symbol.Source.Project, Symbol.Type.ExternalAddr,
FormatDescriptor.SubType.Hex, string.Empty, string.Empty);
ProjectProperties newProps = new ProjectProperties(mProject.ProjectProps);
newProps.ProjectSyms.Add(defSym.Label, defSym);
uc = UndoableChange.CreateProjectPropertiesChange(
mProject.ProjectProps, newProps);
cs.Add(uc);
break;
case WpfGui.EditInstructionOperand.SymbolShortcutAction.None:
break;
}
#else
EditInstructionOperand dlg = new EditInstructionOperand(mMainWin, mProject,
offset, mOutputFormatter);
if (dlg.ShowDialog() != true) {
@ -1934,18 +1865,45 @@ namespace SourceGen {
Debug.WriteLine("No change to operand format");
}
// We can't delete an LvTable, so a null value here means no changes made.
// Check for changes to a local variable table. The edit dialog can't delete an
// entire table, so a null value here means no changes were made.
if (dlg.LocalVariableResult != null) {
int tableOffset = dlg.LocalVariableTableOffsetResult;
LocalVariableTable lvt = mProject.LvTables[tableOffset];
Debug.Assert(lvt != null); // cannot create or delete a table
Debug.Assert(lvt != null); // cannot create a table either
UndoableChange uc = UndoableChange.CreateLocalVariableTableChange(tableOffset,
lvt, dlg.LocalVariableResult);
cs.Add(uc);
} else {
Debug.WriteLine("No change to LvTable");
}
#endif
// Check for changes to label at operand target address. Labels can be created,
// modified, or deleted.
if (dlg.SymbolEditOffsetResult >= 0) {
mProject.UserLabels.TryGetValue(dlg.SymbolEditOffsetResult, out Symbol oldLabel);
UndoableChange uc = UndoableChange.CreateLabelChange(dlg.SymbolEditOffsetResult,
oldLabel, dlg.SymbolEditResult);
cs.Add(uc);
} else {
Debug.WriteLine("No change to label");
}
// Check for changes to a project property. The dialog can create a new entry or
// modify an existing entry.
if (dlg.ProjectPropertyResult != null) {
DefSymbol defSym = dlg.ProjectPropertyResult;
ProjectProperties newProps = new ProjectProperties(mProject.ProjectProps);
// Add new entry, or replace existing entry.
newProps.ProjectSyms.Remove(dlg.PrevProjectPropertyResult.Label);
newProps.ProjectSyms.Add(defSym.Label, defSym);
UndoableChange uc = UndoableChange.CreateProjectPropertiesChange(
mProject.ProjectProps, newProps);
cs.Add(uc);
} else {
Debug.WriteLine("No change to project property");
}
Debug.WriteLine("EditInstructionOperand: " + cs.Count + " changes");
if (cs.Count != 0) {
ApplyUndoableChanges(cs);

View File

@ -132,7 +132,8 @@ namespace SourceGen.WpfGui {
: this(owner, formatter, defList, defSym, symbolTable, false, false) { }
/// <summary>
/// Constructor, for editing a local variable.
/// Constructor, for editing a local variable, or editing a project symbol with
/// the value field locked.
/// </summary>
public EditDefSymbol(Window owner, Formatter formatter,
SortedList<string, DefSymbol> defList, DefSymbol defSym,

View File

@ -37,6 +37,15 @@ limitations under the License.
<system:String x:Key="str_CreateLocalVariable">Create Local Variable</system:String>
<system:String x:Key="str_EditLocalVariable">Edit Local Variable</system:String>
<system:String x:Key="str_LvMatchFoundAddress">Match found (ZP address):</system:String>
<system:String x:Key="str_LvMatchFoundConstant">Match found (StackRel constant):</system:String>
<system:String x:Key="str_CreateLabel">Create Label</system:String>
<system:String x:Key="str_EditLabel">Edit Label</system:String>
<system:String x:Key="str_CreateProjectSymbol">Create Project Symbol</system:String>
<system:String x:Key="str_EditProjectSymbol">Edit Project Symbol</system:String>
<system:String x:Key="str_CurrentLabel">Current label:</system:String>
<system:String x:Key="str_CurrentLabelAdjustedFmt">Current label (adjusted {0}):</system:String>
</Window.Resources>
<Grid Margin="8" Width="500">
@ -102,6 +111,8 @@ limitations under the License.
Text="{Binding SymbolLabel, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="(auto)" Foreground="Red" Margin="4,0,0,0"
Visibility="{Binding IsSymbolAuto, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text="(var)" Foreground="Red" Margin="4,0,0,0"
Visibility="{Binding IsSymbolVar, Converter={StaticResource BoolToVis}}"/>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="18,4,0,0"
IsEnabled="{Binding IsPartPanelEnabled}">
@ -145,17 +156,42 @@ limitations under the License.
<!-- numeric reference box, for labels and project/platform symbols -->
<GroupBox Grid.Column="0" Grid.Row="4" Margin="0,4,0,0" Padding="2,4" Header="Numeric Address Reference">
<StackPanel>
<TextBlock Text="Operand is not an 8, 16, or 24-bit address"/>
<TextBlock Text="Address is inside the project"/>
<TextBlock Text="Address is NOT the start of a thing"/>
<TextBlock Text="Label at target address: ______"/>
<Button Width="120" Content="Edit Label"/>
<TextBlock Text="Operand is not an 8, 16, or 24-bit address" TextWrapping="Wrap"
Visibility="{Binding ShowNarNotAddress, Converter={StaticResource BoolToVis}}"/>
<!--<TextBlock Text="Operand does not reference the start of an instruction or data item"
TextWrapping="Wrap" IsEnabled="{Binding ShowNarNotStart}"/>-->
<StackPanel Visibility="{Binding ShowNarEditLabel, Converter={StaticResource BoolToVis}}">
<TextBlock Text="Operand's address is inside project"/>
<StackPanel Visibility="{Binding ShowNarCurrentLabel, Converter={StaticResource BoolToVis}}">
<TextBlock Text="{Binding NarLabelOffsetText, FallbackValue=Current label (adjusted +1):}"/>
<TextBlock Margin="16,2,0,0" FontFamily="{StaticResource GeneralMonoFont}"
Text="{Binding NarTargetLabel, FallbackValue=LABEL_67890123456789012345678901}"/>
</StackPanel>
<Button Width="150" Margin="0,8,0,0" HorizontalAlignment="Left"
Content="{Binding CreateEditLabelText, FallbackValue=Diddle Label}"
Click="EditLabel_Click"/>
</StackPanel>
<StackPanel Visibility="{Binding ShowNarExternalSymbol, Converter={StaticResource BoolToVis}}">
<TextBlock Text="Operand's address is outside project" Margin="0,0,0,2"/>
<StackPanel Visibility="{Binding ShowNarPlatformSymbol, Converter={StaticResource BoolToVis}}">
<TextBlock Text="Found a matching symbol in platform defs:"/>
<TextBlock Margin="16,2,0,0" FontFamily="{StaticResource GeneralMonoFont}"
Text="{Binding NarPlatformSymbol, FallbackValue=PLATFORM_SYMBOL}"/>
</StackPanel>
<TextBlock Text="No matching project symbol"
Visibility="{Binding ShowNarNoProjectMatch, Converter={StaticResource BoolToVis}}"/>
<StackPanel Visibility="{Binding ShowNarProjectSymbol, Converter={StaticResource BoolToVis}}">
<TextBlock Text="Found matching project symbol:"/>
<TextBlock Margin="16,2,0,0" FontFamily="{StaticResource GeneralMonoFont}"
Text="{Binding NarProjectSymbol, FallbackValue=PROJECT_SYMBOL}"/>
</StackPanel>
<Button Width="150" Margin="0,8,0,0" HorizontalAlignment="Left"
Content="{Binding CreateEditProjectSymbolText, FallbackValue=Diddle Project Symbol}"
Click="EditProjectSymbol_Click"/>
</StackPanel>
<TextBlock Text="Address is outside the project"/>
<TextBlock Text="No matching platform / project symbol"/>
<TextBlock Text="Found matching {platform|project} symbol"/>
<TextBlock Text="[______] ($value)"/>
<Button Width="120" Content="Create/Edit Project Symbol"/>
</StackPanel>
</GroupBox>
@ -168,20 +204,19 @@ limitations under the License.
Visibility="{Binding ShowLvTableNotFound, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text="No matching local variable found" TextWrapping="Wrap"
Visibility="{Binding ShowLvNoMatchFound, Converter={StaticResource BoolToVis}}"/>
<StackPanel Orientation="Horizontal"
Visibility="{Binding ShowLvMatchFound, Converter={StaticResource BoolToVis}}">
<TextBlock Text="Match found:"/>
<TextBlock Margin="4,2,0,0" FontFamily="{StaticResource GeneralMonoFont}"
Text="{Binding LocalVariableLabel, FallbackValue=VAR_NAME}"/>
<StackPanel Visibility="{Binding ShowLvMatchFound, Converter={StaticResource BoolToVis}}">
<TextBlock Text="{Binding LvMatchFoundText, FallbackValue=Match found (ZP address):}"/>
<TextBlock Margin="16,2,0,0" FontFamily="{StaticResource GeneralMonoFont}"
Text="{Binding LocalVariableLabel, FallbackValue=VAR_NAME_90123456789012345678901}"/>
</StackPanel>
<Button Width="150" Margin="0,4,0,0"
<Button Width="150" Margin="0,8,0,0" HorizontalAlignment="Left"
Content="{Binding CreateEditLocalVariableText, FallbackValue=Diddle Local Variable}"
Visibility="{Binding ShowLvCreateEditButton, Converter={StaticResource BoolToVis}}"
Click="EditLocalVariableButton_Click"/>
</StackPanel>
</GroupBox>
<DockPanel Grid.Column="0" Grid.Row="5" Grid.ColumnSpan="2" Margin="0,16,0,0" LastChildFill="False">
<DockPanel Grid.Column="0" Grid.Row="5" Grid.ColumnSpan="2" Margin="0,8,0,0" LastChildFill="False">
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" IsCancel="True" Margin="8,0,0,0"/>
<Button DockPanel.Dock="Right" Content="OK" Width="70" IsDefault="True"
IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>

View File

@ -33,7 +33,6 @@ namespace SourceGen.WpfGui {
/// </summary>
public FormatDescriptor FormatDescriptorResult { get; private set; }
/// <summary>
/// Updated local variable table. Will be null if no changes were made.
/// </summary>
@ -44,12 +43,42 @@ namespace SourceGen.WpfGui {
/// </summary>
public int LocalVariableTableOffsetResult { get; private set; }
/// <summary>
/// Offset of label that was edited. A non-negative value here indicates that an
/// edit has been made.
/// </summary>
public int SymbolEditOffsetResult { get; private set; }
/// <summary>
/// Edited project property, or null if no changes were made.
/// </summary>
public DefSymbol ProjectPropertyResult { get; private set; }
/// <summary>
/// The project property that was modified, or null if none.
/// </summary>
public DefSymbol PrevProjectPropertyResult { get; private set; }
/// <summary>
/// Updated label.
/// </summary>
public Symbol SymbolEditResult { get; private set; }
private readonly string SYMBOL_NOT_USED;
private readonly string SYMBOL_UNKNOWN;
private readonly string SYMBOL_INVALID;
private readonly string CREATE_LOCAL_VARIABLE;
private readonly string EDIT_LOCAL_VARIABLE;
private readonly string LV_MATCH_FOUND_ADDRESS;
private readonly string LV_MATCH_FOUND_CONSTANT;
private readonly string CREATE_LABEL;
private readonly string EDIT_LABEL;
private readonly string CREATE_PROJECT_SYMBOL;
private readonly string EDIT_PROJECT_SYMBOL;
private readonly string CURRENT_LABEL;
private readonly string CURRENT_LABEL_ADJUSTED_FMT;
/// <summary>
/// Project reference.
@ -127,6 +156,15 @@ namespace SourceGen.WpfGui {
CREATE_LOCAL_VARIABLE = (string)FindResource("str_CreateLocalVariable");
EDIT_LOCAL_VARIABLE = (string)FindResource("str_EditLocalVariable");
LV_MATCH_FOUND_ADDRESS = (string)FindResource("str_LvMatchFoundAddress");
LV_MATCH_FOUND_CONSTANT = (string)FindResource("str_LvMatchFoundConstant");
CREATE_LABEL = (string)FindResource("str_CreateLabel");
EDIT_LABEL = (string)FindResource("str_EditLabel");
CREATE_PROJECT_SYMBOL = (string)FindResource("str_CreateProjectSymbol");
EDIT_PROJECT_SYMBOL = (string)FindResource("str_EditProjectSymbol");
CURRENT_LABEL = (string)FindResource("str_CurrentLabel");
CURRENT_LABEL_ADJUSTED_FMT = (string)FindResource("str_CurrentLabelAdjustedFmt");
Debug.Assert(offset >= 0 && offset < project.FileDataLength);
mOpDef = project.CpuDef.GetOpDef(project.FileData[offset]);
@ -146,7 +184,8 @@ namespace SourceGen.WpfGui {
private void Window_Loaded(object sender, RoutedEventArgs e) {
BasicFormat_Loaded();
NumericRefs_Loaded();
NumericReferences_Loaded();
LocalVariables_Loaded();
mLoadDone = true;
}
@ -172,6 +211,14 @@ namespace SourceGen.WpfGui {
Debug.WriteLine("No change to LvTable, not exporting");
}
}
if (mLabelHasBeenEdited) {
SymbolEditOffsetResult = mEditedLabelOffset;
SymbolEditResult = mEditedLabel;
}
ProjectPropertyResult = mEditedProjectSymbol;
DialogResult = true;
}
@ -186,6 +233,7 @@ namespace SourceGen.WpfGui {
// Parts panel IsEnabled depends directly on formatSymbolButton.IsChecked.
IsValid = true;
IsSymbolAuto = false;
IsSymbolVar = false;
IsPartPanelEnabled = false;
SymbolValueDecimal = string.Empty;
if (FormatSymbol) {
@ -200,8 +248,17 @@ namespace SourceGen.WpfGui {
// around it because FormatDescriptors are weak references (replace auto
// label with user label, reference non-existent auto label, remove user
// label). We could try harder, but currently not necessary.
//
// Referencing an auto label is unwise because we use weak references
// by name, and auto labels can appear, disappear, or be renamed.
IsValid = false;
IsSymbolAuto = true;
} else if (sym.SymbolSource == Symbol.Source.Variable) {
// Local variables can be de-duplicated and uniquified, so referring to
// them by name doesn't make sense. The numeric operand formatter will
// disregard attempts to use them in this way.
IsValid = false;
IsSymbolVar = true;
}
SymbolValueHex = mFormatter.FormatHexValue(sym.Value, 4);
@ -440,6 +497,12 @@ namespace SourceGen.WpfGui {
}
private bool mIsSymbolAuto;
public bool IsSymbolVar{
get { return mIsSymbolVar; }
set { mIsSymbolVar = value; OnPropertyChanged(); }
}
private bool mIsSymbolVar;
public string SymbolValueHex {
get { return mSymbolValueHex; }
set { mSymbolValueHex = value; OnPropertyChanged(); }
@ -643,6 +706,239 @@ namespace SourceGen.WpfGui {
#region Numeric References
public bool ShowNarNotAddress {
get { return mShowNarNotAddress; }
set { mShowNarNotAddress = value; OnPropertyChanged(); }
}
private bool mShowNarNotAddress;
public bool ShowNarEditLabel {
get { return mShowNarEditLabel; }
set { mShowNarEditLabel = value; OnPropertyChanged(); }
}
private bool mShowNarEditLabel;
public bool ShowNarCurrentLabel {
get { return mShowNarCurrentLabel; }
set { mShowNarCurrentLabel = value; OnPropertyChanged(); }
}
private bool mShowNarCurrentLabel;
public string NarLabelOffsetText {
get { return mNarLabelOffsetText; }
set { mNarLabelOffsetText = value; OnPropertyChanged(); }
}
private string mNarLabelOffsetText;
public string NarTargetLabel {
get { return mNarTargetLabel; }
set { mNarTargetLabel = value; OnPropertyChanged(); }
}
private string mNarTargetLabel;
public string CreateEditLabelText {
get { return mCreateEditLabelText; }
set { mCreateEditLabelText = value; OnPropertyChanged(); }
}
private string mCreateEditLabelText;
public bool ShowNarExternalSymbol {
get { return mShowNarExternalSymbol; }
set { mShowNarExternalSymbol = value; OnPropertyChanged(); }
}
private bool mShowNarExternalSymbol;
public bool ShowNarPlatformSymbol {
get { return mShowNarPlatformSymbol; }
set { mShowNarPlatformSymbol = value; OnPropertyChanged(); }
}
private bool mShowNarPlatformSymbol;
public string NarPlatformSymbol {
get { return mNarPlatformSymbol; }
set { mNarPlatformSymbol = value; OnPropertyChanged(); }
}
private string mNarPlatformSymbol;
public bool ShowNarNoProjectMatch {
get { return mShowNarNoProjectMatch; }
set { mShowNarNoProjectMatch = value; OnPropertyChanged(); }
}
private bool mShowNarNoProjectMatch;
public bool ShowNarProjectSymbol {
get { return mShowNarProjectSymbol; }
set { mShowNarProjectSymbol = value; OnPropertyChanged(); }
}
private bool mShowNarProjectSymbol;
public string NarProjectSymbol {
get { return mNarProjectSymbol; }
set { mNarProjectSymbol = value; OnPropertyChanged(); }
}
private string mNarProjectSymbol;
public string CreateEditProjectSymbolText {
get { return mCreateEditProjectSymbolText; }
set { mCreateEditProjectSymbolText = value; OnPropertyChanged(); }
}
private string mCreateEditProjectSymbolText;
/// <summary>
/// Edited label value. Will be null if the label hasn't been created, or has been
/// deleted (by entering a blank string in the label edit box).
/// </summary>
private Symbol mEditedLabel;
private bool mLabelHasBeenEdited;
/// <summary>
/// Address associated with the label (for the Symbol's value).
/// </summary>
private int mLabelTargetAddress = -1;
/// <summary>
/// Offset of edited label.
/// </summary>
private int mEditedLabelOffset = -1;
/// <summary>
/// Edited project symbol. Will be null if the symbol doesn't exist. Symbols can't
/// be deleted.
/// </summary>
private DefSymbol mEditedProjectSymbol;
/// <summary>
/// Configures the UI in the local variables box at load time.
/// </summary>
private void NumericReferences_Loaded() {
SymbolEditOffsetResult = -1;
Anattrib attr = mProject.GetAnattrib(mOffset);
if (attr.OperandOffset >= 0) {
// Operand target is inside the file.
ShowNarEditLabel = true;
// Seek back to the start of the instruction or data item if the operand points
// into the middle of one. This is *not* the same as the "nearby" search,
// which will traverse multiple items to find a match.
mEditedLabelOffset =
DataAnalysis.GetBaseOperandOffset(mProject, attr.OperandOffset);
mLabelTargetAddress = mProject.GetAnattrib(mEditedLabelOffset).Address;
if (mProject.UserLabels.TryGetValue(mEditedLabelOffset, out Symbol sym)) {
// Has a label.
ShowNarCurrentLabel = true;
if (mEditedLabelOffset != attr.OperandOffset) {
NarLabelOffsetText = string.Format(CURRENT_LABEL_ADJUSTED_FMT,
mFormatter.FormatAdjustment(attr.OperandOffset - mEditedLabelOffset));
} else {
NarLabelOffsetText = CURRENT_LABEL;
}
NarTargetLabel = sym.Label;
mEditedLabel = sym;
CreateEditLabelText = EDIT_LABEL;
} else {
NarLabelOffsetText = CURRENT_LABEL;
CreateEditLabelText = CREATE_LABEL;
}
} else if (attr.OperandAddress >= 0) {
ShowNarExternalSymbol = true;
// There can be multiple symbols with the same value, so we walk through the
// list and identify the first matching platform and project symbols. We're
// only interested in address symbols, not constants.
Symbol firstPlatform = null;
Symbol firstProject = null;
foreach (Symbol sym in mProject.SymbolTable) {
if (sym.Value == attr.OperandAddress &&
sym.SymbolType != Symbol.Type.Constant) {
if (firstPlatform == null && sym.SymbolSource == Symbol.Source.Platform) {
firstPlatform = sym;
} else if (firstProject == null &&
sym.SymbolSource == Symbol.Source.Project) {
firstProject = sym;
}
if (firstPlatform != null && firstProject != null) {
break;
}
}
}
if (firstPlatform != null) {
ShowNarPlatformSymbol = true;
NarPlatformSymbol = firstPlatform.Label;
}
if (firstProject != null) {
ShowNarProjectSymbol = true;
NarProjectSymbol = firstProject.Label;
CreateEditProjectSymbolText = EDIT_PROJECT_SYMBOL;
mEditedProjectSymbol = (DefSymbol)firstProject;
PrevProjectPropertyResult = mEditedProjectSymbol;
} else {
ShowNarNoProjectMatch = true;
CreateEditProjectSymbolText = CREATE_PROJECT_SYMBOL;
}
} else {
// Probably an immediate operand.
ShowNarNotAddress = true;
}
}
private void EditLabel_Click(object sender, RoutedEventArgs e) {
EditLabel dlg = new EditLabel(this, mEditedLabel, mLabelTargetAddress,
mProject.SymbolTable);
if (dlg.ShowDialog() != true || mEditedLabel == dlg.LabelSym) {
Debug.WriteLine("No change to label, ignoring edit");
return;
}
mEditedLabel = dlg.LabelSym;
mLabelHasBeenEdited = true;
// Update UI to match current state.
if (mEditedLabel == null) {
ShowNarCurrentLabel = false;
CreateEditLabelText = CREATE_LABEL;
} else {
ShowNarCurrentLabel = true;
CreateEditLabelText = EDIT_LABEL;
NarTargetLabel = mEditedLabel.Label;
}
}
private void EditProjectSymbol_Click(object sender, RoutedEventArgs e) {
DefSymbol origSym = mEditedProjectSymbol;
if (origSym == null) {
// Need to start with a symbol so we can set the value field.
origSym = new DefSymbol("SYM", mOperandValue, Symbol.Source.Project,
Symbol.Type.ExternalAddr, FormatDescriptor.SubType.None,
string.Empty, string.Empty);
}
EditDefSymbol dlg = new EditDefSymbol(this, mFormatter,
mProject.ProjectProps.ProjectSyms, origSym, null, false, true);
if (dlg.ShowDialog() != true) {
return;
}
Debug.Assert(dlg.NewSym != null); // can't delete a symbol from dialog
if (mEditedProjectSymbol == dlg.NewSym) {
Debug.WriteLine("No change to project symbol, ignoring edit");
return;
}
mEditedProjectSymbol = dlg.NewSym;
ShowNarProjectSymbol = true;
ShowNarNoProjectMatch = false;
NarProjectSymbol = mEditedProjectSymbol.Label;
CreateEditProjectSymbolText = EDIT_PROJECT_SYMBOL;
}
#endregion Numeric References
#region Local Variables
public bool ShowLvNotApplicable {
get { return mShowLvNotApplicable; }
set { mShowLvNotApplicable = value; OnPropertyChanged(); }
@ -667,6 +963,12 @@ namespace SourceGen.WpfGui {
}
private bool mShowLvMatchFound;
public string LvMatchFoundText {
get { return mLvMatchFoundText; }
set { mLvMatchFoundText = value; OnPropertyChanged(); }
}
private string mLvMatchFoundText;
public string LocalVariableLabel {
get { return mLocalVariableLabel; }
set { mLocalVariableLabel = value; OnPropertyChanged(); }
@ -688,7 +990,7 @@ namespace SourceGen.WpfGui {
/// <summary>
/// Offset of LocalVariableTable we're going to modify.
/// </summary>
private int mLvTableOffset;
private int mLvTableOffset = -1;
/// <summary>
/// Local variable value. If there's already a definition, this will be pre-filled
@ -703,60 +1005,64 @@ namespace SourceGen.WpfGui {
/// <summary>
/// Configures the UI on the bottom half of the dialog.
/// Configures the UI in the local variables box at load time.
/// </summary>
private void NumericRefs_Loaded() {
if (mOpDef.IsDirectPageInstruction || mOpDef.IsStackRelInstruction) {
LocalVariableLookup lvLookup =
new LocalVariableLookup(mProject.LvTables, mProject, false);
// If the operand is already a local variable, use whichever one the
// analyzer found.
Anattrib attr = mProject.GetAnattrib(mOffset);
if (attr.DataDescriptor != null && attr.DataDescriptor.HasSymbol &&
attr.DataDescriptor.SymbolRef.IsVariable) {
// Select the table that defines the local variable that's currently
// associated with this operand.
mLvTableOffset = lvLookup.GetDefiningTableOffset(mOffset,
attr.DataDescriptor.SymbolRef);
Debug.Assert(mLvTableOffset >= 0);
Debug.WriteLine("Symbol " + attr.DataDescriptor.SymbolRef +
" from var table at +" + mLvTableOffset.ToString("x6"));
} else {
// Operand is not a local variable. Find the closest table.
mLvTableOffset = lvLookup.GetNearestTableOffset(mOffset);
Debug.WriteLine("Closest table is at +" + mLvTableOffset.ToString("x6"));
}
if (mLvTableOffset < 0) {
ShowLvTableNotFound = true;
} else {
// Found a table. Do we have a matching symbol?
ShowLvCreateEditButton = true;
mEditedLocalVar = lvLookup.GetSymbol(mOffset, mOperandValue,
mOpDef.IsDirectPageInstruction ?
Symbol.Type.ExternalAddr : Symbol.Type.Constant);
if (mEditedLocalVar == null) {
ShowLvNoMatchFound = true;
CreateEditLocalVariableText = CREATE_LOCAL_VARIABLE;
} else {
ShowLvMatchFound = true;
CreateEditLocalVariableText = EDIT_LOCAL_VARIABLE;
LocalVariableLabel = mEditedLocalVar.Label;
}
// We need to update the symbol table while we work to make the uniqueness
// check come out right. Otherwise if you edit, rename FOO to BAR,
// then edit again, you won't be able to rename BAR back to FOO because
// it's already in the list and it's not self.
//
// We don't need the full LVT, just the list of symbols, but we'll want
// to hand the modified table to the caller when we exit.
LocalVariableTable lvt = mProject.LvTables[mLvTableOffset];
mEditedLvTable = new LocalVariableTable(lvt);
}
} else {
private void LocalVariables_Loaded() {
if (!mOpDef.IsDirectPageInstruction && !mOpDef.IsStackRelInstruction) {
ShowLvNotApplicable = true;
return;
}
LvMatchFoundText = mOpDef.IsDirectPageInstruction ?
LV_MATCH_FOUND_ADDRESS : LV_MATCH_FOUND_CONSTANT;
LocalVariableLookup lvLookup =
new LocalVariableLookup(mProject.LvTables, mProject, false);
// If the operand is already a local variable, use whichever one the
// analyzer found.
Anattrib attr = mProject.GetAnattrib(mOffset);
if (attr.DataDescriptor != null && attr.DataDescriptor.HasSymbol &&
attr.DataDescriptor.SymbolRef.IsVariable) {
// Select the table that defines the local variable that's currently
// associated with this operand.
mLvTableOffset = lvLookup.GetDefiningTableOffset(mOffset,
attr.DataDescriptor.SymbolRef);
Debug.Assert(mLvTableOffset >= 0);
Debug.WriteLine("Symbol " + attr.DataDescriptor.SymbolRef +
" from var table at +" + mLvTableOffset.ToString("x6"));
} else {
// Operand is not a local variable. Find the closest table.
mLvTableOffset = lvLookup.GetNearestTableOffset(mOffset);
Debug.WriteLine("Closest table is at +" + mLvTableOffset.ToString("x6"));
}
if (mLvTableOffset < 0) {
ShowLvTableNotFound = true;
} else {
// Found a table. Do we have a matching symbol?
ShowLvCreateEditButton = true;
mEditedLocalVar = lvLookup.GetSymbol(mOffset, mOperandValue,
mOpDef.IsDirectPageInstruction ?
Symbol.Type.ExternalAddr : Symbol.Type.Constant);
if (mEditedLocalVar == null) {
ShowLvNoMatchFound = true;
CreateEditLocalVariableText = CREATE_LOCAL_VARIABLE;
} else {
ShowLvMatchFound = true;
CreateEditLocalVariableText = EDIT_LOCAL_VARIABLE;
LocalVariableLabel = mEditedLocalVar.Label;
}
// We need to update the symbol table while we work to make the uniqueness
// check come out right. Otherwise if you edit, rename FOO to BAR,
// then edit again, you won't be able to rename BAR back to FOO because
// it's already in the list and it's not self.
//
// We don't need the full LVT, just the list of symbols, but we'll want
// to hand the modified table to the caller when we exit.
LocalVariableTable lvt = mProject.LvTables[mLvTableOffset];
mEditedLvTable = new LocalVariableTable(lvt);
}
}
@ -794,67 +1100,14 @@ namespace SourceGen.WpfGui {
mEditedLvTable.AddOrReplace(dlg.NewSym);
LocalVariableLabel = mEditedLocalVar.Label;
CreateEditLocalVariableText = EDIT_LOCAL_VARIABLE;
ShowLvNoMatchFound = false;
ShowLvMatchFound = true;
} else {
Debug.WriteLine("No change to def symbol, ignoring edit");
}
}
}
#endregion Numeric References
#if false
/// <summary>
/// Configures the buttons in the "symbol shortcuts" group box. The entire box is
/// disabled unless "symbol" is selected. Other options are selectively enabled or
/// disabled as appropriate for the current input. If we disable the selection option,
/// the selection will be reset to default.
/// </summary>
private void ConfigureSymbolShortcuts() {
// operandOnlyRadioButton: always enabled
// labelInsteadRadioButton: symbol is unknown and operand address has no label
// operandAndLabelRadioButton: same as labelInstead
// operandAndProjRadioButton: symbol is unknown and operand address is outside project
string labelStr = symbolTextBox.Text;
ShortcutArg = -1;
// Is this a known symbol? If so, disable most options and bail.
if (mProject.SymbolTable.TryGetValue(labelStr, out Symbol sym)) {
labelInsteadButton.IsEnabled = operandAndLabelButton.IsEnabled =
operandAndProjButton.IsEnabled = false;
operandOnlyButton.IsChecked = true;
return;
}
if (mAttr.OperandOffset >= 0) {
// Operand target is inside the file. Does the target offset already have a label?
int targetOffset =
DataAnalysis.GetBaseOperandOffset(mProject, mAttr.OperandOffset);
bool hasLabel = mProject.UserLabels.ContainsKey(targetOffset);
labelInsteadButton.IsEnabled = operandAndLabelButton.IsEnabled =
!hasLabel;
operandAndProjButton.IsEnabled = false;
ShortcutArg = targetOffset;
} else if (mAttr.OperandAddress >= 0) {
// Operand target is outside the file.
labelInsteadButton.IsEnabled = operandAndLabelButton.IsEnabled = false;
operandAndProjButton.IsEnabled = true;
ShortcutArg = mAttr.OperandAddress;
} else {
// Probably an immediate operand.
// ?? Should operandAndProjButton be enabled for 8-bit constants? We'd want
// to add it as a constant rather than an address.
labelInsteadButton.IsEnabled = operandAndLabelButton.IsEnabled =
operandAndProjButton.IsEnabled = false;
}
// Select the default option if the currently-selected option is no longer available.
if ((labelInsteadButton.IsChecked == true && labelInsteadButton.IsEnabled != true) ||
(operandAndLabelButton.IsChecked == true && !operandAndLabelButton.IsEnabled == true) ||
(operandAndProjButton.IsChecked == true && !operandAndProjButton.IsEnabled == true)) {
operandOnlyButton.IsChecked = true;
}
}
#endif
#endregion Local Variables
}
}