48 LOG_INFO(
"App",
"Initializing Application instance...");
63 LOG_INFO(
"App",
"Found pending ROM load: %s", start_path.c_str());
64 }
else if (!start_path.empty()) {
65 LOG_INFO(
"App",
"Using configured startup ROM: %s", start_path.c_str());
67 LOG_INFO(
"App",
"No pending ROM, starting empty.");
70 LOG_INFO(
"App",
"WASM build - ROM loading handled via wasm_bootstrap queue.");
78 LOG_ERROR(
"App",
"Failed to initialize controller: %s",
79 std::string(status.message()).c_str());
85 LOG_INFO(
"App",
"Controller initialized successfully. Active: %s",
91 const std::string& preferred_path,
92 test::TestManager::FailureScreenshotCallback callback) {
93 controller->RequestScreenshot({.preferred_path = preferred_path,
94 .reveal_to_user = false,
95 .callback = std::move(callback)});
104 if (!start_path.empty() &&
controller_->editor_manager()) {
111 LOG_INFO(
"App",
"Initializing Unified gRPC Server...");
112 canvas_automation_service_ =
113 std::make_unique<CanvasAutomationServiceImpl>();
114 grpc_server_ = std::make_unique<YazeGRPCServer>();
116 auto rom_getter = [
this]() {
119 auto rom_loader = [
this](
const std::string& path) ->
bool {
122 auto status =
controller_->editor_manager()->OpenRomOrProject(path);
129 LOG_INFO(
"App",
"Using Mesen2 backend for emulator service");
131 std::make_unique<emu::mesen::MesenEmulatorAdapter>();
132 emulator_interface = emulator_backend_.get();
136 internal_emulator = &
controller_->editor_manager()->emulator();
139 "EditorManager not ready; internal emulator services may be "
144 std::make_unique<emu::InternalEmulatorAdapter>(internal_emulator);
147 adapter->SetRomLoader([
this](
const std::string& path) ->
bool {
150 auto status =
controller_->editor_manager()->OpenRomOrProject(path);
154 adapter->SetRomGetter(
155 [
this]() {
return controller_->GetCurrentRom(); });
157 emulator_backend_ = std::move(adapter);
158 emulator_interface = emulator_backend_.get();
162 auto status = grpc_server_->Initialize(
167 canvas_automation_service_.get());
170 status = grpc_server_->StartAsync();
172 LOG_ERROR(
"App",
"Failed to start gRPC server: %s",
173 std::string(status.message()).c_str());
175 LOG_INFO(
"App",
"Unified gRPC server started on port %d",
179 LOG_ERROR(
"App",
"Failed to initialize gRPC server: %s",
180 std::string(status.message()).c_str());
184 if (canvas_automation_service_) {
186 canvas_automation_service_.get());
194 yaze::app::wasm::SetRomLoadHandler(
200 const char* runtime_dir = std::getenv(
"XDG_RUNTIME_DIR");
201 const char* status_dir = (runtime_dir && *runtime_dir) ? runtime_dir :
"/tmp";
202 activity_file_ = std::make_unique<app::ActivityFile>(
203 absl::StrFormat(
"%s/yaze-%d.status", status_dir, pid));
204 UpdateActivityStatus();
205 LOG_INFO(
"App",
"Activity file created: %s",
206 activity_file_->GetPath().c_str());
210void Application::Tick() {
215 auto now = std::chrono::steady_clock::now();
217 delta_time_ = 0.016f;
218 first_frame_ =
false;
220 auto elapsed = std::chrono::duration<float>(now - last_frame_time_);
221 delta_time_ = elapsed.count();
223 last_frame_time_ = now;
226 if (
auto* bus = editor::ContentRegistry::Context::event_bus()) {
227 bus->Publish(editor::FrameBeginEvent::Create(delta_time_));
231 auto& wasm_collab = app::platform::GetWasmCollaborationInstance();
232 wasm_collab.ProcessPendingChanges();
235 controller_->OnInput();
236 auto status = controller_->OnLoad();
238 LOG_ERROR(
"App",
"Controller Load Error: %s",
239 std::string(status.message()).c_str());
241 emscripten_cancel_main_loop();
246 if (!controller_->IsActive()) {
251 controller_->DoRender();
254 if (
auto* bus = editor::ContentRegistry::Context::event_bus()) {
255 bus->Publish(editor::FrameEndEvent::Create(delta_time_));
259void Application::LoadRom(
const std::string& path) {
260 LOG_INFO(
"App",
"Requesting ROM load: %s", path.c_str());
264 yaze::app::wasm::TriggerRomLoad(path);
266 "Forwarded to wasm_bootstrap queue (controller not ready): %s",
270 LOG_INFO(
"App",
"Queued ROM load (controller not ready): %s", path.c_str());
277 if (!controller_->IsActive()) {
278 status = controller_->OnEntry(path);
280 status = controller_->editor_manager()->OpenRomOrProject(path);
284 std::string error_msg =
285 absl::StrCat(
"Failed to load ROM: ", status.message());
286 LOG_ERROR(
"App",
"%s", error_msg.c_str());
291 var msg = UTF8ToString($0);
298 LOG_INFO(
"App",
"ROM loaded successfully: %s", path.c_str());
307#ifndef __EMSCRIPTEN__
309 UpdateActivityStatus();
314 { console.log(
"ROM loaded successfully: " + UTF8ToString($0)); },
329void Application::UpdateActivityStatus() {
334 status.
pid = getpid();
338 if (controller_ && controller_->editor_manager()) {
339 auto* rom = controller_->GetCurrentRom();
344 if (config_.enable_test_harness && config_.test_harness_port > 0) {
346 absl::StrFormat(
"localhost:%d", config_.test_harness_port);
350 activity_file_->Update(status);
358void Application::Shutdown() {
361 LOG_INFO(
"App",
"Syncing filesystem before shutdown...");
367 LOG_INFO(
"App",
"Shutting down Unified gRPC Server...");
368 grpc_server_->Shutdown();
369 grpc_server_.reset();
371 canvas_automation_service_.reset();
372 test::TestManager::Get().SetFailureScreenshotRequester({});
375#ifndef __EMSCRIPTEN__
377 if (activity_file_) {
378 LOG_INFO(
"App",
"Removing activity file: %s",
379 activity_file_->GetPath().c_str());
380 activity_file_.reset();
385 controller_->OnExit();