1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-02 19:29:29 +00:00

First cut of split-address table formatter

Allows specification of table data in various ways, for 16-bit and
24-bit addresses.  Shows a preview so you can see if the addresses
look about right.  Adds permanent labels at target offsets if none
are present.  Optionally sets code hints.

Works beautifully on the A2-Amper-fdraw example, but needs some
additional testing, documentation, etc.  Dialog is more complicated
that I would have liked, mostly because of 65816 support, but I
think it'll do.

(issue #10)
This commit is contained in:
Andy McFadden 2018-10-06 15:13:20 -07:00
parent d4726dac7e
commit f4e4ac842d
7 changed files with 548 additions and 91 deletions

View File

@ -23,15 +23,16 @@
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem(new string[] {
"123456",
System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem(new string[] {
"12/3456",
"+123456",
"(+) T_123456"}, -1);
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.selectionInfoLabel = new System.Windows.Forms.Label();
this.addressCharacteristicsGroup = new System.Windows.Forms.GroupBox();
this.returnAddrCheckBox = new System.Windows.Forms.CheckBox();
this.width24Button = new System.Windows.Forms.RadioButton();
this.pushRtsCheckBox = new System.Windows.Forms.CheckBox();
this.width24Radio = new System.Windows.Forms.RadioButton();
this.width16Radio = new System.Windows.Forms.RadioButton();
this.lowByteGroupBox = new System.Windows.Forms.GroupBox();
this.lowThirdPartRadio = new System.Windows.Forms.RadioButton();
@ -51,8 +52,11 @@
this.addrColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.symbolColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.outputPreviewGroupBox = new System.Windows.Forms.GroupBox();
this.invalidConstantLabel = new System.Windows.Forms.Label();
this.incompatibleSelectionLabel = new System.Windows.Forms.Label();
this.addCodeHintCheckBox = new System.Windows.Forms.CheckBox();
this.optionsGroupBox = new System.Windows.Forms.GroupBox();
this.offsetColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.addressCharacteristicsGroup.SuspendLayout();
this.lowByteGroupBox.SuspendLayout();
this.highByteGroupBox.SuspendLayout();
@ -65,10 +69,10 @@
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(479, 465);
this.cancelButton.Location = new System.Drawing.Point(461, 461);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 0;
this.cancelButton.TabIndex = 8;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
//
@ -76,10 +80,10 @@
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
this.okButton.Location = new System.Drawing.Point(398, 465);
this.okButton.Location = new System.Drawing.Point(380, 461);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 1;
this.okButton.TabIndex = 7;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
@ -89,42 +93,44 @@
this.selectionInfoLabel.AutoSize = true;
this.selectionInfoLabel.Location = new System.Drawing.Point(13, 13);
this.selectionInfoLabel.Name = "selectionInfoLabel";
this.selectionInfoLabel.Size = new System.Drawing.Size(207, 13);
this.selectionInfoLabel.TabIndex = 2;
this.selectionInfoLabel.Text = "There are {0} bytes selected in {1} groups.";
this.selectionInfoLabel.Size = new System.Drawing.Size(213, 13);
this.selectionInfoLabel.TabIndex = 0;
this.selectionInfoLabel.Text = "There are {0} bytes selected, in {1} group(s)";
//
// addressCharacteristicsGroup
//
this.addressCharacteristicsGroup.Controls.Add(this.returnAddrCheckBox);
this.addressCharacteristicsGroup.Controls.Add(this.width24Button);
this.addressCharacteristicsGroup.Controls.Add(this.pushRtsCheckBox);
this.addressCharacteristicsGroup.Controls.Add(this.width24Radio);
this.addressCharacteristicsGroup.Controls.Add(this.width16Radio);
this.addressCharacteristicsGroup.Location = new System.Drawing.Point(16, 44);
this.addressCharacteristicsGroup.Location = new System.Drawing.Point(16, 40);
this.addressCharacteristicsGroup.Name = "addressCharacteristicsGroup";
this.addressCharacteristicsGroup.Size = new System.Drawing.Size(222, 90);
this.addressCharacteristicsGroup.TabIndex = 3;
this.addressCharacteristicsGroup.Size = new System.Drawing.Size(204, 90);
this.addressCharacteristicsGroup.TabIndex = 1;
this.addressCharacteristicsGroup.TabStop = false;
this.addressCharacteristicsGroup.Text = "Address Characteristics";
//
// returnAddrCheckBox
// pushRtsCheckBox
//
this.returnAddrCheckBox.AutoSize = true;
this.returnAddrCheckBox.Location = new System.Drawing.Point(7, 68);
this.returnAddrCheckBox.Name = "returnAddrCheckBox";
this.returnAddrCheckBox.Size = new System.Drawing.Size(170, 17);
this.returnAddrCheckBox.TabIndex = 2;
this.returnAddrCheckBox.Text = "Return addresses (address - 1)";
this.returnAddrCheckBox.UseVisualStyleBackColor = true;
this.pushRtsCheckBox.AutoSize = true;
this.pushRtsCheckBox.Location = new System.Drawing.Point(7, 68);
this.pushRtsCheckBox.Name = "pushRtsCheckBox";
this.pushRtsCheckBox.Size = new System.Drawing.Size(167, 17);
this.pushRtsCheckBox.TabIndex = 2;
this.pushRtsCheckBox.Text = "Push for RTS/RTL (target - 1)";
this.pushRtsCheckBox.UseVisualStyleBackColor = true;
this.pushRtsCheckBox.CheckedChanged += new System.EventHandler(this.pushRtsCheckBox_CheckedChanged);
//
// width24Button
// width24Radio
//
this.width24Button.AutoSize = true;
this.width24Button.Location = new System.Drawing.Point(7, 44);
this.width24Button.Name = "width24Button";
this.width24Button.Size = new System.Drawing.Size(51, 17);
this.width24Button.TabIndex = 1;
this.width24Button.TabStop = true;
this.width24Button.Text = "24-bit";
this.width24Button.UseVisualStyleBackColor = true;
this.width24Radio.AutoSize = true;
this.width24Radio.Location = new System.Drawing.Point(7, 44);
this.width24Radio.Name = "width24Radio";
this.width24Radio.Size = new System.Drawing.Size(51, 17);
this.width24Radio.TabIndex = 1;
this.width24Radio.TabStop = true;
this.width24Radio.Text = "24-bit";
this.width24Radio.UseVisualStyleBackColor = true;
this.width24Radio.CheckedChanged += new System.EventHandler(this.widthRadio_CheckedChanged);
//
// width16Radio
//
@ -136,16 +142,17 @@
this.width16Radio.TabStop = true;
this.width16Radio.Text = "16-bit";
this.width16Radio.UseVisualStyleBackColor = true;
this.width16Radio.CheckedChanged += new System.EventHandler(this.widthRadio_CheckedChanged);
//
// lowByteGroupBox
//
this.lowByteGroupBox.Controls.Add(this.lowThirdPartRadio);
this.lowByteGroupBox.Controls.Add(this.lowSecondPartRadio);
this.lowByteGroupBox.Controls.Add(this.lowFirstPartRadio);
this.lowByteGroupBox.Location = new System.Drawing.Point(13, 140);
this.lowByteGroupBox.Location = new System.Drawing.Point(13, 136);
this.lowByteGroupBox.Name = "lowByteGroupBox";
this.lowByteGroupBox.Size = new System.Drawing.Size(225, 94);
this.lowByteGroupBox.TabIndex = 4;
this.lowByteGroupBox.Size = new System.Drawing.Size(207, 94);
this.lowByteGroupBox.TabIndex = 2;
this.lowByteGroupBox.TabStop = false;
this.lowByteGroupBox.Text = "Low Byte";
//
@ -159,6 +166,7 @@
this.lowThirdPartRadio.TabStop = true;
this.lowThirdPartRadio.Text = "Third part of selection";
this.lowThirdPartRadio.UseVisualStyleBackColor = true;
this.lowThirdPartRadio.CheckedChanged += new System.EventHandler(this.lowByte_CheckedChanged);
//
// lowSecondPartRadio
//
@ -170,6 +178,7 @@
this.lowSecondPartRadio.TabStop = true;
this.lowSecondPartRadio.Text = "Second part of selection";
this.lowSecondPartRadio.UseVisualStyleBackColor = true;
this.lowSecondPartRadio.CheckedChanged += new System.EventHandler(this.lowByte_CheckedChanged);
//
// lowFirstPartRadio
//
@ -181,6 +190,7 @@
this.lowFirstPartRadio.TabStop = true;
this.lowFirstPartRadio.Text = "First part of selection";
this.lowFirstPartRadio.UseVisualStyleBackColor = true;
this.lowFirstPartRadio.CheckedChanged += new System.EventHandler(this.lowByte_CheckedChanged);
//
// highByteGroupBox
//
@ -189,10 +199,10 @@
this.highByteGroupBox.Controls.Add(this.highThirdPartRadio);
this.highByteGroupBox.Controls.Add(this.highSecondPartRadio);
this.highByteGroupBox.Controls.Add(this.highFirstPartRadio);
this.highByteGroupBox.Location = new System.Drawing.Point(13, 240);
this.highByteGroupBox.Location = new System.Drawing.Point(13, 236);
this.highByteGroupBox.Name = "highByteGroupBox";
this.highByteGroupBox.Size = new System.Drawing.Size(225, 120);
this.highByteGroupBox.TabIndex = 5;
this.highByteGroupBox.Size = new System.Drawing.Size(207, 120);
this.highByteGroupBox.TabIndex = 3;
this.highByteGroupBox.TabStop = false;
this.highByteGroupBox.Text = "High Byte";
//
@ -203,6 +213,7 @@
this.highConstantTextBox.Name = "highConstantTextBox";
this.highConstantTextBox.Size = new System.Drawing.Size(93, 20);
this.highConstantTextBox.TabIndex = 4;
this.highConstantTextBox.TextChanged += new System.EventHandler(this.highConstantTextBox_TextChanged);
//
// highConstantRadio
//
@ -214,6 +225,7 @@
this.highConstantRadio.TabStop = true;
this.highConstantRadio.Text = "Constant:";
this.highConstantRadio.UseVisualStyleBackColor = true;
this.highConstantRadio.CheckedChanged += new System.EventHandler(this.highByte_CheckedChanged);
//
// highThirdPartRadio
//
@ -225,6 +237,7 @@
this.highThirdPartRadio.TabStop = true;
this.highThirdPartRadio.Text = "Third part of selection";
this.highThirdPartRadio.UseVisualStyleBackColor = true;
this.highThirdPartRadio.CheckedChanged += new System.EventHandler(this.highByte_CheckedChanged);
//
// highSecondPartRadio
//
@ -236,6 +249,7 @@
this.highSecondPartRadio.TabStop = true;
this.highSecondPartRadio.Text = "Second part of selection";
this.highSecondPartRadio.UseVisualStyleBackColor = true;
this.highSecondPartRadio.CheckedChanged += new System.EventHandler(this.highByte_CheckedChanged);
//
// highFirstPartRadio
//
@ -247,16 +261,17 @@
this.highFirstPartRadio.TabStop = true;
this.highFirstPartRadio.Text = "First part of selection";
this.highFirstPartRadio.UseVisualStyleBackColor = true;
this.highFirstPartRadio.CheckedChanged += new System.EventHandler(this.highByte_CheckedChanged);
//
// bankByteGroupBox
//
this.bankByteGroupBox.Controls.Add(this.bankConstantTextBox);
this.bankByteGroupBox.Controls.Add(this.bankNthPartRadio);
this.bankByteGroupBox.Controls.Add(this.bankConstantRadio);
this.bankByteGroupBox.Location = new System.Drawing.Point(13, 367);
this.bankByteGroupBox.Location = new System.Drawing.Point(13, 362);
this.bankByteGroupBox.Name = "bankByteGroupBox";
this.bankByteGroupBox.Size = new System.Drawing.Size(225, 70);
this.bankByteGroupBox.TabIndex = 6;
this.bankByteGroupBox.Size = new System.Drawing.Size(207, 70);
this.bankByteGroupBox.TabIndex = 4;
this.bankByteGroupBox.TabStop = false;
this.bankByteGroupBox.Text = "Bank Byte";
//
@ -266,7 +281,8 @@
this.bankConstantTextBox.MaxLength = 10;
this.bankConstantTextBox.Name = "bankConstantTextBox";
this.bankConstantTextBox.Size = new System.Drawing.Size(93, 20);
this.bankConstantTextBox.TabIndex = 5;
this.bankConstantTextBox.TabIndex = 2;
this.bankConstantTextBox.TextChanged += new System.EventHandler(this.bankConstantTextBox_TextChanged);
//
// bankNthPartRadio
//
@ -274,10 +290,11 @@
this.bankNthPartRadio.Location = new System.Drawing.Point(10, 19);
this.bankNthPartRadio.Name = "bankNthPartRadio";
this.bankNthPartRadio.Size = new System.Drawing.Size(120, 17);
this.bankNthPartRadio.TabIndex = 2;
this.bankNthPartRadio.TabIndex = 0;
this.bankNthPartRadio.TabStop = true;
this.bankNthPartRadio.Text = "Nth part of selection";
this.bankNthPartRadio.UseVisualStyleBackColor = true;
this.bankNthPartRadio.CheckedChanged += new System.EventHandler(this.bankByte_CheckedChanged);
//
// bankConstantRadio
//
@ -289,6 +306,7 @@
this.bankConstantRadio.TabStop = true;
this.bankConstantRadio.Text = "Constant:";
this.bankConstantRadio.UseVisualStyleBackColor = true;
this.bankConstantRadio.CheckedChanged += new System.EventHandler(this.bankByte_CheckedChanged);
//
// outputPreviewListView
//
@ -296,38 +314,67 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.outputPreviewListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.addrColumnHeader,
this.offsetColumnHeader,
this.symbolColumnHeader});
this.outputPreviewListView.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.outputPreviewListView.FullRowSelect = true;
this.outputPreviewListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.outputPreviewListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem2});
listViewItem5});
this.outputPreviewListView.Location = new System.Drawing.Point(6, 19);
this.outputPreviewListView.MultiSelect = false;
this.outputPreviewListView.Name = "outputPreviewListView";
this.outputPreviewListView.Size = new System.Drawing.Size(290, 369);
this.outputPreviewListView.TabIndex = 7;
this.outputPreviewListView.TabIndex = 0;
this.outputPreviewListView.UseCompatibleStateImageBehavior = false;
this.outputPreviewListView.View = System.Windows.Forms.View.Details;
//
// addrColumnHeader
//
this.addrColumnHeader.Text = "Addr";
this.addrColumnHeader.Width = 52;
//
// symbolColumnHeader
//
this.symbolColumnHeader.Text = "Symbol";
this.symbolColumnHeader.Width = 200;
this.symbolColumnHeader.Width = 174;
//
// outputPreviewGroupBox
//
this.outputPreviewGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.outputPreviewGroupBox.Controls.Add(this.invalidConstantLabel);
this.outputPreviewGroupBox.Controls.Add(this.incompatibleSelectionLabel);
this.outputPreviewGroupBox.Controls.Add(this.outputPreviewListView);
this.outputPreviewGroupBox.Location = new System.Drawing.Point(252, 44);
this.outputPreviewGroupBox.Location = new System.Drawing.Point(234, 40);
this.outputPreviewGroupBox.Name = "outputPreviewGroupBox";
this.outputPreviewGroupBox.Size = new System.Drawing.Size(302, 394);
this.outputPreviewGroupBox.TabIndex = 8;
this.outputPreviewGroupBox.Size = new System.Drawing.Size(302, 393);
this.outputPreviewGroupBox.TabIndex = 6;
this.outputPreviewGroupBox.TabStop = false;
this.outputPreviewGroupBox.Text = "Output Preview";
this.outputPreviewGroupBox.Text = "Generated Addresses";
//
// invalidConstantLabel
//
this.invalidConstantLabel.AutoSize = true;
this.invalidConstantLabel.BackColor = System.Drawing.SystemColors.Window;
this.invalidConstantLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.invalidConstantLabel.ForeColor = System.Drawing.Color.Red;
this.invalidConstantLabel.Location = new System.Drawing.Point(101, 200);
this.invalidConstantLabel.Name = "invalidConstantLabel";
this.invalidConstantLabel.Size = new System.Drawing.Size(100, 16);
this.invalidConstantLabel.TabIndex = 2;
this.invalidConstantLabel.Text = "Invalid constant";
//
// incompatibleSelectionLabel
//
this.incompatibleSelectionLabel.AutoSize = true;
this.incompatibleSelectionLabel.BackColor = System.Drawing.SystemColors.Window;
this.incompatibleSelectionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.incompatibleSelectionLabel.ForeColor = System.Drawing.Color.Red;
this.incompatibleSelectionLabel.Location = new System.Drawing.Point(43, 177);
this.incompatibleSelectionLabel.Name = "incompatibleSelectionLabel";
this.incompatibleSelectionLabel.Size = new System.Drawing.Size(216, 16);
this.incompatibleSelectionLabel.TabIndex = 1;
this.incompatibleSelectionLabel.Text = "Options incompatible with selection";
//
// addCodeHintCheckBox
//
@ -336,26 +383,33 @@
this.addCodeHintCheckBox.AutoSize = true;
this.addCodeHintCheckBox.Location = new System.Drawing.Point(10, 19);
this.addCodeHintCheckBox.Name = "addCodeHintCheckBox";
this.addCodeHintCheckBox.Size = new System.Drawing.Size(123, 17);
this.addCodeHintCheckBox.TabIndex = 8;
this.addCodeHintCheckBox.Text = "Add code entry hints";
this.addCodeHintCheckBox.Size = new System.Drawing.Size(165, 17);
this.addCodeHintCheckBox.TabIndex = 0;
this.addCodeHintCheckBox.Text = "Add code entry hint if needed";
this.addCodeHintCheckBox.UseVisualStyleBackColor = true;
//
// optionsGroupBox
//
this.optionsGroupBox.Controls.Add(this.addCodeHintCheckBox);
this.optionsGroupBox.Location = new System.Drawing.Point(13, 444);
this.optionsGroupBox.Location = new System.Drawing.Point(13, 439);
this.optionsGroupBox.Name = "optionsGroupBox";
this.optionsGroupBox.Size = new System.Drawing.Size(225, 43);
this.optionsGroupBox.TabIndex = 9;
this.optionsGroupBox.Size = new System.Drawing.Size(207, 43);
this.optionsGroupBox.TabIndex = 5;
this.optionsGroupBox.TabStop = false;
this.optionsGroupBox.Text = "Options";
//
// offsetColumnHeader
//
this.offsetColumnHeader.Text = "Offset";
this.offsetColumnHeader.Width = 55;
//
// FormatSplitAddress
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(566, 500);
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(548, 496);
this.Controls.Add(this.optionsGroupBox);
this.Controls.Add(this.outputPreviewGroupBox);
this.Controls.Add(this.bankByteGroupBox);
@ -382,6 +436,7 @@
this.bankByteGroupBox.ResumeLayout(false);
this.bankByteGroupBox.PerformLayout();
this.outputPreviewGroupBox.ResumeLayout(false);
this.outputPreviewGroupBox.PerformLayout();
this.optionsGroupBox.ResumeLayout(false);
this.optionsGroupBox.PerformLayout();
this.ResumeLayout(false);
@ -396,8 +451,8 @@
private System.Windows.Forms.Label selectionInfoLabel;
private System.Windows.Forms.GroupBox addressCharacteristicsGroup;
private System.Windows.Forms.RadioButton width16Radio;
private System.Windows.Forms.RadioButton width24Button;
private System.Windows.Forms.CheckBox returnAddrCheckBox;
private System.Windows.Forms.RadioButton width24Radio;
private System.Windows.Forms.CheckBox pushRtsCheckBox;
private System.Windows.Forms.GroupBox lowByteGroupBox;
private System.Windows.Forms.RadioButton lowFirstPartRadio;
private System.Windows.Forms.RadioButton lowSecondPartRadio;
@ -418,5 +473,8 @@
private System.Windows.Forms.GroupBox outputPreviewGroupBox;
private System.Windows.Forms.CheckBox addCodeHintCheckBox;
private System.Windows.Forms.GroupBox optionsGroupBox;
private System.Windows.Forms.Label incompatibleSelectionLabel;
private System.Windows.Forms.Label invalidConstantLabel;
private System.Windows.Forms.ColumnHeader offsetColumnHeader;
}
}

