yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
emulator_service_impl.cc
Go to the documentation of this file.
2
3#include <chrono>
4#include <filesystem>
5#include <fstream>
6#include <thread>
7#include <vector>
8
9#include "absl/strings/str_format.h"
13#include "rom/rom.h"
14#include "util/log.h"
15
16namespace yaze::net {
17
18namespace {
19grpc::Status ToGrpcStatus(const absl::Status& status) {
20 if (status.ok())
21 return grpc::Status::OK;
22
23 grpc::StatusCode code = grpc::StatusCode::UNKNOWN;
24 switch (status.code()) {
25 case absl::StatusCode::kOk:
26 code = grpc::StatusCode::OK;
27 break;
28 case absl::StatusCode::kCancelled:
29 code = grpc::StatusCode::CANCELLED;
30 break;
31 case absl::StatusCode::kUnknown:
32 code = grpc::StatusCode::UNKNOWN;
33 break;
34 case absl::StatusCode::kInvalidArgument:
35 code = grpc::StatusCode::INVALID_ARGUMENT;
36 break;
37 case absl::StatusCode::kDeadlineExceeded:
38 code = grpc::StatusCode::DEADLINE_EXCEEDED;
39 break;
40 case absl::StatusCode::kNotFound:
41 code = grpc::StatusCode::NOT_FOUND;
42 break;
43 case absl::StatusCode::kAlreadyExists:
44 code = grpc::StatusCode::ALREADY_EXISTS;
45 break;
46 case absl::StatusCode::kPermissionDenied:
47 code = grpc::StatusCode::PERMISSION_DENIED;
48 break;
49 case absl::StatusCode::kUnauthenticated:
50 code = grpc::StatusCode::UNAUTHENTICATED;
51 break;
52 case absl::StatusCode::kResourceExhausted:
53 code = grpc::StatusCode::RESOURCE_EXHAUSTED;
54 break;
55 case absl::StatusCode::kFailedPrecondition:
56 code = grpc::StatusCode::FAILED_PRECONDITION;
57 break;
58 case absl::StatusCode::kAborted:
59 code = grpc::StatusCode::ABORTED;
60 break;
61 case absl::StatusCode::kOutOfRange:
62 code = grpc::StatusCode::OUT_OF_RANGE;
63 break;
64 case absl::StatusCode::kUnimplemented:
65 code = grpc::StatusCode::UNIMPLEMENTED;
66 break;
67 case absl::StatusCode::kInternal:
68 code = grpc::StatusCode::INTERNAL;
69 break;
70 case absl::StatusCode::kUnavailable:
71 code = grpc::StatusCode::UNAVAILABLE;
72 break;
73 case absl::StatusCode::kDataLoss:
74 code = grpc::StatusCode::DATA_LOSS;
75 break;
76 default:
77 code = grpc::StatusCode::UNKNOWN;
78 break;
79 }
80 return grpc::Status(code, std::string(status.message()));
81}
82} // namespace
83
85 RomGetter rom_getter,
86 RomLoader rom_loader)
87 : emulator_(emulator), rom_getter_(rom_getter), rom_loader_(rom_loader) {}
88
89// --- ROM Loading ---
90
91grpc::Status EmulatorServiceImpl::LoadRom(grpc::ServerContext* context,
92 const agent::LoadRomRequest* request,
93 agent::LoadRomResponse* response) {
94 if (!emulator_) {
95 response->set_success(false);
96 response->set_message("Emulator middleware not initialized");
97 return grpc::Status::OK;
98 }
99 auto status = emulator_->LoadRom(request->filepath());
100 if (status.ok()) {
101 response->set_success(true);
102 response->set_message("ROM loaded successfully");
103 if (rom_getter_) {
104 Rom* rom = rom_getter_();
105 if (rom && rom->is_loaded()) {
106 response->set_rom_title(rom->title());
107 response->set_rom_size(rom->size());
108 }
109 }
110 } else {
111 response->set_success(false);
112 response->set_message("Failed to load ROM: " +
113 std::string(status.message()));
114 }
115 return grpc::Status::OK;
116}
117
119 grpc::ServerContext* context, const agent::Empty* request,
120 agent::LoadedRomPathResponse* response) {
121 if (emulator_) {
122 std::string path = emulator_->GetLoadedRomPath();
123 if (!path.empty()) {
124 response->set_has_rom(true);
125 response->set_filepath(path);
126 response->set_title(std::filesystem::path(path).stem().string());
127 return grpc::Status::OK;
128 }
129 }
130
131 response->set_has_rom(false);
132 return grpc::Status::OK;
133}
134
135// --- Core Lifecycle & Control ---
136
138 grpc::ServerContext* context, const agent::ControlRequest* request,
139 agent::CommandResponse* response) {
140 if (!emulator_ || !emulator_->IsConnected())
141 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
142 "Emulator not connected.");
143
144 std::string action = request->action();
145 if (action == "start" || action == "resume") {
146 emulator_->Resume();
147 response->set_message("Emulator resumed.");
148 } else if (action == "stop" || action == "pause") {
149 emulator_->Pause();
150 response->set_message("Emulator paused.");
151 } else if (action == "reset") {
152 emulator_->Reset();
153 response->set_message("Emulator reset.");
154 } else if (action == "init" || action == "initialize") {
155 response->set_message("Emulator connection active.");
156 } else {
157 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
158 "Unknown action: " + action);
159 }
160
161 response->set_success(true);
162 return grpc::Status::OK;
163}
164
166 grpc::ServerContext* context, const agent::StepControlRequest* request,
167 agent::StepResponse* response) {
168 if (!emulator_ || !emulator_->IsConnected()) {
169 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
170 "Emulator not connected.");
171 }
172
173 std::string mode = request->mode();
174 absl::Status status;
175 if (mode == "instruction") {
176 status = emulator_->Step(1);
177 response->set_message("Stepped 1 instruction.");
178 } else if (mode == "over") {
179 status = emulator_->StepOver();
180 response->set_message("Step Over executed.");
181 } else if (mode == "out") {
182 status = emulator_->StepOut();
183 response->set_message("Step Out executed.");
184 } else {
185 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
186 "Unknown step mode: " + mode);
187 }
188
189 if (!status.ok())
190 return ToGrpcStatus(status);
191
192 emu::CpuStateSnapshot cpu_snap;
193 auto cpu_status = emulator_->GetCpuState(&cpu_snap);
194 if (!cpu_status.ok())
195 return ToGrpcStatus(cpu_status);
196 emu::ToProtoCpuState(cpu_snap, response->mutable_cpu_state());
197 response->set_success(true);
198 return grpc::Status::OK;
199}
200
202 grpc::ServerContext* context, const agent::Empty* request,
203 agent::BreakpointHitResponse* response) {
204 if (!emulator_)
205 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
206 "Emulator not initialized.");
207
209 auto status = emulator_->RunToBreakpoint(&result);
210 if (!status.ok())
211 return ToGrpcStatus(status);
212 emu::ToProtoBreakpointHitResponse(result, response);
213 return grpc::Status::OK;
214}
215
216// --- Input & State ---
217
219 grpc::ServerContext* context, const agent::ButtonRequest* request,
220 agent::CommandResponse* response) {
221 if (!emulator_)
222 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
223 "Emulator not initialized.");
224
225 std::vector<emu::InputButton> pressed_buttons;
226 pressed_buttons.reserve(request->buttons_size());
227 for (int i = 0; i < request->buttons_size(); i++) {
228 auto btn =
229 emu::FromProtoButton(static_cast<agent::Button>(request->buttons(i)));
231 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
232 absl::StrFormat("Invalid button at index %d: %d", i,
233 request->buttons(i)));
234 }
235 auto press_status = emulator_->PressButton(btn);
236 if (!press_status.ok()) {
237 for (auto it = pressed_buttons.rbegin(); it != pressed_buttons.rend();
238 ++it) {
239 (void)emulator_->ReleaseButton(*it);
240 }
241 return ToGrpcStatus(press_status);
242 }
243 pressed_buttons.push_back(btn);
244 }
245 std::this_thread::sleep_for(std::chrono::milliseconds(50));
246 for (auto it = pressed_buttons.rbegin(); it != pressed_buttons.rend(); ++it) {
247 auto release_status = emulator_->ReleaseButton(*it);
248 if (!release_status.ok())
249 return ToGrpcStatus(release_status);
250 }
251 response->set_success(true);
252 return grpc::Status::OK;
253}
254
256 grpc::ServerContext* context, const agent::ButtonRequest* request,
257 agent::CommandResponse* response) {
258 if (!emulator_)
259 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
260 "Emulator not initialized.");
261
262 for (int i = 0; i < request->buttons_size(); i++) {
263 auto btn =
264 emu::FromProtoButton(static_cast<agent::Button>(request->buttons(i)));
266 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
267 absl::StrFormat("Invalid button at index %d: %d", i,
268 request->buttons(i)));
269 }
270 auto status = emulator_->ReleaseButton(btn);
271 if (!status.ok())
272 return ToGrpcStatus(status);
273 }
274 response->set_success(true);
275 return grpc::Status::OK;
276}
277
279 grpc::ServerContext* context, const agent::ButtonHoldRequest* request,
280 agent::CommandResponse* response) {
281 if (!emulator_)
282 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
283 "Emulator not initialized.");
284
285 std::vector<emu::InputButton> held_buttons;
286 held_buttons.reserve(request->buttons_size());
287 for (int i = 0; i < request->buttons_size(); i++) {
288 auto btn =
289 emu::FromProtoButton(static_cast<agent::Button>(request->buttons(i)));
291 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
292 absl::StrFormat("Invalid button at index %d: %d", i,
293 request->buttons(i)));
294 }
295 auto press_status = emulator_->PressButton(btn);
296 if (!press_status.ok()) {
297 for (auto it = held_buttons.rbegin(); it != held_buttons.rend(); ++it) {
298 (void)emulator_->ReleaseButton(*it);
299 }
300 return ToGrpcStatus(press_status);
301 }
302 held_buttons.push_back(btn);
303 }
304 std::this_thread::sleep_for(
305 std::chrono::milliseconds(request->duration_ms()));
306 for (auto it = held_buttons.rbegin(); it != held_buttons.rend(); ++it) {
307 auto release_status = emulator_->ReleaseButton(*it);
308 if (!release_status.ok())
309 return ToGrpcStatus(release_status);
310 }
311 response->set_success(true);
312 return grpc::Status::OK;
313}
314
316 grpc::ServerContext* context, const agent::GameStateRequest* request,
317 agent::GameStateResponse* response) {
318 if (!emulator_)
319 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
320 "Emulator not initialized.");
321
322 emu::GameSnapshot snapshot;
323 auto status = emulator_->GetGameState(&snapshot);
324 if (!status.ok())
325 return ToGrpcStatus(status);
326 emu::ToProtoGameState(snapshot, response);
327
328 // Fill memory reads if requested
329 for (const auto& mem_req : request->memory_reads()) {
330 auto* mem_resp = response->add_memory_responses();
331 mem_resp->set_address(mem_req.address());
332 auto data_or = emulator_->ReadBlock(mem_req.address(), mem_req.size());
333 if (data_or.ok()) {
334 mem_resp->set_data(data_or->data(), data_or->size());
335 }
336 }
337
338#ifdef YAZE_WITH_GRPC
339 if (request->include_screenshot()) {
340 // Never capture here: the emulator updates its texture on the render
341 // thread every frame, and reading the SDL/Metal renderer from this gRPC
342 // thread aborts in endEncoding. The capturer marshals onto that thread.
343 absl::StatusOr<test::ScreenshotArtifact> screenshot =
346 : absl::FailedPreconditionError(
347 "No render-thread screenshot capturer is configured");
348 if (!screenshot.ok()) {
349 LOG_WARN("EmulatorService", "GetGameState screenshot skipped: %s",
350 std::string(screenshot.status().message()).c_str());
351 } else {
352 {
353 std::ifstream file(screenshot->file_path, std::ios::binary);
354 if (file.good()) {
355 std::string png_data((std::istreambuf_iterator<char>(file)),
356 std::istreambuf_iterator<char>());
357 response->set_screenshot_png(png_data);
358 }
359 }
360 // The capture is only a carrier for the reply; don't leave one file
361 // per call on disk.
362 std::error_code remove_error;
363 std::filesystem::remove(screenshot->file_path, remove_error);
364 }
365 }
366#endif
367 return grpc::Status::OK;
368}
369
371 grpc::ServerContext* context, const agent::MemoryRequest* request,
372 agent::MemoryResponse* response) {
373 if (!emulator_)
374 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
375 "Emulator not initialized.");
376
377 response->set_address(request->address());
378 auto data_or = emulator_->ReadBlock(request->address(), request->size());
379 if (!data_or.ok())
380 return ToGrpcStatus(data_or.status());
381
382 response->set_data(data_or->data(), data_or->size());
383 return grpc::Status::OK;
384}
385
387 grpc::ServerContext* context, const agent::MemoryWriteRequest* request,
388 agent::CommandResponse* response) {
389 if (!emulator_)
390 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
391 "Emulator not initialized.");
392
393 std::vector<uint8_t> data(request->data().begin(), request->data().end());
394 auto status = emulator_->WriteBlock(request->address(), data);
395 if (!status.ok())
396 return ToGrpcStatus(status);
397
398 response->set_success(true);
399 return grpc::Status::OK;
400}
401
402// --- Debugging Management ---
403
405 grpc::ServerContext* context,
406 const agent::BreakpointControlRequest* request,
407 agent::BreakpointControlResponse* response) {
408 if (!emulator_)
409 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
410 "Emulator not initialized.");
411
412 std::string action = request->action();
413 if (action == "add") {
414 auto id_or = emulator_->AddBreakpoint(
415 request->address(), emu::FromProtoBreakpointType(request->type()),
416 emu::FromProtoCpuType(request->cpu()), request->condition(),
417 request->description());
418 if (!id_or.ok())
419 return ToGrpcStatus(id_or.status());
420 response->set_breakpoint_id(*id_or);
421 response->set_message("Breakpoint added.");
422 } else if (action == "remove") {
423 auto status = emulator_->RemoveBreakpoint(request->id());
424 if (!status.ok())
425 return ToGrpcStatus(status);
426 response->set_message("Breakpoint removed.");
427 } else if (action == "toggle") {
428 auto status =
429 emulator_->ToggleBreakpoint(request->id(), request->enabled());
430 if (!status.ok())
431 return ToGrpcStatus(status);
432 response->set_message("Breakpoint toggled.");
433 } else if (action == "list") {
434 auto list = emulator_->ListBreakpoints();
435 for (const auto& bp_snap : list) {
436 emu::ToProtoBreakpointInfo(bp_snap, response->add_breakpoints());
437 }
438 } else {
439 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
440 "Unknown action: " + action);
441 }
442
443 response->set_success(true);
444 return grpc::Status::OK;
445}
446
448 grpc::ServerContext* context,
449 const agent::WatchpointControlRequest* request,
450 agent::WatchpointControlResponse* response) {
451 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
452 "WatchpointManager integration pending.");
453}
454
455// --- Analysis & Symbols ---
456
458 grpc::ServerContext* context, const agent::DisassemblyRequest* request,
459 agent::DisassemblyResponse* response) {
460 if (!emulator_)
461 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
462 "Emulator not initialized.");
463
465
466 uint32_t addr = request->start_address();
467 int fetch_size = request->count() * 4;
468 auto data_or = emulator_->ReadBlock(addr, fetch_size);
469 if (!data_or.ok())
470 return ToGrpcStatus(data_or.status());
471
472 const auto& data = *data_or;
473 auto mem_reader = [&](uint32_t read_addr) -> uint8_t {
474 if (read_addr >= addr && read_addr < addr + data.size()) {
475 return data[read_addr - addr];
476 }
477 return 0;
478 };
479
480 emu::CpuStateSnapshot cpu_snap;
481 auto cpu_status = emulator_->GetCpuState(&cpu_snap);
482 if (!cpu_status.ok())
483 return ToGrpcStatus(cpu_status);
484 bool m_flag = (cpu_snap.status & 0x20) != 0;
485 bool x_flag = (cpu_snap.status & 0x10) != 0;
486
487 for (uint32_t i = 0; i < request->count(); ++i) {
488 auto inst = dis.Disassemble(addr, mem_reader, m_flag, x_flag);
489 auto* line = response->add_lines();
490 line->set_address(inst.address);
491 line->set_mnemonic(inst.mnemonic);
492 line->set_operand_str(inst.operand_str);
493 addr += inst.size;
494 if (addr >= request->start_address() + fetch_size)
495 break;
496 }
497 return grpc::Status::OK;
498}
499
501 grpc::ServerContext* context, const agent::TraceRequest* request,
502 agent::TraceResponse* response) {
503 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
504 "Trace not implemented.");
505}
506
508 grpc::ServerContext* context, const agent::SymbolLookupRequest* request,
509 agent::SymbolLookupResponse* response) {
510 auto sym = symbol_provider_.FindSymbol(request->symbol_name());
511 if (sym) {
512 response->set_found(true);
513 response->set_symbol_name(sym->name);
514 response->set_address(sym->address);
515 }
516 return grpc::Status::OK;
517}
518
520 grpc::ServerContext* context, const agent::AddressRequest* request,
521 agent::SymbolLookupResponse* response) {
522 auto sym = symbol_provider_.GetSymbol(request->address());
523 if (sym) {
524 response->set_found(true);
525 response->set_symbol_name(sym->name);
526 response->set_address(sym->address);
527 }
528 return grpc::Status::OK;
529}
530
532 grpc::ServerContext* context, const agent::SymbolFileRequest* request,
533 agent::CommandResponse* response) {
534 auto status = symbol_provider_.LoadSymbolFile(
535 request->filepath(),
536 static_cast<emu::debug::SymbolFormat>(request->format()));
537 response->set_success(status.ok());
538 response->set_message(std::string(status.message()));
539 return grpc::Status::OK;
540}
541
542// --- Session & Experiments ---
543
545 grpc::ServerContext* context, const agent::Empty* request,
546 agent::DebugStatusResponse* response) {
547 if (!emulator_)
548 return grpc::Status(grpc::StatusCode::UNAVAILABLE,
549 "Emulator not initialized.");
550
551 response->set_is_running(emulator_->IsRunning());
552
553 emu::CpuStateSnapshot cpu_snap;
554 auto cpu_status = emulator_->GetCpuState(&cpu_snap);
555 if (!cpu_status.ok())
556 return ToGrpcStatus(cpu_status);
557 emu::ToProtoCpuState(cpu_snap, response->mutable_cpu_state());
558
559 response->set_active_breakpoints(emulator_->ListBreakpoints().size());
560 return grpc::Status::OK;
561}
562
563grpc::Status EmulatorServiceImpl::TestRun(grpc::ServerContext* context,
564 const agent::TestRunRequest* request,
565 agent::TestRunResponse* response) {
566 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
567 "TestRun requires refactoring for IEmulator");
568}
569
570// --- Save State Management ---
571
573 grpc::ServerContext* context, const agent::SaveStateRequest* request,
574 agent::SaveStateResponse* response) {
575 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
576 "SaveState not yet ported to IEmulator");
577}
578
580 grpc::ServerContext* context, const agent::LoadStateRequest* request,
581 agent::LoadStateResponse* response) {
582 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
583 "LoadState not yet ported to IEmulator");
584}
585
587 grpc::ServerContext* context, const agent::ListStatesRequest* request,
588 agent::ListStatesResponse* response) {
589 return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
590 "ListStates not yet ported to IEmulator");
591}
592
593} // namespace yaze::net
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:49
auto size() const
Definition rom.h:200
bool is_loaded() const
Definition rom.h:187
auto title() const
Definition rom.h:199
Abstract interface for emulator backends (Internal vs Mesen2)
Definition i_emulator.h:23
virtual bool IsRunning() const =0
virtual absl::StatusOr< std::vector< uint8_t > > ReadBlock(uint32_t addr, size_t len)=0
virtual void Pause()=0
virtual absl::Status StepOver()=0
virtual absl::Status LoadRom(const std::string &path)=0
virtual void Resume()=0
virtual absl::Status GetCpuState(CpuStateSnapshot *out_state)=0
virtual absl::Status RemoveBreakpoint(uint32_t breakpoint_id)=0
virtual absl::Status ToggleBreakpoint(uint32_t breakpoint_id, bool enabled)=0
virtual absl::Status Step(int count)=0
virtual absl::Status ReleaseButton(InputButton button)=0
virtual absl::Status GetGameState(GameSnapshot *out_state)=0
virtual absl::Status StepOut()=0
virtual std::string GetLoadedRomPath() const =0
virtual bool IsConnected() const =0
virtual absl::Status WriteBlock(uint32_t addr, const std::vector< uint8_t > &data)=0
virtual absl::Status PressButton(InputButton button)=0
virtual std::vector< BreakpointSnapshot > ListBreakpoints()=0
virtual absl::StatusOr< uint32_t > AddBreakpoint(uint32_t addr, BreakpointKind type, CpuKind cpu, const std::string &condition, const std::string &description)=0
virtual absl::Status RunToBreakpoint(BreakpointHitResult *response)=0
virtual void Reset()=0
65816 CPU disassembler for debugging and ROM hacking
DisassembledInstruction Disassemble(uint32_t address, MemoryReader read_byte, bool m_flag=true, bool x_flag=true) const
Disassemble a single instruction.
absl::Status LoadSymbolFile(const std::string &path, SymbolFormat format=SymbolFormat::kAuto)
Load symbols from a .sym file (various formats)
std::optional< Symbol > GetSymbol(uint32_t address) const
Get full symbol info for an address.
std::optional< Symbol > FindSymbol(const std::string &name) const
Find symbol by name.
grpc::Status GetSymbolAt(grpc::ServerContext *context, const agent::AddressRequest *request, agent::SymbolLookupResponse *response) override
std::function< bool(const std::string &path)> RomLoader
grpc::Status ControlEmulator(grpc::ServerContext *context, const agent::ControlRequest *request, agent::CommandResponse *response) override
grpc::Status TestRun(grpc::ServerContext *context, const agent::TestRunRequest *request, agent::TestRunResponse *response) override
grpc::Status GetDebugStatus(grpc::ServerContext *context, const agent::Empty *request, agent::DebugStatusResponse *response) override
grpc::Status WriteMemory(grpc::ServerContext *context, const agent::MemoryWriteRequest *request, agent::CommandResponse *response) override
grpc::Status ReleaseButtons(grpc::ServerContext *context, const agent::ButtonRequest *request, agent::CommandResponse *response) override
grpc::Status PressButtons(grpc::ServerContext *context, const agent::ButtonRequest *request, agent::CommandResponse *response) override
grpc::Status GetGameState(grpc::ServerContext *context, const agent::GameStateRequest *request, agent::GameStateResponse *response) override
grpc::Status BreakpointControl(grpc::ServerContext *context, const agent::BreakpointControlRequest *request, agent::BreakpointControlResponse *response) override
grpc::Status GetDisassembly(grpc::ServerContext *context, const agent::DisassemblyRequest *request, agent::DisassemblyResponse *response) override
grpc::Status LoadSymbols(grpc::ServerContext *context, const agent::SymbolFileRequest *request, agent::CommandResponse *response) override
grpc::Status ReadMemory(grpc::ServerContext *context, const agent::MemoryRequest *request, agent::MemoryResponse *response) override
grpc::Status StepEmulator(grpc::ServerContext *context, const agent::StepControlRequest *request, agent::StepResponse *response) override
grpc::Status HoldButtons(grpc::ServerContext *context, const agent::ButtonHoldRequest *request, agent::CommandResponse *response) override
grpc::Status LoadRom(grpc::ServerContext *context, const agent::LoadRomRequest *request, agent::LoadRomResponse *response) override
grpc::Status GetLoadedRomPath(grpc::ServerContext *context, const agent::Empty *request, agent::LoadedRomPathResponse *response) override
grpc::Status LoadState(grpc::ServerContext *context, const agent::LoadStateRequest *request, agent::LoadStateResponse *response) override
grpc::Status SaveState(grpc::ServerContext *context, const agent::SaveStateRequest *request, agent::SaveStateResponse *response) override
grpc::Status ResolveSymbol(grpc::ServerContext *context, const agent::SymbolLookupRequest *request, agent::SymbolLookupResponse *response) override
emu::debug::SymbolProvider symbol_provider_
grpc::Status ListStates(grpc::ServerContext *context, const agent::ListStatesRequest *request, agent::ListStatesResponse *response) override
grpc::Status GetExecutionTrace(grpc::ServerContext *context, const agent::TraceRequest *request, agent::TraceResponse *response) override
grpc::Status RunToBreakpoint(grpc::ServerContext *context, const agent::Empty *request, agent::BreakpointHitResponse *response) override
EmulatorServiceImpl(emu::IEmulator *emulator, RomGetter rom_getter=nullptr, RomLoader rom_loader=nullptr)
grpc::Status WatchpointControl(grpc::ServerContext *context, const agent::WatchpointControlRequest *request, agent::WatchpointControlResponse *response) override
#define LOG_WARN(category, format,...)
Definition log.h:138
SymbolFormat
Supported symbol file formats.