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

Finish split-address table formatter

A lot of things react to other things in this dialog.  I think I
got everything behaving correctly.
This commit is contained in:
Andy McFadden 2019-07-13 15:50:11 -07:00
parent c6b63afb3e
commit e49ee6f20b
6 changed files with 288 additions and 202 deletions

View File

@ -343,12 +343,17 @@ jmptabh .dd1 >func1
<p>Sometimes the tables contain <code>address - 1</code>, because the
values are to be pushed onto the stack for an RTS call.</p>
<p>The split-address table formatter helps you associate symbols with the
<p>While the .dd2 case is easy to format with the data operand editor,
formatting addresses whose components are split into multiple tables can
be tedious.</p>
<p>The Split-Address Table Formatter helps you associate symbols with the
addresses in the table. To use it, start by selecting the entire table.
In the example above, you would select all 6 bytes. The number of bytes
in each part must be equal: here, it's 3 low bytes, followed by 3 high
bytes. If the number of bytes selected can't be evenly divided by the
number of parts, the formatter will report an error.</p>
number of parts -- two parts for 16-bit data, three parts for 24-bit data --
the formatter will report an error.</p>
<p>With the data selected, open the format dialog with
Actions &gt; Format Split-Address Table. The rather complicated dialog
is split into sections.</p>
@ -358,17 +363,17 @@ is split into sections.</p>
don't have the CPU set to 65816.) If the address parts are being pushed
on the stack for an RTS/RTL, check the "Adjusted for RTS/RTL" box to
adjust them by 1.</li>
<li>Low Bytes: indicate which part of the table holds the low bytes. In
<li>Low Byte Source: indicate which part of the table holds the low bytes. In
the example above, the low bytes came first, followed by the high bytes,
so you would select "first part of selection". If they were stored the
other way around, you would click "second part" instead.</li>
<li>High Bytes: indicate which part of the table holds the high bytes. For
<li>High Byte Source: indicate which part of the table holds the high bytes. For
a 16-bit address this will be the part you didn't pick for the low bytes.
Sometimes, if all addresses land on the same 256-byte page, the high byte
will be a constant in the code, and only the low bytes will be stored in
a table. If that's the case, select "Constant", and enter the high byte
in the text box. (Decimal, hex, and binary are accepted.)</li>
<li>Bank Bytes: for 24-bit addresses, you can select "Nth part of
<li>Bank Byte Source: for 24-bit addresses, you can select "Nth part of
selection", which will just use whichever part you didn't specify for
the low and high bytes. If the table holds 16-bit addresses, you can
use the "Constant" field to specify the data bank.</li>
@ -394,7 +399,7 @@ It also tells you how many groups there are, but unlike the data operand
formatter, the split-address table formatter doesn't care about group
boundaries. For this reason, tables do not have to be contiguous in
memory. The low bytes and high bytes could be on separate 256-byte
pages.</p>
pages. You just need to have all of the data selected.</p>
<p>It should be mentioned that SourceGen does not record the fact that the
data in question is part of a table. The formatting, labels, and code hints

View File

