/// <summary> /// Generates byte array output for the specified section /// </summary> /// <param name="section">Section information</param> private void GenerateByteArray(MemorySection section) { var length = section.EndAddress - section.StartAddress + 1; for (var i = 0; i < length; i += 8) { var sb = new StringBuilder(200); sb.Append(".defb "); for (var j = 0; j < 8; j++) { if (i + j >= length) { break; } if (j > 0) { sb.Append(", "); } sb.AppendFormat("#{0:X2}", MemoryContents[section.StartAddress + i + j]); } var item = new DisassemblyItem((ushort)(section.StartAddress + i)) { Instruction = sb.ToString() }; _output.AddItem(item); } }
/// <summary> /// Creates disassembler output for the specified section /// </summary> /// <param name="section">Section information</param> private void DisassembleSection(MemorySection section) { _offset = section.StartAddress; _overflow = false; var endOffset = section.EndAddress; var isSpectrumSpecific = false; while (_offset <= endOffset && !_overflow) { if (isSpectrumSpecific) { var spectItem = DisassembleSpectrumSpecificOperation(out isSpectrumSpecific); if (spectItem != null) { _output.AddItem(spectItem); } } else { // --- Disassemble the current item var item = DisassembleOperation(); if (item != null) { _output.AddItem(item); isSpectrumSpecific = ShouldEnterSpectrumSpecificMode(item); } } } LabelFixup(); }
/// <summary> /// Generates word array output for the specified section /// </summary> /// <param name="section">Section information</param> private void GenerateWordArray(MemorySection section) { var length = section.EndAddress - section.StartAddress + 1; for (var i = 0; i < length; i += 8) { if (i + 1 >= length) break; var sb = new StringBuilder(200); sb.Append(".defw "); for (var j = 0; j < 8; j += 2) { if (i + j + 1 >= length) break; if (j > 0) { sb.Append(", "); } var value = (ushort)(MemoryContents[section.StartAddress + i + j * 2] + (MemoryContents[section.StartAddress + i + j * 2 + 1] << 8)); sb.AppendFormat("#{0:X4}", value); } var item = new DisassemblyItem((ushort)(section.StartAddress + i)) { Instruction = sb.ToString() }; _output.AddItem(item); } if (length % 2 == 1) { GenerateByteArray(new MemorySection(section.EndAddress, section.EndAddress)); } }
/// <summary> /// Disassembles the memory from the specified start address with the given endAddress /// </summary> /// <param name="startAddress">The start address of the disassembly</param> /// <param name="endAddress">The end address of the disassembly</param> /// <returns> /// The disassembly output /// </returns> public DisassemblyOutput Disassemble(ushort startAddress = 0x0000, ushort endAddress = 0xFFFF) { _output = new DisassemblyOutput(); if (endAddress >= MemoryContents.Length) { endAddress = (ushort)(MemoryContents.Length - 1); } var refSection = new MemorySection(startAddress, endAddress); // --- Let's go through the memory sections foreach (var section in MemorySections) { if (!section.Overlaps(refSection)) { continue; } var toDisassemble = section.Intersect(refSection); switch (section.SectionType) { case MemorySectionType.Disassemble: DisassembleSection(toDisassemble); break; case MemorySectionType.ByteArray: GenerateByteArray(toDisassemble); break; case MemorySectionType.WordArray: GenerateWordArray(toDisassemble); break; case MemorySectionType.Skip: GenerateSkipOutput(toDisassemble); break; case MemorySectionType.Rst28Calculator: GenerateRst28ByteCodeOutput(toDisassemble); break; case MemorySectionType.GraphArray: GenerateDefgArray(toDisassemble, 1); break; case MemorySectionType.GraphArray2: GenerateDefgArray(toDisassemble, 2); break; case MemorySectionType.GraphArray3: GenerateDefgArray(toDisassemble, 3); break; case MemorySectionType.GraphArray4: GenerateDefgArray(toDisassemble, 4); break; } } return(_output); }
/// <summary> /// Generates skip output for the specified section /// </summary> /// <param name="section">Section information</param> private void GenerateSkipOutput(MemorySection section) { var item = new DisassemblyItem(section.StartAddress) { Instruction = $".skip {section.EndAddress - section.StartAddress + 1:X4}H" }; _output.AddItem(item); }
/// <summary> /// Generates byte array output for the specified section /// </summary> /// <param name="section">Section information</param> /// <param name="rowBytes">Number of bytes to add to a .DEFG row</param> private void GenerateDefgArray(MemorySection section, int rowBytes) { var length = section.EndAddress - section.StartAddress + 1; var sb = new StringBuilder(200); var opCodes = new StringBuilder(); var byteInRow = 0; var startAddr = section.StartAddress; for (var i = 0; i < length; i++) { if (byteInRow == 0) { sb.Append(".defg"); } var content = MemoryContents[section.StartAddress + i]; opCodes.Append($"{content:X2} "); sb.Append(" "); for (var j = 0; j < 8; j++) { sb.Append((content & 0x80) == 0 ? "." : "X"); content <<= 1; } byteInRow++; if (byteInRow >= rowBytes) { byteInRow = 0; var item = new DisassemblyItem(startAddr) { Instruction = sb.ToString(), OpCodes = opCodes.ToString() }; _output.AddItem(item); startAddr = (ushort)(section.StartAddress + i + 1); sb.Clear(); opCodes.Clear(); } } if (byteInRow == 0) { return; } var lastItem = new DisassemblyItem(startAddr) { Instruction = sb.ToString(), OpCodes = opCodes.ToString() }; _output.AddItem(lastItem); }
/// <summary> /// Generates bytecode output for the specified memory section /// </summary> /// <param name="section">Section information</param> private void GenerateRst28ByteCodeOutput(MemorySection section) { _spectMode = SpectrumSpecificMode.Spectrum48Rst28; _seriesCount = 0; _currentOpCodes = new StringBuilder(16); var addr = _offset = section.StartAddress; while (addr <= section.EndAddress) { _currentOpCodes.Clear(); var opCode = Fetch(); // ReSharper disable once UnusedVariable var item = DisassembleCalculatorEntry((ushort)addr, opCode, out var carryOn); _output.AddItem(item); addr = _offset; } }