mirror of
https://github.com/fadden/6502bench.git
synced 2025-01-05 23:30:20 +00:00
Add two options to OMF converter
First, make the per-segment comments and notes optional. Second, add an "offset segment by $0100" feature that tries to shift each segment forward 256 bytes. Doing so avoids potential ambiguity with direct page locations. The 20212-reloc-data test no longer has the per-segment comments.
This commit is contained in:
parent
288a857e47
commit
6892040ea8
@ -138,6 +138,10 @@ namespace SourceGen {
|
||||
public const string EXPORT_LONG_LABEL_NEW_LINE = "export-long-label-new-line";
|
||||
public const string EXPORT_GENERATE_IMAGE_FILES = "export-generate-image-files";
|
||||
|
||||
// OMF export settings.
|
||||
public const string OMF_ADD_NOTES = "omf-add-notes";
|
||||
public const string OMF_OFFSET_SEGMENT_START = "omf-offset-segment-start";
|
||||
|
||||
// Internal debugging features.
|
||||
public const string DEBUG_MENU_ENABLED = "debug-menu-enabled";
|
||||
|
||||
|
@ -101,6 +101,25 @@ created with some basic attributes filled in.</p>
|
||||
<p>Only "Load" files (S16, PIF, TOL, etc) may be converted. Compiler object
|
||||
files and libraries contain unresolved references and are not supported.</p>
|
||||
|
||||
<p>To convert a file, extract it from the Apple II disk image, using a
|
||||
mode that does not modify the original (e.g. extract with "configure to
|
||||
preserve Apple II formats" in CiderPress). Open it with the OMF
|
||||
Converter tool. Click "Generate" to create a modified binary and a
|
||||
SourceGen project file.</p>
|
||||
|
||||
<p>If "offset segment start by $0100" is checked, the converter will try
|
||||
to shift the segment's load address from <code>$xx/0000</code> to
|
||||
<code>$xx/0100</code>. This can make the generated code a little nicer
|
||||
to work with because it removes potential ambiguity with direct page
|
||||
addresses. For example, <code>LDA $56</code> and <code>LDA $0056</code>
|
||||
may be interpreted as the same thing by the assembler, requiring
|
||||
generation of operand width disambiguators. By shifting the initial
|
||||
address we avoid the potential ambiguity.</p>
|
||||
<p>Check "add comments and notes for each segment" to add a long comment
|
||||
and a note at the start of each segment. The comments include the
|
||||
segment name, type, and optional flags. The notes just provide a quick
|
||||
way to jump to a segment.</p>
|
||||
|
||||
<p>The binary generated by the tool is not in OMF format and will not
|
||||
execute on an Apple IIgs. To be functional, the sources must be
|
||||
assembled by a program capable of generating OMF output, such as Merlin.</p>
|
||||
|
@ -19,6 +19,8 @@
|
||||
"SmartPlbHandling":true},
|
||||
|
||||
"PlatformSymbolFileIdentifiers":["RT:Apple/Cxxx-IO.sym65",
|
||||
"RT:Apple/C08x-DiskII.sym65",
|
||||
"RT:Apple/E0Cxxx-IO.sym65",
|
||||
"RT:Apple/IIgs-ROM.sym65",
|
||||
"RT:Apple/GSOS.sym65"],
|
||||
"ExtensionScriptFileIdentifiers":["RT:Apple/GSOS.cs",
|
||||
@ -60,66 +62,10 @@
|
||||
},
|
||||
|
||||
"LongComments":{
|
||||
"0":{
|
||||
"Text":"Segment 02: Kind=Code; Attrs=NoSpecial; Name=\u0027 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"143":{
|
||||
"Text":"Segment 03: Kind=Data; Attrs=BankRel, Dynamic; Name=\u0027PosFFE0 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"195":{
|
||||
"Text":"Segment 04: Kind=Code; Attrs=NoSpecial; Name=\u0027Bank2 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"230":{
|
||||
"Text":"Segment 05: Kind=Code; Attrs=AbsBank, Dynamic; Name=\u0027Bank8 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"284":{
|
||||
"Text":"Segment 06: Kind=Data; Attrs=0; Name=\u0027Filler \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0}},
|
||||
},
|
||||
|
||||
"Notes":{
|
||||
"0":{
|
||||
"Text":"Seg02: 03/0000 \u0027 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"143":{
|
||||
"Text":"Seg03: 04/ffe0 \u0027PosFFE0 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"195":{
|
||||
"Text":"Seg04: 02/3456 \u0027Bank2 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"230":{
|
||||
"Text":"Seg05: 08/0000 \u0027Bank8 \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0},
|
||||
|
||||
"284":{
|
||||
"Text":"Seg06: 06/0000 \u0027Filler \u0027",
|
||||
"BoxMode":false,
|
||||
"MaxWidth":80,
|
||||
"BackgroundColor":0}},
|
||||
},
|
||||
|
||||
"UserLabels":{
|
||||
},
|
||||
|
@ -19,9 +19,9 @@
|
||||
; "PosFFE0" -> E0 FF 00
|
||||
; "Bank2" -> 56 34 02
|
||||
; "Bank8" -> 00 10 08
|
||||
; - Convert out.20212 to "20212-reloc-data" with OMF converter.
|
||||
; - The project file generally requires no edits, except to delete the
|
||||
; header comment. Leaving the segment-start comments in seems fine.
|
||||
; - Convert out.20212 to "20212-reloc-data" with OMF converter. Disable
|
||||
; "offset segment by $0100" and "add comments and notes".
|
||||
; - The project file requires no edits, except to delete the header comment.
|
||||
|
||||
DSK out.20212 ;output file name, must be ProDOS-compat
|
||||
TYP $b3 ;S16
|
||||
|
@ -31,8 +31,15 @@ namespace SourceGen.Tools.Omf {
|
||||
public class Loader {
|
||||
private const string IIGS_SYSTEM_DEF = "Apple IIgs (GS/OS)";
|
||||
|
||||
[Flags]
|
||||
public enum Flags {
|
||||
AddNotes = 1 << 0,
|
||||
OffsetSegmentStart = 1 << 1,
|
||||
}
|
||||
|
||||
private OmfFile mOmfFile;
|
||||
private Formatter mFormatter;
|
||||
private Flags mFlags;
|
||||
|
||||
private byte[] mLoadedData;
|
||||
private DisasmProject mNewProject;
|
||||
@ -57,11 +64,12 @@ namespace SourceGen.Tools.Omf {
|
||||
/// </summary>
|
||||
/// <param name="omfFile">OMF file to load.</param>
|
||||
/// <param name="formatter">Text formatter.</param>
|
||||
public Loader(OmfFile omfFile, Formatter formatter) {
|
||||
public Loader(OmfFile omfFile, Formatter formatter, Flags flags) {
|
||||
Debug.Assert(omfFile.OmfFileKind == OmfFile.FileKind.Load);
|
||||
|
||||
mOmfFile = omfFile;
|
||||
mFormatter = formatter;
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -259,6 +267,19 @@ namespace SourceGen.Tools.Omf {
|
||||
}
|
||||
}
|
||||
|
||||
// If possible, shift the address to xx/$0100. This is useful because it means
|
||||
// we won't have to put width disambiguators on any data accesses to $00xx
|
||||
// locations. We can't do this if the address is fixed, aligned to a 64K
|
||||
// boundary, or is too large.
|
||||
if ((mFlags & Flags.OffsetSegmentStart) != 0 && !fixedAddr && !bankRel &&
|
||||
omfSeg.Align <= 0x0100 && omfSeg.Length <= (65536-256)) {
|
||||
if ((addr & 0x0000ffff) == 0x0000) {
|
||||
addr |= 0x0100;
|
||||
} else {
|
||||
Debug.Assert(false, "Unexpected nonzero bank address found");
|
||||
}
|
||||
}
|
||||
|
||||
SegmentMapEntry ent = new SegmentMapEntry(omfSeg, addr);
|
||||
mSegmentMap.Add(ent);
|
||||
}
|
||||
@ -352,20 +373,22 @@ namespace SourceGen.Tools.Omf {
|
||||
// can straddle multiple pages.)
|
||||
AddAddressEntries(proj, ent, bufOffset, cs);
|
||||
|
||||
// Add a comment identifying the segment and its attributes.
|
||||
string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT,
|
||||
ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.Attrs, ent.Segment.SegName);
|
||||
uc = UndoableChange.CreateLongCommentChange(bufOffset, null,
|
||||
new MultiLineComment(segCmt));
|
||||
cs.Add(uc);
|
||||
if ((mFlags & Flags.AddNotes) != 0) {
|
||||
// Add a comment identifying the segment and its attributes.
|
||||
string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT,
|
||||
ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.Attrs, ent.Segment.SegName);
|
||||
uc = UndoableChange.CreateLongCommentChange(bufOffset, null,
|
||||
new MultiLineComment(segCmt));
|
||||
cs.Add(uc);
|
||||
|
||||
// Add a note identifying the segment.
|
||||
string segNote = string.Format(Res.Strings.OMF_SEG_NOTE_FMT,
|
||||
ent.Segment.SegNum, mFormatter.FormatAddress(ent.Address, true),
|
||||
ent.Segment.SegName);
|
||||
uc = UndoableChange.CreateNoteChange(bufOffset, null,
|
||||
new MultiLineComment(segNote));
|
||||
cs.Add(uc);
|
||||
// Add a note identifying the segment.
|
||||
string segNote = string.Format(Res.Strings.OMF_SEG_NOTE_FMT,
|
||||
ent.Segment.SegNum, mFormatter.FormatAddress(ent.Address, true),
|
||||
ent.Segment.SegName);
|
||||
uc = UndoableChange.CreateNoteChange(bufOffset, null,
|
||||
new MultiLineComment(segNote));
|
||||
cs.Add(uc);
|
||||
}
|
||||
|
||||
bufOffset += ent.Segment.Length;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ limitations under the License.
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Grid.Row="0">
|
||||
@ -95,10 +96,19 @@ limitations under the License.
|
||||
IsReadOnly="True" VerticalScrollBarVisibility="Auto">
|
||||
</TextBox>
|
||||
|
||||
<DockPanel Grid.Row="5" LastChildFill="False" Margin="0,16,0,0">
|
||||
<Button DockPanel.Dock="Left" Content="Generate SourceGen Project" Padding="4,0"
|
||||
IsEnabled="{Binding IsLoadFile}" Click="GenerateProject_Click"/>
|
||||
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" IsCancel="True"/>
|
||||
<GroupBox Grid.Row="5" Header="Generate SourceGen Project" Padding="2,0" Margin="0,8,0,0">
|
||||
<StackPanel>
|
||||
<CheckBox Content="Offset segment start by $0100" Margin="0,4,0,0"
|
||||
IsChecked="{Binding OffsetSegmentStart}"/>
|
||||
<CheckBox Content="Add comments and notes for each segment" Margin="0,4,0,0"
|
||||
IsChecked="{Binding AddNotes}"/>
|
||||
<Button Content="Generate" Width="100" Margin="0,8" HorizontalAlignment="Left"
|
||||
IsEnabled="{Binding IsLoadFile}" Click="GenerateProject_Click"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<DockPanel Grid.Row="6" LastChildFill="False" Margin="0,16,0,0">
|
||||
<Button DockPanel.Dock="Right" Content="Close" Width="70" IsCancel="True"/>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
@ -101,6 +101,22 @@ namespace SourceGen.Tools.Omf.WpfGui {
|
||||
get { return mOmfFile.OmfFileKind == OmfFile.FileKind.Load; }
|
||||
}
|
||||
|
||||
public bool OffsetSegmentStart {
|
||||
get { return AppSettings.Global.GetBool(AppSettings.OMF_OFFSET_SEGMENT_START, true); }
|
||||
set {
|
||||
AppSettings.Global.SetBool(AppSettings.OMF_OFFSET_SEGMENT_START, value);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddNotes {
|
||||
get { return AppSettings.Global.GetBool(AppSettings.OMF_ADD_NOTES, false); }
|
||||
set {
|
||||
AppSettings.Global.SetBool(AppSettings.OMF_ADD_NOTES, value);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
@ -166,7 +182,15 @@ namespace SourceGen.Tools.Omf.WpfGui {
|
||||
}
|
||||
|
||||
private void GenerateProject_Click(object sender, RoutedEventArgs e) {
|
||||
Loader loader = new Loader(mOmfFile, mFormatter);
|
||||
Loader.Flags flags = 0;
|
||||
if (AddNotes) {
|
||||
flags |= Loader.Flags.AddNotes;
|
||||
}
|
||||
if (OffsetSegmentStart) {
|
||||
flags |= Loader.Flags.OffsetSegmentStart;
|
||||
}
|
||||
|
||||
Loader loader = new Loader(mOmfFile, mFormatter, flags);
|
||||
if (!loader.Prepare()) {
|
||||
// Unexpected. If there's a valid reason for this, we need to add details
|
||||
// to the error message.
|
||||
|
Loading…
Reference in New Issue
Block a user