1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-25 14:34:27 +00:00

First step toward Apple IIgs OMF file handling

This lays a bit of groundwork for an OMF file analyzer / viewer.
This commit is contained in:
Andy McFadden 2020-06-23 17:21:18 -07:00
parent c47beffcee
commit 5026fd6569
11 changed files with 298 additions and 27 deletions

View File

@ -797,7 +797,7 @@ namespace SourceGen {
/// </summary>
/// <param name="dataFileName">Full pathname.</param>
/// <returns>Data file contents.</returns>
private byte[] LoadDataFile(string dataFileName) {
private static byte[] LoadDataFile(string dataFileName) {
byte[] fileData;
using (FileStream fs = File.Open(dataFileName, FileMode.Open, FileAccess.Read)) {
@ -4093,15 +4093,10 @@ namespace SourceGen {
}
public void ShowFileHexDump() {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = Res.Strings.FILE_FILTER_ALL,
FilterIndex = 1
};
if (fileDlg.ShowDialog() != true) {
if (!OpenAnyFile(out string pathName)) {
return;
}
string fileName = fileDlg.FileName;
FileInfo fi = new FileInfo(fileName);
FileInfo fi = new FileInfo(pathName);
if (fi.Length > Tools.WpfGui.HexDumpViewer.MAX_LENGTH) {
string msg = string.Format(Res.Strings.OPEN_DATA_TOO_LARGE_FMT,
fi.Length / 1024, Tools.WpfGui.HexDumpViewer.MAX_LENGTH / 1024);
@ -4111,7 +4106,7 @@ namespace SourceGen {
}
byte[] data;
try {
data = File.ReadAllBytes(fileName);
data = File.ReadAllBytes(pathName);
} catch (Exception ex) {
// not expecting this to happen
MessageBox.Show(ex.Message);
@ -4121,7 +4116,7 @@ namespace SourceGen {
// Create the dialog without an owner, and add it to the "unowned" list.
Tools.WpfGui.HexDumpViewer dlg = new Tools.WpfGui.HexDumpViewer(null,
data, mFormatter);
dlg.SetFileName(Path.GetFileName(fileName));
dlg.SetFileName(Path.GetFileName(pathName));
dlg.Closing += (sender, e) => {
Debug.WriteLine("Window " + dlg + " closed, removing from unowned list");
mUnownedWindows.Remove(dlg);
@ -4137,18 +4132,66 @@ namespace SourceGen {
}
public void SliceFiles() {
if (!OpenAnyFile(out string pathName)) {
return;
}
Tools.WpfGui.FileSlicer slicer = new Tools.WpfGui.FileSlicer(this.mMainWin, pathName,
mFormatter);
slicer.ShowDialog();
}
public void ConvertOmf() {
if (!OpenAnyFile(out string pathName)) {
return;
}
// Load the file here, so basic problems like empty / oversized files can be
// reported immediately.
byte[] fileData = null;
using (FileStream fs = File.Open(pathName, FileMode.Open, FileAccess.Read)) {
string errMsg = null;
if (fs.Length == 0) {
errMsg = Res.Strings.OPEN_DATA_EMPTY;
} else if (fs.Length < Tools.Omf.OmfFile.MIN_FILE_SIZE) {
errMsg = string.Format(Res.Strings.OPEN_DATA_TOO_SMALL_FMT, fs.Length);
} else if (fs.Length > Tools.Omf.OmfFile.MAX_FILE_SIZE) {
errMsg = string.Format(Res.Strings.OPEN_DATA_TOO_LARGE_FMT,
fs.Length / 1024, Tools.Omf.OmfFile.MAX_FILE_SIZE / 1024);
}
if (errMsg == null) {
fileData = new byte[fs.Length];
int actual = fs.Read(fileData, 0, (int)fs.Length);
if (actual != fs.Length) {
errMsg = Res.Strings.OPEN_DATA_PARTIAL_READ;
}
}
if (errMsg != null) {
MessageBox.Show(errMsg, Res.Strings.ERR_FILE_GENERIC_CAPTION,
MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
Tools.Omf.WpfGui.OmfViewer ov =
new Tools.Omf.WpfGui.OmfViewer(this.mMainWin, pathName, fileData);
ov.ShowDialog();
}
private bool OpenAnyFile(out string pathName) {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = Res.Strings.FILE_FILTER_ALL,
FilterIndex = 1
};
if (fileDlg.ShowDialog() != true) {
return;
pathName = null;
return false;
}
string pathName = Path.GetFullPath(fileDlg.FileName);
Tools.WpfGui.FileSlicer slicer = new Tools.WpfGui.FileSlicer(this.mMainWin, pathName,
mFormatter);
slicer.ShowDialog();
pathName = Path.GetFullPath(fileDlg.FileName);
return true;
}
#endregion Tools
@ -4240,16 +4283,11 @@ namespace SourceGen {
}
public void Debug_ApplesoftToHtml() {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = Res.Strings.FILE_FILTER_ALL,
FilterIndex = 1
};
if (fileDlg.ShowDialog() != true) {
if (!OpenAnyFile(out string basPathName)) {
return;
}
byte[] data;
string basPathName = Path.GetFullPath(fileDlg.FileName);
try {
data = File.ReadAllBytes(basPathName);
} catch (IOException ex) {
@ -4326,6 +4364,7 @@ namespace SourceGen {
ApplyUndoableChanges(cs);
}
// Disable "analyze uncategorized data" for best results.
public void Debug_ApplyPlatformSymbols() {
ChangeSet cs = new ChangeSet(1);

View File

@ -137,6 +137,7 @@ limitations under the License.
<system:String x:Key="str_OpenDataLoadFailedFmt">The file could not be opened: {0}.</system:String>
<system:String x:Key="str_OpenDataPartialRead">Unable to read the entire file</system:String>
<system:String x:Key="str_OpenDataTooLargeFmt">File is too large ({0:N0} KiB, max is {1:N0} KiB).</system:String>
<system:String x:Key="str_OpenDataTooSmallFmt">File is too small ({0} bytes).</system:String>
<system:String x:Key="str_OpenDataWrongLengthFmt">The file is {0:N0} bytes long, but the project expected {1:N0}.</system:String>
<system:String x:Key="str_OpenDataWrongCrcFmt">The file has CRC {0}, but the project expected {1}.</system:String>
<system:String x:Key="str_OperationFailed">Failed</system:String>

View File

@ -255,6 +255,8 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_OpenDataLoadFailedFmt");
public static string OPEN_DATA_TOO_LARGE_FMT =
(string)Application.Current.FindResource("str_OpenDataTooLargeFmt");
public static string OPEN_DATA_TOO_SMALL_FMT =
(string)Application.Current.FindResource("str_OpenDataTooSmallFmt");
public static string OPEN_DATA_WRONG_CRC_FMT =
(string)Application.Current.FindResource("str_OpenDataWrongCrcFmt");
public static string OPEN_DATA_WRONG_LENGTH_FMT =

View File

@ -85,6 +85,10 @@
<DependentUpon>GenTestRunner.xaml</DependentUpon>
</Compile>
<Compile Include="Tools\ApplesoftToHtml.cs" />
<Compile Include="Tools\Omf\OmfFile.cs" />
<Compile Include="Tools\Omf\WpfGui\OmfViewer.xaml.cs">
<DependentUpon>OmfViewer.xaml</DependentUpon>
</Compile>
<Compile Include="Tools\VirtualHexDump.cs" />
<Compile Include="Tools\WpfGui\FileConcatenator.xaml.cs">
<DependentUpon>FileConcatenator.xaml</DependentUpon>
@ -276,6 +280,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Tools\Omf\WpfGui\OmfViewer.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Tools\WpfGui\FileConcatenator.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -0,0 +1,58 @@
/*
* Copyright 2020 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
namespace SourceGen.Tools.Omf {
/// <summary>
/// Apple IIgs OMF file.
/// </summary>
/// <remarks>
/// References:
/// - "Apple IIgs Programmer's Workshop Reference". Chapter 7, page 228, describes
/// OMF v1.0 and v2.0.
/// - "Apple IIgs GS/OS Reference, for GS/OS System Software Version 5.0 and later".
/// Appendix F describes OMF v2.1, and Chapter 8 has some useful information about
/// how the loader works.
/// - "Undocumented Secrets of the Apple IIGS System Loader" by Neil Parker,
/// http://nparker.llx.com/a2/loader.html . Among other things it documents ExpressLoad
/// segments, something Apple apparently never did.
/// - Apple IIgs Tech Note #66, "ExpressLoad Philosophy".
///
/// Related:
/// - https://www.brutaldeluxe.fr/products/crossdevtools/omfanalyzer/
/// - https://github.com/fadden/ciderpress/blob/master/reformat/Disasm.cpp
/// </remarks>
public class OmfFile {
public const int MIN_FILE_SIZE = 37; // can't be smaller than v0 segment hdr
public const int MAX_FILE_SIZE = (1 << 24) - 1; // cap it at 16MB
// TODO:
// - has an overall file type (load, object, RTL)
// - determine with a prioritized series of "could this be ____" checks
// - holds list of OmfSegment
// - has a list of warnings and errors that arose during parsing
// - holds on to byte[] with data
// OmfSegment:
// - header (common data, plus name/value dict with version-specific fields for display)
// - ref back to OmfFile for byte[] access?
// - list of OmfRecord
// - file-type-specific stuff can be generated and cached in second pass, e.g.
// generate a full relocation dictionary for load files (can't do this until we
// know the overall file type, which we can't know until all segments have been
// processed a bit)
}
}

View File

@ -0,0 +1,89 @@
<!--
Copyright 2020 faddenSoft
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Window x:Class="SourceGen.Tools.Omf.WpfGui.OmfViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SourceGen.Tools.Omf.WpfGui"
mc:Ignorable="d"
Title="OMF File Viewer"
SizeToContent="Height" Width="600" ResizeMode="NoResize"
ShowInTaskbar="False" WindowStartupLocation="CenterOwner">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<TextBlock DockPanel.Dock="Left" Text="File:" Margin="0,1,0,0"/>
<TextBox DockPanel.Dock="Left" IsReadOnly="True" Margin="8,0,0,0" Text="C:\\File\Name\Here"/>
</DockPanel>
<TextBlock Grid.Row="1" Text="File is a {something}, with {N} segments" Margin="0,8,0,0"/>
<DataGrid Name="segmentList" Grid.Row="2" Height="200" Margin="0,8,0,0"
IsReadOnly="True"
ItemsSource="{Binding SegmentListItems}"
FontFamily="{StaticResource GeneralMonoFont}"
SnapsToDevicePixels="True"
GridLinesVisibility="Vertical"
VerticalGridLinesBrush="#FF7F7F7F"
AutoGenerateColumns="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
SelectionMode="Single"
MouseDoubleClick="SegmentList_MouseDoubleClick">
<DataGrid.Resources>
<!-- make the no-focus color the same as the in-focus color -->
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="{x:Static SystemColors.HighlightColor}"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
Color="{x:Static SystemColors.HighlightTextColor}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Num" Width="50" Binding="{Binding SegNum}"/>
<DataGridTextColumn Header="Type" Width="72" Binding="{Binding Value}"/>
<DataGridTextColumn Header="LoadName" Width="100" Binding="{Binding Type}"/>
<DataGridTextColumn Header="SegName" Width="100" Binding="{Binding Width}"/>
<DataGridTextColumn Header="File Size" Width="100" Binding="{Binding Comment}"/>
<DataGridTextColumn Header="Mem Size Size" Width="100" Binding="{Binding Comment}"/>
</DataGrid.Columns>
</DataGrid>
<TextBlock Grid.Row="3" Text="File notes:" Margin="0,8,0,0"/>
<TextBox Grid.Row="4" Margin="0,4,0,0" Height="50"
Text="Test&#x0d;stuff1&#x0d;stuff2&#x0d;stuff3"
IsReadOnly="True" VerticalScrollBarVisibility="Auto">
</TextBox>
<DockPanel Grid.Row="5" LastChildFill="False" Margin="0,16,0,0">
<Button DockPanel.Dock="Left" Content="Convert to SourceGen Project" Padding="4,0"/>
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" IsCancel="True"/>
</DockPanel>
</Grid>
</Window>

View File

@ -0,0 +1,68 @@
/*
* Copyright 2020 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace SourceGen.Tools.Omf.WpfGui {
/// <summary>
/// Apple IIgs OMF file viewer.
/// </summary>
public partial class OmfViewer : Window, INotifyPropertyChanged {
private string mPathName;
private byte[] mFileData;
//private Brush mDefaultLabelColor = SystemColors.WindowTextBrush;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class SegmentListItem {
public int SegNum { get; private set; }
// TODO: take OMFSegment obj
public SegmentListItem(int segNum) {
SegNum = segNum;
}
}
public List<SegmentListItem> SegmentListItems { get; private set; } = new List<SegmentListItem>();
public OmfViewer(Window owner, string pathName, byte[] data) {
InitializeComponent();
Owner = owner;
DataContext = this;
mPathName = pathName;
mFileData = data;
SegmentListItems.Add(new SegmentListItem(123));
SegmentListItems.Add(new SegmentListItem(456));
}
private void SegmentList_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
Debug.WriteLine("DCLICK");
}
}
}

View File

@ -20,10 +20,10 @@ using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using CommonUtil;
using System.Windows.Controls;
namespace SourceGen.Tools.WpfGui {
/// <summary>

View File

@ -14,18 +14,16 @@
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Win32;
using Asm65;
using System.Text;
using System.Windows.Media;
namespace SourceGen.Tools.WpfGui {
/// <summary>

View File

@ -64,6 +64,7 @@ limitations under the License.
</RoutedUICommand>
<RoutedUICommand x:Key="CloseCmd" Text="Close"/>
<RoutedUICommand x:Key="ConcatenateFilesCmd" Text="Concatenate Files..."/>
<RoutedUICommand x:Key="ConvertOmfCmd" Text="Convert OMF..."/>
<RoutedUICommand x:Key="CreateLocalVariableTableCmd" Text="Create Local Variable Table..."/>
<RoutedUICommand x:Key="DeleteMlcCmd" Text="Delete Note/Long Comment">
<RoutedUICommand.InputGestures>
@ -221,6 +222,8 @@ limitations under the License.
CanExecute="IsProjectOpen" Executed="CloseCmd_Executed"/>
<CommandBinding Command="{StaticResource ConcatenateFilesCmd}"
Executed="ConcatenateFilesCmd_Executed"/>
<CommandBinding Command="{StaticResource ConvertOmfCmd}"
Executed="ConvertOmfCmd_Executed"/>
<CommandBinding Command="{StaticResource CreateLocalVariableTableCmd}"
CanExecute="CanCreateLocalVariableTable" Executed="CreateLocalVariableTableCmd_Executed"/>
<CommandBinding Command="{StaticResource DeleteMlcCmd}"
@ -426,6 +429,7 @@ limitations under the License.
<MenuItem Command="{StaticResource ShowFileHexDumpCmd}"/>
<MenuItem Command="{StaticResource ConcatenateFilesCmd}"/>
<MenuItem Command="{StaticResource SliceFilesCmd}"/>
<MenuItem Command="{StaticResource ConvertOmfCmd}"/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Command="Help"/>

View File

@ -1142,6 +1142,10 @@ namespace SourceGen.WpfGui {
mMainCtrl.ConcatenateFiles();
}
private void ConvertOmfCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.ConvertOmf();
}
private void CreateLocalVariableTableCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.CreateLocalVariableTable();
}