11#define IMGUI_DEFINE_MATH_OPERATORS
18#include "absl/debugging/symbolize.h"
19#include "absl/strings/ascii.h"
20#include "absl/strings/str_split.h"
21#include "absl/strings/strip.h"
27#if !defined(__EMSCRIPTEN__) && defined(YAZE_HTTP_API_ENABLED)
39DEFINE_FLAG(std::string, log_file,
"",
"Output log file path for debugging.");
40DEFINE_FLAG(std::string, rom_file,
"",
"ROM file to load on startup.");
41DEFINE_FLAG(
bool, debug,
false,
"Enable debug logging and verbose output.");
43 "Minimum log level: debug, info, warn, error, or fatal.");
45 "Mirror logs to stderr even when writing to a file.");
47 std::string, log_categories,
"",
48 "Comma-separated list of log categories to enable or disable. "
49 "Prefix with '-' to disable a category. "
50 "Example: \"Room,DungeonEditor\" (allowlist) or \"-Input,-Graphics\" "
55 "The editor to open on startup (e.g., Dungeon, Overworld, Assembly).");
58 "Comma-separated list of panel IDs to open (e.g. 'dungeon.room_list,emulator.cpu_debugger')");
62 "Welcome screen behavior at startup: auto, show, or hide.");
64 "Dashboard panel behavior at startup: auto, show, or hide.");
66 "Panel sidebar visibility at startup: auto, show, or hide.");
68 "Asset load mode: auto, full, or lazy.");
70DEFINE_FLAG(
int, room, -1,
"Open Dungeon Editor at specific room ID (0-295).");
71DEFINE_FLAG(
int, map, -1,
"Open Overworld Editor at specific map ID (0-159).");
74DEFINE_FLAG(
bool, enable_api,
false,
"Enable the AI Agent API server.");
75DEFINE_FLAG(
int, api_port, 8080,
"Port for the AI Agent API server.");
77DEFINE_FLAG(
bool, headless,
false,
"Run in headless mode without a GUI window.");
78DEFINE_FLAG(
bool, service,
false,
"Run in service mode (GUI backend initialized but window hidden).");
79DEFINE_FLAG(
bool, server,
false,
"Run in server mode (implies --enable_api, --enable_test_harness). Defaults to --headless unless --service or --no-headless is specified.");
84 "Start gRPC test harness server for automated GUI testing.");
87 "Port for Unified gRPC server (default: 50052).");
89 "Emulator backend for gRPC service: 'internal' or 'mesen'.");
93DEFINE_FLAG(std::string, export_symbols,
"",
"Export symbols to file (requires --rom_file).");
94DEFINE_FLAG(std::string, symbol_format,
"mesen",
"Format for symbol export: mesen, wla, asar, bsnes.");
95DEFINE_FLAG(std::string, load_symbols,
"",
"Load symbol file (.mlb, .sym, .asm) on startup.");
96DEFINE_FLAG(std::string, load_asar_symbols,
"",
"Load Asar symbols from directory on startup.");
98 "Export symbols without initializing UI. Requires --load_symbols or --load_asar_symbols.");
117 if (ctrl && ctrl->editor_manager()) {
141 const std::string lower = absl::AsciiStrToLower(raw_level);
142 if (lower ==
"debug") {
145 if (lower ==
"warn" || lower ==
"warning") {
148 if (lower ==
"error") {
151 if (lower ==
"fatal") {
158 std::set<std::string> categories;
159 for (absl::string_view token :
160 absl::StrSplit(raw,
',', absl::SkipWhitespace())) {
161 if (!token.empty()) {
162 categories.insert(std::string(absl::StripAsciiWhitespace(token)));
185 std::vector<std::string> tokens;
186 for (absl::string_view token :
187 absl::StrSplit(raw,
',', absl::SkipWhitespace())) {
188 if (!token.empty()) {
189 tokens.emplace_back(absl::StripAsciiWhitespace(token));
204#ifndef __EMSCRIPTEN__
213 std::set<std::string> log_categories =
216 std::string log_path = FLAGS_log_file->Get();
217 if (log_path.empty()) {
220 log_path = (*logs_dir /
"yaze.log").
string();
227 if (debug_flag || log_to_console_flag) {
231 LOG_INFO(
"Main",
"🚀 YAZE started in debug mode");
234 "Logging configured (level=%s, file=%s, console=%s, categories=%zu)",
236 log_path.empty() ?
"<stderr>" : log_path.c_str(),
237 (debug_flag || log_to_console_flag) ?
"on" :
"off",
238 log_categories.size());
245 bool server_mode = FLAGS_server->Get();
246 bool service_mode = FLAGS_service->Get();
248 config.
headless = FLAGS_headless->Get() || (server_mode && !service_mode);
250 config.
enable_api = FLAGS_enable_api->Get() || server_mode || service_mode;
253 config.
enable_test_harness = FLAGS_enable_test_harness->Get() || server_mode || service_mode;
255 config.
backend = FLAGS_backend->Get();
258 config.
rom_file = FLAGS_rom_file->Get();
265 config.
api_port = FLAGS_api_port->Get();
281 if (!FLAGS_open_panels->Get().empty()) {
288 if (!FLAGS_export_symbols->Get().empty() && FLAGS_export_symbols_fast->Get()) {
292 if (!FLAGS_load_symbols->Get().empty()) {
293 LOG_INFO(
"Main",
"Loading symbols from %s...", FLAGS_load_symbols->Get().c_str());
296 LOG_ERROR(
"Main",
"Failed to load symbols: %s", status.ToString().c_str());
302 if (!FLAGS_load_asar_symbols->Get().empty()) {
303 LOG_INFO(
"Main",
"Loading Asar symbols from %s...", FLAGS_load_asar_symbols->Get().c_str());
306 LOG_ERROR(
"Main",
"Failed to load Asar symbols: %s", status.ToString().c_str());
313 LOG_ERROR(
"Main",
"No symbols loaded. Use --load_symbols or --load_asar_symbols.");
317 LOG_INFO(
"Main",
"Exporting symbols to %s...", FLAGS_export_symbols->Get().c_str());
319 std::string format_str = absl::AsciiStrToLower(FLAGS_symbol_format->Get());
325 if (export_or.ok()) {
326 std::ofstream out(FLAGS_export_symbols->Get());
329 LOG_INFO(
"Main",
"Symbols exported successfully (fast path)");
332 LOG_ERROR(
"Main",
"Failed to open output file: %s", FLAGS_export_symbols->Get().c_str());
335 LOG_ERROR(
"Main",
"Failed to export symbols: %s", export_or.status().ToString().c_str());
341#if !defined(__EMSCRIPTEN__) && defined(YAZE_HTTP_API_ENABLED)
342std::unique_ptr<yaze::cli::api::HttpServer> SetupApiServer(
348 auto api_server = std::make_unique<yaze::cli::api::HttpServer>();
354 return &manager->emulator().symbol_provider();
360 api_server->SetWindowActions(
363 return controller ? (controller->ShowWindow(),
true) : false;
367 return controller ? (controller->HideWindow(),
false) : false;
370 auto status = api_server->Start(config.
api_port);
372 LOG_ERROR(
"Main",
"Failed to start API server: %s", std::string(status.message()).c_str());
383int main(
int argc,
char** argv) {
384 absl::InitializeSymbolizer(argv[0]);
392 const bool debug_flag = FLAGS_debug->Get();
393 const bool log_to_console_flag = FLAGS_log_to_console->Get();
395 std::string log_path = FLAGS_log_file->Get();
396 if (log_path.empty()) {
399 log_path = (*logs_dir /
"yaze.log").
string();
410#if !defined(__EMSCRIPTEN__)
415 if (!FLAGS_export_symbols->Get().empty() && FLAGS_export_symbols_fast->Get()) {
422 return yaze_run_cocoa_app_delegate(config);
426#if defined(_WIN32) && !defined(__EMSCRIPTEN__)
431 yaze::app::wasm::InitializeWasmPlatform();
435 static bool s_wasm_initialized =
false;
438 auto WasmMainLoop = []() {
440 if (!s_wasm_initialized) {
441 if (yaze::app::wasm::IsFileSystemReady()) {
442 LOG_INFO(
"Main",
"Filesystem ready, initializing application...");
444 s_wasm_initialized =
true;
457 emscripten_set_main_loop(WasmMainLoop, 0, 1);
462#if defined(YAZE_HTTP_API_ENABLED)
463 std::unique_ptr<yaze::cli::api::HttpServer> api_server;
465#if defined(YAZE_HTTP_API_ENABLED)
466 api_server = SetupApiServer(config);
470 "HTTP API requested but not enabled at build time "
471 "(set -DYAZE_ENABLE_HTTP_API=ON and rebuild).");
479 if (ctrl && ctrl->editor_manager()) {
482 if (!FLAGS_load_symbols->Get().empty()) {
483 LOG_INFO(
"Main",
"Loading symbols from %s...", FLAGS_load_symbols->Get().c_str());
484 auto status = symbols.LoadSymbolFile(FLAGS_load_symbols->Get());
486 LOG_ERROR(
"Main",
"Failed to load symbols: %s", status.ToString().c_str());
490 if (!FLAGS_load_asar_symbols->Get().empty()) {
491 LOG_INFO(
"Main",
"Loading Asar symbols from %s...", FLAGS_load_asar_symbols->Get().c_str());
492 auto status = symbols.LoadAsarAsmDirectory(FLAGS_load_asar_symbols->Get());
494 LOG_ERROR(
"Main",
"Failed to load Asar symbols: %s", status.ToString().c_str());
500 if (!FLAGS_export_symbols->Get().empty()) {
501 LOG_INFO(
"Main",
"Exporting symbols to %s...", FLAGS_export_symbols->Get().c_str());
504 if (ctrl && ctrl->editor_manager()) {
509 auto& symbols = manager->
emulator().symbol_provider();
512 std::string format_str = absl::AsciiStrToLower(FLAGS_symbol_format->Get());
517 auto export_or = symbols.ExportSymbols(format);
518 if (export_or.ok()) {
519 std::ofstream out(FLAGS_export_symbols->Get());
522 LOG_INFO(
"Main",
"Symbols exported successfully");
524 LOG_ERROR(
"Main",
"Failed to open output file: %s", FLAGS_export_symbols->Get().c_str());
527 LOG_ERROR(
"Main",
"Failed to export symbols: %s", export_or.status().ToString().c_str());
536 LOG_INFO(
"Main",
"Running in HEADLESS mode (no GUI window)");
542 std::this_thread::sleep_for(std::chrono::milliseconds(16));
547 LOG_INFO(
"Main",
"Running in SERVICE mode (Hidden GUI window)");
556#if defined(YAZE_HTTP_API_ENABLED)
bool RunSymbolExportFastPath()
yaze::AppConfig BuildAppConfig(yaze::util::LogLevel log_level, std::string log_path)
int main(int argc, char **argv)
yaze::util::LogLevel ResolveLogConfig(bool debug_flag, bool log_to_console_flag)
void SetupCrashHandling()
Controller * GetController()
static Application & Instance()
void Initialize(const AppConfig &config)
editor::EditorManager * editor_manager()
The EditorManager controls the main editor window and manages the various editor classes.
auto emulator() -> emu::Emulator &
A class for emulating and debugging SNES games.
Provider for symbol (label) resolution in disassembly.
absl::Status LoadAsarAsmDirectory(const std::string &directory_path)
Load symbols from a directory of ASM files.
absl::StatusOr< std::string > ExportSymbols(SymbolFormat format) const
Export all symbols to a string in the specified format.
absl::Status LoadSymbolFile(const std::string &path, SymbolFormat format=SymbolFormat::kAuto)
Load symbols from a .sym file (various formats)
static void CleanupOldLogs(int keep_count=5)
Clean up old crash logs, keeping only the most recent N logs.
static void Initialize(const std::string &version)
Initialize the crash handler for the application.
void Parse(int argc, char **argv)
static LogManager & instance()
void configure(LogLevel level, const std::string &file_path, const std::set< std::string > &categories)
Configures the logging system.
#define DEFINE_FLAG(type, name, default_val, help_text)
#define YAZE_VERSION_STRING
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
#define RETURN_IF_EXCEPTION(expression)
const char * LogLevelToString(yaze::util::LogLevel level)
std::set< std::string > ParseLogCategories(const std::string &raw)
yaze::util::LogLevel ParseLogLevelFlag(const std::string &raw_level, bool debug_flag)
std::vector< std::string > ParseCommaList(const std::string &raw)
yaze::editor::EditorManager * GetGlobalEditorManager()
yaze::emu::Emulator * GetGlobalEmulator()
SymbolFormat
Supported symbol file formats.
FlagRegistry * global_flag_registry()
LogLevel
Defines the severity levels for log messages. This allows for filtering messages based on their impor...
AssetLoadMode AssetLoadModeFromString(absl::string_view value)
StartupVisibility StartupVisibilityFromString(absl::string_view value)
Configuration options for the application startup.
AssetLoadMode asset_load_mode
std::string startup_editor
std::string log_categories
StartupVisibility welcome_mode
std::vector< std::string > open_panels
StartupVisibility sidebar_mode
StartupVisibility dashboard_mode
Public YAZE API umbrella header.