diff --git a/bin/docs/debugger.txt b/bin/docs/debugger.txt index ad5cfe3a17..b37bdf7d70 100644 --- a/bin/docs/debugger.txt +++ b/bin/docs/debugger.txt @@ -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: diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index f69a24006e..071058378b 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -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; diff --git a/pcsx2/DebugTools/DebugInterface.h b/pcsx2/DebugTools/DebugInterface.h index a7091bbd3a..31c7c643c1 100644 --- a/pcsx2/DebugTools/DebugInterface.h +++ b/pcsx2/DebugTools/DebugInterface.h @@ -58,6 +58,7 @@ public: bool isCpuPaused(); void pauseCpu(); void resumeCpu(); + char *stringFromPointer(u32 p); }; class R5900DebugInterface: public DebugInterface diff --git a/pcsx2/PrecompiledHeader.h b/pcsx2/PrecompiledHeader.h index a9dc78ab24..0a97c20b4b 100644 --- a/pcsx2/PrecompiledHeader.h +++ b/pcsx2/PrecompiledHeader.h @@ -41,6 +41,7 @@ #include #include #include +#include #include // string.h under c++ #include // stdio.h under c++ #include diff --git a/pcsx2/gui/Debugger/BreakpointWindow.h b/pcsx2/gui/Debugger/BreakpointWindow.h index 50fc27ede1..c1c4285ee5 100644 --- a/pcsx2/gui/Debugger/BreakpointWindow.h +++ b/pcsx2/gui/Debugger/BreakpointWindow.h @@ -60,4 +60,4 @@ private: u32 size; char condition[128]; PostfixExpression compiledCondition; -}; \ No newline at end of file +}; diff --git a/pcsx2/gui/Debugger/CtrlMemView.cpp b/pcsx2/gui/Debugger/CtrlMemView.cpp index 0e6afffc55..031e600a1d 100644 --- a/pcsx2/gui/Debugger/CtrlMemView.cpp +++ b/pcsx2/gui/Debugger/CtrlMemView.cpp @@ -24,6 +24,7 @@ #include #include + 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(); } diff --git a/pcsx2/gui/Debugger/CtrlMemView.h b/pcsx2/gui/Debugger/CtrlMemView.h index 562414d578..250f77deeb 100644 --- a/pcsx2/gui/Debugger/CtrlMemView.h +++ b/pcsx2/gui/Debugger/CtrlMemView.h @@ -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 history; wxMenu menu; -}; \ No newline at end of file +}; diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.cpp b/pcsx2/gui/Debugger/CtrlRegisterList.cpp index ee3aa46a00..5243b97f8c 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.cpp +++ b/pcsx2/gui/Debugger/CtrlRegisterList.cpp @@ -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(3,maxBits/32-1); + int startIndex = std::min(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(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); diff --git a/pcsx2/gui/Debugger/CtrlRegisterList.h b/pcsx2/gui/Debugger/CtrlRegisterList.h index 6ca8c6adf8..33746850cd 100644 --- a/pcsx2/gui/Debugger/CtrlRegisterList.h +++ b/pcsx2/gui/Debugger/CtrlRegisterList.h @@ -71,4 +71,5 @@ private: u32 lastPc; int category; int maxBits; -}; \ No newline at end of file + bool resolvePointerStrings; +}; diff --git a/pcsx2/gui/Debugger/DebugEvents.cpp b/pcsx2/gui/Debugger/DebugEvents.cpp index eabb3c0e3f..852e6cd87e 100644 --- a/pcsx2/gui/Debugger/DebugEvents.cpp +++ b/pcsx2/gui/Debugger/DebugEvents.cpp @@ -54,4 +54,4 @@ bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, c } return true; -} \ No newline at end of file +} diff --git a/pcsx2/gui/Debugger/DisassemblyDialog.cpp b/pcsx2/gui/Debugger/DisassemblyDialog.cpp index c1c5d0030f..5d1e357eaa 100644 --- a/pcsx2/gui/Debugger/DisassemblyDialog.cpp +++ b/pcsx2/gui/Debugger/DisassemblyDialog.cpp @@ -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) {