debugger: some user-friendly improves in ui

Grouping bytes in debugger memory window, following pointers and history
Goto in register view
Printing strings in pointer registers
Memory view can be resized correctly by ctrl+wheel
Improvement in function 5900DebugInterface::isValidAddress
This commit is contained in:
Vladimir Jigulin 2016-04-09 13:32:51 +03:00
parent 00643dbdfb
commit 7e91eb6616
11 changed files with 403 additions and 172 deletions

View File

@ -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:

View File

@ -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;

View File

@ -58,6 +58,7 @@ public:
bool isCpuPaused();
void pauseCpu();
void resumeCpu();
char *stringFromPointer(u32 p);
};
class R5900DebugInterface: public DebugInterface

View File

@ -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>

View File

@ -60,4 +60,4 @@ private:
u32 size;
char condition[128];
PostfixExpression compiledCondition;
};
};

View File

@ -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();
}

View File

@ -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;
};
};

View File

@ -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;
@ -495,6 +525,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)
@ -505,10 +536,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);

View File

@ -71,4 +71,5 @@ private:
u32 lastPc;
int category;
int maxBits;
};
bool resolvePointerStrings;
};

View File

@ -54,4 +54,4 @@ bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, c
}
return true;
}
}

View File

@ -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)
{