mirror of
https://github.com/fadden/6502bench.git
synced 2025-03-08 17:30:46 +00:00
Use relocation data to format instruction operands
This was a relatively lightweight change to confirm the usefulness of relocation data. The results were very positive. The relatively superficial integration of the data into the data analysis process causes some problems, e.g. the cross-reference table entries show an offset because the code analyzer's computed operand offset doesn't match the value of the label. The feature should be considered experimental The feature can be enabled or disabled with a project property. The results were sufficiently useful and non-annoying to make the setting enabled by default.
This commit is contained in:
parent
6d7fdff6b5
commit
d58b747571
@ -174,6 +174,7 @@ namespace SourceGen {
|
||||
/// bytes.</param>
|
||||
/// <param name="entryFlags">Status flags to use at code entry points.</param>
|
||||
/// <param name="scriptMan">Extension script manager.</param>
|
||||
/// <param name="parms">Analysis parameters.</param>
|
||||
/// <param name="debugLog">Object that receives debug log messages.</param>
|
||||
public CodeAnalysis(byte[] data, CpuDef cpuDef, Anattrib[] anattribs,
|
||||
AddressMap addrMap, TypeHint[] hints, StatusFlags[] statusFlagOverrides,
|
||||
|
@ -80,6 +80,11 @@ namespace SourceGen {
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="proj">Project to analyze.</param>
|
||||
/// <param name="anattribs">Anattrib array.</param>
|
||||
public DataAnalysis(DisasmProject proj, Anattrib[] anattribs) {
|
||||
mProject = proj;
|
||||
mAnattribs = anattribs;
|
||||
@ -156,12 +161,42 @@ namespace SourceGen {
|
||||
FormatDescriptor.SubType.Address);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for a relocation. It'll be at offset+1 because it's on the operand,
|
||||
// not the opcode byte.
|
||||
if (mAnalysisParams.UseRelocData && mProject.RelocList.TryGetValue(offset + 1,
|
||||
out DisasmProject.RelocData reloc)) {
|
||||
if (reloc.Value != attr.OperandAddress) {
|
||||
// The relocation address differs from what the analyzer came up
|
||||
// with. This may be because of incorrect assumptions about the
|
||||
// bank (assuming B==K) or because the partial address refers to
|
||||
// a location outside the file bounds. Whatever the case, if the
|
||||
// address is different, attr.OperandOffset will also be different.
|
||||
int relOperandOffset = mProject.AddrMap.AddressToOffset(offset,
|
||||
reloc.Value);
|
||||
if (relOperandOffset >= 0 && relOperandOffset != attr.OperandOffset) {
|
||||
// Determined a different offset. Use that instead.
|
||||
//Debug.WriteLine("REL +" + offset.ToString("x6") + " " +
|
||||
// reloc.Value.ToString("x6") + " vs. " +
|
||||
// attr.OperandAddress.ToString("x6"));
|
||||
WeakSymbolRef.Part part = WeakSymbolRef.Part.Low;
|
||||
if (reloc.Shift == -8) {
|
||||
part = WeakSymbolRef.Part.High;
|
||||
} else if (reloc.Shift == -16) {
|
||||
part = WeakSymbolRef.Part.Bank;
|
||||
}
|
||||
SetDataTarget(offset, attr.Length, relOperandOffset, part);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int operandOffset = attr.OperandOffset;
|
||||
if (operandOffset >= 0) {
|
||||
// This is an offset reference: a branch or data access instruction whose
|
||||
// target is inside the file. Create a FormatDescriptor for it, and
|
||||
// generate a label at the target if one is not already present.
|
||||
SetDataTarget(offset, attr.Length, operandOffset);
|
||||
SetDataTarget(offset, attr.Length, operandOffset, WeakSymbolRef.Part.Low);
|
||||
}
|
||||
|
||||
// We advance by a single byte, rather than .Length, in case there's
|
||||
@ -190,7 +225,8 @@ namespace SourceGen {
|
||||
}
|
||||
int operandOffset = mProject.AddrMap.AddressToOffset(offset, address);
|
||||
if (operandOffset >= 0) {
|
||||
SetDataTarget(offset, dfd.Length, operandOffset);
|
||||
SetDataTarget(offset, dfd.Length, operandOffset,
|
||||
WeakSymbolRef.Part.Low);
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +305,8 @@ namespace SourceGen {
|
||||
/// <param name="srcOffset">Offset of instruction or address data.</param>
|
||||
/// <param name="srcLen">Length of instruction or data item.</param>
|
||||
/// <param name="targetOffset">Offset of target.</param>
|
||||
private void SetDataTarget(int srcOffset, int srcLen, int targetOffset) {
|
||||
private void SetDataTarget(int srcOffset, int srcLen, int targetOffset,
|
||||
WeakSymbolRef.Part part) {
|
||||
// NOTE: don't try to cache mAnattribs[targetOffset] -- we may be changing
|
||||
// targetOffset and/or altering the Anattrib entry, so grabbing a copy of the
|
||||
// struct may lead to problems.
|
||||
@ -359,8 +396,7 @@ namespace SourceGen {
|
||||
", adj=" + (origTargetOffset - targetOffset));
|
||||
}
|
||||
mAnattribs[srcOffset].DataDescriptor = FormatDescriptor.Create(srcLen,
|
||||
new WeakSymbolRef(mAnattribs[targetOffset].Symbol.Label, WeakSymbolRef.Part.Low),
|
||||
isBigEndian);
|
||||
new WeakSymbolRef(mAnattribs[targetOffset].Symbol.Label, part), isBigEndian);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -122,24 +122,26 @@ namespace SourceGen {
|
||||
/// <summary>
|
||||
/// "Cooked" form of relocation data (e.g. OmfReloc). This does not contain the file
|
||||
/// offset, as that's expected to be used as the dictionary key.
|
||||
///
|
||||
/// Will be null unless the project was generated from a relocatable source.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RelocData {
|
||||
public byte Width; // width of area written by relocator
|
||||
public byte Shift; // amount to shift the value
|
||||
public byte Width; // width of area written by relocator (1-4 bytes)
|
||||
public sbyte Shift; // amount to shift the value (usually 0 or -16)
|
||||
public int Value; // value used (unshifted, full width)
|
||||
|
||||
public RelocData() { } // for deserialization
|
||||
|
||||
public RelocData(byte width, byte shift, int value) {
|
||||
public RelocData(byte width, sbyte shift, int value) {
|
||||
Width = width;
|
||||
Shift = shift;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
public Dictionary<int, RelocData> RelocList { get; set; }
|
||||
/// <summary>
|
||||
/// List of relocation data. Will be empty unless file was generated from a
|
||||
/// relocatable source.
|
||||
/// </summary>
|
||||
public Dictionary<int, RelocData> RelocList { get; private set; }
|
||||
|
||||
#endregion // data to save & restore
|
||||
|
||||
@ -280,6 +282,7 @@ namespace SourceGen {
|
||||
LvTables = new SortedList<int, LocalVariableTable>();
|
||||
VisualizationSets = new SortedList<int, VisualizationSet>();
|
||||
ProjectProps = new ProjectProperties();
|
||||
RelocList = new Dictionary<int, RelocData>();
|
||||
|
||||
SymbolTable = new SymbolTable();
|
||||
PlatformSyms = new List<PlatformSymbols>();
|
||||
|
@ -1282,6 +1282,8 @@ namespace SourceGen {
|
||||
// This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
|
||||
// when outside bank zero. The bank is included in the operand address,
|
||||
// but we don't want to show it here.
|
||||
// (Some assemblers want the bank to be shown for JSR/JMP, but we don't
|
||||
// do that here. See the corresponding code in AsmGen.GenCommon)
|
||||
operandForSymbol &= 0xffff;
|
||||
}
|
||||
formattedOperand = mFormatter.FormatHexValue(operandForSymbol, operandLen * 2);
|
||||
|
@ -1597,17 +1597,10 @@ namespace SourceGen {
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
FormatDescriptor dfd = attr.DataDescriptor;
|
||||
|
||||
// Does this have an operand with an in-file target offset?
|
||||
// (Resolve it as a numeric reference.)
|
||||
if (attr.OperandOffset >= 0) {
|
||||
// Yup, find the line for that offset and jump to it.
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
} else if (dfd != null && dfd.HasSymbol) {
|
||||
// Operand has a symbol, do a symbol lookup.
|
||||
if (dfd != null && dfd.HasSymbol) {
|
||||
// Operand has a symbol, do a symbol lookup. This is slower than a simple
|
||||
// jump based on OperandOffset, but if we've incorporated reloc data then
|
||||
// the jump will be wrong.
|
||||
if (dfd.SymbolRef.IsVariable) {
|
||||
if (!testOnly) {
|
||||
GoToVarDefinition(line.FileOffset, dfd.SymbolRef, true);
|
||||
@ -1646,6 +1639,14 @@ namespace SourceGen {
|
||||
Debug.WriteLine("Operand symbol not found: " + dfd.SymbolRef.Label);
|
||||
}
|
||||
}
|
||||
} else if (attr.OperandOffset >= 0) {
|
||||
// Operand has an in-file target offset. We can resolve it as a numeric reference.
|
||||
// Find the line for that offset and jump to it.
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||
// If it's an Address or Symbol, we can try to resolve
|
||||
// the value. (Symbols should have been resolved by the
|
||||
@ -2198,7 +2199,7 @@ namespace SourceGen {
|
||||
if (!string.IsNullOrEmpty(mProjectPathName)) {
|
||||
projectDir = Path.GetDirectoryName(mProjectPathName);
|
||||
}
|
||||
EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject.ProjectProps,
|
||||
EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject,
|
||||
projectDir, mFormatter, initialTab);
|
||||
dlg.ShowDialog();
|
||||
ProjectProperties newProps = dlg.NewProps;
|
||||
@ -3201,6 +3202,7 @@ namespace SourceGen {
|
||||
Debug.Assert(line.FileOffset >= 0);
|
||||
|
||||
// Does this have an operand with an in-file target offset?
|
||||
// TODO: may not work correctly with reloc data?
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
if (attr.OperandOffset >= 0) {
|
||||
return CodeLineList.FindCodeDataIndexByOffset(attr.OperandOffset);
|
||||
|
@ -223,6 +223,7 @@ namespace SourceGen {
|
||||
public string DefaultTextScanMode { get; set; }
|
||||
public int MinCharsForString { get; set; }
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool UseRelocData { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
|
||||
public SerAnalysisParameters() { }
|
||||
@ -231,6 +232,7 @@ namespace SourceGen {
|
||||
DefaultTextScanMode = src.DefaultTextScanMode.ToString();
|
||||
MinCharsForString = src.MinCharsForString;
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
UseRelocData = src.UseRelocData;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
}
|
||||
}
|
||||
@ -526,13 +528,10 @@ namespace SourceGen {
|
||||
|
||||
spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);
|
||||
|
||||
if (proj.RelocList != null) {
|
||||
// The objects can serialize directly, but the Dictionary key can't be an int.
|
||||
spf.RelocList =
|
||||
new Dictionary<string, DisasmProject.RelocData>(proj.RelocList.Count);
|
||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in proj.RelocList) {
|
||||
spf.RelocList.Add(kvp.Key.ToString(), kvp.Value);
|
||||
}
|
||||
// The objects are serializable, but the Dictionary key can't be an int.
|
||||
spf.RelocList = new Dictionary<string, DisasmProject.RelocData>(proj.RelocList.Count);
|
||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in proj.RelocList) {
|
||||
spf.RelocList.Add(kvp.Key.ToString(), kvp.Value);
|
||||
}
|
||||
|
||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||
@ -610,6 +609,8 @@ namespace SourceGen {
|
||||
spf.ProjectProps.AnalysisParams.MinCharsForString;
|
||||
proj.ProjectProps.AnalysisParams.SeekNearbyTargets =
|
||||
spf.ProjectProps.AnalysisParams.SeekNearbyTargets;
|
||||
proj.ProjectProps.AnalysisParams.UseRelocData =
|
||||
spf.ProjectProps.AnalysisParams.UseRelocData;
|
||||
if (spf._ContentVersion < 2) {
|
||||
// This was made optional in v1.3. Default it to true for older projects.
|
||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling = true;
|
||||
@ -844,7 +845,6 @@ namespace SourceGen {
|
||||
|
||||
// Deserialize relocation data. This was added in v1.7.
|
||||
if (spf.RelocList != null) {
|
||||
proj.RelocList = new Dictionary<int, DisasmProject.RelocData>();
|
||||
foreach (KeyValuePair<string, DisasmProject.RelocData> kvp in spf.RelocList) {
|
||||
if (!ParseValidateKey(kvp.Key, spf.FileDataLength,
|
||||
Res.Strings.PROJECT_FIELD_RELOC_DATA, report, out int intKey)) {
|
||||
|
@ -28,9 +28,10 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
public class ProjectProperties {
|
||||
//
|
||||
// NOTE:
|
||||
// *** NOTE ***
|
||||
// If you add or modify a member, make sure to update the copy constructor and
|
||||
// add serialization code to ProjectFile.
|
||||
// *** NOTE ***
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
@ -51,6 +52,7 @@ namespace SourceGen {
|
||||
public TextScanMode DefaultTextScanMode { get; set; }
|
||||
public int MinCharsForString { get; set; }
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool UseRelocData { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
|
||||
public AnalysisParameters() {
|
||||
@ -59,6 +61,7 @@ namespace SourceGen {
|
||||
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
||||
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
||||
SeekNearbyTargets = true;
|
||||
UseRelocData = true;
|
||||
SmartPlpHandling = true;
|
||||
}
|
||||
public AnalysisParameters(AnalysisParameters src) {
|
||||
@ -66,6 +69,7 @@ namespace SourceGen {
|
||||
DefaultTextScanMode = src.DefaultTextScanMode;
|
||||
MinCharsForString = src.MinCharsForString;
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
UseRelocData = src.UseRelocData;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
}
|
||||
}
|
||||
|
@ -137,10 +137,12 @@ and 65816 code. The official web site is
|
||||
|
||||
<li><a href="tools.html">Tools</a>
|
||||
<ul>
|
||||
<li><a href="tools.html#instruction-chart">Instruction Chart</a></li>
|
||||
<li><a href="tools.html#ascii-chart">ASCII Chart</a></li>
|
||||
<li><a href="tools.html#hexdump">Hex Dump Viewer</a></li>
|
||||
<li><a href="tools.html#file-concat">File Concatenator</a></li>
|
||||
<li><a href="tools.html#ascii-chart">ASCII Chart</a></li>
|
||||
<li><a href="tools.html#instruction-chart">Instruction Chart</a></li>
|
||||
<li><a href="tools.html#file-slicer">File Slicer</a></li>
|
||||
<li><a href="tools.html#omf-converter">OMF Converter</a></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="advanced.html">Advanced Topics</a>
|
||||
|
@ -254,6 +254,10 @@ unless they match exactly. Note that references into the middle of an
|
||||
instruction or formatted data area are always adjusted, regardless of
|
||||
how this is set. This setting has no effect on local variables, and
|
||||
only enables a 1-byte backward search on project/platform symbols.</p>
|
||||
<p>The "use relocation data" checkbox is only available if the project
|
||||
was created from a relocatable source, e.g. by the OMF Converter tool.
|
||||
If checked, information from the relocation dictionary will be used to
|
||||
improve automatic operand formatting.</p>
|
||||
<p>If "smart PLP handling" is checked, the analyzer will try to use
|
||||
the processor status flags from a nearby <code>PHP</code> when a
|
||||
<code>PLP</code> is encountered. If not enabled, all flags are set to
|
||||
|
@ -13,6 +13,7 @@
|
||||
<h1>6502bench SourceGen: Tools</h1>
|
||||
|
||||
<h2><a name="instruction-chart">Instruction Chart</a></h2>
|
||||
|
||||
<p>This opens a window with a summary of all 256 opcodes. The CPU can
|
||||
be chosen from the pop-up list at the bottom. Undocumented opcodes for
|
||||
6502/65C02 are shown in italics, and can be excluded from the list
|
||||
@ -84,6 +85,20 @@ length of the file, respectively.</p>
|
||||
sliced, allowing you to confirm the placement.</p>
|
||||
|
||||
|
||||
<h2><a name="omf-converter">OMF Converter</a></h2>
|
||||
|
||||
<p>This tool allows you to view Apple IIgs Object Module Format
|
||||
binaries, and convert them for disassembly. OMF files have multiple
|
||||
segments with relocatable code. The conversion tool loads the OMF
|
||||
file the same way the GS/OS System Loader would, and creates a
|
||||
SourceGen project file for it with some basic attributes filled in.</p>
|
||||
|
||||
<p>Only Load files may be converted (S16, PIF, etc). Compiler object
|
||||
files and libraries contain unresolved references and are not supported.</p>
|
||||
|
||||
<p>The generated binary file is not in OMF format and will not execute
|
||||
on an Apple IIgs.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
|
@ -344,7 +344,9 @@ namespace SourceGen.Tools.Omf {
|
||||
|
||||
proj.PrepForNew(data, "new_proj");
|
||||
proj.ApplyChanges(cs, false, out _);
|
||||
proj.RelocList = mRelocData;
|
||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in mRelocData) {
|
||||
proj.RelocList.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
mLoadedData = data;
|
||||
mNewProject = proj;
|
||||
@ -410,38 +412,39 @@ namespace SourceGen.Tools.Omf {
|
||||
Debug.WriteLine("Invalid reloc shift " + omfRel.Shift);
|
||||
return false;
|
||||
}
|
||||
int adjRelocAddr = relocAddr;
|
||||
if (omfRel.Shift < 0) {
|
||||
relocAddr >>= -omfRel.Shift;
|
||||
adjRelocAddr >>= -omfRel.Shift;
|
||||
} else if (omfRel.Shift > 0) {
|
||||
relocAddr <<= omfRel.Shift;
|
||||
adjRelocAddr <<= omfRel.Shift;
|
||||
}
|
||||
|
||||
switch (omfRel.Width) {
|
||||
case 1:
|
||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
||||
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||
break;
|
||||
case 2:
|
||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
||||
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||
break;
|
||||
case 3:
|
||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
||||
data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16);
|
||||
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||
data[bufOffset + omfRel.Offset + 2] = (byte)(adjRelocAddr >> 16);
|
||||
break;
|
||||
case 4:
|
||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
||||
data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16);
|
||||
data[bufOffset + omfRel.Offset + 3] = (byte)(relocAddr >> 24);
|
||||
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||
data[bufOffset + omfRel.Offset + 2] = (byte)(adjRelocAddr >> 16);
|
||||
data[bufOffset + omfRel.Offset + 3] = (byte)(adjRelocAddr >> 24);
|
||||
break;
|
||||
default:
|
||||
Debug.WriteLine("Invalid reloc width " + omfRel.Width);
|
||||
return false;
|
||||
}
|
||||
|
||||
mRelocData.Add(bufOffset + omfRel.Offset,
|
||||
new DisasmProject.RelocData((byte)omfRel.Width, (byte)omfRel.Shift, relocAddr));
|
||||
mRelocData.Add(bufOffset + omfRel.Offset, new DisasmProject.RelocData(
|
||||
(byte)omfRel.Width, (sbyte)omfRel.Shift, relocAddr));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -103,6 +103,8 @@ limitations under the License.
|
||||
IsChecked="{Binding AnalyzeUncategorizedData}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Seek nearby targets"
|
||||
IsChecked="{Binding SeekNearbyTargets}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Use relocation data (experimental)"
|
||||
IsChecked="{Binding UseRelocData}" IsEnabled="{Binding IsRelocDataAvailable}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Smart PLP handling"
|
||||
IsChecked="{Binding SmartPlpHandling}"/>
|
||||
|
||||
|
@ -105,21 +105,23 @@ namespace SourceGen.WpfGui {
|
||||
/// Constructor. Initial state is configured from an existing ProjectProperties object.
|
||||
/// </summary>
|
||||
/// <param name="owner">Parent window.</param>
|
||||
/// <param name="props">Property holder to clone.</param>
|
||||
/// <param name="project">Project object.</param>
|
||||
/// <param name="projectDir">Project directory, if known.</param>
|
||||
/// <param name="formatter">Text formatter.</param>
|
||||
/// <param name="initialTab">Tab to open initially. Pass "Unknown" for default.</param>
|
||||
public EditProjectProperties(Window owner, ProjectProperties props, string projectDir,
|
||||
public EditProjectProperties(Window owner, DisasmProject project, string projectDir,
|
||||
Formatter formatter, Tab initialTab) {
|
||||
InitializeComponent();
|
||||
Owner = owner;
|
||||
DataContext = this;
|
||||
|
||||
mWorkProps = new ProjectProperties(props);
|
||||
mWorkProps = new ProjectProperties(project.ProjectProps); // make a work copy
|
||||
mProjectDir = projectDir;
|
||||
mFormatter = formatter;
|
||||
mInitialTab = initialTab;
|
||||
|
||||
IsRelocDataAvailable = (project.RelocList.Count > 0);
|
||||
|
||||
// Construct arrays used as item sources for combo boxes.
|
||||
CpuItems = new CpuItem[] {
|
||||
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
|
||||
@ -341,6 +343,19 @@ namespace SourceGen.WpfGui {
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool UseRelocData {
|
||||
get { return mWorkProps.AnalysisParams.UseRelocData; }
|
||||
set {
|
||||
mWorkProps.AnalysisParams.UseRelocData = value;
|
||||
OnPropertyChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
private bool mIsRelocDataAvailable;
|
||||
public bool IsRelocDataAvailable {
|
||||
get { return mIsRelocDataAvailable; }
|
||||
set { mIsRelocDataAvailable = value; OnPropertyChanged(); }
|
||||
}
|
||||
public bool SmartPlpHandling {
|
||||
get { return mWorkProps.AnalysisParams.SmartPlpHandling; }
|
||||
set {
|
||||
|
Loading…
x
Reference in New Issue
Block a user