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