private void AddHeaderComment(DisasmProject proj, ChangeSet cs) { // Add header comment. StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format(Res.Strings.DEFAULT_HEADER_COMMENT_FMT, App.ProgramVersion)); sb.AppendLine(); foreach (SegmentMapEntry ent in mSegmentMap) { if (ent == null) { continue; } string segCmt = string.Format(Res.Strings.OMF_SEG_HDR_COMMENT_FMT, ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.SegName, mFormatter.FormatAddress(ent.Address, true), ent.Segment.Length); sb.AppendLine(segCmt); } UndoableChange uc = UndoableChange.CreateLongCommentChange( LineListGen.Line.HEADER_COMMENT_OFFSET, null, new MultiLineComment(sb.ToString())); cs.Add(uc); }
private bool GenerateDataAndProject() { // Sum up the segment lengths to get the total project size. int totalLen = 0; foreach (SegmentMapEntry ent in mSegmentMap) { if (ent == null) { continue; } totalLen += ent.Segment.Length; } Debug.WriteLine("Total length of loaded binary is " + totalLen); byte[] data = new byte[totalLen]; // Create the project object. DisasmProject proj = new DisasmProject(); proj.Initialize(data.Length); // Try to get the Apple IIgs system definition. This is fragile, because it // relies on the name in the JSON file, but it's optional. (If the default CPU // type stops being 65816, we should be sure to set that here.) try { // TODO(maybe): encapsulate this somewhere else string sysDefsPath = RuntimeDataAccess.GetPathName("SystemDefs.json"); SystemDefSet sds = SystemDefSet.ReadFile(sysDefsPath); SystemDef sd = sds.FindEntryByName(IIGS_SYSTEM_DEF); if (sd != null) { proj.ApplySystemDef(sd); } else { Debug.WriteLine("Unable to find Apple IIgs system definition"); } } catch (Exception) { // never mind Debug.WriteLine("Failed to apply Apple IIgs system definition"); } ChangeSet cs = new ChangeSet(mSegmentMap.Count * 2); AddHeaderComment(proj, cs); UndoableChange uc; // Load the segments, and add entries to the project. int bufOffset = 0; foreach (SegmentMapEntry ent in mSegmentMap) { if (ent == null) { continue; } if (ent.Segment.Kind == OmfSegment.SegmentKind.JumpTable) { if (!RelocJumpTable(ent, data, bufOffset, cs)) { // Could treat this as non-fatal, but it really ought to work. Debug.WriteLine("Jump Table reloc failed"); return(false); } } else { // Perform relocation. if (!RelocSegment(ent, data, bufOffset)) { return(false); } } // Add one or more address entries. (Normally one, but data segments // can straddle multiple pages.) AddAddressEntries(proj, ent, bufOffset, cs); 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); } bufOffset += ent.Segment.Length; } proj.PrepForNew(data, "new_proj"); foreach (KeyValuePair <int, DisasmProject.RelocData> kvp in mRelocData) { proj.RelocList.Add(kvp.Key, kvp.Value); } // Enable "use reloc" in the analysis parameters. ProjectProperties newProps = new ProjectProperties(proj.ProjectProps); newProps.AnalysisParams.UseRelocData = true; uc = UndoableChange.CreateProjectPropertiesChange(proj.ProjectProps, newProps); cs.Add(uc); // TODO(someday): by default we apply a code start tag to offset 0 of the first // segment. The placement should take the segment's ENTRY into account. Debug.WriteLine("Applying " + cs.Count + " changes"); proj.ApplyChanges(cs, false, out _); mLoadedData = data; mNewProject = proj; return(true); }