add networking, 3d improvements, reorganize src structure

This commit is contained in:
asrael 2026-01-17 22:52:36 -06:00
parent 39b604b333
commit 415d424057
122 changed files with 5358 additions and 721 deletions

316
src/script/pxl8_repl.c Normal file
View file

@ -0,0 +1,316 @@
#include "pxl8_repl.h"
#include <poll.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <linenoise.h>
#define PXL8_MAX_REPL_COMMAND_SIZE 4096
#define PXL8_REPL_QUEUE_SIZE 8
struct pxl8_repl_command {
char buffer[PXL8_MAX_REPL_COMMAND_SIZE];
};
struct pxl8_repl {
char commands[PXL8_REPL_QUEUE_SIZE][PXL8_MAX_REPL_COMMAND_SIZE];
atomic_uint cmd_write_idx;
atomic_uint cmd_read_idx;
atomic_bool cmd_complete;
char logs[PXL8_REPL_QUEUE_SIZE][PXL8_MAX_REPL_COMMAND_SIZE];
atomic_uint log_write_idx;
atomic_uint log_read_idx;
atomic_bool should_quit;
pthread_t thread;
char accumulator[PXL8_MAX_REPL_COMMAND_SIZE];
pxl8_repl_command command;
};
static pxl8_repl* g_repl = NULL;
static void pxl8_repl_completion(const char* buf, linenoiseCompletions* lc) {
const char* fennel_keywords[] = {
"fn", "let", "var", "set", "global", "local",
"if", "when", "do", "while", "for", "each",
"lambda", "λ", "partial", "macro", "macros",
"require", "include", "import-macros",
"values", "select", "table", "length",
".", "..", ":", "->", "->>", "-?>", "-?>>",
"doto", "match", "case", "pick-values",
"collect", "icollect", "accumulate"
};
const char* pxl8_functions[] = {
"pxl8.clr", "pxl8.pixel", "pxl8.get_pixel",
"pxl8.line", "pxl8.rect", "pxl8.rect_fill",
"pxl8.circle", "pxl8.circle_fill", "pxl8.text",
"pxl8.get_screen", "pxl8.info", "pxl8.warn",
"pxl8.error", "pxl8.debug", "pxl8.trace"
};
size_t buf_len = strlen(buf);
for (size_t i = 0; i < sizeof(fennel_keywords) / sizeof(fennel_keywords[0]); i++) {
if (strncmp(buf, fennel_keywords[i], buf_len) == 0) {
linenoiseAddCompletion(lc, fennel_keywords[i]);
}
}
for (size_t i = 0; i < sizeof(pxl8_functions) / sizeof(pxl8_functions[0]); i++) {
if (strncmp(buf, pxl8_functions[i], buf_len) == 0) {
linenoiseAddCompletion(lc, pxl8_functions[i]);
}
}
}
static char* pxl8_repl_hints(const char* buf, int* color, int* bold) {
if (strncmp(buf, "pxl8.", 5) == 0 && strlen(buf) == 5) {
*color = 35;
*bold = 0;
return "clr|pixel|line|rect|circle|text|get_screen";
}
if (strcmp(buf, "(fn") == 0) {
*color = 36;
*bold = 0;
return " [args] body)";
}
if (strcmp(buf, "(let") == 0) {
*color = 36;
*bold = 0;
return " [bindings] body)";
}
return NULL;
}
static void pxl8_repl_flush_logs(pxl8_repl* repl) {
u32 log_read_idx = atomic_load(&repl->log_read_idx);
u32 log_write_idx = atomic_load(&repl->log_write_idx);
while (log_read_idx != log_write_idx) {
printf("%s", repl->logs[log_read_idx]);
atomic_store(&repl->log_read_idx, (log_read_idx + 1) % PXL8_REPL_QUEUE_SIZE);
log_read_idx = atomic_load(&repl->log_read_idx);
log_write_idx = atomic_load(&repl->log_write_idx);
}
fflush(stdout);
}
static void* pxl8_repl_thread(void* arg) {
pxl8_repl* repl = (pxl8_repl*)arg;
printf("[pxl8 REPL] Fennel 1.6.0 - Tab for completion, Ctrl-D to exit\n");
fflush(stdout);
struct linenoiseState ls;
char input_buf[PXL8_MAX_REPL_COMMAND_SIZE];
bool editing = false;
struct pollfd pfd = {
.fd = STDIN_FILENO,
.events = POLLIN
};
while (!atomic_load(&repl->should_quit)) {
u32 log_read_idx = atomic_load(&repl->log_read_idx);
u32 log_write_idx = atomic_load(&repl->log_write_idx);
if (log_read_idx != log_write_idx) {
printf("\r\033[K");
if (editing) {
linenoiseEditStop(&ls);
editing = false;
printf("\033[A\r\033[K");
}
while (log_read_idx != log_write_idx) {
printf("%s", repl->logs[log_read_idx]);
atomic_store(&repl->log_read_idx, (log_read_idx + 1) % PXL8_REPL_QUEUE_SIZE);
log_read_idx = atomic_load(&repl->log_read_idx);
log_write_idx = atomic_load(&repl->log_write_idx);
}
fflush(stdout);
continue;
}
if (!editing && !atomic_load(&repl->should_quit)) {
const char* prompt = (repl->accumulator[0] != '\0') ? ".. " : ">> ";
if (linenoiseEditStart(&ls, STDIN_FILENO, STDOUT_FILENO, input_buf, sizeof(input_buf), prompt) == -1) {
atomic_store(&repl->should_quit, true);
break;
}
editing = true;
}
if (poll(&pfd, 1, 1) <= 0) continue;
char* line = linenoiseEditFeed(&ls);
if (line == NULL) {
atomic_store(&repl->should_quit, true);
break;
}
if (line == linenoiseEditMore) continue;
linenoiseEditStop(&ls);
editing = false;
bool in_multiline = (repl->accumulator[0] != '\0');
if (strlen(line) > 0 || in_multiline) {
if (!in_multiline) {
linenoiseHistoryAdd(line);
linenoiseHistorySave(".pxl8_history");
}
if (repl->accumulator[0] != '\0') {
strncat(repl->accumulator, "\n",
PXL8_MAX_REPL_COMMAND_SIZE - strlen(repl->accumulator) - 1);
}
strncat(repl->accumulator, line,
PXL8_MAX_REPL_COMMAND_SIZE - strlen(repl->accumulator) - 1);
u32 write_idx = atomic_load(&repl->cmd_write_idx);
u32 read_idx = atomic_load(&repl->cmd_read_idx);
u32 next_write = (write_idx + 1) % PXL8_REPL_QUEUE_SIZE;
if (next_write != read_idx) {
strncpy(repl->commands[write_idx], repl->accumulator, PXL8_MAX_REPL_COMMAND_SIZE - 1);
repl->commands[write_idx][PXL8_MAX_REPL_COMMAND_SIZE - 1] = '\0';
atomic_store(&repl->cmd_write_idx, next_write);
}
}
linenoiseFree(line);
while (!atomic_load(&repl->should_quit) &&
(atomic_load(&repl->cmd_write_idx) != atomic_load(&repl->cmd_read_idx) ||
!atomic_load(&repl->cmd_complete))) {
u32 lr = atomic_load(&repl->log_read_idx);
u32 lw = atomic_load(&repl->log_write_idx);
while (lr != lw) {
printf("%s", repl->logs[lr]);
atomic_store(&repl->log_read_idx, (lr + 1) % PXL8_REPL_QUEUE_SIZE);
lr = atomic_load(&repl->log_read_idx);
lw = atomic_load(&repl->log_write_idx);
}
fflush(stdout);
struct timespec ts = {.tv_sec = 0, .tv_nsec = 1000000};
nanosleep(&ts, NULL);
}
atomic_store(&repl->cmd_complete, false);
}
if (editing) linenoiseEditStop(&ls);
pxl8_repl_flush_logs(repl);
return NULL;
}
pxl8_repl* pxl8_repl_create(void) {
pxl8_repl* repl = (pxl8_repl*)calloc(1, sizeof(pxl8_repl));
if (!repl) return NULL;
repl->accumulator[0] = '\0';
atomic_store(&repl->cmd_write_idx, 0);
atomic_store(&repl->cmd_read_idx, 0);
atomic_store(&repl->cmd_complete, true);
atomic_store(&repl->log_write_idx, 0);
atomic_store(&repl->log_read_idx, 0);
atomic_store(&repl->should_quit, false);
linenoiseHistorySetMaxLen(100);
linenoiseSetMultiLine(1);
linenoiseSetCompletionCallback(pxl8_repl_completion);
linenoiseSetHintsCallback(pxl8_repl_hints);
linenoiseHistoryLoad(".pxl8_history");
g_repl = repl;
if (pthread_create(&repl->thread, NULL, pxl8_repl_thread, repl) != 0) {
free(repl);
g_repl = NULL;
return NULL;
}
return repl;
}
void pxl8_repl_destroy(pxl8_repl* repl) {
if (!repl) return;
atomic_store(&repl->should_quit, true);
struct timespec ts = {.tv_sec = 0, .tv_nsec = 2000000};
nanosleep(&ts, NULL);
printf("\r\033[K");
fflush(stdout);
pthread_join(repl->thread, NULL);
pxl8_repl_flush_logs(repl);
g_repl = NULL;
system("stty sane 2>/dev/null");
free(repl);
}
pxl8_repl_command* pxl8_repl_pop_command(pxl8_repl* repl) {
if (!repl) return NULL;
u32 read_idx = atomic_load(&repl->cmd_read_idx);
u32 write_idx = atomic_load(&repl->cmd_write_idx);
if (read_idx == write_idx) return NULL;
strncpy(repl->command.buffer, repl->commands[read_idx], PXL8_MAX_REPL_COMMAND_SIZE - 1);
repl->command.buffer[PXL8_MAX_REPL_COMMAND_SIZE - 1] = '\0';
atomic_store(&repl->cmd_read_idx, (read_idx + 1) % PXL8_REPL_QUEUE_SIZE);
return &repl->command;
}
const char* pxl8_repl_command_buffer(pxl8_repl_command* cmd) {
return cmd ? cmd->buffer : NULL;
}
bool pxl8_repl_should_quit(pxl8_repl* repl) {
return repl ? atomic_load(&repl->should_quit) : false;
}
bool pxl8_repl_push_log(const char* message) {
if (!g_repl || !message) return false;
u32 write_idx = atomic_load(&g_repl->log_write_idx);
u32 read_idx = atomic_load(&g_repl->log_read_idx);
u32 next_write = (write_idx + 1) % PXL8_REPL_QUEUE_SIZE;
if (next_write != read_idx) {
strncpy(g_repl->logs[write_idx], message, PXL8_MAX_REPL_COMMAND_SIZE - 1);
g_repl->logs[write_idx][PXL8_MAX_REPL_COMMAND_SIZE - 1] = '\0';
atomic_store(&g_repl->log_write_idx, next_write);
}
return true;
}
void pxl8_repl_clear_accumulator(pxl8_repl* repl) {
if (!repl) return;
repl->accumulator[0] = '\0';
}
void pxl8_repl_signal_complete(pxl8_repl* repl) {
if (!repl) return;
atomic_store(&repl->cmd_complete, true);
}

