mirror of
https://github.com/fadden/6502bench.git
synced 2026-04-20 04:16:47 +00:00
Add "edit operand target label" action
This adds a shortcut for editing the label at the address referenced by an instruction operand or data address pseudo-op. This can be activated from the Actions menu, or with Ctrl+Shift+L. For references inside the file, the Edit Label dialog is opened. For external addresses, the project symbol editor is opened. Local variable table entries are currently not supported. (issue #166)
This commit is contained in:
@@ -317,8 +317,10 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
/// <param name="proj">Project reference.</param>
|
||||
/// <param name="offset">Offset of data item.</param>
|
||||
/// <param name="address">Result: decoded address.</param>
|
||||
/// <returns>Operand offset, or -1 if not applicable.</returns>
|
||||
public static int GetDataOperandOffset(DisasmProject proj, int offset) {
|
||||
public static int GetDataOperandOffset(DisasmProject proj, int offset, out int address) {
|
||||
address = -1;
|
||||
Anattrib attr = proj.GetAnattrib(offset);
|
||||
if (!attr.IsDataStart && !attr.IsInlineDataStart) {
|
||||
return -1;
|
||||
@@ -335,7 +337,7 @@ namespace SourceGen {
|
||||
|
||||
// Treat like an absolute address. Convert the operand
|
||||
// to an address, then resolve the file offset.
|
||||
int address = RawData.GetWord(proj.FileData, offset, dfd.Length,
|
||||
address = RawData.GetWord(proj.FileData, offset, dfd.Length,
|
||||
(dfd.FormatType == FormatDescriptor.Type.NumericBE));
|
||||
if (dfd.Length < 3) {
|
||||
// Add the program bank where the data bank should go. Not perfect but
|
||||
|
||||
@@ -875,7 +875,7 @@ namespace SourceGen {
|
||||
/// project file.)
|
||||
/// </summary>
|
||||
/// <param name="index">Index into DisasmProject.ActiveDefSymbolListlist.</param>
|
||||
/// <returns>Synthetic file offset. Value will be < 0.</returns>
|
||||
/// <returns>Synthetic file offset. Value will be < 0.</returns>
|
||||
public static int DefSymOffsetFromIndex(int index) {
|
||||
Debug.Assert(index >= 0 && index < (1 << 24));
|
||||
return index - (1 << 24);
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace SourceGen {
|
||||
///
|
||||
/// To reduce confusion, the fact that something has been de-duped should be obvious.
|
||||
///
|
||||
/// A few quick clicks in the 2019-local-variables test should confirm these.
|
||||
/// A few quick clicks in the 20150-local-variables test should confirm these.
|
||||
/// </remarks>
|
||||
public class LocalVariableLookup {
|
||||
/// <summary>
|
||||
|
||||
+162
-7
@@ -60,7 +60,6 @@ namespace SourceGen {
|
||||
|
||||
#endregion Project state
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reference back to MainWindow object.
|
||||
/// </summary>
|
||||
@@ -239,7 +238,6 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Init and settings
|
||||
|
||||
/// <summary>
|
||||
@@ -726,7 +724,6 @@ namespace SourceGen {
|
||||
|
||||
#endregion Init and settings
|
||||
|
||||
|
||||
#region Auto-save
|
||||
|
||||
private const string RECOVERY_EXT_ADD = "_rec";
|
||||
@@ -1016,7 +1013,6 @@ namespace SourceGen {
|
||||
|
||||
#endregion Auto-save
|
||||
|
||||
|
||||
#region Project management
|
||||
|
||||
private bool PrepareNewProject(string dataPathName, SystemDef sysDef) {
|
||||
@@ -2114,7 +2110,8 @@ namespace SourceGen {
|
||||
// If it's an Address or Symbol, we can try to resolve
|
||||
// the value. (Symbols should have been resolved by the
|
||||
// previous clause, but Address entries would not have been.)
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset);
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset,
|
||||
out int unused);
|
||||
if (operandOffset >= 0) {
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(operandOffset, 0,
|
||||
@@ -2373,7 +2370,9 @@ namespace SourceGen {
|
||||
public void EditLabel() {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int offset = CodeLineList[selIndex].FileOffset;
|
||||
|
||||
DoEditLabel(offset);
|
||||
}
|
||||
private void DoEditLabel(int offset) {
|
||||
Anattrib attr = mProject.GetAnattrib(offset);
|
||||
int addr = attr.Address;
|
||||
if (attr.IsNonAddressable) {
|
||||
@@ -2412,6 +2411,158 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the address and offset referenced by an instruction or data operand.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>There are five distinct situations (see issue #166):</para>
|
||||
/// <list type="number">
|
||||
/// <item>instruction, target address is inside file</item>
|
||||
/// <item>instruction, target address is outside file</item>
|
||||
/// <item>instruction, target is a zero-page address currently defined in an LVT</item>
|
||||
/// <item>data item with address operand, target address is inside file</item>
|
||||
/// <item>data item with address operand, target address is outside file</item>
|
||||
/// </list>
|
||||
/// <para>For the case of wanting to edit the label at the target location, the caller
|
||||
/// will either need to open the LVT editor, the user label editor, or the project
|
||||
/// symbol editor. Determining priority in the event of a conflict is up to the
|
||||
/// caller.</para>
|
||||
/// <para>It is possible to have an LVT entry and also an internal or external reference
|
||||
/// to zero-page (e.g. zero page is included in the file, or there's a project/platform
|
||||
/// symbol for the address). We don't currently try to handle LVT entries.</para>
|
||||
/// <para>Sometimes instruction operands are formatted with an explicit symbol. We pay
|
||||
/// no attention to that here. This causes us to differ from the Ctrl+J "jump to operand"
|
||||
/// behavior, which prefers to jump to symbols when available.</para>
|
||||
/// <para>This currently ignores explicit symbolic references, and goes directly to
|
||||
/// the address referenced. If you have a jump table that includes address FOO, but
|
||||
/// encodes it as FOO-1 (for RTS), we will set a label on FOO-1.</para>
|
||||
/// </remarks>
|
||||
/// <param name="project">Disassembly project.</param>
|
||||
/// <param name="selOffset">File offset of selection.</param>
|
||||
/// <param name="isInternal">Result: true if target is internal.</param>
|
||||
/// <param name="internalTargetOffset">Result: offset of target in project file.</param>
|
||||
/// <param name="externalSym">Result: first matching project/platform symbol,
|
||||
/// if any.</param>
|
||||
/// <param name="externalAddr">Result: decoded external address.</param>
|
||||
/// <returns>True if a target was found.</returns>
|
||||
public static bool GetOperandTargetOffset(DisasmProject project, int selOffset,
|
||||
out bool isInternal, out int internalTargetOffset, out Symbol externalSym,
|
||||
out int externalAddr, out bool isLV) {
|
||||
isInternal = isLV = false;
|
||||
internalTargetOffset = externalAddr = -1;
|
||||
externalSym = null;
|
||||
|
||||
Anattrib attr = project.GetAnattrib(selOffset);
|
||||
if (attr.IsInstructionStart) {
|
||||
if (!attr.IsInstructionWithOperand) {
|
||||
return false;
|
||||
}
|
||||
if (attr.OperandOffset >= 0) {
|
||||
// Internal address. Walk back to start of line if necessary.
|
||||
isInternal = true;
|
||||
internalTargetOffset =
|
||||
DataAnalysis.GetBaseOperandOffset(project, attr.OperandOffset);
|
||||
} else if (attr.OperandAddress >= 0) {
|
||||
// External address. Do a symbol table lookup, which will give us the correct
|
||||
// answer when there are overlapping multi-byte values and masks. If we don't
|
||||
// find a match, we still want to return "true" so that the caller can offer
|
||||
// to create a new project symbol.
|
||||
externalSym = project.SymbolTable.FindNonVariableByAddress(attr.OperandAddress,
|
||||
OpDef.MemoryEffect.ReadModifyWrite); // could get effect from op
|
||||
externalAddr = attr.OperandAddress;
|
||||
} else {
|
||||
// Probably an immediate operand, nothing to do.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(someday): see if a local variable is defined for this operand.
|
||||
OpDef opDef = project.CpuDef.GetOpDef(project.FileData[selOffset]);
|
||||
if ((opDef.IsDirectPageInstruction || opDef.IsStackRelInstruction) &&
|
||||
attr.DataDescriptor != null && attr.DataDescriptor.HasSymbol &&
|
||||
attr.DataDescriptor.SymbolRef.IsVariable) {
|
||||
// The operand is formatted as a local variable.
|
||||
isLV = true;
|
||||
}
|
||||
|
||||
//Debug.WriteLine("Instr ref: offset=+" + internalTargetOffset.ToString("x6") +
|
||||
// " extSym=" + externalSym);
|
||||
return true;
|
||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||
// If it's address or symbol, get the target offset. This only works for
|
||||
// internal addresses.
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(project, selOffset,
|
||||
out int extAddr);
|
||||
if (operandOffset >= 0) {
|
||||
// Internal address reference. Walk back to start of line if necessary.
|
||||
isInternal = true;
|
||||
internalTargetOffset =
|
||||
DataAnalysis.GetBaseOperandOffset(project, operandOffset);
|
||||
} else if (extAddr >= 0) {
|
||||
// External address reference.
|
||||
externalSym = project.SymbolTable.FindNonVariableByAddress(extAddr,
|
||||
OpDef.MemoryEffect.ReadModifyWrite); // mem effect unknowable
|
||||
externalAddr = extAddr;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
//Debug.WriteLine("Data ref: offset=+" + internalTargetOffset.ToString("x6") +
|
||||
// " extSym=" + externalSym);
|
||||
return true;
|
||||
} else {
|
||||
Debug.Assert(false, "should be some sort of start");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanEditOperandTargetLabel() {
|
||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
||||
return false;
|
||||
}
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int selOffset = CodeLineList[selIndex].FileOffset;
|
||||
return GetOperandTargetOffset(mProject, selOffset, out bool unused1,
|
||||
out int unused2, out Symbol unused3, out int unused4, out bool unused5);
|
||||
}
|
||||
|
||||
public void EditOperandTargetLabel() {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int selOffset = CodeLineList[selIndex].FileOffset;
|
||||
if (!GetOperandTargetOffset(mProject, selOffset, out bool isInternal,
|
||||
out int internalLabelOffset, out Symbol externalSym, out int externalAddr,
|
||||
out bool isLV)) {
|
||||
Debug.Assert(false, "should not be here");
|
||||
return;
|
||||
}
|
||||
Debug.WriteLine("EOTL: isInternal=" + isInternal + " intOff=+" +
|
||||
internalLabelOffset.ToString("x6") + " extSym=" + externalSym +
|
||||
" extAddr=" + externalAddr + " isLV=" + isLV);
|
||||
|
||||
// Operand targets can be internal or external, and can be in an LVT. Internal
|
||||
// address user labels have the highest priority, LVTs are next, then external
|
||||
// project/platform symbols.
|
||||
if (isInternal) {
|
||||
Debug.Assert(internalLabelOffset >= 0);
|
||||
DoEditLabel(internalLabelOffset);
|
||||
} else if (isLV) {
|
||||
// Formatted as a local variable, do nothing.
|
||||
// TODO(someday): make this edit the specific symbol in the table
|
||||
} else {
|
||||
// Create or edit project symbol.
|
||||
if (externalSym != null && externalSym.SymbolSource == Symbol.Source.Project) {
|
||||
// Edit existing project symbol.
|
||||
DoEditProjectSymbol(CodeListColumn.Label, (DefSymbol)externalSym);
|
||||
} else {
|
||||
// Platform symbol or nothing at all. Create a new project symbol.
|
||||
// (Should we refuse to act if there's only a platform symbol? Could be
|
||||
// confusing if they think they're editing the platform, but it's also
|
||||
// convenient to be able to create the project sym here.)
|
||||
DefSymbol initVals = new DefSymbol("SYM", externalAddr, Symbol.Source.Project,
|
||||
Symbol.Type.ExternalAddr, FormatDescriptor.SubType.None);
|
||||
DoEditProjectSymbol(CodeListColumn.Label, initVals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanCreateLocalVariableTable() {
|
||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
||||
return false;
|
||||
@@ -2743,6 +2894,9 @@ namespace SourceGen {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int symIndex = LineListGen.DefSymIndexFromOffset(CodeLineList[selIndex].FileOffset);
|
||||
DefSymbol origDefSym = mProject.ActiveDefSymbolList[symIndex];
|
||||
DoEditProjectSymbol(col, origDefSym);
|
||||
}
|
||||
private void DoEditProjectSymbol(CodeListColumn col, DefSymbol origDefSym) {
|
||||
Debug.Assert(origDefSym.SymbolSource == Symbol.Source.Project);
|
||||
|
||||
EditDefSymbol dlg = new EditDefSymbol(mMainWin, mFormatter,
|
||||
@@ -3919,7 +4073,8 @@ namespace SourceGen {
|
||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||
// If it's an Address or Symbol, we can try to resolve
|
||||
// the value.
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset);
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset,
|
||||
out int unused);
|
||||
if (operandOffset >= 0) {
|
||||
return CodeLineList.FindCodeDataIndexByOffset(operandOffset);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":6,
|
||||
"FileDataLength":183,
|
||||
"FileDataCrc32":-593505978,
|
||||
"FileDataLength":193,
|
||||
"FileDataCrc32":960553569,
|
||||
"ProjectProps":{
|
||||
"CpuName":"6502",
|
||||
"IncludeUndocumentedInstr":false,
|
||||
@@ -132,7 +132,7 @@
|
||||
{
|
||||
"Offset":53,
|
||||
"Addr":8704,
|
||||
"Length":130,
|
||||
"Length":140,
|
||||
"PreLabel":"",
|
||||
"DisallowInward":false,
|
||||
"DisallowOutward":false,
|
||||
@@ -197,16 +197,16 @@
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"182":{
|
||||
"192":{
|
||||
"Label":"done",
|
||||
"Value":8833,
|
||||
"Value":8843,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"},
|
||||
|
||||
"157":{
|
||||
"163":{
|
||||
"Label":"bitsy",
|
||||
"Value":8808,
|
||||
"Value":8814,
|
||||
"Source":"User",
|
||||
"Type":"GlobalAddr",
|
||||
"LabelAnno":"None"}},
|
||||
@@ -260,7 +260,7 @@
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"137":{
|
||||
"143":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
@@ -270,7 +270,7 @@
|
||||
|
||||
"Extra":null},
|
||||
|
||||
"155":{
|
||||
"161":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
@@ -280,27 +280,6 @@
|
||||
|
||||
"Extra":null},
|
||||
|
||||
"163":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"165":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"167":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"169":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
@@ -332,6 +311,41 @@
|
||||
"177":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"179":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"181":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"183":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"185":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
"SymbolRef":null,
|
||||
"Extra":null},
|
||||
|
||||
"187":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"line2",
|
||||
@@ -339,7 +353,7 @@
|
||||
|
||||
"Extra":null},
|
||||
|
||||
"179":{
|
||||
"189":{
|
||||
"Length":2,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Address",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
.cdef $20,$7e,$20
|
||||
FOOZP = $f0
|
||||
OVERL = $3000
|
||||
projover = $3100 ;replaced by proj symbol w/same name, diff addr (no match)
|
||||
FOO = $f000
|
||||
FOO_5 = $f005
|
||||
|
||||
@@ -45,8 +46,10 @@ next1 lda addr1
|
||||
sta FOO_5
|
||||
sta FOO+8
|
||||
ldx OVERL
|
||||
ldx projover
|
||||
ldx $4000
|
||||
ldx line1
|
||||
ldx line2
|
||||
ldx line2+1
|
||||
ldx L221C
|
||||
ldx L221C+1
|
||||
ldx line2+35
|
||||
@@ -67,8 +70,10 @@ bitsy .byte $2c
|
||||
.word FOO_5
|
||||
.word FOO+9
|
||||
.word OVERL
|
||||
.word projover
|
||||
.word $4000
|
||||
.word line1
|
||||
.word line2
|
||||
.word line2+5
|
||||
.word L221C
|
||||
.word line2+33
|
||||
.word zf4
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
!cpu 6502
|
||||
FOOZP = $f0
|
||||
OVERL = $3000
|
||||
projover = $3100 ;replaced by proj symbol w/same name, diff addr (no match)
|
||||
FOO = $f000
|
||||
FOO_5 = $f005
|
||||
|
||||
@@ -44,8 +45,10 @@ next1 lda addr1
|
||||
sta FOO_5
|
||||
sta FOO+8
|
||||
ldx OVERL
|
||||
ldx projover
|
||||
ldx $4000
|
||||
ldx line1
|
||||
ldx line2
|
||||
ldx line2+1
|
||||
ldx L221C
|
||||
ldx L221C+1
|
||||
ldx line2+35
|
||||
@@ -66,8 +69,10 @@ bitsy !byte $2c
|
||||
!word FOO_5
|
||||
!word FOO+9
|
||||
!word OVERL
|
||||
!word projover
|
||||
!word $4000
|
||||
!word line1
|
||||
!word line2
|
||||
!word line2+5
|
||||
!word L221C
|
||||
!word line2+33
|
||||
!word zf4
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.setcpu "6502"
|
||||
FOOZP = $f0
|
||||
OVERL = $3000
|
||||
projover = $3100 ;replaced by proj symbol w/same name, diff addr (no match)
|
||||
FOO = $f000
|
||||
FOO_5 = $f005
|
||||
|
||||
@@ -40,8 +41,10 @@ next1: lda addr1
|
||||
sta FOO_5
|
||||
sta FOO+8
|
||||
ldx OVERL
|
||||
ldx projover
|
||||
ldx $4000
|
||||
ldx line1
|
||||
ldx line2
|
||||
ldx line2+1
|
||||
ldx L221C
|
||||
ldx L221C+1
|
||||
ldx line2+35
|
||||
@@ -62,8 +65,10 @@ bitsy: .byte $2c
|
||||
.word FOO_5
|
||||
.word FOO+9
|
||||
.word OVERL
|
||||
.word projover
|
||||
.word $4000
|
||||
.word line1
|
||||
.word line2
|
||||
.word line2+5
|
||||
.word L221C
|
||||
.word line2+33
|
||||
.word zf4
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
FOOZP equ $f0
|
||||
OVERL equ $3000
|
||||
projover equ $3100 ;replaced by proj symbol w/same name, diff addr (no match)
|
||||
FOO equ $f000
|
||||
FOO_5 equ $f005
|
||||
|
||||
@@ -39,8 +40,10 @@ next1 lda addr1
|
||||
sta FOO_5
|
||||
sta FOO+8
|
||||
ldx OVERL
|
||||
ldx projover
|
||||
ldx $4000
|
||||
ldx line1
|
||||
ldx line2
|
||||
ldx line2+1
|
||||
ldx L221C
|
||||
ldx L221C+1
|
||||
ldx line2+35
|
||||
@@ -61,8 +64,10 @@ bitsy dfb $2c
|
||||
dw FOO_5
|
||||
dw FOO+9
|
||||
dw OVERL
|
||||
dw projover
|
||||
dw $4000
|
||||
dw line1
|
||||
dw line2
|
||||
dw line2+5
|
||||
dw L221C
|
||||
dw line2+33
|
||||
dw zf4
|
||||
|
||||
@@ -41,7 +41,9 @@ addr2 asc '?'
|
||||
FOO equ $f000
|
||||
FOO_5 equ $f005
|
||||
FOOZP equ $f0
|
||||
OVERL equ $3000
|
||||
plataddr equ $3000
|
||||
OVERL equ $3100
|
||||
NOLAB equ $4000
|
||||
|
||||
; Define a slice of zero page inside the program.
|
||||
org $f4 ;EDIT: add this
|
||||
@@ -61,11 +63,13 @@ next1
|
||||
sta FOO ;external addr
|
||||
sta FOO_5 ;external addr (overlaps w/FOO)
|
||||
sta FOO+8 ;external addr (range)
|
||||
ldx plataddr ;external addr, platform only
|
||||
ldx OVERL ;external addr, plat and proj
|
||||
ldx NOLAB ;external addr, no symbol
|
||||
ldx line1 ;internal addr
|
||||
ldx line2 ;internal addr
|
||||
ldx line3 ;internal addr with offset, line start
|
||||
ldx line3+1 ;internal addr with offset, inside line
|
||||
ldx line2+1 ;internal addr with offset
|
||||
ldx line3 ;internal addr, auto label
|
||||
ldx line3+1 ;internal addr, auto label, offset
|
||||
ldx line4+7 ;EDIT: set operand symbol "line2"
|
||||
|
||||
; EDIT: add local variable entry "foo_f0", value $f0, width 2
|
||||
@@ -88,9 +92,11 @@ bitsy bit $ffa9 ;EDIT: set label "bitsy" on BIT instruction
|
||||
dw FOO
|
||||
dw FOO_5
|
||||
dw FOO+9
|
||||
dw plataddr
|
||||
dw OVERL
|
||||
dw NOLAB
|
||||
dw line1
|
||||
dw line2
|
||||
dw line2+5
|
||||
dw line3
|
||||
dw line4+5 ;EDIT: set operand symbol "line2"
|
||||
dw zf4
|
||||
|
||||
@@ -912,23 +912,24 @@ namespace SourceGen.WpfGui {
|
||||
private void NumericReferences_Loaded() {
|
||||
SymbolEditOffsetResult = -1;
|
||||
|
||||
if (!MainController.GetOperandTargetOffset(mProject, mOffset, out bool isInternal,
|
||||
out int internalTargetOffset, out Symbol externalSym, out int unused1,
|
||||
out bool unused2)) {
|
||||
// Probably an immediate operand.
|
||||
ShowNarNotAddress = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Anattrib attr = mProject.GetAnattrib(mOffset);
|
||||
|
||||
if (attr.OperandOffset >= 0) {
|
||||
if (isInternal) {
|
||||
// Operand target is inside the file.
|
||||
ShowNarEditLabel = true;
|
||||
Debug.Assert(internalTargetOffset >= 0);
|
||||
|
||||
// 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.
|
||||
// TODO: this can create a situation where the code list shows FUBAR-1 but we
|
||||
// edit an earlier label, if the earlier label has a multi-byte format that
|
||||
// includes the target address. (An example can be found in 20200-ui-edge-cases.)
|
||||
mEditedLabelOffset =
|
||||
DataAnalysis.GetBaseOperandOffset(mProject, attr.OperandOffset);
|
||||
ShowNarEditLabel = true;
|
||||
mEditedLabelOffset = internalTargetOffset;
|
||||
mLabelTargetAddress = mProject.GetAnattrib(mEditedLabelOffset).Address;
|
||||
if (mProject.UserLabels.TryGetValue(mEditedLabelOffset, out Symbol sym)) {
|
||||
// Has a label.
|
||||
// Has a user label.
|
||||
ShowNarCurrentLabel = true;
|
||||
if (mEditedLabelOffset != attr.OperandOffset) {
|
||||
NarLabelOffsetText = string.Format(CURRENT_LABEL_ADJUSTED_FMT,
|
||||
@@ -940,10 +941,11 @@ namespace SourceGen.WpfGui {
|
||||
mEditedLabel = sym;
|
||||
CreateEditLabelText = EDIT_LABEL;
|
||||
} else {
|
||||
// Does not have a user label. Probably has an auto label.
|
||||
NarLabelOffsetText = CURRENT_LABEL;
|
||||
CreateEditLabelText = CREATE_LABEL;
|
||||
}
|
||||
} else if (attr.OperandAddress >= 0) {
|
||||
} else {
|
||||
ShowNarExternalSymbol = true;
|
||||
|
||||
// There can be multiple symbols with the same address, so we walk through the
|
||||
@@ -956,14 +958,12 @@ namespace SourceGen.WpfGui {
|
||||
|
||||
// Start by doing a symbol table lookup, which will give us the correct answer
|
||||
// when there are overlapping multi-byte values and masks.
|
||||
Symbol lsym = mProject.SymbolTable.FindNonVariableByAddress(attr.OperandAddress,
|
||||
OpDef.MemoryEffect.ReadModifyWrite); // just guess at the mem effect
|
||||
if (lsym == null) {
|
||||
if (externalSym == null) {
|
||||
// Nothing currently defined.
|
||||
} else if (lsym.SymbolSource == Symbol.Source.Platform) {
|
||||
firstPlatform = lsym;
|
||||
} else if (lsym.SymbolSource == Symbol.Source.Project) {
|
||||
firstProject = lsym;
|
||||
} else if (externalSym.SymbolSource == Symbol.Source.Platform) {
|
||||
firstPlatform = externalSym;
|
||||
} else if (externalSym.SymbolSource == Symbol.Source.Project) {
|
||||
firstProject = externalSym;
|
||||
} else {
|
||||
Debug.Assert(false, "was expecting project or platform for external addr");
|
||||
}
|
||||
@@ -1005,9 +1005,6 @@ namespace SourceGen.WpfGui {
|
||||
ShowNarNoProjectMatch = true;
|
||||
CreateEditProjectSymbolText = CREATE_PROJECT_SYMBOL;
|
||||
}
|
||||
} else {
|
||||
// Probably an immediate operand.
|
||||
ShowNarNotAddress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace SourceGen.WpfGui {
|
||||
private int mUniqueTag;
|
||||
|
||||
/// <summary>
|
||||
/// Address we are editing the label for.
|
||||
/// Address we are editing the label for. This is needed when creating the Symbol result.
|
||||
/// </summary>
|
||||
private int mAddress;
|
||||
|
||||
@@ -150,6 +150,10 @@ namespace SourceGen.WpfGui {
|
||||
} else {
|
||||
NonAddrWarningVis = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
this.Title += " (" + formatter.FormatAddress(address, true) + ")";
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
|
||||
@@ -102,6 +102,11 @@ limitations under the License.
|
||||
<KeyGesture>Ctrl+N</KeyGesture>
|
||||
</RoutedUICommand.InputGestures>
|
||||
</RoutedUICommand>
|
||||
<RoutedUICommand x:Key="EditOperandTargetLabelCmd" Text="Edit Operand Target Label...">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>Ctrl+Shift+L</KeyGesture>
|
||||
</RoutedUICommand.InputGestures>
|
||||
</RoutedUICommand>
|
||||
<RoutedUICommand x:Key="EditProjectPropertiesSymbolsCmd">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>F6</KeyGesture>
|
||||
@@ -263,6 +268,8 @@ limitations under the License.
|
||||
CanExecute="CanEditNote" Executed="EditNoteCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource EditOperandCmd}"
|
||||
CanExecute="CanEditOperand" Executed="EditOperandCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource EditOperandTargetLabelCmd}"
|
||||
CanExecute="CanEditOperandTargetLabel" Executed="EditOperandTargetLabelCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource EditProjectPropertiesSymbolsCmd}"
|
||||
CanExecute="IsProjectOpen" Executed="EditProjectPropertiesSymbolsCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource EditProjectSymbolCmd}"
|
||||
@@ -436,6 +443,7 @@ limitations under the License.
|
||||
<MenuItem Command="{StaticResource EditCommentCmd}" InputGestureText="Ctrl+;"/>
|
||||
<MenuItem Command="{StaticResource EditLongCommentCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditNoteCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditOperandTargetLabelCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditAddressCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditStatusFlagsCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditDataBankCmd}"/>
|
||||
|
||||
@@ -1122,6 +1122,10 @@ namespace SourceGen.WpfGui {
|
||||
e.CanExecute = IsProjectOpen() && mMainCtrl.CanEditOperand();
|
||||
}
|
||||
|
||||
private void CanEditOperandTargetLabel(object sender, CanExecuteRoutedEventArgs e) {
|
||||
e.CanExecute = IsProjectOpen() && mMainCtrl.CanEditOperandTargetLabel();
|
||||
}
|
||||
|
||||
private void CanEditProjectSymbol(object sender, CanExecuteRoutedEventArgs e) {
|
||||
e.CanExecute = IsProjectOpen() && mMainCtrl.CanEditProjectSymbol();
|
||||
}
|
||||
@@ -1288,6 +1292,10 @@ namespace SourceGen.WpfGui {
|
||||
mMainCtrl.EditOperand();
|
||||
}
|
||||
|
||||
private void EditOperandTargetLabelCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.EditOperandTargetLabel();
|
||||
}
|
||||
|
||||
private void EditProjectPropertiesCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.EditProjectProperties(WpfGui.EditProjectProperties.Tab.Unknown);
|
||||
}
|
||||
|
||||
@@ -338,6 +338,24 @@ CODE LDA LABEL+2
|
||||
<p>With the label out of the way, the data can be formatted as desired.</p>
|
||||
|
||||
|
||||
<h2 id="operand-target-label">Edit Operand Target Label</h2>
|
||||
|
||||
<p>This is an Actions menu shortcut that is equivalent to moving to the
|
||||
address specified by the operand and editing the label there. For example,
|
||||
if you use this on the line <code>LDA $1234</code>, it would open the
|
||||
label edit dialog for the line at address $1234.</p>
|
||||
<p>When used on references to addresses outside the scope of the file, the
|
||||
project symbol editor will be opened instead. This does not currently
|
||||
allow editing of local variable table entries.</p>
|
||||
<p>This also works for data items formatted as 16- or 24-bit addresses.</p>
|
||||
<p>Note: the target address is taken from the operand even when a symbol is
|
||||
provided. For example, sometimes jump tables will encode (address - 1)
|
||||
for the benefit of a PHA/RTS combination, so the entry for <code>FOO</code>
|
||||
will appear as <samp>FOO-1</samp>. The operand target is actually
|
||||
<code>FOO-1</code>, so using this feature won't edit the <code>FOO</code>
|
||||
label but instead try to add a new one at the previous address.</p>
|
||||
|
||||
|
||||
<h2 id="comment">Edit Comment</h2>
|
||||
<p>Enter an end-of-line (EOL) comment, or leave the text field blank to
|
||||
delete it. EOL comments may be placed on instruction and data lines, but
|
||||
|
||||
@@ -105,6 +105,7 @@ using the <samp>Help > Help</samp> menu item or by hitting
|
||||
<li><a href="editors.html#shortcut-local-var">Local Variable References</a></li>
|
||||
</ul></li>
|
||||
<li><a href="editors.html#data-operand">Edit Operand (Data)</a></li>
|
||||
<li><a href="editors.html#operand-target-label">Edit Operand Target Label</a></li>
|
||||
<li><a href="editors.html#comment">Edit Comment</a></li>
|
||||
<li><a href="editors.html#long-comment">Edit Long Comment</a></li>
|
||||
<li><a href="editors.html#data-bank">Edit Data Bank (65816 only)</a></li>
|
||||
|
||||
Reference in New Issue
Block a user