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:
parent
e8ae534879
commit
4d9d5e2ecf
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user