yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
internal_emulator_adapter.cc
Go to the documentation of this file.
2
3#include "absl/strings/str_format.h"
4
5#include <iostream>
6#include <thread>
7#include <chrono>
8
9namespace yaze {
10namespace emu {
11
12namespace {
13
14absl::StatusOr<input::SnesButton> ToSnesButton(InputButton button) {
16 switch (button) {
17 case InputButton::kA:
18 return SnesButton::A;
19 case InputButton::kB:
20 return SnesButton::B;
21 case InputButton::kX:
22 return SnesButton::X;
23 case InputButton::kY:
24 return SnesButton::Y;
25 case InputButton::kL:
26 return SnesButton::L;
27 case InputButton::kR:
28 return SnesButton::R;
30 return SnesButton::SELECT;
32 return SnesButton::START;
34 return SnesButton::UP;
36 return SnesButton::DOWN;
38 return SnesButton::LEFT;
40 return SnesButton::RIGHT;
41 default:
42 return absl::InvalidArgumentError(absl::StrFormat(
43 "Unsupported button value: %d", static_cast<int>(button)));
44 }
45}
46
58
67
79
88
89} // namespace
90
92 : emulator_(emulator) {}
93
95 return emulator_ != nullptr;
96}
97
101
105
109
111 if (emulator_) emulator_->snes().Reset(true);
112}
113
114absl::Status InternalEmulatorAdapter::Step(int count) {
115 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
116 for (int i = 0; i < count; ++i) {
118 }
119 return absl::OkStatus();
120}
121
123 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
126 return absl::OkStatus();
127}
128
130 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
133 return absl::OkStatus();
134}
135
137 auto& memory = emulator_->snes().memory();
138 auto& cpu = emulator_->snes().cpu();
140 [&memory](uint32_t addr) -> uint8_t { return memory.ReadByte(addr); });
142 [this]() { emulator_->StepSingleInstruction(); });
144 [&cpu]() -> uint32_t { return (cpu.PB << 16) | cpu.PC; });
145}
146
147absl::Status InternalEmulatorAdapter::LoadRom(const std::string& path) {
148 if (!rom_loader_) return absl::UnavailableError("No ROM loader configured");
149 if (rom_loader_(path)) return absl::OkStatus();
150 return absl::InternalError("Failed to load ROM");
151}
152
154 if (rom_getter_) {
155 Rom* rom = rom_getter_();
156 if (rom && rom->is_loaded()) {
157 return rom->filename();
158 }
159 }
160 return "";
161}
162
163absl::StatusOr<uint8_t> InternalEmulatorAdapter::ReadByte(uint32_t addr) {
164 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
165 return emulator_->snes().Read(addr);
166}
167
168absl::StatusOr<std::vector<uint8_t>> InternalEmulatorAdapter::ReadBlock(
169 uint32_t addr, size_t len) {
170 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
171 std::vector<uint8_t> data(len);
172 for (size_t i = 0; i < len; ++i) {
173 data[i] = emulator_->snes().Read(addr + i);
174 }
175 return data;
176}
177
178absl::Status InternalEmulatorAdapter::WriteByte(uint32_t addr, uint8_t val) {
179 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
180 emulator_->snes().Write(addr, val);
181 return absl::OkStatus();
182}
183
185 uint32_t addr, const std::vector<uint8_t>& data) {
186 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
187 for (size_t i = 0; i < data.size(); ++i) {
188 emulator_->snes().Write(addr + i, data[i]);
189 }
190 return absl::OkStatus();
191}
192
194 auto& cpu = emulator_->snes().cpu();
195 state->a = cpu.A;
196 state->x = cpu.X;
197 state->y = cpu.Y;
198 state->pc = cpu.PC;
199 state->pb = cpu.PB;
200 state->db = cpu.DB;
201 state->sp = cpu.SP();
202 state->d = cpu.D;
203 state->status = cpu.status;
204 state->flag_n = cpu.GetNegativeFlag();
205 state->flag_v = cpu.GetOverflowFlag();
206 state->flag_z = cpu.GetZeroFlag();
207 state->flag_c = cpu.GetCarryFlag();
208 state->cycles = emulator_->GetCurrentCycle();
209}
210
212 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
213 CaptureCPUState(out_state);
214 return absl::OkStatus();
215}
216
218 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
219
220 auto& snes = emulator_->snes();
221 auto read8 = [&snes](uint32_t addr) { return snes.Read(addr); };
222 auto read16 = [&read8](uint32_t addr) {
223 return static_cast<uint16_t>(read8(addr)) |
224 (static_cast<uint16_t>(read8(addr + 1)) << 8);
225 };
226
227 response->game_mode = read8(0x7E0010);
228 response->link_state = read8(0x7E005D);
229 response->link_pos_x = read16(0x7E0020);
230 response->link_pos_y = read16(0x7E0022);
231 response->link_health = read8(0x7EF36D);
232
233 return absl::OkStatus();
234}
235
237 BreakpointHitResult* response) {
239 return absl::UnavailableError("SNES is not initialized.");
240 }
241
242 const int kMaxInstructions = 1000000;
243 int instruction_count = 0;
244 auto& bp_manager = emulator_->breakpoint_manager();
245 auto& cpu = emulator_->snes().cpu();
246
247 while (instruction_count++ < kMaxInstructions) {
248 uint32_t pc = (cpu.PB << 16) | cpu.PC;
249 if (bp_manager.ShouldBreakOnExecute(
251 response->hit = true;
252 auto* last_hit = bp_manager.GetLastHit();
253 if (last_hit) {
254 response->breakpoint.id = last_hit->id;
255 response->breakpoint.address = last_hit->address;
256 response->breakpoint.kind = FromBreakpointType(last_hit->type);
257 response->breakpoint.cpu = FromCpuType(last_hit->cpu);
258 response->breakpoint.enabled = last_hit->enabled;
259 }
260 CaptureCPUState(&response->cpu_state);
261 return absl::OkStatus();
262 }
264 }
265 response->hit = false;
266 return absl::OkStatus();
267}
268
270 uint32_t addr, BreakpointKind type, CpuKind cpu,
271 const std::string& condition, const std::string& description) {
272 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
273 auto& bp_manager = emulator_->breakpoint_manager();
274 return bp_manager.AddBreakpoint(addr, ToBreakpointType(type),
275 ToCpuType(cpu), condition, description);
276}
277
278absl::Status InternalEmulatorAdapter::RemoveBreakpoint(uint32_t breakpoint_id) {
279 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
281 return absl::OkStatus();
282}
283
284absl::Status InternalEmulatorAdapter::ToggleBreakpoint(uint32_t breakpoint_id,
285 bool enabled) {
286 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
287 emulator_->breakpoint_manager().SetEnabled(breakpoint_id, enabled);
288 return absl::OkStatus();
289}
290
291std::vector<BreakpointSnapshot> InternalEmulatorAdapter::ListBreakpoints() {
292 std::vector<BreakpointSnapshot> result;
293 if (!emulator_) return result;
294
295 auto breakpoints = emulator_->breakpoint_manager().GetAllBreakpoints();
296 for (const auto& bp : breakpoints) {
298 info.id = bp.id;
299 info.address = bp.address;
300 info.kind = FromBreakpointType(bp.type);
301 info.cpu = FromCpuType(bp.cpu);
302 info.enabled = bp.enabled;
303 result.push_back(info);
304 }
305 return result;
306}
307
309 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
310 auto snes_button = ToSnesButton(button);
311 if (!snes_button.ok()) return snes_button.status();
312 emulator_->input_manager().PressButton(*snes_button);
313 return absl::OkStatus();
314}
315
317 if (!emulator_) return absl::UnavailableError("Emulator not initialized");
318 auto snes_button = ToSnesButton(button);
319 if (!snes_button.ok()) return snes_button.status();
320 emulator_->input_manager().ReleaseButton(*snes_button);
321 return absl::OkStatus();
322}
323
324} // namespace emu
325} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
auto filename() const
Definition rom.h:145
bool is_loaded() const
Definition rom.h:132
Manages CPU and SPC700 breakpoints for debugging.
void RemoveBreakpoint(uint32_t id)
Remove a breakpoint by ID.
void SetEnabled(uint32_t id, bool enabled)
Enable or disable a breakpoint.
std::vector< Breakpoint > GetAllBreakpoints() const
Get all breakpoints.
uint32_t AddBreakpoint(uint32_t address, Type type, CpuType cpu, const std::string &condition="", const std::string &description="")
Add a new breakpoint.
A class for emulating and debugging SNES games.
Definition emulator.h:40
BreakpointManager & breakpoint_manager()
Definition emulator.h:117
uint64_t GetCurrentCycle()
Definition emulator.h:132
void StepSingleInstruction()
Definition emulator.h:135
input::InputManager & input_manager()
Definition emulator.h:123
void set_running(bool running)
Definition emulator.h:61
bool is_snes_initialized() const
Definition emulator.h:127
auto snes() -> Snes &
Definition emulator.h:59
auto running() const -> bool
Definition emulator.h:60
void CaptureCPUState(CpuStateSnapshot *state)
absl::StatusOr< uint32_t > AddBreakpoint(uint32_t addr, BreakpointKind type, CpuKind cpu, const std::string &condition, const std::string &description) override
absl::Status GetCpuState(CpuStateSnapshot *out_state) override
absl::Status WriteBlock(uint32_t addr, const std::vector< uint8_t > &data) override
absl::Status ToggleBreakpoint(uint32_t breakpoint_id, bool enabled) override
absl::Status Step(int count) override
absl::Status RemoveBreakpoint(uint32_t breakpoint_id) override
std::string GetLoadedRomPath() const override
absl::StatusOr< std::vector< uint8_t > > ReadBlock(uint32_t addr, size_t len) override
absl::Status ReleaseButton(InputButton button) override
absl::Status WriteByte(uint32_t addr, uint8_t val) override
absl::Status GetGameState(GameSnapshot *out_state) override
absl::Status RunToBreakpoint(BreakpointHitResult *response) override
std::vector< BreakpointSnapshot > ListBreakpoints() override
std::function< bool(const std::string &) rom_loader_)
absl::Status LoadRom(const std::string &path) override
absl::Status PressButton(InputButton button) override
absl::StatusOr< uint8_t > ReadByte(uint32_t addr) override
yaze::emu::debug::StepController step_controller_
void SetMemoryReader(MemoryReader reader)
void SetPcGetter(PcGetter getter)
StepResult StepOver(uint32_t max_instructions=1000000)
Step over the current instruction.
void SetSingleStepper(SingleStepper stepper)
StepResult StepOut(uint32_t max_instructions=1000000)
Step out of the current subroutine.
void PressButton(SnesButton button)
void ReleaseButton(SnesButton button)
absl::StatusOr< input::SnesButton > ToSnesButton(InputButton button)
BreakpointKind FromBreakpointType(BreakpointManager::Type type)
SnesButton
SNES controller button mapping (platform-agnostic)