summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h
blob: 500a8ca53c338380d637955d2b750dc4928f4d2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <cstdio>

#include <QAbstractTableModel>
#include <QFont>
#include <QList>
#include <QVariant>

#include "Common/SymbolDB.h"

namespace Core
{
class BranchWatch;
class CPUThreadGuard;
class System;
}  // namespace Core
class PPCSymbolDB;

namespace BranchWatchTableModelColumn
{
enum EnumType : int
{
  Instruction = 0,
  Condition,
  Origin,
  Destination,
  RecentHits,
  TotalHits,
  OriginSymbol,
  DestinSymbol,
  NumberOfColumns,
};
}

namespace BranchWatchTableModelUserRole
{
enum EnumType : int
{
  ClickRole = Qt::UserRole,
  SortRole,
};
}

struct BranchWatchTableModelSymbolListValueType
{
  explicit BranchWatchTableModelSymbolListValueType(const Common::Symbol* const origin_symbol,
                                                    const Common::Symbol* const destin_symbol)
      : origin_name(origin_symbol ? QString::fromStdString(origin_symbol->name) : QVariant{}),
        origin_addr(origin_symbol ? origin_symbol->address : QVariant{}),
        destin_name(destin_symbol ? QString::fromStdString(destin_symbol->name) : QVariant{}),
        destin_addr(destin_symbol ? destin_symbol->address : QVariant{})
  {
  }
  QVariant origin_name, origin_addr;
  QVariant destin_name, destin_addr;
};

class BranchWatchTableModel final : public QAbstractTableModel
{
  Q_OBJECT

public:
  using Column = BranchWatchTableModelColumn::EnumType;
  using UserRole = BranchWatchTableModelUserRole::EnumType;
  using SymbolListValueType = BranchWatchTableModelSymbolListValueType;
  using SymbolList = QList<SymbolListValueType>;

  explicit BranchWatchTableModel(Core::System& system, Core::BranchWatch& branch_watch,
                                 PPCSymbolDB& ppc_symbol_db, QObject* parent = nullptr)
      : QAbstractTableModel(parent), m_system(system), m_branch_watch(branch_watch),
        m_ppc_symbol_db(ppc_symbol_db)
  {
  }
  ~BranchWatchTableModel() override = default;

  BranchWatchTableModel(const BranchWatchTableModel&) = delete;
  BranchWatchTableModel(BranchWatchTableModel&&) = delete;
  BranchWatchTableModel& operator=(const BranchWatchTableModel&) = delete;
  BranchWatchTableModel& operator=(BranchWatchTableModel&&) = delete;

  QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
  QVariant headerData(int section, Qt::Orientation orientation,
                      int role = Qt::DisplayRole) const override;
  int rowCount(const QModelIndex& parent = QModelIndex{}) const override;
  int columnCount(const QModelIndex& parent = QModelIndex{}) const override;
  bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex{}) override;
  void setFont(const QFont& font) { m_font = font; }

  void OnClearBranchWatch(const Core::CPUThreadGuard& guard);
  void OnCodePathWasTaken(const Core::CPUThreadGuard& guard);
  void OnCodePathNotTaken(const Core::CPUThreadGuard& guard);
  void OnBranchWasOverwritten(const Core::CPUThreadGuard& guard);
  void OnBranchNotOverwritten(const Core::CPUThreadGuard& guard);
  void OnWipeRecentHits();
  void OnWipeInspection();

  void Save(const Core::CPUThreadGuard& guard, std::FILE* file) const;
  void Load(const Core::CPUThreadGuard& guard, std::FILE* file);
  void UpdateSymbols();
  void UpdateHits();
  void SetInspected(const QModelIndex& index);

  const SymbolList& GetSymbolList() const { return m_symbol_list; }

private:
  void SetOriginInspected(u32 origin_addr);
  void SetDestinInspected(u32 destin_addr, bool nested);
  void SetSymbolInspected(u32 symbol_addr, bool nested);
  void PrefetchSymbols();

  [[nodiscard]] QVariant DisplayRoleData(const QModelIndex& index) const;
  [[nodiscard]] QVariant FontRoleData(const QModelIndex& index) const;
  [[nodiscard]] QVariant TextAlignmentRoleData(const QModelIndex& index) const;
  [[nodiscard]] QVariant ForegroundRoleData(const QModelIndex& index) const;
  [[nodiscard]] QVariant ClickRoleData(const QModelIndex& index) const;
  [[nodiscard]] QVariant SortRoleData(const QModelIndex& index) const;

  Core::System& m_system;
  Core::BranchWatch& m_branch_watch;
  PPCSymbolDB& m_ppc_symbol_db;

  SymbolList m_symbol_list;
  mutable QFont m_font;
};