refactor: add helpers for file I/O, main script detection, safe strncpy, & make hal generic
This commit is contained in:
parent
a33d4c0068
commit
097e3a604d
19 changed files with 323 additions and 454 deletions
|
|
@ -14,8 +14,9 @@
|
|||
|
||||
#include "pxl8_cart.h"
|
||||
#include "pxl8_embed.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_gui.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_macros.h"
|
||||
|
||||
struct pxl8_script {
|
||||
lua_State* L;
|
||||
|
|
@ -193,7 +194,6 @@ static const char* pxl8_ffi_cdefs =
|
|||
"i32 pxl8_gfx_load_palette(pxl8_gfx* ctx, const char* filepath);\n"
|
||||
"i32 pxl8_gfx_load_sprite(pxl8_gfx* ctx, const char* filepath, u32* sprite_id);\n"
|
||||
"i32 pxl8_gfx_create_texture(pxl8_gfx* ctx, const u8* pixels, u32 width, u32 height);\n"
|
||||
"void pxl8_gfx_upload_atlas(pxl8_gfx* ctx);\n"
|
||||
"typedef struct pxl8_input_state pxl8_input_state;\n"
|
||||
"bool pxl8_key_down(const pxl8_input_state* input, const char* key_name);\n"
|
||||
"bool pxl8_key_pressed(const pxl8_input_state* input, const char* key_name);\n"
|
||||
|
|
@ -422,17 +422,52 @@ static const char* pxl8_ffi_cdefs =
|
|||
void pxl8_lua_log(int level, const char* file, int line, const char* msg) {
|
||||
if (file && (file[0] == '?' || file[0] == '\0')) file = NULL;
|
||||
switch (level) {
|
||||
case 0: pxl8_log_write_info("%s", msg); break;
|
||||
case 1: pxl8_log_write_warn(file, line, "%s", msg); break;
|
||||
case 2: pxl8_log_write_error(file, line, "%s", msg); break;
|
||||
case 3: pxl8_log_write_debug(file, line, "%s", msg); break;
|
||||
case 4: pxl8_log_write_trace(file, line, "%s", msg); break;
|
||||
case PXL8_LOG_LEVEL_TRACE: pxl8_log_write_trace(file, line, "%s", msg); break;
|
||||
case PXL8_LOG_LEVEL_DEBUG: pxl8_log_write_debug(file, line, "%s", msg); break;
|
||||
case PXL8_LOG_LEVEL_INFO: pxl8_log_write_info("%s", msg); break;
|
||||
case PXL8_LOG_LEVEL_WARN: pxl8_log_write_warn(file, line, "%s", msg); break;
|
||||
case PXL8_LOG_LEVEL_ERROR: pxl8_log_write_error(file, line, "%s", msg); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pxl8_script_set_error(pxl8_script* script, const char* error) {
|
||||
if (!script) return;
|
||||
snprintf(script->last_error, sizeof(script->last_error), "%s", error ? error : "Unknown error");
|
||||
if (!error) {
|
||||
snprintf(script->last_error, sizeof(script->last_error), "Unknown error");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* src = error;
|
||||
char* dst = script->last_error;
|
||||
char* end = dst + sizeof(script->last_error) - 1;
|
||||
|
||||
while (*src && dst < end) {
|
||||
if (strncmp(src, "[string \"", 9) == 0) {
|
||||
src += 9;
|
||||
const char* mod_start = src;
|
||||
while (*src && !(*src == '"' && *(src+1) == ']')) src++;
|
||||
size_t mod_len = src - mod_start;
|
||||
|
||||
if (mod_len > 4 && strncmp(mod_start, "pxl8", 4) == 0) {
|
||||
const char* prefix = "src/lua/";
|
||||
while (*prefix && dst < end) *dst++ = *prefix++;
|
||||
for (size_t i = 0; i < mod_len && dst < end; i++) {
|
||||
*dst++ = (mod_start[i] == '.') ? '/' : mod_start[i];
|
||||
}
|
||||
const char* suffix = ".lua";
|
||||
while (*suffix && dst < end) *dst++ = *suffix++;
|
||||
} else {
|
||||
for (size_t i = 0; i < mod_len && dst < end; i++) {
|
||||
*dst++ = mod_start[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (*src == '"' && *(src+1) == ']') src += 2;
|
||||
} else {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
const char* pxl8_script_get_last_error(pxl8_script* script) {
|
||||
|
|
@ -610,8 +645,7 @@ void pxl8_script_set_sys(pxl8_script* script, void* sys) {
|
|||
|
||||
static pxl8_result pxl8_script_prepare_path(pxl8_script* script, const char* filename, char* out_basename, size_t basename_size) {
|
||||
char filename_copy[PATH_MAX];
|
||||
strncpy(filename_copy, filename, sizeof(filename_copy) - 1);
|
||||
filename_copy[sizeof(filename_copy) - 1] = '\0';
|
||||
pxl8_strncpy(filename_copy, filename, sizeof(filename_copy));
|
||||
|
||||
char* last_slash = strrchr(filename_copy, '/');
|
||||
|
||||
|
|
@ -933,8 +967,7 @@ static time_t get_latest_script_mod_time(const char* dir_path) {
|
|||
pxl8_result pxl8_script_load_main(pxl8_script* script, const char* path) {
|
||||
if (!script || !path) return PXL8_ERROR_NULL_POINTER;
|
||||
|
||||
strncpy(script->main_path, path, sizeof(script->main_path) - 1);
|
||||
script->main_path[sizeof(script->main_path) - 1] = '\0';
|
||||
pxl8_strncpy(script->main_path, path, sizeof(script->main_path));
|
||||
|
||||
char* last_slash = strrchr(script->main_path, '/');
|
||||
if (last_slash) {
|
||||
|
|
@ -1006,3 +1039,90 @@ bool pxl8_script_is_incomplete_input(pxl8_script* script) {
|
|||
if (!script) return false;
|
||||
return pxl8_script_is_incomplete_error(script->last_error);
|
||||
}
|
||||
|
||||
static pxl8_resolution parse_resolution(const char* str) {
|
||||
if (strcmp(str, "240x160") == 0) return PXL8_RESOLUTION_240x160;
|
||||
if (strcmp(str, "320x180") == 0) return PXL8_RESOLUTION_320x180;
|
||||
if (strcmp(str, "320x240") == 0) return PXL8_RESOLUTION_320x240;
|
||||
if (strcmp(str, "640x360") == 0) return PXL8_RESOLUTION_640x360;
|
||||
if (strcmp(str, "640x480") == 0) return PXL8_RESOLUTION_640x480;
|
||||
if (strcmp(str, "800x600") == 0) return PXL8_RESOLUTION_800x600;
|
||||
if (strcmp(str, "960x540") == 0) return PXL8_RESOLUTION_960x540;
|
||||
return PXL8_RESOLUTION_640x360;
|
||||
}
|
||||
|
||||
static pxl8_pixel_mode parse_pixel_mode(const char* str) {
|
||||
if (strcmp(str, "indexed") == 0) return PXL8_PIXEL_INDEXED;
|
||||
if (strcmp(str, "hicolor") == 0) return PXL8_PIXEL_HICOLOR;
|
||||
return PXL8_PIXEL_INDEXED;
|
||||
}
|
||||
|
||||
pxl8_result pxl8_script_load_cart_manifest(pxl8_script* script, pxl8_cart* cart) {
|
||||
if (!script || !script->L || !cart) return PXL8_ERROR_NULL_POINTER;
|
||||
|
||||
if (!pxl8_cart_file_exists(cart, "cart.fnl")) {
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
||||
u8* data = NULL;
|
||||
u32 size = 0;
|
||||
if (pxl8_cart_read_file(cart, "cart.fnl", &data, &size) != PXL8_OK) {
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
||||
lua_getglobal(script->L, "fennel");
|
||||
if (lua_isnil(script->L, -1)) {
|
||||
lua_pop(script->L, 1);
|
||||
pxl8_cart_free_file(data);
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
||||
lua_getfield(script->L, -1, "eval");
|
||||
lua_pushlstring(script->L, (const char*)data, size);
|
||||
lua_createtable(script->L, 0, 1);
|
||||
lua_pushstring(script->L, "cart.fnl");
|
||||
lua_setfield(script->L, -2, "filename");
|
||||
|
||||
pxl8_cart_free_file(data);
|
||||
|
||||
if (lua_pcall(script->L, 2, 1, 0) != 0) {
|
||||
pxl8_warn("Failed to load cart.fnl: %s", lua_tostring(script->L, -1));
|
||||
lua_pop(script->L, 2);
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
||||
if (lua_istable(script->L, -1)) {
|
||||
lua_getfield(script->L, -1, "title");
|
||||
if (lua_isstring(script->L, -1)) {
|
||||
pxl8_cart_set_title(cart, lua_tostring(script->L, -1));
|
||||
}
|
||||
lua_pop(script->L, 1);
|
||||
|
||||
lua_getfield(script->L, -1, "resolution");
|
||||
if (lua_isstring(script->L, -1)) {
|
||||
pxl8_cart_set_resolution(cart, parse_resolution(lua_tostring(script->L, -1)));
|
||||
}
|
||||
lua_pop(script->L, 1);
|
||||
|
||||
lua_getfield(script->L, -1, "pixel-mode");
|
||||
if (lua_isstring(script->L, -1)) {
|
||||
pxl8_cart_set_pixel_mode(cart, parse_pixel_mode(lua_tostring(script->L, -1)));
|
||||
}
|
||||
lua_pop(script->L, 1);
|
||||
|
||||
lua_getfield(script->L, -1, "window-size");
|
||||
if (lua_istable(script->L, -1)) {
|
||||
lua_rawgeti(script->L, -1, 1);
|
||||
lua_rawgeti(script->L, -2, 2);
|
||||
if (lua_isnumber(script->L, -2) && lua_isnumber(script->L, -1)) {
|
||||
pxl8_size size = {(i32)lua_tonumber(script->L, -2), (i32)lua_tonumber(script->L, -1)};
|
||||
pxl8_cart_set_window_size(cart, size);
|
||||
}
|
||||
lua_pop(script->L, 2);
|
||||
}
|
||||
lua_pop(script->L, 1);
|
||||
}
|
||||
|
||||
lua_pop(script->L, 2);
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue