From 58a415bd9301b95735bc9b824f403676341b33f3 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Tue, 30 Jun 2020 09:27:29 -0700 Subject: [PATCH] Finish initial work on OMF file handling Generate multiple .ORG directives for segments that span multiple banks. Some assemblers don't like it when things cross. This is pretty rare (Cryllan Mission is an example). Conversion of OMF Load files to a data/project pair is generally working. The 65816 source code generators need some work though. --- SourceGen/Tools/Omf/Loader.cs | 46 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/SourceGen/Tools/Omf/Loader.cs b/SourceGen/Tools/Omf/Loader.cs index 0bcb762..35dda01 100644 --- a/SourceGen/Tools/Omf/Loader.cs +++ b/SourceGen/Tools/Omf/Loader.cs @@ -305,19 +305,14 @@ namespace SourceGen.Tools.Omf { return false; } - // Add an address entry. - - // TODO: need to add multiple address entries if this straddles a segment. - - int origAddr = proj.AddrMap.Get(bufOffset); - UndoableChange uc = UndoableChange.CreateAddressChange(bufOffset, - origAddr, ent.Address); - cs.Add(uc); + // Add one or more address entries. (Normally one, but data segments + // can straddle multiple pages.) + AddAddressEntries(proj, ent, bufOffset, cs); // Add a comment identifying the segment. string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT, ent.Segment.SegNum, ent.Segment.SegName, ent.Segment.Kind); - uc = UndoableChange.CreateLongCommentChange(bufOffset, null, + UndoableChange uc = UndoableChange.CreateLongCommentChange(bufOffset, null, new MultiLineComment(segCmt)); cs.Add(uc); @@ -333,6 +328,33 @@ namespace SourceGen.Tools.Omf { return true; } + private static void AddAddressEntries(DisasmProject proj, SegmentMapEntry ent, + int bufOffset, ChangeSet cs) { + int addr = ent.Address; + int segRem = ent.Segment.Length; + + while (true) { + int origAddr = proj.AddrMap.Get(bufOffset); + UndoableChange uc = UndoableChange.CreateAddressChange(bufOffset, + origAddr, addr); + cs.Add(uc); + + // Compare amount of space in this bank to amount left in segment. + int bankRem = 0x00010000 - (addr & 0xffff); + if (bankRem > segRem) { + // All done, bail. + break; + } + + // Advance to start of next bank. + addr += bankRem; + Debug.Assert((addr & 0x0000ffff) == 0); + bufOffset += bankRem; + segRem -= bankRem; + Debug.WriteLine("Adding additional ORG at " + addr); + } + } + private bool RelocSegment(SegmentMapEntry ent, byte[] data, int bufOffset) { //const int INVALID_RELOC = 0x00ffffff; byte[] srcData = ent.Segment.GetConstData(); @@ -377,6 +399,12 @@ namespace SourceGen.Tools.Omf { data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8); data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16); break; + case 4: + data[bufOffset + omfRel.Offset] = (byte)(relocAddr); + data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8); + data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16); + data[bufOffset + omfRel.Offset + 3] = (byte)(relocAddr >> 24); + break; default: Debug.WriteLine("Invalid reloc width " + omfRel.Width); return false;