From 3cb93d4aeb9ae14d8a8254eefacb1174f37af290 Mon Sep 17 00:00:00 2001 From: TSnake41 Date: Sun, 8 Mar 2020 15:16:50 +0100 Subject: [PATCH] Fix some bugs, allow requirable library building. --- examples/physics_demo.lua | 27 +++++++----- makefile | 3 ++ src/raylua.c | 12 ++++- src/raylua.h | 6 ++- src/raylua.lua | 71 +++++++++++++++++------------- src/raylua_builder.c | 43 +++++++++--------- src/raylua_builder.lua | 21 ++++++--- src/raylua_e.c | 93 +++++++++++++++++++++++++-------------- src/raylua_s.c | 2 +- 9 files changed, 171 insertions(+), 107 deletions(-) diff --git a/examples/physics_demo.lua b/examples/physics_demo.lua index 47fa09f..395535f 100644 --- a/examples/physics_demo.lua +++ b/examples/physics_demo.lua @@ -23,42 +23,42 @@ rl.SetTargetFPS(60) while not rl.WindowShouldClose() do rl.RunPhysicsStep() - + if needsReset then floor = rl.CreatePhysicsBodyRectangle({ screenWidth/2, screenHeight }, 500, 100, 10) circle = rl.CreatePhysicsBodyCircle({ screenWidth/2, screenHeight/2 }, 45, 10) - + floor.enabled = false circle.enabled = false needsReset = false end - + if rl.IsKeyPressed(string.byte("R")) then rl.ResetPhysics() needsReset = true end - + if rl.IsMouseButtonPressed(rl.MOUSE_LEFT_BUTTON) then rl.CreatePhysicsBodyPolygon(rl.GetMousePosition(), rl.GetRandomValue(20, 80), rl.GetRandomValue(3, 8), 10); elseif rl.IsMouseButtonPressed(rl.MOUSE_RIGHT_BUTTON) then rl.CreatePhysicsBodyCircle(rl.GetMousePosition(), rl.GetRandomValue(10, 45), 10) end - + local bodiesCount = rl.GetPhysicsBodiesCount() - + for i=0,bodiesCount do local body = rl.GetPhysicsBody(i) - + if body ~= nil and (body.position.y > screenHeight*2) then print("Destroyed " .. tostring(body)) rl.DestroyPhysicsBody(body) end end - + rl.BeginDrawing() rl.ClearBackground(rl.BLACK) - + bodiesCount = rl.GetPhysicsBodiesCount() for i=0,bodiesCount-1 do local body = rl.GetPhysicsBody(i) @@ -75,13 +75,16 @@ while not rl.WindowShouldClose() do end end end - + rl.DrawText("Left mouse button to create a polygon", 10, 10, 10, rl.WHITE); rl.DrawText("Right mouse button to create a circle", 10, 25, 10, rl.WHITE); rl.DrawText("Press 'R' to reset example", 10, 40, 10, rl.WHITE); rl.DrawText("Physac", logoX, logoY, 30, rl.WHITE); rl.DrawText("Powered by", logoX + 50, logoY - 7, 10, rl.WHITE); - + rl.EndDrawing() -end \ No newline at end of file +end + +rl.ClosePhysics() +rl.CloseWindow() diff --git a/makefile b/makefile index 88a9a94..81e74ec 100644 --- a/makefile +++ b/makefile @@ -34,6 +34,9 @@ raylua_s: src/raylua.o src/raylua_s.o raylua_e: src/raylua.o src/raylua_e.o src/raylua_builder.o src/lib/miniz.o $(CC) -o $@ $^ $(LDFLAGS) +raylua.dll: src/raylua.o + $(CC) -shared -fPIE -o $@ $^ $(LDFLAGS) + src/raylua.o: luajit raylib src/autogen/boot.c src/autogen/bind.c src/raylua_builder.o: src/autogen/builder.c diff --git a/src/raylua.c b/src/raylua.c index dc13a24..d9fcb1f 100644 --- a/src/raylua.c +++ b/src/raylua.c @@ -30,20 +30,22 @@ extern const char *raylua_boot_str; -void raylua_boot(lua_State *L, lua_CFunction loadfile) +void raylua_boot(lua_State *L, lua_CFunction loadfile, bool repl) { lua_newtable(L); if (loadfile) { lua_pushstring(L, "loadfile"); lua_pushcfunction(L, loadfile); - lua_settable(L, -3); } lua_pushstring(L, "bind_entries"); lua_pushlightuserdata(L, raylua_entries); + lua_settable(L, -3); + lua_pushstring(L, "isrepl"); + lua_pushboolean(L, repl); lua_settable(L, -3); lua_setglobal(L, "raylua"); @@ -51,3 +53,9 @@ void raylua_boot(lua_State *L, lua_CFunction loadfile) if (luaL_dostring(L, raylua_boot_lua)) fputs(luaL_checkstring(L, -1), stderr); } + +int luaopen_raylua(lua_State *L) +{ + raylua_boot(L, NULL, false); + return 0; +} diff --git a/src/raylua.h b/src/raylua.h index 4acb443..f52e2f0 100644 --- a/src/raylua.h +++ b/src/raylua.h @@ -17,8 +17,12 @@ #ifndef H_RAYLUA #define H_RAYLUA +#include #include -void raylua_boot(lua_State *L, lua_CFunction loadfile); +void raylua_boot(lua_State *L, lua_CFunction loadfile, bool repl); + +/* raylua_boot alias to allow direct loading */ +int luaopen_raylua(lua_State *L); #endif /* H_RAYLUA */ diff --git a/src/raylua.lua b/src/raylua.lua index a29cac1..577f178 100644 --- a/src/raylua.lua +++ b/src/raylua.lua @@ -16,37 +16,7 @@ local load = loadstring --- TODO: Embedded ressources loading. - -if raylua.loadfile then - package.path = "?.lua" - - -- Change the second loader to load files using raylua.loadfile - package.loaders[2] = function (name) - for path in package.path:gmatch "([^;]+);?" do - path = path:gsub("?", name) - - local status, content = raylua.loadfile(path) - if status then - local f, err = load(content) - assert(f, err) - - return f - end - end - - return nil - end - - print "[RAYLUA] Load main.lua from payload." - require "main" - return -end - -if arg[1] then - dofile(arg[1]) -else - -- Run small REPL +function raylua.repl() print ">> raylua WIP repl <<" print "" @@ -66,3 +36,42 @@ else end end end + +if raylua.loadfile then + package.path = "?.lua;?/init.lua" + + -- Change the second loader to load files using raylua.loadfile + package.loaders[2] = function (name) + for path in package.path:gmatch "([^;]+);?" do + path = path:gsub("?", name) + + local content, err = raylua.loadfile(path) + if content then + local f, err = load(content) + assert(f, err) + + return f + end + end + + return nil + end + + print "[RAYLUA] Load main.lua from payload." + require "main" + + if not raylua.isrepl then + -- Keep launching the repl even with `loadfile` defined. + return + end +end + +if arg[1] then + dofile() + return +end + +if raylua.isrepl then + print "[RAYLUA] Go to repl." + raylua.repl() +end diff --git a/src/raylua_builder.c b/src/raylua_builder.c index 41b6183..b4e232d 100644 --- a/src/raylua_builder.c +++ b/src/raylua_builder.c @@ -63,15 +63,18 @@ typedef struct raylua_builder { fpos_t offset; } raylua_builder; -raylua_builder *raylua_builder_new(const char *self_path, const char *path) +static int raylua_builder_new(lua_State *L) { + const char *self_path = luaL_checkstring(L, -2); + const char *path = luaL_checkstring(L, -1); + raylua_builder *builder = malloc(sizeof(raylua_builder)); mz_zip_zero_struct(&builder->zip); FILE *f = fopen(path, "wb"); if (!f) { free(builder); - return NULL; + return luaL_error(L, "Can't open %s", path); } builder->file = f; @@ -80,7 +83,7 @@ raylua_builder *raylua_builder_new(const char *self_path, const char *path) if (!self) { free(builder); fclose(f); - return NULL; + return luaL_error(L, "Can't open self (%s)", self_path); } append_file(f, self); @@ -92,14 +95,16 @@ raylua_builder *raylua_builder_new(const char *self_path, const char *path) free(builder); fclose(f); fclose(self); - return NULL; + return luaL_error(L, "Can't initialize miniz writer."); } - return builder; + lua_pushlightuserdata(L, builder); + return 1; } -void raylua_builder_close(raylua_builder *builder) +static int raylua_builder_close(lua_State *L) { + raylua_builder *builder = lua_touserdata(L, -1); mz_zip_writer_finalize_archive(&builder->zip); /* Write offset */ @@ -107,16 +112,23 @@ void raylua_builder_close(raylua_builder *builder) fclose(builder->file); free(builder); + return 0; } -void raylua_builder_add(raylua_builder *builder, const char *path, const char *dest) +static int raylua_builder_add(lua_State *L) { + raylua_builder *builder = lua_touserdata(L, -3); + const char *path = luaL_checkstring(L, -2); + const char *dest = luaL_checkstring(L, -1); + if (!dest) dest = path; if (!mz_zip_writer_add_file(&builder->zip, dest, path, NULL, 0, MZ_BEST_COMPRESSION)) printf("Unable to write %s (%s)\n", dest, path); + + return 0; } static int get_type(lua_State *L) @@ -161,11 +173,8 @@ static int list_dir(lua_State *L) return 1; } -int raylua_build_executable(const char *self, const char *input) +int raylua_builder_boot(lua_State *L) { - lua_State *L = luaL_newstate(); - luaL_openlibs(L); - lua_pushcfunction(L, get_type); lua_setglobal(L, "get_type"); @@ -175,21 +184,15 @@ int raylua_build_executable(const char *self, const char *input) lua_pushlightuserdata(L, append_file_offset); lua_setglobal(L, "append_file_offset"); - lua_pushlightuserdata(L, &raylua_builder_new); + lua_pushcfunction(L, raylua_builder_new); lua_setglobal(L, "builder_new"); - lua_pushlightuserdata(L, &raylua_builder_close); + lua_pushcfunction(L, raylua_builder_close); lua_setglobal(L, "builder_close"); - lua_pushlightuserdata(L, &raylua_builder_add); + lua_pushcfunction(L, raylua_builder_add); lua_setglobal(L, "builder_add"); - lua_pushstring(L, self); - lua_setglobal(L, "self_path"); - - lua_pushstring(L, input); - lua_setglobal(L, "input_path"); - if (luaL_dostring(L, raylua_builder_lua)) fputs(luaL_checkstring(L, -1), stderr); diff --git a/src/raylua_builder.lua b/src/raylua_builder.lua index a8bc258..909a933 100644 --- a/src/raylua_builder.lua +++ b/src/raylua_builder.lua @@ -16,7 +16,7 @@ --[[ Uses miniz licence : - + Copyright 2013-2014 RAD Game Tools and Valve Software Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC All Rights Reserved. @@ -40,16 +40,23 @@ THE SOFTWARE. ]] -local t = get_type(input_path) local ffi = require "ffi" +ffi.cdef "typedef struct FILE FILE;" +local append_file_offset = ffi.cast("void (*)(FILE *, FILE *, FILE *)", append_file_offset) + +local self_path = arg[0] +local input_path = arg[1] + print ">> Raylua builder <<" +if #arg == 0 then + print "TODO: Improve builder usage." -ffi.cdef "typedef struct raylua_builder raylua_builder;" + print "Usage: raylua_e " + return +end -local builder_new = ffi.cast("raylua_builder *(*)(const char *, const char *)", builder_new) -local builder_close = ffi.cast("void (*)(raylua_builder *)", builder_close) -local builder_add = ffi.cast("void (*)(raylua_builder *, const char *, const char *)", builder_add) +local t = get_type(input_path) local function path_concat(...) return table.concat({ ... }, "/") @@ -73,7 +80,7 @@ if t == "directory" then print("Building " .. path) local builder = builder_new(self_path, path) - assert(builder ~= ffi.new("void *", nil), "Can't initialize builder") + assert(builder, "Can't initialize builder") local have_main = false diff --git a/src/raylua_e.c b/src/raylua_e.c index 6ae312b..3761de5 100644 --- a/src/raylua_e.c +++ b/src/raylua_e.c @@ -24,11 +24,10 @@ #include #include "raylua.h" - #include "lib/miniz.h" #ifndef RAYLUA_NO_BUILDER -int raylua_build_executable(const char *self_path, const char *input_path); +int raylua_builder_boot(lua_State *L); #endif static mz_zip_archive zip_file; @@ -39,63 +38,65 @@ int raylua_loadfile(lua_State *L) int index = mz_zip_reader_locate_file(&zip_file, path, NULL, 0); if (index == -1) { - lua_pushboolean(L, false); lua_pushfstring(L, "%s: File not found.", path); + lua_pushnil(L); return 2; } mz_zip_archive_file_stat stat; if (!mz_zip_reader_file_stat(&zip_file, index, &stat)) { - lua_pushboolean(L, false); lua_pushfstring(L, "%s: Can't get file information.", path); + lua_pushnil(L); return 2; } size_t size = stat.m_uncomp_size; char *buffer = malloc(size + 1); if (buffer == NULL) { - lua_pushboolean(L, false); lua_pushfstring(L, "%s: Can't allocate file buffer.", path); + lua_pushnil(L); return 2; } buffer[size] = '\0'; mz_zip_reader_extract_to_mem(&zip_file, index, buffer, size, 0); - lua_pushboolean(L, true); lua_pushlstring(L, buffer, size); free(buffer); + return 1; +} - return 2; +static bool raylua_init_payload(const char *path, bool direct) +{ + mz_zip_zero_struct(&zip_file); + + if (direct) { + if (!mz_zip_reader_init_file(&zip_file, path, 0)) + return false; + } else { + FILE *f = fopen(path, "rb"); + + if (f == NULL) { + puts("[RAYLUA] Can't load self."); + return false; + } else { + /* Read offset at the end of the file */ + fpos_t offset; + fseek(f, -(long)sizeof(fpos_t), SEEK_END); + fread(&offset, sizeof(fpos_t), 1, f); + + fsetpos(f, &offset); + + if (!mz_zip_reader_init_cfile(&zip_file, f, 0, 0)) + return false; + } + } + + return true; } int main(int argc, const char **argv) { - mz_zip_zero_struct(&zip_file); - bool ready = false; - - FILE *f = fopen(argv[0], "rb"); - - if (f != NULL) { - /* Read offset at the end of the file */ - fpos_t offset; - fseek(f, -(long)sizeof(fpos_t), SEEK_END); - fread(&offset, sizeof(fpos_t), 1, f); - - fsetpos(f, &offset); - - if (mz_zip_reader_init_cfile(&zip_file, f, 0, 0)) - ready = true; - } - - if (!ready) { - if (argc < 2) { - puts("Usage: raylua_e "); - return 0; - } else - return raylua_build_executable(argv[0], argv[1]); - } - lua_State *L = luaL_newstate(); luaL_openlibs(L); @@ -115,7 +116,33 @@ int main(int argc, const char **argv) lua_setglobal(L, "arg"); - raylua_boot(L, raylua_loadfile); + const char *path = argv[0]; + #ifdef WIN32 + /* Executable name translation. */ + size_t path_len = strlen(path); + char new_path[path_len + 5]; + + if (path_len > 4 && stricmp(path + path_len - 4, ".exe")) { + strcpy(new_path, path); + strcpy(new_path + path_len, ".exe"); + + printf("[RAYLUA] Translated self executable name from %s to %s.\n", path, new_path); + path = new_path; + } + #endif + + if (!raylua_init_payload(path, false)) { + #ifdef RAYLUA_NO_BUILDER + puts("[RAYLUA] No payload."); + #else + puts("[RAYLUA] No payload, use internal builder."); + raylua_builder_boot(L); + #endif + } else { + /* Boot on payload. */ + raylua_boot(L, raylua_loadfile, false); + } + lua_close(L); return 0; } diff --git a/src/raylua_s.c b/src/raylua_s.c index 2b7a9ed..1087fd2 100644 --- a/src/raylua_s.c +++ b/src/raylua_s.c @@ -44,7 +44,7 @@ int main(int argc, const char **argv) lua_setglobal(L, "arg"); - raylua_boot(L, NULL); + raylua_boot(L, NULL, true); lua_close(L); return 0; }