@ -1853,9 +1853,9 @@ namespace SourceGenWPF {
public bool CanFormatSplitAddress() {
EntityCounts counts = SelectionAnalysis.mEntityCounts;
// Must be at least one byte of data, and no code.
// Must be at least one line of data, and no code. Note this is lines, not bytes,
// so we can't screen out single-byte lines without additional work.
return (counts.mDataLines > 0 && counts.mCodeLines == 0);
}
public void FormatSplitAddress() {

View File

@ -74,6 +74,7 @@ limitations under the License.
<system:String x:Key="str_InitialExtensionScripts">Extension scripts:</system:String>
<system:String x:Key="str_InitialParameters">Default settings:</system:String>
<system:String x:Key="str_InitialSymbolFiles">Symbol files:</system:String>
<system:String x:Key="str_InvalidAddress">(unknown address)</system:String>
<system:String x:Key="str_NoFilesAvailable">no files available</system:String>
<system:String x:Key="str_OpenDataDoesntExist">The file doesn't exist.</system:String>
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>

View File

@ -129,6 +129,8 @@ namespace SourceGenWPF.Res {
(string)Application.Current.FindResource("str_InitialParameters");
public static string INITIAL_SYMBOL_FILES =
(string)Application.Current.FindResource("str_InitialSymbolFiles");
public static string INVALID_ADDRESS =
(string)Application.Current.FindResource("str_InvalidAddress");
public static string NO_FILES_AVAILABLE =
(string)Application.Current.FindResource("str_NoFilesAvailable");
public static string OPEN_DATA_DOESNT_EXIST =

View File

@ -28,9 +28,11 @@ limitations under the License.
Loaded="Window_Loaded">
<Window.Resources>
<system:String x:Key="str_SingleByte">One byte is selected</system:String>
<system:String x:Key="str_SingleGroup">There are {0} bytes selected</system:String>
<system:String x:Key="str_MultiGroup">There are {0} bytes selected, across {1} groups</system:String>
<system:String x:Key="str_SingleByte">Only one byte is selected!</system:String>
<system:String x:Key="str_SingleGroup">There are {0} bytes selected.</system:String>
<system:String x:Key="str_MultiGroup">There are {0} bytes selected, across {1} groups.</system:String>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Grid Margin="8">
@ -43,97 +45,123 @@ limitations under the License.
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"
<TextBlock Name="selectionInfoLabel" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"
Text="{StaticResource str_MultiGroup}"/>
<StackPanel Grid.Column="0" Grid.Row="1" Margin="0,8,8,0">
<GroupBox Header="Address Characteristics">
<StackPanel>
<RadioButton Name="width16Radio" GroupName="Addr" Margin="0,4,0,0"
Content="16-bit"/>
Content="16-bit" Checked="WidthRadio_CheckedChanged"/>
<RadioButton Name="width24Radio" GroupName="Addr" Margin="0,4,0,0"
Content="24-bit"/>
<CheckBox Margin="0,4,0,0" Content="Adjusted for RTS/RTL (target - 1)"/>
Content="24-bit" Checked="WidthRadio_CheckedChanged"/>
<CheckBox Margin="0,4,0,0" Content="Adjusted for RTS/RTL (target - 1)"
IsChecked="{Binding AdjustedForReturn}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Low Bytes">
<GroupBox Header="Low Byte Source">
<StackPanel>
<RadioButton Name="lowFirstPartRadio" GroupName="Low" Margin="0,4,0,0"
Content="First part of selection"/>
Content="First part of selection"
Checked="LowByte_CheckedChanged"/>
<RadioButton Name="lowSecondPartRadio" GroupName="Low" Margin="0,4,0,0"
Content="Second part of selection"/>
Content="Second part of selection"
Checked="LowByte_CheckedChanged"/>
<RadioButton Name="lowThirdPartRadio" GroupName="Low" Margin="0,4,0,0"
Content="Third part of selection"/>
Content="Third part of selection"
IsEnabled="{Binding ElementName=width24Radio, Path=IsChecked}"
Checked="LowByte_CheckedChanged"/>
</StackPanel>
</GroupBox>
<GroupBox Header="High Bytes">
<GroupBox Header="High Byte Source">
<StackPanel>
<RadioButton Name="highFirstPartRadio" GroupName="High" Margin="0,4,0,0"
Content="First part of selection"/>
Content="First part of selection"
Checked="HighByte_CheckedChanged"/>
<RadioButton Name="highSecondPartRadio" GroupName="High" Margin="0,4,0,0"
Content="Second part of selection"/>
Content="Second part of selection"
Checked="HighByte_CheckedChanged"/>
<RadioButton Name="highThirdPartRadio" GroupName="High" Margin="0,4,0,0"
Content="Third part of selection"/>
Content="Third part of selection"
IsEnabled="{Binding ElementName=width24Radio, Path=IsChecked}"
Checked="HighByte_CheckedChanged"/>
<StackPanel Orientation="Horizontal">
<RadioButton Name="highConstantRadio" GroupName="High" Margin="0,4,0,0"
Content="Constant:"/>
<TextBox Name="highConstantTextBox" Width="100" Margin="8,1,0,0"/>
Content="Constant:" Checked="HighByte_CheckedChanged"/>
<TextBox Name="highConstantTextBox" Width="100" Margin="8,2,0,0"
TextChanged="HighConstantTextBox_TextChanged"/>
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="Bank Bytes">
<StackPanel>
<GroupBox Header="Bank Byte Source">
<StackPanel IsEnabled="{Binding ElementName=width24Radio, Path=IsChecked}">
<RadioButton Name="bankNthPartRadio" GroupName="Bank" Margin="0,4,0,0"
Content="Nth part of selection"/>
Content="Nth part of selection"
Checked="BankByte_CheckedChanged"/>
<StackPanel Orientation="Horizontal">
<RadioButton Name="bankConstantRadio" GroupName="Bank" Margin="0,4,0,0"
Content="Constant:"/>
<TextBox Name="bankConstantTextBox" Width="100" Margin="8,1,0,0"/>
Content="Constant:"
Checked="BankByte_CheckedChanged"/>
<TextBox Name="bankConstantTextBox" Width="100" Margin="8,2,0,0"
TextChanged="BankConstantTextBox_TextChanged"/>
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="Options">
<StackPanel>
<CheckBox Content="Add code entry hint if needed" Margin="0,4,0,0"/>
<CheckBox Content="Add code entry hint if needed" Margin="0,4,0,0"
IsChecked="{Binding WantCodeHints}"/>
</StackPanel>
</GroupBox>
</StackPanel>
<DockPanel Grid.Column="1" Grid.Row="1" Margin="0,8,0,0">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
<Button Name="okButton" Content="OK" IsDefault="True" Width="70"
IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
<Button Name="cancelButton" Content="Cancel" IsCancel="True"
Width="70" Margin="4,0,0,0"/>
</StackPanel>
<Grid Grid.Column="1" Grid.Row="1" Margin="0,8,0,0">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
<Button Name="okButton" Content="OK" IsDefault="True" Width="70"
IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
<Button Name="cancelButton" Content="Cancel" IsCancel="True"
Width="70" Margin="4,0,0,0"/>
</StackPanel>
<GroupBox DockPanel.Dock="Top" Header="Generated Addresses">
<!-- We're currently auto-sizing everything outside this, so the width of
the columns determines the width of the window. Resizing the columns resizes
the window, even though the window isn't resizeable. "It's a feature." -->
<DataGrid Name="outputPreviewList"
Margin="0,2,0,0"
IsReadOnly="True"
ItemsSource="{Binding OutputPreviewList}"
FontFamily="{StaticResource GeneralMonoFont}"
SnapsToDevicePixels="True"
GridLinesVisibility="Vertical"
VerticalGridLinesBrush="#FF7F7F7F"
AutoGenerateColumns="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Addr" Width="60" Binding="{Binding Addr}"/>
<DataGridTextColumn Header="Offset" Width="60" Binding="{Binding Offset}"/>
<DataGridTextColumn Header="Symbol" Width="180" Binding="{Binding Type}"/>
</DataGrid.Columns>
</DataGrid>
</GroupBox>
</DockPanel>
<GroupBox DockPanel.Dock="Top" Header="Generated Addresses">
<!-- We're currently auto-sizing everything outside this, so the width of
the columns determines the width of the window. Resizing the columns resizes
the window, even though the window isn't resizeable. "It's a feature." -->
<DataGrid Name="outputPreviewList"
Margin="0,2,0,0"
Height="318"
IsReadOnly="True"
ItemsSource="{Binding OutputPreviewList}"
FontFamily="{StaticResource GeneralMonoFont}"
SnapsToDevicePixels="True"
GridLinesVisibility="Vertical"
VerticalGridLinesBrush="#FF7F7F7F"
AutoGenerateColumns="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Addr" Width="60" Binding="{Binding Addr}"/>
<DataGridTextColumn Header="Offset" Width="60" Binding="{Binding Offset}"/>
<DataGridTextColumn Header="Symbol" Width="180" Binding="{Binding Symbol}"/>
</DataGrid.Columns>
</DataGrid>
</GroupBox>
</DockPanel>
<TextBlock Name="incompatibleSelectionLabel"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-20,0,0"
Text="Options incompatible with selection" FontSize="16" Foreground="Red"
Visibility="{Binding IncompatibleSelectionVisibility, Converter={StaticResource BoolToVis}}"/>
<TextBlock Name="invalidConstantLabel"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,20,0,0"
Text="Invalid constant" FontSize="16" Foreground="Red"
Visibility="{Binding InvalidConstantVisibility, Converter={StaticResource BoolToVis}}"/>
</Grid>
</Grid>
</Window>

View File

@ -15,6 +15,7 @@
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@ -43,19 +44,59 @@ namespace SourceGenWPF.WpfGui {
/// </summary>
public List<int> AllTargetOffsets { get; private set; }
public bool WantCodeHints = true; // TODO
#if false
{
get {
return addCodeHintCheckBox.Checked;
/// <summary>
/// If set, targets are offset by one for RTS/RTL.
/// </summary>
public bool AdjustedForReturn {
get { return mAdjustedForReturn; }
set {
mAdjustedForReturn = value;
OnPropertyChanged();
UpdateControls();
}
}
private bool mAdjustedForReturn;
/// <summary>
/// If set, caller will add code entry hints to targets.
/// </summary>
public bool WantCodeHints {
get { return mWantCodeHints; }
set {
mWantCodeHints = value;
OnPropertyChanged();
}
}
private bool mWantCodeHints;
/// <summary>
/// Set to true to make the "incompatible with selection" message visible.
/// </summary>
public bool IncompatibleSelectionVisibility {
get { return mIncompatibleSelectionVisibility; }
set {
mIncompatibleSelectionVisibility = value;
OnPropertyChanged();
}
}
private bool mIncompatibleSelectionVisibility;
/// <summary>
/// Set to true to make the "invalid constant" message visible.
/// </summary>
public bool InvalidConstantVisibility {
get { return mInvalidConstantVisibility; }
set {
mInvalidConstantVisibility = value;
OnPropertyChanged();
}
}
private bool mInvalidConstantVisibility;
/// <summary>
/// Set to true when valid output is available.
/// </summary>
private bool mOutputReady;
#endif
/// <summary>
/// Set to true when input is valid. Controls whether the OK button is enabled.
@ -69,6 +110,19 @@ namespace SourceGenWPF.WpfGui {
}
private bool mIsValid;
public class OutputPreviewItem {
public string Addr { get; private set; }
public string Offset { get; private set; }
public string Symbol { get; private set; }
public OutputPreviewItem(string addr, string offset, string symbol) {
Addr = addr;
Offset = offset;
Symbol = symbol;
}
}
public ObservableCollection<OutputPreviewItem> OutputPreviewList { 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
@ -86,6 +140,11 @@ namespace SourceGenWPF.WpfGui {
/// </summary>
private Formatter mFormatter;
/// <summary>
/// Reentrancy block for UpdateControls().
/// </summary>
private bool mUpdating;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
@ -103,145 +162,147 @@ namespace SourceGenWPF.WpfGui {
mFormatter = formatter;
mSelection = selection;
IsValid = false;
OutputPreviewList = new ObservableCollection<OutputPreviewItem>();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
// TDOO
mUpdating = true;
string fmt, infoStr;
if (mSelection.RangeCount == 1 && mSelection.Count == 1) {
infoStr = (string)FindResource("str_SingleByte");
} else if (mSelection.RangeCount == 1) {
fmt = (string)FindResource("str_SingleGroup");
infoStr = string.Format(fmt, mSelection.Count);
} else {
fmt = (string)FindResource("str_MultiGroup");
infoStr = string.Format(fmt, mSelection.Count, mSelection.RangeCount);
}
selectionInfoLabel.Text = infoStr;
width16Radio.IsChecked = true;
lowFirstPartRadio.IsChecked = true;
highSecondPartRadio.IsChecked = true;
bankNthPartRadio.IsChecked = true;
IncompatibleSelectionVisibility = InvalidConstantVisibility = false;
if (mProject.CpuDef.HasAddr16) {
// Disable the 24-bit option. Having 16-bit selected will disable the rest.
width24Radio.IsEnabled = false;
}
mUpdating = false;
UpdateControls();
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
DialogResult = true;
}
#if 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 UpdateControls() {
if (mInitializing) {
if (mUpdating) {
return;
}
mInitializing = true; // no re-entry
mUpdating = true; // no re-entry
lowThirdPartRadio.Enabled = width24Radio.Checked;
highThirdPartRadio.Enabled = width24Radio.Checked;
bankByteGroupBox.Enabled = width24Radio.Checked;
// handled with XAML bindings
//lowThirdPartRadio.Enabled = width24Radio.Checked;
//highThirdPartRadio.Enabled = width24Radio.Checked;
//bankByteGroupBox.Enabled = width24Radio.Checked;
lowSecondPartRadio.Enabled = true;
lowSecondPartRadio.IsEnabled = 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 (width24Radio.IsChecked == true) {
bool haveThree = !(highConstantRadio.IsChecked == true ||
bankConstantRadio.IsChecked == true);
lowThirdPartRadio.IsEnabled = haveThree;
highThirdPartRadio.IsEnabled = 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;
if (highConstantRadio.IsChecked == true && bankConstantRadio.IsChecked == true) {
lowSecondPartRadio.IsEnabled = 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;
if (highConstantRadio.IsChecked == true) {
lowSecondPartRadio.IsEnabled = false;
}
}
// Was a now-invalidated radio button selected before?
if (!lowThirdPartRadio.Enabled && lowThirdPartRadio.Checked) {
if (!lowThirdPartRadio.IsEnabled && lowThirdPartRadio.IsChecked == true) {
// low now invalid, switch to whatever high isn't using
if (highFirstPartRadio.Checked) {
lowSecondPartRadio.Checked = true;
if (highFirstPartRadio.IsChecked == true) {
lowSecondPartRadio.IsChecked = true;
} else {
lowFirstPartRadio.Checked = true;
lowFirstPartRadio.IsChecked = true;
}
}
if (!highThirdPartRadio.Enabled && highThirdPartRadio.Checked) {
if (width16Radio.IsChecked == true && highThirdPartRadio.IsChecked == true) {
// high now invalid, switch to whatever low isn't using
if (lowFirstPartRadio.Checked) {
highSecondPartRadio.Checked = true;
if (lowFirstPartRadio.IsChecked == true) {
highSecondPartRadio.IsChecked = true;
} else {
highFirstPartRadio.Checked = true;
highFirstPartRadio.IsChecked = true;
}
}
if (!lowSecondPartRadio.Enabled && lowSecondPartRadio.Checked) {
if (!lowSecondPartRadio.IsEnabled && lowSecondPartRadio.IsChecked == true) {
// Should only happen when high part is constant.
Debug.Assert(highFirstPartRadio.Checked == false);
lowFirstPartRadio.Checked = true;
Debug.Assert(highFirstPartRadio.IsChecked == false);
lowFirstPartRadio.IsChecked = true;
}
mInitializing = false;
mUpdating = false;
UpdatePreview();
okButton.Enabled = mOutputReady;
IsValid = mOutputReady;
}
private void widthRadio_CheckedChanged(object sender, EventArgs e) {
private void WidthRadio_CheckedChanged(object sender, RoutedEventArgs e) {
UpdateControls();
}
private void pushRtsCheckBox_CheckedChanged(object sender, EventArgs e) {
UpdateControls();
}
private void lowByte_CheckedChanged(object sender, EventArgs e) {
private void LowByte_CheckedChanged(object sender, RoutedEventArgs 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;
if (lowFirstPartRadio.IsChecked == true && highFirstPartRadio.IsChecked == true) {
highSecondPartRadio.IsChecked = true;
} else if (lowSecondPartRadio.IsChecked == true && highSecondPartRadio.IsChecked == true) {
highFirstPartRadio.IsChecked = true;
} else if (lowThirdPartRadio.IsChecked == true && highThirdPartRadio.IsChecked == true) {
highFirstPartRadio.IsChecked = true;
}
UpdateControls();
}
private void highByte_CheckedChanged(object sender, EventArgs e) {
private void HighByte_CheckedChanged(object sender, RoutedEventArgs 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;
if (lowFirstPartRadio.IsChecked == true && highFirstPartRadio.IsChecked == true) {
lowSecondPartRadio.IsChecked = true;
} else if (lowSecondPartRadio.IsChecked == true && highSecondPartRadio.IsChecked == true) {
lowFirstPartRadio.IsChecked = true;
} else if (lowThirdPartRadio.IsChecked == true && highThirdPartRadio.IsChecked == true) {
lowFirstPartRadio.IsChecked = true;
}
UpdateControls();
}
private void bankByte_CheckedChanged(object sender, EventArgs e) {
private void BankByte_CheckedChanged(object sender, EventArgs e) {
UpdateControls();
}
private void highConstantTextBox_TextChanged(object sender, EventArgs e) {
highConstantRadio.Checked = true;
private void HighConstantTextBox_TextChanged(object sender, TextChangedEventArgs e) {
highConstantRadio.IsChecked = true;
UpdateControls();
}
private void bankConstantTextBox_TextChanged(object sender, EventArgs e) {
bankConstantRadio.Checked = true;
private void BankConstantTextBox_TextChanged(object sender, TextChangedEventArgs e) {
bankConstantRadio.IsChecked = true;
UpdateControls();
}
@ -250,21 +311,21 @@ namespace SourceGenWPF.WpfGui {
int minDiv;
if (width16Radio.Checked) {
if (highConstantRadio.Checked) {
if (width16Radio.IsChecked == true) {
if (highConstantRadio.IsChecked == true) {
minDiv = 1;
} else {
minDiv = 2;
}
} else {
if (highConstantRadio.Checked) {
if (bankConstantRadio.Checked) {
if (highConstantRadio.IsChecked == true) {
if (bankConstantRadio.IsChecked == true) {
minDiv = 1;
} else {
minDiv = 2;
}
} else {
if (bankConstantRadio.Checked) {
if (bankConstantRadio.IsChecked == true) {
minDiv = 2;
} else {
minDiv = 3;
@ -272,42 +333,37 @@ namespace SourceGenWPF.WpfGui {
}
}
incompatibleSelectionLabel.Visible = invalidConstantLabel.Visible = false;
IncompatibleSelectionVisibility = InvalidConstantVisibility = 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();
// Start by clearing the previous contents of the list. If something goes
// wrong, we want to show the error messages on an empty list.
OutputPreviewList.Clear();
if ((mSelection.Count % minDiv) != 0) {
incompatibleSelectionLabel.Visible = true;
if ((mSelection.Count % minDiv) != 0) {
IncompatibleSelectionVisibility = true;
return;
}
int highConstant = -1;
if (highConstantRadio.IsChecked == true) {
if (!Number.TryParseInt(highConstantTextBox.Text, out highConstant,
out int unused) || (highConstant != (byte) highConstant)) {
InvalidConstantVisibility = 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();
}
int bankConstant = -1;
if (bankConstantRadio.IsEnabled && bankConstantRadio.IsChecked == true) {
if (!Number.TryParseInt(bankConstantTextBox.Text, out bankConstant,
out int unused) || (bankConstant != (byte) bankConstant)) {
InvalidConstantVisibility = true;
return;
}
}
// Looks valid, generate format list.
GenerateFormats(minDiv, highConstant, bankConstant);
}
private void GenerateFormats(int div, int highConst, int bankConst) {
@ -319,27 +375,27 @@ namespace SourceGenWPF.WpfGui {
int span = mSelection.Count / div;
int lowOff, highOff, bankOff;
if (lowFirstPartRadio.Checked) {
if (lowFirstPartRadio.IsChecked == true) {
lowOff = 0;
} else if (lowSecondPartRadio.Checked) {
} else if (lowSecondPartRadio.IsChecked == true) {
lowOff = span;
} else if (lowThirdPartRadio.Checked) {
} else if (lowThirdPartRadio.IsChecked == true) {
lowOff = span * 2;
} else {
Debug.Assert(false);
lowOff = -1;
}
if (highFirstPartRadio.Checked) {
if (highFirstPartRadio.IsChecked == true) {
highOff = 0;
} else if (highSecondPartRadio.Checked) {
} else if (highSecondPartRadio.IsChecked == true) {
highOff = span;
} else if (highThirdPartRadio.Checked) {
} else if (highThirdPartRadio.IsChecked == true) {
highOff = span * 2;
} else {
highOff = -1; // use constant
}
if (width24Radio.Checked) {
if (bankNthPartRadio.Checked) {
if (width24Radio.IsChecked == true) {
if (bankNthPartRadio.IsChecked == true) {
// Use whichever part isn't being used by the other two.
if (lowOff != 0 && highOff != 0) {
bankOff = 0;
@ -369,7 +425,7 @@ namespace SourceGenWPF.WpfGui {
}
int adj = 0;
if (pushRtsCheckBox.Checked) {
if (AdjustedForReturn) {
adj = 1;
}
@ -396,7 +452,7 @@ namespace SourceGenWPF.WpfGui {
if (targetOffset < 0) {
// Address not within file bounds.
// TODO(maybe): look for matching platform/project symbols
AddPreviewItem(addr, -1, Properties.Resources.INVALID_ADDRESS);
AddPreviewItem(addr, -1, Res.Strings.INVALID_ADDRESS);
} else {
// Note the same target offset may appear more than once.
targetOffsets.Add(targetOffset);
@ -447,17 +503,11 @@ namespace SourceGenWPF.WpfGui {
}
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);
OutputPreviewItem newItem = new OutputPreviewItem(
mFormatter.FormatAddress(addr, !mProject.CpuDef.HasAddr16),
(offset >= 0 ? mFormatter.FormatOffset24(offset) : "---"),
label);
OutputPreviewList.Add(newItem);
}
#endif
}
}