diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index e5824330ff..ba0af10b10 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -1730,21 +1730,13 @@ void debugger_frame::RegsShowMemoryViewerAction() } const QTextDocumentFragment frag(cursor); - QString selected = frag.toPlainText().trimmed(); - - int pos = 0; - const HexValidator validator(this); - const QValidator::State st = validator.validate(selected, pos); - if (st != QValidator::Acceptable) + const QString selected = frag.toPlainText().trimmed(); + quint64 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; } - const QString norm = normalize_hex_qstring(selected); - bool ok = false; - const quint64 value = norm.toULongLong(&ok, 16); - const u32 pc = static_cast(value); - - memory_viewer_panel::ShowAtPC(pc); + memory_viewer_panel::ShowAtPC(static_cast(pc)); } diff --git a/rpcs3/rpcs3qt/hex_validator.h b/rpcs3/rpcs3qt/hex_validator.h index 8f2b2fc248..63ada7a17a 100644 --- a/rpcs3/rpcs3qt/hex_validator.h +++ b/rpcs3/rpcs3qt/hex_validator.h @@ -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, quint64* 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 = static_cast(value); + + return ok; +} diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 50ddb13f1c..08d8236ed0 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -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]() + { + QPlainTextEdit* pte = (m_tabWidget->currentIndex() == 1 ? m_tty : m_log); + const QString selected = pte->textCursor().selectedText(); + quint64 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(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 goto_signal_accepted = std::make_shared(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 goto_signal_accepted = std::make_shared(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); diff --git a/rpcs3/rpcs3qt/log_frame.h b/rpcs3/rpcs3qt/log_frame.h index 7909990c27..0de081863c 100644 --- a/rpcs3/rpcs3qt/log_frame.h +++ b/rpcs3/rpcs3qt/log_frame.h @@ -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;