2024-07-30 11:42:36 +00:00
|
|
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
|
|
|
// SPDX-License-Identifier: GPL-3.0+
|
2022-12-24 06:51:44 +00:00
|
|
|
|
|
|
|
#include "BreakpointDialog.h"
|
|
|
|
#include "DebugTools/Breakpoints.h"
|
|
|
|
|
|
|
|
#include "QtUtils.h"
|
|
|
|
#include "QtHost.h"
|
|
|
|
#include <QtWidgets/QDialog>
|
|
|
|
#include <QtWidgets/QMessageBox>
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model)
|
2022-12-24 06:51:44 +00:00
|
|
|
: QDialog(parent)
|
|
|
|
, m_cpu(cpu)
|
2023-01-03 05:27:05 +00:00
|
|
|
, m_purpose(PURPOSE::CREATE)
|
|
|
|
, m_bpModel(model)
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
|
|
|
m_ui.setupUi(this);
|
|
|
|
|
|
|
|
m_ui.grpType->setEnabled(true);
|
|
|
|
m_ui.txtAddress->setEnabled(true);
|
|
|
|
|
|
|
|
connect(m_ui.rdoExecute, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
|
|
|
connect(m_ui.rdoMemory, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
|
|
|
}
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model, BreakpointMemcheck bp_mc, int rowIndex)
|
2022-12-24 06:51:44 +00:00
|
|
|
: QDialog(parent)
|
|
|
|
, m_cpu(cpu)
|
2023-01-03 05:27:05 +00:00
|
|
|
, m_purpose(PURPOSE::EDIT)
|
|
|
|
, m_bpModel(model)
|
|
|
|
, m_bp_mc(bp_mc)
|
|
|
|
, m_rowIndex(rowIndex)
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
|
|
|
m_ui.setupUi(this);
|
|
|
|
|
|
|
|
connect(m_ui.rdoExecute, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
|
|
|
connect(m_ui.rdoMemory, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
|
|
|
{
|
|
|
|
m_ui.rdoExecute->setChecked(true);
|
|
|
|
m_ui.chkEnable->setChecked(bp->enabled);
|
|
|
|
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(bp->addr, 16));
|
2022-12-24 06:51:44 +00:00
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
if (bp->hasCond)
|
2024-07-08 01:41:00 +00:00
|
|
|
m_ui.txtCondition->setText(QString::fromStdString(bp->cond.expressionString));
|
2023-01-03 05:27:05 +00:00
|
|
|
}
|
|
|
|
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
|
|
|
{
|
|
|
|
m_ui.rdoMemory->setChecked(true);
|
2022-12-24 06:51:44 +00:00
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(mc->start, 16));
|
|
|
|
m_ui.txtSize->setText(QtUtils::FilledQStringFromValue(mc->end - mc->start, 16));
|
|
|
|
|
2024-07-08 01:41:00 +00:00
|
|
|
m_ui.chkRead->setChecked(mc->memCond & MEMCHECK_READ);
|
|
|
|
m_ui.chkWrite->setChecked(mc->memCond & MEMCHECK_WRITE);
|
|
|
|
m_ui.chkChange->setChecked(mc->memCond & MEMCHECK_WRITE_ONCHANGE);
|
2023-01-03 05:27:05 +00:00
|
|
|
|
|
|
|
m_ui.chkEnable->setChecked(mc->result & MEMCHECK_BREAK);
|
|
|
|
m_ui.chkLog->setChecked(mc->result & MEMCHECK_LOG);
|
2024-07-08 01:41:00 +00:00
|
|
|
|
|
|
|
if (mc->hasCond)
|
|
|
|
m_ui.txtCondition->setText(QString::fromStdString(mc->cond.expressionString));
|
2023-01-03 05:27:05 +00:00
|
|
|
}
|
2022-12-24 06:51:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointDialog::~BreakpointDialog()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointDialog::onRdoButtonToggled()
|
|
|
|
{
|
|
|
|
const bool isExecute = m_ui.rdoExecute->isChecked();
|
|
|
|
|
|
|
|
m_ui.grpMemory->setEnabled(!isExecute);
|
|
|
|
|
|
|
|
m_ui.chkLog->setEnabled(!isExecute);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointDialog::accept()
|
|
|
|
{
|
2023-01-03 05:27:05 +00:00
|
|
|
if (m_purpose == PURPOSE::CREATE)
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
|
|
|
if (m_ui.rdoExecute->isChecked())
|
2023-01-03 05:27:05 +00:00
|
|
|
m_bp_mc = BreakPoint();
|
|
|
|
else if (m_ui.rdoMemory->isChecked())
|
|
|
|
m_bp_mc = MemCheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto* bp = std::get_if<BreakPoint>(&m_bp_mc))
|
|
|
|
{
|
|
|
|
PostfixExpression expr;
|
|
|
|
|
|
|
|
u64 address;
|
|
|
|
if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit().constData(), expr) ||
|
|
|
|
!m_cpu->parseExpression(expr, address))
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
2023-01-03 05:27:05 +00:00
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text()));
|
|
|
|
return;
|
2022-12-24 06:51:44 +00:00
|
|
|
}
|
2023-01-03 05:27:05 +00:00
|
|
|
|
2023-01-13 02:41:16 +00:00
|
|
|
bp->addr = address;
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
bp->enabled = m_ui.chkEnable->isChecked();
|
|
|
|
|
|
|
|
if (!m_ui.txtCondition->text().isEmpty())
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
2023-01-03 05:27:05 +00:00
|
|
|
bp->hasCond = true;
|
2023-01-13 02:41:16 +00:00
|
|
|
bp->cond.debug = m_cpu;
|
2022-12-24 06:51:44 +00:00
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
if (!m_cpu->initExpression(m_ui.txtCondition->text().toLocal8Bit().constData(), expr))
|
|
|
|
{
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(getExpressionError()));
|
|
|
|
return;
|
|
|
|
}
|
2022-12-24 06:51:44 +00:00
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
bp->cond.expression = expr;
|
2024-07-08 01:41:00 +00:00
|
|
|
bp->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
2023-01-03 05:27:05 +00:00
|
|
|
}
|
2022-12-24 06:51:44 +00:00
|
|
|
}
|
2023-01-03 05:27:05 +00:00
|
|
|
if (auto* mc = std::get_if<MemCheck>(&m_bp_mc))
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
2023-01-03 05:27:05 +00:00
|
|
|
PostfixExpression expr;
|
|
|
|
|
|
|
|
u64 startAddress;
|
|
|
|
if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit().constData(), expr) ||
|
|
|
|
!m_cpu->parseExpression(expr, startAddress))
|
|
|
|
{
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 size;
|
|
|
|
if (!m_cpu->initExpression(m_ui.txtSize->text().toLocal8Bit(), expr) ||
|
|
|
|
!m_cpu->parseExpression(expr, size) || !size)
|
2022-12-24 06:51:44 +00:00
|
|
|
{
|
2022-12-24 11:17:52 +00:00
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Invalid size \"%1\"").arg(m_ui.txtSize->text()));
|
2022-12-24 06:51:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
mc->start = startAddress;
|
|
|
|
mc->end = startAddress + size;
|
2022-12-24 06:51:44 +00:00
|
|
|
|
2024-07-08 01:41:00 +00:00
|
|
|
if (!m_ui.txtCondition->text().isEmpty())
|
|
|
|
{
|
|
|
|
mc->hasCond = true;
|
|
|
|
mc->cond.debug = m_cpu;
|
|
|
|
|
|
|
|
if (!m_cpu->initExpression(m_ui.txtCondition->text().toLocal8Bit().constData(), expr))
|
|
|
|
{
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(getExpressionError()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mc->cond.expression = expr;
|
|
|
|
mc->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
|
|
|
}
|
|
|
|
|
2022-12-24 06:51:44 +00:00
|
|
|
int condition = 0;
|
|
|
|
if (m_ui.chkRead->isChecked())
|
|
|
|
condition |= MEMCHECK_READ;
|
|
|
|
if (m_ui.chkWrite->isChecked())
|
|
|
|
condition |= MEMCHECK_WRITE;
|
|
|
|
if (m_ui.chkChange->isChecked())
|
|
|
|
condition |= MEMCHECK_WRITE_ONCHANGE;
|
|
|
|
|
2024-07-08 01:41:00 +00:00
|
|
|
mc->memCond = static_cast<MemCheckCondition>(condition);
|
2023-01-03 05:27:05 +00:00
|
|
|
|
2022-12-24 06:51:44 +00:00
|
|
|
int result = 0;
|
|
|
|
if (m_ui.chkEnable->isChecked())
|
|
|
|
result |= MEMCHECK_BREAK;
|
|
|
|
if (m_ui.chkLog->isChecked())
|
|
|
|
result |= MEMCHECK_LOG;
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
mc->result = static_cast<MemCheckResult>(result);
|
2022-12-24 06:51:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-03 05:27:05 +00:00
|
|
|
if (m_purpose == PURPOSE::EDIT)
|
|
|
|
{
|
|
|
|
m_bpModel.removeRows(m_rowIndex, 1);
|
2022-12-24 06:51:44 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 09:15:55 +00:00
|
|
|
m_bpModel.insertBreakpointRows(0, 1, {m_bp_mc});
|
2023-01-03 05:27:05 +00:00
|
|
|
|
2022-12-24 06:51:44 +00:00
|
|
|
QDialog::accept();
|
|
|
|
}
|