add pxl8.get_title() API to expose cart title to Lua

This commit is contained in:
asrael 2025-12-07 15:52:54 -06:00
parent db82efe269
commit 99d9c43ea3
No known key found for this signature in database
GPG key ID: 2786557804DFAE24
9 changed files with 75 additions and 22 deletions

View file

@ -1,4 +1,4 @@
{:title "pxl8 demo" {:title "pxl8 demo"
:pixel-mode "indexed"
:resolution "640x360" :resolution "640x360"
:window-size [1280 720] :window-size [1280 720]}
:pixel-mode "indexed"}

12
pxl8.sh
View file

@ -406,17 +406,21 @@ case "$COMMAND" in
"$0" build "$@" || exit 1 "$0" build "$@" || exit 1
CART="" CART=""
EXTRA_ARGS=""
for arg in "$@"; do 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" CART="$arg"
break
fi fi
done done
if [[ -z "$CART" ]]; then if [[ -z "$CART" ]]; then
"$BINDIR/pxl8" "$BINDIR/pxl8" $EXTRA_ARGS
else else
"$BINDIR/pxl8" "$CART" "$BINDIR/pxl8" "$CART" $EXTRA_ARGS
fi fi
;; ;;

View file

@ -18,8 +18,9 @@ core.init(_pxl8_gfx, _pxl8_input, _pxl8_sys)
local pxl8 = {} local pxl8 = {}
pxl8.get_fps = core.get_fps pxl8.get_fps = core.get_fps
pxl8.get_width = core.get_width
pxl8.get_height = core.get_height pxl8.get_height = core.get_height
pxl8.get_title = core.get_title
pxl8.get_width = core.get_width
pxl8.info = core.info pxl8.info = core.info
pxl8.warn = core.warn pxl8.warn = core.warn
pxl8.error = core.error pxl8.error = core.error

View file

@ -21,6 +21,17 @@ function core.get_height()
return C.pxl8_gfx_get_height(core.gfx) return C.pxl8_gfx_get_height(core.gfx)
end 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 function is_user_script(info)
local src = info and info.short_src local src = info and info.short_src
return src and (src:match("%.fnl$") or src:match("%.lua$")) return src and (src:match("%.fnl$") or src:match("%.lua$"))

View file

