refactor some things...
This commit is contained in:
parent
3550fad638
commit
1744e689b5
25 changed files with 2396 additions and 1307 deletions
214
src/pxl8.c
214
src/pxl8.c
|
|
@ -9,13 +9,14 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <linenoise.h>
|
||||
|
||||
#define SDL_MAIN_USE_CALLBACKS
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
#include "pxl8_cart.h"
|
||||
#include "pxl8_lua.h"
|
||||
#include "pxl8_macros.h"
|
||||
#include "pxl8_script.h"
|
||||
#include "pxl8_types.h"
|
||||
|
||||
#define PXL8_MAX_REPL_COMMANDS 4096
|
||||
|
|
@ -36,10 +37,10 @@ typedef struct pxl8_repl_state {
|
|||
typedef struct pxl8_state {
|
||||
pxl8_cart* cart;
|
||||
pxl8_color_mode color_mode;
|
||||
pxl8_gfx_ctx gfx;
|
||||
lua_State* lua;
|
||||
pxl8_gfx* gfx;
|
||||
pxl8_repl_state repl;
|
||||
pxl8_resolution resolution;
|
||||
pxl8_script* script;
|
||||
|
||||
f32 fps_timer;
|
||||
i32 frame_count;
|
||||
|
|
@ -50,8 +51,7 @@ typedef struct pxl8_state {
|
|||
bool running;
|
||||
bool script_loaded;
|
||||
char script_path[256];
|
||||
time_t script_mod_time;
|
||||
|
||||
|
||||
pxl8_input_state input;
|
||||
} pxl8_state;
|
||||
|
||||
|
|
@ -184,54 +184,6 @@ static pxl8_repl_command* pxl8_repl_pop_command(pxl8_repl_state* repl) {
|
|||
return cmd;
|
||||
}
|
||||
|
||||
static void load_script(pxl8_state* app) {
|
||||
const char* ext = strrchr(app->script_path, '.');
|
||||
|
||||
if (ext && strcmp(ext, ".fnl") == 0) {
|
||||
pxl8_result result = pxl8_lua_run_fennel_file(app->lua, app->script_path);
|
||||
if (result == PXL8_OK) {
|
||||
pxl8_info("Loaded script: %s", app->script_path);
|
||||
app->script_loaded = true;
|
||||
lua_getglobal(app->lua, "init");
|
||||
if (lua_isfunction(app->lua, -1)) {
|
||||
lua_pcall(app->lua, 0, 0, 0);
|
||||
} else {
|
||||
pxl8_warn("No init function found (type: %s)", lua_typename(app->lua, lua_type(app->lua, -1)));
|
||||
lua_pop(app->lua, 1);
|
||||
}
|
||||
} else {
|
||||
pxl8_warn("Failed to load script: %s", app->script_path);
|
||||
app->script_loaded = false;
|
||||
}
|
||||
} else if (ext && strcmp(ext, ".lua") == 0) {
|
||||
pxl8_result result = pxl8_lua_run_file(app->lua, app->script_path);
|
||||
if (result == PXL8_OK) {
|
||||
pxl8_info("Loaded script: %s", app->script_path);
|
||||
app->script_loaded = true;
|
||||
lua_getglobal(app->lua, "init");
|
||||
if (lua_isfunction(app->lua, -1)) {
|
||||
lua_pcall(app->lua, 0, 0, 0);
|
||||
} else {
|
||||
pxl8_warn("No init function found (type: %s)", lua_typename(app->lua, lua_type(app->lua, -1)));
|
||||
lua_pop(app->lua, 1);
|
||||
}
|
||||
} else {
|
||||
pxl8_warn("Failed to load script: %s", app->script_path);
|
||||
app->script_loaded = false;
|
||||
}
|
||||
} else {
|
||||
pxl8_warn("Unknown script type for: %s (expected .fnl or .lua)", app->script_path);
|
||||
app->script_loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
static time_t get_file_mod_time(const char* path) {
|
||||
struct stat file_stat;
|
||||
if (stat(path, &file_stat) == 0) {
|
||||
return file_stat.st_mtime;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
||||
static pxl8_state app = {0};
|
||||
|
|
@ -249,7 +201,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
const char* pack_input = NULL;
|
||||
const char* pack_output = NULL;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
for (i32 i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--repl") == 0) {
|
||||
app.repl_mode = true;
|
||||
} else if (strcmp(argv[i], "--pack") == 0) {
|
||||
|
|
@ -277,26 +229,27 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
pxl8_info("Starting up");
|
||||
|
||||
if (pxl8_gfx_init(&app.gfx, app.color_mode, app.resolution, "pxl8", 1280, 720) != PXL8_OK) {
|
||||
pxl8_error("Failed to initialize graphics context");
|
||||
|
||||
app.gfx = pxl8_gfx_create(app.color_mode, app.resolution, "pxl8", 1280, 720);
|
||||
if (!app.gfx) {
|
||||
pxl8_error("Failed to create graphics context");
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (pxl8_gfx_load_font_atlas(&app.gfx) != PXL8_OK) {
|
||||
|
||||
if (pxl8_gfx_load_font_atlas(app.gfx) != PXL8_OK) {
|
||||
pxl8_error("Failed to load font atlas");
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (pxl8_gfx_init_atlas(&app.gfx, 1024, 1024) != PXL8_OK) {
|
||||
|
||||
if (pxl8_gfx_init_atlas(app.gfx, 1024, 1024) != PXL8_OK) {
|
||||
pxl8_error("Failed to initialize sprite atlas");
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
pxl8_result lua_result = pxl8_lua_init(&app.lua);
|
||||
if (lua_result != PXL8_OK) {
|
||||
pxl8_error("Failed to initialize Lua scripting!");
|
||||
pxl8_gfx_shutdown(&app.gfx);
|
||||
|
||||
app.script = pxl8_script_create();
|
||||
if (!app.script) {
|
||||
pxl8_error("Failed to initialize scripting: %s", pxl8_script_get_last_error(app.script));
|
||||
pxl8_gfx_destroy(app.gfx);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -308,16 +261,16 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
|
||||
if (is_cart) {
|
||||
char* original_cwd = getcwd(NULL, 0);
|
||||
app.cart = calloc(1, sizeof(pxl8_cart));
|
||||
app.cart = pxl8_cart_create();
|
||||
if (!app.cart) {
|
||||
pxl8_error("Failed to allocate memory for cart");
|
||||
pxl8_error("Failed to create cart");
|
||||
return false;
|
||||
}
|
||||
if (pxl8_cart_load(app.cart, cart_path) == PXL8_OK) {
|
||||
pxl8_lua_setup_cart_path(app.lua, app.cart->base_path, original_cwd);
|
||||
pxl8_script_set_cart_path(app.script, pxl8_cart_get_base_path(app.cart), original_cwd);
|
||||
pxl8_cart_mount(app.cart);
|
||||
strcpy(app.script_path, "main.fnl");
|
||||
pxl8_info("Loaded cart: %s", app.cart->name);
|
||||
pxl8_info("Loaded cart: %s", pxl8_cart_get_name(app.cart));
|
||||
} else {
|
||||
pxl8_error("Failed to load cart: %s", cart_path);
|
||||
return SDL_APP_FAILURE;
|
||||
|
|
@ -328,25 +281,20 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
app.script_path[sizeof(app.script_path) - 1] = '\0';
|
||||
}
|
||||
|
||||
pxl8_lua_setup_contexts(app.lua, &app.gfx, &app.input);
|
||||
pxl8_script_set_gfx(app.script, app.gfx);
|
||||
pxl8_script_set_input(app.script, &app.input);
|
||||
|
||||
if (app.script_path[0] != '\0') {
|
||||
app.script_mod_time = get_file_mod_time(app.script_path);
|
||||
load_script(&app);
|
||||
pxl8_result result = pxl8_script_load_main(app.script, app.script_path);
|
||||
app.script_loaded = (result == PXL8_OK);
|
||||
}
|
||||
|
||||
if (app.repl_mode) {
|
||||
pxl8_repl_init(&app.repl);
|
||||
fprintf(stderr, "\033[38;2;184;187;38m[pxl8 REPL]\033[0m Fennel %s - Tab for completions, Ctrl-C to exit\n", "1.5.1");
|
||||
|
||||
lua_getglobal(app.lua, "require");
|
||||
lua_pushstring(app.lua, "pxl8");
|
||||
if (lua_pcall(app.lua, 1, 1, 0) == 0) {
|
||||
lua_setglobal(app.lua, "pxl8");
|
||||
} else {
|
||||
const char* error_msg = lua_tostring(app.lua, -1);
|
||||
fprintf(stderr, "Warning: Failed to setup pxl8 global: %s\n", error_msg);
|
||||
lua_pop(app.lua, 1);
|
||||
|
||||
if (pxl8_script_load_module(app.script, "pxl8") != PXL8_OK) {
|
||||
fprintf(stderr, "Warning: Failed to setup pxl8 global: %s\n", pxl8_script_get_last_error(app.script));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -359,110 +307,72 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
|
||||
SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||
pxl8_state* app = (pxl8_state*)appstate;
|
||||
int width, height;
|
||||
pxl8_bounds bounds = pxl8_gfx_get_bounds(app->gfx);
|
||||
|
||||
SDL_GetWindowSize(app->gfx.window, &width, &height);
|
||||
|
||||
u64 current_time = SDL_GetTicksNS();
|
||||
float dt = (float)(current_time - app->last_time) / 1000000000.0f;
|
||||
f32 dt = (f32)(current_time - app->last_time) / 1000000000.0f;
|
||||
|
||||
app->frame_count++;
|
||||
app->fps_timer += dt;
|
||||
app->last_time = current_time;
|
||||
app->time += dt;
|
||||
|
||||
|
||||
if (app->fps_timer >= 3.0f) {
|
||||
if (!app->repl_mode) {
|
||||
float avg_fps = app->frame_count / app->fps_timer;
|
||||
f32 avg_fps = app->frame_count / app->fps_timer;
|
||||
pxl8_info("FPS: %.1f", avg_fps);
|
||||
}
|
||||
app->frame_count = 0;
|
||||
app->fps_timer = 0.0f;
|
||||
}
|
||||
|
||||
time_t current_mod_time = get_file_mod_time(app->script_path);
|
||||
if (current_mod_time != app->script_mod_time && current_mod_time != 0) {
|
||||
pxl8_info("Script modified, reloading: %s", app->script_path);
|
||||
app->script_mod_time = current_mod_time;
|
||||
load_script(app);
|
||||
}
|
||||
pxl8_script_check_reload(app->script);
|
||||
|
||||
if (app->repl_mode) {
|
||||
pxl8_repl_command* cmd = pxl8_repl_pop_command(&app->repl);
|
||||
if (cmd) {
|
||||
pxl8_result result = pxl8_lua_eval_fennel(app->lua, cmd->buffer);
|
||||
if (result == PXL8_OK) {
|
||||
if (lua_gettop(app->lua) > 0 && !lua_isnil(app->lua, -1)) {
|
||||
const char* result_str = lua_tostring(app->lua, -1);
|
||||
if (result_str) {
|
||||
fprintf(stdout, "%s\n", result_str);
|
||||
} else if (lua_isuserdata(app->lua, -1)) {
|
||||
fprintf(stdout, "<userdata>\n");
|
||||
} else if (lua_iscfunction(app->lua, -1)) {
|
||||
fprintf(stdout, "<function>\n");
|
||||
} else if (lua_istable(app->lua, -1)) {
|
||||
fprintf(stdout, "<table>\n");
|
||||
} else {
|
||||
fprintf(stdout, "<%s>\n", lua_typename(app->lua, lua_type(app->lua, -1)));
|
||||
}
|
||||
lua_pop(app->lua, 1);
|
||||
}
|
||||
} else {
|
||||
const char* error_msg = lua_tostring(app->lua, -1);
|
||||
pxl8_error("%s", error_msg ? error_msg : "Unknown error");
|
||||
lua_pop(app->lua, 1);
|
||||
pxl8_result result = pxl8_script_eval(app->script, cmd->buffer);
|
||||
if (result != PXL8_OK) {
|
||||
pxl8_error("%s", pxl8_script_get_last_error(app->script));
|
||||
}
|
||||
SDL_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (app->script_loaded) {
|
||||
lua_getglobal(app->lua, "update");
|
||||
if (lua_isfunction(app->lua, -1)) {
|
||||
lua_pushnumber(app->lua, dt);
|
||||
lua_pcall(app->lua, 1, 0, 0);
|
||||
} else {
|
||||
lua_pop(app->lua, 1);
|
||||
}
|
||||
|
||||
lua_getglobal(app->lua, "draw");
|
||||
if (lua_isfunction(app->lua, -1)) {
|
||||
int result = lua_pcall(app->lua, 0, 0, 0);
|
||||
if (result != 0) {
|
||||
pxl8_error("Error calling draw: %s", lua_tostring(app->lua, -1));
|
||||
lua_pop(app->lua, 1);
|
||||
}
|
||||
} else {
|
||||
pxl8_warn("draw is not a function, type: %s", lua_typename(app->lua, lua_type(app->lua, -1)));
|
||||
lua_pop(app->lua, 1);
|
||||
pxl8_script_call_function_f32(app->script, "update", dt);
|
||||
|
||||
pxl8_result frame_result = pxl8_script_call_function(app->script, "frame");
|
||||
if (frame_result == PXL8_ERROR_SCRIPT_ERROR) {
|
||||
pxl8_error("Error calling frame: %s", pxl8_script_get_last_error(app->script));
|
||||
}
|
||||
} else {
|
||||
pxl8_clr(&app->gfx, 32);
|
||||
pxl8_clr(app->gfx, 32);
|
||||
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
|
||||
for (int y = 0; y < render_height; y += 24) {
|
||||
for (int x = 0; x < render_width; x += 32) {
|
||||
u32 color = ((x / 32) + (y / 24) + (int)(app->time * 2)) % 8;
|
||||
pxl8_rect_fill(&app->gfx, x, y, 31, 23, color);
|
||||
for (i32 y = 0; y < render_height; y += 24) {
|
||||
for (i32 x = 0; x < render_width; x += 32) {
|
||||
u32 color = ((x / 32) + (y / 24) + (i32)(app->time * 2)) % 8;
|
||||
pxl8_rect_fill(app->gfx, x, y, 31, 23, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
|
||||
f32 scale = fminf(bounds.w / (f32)render_width, bounds.h / (f32)render_height);
|
||||
i32 scaled_width = (i32)(render_width * scale);
|
||||
i32 scaled_height = (i32)(render_height * scale);
|
||||
i32 offset_x = (bounds.w - scaled_width) / 2;
|
||||
i32 offset_y = (bounds.h - scaled_height) / 2;
|
||||
|
||||
float scale = fminf(width / (float)render_width, height / (float)render_height);
|
||||
int scaled_width = (int)(render_width * scale);
|
||||
int scaled_height = (int)(render_height * scale);
|
||||
int offset_x = (width - scaled_width) / 2;
|
||||
int offset_y = (height - scaled_height) / 2;
|
||||
|
||||
pxl8_gfx_viewport(&app->gfx, offset_x, offset_y, scaled_width, scaled_height);
|
||||
pxl8_gfx_upload_framebuffer(&app->gfx);
|
||||
pxl8_gfx_upload_atlas(&app->gfx);
|
||||
pxl8_gfx_present(&app->gfx);
|
||||
pxl8_gfx_viewport(app->gfx, offset_x, offset_y, scaled_width, scaled_height);
|
||||
pxl8_gfx_upload_framebuffer(app->gfx);
|
||||
pxl8_gfx_upload_atlas(app->gfx);
|
||||
pxl8_gfx_present(app->gfx);
|
||||
|
||||
SDL_memset(app->input.keys_pressed, 0, sizeof(app->input.keys_pressed));
|
||||
|
||||
|
|
@ -520,9 +430,9 @@ void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
|||
free(app->cart);
|
||||
app->cart = NULL;
|
||||
}
|
||||
pxl8_lua_shutdown(app->lua);
|
||||
pxl8_gfx_shutdown(&app->gfx);
|
||||
pxl8_script_destroy(app->script);
|
||||
pxl8_gfx_destroy(app->gfx);
|
||||
}
|
||||
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue