/// <summary> /// Sets up the annotations for the current machine. /// </summary> public void SetupMachineAnnotations() { // --- Read ROM annotations var spectrumVm = Parent.SpectrumVm; RomPageAnnotations = new Dictionary <int, DisassemblyAnnotation>(); RomAnnotationFiles = new Dictionary <int, string>(); var romConfig = spectrumVm.RomConfiguration; var roms = romConfig.NumberOfRoms; for (var i = 0; i < roms; i++) { var annFile = spectrumVm.RomProvider.GetAnnotationResourceName(romConfig.RomName, roms == 1 ? -1 : i); var annData = spectrumVm.RomProvider.LoadRomAnnotations(romConfig.RomName, roms == 1 ? -1 : i); DisassemblyAnnotation.Deserialize(annData, out var annotation); RomPageAnnotations.Add(i, annotation); RomAnnotationFiles.Add(i, annFile); } // --- Read the initial RAM annotations RamBankAnnotations = new Dictionary <int, DisassemblyAnnotation>(); SpectNetPackage.Default.CodeManager.AnnotationFileChanged += OnAnnotationFileChanged; OnAnnotationFileChanged(null, EventArgs.Empty); // --- Register Disassembly providers to use if (RomPageAnnotations.TryGetValue(romConfig.Spectrum48RomIndex, out var spectrumRomAnn)) { Z80Disassembler.SetProvider <ISpectrum48RomLabelProvider>( new Spectrum48RomLabelProvider(spectrumRomAnn)); } }
/// <summary> /// Loads the ROM information for the specified workspace /// </summary> private static void LoadRom(WorkspaceInfo workspace) { var rom = workspace.RomItem; if (rom == null) { return; } var romAnnotationFile = Path.Combine( Path.GetDirectoryName(rom.Filename), Path.GetFileNameWithoutExtension(rom.Filename)) + ".disann"; if (!File.Exists(romAnnotationFile)) { return; } // --- Get the contents of the annotation file var serialized = File.ReadAllText(romAnnotationFile); var annotations = DisassemblyAnnotation.Deserialize(serialized); workspace.RomInfo = new RomInfo { MemorySections = new List <MemorySection>(annotations.MemoryMap), LoadBytesInvalidHeaderAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesInvalidHeaderAddress")).Key, LoadBytesResumeAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesResumeAddress")).Key, LoadBytesRoutineAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesRoutineAddress")).Key, SaveBytesRoutineAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$SaveBytesRoutineAddress")).Key, SaveBytesResumeAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$SaveBytesResumeAddress")).Key, TokenTableAddress = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$TokenTableAddress")).Key, TokenCount = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$TokenCount")).Key, TokenOffset = annotations.Literals .FirstOrDefault(kvp => kvp.Value.Contains("$TokenOffset")).Key, TokenTable = new List <string>() }; // --- Get the content of the ROM file using (var stream = new StreamReader(rom.Filename).BaseStream) { stream.Seek(0, SeekOrigin.Begin); var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); workspace.RomInfo.RomBytes = bytes; } // --- Read the list of tokens from the ROM ReadTokenTable(workspace.RomInfo); }
public void SerializationWorksAsExpected() { // --- Arrange var dc = new DisassemblyAnnotation(); dc.SetLabel(0x0100, "FirstLabel"); dc.SetLabel(0x0200, "SecondLabel"); dc.SetComment(0x0100, "FirstComment"); dc.SetComment(0x0200, "SecondComment"); dc.SetPrefixComment(0x0100, "FirstPrefixComment"); dc.SetPrefixComment(0x0200, "SecondPrefixComment"); dc.AddLiteral(0x0000, "Entry"); dc.AddLiteral(0x0000, "Start"); dc.AddLiteral(0x0028, "Calculator"); dc.MemoryMap.Add(new MemorySection(0x0000, 0x3BFF)); dc.MemoryMap.Add(new MemorySection(0x3C00, 0x3FFF, MemorySectionType.ByteArray)); dc.SetLiteralReplacement(0x100, "Entry"); dc.SetLiteralReplacement(0x1000, "Calculator"); // --- Act var serialized = dc.Serialize(); DisassemblyAnnotation.Deserialize(serialized, out var back); // --- Assert dc.Labels.Count.ShouldBe(back.Labels.Count); foreach (var item in dc.Labels) { back.Labels[item.Key].ShouldBe(item.Value); } dc.Comments.Count.ShouldBe(back.Comments.Count); foreach (var item in dc.Comments) { back.Comments[item.Key].ShouldBe(item.Value); } dc.PrefixComments.Count.ShouldBe(back.PrefixComments.Count); foreach (var item in dc.PrefixComments) { back.PrefixComments[item.Key].ShouldBe(item.Value); } dc.Literals.Count.ShouldBe(back.Literals.Count); foreach (var item in dc.Literals) { back.Literals[item.Key].ForEach(v => dc.Literals[item.Key].ShouldContain(v)); dc.Literals[item.Key].ForEach(v => back.Literals[item.Key].ShouldContain(v)); } dc.LiteralReplacements.Count.ShouldBe(back.LiteralReplacements.Count); foreach (var item in dc.LiteralReplacements) { back.LiteralReplacements[item.Key].ShouldBe(item.Value); } dc.MemoryMap.Count.ShouldBe(back.MemoryMap.Count); for (var i = 0; i < dc.MemoryMap.Count; i++) { dc.MemoryMap[i].ShouldBe(back.MemoryMap[i]); } }
/// <summary> /// Saves the contents of annotations /// </summary> public void SaveAnnotations(DisassemblyAnnotation annotation, string filename) { if (annotation == null || filename == null) { return; } var annotationData = annotation.Serialize(); File.WriteAllText(filename, annotationData); }
public void ConstructorWorksAsExpected() { // --- Act var dc = new DisassemblyAnnotation(); // --- Assert dc.Labels.Count.ShouldBe(0); dc.Comments.Count.ShouldBe(0); dc.PrefixComments.Count.ShouldBe(0); dc.Literals.Count.ShouldBe(0); }
/// <summary> /// Remerges annotations /// </summary> private void Remerge() { MergedAnnotations = new DisassemblyAnnotation(); if (RomAnnotationFile != null) { MergedAnnotations.Merge(RomAnnotations); } if (ProjectAnnotations != null) { MergedAnnotations.Merge(ProjectAnnotations); } }
public void CreateLabelDoesNotSaveInvalidLabel() { // --- Arrange const string LABEL = "My$$Label$$"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.SetLabel(0x1000, LABEL); // --- Assert result.ShouldBe(false); dc.Labels.Count.ShouldBe(0); }
public void CreateLabelTruncatesTooLongLabel() { // --- Arrange const string LABEL = "Label012345678901234567890123456789"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.SetLabel(0x1000, LABEL); // --- Assert result.ShouldBe(true); dc.Labels.Count.ShouldBe(1); dc.Labels[0x1000].ShouldBe(LABEL.Substring(0, DisassemblyAnnotation.MAX_LABEL_LENGTH)); }
public void CreateReplacementWorksAsExpected() { // --- Arrange const string REPLACEMENT = "MyReplacement"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.SetLiteralReplacement(0x1000, REPLACEMENT); // --- Assert result.ShouldBe(true); dc.LiteralReplacements.Count.ShouldBe(1); dc.LiteralReplacements[0x1000].ShouldBe(REPLACEMENT); }
/// <summary> /// Restores the annotations from the ROM annotation and current project /// annotation files. /// </summary> public void RestoreAnnotations() { if (RomAnnotationFile != null) { var romSerialized = File.ReadAllText(RomAnnotationFile); RomAnnotations = DisassemblyAnnotation.Deserialize(romSerialized); } if (ProjectAnnotationFile != null) { var projectSerialized = File.ReadAllText(ProjectAnnotationFile); ProjectAnnotations = DisassemblyAnnotation.Deserialize(projectSerialized); } Remerge(); }
public void CreateLabelWorksAsExpected() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.SetLabel(0x1000, LABEL); // --- Assert result.ShouldBe(true); dc.Labels.Count.ShouldBe(1); dc.Labels[0x1000].ShouldBe(LABEL); }
public void CreatePrefixCommentWorksAsExpected() { // --- Arrange const string COMMENT = "MyComment"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.SetPrefixComment(0x1000, COMMENT); // --- Assert result.ShouldBe(true); dc.PrefixComments.Count.ShouldBe(1); dc.PrefixComments[0x1000].ShouldBe(COMMENT); }
public void CreatePrefixCommentHandlesNoRemove() { // --- Arrange const string COMMENT = "MyComment"; var dc = new DisassemblyAnnotation(); dc.SetPrefixComment(0x1000, COMMENT); // --- Act var result = dc.SetPrefixComment(0x2000, null); // --- Assert result.ShouldBe(false); dc.PrefixComments.Count.ShouldBe(1); }
public void CreatePrefixCommentRemovesWhitespaceComment() { // --- Arrange const string COMMENT = "MyComment"; var dc = new DisassemblyAnnotation(); dc.SetPrefixComment(0x1000, COMMENT); // --- Act var result = dc.SetPrefixComment(0x1000, " \t\t \r "); // --- Assert result.ShouldBe(true); dc.PrefixComments.Count.ShouldBe(0); }
public void CreateReplacementRemovesWhitespaceReplacement() { // --- Arrange const string REPLACEMENT = "MyReplacement"; var dc = new DisassemblyAnnotation(); dc.SetLiteralReplacement(0x1000, REPLACEMENT); // --- Act var result = dc.SetLiteralReplacement(0x1000, " "); // --- Assert result.ShouldBe(true); dc.LiteralReplacements.Count.ShouldBe(0); }
public void CreateLabelHandlesNoRemove() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); dc.SetLabel(0x1000, LABEL); // --- Act var result = dc.SetLabel(0x2000, null); // --- Assert result.ShouldBe(false); dc.Labels.Count.ShouldBe(1); }
public void CreateLabelRemovesWhitespaceLabel() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); dc.SetLabel(0x1000, LABEL); // --- Act var result = dc.SetLabel(0x1000, " \t\t \r "); // --- Assert result.ShouldBe(true); dc.Labels.Count.ShouldBe(0); }
public void CreateReplacementHandlesNoRemove() { // --- Arrange const string REPLACEMENT = "MyReplacement"; var dc = new DisassemblyAnnotation(); dc.SetLiteralReplacement(0x1000, REPLACEMENT); // --- Act var result = dc.SetComment(0x2000, null); // --- Assert result.ShouldBe(false); dc.LiteralReplacements.Count.ShouldBe(1); }
public void ApplyLiteralCanRemoveReplacement() { // --- Arrange const string REPLACEMENT = "MyReplacement"; var dc = new DisassemblyAnnotation(); dc.SetLiteralReplacement(0x1000, REPLACEMENT); // --- Act var result = dc.ApplyLiteral(0x1000, 0x0000, null); // --- Assert result.ShouldBeNull(); dc.LiteralReplacements.Count.ShouldBe(0); }
public void CreateCommentRemovesNullComment() { // --- Arrange const string COMMENT = "MyComment"; var dc = new DisassemblyAnnotation(); dc.SetComment(0x1000, COMMENT); // --- Act var result = dc.SetComment(0x1000, null); // --- Assert result.ShouldBe(true); dc.Comments.Count.ShouldBe(0); }
public void RemoveLiteralWorksAsExpected() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); dc.AddLiteral(0x1000, LABEL); // --- Act var result = dc.RemoveLiteral(0x1000, LABEL); // --- Assert result.ShouldBe(true); dc.Literals.Count.ShouldBe(0); }
public void GenerateSpectrum48Annotations() { // --- Arrange var dc = new DisassemblyAnnotation(); dc.MemoryMap.Add(new MemorySection(0x0000, 0x3BFF)); dc.MemoryMap.Add(new MemorySection(0x3C00, 0x3FFF)); dc.AddLiteral(0x04C2, "$SaveBytesRoutineAddress"); dc.AddLiteral(0x0000, "$SaveBytesResumeAddress"); dc.AddLiteral(0x056C, "$LoadBytesRoutineAddress"); dc.AddLiteral(0x05E2, "$LoadBytesResumeAddress"); dc.AddLiteral(0x05B6, "$LoadBytesInvalidHeaderAddress"); // --- Act Console.WriteLine(dc.Serialize()); }
public void CreateLabelForbidsDuplicateLabelName() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); dc.SetLabel(0x1000, LABEL); // --- Act var result = dc.SetLabel(0x1100, LABEL); // --- Assert result.ShouldBe(false); dc.Labels.Count.ShouldBe(1); dc.Labels[0x1000].ShouldBe(LABEL); }
public void ApplyLiteralCreatesNewSymbol() { // --- Arrange const string REPLACEMENT = "MyReplacement"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.ApplyLiteral(0x1000, 0x2000, REPLACEMENT); // --- Assert result.ShouldBeNull(); dc.Literals[0x2000].Count.ShouldBe(1); dc.Literals[0x2000][0].ShouldBe(REPLACEMENT); dc.LiteralReplacements.Count.ShouldBe(1); dc.LiteralReplacements[0x1000].ShouldBe(REPLACEMENT); }
/// <summary> /// Execute loading and processing the file /// </summary> /// <param name="fileName">The name of the file to load</param> protected override void LoadFile(string fileName) { // --- Read the .disann file _contents = File.ReadAllText(fileName); if (DisassemblyAnnotation.DeserializeBankAnnotations(_contents, out var anns)) { _annotations = anns; } else { _annotations = new Dictionary <int, DisassemblyAnnotation>(); if (DisassemblyAnnotation.Deserialize(_contents, out var single)) { _annotations.Add(0, single); } } }
public void CreateCommentOverwritesExistingComment() { // --- Arrange const string COMMENT = "MyComment"; const string COMMENT2 = "MyComment2"; var dc = new DisassemblyAnnotation(); dc.SetComment(0x1000, COMMENT); // --- Act var result = dc.SetComment(0x1000, COMMENT2); // --- Assert result.ShouldBe(true); dc.Comments.Count.ShouldBe(1); dc.Comments[0x1000].ShouldBe(COMMENT2); }
public void CreateLabelOverwritesExistingLabel() { // --- Arrange const string LABEL = "MyLabel"; const string LABEL2 = "MyLabel2"; var dc = new DisassemblyAnnotation(); dc.SetLabel(0x1000, LABEL); // --- Act var result = dc.SetLabel(0x1000, LABEL2); // --- Assert result.ShouldBe(true); dc.Labels.Count.ShouldBe(1); dc.Labels[0x1000].ShouldBe(LABEL2); }
public void AddLiteralWorksAsExpected() { // --- Arrange const string LABEL = "MyLabel"; var dc = new DisassemblyAnnotation(); // --- Act var result = dc.AddLiteral(0x1000, LABEL); // --- Assert result.ShouldBe(true); dc.Literals.Count.ShouldBe(1); var literals = dc.Literals[0x1000]; literals.Count.ShouldBe(1); literals.ShouldContain(l => l == LABEL); }
/// <summary> /// Gets the content of the ROM specified by its resource name /// </summary> /// <param name="romResourceName">ROM resource name</param> /// <returns>Content of the ROM</returns> public RomInfo LoadRom(string romResourceName) { RomInfo result; // --- Obtain the ROM annotations var resMan = GetFileResource(ResourceAssembly, romResourceName, ".disann"); if (resMan == null) { throw new InvalidOperationException($"Input stream for the '{romResourceName}' .disann file not found."); } using (var reader = new StreamReader(resMan)) { var serialized = reader.ReadToEnd(); var annotations = DisassemblyAnnotation.Deserialize(serialized); result = new RomInfo { MemorySections = new List <MemorySection>(annotations.MemoryMap), Annotations = annotations, LoadBytesInvalidHeaderAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesInvalidHeaderAddress")).Key, LoadBytesResumeAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesResumeAddress")).Key, LoadBytesRoutineAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$LoadBytesRoutineAddress")).Key, SaveBytesRoutineAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$SaveBytesRoutineAddress")).Key, SaveBytesResumeAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$SaveBytesResumeAddress")).Key, MainExecAddress = annotations.Literals.FirstOrDefault(kvp => kvp.Value.Contains("$MainExecAddress")).Key }; } // --- Obtain the ROM contents resMan = GetFileResource(ResourceAssembly, romResourceName, ".rom"); if (resMan == null) { throw new InvalidOperationException($"Input stream for the '{romResourceName}' .rom file not found."); } using (var stream = new StreamReader(resMan).BaseStream) { stream.Seek(0, SeekOrigin.Begin); var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); result.RomBytes = bytes; } return(result); }
/// <summary> /// Updates the RAM annotation file according to changes /// </summary> private void OnAnnotationFileChanged(object sender, EventArgs eventArgs) { var project = SpectNetPackage.Default.ActiveProject; var annFile = project?.DefaultAnnotationItem ?? project?.AnnotationProjectItems?.FirstOrDefault(); RamBankAnnotations.Clear(); if (annFile == null) { return; } RamBankAnnotationFile = annFile.Filename; var disAnn = File.ReadAllText(annFile.Filename); DisassemblyAnnotation.DeserializeBankAnnotations(disAnn, out var annotations); RamBankAnnotations = annotations; }