yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
breakpoint_manager.cc
Go to the documentation of this file.
2
3#include <algorithm>
4
5#include "util/log.h"
6
7namespace yaze {
8namespace emu {
9
10uint32_t BreakpointManager::AddBreakpoint(uint32_t address, Type type,
11 CpuType cpu,
12 const std::string& condition,
13 const std::string& description) {
14 Breakpoint bp;
15 bp.id = next_id_++;
16 bp.address = address;
17 bp.type = type;
18 bp.cpu = cpu;
19 bp.enabled = true;
20 bp.condition = condition;
21 bp.hit_count = 0;
22 bp.description =
23 description.empty()
24 ? (cpu == CpuType::CPU_65816 ? "CPU Breakpoint" : "SPC700 Breakpoint")
25 : description;
26
27 breakpoints_[bp.id] = bp;
28
29 LOG_INFO("Breakpoint", "Added breakpoint #%d: %s at $%06X (type=%d, cpu=%d)",
30 bp.id, bp.description.c_str(), address, static_cast<int>(type),
31 static_cast<int>(cpu));
32
33 return bp.id;
34}
35
37 auto it = breakpoints_.find(id);
38 if (it != breakpoints_.end()) {
39 LOG_INFO("Breakpoint", "Removed breakpoint #%d", id);
40 breakpoints_.erase(it);
41 }
42}
43
44void BreakpointManager::SetEnabled(uint32_t id, bool enabled) {
45 auto it = breakpoints_.find(id);
46 if (it != breakpoints_.end()) {
47 it->second.enabled = enabled;
48 LOG_INFO("Breakpoint", "Breakpoint #%d %s", id,
49 enabled ? "enabled" : "disabled");
50 }
51}
52
54 for (auto& [id, bp] : breakpoints_) {
55 if (!bp.enabled || bp.cpu != cpu || bp.type != Type::EXECUTE) {
56 continue;
57 }
58
59 if (bp.address == pc) {
60 bp.hit_count++;
61 last_hit_ = &bp;
62
63 // Check condition if present
64 if (!bp.condition.empty()) {
65 if (!EvaluateCondition(bp.condition, pc, pc, 0)) {
66 continue; // Condition not met
67 }
68 }
69
70 LOG_INFO("Breakpoint", "Hit breakpoint #%d at PC=$%06X (hits=%d)", id, pc,
71 bp.hit_count);
72 return true;
73 }
74 }
75 return false;
76}
77
79 bool is_write, uint8_t value,
80 uint32_t pc) {
81 for (auto& [id, bp] : breakpoints_) {
82 if (!bp.enabled || bp.address != address) {
83 continue;
84 }
85
86 // Check if this breakpoint applies to this access type
87 bool applies = false;
88 switch (bp.type) {
89 case Type::READ:
90 applies = !is_write;
91 break;
92 case Type::WRITE:
93 applies = is_write;
94 break;
95 case Type::ACCESS:
96 applies = true;
97 break;
98 default:
99 continue; // Not a memory breakpoint
100 }
101
102 if (applies) {
103 bp.hit_count++;
104 last_hit_ = &bp;
105
106 // Check condition if present
107 if (!bp.condition.empty()) {
108 if (!EvaluateCondition(bp.condition, pc, address, value)) {
109 continue;
110 }
111 }
112
113 LOG_INFO(
114 "Breakpoint",
115 "Hit %s breakpoint #%d at $%06X (value=$%02X, PC=$%06X, hits=%d)",
116 is_write ? "WRITE" : "READ", id, address, value, pc, bp.hit_count);
117 return true;
118 }
119 }
120 return false;
121}
122
123std::vector<BreakpointManager::Breakpoint>
125 std::vector<Breakpoint> result;
126 result.reserve(breakpoints_.size());
127 for (const auto& [id, bp] : breakpoints_) {
128 result.push_back(bp);
129 }
130 // Sort by ID for consistent ordering
131 std::sort(
132 result.begin(), result.end(),
133 [](const Breakpoint& a, const Breakpoint& b) { return a.id < b.id; });
134 return result;
135}
136
137std::vector<BreakpointManager::Breakpoint> BreakpointManager::GetBreakpoints(
138 CpuType cpu) const {
139 std::vector<Breakpoint> result;
140 for (const auto& [id, bp] : breakpoints_) {
141 if (bp.cpu == cpu) {
142 result.push_back(bp);
143 }
144 }
145 std::sort(
146 result.begin(), result.end(),
147 [](const Breakpoint& a, const Breakpoint& b) { return a.id < b.id; });
148 return result;
149}
150
152 LOG_INFO("Breakpoint", "Cleared all breakpoints (%zu total)",
153 breakpoints_.size());
154 breakpoints_.clear();
155 last_hit_ = nullptr;
156}
157
159 auto it = breakpoints_.begin();
160 int cleared = 0;
161 while (it != breakpoints_.end()) {
162 if (it->second.cpu == cpu) {
163 it = breakpoints_.erase(it);
164 cleared++;
165 } else {
166 ++it;
167 }
168 }
169 LOG_INFO("Breakpoint", "Cleared %d breakpoints for %s", cleared,
170 cpu == CpuType::CPU_65816 ? "CPU" : "SPC700");
171}
172
174 for (auto& [id, bp] : breakpoints_) {
175 bp.hit_count = 0;
176 }
177}
178
179bool BreakpointManager::EvaluateCondition(const std::string& condition,
180 uint32_t pc, uint32_t address,
181 uint8_t value) {
182 // Simple condition evaluation for now
183 // Future: Could integrate Lua or expression parser
184
185 if (condition.empty()) {
186 return true; // No condition = always true
187 }
188
189 // Support simple comparisons: "value > 10", "value == 0xFF", etc.
190 // Format: "value OPERATOR number"
191
192 // For now, just return true (conditions not implemented yet)
193 // TODO: Implement proper expression evaluation
194 return true;
195}
196
197} // namespace emu
198} // namespace yaze
bool ShouldBreakOnExecute(uint32_t pc, CpuType cpu)
Check if execution should break at this address.
void RemoveBreakpoint(uint32_t id)
Remove a breakpoint by ID.
bool ShouldBreakOnMemoryAccess(uint32_t address, bool is_write, uint8_t value, uint32_t pc)
Check if execution should break on memory access.
void ClearAll()
Clear all breakpoints.
void SetEnabled(uint32_t id, bool enabled)
Enable or disable a breakpoint.
std::vector< Breakpoint > GetAllBreakpoints() const
Get all breakpoints.
bool EvaluateCondition(const std::string &condition, uint32_t pc, uint32_t address, uint8_t value)
void ResetHitCounts()
Reset hit counts for all breakpoints.
std::vector< Breakpoint > GetBreakpoints(CpuType cpu) const
Get breakpoints for specific CPU.
std::unordered_map< uint32_t, Breakpoint > breakpoints_
uint32_t AddBreakpoint(uint32_t address, Type type, CpuType cpu, const std::string &condition="", const std::string &description="")
Add a new breakpoint.
#define LOG_INFO(category, format,...)
Definition log.h:105