ppsspp/Windows/Debugger/CtrlMemView.cpp
2012-11-01 16:19:01 +01:00

407 lines
9.2 KiB
C++

// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
#include <tchar.h>
#include <math.h>
#include "../../globals.h"
#include "../resource.h"
#include "../../Core/MemMap.h"
#include "../W32Util/Misc.h"
#include "../Main.h"
#include "../../Core/Debugger/SymbolMap.h"
#include "Debugger_Disasm.h"
#include "CtrlMemView.h"
TCHAR CtrlMemView::szClassName[] = _T("CtrlMemView");
extern HMENU g_hPopupMenus;
CtrlMemView::CtrlMemView(HWND _wnd)
{
wnd=_wnd;
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG)this);
SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL);
SetScrollRange(wnd, SB_VERT, -1,1,TRUE);
font = CreateFont(12,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
"Lucida Console");
curAddress=0;
rowHeight=12;
align=4;
alignMul=4;
selecting=false;
mode=MV_NORMAL;
debugger = 0;
}
CtrlMemView::~CtrlMemView()
{
DeleteObject(font);
}
void CtrlMemView::init()
{
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.lpszClassName = szClassName;
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = CtrlMemView::wndProc;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = 0;
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof( CtrlMemView * );
wc.hIconSm = 0;
RegisterClassEx(&wc);
}
void CtrlMemView::deinit()
{
//UnregisterClass(szClassName, hInst)
}
LRESULT CALLBACK CtrlMemView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CtrlMemView *ccp = CtrlMemView::getFrom(hwnd);
static bool lmbDown=false,rmbDown=false;
switch(msg)
{
case WM_NCCREATE:
// Allocate a new CustCtrl structure for this window.
ccp = new CtrlMemView(hwnd);
// Continue with window creation.
return ccp != NULL;
// Clean up when the window is destroyed.
case WM_NCDESTROY:
delete ccp;
break;
case WM_SETFONT:
break;
case WM_SIZE:
ccp->redraw();
break;
case WM_PAINT:
ccp->onPaint(wParam,lParam);
break;
case WM_VSCROLL:
ccp->onVScroll(wParam,lParam);
break;
case WM_ERASEBKGND:
return FALSE;
case WM_KEYDOWN:
ccp->onKeyDown(wParam,lParam);
break;
case WM_LBUTTONDOWN: SetFocus(hwnd); lmbDown=true; ccp->onMouseDown(wParam,lParam,1); break;
case WM_RBUTTONDOWN: rmbDown=true; ccp->onMouseDown(wParam,lParam,2); break;
case WM_MOUSEMOVE: ccp->onMouseMove(wParam,lParam,(lmbDown?1:0) | (rmbDown?2:0)); break;
case WM_LBUTTONUP: lmbDown=false; ccp->onMouseUp(wParam,lParam,1); break;
case WM_RBUTTONUP: rmbDown=false; ccp->onMouseUp(wParam,lParam,2); break;
case WM_SETFOCUS:
SetFocus(hwnd);
ccp->hasFocus=true;
ccp->redraw();
break;
case WM_KILLFOCUS:
ccp->hasFocus=false;
ccp->redraw();
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
CtrlMemView *CtrlMemView::getFrom(HWND hwnd)
{
return (CtrlMemView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
//Yeah this truly turned into a mess with the latest additions.. but it sure looks nice ;)
void CtrlMemView::onPaint(WPARAM wParam, LPARAM lParam)
{
if (!debugger)
return;
GetClientRect(wnd, &rect);
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(wnd, &ps);
int width = rect.right;
int numRows=(rect.bottom/rowHeight)/2+1;
SetBkMode(hdc, TRANSPARENT);
HPEN nullPen=CreatePen(0,0,0xFFFFFF);
HPEN currentPen=CreatePen(0,0,0);
HPEN selPen=CreatePen(0,0,0x808080);
LOGBRUSH lbr;
lbr.lbHatch=0; lbr.lbStyle=0;
lbr.lbColor=0xFFFFFF;
HBRUSH nullBrush=CreateBrushIndirect(&lbr);
lbr.lbColor=0xFFEfE8;
HBRUSH currentBrush=CreateBrushIndirect(&lbr);
lbr.lbColor=0x70FF70;
HBRUSH pcBrush=CreateBrushIndirect(&lbr);
HPEN oldPen=(HPEN)SelectObject(hdc,nullPen);
HBRUSH oldBrush=(HBRUSH)SelectObject(hdc,nullBrush);
HFONT oldFont = (HFONT)SelectObject(hdc,(HGDIOBJ)font);
int i;
curAddress&=~(align-1);
for (i=-numRows; i<=numRows; i++)
{
unsigned int address=curAddress + i*align*alignMul;
int rowY1 = rect.bottom/2 + rowHeight*i - rowHeight/2;
int rowY2 = rect.bottom/2 + rowHeight*i + rowHeight/2;
char temp[256];
sprintf(temp,"%08x",address);
SelectObject(hdc,currentBrush);
if (selecting && address == selection)
SelectObject(hdc,selPen);
else
SelectObject(hdc,i==0 ? currentPen : nullPen);
Rectangle(hdc,0,rowY1,16,rowY2);
Rectangle(hdc,16,rowY1,width,rowY2);
SelectObject(hdc,nullBrush);
SetTextColor(hdc,0x600000);
TextOut(hdc,17,rowY1,temp,strlen(temp));
SetTextColor(hdc,0x000000);
if (debugger->isAlive())
{
switch(mode) {
case MV_NORMAL:
{
const char *m = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
if (Memory::IsValidAddress(address))
{
u32 memory[4] = {
debugger->readMemory(address),
debugger->readMemory(address+4),
debugger->readMemory(address+8),
debugger->readMemory(address+12)
};
m = (const char*)memory;
sprintf(temp, "%08x %08x %08x %08x ................",
memory[0],memory[1],memory[2],memory[3]);
}
for (int i=0; i<16; i++)
{
int c = (unsigned char)m[i];
if (c>=32 && c<255)
temp[i+37]=c;
}
}
// if (align == 16)
// else
// sprintf(temp, "%04x %04x %04x %04x", ReadMem16Unchecked(address),ReadMem16Unchecked(address+2), ReadMem16Unchecked(address+4), ReadMem16Unchecked(address+6))
TextOut(hdc,80,rowY1,temp,strlen(temp));
break;
case MV_SYMBOLS:
{
SetTextColor(hdc,0x0000FF);
int fn = symbolMap.GetSymbolNum(address);
if (fn==-1)
{
sprintf(temp, "%s (ns)", Memory::GetAddressName(address));
}
else
sprintf(temp, "%s (0x%x b)", symbolMap.GetSymbolName(fn),symbolMap.GetSymbolSize(fn));
TextOut(hdc,200,rowY1,temp,strlen(temp));
SetTextColor(hdc,0x0000000);
if (align==4)
{
u32 value = Memory::ReadUnchecked_U32(address);
sprintf(temp, "%08x [%s]", value, symbolMap.GetSymbolName(symbolMap.GetSymbolNum(value)));
}
else if (align==2)
{
u16 value = Memory::ReadUnchecked_U16(address);
sprintf(temp, "%04x [%s]", value, symbolMap.GetSymbolName(symbolMap.GetSymbolNum(value)));
}
TextOut(hdc,70,rowY1,temp,strlen(temp));
break;
}
}
}
}
SelectObject(hdc,oldFont);
SelectObject(hdc,oldPen);
SelectObject(hdc,oldBrush);
DeleteObject(nullPen);
DeleteObject(currentPen);
DeleteObject(selPen);
DeleteObject(nullBrush);
DeleteObject(pcBrush);
DeleteObject(currentBrush);
EndPaint(wnd, &ps);
}
void CtrlMemView::onVScroll(WPARAM wParam, LPARAM lParam)
{
RECT rect;
GetClientRect(this->wnd, &rect);
int page=(rect.bottom/rowHeight)/2-1;
switch (wParam & 0xFFFF)
{
case SB_LINEDOWN:
curAddress+=align*alignMul;
break;
case SB_LINEUP:
curAddress-=align*alignMul;
break;
case SB_PAGEDOWN:
curAddress+=page*align*alignMul;
break;
case SB_PAGEUP:
curAddress-=page*align*alignMul;
break;
default:
return;
}
redraw();
}
void CtrlMemView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
RECT rect;
GetClientRect(this->wnd, &rect);
int page=(rect.bottom/rowHeight)/2-1;
switch (wParam & 0xFFFF)
{
case VK_DOWN:
curAddress+=align*alignMul;
break;
case VK_UP:
curAddress-=align*alignMul;
break;
case VK_NEXT:
curAddress+=page*align*alignMul;
break;
case VK_PRIOR:
curAddress-=page*align*alignMul;
break;
default:
return;
}
redraw();
}
void CtrlMemView::redraw()
{
InvalidateRect(wnd, NULL, FALSE);
UpdateWindow(wnd);
}
void CtrlMemView::onMouseDown(WPARAM wParam, LPARAM lParam, int button)
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
if (x>16)
{
oldSelection=selection;
selection=yToAddress(y);
SetCapture(wnd);
bool oldselecting=selecting;
selecting=true;
if (!oldselecting || (selection!=oldSelection))
redraw();
}
}
void CtrlMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
{
if (button==2)
{
//popup menu?
POINT pt;
GetCursorPos(&pt);
switch (TrackPopupMenuEx(GetSubMenu(g_hPopupMenus,0),TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,wnd,0))
{
case ID_MEMVIEW_DUMP:
MessageBox(wnd,"This feature has not been implemented.","Sorry",0);
break;
case ID_MEMVIEW_COPYVALUE:
{
char temp[24];
sprintf(temp,"%08x",Memory::ReadUnchecked_U32(selection));
W32Util::CopyTextToClipboard(wnd,temp);
}
break;
}
return;
}
int x = LOWORD(lParam);
int y = HIWORD(lParam);
if (x>16)
{
curAddress=yToAddress(y);
selecting=false;
ReleaseCapture();
redraw();
}
}
void CtrlMemView::onMouseMove(WPARAM wParam, LPARAM lParam, int button)
{
if (button&1)
{
int x = LOWORD(lParam);
int y = (signed short)HIWORD(lParam);
if (x>16)
{
if (y<0)
{
curAddress-=align*alignMul;
redraw();
}
else if (y>rect.bottom)
{
curAddress+=align*alignMul;
redraw();
}
else
onMouseDown(wParam,lParam,1);
}
}
}
int CtrlMemView::yToAddress(int y)
{
int ydiff=y-rect.bottom/2-rowHeight/2;
ydiff=(int)(floorf((float)ydiff / (float)rowHeight))+1;
return curAddress + ydiff * align*alignMul;
}