internal BFFile(BFCodeLabel[] procedures, BFCodeLabel[] jumpLabels, List<BFOpcode> opcodes, BMDFile messageFile = null) { _procedures = procedures; _jumpLabels = jumpLabels; _opcodes = opcodes; _messageFile = messageFile; }
private static BFCodeLabel ParseASMLabel(int lineIndex, string nameToken, int jumpIndex, int opIndex, params char[] splitChars) { BFCodeLabel label = new BFCodeLabel() { Name = nameToken.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)[0], ID = jumpIndex, OpcodeIndex = opIndex }; if (label.Name.Length == 0) throw new BFASMParserException("Label", lineIndex + 1); return label; }
private static void ReadCodeLabels(BinaryReader reader, ref BFCodeLabel[] array, int count, out bool requireSort) { array = new BFCodeLabel[count]; requireSort = false; int lastIdx = -1; for (int j = 0; j < array.Length; j++) { array[j] = new BFCodeLabel(reader); if (!requireSort && lastIdx > array[j].OpcodeIndex) requireSort = true; else lastIdx = array[j].OpcodeIndex; } }
public static void Disassemble(string path, List<BFOpcode> opcodes, BFCodeLabel[] procedures, BFCodeLabel[] jumpLabels) { using (StreamWriter writer = new StreamWriter(File.Create(path))) { int procIdx = 0; int jumpIdx = 0; // sorting these is faster than searching every interation BFCodeLabel[] sortedProcedures = procedures.OrderBy(i => i.OpcodeIndex).ToArray(); BFCodeLabel[] sortedJumpLabels = jumpLabels.OrderBy(i => i.OpcodeIndex).ToArray(); for (int i = 0; i < opcodes.Count; i++) { BFOpcode op = opcodes[i]; BFCodeLabel procedure = null; BFCodeLabel jumpLabel = null; // first check if maybe a procedure starts at this index if (procIdx != sortedProcedures.Length && sortedProcedures[procIdx].OpcodeIndex == i) { procedure = sortedProcedures[procIdx++]; writer.WriteLine("\n" + procedure.Name + ": \t; start of procedure \"{0}\"", procedure.Name); } // if it's not the start of a procedure then check if it's maybe a jump label else if (jumpIdx != sortedJumpLabels.Length && sortedJumpLabels[jumpIdx].OpcodeIndex == i) { jumpLabel = sortedJumpLabels[jumpIdx++]; writer.WriteLine("\n@" + jumpLabel.Name + ": \t; jump label \"{0}\"", jumpLabel.Name); } bool isKnown = BFInstructionToASMKeyword.ContainsKey(op.Instruction); string opStr = isKnown ? BFInstructionToASMKeyword[op.Instruction] : "unk_" + op.Instruction.ToString("X"); switch (op.Instruction) { case BFInstruction.CallNative: BFCallNativeType callType = (BFCallNativeType)op.Operand.ImmediateValue; opStr += " " + callType + (Enum.IsDefined(typeof(BFCallNativeType), callType) ? " \t; " + CallNativeToHintString[callType] : string.Empty); break; case BFInstruction.BeginProcedure: opStr += " " + procedure.Name; break; case BFInstruction.CallProcedure: opStr += " " + procedures[(int)op.Operand.ImmediateValue].Name; break; case BFInstruction.Jump: case BFInstruction.JumpIfFalse: opStr += " @" + jumpLabels[(int)op.Operand.ImmediateValue].Name; break; default: if (op.Operand != null) opStr += " " + op.Operand.ToString(); break; } writer.WriteLine("\t" + opStr); } } }