yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
yaze_debug_inspector.cc
Go to the documentation of this file.
1
9#include <emscripten.h>
10#include <emscripten/bind.h>
11
12#include <atomic>
13#include <iomanip>
14#include <sstream>
15#include <unordered_map>
16
17#include "yaze.h" // For YAZE_VERSION_STRING
18#include "app/emu/emulator.h"
19#include "app/emu/snes.h"
20#include "app/emu/video/ppu.h"
22#include "rom/rom.h"
24#include "zelda3/game_data.h"
25
27#include "app/editor/editor.h"
33#include "nlohmann/json.hpp"
34
35using namespace emscripten;
36
37// External function to get the global ROM (defined in wasm_terminal_bridge.cc)
38namespace yaze::cli {
39extern Rom* GetGlobalRom();
40}
41
42// External function to get the global emulator (defined in main.cc)
43namespace yaze::app {
44extern emu::Emulator* GetGlobalEmulator();
45extern editor::EditorManager* GetGlobalEditorManager();
46}
47
48extern "C" {
49// Forward declaration of Z3edProcessCommand from wasm_terminal_bridge.cc
50const char* Z3edProcessCommand(const char* command);
51}
52
53// Helper function to get the emulator for this file
54namespace {
58
59// Helper to access the live EditorManager without repeating the namespace
63
64// =============================================================================
65// AI Driver Bridge (WASM <-> JS)
66// =============================================================================
67
68// JS function to call the AI Manager
69EM_JS(void, CallJsAiDriver, (const char* history_json), {
70 if (window.yaze && window.yaze.ai && window.yaze.ai.processAgentRequest) {
71 window.yaze.ai.processAgentRequest(UTF8ToString(history_json));
72 } else {
73 console.error("AI Driver not found in window.yaze.ai.processAgentRequest");
74 // Try to recover or notify C++
75 }
76});
77
78// Helper to serialize ChatMessage
79nlohmann::json MessageToJson(const yaze::cli::agent::ChatMessage& msg) {
80 nlohmann::json j;
81 j["role"] = (msg.sender == yaze::cli::agent::ChatMessage::Sender::kUser) ? "user" : "model";
82
83 // Convert parts (text, internal logs)
84 // Simplification: just send message content for now
85 j["parts"] = nlohmann::json::array({ {{"text", msg.message}} });
86
87 return j;
88}
89
90// Register the external driver for the active session
92 auto* manager = GetEditorManager();
93 if (!manager) return "{\"error\":\"EditorManager not available\"}";
94
95 auto* agent_ui = manager->GetAgentUiController();
96 if (!agent_ui) return "{\"error\":\"AgentUiController not available\"}";
97
98#if defined(YAZE_BUILD_AGENT_UI)
99 auto& sessions = agent_ui->GetSessionManager();
100
101 // Get the active session (AgentSessionManager creates a session on startup)
102 // This is more reliable than looking for a "default" session ID
103 yaze::editor::AgentSession* session = sessions.GetActiveSession();
104 if (!session) {
105 // Fallback: if no active session but sessions exist, use the first one
106 // This shouldn't happen normally since the constructor creates an active session
107 if (sessions.GetSessionCount() == 0) {
108 return "{\"error\":\"No agent sessions available\"}";
109 }
110 // Get the first session as fallback
111 auto& all_sessions = sessions.GetAllSessions();
112 if (all_sessions.empty()) {
113 return "{\"error\":\"No agent sessions available\"}";
114 }
115 session = &all_sessions[0];
116 }
117
118 // Access agent service through AgentEditor -> AgentChat
119 // The new architecture doesn't store agent_service directly in AgentSession
120 auto* agent_editor = manager->GetAgentEditor();
121 if (!agent_editor) {
122 return "{\"error\":\"AgentEditor not available\"}";
123 }
124
125 auto* agent_chat = agent_editor->GetAgentChat();
126 if (!agent_chat) {
127 return "{\"error\":\"AgentChat not available\"}";
128 }
129
130 auto* agent_service = agent_chat->GetAgentService();
131 if (!agent_service) {
132 return "{\"error\":\"AgentService not available\"}";
133 }
134
135 agent_service->SetExternalDriver([](const std::vector<yaze::cli::agent::ChatMessage>& history) {
136 nlohmann::json j_history = nlohmann::json::array();
137 for (const auto& msg : history) {
138 j_history.push_back(MessageToJson(msg));
139 }
140 CallJsAiDriver(j_history.dump().c_str());
141 });
142
143 return "{\"success\":true}";
144#else
145 return "{\"error\":\"Agent UI disabled in build\"}";
146#endif
147}
148
149// Handle response from JS
150void onExternalAiResponse(std::string response_json) {
151 auto* manager = GetEditorManager();
152 if (!manager) return;
153 auto* agent_ui = manager->GetAgentUiController();
154 if (!agent_ui) return;
155
156#if defined(YAZE_BUILD_AGENT_UI)
157 auto& sessions = agent_ui->GetSessionManager();
158 auto* session = sessions.GetSession("default");
159 if (!session) return;
160
161 // Access agent service through AgentEditor -> AgentChat
162 auto* agent_editor = manager->GetAgentEditor();
163 if (!agent_editor) return;
164
165 auto* agent_chat = agent_editor->GetAgentChat();
166 if (!agent_chat) return;
167
168 auto* agent_service = agent_chat->GetAgentService();
169 if (!agent_service) return;
170
171 try {
172 auto j = nlohmann::json::parse(response_json);
174
175 if (j.contains("text")) response.text_response = j["text"].get<std::string>();
176
177 // Parse tool calls
178 if (j.contains("tool_calls")) {
179 for (const auto& tc : j["tool_calls"]) {
181 call.tool_name = tc["name"].get<std::string>();
182 if (tc.contains("args")) {
183 for (const auto& [k, v] : tc["args"].items()) {
184 call.args[k] = v.is_string() ? v.get<std::string>() : v.dump();
185 }
186 }
187 response.tool_calls.push_back(call);
188 }
189 }
190
191 agent_service->HandleExternalResponse(response);
192
193 } catch (const std::exception& e) {
194 printf("Error parsing AI response: %s\n", e.what());
195 }
196#endif
197}
198
199// =============================================================================
200// Async Operation Tracking
201// =============================================================================
202
203// Operation status for async API calls
204std::atomic<uint32_t> g_operation_counter{0};
205std::unordered_map<uint32_t, std::string> g_pending_operations;
206
207// Parse editor name to EditorType - supports all editor types
209 static const std::unordered_map<std::string, yaze::editor::EditorType>
210 kEditorMap = {
221 {"Text", yaze::editor::EditorType::kMessage}, // Alias
225 };
226 auto it = kEditorMap.find(name);
227 return it != kEditorMap.end() ? it->second
229}
230
231} // namespace
232
233// =============================================================================
234// Editor State Functions
235// =============================================================================
236
237std::string getEditorState() {
238 std::ostringstream json;
239 auto* manager = yaze::app::GetGlobalEditorManager();
240
241 if (!manager) {
242 return "{\"error\":\"EditorManager not available\"}";
243 }
244
245 auto* editor = manager->GetCurrentEditor();
246
247 json << "{";
248 json << "\"active_editor\":\"" << (editor ? yaze::editor::kEditorNames[(int)editor->type()] : "None") << "\",";
249 json << "\"session_id\":" << manager->GetCurrentSessionId() << ",";
250 json << "\"rom_loaded\":" << (manager->GetCurrentRom() && manager->GetCurrentRom()->is_loaded() ? "true" : "false");
251
252 if (editor && editor->type() == yaze::editor::EditorType::kDungeon) {
253 // We can't easily cast to DungeonEditorV2 here without circular deps or massive includes
254 // But we can check if it exposes state via base class if we added virtuals? No.
255 // For now, just knowing it's the Dungeon Editor is a big help.
256 }
257
258 json << "}";
259 return json.str();
260}
261
262std::string executeCommand(std::string command) {
263 // Wrapper around Z3edProcessCommand for easier JS usage
264 const char* result = Z3edProcessCommand(command.c_str());
265 return result ? std::string(result) : "";
266}
267
268std::string switchToEditor(std::string editor_name) {
269 auto* manager = yaze::app::GetGlobalEditorManager();
270 if (!manager) {
271 return "{\"error\":\"EditorManager not available\"}";
272 }
273
274 // Parse editor type using the helper that supports all editors
275 auto editor_type = ParseEditorType(editor_name);
276 if (editor_type == yaze::editor::EditorType::kUnknown) {
277 return "{\"error\":\"Unknown editor name. Valid names: Assembly, Dungeon, "
278 "Emulator, Graphics, Music, Overworld, Palette, Screen, Sprite, "
279 "Message, Text, Hex, Agent, Settings\"}";
280 }
281
282 // Check if ROM is loaded (required for most editors)
283 auto* rom = manager->GetCurrentRom();
284 if (!rom || !rom->is_loaded()) {
285 // Some editors don't require ROM (Settings, Agent)
286 if (editor_type != yaze::editor::EditorType::kSettings &&
287 editor_type != yaze::editor::EditorType::kAgent) {
288 return "{\"error\":\"ROM not loaded\",\"editor\":\"" + editor_name +
289 "\"}";
290 }
291 }
292
293 manager->SwitchToEditor(editor_type);
294 return "{\"success\":true,\"editor\":\"" + editor_name +
295 "\",\"note\":\"Action may be deferred to next frame\"}";
296}
297
298// =============================================================================
299// Async Editor Switching API
300// =============================================================================
301
312std::string switchToEditorAsync(std::string editor_name) {
313 uint32_t op_id = g_operation_counter++;
314
315 auto* manager = yaze::app::GetGlobalEditorManager();
316 if (!manager) {
317 return "{\"error\":\"EditorManager not available\",\"op_id\":" +
318 std::to_string(op_id) + "}";
319 }
320
321 // Parse editor type
322 auto editor_type = ParseEditorType(editor_name);
323 if (editor_type == yaze::editor::EditorType::kUnknown) {
324 return "{\"error\":\"Unknown editor name\",\"op_id\":" +
325 std::to_string(op_id) + "}";
326 }
327
328 // Check ROM loaded (except for Settings/Agent)
329 auto* rom = manager->GetCurrentRom();
330 if (!rom || !rom->is_loaded()) {
331 if (editor_type != yaze::editor::EditorType::kSettings &&
332 editor_type != yaze::editor::EditorType::kAgent) {
333 return "{\"error\":\"ROM not loaded\",\"op_id\":" +
334 std::to_string(op_id) + "}";
335 }
336 }
337
338 // Mark operation as pending
339 g_pending_operations[op_id] = "pending";
340
341 // Queue the deferred action with completion callback
342 manager->QueueDeferredAction([op_id, editor_type, editor_name, manager]() {
343 // Check EditorSet exists
344 auto* editor_set = manager->GetCurrentEditorSet();
345 if (!editor_set) {
346 g_pending_operations[op_id] = "error:No editor set available";
347 return;
348 }
349
350 // Perform the switch
351 manager->SwitchToEditor(editor_type);
352 g_pending_operations[op_id] = "completed:" + editor_name;
353 });
354
355 return "{\"op_id\":" + std::to_string(op_id) +
356 ",\"status\":\"pending\",\"editor\":\"" + editor_name + "\"}";
357}
358
365std::string getOperationStatus(uint32_t op_id) {
366 auto it = g_pending_operations.find(op_id);
367 if (it == g_pending_operations.end()) {
368 return "{\"error\":\"Unknown operation ID\",\"op_id\":" +
369 std::to_string(op_id) + "}";
370 }
371
372 const std::string& status = it->second;
373 std::ostringstream json;
374 json << "{\"op_id\":" << op_id << ",";
375
376 if (status == "pending") {
377 json << "\"status\":\"pending\"}";
378 } else if (status.rfind("completed:", 0) == 0) {
379 // Extract editor name from "completed:EditorName"
380 std::string editor = status.substr(10);
381 json << "\"status\":\"completed\",\"editor\":\"" << editor << "\"}";
382 // Clean up completed operations (keep last 100)
383 if (g_pending_operations.size() > 100) {
384 // Simple cleanup: remove this one since it's done
385 g_pending_operations.erase(it);
386 }
387 } else if (status.rfind("error:", 0) == 0) {
388 // Extract error message from "error:message"
389 std::string error_msg = status.substr(6);
390 json << "\"status\":\"error\",\"error\":\"" << error_msg << "\"}";
391 g_pending_operations.erase(it);
392 } else {
393 json << "\"status\":\"" << status << "\"}";
394 }
395
396 return json.str();
397}
398
399// =============================================================================
400// Panel Control API
401// =============================================================================
402
406static const std::unordered_map<std::string, std::vector<std::string>>
407 kPanelGroups = {
408 {"dungeon_editing",
409 {"dungeon.room_selector", "dungeon.object_editor",
410 "dungeon.tile_selector"}},
411 {"dungeon_debug",
412 {"dungeon.room_selector", "dungeon.palette_debug"}},
413 {"overworld_editing",
414 {"overworld.map_selector", "overworld.tile_selector",
415 "overworld.entity_editor"}},
416 {"graphics_editing",
417 {"graphics.sheet_viewer", "graphics.tile_editor",
418 "graphics.palette_editor"}},
419 {"minimal", {}}, // Empty = hide all
420};
421
427std::string showPanel(std::string card_id) {
428 auto* manager = yaze::app::GetGlobalEditorManager();
429 if (!manager) {
430 return "{\"error\":\"EditorManager not available\"}";
431 }
432
433 // Access card registry through the member function
434 // Note: We need to use the public interface
435 auto& card_registry = manager->card_registry();
436 bool success = card_registry.ShowPanel(card_id);
437
438 if (success) {
439 return "{\"success\":true,\"card\":\"" + card_id + "\"}";
440 } else {
441 return "{\"error\":\"Panel not found\",\"card\":\"" + card_id + "\"}";
442 }
443}
444
448std::string hidePanel(std::string card_id) {
449 auto* manager = yaze::app::GetGlobalEditorManager();
450 if (!manager) {
451 return "{\"error\":\"EditorManager not available\"}";
452 }
453
454 auto& card_registry = manager->card_registry();
455 bool success = card_registry.HidePanel(card_id);
456
457 if (success) {
458 return "{\"success\":true,\"card\":\"" + card_id + "\"}";
459 } else {
460 return "{\"error\":\"Panel not found\",\"card\":\"" + card_id + "\"}";
461 }
462}
463
467std::string togglePanel(std::string card_id) {
468 auto* manager = yaze::app::GetGlobalEditorManager();
469 if (!manager) {
470 return "{\"error\":\"EditorManager not available\"}";
471 }
472
473 auto& card_registry = manager->card_registry();
474
475 // Get current visibility first
476 bool was_visible = card_registry.IsPanelVisible(card_id);
477
478 // Toggle
479 bool success;
480 if (was_visible) {
481 success = card_registry.HidePanel(card_id);
482 } else {
483 success = card_registry.ShowPanel(card_id);
484 }
485
486 if (success) {
487 return "{\"success\":true,\"card\":\"" + card_id +
488 "\",\"visible\":" + (was_visible ? "false" : "true") + "}";
489 } else {
490 return "{\"error\":\"Panel not found\",\"card\":\"" + card_id + "\"}";
491 }
492}
493
498std::string getPanelState() {
499 auto* manager = yaze::app::GetGlobalEditorManager();
500 if (!manager) {
501 return "{\"error\":\"EditorManager not available\"}";
502 }
503
504 auto& card_registry = manager->card_registry();
505 size_t session_id = manager->GetCurrentSessionId();
506
507 std::ostringstream json;
508 json << "{\"session_id\":" << session_id << ",";
509 json << "\"active_category\":\"" << card_registry.GetActiveCategory() << "\",";
510 json << "\"cards\":[";
511
512 // Get all categories and iterate through cards
513 auto categories = card_registry.GetAllCategories(session_id);
514 bool first_card = true;
515
516 for (const auto& category : categories) {
517 auto cards = card_registry.GetPanelsInCategory(session_id, category);
518 for (const auto& card : cards) {
519 if (!first_card) json << ",";
520 first_card = false;
521
522 json << "{";
523 json << "\"id\":\"" << card.card_id << "\",";
524 json << "\"name\":\"" << card.display_name << "\",";
525 json << "\"category\":\"" << card.category << "\",";
526 json << "\"visible\":"
527 << (card_registry.IsPanelVisible(session_id, card.card_id) ? "true"
528 : "false");
529 json << "}";
530 }
531 }
532
533 json << "]}";
534 return json.str();
535}
536
540std::string getPanelsInCategory(std::string category) {
541 auto* manager = yaze::app::GetGlobalEditorManager();
542 if (!manager) {
543 return "{\"error\":\"EditorManager not available\"}";
544 }
545
546 auto& card_registry = manager->card_registry();
547 size_t session_id = manager->GetCurrentSessionId();
548 auto cards = card_registry.GetPanelsInCategory(session_id, category);
549
550 std::ostringstream json;
551 json << "{\"category\":\"" << category << "\",\"cards\":[";
552
553 bool first = true;
554 for (const auto& card : cards) {
555 if (!first) json << ",";
556 first = false;
557
558 json << "{";
559 json << "\"id\":\"" << card.card_id << "\",";
560 json << "\"name\":\"" << card.display_name << "\",";
561 json << "\"visible\":"
562 << (card_registry.IsPanelVisible(session_id, card.card_id) ? "true"
563 : "false");
564 json << "}";
565 }
566
567 json << "]}";
568 return json.str();
569}
570
574std::string showPanelGroup(std::string group_name) {
575 auto* manager = yaze::app::GetGlobalEditorManager();
576 if (!manager) {
577 return "{\"error\":\"EditorManager not available\"}";
578 }
579
580 auto it = kPanelGroups.find(group_name);
581 if (it == kPanelGroups.end()) {
582 std::ostringstream groups;
583 groups << "dungeon_editing, dungeon_debug, overworld_editing, "
584 "graphics_editing, minimal";
585 return "{\"error\":\"Unknown group. Available: " + groups.str() + "\"}";
586 }
587
588 auto& card_registry = manager->card_registry();
589 const auto& card_ids = it->second;
590
591 // Show all cards in the group
592 int shown = 0;
593 for (const auto& card_id : card_ids) {
594 if (card_registry.ShowPanel(card_id)) {
595 shown++;
596 }
597 }
598
599 return "{\"success\":true,\"group\":\"" + group_name +
600 "\",\"cards_shown\":" + std::to_string(shown) + "}";
601}
602
606std::string hidePanelGroup(std::string group_name) {
607 auto* manager = yaze::app::GetGlobalEditorManager();
608 if (!manager) {
609 return "{\"error\":\"EditorManager not available\"}";
610 }
611
612 auto it = kPanelGroups.find(group_name);
613 if (it == kPanelGroups.end()) {
614 return "{\"error\":\"Unknown group\"}";
615 }
616
617 auto& card_registry = manager->card_registry();
618 const auto& card_ids = it->second;
619
620 // Special case: "minimal" hides all cards in active session
621 if (group_name == "minimal") {
622 card_registry.HideAll();
623 return "{\"success\":true,\"group\":\"minimal\",\"action\":\"hid_all\"}";
624 }
625
626 // Hide all cards in the group
627 int hidden = 0;
628 for (const auto& card_id : card_ids) {
629 if (card_registry.HidePanel(card_id)) {
630 hidden++;
631 }
632 }
633
634 return "{\"success\":true,\"group\":\"" + group_name +
635 "\",\"cards_hidden\":" + std::to_string(hidden) + "}";
636}
637
641std::string getPanelGroups() {
642 std::ostringstream json;
643 json << "{\"groups\":[";
644
645 bool first = true;
646 for (const auto& [name, cards] : kPanelGroups) {
647 if (!first) json << ",";
648 first = false;
649
650 json << "{\"name\":\"" << name << "\",\"cards\":[";
651 bool first_card = true;
652 for (const auto& card_id : cards) {
653 if (!first_card) json << ",";
654 first_card = false;
655 json << "\"" << card_id << "\"";
656 }
657 json << "]}";
658 }
659
660 json << "]}";
661 return json.str();
662}
663
664// =============================================================================
665// Sidebar View Mode Functions
666// =============================================================================
667
672 auto* editor_manager = GetEditorManager();
673 if (!editor_manager) return false;
674 // Map legacy \"tree\" terminology to the new expanded side panel state
675 return editor_manager->card_registry().IsPanelExpanded();
676}
677
681std::string setTreeViewMode(bool enabled) {
682 auto* editor_manager = GetEditorManager();
683 if (!editor_manager) {
684 return R"({"success":false,"error":"Editor manager not available"})";
685 }
686 // Tree mode previously meant expanded sidebar; map to panel expansion
687 editor_manager->card_registry().SetPanelExpanded(enabled);
688 return enabled ? R"({"success":true,"mode":"tree"})"
689 : R"({"success":true,"mode":"icon"})";
690}
691
695std::string toggleTreeViewMode() {
696 auto* editor_manager = GetEditorManager();
697 if (!editor_manager) {
698 return R"({"success":false,"error":"Editor manager not available"})";
699 }
700 auto& registry = editor_manager->card_registry();
701 registry.TogglePanelExpanded();
702 bool is_expanded = registry.IsPanelExpanded();
703 return is_expanded ? R"({"success":true,"mode":"tree"})"
704 : R"({"success":true,"mode":"icon"})";
705}
706
710std::string getSidebarState() {
711 auto* editor_manager = GetEditorManager();
712 if (!editor_manager) {
713 return R"({"available":false})";
714 }
715
716 auto& registry = editor_manager->card_registry();
717 bool is_expanded = registry.IsPanelExpanded();
718 bool is_visible = registry.IsSidebarVisible();
719
720 float width = 0.0f;
721 if (is_visible) {
723 if (is_expanded) {
725 }
726 }
727
728 std::ostringstream json;
729 json << "{\"available\":true,";
730 json << "\"mode\":\"" << (is_expanded ? "tree" : "icon") << "\",";
731 json << "\"width\":" << width << ",";
732 json << "\"collapsed\":" << (is_visible ? "false" : "true") << "}";
733 return json.str();
734}
735
736// =============================================================================
737// Right Panel Functions
738// =============================================================================
739
743std::string openRightPanel(std::string panel_name) {
744 auto* editor_manager = GetEditorManager();
745 if (!editor_manager) {
746 return R"({"success":false,"error":"Editor manager not available"})";
747 }
748
749 auto* right_panel = editor_manager->right_panel_manager();
750 if (!right_panel) {
751 return R"({"success":false,"error":"Right panel manager not available"})";
752 }
753
755 PanelType type = PanelType::kNone;
756
757 if (panel_name == "properties") {
758 type = PanelType::kProperties;
759 } else if (panel_name == "agent" || panel_name == "chat") {
760 type = PanelType::kAgentChat;
761 } else if (panel_name == "proposals") {
762 type = PanelType::kProposals;
763 } else if (panel_name == "settings") {
764 type = PanelType::kSettings;
765 } else if (panel_name == "help") {
766 type = PanelType::kHelp;
767 } else {
768 return R"({"success":false,"error":"Unknown panel type"})";
769 }
770
771 right_panel->OpenPanel(type);
772 return R"({"success":true,"panel":")" + panel_name + R"("})";
773}
774
778std::string closeRightPanel() {
779 auto* editor_manager = GetEditorManager();
780 if (!editor_manager) {
781 return R"({"success":false,"error":"Editor manager not available"})";
782 }
783
784 auto* right_panel = editor_manager->right_panel_manager();
785 if (!right_panel) {
786 return R"({"success":false,"error":"Right panel manager not available"})";
787 }
788
789 right_panel->ClosePanel();
790 return R"({"success":true})";
791}
792
796std::string toggleRightPanel(std::string panel_name) {
797 auto* editor_manager = GetEditorManager();
798 if (!editor_manager) {
799 return R"({"success":false,"error":"Editor manager not available"})";
800 }
801
802 auto* right_panel = editor_manager->right_panel_manager();
803 if (!right_panel) {
804 return R"({"success":false,"error":"Right panel manager not available"})";
805 }
806
808 PanelType type = PanelType::kNone;
809
810 if (panel_name == "properties") {
811 type = PanelType::kProperties;
812 } else if (panel_name == "agent" || panel_name == "chat") {
813 type = PanelType::kAgentChat;
814 } else if (panel_name == "proposals") {
815 type = PanelType::kProposals;
816 } else if (panel_name == "settings") {
817 type = PanelType::kSettings;
818 } else if (panel_name == "help") {
819 type = PanelType::kHelp;
820 } else {
821 return R"({"success":false,"error":"Unknown panel type"})";
822 }
823
824 right_panel->TogglePanel(type);
825 bool is_open = right_panel->IsPanelActive(type);
826 return is_open ? R"({"success":true,"state":"open","panel":")" + panel_name +
827 R"("})"
828 : R"({"success":true,"state":"closed"})";
829}
830
834std::string getRightPanelState() {
835 auto* editor_manager = GetEditorManager();
836 if (!editor_manager) {
837 return R"({"available":false})";
838 }
839
840 auto* right_panel = editor_manager->right_panel_manager();
841 if (!right_panel) {
842 return R"({"available":false})";
843 }
844
846 auto active = right_panel->GetActivePanel();
847
848 std::string active_name = "none";
849 switch (active) {
850 case PanelType::kProperties:
851 active_name = "properties";
852 break;
853 case PanelType::kAgentChat:
854 active_name = "agent";
855 break;
856 case PanelType::kProposals:
857 active_name = "proposals";
858 break;
859 case PanelType::kSettings:
860 active_name = "settings";
861 break;
862 case PanelType::kHelp:
863 active_name = "help";
864 break;
865 default:
866 break;
867 }
868
869 std::ostringstream json;
870 json << "{\"available\":true,";
871 json << "\"active\":\"" << active_name << "\",";
872 json << "\"expanded\":" << (right_panel->IsPanelExpanded() ? "true" : "false")
873 << ",";
874 json << "\"width\":" << right_panel->GetPanelWidth() << "}";
875 return json.str();
876}
877
878// =============================================================================
879// Palette Debug Functions
880// =============================================================================
881
883 return yaze::zelda3::PaletteDebugger::Get().ExportToJSON();
884}
885
886std::string getColorComparisons() {
887 return yaze::zelda3::PaletteDebugger::Get().ExportColorComparisonsJSON();
888}
889
890std::string samplePixelAt(int x, int y) {
891 return yaze::zelda3::PaletteDebugger::Get().SamplePixelJSON(x, y);
892}
893
897
898// AI analysis functions for Gemini/Antigravity integration
899std::string getFullPaletteState() {
900 return yaze::zelda3::PaletteDebugger::Get().ExportFullStateJSON();
901}
902
903std::string getPaletteData() {
904 return yaze::zelda3::PaletteDebugger::Get().ExportPaletteDataJSON();
905}
906
907std::string getEventTimeline() {
908 return yaze::zelda3::PaletteDebugger::Get().ExportTimelineJSON();
909}
910
911std::string getDiagnosticSummary() {
912 return yaze::zelda3::PaletteDebugger::Get().GetDiagnosticSummary();
913}
914
916 return yaze::zelda3::PaletteDebugger::Get().GetHypothesisAnalysis();
917}
918
919// =============================================================================
920// Graphics Arena Debug Functions
921// =============================================================================
922
923std::string getArenaStatus() {
924 std::ostringstream json;
925 auto& arena = yaze::gfx::Arena::Get();
926
927 json << "{";
928 json << "\"texture_queue_size\":" << arena.texture_command_queue_size()
929 << ",";
930
931 // Get info about graphics sheets
932 json << "\"gfx_sheets\":[";
933 bool first = true;
934 for (int i = 0; i < 223; i++) {
935 auto sheet = arena.gfx_sheet(i); // Returns by value
936 if (sheet.is_active()) {
937 if (!first) json << ",";
938 json << "{\"index\":" << i << ",\"width\":" << sheet.width()
939 << ",\"height\":" << sheet.height()
940 << ",\"has_texture\":" << (sheet.texture() != nullptr ? "true" : "false")
941 << ",\"has_surface\":" << (sheet.surface() != nullptr ? "true" : "false")
942 << "}";
943 first = false;
944 }
945 }
946 json << "]";
947 json << "}";
948
949 return json.str();
950}
951
952std::string getGfxSheetInfo(int index) {
953 if (index < 0 || index >= 223) {
954 return "{\"error\": \"Invalid sheet index\"}";
955 }
956
957 std::ostringstream json;
958 auto& arena = yaze::gfx::Arena::Get();
959 auto sheet = arena.gfx_sheet(index); // Returns by value
960
961 json << "{";
962 json << "\"index\":" << index << ",";
963 json << "\"active\":" << (sheet.is_active() ? "true" : "false") << ",";
964 json << "\"width\":" << sheet.width() << ",";
965 json << "\"height\":" << sheet.height() << ",";
966 json << "\"has_texture\":" << (sheet.texture() != nullptr ? "true" : "false")
967 << ",";
968 json << "\"has_surface\":" << (sheet.surface() != nullptr ? "true" : "false");
969
970 // If surface exists, get palette info
971 if (sheet.surface() && sheet.surface()->format) {
972 auto* fmt = sheet.surface()->format;
973 json << ",\"surface_format\":" << fmt->format;
974 if (fmt->palette) {
975 json << ",\"palette_colors\":" << fmt->palette->ncolors;
976 }
977 }
978
979 json << "}";
980 return json.str();
981}
982
983// =============================================================================
984// ROM Debug Functions
985// =============================================================================
986
987std::string getRomStatus() {
988 std::ostringstream json;
989 auto* rom = yaze::cli::GetGlobalRom();
990
991 json << "{";
992
993 if (!rom) {
994 json << "\"loaded\":false,\"error\":\"No ROM loaded\"";
995 } else {
996 json << "\"loaded\":" << (rom->is_loaded() ? "true" : "false") << ",";
997 json << "\"size\":" << rom->size() << ",";
998 json << "\"title\":\"" << rom->title() << "\"";
999 }
1000
1001 json << "}";
1002 return json.str();
1003}
1004
1005std::string readRomBytes(int address, int count) {
1006 std::ostringstream json;
1007 auto* rom = yaze::cli::GetGlobalRom();
1008
1009 if (!rom || !rom->is_loaded()) {
1010 return "{\"error\":\"No ROM loaded\"}";
1011 }
1012
1013 if (count > 256) count = 256; // Limit to prevent huge responses
1014 if (count < 1) count = 1;
1015
1016 json << "{\"address\":" << address << ",\"count\":" << count << ",\"bytes\":[";
1017
1018 for (int i = 0; i < count; i++) {
1019 if (i > 0) json << ",";
1020 auto byte_result = rom->ReadByte(address + i);
1021 if (byte_result.ok()) {
1022 json << static_cast<int>(*byte_result);
1023 } else {
1024 json << "null";
1025 }
1026 }
1027
1028 json << "]}";
1029 return json.str();
1030}
1031
1032std::string getRomPaletteGroup(const std::string& group_name, int palette_index) {
1033 std::ostringstream json;
1034 auto* rom = yaze::cli::GetGlobalRom();
1035
1036 if (!rom || !rom->is_loaded()) {
1037 return "{\"error\":\"No ROM loaded\"}";
1038 }
1039
1040 json << "{\"group_name\":\"" << group_name << "\",\"palette_index\":" << palette_index;
1041
1042 // Get palette colors from GameData
1043 try {
1044 yaze::zelda3::GameData game_data;
1045 auto load_status = yaze::zelda3::LoadGameData(*rom, game_data);
1046 if (!load_status.ok()) {
1047 return "{\"error\":\"Failed to load game data\"}";
1048 }
1049 auto* group = game_data.palette_groups.get_group(group_name);
1050 if (group) {
1051 if (palette_index >= 0 && palette_index < static_cast<int>(group->size())) {
1052 auto palette = (*group)[palette_index];
1053 json << ",\"size\":" << palette.size();
1054 json << ",\"colors\":[";
1055 for (size_t i = 0; i < palette.size(); i++) {
1056 if (i > 0) json << ",";
1057 auto rgb = palette[i].rgb();
1058 json << "{\"r\":" << static_cast<int>(rgb.x)
1059 << ",\"g\":" << static_cast<int>(rgb.y)
1060 << ",\"b\":" << static_cast<int>(rgb.z) << "}";
1061 }
1062 json << "]";
1063 } else {
1064 json << ",\"error\":\"Invalid palette index\"";
1065 }
1066 } else {
1067 json << ",\"error\":\"Invalid group name. Valid names: ow_main, ow_aux, ow_animated, hud, global_sprites, armors, swords, shields, sprites_aux1, sprites_aux2, sprites_aux3, dungeon_main, grass, 3d_object, ow_mini_map\"";
1068 }
1069 } catch (...) {
1070 json << ",\"error\":\"Exception accessing palette\"";
1071 }
1072
1073 json << "}";
1074 return json.str();
1075}
1076
1077// =============================================================================
1078// Overworld Debug Functions
1079// =============================================================================
1080
1081std::string getOverworldMapInfo(int map_id) {
1082 std::ostringstream json;
1083 auto* rom = yaze::cli::GetGlobalRom();
1084
1085 if (!rom || !rom->is_loaded()) {
1086 return "{\"error\":\"No ROM loaded\"}";
1087 }
1088
1089 // Overworld map constants
1090 constexpr int kNumOverworldMaps = 160;
1091 if (map_id < 0 || map_id >= kNumOverworldMaps) {
1092 return "{\"error\":\"Invalid map ID (0-159)\"}";
1093 }
1094
1095 json << "{\"map_id\":" << map_id;
1096
1097 // Read map properties from known ROM addresses
1098 // Map size: 0x12844 + map_id
1099 auto size_byte = rom->ReadByte(0x12844 + map_id);
1100 if (size_byte.ok()) {
1101 json << ",\"size_flag\":" << static_cast<int>(*size_byte);
1102 json << ",\"is_large\":" << (*size_byte == 0x20 ? "true" : "false");
1103 }
1104
1105 // Parent ID: 0x125EC + map_id
1106 auto parent_byte = rom->ReadByte(0x125EC + map_id);
1107 if (parent_byte.ok()) {
1108 json << ",\"parent_id\":" << static_cast<int>(*parent_byte);
1109 }
1110
1111 // Determine world type
1112 if (map_id < 64) {
1113 json << ",\"world\":\"light\"";
1114 } else if (map_id < 128) {
1115 json << ",\"world\":\"dark\"";
1116 } else {
1117 json << ",\"world\":\"special\"";
1118 }
1119
1120 json << "}";
1121 return json.str();
1122}
1123
1124std::string getOverworldTileInfo(int map_id, int tile_x, int tile_y) {
1125 std::ostringstream json;
1126 auto* rom = yaze::cli::GetGlobalRom();
1127
1128 if (!rom || !rom->is_loaded()) {
1129 return "{\"error\":\"No ROM loaded\"}";
1130 }
1131
1132 json << "{\"map_id\":" << map_id
1133 << ",\"tile_x\":" << tile_x
1134 << ",\"tile_y\":" << tile_y;
1135
1136 // Note: Full tile data access would require loading the overworld
1137 // For now, provide basic info that can be accessed without full load
1138 json << ",\"note\":\"Full tile data requires overworld to be loaded in editor\"";
1139
1140 json << "}";
1141 return json.str();
1142}
1143
1144// =============================================================================
1145// Emulator Debug Functions
1146// =============================================================================
1147
1169std::string getEmulatorStatus() {
1170 std::ostringstream json;
1171 auto* emulator = GetGlobalEmulator();
1172
1173 json << "{";
1174
1175 if (!emulator) {
1176 json << "\"initialized\":false,\"error\":\"Emulator not available\"";
1177 json << "}";
1178 return json.str();
1179 }
1180
1181 bool is_initialized = emulator->is_snes_initialized();
1182 bool is_running = emulator->running();
1183
1184 json << "\"initialized\":" << (is_initialized ? "true" : "false") << ",";
1185 json << "\"running\":" << (is_running ? "true" : "false") << ",";
1186
1187 if (is_initialized) {
1188 auto& snes = emulator->snes();
1189 auto& cpu = snes.cpu();
1190
1191 // CPU registers
1192 json << "\"cpu\":{";
1193 json << "\"A\":" << cpu.A << ",";
1194 json << "\"X\":" << cpu.X << ",";
1195 json << "\"Y\":" << cpu.Y << ",";
1196 json << "\"SP\":" << cpu.SP() << ",";
1197 json << "\"PC\":" << cpu.PC << ",";
1198 json << "\"D\":" << cpu.D << ","; // Direct page register
1199 json << "\"DB\":" << (int)cpu.DB << ","; // Data bank register
1200 json << "\"PB\":" << (int)cpu.PB << ","; // Program bank register
1201 json << "\"P\":" << (int)cpu.status << ","; // Processor status
1202 json << "\"E\":" << (int)cpu.E << ","; // Emulation mode flag
1203
1204 // Decode status flags for convenience
1205 json << "\"flags\":{";
1206 json << "\"N\":" << (cpu.GetNegativeFlag() ? "true" : "false") << ",";
1207 json << "\"V\":" << (cpu.GetOverflowFlag() ? "true" : "false") << ",";
1208 json << "\"M\":" << (cpu.GetAccumulatorSize() ? "true" : "false") << ",";
1209 json << "\"X\":" << (cpu.GetIndexSize() ? "true" : "false") << ",";
1210 json << "\"D\":" << (cpu.GetDecimalFlag() ? "true" : "false") << ",";
1211 json << "\"I\":" << (cpu.GetInterruptFlag() ? "true" : "false") << ",";
1212 json << "\"Z\":" << (cpu.GetZeroFlag() ? "true" : "false") << ",";
1213 json << "\"C\":" << (cpu.GetCarryFlag() ? "true" : "false");
1214 json << "}";
1215 json << "},";
1216
1217 // Full 24-bit PC address
1218 uint32_t full_pc = ((uint32_t)cpu.PB << 16) | cpu.PC;
1219 json << "\"full_pc\":" << full_pc << ",";
1220 json << "\"full_pc_hex\":\"$" << std::hex << std::uppercase
1221 << std::setfill('0') << std::setw(6) << full_pc << std::dec << "\",";
1222
1223 // Timing information
1224 json << "\"cycles\":" << snes.mutable_cycles() << ",";
1225 json << "\"fps\":" << emulator->GetCurrentFPS();
1226 }
1227
1228 json << "}";
1229 return json.str();
1230}
1231
1244std::string readEmulatorMemory(int address, int count) {
1245 std::ostringstream json;
1246 auto* emulator = GetGlobalEmulator();
1247
1248 if (!emulator || !emulator->is_snes_initialized()) {
1249 return "{\"error\":\"Emulator not initialized\"}";
1250 }
1251
1252 // Clamp count to prevent huge responses
1253 if (count > 256) count = 256;
1254 if (count < 1) count = 1;
1255
1256 auto& snes = emulator->snes();
1257
1258 json << "{\"address\":" << address << ",";
1259 json << "\"address_hex\":\"$" << std::hex << std::uppercase
1260 << std::setfill('0') << std::setw(6) << address << std::dec << "\",";
1261 json << "\"count\":" << count << ",";
1262 json << "\"bytes\":[";
1263
1264 // Read bytes from emulator memory using Snes::Read
1265 // This respects SNES memory mapping
1266 for (int i = 0; i < count; i++) {
1267 if (i > 0) json << ",";
1268 uint8_t byte = snes.Read(address + i);
1269 json << static_cast<int>(byte);
1270 }
1271
1272 json << "],\"hex\":\"";
1273 // Also provide hex string representation
1274 for (int i = 0; i < count; i++) {
1275 uint8_t byte = snes.Read(address + i);
1276 json << std::hex << std::uppercase << std::setfill('0') << std::setw(2)
1277 << static_cast<int>(byte);
1278 }
1279 json << std::dec << "\"}";
1280
1281 return json.str();
1282}
1283
1297 std::ostringstream json;
1298 auto* emulator = GetGlobalEmulator();
1299
1300 if (!emulator || !emulator->is_snes_initialized()) {
1301 return "{\"error\":\"Emulator not initialized\"}";
1302 }
1303
1304 auto& snes = emulator->snes();
1305 auto& ppu = snes.ppu();
1306 auto& memory = snes.memory();
1307
1308 json << "{";
1309
1310 // Scanline and position info from memory interface
1311 json << "\"h_pos\":" << memory.h_pos() << ",";
1312 json << "\"v_pos\":" << memory.v_pos() << ",";
1313 json << "\"current_scanline\":" << ppu.current_scanline_ << ",";
1314
1315 // PPU mode and settings
1316 json << "\"mode\":" << (int)ppu.mode << ",";
1317 json << "\"brightness\":" << (int)ppu.brightness << ",";
1318 json << "\"forced_blank\":" << (ppu.forced_blank_ ? "true" : "false") << ",";
1319 json << "\"overscan\":" << (ppu.overscan_ ? "true" : "false") << ",";
1320 json << "\"frame_overscan\":" << (ppu.frame_overscan_ ? "true" : "false") << ",";
1321 json << "\"interlace\":" << (ppu.interlace ? "true" : "false") << ",";
1322 json << "\"frame_interlace\":" << (ppu.frame_interlace ? "true" : "false") << ",";
1323 json << "\"pseudo_hires\":" << (ppu.pseudo_hires_ ? "true" : "false") << ",";
1324 json << "\"direct_color\":" << (ppu.direct_color_ ? "true" : "false") << ",";
1325 json << "\"bg3_priority\":" << (ppu.bg3priority ? "true" : "false") << ",";
1326 json << "\"even_frame\":" << (ppu.even_frame ? "true" : "false") << ",";
1327
1328 // VRAM pointer info
1329 json << "\"vram_pointer\":" << ppu.vram_pointer << ",";
1330 json << "\"vram_increment\":" << ppu.vram_increment_ << ",";
1331 json << "\"vram_increment_on_high\":" << (ppu.vram_increment_on_high_ ? "true" : "false");
1332
1333 json << "}";
1334 return json.str();
1335}
1336
1337// =============================================================================
1338// Version and Session Management
1339// =============================================================================
1340
1341std::string getYazeVersion() {
1342 return YAZE_VERSION_STRING;
1343}
1344
1345std::string getRomSessions() {
1346 std::ostringstream json;
1347 auto* manager = yaze::app::GetGlobalEditorManager();
1348
1349 if (!manager) {
1350 return "{\"error\":\"EditorManager not available\",\"sessions\":[]}";
1351 }
1352
1353 json << "{";
1354 json << "\"current_session\":" << manager->GetCurrentSessionId() << ",";
1355
1356 // Get current ROM info
1357 auto* current_rom = manager->GetCurrentRom();
1358 if (current_rom && current_rom->is_loaded()) {
1359 json << "\"current_rom\":{";
1360 json << "\"loaded\":true,";
1361 json << "\"title\":\"" << current_rom->title() << "\",";
1362 json << "\"filename\":\"" << current_rom->filename() << "\",";
1363 json << "\"size\":" << current_rom->size();
1364 json << "},";
1365 } else {
1366 json << "\"current_rom\":{\"loaded\":false},";
1367 }
1368
1369 // Note: Full session enumeration would require exposing session_coordinator
1370 // For now, provide current session info
1371 json << "\"sessions\":[]";
1372
1373 json << "}";
1374 return json.str();
1375}
1376
1378 std::ostringstream json;
1379 auto* rom = yaze::cli::GetGlobalRom();
1380
1381 json << "{";
1382 json << "\"global_rom_ptr\":" << (rom ? "true" : "false") << ",";
1383
1384 if (rom) {
1385 json << "\"rom_loaded\":" << (rom->is_loaded() ? "true" : "false") << ",";
1386 json << "\"rom_size\":" << rom->size() << ",";
1387 json << "\"rom_filename\":\"" << rom->filename() << "\",";
1388 json << "\"rom_title\":\"" << rom->title() << "\",";
1389
1390 // // Add diagnostics if available
1391 // if (rom->is_loaded()) {
1392 // auto& diag = rom->GetDiagnostics();
1393 // json << "\"diagnostics\":{";
1394 // json << "\"header_stripped\":" << (diag.header_stripped ? "true" : "false") << ",";
1395 // json << "\"checksum_valid\":" << (diag.checksum_valid ? "true" : "false") << ",";
1396 // json << "\"sheets_loaded\":" << diag.sheets.size();
1397 // json << "}";
1398 // }
1399 }
1400
1401 // EditorManager info
1402 auto* manager = yaze::app::GetGlobalEditorManager();
1403 if (manager) {
1404 json << ",\"editor_manager\":{";
1405 json << "\"session_count\":" << manager->GetActiveSessionCount() << ",";
1406 json << "\"current_session\":" << manager->GetCurrentSessionId() << ",";
1407 json << "\"has_current_rom\":" << (manager->GetCurrentRom() ? "true" : "false");
1408 json << "}";
1409 } else {
1410 json << ",\"editor_manager\":null";
1411 }
1412
1413 json << "}";
1414 return json.str();
1415}
1416
1418 auto* emulator = GetGlobalEmulator();
1419 if (emulator) {
1420 emulator->ResumeAudio();
1421 }
1422}
1423
1424// =============================================================================
1425// Combined Debug State for AI Analysis
1426// =============================================================================
1427
1429 auto* rom = yaze::cli::GetGlobalRom();
1430 if (!rom || !rom->is_loaded()) {
1431 return "{\"error\":\"No ROM loaded\"}";
1432 }
1433 return "Not implemented";
1434 // return rom->GetDiagnostics().ToJson();
1435}
1436
1437std::string getFullDebugState() {
1438 std::ostringstream json;
1439
1440 json << "{";
1441
1442 // Palette debug state
1443 json << "\"palette\":" << getFullPaletteState() << ",";
1444
1445 // Arena status
1446 json << "\"arena\":" << getArenaStatus() << ",";
1447
1448 // ROM status
1449 json << "\"rom\":" << getRomStatus() << ",";
1450
1451 // Emulator status
1452 json << "\"emulator\":" << getEmulatorStatus() << ",";
1453
1454 // Diagnostic summary
1455 json << "\"diagnostic\":\"" << getDiagnosticSummary() << "\",";
1456
1457 // Hypothesis
1458 json << "\"hypothesis\":\"" << getHypothesisAnalysis() << "\"";
1459
1460 json << "}";
1461
1462 return json.str();
1463}
1464
1465// =============================================================================
1466// Emscripten Bindings
1467// =============================================================================
1468
1469EMSCRIPTEN_BINDINGS(yaze_debug_inspector) {
1470 // Palette debug functions
1471 function("getDungeonPaletteEvents", &getDungeonPaletteEvents);
1472 function("getColorComparisons", &getColorComparisons);
1473 function("samplePixelAt", &samplePixelAt);
1474 function("clearPaletteDebugEvents", &clearPaletteDebugEvents);
1475
1476 // AI analysis functions
1477 function("getFullPaletteState", &getFullPaletteState);
1478 function("getPaletteData", &getPaletteData);
1479 function("getEventTimeline", &getEventTimeline);
1480 function("getDiagnosticSummary", &getDiagnosticSummary);
1481 function("getHypothesisAnalysis", &getHypothesisAnalysis);
1482
1483 // Arena debug functions
1484 function("getArenaStatus", &getArenaStatus);
1485 function("getGfxSheetInfo", &getGfxSheetInfo);
1486
1487 // ROM debug functions
1488 function("getRomStatus", &getRomStatus);
1489 function("readRomBytes", &readRomBytes);
1490 function("getRomPaletteGroup", &getRomPaletteGroup);
1491
1492 // Overworld debug functions
1493 function("getOverworldMapInfo", &getOverworldMapInfo);
1494 function("getOverworldTileInfo", &getOverworldTileInfo);
1495
1496 // Emulator debug functions
1497 function("getEmulatorStatus", &getEmulatorStatus);
1498 function("readEmulatorMemory", &readEmulatorMemory);
1499 function("getEmulatorVideoState", &getEmulatorVideoState);
1500 function("resumeAudioContext", &resumeAudioContext);
1501
1502 // Editor state and command execution
1503 function("getEditorState", &getEditorState);
1504 function("executeCommand", &executeCommand);
1505 function("switchToEditor", &switchToEditor);
1506
1507 // Async editor switching API
1508 function("switchToEditorAsync", &switchToEditorAsync);
1509 function("getOperationStatus", &getOperationStatus);
1510
1511 // Panel control API
1512 function("showPanel", &showPanel);
1513 function("hidePanel", &hidePanel);
1514 function("togglePanel", &togglePanel);
1515 function("getPanelState", &getPanelState);
1516 function("getPanelsInCategory", &getPanelsInCategory);
1517 function("showPanelGroup", &showPanelGroup);
1518 function("hidePanelGroup", &hidePanelGroup);
1519 function("getPanelGroups", &getPanelGroups);
1520
1521 // Sidebar view mode
1522 function("isTreeViewMode", &isTreeViewMode);
1523 function("setTreeViewMode", &setTreeViewMode);
1524 function("toggleTreeViewMode", &toggleTreeViewMode);
1525 function("getSidebarState", &getSidebarState);
1526
1527 // Right panel control
1528 function("openRightPanel", &openRightPanel);
1529 function("closeRightPanel", &closeRightPanel);
1530 function("toggleRightPanel", &toggleRightPanel);
1531 function("getRightPanelState", &getRightPanelState);
1532
1533 // Combined state for AI
1534 function("getFullDebugState", &getFullDebugState);
1535 // function("getGraphicsDiagnostics", &getGraphicsDiagnostics);
1536
1537 // Version and session management
1538 function("getYazeVersion", &getYazeVersion);
1539 function("getRomSessions", &getRomSessions);
1540 function("getFileManagerDebugInfo", &getFileManagerDebugInfo);
1541
1542 // AI Driver Bridge
1543 function("registerExternalAiDriver", &registerExternalAiDriver);
1544 function("onExternalAiResponse", &onExternalAiResponse);
1545}
The EditorManager controls the main editor window and manages the various editor classes.
static constexpr float GetSidebarWidth()
static constexpr float GetSidePanelWidth()
A class for emulating and debugging SNES games.
Definition emulator.h:39
static Arena & Get()
Definition arena.cc:19
static PaletteDebugger & Get()
#define YAZE_VERSION_STRING
Definition yaze.h:43
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })
std::unordered_map< uint32_t, std::string > g_pending_operations
nlohmann::json MessageToJson(const yaze::cli::agent::ChatMessage &msg)
yaze::editor::EditorManager * GetEditorManager()
yaze::editor::EditorType ParseEditorType(const std::string &name)
void onExternalAiResponse(std::string response_json)
yaze::editor::EditorManager * GetGlobalEditorManager()
Definition main.cc:98
yaze::emu::Emulator * GetGlobalEmulator()
Definition main.cc:90
Namespace for the command line interface.
Rom * GetGlobalRom()
constexpr std::array< const char *, 14 > kEditorNames
Definition editor.h:167
absl::Status LoadGameData(Rom &rom, GameData &data, const LoadOptions &options)
Loads all Zelda3-specific game data from a generic ROM.
Definition game_data.cc:80
std::vector< ToolCall > tool_calls
Definition common.h:23
std::string text_response
Definition common.h:20
std::map< std::string, std::string > args
Definition common.h:14
std::string tool_name
Definition common.h:13
Represents a single agent session with its own chat history and config.
PaletteGroup * get_group(const std::string &group_name)
gfx::PaletteGroupMap palette_groups
Definition game_data.h:89
Yet Another Zelda3 Editor (YAZE) - Public C API.
std::string showPanelGroup(std::string group_name)
Show a predefined group of cards.
std::string getOperationStatus(uint32_t op_id)
Get the status of an async operation.
std::string showPanel(std::string card_id)
Show a card by ID.
std::string hidePanel(std::string card_id)
Hide a card by ID.
std::string hidePanelGroup(std::string group_name)
Hide a predefined group of cards.
std::string toggleRightPanel(std::string panel_name)
Toggle a specific right panel.
std::string togglePanel(std::string card_id)
Toggle a card's visibility.
std::string closeRightPanel()
Close the currently open right panel.
std::string getHypothesisAnalysis()
std::string getDiagnosticSummary()
std::string samplePixelAt(int x, int y)
std::string getArenaStatus()
std::string getPaletteData()
std::string getEmulatorVideoState()
Get PPU (video) state from the emulator.
std::string switchToEditorAsync(std::string editor_name)
Switch to an editor asynchronously with operation tracking.
std::string getRomPaletteGroup(const std::string &group_name, int palette_index)
std::string getGfxSheetInfo(int index)
std::string getPanelState()
Get the visibility state of all cards.
std::string getEmulatorStatus()
Get the current emulator status including CPU state.
std::string getSidebarState()
Get sidebar state including view mode and width.
std::string getPanelsInCategory(std::string category)
Get cards in a specific category.
std::string getYazeVersion()
std::string getOverworldMapInfo(int map_id)
std::string getOverworldTileInfo(int map_id, int tile_x, int tile_y)
std::string getPanelGroups()
Get available card groups.
const char * Z3edProcessCommand(const char *command)
void clearPaletteDebugEvents()
std::string executeCommand(std::string command)
std::string getRightPanelState()
Get the state of the right panel.
std::string getRomStatus()
std::string getFileManagerDebugInfo()
std::string switchToEditor(std::string editor_name)
void resumeAudioContext()
std::string getFullPaletteState()
std::string toggleTreeViewMode()
Toggle tree view mode.
std::string getColorComparisons()
EMSCRIPTEN_BINDINGS(yaze_debug_inspector)
std::string readRomBytes(int address, int count)
std::string openRightPanel(std::string panel_name)
Open a specific right panel.
bool isTreeViewMode()
Check if tree view mode is enabled.
std::string readEmulatorMemory(int address, int count)
Read memory from the emulator's WRAM.
std::string getRomSessions()
std::string setTreeViewMode(bool enabled)
Set tree view mode.
std::string getEditorState()
std::string getGraphicsDiagnostics()
std::string getFullDebugState()
std::string getDungeonPaletteEvents()
std::string getEventTimeline()