diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f7804a7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ext/lua"] + path = ext/lua + url = git@github.com:lua/lua.git diff --git a/build.zig b/build.zig index efb67d4..42079be 100644 --- a/build.zig +++ b/build.zig @@ -11,8 +11,55 @@ pub fn build(builder: *std.build.Builder) void { ona_exe.setTarget(target); ona_exe.setBuildMode(mode); ona_exe.install(); + ona_exe.addIncludeDir("./ext"); ona_exe.linkSystemLibrary("sdl2"); + // Lua dependency. + ona_exe.linkLibrary(link_lua: { + const lua_lib = builder.addStaticLibrary("lua", null); + + lua_lib.addIncludeDir("./ext/lua"); + lua_lib.linkLibC(); + + // TODO: Implement support for more than Linux. + lua_lib.addCSourceFiles(&.{ + "./ext/lua/lapi.c", + "./ext/lua/lauxlib.c", + "./ext/lua/lbaselib.c", + "./ext/lua/lcode.c", + "./ext/lua/lcorolib.c", + "./ext/lua/lctype.c", + "./ext/lua/ldblib.c", + "./ext/lua/ldebug.c", + "./ext/lua/ldo.c", + "./ext/lua/ldump.c", + "./ext/lua/lfunc.c", + "./ext/lua/lgc.c", + "./ext/lua/llex.c", + "./ext/lua/lmathlib.c", + "./ext/lua/lmem.c", + "./ext/lua/loadlib.c", + "./ext/lua/lobject.c", + "./ext/lua/lopcodes.c", + "./ext/lua/loslib.c", + "./ext/lua/lparser.c", + "./ext/lua/lstate.c", + "./ext/lua/lstring.c", + "./ext/lua/lstrlib.c", + "./ext/lua/ltablib.c", + "./ext/lua/lundump.c", + "./ext/lua/lutf8lib.c", + "./ext/lua/lvm.c", + "./ext/lua/lzio.c", + "./ext/lua/ltable.c", + "./ext/lua/ltm.c", + }, &.{"-DLUA_USE_LINUX", "-Wl"}); + + lua_lib.install(); + + break: link_lua lua_lib; + }); + const run_cmd = ona_exe.run(); run_cmd.step.dependOn(builder.getInstallStep()); diff --git a/ext/lua b/ext/lua new file mode 160000 index 0000000..5d708c3 --- /dev/null +++ b/ext/lua @@ -0,0 +1 @@ +Subproject commit 5d708c3f9cae12820e415d4f89c9eacbe2ab964b diff --git a/ona.lua b/ona.lua new file mode 100644 index 0000000..286067e --- /dev/null +++ b/ona.lua @@ -0,0 +1,8 @@ + +return { + name = "Ona", + initial_width = 1280, + initial_height = 800, + + initial_scene = nil, +} diff --git a/src/main.zig b/src/main.zig index a482a78..baee43f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,18 +1,64 @@ const c = @cImport({ @cInclude("SDL2/SDL.h"); + @cInclude("lua/lua.h"); + @cInclude("lua/lualib.h"); + @cInclude("lua/lauxlib.h"); }); const std = @import("std"); +fn luaAlloc(userdata: ?*anyopaque, ptr: ?*anyopaque, original_size: usize, + updated_size: usize) callconv(.C) ?*anyopaque { + + // Implementation derived from + // https://github.com/natecraddock/ziglua/blob/master/src/ziglua.zig. + const alignment = @alignOf(std.c.max_align_t); + const Allocator = std.mem.Allocator; + const allocator = @ptrCast(*Allocator, @alignCast(@alignOf(Allocator), userdata.?)); + + if (@ptrCast(?[*]align(alignment) u8, @alignCast(alignment, ptr))) |prev_ptr| { + // Allocator is working with an existing pointer. + const prev_slice = prev_ptr[0 .. original_size]; + + if (updated_size == 0) { + // Updated size of `0` to free the existing memory block. + allocator.free(prev_slice); + + return null; + } + + // Resize the existing memory block. + return (allocator.reallocAdvanced(prev_slice, alignment, + updated_size, .exact) catch return null).ptr; + } + + // No existing pointer, allocate a new block of memory. + return (allocator.alignedAlloc(u8, alignment, updated_size) catch return null).ptr; +} + pub fn main() anyerror!void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + if (c.SDL_Init(c.SDL_INIT_EVERYTHING) != 0) { - c.SDL_LogCritical(c.SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL2"); + c.SDL_LogCritical(c.SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL2 runtime"); return error.SystemFailure; } defer c.SDL_Quit(); + var lua_allocator = gpa.allocator(); + const lua_state = c.lua_newstate(luaAlloc, @ptrCast(*anyopaque, &lua_allocator)); + + if (lua_state == null) { + c.SDL_LogCritical(c.SDL_LOG_CATEGORY_APPLICATION, + "Failed to initialize Lua virtual machine"); + + return error.SystemFailure; + } + + defer c.lua_close(lua_state); + const sdl_window = create_sdl_window: { const pos = c.SDL_WINDOWPOS_UNDEFINED; var flags = @as(u32, 0); @@ -21,13 +67,27 @@ pub fn main() anyerror!void { }; if (sdl_window == null) { - c.SDL_LogCritical(c.SDL_LOG_CATEGORY_APPLICATION, "Failed to create window"); + c.SDL_LogCritical(c.SDL_LOG_CATEGORY_VIDEO, "Failed to create SDL2 window"); return error.SystemFailure; } defer c.SDL_DestroyWindow(sdl_window); + const sdl_renderer = create_sdl_renderer: { + var flags = @as(u32, 0); + + break: create_sdl_renderer c.SDL_CreateRenderer(sdl_window, -1, flags); + }; + + if (sdl_renderer == null) { + c.SDL_LogCritical(c.SDL_LOG_CATEGORY_VIDEO, "Failed to create SDL2 renderer"); + + return error.SystemFailure; + } + + defer c.SDL_DestroyRenderer(sdl_renderer); + var is_running = true; while (is_running) { @@ -40,5 +100,10 @@ pub fn main() anyerror!void { else => {}, } } + + _ = c.SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255); + _ = c.SDL_RenderClear(sdl_renderer); + + c.SDL_RenderPresent(sdl_renderer); } }