diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index ab5628e739..98c380388b 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -320,22 +320,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) case Qt::Key_M: { // Memory viewer - - u32 addr = pc; - - if (auto spu = static_cast(cpu->id_type() == 2 ? cpu.get() : nullptr)) - { - if (spu->get_type() != spu_type::threaded) - { - addr += RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * spu->index; - } - else - { - addr += SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (spu->id & 0xffffff); - } - } - - auto mvp = new memory_viewer_panel(this, addr); + auto mvp = new memory_viewer_panel(this, pc, cpu); mvp->show(); return; } diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.cpp b/rpcs3/rpcs3qt/memory_viewer_panel.cpp index 1d8154ad26..2330efeda1 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.cpp +++ b/rpcs3/rpcs3qt/memory_viewer_panel.cpp @@ -16,19 +16,23 @@ #include #include "util/asm.hpp" +#include "util/vm.hpp" constexpr auto qstr = QString::fromStdString; -memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr) +memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, const std::shared_ptr& cpu) : QDialog(parent) , m_addr(addr) + , m_type(!cpu || cpu->id_type() != 2 ? thread_type::ppu : thread_type::spu) + , m_spu_shm(m_type == thread_type::spu ? static_cast(cpu.get())->shm : nullptr) + , m_addr_mask(m_type == thread_type::spu ? SPU_LS_SIZE - 1 : ~0) { - setWindowTitle(tr("Memory Viewer")); + setWindowTitle(m_type != thread_type::spu ? tr("Memory Viewer") : tr("Memory Viewer Of %0").arg(qstr(cpu->get_name()))); + setObjectName("memory_viewer"); setAttribute(Qt::WA_DeleteOnClose); m_colcount = 4; m_rowcount = 16; - m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row int pSize = 10; // Font @@ -51,12 +55,11 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr) QHBoxLayout* hbox_tools_mem_addr = new QHBoxLayout(); m_addr_line = new QLineEdit(this); m_addr_line->setPlaceholderText("00000000"); - m_addr_line->setText(qstr(fmt::format("%08x", m_addr))); m_addr_line->setFont(mono); m_addr_line->setMaxLength(18); m_addr_line->setFixedWidth(75); m_addr_line->setFocus(); - m_addr_line->setValidator(new QRegExpValidator(QRegExp("^(0[xX])?0*[a-fA-F0-9]{0,8}$"))); + m_addr_line->setValidator(new QRegExpValidator(QRegExp(m_type == thread_type::spu ? "^(0[xX])?0*[a-fA-F0-9]{0,5}$" : "^(0[xX])?0*[a-fA-F0-9]{0,8}$"))); hbox_tools_mem_addr->addWidget(m_addr_line); tools_mem_addr->setLayout(hbox_tools_mem_addr); @@ -125,8 +128,8 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr) QLabel* l_x = new QLabel(" x "); QSpinBox* sb_img_size_x = new QSpinBox(this); QSpinBox* sb_img_size_y = new QSpinBox(this); - sb_img_size_x->setRange(1, 8192); - sb_img_size_y->setRange(1, 8192); + sb_img_size_x->setRange(1, m_type == thread_type::spu ? 256 : 4096); + sb_img_size_y->setRange(1, m_type == thread_type::spu ? 256 : 4096); sb_img_size_x->setValue(256); sb_img_size_y->setValue(256); hbox_tools_img_size->addWidget(sb_img_size_x); @@ -225,17 +228,18 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr) vbox_panel->setSizeConstraint(QLayout::SetNoConstraint); setLayout(vbox_panel); + // Fill the QTextEdits + scroll(0); + // Events connect(m_addr_line, &QLineEdit::returnPressed, [this]() { bool ok = false; const QString text = m_addr_line->text(); const u32 addr = (text.startsWith("0x", Qt::CaseInsensitive) ? text.right(text.size() - 2) : text).toULong(&ok, 16); - if (!ok) return; + if (ok) m_addr = addr; - 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 - ShowMemory(); + scroll(0); // Refresh }); connect(sb_words, static_cast(&QSpinBox::valueChanged), [=, this]() { @@ -255,9 +259,6 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr) ShowImage(this, m_addr, format, sizex, sizey, false); }); - // Fill the QTextEdits - ShowMemory(); - setFixedWidth(sizeHint().width()); } @@ -279,9 +280,10 @@ void memory_viewer_panel::wheelEvent(QWheelEvent *event) void memory_viewer_panel::scroll(s32 steps) { - if (steps == 0) return; + m_addr += m_colcount * 4 * steps; // Add steps + m_addr &= m_addr_mask; // Mask it + m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row - m_addr += m_colcount * 4 * steps; m_addr_line->setText(qstr(fmt::format("%08x", m_addr))); ShowMemory(); } @@ -314,6 +316,8 @@ void memory_viewer_panel::resizeEvent(QResizeEvent *event) std::string memory_viewer_panel::getHeaderAtAddr(u32 addr) { + if (m_type == thread_type::spu) return {}; + // Check if its an SPU Local Storage beginning const u32 spu_boundary = utils::align(addr, SPU_LS_SIZE); @@ -366,7 +370,7 @@ void memory_viewer_panel::ShowMemory() { // Check if this address contains potential header - const u32 addr = m_addr + (row - spu_passed) * m_colcount * 4; + const u32 addr = (m_addr + (row - spu_passed) * m_colcount * 4) & m_addr_mask; const std::string header = getHeaderAtAddr(addr); if (!header.empty()) { @@ -412,7 +416,7 @@ void memory_viewer_panel::ShowMemory() } } - t_mem_addr_str += qstr(fmt::format("%08x", m_addr + (row - spu_passed) * m_colcount * 4)); + t_mem_addr_str += qstr(fmt::format("%08x", (m_addr + (row - spu_passed) * m_colcount * 4) & m_addr_mask)); } for (u32 col = 0; col < m_colcount; col++) @@ -422,11 +426,11 @@ void memory_viewer_panel::ShowMemory() t_mem_hex_str += " "; } - u32 addr = m_addr + (row - spu_passed) * m_colcount * 4 + col * 4; + u32 addr = (m_addr + (row - spu_passed) * m_colcount * 4 + col * 4) & m_addr_mask; - if (vm::check_addr(addr, 0, 4)) + if (m_spu_shm || vm::check_addr(addr, 0, 4)) { - const be_t rmem = *vm::get_super_ptr(addr); + const be_t rmem = m_spu_shm ? *reinterpret_cast*>(m_spu_shm->map_self() + addr) : *vm::get_super_ptr(addr); t_mem_hex_str += qstr(fmt::format("%02x %02x %02x %02x", static_cast(rmem >> 24), static_cast(rmem >> 16), @@ -472,20 +476,28 @@ void memory_viewer_panel::SetPC(const uint pc) void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format format, u32 width, u32 height, bool flipv) { - if (width == 0 || height == 0) + const u64 memsize = 4ull * width * height; + + if (!memsize || memsize > m_addr_mask) { return; } std::shared_lock rlock(vm::g_mutex); - if (!vm::check_addr(addr, 0, width * height * 4)) + if (!m_spu_shm && !vm::check_addr(addr, 0, static_cast(memsize))) { return; } - const auto originalBuffer = vm::get_super_ptr(addr); - const auto convertedBuffer = static_cast(std::malloc(4ULL * width * height)); + const auto originalBuffer = m_spu_shm ? (m_spu_shm->map_self() + addr) : vm::get_super_ptr(addr); + const auto convertedBuffer = new (std::nothrow) u8[static_cast(memsize)]; + + if (!convertedBuffer) + { + // OOM, give up + return; + } switch (format) { @@ -576,7 +588,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form } } - QImage image(convertedBuffer, width, height, QImage::Format_ARGB32, [](void* buffer){ std::free(buffer); }, convertedBuffer); + QImage image(convertedBuffer, width, height, QImage::Format_ARGB32, [](void* buffer){ delete[] static_cast(buffer); }, convertedBuffer); if (image.isNull()) return; QLabel* canvas = new QLabel(); diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.h b/rpcs3/rpcs3qt/memory_viewer_panel.h index f024ef7fff..5229ce6450 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.h +++ b/rpcs3/rpcs3qt/memory_viewer_panel.h @@ -10,12 +10,19 @@ #include +class cpu_thread; + +namespace utils +{ + class shm; +} + class memory_viewer_panel : public QDialog { Q_OBJECT public: - memory_viewer_panel(QWidget* parent, u32 addr = 0); + memory_viewer_panel(QWidget* parent, u32 addr = 0, const std::shared_ptr& cpu = nullptr); ~memory_viewer_panel(); enum class color_format : int @@ -44,11 +51,22 @@ private: QFontMetrics* m_fontMetrics; + enum class thread_type + { + ppu, + spu, + //rsx + }; + + const thread_type m_type; + const std::shared_ptr m_spu_shm; + const u32 m_addr_mask; + std::string getHeaderAtAddr(u32 addr); void scroll(s32 steps); void SetPC(const uint pc); virtual void ShowMemory(); - static void ShowImage(QWidget* parent, u32 addr, color_format format, u32 sizex, u32 sizey, bool flipv); + void ShowImage(QWidget* parent, u32 addr, color_format format, u32 sizex, u32 sizey, bool flipv); };