/// <summary> /// Generates a pseudo-op statement for the specified data operation. /// /// For most operations, only one output line will be generated. For larger items, /// like long comments, the value may be split into multiple lines. The sub-index /// indicates which line should be formatted. /// </summary> /// <param name="formatter">Format definition.</param> /// <param name="opNames">Table of pseudo-op names.</param> /// <param name="symbolTable">Project symbol table.</param> /// <param name="labelMap">Symbol label map. May be null.</param> /// <param name="dfd">Data format descriptor.</param> /// <param name="data">File data array.</param> /// <param name="offset">Start offset.</param> /// <param name="subIndex">For multi-line items, which line.</param> public static PseudoOut FormatDataOp(Formatter formatter, PseudoOpNames opNames, SymbolTable symbolTable, Dictionary <string, string> labelMap, FormatDescriptor dfd, byte[] data, int offset, int subIndex) { if (dfd == null) { // should never happen //Debug.Assert(false, "Null dfd at offset+" + offset.ToString("x6")); PseudoOut failed = new PseudoOut(); failed.Opcode = failed.Operand = "!FAILED!+" + offset.ToString("x6"); return(failed); } int length = dfd.Length; Debug.Assert(length > 0); // All outputs for a given offset show the same offset and length, even for // multi-line items. PseudoOut po = new PseudoOut(); switch (dfd.FormatType) { case FormatDescriptor.Type.Default: if (length != 1) { // This shouldn't happen. Debug.Assert(false); length = 1; } po.Opcode = opNames.GetDefineData(length); int operand = RawData.GetWord(data, offset, length, false); po.Operand = formatter.FormatHexValue(operand, length * 2); break; case FormatDescriptor.Type.NumericLE: po.Opcode = opNames.GetDefineData(length); operand = RawData.GetWord(data, offset, length, false); po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd, operand, length, FormatNumericOpFlags.None); break; case FormatDescriptor.Type.NumericBE: po.Opcode = opNames.GetDefineBigData(length); operand = RawData.GetWord(data, offset, length, true); po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd, operand, length, FormatNumericOpFlags.None); break; case FormatDescriptor.Type.Fill: po.Opcode = opNames.Fill; po.Operand = length + "," + formatter.FormatHexValue(data[offset], 2); break; case FormatDescriptor.Type.Dense: { int maxPerLine = MAX_OPERAND_LEN / 2; offset += subIndex * maxPerLine; length -= subIndex * maxPerLine; if (length > maxPerLine) { length = maxPerLine; } po.Opcode = opNames.Dense; po.Operand = formatter.FormatDenseHex(data, offset, length); //List<PseudoOut> outList = new List<PseudoOut>(); //GenerateTextLines(text, "", "", po, outList); //po = outList[subIndex]; } break; case FormatDescriptor.Type.String: // It's hard to do strings in single-line pieces because of prefix lengths, // terminating nulls, DCI polarity, and reverse-order strings. We // really just want to convert the whole thing to a run of chars // and then pull out a chunk. As an optimization we can handle // generic strings (subtype=None) more efficiently, which should solve // the problem of massive strings created by auto-analysis. if (dfd.FormatSubType == FormatDescriptor.SubType.None) { int maxPerLine = MAX_OPERAND_LEN - 2; offset += subIndex * maxPerLine; length -= subIndex * maxPerLine; if (length > maxPerLine) { length = maxPerLine; } char[] ltext = BytesToChars(formatter, opNames, dfd.FormatSubType, data, offset, length, out string lpopcode, out int unused); po.Opcode = lpopcode; po.Operand = "\u201c" + new string(ltext) + "\u201d"; } else { char[] text = BytesToChars(formatter, opNames, dfd.FormatSubType, data, offset, length, out string popcode, out int showHexZeroes); if (showHexZeroes == 1) { po.Opcode = opNames.DefineData1; po.Operand = formatter.FormatHexValue(0, 2); } else if (showHexZeroes == 2) { po.Opcode = opNames.DefineData2; po.Operand = formatter.FormatHexValue(0, 4); } else { Debug.Assert(showHexZeroes == 0); po.Opcode = popcode; List <PseudoOut> outList = new List <PseudoOut>(); GenerateTextLines(text, "\u201c", "\u201d", po, outList); po = outList[subIndex]; } } break; default: Debug.Assert(false); po.Opcode = ".???"; po.Operand = "$" + data[offset].ToString("x2"); break; } return(po); }
/// <summary> /// Generates a pseudo-op statement for the specified data operation. /// /// For most operations, only one output line will be generated. For larger items, /// like dense hex, the value may be split into multiple lines. The sub-index /// indicates which line should be formatted. /// </summary> /// <param name="formatter">Format definition.</param> /// <param name="opNames">Table of pseudo-op names.</param> /// <param name="symbolTable">Project symbol table.</param> /// <param name="labelMap">Symbol label map. May be null.</param> /// <param name="dfd">Data format descriptor.</param> /// <param name="data">File data array.</param> /// <param name="offset">Start offset.</param> /// <param name="subIndex">For multi-line items, which line.</param> public static PseudoOut FormatDataOp(Formatter formatter, PseudoOpNames opNames, SymbolTable symbolTable, Dictionary <string, string> labelMap, FormatDescriptor dfd, byte[] data, int offset, int subIndex) { if (dfd == null) { // should never happen //Debug.Assert(false, "Null dfd at offset+" + offset.ToString("x6")); PseudoOut failed = new PseudoOut(); failed.Opcode = failed.Operand = "!FAILED!+" + offset.ToString("x6"); return(failed); } int length = dfd.Length; Debug.Assert(length > 0); // All outputs for a given offset show the same offset and length, even for // multi-line items. PseudoOut po = new PseudoOut(); if (dfd.IsString) { Debug.Assert(false); // shouldn't be calling here anymore List <string> lines = FormatStringOp(formatter, opNames, dfd, data, offset, out string popcode); po.Opcode = popcode; po.Operand = lines[subIndex]; } else { switch (dfd.FormatType) { case FormatDescriptor.Type.Default: if (length != 1) { // This shouldn't happen. Debug.Assert(false); length = 1; } po.Opcode = opNames.GetDefineData(length); int operand = RawData.GetWord(data, offset, length, false); po.Operand = formatter.FormatHexValue(operand, length * 2); break; case FormatDescriptor.Type.NumericLE: po.Opcode = opNames.GetDefineData(length); operand = RawData.GetWord(data, offset, length, false); po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd, operand, length, FormatNumericOpFlags.None); break; case FormatDescriptor.Type.NumericBE: po.Opcode = opNames.GetDefineBigData(length); operand = RawData.GetWord(data, offset, length, true); po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd, operand, length, FormatNumericOpFlags.None); break; case FormatDescriptor.Type.Fill: po.Opcode = opNames.Fill; po.Operand = length + "," + formatter.FormatHexValue(data[offset], 2); break; case FormatDescriptor.Type.Junk: if (dfd.FormatSubType != FormatDescriptor.SubType.None) { po.Opcode = opNames.Align; int alignPow = FormatDescriptor.AlignmentToPower(dfd.FormatSubType); po.Operand = formatter.FormatHexValue(1 << alignPow, 2) + " (" + length.ToString() + " bytes)"; } else { po.Opcode = opNames.Junk; po.Operand = length.ToString(); } break; case FormatDescriptor.Type.Dense: { int maxPerLine = MAX_OPERAND_LEN / 2; offset += subIndex * maxPerLine; length -= subIndex * maxPerLine; if (length > maxPerLine) { length = maxPerLine; } po.Opcode = opNames.Dense; po.Operand = formatter.FormatDenseHex(data, offset, length); //List<PseudoOut> outList = new List<PseudoOut>(); //GenerateTextLines(text, "", "", po, outList); //po = outList[subIndex]; } break; default: Debug.Assert(false); po.Opcode = ".???"; po.Operand = "$" + data[offset].ToString("x2"); break; } } return(po); }