mirror of
https://github.com/libretro/pcsx2.git
synced 2024-12-20 08:48:16 +00:00
Merge pull request #1287 from mogaika/debug_window_improve
Debugger features
This commit is contained in:
commit
a735e2b58f
@ -30,6 +30,8 @@ memory view:
|
||||
any overwrite ansi byte
|
||||
left click select byte/nibble
|
||||
right click open context menu
|
||||
ctrl+wheel zoom memory view
|
||||
esc return to previous goto address
|
||||
|
||||
breakpoint list:
|
||||
|
||||
|
@ -184,6 +184,37 @@ void DebugInterface::resumeCpu()
|
||||
core.Resume();
|
||||
}
|
||||
|
||||
|
||||
char* DebugInterface::stringFromPointer(u32 p)
|
||||
{
|
||||
const int BUFFER_LEN = 25;
|
||||
static char buf[BUFFER_LEN] = { 0 };
|
||||
|
||||
if (!isValidAddress(p))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
for (u32 i = 0; i < BUFFER_LEN; i++) {
|
||||
char c = read8(p + i);
|
||||
buf[i] = c;
|
||||
|
||||
if (c == 0) {
|
||||
return i > 0 ? buf : NULL;
|
||||
}
|
||||
else if (c < 0x20 || c >= 0x7f) {
|
||||
// non printable character
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception::Ps2Generic&) {
|
||||
return NULL;
|
||||
}
|
||||
buf[BUFFER_LEN - 1] = 0;
|
||||
buf[BUFFER_LEN - 2] = '~';
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool DebugInterface::initExpression(const char* exp, PostfixExpression& dest)
|
||||
{
|
||||
MipsExpressionFunctions funcs(this);
|
||||
@ -509,33 +540,59 @@ std::string R5900DebugInterface::disasm(u32 address, bool simplify)
|
||||
|
||||
bool R5900DebugInterface::isValidAddress(u32 addr)
|
||||
{
|
||||
// ee can't access the first part of memory.
|
||||
if (addr < 0x80000)
|
||||
return false;
|
||||
|
||||
if (addr >= 0xFFFF8000)
|
||||
return true;
|
||||
|
||||
addr &= 0x7FFFFFFF;
|
||||
u32 lopart = addr & 0xfFFffFF;
|
||||
|
||||
// get rid of ee ram mirrors
|
||||
if ((addr >> 28) == 2 || (addr >> 28) == 3)
|
||||
addr &= ~(0xF << 28);
|
||||
|
||||
// registers
|
||||
if (addr >= 0x10000000 && addr < 0x10010000)
|
||||
return true;
|
||||
if (addr >= 0x12000000 && addr < 0x12001100)
|
||||
return true;
|
||||
switch (addr >> 28)
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
// case 3: throw exception (not mapped ?)
|
||||
// [ 0000_8000 - 01FF_FFFF ] RAM
|
||||
// [ 2000_8000 - 21FF_FFFF ] RAM MIRROR
|
||||
// [ 3000_8000 - 31FF_FFFF ] RAM MIRROR
|
||||
if (lopart >= 0x80000 && lopart <= 0x1ffFFff)
|
||||
return !!vtlb_GetPhyPtr(lopart);
|
||||
break;
|
||||
case 1:
|
||||
// [ 1000_0000 - 1000_CFFF ] EE register
|
||||
if (lopart <= 0xcfff)
|
||||
return true;
|
||||
|
||||
// scratchpad
|
||||
if (addr >= 0x70000000 && addr < 0x70004000)
|
||||
return true;
|
||||
// [ 1100_0000 - 1100_FFFF ] VU mem
|
||||
if (lopart >= 0x1000000 && lopart <= 0x100FFff)
|
||||
return true;
|
||||
|
||||
return !(addr & 0x40000000) && vtlb_GetPhyPtr(addr & 0x1FFFFFFF) != NULL;
|
||||
// [ 1200_0000 - 1200_FFFF ] GS regs
|
||||
if (lopart >= 0x2000000 && lopart <= 0x20010ff)
|
||||
return true;
|
||||
|
||||
// [ 1E00_0000 - 1FFF_FFFF ] ROM
|
||||
// if (lopart >= 0xe000000)
|
||||
// return true; throw exception (not mapped ?)
|
||||
break;
|
||||
case 7:
|
||||
// [ 7000_0000 - 7000_3FFF ] Scratchpad
|
||||
if (lopart <= 0x3fff)
|
||||
return true;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 0xA:
|
||||
case 0xB:
|
||||
// [ 8000_0000 - BFFF_FFFF ] kernel
|
||||
// return true;
|
||||
break;
|
||||
case 0xF:
|
||||
// [ 8000_0000 - BFFF_FFFF ] IOP or kernel stack
|
||||
if (lopart >= 0xfff8000)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
u32 R5900DebugInterface::getCycles()
|
||||
{
|
||||
return cpuRegs.cycle;
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
bool isCpuPaused();
|
||||
void pauseCpu();
|
||||
void resumeCpu();
|
||||
char *stringFromPointer(u32 p);
|
||||
};
|
||||
|
||||
class R5900DebugInterface: public DebugInterface
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <cstring> // string.h under c++
|
||||
#include <cstdio> // stdio.h under c++
|
||||
#include <cstdlib>
|
||||
|
@ -60,4 +60,4 @@ private:
|
||||
u32 size;
|
||||
char condition[128];
|
||||
PostfixExpression compiledCondition;
|
||||
};
|
||||
};
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <wchar.h>
|
||||
#include <wx/clipbrd.h>
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(CtrlMemView, wxWindow)
|
||||
EVT_PAINT(CtrlMemView::paintEvent)
|
||||
EVT_MOUSEWHEEL(CtrlMemView::mouseEvent)
|
||||
@ -45,6 +46,12 @@ enum MemoryViewMenuIdentifiers
|
||||
{
|
||||
ID_MEMVIEW_GOTOINDISASM = 1,
|
||||
ID_MEMVIEW_COPYADDRESS,
|
||||
ID_MEMVIEW_FOLLOWADDRESS,
|
||||
ID_MEMVIEW_DISPLAYVALUE_8,
|
||||
ID_MEMVIEW_DISPLAYVALUE_16,
|
||||
ID_MEMVIEW_DISPLAYVALUE_32,
|
||||
ID_MEMVIEW_DISPLAYVALUE_64,
|
||||
ID_MEMVIEW_DISPLAYVALUE_128,
|
||||
ID_MEMVIEW_COPYVALUE_8,
|
||||
ID_MEMVIEW_COPYVALUE_16,
|
||||
ID_MEMVIEW_COPYVALUE_32,
|
||||
@ -60,14 +67,14 @@ CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
||||
charWidth = getDebugFontWidth();
|
||||
windowStart = 0x480000;
|
||||
curAddress = windowStart;
|
||||
rowSize = 16;
|
||||
|
||||
byteGroupSize = 1;
|
||||
|
||||
asciiSelected = false;
|
||||
selectedNibble = 0;
|
||||
rowSize = 16;
|
||||
addressStart = charWidth;
|
||||
hexStart = addressStart + 9*charWidth;
|
||||
asciiStart = hexStart + (rowSize*3+1)*charWidth;
|
||||
|
||||
setRowSize(16);
|
||||
|
||||
#ifdef _WIN32
|
||||
font = wxFont(wxSize(charWidth,rowHeight),wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,L"Lucida Console");
|
||||
@ -81,6 +88,13 @@ CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
||||
|
||||
menu.Append(ID_MEMVIEW_GOTOINDISASM, L"Go to in Disasm");
|
||||
menu.Append(ID_MEMVIEW_COPYADDRESS, L"Copy address");
|
||||
menu.Append(ID_MEMVIEW_FOLLOWADDRESS, L"Follow address");
|
||||
menu.AppendSeparator();
|
||||
menu.Append(ID_MEMVIEW_DISPLAYVALUE_8, L"Display as 1 byte");
|
||||
menu.Append(ID_MEMVIEW_DISPLAYVALUE_16, L"Display as 2 byte");
|
||||
menu.Append(ID_MEMVIEW_DISPLAYVALUE_32, L"Display as 4 byte");
|
||||
menu.Append(ID_MEMVIEW_DISPLAYVALUE_64, L"Display as 8 byte");
|
||||
menu.Append(ID_MEMVIEW_DISPLAYVALUE_128, L"Display as 16 byte");
|
||||
menu.AppendSeparator();
|
||||
menu.Append(ID_MEMVIEW_COPYVALUE_8, L"Copy Value (8 bit)");
|
||||
menu.Append(ID_MEMVIEW_COPYVALUE_16, L"Copy Value (16 bit)");
|
||||
@ -95,6 +109,11 @@ CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
||||
SetDoubleBuffered(true);
|
||||
}
|
||||
|
||||
void CtrlMemView::setRowSize(int bytesInRow) {
|
||||
rowSize = (std::max(16, std::min(256, bytesInRow)) / 16) * 16;
|
||||
asciiStart = hexStart + (rowSize * 3 + 1)*charWidth;
|
||||
}
|
||||
|
||||
void CtrlMemView::postEvent(wxEventType type, wxString text)
|
||||
{
|
||||
wxCommandEvent event( type, GetId() );
|
||||
@ -125,137 +144,167 @@ void CtrlMemView::redraw()
|
||||
render(dc);
|
||||
}
|
||||
|
||||
int CtrlMemView::hexGroupPositionFromIndex(int idx)
|
||||
{
|
||||
int groupPos = idx * charWidth * 2;
|
||||
|
||||
int space = (charWidth / 4);
|
||||
|
||||
// spaces after every byte
|
||||
groupPos += idx * space;
|
||||
|
||||
// spaces after every 2 bytes
|
||||
groupPos += (idx / 2) * space;
|
||||
|
||||
// spaces after every 4 bytes
|
||||
return groupPos + (idx / 4) * space;
|
||||
}
|
||||
|
||||
void CtrlMemView::render(wxDC& dc)
|
||||
{
|
||||
bool hasFocus = wxWindow::FindFocus() == this;
|
||||
int visibleRows = GetClientSize().y/rowHeight;
|
||||
int visibleRows = GetClientSize().y / rowHeight;
|
||||
|
||||
wxColor white = wxColor(0xFFFFFFFF);
|
||||
dc.SetBrush(wxBrush(white));
|
||||
dc.SetPen(wxPen(white));
|
||||
const wxColor COLOR_WHITE = wxColor(0xFFFFFFFF);
|
||||
const wxColor COLOR_BLACK = wxColor(0xFF000000);
|
||||
const wxColor COLOR_SELECTED_BG = wxColor(0xFFFF9933);
|
||||
const wxColor COLOR_SELECTED_INACTIVE_BG = wxColor(0xFFC0C0C0);
|
||||
const wxColor COLOR_ADDRESS = wxColor(0xFF600000);
|
||||
const wxColor COLOR_DELIMETER = wxColor(0xFFC0C0C0);
|
||||
|
||||
int width,height;
|
||||
dc.GetSize(&width,&height);
|
||||
dc.DrawRectangle(0,0,width,height);
|
||||
dc.SetBrush(wxBrush(COLOR_WHITE));
|
||||
dc.SetPen(wxPen(COLOR_WHITE));
|
||||
|
||||
for (int i = 0; i < visibleRows+1; i++)
|
||||
int width, height;
|
||||
dc.GetSize(&width, &height);
|
||||
dc.DrawRectangle(0, 0, width, height);
|
||||
|
||||
const int TEMP_SIZE = 64;
|
||||
wchar_t temp[TEMP_SIZE];
|
||||
|
||||
u32 byteGroupMask = ~(byteGroupSize - 1);
|
||||
bool validCpu = cpu && cpu->isAlive();
|
||||
|
||||
// not hexGroupPositionFromIndex(byteGroupSize), because we dont need space after last symbol;
|
||||
int groupWidth = hexGroupPositionFromIndex(byteGroupSize - 1) + charWidth * 2;
|
||||
|
||||
for (int i = 0; i < visibleRows + 1; i++)
|
||||
{
|
||||
wchar_t temp[32];
|
||||
u32 rowAddress = windowStart + i * rowSize;
|
||||
int rowY = rowHeight * i;
|
||||
|
||||
unsigned int address = windowStart + i*rowSize;
|
||||
int rowY = rowHeight*i;
|
||||
|
||||
swprintf(temp,32,L"%08X",address);
|
||||
swprintf(temp, TEMP_SIZE, L"%08X" , rowAddress);
|
||||
dc.SetFont(font);
|
||||
dc.SetTextForeground(wxColor(0xFF600000));
|
||||
dc.DrawText(temp,addressStart,rowY);
|
||||
dc.SetTextForeground(COLOR_ADDRESS);
|
||||
dc.DrawText(temp, addressStart, rowY);
|
||||
|
||||
u32 memory[4];
|
||||
bool valid = cpu != NULL && cpu->isAlive() && cpu->isValidAddress(address);
|
||||
if (valid)
|
||||
{
|
||||
memory[0] = cpu->read32(address);
|
||||
memory[1] = cpu->read32(address+4);
|
||||
memory[2] = cpu->read32(address+8);
|
||||
memory[3] = cpu->read32(address+12);
|
||||
}
|
||||
|
||||
u8* m = (u8*) memory;
|
||||
for (int j = 0; j < rowSize; j++)
|
||||
{
|
||||
if (valid)
|
||||
swprintf(temp,32,L"%02X",m[j]);
|
||||
else
|
||||
wcscpy(temp,L"??");
|
||||
u32 byteAddress = rowAddress + j;
|
||||
u8 byteCurrent;
|
||||
bool byteValid;
|
||||
|
||||
unsigned char c = m[j];
|
||||
if (c < 32 || c >= 128 || valid == false)
|
||||
c = '.';
|
||||
|
||||
if (address+j == curAddress)
|
||||
{
|
||||
wchar_t text[2];
|
||||
try {
|
||||
byteValid = validCpu && cpu->isValidAddress(byteAddress);
|
||||
|
||||
if (hasFocus && !asciiSelected)
|
||||
{
|
||||
dc.SetTextForeground(wxColor(0xFFFFFFFF));
|
||||
|
||||
dc.SetPen(wxColor(0xFFFF9933));
|
||||
dc.SetBrush(wxColor(0xFFFF9933));
|
||||
dc.DrawRectangle(hexStart+j*3*charWidth,rowY,charWidth,rowHeight);
|
||||
|
||||
if (selectedNibble == 0)
|
||||
dc.SetFont(underlineFont);
|
||||
} else {
|
||||
dc.SetTextForeground(wxColor(0xFF000000));
|
||||
|
||||
dc.SetPen(wxColor(0xFFC0C0C0));
|
||||
dc.SetBrush(wxColor(0xFFC0C0C0));
|
||||
dc.DrawRectangle(hexStart+j*3*charWidth,rowY,charWidth,rowHeight);
|
||||
}
|
||||
|
||||
text[0] = temp[0];
|
||||
text[1] = 0;
|
||||
dc.DrawText(text,hexStart+j*3*charWidth,rowY);
|
||||
|
||||
if (hasFocus && !asciiSelected)
|
||||
{
|
||||
dc.DrawRectangle(hexStart+j*3*charWidth+charWidth,rowY,charWidth,rowHeight);
|
||||
|
||||
if (selectedNibble == 1)
|
||||
dc.SetFont(underlineFont);
|
||||
else
|
||||
dc.SetFont(font);
|
||||
} else {
|
||||
dc.DrawRectangle(hexStart+j*3*charWidth+charWidth,rowY,charWidth,rowHeight);
|
||||
}
|
||||
|
||||
text[0] = temp[1];
|
||||
text[1] = 0;
|
||||
dc.DrawText(text,hexStart+j*3*charWidth+charWidth,rowY);
|
||||
|
||||
if (hasFocus && asciiSelected)
|
||||
{
|
||||
dc.SetTextForeground(wxColor(0xFFFFFFFF));
|
||||
|
||||
dc.SetPen(wxColor(0xFFFF9933));
|
||||
dc.SetBrush(wxColor(0xFFFF9933));
|
||||
dc.DrawRectangle(asciiStart+j*(charWidth+2),rowY,charWidth,rowHeight);
|
||||
} else {
|
||||
dc.SetTextForeground(wxColor(0xFF000000));
|
||||
dc.SetFont(font);
|
||||
|
||||
dc.SetPen(wxColor(0xFFC0C0C0));
|
||||
dc.SetBrush(wxColor(0xFFC0C0C0));
|
||||
dc.DrawRectangle(asciiStart+j*(charWidth+2),rowY,charWidth,rowHeight);
|
||||
}
|
||||
|
||||
text[0] = c;
|
||||
text[1] = 0;
|
||||
dc.DrawText(text,asciiStart+j*(charWidth+2),rowY);
|
||||
} else {
|
||||
wchar_t text[2];
|
||||
text[0] = c;
|
||||
text[1] = 0;
|
||||
|
||||
dc.SetTextForeground(wxColor(0xFF000000));
|
||||
dc.DrawText(temp,hexStart+j*3*charWidth,rowY);
|
||||
dc.DrawText(text,asciiStart+j*(charWidth+2),rowY);
|
||||
if (byteValid)
|
||||
byteCurrent = cpu->read8(byteAddress);
|
||||
}
|
||||
catch (Exception::Ps2Generic &) {
|
||||
byteValid = false;
|
||||
}
|
||||
|
||||
// not optimized way, but more flexible than previous
|
||||
|
||||
// calculate group position
|
||||
int groupNum = j / byteGroupSize;
|
||||
int groupPosX = hexStart + groupNum * byteGroupSize * 3 * charWidth;
|
||||
|
||||
// calculate symbol position in group
|
||||
int groupIndex = j % byteGroupSize;
|
||||
|
||||
int symbolPosX = groupPosX + hexGroupPositionFromIndex(byteGroupSize - groupIndex - 1);
|
||||
|
||||
u32 groupAddress = byteAddress - groupIndex;
|
||||
|
||||
if (curAddress >= groupAddress && curAddress < groupAddress + byteGroupSize)
|
||||
{
|
||||
// if group selected, draw rectangle behind
|
||||
if (groupIndex == 0) {
|
||||
if (hasFocus && !asciiSelected) {
|
||||
dc.SetPen(COLOR_SELECTED_BG);
|
||||
dc.SetBrush(COLOR_SELECTED_BG);
|
||||
}
|
||||
else {
|
||||
dc.SetPen(COLOR_SELECTED_INACTIVE_BG);
|
||||
dc.SetBrush(COLOR_SELECTED_INACTIVE_BG);
|
||||
}
|
||||
|
||||
dc.DrawRectangle(groupPosX, rowY, groupWidth, rowHeight);
|
||||
}
|
||||
|
||||
dc.SetTextForeground((hasFocus && !asciiSelected) ? COLOR_WHITE : COLOR_BLACK);
|
||||
}
|
||||
else {
|
||||
dc.SetTextForeground(COLOR_BLACK);
|
||||
}
|
||||
|
||||
swprintf(temp, TEMP_SIZE, byteValid ? L"%02X" : L"??", byteCurrent);
|
||||
// if selected byte, need hint current nibble
|
||||
if (byteAddress == curAddress) {
|
||||
if (selectedNibble == 1)
|
||||
dc.SetFont(underlineFont);
|
||||
|
||||
dc.DrawText(temp + 1, symbolPosX + charWidth, rowY);
|
||||
|
||||
if (selectedNibble == 1)
|
||||
dc.SetFont(font);
|
||||
else
|
||||
dc.SetFont(underlineFont);
|
||||
|
||||
temp[1] = 0;
|
||||
dc.DrawText(temp, symbolPosX, rowY);
|
||||
|
||||
if (selectedNibble == 0)
|
||||
dc.SetFont(font);
|
||||
}
|
||||
else {
|
||||
dc.DrawText(temp, symbolPosX, rowY);
|
||||
}
|
||||
|
||||
// draw in ansii text representation table
|
||||
temp[1] = 0;
|
||||
temp[0] = (!byteValid || byteCurrent < 32 || byteCurrent > 128) ? '.' : byteCurrent;
|
||||
|
||||
if (byteAddress == curAddress) {
|
||||
if (hasFocus && asciiSelected) {
|
||||
dc.SetPen(COLOR_SELECTED_BG);
|
||||
dc.SetBrush(COLOR_SELECTED_BG);
|
||||
dc.SetTextForeground(COLOR_WHITE);
|
||||
}
|
||||
else {
|
||||
dc.SetPen(COLOR_SELECTED_INACTIVE_BG);
|
||||
dc.SetBrush(COLOR_SELECTED_INACTIVE_BG);
|
||||
dc.SetTextForeground(COLOR_BLACK);
|
||||
}
|
||||
dc.DrawRectangle(asciiStart + j*(charWidth + 2), rowY, charWidth, rowHeight);
|
||||
}
|
||||
else {
|
||||
dc.SetTextForeground(COLOR_BLACK);
|
||||
}
|
||||
|
||||
dc.DrawText(temp, asciiStart + j*(charWidth + 2), rowY);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make optional?
|
||||
if (true)
|
||||
dc.SetPen(COLOR_DELIMETER);
|
||||
dc.SetBrush(COLOR_DELIMETER);
|
||||
int linestep = std::max((u32) 4, byteGroupSize);
|
||||
for (int i = linestep; i < rowSize; i += linestep)
|
||||
{
|
||||
dc.SetPen(wxColor(0xFFC0C0C0));
|
||||
dc.SetBrush(wxColor(0xFFC0C0C0));
|
||||
for (int i = 4; i < rowSize; i += 4)
|
||||
{
|
||||
int x = hexStart+i*3*charWidth-charWidth/2;
|
||||
int y = (visibleRows+1)*rowHeight;
|
||||
dc.DrawLine(x,0,x,y);
|
||||
}
|
||||
int x = hexStart + i * 3 * charWidth - charWidth / 2;
|
||||
int y = (visibleRows + 1) * rowHeight;
|
||||
dc.DrawLine(x, 0, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +325,29 @@ void CtrlMemView::onPopupClick(wxCommandEvent& evt)
|
||||
case ID_MEMVIEW_GOTOINDISASM:
|
||||
postEvent(debEVT_GOTOINDISASM,curAddress);
|
||||
break;
|
||||
case ID_MEMVIEW_FOLLOWADDRESS:
|
||||
gotoAddress(cpu->read32(curAddress), true);
|
||||
break;
|
||||
case ID_MEMVIEW_DISPLAYVALUE_8:
|
||||
byteGroupSize = 1;
|
||||
Refresh();
|
||||
break;
|
||||
case ID_MEMVIEW_DISPLAYVALUE_16:
|
||||
byteGroupSize = 2;
|
||||
Refresh();
|
||||
break;
|
||||
case ID_MEMVIEW_DISPLAYVALUE_32:
|
||||
byteGroupSize = 4;
|
||||
Refresh();
|
||||
break;
|
||||
case ID_MEMVIEW_DISPLAYVALUE_64:
|
||||
byteGroupSize = 8;
|
||||
Refresh();
|
||||
break;
|
||||
case ID_MEMVIEW_DISPLAYVALUE_128:
|
||||
byteGroupSize = 16;
|
||||
Refresh();
|
||||
break;
|
||||
case ID_MEMVIEW_COPYVALUE_8:
|
||||
if (wxTheClipboard->Open())
|
||||
{
|
||||
@ -331,6 +403,16 @@ void CtrlMemView::mouseEvent(wxMouseEvent& evt)
|
||||
SetFocusFromKbd();
|
||||
} else if (evt.GetEventType() == wxEVT_RIGHT_UP)
|
||||
{
|
||||
curAddress -= (curAddress - windowStart) % byteGroupSize;
|
||||
|
||||
menu.Enable(ID_MEMVIEW_FOLLOWADDRESS, (curAddress & 3) == 0);
|
||||
|
||||
menu.Enable(ID_MEMVIEW_DISPLAYVALUE_8, byteGroupSize != 1);
|
||||
menu.Enable(ID_MEMVIEW_DISPLAYVALUE_16, byteGroupSize != 2);
|
||||
menu.Enable(ID_MEMVIEW_DISPLAYVALUE_32, byteGroupSize != 4);
|
||||
menu.Enable(ID_MEMVIEW_DISPLAYVALUE_64, byteGroupSize != 8);
|
||||
menu.Enable(ID_MEMVIEW_DISPLAYVALUE_128, byteGroupSize != 16);
|
||||
|
||||
menu.Enable(ID_MEMVIEW_COPYVALUE_128,(curAddress & 15) == 0);
|
||||
menu.Enable(ID_MEMVIEW_COPYVALUE_64,(curAddress & 7) == 0);
|
||||
menu.Enable(ID_MEMVIEW_COPYVALUE_32,(curAddress & 3) == 0);
|
||||
@ -340,11 +422,22 @@ void CtrlMemView::mouseEvent(wxMouseEvent& evt)
|
||||
return;
|
||||
} else if (evt.GetEventType() == wxEVT_MOUSEWHEEL)
|
||||
{
|
||||
if (evt.GetWheelRotation() > 0)
|
||||
{
|
||||
scrollWindow(-3);
|
||||
} else if (evt.GetWheelRotation() < 0) {
|
||||
scrollWindow(3);
|
||||
if (evt.ControlDown()) {
|
||||
if (evt.GetWheelRotation() > 0) {
|
||||
setRowSize(rowSize + 16);
|
||||
}
|
||||
else {
|
||||
setRowSize(rowSize - 16);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (evt.GetWheelRotation() > 0)
|
||||
{
|
||||
scrollWindow(-3);
|
||||
}
|
||||
else if (evt.GetWheelRotation() < 0) {
|
||||
scrollWindow(3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
evt.Skip();
|
||||
@ -366,7 +459,8 @@ void CtrlMemView::keydownEvent(wxKeyEvent& evt)
|
||||
u64 addr;
|
||||
if (executeExpressionWindow(this,cpu,addr) == false)
|
||||
return;
|
||||
gotoAddress(addr);
|
||||
|
||||
gotoAddress(addr, true);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
@ -407,6 +501,12 @@ void CtrlMemView::keydownEvent(wxKeyEvent& evt)
|
||||
case WXK_PAGEDOWN:
|
||||
scrollWindow(GetClientSize().y/rowHeight);
|
||||
break;
|
||||
case WXK_ESCAPE:
|
||||
if (history.size()) {
|
||||
gotoAddress(history.top());
|
||||
history.pop();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
evt.Skip();
|
||||
break;
|
||||
@ -510,12 +610,14 @@ void CtrlMemView::scrollCursor(int bytes)
|
||||
|
||||
int visibleRows = GetClientSize().y/rowHeight;
|
||||
u32 windowEnd = windowStart+visibleRows*rowSize;
|
||||
|
||||
if (curAddress < windowStart)
|
||||
{
|
||||
windowStart = curAddress & ~15;
|
||||
windowStart = (curAddress / rowSize) * curAddress;
|
||||
} else if (curAddress >= windowEnd)
|
||||
{
|
||||
windowStart = (curAddress-(visibleRows-1)*rowSize) & ~15;
|
||||
windowStart = curAddress - (visibleRows - 1)*rowSize;
|
||||
windowStart = (windowStart / rowSize) * windowStart;
|
||||
}
|
||||
|
||||
updateStatusBarText();
|
||||
@ -525,22 +627,26 @@ void CtrlMemView::scrollCursor(int bytes)
|
||||
void CtrlMemView::updateStatusBarText()
|
||||
{
|
||||
wchar_t text[64];
|
||||
swprintf(text,64,L"%08X",curAddress);
|
||||
|
||||
int needpad = (curAddress - windowStart) % byteGroupSize;
|
||||
u32 addr = curAddress - needpad;
|
||||
|
||||
swprintf(text, 64, L"%08X %08X", curAddress, addr);
|
||||
|
||||
postEvent(debEVT_SETSTATUSBARTEXT,text);
|
||||
}
|
||||
|
||||
void CtrlMemView::gotoAddress(u32 addr)
|
||||
void CtrlMemView::gotoAddress(u32 addr, bool pushInHistory)
|
||||
{
|
||||
int lines= GetClientSize().y/rowHeight;
|
||||
u32 windowEnd = windowStart+lines*rowSize;
|
||||
if (pushInHistory)
|
||||
history.push(windowStart);
|
||||
|
||||
int lines= GetClientSize().y / rowHeight;
|
||||
u32 windowEnd = windowStart + lines * rowSize;
|
||||
|
||||
curAddress = addr;
|
||||
selectedNibble = 0;
|
||||
|
||||
if (curAddress < windowStart || curAddress >= windowEnd)
|
||||
{
|
||||
windowStart = curAddress & ~15;
|
||||
}
|
||||
windowStart = curAddress;
|
||||
|
||||
updateStatusBarText();
|
||||
redraw();
|
||||
@ -563,18 +669,37 @@ void CtrlMemView::gotoPoint(int x, int y)
|
||||
redraw();
|
||||
} else if (x >= hexStart)
|
||||
{
|
||||
int col = (x-hexStart) / charWidth;
|
||||
if ((col/3) >= rowSize) return;
|
||||
int col = (x-hexStart);
|
||||
int space = (charWidth / 4);
|
||||
|
||||
switch (col % 3)
|
||||
{
|
||||
case 0: selectedNibble = 0; break;
|
||||
case 1: selectedNibble = 1; break;
|
||||
case 2: return; // don't change position when clicking on the space
|
||||
int groupWidth = byteGroupSize * charWidth * 3;
|
||||
int group = col / groupWidth;
|
||||
|
||||
int posInGroup = col % groupWidth;
|
||||
|
||||
int indexInGroup = -1;
|
||||
|
||||
for (int i = 0; i < int(byteGroupSize); i++) {
|
||||
int start = hexGroupPositionFromIndex(i);
|
||||
int end = start + 2 * charWidth -1;
|
||||
if (posInGroup < start)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (posInGroup <= end)
|
||||
{
|
||||
selectedNibble = ((posInGroup - start) / charWidth) % 2;
|
||||
indexInGroup = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexInGroup == -1)
|
||||
return;
|
||||
|
||||
curAddress = lineAddress + group * byteGroupSize + (byteGroupSize - indexInGroup - 1);
|
||||
|
||||
asciiSelected = false;
|
||||
curAddress = lineAddress+col/3;
|
||||
updateStatusBarText();
|
||||
redraw();
|
||||
}
|
||||
|
@ -30,11 +30,13 @@ public:
|
||||
void scrollbarEvent(wxScrollWinEvent& evt);
|
||||
void charEvent(wxKeyEvent& evt);
|
||||
void redraw();
|
||||
void gotoAddress(u32 address);
|
||||
void gotoAddress(u32 address, bool pushInHistory = false);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
private:
|
||||
void render(wxDC& dc);
|
||||
int hexGroupPositionFromIndex(int idx);
|
||||
void setRowSize(int bytesInRow);
|
||||
void gotoPoint(int x, int y);
|
||||
void updateStatusBarText();
|
||||
void postEvent(wxEventType type, wxString text);
|
||||
@ -49,6 +51,7 @@ private:
|
||||
int charWidth;
|
||||
u32 windowStart;
|
||||
u32 curAddress;
|
||||
u32 byteGroupSize;
|
||||
int rowSize;
|
||||
wxFont font,underlineFont;
|
||||
|
||||
@ -58,5 +61,6 @@ private:
|
||||
bool asciiSelected;
|
||||
int selectedNibble;
|
||||
|
||||
std::stack<u32> history;
|
||||
wxMenu menu;
|
||||
};
|
||||
};
|
||||
|
@ -35,9 +35,12 @@ enum DisassemblyMenuIdentifiers
|
||||
ID_REGISTERLIST_DISPLAY32 = 1,
|
||||
ID_REGISTERLIST_DISPLAY64,
|
||||
ID_REGISTERLIST_DISPLAY128,
|
||||
ID_REGISTERLIST_DISPLAY128STRINGS,
|
||||
ID_REGISTERLIST_CHANGELOWER,
|
||||
ID_REGISTERLIST_CHANGEUPPER,
|
||||
ID_REGISTERLIST_CHANGEVALUE
|
||||
ID_REGISTERLIST_CHANGEVALUE,
|
||||
ID_REGISTERLIST_GOTOINMEMORYVIEW,
|
||||
ID_REGISTERLIST_GOTOINDISASM
|
||||
};
|
||||
|
||||
|
||||
@ -276,7 +279,18 @@ void CtrlRegisterList::OnDraw(wxDC& dc)
|
||||
{
|
||||
case 128:
|
||||
{
|
||||
int startIndex = std::min<int>(3,maxBits/32-1);
|
||||
int startIndex = std::min<int>(3, maxBits / 32 - 1);
|
||||
|
||||
if (resolvePointerStrings && cpu && cpu->isAlive()) {
|
||||
char *strval = cpu->stringFromPointer(value._u32[0]);
|
||||
if (strval) {
|
||||
static wxColor clr = wxColor(0xFF228822);
|
||||
dc.SetTextForeground(clr);
|
||||
dc.DrawText(wxString(strval), width - (32 * charWidth + 12), y + 2);
|
||||
startIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int actualX = width-4-(startIndex+1)*(8*charWidth+2);
|
||||
x = std::max<int>(actualX,x);
|
||||
|
||||
@ -396,23 +410,33 @@ void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||
switch (evt.GetId())
|
||||
{
|
||||
case ID_REGISTERLIST_DISPLAY32:
|
||||
resolvePointerStrings = false;
|
||||
maxBits = 32;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY64:
|
||||
resolvePointerStrings = false;
|
||||
maxBits = 64;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY128:
|
||||
resolvePointerStrings = false;
|
||||
maxBits = 128;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_DISPLAY128STRINGS:
|
||||
resolvePointerStrings = true;
|
||||
maxBits = 128;
|
||||
SetInitialSize(ClientToWindowSize(GetMinClientSize()));
|
||||
postEvent(debEVT_UPDATELAYOUT, 0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGELOWER:
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
@ -428,6 +452,12 @@ void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_GOTOINMEMORYVIEW:
|
||||
postEvent(debEVT_GOTOINMEMORYVIEW, cpu->getRegister(category, currentRows[category])._u32[0]);
|
||||
break;
|
||||
case ID_REGISTERLIST_GOTOINDISASM:
|
||||
postEvent(debEVT_GOTOINDISASM, cpu->getRegister(category, currentRows[category])._u32[0]);
|
||||
break;
|
||||
default:
|
||||
wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
||||
break;
|
||||
@ -496,6 +526,7 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128STRINGS, L"Display 128 bit + Resolve string pointers");
|
||||
menu.AppendSeparator();
|
||||
|
||||
if (bits >= 64)
|
||||
@ -506,10 +537,17 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||
}
|
||||
|
||||
menu.AppendSeparator();
|
||||
menu.Append(ID_REGISTERLIST_GOTOINMEMORYVIEW, L"Follow in Memory view");
|
||||
menu.Append(ID_REGISTERLIST_GOTOINDISASM, L"Follow in Disasm");
|
||||
|
||||
switch (maxBits)
|
||||
{
|
||||
case 128:
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
||||
if (resolvePointerStrings)
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY128STRINGS, true);
|
||||
else
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
||||
break;
|
||||
case 64:
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY64,true);
|
||||
|
@ -72,4 +72,5 @@ private:
|
||||
u32 lastPc;
|
||||
int category;
|
||||
int maxBits;
|
||||
};
|
||||
bool resolvePointerStrings;
|
||||
};
|
||||
|
@ -54,4 +54,4 @@ bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, c
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -501,8 +501,10 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
||||
if (currentCpu != NULL)
|
||||
{
|
||||
currentCpu->showMemoryView();
|
||||
currentCpu->getMemoryView()->gotoAddress(evt.GetInt());
|
||||
currentCpu->getDisassembly()->SetFocus();
|
||||
|
||||
CtrlMemView *memview = currentCpu->getMemoryView();
|
||||
memview->gotoAddress(evt.GetInt(), true);
|
||||
memview->SetFocus();
|
||||
}
|
||||
} else if (type == debEVT_RUNTOPOS)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user