static TreeNode PopulateTree(CallingDetail CallingDetail, TreeNode node) { int sourceaddress = CallingDetail.SourceAddress; int address = CallingDetail.DestinationAddress; int imageindex = (int)CallingDetail.CallType; if (!DisassembleROM) { if (address < 0x4000) { return(node); } } //TreeNode[] tn = node.Nodes.Find(address.ToString("X4"), false); //if (tn.Length == 0) { string text = sourceaddress.ToString("X4"); node = node.Nodes.Add(text, text, imageindex, imageindex); node.ToolTipText = tooltiptext[imageindex]; node.Tag += CallingDetail.DestinationAddress.ToString("X4"); node.ToolTipText += " To " + node.Tag.ToString(); text = address.ToString("X4"); node = node.Nodes.Add(text, text, 0, 0); node.ToolTipText = "Procedure entry point: " + tooltiptext[imageindex]; node.ImageIndex = node.SelectedImageIndex = 0; if (node.Tag == null) { node.Tag += CallingDetail.SourceAddress.ToString("X4"); } else { node.Tag += ", " + CallingDetail.SourceAddress.ToString("X4"); } node.ToolTipText += " From " + node.Tag.ToString(); } //else { // node = tn[0]; // node.Text += ">"; } return(node); }
static string DecodeOpcode(byte[] memory, int address) { // // Decode one opcode // DOpcode opcode; List <byte> opcodebytes = new List <byte>(); int startaddress = address; Visited[address] = true; if (address + 1 > memory.Length) { return(""); } byte opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); switch (opcodebyte) { case 0xCB: { opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.CBPrefix[opcodebyte].Clone(); } break; case 0xED: { opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.EDPrefix[opcodebyte].Clone(); } break; case 0xDD: { opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); if (opcodebyte == 0xCB) { byte offset = memory[address++]; opcodebytes.Add(offset); opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.DDCBPrefix[opcodebyte].Clone(); opcode.Offset = offset; } else { opcode = (DOpcode)Opcodes.DDPrefix[opcodebyte].Clone(); } } break; case 0xFD: { opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); if (opcodebyte == 0xCB) { byte offset = memory[address++]; opcodebytes.Add(offset); opcodebyte = memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.FDCBPrefix[opcodebyte].Clone(); opcode.Offset = offset; } else { opcode = (DOpcode)Opcodes.FDPrefix[opcodebyte].Clone(); } } break; default: opcode = (DOpcode)Opcodes.NoPrefix[opcodebyte].Clone(); break; } // // Decode operands // if (opcode.Mnemonic != null) { // Index offset i.e. (IX+$o) if (opcode.Mnemonic.Contains("$o")) { sbyte offset = (sbyte)memory[address++]; opcodebytes.Add((byte)offset); opcode.Offset = (byte)offset; } // Word; i.e. LD HL,$nn if (opcode.Mnemonic.Contains("$nn")) { byte lo = memory[address++]; byte hi = memory[address++]; opcodebytes.Add(lo); opcodebytes.Add(hi); int word = ((hi << 8) | lo); opcode.Operand = word; } // Address; i.e. CALL $aa CallingDetail callingDetail = null; if (opcode.Mnemonic.Contains("$aa")) { byte lo = memory[address++]; byte hi = memory[address++]; opcodebytes.Add(lo); opcodebytes.Add(hi); int word = ((hi << 8) | lo); Destination[word] = true; opcode.Operand = word; if (opcode.Mnemonic.StartsWith("JP")) { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(word, startaddress, CallingType.JpCC); } else { callingDetail = new CallingDetail(word, startaddress, CallingType.Jp); } } else { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(word, startaddress, CallingType.CallCC); } else { callingDetail = new CallingDetail(word, startaddress, CallingType.Call); } } } // Displacement i.e. DJNZ $d else if (opcode.Mnemonic.Contains("$d")) { sbyte displacement = (sbyte)memory[address++]; opcodebytes.Add((byte)displacement); int dispaddress = address + displacement; opcode.Operand = dispaddress; Destination[dispaddress] = true; if (opcode.Mnemonic.StartsWith("JR")) { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.JrCC); } else { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.Jr); } } else { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.Djnz); } } // Byte; i.e. LD A,$b else if (opcode.Mnemonic.Contains("$b")) { byte value = memory[address++]; opcodebytes.Add(value); opcode.Operand = value; } } return(opcode.Disassembly); }
public static void Disassemble(CallingDetail callDetail, byte[] memory, TreeNode node) { if (callDetail.DestinationAddress > memory.Length) { return; } int address = callDetail.DestinationAddress; int imageindex = (int)callDetail.CallType; node = PopulateTree(callDetail, node); if (Visited[callDetail.DestinationAddress]) { return; } Stack <CallingDetail> CallStack = new Stack <CallingDetail>(); while (true) { try { if (!DisassembleROM) { if (address < 0x4000) { break; } } if (address > 0xffff) { break; } //if (address == 0x162c) // Console.Write(""); // // Decode one opcode // DOpcode opcode; List <byte> opcodebytes = new List <byte>(); int startaddress = address; Visited[address] = true; if (address + 1 > memory.Length) { return; } byte opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); switch (opcodebyte) { case 0xCB: { opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.CBPrefix[opcodebyte].Clone(); } break; case 0xED: { opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.EDPrefix[opcodebyte].Clone(); } break; case 0xDD: { opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); if (opcodebyte == 0xCB) { byte offset = (byte)memory[address++]; opcodebytes.Add(offset); opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.DDCBPrefix[opcodebyte].Clone(); opcode.Offset = offset; } else { opcode = (DOpcode)Opcodes.DDPrefix[opcodebyte].Clone(); } } break; case 0xFD: { opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); if (opcodebyte == 0xCB) { byte offset = (byte)memory[address++]; opcodebytes.Add(offset); opcodebyte = (byte)memory[address++]; opcodebytes.Add(opcodebyte); opcode = (DOpcode)Opcodes.FDCBPrefix[opcodebyte].Clone(); opcode.Offset = offset; } else { opcode = (DOpcode)Opcodes.FDPrefix[opcodebyte].Clone(); } } break; default: opcode = (DOpcode)Opcodes.NoPrefix[opcodebyte].Clone(); break; } // // Decode operands // if (opcode.Mnemonic != null) { // Index offset i.e. (IX+$o) if (opcode.Mnemonic.Contains("$o")) { sbyte offset = (sbyte)memory[address++]; opcodebytes.Add((byte)offset); opcode.Offset = (byte)offset; } // Word; i.e. LD HL,$nn if (opcode.Mnemonic.Contains("$nn")) { byte lo = (byte)memory[address++]; byte hi = (byte)memory[address++]; opcodebytes.Add(lo); opcodebytes.Add(hi); int word = ((hi << 8) | lo); opcode.Operand = word; } // Address; i.e. CALL $aa CallingDetail callingDetail = null; if (opcode.Mnemonic.Contains("$aa")) { byte lo = (byte)memory[address++]; byte hi = (byte)memory[address++]; opcodebytes.Add(lo); opcodebytes.Add(hi); int word = ((hi << 8) | lo); Destination[word] = true; opcode.Operand = word; if (opcode.Mnemonic.StartsWith("JP")) { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(word, startaddress, CallingType.JpCC); } else { callingDetail = new CallingDetail(word, startaddress, CallingType.Jp); } } else { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(word, startaddress, CallingType.CallCC); } else { callingDetail = new CallingDetail(word, startaddress, CallingType.Call); } } if (word != 0x335E) { CallStack.Push(callingDetail); } else { Disassembly[startaddress] = opcode; break; } } // Displacement i.e. DJNZ $d else if (opcode.Mnemonic.Contains("$d")) { sbyte displacement = (sbyte)memory[address++]; opcodebytes.Add((byte)displacement); int dispaddress = address + displacement; opcode.Operand = dispaddress; Destination[dispaddress] = true; if (opcode.Mnemonic.StartsWith("JR")) { if ((opcode.OpcodePropertys & OpcodeProperty.Conditional) == OpcodeProperty.Conditional) { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.JrCC); } else { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.Jr); } } else { callingDetail = new CallingDetail(dispaddress, startaddress, CallingType.Djnz); } CallStack.Push(callingDetail); } // Byte; i.e. LD A,$b else if (opcode.Mnemonic.Contains("$b")) { byte value = (byte)memory[address++]; opcodebytes.Add(value); opcode.Operand = value; } } opcode.Address = startaddress; opcode.Bytes = opcodebytes; //Visited[startaddress] = true; // RST 08H; THE 'ERROR' RESTART (0xcf) if (opcode.Value == 0xcf) { Disassembly[startaddress] = opcode; Visited[address++] = true; //CallingDetail callingDetail = new CallingDetail(address, address, CallingType.Jp); //CallStack.Push(callingDetail); break; } // RST 28H; THE 'CALCULATE' RESTART (0xef) if (opcode.Value == 0xef) { Disassembly[startaddress] = opcode; while (true) { Visited[address++] = true; // END WITH 0x38 if (memory[address] == 0x38) { if (memory[address - 1] != 0x8f) { break; } } } Visited[address++] = true; CallingDetail callingDetail = new CallingDetail(address, address, CallingType.Jp); CallStack.Push(callingDetail); break; } // Any other opcode for (int i = startaddress; i < startaddress + opcodebytes.Count; i++) { Disassembly[i] = null; } Disassembly[startaddress] = opcode; if (opcode.IsTerminal) { break; } } catch { break; } } IEnumerable <CallingDetail> list = CallStack.Reverse(); foreach (CallingDetail callingDetail in list) { Disassemble(callingDetail, memory, node); } }