refactor: add helpers for file I/O, main script detection, safe strncpy, & make hal generic

This commit is contained in:
asrael 2025-12-06 15:04:53 -06:00
parent a33d4c0068
commit db82efe269
No known key found for this signature in database
GPG key ID: 2786557804DFAE24
19 changed files with 327 additions and 457 deletions

View file

@ -45,7 +45,10 @@ struct pxl8_cart {
pxl8_cart_file* files;
u32 file_count;
char* base_path;
char* name;
char* title;
pxl8_resolution resolution;
pxl8_size window_size;
pxl8_pixel_mode pixel_mode;
bool is_folder;
bool is_mounted;
};
@ -63,19 +66,12 @@ static bool is_pxc_file(const char* path) {
return len > 4 && strcmp(path + len - 4, ".pxc") == 0;
}
static char* get_cart_name(const char* path) {
char* name = strdup(path);
size_t len = strlen(name);
if (len > 4 && strcmp(name + len - 4, ".pxc") == 0) {
name[len - 4] = '\0';
}
char* last_slash = strrchr(name, '/');
if (last_slash) {
char* result = strdup(last_slash + 1);
free(name);
return result;
}
return name;
static bool has_main_script(const char* base_path) {
char path[512];
snprintf(path, sizeof(path), "%s/main.fnl", base_path);
if (access(path, F_OK) == 0) return true;
snprintf(path, sizeof(path), "%s/main.lua", base_path);
return access(path, F_OK) == 0;
}
static void collect_files_recursive(const char* dir_path, const char* prefix,
@ -155,7 +151,13 @@ static pxl8_result load_packed_cart(pxl8_cart* cart, const u8* data, u32 size) {
}
pxl8_cart* pxl8_cart_create(void) {
return calloc(1, sizeof(pxl8_cart));
pxl8_cart* cart = calloc(1, sizeof(pxl8_cart));
if (cart) {
cart->resolution = PXL8_RESOLUTION_640x360;
cart->window_size = (pxl8_size){1280, 720};
cart->pixel_mode = PXL8_PIXEL_INDEXED;
}
return cart;
}
pxl8_cart* pxl8_cart_current(void) {
@ -171,7 +173,6 @@ void pxl8_cart_destroy(pxl8_cart* cart) {
pxl8_result pxl8_cart_load(pxl8_cart* cart, const char* path) {
if (!cart || !path) return PXL8_ERROR_NULL_POINTER;
pxl8_cart_unload(cart);
cart->name = get_cart_name(path);
if (is_directory(path)) {
cart->base_path = realpath(path, NULL);
@ -181,17 +182,12 @@ pxl8_result pxl8_cart_load(pxl8_cart* cart, const char* path) {
}
cart->is_folder = true;
char main_path[512];
snprintf(main_path, sizeof(main_path), "%s/main.fnl", cart->base_path);
if (access(main_path, F_OK) != 0) {
snprintf(main_path, sizeof(main_path), "%s/main.lua", cart->base_path);
if (access(main_path, F_OK) != 0) {
pxl8_error("No main.fnl or main.lua found in cart: %s", path);
return PXL8_ERROR_FILE_NOT_FOUND;
}
if (!has_main_script(cart->base_path)) {
pxl8_error("No main.fnl or main.lua found in cart: %s", path);
return PXL8_ERROR_FILE_NOT_FOUND;
}
pxl8_info("Loaded cart folder: %s", cart->name);
pxl8_info("Loaded cart");
return PXL8_OK;
}
@ -218,7 +214,7 @@ pxl8_result pxl8_cart_load(pxl8_cart* cart, const char* path) {
free(data);
if (result == PXL8_OK) {
pxl8_info("Loaded cart: %s", cart->name);
pxl8_info("Loaded cart");
}
return result;
}
@ -254,19 +250,27 @@ pxl8_result pxl8_cart_load_embedded(pxl8_cart* cart, const char* exe_path) {
}
fclose(file);
cart->name = get_cart_name(exe_path);
pxl8_result result = load_packed_cart(cart, data, trailer.cart_size);
free(data);
if (result == PXL8_OK) {
pxl8_info("Loaded embedded cart: %s", cart->name);
pxl8_info("Loaded embedded cart");
}
return result;
}
void pxl8_cart_unload(pxl8_cart* cart) {
if (!cart) return;
pxl8_cart_unmount(cart);
if (cart->title) {
pxl8_info("Unloaded cart: %s", cart->title);
pxl8_cart_unmount(cart);
free(cart->title);
cart->title = NULL;
} else if (cart->base_path || cart->data) {
pxl8_info("Unloaded cart");
pxl8_cart_unmount(cart);
}
if (cart->files) {
for (u32 i = 0; i < cart->file_count; i++) {
@ -281,12 +285,6 @@ void pxl8_cart_unload(pxl8_cart* cart) {
cart->data = NULL;
cart->data_size = 0;
if (cart->name) {
pxl8_info("Unloaded cart: %s", cart->name);
free(cart->name);
cart->name = NULL;
}
free(cart->base_path);
cart->base_path = NULL;
cart->is_folder = false;
@ -312,7 +310,11 @@ pxl8_result pxl8_cart_mount(pxl8_cart* cart) {
cart->is_mounted = true;
pxl8_current_cart = cart;
pxl8_info("Mounted cart: %s", cart->name);
if (cart->title) {
pxl8_info("Mounted cart: %s", cart->title);
} else {
pxl8_info("Mounted cart");
}
return PXL8_OK;
}
@ -335,8 +337,38 @@ const char* pxl8_cart_get_base_path(const pxl8_cart* cart) {
return cart ? cart->base_path : NULL;
}
const char* pxl8_cart_get_name(const pxl8_cart* cart) {
return cart ? cart->name : NULL;
const char* pxl8_cart_get_title(const pxl8_cart* cart) {
return cart ? cart->title : NULL;
}
void pxl8_cart_set_title(pxl8_cart* cart, const char* title) {
if (!cart || !title) return;
free(cart->title);
cart->title = strdup(title);
}
pxl8_resolution pxl8_cart_get_resolution(const pxl8_cart* cart) {
return cart ? cart->resolution : PXL8_RESOLUTION_640x360;
}
void pxl8_cart_set_resolution(pxl8_cart* cart, pxl8_resolution resolution) {
if (cart) cart->resolution = resolution;
}
pxl8_size pxl8_cart_get_window_size(const pxl8_cart* cart) {
return cart ? cart->window_size : (pxl8_size){1280, 720};
}
void pxl8_cart_set_window_size(pxl8_cart* cart, pxl8_size size) {
if (cart) cart->window_size = size;
}
pxl8_pixel_mode pxl8_cart_get_pixel_mode(const pxl8_cart* cart) {
return cart ? cart->pixel_mode : PXL8_PIXEL_INDEXED;
}
void pxl8_cart_set_pixel_mode(pxl8_cart* cart, pxl8_pixel_mode mode) {
if (cart) cart->pixel_mode = mode;
}
bool pxl8_cart_is_packed(const pxl8_cart* cart) {
@ -429,14 +461,9 @@ pxl8_result pxl8_cart_pack(const char* folder_path, const char* output_path) {
return PXL8_ERROR_FILE_NOT_FOUND;
}
char main_path[512];
snprintf(main_path, sizeof(main_path), "%s/main.fnl", folder_path);
if (access(main_path, F_OK) != 0) {
snprintf(main_path, sizeof(main_path), "%s/main.lua", folder_path);
if (access(main_path, F_OK) != 0) {
pxl8_error("No main.fnl or main.lua found in cart: %s", folder_path);
return PXL8_ERROR_FILE_NOT_FOUND;
}
if (!has_main_script(folder_path)) {
pxl8_error("No main.fnl or main.lua found in cart: %s", folder_path);
return PXL8_ERROR_FILE_NOT_FOUND;
}
char** paths = NULL;