From 31cedb619216515467d29e78bbe09f033c7e8257 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Fri, 16 Jun 2017 20:35:58 +0200 Subject: [PATCH] Reimplement debugger resize & disassembly (#2876) * Reimplement debugger resize fix interrupt * add splitter to disassembly fix debugger regression of last commit fix gotoaddr pos * travis sth sth * add drag & drop to cg_disasm * check for invalid address on set breakpoint reenable debugger controls on Emu.IsReady() * check for valid address more thoroughly --- rpcs3/rpcs3qt/cg_disasm_window.cpp | 113 +++++++++++++++++++++++------ rpcs3/rpcs3qt/cg_disasm_window.h | 23 ++++-- rpcs3/rpcs3qt/debugger_frame.cpp | 104 +++++++++++++++----------- rpcs3/rpcs3qt/debugger_frame.h | 7 +- rpcs3/rpcs3qt/gui_settings.h | 1 + rpcs3/rpcs3qt/main_window.cpp | 3 +- 6 files changed, 173 insertions(+), 78 deletions(-) diff --git a/rpcs3/rpcs3qt/cg_disasm_window.cpp b/rpcs3/rpcs3qt/cg_disasm_window.cpp index f2a35eba69..81f0ffd4a0 100644 --- a/rpcs3/rpcs3qt/cg_disasm_window.cpp +++ b/rpcs3/rpcs3qt/cg_disasm_window.cpp @@ -1,7 +1,8 @@ #include "stdafx.h" #include "cg_disasm_window.h" -#include "Emu/System.h" + +#include #include #include #include @@ -11,51 +12,53 @@ #include #include #include +#include + #include "Emu/RSX/CgBinaryProgram.h" inline QString qstr(const std::string& _in) { return QString::fromUtf8(_in.data(), _in.size()); } inline std::string sstr(const QString& _in) { return _in.toUtf8().toStdString(); } -cg_disasm_window::cg_disasm_window(QWidget* parent): QTabWidget() +cg_disasm_window::cg_disasm_window(std::shared_ptr xSettings, QWidget* parent): QWidget(), xgui_settings(xSettings) { setWindowTitle(tr("Cg Disasm")); setAttribute(Qt::WA_DeleteOnClose); - setMinimumSize(200, 150); // seems fine on win 10 + setAcceptDrops(true); + setMinimumSize(QSize(200, 150)); // seems fine on win 10 resize(QSize(620, 395)); + + m_path_last = xgui_settings->GetValue(GUI::fd_cg_disasm).toString(); - tab_disasm = new QWidget(this); - tab_glsl = new QWidget(this); - addTab(tab_disasm, "ASM"); - addTab(tab_glsl, "GLSL"); - - QVBoxLayout* layout_disasm = new QVBoxLayout(); - m_disasm_text = new QTextEdit(); - m_disasm_text->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_disasm_text = new QTextEdit(this); m_disasm_text->setReadOnly(true); m_disasm_text->setWordWrapMode(QTextOption::NoWrap); m_disasm_text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - layout_disasm->addWidget(m_disasm_text); - tab_disasm->setLayout(layout_disasm); - QVBoxLayout* layout_glsl = new QVBoxLayout(); - m_glsl_text = new QTextEdit(); - m_glsl_text->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_glsl_text = new QTextEdit(this); m_glsl_text->setReadOnly(true); m_glsl_text->setWordWrapMode(QTextOption::NoWrap); m_glsl_text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - layout_glsl->addWidget(m_glsl_text); - tab_glsl->setLayout(layout_glsl); + + QSplitter* splitter = new QSplitter(); + splitter->addWidget(m_disasm_text); + splitter->addWidget(m_glsl_text); + + QHBoxLayout* layout = new QHBoxLayout(); + layout->addWidget(splitter); + + setLayout(layout); m_disasm_text->setContextMenuPolicy(Qt::CustomContextMenu); m_glsl_text->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_disasm_text, &QWidget::customContextMenuRequested, this, &cg_disasm_window::ShowContextMenu); connect(m_glsl_text, &QWidget::customContextMenuRequested, this, &cg_disasm_window::ShowContextMenu); + + ShowDisasm(); } -void cg_disasm_window::ShowContextMenu(const QPoint &pos) // this is a slot +void cg_disasm_window::ShowContextMenu(const QPoint &pos) { QMenu myMenu; - QPoint globalPos = mapToGlobal(pos); QAction* clear = new QAction(tr("&Clear")); QAction* open = new QAction(tr("Open &Cg binary program")); @@ -70,11 +73,73 @@ void cg_disasm_window::ShowContextMenu(const QPoint &pos) // this is a slot if (filePath == NULL) return; m_path_last = QFileInfo(filePath).path(); - CgBinaryDisasm disasm(sstr(filePath)); + ShowDisasm(); + }); + + myMenu.exec(QCursor::pos()); +} + +void cg_disasm_window::ShowDisasm() +{ + if (QFileInfo(m_path_last).isFile()) + { + CgBinaryDisasm disasm(sstr(m_path_last)); disasm.BuildShaderBody(); m_disasm_text->setText(qstr(disasm.GetArbShader())); m_glsl_text->setText(qstr(disasm.GetGlslShader())); - }); - - myMenu.exec(globalPos); + } + else if (!m_path_last.isEmpty()) + { + LOG_ERROR(LOADER, "CgDisasm: Failed to open %s", sstr(m_path_last)); + } +} + +bool cg_disasm_window::IsValidFile(const QMimeData& md, bool save) +{ + for (auto url : md.urls()) + { + for (QString suff : {"fpo", "vpo"}) + { + if (QFileInfo(url.fileName()).suffix().toLower() == suff) + { + if (save) + { + m_path_last = url.toLocalFile(); + xgui_settings->SetValue(GUI::fd_cg_disasm, m_path_last); + } + + return true; + } + } + } + return false; +} + +void cg_disasm_window::dropEvent(QDropEvent* ev) +{ + if (IsValidFile(*ev->mimeData(), true)) + { + ShowDisasm(); + } +} + +void cg_disasm_window::dragEnterEvent(QDragEnterEvent* ev) +{ + if (IsValidFile(*ev->mimeData())) + { + ev->accept(); + } +} + +void cg_disasm_window::dragMoveEvent(QDragMoveEvent* ev) +{ + if (IsValidFile(*ev->mimeData())) + { + ev->accept(); + } +} + +void cg_disasm_window::dragLeaveEvent(QDragLeaveEvent* ev) +{ + ev->accept(); } diff --git a/rpcs3/rpcs3qt/cg_disasm_window.h b/rpcs3/rpcs3qt/cg_disasm_window.h index f6e837314a..f10e1aa2ff 100644 --- a/rpcs3/rpcs3qt/cg_disasm_window.h +++ b/rpcs3/rpcs3qt/cg_disasm_window.h @@ -2,25 +2,38 @@ #define CGDISASMWINDOW_H #include -#include +#include -class cg_disasm_window : public QTabWidget +#include "stdafx.h" +#include "gui_settings.h" + +class cg_disasm_window : public QWidget { Q_OBJECT private slots: void ShowContextMenu(const QPoint &pos); + void ShowDisasm(); + bool IsValidFile(const QMimeData& md, bool save = false); + private: QString m_path_last; QTextEdit* m_disasm_text; QTextEdit* m_glsl_text; - QWidget* tab_disasm; - QWidget* tab_glsl; + QList m_urls; QAction *openCgBinaryProgram; + std::shared_ptr xgui_settings; + public: - explicit cg_disasm_window(QWidget *parent); + explicit cg_disasm_window(std::shared_ptr xSettings, QWidget *parent); + +protected: + void dropEvent(QDropEvent* ev); + void dragEnterEvent(QDragEnterEvent* ev); + void dragMoveEvent(QDragMoveEvent* ev); + void dragLeaveEvent(QDragLeaveEvent* ev); }; #endif // CGDISASMWINDOW_H diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 3e904a9910..f3a513d43c 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -1,5 +1,9 @@ #include "debugger_frame.h" +#include +#include +#include + inline QString qstr(const std::string& _in) { return QString::fromUtf8(_in.data(), _in.size()); } debugger_frame::debugger_frame(QWidget *parent) : QDockWidget(tr("Debugger"), parent) @@ -30,7 +34,7 @@ debugger_frame::debugger_frame(QWidget *parent) : QDockWidget(tr("Debugger"), pa m_btn_run = new QPushButton(tr("Run"), this); m_btn_pause = new QPushButton(tr("Pause"), this); - EnableButtons(Emu.IsRunning() || Emu.IsPaused()); + EnableButtons(!Emu.IsStopped()); hbox_b_main->addWidget(m_go_to_addr); hbox_b_main->addWidget(m_go_to_pc); @@ -48,9 +52,12 @@ debugger_frame::debugger_frame(QWidget *parent) : QDockWidget(tr("Debugger"), pa m_list->setFont(mono); m_regs->setFont(mono); + QSplitter* splitter = new QSplitter(this); + splitter->addWidget(m_list); + splitter->addWidget(m_regs); + QHBoxLayout* hbox_w_list = new QHBoxLayout(); - hbox_w_list->addWidget(m_list); - hbox_w_list->addWidget(m_regs); + hbox_w_list->addWidget(splitter); vbox_p_main->addLayout(hbox_b_main); vbox_p_main->addLayout(hbox_w_list); @@ -190,25 +197,36 @@ void debugger_frame::UpdateUnitList() return; } + QVariant old_cpu = m_choice_units->currentData(); + m_choice_units->clear(); const auto on_select = [&](u32, cpu_thread& cpu) { QVariant var_cpu = qVariantFromValue((void *)&cpu); m_choice_units->addItem(qstr(cpu.get_name()), var_cpu); + if (old_cpu == var_cpu) m_choice_units->setCurrentIndex(m_choice_units->count() - 1); }; - idm::select(on_select); - idm::select(on_select); - idm::select(on_select); - idm::select(on_select); + { + const QSignalBlocker blocker(m_choice_units); + + idm::select(on_select); + idm::select(on_select); + idm::select(on_select); + idm::select(on_select); + } + + OnSelectUnit(); m_choice_units->update(); } void debugger_frame::OnSelectUnit() { - if (m_choice_units->count() < 1) return; + if (m_choice_units->count() < 1 || m_current_choice == m_choice_units->currentText()) return; + + m_current_choice = m_choice_units->currentText(); m_disasm.reset(); @@ -242,38 +260,6 @@ void debugger_frame::OnSelectUnit() DoUpdate(); } -//void debugger_frame::resizeEvent(QResizeEvent* event) -//{ -// if (0) -// { -// if (!m_list->rowCount()) -// { -// m_list->InsertItem(m_list->rowCount(), ""); -// } -// -// int size = 0; -// m_list->clear(); -// int item = 0; -// while (size < m_list->GetSize().GetHeight()) -// { -// item = m_list->rowCount(); -// m_list->InsertItem(item, ""); -// QRect rect; -// m_list->GetItemRect(item, rect); -// -// size = rect.GetBottom(); -// } -// -// if (item) -// { -// m_list->removeRow(--item); -// } -// -// m_item_count = item; -// ShowAddr(m_pc); -// } -//} - void debugger_frame::DoUpdate() { Show_PC(); @@ -360,7 +346,9 @@ void debugger_frame::Show_Val() connect(p_pc, &QLineEdit::textChanged, l_changeLabel); connect(button_ok, &QAbstractButton::clicked, diag, &QDialog::accept); - connect(button_cancel, &QAbstractButton::clicked, diag, &QDialog::reject);; + connect(button_cancel, &QAbstractButton::clicked, diag, &QDialog::reject); + + diag->move(QCursor::pos()); if (diag->exec() == QDialog::Accepted) { @@ -537,7 +525,7 @@ void debugger_list::keyPressEvent(QKeyEvent* event) void debugger_list::mouseDoubleClickEvent(QMouseEvent* event) { - if (event->button() == Qt::LeftButton && (Emu.IsRunning() || Emu.IsPaused())) + if (event->button() == Qt::LeftButton && !Emu.IsStopped()) { long i = currentRow(); if (i < 0) return; @@ -552,7 +540,12 @@ void debugger_list::mouseDoubleClickEvent(QMouseEvent* event) } else { - AddBreakPoint(pc); + const auto cpu = m_debugFrame->cpu.lock(); + + if (g_system == system_type::ps3 && cpu->id_type() == 1 && vm::check_addr(pc)) + { + AddBreakPoint(pc); + } } ShowAddr(start_pc); @@ -566,3 +559,28 @@ void debugger_list::wheelEvent(QWheelEvent* event) ShowAddr(m_pc - (event->modifiers() == Qt::ControlModifier ? m_item_count * (value + 1) : m_item_count + value) * 4); } + +void debugger_list::resizeEvent(QResizeEvent* event) +{ + if (count() < 1 || visualItemRect(item(0)).height() < 1) + { + return; + } + + m_item_count = (rect().height() - frameWidth()*2) / visualItemRect(item(0)).height(); + + clear(); + + for (u32 i = 0; i < m_item_count; ++i) + { + insertItem(i, new QListWidgetItem("")); + } + + if (horizontalScrollBar()) + { + m_item_count--; + delete item(m_item_count); + } + + ShowAddr(m_pc - m_item_count * 4); +} diff --git a/rpcs3/rpcs3qt/debugger_frame.h b/rpcs3/rpcs3qt/debugger_frame.h index c1accb3aaf..3d5a8489be 100644 --- a/rpcs3/rpcs3qt/debugger_frame.h +++ b/rpcs3/rpcs3qt/debugger_frame.h @@ -19,16 +19,12 @@ #include "instruction_editor_dialog.h" #include "register_editor_dialog.h" -#include #include #include #include -#include #include #include #include -#include -#include #include #include @@ -49,6 +45,7 @@ class debugger_frame : public QDockWidget QPushButton* m_btn_run; QPushButton* m_btn_pause; QComboBox* m_choice_units; + QString m_current_choice; u64 m_threads_created = 0; u64 m_threads_deleted = 0; @@ -69,7 +66,6 @@ public: u32 GetPc() const; u32 CentrePc(u32 pc) const; - //void resizeEvent(QResizeEvent* event); void DoUpdate(); void WriteRegs(); void EnableButtons(bool enable); @@ -114,6 +110,7 @@ protected: void keyPressEvent(QKeyEvent* event); void mouseDoubleClickEvent(QMouseEvent* event); void wheelEvent(QWheelEvent* event); + void resizeEvent(QResizeEvent* event); }; #endif // DEBUGGERFRAME_H diff --git a/rpcs3/rpcs3qt/gui_settings.h b/rpcs3/rpcs3qt/gui_settings.h index 865d1d651f..6e01a645ee 100644 --- a/rpcs3/rpcs3qt/gui_settings.h +++ b/rpcs3/rpcs3qt/gui_settings.h @@ -64,6 +64,7 @@ namespace GUI const GUI_SAVE fd_boot_elf = GUI_SAVE( main_window, "lastExplorePathELF", "" ); const GUI_SAVE fd_boot_game = GUI_SAVE( main_window, "lastExplorePathGAME", "" ); const GUI_SAVE fd_decrypt_sprx = GUI_SAVE( main_window, "lastExplorePathSPRX", "" ); + const GUI_SAVE fd_cg_disasm = GUI_SAVE( main_window, "lastExplorePathCGD", "" ); const GUI_SAVE mw_debugger = GUI_SAVE( main_window, "debuggerVisible", false ); const GUI_SAVE mw_logger = GUI_SAVE( main_window, "loggerVisible", true ); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index eb689e0873..f1b46a8817 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -742,6 +742,7 @@ void main_window::OnEmuStop() void main_window::OnEmuReady() { + debuggerFrame->EnableButtons(true); #ifdef _WIN32 thumb_playPause->setToolTip(Emu.IsReady() ? tr("Start") : tr("Resume")); thumb_playPause->setIcon(icon_play); @@ -1162,7 +1163,7 @@ void main_window::CreateConnects() sdid->show(); }); connect(toolsCgDisasmAct, &QAction::triggered, [=](){ - cg_disasm_window* cgdw = new cg_disasm_window(this); + cg_disasm_window* cgdw = new cg_disasm_window(guiSettings, this); cgdw->show(); }); connect(toolskernel_explorerAct, &QAction::triggered, [=](){