24
src/script/pxl8_repl.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include "pxl8_types.h"
typedef struct pxl8_repl pxl8_repl;
typedef struct pxl8_repl_command pxl8_repl_command;
#ifdef __cplusplus
extern "C" {
#endif
pxl8_repl* pxl8_repl_create(void);
void pxl8_repl_destroy(pxl8_repl* repl);
pxl8_repl_command* pxl8_repl_pop_command(pxl8_repl* repl);
const char* pxl8_repl_command_buffer(pxl8_repl_command* cmd);
bool pxl8_repl_push_log(const char* message);
void pxl8_repl_clear_accumulator(pxl8_repl* repl);
bool pxl8_repl_should_quit(pxl8_repl* repl);
void pxl8_repl_signal_complete(pxl8_repl* repl);
#ifdef __cplusplus
}
#endif

1285
src/script/pxl8_script.c Normal file

File diff suppressed because it is too large Load diff

44
src/script/pxl8_script.h Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include "pxl8_cart.h"
#include "pxl8_gfx.h"
#include "pxl8_sfx.h"
#include "pxl8_types.h"
typedef struct pxl8_script pxl8_script;
#ifdef __cplusplus
extern "C" {
#endif
pxl8_script* pxl8_script_create(bool repl_mode);
void pxl8_script_destroy(pxl8_script* script);
const char* pxl8_script_get_last_error(pxl8_script* script);
bool pxl8_script_is_incomplete_input(pxl8_script* script);
void pxl8_script_set_cart_path(pxl8_script* script, const char* cart_path, const char* original_cwd);
void pxl8_script_set_gfx(pxl8_script* script, pxl8_gfx* gfx);
void pxl8_script_set_input(pxl8_script* script, pxl8_input_state* input);
void pxl8_script_set_rng(pxl8_script* script, void* rng);
void pxl8_script_set_sfx(pxl8_script* script, pxl8_sfx_mixer* mixer);
void pxl8_script_set_sys(pxl8_script* script, void* sys);
pxl8_result pxl8_script_call_function(pxl8_script* script, const char* name);
pxl8_result pxl8_script_call_function_f32(pxl8_script* script, const char* name, f32 arg);
bool pxl8_script_check_reload(pxl8_script* script);
pxl8_result pxl8_script_eval(pxl8_script* script, const char* code);
pxl8_result pxl8_script_eval_repl(pxl8_script* script, const char* code);
pxl8_result pxl8_script_load_cart_manifest(pxl8_script* script, pxl8_cart* cart);
pxl8_result pxl8_script_load_main(pxl8_script* script, const char* path);
pxl8_result pxl8_script_load_module(pxl8_script* script, const char* module_name);
pxl8_result pxl8_script_run_fennel_file(pxl8_script* script, const char* filename);
pxl8_result pxl8_script_run_file(pxl8_script* script, const char* filename);
u32 pxl8_script_serialize_globals(pxl8_script* script, u8** out_data);
void pxl8_script_deserialize_globals(pxl8_script* script, const u8* data, u32 size);
void pxl8_script_free_serialized(u8* data);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,525 @@
#pragma once
static const char* pxl8_ffi_cdefs =
"typedef uint8_t u8;\n"
"typedef uint16_t u16;\n"
"typedef uint32_t u32;\n"
"typedef uint64_t u64;\n"
"typedef int8_t i8;\n"
"typedef int16_t i16;\n"
"typedef int32_t i32;\n"
"typedef int64_t i64;\n"
"typedef float f32;\n"
"typedef double f64;\n"
"typedef struct pxl8 pxl8;\n"
"typedef struct pxl8_gfx pxl8_gfx;\n"
"typedef struct { int x, y, w, h; } pxl8_bounds;\n"
"typedef struct { int x, y; } pxl8_point;\n"
"typedef struct pxl8_rng { u32 state; } pxl8_rng;\n"
"\n"
"void pxl8_rng_seed(pxl8_rng* rng, u32 seed);\n"
"u32 pxl8_rng_next(pxl8_rng* rng);\n"
"f32 pxl8_rng_f32(pxl8_rng* rng);\n"
"i32 pxl8_rng_range(pxl8_rng* rng, i32 min, i32 max);\n"
"\n"
"f32 pxl8_get_fps(const pxl8* sys);\n"
"\n"
"u8 pxl8_gfx_find_color(pxl8_gfx* gfx, u32 color);\n"
"i32 pxl8_gfx_get_height(pxl8_gfx* ctx);\n"
"typedef struct pxl8_palette pxl8_palette;\n"
"pxl8_palette* pxl8_gfx_get_palette(pxl8_gfx* gfx);\n"
"u32 pxl8_palette_color(const pxl8_palette* pal, u8 idx);\n"
"void pxl8_palette_set_rgb(pxl8_palette* pal, u8 idx, u8 r, u8 g, u8 b);\n"
"i32 pxl8_palette_index(const pxl8_palette* pal, u32 color);\n"
"u8 pxl8_palette_ramp_index(const pxl8_palette* pal, u8 position);\n"
"i32 pxl8_gfx_get_width(pxl8_gfx* ctx);\n"
"void pxl8_2d_circle(pxl8_gfx* ctx, i32 x, i32 y, i32 r, u32 color);\n"
"void pxl8_2d_circle_fill(pxl8_gfx* ctx, i32 x, i32 y, i32 r, u32 color);\n"
"void pxl8_2d_clear(pxl8_gfx* ctx, u32 color);\n"
"u32 pxl8_2d_get_pixel(pxl8_gfx* ctx, i32 x, i32 y);\n"
"void pxl8_2d_line(pxl8_gfx* ctx, i32 x0, i32 y0, i32 x1, i32 y1, u32 color);\n"
"void pxl8_2d_pixel(pxl8_gfx* ctx, i32 x, i32 y, u32 color);\n"
"void pxl8_2d_rect(pxl8_gfx* ctx, i32 x, i32 y, i32 w, i32 h, u32 color);\n"
"void pxl8_2d_rect_fill(pxl8_gfx* ctx, i32 x, i32 y, i32 w, i32 h, u32 color);\n"
"void pxl8_2d_sprite(pxl8_gfx* ctx, u32 id, i32 x, i32 y, i32 w, i32 h, bool flip_x, bool flip_y);\n"
"void pxl8_2d_text(pxl8_gfx* ctx, const char* str, i32 x, i32 y, u32 color);\n"
"void pxl8_gfx_color_ramp(pxl8_gfx* ctx, u8 start, u8 count, u32 from_color, u32 to_color);\n"
"void pxl8_gfx_cycle_palette(pxl8_gfx* ctx, u8 start, u8 count, i32 step);\n"
"void pxl8_gfx_fade_palette(pxl8_gfx* ctx, u8 start, u8 count, f32 amount, u32 target_color);\n"
"i32 pxl8_gfx_add_palette_cycle(pxl8_gfx* ctx, u8 start_index, u8 end_index, f32 speed);\n"
"void pxl8_gfx_remove_palette_cycle(pxl8_gfx* ctx, i32 cycle_id);\n"
"void pxl8_gfx_set_palette_cycle_speed(pxl8_gfx* ctx, i32 cycle_id, f32 speed);\n"
"void pxl8_gfx_clear_palette_cycles(pxl8_gfx* ctx);\n"
"void pxl8_gfx_update(pxl8_gfx* ctx, f32 dt);\n"
"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"
"bool pxl8_gfx_push_target(pxl8_gfx* ctx);\n"
"void pxl8_gfx_pop_target(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"
"bool pxl8_key_released(const pxl8_input_state* input, const char* key_name);\n"
"bool pxl8_mouse_pressed(const pxl8_input_state* input, i32 button);\n"
"bool pxl8_mouse_released(const pxl8_input_state* input, i32 button);\n"
"int pxl8_mouse_wheel_x(const pxl8_input_state* input);\n"
"int pxl8_mouse_wheel_y(const pxl8_input_state* input);\n"
"int pxl8_mouse_x(const pxl8_input_state* input);\n"
"int pxl8_mouse_y(const pxl8_input_state* input);\n"
"int pxl8_mouse_dx(const pxl8_input_state* input);\n"
"int pxl8_mouse_dy(const pxl8_input_state* input);\n"
"typedef enum { PXL8_CURSOR_ARROW = 0, PXL8_CURSOR_HAND = 1 } pxl8_cursor;\n"
"void pxl8_center_cursor(pxl8* sys);\n"
"void pxl8_set_cursor(pxl8* sys, pxl8_cursor cursor);\n"
"void pxl8_set_relative_mouse_mode(pxl8* sys, bool enabled);\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"
"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 struct pxl8_tilemap pxl8_tilemap;\n"
"typedef struct pxl8_tilesheet pxl8_tilesheet;\n"
"pxl8_tilemap* pxl8_tilemap_create(u32 width, u32 height, u32 tile_size);\n"
"void pxl8_tilemap_destroy(pxl8_tilemap* tilemap);\n"
"u32 pxl8_tilemap_get_height(const pxl8_tilemap* tilemap);\n"
"pxl8_tile pxl8_tilemap_get_tile(const pxl8_tilemap* tilemap, u32 layer, u32 x, u32 y);\n"
"u32 pxl8_tilemap_get_tile_size(const pxl8_tilemap* tilemap);\n"
"void* pxl8_tilemap_get_tile_user_data(const pxl8_tilemap* tilemap, u16 tile_id);\n"
"u32 pxl8_tilemap_get_width(const pxl8_tilemap* tilemap);\n"
"void pxl8_tilemap_set_tile_user_data(pxl8_tilemap* tilemap, u16 tile_id, void* user_data);\n"
"bool pxl8_tilemap_check_collision(const pxl8_tilemap* tilemap, i32 x, i32 y, i32 w, i32 h);\n"
"u16 pxl8_tilemap_get_tile_id(const pxl8_tilemap* tilemap, u32 layer, u32 x, u32 y);\n"
"bool pxl8_tilemap_is_solid(const pxl8_tilemap* tilemap, u32 x, u32 y);\n"
"void pxl8_tilemap_render(const pxl8_tilemap* tilemap, pxl8_gfx* gfx);\n"
"void pxl8_tilemap_render_layer(const pxl8_tilemap* tilemap, pxl8_gfx* gfx, u32 layer);\n"
"void pxl8_tilemap_set_camera(pxl8_tilemap* tilemap, i32 x, i32 y);\n"
"void pxl8_tilemap_set_tile(pxl8_tilemap* tilemap, u32 layer, u32 x, u32 y, u16 tile_id, u8 flags);\n"
"i32 pxl8_tilemap_set_tilesheet(pxl8_tilemap* tilemap, pxl8_tilesheet* tilesheet);\n"
"i32 pxl8_tilemap_load_ase(pxl8_tilemap* tilemap, const char* filepath, u32 layer);\n"
"pxl8_tilesheet* pxl8_tilesheet_create(u32 tile_size);\n"
"void pxl8_tilesheet_destroy(pxl8_tilesheet* tilesheet);\n"
"i32 pxl8_tilesheet_load(pxl8_tilesheet* tilesheet, const char* filepath, pxl8_gfx* gfx);\n"
"\n"
"typedef struct {\n"
" float angle;\n"
" float ax, ay, az;\n"
" unsigned int color;\n"
" unsigned int end_color;\n"
" unsigned char flags;\n"
" float life;\n"
" float max_life;\n"
" float size;\n"
" float spin;\n"
" unsigned int start_color;\n"
" float vx, vy, vz;\n"
" float x, y, z;\n"
"} pxl8_particle;\n"
"\n"
"typedef struct pxl8_particles pxl8_particles;\n"
"pxl8_particles* pxl8_particles_create(u32 max_count, pxl8_rng* rng);\n"
"void pxl8_particles_destroy(pxl8_particles* ps);\n"
"void pxl8_particles_clear(pxl8_particles* ps);\n"
"void pxl8_particles_emit(pxl8_particles* ps, u32 count);\n"
"void pxl8_particles_render(pxl8_particles* ps, pxl8_gfx* gfx);\n"
"void pxl8_particles_update(pxl8_particles* ps, float dt);\n"
"u32 pxl8_particles_count(const pxl8_particles* ps);\n"
"u32 pxl8_particles_max_count(const pxl8_particles* ps);\n"
"pxl8_particle* pxl8_particles_get(pxl8_particles* ps, u32 index);\n"
"pxl8_rng* pxl8_particles_rng(pxl8_particles* ps);\n"
"f32 pxl8_particles_get_drag(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_gravity_x(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_gravity_y(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_spawn_rate(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_spread_x(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_spread_y(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_turbulence(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_x(const pxl8_particles* ps);\n"
"f32 pxl8_particles_get_y(const pxl8_particles* ps);\n"
"void pxl8_particles_set_colors(pxl8_particles* ps, u8 color_min, u8 color_max);\n"
"void pxl8_particles_set_drag(pxl8_particles* ps, f32 drag);\n"
"void pxl8_particles_set_gravity(pxl8_particles* ps, f32 gx, f32 gy);\n"
"void pxl8_particles_set_life(pxl8_particles* ps, f32 life_min, f32 life_max);\n"
"void pxl8_particles_set_palette(pxl8_particles* ps, pxl8_palette* palette);\n"
"void pxl8_particles_set_position(pxl8_particles* ps, f32 x, f32 y);\n"
"void pxl8_particles_set_size(pxl8_particles* ps, f32 size_min, f32 size_max);\n"
"void pxl8_particles_set_spawn_rate(pxl8_particles* ps, f32 rate);\n"
"void pxl8_particles_set_spread(pxl8_particles* ps, f32 spread_x, f32 spread_y);\n"
"void pxl8_particles_set_turbulence(pxl8_particles* ps, f32 turbulence);\n"
"void pxl8_particles_set_velocity(pxl8_particles* ps, f32 vx_min, f32 vx_max, f32 vy_min, f32 vy_max);\n"
"\n"
"typedef struct pxl8_transition pxl8_transition;\n"
"typedef struct pxl8_anim pxl8_anim;\n"
"\n"
"pxl8_transition* pxl8_transition_create(i32 type, f32 duration);\n"
"void pxl8_transition_destroy(pxl8_transition* transition);\n"
"f32 pxl8_transition_get_progress(const pxl8_transition* transition);\n"
"bool pxl8_transition_is_active(const pxl8_transition* transition);\n"
"bool pxl8_transition_is_complete(const pxl8_transition* transition);\n"
"void pxl8_transition_render(const pxl8_transition* transition, pxl8_gfx* gfx);\n"
"void pxl8_transition_reset(pxl8_transition* transition);\n"
"void pxl8_transition_set_color(pxl8_transition* transition, u32 color);\n"
"void pxl8_transition_set_reverse(pxl8_transition* transition, bool reverse);\n"
"void pxl8_transition_start(pxl8_transition* transition);\n"
"void pxl8_transition_stop(pxl8_transition* transition);\n"
"void pxl8_transition_update(pxl8_transition* transition, f32 dt);\n"
"\n"
"pxl8_anim* pxl8_anim_create(const u32* frame_ids, const u16* frame_durations, u16 frame_count);\n"
"pxl8_anim* pxl8_anim_create_from_ase(pxl8_gfx* gfx, const char* path);\n"
"void pxl8_anim_destroy(pxl8_anim* anim);\n"
"i32 pxl8_anim_add_state(pxl8_anim* anim, const char* name, pxl8_anim* state_anim);\n"
"u16 pxl8_anim_get_current_frame(const pxl8_anim* anim);\n"
"u32 pxl8_anim_get_current_frame_id(const pxl8_anim* anim);\n"
"const char* pxl8_anim_get_state(const pxl8_anim* anim);\n"
"bool pxl8_anim_has_state_machine(const pxl8_anim* anim);\n"
"bool pxl8_anim_is_complete(const pxl8_anim* anim);\n"
"bool pxl8_anim_is_playing(const pxl8_anim* anim);\n"
"void pxl8_anim_pause(pxl8_anim* anim);\n"
"void pxl8_anim_play(pxl8_anim* anim);\n"
"void pxl8_anim_render_sprite(const pxl8_anim* anim, pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, bool flip_x, bool flip_y);\n"
"void pxl8_anim_reset(pxl8_anim* anim);\n"
"void pxl8_anim_set_frame(pxl8_anim* anim, u16 frame);\n"
"void pxl8_anim_set_loop(pxl8_anim* anim, bool loop);\n"
"void pxl8_anim_set_reverse(pxl8_anim* anim, bool reverse);\n"
"void pxl8_anim_set_speed(pxl8_anim* anim, f32 speed);\n"
"i32 pxl8_anim_set_state(pxl8_anim* anim, const char* name);\n"
"void pxl8_anim_stop(pxl8_anim* anim);\n"
"void pxl8_anim_update(pxl8_anim* anim, f32 dt);\n"
"\n"
"typedef struct { float x, y, z; } pxl8_vec3;\n"
"typedef struct { float x, y, z, w; } pxl8_vec4;\n"
"typedef struct { float m[16]; } pxl8_mat4;\n"
"\n"
"typedef struct pxl8_light {\n"
" pxl8_vec3 position;\n"
" u8 r, g, b;\n"
" u8 intensity;\n"
" f32 radius;\n"
" f32 radius_sq;\n"
" f32 inv_radius_sq;\n"
"} pxl8_light;\n"
"\n"
"typedef struct pxl8_3d_uniforms {\n"
" u8 ambient;\n"
" pxl8_vec3 celestial_dir;\n"
" f32 celestial_intensity;\n"
" u8 fog_color;\n"
" f32 fog_density;\n"
" pxl8_light lights[16];\n"
" u32 num_lights;\n"
" f32 time;\n"
"} pxl8_3d_uniforms;\n"
"\n"
"typedef struct pxl8_3d_camera pxl8_3d_camera;\n"
"pxl8_3d_camera* pxl8_3d_camera_create(void);\n"
"void pxl8_3d_camera_destroy(pxl8_3d_camera* cam);\n"
"void pxl8_3d_camera_set_perspective(pxl8_3d_camera* cam, f32 fov, f32 aspect, f32 near, f32 far);\n"
"void pxl8_3d_camera_set_position(pxl8_3d_camera* cam, pxl8_vec3 pos);\n"
"void pxl8_3d_camera_set_rotation(pxl8_3d_camera* cam, f32 pitch, f32 yaw, f32 roll);\n"
"void pxl8_3d_camera_lookat(pxl8_3d_camera* cam, pxl8_vec3 eye, pxl8_vec3 target, pxl8_vec3 up);\n"
"pxl8_vec3 pxl8_3d_camera_get_forward(const pxl8_3d_camera* cam);\n"
"pxl8_vec3 pxl8_3d_camera_get_position(const pxl8_3d_camera* cam);\n"
"pxl8_vec3 pxl8_3d_camera_get_right(const pxl8_3d_camera* cam);\n"
"pxl8_vec3 pxl8_3d_camera_get_up(const pxl8_3d_camera* cam);\n"
"pxl8_mat4 pxl8_3d_camera_get_view(const pxl8_3d_camera* cam);\n"
"pxl8_mat4 pxl8_3d_camera_get_projection(const pxl8_3d_camera* cam);\n"
"void pxl8_3d_camera_update(pxl8_3d_camera* cam, f32 dt);\n"
"\n"
"typedef enum pxl8_gfx_effect { PXL8_GFX_EFFECT_GLOWS = 0 } pxl8_gfx_effect;\n"
"\n"
"typedef enum pxl8_glow_shape { PXL8_GLOW_CIRCLE = 0, PXL8_GLOW_DIAMOND = 1, PXL8_GLOW_SHAFT = 2 } pxl8_glow_shape;\n"
"\n"
"typedef struct pxl8_glow_source {\n"
" u8 color;\n"
" u16 depth;\n"
" u8 height;\n"
" u16 intensity;\n"
" u8 radius;\n"
" pxl8_glow_shape shape;\n"
" i16 x;\n"
" i16 y;\n"
"} pxl8_glow_source;\n"
"\n"
"void pxl8_gfx_apply_effect(pxl8_gfx* gfx, pxl8_gfx_effect effect, const void* params, u32 count);\n"
"void pxl8_gfx_blend_tables_update(pxl8_gfx* gfx);\n"
"void pxl8_gfx_colormap_update(pxl8_gfx* gfx);\n"
"\n"
"void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_3d_uniforms* uniforms);\n"
"void pxl8_3d_clear(pxl8_gfx* gfx, u8 color);\n"
"void pxl8_3d_clear_depth(pxl8_gfx* gfx);\n"
"void pxl8_3d_draw_line(pxl8_gfx* gfx, pxl8_vec3 p0, pxl8_vec3 p1, u8 color);\n"
"void pxl8_3d_end_frame(pxl8_gfx* gfx);\n"
"\n"
"typedef enum pxl8_blend_mode { PXL8_BLEND_OPAQUE = 0, PXL8_BLEND_ALPHA_TEST, PXL8_BLEND_ALPHA, PXL8_BLEND_ADDITIVE } pxl8_blend_mode;\n"
"\n"
"typedef struct pxl8_material {\n"
" u32 texture_id;\n"
" u8 alpha;\n"
" u8 blend_mode;\n"
" bool dither;\n"
" bool double_sided;\n"
" bool dynamic_lighting;\n"
" bool per_pixel;\n"
" bool vertex_color_passthrough;\n"
" f32 emissive_intensity;\n"
"} pxl8_material;\n"
"\n"
"typedef struct pxl8_vertex {\n"
" pxl8_vec3 position;\n"
" pxl8_vec3 normal;\n"
" f32 u, v;\n"
" u8 color;\n"
" u8 light;\n"
" u8 _pad[2];\n"
"} pxl8_vertex;\n"
"\n"
"typedef struct pxl8_mesh {\n"
" pxl8_vertex* vertices;\n"
" u16* indices;\n"
" u32 vertex_count;\n"
" u32 index_count;\n"
" u32 vertex_capacity;\n"
" u32 index_capacity;\n"
"} pxl8_mesh;\n"
"\n"
"pxl8_mesh* pxl8_mesh_create(u32 vertex_capacity, u32 index_capacity);\n"
"void pxl8_mesh_destroy(pxl8_mesh* mesh);\n"
"void pxl8_mesh_clear(pxl8_mesh* mesh);\n"
"u16 pxl8_mesh_push_vertex(pxl8_mesh* mesh, pxl8_vertex v);\n"
"void pxl8_mesh_push_triangle(pxl8_mesh* mesh, u16 i0, u16 i1, u16 i2);\n"
"void pxl8_3d_draw_mesh(pxl8_gfx* gfx, const pxl8_mesh* mesh, const pxl8_mat4* model, const pxl8_material* material);\n"
"\n"
"pxl8_mat4 pxl8_mat4_identity(void);\n"
"pxl8_mat4 pxl8_mat4_lookat(pxl8_vec3 eye, pxl8_vec3 center, pxl8_vec3 up);\n"
"pxl8_mat4 pxl8_mat4_mul(pxl8_mat4 a, pxl8_mat4 b);\n"
"pxl8_mat4 pxl8_mat4_ortho(float left, float right, float bottom, float top, float near, float far);\n"
"pxl8_mat4 pxl8_mat4_perspective(float fov, float aspect, float near, float far);\n"
"pxl8_mat4 pxl8_mat4_rotate_x(float angle);\n"
"pxl8_mat4 pxl8_mat4_rotate_y(float angle);\n"
"pxl8_mat4 pxl8_mat4_rotate_z(float angle);\n"
"pxl8_mat4 pxl8_mat4_scale(float x, float y, float z);\n"
"pxl8_mat4 pxl8_mat4_translate(float x, float y, float z);\n"
"\n"
"typedef enum pxl8_procgen_type {\n"
" PXL8_PROCGEN_ROOMS = 0,\n"
" PXL8_PROCGEN_TERRAIN = 1\n"
"} pxl8_procgen_type;\n"
"\n"
"typedef struct pxl8_procgen_params {\n"
" pxl8_procgen_type type;\n"
" int width;\n"
" int height;\n"
" int depth;\n"
" unsigned int seed;\n"
" int min_room_size;\n"
" int max_room_size;\n"
" int num_rooms;\n"
"} pxl8_procgen_params;\n"
"\n"
"typedef struct pxl8_procgen_tex_params {\n"
" char name[16];\n"
" unsigned int seed;\n"
" int width;\n"
" int height;\n"
" float scale;\n"
" float roughness;\n"
" unsigned char base_color;\n"
" unsigned char variation;\n"
"} pxl8_procgen_tex_params;\n"
"\n"
"void pxl8_procgen_tex(u8* buffer, const pxl8_procgen_tex_params* params);\n"
"\n"
"typedef struct pxl8_bsp pxl8_bsp;\n"
"typedef struct pxl8_bsp_face pxl8_bsp_face;\n"
"typedef bool (*pxl8_texture_rule)(const pxl8_vec3* normal, const pxl8_bsp_face* face, const pxl8_bsp* bsp);\n"
"\n"
"typedef struct pxl8_world_texture {\n"
" char name[16];\n"
" unsigned int texture_id;\n"
" pxl8_texture_rule rule;\n"
"} pxl8_world_texture;\n"
"\n"
"typedef struct pxl8_world pxl8_world;\n"
"pxl8_world* pxl8_world_create(void);\n"
"void pxl8_world_destroy(pxl8_world* world);\n"
"int pxl8_world_generate(pxl8_world* world, pxl8_gfx* gfx, const pxl8_procgen_params* params);\n"
"int pxl8_world_load(pxl8_world* world, const char* path);\n"
"void pxl8_world_unload(pxl8_world* world);\n"
"int pxl8_world_apply_textures(pxl8_world* world, const pxl8_world_texture* textures, unsigned int count);\n"
"bool pxl8_world_check_collision(const pxl8_world* world, pxl8_vec3 pos, float radius);\n"
"bool pxl8_world_is_loaded(const pxl8_world* world);\n"
"void pxl8_world_render(pxl8_world* world, pxl8_gfx* gfx, pxl8_vec3 camera_pos);\n"
"pxl8_vec3 pxl8_world_resolve_collision(const pxl8_world* world, pxl8_vec3 from, pxl8_vec3 to, float radius);\n"
"\n"
"typedef struct { i32 cursor_x; i32 cursor_y; bool cursor_down; bool cursor_clicked; u32 hot_id; u32 active_id; } pxl8_gui_state;\n"
"pxl8_gui_state* pxl8_gui_state_create(void);\n"
"void pxl8_gui_state_destroy(pxl8_gui_state* state);\n"
"void pxl8_gui_begin_frame(pxl8_gui_state* state);\n"
"void pxl8_gui_end_frame(pxl8_gui_state* state);\n"
"void pxl8_gui_cursor_move(pxl8_gui_state* state, i32 x, i32 y);\n"
"void pxl8_gui_cursor_down(pxl8_gui_state* state);\n"
"void pxl8_gui_cursor_up(pxl8_gui_state* state);\n"
"bool pxl8_gui_button(pxl8_gui_state* state, pxl8_gfx* gfx, u32 id, i32 x, i32 y, i32 w, i32 h, const char* label);\n"
"void pxl8_gui_window(pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, const char* title);\n"
"void pxl8_gui_label(pxl8_gfx* gfx, i32 x, i32 y, const char* text, u8 color);\n"
"bool pxl8_gui_is_hovering(const pxl8_gui_state* state);\n"
"void pxl8_gui_get_cursor_pos(const pxl8_gui_state* state, i32* x, i32* y);\n"
"\n"
"typedef struct pxl8_save pxl8_save;\n"
"pxl8_save* pxl8_save_create(const char* game_name, u32 magic, u32 version);\n"
"void pxl8_save_destroy(pxl8_save* save);\n"
"i32 pxl8_save_write(pxl8_save* save, u8 slot, const u8* data, u32 size);\n"
"i32 pxl8_save_read(pxl8_save* save, u8 slot, u8** data_out, u32* size_out);\n"
"void pxl8_save_free(u8* data);\n"
"bool pxl8_save_exists(pxl8_save* save, u8 slot);\n"
"i32 pxl8_save_delete(pxl8_save* save, u8 slot);\n"
"const char* pxl8_save_get_directory(pxl8_save* save);\n"
"\n"
"typedef struct pxl8_sfx_context pxl8_sfx_context;\n"
"typedef struct pxl8_sfx_mixer pxl8_sfx_mixer;\n"
"typedef struct pxl8_sfx_node pxl8_sfx_node;\n"
"typedef enum pxl8_sfx_filter_type { PXL8_SFX_FILTER_BANDPASS = 0, PXL8_SFX_FILTER_HIGHPASS, PXL8_SFX_FILTER_LOWPASS, PXL8_SFX_FILTER_NONE } pxl8_sfx_filter_type;\n"
"typedef enum pxl8_sfx_lfo_target { PXL8_SFX_LFO_AMPLITUDE = 0, PXL8_SFX_LFO_FILTER, PXL8_SFX_LFO_PITCH } pxl8_sfx_lfo_target;\n"
"typedef enum pxl8_sfx_node_type { PXL8_SFX_NODE_COMPRESSOR, PXL8_SFX_NODE_DELAY, PXL8_SFX_NODE_REVERB } pxl8_sfx_node_type;\n"
"typedef enum pxl8_sfx_waveform { PXL8_SFX_WAVE_NOISE = 0, PXL8_SFX_WAVE_PULSE, PXL8_SFX_WAVE_SAW, PXL8_SFX_WAVE_SINE, PXL8_SFX_WAVE_SQUARE, PXL8_SFX_WAVE_TRIANGLE } pxl8_sfx_waveform;\n"
"typedef struct pxl8_sfx_adsr { f32 attack; f32 decay; f32 sustain; f32 release; } pxl8_sfx_adsr;\n"
"typedef struct pxl8_sfx_compressor_config { f32 attack; f32 ratio; f32 release; f32 threshold; } pxl8_sfx_compressor_config;\n"
"typedef struct pxl8_sfx_delay_config { f32 feedback; f32 mix; u32 time_l; u32 time_r; } pxl8_sfx_delay_config;\n"
"typedef struct pxl8_sfx_reverb_config { f32 damping; f32 mix; f32 room; } pxl8_sfx_reverb_config;\n"
"typedef struct pxl8_sfx_voice_params { pxl8_sfx_adsr amp_env; pxl8_sfx_adsr filter_env; pxl8_sfx_filter_type filter_type; pxl8_sfx_lfo_target lfo_target; pxl8_sfx_waveform lfo_waveform; pxl8_sfx_waveform waveform; f32 filter_cutoff; f32 filter_env_depth; f32 filter_resonance; f32 fx_send; f32 lfo_depth; f32 lfo_rate; f32 pulse_width; } pxl8_sfx_voice_params;\n"
"pxl8_sfx_node* pxl8_sfx_compressor_create(pxl8_sfx_compressor_config cfg);\n"
"void pxl8_sfx_compressor_set_attack(pxl8_sfx_node* node, f32 attack);\n"
"void pxl8_sfx_compressor_set_ratio(pxl8_sfx_node* node, f32 ratio);\n"
"void pxl8_sfx_compressor_set_release(pxl8_sfx_node* node, f32 release);\n"
"void pxl8_sfx_compressor_set_threshold(pxl8_sfx_node* node, f32 threshold);\n"
"void pxl8_sfx_context_append_node(pxl8_sfx_context* ctx, pxl8_sfx_node* node);\n"
"pxl8_sfx_context* pxl8_sfx_context_create(void);\n"
"void pxl8_sfx_context_destroy(pxl8_sfx_context* ctx);\n"
"pxl8_sfx_node* pxl8_sfx_context_get_head(pxl8_sfx_context* ctx);\n"
"f32 pxl8_sfx_context_get_volume(const pxl8_sfx_context* ctx);\n"
"void pxl8_sfx_context_insert_node(pxl8_sfx_context* ctx, pxl8_sfx_node* after, pxl8_sfx_node* node);\n"
"void pxl8_sfx_context_remove_node(pxl8_sfx_context* ctx, pxl8_sfx_node* node);\n"
"void pxl8_sfx_context_set_volume(pxl8_sfx_context* ctx, f32 volume);\n"
"pxl8_sfx_node* pxl8_sfx_delay_create(pxl8_sfx_delay_config cfg);\n"
"void pxl8_sfx_delay_set_feedback(pxl8_sfx_node* node, f32 feedback);\n"
"void pxl8_sfx_delay_set_mix(pxl8_sfx_node* node, f32 mix);\n"
"void pxl8_sfx_delay_set_time(pxl8_sfx_node* node, u32 time_l, u32 time_r);\n"
"void pxl8_sfx_mixer_attach(pxl8_sfx_mixer* mixer, pxl8_sfx_context* ctx);\n"
"pxl8_sfx_mixer* pxl8_sfx_mixer_create(void);\n"
"void pxl8_sfx_mixer_destroy(pxl8_sfx_mixer* mixer);\n"
"void pxl8_sfx_mixer_detach(pxl8_sfx_mixer* mixer, pxl8_sfx_context* ctx);\n"
"f32 pxl8_sfx_mixer_get_master_volume(const pxl8_sfx_mixer* mixer);\n"
"void pxl8_sfx_mixer_set_master_volume(pxl8_sfx_mixer* mixer, f32 volume);\n"
"void pxl8_sfx_node_destroy(pxl8_sfx_node* node);\n"
"f32 pxl8_sfx_note_to_freq(u8 note);\n"
"u16 pxl8_sfx_play_note(pxl8_sfx_context* ctx, u8 note, const pxl8_sfx_voice_params* params, f32 volume, f32 duration);\n"
"void pxl8_sfx_release_voice(pxl8_sfx_context* ctx, u16 voice_id);\n"
"pxl8_sfx_node* pxl8_sfx_reverb_create(pxl8_sfx_reverb_config cfg);\n"
"void pxl8_sfx_reverb_set_damping(pxl8_sfx_node* node, f32 damping);\n"
"void pxl8_sfx_reverb_set_mix(pxl8_sfx_node* node, f32 mix);\n"
"void pxl8_sfx_reverb_set_room(pxl8_sfx_node* node, f32 room);\n"
"void pxl8_sfx_stop_all(pxl8_sfx_context* ctx);\n"
"void pxl8_sfx_stop_voice(pxl8_sfx_context* ctx, u16 voice_id);\n"
"\n"
"typedef struct pxl8_net pxl8_net;\n"
"typedef enum pxl8_net_mode { PXL8_NET_LOCAL = 0, PXL8_NET_REMOTE } pxl8_net_mode;\n"
"typedef struct pxl8_net_config { const char* address; pxl8_net_mode mode; u16 port; } pxl8_net_config;\n"
"typedef enum pxl8_cmd_type { PXL8_CMD_NONE = 0, PXL8_CMD_SPAWN_ENTITY } pxl8_cmd_type;\n"
"\n"
"typedef struct pxl8_command_msg {\n"
" u16 cmd_type;\n"
" u8 payload[64];\n"
" u16 payload_size;\n"
" u64 tick;\n"
"} pxl8_command_msg;\n"
"\n"
"typedef struct pxl8_input_msg {\n"
" u32 buttons;\n"
" f32 look_dx;\n"
" f32 look_dy;\n"
" f32 move_x;\n"
" f32 move_y;\n"
" f32 yaw;\n"
" u64 tick;\n"
" u64 timestamp;\n"
"} pxl8_input_msg;\n"
"\n"
"typedef struct pxl8_entity_state {\n"
" u64 entity_id;\n"
" u8 userdata[56];\n"
"} pxl8_entity_state;\n"
"\n"
"typedef struct pxl8_snapshot_header {\n"
" u16 entity_count;\n"
" u16 event_count;\n"
" u64 player_id;\n"
" u64 tick;\n"
" f32 time;\n"
"} pxl8_snapshot_header;\n"
"\n"
"i32 pxl8_net_connect(pxl8_net* net);\n"
"bool pxl8_net_connected(const pxl8_net* net);\n"
"pxl8_net* pxl8_net_create(const pxl8_net_config* config);\n"
"void pxl8_net_destroy(pxl8_net* net);\n"
"void pxl8_net_disconnect(pxl8_net* net);\n"
"const pxl8_entity_state* pxl8_net_entities(const pxl8_net* net);\n"
"const u8* pxl8_net_entity_prev_userdata(const pxl8_net* net, u64 entity_id);\n"
"const u8* pxl8_net_entity_userdata(const pxl8_net* net, u64 entity_id);\n"
"const pxl8_input_msg* pxl8_net_input_at(const pxl8_net* net, u64 tick);\n"
"u64 pxl8_net_input_oldest_tick(const pxl8_net* net);\n"
"void pxl8_net_input_push(pxl8_net* net, const pxl8_input_msg* input);\n"
"f32 pxl8_net_lerp_alpha(const pxl8_net* net);\n"
"bool pxl8_net_needs_correction(const pxl8_net* net);\n"
"u64 pxl8_net_player_id(const pxl8_net* net);\n"
"bool pxl8_net_poll(pxl8_net* net);\n"
"u8* pxl8_net_predicted_state(pxl8_net* net);\n"
"void pxl8_net_predicted_tick_set(pxl8_net* net, u64 tick);\n"
"i32 pxl8_net_send_command(pxl8_net* net, const pxl8_command_msg* cmd);\n"
"i32 pxl8_net_send_input(pxl8_net* net, const pxl8_input_msg* input);\n"
"const pxl8_snapshot_header* pxl8_net_snapshot(const pxl8_net* net);\n"
"u64 pxl8_net_tick(const pxl8_net* net);\n"
"void pxl8_net_update(pxl8_net* net, f32 dt);\n"
"\n"
"void pxl8_bit_clear(u32* val, u8 bit);\n"
"u32 pxl8_bit_count(u32 val);\n"
"void pxl8_bit_set(u32* val, u8 bit);\n"
"bool pxl8_bit_test(u32 val, u8 bit);\n"
"void pxl8_bit_toggle(u32* val, u8 bit);\n"
"\n"
"void pxl8_pack_u8(u8* buf, size_t offset, u8 val);\n"
"void pxl8_pack_u16_be(u8* buf, size_t offset, u16 val);\n"
"void pxl8_pack_u16_le(u8* buf, size_t offset, u16 val);\n"
"void pxl8_pack_u32_be(u8* buf, size_t offset, u32 val);\n"
"void pxl8_pack_u32_le(u8* buf, size_t offset, u32 val);\n"
"void pxl8_pack_u64_be(u8* buf, size_t offset, u64 val);\n"
"void pxl8_pack_u64_le(u8* buf, size_t offset, u64 val);\n"
"void pxl8_pack_i8(u8* buf, size_t offset, i8 val);\n"
"void pxl8_pack_i16_be(u8* buf, size_t offset, i16 val);\n"
"void pxl8_pack_i16_le(u8* buf, size_t offset, i16 val);\n"
"void pxl8_pack_i32_be(u8* buf, size_t offset, i32 val);\n"
"void pxl8_pack_i32_le(u8* buf, size_t offset, i32 val);\n"
"void pxl8_pack_i64_be(u8* buf, size_t offset, i64 val);\n"
"void pxl8_pack_i64_le(u8* buf, size_t offset, i64 val);\n"
"void pxl8_pack_f32_be(u8* buf, size_t offset, f32 val);\n"
"void pxl8_pack_f32_le(u8* buf, size_t offset, f32 val);\n"
"void pxl8_pack_f64_be(u8* buf, size_t offset, f64 val);\n"
"void pxl8_pack_f64_le(u8* buf, size_t offset, f64 val);\n"
"\n"
"u8 pxl8_unpack_u8(const u8* buf, size_t offset);\n"
"u16 pxl8_unpack_u16_be(const u8* buf, size_t offset);\n"
"u16 pxl8_unpack_u16_le(const u8* buf, size_t offset);\n"
"u32 pxl8_unpack_u32_be(const u8* buf, size_t offset);\n"
"u32 pxl8_unpack_u32_le(const u8* buf, size_t offset);\n"
"u64 pxl8_unpack_u64_be(const u8* buf, size_t offset);\n"
"u64 pxl8_unpack_u64_le(const u8* buf, size_t offset);\n"
"i8 pxl8_unpack_i8(const u8* buf, size_t offset);\n"
"i16 pxl8_unpack_i16_be(const u8* buf, size_t offset);\n"
"i16 pxl8_unpack_i16_le(const u8* buf, size_t offset);\n"
"i32 pxl8_unpack_i32_be(const u8* buf, size_t offset);\n"
"i32 pxl8_unpack_i32_le(const u8* buf, size_t offset);\n"
"i64 pxl8_unpack_i64_be(const u8* buf, size_t offset);\n"
"i64 pxl8_unpack_i64_le(const u8* buf, size_t offset);\n"
"f32 pxl8_unpack_f32_be(const u8* buf, size_t offset);\n"
"f32 pxl8_unpack_f32_le(const u8* buf, size_t offset);\n"
"f64 pxl8_unpack_f64_be(const u8* buf, size_t offset);\n"
"f64 pxl8_unpack_f64_le(const u8* buf, size_t offset);\n";