mirror of https://github.com/PCSX2/pcsx2.git
Debugger Breakpoints: (Refactor) Use some reflection and item models
This commit is contained in:
parent
8fca67f0d6
commit
37540d1c68
|
@ -134,6 +134,8 @@ target_sources(pcsx2-qt PRIVATE
|
|||
Debugger/BreakpointDialog.cpp
|
||||
Debugger/BreakpointDialog.h
|
||||
Debugger/BreakpointDialog.ui
|
||||
Debugger/Models/BreakpointModel.cpp
|
||||
Debugger/Models/BreakpointModel.h
|
||||
Tools/InputRecording/NewInputRecordingDlg.cpp
|
||||
Tools/InputRecording/NewInputRecordingDlg.h
|
||||
Tools/InputRecording/NewInputRecordingDlg.ui
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu)
|
||||
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model)
|
||||
: QDialog(parent)
|
||||
, m_cpu(cpu)
|
||||
, m_purpose(BPDIALOG_PURPOSE::CREATE)
|
||||
, m_purpose(PURPOSE::CREATE)
|
||||
, m_bpModel(model)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
|
@ -37,43 +38,42 @@ BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu)
|
|||
connect(m_ui.rdoMemory, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
||||
}
|
||||
|
||||
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakPoint* bp)
|
||||
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model, BreakpointMemcheck bp_mc, int rowIndex)
|
||||
: QDialog(parent)
|
||||
, m_cpu(cpu)
|
||||
, m_purpose(BPDIALOG_PURPOSE::EDIT_BP)
|
||||
, m_bp(bp)
|
||||
, m_purpose(PURPOSE::EDIT)
|
||||
, m_bpModel(model)
|
||||
, m_bp_mc(bp_mc)
|
||||
, m_rowIndex(rowIndex)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(m_bp->addr, 16));
|
||||
if (m_bp->hasCond)
|
||||
m_ui.txtCondition->setText(QString::fromLocal8Bit(&m_bp->cond.expressionString[0]));
|
||||
m_ui.chkEnable->setChecked(m_bp->enabled);
|
||||
|
||||
connect(m_ui.rdoExecute, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
||||
connect(m_ui.rdoMemory, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
||||
m_ui.rdoExecute->toggle();
|
||||
}
|
||||
|
||||
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, MemCheck* mc)
|
||||
: QDialog(parent)
|
||||
, m_cpu(cpu)
|
||||
, m_purpose(BPDIALOG_PURPOSE::EDIT_MC)
|
||||
, m_mc(mc)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
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));
|
||||
|
||||
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(m_mc->start, 16));
|
||||
m_ui.txtSize->setText(QString::number(m_mc->end - m_mc->start, 16).toUpper());
|
||||
m_ui.chkLog->setChecked(m_mc->result & MEMCHECK_LOG);
|
||||
m_ui.chkEnable->setChecked(m_mc->result & MEMCHECK_BREAK);
|
||||
m_ui.chkChange->setChecked(m_mc->cond & MEMCHECK_WRITE_ONCHANGE);
|
||||
m_ui.chkRead->setChecked(m_mc->cond & MEMCHECK_READ);
|
||||
m_ui.chkWrite->setChecked(m_mc->cond & MEMCHECK_WRITE);
|
||||
if (bp->hasCond)
|
||||
m_ui.txtCondition->setText(QString::fromLocal8Bit(bp->cond.expressionString));
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
m_ui.rdoMemory->setChecked(true);
|
||||
|
||||
connect(m_ui.rdoExecute, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
||||
connect(m_ui.rdoMemory, &QRadioButton::toggled, this, &BreakpointDialog::onRdoButtonToggled);
|
||||
m_ui.rdoMemory->toggle();
|
||||
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(mc->start, 16));
|
||||
m_ui.txtSize->setText(QtUtils::FilledQStringFromValue(mc->end - mc->start, 16));
|
||||
|
||||
m_ui.chkRead->setChecked(mc->cond & MEMCHECK_READ);
|
||||
m_ui.chkWrite->setChecked(mc->cond & MEMCHECK_WRITE);
|
||||
m_ui.chkChange->setChecked(mc->cond & MEMCHECK_WRITE_ONCHANGE);
|
||||
|
||||
m_ui.chkEnable->setChecked(mc->result & MEMCHECK_BREAK);
|
||||
m_ui.chkLog->setChecked(mc->result & MEMCHECK_LOG);
|
||||
}
|
||||
}
|
||||
|
||||
BreakpointDialog::~BreakpointDialog()
|
||||
|
@ -90,48 +90,67 @@ void BreakpointDialog::onRdoButtonToggled()
|
|||
m_ui.chkLog->setEnabled(!isExecute);
|
||||
}
|
||||
|
||||
// When we are creating a breakpoint, use m_bp or m_mc only as a place to store information for the new breakpoint
|
||||
// When we are modifying a breakpoint, m_bp or m_mc is a pointer to the breakpoint we are updating
|
||||
void BreakpointDialog::accept()
|
||||
{
|
||||
if (m_purpose == BPDIALOG_PURPOSE::CREATE)
|
||||
if (m_purpose == PURPOSE::CREATE)
|
||||
{
|
||||
if (m_ui.rdoExecute->isChecked())
|
||||
{
|
||||
m_bp = new BreakPoint;
|
||||
m_bp->cpu = m_cpu->getCpuType();
|
||||
m_bp->cond.debug = m_cpu;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mc = new MemCheck;
|
||||
m_mc->cpu = m_cpu->getCpuType();
|
||||
}
|
||||
m_bp_mc = BreakPoint();
|
||||
else if (m_ui.rdoMemory->isChecked())
|
||||
m_bp_mc = MemCheck();
|
||||
}
|
||||
|
||||
PostfixExpression expression;
|
||||
|
||||
// Validate the address
|
||||
u64 address;
|
||||
if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit(), expression) || !m_cpu->parseExpression(expression, address))
|
||||
if (auto* bp = std::get_if<BreakPoint>(&m_bp_mc))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text()));
|
||||
return;
|
||||
PostfixExpression expr;
|
||||
|
||||
u64 address;
|
||||
if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit().constData(), expr) ||
|
||||
!m_cpu->parseExpression(expr, address))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text()));
|
||||
return;
|
||||
}
|
||||
|
||||
bp->enabled = m_ui.chkEnable->isChecked();
|
||||
|
||||
if (!m_ui.txtCondition->text().isEmpty())
|
||||
{
|
||||
bp->hasCond = true;
|
||||
|
||||
if (!m_cpu->initExpression(m_ui.txtCondition->text().toLocal8Bit().constData(), expr))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(getExpressionError()));
|
||||
return;
|
||||
}
|
||||
|
||||
bp->cond.expression = expr;
|
||||
strncpy(&bp->cond.expressionString[0], m_ui.txtCondition->text().toLocal8Bit().constData(),
|
||||
sizeof(bp->cond.expressionString));
|
||||
}
|
||||
}
|
||||
|
||||
u64 size;
|
||||
if (m_ui.rdoMemory->isChecked())
|
||||
if (auto* mc = std::get_if<MemCheck>(&m_bp_mc))
|
||||
{
|
||||
if (!m_cpu->initExpression(m_ui.txtSize->text().toLocal8Bit(), expression) || !m_cpu->parseExpression(expression, size) || !size)
|
||||
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)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid size \"%1\"").arg(m_ui.txtSize->text()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_mc->start = address;
|
||||
const bool changedSize = m_mc->end != (m_mc->start + size);
|
||||
const u32 prevEnd = m_mc->end;
|
||||
m_mc->end = m_mc->start + size;
|
||||
mc->start = startAddress;
|
||||
mc->end = startAddress + size;
|
||||
|
||||
int condition = 0;
|
||||
if (m_ui.chkRead->isChecked())
|
||||
|
@ -141,68 +160,24 @@ void BreakpointDialog::accept()
|
|||
if (m_ui.chkChange->isChecked())
|
||||
condition |= MEMCHECK_WRITE_ONCHANGE;
|
||||
|
||||
mc->cond = static_cast<MemCheckCondition>(condition);
|
||||
|
||||
int result = 0;
|
||||
if (m_ui.chkEnable->isChecked())
|
||||
result |= MEMCHECK_BREAK;
|
||||
if (m_ui.chkLog->isChecked())
|
||||
result |= MEMCHECK_LOG;
|
||||
|
||||
if (m_purpose == BPDIALOG_PURPOSE::CREATE)
|
||||
{
|
||||
Host::RunOnCPUThread([this, condition, result] {
|
||||
CBreakPoints::AddMemCheck(m_cpu->getCpuType(), m_mc->start, m_mc->end, (MemCheckCondition)condition, (MemCheckResult)result);
|
||||
delete m_mc;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::RunOnCPUThread([this, mc = *m_mc, condition, result, prevEnd, changedSize] {
|
||||
if (changedSize)
|
||||
{
|
||||
CBreakPoints::RemoveMemCheck(m_cpu->getCpuType(), mc.start, prevEnd);
|
||||
CBreakPoints::AddMemCheck(m_cpu->getCpuType(), mc.start, mc.end, static_cast<MemCheckCondition>(condition), static_cast<MemCheckResult>(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
CBreakPoints::ChangeMemCheck(m_cpu->getCpuType(), mc.start, mc.end, static_cast<MemCheckCondition>(condition), static_cast<MemCheckResult>(result));
|
||||
}
|
||||
});
|
||||
}
|
||||
mc->result = static_cast<MemCheckResult>(result);
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
if (m_purpose == PURPOSE::EDIT)
|
||||
{
|
||||
if (m_purpose == BPDIALOG_PURPOSE::CREATE)
|
||||
Host::RunOnCPUThread([this, address] {
|
||||
CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), address);
|
||||
});
|
||||
|
||||
// Validate the condition
|
||||
// TODO: Expression management in the core should be updated to make this prettier
|
||||
if (!m_ui.txtCondition->text().isEmpty())
|
||||
{
|
||||
auto strData = m_ui.txtCondition->text().toLocal8Bit();
|
||||
expression.clear();
|
||||
if (!m_cpu->initExpression(strData.constData(), expression))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(strData));
|
||||
return;
|
||||
}
|
||||
|
||||
m_bp->cond.expression = expression;
|
||||
strncpy(&m_bp->cond.expressionString[0], strData.constData(), sizeof(m_bp->cond.expressionString));
|
||||
|
||||
Host::RunOnCPUThread([this, address] {
|
||||
CBreakPoints::ChangeBreakPointAddCond(m_cpu->getCpuType(), address, m_bp->cond);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::RunOnCPUThread([this, address] { CBreakPoints::ChangeBreakPointRemoveCond(m_cpu->getCpuType(), address); });
|
||||
}
|
||||
|
||||
Host::RunOnCPUThread([this, address] { CBreakPoints::ChangeBreakPoint(m_cpu->getCpuType(), address, m_ui.chkEnable->isChecked()); });
|
||||
m_bp->addr = address;
|
||||
m_bpModel.removeRows(m_rowIndex, 1);
|
||||
}
|
||||
|
||||
m_bpModel.insertRows(0, 1, {m_bp_mc});
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
|
||||
#include "Models/BreakpointModel.h"
|
||||
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
class BreakpointDialog final : public QDialog
|
||||
|
@ -26,28 +28,26 @@ class BreakpointDialog final : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BreakpointDialog(QWidget* parent, DebugInterface* cpu);
|
||||
BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakPoint* bp);
|
||||
BreakpointDialog(QWidget* parent, DebugInterface* cpu, MemCheck* mc);
|
||||
BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model);
|
||||
BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model, BreakpointMemcheck bpmc, int rowIndex);
|
||||
~BreakpointDialog();
|
||||
|
||||
|
||||
public slots:
|
||||
void onRdoButtonToggled();
|
||||
void accept() override;
|
||||
|
||||
private:
|
||||
enum class BPDIALOG_PURPOSE
|
||||
enum class PURPOSE
|
||||
{
|
||||
CREATE,
|
||||
EDIT_BP,
|
||||
EDIT_MC
|
||||
EDIT
|
||||
};
|
||||
|
||||
Ui::BreakpointDialog m_ui;
|
||||
DebugInterface* m_cpu;
|
||||
|
||||
const BPDIALOG_PURPOSE m_purpose;
|
||||
BreakPoint* m_bp = nullptr;
|
||||
MemCheck* m_mc = nullptr;
|
||||
};
|
||||
const PURPOSE m_purpose;
|
||||
BreakpointModel& m_bpModel;
|
||||
BreakpointMemcheck m_bp_mc;
|
||||
int m_rowIndex;
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "DisassemblyWidget.h"
|
||||
#include "BreakpointDialog.h"
|
||||
#include "Models/BreakpointModel.h"
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
|
@ -27,7 +28,6 @@
|
|||
#include "common/BitCast.h"
|
||||
|
||||
#include "QtUtils.h"
|
||||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
@ -40,6 +40,7 @@ using namespace MipsStackWalk;
|
|||
|
||||
CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
||||
: m_cpu(cpu)
|
||||
, m_bpModel(cpu)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
|
@ -55,9 +56,10 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
|||
connect(m_ui.registerWidget, &RegisterWidget::VMUpdate, this, &CpuWidget::reloadCPUWidgets);
|
||||
connect(m_ui.disassemblyWidget, &DisassemblyWidget::VMUpdate, this, &CpuWidget::reloadCPUWidgets);
|
||||
|
||||
connect(m_ui.tabWidget, &QTabWidget::currentChanged, [this] { fixBPListColumnSize(); });
|
||||
connect(m_ui.breakpointList, &QTableWidget::customContextMenuRequested, this, &CpuWidget::onBPListContextMenu);
|
||||
connect(m_ui.breakpointList, &QTableWidget::itemChanged, this, &CpuWidget::onBPListItemChange);
|
||||
connect(m_ui.breakpointList, &QTableView::customContextMenuRequested, this, &CpuWidget::onBPListContextMenu);
|
||||
connect(m_ui.breakpointList, &QTableView::doubleClicked, this, &CpuWidget::onBPListDoubleClicked);
|
||||
|
||||
m_ui.breakpointList->setModel(&m_bpModel);
|
||||
|
||||
connect(m_ui.threadList, &QTableWidget::customContextMenuRequested, this, &CpuWidget::onThreadListContextMenu);
|
||||
connect(m_ui.threadList, &QTableWidget::cellDoubleClicked, this, &CpuWidget::onThreadListDoubleClick);
|
||||
|
@ -86,9 +88,6 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
|||
m_ui.registerWidget->SetCpu(&cpu);
|
||||
m_ui.memoryviewWidget->SetCpu(&cpu);
|
||||
|
||||
if (m_cpu.getCpuType() == BREAKPOINT_EE)
|
||||
CBreakPoints::SetUpdateHandler(std::bind(&CpuWidget::reloadCPUWidgets, this));
|
||||
|
||||
this->repaint();
|
||||
}
|
||||
|
||||
|
@ -101,11 +100,6 @@ void CpuWidget::paintEvent(QPaintEvent* event)
|
|||
m_ui.memoryviewWidget->update();
|
||||
}
|
||||
|
||||
void CpuWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
fixBPListColumnSize();
|
||||
}
|
||||
|
||||
// The cpu shouldn't be alive when these are called
|
||||
// But make sure it isn't just in case
|
||||
void CpuWidget::onStepInto()
|
||||
|
@ -234,145 +228,18 @@ void CpuWidget::onVMPaused()
|
|||
|
||||
void CpuWidget::updateBreakpoints()
|
||||
{
|
||||
m_ui.breakpointList->blockSignals(true);
|
||||
|
||||
m_ui.breakpointList->setRowCount(0);
|
||||
m_bplistObjects.clear();
|
||||
|
||||
int iter = 0;
|
||||
for (const auto& breakpoint : CBreakPoints::GetBreakpoints())
|
||||
{
|
||||
if (breakpoint.cpu != m_cpu.getCpuType())
|
||||
continue;
|
||||
|
||||
if (breakpoint.temporary)
|
||||
continue;
|
||||
|
||||
m_ui.breakpointList->insertRow(iter);
|
||||
BreakpointObject obj;
|
||||
obj.bp = std::make_shared<BreakPoint>(breakpoint);
|
||||
m_bplistObjects.push_back(obj);
|
||||
|
||||
// Type (R/O)
|
||||
QTableWidgetItem* typeItem = new QTableWidgetItem();
|
||||
typeItem->setText(tr("Execute"));
|
||||
typeItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 0, typeItem);
|
||||
|
||||
// Offset (R/O), possibly allow changing offset???
|
||||
QTableWidgetItem* offsetItem = new QTableWidgetItem();
|
||||
offsetItem->setText(FilledQStringFromValue(breakpoint.addr, 16));
|
||||
offsetItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 1, offsetItem);
|
||||
|
||||
// Size & Label (R/O)
|
||||
QTableWidgetItem* sizeLabelItem = new QTableWidgetItem();
|
||||
sizeLabelItem->setText(m_cpu.GetSymbolMap().GetLabelString(breakpoint.addr).c_str());
|
||||
sizeLabelItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 2, sizeLabelItem);
|
||||
|
||||
// Opcode (R/O)
|
||||
QTableWidgetItem* opcodeItem = new QTableWidgetItem();
|
||||
opcodeItem->setText(m_ui.disassemblyWidget->GetLineDisasm(breakpoint.addr));
|
||||
opcodeItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 3, opcodeItem);
|
||||
|
||||
// Condition (R/W)
|
||||
QTableWidgetItem* conditionItem = new QTableWidgetItem();
|
||||
conditionItem->setText(breakpoint.hasCond ? QString::fromLocal8Bit(breakpoint.cond.expressionString) : "");
|
||||
conditionItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEditable);
|
||||
m_ui.breakpointList->setItem(iter, 4, conditionItem);
|
||||
|
||||
// Hits (R/O) (Disabled for execute bp)
|
||||
QTableWidgetItem* hitsItem = new QTableWidgetItem();
|
||||
hitsItem->setText("N/A");
|
||||
hitsItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 5, hitsItem);
|
||||
|
||||
// Enabled (R/W)
|
||||
QTableWidgetItem* enabledItem = new QTableWidgetItem();
|
||||
enabledItem->setCheckState(breakpoint.enabled ? Qt::Checked : Qt::Unchecked);
|
||||
enabledItem->setFlags(Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEnabled);
|
||||
m_ui.breakpointList->setItem(iter, 6, enabledItem);
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
for (const auto& memcheck : CBreakPoints::GetMemChecks())
|
||||
{
|
||||
if (memcheck.cpu != m_cpu.getCpuType())
|
||||
continue;
|
||||
|
||||
m_ui.breakpointList->insertRow(iter);
|
||||
BreakpointObject obj;
|
||||
obj.mc = std::make_shared<MemCheck>(memcheck);
|
||||
m_bplistObjects.push_back(obj);
|
||||
|
||||
// Type (R/O)
|
||||
QTableWidgetItem* typeItem = new QTableWidgetItem();
|
||||
QString type("");
|
||||
type += (memcheck.cond & MEMCHECK_READ) ? tr("Read") : "";
|
||||
type += ((memcheck.cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
|
||||
type += (memcheck.cond & MEMCHECK_WRITE) ? (memcheck.cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
|
||||
typeItem->setText(type);
|
||||
typeItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 0, typeItem);
|
||||
|
||||
// Offset (R/O), possibly allow changing offset?
|
||||
QTableWidgetItem* offsetItem = new QTableWidgetItem();
|
||||
offsetItem->setText(FilledQStringFromValue(memcheck.start, 16));
|
||||
offsetItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 1, offsetItem);
|
||||
|
||||
// Size & Label (R/O)
|
||||
QTableWidgetItem* sizeLabelItem = new QTableWidgetItem();
|
||||
sizeLabelItem->setText(QString::number(memcheck.end - memcheck.start, 16));
|
||||
sizeLabelItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEditable);
|
||||
m_ui.breakpointList->setItem(iter, 2, sizeLabelItem);
|
||||
|
||||
// Opcode (R/O)
|
||||
QTableWidgetItem* opcodeItem = new QTableWidgetItem();
|
||||
opcodeItem->setText(m_ui.disassemblyWidget->GetLineDisasm(memcheck.start));
|
||||
opcodeItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 3, opcodeItem);
|
||||
|
||||
// Condition (R/W) (Disabled for memchecks)
|
||||
QTableWidgetItem* conditionItem = new QTableWidgetItem();
|
||||
conditionItem->setText("N/A");
|
||||
conditionItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 4, conditionItem);
|
||||
|
||||
|
||||
// Hits (R/O)
|
||||
QTableWidgetItem* hitsItem = new QTableWidgetItem();
|
||||
hitsItem->setText(QString::number(memcheck.numHits));
|
||||
hitsItem->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable);
|
||||
m_ui.breakpointList->setItem(iter, 5, hitsItem);
|
||||
|
||||
// Enabled (R/W)
|
||||
QTableWidgetItem* enabledItem = new QTableWidgetItem();
|
||||
enabledItem->setCheckState((memcheck.result & MEMCHECK_BREAK) ? Qt::Checked : Qt::Unchecked);
|
||||
enabledItem->setFlags(Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEnabled);
|
||||
m_ui.breakpointList->setItem(iter, 6, enabledItem);
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
m_ui.breakpointList->blockSignals(false);
|
||||
m_bpModel.refreshData();
|
||||
}
|
||||
|
||||
void CpuWidget::fixBPListColumnSize()
|
||||
void CpuWidget::onBPListDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(0, 90);
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(1, 65);
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(5, 40);
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(6, 60);
|
||||
|
||||
constexpr int currentWidthTotal = 90 + 65 + 40 + 60;
|
||||
const int sectionWidth = (m_ui.breakpointList->width() - currentWidthTotal) / 3.0f;
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(2, sectionWidth);
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(3, sectionWidth);
|
||||
m_ui.breakpointList->horizontalHeader()->resizeSection(4, sectionWidth);
|
||||
if (index.isValid())
|
||||
{
|
||||
if (index.column() == BreakpointModel::OFFSET)
|
||||
{
|
||||
m_ui.disassemblyWidget->gotoAddress(m_bpModel.data(index).toString().toUInt(nullptr, 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWidget::onBPListContextMenu(QPoint pos)
|
||||
|
@ -397,8 +264,6 @@ void CpuWidget::onBPListContextMenu(QPoint pos)
|
|||
connect(editAction, &QAction::triggered, this, &CpuWidget::contextBPListEdit);
|
||||
m_bplistContextMenu->addAction(editAction);
|
||||
|
||||
// Only copy when one column is selected
|
||||
// Shouldn't be trivial to support cross column copy
|
||||
if (selModel->selectedIndexes().count() == 1)
|
||||
{
|
||||
QAction* copyAction = new QAction(tr("Copy"), m_ui.breakpointList);
|
||||
|
@ -414,81 +279,6 @@ void CpuWidget::onBPListContextMenu(QPoint pos)
|
|||
m_bplistContextMenu->popup(m_ui.breakpointList->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void CpuWidget::onBPListItemChange(QTableWidgetItem* item)
|
||||
{
|
||||
if (item->column() == 2 && m_bplistObjects.at(item->row()).mc) // Size / Label column. Size is editable for memchecks
|
||||
{
|
||||
const auto& mc = m_bplistObjects.at(item->row()).mc;
|
||||
|
||||
bool ok;
|
||||
u32 val = item->text().toUInt(&ok, 16);
|
||||
if (!ok)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid size \"%1\"").arg(item->text()));
|
||||
item->setText(QString::number((mc->end - mc->start), 16));
|
||||
return;
|
||||
}
|
||||
|
||||
if (val == (mc->end - mc->start))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Host::RunOnCPUThread([this, val, mc] {
|
||||
CBreakPoints::RemoveMemCheck(m_cpu.getCpuType(), mc->start, mc->end);
|
||||
|
||||
CBreakPoints::AddMemCheck(m_cpu.getCpuType(), mc->start, mc->start + val, mc->cond, mc->result);
|
||||
});
|
||||
updateBreakpoints();
|
||||
}
|
||||
else if (item->column() == 4 && m_bplistObjects.at(item->row()).bp) // Condition column. Only editable for breakpoints
|
||||
{
|
||||
const auto& bp = m_bplistObjects.at(item->row()).bp;
|
||||
|
||||
if (item->text().isEmpty() && bp->hasCond)
|
||||
{
|
||||
Host::RunOnCPUThread([this, bp] {
|
||||
CBreakPoints::ChangeBreakPointRemoveCond(m_cpu.getCpuType(), bp->addr);
|
||||
});
|
||||
|
||||
updateBreakpoints();
|
||||
}
|
||||
else if (item->text() != QString::fromLocal8Bit(&bp->cond.expressionString[0]))
|
||||
{
|
||||
PostfixExpression expression;
|
||||
|
||||
if (!m_cpu.initExpression(item->text().toLocal8Bit().constData(), expression))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(item->text()));
|
||||
item->setText(QString::fromLocal8Bit(&bp->cond.expressionString[0]));
|
||||
return;
|
||||
}
|
||||
BreakPointCond cond;
|
||||
cond.debug = &m_cpu;
|
||||
cond.expression = expression;
|
||||
strcpy(&cond.expressionString[0], item->text().toLocal8Bit().constData());
|
||||
Host::RunOnCPUThread([this, bp, cond] {
|
||||
CBreakPoints::ChangeBreakPointAddCond(m_cpu.getCpuType(), bp->addr, cond);
|
||||
});
|
||||
updateBreakpoints();
|
||||
}
|
||||
}
|
||||
else if (item->column() == 6)
|
||||
{
|
||||
auto bpmc = m_bplistObjects.at(item->row());
|
||||
|
||||
Host::RunOnCPUThread([this, bpmc, checked = item->checkState()] {
|
||||
if (bpmc.bp)
|
||||
{
|
||||
CBreakPoints::ChangeBreakPoint(m_cpu.getCpuType(), bpmc.bp->addr, checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBreakPoints::ChangeMemCheck(m_cpu.getCpuType(), bpmc.mc->start, bpmc.mc->end, bpmc.mc->cond, MemCheckResult(bpmc.mc->result ^ MEMCHECK_BREAK));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWidget::contextBPListCopy()
|
||||
{
|
||||
const QItemSelectionModel* selModel = m_ui.breakpointList->selectionModel();
|
||||
|
@ -496,7 +286,7 @@ void CpuWidget::contextBPListCopy()
|
|||
if (!selModel->hasSelection())
|
||||
return;
|
||||
|
||||
QGuiApplication::clipboard()->setText(m_ui.breakpointList->selectedItems().first()->text());
|
||||
QGuiApplication::clipboard()->setText(m_bpModel.data(selModel->currentIndex()).toString());
|
||||
}
|
||||
|
||||
void CpuWidget::contextBPListDelete()
|
||||
|
@ -506,34 +296,21 @@ void CpuWidget::contextBPListDelete()
|
|||
if (!selModel->hasSelection())
|
||||
return;
|
||||
|
||||
int last_row = -1;
|
||||
for (auto& index : selModel->selectedIndexes())
|
||||
QModelIndexList rows = selModel->selectedIndexes();
|
||||
|
||||
std::sort(rows.begin(), rows.end(), [](const QModelIndex& a, const QModelIndex& b) {
|
||||
return a.row() > b.row();
|
||||
});
|
||||
|
||||
for (const QModelIndex& index : rows)
|
||||
{
|
||||
if (index.row() == last_row) // If the next index is in the same row, don't delete that breakpoint twice!
|
||||
continue;
|
||||
auto& bpObject = m_bplistObjects.at(index.row());
|
||||
|
||||
Host::RunOnCPUThread([&] {
|
||||
if (bpObject.bp)
|
||||
{
|
||||
CBreakPoints::RemoveBreakPoint(m_cpu.getCpuType(), bpObject.bp->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBreakPoints::RemoveMemCheck(m_cpu.getCpuType(), bpObject.mc->start, bpObject.mc->end);
|
||||
}
|
||||
});
|
||||
|
||||
last_row = index.row();
|
||||
m_bpModel.removeRows(index.row(), 1);
|
||||
}
|
||||
updateBreakpoints();
|
||||
}
|
||||
|
||||
void CpuWidget::contextBPListNew()
|
||||
{
|
||||
BreakpointDialog* bpDialog = new BreakpointDialog(this, &m_cpu);
|
||||
connect(bpDialog, &BreakpointDialog::accepted, this, &CpuWidget::updateBreakpoints);
|
||||
|
||||
BreakpointDialog* bpDialog = new BreakpointDialog(this, &m_cpu, m_bpModel);
|
||||
bpDialog->show();
|
||||
}
|
||||
|
||||
|
@ -544,20 +321,11 @@ void CpuWidget::contextBPListEdit()
|
|||
if (!selModel->hasSelection())
|
||||
return;
|
||||
|
||||
auto& bpObject = m_bplistObjects.at(selModel->selectedIndexes().first().row());
|
||||
const int selectedRow = selModel->selectedIndexes().first().row();
|
||||
|
||||
BreakpointDialog* bpDialog;
|
||||
auto bpObject = m_bpModel.at(selectedRow);
|
||||
|
||||
if (bpObject.bp)
|
||||
{
|
||||
bpDialog = new BreakpointDialog(this, &m_cpu, bpObject.bp.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
bpDialog = new BreakpointDialog(this, &m_cpu, bpObject.mc.get());
|
||||
}
|
||||
|
||||
connect(bpDialog, &BreakpointDialog::accepted, this, &CpuWidget::updateBreakpoints);
|
||||
BreakpointDialog* bpDialog = new BreakpointDialog(this, &m_cpu, m_bpModel, bpObject, selectedRow);
|
||||
bpDialog->show();
|
||||
}
|
||||
|
||||
|
@ -566,6 +334,8 @@ void CpuWidget::updateFunctionList(bool whenEmpty)
|
|||
if (!m_cpu.isAlive())
|
||||
return;
|
||||
|
||||
m_bpModel.refreshData();
|
||||
|
||||
if (whenEmpty && m_ui.listFunctions->count())
|
||||
return;
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "DebugTools/BiosDebugData.h"
|
||||
#include "DebugTools/MipsStackWalk.h"
|
||||
|
||||
#include "Models/BreakpointModel.h"
|
||||
|
||||
#include "QtHost.h"
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtWidgets/QTableWidget>
|
||||
|
@ -39,7 +41,6 @@ public:
|
|||
~CpuWidget();
|
||||
|
||||
public slots:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void paintEvent(QPaintEvent* event);
|
||||
|
||||
void onStepInto();
|
||||
|
@ -49,10 +50,9 @@ public slots:
|
|||
void onVMPaused();
|
||||
|
||||
void updateBreakpoints();
|
||||
void fixBPListColumnSize();
|
||||
|
||||
void onBPListDoubleClicked(const QModelIndex& index);
|
||||
void onBPListContextMenu(QPoint pos);
|
||||
void onBPListItemChange(QTableWidgetItem* item);
|
||||
|
||||
void contextBPListCopy();
|
||||
void contextBPListDelete();
|
||||
|
@ -82,7 +82,6 @@ public slots:
|
|||
updateBreakpoints();
|
||||
updateThreads();
|
||||
updateStackFrames();
|
||||
updateFunctionList();
|
||||
|
||||
m_ui.registerWidget->update();
|
||||
m_ui.disassemblyWidget->update();
|
||||
|
@ -103,15 +102,8 @@ private:
|
|||
|
||||
DebugInterface& m_cpu;
|
||||
|
||||
// Poor mans variant
|
||||
// Allows us to map row index to breakpoint / memcheck objects
|
||||
struct BreakpointObject
|
||||
{
|
||||
std::shared_ptr<BreakPoint> bp;
|
||||
std::shared_ptr<MemCheck> mc;
|
||||
};
|
||||
BreakpointModel m_bpModel;
|
||||
|
||||
std::vector<BreakpointObject> m_bplistObjects;
|
||||
std::vector<EEThread> m_threadlistObjects;
|
||||
EEThread m_activeThread;
|
||||
std::vector<StackFrame> m_stacklistObjects;
|
||||
|
|
|
@ -322,7 +322,7 @@
|
|||
<enum>QTabWidget::South</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_memory">
|
||||
<property name="sizePolicy">
|
||||
|
@ -403,7 +403,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="breakpointList">
|
||||
<widget class="QTableView" name="breakpointList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
|
@ -413,59 +413,6 @@
|
|||
<property name="gridStyle">
|
||||
<enum>Qt::NoPen</enum>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>75</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size / Label</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Opcode</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Condition</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Hits</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -61,6 +61,9 @@ DebuggerWindow::DebuggerWindow(QWidget* parent)
|
|||
|
||||
m_ui.cpuTabs->addTab(m_cpuWidget_r5900, "R5900");
|
||||
m_ui.cpuTabs->addTab(m_cpuWidget_r3000, "R3000");
|
||||
|
||||
CBreakPoints::SetUpdateHandler(std::bind(&DebuggerWindow::onBreakpointsChanged, this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -121,3 +124,9 @@ void DebuggerWindow::onStepOut()
|
|||
CpuWidget* currentCpu = static_cast<CpuWidget*>(m_ui.cpuTabs->currentWidget());
|
||||
currentCpu->onStepOut();
|
||||
}
|
||||
|
||||
void DebuggerWindow::onBreakpointsChanged()
|
||||
{
|
||||
m_cpuWidget_r5900->reloadCPUWidgets();
|
||||
m_cpuWidget_r3000->reloadCPUWidgets();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public slots:
|
|||
void onStepInto();
|
||||
void onStepOver();
|
||||
void onStepOut();
|
||||
void onBreakpointsChanged();
|
||||
|
||||
private:
|
||||
Ui::DebuggerWindow m_ui;
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "BreakpointModel.h"
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "DebugTools/DisassemblyManager.h"
|
||||
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
BreakpointModel::BreakpointModel(DebugInterface& cpu, QObject* parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_cpu(cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int BreakpointModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_breakpoints.size();
|
||||
}
|
||||
|
||||
int BreakpointModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return BreakpointColumns::COLUMN_COUNT;
|
||||
}
|
||||
|
||||
QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
auto bp_mc = m_breakpoints.at(index.row());
|
||||
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::TYPE:
|
||||
return tr("Execute");
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(bp->addr, 16);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return m_cpu.GetSymbolMap().GetLabelString(bp->addr).c_str();
|
||||
case BreakpointColumns::OPCODE:
|
||||
// Note: Fix up the disassemblymanager so we can use it here, instead of calling a function through the disassemblyview (yuck)
|
||||
return m_cpu.disasm(bp->addr, true).c_str();
|
||||
case BreakpointColumns::CONDITION:
|
||||
return bp->hasCond ? QString::fromLocal8Bit(bp->cond.expressionString) : tr("No Condition");
|
||||
case BreakpointColumns::HITS:
|
||||
return tr("--");
|
||||
case BreakpointColumns::ENABLED:
|
||||
return bp->enabled ? tr("Enabled") : tr("Disabled");
|
||||
}
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::TYPE:
|
||||
{
|
||||
QString type("");
|
||||
type += (mc->cond & MEMCHECK_READ) ? tr("Read") : "";
|
||||
type += ((mc->cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
|
||||
type += (mc->cond & MEMCHECK_WRITE) ? (mc->cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
|
||||
return type;
|
||||
}
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(mc->start, 16);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return QString::number(mc->end - mc->start, 16);
|
||||
case BreakpointColumns::OPCODE:
|
||||
return tr("--"); // Our address is going to point to memory, no purpose in printing the op
|
||||
case BreakpointColumns::CONDITION:
|
||||
return tr("--"); // No condition on memchecks
|
||||
case BreakpointColumns::HITS:
|
||||
return QString::number(mc->numHits);
|
||||
case BreakpointColumns::ENABLED:
|
||||
return (mc->result & MEMCHECK_BREAK) ? tr("Enabled") : tr("Disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::CheckStateRole)
|
||||
{
|
||||
if (index.column() == 6)
|
||||
{
|
||||
auto bp_mc = m_breakpoints.at(index.row());
|
||||
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
return bp->enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked;
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
return (mc->result & MEMCHECK_BREAK) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case BreakpointColumns::TYPE:
|
||||
return tr("TYPE");
|
||||
case BreakpointColumns::OFFSET:
|
||||
return tr("OFFSET");
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return tr("SIZE / LABEL");
|
||||
case BreakpointColumns::OPCODE:
|
||||
return tr("INSTRUCTION");
|
||||
case BreakpointColumns::CONDITION:
|
||||
return tr("CONDITION");
|
||||
case BreakpointColumns::HITS:
|
||||
return tr("HITS");
|
||||
case BreakpointColumns::ENABLED:
|
||||
return tr("ENABLED");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags BreakpointModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
volatile const int row = index.row();
|
||||
|
||||
bool is_breakpoint = std::holds_alternative<BreakPoint>(m_breakpoints.at(row));
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::CONDITION:
|
||||
if (is_breakpoint)
|
||||
return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEditable;
|
||||
[[fallthrough]];
|
||||
case BreakpointColumns::TYPE:
|
||||
case BreakpointColumns::OPCODE:
|
||||
case BreakpointColumns::HITS:
|
||||
case BreakpointColumns::OFFSET:
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable;
|
||||
case BreakpointColumns::ENABLED:
|
||||
return Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable;
|
||||
}
|
||||
|
||||
return index.flags();
|
||||
}
|
||||
|
||||
bool BreakpointModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if (role == Qt::CheckStateRole && index.column() == BreakpointColumns::ENABLED)
|
||||
{
|
||||
auto bp_mc = m_breakpoints.at(index.row());
|
||||
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = this->m_cpu.getCpuType(), bp = *bp, enabled = value.toBool()] {
|
||||
CBreakPoints::ChangeBreakPoint(cpu, bp.addr, enabled);
|
||||
});
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = this->m_cpu.getCpuType(), mc = *mc] {
|
||||
CBreakPoints::ChangeMemCheck(cpu, mc.start, mc.end, mc.cond,
|
||||
MemCheckResult(mc.result ^ MEMCHECK_BREAK));
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (role == Qt::EditRole && index.column() == BreakpointColumns::CONDITION)
|
||||
{
|
||||
auto bp_mc = m_breakpoints.at(index.row());
|
||||
|
||||
if (std::holds_alternative<MemCheck>(bp_mc))
|
||||
return false;
|
||||
|
||||
const auto bp = std::get<BreakPoint>(bp_mc);
|
||||
|
||||
const QString condValue = value.toString();
|
||||
|
||||
if (condValue.isEmpty())
|
||||
{
|
||||
if (bp.hasCond)
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp] {
|
||||
CBreakPoints::ChangeBreakPointRemoveCond(cpu, bp.addr);
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PostfixExpression expr;
|
||||
|
||||
if (!m_cpu.initExpression(condValue.toLocal8Bit().constData(), expr))
|
||||
{
|
||||
QMessageBox::warning(nullptr, "Condition Error", QString(getExpressionError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
BreakPointCond cond;
|
||||
cond.debug = &m_cpu;
|
||||
cond.expression = expr;
|
||||
strcpy(&cond.expressionString[0], condValue.toLocal8Bit().constData());
|
||||
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp, cond] {
|
||||
CBreakPoints::ChangeBreakPointAddCond(cpu, bp.addr, cond);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BreakpointModel::removeRows(int row, int count, const QModelIndex& index)
|
||||
{
|
||||
beginRemoveRows(index, row, row + count);
|
||||
|
||||
for (int i = row; i < row + count; i++)
|
||||
{
|
||||
auto bp_mc = m_breakpoints.at(i);
|
||||
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), addr = bp->addr] {
|
||||
CBreakPoints::RemoveBreakPoint(cpu, addr);
|
||||
});
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), start = mc->start, end = mc->end] {
|
||||
CBreakPoints::RemoveMemCheck(cpu, start, end);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BreakpointModel::insertRows(int row, int count, std::vector<BreakpointMemcheck> breakpoints, const QModelIndex& index)
|
||||
{
|
||||
if (breakpoints.size() != count)
|
||||
return false;
|
||||
|
||||
beginInsertRows(index, row, row + count);
|
||||
|
||||
for (const auto& bp_mc : breakpoints)
|
||||
{
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp = *bp] {
|
||||
CBreakPoints::AddBreakPoint(cpu, bp.addr);
|
||||
|
||||
if (bp.hasCond)
|
||||
{
|
||||
CBreakPoints::ChangeBreakPointAddCond(cpu, bp.addr, bp.cond);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), mc = *mc] {
|
||||
CBreakPoints::AddMemCheck(cpu, mc.start, mc.end, mc.cond, mc.result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
void BreakpointModel::refreshData()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_breakpoints.clear();
|
||||
|
||||
auto breakpoints = CBreakPoints::GetBreakpoints(m_cpu.getCpuType(), false);
|
||||
for (const auto& bp : breakpoints)
|
||||
{
|
||||
m_breakpoints.push_back(bp);
|
||||
}
|
||||
|
||||
auto memchecks = CBreakPoints::GetMemChecks(m_cpu.getCpuType());
|
||||
for (const auto& mc : memchecks)
|
||||
{
|
||||
m_breakpoints.push_back(mc);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
|
||||
using BreakpointMemcheck = std::variant<BreakPoint, MemCheck>;
|
||||
|
||||
class BreakpointModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum BreakpointColumns : int
|
||||
{
|
||||
TYPE = 0,
|
||||
OFFSET,
|
||||
SIZE_LABEL,
|
||||
OPCODE,
|
||||
CONDITION,
|
||||
HITS,
|
||||
ENABLED,
|
||||
COLUMN_COUNT
|
||||
};
|
||||
|
||||
explicit BreakpointModel(DebugInterface& cpu, QObject* parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
|
||||
bool removeRows(int row, int count, const QModelIndex& index = QModelIndex()) override;
|
||||
bool insertRows(int row, int count, std::vector<BreakpointMemcheck> breakpoints, const QModelIndex& index = QModelIndex());
|
||||
|
||||
BreakpointMemcheck at(int row) const { return m_breakpoints.at(row); };
|
||||
public slots:
|
||||
void refreshData();
|
||||
|
||||
private:
|
||||
DebugInterface& m_cpu;
|
||||
std::vector<BreakpointMemcheck> m_breakpoints;
|
||||
};
|
|
@ -48,7 +48,7 @@
|
|||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)pcsx2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<!-- Needed for moc pch -->
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(ProjectDir)\Settings;$(ProjectDir)\GameList;$(ProjectDir)\Tools\InputRecording;$(ProjectDir)\Debugger</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(ProjectDir)\Settings;$(ProjectDir)\GameList;$(ProjectDir)\Tools\InputRecording;$(ProjectDir)\Debugger;$(ProjectDir)\Debugger\Models</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>PrecompiledHeader.h</PrecompiledHeaderFile>
|
||||
|
@ -148,6 +148,7 @@
|
|||
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
|
||||
<ClCompile Include="Debugger\RegisterWidget.cpp" />
|
||||
<ClCompile Include="Debugger\BreakpointDialog.cpp" />
|
||||
<ClCompile Include="Debugger\Models\BreakpointModel.cpp" />
|
||||
<ClCompile Include="Settings\BIOSSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\ControllerBindingWidgets.cpp" />
|
||||
<ClCompile Include="Settings\ControllerGlobalSettingsWidget.cpp" />
|
||||
|
@ -228,6 +229,7 @@
|
|||
<QtMoc Include="Debugger\MemoryViewWidget.h" />
|
||||
<QtMoc Include="Debugger\RegisterWidget.h" />
|
||||
<QtMoc Include="Debugger\BreakpointDialog.h" />
|
||||
<QtMoc Include="Debugger\Models\BreakpointModel.h" />
|
||||
<QtMoc Include="Settings\ControllerBindingWidgets.h" />
|
||||
<QtMoc Include="Settings\ControllerGlobalSettingsWidget.h" />
|
||||
<ClInclude Include="Settings\MemoryCardConvertWorker.h" />
|
||||
|
@ -278,6 +280,7 @@
|
|||
<ClCompile Include="$(IntDir)Debugger\moc_RegisterWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\moc_MemoryViewWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\moc_BreakpointDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_BreakpointModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListRefreshThread.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" />
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
<Filter Include="Debugger">
|
||||
<UniqueIdentifier>{ddb40cc4-9996-4ade-b647-eb549063553c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Debugger\Models">
|
||||
<UniqueIdentifier>{f4084ca0-d9d5-4584-b9d2-063db9f67de2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\pcsx2\PCSX2.rc">
|
||||
|
@ -274,6 +277,9 @@
|
|||
<ClCompile Include="Debugger\BreakpointDialog.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\Models\BreakpointModel.cpp">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)Debugger\moc_CpuWidget.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
|
@ -292,6 +298,9 @@
|
|||
<ClCompile Include="$(IntDir)Debugger\moc_BreakpointDialog.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_BreakpointModel.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
|
||||
|
@ -429,6 +438,9 @@
|
|||
<QtMoc Include="Debugger\BreakpointDialog.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Debugger\Models\BreakpointModel.h">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtResource Include="resources\resources.qrc">
|
||||
|
|
|
@ -27,7 +27,7 @@ u64 CBreakPoints::breakSkipFirstTicksEE_ = 0;
|
|||
u32 CBreakPoints::breakSkipFirstAtIop_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicksIop_ = 0;
|
||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck *> CBreakPoints::cleanupMemChecks_;
|
||||
std::vector<MemCheck*> CBreakPoints::cleanupMemChecks_;
|
||||
bool CBreakPoints::breakpointTriggered_ = false;
|
||||
bool CBreakPoints::corePaused = false;
|
||||
std::function<void()> CBreakPoints::cb_bpUpdated_;
|
||||
|
@ -171,8 +171,10 @@ bool CBreakPoints::IsAddressBreakPoint(BreakPointCpu cpu, u32 addr)
|
|||
bool CBreakPoints::IsAddressBreakPoint(BreakPointCpu cpu, u32 addr, bool* enabled)
|
||||
{
|
||||
size_t bp = FindBreakpoint(cpu, addr);
|
||||
if (bp == INVALID_BREAKPOINT) return false;
|
||||
if (enabled != NULL) *enabled = breakPoints_[bp].enabled;
|
||||
if (bp == INVALID_BREAKPOINT)
|
||||
return false;
|
||||
if (enabled != NULL)
|
||||
*enabled = breakPoints_[bp].enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -244,7 +246,7 @@ void CBreakPoints::ClearTemporaryBreakPoints()
|
|||
if (breakPoints_.empty())
|
||||
return;
|
||||
|
||||
for (int i = (int)breakPoints_.size()-1; i >= 0; --i)
|
||||
for (int i = (int)breakPoints_.size() - 1; i >= 0; --i)
|
||||
{
|
||||
if (breakPoints_[i].temporary)
|
||||
{
|
||||
|
@ -254,7 +256,7 @@ void CBreakPoints::ClearTemporaryBreakPoints()
|
|||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond &cond)
|
||||
void CBreakPoints::ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond& cond)
|
||||
{
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, false);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
|
@ -275,7 +277,7 @@ void CBreakPoints::ChangeBreakPointRemoveCond(BreakPointCpu cpu, u32 addr)
|
|||
}
|
||||
}
|
||||
|
||||
BreakPointCond *CBreakPoints::GetBreakPointCondition(BreakPointCpu cpu, u32 addr)
|
||||
BreakPointCond* CBreakPoints::GetBreakPointCondition(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, true);
|
||||
//temp breakpoints are unconditional
|
||||
|
@ -389,14 +391,35 @@ const std::vector<MemCheck> CBreakPoints::GetMemCheckRanges()
|
|||
return ranges;
|
||||
}
|
||||
|
||||
const std::vector<MemCheck> CBreakPoints::GetMemChecks()
|
||||
const std::vector<MemCheck> CBreakPoints::GetMemChecks(BreakPointCpu cpu)
|
||||
{
|
||||
return memChecks_;
|
||||
std::vector<MemCheck> memChecks;
|
||||
std::copy_if(memChecks_.begin(), memChecks_.end(), std::back_inserter(memChecks), [cpu](MemCheck& mc) { return mc.cpu == cpu; });
|
||||
return memChecks;
|
||||
}
|
||||
|
||||
const std::vector<BreakPoint> CBreakPoints::GetBreakpoints()
|
||||
const std::vector<BreakPoint> CBreakPoints::GetBreakpoints(BreakPointCpu cpu, bool includeTemp)
|
||||
{
|
||||
return breakPoints_;
|
||||
std::vector<BreakPoint> breakPoints;
|
||||
|
||||
std::copy_if(breakPoints_.begin(), breakPoints_.end(), std::back_inserter(breakPoints), [cpu, includeTemp](BreakPoint& bp) {
|
||||
if (bp.cpu == cpu)
|
||||
{
|
||||
if (includeTemp)
|
||||
return true;
|
||||
else
|
||||
return bp.temporary == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (includeTemp)
|
||||
return breakPoints_;
|
||||
|
||||
return breakPoints;
|
||||
}
|
||||
|
||||
void CBreakPoints::Update(BreakPointCpu cpu, u32 addr)
|
||||
|
@ -409,14 +432,11 @@ void CBreakPoints::Update(BreakPointCpu cpu, u32 addr)
|
|||
resume = true;
|
||||
}
|
||||
|
||||
// if (addr != 0)
|
||||
// Cpu->Clear(addr-4,8);
|
||||
// else
|
||||
SysClearExecutionCache();
|
||||
SysClearExecutionCache();
|
||||
|
||||
if (resume)
|
||||
r5900Debug.resumeCpu();
|
||||
|
||||
if(cb_bpUpdated_)
|
||||
if (cb_bpUpdated_)
|
||||
cb_bpUpdated_();
|
||||
}
|
||||
|
|
|
@ -141,8 +141,13 @@ public:
|
|||
// Includes uncached addresses.
|
||||
static const std::vector<MemCheck> GetMemCheckRanges();
|
||||
|
||||
static const std::vector<MemCheck> GetMemChecks();
|
||||
static const std::vector<BreakPoint> GetBreakpoints();
|
||||
static const std::vector<MemCheck> GetMemChecks(BreakPointCpu cpu);
|
||||
static const std::vector<BreakPoint> GetBreakpoints(BreakPointCpu cpu, bool includeTemp);
|
||||
// Returns count of all non-temporary breakpoints
|
||||
static size_t GetNumBreakpoints()
|
||||
{
|
||||
return std::count_if(breakPoints_.begin(), breakPoints_.end(), [](BreakPoint& bp) { return !bp.temporary; });
|
||||
}
|
||||
static size_t GetNumMemchecks() { return memChecks_.size(); }
|
||||
|
||||
static void Update(BreakPointCpu cpu = BREAKPOINT_IOP_AND_EE, u32 addr = 0);
|
||||
|
|
|
@ -70,13 +70,11 @@ void intMemcheck(u32 op, u32 bits, bool store)
|
|||
start = standardizeBreakpointAddress(start);
|
||||
u32 end = start + bits/8;
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
auto checks = CBreakPoints::GetMemChecks(BREAKPOINT_EE);
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
auto& check = checks[i];
|
||||
|
||||
if (check.cpu != BREAKPOINT_EE)
|
||||
continue;
|
||||
if (check.result == 0)
|
||||
continue;
|
||||
if ((check.cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
|
|
@ -157,13 +157,11 @@ void psxMemcheck(u32 op, u32 bits, bool store)
|
|||
|
||||
u32 end = start + bits / 8;
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
auto checks = CBreakPoints::GetMemChecks(BREAKPOINT_IOP);
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
auto& check = checks[i];
|
||||
|
||||
if (check.cpu != BREAKPOINT_IOP)
|
||||
continue;
|
||||
if (check.result == 0)
|
||||
continue;
|
||||
if ((check.cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
|
|
@ -1364,11 +1364,9 @@ static void psxRecMemcheck(u32 op, u32 bits, bool store)
|
|||
// ecx = access address
|
||||
// edx = access address+size
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
auto checks = CBreakPoints::GetMemChecks(BREAKPOINT_IOP);
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if (checks[i].cpu != BREAKPOINT_IOP)
|
||||
continue;
|
||||
if (checks[i].result == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
|
|
@ -1613,11 +1613,9 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
|||
// ecx = access address
|
||||
// edx = access address+size
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
auto checks = CBreakPoints::GetMemChecks(BREAKPOINT_EE);
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if (checks[i].cpu != BREAKPOINT_EE)
|
||||
continue;
|
||||
if (checks[i].result == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
|
Loading…
Reference in New Issue