View File

@ -20,54 +20,409 @@ using System.Windows.Forms;
using Asm65;
using CommonUtil;
using CommonWinForms;
namespace SourceGen.AppForms {
public partial class FormatSplitAddress : Form {
/// <summary>
/// Result set that describes the formatting to perform. Not all regions will have
/// the same format, e.g. the "mixed ASCII" mode will alternate strings and bytes
/// (rather than a dedicated "mixed ASCII" format type).
/// Format descriptors to apply.
/// </summary>
public SortedList<int, FormatDescriptor> Results { get; private set; }
public SortedList<int, FormatDescriptor> NewFormatDescriptors { get; private set; }
/// <summary>
/// User labels to apply.
/// </summary>
public Dictionary<int, Symbol> NewUserLabels { get; private set; }
/// <summary>
/// All target offsets found. The list may contain redundant entries.
/// </summary>
public List<int> AllTargetOffsets { get; private set; }
/// <summary>
/// Selected offsets. An otherwise contiguous range of offsets can be broken up
/// by user-specified labels and address discontinuities, so this needs to be
/// processed by range.
/// </summary>
public TypedRangeSet Selection { private get; set; }
private TypedRangeSet mSelection;
/// <summary>
/// Raw file data.
/// Project reference.
/// </summary>
private byte[] mFileData;
/// <summary>
/// Symbol table to use when resolving symbolic values.
/// </summary>
private SymbolTable mSymbolTable;
private DisasmProject mProject;
/// <summary>
/// Formatter to use when displaying addresses and hex values.
/// </summary>
private Asm65.Formatter mFormatter;
private Formatter mFormatter;
/// <summary>
/// Set to prevent controls from going nuts while initializing.
/// </summary>
private bool mInitializing;
/// <summary>
/// Set to true when valid output is available.
/// </summary>
private bool mOutputReady;
public FormatSplitAddress(byte[] fileData, SymbolTable symbolTable,
public FormatSplitAddress(DisasmProject project, TypedRangeSet selection,
Formatter formatter) {
InitializeComponent();
mFileData = fileData;
mSymbolTable = symbolTable;
mProject = project;
mFormatter = formatter;
mSelection = selection;
mOutputReady = false;
}
private void FormatSplitAddress_Load(object sender, EventArgs e) {
mInitializing = true;
string fmt = selectionInfoLabel.Text;
selectionInfoLabel.Text = string.Format(fmt, mSelection.Count, mSelection.RangeCount);
width16Radio.Checked = true;
lowFirstPartRadio.Checked = true;
highSecondPartRadio.Checked = true;
bankNthPartRadio.Checked = true;
incompatibleSelectionLabel.Visible = invalidConstantLabel.Visible = false;
if (mProject.CpuDef.HasAddr16) {
// Disable the 24-bit option. Having 16-bit selected will disable the rest.
width24Radio.Enabled = false;
}
outputPreviewListView.SetDoubleBuffered(true);
mInitializing = false;
UpdateControls();
}
private void okButton_Click(object sender, EventArgs e) {
Results = new SortedList<int, FormatDescriptor>();
private void okButton_Click(object sender, EventArgs e) { }
private void UpdateControls() {
if (mInitializing) {
return;
}
mInitializing = true; // no re-entry
lowThirdPartRadio.Enabled = width24Radio.Checked;
highThirdPartRadio.Enabled = width24Radio.Checked;
bankByteGroupBox.Enabled = width24Radio.Checked;
lowSecondPartRadio.Enabled = true;
// If the user selects "constant" for high byte or bank byte, then there is no
// 3rd part available for low/high, so we need to turn those back off.
if (width24Radio.Checked) {
bool haveThree = !(highConstantRadio.Checked || bankConstantRadio.Checked);
lowThirdPartRadio.Enabled = haveThree;
highThirdPartRadio.Enabled = haveThree;
// If "constant" is selected for high byte *and* bank byte, then there's no
// 2nd part available for low.
if (highConstantRadio.Checked && bankConstantRadio.Checked) {
lowSecondPartRadio.Enabled = false;
}
} else {
// For 16-bit address, if high byte is constant, then there's no second
// part for the low byte.
if (highConstantRadio.Checked) {
lowSecondPartRadio.Enabled = false;
}
}
// Was a now-invalidated radio button selected before?
if (!lowThirdPartRadio.Enabled && lowThirdPartRadio.Checked) {
// low now invalid, switch to whatever high isn't using
if (highFirstPartRadio.Checked) {
lowSecondPartRadio.Checked = true;
} else {
lowFirstPartRadio.Checked = true;
}
}
if (!highThirdPartRadio.Enabled && highThirdPartRadio.Checked) {
// high now invalid, switch to whatever low isn't using
if (lowFirstPartRadio.Checked) {
highSecondPartRadio.Checked = true;
} else {
highFirstPartRadio.Checked = true;
}
}
if (!lowSecondPartRadio.Enabled && lowSecondPartRadio.Checked) {
// Should only happen when high part is constant.
Debug.Assert(highFirstPartRadio.Checked == false);
lowFirstPartRadio.Checked = true;
}
mInitializing = false;
UpdatePreview();
okButton.Enabled = mOutputReady;
}
private void widthRadio_CheckedChanged(object sender, EventArgs e) {
UpdateControls();
}
private void pushRtsCheckBox_CheckedChanged(object sender, EventArgs e) {
UpdateControls();
}
private void lowByte_CheckedChanged(object sender, EventArgs e) {
// If we conflict with the high byte, change the high byte.
if (lowFirstPartRadio.Checked && highFirstPartRadio.Checked) {
highSecondPartRadio.Checked = true;
} else if (lowSecondPartRadio.Checked && highSecondPartRadio.Checked) {
highFirstPartRadio.Checked = true;
} else if (lowThirdPartRadio.Checked && highThirdPartRadio.Checked) {
highFirstPartRadio.Checked = true;
}
UpdateControls();
}
private void highByte_CheckedChanged(object sender, EventArgs e) {
// If we conflict with the low byte, change the low byte.
if (lowFirstPartRadio.Checked && highFirstPartRadio.Checked) {
lowSecondPartRadio.Checked = true;
} else if (lowSecondPartRadio.Checked && highSecondPartRadio.Checked) {
lowFirstPartRadio.Checked = true;
} else if (lowThirdPartRadio.Checked && highThirdPartRadio.Checked) {
lowFirstPartRadio.Checked = true;
}
UpdateControls();
}
private void bankByte_CheckedChanged(object sender, EventArgs e) {
UpdateControls();
}
private void highConstantTextBox_TextChanged(object sender, EventArgs e) {
highConstantRadio.Checked = true;
UpdateControls();
}
private void bankConstantTextBox_TextChanged(object sender, EventArgs e) {
bankConstantRadio.Checked = true;
UpdateControls();
}
private void UpdatePreview() {
mOutputReady = false;
int minDiv;
if (width16Radio.Checked) {
if (highConstantRadio.Checked) {
minDiv = 1;
} else {
minDiv = 2;
}
} else {
if (highConstantRadio.Checked) {
if (bankConstantRadio.Checked) {
minDiv = 1;
} else {
minDiv = 2;
}
} else {
if (bankConstantRadio.Checked) {
minDiv = 2;
} else {
minDiv = 3;
}
}
}
incompatibleSelectionLabel.Visible = invalidConstantLabel.Visible = false;
try {
// Start by clearing the previous contents of the list. If something goes
// wrong, we want to show the error messages on an empty list.
outputPreviewListView.BeginUpdate();
outputPreviewListView.Items.Clear();
if ((mSelection.Count % minDiv) != 0) {
incompatibleSelectionLabel.Visible = true;
return;
}
int highConstant = -1;
if (highConstantRadio.Checked) {
if (!Number.TryParseInt(highConstantTextBox.Text, out highConstant,
out int unused) || (highConstant != (byte) highConstant)) {
invalidConstantLabel.Visible = true;
return;
}
}
int bankConstant = -1;
if (bankConstantRadio.Enabled && bankConstantRadio.Checked) {
if (!Number.TryParseInt(bankConstantTextBox.Text, out bankConstant,
out int unused) || (bankConstant != (byte) bankConstant)) {
invalidConstantLabel.Visible = true;
return;
}
}
// Looks valid, generate format list.
GenerateFormats(minDiv, highConstant, bankConstant);
} finally {
outputPreviewListView.EndUpdate();
}
}
private void GenerateFormats(int div, int highConst, int bankConst) {
SortedList<int, FormatDescriptor> newDfds = new SortedList<int, FormatDescriptor>();
Dictionary<int, Symbol> newLabels = new Dictionary<int, Symbol>();
List<int> targetOffsets = new List<int>();
// Identify the offset where each set of data starts.
int span = mSelection.Count / div;
int lowOff, highOff, bankOff;
if (lowFirstPartRadio.Checked) {
lowOff = 0;
} else if (lowSecondPartRadio.Checked) {
lowOff = span;
} else if (lowThirdPartRadio.Checked) {
lowOff = span * 2;
} else {
Debug.Assert(false);
lowOff = -1;
}
if (highFirstPartRadio.Checked) {
highOff = 0;
} else if (highSecondPartRadio.Checked) {
highOff = span;
} else if (highThirdPartRadio.Checked) {
highOff = span * 2;
} else {
highOff = -1; // use constant
}
if (width24Radio.Checked) {
if (bankNthPartRadio.Checked) {
// Use whichever part isn't being used by the other two.
if (lowOff != 0 && highOff != 0) {
bankOff = 0;
} else if (lowOff != span && highOff != span) {
bankOff = span;
} else {
Debug.Assert(lowOff != span * 2 && highOff != span * 2);
bankOff = span * 2;
}
} else {
bankOff = -1; // use constant
}
} else {
bankOff = -1; // use constant
bankConst = 0; // always bank 0
}
Debug.WriteLine("Extract from low=" + lowOff + " high=" + highOff +
" bank=" + bankOff);
// The TypedRangeSet doesn't have an index operation, so copy the values into
// an array.
int[] offsets = new int[mSelection.Count];
int index = 0;
foreach (TypedRangeSet.Tuple tup in mSelection) {
offsets[index++] = tup.Value;
}
int adj = 0;
if (pushRtsCheckBox.Checked) {
adj = 1;
}
// Walk through the file data, generating addresses as we go.
byte[] fileData = mProject.FileData;
for (int i = 0; i < span; i++) {
byte low, high, bank;
low = fileData[offsets[lowOff + i]];
if (highOff >= 0) {
high = fileData[offsets[highOff + i]];
} else {
high = (byte) highConst;
}
if (bankOff >= 0) {
bank = fileData[offsets[bankOff + i]];
} else {
bank = (byte) bankConst;
}
int addr = ((bank << 16) | (high << 8) | low) + adj;
Debug.WriteLine("GOT " + i + ": " + addr.ToString("x6"));
int targetOffset = mProject.AddrMap.AddressToOffset(offsets[0], addr);
if (targetOffset < 0) {
// Address not within file bounds.
// TODO(maybe): look for matching platform/project symbols
AddPreviewItem(addr, -1, Properties.Resources.INVALID_ADDRESS);
} else {
// Note the same target offset may appear more than once.
targetOffsets.Add(targetOffset);
// If there's a user-defined label there already, use it. Otherwise, we'll
// need to generate one.
string targetLabel;
if (mProject.UserLabels.TryGetValue(targetOffset, out Symbol sym)) {
AddPreviewItem(addr, targetOffset, sym.Label);
targetLabel = sym.Label;
} else {
AddPreviewItem(addr, targetOffset, "(+)");
// Generate a symbol that's unique vs. the symbol table. We don't need
// it to be unique vs. the labels we're generating here, because we
// won't generate identical labels for different addresses, and we do
// want to generate a single label if more than one table entry refers
// to the same target.
Symbol tmpSym = SymbolTable.GenerateUniqueForAddress(addr,
mProject.SymbolTable, "T");
// tmpSym was returned as an auto-label, make it a user label instead
tmpSym = new Symbol(tmpSym.Label, tmpSym.Value, Symbol.Source.User,
Symbol.Type.LocalOrGlobalAddr);
newLabels[targetOffset] = tmpSym; // overwrites previous
targetLabel = tmpSym.Label;
}
// Now we need to create format descriptors for the addresses where we
// extracted the low, high, and bank values.
newDfds.Add(offsets[lowOff + i], FormatDescriptor.Create(1,
new WeakSymbolRef(targetLabel, WeakSymbolRef.Part.Low), false));
if (highOff >= 0) {
newDfds.Add(offsets[highOff + i], FormatDescriptor.Create(1,
new WeakSymbolRef(targetLabel, WeakSymbolRef.Part.High), false));
}
if (bankOff >= 0) {
newDfds.Add(offsets[bankOff + i], FormatDescriptor.Create(1,
new WeakSymbolRef(targetLabel, WeakSymbolRef.Part.Bank), false));
}
}
}
NewFormatDescriptors = newDfds;
NewUserLabels = newLabels;
AllTargetOffsets = targetOffsets;
mOutputReady = true;
}
private void AddPreviewItem(int addr, int offset, string label) {
ListViewItem lvi = new ListViewItem(mFormatter.FormatAddress(addr,
!mProject.CpuDef.HasAddr16));
if (offset >= 0) {
lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi,
mFormatter.FormatOffset24(offset)));
} else {
lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, "---"));
}
lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, label));
outputPreviewListView.Items.Add(lvi);
}
}
}

