summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2023-12-16 21:15:31 +0000
committerGitHub <noreply@github.com>2023-12-16 21:15:31 +0000
commit773ffd04b8ce3695e2676db66ac2a2bf2ba73494 (patch)
tree64d79a5c4e238cee05128e0c61b7e2e4e9ca71bb /Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp
parent190c4e8cda7a78dd7b1ae184425b49d363734c7e (diff)
parentc8c9928eb11cea81808127bae9894fc6cfbac770 (diff)
Merge pull request #11497 from vyuuui/debugger_assembler_ui
Built-in assembler for debugger interface
Diffstat (limited to 'Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp')
-rw-r--r--Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp b/Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp
new file mode 100644
index 0000000000..01d3c91d5d
--- /dev/null
+++ b/Source/Core/DolphinQt/Debugger/AssembleInstructionDialog.cpp
@@ -0,0 +1,131 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "DolphinQt/Debugger/AssembleInstructionDialog.h"
+
+#include <QDialogButtonBox>
+#include <QFontDatabase>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+#include "Common/Assembler/GekkoAssembler.h"
+#include "Common/StringUtil.h"
+
+namespace
+{
+QString HtmlFormatErrorLoc(const Common::GekkoAssembler::AssemblerError& err)
+{
+ const QString error = QStringLiteral("<span style=\"color: red; font-weight: bold\">%1</span>")
+ .arg(QObject::tr("Error"));
+ // i18n: '%1' is the translation of 'Error'
+ return QObject::tr("%1 in column %2").arg(error).arg(err.col + 1);
+}
+
+QString HtmlFormatErrorLine(const Common::GekkoAssembler::AssemblerError& err)
+{
+ const QString line_pre_error =
+ QString::fromStdString(std::string(err.error_line.substr(0, err.col))).toHtmlEscaped();
+ const QString line_error =
+ QString::fromStdString(std::string(err.error_line.substr(err.col, err.len))).toHtmlEscaped();
+ const QString line_post_error =
+ QString::fromStdString(std::string(err.error_line.substr(err.col + err.len))).toHtmlEscaped();
+
+ return QStringLiteral("%1<u><span style=\"color:red; font-weight:bold\">%2</span></u>%3")
+ .arg(line_pre_error)
+ .arg(line_error)
+ .arg(line_post_error);
+}
+} // namespace
+
+AssembleInstructionDialog::AssembleInstructionDialog(QWidget* parent, u32 address, u32 value)
+ : QDialog(parent), m_code(value), m_address(address)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowModality(Qt::WindowModal);
+ setWindowTitle(tr("Instruction"));
+
+ CreateWidgets();
+ ConnectWidgets();
+}
+
+void AssembleInstructionDialog::CreateWidgets()
+{
+ auto* layout = new QVBoxLayout;
+
+ m_input_edit = new QLineEdit;
+ m_error_loc_label = new QLabel;
+ m_error_line_label = new QLabel;
+ m_msg_label = new QLabel(tr("No input"));
+ m_button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ m_error_line_label->setFont(QFont(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()));
+ m_input_edit->setFont(QFont(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()));
+ layout->addWidget(m_error_loc_label);
+ layout->addWidget(m_input_edit);
+ layout->addWidget(m_error_line_label);
+ layout->addWidget(m_msg_label);
+ layout->addWidget(m_button_box);
+ m_input_edit->setText(QStringLiteral(".4byte 0x%1").arg(m_code, 8, 16, QLatin1Char('0')));
+
+ setLayout(layout);
+ OnEditChanged();
+}
+
+void AssembleInstructionDialog::ConnectWidgets()
+{
+ connect(m_button_box, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ connect(m_input_edit, &QLineEdit::textChanged, this, &AssembleInstructionDialog::OnEditChanged);
+}
+
+void AssembleInstructionDialog::OnEditChanged()
+{
+ using namespace Common::GekkoAssembler;
+ std::string line = m_input_edit->text().toStdString();
+ Common::ToLower(&line);
+
+ FailureOr<std::vector<CodeBlock>> asm_result = Assemble(line, m_address);
+
+ if (IsFailure(asm_result))
+ {
+ m_button_box->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+ const AssemblerError& failure = GetFailure(asm_result);
+ m_error_loc_label->setText(HtmlFormatErrorLoc(failure));
+ m_error_line_label->setText(HtmlFormatErrorLine(failure));
+ m_msg_label->setText(QString::fromStdString(failure.message).toHtmlEscaped());
+ }
+ else if (GetT(asm_result).empty() || GetT(asm_result)[0].instructions.empty())
+ {
+ m_button_box->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+ m_error_loc_label->setText(
+ QStringLiteral("<span style=\"color: red; font-weight: bold\">%1</span>").arg(tr("Error")));
+ m_error_line_label->clear();
+ m_msg_label->setText(tr("No input"));
+ }
+ else
+ {
+ m_button_box->button(QDialogButtonBox::Ok)->setEnabled(true);
+ m_code = 0;
+
+ const std::vector<u8>& block_bytes = GetT(asm_result)[0].instructions;
+ for (size_t i = 0; i < 4 && i < block_bytes.size(); i++)
+ {
+ m_code = (m_code << 8) | block_bytes[i];
+ }
+
+ m_error_loc_label->setText(
+ QStringLiteral("<span style=\"color: green; font-weight: bold\">%1</span>").arg(tr("OK")));
+ m_error_line_label->clear();
+ m_msg_label->setText(tr("Instruction: %1").arg(m_code, 8, 16, QLatin1Char('0')));
+ }
+}
+
+u32 AssembleInstructionDialog::GetCode() const
+{
+ return m_code;
+}