mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 13:01:27 +12:00
Qt: "Show in Memory Viewer" context action (#17131)
This commit is contained in:
parent
c0a1e8d5a5
commit
6428088e46
8 changed files with 165 additions and 1 deletions
|
@ -7,6 +7,7 @@
|
|||
#include <QGuiApplication>
|
||||
|
||||
#include "cheat_manager.h"
|
||||
#include "memory_viewer_panel.h"
|
||||
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
@ -829,6 +830,7 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent)
|
|||
QMenu* menu = new QMenu();
|
||||
|
||||
QAction* add_to_cheat_list = new QAction(tr("Add to cheat list"), menu);
|
||||
QAction* show_in_mem_viewer = new QAction(tr("Show in Memory Viewer"), menu);
|
||||
|
||||
const u32 offset = offsets_found[current_row];
|
||||
const cheat_type type = static_cast<cheat_type>(cbx_cheat_search_type->currentIndex());
|
||||
|
@ -849,7 +851,13 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent)
|
|||
update_cheat_list();
|
||||
});
|
||||
|
||||
connect(show_in_mem_viewer, &QAction::triggered, this, [offset]()
|
||||
{
|
||||
memory_viewer_panel::ShowAtPC(offset);
|
||||
});
|
||||
|
||||
menu->addAction(add_to_cheat_list);
|
||||
menu->addAction(show_in_mem_viewer);
|
||||
menu->exec(globalPos);
|
||||
});
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <QTimer>
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QTextDocumentFragment>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
|
@ -125,7 +127,8 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> gui_settings, QWidg
|
|||
m_regs = new QPlainTextEdit(this);
|
||||
m_regs->setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||
m_regs->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||
|
||||
m_regs->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
m_debugger_list->setFont(m_mono);
|
||||
m_misc_state->setFont(m_mono);
|
||||
m_regs->setFont(m_mono);
|
||||
|
@ -158,6 +161,8 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> gui_settings, QWidg
|
|||
body->setLayout(vbox_p_main);
|
||||
setWidget(body);
|
||||
|
||||
connect(m_regs, &QPlainTextEdit::customContextMenuRequested, this, &debugger_frame::OnRegsContextMenu);
|
||||
|
||||
connect(m_go_to_addr, &QAbstractButton::clicked, this, &debugger_frame::ShowGotoAddressDialog);
|
||||
connect(m_go_to_pc, &QAbstractButton::clicked, this, [this]() { ShowPC(true); });
|
||||
|
||||
|
@ -1702,3 +1707,36 @@ void debugger_frame::EnableButtons(bool enable)
|
|||
m_btn_step_over->setEnabled(step);
|
||||
m_btn_run->setEnabled(enable);
|
||||
}
|
||||
|
||||
void debugger_frame::OnRegsContextMenu(const QPoint& pos)
|
||||
{
|
||||
QMenu* menu = m_regs->createStandardContextMenu();
|
||||
QAction* memory_viewer_action = new QAction(tr("Show in Memory Viewer"), menu);
|
||||
|
||||
connect(memory_viewer_action, &QAction::triggered, this, &debugger_frame::RegsShowMemoryViewerAction);
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addAction(memory_viewer_action);
|
||||
menu->exec(m_regs->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void debugger_frame::RegsShowMemoryViewerAction()
|
||||
{
|
||||
const QTextCursor cursor = m_regs->textCursor();
|
||||
if (!cursor.hasSelection())
|
||||
{
|
||||
QMessageBox::warning(this, tr("No Selection"), tr("Please select a hex value first."));
|
||||
return;
|
||||
}
|
||||
|
||||
const QTextDocumentFragment frag(cursor);
|
||||
const QString selected = frag.toPlainText().trimmed();
|
||||
u64 pc = 0;
|
||||
if (!parse_hex_qstring(selected, &pc))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Hex"), tr("“%0” is not a valid 32-bit hex value.").arg(selected));
|
||||
return;
|
||||
}
|
||||
|
||||
memory_viewer_panel::ShowAtPC(static_cast<u32>(pc), make_check_cpu(get_cpu()));
|
||||
}
|
||||
|
|
|
@ -137,9 +137,11 @@ public Q_SLOTS:
|
|||
private Q_SLOTS:
|
||||
void OnSelectUnit();
|
||||
void OnSelectSPUDisassembler();
|
||||
void OnRegsContextMenu(const QPoint& pos);
|
||||
void ShowPC(bool user_requested = false);
|
||||
void EnableUpdateTimer(bool enable) const;
|
||||
void RunBtnPress();
|
||||
void RegsShowMemoryViewerAction();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(u32)
|
||||
|
|
|
@ -69,3 +69,23 @@ inline QString normalize_hex_qstring(const QString& input)
|
|||
s.chop(1);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline bool parse_hex_qstring(const QString& input, u64* result, int max_bits = 32)
|
||||
{
|
||||
QString s = input;
|
||||
int pos = 0;
|
||||
const HexValidator validator(nullptr, max_bits);
|
||||
const QValidator::State st = validator.validate(s, pos);
|
||||
|
||||
if (st != QValidator::Acceptable)
|
||||
return false;
|
||||
|
||||
const QString norm = normalize_hex_qstring(input);
|
||||
bool ok = false;
|
||||
const quint64 value = norm.toULongLong(&ok, 16);
|
||||
|
||||
if (ok && result)
|
||||
*result = static_cast<u64>(value);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "log_frame.h"
|
||||
#include "qt_utils.h"
|
||||
#include "gui_settings.h"
|
||||
#include "hex_validator.h"
|
||||
#include "memory_viewer_panel.h"
|
||||
|
||||
#include "Utilities/lockless.h"
|
||||
#include "util/asm.hpp"
|
||||
|
@ -250,6 +252,21 @@ void log_frame::CreateAndConnectActions()
|
|||
Q_EMIT PerformGoToOnDebugger(pte->textCursor().selectedText(), true);
|
||||
});
|
||||
|
||||
m_perform_show_in_mem_viewer = new QAction(tr("Show in Memory Viewer"), this);
|
||||
connect(m_perform_show_in_mem_viewer, &QAction::triggered, this, [this]()
|
||||
{
|
||||
const QPlainTextEdit* pte = (m_tabWidget->currentIndex() == 1 ? m_tty : m_log);
|
||||
const QString selected = pte->textCursor().selectedText();
|
||||
u64 pc = 0;
|
||||
if (!parse_hex_qstring(selected, &pc))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Hex"), tr("“%0” is not a valid 32-bit hex value.").arg(selected));
|
||||
return;
|
||||
}
|
||||
|
||||
memory_viewer_panel::ShowAtPC(static_cast<u32>(pc));
|
||||
});
|
||||
|
||||
m_perform_goto_thread_on_debugger = new QAction(tr("Show Thread On The Debugger"), this);
|
||||
connect(m_perform_goto_thread_on_debugger, &QAction::triggered, [this]()
|
||||
{
|
||||
|
@ -354,13 +371,16 @@ void log_frame::CreateAndConnectActions()
|
|||
menu->addAction(m_clear_act);
|
||||
menu->addAction(m_perform_goto_on_debugger);
|
||||
menu->addAction(m_perform_goto_thread_on_debugger);
|
||||
menu->addAction(m_perform_show_in_mem_viewer);
|
||||
|
||||
std::shared_ptr<bool> goto_signal_accepted = std::make_shared<bool>(false);
|
||||
Q_EMIT PerformGoToOnDebugger("", true, true, goto_signal_accepted);
|
||||
m_perform_goto_on_debugger->setEnabled(m_log->textCursor().hasSelection() && *goto_signal_accepted);
|
||||
m_perform_goto_thread_on_debugger->setEnabled(m_log->textCursor().hasSelection() && *goto_signal_accepted);
|
||||
m_perform_show_in_mem_viewer->setEnabled(m_log->textCursor().hasSelection() && *goto_signal_accepted);
|
||||
m_perform_goto_on_debugger->setToolTip(tr("Jump to the selected hexadecimal address from the log text on the debugger."));
|
||||
m_perform_goto_thread_on_debugger->setToolTip(tr("Show the thread that corresponds to the thread ID from the log text on the debugger."));
|
||||
m_perform_show_in_mem_viewer->setToolTip(tr("Jump to the selected hexadecimal address from the log text on the memory viewer."));
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addActions(m_log_level_acts->actions());
|
||||
|
@ -376,11 +396,14 @@ void log_frame::CreateAndConnectActions()
|
|||
QMenu* menu = m_tty->createStandardContextMenu();
|
||||
menu->addAction(m_clear_tty_act);
|
||||
menu->addAction(m_perform_goto_on_debugger);
|
||||
menu->addAction(m_perform_show_in_mem_viewer);
|
||||
|
||||
std::shared_ptr<bool> goto_signal_accepted = std::make_shared<bool>(false);
|
||||
Q_EMIT PerformGoToOnDebugger("", false, true, goto_signal_accepted);
|
||||
m_perform_goto_on_debugger->setEnabled(m_tty->textCursor().hasSelection() && *goto_signal_accepted);
|
||||
m_perform_show_in_mem_viewer->setEnabled(m_tty->textCursor().hasSelection() && *goto_signal_accepted);
|
||||
m_perform_goto_on_debugger->setToolTip(tr("Jump to the selected hexadecimal address from the TTY text on the debugger."));
|
||||
m_perform_show_in_mem_viewer->setToolTip(tr("Jump to the selected hexadecimal address from the TTY text on the memory viewer."));
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addAction(m_tty_act);
|
||||
|
|
|
@ -74,6 +74,7 @@ private:
|
|||
QAction* m_clear_tty_act = nullptr;
|
||||
QAction* m_perform_goto_on_debugger = nullptr;
|
||||
QAction* m_perform_goto_thread_on_debugger = nullptr;
|
||||
QAction* m_perform_show_in_mem_viewer = nullptr;
|
||||
|
||||
QActionGroup* m_log_level_acts = nullptr;
|
||||
QAction* m_nothing_act = nullptr;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Emu/RSX/rsx_utils.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/System.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
|
@ -25,6 +26,7 @@
|
|||
|
||||
#include "util/logs.hpp"
|
||||
#include "util/asm.hpp"
|
||||
#include "debugger_frame.h"
|
||||
|
||||
LOG_CHANNEL(gui_log, "GUI");
|
||||
|
||||
|
@ -589,6 +591,24 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
|||
|
||||
idm::remove_verify<memory_viewer_handle>(id, handle_ptr);
|
||||
});
|
||||
|
||||
if (!g_fxo->try_get<memory_viewer_fxo>())
|
||||
{
|
||||
g_fxo->init<memory_viewer_fxo>();
|
||||
}
|
||||
|
||||
auto& fxo = g_fxo->get<memory_viewer_fxo>();
|
||||
fxo.last_opened[m_type] = this;
|
||||
|
||||
connect(this, &memory_viewer_panel::destroyed, this, [this]()
|
||||
{
|
||||
if (auto fxo = g_fxo->try_get<memory_viewer_fxo>())
|
||||
{
|
||||
auto it = fxo->last_opened.find(m_type);
|
||||
if (it != fxo->last_opened.end() && it->second == this)
|
||||
fxo->last_opened.erase(it);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
memory_viewer_panel::~memory_viewer_panel()
|
||||
|
@ -1244,3 +1264,43 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form
|
|||
f_image_viewer->setFixedSize(f_image_viewer->sizeHint());
|
||||
});
|
||||
}
|
||||
|
||||
void memory_viewer_panel::ShowAtPC(u32 pc, std::function<cpu_thread*()> func)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
return;
|
||||
|
||||
cpu_thread* cpu = func ? func() : nullptr;
|
||||
thread_class type = cpu ? cpu->get_class() : thread_class::ppu;
|
||||
|
||||
if (type == thread_class::spu)
|
||||
{
|
||||
idm::make<memory_viewer_handle>(nullptr, nullptr, pc, std::move(func));
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto* fxo = g_fxo->try_get<memory_viewer_fxo>())
|
||||
{
|
||||
auto it = fxo->last_opened.find(type);
|
||||
|
||||
if (it != fxo->last_opened.end())
|
||||
{
|
||||
memory_viewer_panel* panel = it->second;
|
||||
|
||||
if (panel)
|
||||
{
|
||||
panel->SetPC(pc);
|
||||
panel->scroll(0);
|
||||
|
||||
if (!panel->isVisible())
|
||||
panel->show();
|
||||
|
||||
panel->raise();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idm::make<memory_viewer_handle>(nullptr, nullptr, pc, std::move(func));
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QFontDatabase>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class QLineEdit;
|
||||
class QCheckBox;
|
||||
|
@ -55,6 +56,8 @@ public:
|
|||
memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDisAsm> disasm, u32 addr = 0, std::function<cpu_thread*()> func = []() -> cpu_thread* { return {}; });
|
||||
~memory_viewer_panel();
|
||||
|
||||
static void ShowAtPC(u32 pc, std::function<cpu_thread*()> func = nullptr);
|
||||
|
||||
enum class color_format : int
|
||||
{
|
||||
RGB,
|
||||
|
@ -137,3 +140,12 @@ struct memory_viewer_handle
|
|||
private:
|
||||
const std::add_pointer_t<memory_viewer_panel> m_mvp;
|
||||
};
|
||||
|
||||
struct memory_viewer_fxo
|
||||
{
|
||||
std::map<thread_class, memory_viewer_panel*> last_opened;
|
||||
|
||||
memory_viewer_fxo() = default;
|
||||
memory_viewer_fxo(const memory_viewer_fxo&) = delete;
|
||||
memory_viewer_fxo& operator=(const memory_viewer_fxo&) = delete;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue