diff --git a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp index 7f8deb09cf..4860f4d9f6 100644 --- a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp +++ b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp @@ -77,6 +77,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const return tr("Execute"); case BreakpointColumns::OFFSET: return QtUtils::FilledQStringFromValue(bp->addr, 16); + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(bp->description); case BreakpointColumns::SIZE_LABEL: return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name); case BreakpointColumns::OPCODE: @@ -105,6 +107,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const } case BreakpointColumns::OFFSET: return QtUtils::FilledQStringFromValue(mc->start, 16); + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(mc->description); case BreakpointColumns::SIZE_LABEL: return QString::number(mc->end - mc->start, 16); case BreakpointColumns::OPCODE: @@ -116,6 +120,29 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const } } } + else if (role == Qt::EditRole) + { + if (const auto* bp = std::get_if(&bp_mc)) + { + switch (index.column()) + { + case BreakpointColumns::CONDITION: + return bp->hasCond ? QString::fromStdString(bp->cond.expressionString) : ""; + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(bp->description); + } + } + else if (const auto* mc = std::get_if(&bp_mc)) + { + switch (index.column()) + { + case BreakpointColumns::CONDITION: + return mc->hasCond ? QString::fromStdString(mc->cond.expressionString) : ""; + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(mc->description); + } + } + } else if (role == BreakpointModel::DataRole) { if (const auto* bp = std::get_if(&bp_mc)) @@ -128,6 +155,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const return MEMCHECK_INVALID; case BreakpointColumns::OFFSET: return bp->addr; + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(bp->description); case BreakpointColumns::SIZE_LABEL: return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name); case BreakpointColumns::OPCODE: @@ -149,6 +178,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const return mc->memCond; case BreakpointColumns::OFFSET: return mc->start; + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(mc->description); case BreakpointColumns::SIZE_LABEL: return mc->end - mc->start; case BreakpointColumns::OPCODE: @@ -172,6 +203,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const return MEMCHECK_INVALID; case BreakpointColumns::OFFSET: return QtUtils::FilledQStringFromValue(bp->addr, 16); + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(bp->description); case BreakpointColumns::SIZE_LABEL: return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name); case BreakpointColumns::OPCODE: @@ -191,6 +224,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const return mc->memCond; case BreakpointColumns::OFFSET: return QtUtils::FilledQStringFromValue(mc->start, 16); + case BreakpointColumns::DESCRIPTION: + return QString::fromStdString(mc->description); case BreakpointColumns::SIZE_LABEL: return mc->end - mc->start; case BreakpointColumns::OPCODE: @@ -233,6 +268,8 @@ QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, i case BreakpointColumns::OFFSET: //: Warning: limited space available. Abbreviate if needed. return tr("OFFSET"); + case BreakpointColumns::DESCRIPTION: + return "DESCRIPTION"; case BreakpointColumns::SIZE_LABEL: //: Warning: limited space available. Abbreviate if needed. return tr("SIZE / LABEL"); @@ -260,6 +297,8 @@ QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, i return "TYPE"; case BreakpointColumns::OFFSET: return "OFFSET"; + case BreakpointColumns::DESCRIPTION: + return "DESCRIPTION"; case BreakpointColumns::SIZE_LABEL: return "SIZE / LABEL"; case BreakpointColumns::OPCODE: @@ -282,6 +321,7 @@ Qt::ItemFlags BreakpointModel::flags(const QModelIndex& index) const switch (index.column()) { case BreakpointColumns::CONDITION: + case BreakpointColumns::DESCRIPTION: return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEditable; case BreakpointColumns::TYPE: case BreakpointColumns::OPCODE: @@ -393,6 +433,27 @@ bool BreakpointModel::setData(const QModelIndex& index, const QVariant& value, i } } emit dataChanged(index, index); + return true; + } + else if (role == Qt::EditRole && index.column() == BreakpointColumns::DESCRIPTION) + { + // Update BreakPoint description + if (auto* bp = std::get_if(&bp_mc)) + { + const QString descValue = value.toString(); + Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp, descValue] { + CBreakPoints::ChangeBreakPointDescription(cpu, bp->addr, descValue.toStdString()); + }); + } + // Update MemCheck description + else if (auto* mc = std::get_if(&bp_mc)) + { + const QString descValue = value.toString(); + Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), mc, descValue] { + CBreakPoints::ChangeMemCheckDescription(cpu, mc->start, mc->end, descValue.toStdString()); + }); + } + emit dataChanged(index, index); return true; } @@ -548,6 +609,12 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) return; } + // Description + if (!fields[BreakpointColumns::DESCRIPTION].isEmpty()) + { + bp.description = fields[BreakpointColumns::DESCRIPTION].toStdString(); + } + insertBreakpointRows(0, 1, {bp}); } else @@ -608,6 +675,12 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) } mc.result = static_cast(result); + // Description + if (!fields[BreakpointColumns::DESCRIPTION].isEmpty()) + { + mc.description = fields[BreakpointColumns::DESCRIPTION].toStdString(); + } + insertBreakpointRows(0, 1, {mc}); } } diff --git a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h index fd603bb858..161625eb6e 100644 --- a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h +++ b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h @@ -21,6 +21,7 @@ public: ENABLED = 0, TYPE, OFFSET, + DESCRIPTION, SIZE_LABEL, OPCODE, CONDITION, @@ -38,6 +39,7 @@ public: QHeaderView::ResizeMode::ResizeToContents, QHeaderView::ResizeMode::ResizeToContents, QHeaderView::ResizeMode::ResizeToContents, + QHeaderView::ResizeMode::ResizeToContents, QHeaderView::ResizeMode::Stretch, QHeaderView::ResizeMode::Stretch, QHeaderView::ResizeMode::ResizeToContents, diff --git a/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp b/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp index 81a23c8858..d189289309 100644 --- a/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp +++ b/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp @@ -12,7 +12,7 @@ #include "VMManager.h" std::mutex DebuggerSettingsManager::writeLock; -const QString DebuggerSettingsManager::settingsFileVersion = "0.00"; +const QString DebuggerSettingsManager::settingsFileVersion = "0.01"; QJsonObject DebuggerSettingsManager::loadGameSettingsJSON() { @@ -61,6 +61,13 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel) Console.WriteLnFmt("Debugger Settings Manager: Failed to read Breakpoints array from settings file: '{}'", path); return; } + + // Breakpoint descriptions were added at debugger settings version 0.01. If loading + // saved breakpoints from a previous version, we will add in an empty description + // so that the previous version is compatible with the current version. + const QJsonValue savedVersionValue = loadGameSettingsJSON().value("Version"); + const QString savedVersion = savedVersionValue.toString(); + const bool needDescription = savedVersion != settingsFileVersion && savedVersion.toStdString() == "0.00" && settingsFileVersion.toStdString() == "0.01"; const QJsonArray breakpointsArray = breakpointsValue.toArray(); for (u32 row = 0; row < breakpointsArray.size(); row++) @@ -71,7 +78,13 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel) Console.WriteLn("Debugger Settings Manager: Failed to load invalid Breakpoint object."); continue; } - const QJsonObject rowObject = rowValue.toObject(); + QJsonObject rowObject = rowValue.toObject(); + + // convert from 0.00 to 0.01 settings version + if (needDescription) + { + rowObject.insert(QString("DESCRIPTION"), QJsonValue("conv-desc")); + } QStringList fields; u32 col = 0; diff --git a/pcsx2/DebugTools/Breakpoints.cpp b/pcsx2/DebugTools/Breakpoints.cpp index 8bc670e294..da87b27d84 100644 --- a/pcsx2/DebugTools/Breakpoints.cpp +++ b/pcsx2/DebugTools/Breakpoints.cpp @@ -285,6 +285,16 @@ BreakPointCond* CBreakPoints::GetBreakPointCondition(BreakPointCpu cpu, u32 addr return NULL; } +void CBreakPoints::ChangeBreakPointDescription(BreakPointCpu cpu, u32 addr, std::string description) +{ + const size_t bp = FindBreakpoint(cpu, addr, true, false); + if (bp != INVALID_BREAKPOINT) + { + breakPoints_[bp].description = description; + Update(); + } +} + void CBreakPoints::AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result) { // This will ruin any pending memchecks. @@ -356,6 +366,16 @@ void CBreakPoints::ChangeMemCheckAddCond(BreakPointCpu cpu, u32 start, u32 end, } } +void CBreakPoints::ChangeMemCheckDescription(BreakPointCpu cpu, u32 start, u32 end, std::string description) +{ + const size_t mc = FindMemCheck(cpu, start, end); + if (mc != INVALID_MEMCHECK) + { + memChecks_[mc].description = description; + Update(cpu); + } +} + void CBreakPoints::ClearAllMemChecks() { // This will ruin any pending memchecks. diff --git a/pcsx2/DebugTools/Breakpoints.h b/pcsx2/DebugTools/Breakpoints.h index fd100b4cc7..3d63f39fcc 100644 --- a/pcsx2/DebugTools/Breakpoints.h +++ b/pcsx2/DebugTools/Breakpoints.h @@ -37,6 +37,8 @@ struct BreakPoint BreakPointCond cond; BreakPointCpu cpu; + std::string description; + bool operator==(const BreakPoint& other) const { return addr == other.addr; @@ -78,6 +80,8 @@ struct MemCheck MemCheckResult result; BreakPointCpu cpu; + std::string description; + u32 numHits; u32 lastPC; @@ -119,12 +123,14 @@ public: static void ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond& cond); static void ChangeBreakPointRemoveCond(BreakPointCpu cpu, u32 addr); static BreakPointCond* GetBreakPointCondition(BreakPointCpu cpu, u32 addr); + static void ChangeBreakPointDescription(BreakPointCpu cpu, u32 addr, std::string description); static void AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result); static void RemoveMemCheck(BreakPointCpu cpu, u32 start, u32 end); static void ChangeMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result); static void ChangeMemCheckRemoveCond(BreakPointCpu cpu, u32 start, u32 end); static void ChangeMemCheckAddCond(BreakPointCpu cpu, u32 start, u32 end, const BreakPointCond& cond); + static void ChangeMemCheckDescription(BreakPointCpu cpu, u32 start, u32 end, std::string description); static void ClearAllMemChecks(); static void SetSkipFirst(BreakPointCpu cpu, u32 pc);