ppsspp/Qt/ctrlmemview.cpp
Peter Tissen b40278fff6 Set Qt to build debug menus on non Linux platforms and fix some debugger crashes
This makes Common.pro and Native.pro use their own distinct object directories
to prevent the two fbo.cpp and sha1.c files repectively to clash into the same
*.obj file.

The registerlist had polled register values of -1 in some cases when resizing
the window. Making sure it doesn't poll values smaller than 0 fixes it.

The memoryview crashed if it was switched into symbol mode outside of the
symbol definition range. Also, under Windows the monospace font wasn't
used because there's not literal font called "monospace" so a font family
hint had to be used.

The UpdateDisassembly() function jumped to the current PC, which sounds
reasonable at first but the issue is that this function gets called when a
breakpoint get set, so if you set a breakpoint somewhere completely
different then you suddenly lose that position for no good reason.

Enable the desktop QT interface for all non ARM QT platforms

make sure the QtMain.cpp in the native submodule is also updated
2013-11-05 13:17:27 +01:00

267 lines
6.3 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);
alignedFont.setStyleHint(QFont::Monospace);
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);
int symbolnum = symbolMap.GetSymbolNum(value);
if(symbolnum>=0)
sprintf(temp, "%08x [%s]", value, symbolMap.GetSymbolName(symbolnum));
}
else if (align==2)
{
u16 value = Memory::ReadUnchecked_U16(address);
int symbolnum = symbolMap.GetSymbolNum(value);
if(symbolnum>=0)
sprintf(temp, "%04x [%s]", value, symbolMap.GetSymbolName(symbolnum));
}
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;
}