const std = @import("std"); const core = @import("core").module; const panickers = core.panickers; // const realMain = @import("main"); pub const gamespec = @import("gamespec"); pub const options = @import("BacklogOptions"); pub const std_options = std.Options{ .enable_segfault_handler = true, }; //pub const build_options = @import("build_options"); //pub const tracy_enabled = build_options.tracy_enabled; // pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, x: ?usize) noreturn { // core.forceFlush(); // core.script.lua.takeDump(); // std.debug.defaultPanic(error_return_trace, x, msg); // } pub const NwArgs = struct { useGPA: bool = false, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations vulkanValidation: bool = true, fastTest: bool = false, dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations fatDump: bool = false, // takes a full fat minidump on crash, very large files are produced }; pub fn getArgs() !NwArgs { const a = try core.ParseArgs(NwArgs); return a; } fn fileExists(path: []const u8) bool { std.fs.cwd().access(path, .{}) catch return false; return true; } pub fn run() !void { core.engine_logs("calling gEngine.run"); try core.getEngine().run(); while (!core.getEngine().exitFinished()) { const z = core.tracy.ZoneN(@src(), "shutdown poll"); z.End(); } } pub fn startEngine(spec: *core.SpecVariantMap) bool { const args = getArgs() catch return false; var backingAllocator: std.mem.Allocator = std.heap.smp_allocator; var gpa: std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 20, }) = .{}; defer { const cleanupStatus = gpa.deinit(); if (cleanupStatus == .leak) { std.debug.print("gpa cleanup leaked memory\n", .{}); } } if (spec.get("useGPA")) |arg| { if (arg.boolean == true) { backingAllocator = gpa.allocator(); } } const memory = core.MemoryTracker; memory.MTSetup(backingAllocator, .{ .timeline = args.dmt }); defer memory.MTShutdown(); var tracker = memory.MTGet().?; const allocator = tracker.allocator(); _ = core.createNameRegistry(allocator) catch return false; core.maybeInitPackerFs(allocator) catch return false; if (comptime core.BuildOption("static_build")) { core.engine_log("static build, using embedded shaders", .{}); // const loader = @import("staticShaderLoader"); // loader.installStaticResources() catch return false; } core.start_module(spec, args, allocator) catch return false; const moduleName = spec.get("moduleName").?.string; if (comptime core.BuildOption("static_build")) { const modlaunch = @import("modulelaunch.zig"); var modargs = core.externModule.getModuleLoaderArgs(true); var modalloc = allocator; _ = modlaunch.startup_module(&modalloc, &modargs); } else { core.loadModule(moduleName, true) catch return false; } // load the shared object and call startup() // core.beginLoading(""); // if (!start_modules(spec, args, allocator)) return false; // defer shutdown_modules(allocator); run() catch return false; if (core.getEngine().shutdownModuleFunction) |f| { f(); } else { core.shutdown_module(allocator); } return true; } pub fn main() !void { if (!core.BuildOption("RootDeploymentOnly")) { // if we don't see a content/ folder or a // content.pak file in the current directory, // walk up the directory tree until we see one, then change dirs to that before doing anything else var iterations: u32 = 0; var BUFFER: [8192]u8 = undefined; while (iterations < 8) : (iterations += 1) { if (fileExists("content") or fileExists("content.pak")) { break; } var dir = try std.fs.cwd().openDir("..", .{}); defer dir.close(); core.engine_log("content not found scanning dir {s}", .{try dir.realpath(".", &BUFFER)}); try dir.setAsCwd(); } core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)}); } const spec = try gamespec.getSpec(); _ = startEngine(spec); // panickers.attachSegfaultHandler(); // try realMain.main(); shutdown_hook(); } pub fn shutdown_hook() void { std.debug.print("[engine] shutting down now! goodbye!", .{}); }