148 lines
3.5 KiB
Zig
148 lines
3.5 KiB
Zig
const app = @import("./app.zig");
|
|
|
|
const coral = @import("coral");
|
|
|
|
const ext = @import("./ext.zig");
|
|
|
|
pub const file = @import("./file.zig");
|
|
|
|
const heap = @import("./heap.zig");
|
|
|
|
const kym = @import("./kym.zig");
|
|
|
|
fn kym_handle_errors(info: kym.ErrorInfo) void {
|
|
app.log_fail(info.message);
|
|
|
|
var remaining_frames = info.frames.len;
|
|
|
|
if (remaining_frames != 0) {
|
|
app.log_fail("stack trace:");
|
|
|
|
while (remaining_frames != 0) {
|
|
remaining_frames -= 1;
|
|
|
|
app.log_fail(info.frames[remaining_frames].name);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn kym_log_info(env: *kym.RuntimeEnv) kym.RuntimeError!?*kym.RuntimeRef {
|
|
const argument = try env.expect(try env.arg(0));
|
|
|
|
defer env.discard(argument);
|
|
|
|
app.log_info(try env.unbox_string(argument));
|
|
|
|
return null;
|
|
}
|
|
|
|
fn kym_log_warn(env: *kym.RuntimeEnv) kym.RuntimeError!?*kym.RuntimeRef {
|
|
const argument = try env.expect(try env.arg(0));
|
|
|
|
defer env.discard(argument);
|
|
|
|
app.log_warn(try env.unbox_string(argument));
|
|
|
|
return null;
|
|
}
|
|
|
|
fn kym_log_fail(env: *kym.RuntimeEnv) kym.RuntimeError!?*kym.RuntimeRef {
|
|
const argument = try env.expect(try env.arg(0));
|
|
|
|
defer env.discard(argument);
|
|
|
|
app.log_fail(try env.unbox_string(argument));
|
|
|
|
return null;
|
|
}
|
|
|
|
fn last_sdl_error() [:0]const u8 {
|
|
return coral.io.slice_sentineled(@as(u8, 0), @as([*:0]const u8, @ptrCast(ext.SDL_GetError())));
|
|
}
|
|
|
|
pub fn run_app(file_access: file.Access) void {
|
|
defer heap.trace_leaks();
|
|
|
|
if (ext.SDL_Init(ext.SDL_INIT_EVERYTHING) != 0) {
|
|
return app.log_fail(last_sdl_error());
|
|
}
|
|
|
|
defer ext.SDL_Quit();
|
|
|
|
var script_env = kym.RuntimeEnv.make(heap.allocator, kym.ErrorHandler.from(kym_handle_errors)) catch {
|
|
return app.log_fail("failed to initialize script runtime");
|
|
};
|
|
|
|
defer script_env.free();
|
|
|
|
kym.bind_syscaller(&script_env, "log_info", kym.Caller.from(kym_log_info)) catch {
|
|
return app.log_fail("failed to bind `log_info` syscall");
|
|
};
|
|
|
|
kym.bind_syscaller(&script_env, "log_warn", kym.Caller.from(kym_log_warn)) catch {
|
|
return app.log_fail("failed to bind `log_warn` syscall");
|
|
};
|
|
|
|
kym.bind_syscaller(&script_env, "log_fail", kym.Caller.from(kym_log_fail)) catch {
|
|
return app.log_fail("failed to bind `log_fail` syscall");
|
|
};
|
|
|
|
var manifest = app.Manifest{};
|
|
|
|
manifest.load(&script_env, file_access) catch return;
|
|
|
|
const window = create: {
|
|
const pos = ext.SDL_WINDOWPOS_CENTERED;
|
|
const flags = 0;
|
|
|
|
break: create ext.SDL_CreateWindow(&manifest.title, pos, pos, manifest.width, manifest.height, flags) orelse {
|
|
return app.log_fail(last_sdl_error());
|
|
};
|
|
};
|
|
|
|
defer ext.SDL_DestroyWindow(window);
|
|
|
|
const renderer = create: {
|
|
const default_driver_index = -1;
|
|
const flags = ext.SDL_RENDERER_ACCELERATED;
|
|
|
|
break: create ext.SDL_CreateRenderer(window, default_driver_index, flags) orelse {
|
|
return app.log_fail(last_sdl_error());
|
|
};
|
|
};
|
|
|
|
defer ext.SDL_DestroyRenderer(renderer);
|
|
|
|
{
|
|
var previous_ticks = ext.SDL_GetTicks64();
|
|
|
|
while (true) {
|
|
{
|
|
var event = @as(ext.SDL_Event, undefined);
|
|
|
|
while (ext.SDL_PollEvent(&event) != 0) {
|
|
switch (event.type) {
|
|
ext.SDL_QUIT => return,
|
|
else => {},
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
// Based on https://fabiensanglard.net/timer_and_framerate/index.php.
|
|
const current_ticks = ext.SDL_GetTicks64();
|
|
const milliseconds_per_second = 1000.0;
|
|
const tick_frequency = @as(u64, @intFromFloat(milliseconds_per_second / manifest.tick_rate));
|
|
|
|
while (previous_ticks < current_ticks) {
|
|
previous_ticks += tick_frequency;
|
|
}
|
|
}
|
|
|
|
_ = ext.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
_ = ext.SDL_RenderClear(renderer);
|
|
_ = ext.SDL_RenderPresent(renderer);
|
|
}
|
|
}
|
|
}
|