BizHawk/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassemble...

217 lines
4.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk
{
public partial class GenericDebugger
{
private readonly List<DisasmOp> DisassemblyLines = new List<DisasmOp>();
private class DisasmOp
{
public DisasmOp(uint address, int s, string m)
{
Address = address;
Size = s;
Mnemonic = m;
}
public uint Address { get; private set; }
public int Size { get; private set; }
public string Mnemonic { get; private set; }
}
private long BusMaxValue
{
get
{
return MemoryDomains.SystemBus.Size;
}
}
private void UpdateDisassembler()
{
if (CanDisassemble)
{
DisassemblerView.BlazingFast = true;
2016-02-21 12:46:45 +00:00
2015-02-06 00:56:54 +00:00
currentDisassemblerAddress = (uint)PCRegister.Value;
Disassemble();
2016-02-21 12:46:45 +00:00
SetDisassemblerItemCount();
DisassemblerView.BlazingFast = false;
}
}
uint currentDisassemblerAddress = 0;
private void Disassemble()
{
int line_count = DisassemblerView.NumberOfVisibleRows;
DisassemblyLines.Clear();
uint a = currentDisassemblerAddress;
for (int i = 0; i <= line_count; ++i)
{
int advance;
string line = Disassembler.Disassemble(MemoryDomains.SystemBus, a, out advance);
DisassemblyLines.Add(new DisasmOp(a, advance, line));
a += (uint)advance;
if (a > BusMaxValue)
{
break;
}
}
}
private void DisassemblerView_QueryItemText(int index, int column, out string text)
{
text = "";
if (index < DisassemblyLines.Count)
{
if (column == 0)
{
// feos: address size must be platform dependant
text = string.Format("{0:X4}", DisassemblyLines[index].Address);
}
else if (column == 1)
{
text = DisassemblyLines[index].Mnemonic;
}
}
}
private void DisassemblerView_QueryItemBkColor(int index, int column, ref Color color)
{
2014-12-23 03:13:13 +00:00
if (DisassemblyLines.Any() && index < DisassemblyLines.Count)
{
2015-02-06 00:56:54 +00:00
if (DisassemblyLines[index].Address == (uint)PCRegister.Value)
2014-12-23 03:13:13 +00:00
{
color = Color.LightCyan;
}
}
}
private void DecrementCurrentAddress()
{
uint newaddress = currentDisassemblerAddress;
while (true)
{
int bytestoadvance;
Disassembler.Disassemble(MemoryDomains.SystemBus, newaddress, out bytestoadvance);
if (newaddress + bytestoadvance == currentDisassemblerAddress)
{
break;
}
newaddress--;
if (newaddress < 0)
{
newaddress = 0;
break;
}
// Just in case
if (currentDisassemblerAddress - newaddress > 5)
{
newaddress = currentDisassemblerAddress - 1;
break;
}
}
currentDisassemblerAddress = newaddress;
}
private void IncrementCurrentAddress()
{
currentDisassemblerAddress += (uint)DisassemblyLines.First().Size;
if (currentDisassemblerAddress >= BusMaxValue)
{
currentDisassemblerAddress = (uint)(BusMaxValue - 1);
}
}
private void DisassemblerView_Scroll(object sender, ScrollEventArgs e)
{
if (e.Type == ScrollEventType.SmallIncrement)
{
IncrementCurrentAddress();
Disassemble();
DisassemblerView.Refresh();
}
if (e.Type == ScrollEventType.SmallDecrement)
{
DecrementCurrentAddress();
Disassemble();
DisassemblerView.Refresh();
}
}
private void SetDisassemblerItemCount()
{
DisassemblerView.ItemCount = DisassemblerView.NumberOfVisibleRows + 1;
}
private void DisassemblerView_SizeChanged(object sender, EventArgs e)
{
SetDisassemblerItemCount();
if (CanDisassemble)
{
Disassemble();
}
}
private void DisassemblerView_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.C) // Ctrl + C
{
CopySelectedDisassembler();
}
}
private void CopySelectedDisassembler()
{
var indices = DisassemblerView.SelectedIndices;
if (indices.Count > 0)
{
var blob = new StringBuilder();
foreach (int index in indices)
{
if (blob.Length != 0) blob.AppendLine();
blob.Append(DisassemblyLines[index].Address)
.Append(" ")
.Append(DisassemblyLines[index].Mnemonic);
}
Clipboard.SetDataObject(blob.ToString());
}
}
private void OnPauseChanged(object sender, MainForm.PauseChangedEventArgs e)
{
FullUpdate();
}
private void DisassemblerContextMenu_Opening(object sender, EventArgs e)
{
AddBreakpointContextMenuItem.Enabled = DisassemblerView.SelectedIndices.Count > 0;
}
private void AddBreakpointContextMenuItem_Click(object sender, EventArgs e)
{
var indices = DisassemblerView.SelectedIndices;
if (indices.Count > 0)
{
var line = DisassemblyLines[indices[0]];
BreakPointControl1.AddBreakpoint(line.Address, Emulation.Common.MemoryCallbackType.Execute);
}
}
}
}