@ -2,6 +2,7 @@
#define PXL8_COPYRIGHT "Copyright (c) 2024-2025 pxl8.org" #define PXL8_COPYRIGHT "Copyright (c) 2024-2025 pxl8.org"
#define PXL8_VERSION "0.1.0" #define PXL8_VERSION "0.1.0"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -60,6 +61,20 @@ void pxl8_destroy(pxl8* sys) {
free(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 <folder> <out.pxc> Pack folder into cart file\n");
printf(" pxl8 bundle <in> <out> Bundle cart into executable\n");
printf(" pxl8 help Show this help\n");
}
pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) { pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
if (!sys || !sys->game) return PXL8_ERROR_INVALID_ARGUMENT; 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; const char* script_arg = NULL;
bool bundle_mode = false; bool bundle_mode = false;
bool pack_mode = false; bool pack_mode = false;
bool run_mode = false;
const char* pack_input = NULL; const char* pack_input = NULL;
const char* pack_output = NULL; const char* pack_output = NULL;
bool has_embedded = pxl8_cart_has_embedded(argv[0]);
for (i32 i = 1; i < argc; i++) { 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; 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; bundle_mode = true;
if (i + 2 < argc) { if (i + 2 < argc) {
pack_input = argv[++i]; pack_input = argv[++i];
pack_output = argv[++i]; pack_output = argv[++i];
} else { } else {
pxl8_error("--bundle requires <folder|.pxc> <output>"); pxl8_error("bundle requires <folder|.pxc> <output>");
return PXL8_ERROR_INVALID_ARGUMENT; 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; pack_mode = true;
if (i + 2 < argc) { if (i + 2 < argc) {
pack_input = argv[++i]; pack_input = argv[++i];
pack_output = argv[++i]; pack_output = argv[++i];
} else { } else {
pxl8_error("--pack requires <folder> <output.pxc>"); pxl8_error("pack requires <folder> <output.pxc>");
return PXL8_ERROR_INVALID_ARGUMENT; return PXL8_ERROR_INVALID_ARGUMENT;
} }
} else if (!script_arg) { } 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) { if (bundle_mode) {
char exe_path[1024]; char exe_path[1024];
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); 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; return PXL8_ERROR_INITIALIZATION_FAILED;
} }
bool has_embedded = pxl8_cart_has_embedded(argv[0]);
const char* cart_path = script_arg; const char* cart_path = script_arg;
char* original_cwd = getcwd(NULL, 0); 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; bool load_from_path = false;
if (!load_embedded && (cart_path || !has_embedded)) { if (!load_embedded && run_mode) {
if (!cart_path) cart_path = "demo"; 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; struct stat st;
load_from_path = (stat(cart_path, &st) == 0 && S_ISDIR(st.st_mode)) || 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) { if (load_embedded || load_from_path) {

View file

@ -160,7 +160,7 @@ pxl8_cart* pxl8_cart_create(void) {
return cart; return cart;
} }
pxl8_cart* pxl8_cart_current(void) { pxl8_cart* pxl8_get_cart(void) {
return pxl8_current_cart; return pxl8_current_cart;
} }

View file

@ -9,7 +9,6 @@ extern "C" {
#endif #endif
pxl8_cart* pxl8_cart_create(void); pxl8_cart* pxl8_cart_create(void);
pxl8_cart* pxl8_cart_current(void);
void pxl8_cart_destroy(pxl8_cart* cart); void pxl8_cart_destroy(pxl8_cart* cart);
pxl8_result pxl8_cart_bundle(const char* input_path, const char* output_path, const char* exe_path); 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); pxl8_result pxl8_cart_mount(pxl8_cart* cart);
void pxl8_cart_unmount(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_base_path(const pxl8_cart* cart);
const char* pxl8_cart_get_title(const pxl8_cart* cart); const char* pxl8_cart_get_title(const pxl8_cart* cart);
pxl8_resolution pxl8_cart_get_resolution(const pxl8_cart* cart); pxl8_resolution pxl8_cart_get_resolution(const pxl8_cart* cart);

View file

@ -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) { pxl8_result pxl8_io_read_file(const char* path, char** content, size_t* size) {
if (!path || !content || !size) return PXL8_ERROR_NULL_POINTER; 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)) { if (cart && pxl8_cart_is_packed(cart)) {
u8* data = NULL; u8* data = NULL;
u32 cart_size = 0; u32 cart_size = 0;

View file

@ -66,7 +66,7 @@ static int pxl8_cart_loader(lua_State* L) {
static int pxl8_cart_searcher(lua_State* L) { static int pxl8_cart_searcher(lua_State* L) {
const char* modname = luaL_checkstring(L, 1); 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)) { if (!cart || !pxl8_cart_is_packed(cart)) {
lua_pushstring(L, "\n\tno packed cart mounted"); lua_pushstring(L, "\n\tno packed cart mounted");
return 1; 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_relative_mouse_mode(pxl8* sys, bool enabled);\n"
"void pxl8_set_running(pxl8* sys, bool running);\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" "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 u32 pxl8_tile;\n"
"typedef struct pxl8_tilemap pxl8_tilemap;\n" "typedef struct pxl8_tilemap pxl8_tilemap;\n"
"typedef struct pxl8_tilesheet pxl8_tilesheet;\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; return PXL8_ERROR_SCRIPT_ERROR;
} }
pxl8_cart* cart = pxl8_cart_current(); pxl8_cart* cart = pxl8_get_cart();
pxl8_result result = PXL8_OK; pxl8_result result = PXL8_OK;
if (cart && pxl8_cart_is_packed(cart)) { if (cart && pxl8_cart_is_packed(cart)) {