diff --git a/bootstrap/boot.lua b/bootstrap/boot.lua index 1eded180291449a68c97cb91917e91ee54ed43dd..e719e5b8e4ee0d6ba3950e0d84365088a15f8c66 100644 --- a/bootstrap/boot.lua +++ b/bootstrap/boot.lua @@ -19,19 +19,25 @@ if __SELFEXE then print("SelfExe gave us app directory of:", dir) fs.mount(dir..fs.getPathSeparator().."game"..fs.getPathSeparator().."thirdparty", "/", true) fs.mount(dir..fs.getPathSeparator().."game", "/", true) - if fs.exists("/engine.teae") and fs.exists("/thirdparty.teae") then - fs.mount(dir..fs.getPathSeparator().."game/engine.teae", "/", true) - fs.mount(dir..fs.getPathSeparator().."game/thirdparty.teae", "/", true) - print("Using engine.teae") - end else fs.mount("game"..fs.getPathSeparator().."thirdparty", "/", true) fs.mount("game", "/", true) - if fs.exists("/engine.teae") and fs.exists("/thirdparty.teae") then - fs.mount(dir..fs.getPathSeparator().."game/engine.teae", "/", true) - fs.mount(dir..fs.getPathSeparator().."game/thirdparty.teae", "/", true) - print("Using engine.teae") +end + +-- Look for a core +function get_core(id) + for i, file in ipairs(fs.list("/engines/cores/")) do + if file:find("%.tec$") then + print("Possible engine core", file) + end + end + local core = "/engines/cores/te4core-"..id..".tec" + if fs.exists(core) then + local rcore = fs.getRealPath(core) + print("Using TE4CORE: ", core, rcore) + return rcore end + return "NO CORE" end -- We need it no more, lets forget about it just it case some malovelant script tried something silly diff --git a/premake4.lua b/premake4.lua index e5af86233667018114eb7ff27e1880ca49c851d5..354133d7df0c2bb0ecd46ca274d314a2623d1f0c 100644 --- a/premake4.lua +++ b/premake4.lua @@ -91,15 +91,15 @@ project "TEngineRunner" kind "WindowedApp" language "C" targetname "t-engine" - files { "src/runner/*.c", "src/getself.c" } - links { "physfs", "lua".._OPTIONS.lua } + files { "src/runner/*.c", "src/getself.c", "src/physfs.c", "src/auxiliar.c" } + links { "physfs", "lua".._OPTIONS.lua, "m" } configuration "linux" links { "dl" } - defines { 'SELFEXE_LINUX' } + defines { [[TENGINE_HOME_PATH='".t-engine"']], 'SELFEXE_LINUX' } configuration "windows" - defines { 'SELFEXE_WINDOWS' } + defines { [[TENGINE_HOME_PATH='"T-Engine"']], 'SELFEXE_WINDOWS' } configuration "macosx" - defines { "USE_TENGINE_MAIN", 'SELFEXE_MACOSX' } + defines { [[TENGINE_HOME_PATH='".t-engine"']], "USE_TENGINE_MAIN", 'SELFEXE_MACOSX' } configuration {"Debug"} postbuildcommands { "cp bin/Debug/t-engine t-engine", } configuration {"Release"} @@ -107,6 +107,7 @@ configuration {"Release"} project "TEngine" targetprefix "" + targetextension ".tec" kind "SharedLib" language "C" targetname(corename) diff --git a/src/core_lua.c b/src/core_lua.c index 6670df89bad1ecbc54dff0d08e5624f24bf41f59..dba15b726f631baf6bc4caf98147a02d37b309bf 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -1975,397 +1975,6 @@ static const struct luaL_reg line_reg[] = {NULL, NULL}, }; - -/****************************************************************** - ****************************************************************** - * FS * - ****************************************************************** - ******************************************************************/ - -static int lua_fs_exists(lua_State *L) -{ - const char *file = luaL_checkstring(L, 1); - - lua_pushboolean(L, PHYSFS_exists(file)); - - return 1; -} - -static int lua_fs_isdir(lua_State *L) -{ - const char *file = luaL_checkstring(L, 1); - - lua_pushboolean(L, PHYSFS_isDirectory(file)); - - return 1; -} - -static int lua_fs_mkdir(lua_State *L) -{ - const char *dir = luaL_checkstring(L, 1); - - PHYSFS_mkdir(dir); - - return 0; -} - -static int lua_fs_delete(lua_State *L) -{ - const char *file = luaL_checkstring(L, 1); - - PHYSFS_delete(file); - - return 0; -} - -static int lua_fs_list(lua_State* L) -{ - const char *dir = luaL_checkstring(L, 1); - bool only_dir = lua_toboolean(L, 2); - - char **rc = PHYSFS_enumerateFiles(dir); - char **i; - int nb = 1; - char buf[2048]; - - lua_newtable(L); - for (i = rc; *i != NULL; i++) - { - strcpy(buf, dir); - strcat(buf, "/"); - strcat(buf, *i); - if (only_dir && (!PHYSFS_isDirectory(buf))) - continue; - - lua_pushnumber(L, nb); - lua_pushstring(L, *i); - lua_settable(L, -3); - nb++; - } - - PHYSFS_freeList(rc); - - return 1; -} - - -static int lua_fs_open(lua_State *L) -{ - const char *file = luaL_checkstring(L, 1); - const char *mode = luaL_checkstring(L, 2); - - PHYSFS_file **f = (PHYSFS_file **)lua_newuserdata(L, sizeof(PHYSFS_file *)); - auxiliar_setclass(L, "physfs{file}", -1); - - if (strchr(mode, 'w')) - *f = PHYSFS_openWrite(file); - else if (strchr(mode, 'a')) - *f = PHYSFS_openAppend(file); - else - *f = PHYSFS_openRead(file); - if (!*f) - { - lua_pop(L, 1); - lua_pushnil(L); - const char *error = PHYSFS_getLastError(); - lua_pushstring(L, error); - return 2; - } - return 1; -} - -static int lua_file_read(lua_State *L) -{ - PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); - long n = luaL_optlong(L, 2, ~((size_t)0)); - - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ - luaL_Buffer b; - luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { - char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = PHYSFS_read(*f, p, sizeof(char), rlen); - luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); - return 1; -} - -// This will return empty lines if you've got DOS-style "\r\n" endlines! -// extra credit for handling buffer overflows and EOF more gracefully. -static int lua_file_readline(lua_State *L) -{ - PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); - char buf[1024]; - char *ptr = buf; - int bufsize = 1024; - int total = 0; - - if (PHYSFS_eof(*f)) return 0; - - bufsize--; /* allow for null terminating char */ - while ((total < bufsize) && (PHYSFS_read(*f, ptr, 1, 1) == 1)) - { - if ((*ptr == '\r') || (*ptr == '\n')) - break; - ptr++; - total++; - } - - *ptr = '\0'; // null terminate it. - lua_pushstring(L, buf); - return 1; -} - - -static int lua_file_write(lua_State *L) -{ - PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); - size_t len; - const char *data = lua_tolstring(L, 2, &len); - - PHYSFS_write(*f, data, sizeof(char), len); - - return 0; -} - -static int lua_close_file(lua_State *L) -{ - PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); - if (*f) - { - PHYSFS_close(*f); - *f = NULL; - } - lua_pushnumber(L, 1); - return 1; -} - -static int lua_fs_zipopen(lua_State *L) -{ - const char *file = luaL_checkstring(L, 1); - - zipFile *zf = (zipFile*)lua_newuserdata(L, sizeof(zipFile*)); - auxiliar_setclass(L, "physfs{zip}", -1); - - *zf = zipOpen(file, APPEND_STATUS_CREATE); - if (!*zf) - { - lua_pop(L, 1); - lua_pushnil(L); - } - return 1; -} - -static int lua_close_zip(lua_State *L) -{ - zipFile *zf = (zipFile*)auxiliar_checkclass(L, "physfs{zip}", 1); - if (*zf) - { - zipClose(*zf, NULL); - *zf = NULL; - } - lua_pushnumber(L, 1); - return 1; -} - -static int lua_zip_add(lua_State *L) -{ - zipFile *zf = (zipFile*)auxiliar_checkclass(L, "physfs{zip}", 1); - const char *filenameinzip = luaL_checkstring(L, 2); - size_t datalen; - const char *data = lua_tolstring(L, 3, &datalen); - int opt_compress_level = luaL_optnumber(L, 4, 4); - - int err=0; - zip_fileinfo zi; - unsigned long crcFile=0; - - zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = - zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; - zi.dosDate = 0; - zi.internal_fa = 0; - zi.external_fa = 0; - - err = zipOpenNewFileInZip3(*zf,filenameinzip,&zi, - NULL,0,NULL,0,NULL /* comment*/, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level,0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL,crcFile); - - if (err != ZIP_OK) - { - lua_pushnil(L); - lua_pushstring(L, "could not add file to zip"); - return 2; - } - else - { - err = zipWriteInFileInZip(*zf, data, datalen); - } - - zipCloseFileInZip(*zf); - - lua_pushboolean(L, 1); - return 1; -} - -static int lua_fs_mount(lua_State *L) -{ - const char *src = luaL_checkstring(L, 1); - const char *dest = luaL_checkstring(L, 2); - bool append = lua_toboolean(L, 3); - - int err = PHYSFS_mount(src, dest, append); - if (err == 0) - { - lua_pushnil(L); - lua_pushstring(L, PHYSFS_getLastError()); - return 2; - } - lua_pushboolean(L, TRUE); - - return 1; -} - -static int lua_fs_umount(lua_State *L) -{ - const char *src = luaL_checkstring(L, 1); - - int err = PHYSFS_removeFromSearchPath(src); - if (err == 0) - { - lua_pushnil(L); - lua_pushstring(L, PHYSFS_getLastError()); - return 2; - } - lua_pushboolean(L, TRUE); - - return 1; -} - -static int lua_fs_get_real_path(lua_State *L) -{ - const char *src = luaL_checkstring(L, 1); - char *path = PHYSFS_getDependentPath(src); - lua_pushstring(L, path); - free(path); - return 1; -} - -static int lua_fs_set_write_dir(lua_State *L) -{ - const char *src = luaL_checkstring(L, 1); - const int error = PHYSFS_setWriteDir(src); - if (error == 0) - { - lua_pushnil(L); - lua_pushstring(L, PHYSFS_getLastError()); - return 2; - } - lua_pushboolean(L, TRUE); - return 1; -} - -static int lua_fs_rename(lua_State *L) -{ - const char *src = luaL_checkstring(L, 1); - const char *dst = luaL_checkstring(L, 2); - PHYSFS_rename(src, dst); - return 0; -} - -static int lua_fs_get_write_dir(lua_State *L) -{ - lua_pushstring(L, PHYSFS_getWriteDir()); - return 1; -} - -static int lua_fs_get_home_path(lua_State *L) -{ - lua_pushstring(L, TENGINE_HOME_PATH); - return 1; -} - -static int lua_fs_get_user_path(lua_State *L) -{ - lua_pushstring(L, PHYSFS_getUserDir()); - return 1; -} - -static int lua_fs_get_path_separator(lua_State *L) -{ - lua_pushstring(L, PHYSFS_getDirSeparator()); - return 1; -} - -static int lua_fs_get_search_path(lua_State *L) -{ - char **rc = PHYSFS_getSearchPath(); - - char **i; - int nb = 1; - - lua_newtable(L); - for (i = rc; *i != NULL; i++) - { - lua_pushnumber(L, nb); - lua_pushstring(L, *i); - lua_settable(L, -3); - nb++; - } - - PHYSFS_freeList(rc); - return 1; -} - -static const struct luaL_reg fslib[] = -{ - {"open", lua_fs_open}, - {"zipOpen", lua_fs_zipopen}, - {"exists", lua_fs_exists}, - {"rename", lua_fs_rename}, - {"mkdir", lua_fs_mkdir}, - {"isdir", lua_fs_isdir}, - {"delete", lua_fs_delete}, - {"list", lua_fs_list}, - {"setWritePath", lua_fs_set_write_dir}, - {"getWritePath", lua_fs_get_write_dir}, - {"getPathSeparator", lua_fs_get_path_separator}, - {"getRealPath", lua_fs_get_real_path}, - {"getUserPath", lua_fs_get_user_path}, - {"getHomePath", lua_fs_get_home_path}, - {"getSearchPath", lua_fs_get_search_path}, - {"mount", lua_fs_mount}, - {"umount", lua_fs_umount}, - {NULL, NULL}, -}; - -static const struct luaL_reg fsfile_reg[] = -{ - {"__gc", lua_close_file}, - {"close", lua_close_file}, - {"read", lua_file_read}, - {"readLine", lua_file_readline}, - {"write", lua_file_write}, - {NULL, NULL}, -}; - -static const struct luaL_reg fszipfile_reg[] = -{ - {"__gc", lua_close_zip}, - {"close", lua_close_zip}, - {"add", lua_zip_add}, - {NULL, NULL}, -}; - /****************************************************************** ****************************************************************** * ZLIB * @@ -2442,8 +2051,6 @@ static const struct luaL_reg zliblib[] = int luaopen_core(lua_State *L) { - auxiliar_newclass(L, "physfs{file}", fsfile_reg); - auxiliar_newclass(L, "physfs{zip}", fszipfile_reg); auxiliar_newclass(L, "line{core}", line_reg); auxiliar_newclass(L, "gl{texture}", sdl_texture_reg); auxiliar_newclass(L, "gl{fbo}", gl_fbo_reg); @@ -2461,8 +2068,7 @@ int luaopen_core(lua_State *L) luaL_openlib(L, "rng", rnglib, 0); luaL_openlib(L, "line", linelib, 0); - luaL_openlib(L, "fs", fslib, 0); - lua_pop(L, 8); + lua_settop(L, 0); return 1; } diff --git a/src/main.c b/src/main.c index 0228c330ec967786c1c3aa25ed2fc9550d2d0c9e..7babeb1e7dadbd103428222963c821be8d48f686 100644 --- a/src/main.c +++ b/src/main.c @@ -687,9 +687,8 @@ void boot_lua(int state, bool rebooting, int argc, char *argv[]) PHYSFS_init(argv[0]); selfexe = get_self_executable(argc, argv); - if (selfexe) + if (selfexe && PHYSFS_mount(selfexe, "/", 1)) { - PHYSFS_mount(selfexe, "/", 1); } else { @@ -700,6 +699,7 @@ void boot_lua(int state, bool rebooting, int argc, char *argv[]) /***************** Lua Init *****************/ L = lua_open(); /* create state */ luaL_openlibs(L); /* open libraries */ + luaopen_physfs(L); luaopen_core(L); luaopen_fov(L); luaopen_socket_core(L); diff --git a/src/physfs.c b/src/physfs.c new file mode 100644 index 0000000000000000000000000000000000000000..8d09b45d66dd30de6ef3c0b68a73927257498bd4 --- /dev/null +++ b/src/physfs.c @@ -0,0 +1,429 @@ +/* + TE4 - T-Engine 4 + Copyright (C) 2009, 2010 Nicolas Casalini + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + Nicolas Casalini "DarkGod" + darkgod@te4.org +*/ +#include <string.h> +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "auxiliar.h" +#include "physfs.h" +#include "mzip.h" +#include "zlib.h" +#include "types.h" + +/****************************************************************** + ****************************************************************** + * FS * + ****************************************************************** + ******************************************************************/ + +static int lua_fs_exists(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + + lua_pushboolean(L, PHYSFS_exists(file)); + + return 1; +} + +static int lua_fs_isdir(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + + lua_pushboolean(L, PHYSFS_isDirectory(file)); + + return 1; +} + +static int lua_fs_mkdir(lua_State *L) +{ + const char *dir = luaL_checkstring(L, 1); + + PHYSFS_mkdir(dir); + + return 0; +} + +static int lua_fs_delete(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + + PHYSFS_delete(file); + + return 0; +} + +static int lua_fs_list(lua_State* L) +{ + const char *dir = luaL_checkstring(L, 1); + bool only_dir = lua_toboolean(L, 2); + + char **rc = PHYSFS_enumerateFiles(dir); + char **i; + int nb = 1; + char buf[2048]; + + lua_newtable(L); + for (i = rc; *i != NULL; i++) + { + strcpy(buf, dir); + strcat(buf, "/"); + strcat(buf, *i); + if (only_dir && (!PHYSFS_isDirectory(buf))) + continue; + + lua_pushnumber(L, nb); + lua_pushstring(L, *i); + lua_settable(L, -3); + nb++; + } + + PHYSFS_freeList(rc); + + return 1; +} + + +static int lua_fs_open(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + const char *mode = luaL_checkstring(L, 2); + + PHYSFS_file **f = (PHYSFS_file **)lua_newuserdata(L, sizeof(PHYSFS_file *)); + auxiliar_setclass(L, "physfs{file}", -1); + + if (strchr(mode, 'w')) + *f = PHYSFS_openWrite(file); + else if (strchr(mode, 'a')) + *f = PHYSFS_openAppend(file); + else + *f = PHYSFS_openRead(file); + if (!*f) + { + lua_pop(L, 1); + lua_pushnil(L); + const char *error = PHYSFS_getLastError(); + lua_pushstring(L, error); + return 2; + } + return 1; +} + +static int lua_file_read(lua_State *L) +{ + PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); + long n = luaL_optlong(L, 2, ~((size_t)0)); + + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = PHYSFS_read(*f, p, sizeof(char), rlen); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); + return 1; +} + +// This will return empty lines if you've got DOS-style "\r\n" endlines! +// extra credit for handling buffer overflows and EOF more gracefully. +static int lua_file_readline(lua_State *L) +{ + PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); + char buf[1024]; + char *ptr = buf; + int bufsize = 1024; + int total = 0; + + if (PHYSFS_eof(*f)) return 0; + + bufsize--; /* allow for null terminating char */ + while ((total < bufsize) && (PHYSFS_read(*f, ptr, 1, 1) == 1)) + { + if ((*ptr == '\r') || (*ptr == '\n')) + break; + ptr++; + total++; + } + + *ptr = '\0'; // null terminate it. + lua_pushstring(L, buf); + return 1; +} + + +static int lua_file_write(lua_State *L) +{ + PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); + size_t len; + const char *data = lua_tolstring(L, 2, &len); + + PHYSFS_write(*f, data, sizeof(char), len); + + return 0; +} + +static int lua_close_file(lua_State *L) +{ + PHYSFS_file **f = (PHYSFS_file**)auxiliar_checkclass(L, "physfs{file}", 1); + if (*f) + { + PHYSFS_close(*f); + *f = NULL; + } + lua_pushnumber(L, 1); + return 1; +} + +static int lua_fs_zipopen(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + + zipFile *zf = (zipFile*)lua_newuserdata(L, sizeof(zipFile*)); + auxiliar_setclass(L, "physfs{zip}", -1); + + *zf = zipOpen(file, APPEND_STATUS_CREATE); + if (!*zf) + { + lua_pop(L, 1); + lua_pushnil(L); + } + return 1; +} + +static int lua_close_zip(lua_State *L) +{ + zipFile *zf = (zipFile*)auxiliar_checkclass(L, "physfs{zip}", 1); + if (*zf) + { + zipClose(*zf, NULL); + *zf = NULL; + } + lua_pushnumber(L, 1); + return 1; +} + +static int lua_zip_add(lua_State *L) +{ + zipFile *zf = (zipFile*)auxiliar_checkclass(L, "physfs{zip}", 1); + const char *filenameinzip = luaL_checkstring(L, 2); + size_t datalen; + const char *data = lua_tolstring(L, 3, &datalen); + int opt_compress_level = luaL_optnumber(L, 4, 4); + + int err=0; + zip_fileinfo zi; + unsigned long crcFile=0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + + err = zipOpenNewFileInZip3(*zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL /* comment*/, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level,0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL,crcFile); + + if (err != ZIP_OK) + { + lua_pushnil(L); + lua_pushstring(L, "could not add file to zip"); + return 2; + } + else + { + err = zipWriteInFileInZip(*zf, data, datalen); + } + + zipCloseFileInZip(*zf); + + lua_pushboolean(L, 1); + return 1; +} + +static int lua_fs_mount(lua_State *L) +{ + const char *src = luaL_checkstring(L, 1); + const char *dest = luaL_checkstring(L, 2); + bool append = lua_toboolean(L, 3); + + int err = PHYSFS_mount(src, dest, append); + if (err == 0) + { + lua_pushnil(L); + lua_pushstring(L, PHYSFS_getLastError()); + return 2; + } + lua_pushboolean(L, TRUE); + + return 1; +} + +static int lua_fs_umount(lua_State *L) +{ + const char *src = luaL_checkstring(L, 1); + + int err = PHYSFS_removeFromSearchPath(src); + if (err == 0) + { + lua_pushnil(L); + lua_pushstring(L, PHYSFS_getLastError()); + return 2; + } + lua_pushboolean(L, TRUE); + + return 1; +} + +static int lua_fs_get_real_path(lua_State *L) +{ + const char *src = luaL_checkstring(L, 1); + char *path = PHYSFS_getDependentPath(src); + lua_pushstring(L, path); + free(path); + return 1; +} + +static int lua_fs_set_write_dir(lua_State *L) +{ + const char *src = luaL_checkstring(L, 1); + const int error = PHYSFS_setWriteDir(src); + if (error == 0) + { + lua_pushnil(L); + lua_pushstring(L, PHYSFS_getLastError()); + return 2; + } + lua_pushboolean(L, TRUE); + return 1; +} + +static int lua_fs_rename(lua_State *L) +{ + const char *src = luaL_checkstring(L, 1); + const char *dst = luaL_checkstring(L, 2); + PHYSFS_rename(src, dst); + return 0; +} + +static int lua_fs_get_write_dir(lua_State *L) +{ + lua_pushstring(L, PHYSFS_getWriteDir()); + return 1; +} + +static int lua_fs_get_home_path(lua_State *L) +{ + lua_pushstring(L, TENGINE_HOME_PATH); + return 1; +} + +static int lua_fs_get_user_path(lua_State *L) +{ + lua_pushstring(L, PHYSFS_getUserDir()); + return 1; +} + +static int lua_fs_get_path_separator(lua_State *L) +{ + lua_pushstring(L, PHYSFS_getDirSeparator()); + return 1; +} + +static int lua_fs_get_search_path(lua_State *L) +{ + char **rc = PHYSFS_getSearchPath(); + + char **i; + int nb = 1; + + lua_newtable(L); + for (i = rc; *i != NULL; i++) + { + lua_pushnumber(L, nb); + lua_pushstring(L, *i); + lua_settable(L, -3); + nb++; + } + + PHYSFS_freeList(rc); + return 1; +} + +static const struct luaL_reg fslib[] = +{ + {"open", lua_fs_open}, + {"zipOpen", lua_fs_zipopen}, + {"exists", lua_fs_exists}, + {"rename", lua_fs_rename}, + {"mkdir", lua_fs_mkdir}, + {"isdir", lua_fs_isdir}, + {"delete", lua_fs_delete}, + {"list", lua_fs_list}, + {"setWritePath", lua_fs_set_write_dir}, + {"getWritePath", lua_fs_get_write_dir}, + {"getPathSeparator", lua_fs_get_path_separator}, + {"getRealPath", lua_fs_get_real_path}, + {"getUserPath", lua_fs_get_user_path}, + {"getHomePath", lua_fs_get_home_path}, + {"getSearchPath", lua_fs_get_search_path}, + {"mount", lua_fs_mount}, + {"umount", lua_fs_umount}, + {NULL, NULL}, +}; + +static const struct luaL_reg fsfile_reg[] = +{ + {"__gc", lua_close_file}, + {"close", lua_close_file}, + {"read", lua_file_read}, + {"readLine", lua_file_readline}, + {"write", lua_file_write}, + {NULL, NULL}, +}; + +static const struct luaL_reg fszipfile_reg[] = +{ + {"__gc", lua_close_zip}, + {"close", lua_close_zip}, + {"add", lua_zip_add}, + {NULL, NULL}, +}; + +int luaopen_physfs(lua_State *L) +{ + auxiliar_newclass(L, "physfs{file}", fsfile_reg); + auxiliar_newclass(L, "physfs{zip}", fszipfile_reg); + luaL_openlib(L, "fs", fslib, 0); + + lua_settop(L, 0); + return 1; +} diff --git a/src/runner/main.c b/src/runner/main.c index f19ba5ccffc57b9f2f406ac88505253afbbf8895..b4b0d7d0eb1be119c5a05e6bc6154b27aabc1b41 100644 --- a/src/runner/main.c +++ b/src/runner/main.c @@ -28,6 +28,9 @@ #include <dlfcn.h> #endif +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" #include "physfs.h" // Load the shared lib containing the core and calls te4main inside it, passing control to that core @@ -35,20 +38,70 @@ int run_core(int corenum, int argc, char **argv) { int (*te4main)(int, char**); + /****************************************************************** + ** Find a core file + ******************************************************************/ + PHYSFS_init(argv[0]); + + const char *selfexe = get_self_executable(argc, argv); + if (selfexe && PHYSFS_mount(selfexe, "/", 1)) {} else + { + printf("NO SELFEXE: bootstrapping from CWD\n"); + PHYSFS_mount("bootstrap", "/bootstrap", 1); + } + + lua_State *L = lua_open(); + luaL_openlibs(L); + luaopen_physfs(L); + + // Tell the boostrapping code the selfexe path + if (selfexe) lua_pushstring(L, selfexe); + else lua_pushnil(L); + lua_setglobal(L, "__SELFEXE"); + + // Will be useful +#ifdef __APPLE__ + lua_pushboolean(L, TRUE); + lua_setglobal(L, "__APPLE__"); +#endif + + // Run bootstrapping + if (!luaL_loadfile(L, "/bootstrap/boot.lua")) { lua_call(L, 0, 0); } + // Could not load bootstrap! Try to mount the engine from working directory as last resort + else + { + printf("Could not find bootstrapping code! Aborting!\n"); + exit(1); + } + + // Get the core + lua_getglobal(L, "get_core"); + lua_pushnumber(L, corenum); + lua_call(L, 1, 1); + char *core = lua_tostring(L, -1); + + lua_close(L); + PHYSFS_deinit(); + + if (!core) { + printf("No core found!"); + exit(1); + } + /*********************************************************************** ** Windows DLL loading code ***********************************************************************/ #ifdef SELFEXE_WINDOWS - HINSTANCE handle = LoadLibrary("game/engines/cores/te4core-12.dll"); + HINSTANCE handle = LoadLibrary(core); if (!handle) { - fprintf(stderr, "Error loading core %d: %d\n", corenum, GetLastError()); + fprintf(stderr, "Error loading core %d (%s): %d\n", corenum, core, GetLastError()); exit(EXIT_FAILURE); } te4main = GetProcAddress(handle, "te4main"); if (te4main == NULL) { - fprintf(stderr, "Error binding to core %d: %d\n", corenum, GetLastError()); + fprintf(stderr, "Error binding to core %d (%s): %d\n", corenum, core, GetLastError()); exit(EXIT_FAILURE); } @@ -63,9 +116,9 @@ int run_core(int corenum, int argc, char **argv) #else char *error; - void *handle = dlopen("game/engines/cores/te4core-12.so", RTLD_LAZY); + void *handle = dlopen(core, RTLD_LAZY); if (!handle) { - fprintf(stderr, "Error loading core %d: %s\n", corenum, dlerror()); + fprintf(stderr, "Error loading core %d (%s): %s\n", corenum, core, dlerror()); exit(EXIT_FAILURE); } @@ -81,7 +134,7 @@ int run_core(int corenum, int argc, char **argv) *(void **) (&te4main) = dlsym(handle, "te4main"); if ((error = dlerror()) != NULL) { - fprintf(stderr, "Error binding to core %d: %s\n", corenum, error); + fprintf(stderr, "Error binding to core %d (%s): %s\n", corenum, core, error); exit(EXIT_FAILURE); } @@ -91,6 +144,8 @@ int run_core(int corenum, int argc, char **argv) dlclose(handle); #endif + free(core); + return corenum; } @@ -106,22 +161,6 @@ int main(int argc, char **argv) { int core = 12; - /***************** Physfs Init *****************/ - PHYSFS_init(argv[0]); - - const char *selfexe = get_self_executable(argc, argv); - if (selfexe) - { - PHYSFS_mount(selfexe, "/", 1); - } - else - { - printf("NO SELFEXE: bootstrapping from CWD\n"); - PHYSFS_mount("bootstrap", "/bootstrap", 1); - } - - PHYSFS_deinit(); - // Run the requested cores until we want no more while (core) core = run_core(core, argc, argv);