View File

@ -2225,7 +2225,7 @@ namespace SourceGen.AppForms {
}
formatSplitAddressTableToolStripMenuItem.Enabled =
(entityCounts.mDataLines > 1 && entityCounts.mCodeLines == 0);
(entityCounts.mDataLines > 0 && entityCounts.mCodeLines == 0);
toggleSingleBytesToolStripMenuItem.Enabled =
(entityCounts.mDataLines > 0 && entityCounts.mCodeLines == 0);
@ -2618,27 +2618,56 @@ namespace SourceGen.AppForms {
}
private void FormatSplitAddressTable_Click(object sender, EventArgs e) {
FormatSplitAddress dlg = new FormatSplitAddress(mProject.FileData,
mProject.SymbolTable, mOutputFormatter);
TypedRangeSet trs = dlg.Selection = GroupedOffsetSetFromSelected();
TypedRangeSet trs = GroupedOffsetSetFromSelected();
if (trs.Count == 0) {
// shouldn't happen
Debug.Assert(false, "FormatSplitAddressTable found nothing to edit");
dlg.Dispose();
return;
}
// TODO: check to see if the selection is eligible for treatment as a
// split-address table. If not, show a dialog explaining why.
FormatSplitAddress dlg = new FormatSplitAddress(mProject, trs, mOutputFormatter);
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.OK) {
ChangeSet cs = mProject.GenerateFormatMergeSet(dlg.Results);
// Start with the format descriptors.
ChangeSet cs = mProject.GenerateFormatMergeSet(dlg.NewFormatDescriptors);
// Add in the user labels.
foreach (KeyValuePair<int, Symbol> kvp in dlg.NewUserLabels) {
Symbol oldUserValue = null;
if (mProject.UserLabels.ContainsKey(kvp.Key)) {
Debug.Assert(false, "should not be replacing label");
oldUserValue = mProject.UserLabels[kvp.Key];
}
UndoableChange uc = UndoableChange.CreateLabelChange(kvp.Key,
oldUserValue, kvp.Value);
cs.Add(uc);
}
// Apply code hints.
TypedRangeSet newSet = new TypedRangeSet();
TypedRangeSet undoSet = new TypedRangeSet();
foreach (int offset in dlg.AllTargetOffsets) {
if (!mProject.GetAnattrib(offset).IsInstruction) {
CodeAnalysis.TypeHint oldType = mProject.TypeHints[offset];
if (oldType == CodeAnalysis.TypeHint.Code) {
continue; // already set
}
undoSet.Add(offset, (int)oldType);
newSet.Add(offset, (int)CodeAnalysis.TypeHint.Code);
}
}
if (newSet.Count != 0) {
cs.Add(UndoableChange.CreateTypeHintChange(undoSet, newSet));
}
// Finally, apply the change.
if (cs.Count != 0) {
ApplyUndoableChanges(cs);
} else {
Debug.WriteLine("No change to data formats");
Debug.WriteLine("No changes found");
}
}

