mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
GUI: Polish the memory viewer
This commit is contained in:
parent
2172974db9
commit
6c1ca7d797
2 changed files with 144 additions and 46 deletions
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "memory_viewer_panel.h"
|
#include "memory_viewer_panel.h"
|
||||||
|
|
||||||
|
#include "Emu/Cell/SPUThread.h"
|
||||||
|
#include "Emu/IdManager.h"
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
@ -23,8 +25,9 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr)
|
||||||
setObjectName("memory_viewer");
|
setObjectName("memory_viewer");
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
exit = false;
|
exit = false;
|
||||||
m_colcount = 16;
|
m_colcount = 4;
|
||||||
m_rowcount = 16;
|
m_rowcount = 16;
|
||||||
|
m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row
|
||||||
int pSize = 10;
|
int pSize = 10;
|
||||||
|
|
||||||
//Font
|
//Font
|
||||||
|
@ -55,14 +58,14 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr)
|
||||||
hbox_tools_mem_addr->addWidget(m_addr_line);
|
hbox_tools_mem_addr->addWidget(m_addr_line);
|
||||||
tools_mem_addr->setLayout(hbox_tools_mem_addr);
|
tools_mem_addr->setLayout(hbox_tools_mem_addr);
|
||||||
|
|
||||||
//Tools: Memory Viewer Options: Bytes
|
//Tools: Memory Viewer Options: Words
|
||||||
QGroupBox* tools_mem_bytes = new QGroupBox(tr("Bytes"));
|
QGroupBox* tools_mem_words = new QGroupBox(tr("Words"));
|
||||||
QHBoxLayout* hbox_tools_mem_bytes = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_mem_words = new QHBoxLayout();
|
||||||
QSpinBox* sb_bytes = new QSpinBox(this);
|
QSpinBox* sb_words = new QSpinBox(this);
|
||||||
sb_bytes->setRange(1, 16);
|
sb_words->setRange(1, 4);
|
||||||
sb_bytes->setValue(16);
|
sb_words->setValue(4);
|
||||||
hbox_tools_mem_bytes->addWidget(sb_bytes);
|
hbox_tools_mem_words->addWidget(sb_words);
|
||||||
tools_mem_bytes->setLayout(hbox_tools_mem_bytes);
|
tools_mem_words->setLayout(hbox_tools_mem_words);
|
||||||
|
|
||||||
//Tools: Memory Viewer Options: Control
|
//Tools: Memory Viewer Options: Control
|
||||||
QGroupBox* tools_mem_buttons = new QGroupBox(tr("Control"));
|
QGroupBox* tools_mem_buttons = new QGroupBox(tr("Control"));
|
||||||
|
@ -87,7 +90,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr)
|
||||||
|
|
||||||
//Merge Tools: Memory Viewer
|
//Merge Tools: Memory Viewer
|
||||||
hbox_tools_mem->addWidget(tools_mem_addr);
|
hbox_tools_mem->addWidget(tools_mem_addr);
|
||||||
hbox_tools_mem->addWidget(tools_mem_bytes);
|
hbox_tools_mem->addWidget(tools_mem_words);
|
||||||
hbox_tools_mem->addWidget(tools_mem_buttons);
|
hbox_tools_mem->addWidget(tools_mem_buttons);
|
||||||
tools_mem->setLayout(hbox_tools_mem);
|
tools_mem->setLayout(hbox_tools_mem);
|
||||||
|
|
||||||
|
@ -179,15 +182,11 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr)
|
||||||
hbox_mem_panel->addWidget(m_mem_ascii);
|
hbox_mem_panel->addWidget(m_mem_ascii);
|
||||||
hbox_mem_panel->addSpacing(10);
|
hbox_mem_panel->addSpacing(10);
|
||||||
|
|
||||||
//Memory Panel: Set size of the QTextEdits
|
|
||||||
m_mem_hex->setFixedSize(QSize(pSize * 3 * m_colcount + 6, 228));
|
|
||||||
m_mem_ascii->setFixedSize(QSize(pSize * m_colcount + 6, 228));
|
|
||||||
|
|
||||||
//Set Margins to adjust WindowSize
|
//Set Margins to adjust WindowSize
|
||||||
vbox_panel->setContentsMargins(0, 0, 0, 0);
|
vbox_panel->setContentsMargins(0, 0, 0, 0);
|
||||||
hbox_tools->setContentsMargins(0, 0, 0, 0);
|
hbox_tools->setContentsMargins(0, 0, 0, 0);
|
||||||
tools_mem_addr->setContentsMargins(0, 10, 0, 0);
|
tools_mem_addr->setContentsMargins(0, 10, 0, 0);
|
||||||
tools_mem_bytes->setContentsMargins(0, 10, 0, 0);
|
tools_mem_words->setContentsMargins(0, 10, 0, 0);
|
||||||
tools_mem_buttons->setContentsMargins(0, 10, 0, 0);
|
tools_mem_buttons->setContentsMargins(0, 10, 0, 0);
|
||||||
tools_img_mode->setContentsMargins(0, 10, 0, 0);
|
tools_img_mode->setContentsMargins(0, 10, 0, 0);
|
||||||
tools_img_size->setContentsMargins(0, 10, 0, 0);
|
tools_img_size->setContentsMargins(0, 10, 0, 0);
|
||||||
|
@ -205,25 +204,24 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr)
|
||||||
setLayout(vbox_panel);
|
setLayout(vbox_panel);
|
||||||
|
|
||||||
//Events
|
//Events
|
||||||
connect(m_addr_line, &QLineEdit::returnPressed, [=, this]()
|
connect(m_addr_line, &QLineEdit::returnPressed, [this]()
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
m_addr = m_addr_line->text().toULong(&ok, 16);
|
m_addr = m_addr_line->text().toULong(&ok, 16);
|
||||||
|
m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row
|
||||||
m_addr_line->setText(QString("%1").arg(m_addr, 8, 16, QChar('0'))); // get 8 digits in input line
|
m_addr_line->setText(QString("%1").arg(m_addr, 8, 16, QChar('0'))); // get 8 digits in input line
|
||||||
ShowMemory();
|
ShowMemory();
|
||||||
});
|
});
|
||||||
connect(sb_bytes, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=, this]()
|
connect(sb_words, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=, this]()
|
||||||
{
|
{
|
||||||
m_colcount = sb_bytes->value();
|
m_colcount = sb_words->value();
|
||||||
m_mem_hex->setFixedSize(QSize(pSize * 3 * m_colcount + 6, 228));
|
|
||||||
m_mem_ascii->setFixedSize(QSize(pSize * m_colcount + 6, 228));
|
|
||||||
ShowMemory();
|
ShowMemory();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(b_prev, &QAbstractButton::clicked, [=, this]() { m_addr -= m_colcount; ShowMemory(); });
|
connect(b_prev, &QAbstractButton::clicked, [this]() { scroll(-1); });
|
||||||
connect(b_next, &QAbstractButton::clicked, [=, this]() { m_addr += m_colcount; ShowMemory(); });
|
connect(b_next, &QAbstractButton::clicked, [this]() { scroll(1); });
|
||||||
connect(b_fprev, &QAbstractButton::clicked, [=, this]() { m_addr -= m_rowcount * m_colcount; ShowMemory(); });
|
connect(b_fprev, &QAbstractButton::clicked, [this]() { scroll(-m_rowcount); });
|
||||||
connect(b_fnext, &QAbstractButton::clicked, [=, this]() { m_addr += m_rowcount * m_colcount; ShowMemory(); });
|
connect(b_fnext, &QAbstractButton::clicked, [this]() { scroll(m_rowcount); });
|
||||||
connect(b_img, &QAbstractButton::clicked, [=, this]()
|
connect(b_img, &QAbstractButton::clicked, [=, this]()
|
||||||
{
|
{
|
||||||
int mode = cbox_img_mode->currentIndex();
|
int mode = cbox_img_mode->currentIndex();
|
||||||
|
@ -252,8 +250,15 @@ void memory_viewer_panel::wheelEvent(QWheelEvent *event)
|
||||||
stepSize *= m_rowcount;
|
stepSize *= m_rowcount;
|
||||||
|
|
||||||
QPoint numSteps = event->angleDelta() / 8 / 15; // http://doc.qt.io/qt-5/qwheelevent.html#pixelDelta
|
QPoint numSteps = event->angleDelta() / 8 / 15; // http://doc.qt.io/qt-5/qwheelevent.html#pixelDelta
|
||||||
m_addr -= stepSize * m_colcount * numSteps.y();
|
|
||||||
|
|
||||||
|
scroll(stepSize * (0 - numSteps.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_viewer_panel::scroll(s32 steps)
|
||||||
|
{
|
||||||
|
if (steps == 0) return;
|
||||||
|
|
||||||
|
m_addr += m_colcount * 4 * steps;
|
||||||
m_addr_line->setText(qstr(fmt::format("%08x", m_addr)));
|
m_addr_line->setText(qstr(fmt::format("%08x", m_addr)));
|
||||||
ShowMemory();
|
ShowMemory();
|
||||||
}
|
}
|
||||||
|
@ -281,42 +286,132 @@ void memory_viewer_panel::resizeEvent(QResizeEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string memory_viewer_panel::getHeaderAtAddr(u32 addr)
|
||||||
|
{
|
||||||
|
// Check if its an SPU Local Storage beginning
|
||||||
|
const u32 spu_boundary = ::align<u32>(addr, SPU_LS_SIZE);
|
||||||
|
|
||||||
|
if (spu_boundary <= addr + m_colcount * 4 - 1)
|
||||||
|
{
|
||||||
|
std::shared_ptr<named_thread<spu_thread>> spu;
|
||||||
|
|
||||||
|
if (u32 raw_spu_index = (spu_boundary - RAW_SPU_BASE_ADDR) / SPU_LS_SIZE; raw_spu_index < 5)
|
||||||
|
{
|
||||||
|
spu = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(raw_spu_index));
|
||||||
|
}
|
||||||
|
else if (u32 spu_index = (spu_boundary - SPU_FAKE_BASE_ADDR) / SPU_LS_SIZE; spu_index < spu_thread::id_count)
|
||||||
|
{
|
||||||
|
spu = idm::get<named_thread<spu_thread>>(spu_thread::id_base | spu_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spu)
|
||||||
|
{
|
||||||
|
return spu->get_name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void memory_viewer_panel::ShowMemory()
|
void memory_viewer_panel::ShowMemory()
|
||||||
{
|
{
|
||||||
QString t_mem_addr_str;
|
QString t_mem_addr_str;
|
||||||
QString t_mem_hex_str;
|
QString t_mem_hex_str;
|
||||||
QString t_mem_ascii_str;
|
QString t_mem_ascii_str;
|
||||||
|
|
||||||
for(u32 addr = m_addr; addr != m_addr + m_rowcount * m_colcount; addr += m_colcount)
|
for (u32 row = 0, spu_passed = 0; row < m_rowcount; row++)
|
||||||
{
|
{
|
||||||
t_mem_addr_str += qstr(fmt::format("%08x", addr));
|
if (row)
|
||||||
if (addr != m_addr + m_rowcount * m_colcount - m_colcount) t_mem_addr_str += "\r\n";
|
{
|
||||||
}
|
t_mem_addr_str += "\r\n";
|
||||||
|
t_mem_hex_str += "\r\n";
|
||||||
|
t_mem_ascii_str += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check if this address contains potential header
|
||||||
|
const u32 addr = m_addr + (row - spu_passed) * m_colcount * 4;
|
||||||
|
const std::string header = getHeaderAtAddr(addr);
|
||||||
|
if (!header.empty())
|
||||||
|
{
|
||||||
|
// Create an SPU header at the beginning of local storage
|
||||||
|
// Like so:
|
||||||
|
// =======================================
|
||||||
|
// SPU[0x0000100] CellSpursKernel0
|
||||||
|
// =======================================
|
||||||
|
|
||||||
|
bool _break = false;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
t_mem_addr_str += qstr(fmt::format("%08x", addr));
|
||||||
|
|
||||||
|
std::string str(i == 1 ? header : "");
|
||||||
|
|
||||||
|
const u32 expected_str_size = m_colcount * 13 - 2;
|
||||||
|
|
||||||
|
// Truncate or enlarge string to a fixed size
|
||||||
|
str.resize(expected_str_size);
|
||||||
|
std::replace(str.begin(), str.end(), '\0', i == 1 ? ' ' : '=');
|
||||||
|
|
||||||
|
t_mem_hex_str += qstr(str);
|
||||||
|
|
||||||
|
spu_passed++;
|
||||||
|
row++;
|
||||||
|
|
||||||
|
if (row >= m_rowcount)
|
||||||
|
{
|
||||||
|
_break = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_mem_addr_str += "\r\n";
|
||||||
|
t_mem_hex_str += "\r\n";
|
||||||
|
t_mem_ascii_str += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_break)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t_mem_addr_str += qstr(fmt::format("%08x", m_addr + (row - spu_passed) * m_colcount * 4));
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 row = 0; row < m_rowcount; row++)
|
|
||||||
{
|
|
||||||
for (u32 col = 0; col < m_colcount; col++)
|
for (u32 col = 0; col < m_colcount; col++)
|
||||||
{
|
{
|
||||||
u32 addr = m_addr + row * m_colcount + col;
|
if (col)
|
||||||
|
|
||||||
if (vm::check_addr(addr, 0))
|
|
||||||
{
|
{
|
||||||
const u8 rmem = *vm::get_super_ptr<u8>(addr);
|
t_mem_hex_str += " ";
|
||||||
t_mem_hex_str += qstr(fmt::format("%02x ", rmem));
|
}
|
||||||
t_mem_ascii_str += qstr(std::string(1, std::isprint(rmem) ? static_cast<char>(rmem) : '.'));
|
|
||||||
|
u32 addr = m_addr + (row - spu_passed) * m_colcount * 4 + col * 4;
|
||||||
|
|
||||||
|
if (vm::check_addr(addr, 0, 4))
|
||||||
|
{
|
||||||
|
const be_t<u32> rmem = *vm::get_super_ptr<u32>(addr);
|
||||||
|
t_mem_hex_str += qstr(fmt::format("%02x %02x %02x %02x",
|
||||||
|
static_cast<u8>(rmem >> 24),
|
||||||
|
static_cast<u8>(rmem >> 16),
|
||||||
|
static_cast<u8>(rmem >> 8),
|
||||||
|
static_cast<u8>(rmem >> 0)));
|
||||||
|
|
||||||
|
std::string str{reinterpret_cast<const char*>(&rmem), 4};
|
||||||
|
|
||||||
|
for (auto& ch : str)
|
||||||
|
{
|
||||||
|
if (!std::isprint(static_cast<u8>(ch))) ch = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
t_mem_ascii_str += qstr(std::move(str));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t_mem_hex_str += "??";
|
t_mem_hex_str += "?? ?? ?? ??";
|
||||||
t_mem_ascii_str += "?";
|
t_mem_ascii_str += "????";
|
||||||
if (col != m_colcount - 1) t_mem_hex_str += " ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (row != m_rowcount - 1)
|
|
||||||
{
|
|
||||||
t_mem_hex_str += "\r\n";
|
|
||||||
t_mem_ascii_str += "\r\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mem_addr->setText(t_mem_addr_str);
|
m_mem_addr->setText(t_mem_addr_str);
|
||||||
|
|
|
@ -26,6 +26,9 @@ private:
|
||||||
|
|
||||||
QFontMetrics* m_fontMetrics;
|
QFontMetrics* m_fontMetrics;
|
||||||
|
|
||||||
|
std::string getHeaderAtAddr(u32 addr);
|
||||||
|
void scroll(s32 steps);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool exit;
|
bool exit;
|
||||||
memory_viewer_panel(QWidget* parent, u32 addr = 0);
|
memory_viewer_panel(QWidget* parent, u32 addr = 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue