add save and bundle pxl8 with game for standalone game distribution
This commit is contained in:
parent
b1e8525c3e
commit
04d3af11a9
25 changed files with 1173 additions and 346 deletions
109
src/pxl8.c
109
src/pxl8.c
|
|
@ -73,10 +73,11 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
|
|||
|
||||
pxl8_game* game = sys->game;
|
||||
|
||||
game->color_mode = PXL8_COLOR_MODE_MEGA;
|
||||
game->resolution = PXL8_RESOLUTION_640x360;
|
||||
pxl8_pixel_mode pixel_mode = PXL8_PIXEL_INDEXED;
|
||||
pxl8_resolution resolution = PXL8_RESOLUTION_640x360;
|
||||
|
||||
const char* script_arg = NULL;
|
||||
bool bundle_mode = false;
|
||||
bool pack_mode = false;
|
||||
const char* pack_input = NULL;
|
||||
const char* pack_output = NULL;
|
||||
|
|
@ -84,6 +85,15 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
|
|||
for (i32 i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--repl") == 0) {
|
||||
game->repl_mode = true;
|
||||
} else if (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 <folder|.pxc> <output>");
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
} else if (strcmp(argv[i], "--pack") == 0) {
|
||||
pack_mode = true;
|
||||
if (i + 2 < argc) {
|
||||
|
|
@ -98,6 +108,18 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (bundle_mode) {
|
||||
char exe_path[1024];
|
||||
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
|
||||
if (len == -1) {
|
||||
pxl8_error("Failed to resolve executable path");
|
||||
return PXL8_ERROR_SYSTEM_FAILURE;
|
||||
}
|
||||
exe_path[len] = '\0';
|
||||
pxl8_result result = pxl8_cart_bundle(pack_input, pack_output, exe_path);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (pack_mode) {
|
||||
pxl8_result result = pxl8_cart_pack(pack_input, pack_output);
|
||||
return result;
|
||||
|
|
@ -109,13 +131,13 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
|
|||
|
||||
pxl8_info("Starting up");
|
||||
|
||||
sys->platform_data = sys->hal->create(game->color_mode, game->resolution, "pxl8", 1280, 720);
|
||||
sys->platform_data = sys->hal->create(pixel_mode, resolution, "pxl8", 1280, 720);
|
||||
if (!sys->platform_data) {
|
||||
pxl8_error("Failed to create platform context");
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
game->gfx = pxl8_gfx_create(sys->hal, sys->platform_data, game->color_mode, game->resolution);
|
||||
game->gfx = pxl8_gfx_create(sys->hal, sys->platform_data, pixel_mode, resolution);
|
||||
if (!game->gfx) {
|
||||
pxl8_error("Failed to create graphics context");
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
|
|
@ -126,39 +148,58 @@ pxl8_result pxl8_init(pxl8* sys, i32 argc, char* argv[]) {
|
|||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
game->script = pxl8_script_create();
|
||||
game->script = pxl8_script_create(game->repl_mode);
|
||||
if (!game->script) {
|
||||
pxl8_error("Failed to initialize scripting: %s", pxl8_script_get_last_error(game->script));
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
const char* cart_path = script_arg ? script_arg : "demo";
|
||||
bool has_embedded = pxl8_cart_has_embedded(argv[0]);
|
||||
const char* cart_path = script_arg;
|
||||
|
||||
struct stat st;
|
||||
bool is_cart = (stat(cart_path, &st) == 0 && S_ISDIR(st.st_mode)) ||
|
||||
(cart_path && strstr(cart_path, ".pxc"));
|
||||
|
||||
if (is_cart) {
|
||||
char* original_cwd = getcwd(NULL, 0);
|
||||
if (has_embedded && !script_arg) {
|
||||
sys->cart = pxl8_cart_create();
|
||||
if (!sys->cart) {
|
||||
pxl8_error("Failed to create cart");
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
if (pxl8_cart_load(sys->cart, cart_path) == PXL8_OK) {
|
||||
pxl8_script_set_cart_path(game->script, pxl8_cart_get_base_path(sys->cart), original_cwd);
|
||||
if (pxl8_cart_load_embedded(sys->cart, argv[0]) == PXL8_OK) {
|
||||
pxl8_cart_mount(sys->cart);
|
||||
strncpy(game->script_path, "main.fnl", sizeof(game->script_path) - 1);
|
||||
game->script_path[sizeof(game->script_path) - 1] = '\0';
|
||||
pxl8_info("Loaded cart: %s", pxl8_cart_get_name(sys->cart));
|
||||
pxl8_info("Running embedded cart");
|
||||
} else {
|
||||
pxl8_error("Failed to load cart: %s", cart_path);
|
||||
pxl8_error("Failed to load embedded cart");
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
free(original_cwd);
|
||||
} else if (script_arg) {
|
||||
strncpy(game->script_path, script_arg, sizeof(game->script_path) - 1);
|
||||
game->script_path[sizeof(game->script_path) - 1] = '\0';
|
||||
} else if (cart_path || !has_embedded) {
|
||||
if (!cart_path) cart_path = "demo";
|
||||
|
||||
struct stat st;
|
||||
bool is_cart = (stat(cart_path, &st) == 0 && S_ISDIR(st.st_mode)) ||
|
||||
(cart_path && strstr(cart_path, ".pxc"));
|
||||
|
||||
if (is_cart) {
|
||||
char* original_cwd = getcwd(NULL, 0);
|
||||
sys->cart = pxl8_cart_create();
|
||||
if (!sys->cart) {
|
||||
pxl8_error("Failed to create cart");
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
if (pxl8_cart_load(sys->cart, cart_path) == PXL8_OK) {
|
||||
pxl8_script_set_cart_path(game->script, pxl8_cart_get_base_path(sys->cart), original_cwd);
|
||||
pxl8_cart_mount(sys->cart);
|
||||
strncpy(game->script_path, "main.fnl", sizeof(game->script_path) - 1);
|
||||
game->script_path[sizeof(game->script_path) - 1] = '\0';
|
||||
} else {
|
||||
pxl8_error("Failed to load cart: %s", cart_path);
|
||||
return PXL8_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
free(original_cwd);
|
||||
} else if (script_arg) {
|
||||
strncpy(game->script_path, script_arg, sizeof(game->script_path) - 1);
|
||||
game->script_path[sizeof(game->script_path) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_script_set_gfx(game->script, game->gfx);
|
||||
|
|
@ -245,6 +286,8 @@ pxl8_result pxl8_update(pxl8* sys) {
|
|||
}
|
||||
}
|
||||
|
||||
pxl8_gfx_update(game->gfx, dt);
|
||||
|
||||
if (game->script_loaded) {
|
||||
pxl8_script_call_function_f32(game->script, "update", dt);
|
||||
}
|
||||
|
|
@ -268,19 +311,18 @@ pxl8_result pxl8_frame(pxl8* sys) {
|
|||
} else {
|
||||
pxl8_clear(game->gfx, 32);
|
||||
|
||||
pxl8_size render_size = pxl8_get_resolution_dimensions(game->resolution);
|
||||
i32 render_w = pxl8_gfx_get_width(game->gfx);
|
||||
i32 render_h = pxl8_gfx_get_height(game->gfx);
|
||||
|
||||
for (i32 y = 0; y < render_size.h; y += 24) {
|
||||
for (i32 x = 0; x < render_size.w; x += 32) {
|
||||
for (i32 y = 0; y < render_h; y += 24) {
|
||||
for (i32 x = 0; x < render_w; x += 32) {
|
||||
u32 color = ((x / 32) + (y / 24) + (i32)(game->time * 2)) % 8;
|
||||
pxl8_rect_fill(game->gfx, x, y, 31, 23, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_size render_size = pxl8_get_resolution_dimensions(game->resolution);
|
||||
|
||||
pxl8_gfx_set_viewport(game->gfx, pxl8_gfx_viewport(bounds, render_size.w, render_size.h));
|
||||
pxl8_gfx_set_viewport(game->gfx, pxl8_gfx_viewport(bounds, pxl8_gfx_get_width(game->gfx), pxl8_gfx_get_height(game->gfx)));
|
||||
pxl8_gfx_upload_framebuffer(game->gfx);
|
||||
pxl8_gfx_upload_atlas(game->gfx);
|
||||
pxl8_gfx_present(game->gfx);
|
||||
|
|
@ -343,10 +385,6 @@ pxl8_input_state* pxl8_get_input(const pxl8* sys) {
|
|||
return (sys && sys->game) ? &sys->game->input : NULL;
|
||||
}
|
||||
|
||||
pxl8_resolution pxl8_get_resolution(const pxl8* sys) {
|
||||
return (sys && sys->game) ? sys->game->resolution : PXL8_RESOLUTION_640x360;
|
||||
}
|
||||
|
||||
void pxl8_center_cursor(pxl8* sys) {
|
||||
if (!sys || !sys->hal || !sys->hal->center_cursor) return;
|
||||
sys->hal->center_cursor(sys->platform_data);
|
||||
|
|
@ -365,17 +403,6 @@ void pxl8_set_relative_mouse_mode(pxl8* sys, bool enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
u32 pxl8_get_palette_size(pxl8_color_mode mode) {
|
||||
switch (mode) {
|
||||
case PXL8_COLOR_MODE_HICOLOR: return 0;
|
||||
case PXL8_COLOR_MODE_FAMI: return 64;
|
||||
case PXL8_COLOR_MODE_MEGA: return 512;
|
||||
case PXL8_COLOR_MODE_GBA:
|
||||
case PXL8_COLOR_MODE_SNES: return 32768;
|
||||
default: return 256;
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_size pxl8_get_resolution_dimensions(pxl8_resolution resolution) {
|
||||
switch (resolution) {
|
||||
case PXL8_RESOLUTION_240x160: return (pxl8_size){240, 160};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue