ppsspp/Qt/ctrlmemview.cpp
2013-10-19 14:57:45 -07:00

262 lines
6.2 KiB
C++

#include "ctrlmemview.h"
#include <QPainter>
#include <QKeyEvent>
#include <QMenu>
#include <QMessageBox>
#include <QApplication>
#include <QClipboard>
#include <QInputDialog>
#include "EmuThread.h"
#include "Core/MemMap.h"
#include "Core/Debugger/SymbolMap.h"
CtrlMemView::CtrlMemView(QWidget *parent) :
QWidget(parent)
{
curAddress=0;
rowHeight=14;
align=4;
alignMul=4;
selecting=false;
mode=MV_NORMAL;
debugger = 0;
setMinimumWidth(500);
}
void CtrlMemView::redraw()
{
update();
}
void CtrlMemView::wheelEvent(QWheelEvent* e)
{
int numDegrees = e->delta() / 8;
int numSteps = numDegrees / 15;
if (e->orientation() == Qt::Vertical)
{
curAddress -= numSteps*align*alignMul;
redraw();
}
}
void CtrlMemView::keyPressEvent(QKeyEvent *e)
{
int page=(rect().bottom()/rowHeight)/2-1;
switch (e->key())
{
case Qt::Key_Up: curAddress -= align*alignMul; break;
case Qt::Key_Down: curAddress += align*alignMul; break;
case Qt::Key_PageUp: curAddress -= page*align*alignMul; break;
case Qt::Key_PageDown: curAddress += page*align*alignMul; break;
default: QWidget::keyPressEvent(e); break;
}
redraw();
}
void CtrlMemView::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setBrush(Qt::white);
painter.setPen(Qt::white);
painter.drawRect(rect());
if (!debugger)
return;
int width = rect().width();
int numRows=(rect().bottom()/rowHeight)/2+1;
QPen nullPen(0xFFFFFF);
QPen currentPen(0xFF000000);
QPen selPen(0x808080);
QBrush lbr(0xFFFFFF);
QBrush nullBrush(0xFFFFFF);
QBrush currentBrush(0xFFEFE8);
QBrush pcBrush(0x70FF70);
QPen textPen;
QFont normalFont("Arial", 10);
QFont alignedFont("Monospace", 10);
painter.setFont(normalFont);
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];
painter.setBrush(currentBrush);
if (selecting && address == (unsigned int)selection)
painter.setPen(selPen);
else
painter.setPen(i==0 ? currentPen : nullPen);
painter.drawRect(0, rowY1, 16-1, rowY2 - rowY1 - 1);
painter.drawRect(16, rowY1, width - 16 -1, rowY2 - rowY1 - 1);
painter.setBrush(nullBrush);
textPen.setColor(0x600000);
painter.setPen(textPen);
painter.setFont(alignedFont);
painter.drawText(17,rowY1-2+rowHeight, QString("%1").arg(address,8,16,QChar('0')));
textPen.setColor(0xFF000000);
painter.setPen(textPen);
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))
{
EmuThread_LockDraw(true);
u32 memory[4] = {
debugger->readMemory(address),
debugger->readMemory(address+4),
debugger->readMemory(address+8),
debugger->readMemory(address+12)
};
EmuThread_LockDraw(false);
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;
}
}
painter.setFont(alignedFont);
painter.drawText(85,rowY1 - 2 + rowHeight, temp);
break;
case MV_SYMBOLS:
{
textPen.setColor(0x0000FF);
painter.setPen(textPen);
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));
painter.drawText(205,rowY1 - 2 + rowHeight, temp);
textPen.setColor(0xFF000000);
painter.setPen(textPen);
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)));
}
painter.drawText(85,rowY1 - 2 + rowHeight, temp);
break;
}
case MV_MAX: break;
}
}
}
}
void CtrlMemView::mousePressEvent(QMouseEvent *e)
{
int x = e->pos().x();
int y = e->pos().y();
if (x>16)
{
oldSelection=selection;
selection=yToAddress(y);
bool oldselecting=selecting;
selecting=true;
if (!oldselecting || (selection!=oldSelection))
redraw();
}
}
void CtrlMemView::contextMenu(const QPoint &pos)
{
QMenu menu(this);
QAction *gotoDisAsm = new QAction(tr("Go to in &disasm"), this);
//connect(gotoDisAsm, SIGNAL(triggered()), this, SLOT(GotoDisAsm()));
menu.addAction(gotoDisAsm);
menu.addSeparator();
QAction *copyValue = new QAction(tr("&Copy value"), this);
connect(copyValue, SIGNAL(triggered()), this, SLOT(CopyValue()));
menu.addAction(copyValue);
QAction *changeValue = new QAction(tr("C&hange value"), this);
connect(changeValue, SIGNAL(triggered()), this, SLOT(Change()));
menu.addAction(changeValue);
QAction *dump = new QAction(tr("Dump..."), this);
connect(dump, SIGNAL(triggered()), this, SLOT(Dump()));
menu.addAction(dump);
menu.exec( mapToGlobal(pos));
}
void CtrlMemView::CopyValue()
{
EmuThread_LockDraw(true);
QApplication::clipboard()->setText(QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0')));
EmuThread_LockDraw(false);
}
void CtrlMemView::Dump()
{
QMessageBox::information(this,"Sorry","This feature has not been implemented.",QMessageBox::Ok);
}
void CtrlMemView::Change()
{
EmuThread_LockDraw(true);
QString curVal = QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0'));
EmuThread_LockDraw(false);
bool ok;
QString text = QInputDialog::getText(this, tr("Set new value"),
tr("Set new value:"), QLineEdit::Normal,
curVal, &ok);
if (ok && !text.isEmpty())
{
EmuThread_LockDraw(true);
Memory::WriteUnchecked_U32(text.toUInt(0,16),selection);
EmuThread_LockDraw(false);
redraw();
}
}
int CtrlMemView::yToAddress(int y)
{
int ydiff=y-rect().bottom()/2-rowHeight/2;
ydiff=(int)(floor((float)ydiff / (float)rowHeight))+1;
return curAddress + ydiff * align*alignMul;
}