View File

@ -292,7 +292,7 @@ namespace SourceGen {
// up with a user or platform label that matches an auto label, so we
// need to do some renaming in that case. Shouldn't happen often.
Symbol sym = SymbolTable.GenerateUniqueForAddress(mAnattribs[targetOffset].Address,
mProject.SymbolTable);
mProject.SymbolTable, "L");
mAnattribs[targetOffset].Symbol = sym;
// This will throw if the symbol already exists. That is the desired
// behavior, as that would be a bug.

View File

@ -582,6 +582,15 @@ namespace SourceGen.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to (unknown address).
/// </summary>
internal static string INVALID_ADDRESS {
get {
return ResourceManager.GetString("INVALID_ADDRESS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Legal Stuff.
/// </summary>

View File

@ -291,6 +291,9 @@
<data name="INITIAL_SYMBOL_FILES" xml:space="preserve">
<value>Symbol files:</value>
</data>
<data name="INVALID_ADDRESS" xml:space="preserve">
<value>(unknown address)</value>
</data>
<data name="LEGAL_STUFF_TITLE" xml:space="preserve">
<value>Legal Stuff</value>
</data>

View File

@ -216,10 +216,13 @@ namespace SourceGen {
/// Generates a unique address symbol. Does not add the symbol to the list.
/// </summary>
/// <param name="addr">Address label will be applied to</param>
/// <param name="symbols">Symbol table.</param>
/// <param name="prefix">Prefix to use; must start with a letter.</param>
/// <returns>Newly-created, unique symbol.</returns>
public static Symbol GenerateUniqueForAddress(int addr, SymbolTable symbols) {
public static Symbol GenerateUniqueForAddress(int addr, SymbolTable symbols,
string prefix) {
// $1234 == L1234, $05/1234 == L51234.
string label = "L" + addr.ToString("X4");
string label = prefix + addr.ToString("X4"); // always upper-case
if (symbols.TryGetValue(label, out Symbol unused)) {
const int MAX_RENAME = 999;
string baseLabel = label;