diff --git a/demo/cart.fnl b/demo/cart.fnl index bb0e721..235cffe 100644 --- a/demo/cart.fnl +++ b/demo/cart.fnl @@ -1,4 +1,4 @@ {:title "pxl8 demo" + :pixel-mode "indexed" :resolution "640x360" - :window-size [1280 720] - :pixel-mode "indexed"} + :window-size [1280 720]} diff --git a/pxl8.sh b/pxl8.sh index f7257e3..f6a82c1 100755 --- a/pxl8.sh +++ b/pxl8.sh @@ -406,17 +406,21 @@ case "$COMMAND" in "$0" build "$@" || exit 1 CART="" + EXTRA_ARGS="" for arg in "$@"; do - if [[ "$arg" != "--release" ]]; then + if [[ "$arg" == "--release" ]]; then + continue + elif [[ "$arg" == "--repl" ]]; then + EXTRA_ARGS="$EXTRA_ARGS --repl" + elif [[ -z "$CART" ]]; then CART="$arg" - break fi done if [[ -z "$CART" ]]; then - "$BINDIR/pxl8" + "$BINDIR/pxl8" $EXTRA_ARGS else - "$BINDIR/pxl8" "$CART" + "$BINDIR/pxl8" "$CART" $EXTRA_ARGS fi ;; diff --git a/src/lua/pxl8.lua b/src/lua/pxl8.lua index 5cbd0cd..750a499 100644 --- a/src/lua/pxl8.lua +++ b/src/lua/pxl8.lua @@ -18,8 +18,9 @@ core.init(_pxl8_gfx, _pxl8_input, _pxl8_sys) local pxl8 = {} pxl8.get_fps = core.get_fps -pxl8.get_width = core.get_width pxl8.get_height = core.get_height +pxl8.get_title = core.get_title +pxl8.get_width = core.get_width pxl8.info = core.info pxl8.warn = core.warn pxl8.error = core.error diff --git a/src/lua/pxl8/core.lua b/src/lua/pxl8/core.lua index e4b0348..531e3da 100644 --- a/src/lua/pxl8/core.lua +++ b/src/lua/pxl8/core.lua @@ -21,6 +21,17 @@ function core.get_height() return C.pxl8_gfx_get_height(core.gfx) end +function core.get_title() + local cart = C.pxl8_get_cart() + if cart ~= nil then + local title = C.pxl8_cart_get_title(cart) + if title ~= nil then + return ffi.string(title) + end + end + return "pxl8" +end + local function is_user_script(info) local src = info and info.short_src return src and (src:match("%.fnl$") or src:match("%.lua$")) diff --git a/src/pxl8.c b/src/pxl8.c index 28867c6..9f5ea5c 100644 --- a/src/pxl8.c +++ b/src/pxl8.c @@ -2,6 +2,7 @@ #define PXL8_COPYRIGHT "Copyright (c) 2024-2025 pxl8.org" #define PXL8_VERSION "0.1.0" +#include #include #include @@ -60,6 +61,20 @@ void pxl8_destroy(pxl8* sys) { free(sys); } +static void pxl8_print_help(void) { + printf("pxl8 %s - pixel art game framework\n", PXL8_VERSION); + printf("%s\n\n", PXL8_COPYRIGHT); + printf("Usage: pxl8 [path] [--repl]\n\n"); + printf(" pxl8 Run main.fnl from current directory\n"); + printf(" pxl8 ./game Run game from folder\n"); + printf(" pxl8 game.pxc Run packed cart file\n"); + printf(" pxl8 --repl Run with REPL enabled\n\n"); + printf("Other commands:\n"); + printf(" pxl8 pack Pack folder into cart file\n"); + printf(" pxl8 bundle Bundle cart into executable\n"); + printf(" pxl8 help Show this help\n"); +} + pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) { if (!sys || !sys->game) return PXL8_ERROR_INVALID_ARGUMENT; @@ -67,28 +82,36 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) { const char* script_arg = NULL; bool bundle_mode = false; bool pack_mode = false; + bool run_mode = false; const char* pack_input = NULL; const char* pack_output = NULL; + bool has_embedded = pxl8_cart_has_embedded(argv[0]); + for (i32 i = 1; i < argc; i++) { - if (strcmp(argv[i], "--repl") == 0) { + if (strcmp(argv[i], "help") == 0 || strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + pxl8_print_help(); + return PXL8_ERROR_INVALID_ARGUMENT; + } else if (strcmp(argv[i], "run") == 0) { + run_mode = true; + } else if (strcmp(argv[i], "--repl") == 0) { game->repl_mode = true; - } else if (strcmp(argv[i], "--bundle") == 0) { + } else if (strcmp(argv[i], "bundle") == 0 || strcmp(argv[i], "--bundle") == 0) { bundle_mode = true; if (i + 2 < argc) { pack_input = argv[++i]; pack_output = argv[++i]; } else { - pxl8_error("--bundle requires "); + pxl8_error("bundle requires "); return PXL8_ERROR_INVALID_ARGUMENT; } - } else if (strcmp(argv[i], "--pack") == 0) { + } else if (strcmp(argv[i], "pack") == 0 || strcmp(argv[i], "--pack") == 0) { pack_mode = true; if (i + 2 < argc) { pack_input = argv[++i]; pack_output = argv[++i]; } else { - pxl8_error("--pack requires "); + pxl8_error("pack requires "); return PXL8_ERROR_INVALID_ARGUMENT; } } else if (!script_arg) { @@ -96,6 +119,10 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) { } } + if (!run_mode && !bundle_mode && !pack_mode) { + run_mode = true; + } + if (bundle_mode) { char exe_path[1024]; ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); @@ -121,18 +148,25 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) { return PXL8_ERROR_INITIALIZATION_FAILED; } - bool has_embedded = pxl8_cart_has_embedded(argv[0]); const char* cart_path = script_arg; char* original_cwd = getcwd(NULL, 0); - bool load_embedded = has_embedded && !script_arg; + bool load_embedded = has_embedded && !run_mode; bool load_from_path = false; - if (!load_embedded && (cart_path || !has_embedded)) { - if (!cart_path) cart_path = "demo"; + if (!load_embedded && run_mode) { + if (!cart_path) { + if (access("main.fnl", F_OK) == 0 || access("main.lua", F_OK) == 0) { + cart_path = "."; + } else { + pxl8_error("no main.fnl or main.lua found in current directory"); + free(original_cwd); + return PXL8_ERROR_INITIALIZATION_FAILED; + } + } struct stat st; load_from_path = (stat(cart_path, &st) == 0 && S_ISDIR(st.st_mode)) || - (cart_path && strstr(cart_path, ".pxc")); + strstr(cart_path, ".pxc"); } if (load_embedded || load_from_path) { diff --git a/src/pxl8_cart.c b/src/pxl8_cart.c index 431132d..1bbf69f 100644 --- a/src/pxl8_cart.c +++ b/src/pxl8_cart.c @@ -160,7 +160,7 @@ pxl8_cart* pxl8_cart_create(void) { return cart; } -pxl8_cart* pxl8_cart_current(void) { +pxl8_cart* pxl8_get_cart(void) { return pxl8_current_cart; } diff --git a/src/pxl8_cart.h b/src/pxl8_cart.h index 16b5914..b142c9b 100644 --- a/src/pxl8_cart.h +++ b/src/pxl8_cart.h @@ -9,7 +9,6 @@ extern "C" { #endif pxl8_cart* pxl8_cart_create(void); -pxl8_cart* pxl8_cart_current(void); void pxl8_cart_destroy(pxl8_cart* cart); pxl8_result pxl8_cart_bundle(const char* input_path, const char* output_path, const char* exe_path); @@ -21,6 +20,7 @@ void pxl8_cart_unload(pxl8_cart* cart); pxl8_result pxl8_cart_mount(pxl8_cart* cart); void pxl8_cart_unmount(pxl8_cart* cart); +pxl8_cart* pxl8_get_cart(void); const char* pxl8_cart_get_base_path(const pxl8_cart* cart); const char* pxl8_cart_get_title(const pxl8_cart* cart); pxl8_resolution pxl8_cart_get_resolution(const pxl8_cart* cart); diff --git a/src/pxl8_io.c b/src/pxl8_io.c index f112bb9..ae354b7 100644 --- a/src/pxl8_io.c +++ b/src/pxl8_io.c @@ -13,7 +13,7 @@ static inline char pxl8_to_lower(char c) { pxl8_result pxl8_io_read_file(const char* path, char** content, size_t* size) { if (!path || !content || !size) return PXL8_ERROR_NULL_POINTER; - pxl8_cart* cart = pxl8_cart_current(); + pxl8_cart* cart = pxl8_get_cart(); if (cart && pxl8_cart_is_packed(cart)) { u8* data = NULL; u32 cart_size = 0; diff --git a/src/pxl8_script.c b/src/pxl8_script.c index 70a092d..c5972b1 100644 --- a/src/pxl8_script.c +++ b/src/pxl8_script.c @@ -66,7 +66,7 @@ static int pxl8_cart_loader(lua_State* L) { static int pxl8_cart_searcher(lua_State* L) { const char* modname = luaL_checkstring(L, 1); - pxl8_cart* cart = pxl8_cart_current(); + pxl8_cart* cart = pxl8_get_cart(); if (!cart || !pxl8_cart_is_packed(cart)) { lua_pushstring(L, "\n\tno packed cart mounted"); return 1; @@ -212,6 +212,9 @@ static const char* pxl8_ffi_cdefs = "void pxl8_set_relative_mouse_mode(pxl8* sys, bool enabled);\n" "void pxl8_set_running(pxl8* sys, bool running);\n" "void pxl8_lua_log(int level, const char* file, int line, const char* msg);\n" +"typedef struct pxl8_cart pxl8_cart;\n" +"pxl8_cart* pxl8_get_cart(void);\n" +"const char* pxl8_cart_get_title(const pxl8_cart* cart);\n" "typedef u32 pxl8_tile;\n" "typedef struct pxl8_tilemap pxl8_tilemap;\n" "typedef struct pxl8_tilesheet pxl8_tilesheet;\n" @@ -736,7 +739,7 @@ pxl8_result pxl8_script_run_fennel_file(pxl8_script* script, const char* filenam return PXL8_ERROR_SCRIPT_ERROR; } - pxl8_cart* cart = pxl8_cart_current(); + pxl8_cart* cart = pxl8_get_cart(); pxl8_result result = PXL8_OK; if (cart && pxl8_cart_is_packed(cart)) {