summaryrefslogtreecommitdiff
path: root/Podium
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 00:56:24 +0100
committerVasco <[email protected]>2026-08-24 00:56:24 +0100
commit5dc2716abd43166cd65133625f408ad36a6623b3 (patch)
tree19d89b838206b6bb11cc0b9f88311d855999d447 /Podium
parentdc96fcd771bea09d726a760266739906e95c09a6 (diff)
Peak 0.4.0 and Draw
Diffstat (limited to 'Podium')
-rw-r--r--Podium/README.md9
-rw-r--r--Podium/p_allocators.c301
-rw-r--r--Podium/p_allocators.h44
-rw-r--r--Podium/p_ds.h52
-rw-r--r--Podium/p_log.h186
-rw-r--r--Podium/p_math.c255
-rw-r--r--Podium/p_math.h33
-rw-r--r--Podium/p_platform_linux.c404
-rw-r--r--Podium/p_platform_win32.c402
-rw-r--r--Podium/p_string.c201
-rw-r--r--Podium/p_string.h38
-rw-r--r--Podium/p_types.h88
-rw-r--r--Podium/podium.c1
-rw-r--r--Podium/podium.h2269
-rw-r--r--Podium/podium_header.h258
15 files changed, 0 insertions, 4541 deletions
diff --git a/Podium/README.md b/Podium/README.md
deleted file mode 100644
index fccb70d..0000000
--- a/Podium/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Podium
-
-Single header platform library with batteries included.
-
-NOTE TO SELF: Stop trying to redesign your own library!
-This shit works! Podium stands on business!!!
-
-The library does it's best to auto-detect your operating system
-and the include the correct OS code for that platform.
diff --git a/Podium/p_allocators.c b/Podium/p_allocators.c
deleted file mode 100644
index 7e59807..0000000
--- a/Podium/p_allocators.c
+++ /dev/null
@@ -1,301 +0,0 @@
-PODEF bool
-is_power_of_two(uintptr x) {
- return (x & (x-1)) == 0;
-}
-
-PODEF uintptr
-align_forward(uintptr ptr, usize align)
-{
- uintptr p, a, remainder;
- assert(is_power_of_two(align));
-
- p = ptr;
- a = (uintptr)align;
- remainder = p & (a-1);
-
- return (remainder != 0) ? p + a - remainder : p;
-}
-
-PODEF void
-p_arena_create(Arena *a, void *backing_buffer, usize backing_buffer_length)
-{
- a->buf = (unsigned char *)backing_buffer;
- a->buf_len = backing_buffer_length;
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void*
-p_arena_alloc_align(Arena *a, usize s, usize align)
-{
-
- // Align 'curr_offset' forward to the specified alignment
- uintptr curr_ptr = (uintptr)a->buf + (uintptr)a->curr_offset;
- uintptr offset = align_forward(curr_ptr, align);
- offset -= (uintptr)a->buf; // Change to relative offset
-
- // Check to see if the backing memory has space left
- if (offset+s <= a->buf_len) {
- void *ptr = &a->buf[offset];
- a->prev_offset = offset;
- a->curr_offset = offset+s;
-
- memset(ptr, 0, s);
- return ptr;
- }
-
- return NULL;
-}
-
-PODEF void*
-p_arena_alloc(Arena *a, usize s) {
- return p_arena_alloc_align(a, s, DEFAULT_ALIGNMENT);
-}
-
-PODEF void*
-p_arena_resize_align(Arena *a, void *old_memory, usize old_size, usize new_size, usize align)
-{
- assert(is_power_of_two(align));
- unsigned char *old_mem = (unsigned char *)old_memory;
-
- if (old_mem == NULL || old_size == 0) {
- return p_arena_alloc_align(a, new_size, align);
- } else if (a->buf <= old_mem && old_mem < a->buf+a->buf_len) {
- if (a->buf+a->prev_offset == old_mem) {
- a->curr_offset = a->prev_offset + new_size;
- if (new_size > old_size) {
- // Zero the new memory by default
- memset(&a->buf[a->curr_offset], 0, new_size-old_size);
- }
- return old_memory;
- } else {
- void *new_memory = p_arena_alloc_align(a, new_size, align);
- size_t copy_size = old_size < new_size ? old_size : new_size;
- memmove(new_memory, old_memory, copy_size);
- return new_memory;
- }
-
- } else {
- assert(0 && "Memory is out of bounds of the buffer in this arena");
- return NULL;
- }
-}
-
-PODEF void*
-p_arena_resize(Arena *a, void *old_memory, usize old_size, usize new_size)
-{
- return p_arena_resize_align(a, old_memory, old_size, new_size, DEFAULT_ALIGNMENT);
-}
-
-PODEF void
-p_arena_free_all(Arena *a)
-{
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void
-p_arena_destroy(Arena* a)
-{
- a->buf_len = 0;
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void
-p_stack_create(Stack *s, void *backing_buffer, usize backing_buffer_length)
-{
- s->buf = (unsigned char*) backing_buffer;
- s->buf_len = backing_buffer_length;
- s->offset = 0;
-}
-
-PODEF usize
-calc_padding_with_header(uintptr ptr, uintptr alignment, usize header_size)
-{
- uintptr p, a, modulo, padding, needed_space;
-
- assert(is_power_of_two(alignment));
-
- p = ptr;
- a = alignment;
- modulo = p & (a-1); // (p % a) as it assumes alignment is a power of two
-
- padding = 0;
- needed_space = 0;
-
- if (modulo != 0) { // Same logic as 'align_forward'
- padding = a - modulo;
- }
-
- needed_space = (uintptr)header_size;
-
- if (padding < needed_space) {
- needed_space -= padding;
-
- if ((needed_space & (a-1)) != 0) {
- padding += a * (1+(needed_space/a));
- } else {
- padding += a * (needed_space/a);
- }
- }
-
- return (usize)padding;
-}
-
-PODEF void*
-p_stack_alloc(Stack *s, usize len, usize alignment)
-{
- uintptr curr_addr, next_addr;
- usize padding;
- Stack_Allocation_Header *header;
-
- assert(is_power_of_two(alignment));
-
- if (alignment > 128) {
- // As the padding is 8 bits (1 byte), the largest alignment that can
- // be used is 128 bytes
- alignment = 128;
- }
-
- curr_addr = (uintptr)s->buf + (uintptr)s->offset;
- padding = calc_padding_with_header(curr_addr, (uintptr)alignment, sizeof(Stack_Allocation_Header));
- if (s->offset + padding + len > s->buf_len) {
- // Stack allocator is out of memory
- return NULL;
- }
- s->offset += padding;
-
- next_addr = curr_addr + (uintptr)padding;
- header = (Stack_Allocation_Header *)(next_addr - sizeof(Stack_Allocation_Header));
- header->padding = (u8)padding;
-
- s->offset += len;
-
- return memset((void *)next_addr, 0, len);
-}
-
-PODEF void
-p_stack_free(Stack *s, void *ptr)
-{
- if (ptr != NULL) {
- uintptr start, end, curr_addr;
- Stack_Allocation_Header *header;
- usize prev_offset;
-
- start = (uintptr)s->buf;
- end = start + (uintptr)s->buf_len;
- curr_addr = (uintptr)ptr;
-
- if (!(start <= curr_addr && curr_addr < end)) {
- assert(0 && "Out of bounds memory address passed to stack allocator (free)");
- return;
- }
-
- if (curr_addr >= start+(uintptr)s->offset) {
- // Allow double frees
- return;
- }
-
- header = (Stack_Allocation_Header *)(curr_addr - sizeof(Stack_Allocation_Header));
- prev_offset = (usize)(curr_addr - (uintptr)header->padding - start);
-
- s->offset = prev_offset;
- }
-}
-
-PODEF void
-p_stack_free_all(Stack* s)
-{
- s->offset = 0;
-}
-
-PODEF void
-p_stack_destroy(Stack* s)
-{
- s->buf = 0;
- s->buf_len = 0;
- s->offset = 0;
-}
-
-PODEF void
-p_pool_create(Pool *p, void *buf, usize buf_len, usize chunk_size, usize chunk_align)
-{
- /* align start */
- uintptr start = (uintptr) buf;
- uintptr aligned = align_forward(start, chunk_align);
- buf_len -= (aligned - start);
-
- /* align chunk usize */
- chunk_size = (usize) align_forward(chunk_size, chunk_align);
-
- assert(chunk_size >= sizeof(Pool_Free_Node) && "Chunk usize is too small");
- assert(buf_len >= chunk_size && "Backing buffer length is smaller than the chunk size");
-
- p->buf = (unsigned char *) buf;
- p->pool_size = buf_len;
- p->chunk_size = chunk_size;
- p->head = NULL;
-
- p_pool_free_all(p);
-}
-
-PODEF void*
-p_pool_alloc(Pool *p)
-{
- Pool_Free_Node *node = p->head;
-
- assert(node != NULL && "Pool allocator has no free memory");
-
- p->head = p->head->next;
-
- return memset(node, 0 , p->chunk_size);
-}
-
-PODEF void
-p_pool_free(Pool *p, void *ptr)
-{
- Pool_Free_Node *node;
-
- void *start = p->buf;
- void *end = &p->buf[p->pool_size];
-
- if (ptr == NULL) {
- return;
- }
-
- if (!(start <= ptr && ptr < end)) {
- assert(0 && "Memory is out of bounds of the buffer in this pool");
- return;
- }
-
- node = (Pool_Free_Node *)ptr;
- node->next = p->head;
- p->head = node;
-}
-
-PODEF void
-p_pool_free_all(Pool *p)
-{
- usize chunk_count = p->pool_size / p->chunk_size;
- usize i;
-
- for (i = 0; i < chunk_count; i++) {
- void *ptr = &p->buf[i * p->chunk_size];
- Pool_Free_Node *node = (Pool_Free_Node *)ptr;
-
- // Push free node onto thte free list
- node->next = p->head;
- p->head = node;
- }
-}
-
-PODEF void
-p_pool_destroy(Pool *p)
-{
- p->buf = NULL;
- p->pool_size = 0;
- p->chunk_size = 0;
- p->head = NULL;
-}
-
diff --git a/Podium/p_allocators.h b/Podium/p_allocators.h
deleted file mode 100644
index 72bae56..0000000
--- a/Podium/p_allocators.h
+++ /dev/null
@@ -1,44 +0,0 @@
-typedef struct Arena {
- unsigned char *buf;
- usize buf_len;
- usize curr_offset;
- usize prev_offset;
-} Arena;
-
-PODEF void p_arena_create(Arena *a, void *backing_buffer, usize backing_buffer_length);
-PODEF void* p_arena_alloc_align(Arena *a, usize s, usize align);
-PODEF void* p_arena_alloc(Arena *a, usize s);
-PODEF void* p_arena_resize_align(Arena *a, void *old_memory, usize old_size, usize new_size, usize align);
-PODEF void* p_arena_resize(Arena *a, void *old_memory, usize old_size, usize new_size);
-PODEF void p_arena_free_all(Arena *a);
-PODEF void p_arena_destroy(Arena* a);
-
-typedef struct { u8 padding; } Stack_Allocation_Header;
-typedef struct Stack {
- unsigned char *buf;
- usize buf_len;
- usize offset;
-} Stack;
-
-PODEF void p_stack_create(Stack *s, void *backing_buffer, usize backing_buffer_length);
-PODEF usize calc_padding_with_header(uintptr ptr, uintptr alignment, usize header_size);
-PODEF void* p_stack_alloc(Stack *s, usize len, usize alignment);
-PODEF void p_stack_free(Stack *s, void *ptr);
-PODEF void p_stack_free_all(Stack* s);
-PODEF void p_stack_destroy(Stack* s);
-
-typedef struct Pool_Free_Node Pool_Free_Node;
-
-typedef struct Pool {
- unsigned char *buf;
- usize chunk_size;
- usize pool_size;
- Pool_Free_Node *head;
-} Pool;
-
-struct Pool_Free_Node { struct Pool_Free_Node *next; };
-PODEF void p_pool_create(Pool *p, void *buf, usize buf_len, usize chunk_size, usize chunk_align);
-PODEF void* p_pool_alloc(Pool *p);
-PODEF void p_pool_free(Pool *p, void *ptr);
-PODEF void p_pool_free_all(Pool *p);
-PODEF void p_pool_destroy(Pool *p);
diff --git a/Podium/p_ds.h b/Podium/p_ds.h
deleted file mode 100644
index 8731975..0000000
--- a/Podium/p_ds.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
-#define ARRAY_GROW_FACTOR 2
-
-typedef struct {
- u32 size;
- u32 capacity;
-} DynamicArrayHeader;
-
-#define DARRAY_INIT_CAPACITY 64
-#define p_darray_push(array, var) \
- do { \
- if (array == NULL) { \
- DynamicArrayHeader *header = \
- malloc(DARRAY_INIT_CAPACITY * sizeof *array + sizeof *header); \
- header->size = 0; \
- header->capacity = DARRAY_INIT_CAPACITY; \
- array = (void *)(header + 1); \
- } \
- DynamicArrayHeader *header = (DynamicArrayHeader *)(array) - 1; \
- if (header->size >= header->capacity - 1) { \
- unsigned long new_capacity = header->capacity * 2; \
- DynamicArrayHeader *new_header = \
- realloc(header, new_capacity * sizeof *array + sizeof *header); \
- if (!new_header) \
- break; \
- header = new_header; \
- array = (void *)(header + 1); \
- header->capacity = new_capacity; \
- } \
- (array)[header->size++] = var; \
- } while (0)
-
-#define p_darray_len(array) ((array) ? ((DynamicArrayHeader *)(array) - 1)->size : 0)
-#define p_darray_destroy(array) \
-{ \
- free((DynamicArrayHeader *)(array) - 1); \
-}
-
-#define p_darray_shrink(array) \
- do { \
- DynamicArrayHeader *header = (array) ? ((DynamicArrayHeader *)(array) - 1) : 0;\
- if (header) {\
- if (header->capacity > 4) {\
- unsigned long new_capacity = (header->capacity >> 1) + (header->capacity & 1); \
- void *new_header = realloc(header, new_capacity * sizeof *array + sizeof *header); \
- if (!new_header) break; \
- header = new_header; \
- array = (void *)(header + 1); \
- header->capacity = new_capacity; \
- }\
- }\
- } while (0)
diff --git a/Podium/p_log.h b/Podium/p_log.h
deleted file mode 100644
index 0f6ce6c..0000000
--- a/Podium/p_log.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Logging!
- */
-
-#include <stdlib.h>
-
-#ifdef DEBUG
-#define LOG_DEBUG(...) PRINTF(__VA_ARGS__)
-#else
-#define LOG_DEBUG(...) ((void)0)
-#endif
-
-/* fatal and error always enabled */
-#define PFATAL(message, ...) p_log_printf(P_LOG_LEVEL_FATAL, message, ##__VA_ARGS__)
-#define PERROR(message, ...) p_log_printf(P_LOG_LEVEL_ERROR, message, ##__VA_ARGS__)
-
-/* warn and info enabled by default but can be disabled */
-#define P_LOG_WARN_ENABLED 1
-#define P_LOG_INFO_ENABLED 1
-
-#if P_LOG_WARN_ENABLED == 1
-#define PWARN(message, ...) p_log_printf(P_LOG_LEVEL_WARN, message, ##__VA_ARGS__)
-#else
-#define PWARN(message, ...)
-#endif
-
-#if P_LOG_INFO_ENABLED == 1
-#define PINFO(message, ...) p_log_printf(P_LOG_LEVEL_INFO, message, ##__VA_ARGS__)
-#else
-#define PINFO(message, ...)
-#endif
-
-#if P_LOG_DEBUG_ENABLED == 1
-#define PDEBUG(message, ...) p_log_printf(P_LOG_LEVEL_DEBUG, message, ##__VA_ARGS__)
-#else
-#define PDEBUG(message, ...)
-#endif
-
-#if P_LOG_TRACE_ENABLED == 1
-#define PTRACE(message, ...) p_log_printf(P_LOG_LEVEL_TRACE, message, ##__VA_ARGS__)
-#else
-#define PTRACE(message, ...)
-#endif
-
-typedef enum P_Log_Level {
- P_LOG_LEVEL_FATAL = 0,
- P_LOG_LEVEL_ERROR,
- P_LOG_LEVEL_WARN,
- P_LOG_LEVEL_INFO,
- P_LOG_LEVEL_DEBUG,
- P_LOG_LEVEL_TRACE,
- P_COUNT_LOG_LEVEL
-} P_Log_Level;
-
-#define P_PREFIX_LEN 7
-static const char *p_prefix[P_COUNT_LOG_LEVEL] = {
- [P_LOG_LEVEL_FATAL] = "[FATAL]",
- [P_LOG_LEVEL_ERROR] = "[ERROR]",
- [P_LOG_LEVEL_WARN] = "[WARNI]",
- [P_LOG_LEVEL_INFO] = "[INFOR]",
- [P_LOG_LEVEL_DEBUG] = "[DEBUG]",
- [P_LOG_LEVEL_TRACE] = "[TRACE]",
-};
-
-#define P_MAX_ALLOCS 512
-
-typedef struct P_DebugMemoryInfo {
- void *ptr;
- size_t size;
- const char *file;
- const char *func;
- int line;
-} P_DebugMemoryInfo;
-
-static uint64_t p_alloc_count = 0;
-static P_DebugMemoryInfo p_ptr_array[P_MAX_ALLOCS];
-
-static inline void *
-p_debug_malloc_impl(size_t size, const char *file, int line, const char *func)
-{
- void *ptr = malloc(size);
- printf("[ALLOC] %p (%zu bytes) -> %s:%d %s()\n", ptr, size, file, line, func);
-
- if (ptr) {
- if (p_alloc_count < P_MAX_ALLOCS) {
- p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){
- .ptr = ptr,
- .size = size,
- .file = file,
- .func = func,
- .line = line
- };
- } else {
- fprintf(stderr, "[ERROR] Debug allocator tracking capacity (%d) exceeded!\n", P_MAX_ALLOCS);
- }
- }
- return ptr;
-}
-
-static inline void
-p_debug_free_impl(void *ptr, const char *file, int line, const char *func)
-{
- printf("[FREE] %p -> %s:%d %s()\n", ptr, file, line, func);
-
- if (!ptr) return; // Standard C allows free(NULL)
-
- bool found = false;
- uint64_t index = 0;
-
- /* Find allocation metadata */
- for (index = 0; index < p_alloc_count; ++index) {
- if (p_ptr_array[index].ptr == ptr) {
- found = true;
- break;
- }
- }
-
- if (found) {
- /* Shift array left to remove tracked struct */
- for (uint64_t j = index; j < p_alloc_count - 1; ++j) {
- p_ptr_array[j] = p_ptr_array[j + 1];
- }
- p_alloc_count--;
- } else {
- fprintf(stderr, "[WARNING] Attempted to free untracked/double-freed pointer %p at %s:%d %s()\n",
- ptr, file, line, func);
- }
-
- free(ptr);
-}
-
-static inline void *
-p_debug_realloc_impl(void *ptr, size_t size, const char *file, int line, const char *func)
-{
- if (!ptr) {
- return p_debug_malloc_impl(size, file, line, func);
- }
- if (size == 0) {
- p_debug_free_impl(ptr, file, line, func);
- return NULL;
- }
-
- void *new_ptr = realloc(ptr, size);
- printf("[REALLOC] %p -> %p (%zu bytes) -> %s:%d %s()\n", ptr, new_ptr, size, file, line, func);
-
- if (new_ptr) {
- bool found = false;
- for (uint64_t i = 0; i < p_alloc_count; ++i) {
- if (p_ptr_array[i].ptr == ptr) {
- p_ptr_array[i].ptr = new_ptr;
- p_ptr_array[i].size = size;
- p_ptr_array[i].file = file;
- p_ptr_array[i].line = line;
- p_ptr_array[i].func = func;
- found = true;
- break;
- }
- }
- if (!found) {
- if (p_alloc_count < P_MAX_ALLOCS) {
- p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){
- .ptr = new_ptr,
- .size = size,
- .file = file,
- .func = func,
- .line = line
- };
- }
- }
- }
- return new_ptr;
-}
-
-static void
-p_debug_memory_report(void)
-{
- printf("\n==================== MEMORY REPORT ====================\n");
- printf("Remaining unfreed allocations: %lu\n", (unsigned long)p_alloc_count);
-
- for (uint64_t i = 0; i < p_alloc_count; ++i) {
- P_DebugMemoryInfo *info = &p_ptr_array[i];
- printf("[LEAK] %p (%zu bytes) allocated at %s:%d in %s()\n",
- info->ptr, info->size, info->file, info->line, info->func);
- }
- printf("=======================================================\n");
-}
diff --git a/Podium/p_math.c b/Podium/p_math.c
deleted file mode 100644
index 928738b..0000000
--- a/Podium/p_math.c
+++ /dev/null
@@ -1,255 +0,0 @@
-PODEF
-int p_ceil(float x)
-{
- int base = (int) x;
- return (x > base) ? base + 1 : base;
-}
-
-PODEF float
-p_cosf(float x)
-{
- x += 1.57079632679f;
-
- while (x > P_PI) x -= P_PI2;
- while (x < -P_PI) x += P_PI2;
-
- const float B = 4.0f / P_PI;
- const float C = -4.0f / P_PI_POW2;
-
- float y = B * x + C * x * (x < 0 ? -x : x);
-
- const float P = 0.225f;
- y = P * (y * (y < 0 ? -y : y) - y) + y;
-
- return y;
-}
-
-PODEF float
-p_sinf(float x)
-{
- while (x > P_PI) x -= P_PI2;
- while (x < -P_PI) x += P_PI2;
-
- const float B = 4.0f / P_PI;
- const float C = -4.0f / (P_PI_POW2);
-
- float y = B * x + C * x * (x < 0 ? -x : x);
-
- const float P = 0.225f;
- y = P * (y * (y < 0 ? -y : y) - y) + y;
-
- return y;
-}
-
-PODEF Vec2f
-p_vec2f(float x, float y)
-{
- return (Vec2f) { .x = x, .y = y };
-}
-
-PODEF Vec2f
-p_vec2f_add(Vec2f a, Vec2f b)
-{
- return (Vec2f) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- };
-}
-
-PODEF float
-p_vec2f_cross(Vec2f a, Vec2f b)
-{
- // axby − aybx
- return a.x * b.y - a.y * b.x;
-}
-
-PODEF float
-p_vec2f_dot(Vec2f a, Vec2f b)
-{
- // a · b = ax × bx + ay × by
- return a.x * b.x + a.y * b.y;
-}
-
-PODEF Vec2f
-p_vec2f_mult(Vec2f a, float b)
-{
- return (Vec2f) {
- .x = a.x * b,
- .y = a.y * b,
- };
-}
-
-PODEF Vec2f
-p_vec2f_sub(Vec2f a, Vec2f b)
-{
- return (Vec2f) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- };
-}
-
-PODEF Vec2i
-p_vec2i(float x, float y)
-{
- return (Vec2i) { .x = x, .y = y };
-}
-
-PODEF Vec2i
-p_vec2i_add(Vec2i a, Vec2i b)
-{
- return (Vec2i) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- };
-}
-
-PODEF float
-p_vec2i_cross(Vec2i a, Vec2i b)
-{
- // axby − aybx
- return a.x * b.y - a.y * b.x;
-}
-
-PODEF float
-p_vec2i_dot(Vec2i a, Vec2i b)
-{
- // a · b = ax × bx + ay × by
- return a.x * b.x + a.y * b.y;
-}
-
-PODEF Vec2i
-p_vec2i_mult(Vec2i a, float b)
-{
- return (Vec2i) {
- .x = a.x * b,
- .y = a.y * b,
- };
-}
-
-PODEF Vec2i
-p_vec2i_sub(Vec2i a, Vec2i b)
-{
- return (Vec2i) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- };
-}
-
-PODEF Vec3f
-p_vec3f(float x, float y, float z)
-{
- return (Vec3f) { .x = x, .y = y, .z = z };
-}
-
-PODEF P_Mat4
-p_mat4_identity(void)
-{
- P_Mat4 res = {0};
- res.m[0] = 1.0f;
- res.m[5] = 1.0f;
- res.m[10] = 1.0f;
- res.m[15] = 1.0f;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_mul(P_Mat4 a, P_Mat4 b)
-{
- P_Mat4 res = {0};
- for (int col = 0; col < 4; ++col) {
- for (int row = 0; row < 4; ++row) {
- float sum = 0.0f;
- for (int k = 0; k < 4; ++k) {
- sum += a.m[k * 4 + row] * b.m[col * 4 + k];
- }
- res.m[col * 4 + row] = sum;
- }
- }
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_translate(Vec3f v)
-{
- P_Mat4 res = p_mat4_identity();
- res.m[12] = v.x;
- res.m[13] = v.y;
- res.m[14] = v.z;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_translate_by(P_Mat4 m, Vec3f v)
-{
- P_Mat4 res = m;
- res.m[12] = m.m[0] * v.x + m.m[4] * v.y + m.m[8] * v.z + m.m[12];
- res.m[13] = m.m[1] * v.x + m.m[5] * v.y + m.m[9] * v.z + m.m[13];
- res.m[14] = m.m[2] * v.x + m.m[6] * v.y + m.m[10] * v.z + m.m[14];
- res.m[15] = m.m[3] * v.x + m.m[7] * v.y + m.m[11] * v.z + m.m[15];
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_x(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[5] = c;
- res.m[6] = s;
- res.m[9] = -s;
- res.m[10] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_x_by(P_Mat4 m, float rad)
-{
- return p_mat4_mul(m, p_mat4_rotate_x(rad));
-}
-
-PODEF P_Mat4
-p_mat4_rotate_y(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[0] = c;
- res.m[2] = -s;
- res.m[8] = s;
- res.m[10] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_y_by(P_Mat4 m, float rad)
-{
- return p_mat4_mul(m, p_mat4_rotate_y(rad));
-}
-
-PODEF P_Mat4
-p_mat4_rotate_z(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[0] = c;
- res.m[1] = s;
- res.m[4] = -s;
- res.m[5] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_perspective(float fov_rad, float aspect, float near_z, float far_z)
-{
- P_Mat4 res = {0};
- float tan_half_fov = p_sinf(fov_rad * 0.5f) / p_cosf(fov_rad * 0.5f);
-
- res.m[0] = 1.0f / (aspect * tan_half_fov);
- res.m[5] = 1.0f / tan_half_fov;
- res.m[10] = far_z / (near_z - far_z);
- res.m[11] = -1.0f;
- res.m[14] = (near_z * far_z) / (near_z - far_z);
- return res;
-}
diff --git a/Podium/p_math.h b/Podium/p_math.h
deleted file mode 100644
index 1dad6ec..0000000
--- a/Podium/p_math.h
+++ /dev/null
@@ -1,33 +0,0 @@
-typedef struct {int x, y; } Vec2i;
-typedef struct {float x, y; } Vec2f;
-typedef struct {float x, y, z; } Vec3f;
-typedef struct { float m[16];} P_Mat4; // column-major: m[col * 4 + row]
-PODEF int p_ceil(float x);
-PODEF float p_cosf(float x);
-PODEF float p_sinf(float x);
-
-PODEF Vec2f p_vec2f(float, float);
-PODEF Vec2f p_vec2f_add(Vec2f, Vec2f);
-PODEF float p_vec2f_cross(Vec2f, Vec2f);
-PODEF float p_vec2f_dot(Vec2f, Vec2f);
-PODEF Vec2f p_vec2f_mult(Vec2f a, float b);
-PODEF Vec2f p_vec2f_sub(Vec2f, Vec2f);
-PODEF Vec2i p_vec2i(float, float);
-PODEF Vec2i p_vec2i_add(Vec2i, Vec2i);
-PODEF float p_vec2i_cross(Vec2i, Vec2i);
-PODEF float p_vec2i_dot(Vec2i, Vec2i);
-PODEF Vec2i p_vec2i_mult(Vec2i a, float b);
-PODEF Vec2i p_vec2i_sub(Vec2i, Vec2i);
-
-PODEF Vec3f p_vec3f(float, float, float);
-
-PODEF P_Mat4 p_mat4_identity(void);
-PODEF P_Mat4 p_mat4_mul(P_Mat4 a, P_Mat4 b);
-PODEF P_Mat4 p_mat4_translate(Vec3f v);
-PODEF P_Mat4 p_mat4_translate_by(P_Mat4 m, Vec3f v);
-PODEF P_Mat4 p_mat4_rotate_x(float rad);
-PODEF P_Mat4 p_mat4_rotate_x_by(P_Mat4 m, float rad);
-PODEF P_Mat4 p_mat4_rotate_y(float rad);
-PODEF P_Mat4 p_mat4_rotate_y_by(P_Mat4 m, float rad);
-PODEF P_Mat4 p_mat4_rotate_z(float rad);
-PODEF P_Mat4 p_mat4_perspective(float fov_rad, float aspect, float near_z, float far_z);
diff --git a/Podium/p_platform_linux.c b/Podium/p_platform_linux.c
deleted file mode 100644
index 366e3d7..0000000
--- a/Podium/p_platform_linux.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/* linux */
-#include <time.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <errno.h>
-/* x11 */
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-/* pulse audio */
-#include <pulse/pulseaudio.h>
-#include <pulse/simple.h>
-#include <pulse/error.h>
-/* joystick */
-#include <linux/joystick.h>
-
-typedef struct {
- pa_simple *audio_stream;
-} P_LinuxCtx;
-
-struct P_Window_Impl {
- Display *display;
- XImage *image;
- Window window;
- GC gc;
- int screen;
- int width;
- int height;
-};
-
-P_LinuxCtx p_ctx = {0};
-
-static inline P_KeyCode
-_x11_translate_keycode(XEvent xev)
-{
- static KeySym ks;
- ks = XLookupKeysym(&xev.xkey, 0);
- switch (ks) {
- /* Arrow keys */
- case XK_Left: return P_KEY_LEFT;
- case XK_Right: return P_KEY_RIGHT;
- case XK_Up: return P_KEY_UP;
- case XK_Down: return P_KEY_DOWN;
- /* Common keys */
- case XK_space: return P_KEY_SPACE;
- case XK_Escape: return P_KEY_ESCAPE;
- case XK_Return: return P_KEY_ENTER;
- case XK_A: case XK_a: return P_KEY_A;
- case XK_B: case XK_b: return P_KEY_B;
- case XK_C: case XK_c: return P_KEY_C;
- case XK_D: case XK_d: return P_KEY_D;
- case XK_E: case XK_e: return P_KEY_E;
- case XK_F: case XK_f: return P_KEY_F;
- case XK_G: case XK_g: return P_KEY_G;
- case XK_H: case XK_h: return P_KEY_H;
- case XK_I: case XK_i: return P_KEY_I;
- case XK_J: case XK_j: return P_KEY_J;
- case XK_K: case XK_k: return P_KEY_K;
- case XK_L: case XK_l: return P_KEY_L;
- case XK_M: case XK_m: return P_KEY_M;
- case XK_N: case XK_n: return P_KEY_N;
- case XK_O: case XK_o: return P_KEY_O;
- case XK_P: case XK_p: return P_KEY_P;
- case XK_Q: case XK_q: return P_KEY_Q;
- case XK_R: case XK_r: return P_KEY_R;
- case XK_S: case XK_s: return P_KEY_S;
- case XK_T: case XK_t: return P_KEY_T;
- case XK_U: case XK_u: return P_KEY_U;
- case XK_V: case XK_v: return P_KEY_V;
- case XK_W: case XK_w: return P_KEY_W;
- case XK_X: case XK_x: return P_KEY_X;
- case XK_Y: case XK_y: return P_KEY_Y;
- case XK_Z: case XK_z: return P_KEY_Z;
- default: return P_KEY_UNKNOWN;
- }
-}
-
-POAPI u64
-p_get_time(void)
-{
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return NANOS_PER_SEC * ts.tv_sec + ts.tv_nsec;
-}
-
-POAPI void
-p_sleep_ns(i64 ns)
-{
- struct timespec ts;
- ts.tv_sec = ns / 1000000000L;
- ts.tv_nsec = ns % 1000000000L;
- clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
-}
-
-POAPI void
-p_stdout(void *msg, usize bytes)
-{
- write(1, msg, bytes);
-}
-
-POAPI bool
-p_file_exists(const char *path)
-{
- return (access(path, F_OK) == 0);
-}
-
-POAPI usize
-p_file_size(const char *path)
-{
- struct stat st;
- if (stat(path, &st) == 0) {
- return st.st_size;
- }
- return 0;
-}
-
-PODEF void
-p_file_load(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- int fd = open(path, O_RDONLY);
- if (fd >= 0) {
- read(fd, buf_ptr, (size_t)buf_size);
- close(fd);
- }
-}
-
-PODEF void
-p_file_write(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644);
- if (fd >= 0) {
- write(fd, buf_ptr, (size_t)buf_size);
- close(fd);
- }
-}
-
-POAPI bool
-p_window_open(P_Window *win, int width, int height, const char *title)
-{
- win->width = width;
- win->height = height;
-
- XInitThreads();
-
- win->display = XOpenDisplay(NULL);
- if (win->display == NULL) {
- PERROR("Cannot open display!");
- return false;
- }
-
- int screen = DefaultScreen(win->display);
- win->window = XCreateSimpleWindow(
- win->display,
- RootWindow(win->display, screen),
- 0, 0, width, height,
- 1,
- BlackPixel(win->display, screen),
- BlackPixel(win->display, screen)
- );
-
- win->screen = screen;
-
- XStoreName(win->display, win->window, title);
- XSelectInput(win->display, win->window,
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | StructureNotifyMask);
- XMapWindow(win->display, win->window);
-
- win->gc = DefaultGC(win->display, screen);
-
- Atom wm_delete = XInternAtom(win->display, "WM_DELETE_WINDOW", False);
- XSetWMProtocols(win->display, win->window, &wm_delete, 1);
-
- return true;
-}
-
-POAPI void
-p_window_close(P_Window *win)
-{
- if (!win) return;
-
- if (win->image) {
- // XDestroyImage(win->image);
- win->image = NULL;
- }
-
- if (win->display) {
- Display *dpy = win->display;
- Window w = win->window;
- win->display = NULL;
- win->window = 0;
-
- if (w) {
- XDestroyWindow(dpy, w);
- }
- XSync(dpy, False);
- }
-}
-
-POAPI bool
-p_window_is_open(P_Window *win)
-{
- return win && win->display != NULL;
-}
-
-POAPI void
-p_window_size(P_Window *win, int *window_width, int *window_height)
-{
- if (!win) return;
-
- XWindowAttributes attr;
- XGetWindowAttributes(win->display, win->window, &attr);
- *window_width = attr.width;
- *window_height = attr.height;
-
- win->width = attr.width;
- win->height = attr.height;
-}
-
-POAPI void
-p_window_draw(P_Window *win, u32 *pixels, int width, int height)
-{
- int screen = win->screen;
-
- win->image = XCreateImage(
- win->display,
- DefaultVisual(win->display, screen),
- DefaultDepth(win->display, screen),
- ZPixmap,
- 0,
- (char*)pixels,
- width,
- height,
- 32,
- width * 4
- );
-
- int window_width, window_height;
- p_window_size(win, &window_width, &window_height);
-
- XPutImage(
- win->display,
- win->window,
- win->gc,
- win->image,
- 0, 0,
- 0, 0,
- win->width,
- win->height);
-
- XFlush(win->display);
-}
-
-POAPI bool
-p_window_poll_event(P_Window *win, P_Event *ev)
-{
- if (XPending(win->display)) {
- static XEvent xev;
- XNextEvent(win->display, &xev);
-
- switch (xev.type) {
-
- case KeyPress:
- ev->type = P_EVENT_KEY_DOWN;
- ev->key.key = _x11_translate_keycode(xev);
- return true;
-
- case KeyRelease:
- ev->type = P_EVENT_KEY_UP;
- ev->key.key = _x11_translate_keycode(xev);
- return true;
-
- case ConfigureNotify:
- ev->type = P_EVENT_WINDOW_RESIZE;
- ev->resize.width = xev.xconfigure.width;
- ev->resize.height = xev.xconfigure.height;
- return true;
-
- case ClientMessage:
- if ((Atom)xev.xclient.data.l[0] ==
- XInternAtom(win->display, "WM_DELETE_WINDOW", False)) {
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
- }
- break;
-
- case MotionNotify:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_MOVED;
- ev->pointer.button = 0;
- ev->pointer.x = xev.xmotion.x;
- ev->pointer.y = xev.xmotion.y;
- return true;
-
- case ButtonPress:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = xev.xbutton.button; /* 1=LMB, 2=MMB, 3=RMB */
- ev->pointer.x = xev.xbutton.x;
- ev->pointer.y = xev.xbutton.y;
- return true;
-
- case ButtonRelease:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = xev.xbutton.button;
- ev->pointer.x = xev.xbutton.x;
- ev->pointer.y = xev.xbutton.y;
- return true;
- }
- }
-
- ev->type = P_EVENT_NONE;
- return false;
-}
-
-POAPI void
-p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc)
-{
- pa_sample_spec ss = {
- .format = PA_SAMPLE_S16LE,
- .rate = sample_rate,
- .channels = channels,
- };
-
- int error;
- p_ctx.audio_stream = pa_simple_new(
- NULL,
- name,
- PA_STREAM_PLAYBACK,
- NULL,
- desc,
- &ss,
- NULL,
- NULL,
- &error
- );
-
- if (!p_ctx.audio_stream) {
- PERROR("PulseAudio init failed: %s\n", pa_strerror(error));
- exit(1);
- }
-}
-
-POAPI void
-p_audio_quit()
-{
- if (p_ctx.audio_stream) {
- pa_simple_free(p_ctx.audio_stream);
- p_ctx.audio_stream = NULL;
- }
-}
-
-POAPI void
-p_audio_write(const i16 *samples, usize count)
-{
- if (!p_ctx.audio_stream) return;
-
- int error;
- if (pa_simple_write(p_ctx.audio_stream, samples, count * sizeof(i16), &error) < 0) {
- PERROR("PulseAudio write failed: %s\n", pa_strerror(error));
- }
-
- pa_simple_drain(p_ctx.audio_stream, &error);
-}
-
-#ifdef P_MODULE_VULKAN
-
-#ifndef VK_USE_PLATFORM_XLIB_KHR
-#define VK_USE_PLATFORM_XLIB_KHR
-#endif
-#include <vulkan/vulkan_xlib.h>
-
-POAPI char**
-p_vulkan_get_extensions()
-{
- char **darr = NULL;
- p_darray_push(darr, "VK_KHR_surface");
- p_darray_push(darr, "VK_KHR_xcb_surface");
- p_darray_push(darr, "VK_KHR_xlib_surface");
- return darr;
-}
-
-POAPI bool
-p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface)
-{
- if (!instance || !window || !window->display || !window->window || !out_surface) {
- return false;
- }
-
- VkXlibSurfaceCreateInfoKHR create_info = {0};
- create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = NULL;
- create_info.flags = 0;
- create_info.dpy = window->display;
- create_info.window = window->window;
-
- VkResult result = vkCreateXlibSurfaceKHR(instance, &create_info, allocator, out_surface);
-
- return (result == VK_SUCCESS);
-}
-#endif
diff --git a/Podium/p_platform_win32.c b/Podium/p_platform_win32.c
deleted file mode 100644
index 556b43b..0000000
--- a/Podium/p_platform_win32.c
+++ /dev/null
@@ -1,402 +0,0 @@
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <mmsystem.h>
-#include <xinput.h> /* gamepad support */
-
-typedef struct {
- HWAVEOUT wave_out;
- WAVEHDR wave_header;
-} P_Win32Ctx;
-
-struct P_Window_Impl {
- HWND hwnd;
- HDC hdc;
- BITMAPINFO bitmap_info;
- int width;
- int height;
- bool closed;
-};
-
-P_Win32Ctx p_ctx = {0};
-
-static inline P_KeyCode
-_win32_translate_vkey(WPARAM vk)
-{
- switch (vk) {
- case VK_LEFT: return P_KEY_LEFT;
- case VK_RIGHT: return P_KEY_RIGHT;
- case VK_UP: return P_KEY_UP;
- case VK_DOWN: return P_KEY_DOWN;
- case VK_SPACE: return P_KEY_SPACE;
- case VK_ESCAPE: return P_KEY_ESCAPE;
- case VK_RETURN: return P_KEY_ENTER;
- case 'A': return P_KEY_A;
- case 'B': return P_KEY_B;
- case 'C': return P_KEY_C;
- case 'D': return P_KEY_D;
- case 'E': return P_KEY_E;
- case 'F': return P_KEY_F;
- case 'G': return P_KEY_G;
- case 'H': return P_KEY_H;
- case 'I': return P_KEY_I;
- case 'J': return P_KEY_J;
- case 'K': return P_KEY_K;
- case 'L': return P_KEY_L;
- case 'M': return P_KEY_M;
- case 'N': return P_KEY_N;
- case 'O': return P_KEY_O;
- case 'P': return P_KEY_P;
- case 'Q': return P_KEY_Q;
- case 'R': return P_KEY_R;
- case 'S': return P_KEY_S;
- case 'T': return P_KEY_T;
- case 'U': return P_KEY_U;
- case 'V': return P_KEY_V;
- case 'W': return P_KEY_W;
- case 'X': return P_KEY_X;
- case 'Y': return P_KEY_Y;
- case 'Z': return P_KEY_Z;
- default: return P_KEY_UNKNOWN;
- }
-}
-
-POAPI u64
-p_get_time(void)
-{
- LARGE_INTEGER count, freq;
- QueryPerformanceCounter(&count);
- QueryPerformanceFrequency(&freq);
- return (u64)((count.QuadPart * 1000000000ULL) / freq.QuadPart);
-}
-
-POAPI void
-p_sleep_ns(i64 ns)
-{
- /* windows sleep is millisecond-based........ */
- Sleep((DWORD)(ns / 1000000));
-}
-
-POAPI void
-p_stdout(void *msg, usize bytes)
-{
- HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD bytes_written;
- WriteFile(stdout_handle, msg, bytes, &bytes_written, NULL);
-}
-
-POAPI bool
-p_file_exists(const char *path)
-{
- DWORD attr = GetFileAttributesA(path);
- return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY));
-}
-
-POAPI usize
-p_file_size(const char *path)
-{
- WIN32_FILE_ATTRIBUTE_DATA data;
- if (GetFileAttributesExA(path, GetFileExInfoStandard, &data)) {
- return data.nFileSizeLow;
- }
- return 0;
-}
-
-PODEF void
-p_file_load(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- HANDLE file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (file != INVALID_HANDLE_VALUE) {
- DWORD bytes_read;
- ReadFile(file, buf_ptr, buf_size, &bytes_read, NULL);
- CloseHandle(file);
- }
-}
-
-PODEF void
-p_file_write(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- HANDLE file = CreateFileA(path, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE) {
- DWORD bytes_written;
- WriteFile(file, buf_ptr, buf_size, &bytes_written, NULL);
- CloseHandle(file);
- }
-}
-
-static LRESULT CALLBACK
-_win32_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
- P_Window *win = (P_Window*)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
- switch (msg) {
- case WM_CLOSE:
- /* Handled in poll_event; mark as closed */
- if (win) win->closed = true;
- return 0;
- }
- return DefWindowProcA(hwnd, msg, wparam, lparam);
-}
-
-POAPI bool
-p_window_open(P_Window *win, int width, int height, const char *title)
-{
- HINSTANCE instance = GetModuleHandleA(NULL);
-
- WNDCLASSA wc = {0};
- wc.lpfnWndProc = _win32_wnd_proc;
- wc.hInstance = instance;
- wc.lpszClassName = "P_Window_Class";
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-
- RegisterClassA(&wc);
-
- win->hwnd = CreateWindowExA(0, wc.lpszClassName, title,
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT, width, height,
- NULL, NULL, instance, NULL);
-
- if (!win->hwnd) return false;
-
- SetWindowLongPtrA(win->hwnd, GWLP_USERDATA, (LONG_PTR)win);
- win->hdc = GetDC(win->hwnd);
- win->width = width;
- win->height = height;
- win->closed = false;
-
- return true;
-}
-
-POAPI void
-p_window_close(P_Window *win)
-{
- if (!win) return;
- if (win->hdc) ReleaseDC(win->hwnd, win->hdc);
- if (win->hwnd) DestroyWindow(win->hwnd);
- win->hdc = NULL;
- win->hwnd = NULL;
-}
-
-POAPI bool
-p_window_is_open(P_Window *win)
-{
- return win && win->hwnd != NULL;
-}
-
-POAPI void
-p_window_size(P_Window *win, int *window_width, int *window_height)
-{
- if (!win) return;
- RECT rect;
- GetClientRect(win->hwnd, &rect);
- *window_width = rect.right - rect.left;
- *window_height = rect.bottom - rect.top;
- win->width = *window_width;
- win->height = *window_height;
-}
-
-POAPI void
-p_window_draw(P_Window *win, u32 *pixels, int width, int height)
-{
- BITMAPINFO bmi = {0};
- bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = -height; /* top-down */
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
-
- StretchDIBits(win->hdc,
- 0, 0, win->width, win->height,
- 0, 0, width, height,
- pixels, &bmi, DIB_RGB_COLORS, SRCCOPY);
-}
-
-POAPI bool
-p_window_poll_event(P_Window *win, P_Event *ev)
-{
- if (win->closed) {
- win->closed = false;
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
- }
-
- MSG msg;
- while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
- switch (msg.message) {
-
- case WM_QUIT:
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
-
- /* Key press */
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- ev->type = P_EVENT_KEY_DOWN;
- ev->key.key = _win32_translate_vkey(msg.wParam);
- return true;
-
- /* Key release */
- case WM_KEYUP:
- case WM_SYSKEYUP:
- ev->type = P_EVENT_KEY_UP;
- ev->key.key = _win32_translate_vkey(msg.wParam);
- return true;
-
- /* Mouse movement */
- case WM_MOUSEMOVE:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_MOVED;
- ev->pointer.button = 0;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- /* Mouse buttons */
- case WM_LBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 1; /* 1 = LMB, matching X11 convention */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_LBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 1;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_RBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 3; /* 3 = RMB */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_RBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 3;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_MBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 2; /* 2 = MMB */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_MBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 2;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- /* Window resize */
- case WM_SIZE:
- ev->type = P_EVENT_WINDOW_RESIZE;
- ev->resize.width = (u32)(msg.lParam & 0xFFFF);
- ev->resize.height = (u32)((msg.lParam >> 16) & 0xFFFF);
- win->width = ev->resize.width;
- win->height = ev->resize.height;
- return true;
-
- default:
- TranslateMessage(&msg);
- DispatchMessageA(&msg);
- break;
- }
- }
-
- ev->type = P_EVENT_NONE;
- return false;
-}
-
-
-POAPI void
-p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc)
-{
- (void)name; (void)desc; /* WinMM doesn't use a stream name */
-
- WAVEFORMATEX wfx = {0};
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = channels;
- wfx.nSamplesPerSec = sample_rate;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-
- if (waveOutOpen(&p_ctx.wave_out, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
- exit(1);
- }
-}
-
-POAPI void
-p_audio_quit()
-{
- if (p_ctx.wave_out) {
- waveOutReset(p_ctx.wave_out);
- waveOutClose(p_ctx.wave_out);
- p_ctx.wave_out = NULL;
- }
-}
-
-POAPI void
-p_audio_write(const i16 *samples, usize count)
-{
- if (!p_ctx.wave_out) return;
-
- WAVEHDR header = {0};
- header.lpData = (LPSTR)samples;
- header.dwBufferLength = (DWORD)(count * sizeof(i16));
-
- waveOutPrepareHeader(p_ctx.wave_out, &header, sizeof(WAVEHDR));
- waveOutWrite(p_ctx.wave_out, &header, sizeof(WAVEHDR));
-
- /* wait for playback to finish (synchronous, mirrors pa_simple_drain) */
- while (!(header.dwFlags & WHDR_DONE)) Sleep(1);
-
- waveOutUnprepareHeader(p_ctx.wave_out, &header, sizeof(WAVEHDR));
-}
-
-#ifdef P_MODULE_VULKAN
-
-#ifndef VK_USE_PLATFORM_WIN32_KHR
-#define VK_USE_PLATFORM_WIN32_KHR
-#endif
-#include <vulkan/vulkan_win32.h>
-
-POAPI char**
-p_vulkan_get_extensions()
-{
- char **darr = NULL;
- p_darray_push(darr, "VK_KHR_surface");
- p_darray_push(darr, "VK_KHR_win32_surface");
- return darr;
-}
-
-POAPI bool
-p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface)
-{
- if (!instance || !window || !window->hwnd || !out_surface) {
- return false;
- }
-
- VkWin32SurfaceCreateInfoKHR create_info = {0};
- create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = NULL;
- create_info.flags = 0;
- create_info.hwnd = window->hwnd;
- create_info.hinstance = GetModuleHandleA(NULL);
-
- VkResult result = vkCreateWin32SurfaceKHR(instance, &create_info, allocator, out_surface);
- return (result == VK_SUCCESS);
-}
-#endif
diff --git a/Podium/p_string.c b/Podium/p_string.c
deleted file mode 100644
index 73cb0ea..0000000
--- a/Podium/p_string.c
+++ /dev/null
@@ -1,201 +0,0 @@
-PODEF char*
-p_find_char(char *buf, char needle)
-{
- while (buf && *buf != needle) buf++;
- return buf;
-}
-
-PODEF bool
-p_strcmp(const char *a, const char *b)
-{
- if (p_strlen(a) != p_strlen(b))
- return false;
-
- while (a && b && *a != '\0') {
- if (*(a++) != *(b++)) return false;
- }
-
- return true;
-}
-
-PODEF int
-p_strlen(const char *a)
-{
- int i = 0;
- while (*a++ != '\0') i++;
- return i;
-}
-
-PODEF int
-p_strtoi(const char *str)
-{
- int res = 0;
-
- while (*str) {
- if (*str >= '0' && *str <= '9') {
- res = res * 10 + (*str - '0');
- } else {
- return res;
- }
- str++;
- }
-
- return res;
-}
-
-PODEF char*
-p_strtok(const char *str, char c)
-{
- while (*str != c && *str++ != '\0');
- return (*str == c) ? (char*) ++str : 0;
-}
-
-PODEF P_StringView
-p_strview(const char *cstr)
-{
- P_StringView sv = {0};
- sv.cstr = cstr;
- sv.len = p_strlen(cstr);
- return sv;
-}
-
-PODEF void
-p_strview_chop_left(P_StringView *sv, u32 n)
-{
- if (n > sv->len) n = sv->len;
- sv->cstr += n;
- sv->len -= n;
-}
-
-PODEF void
-p_strview_chop_right(P_StringView *sv, u32 n)
-{
- if (n > sv->len) n = sv->len;
- sv->len -= n;
-}
-
-PODEF P_StringView
-p_strview_chop_delim(P_StringView *sv, char delim)
-{
- u32 i = 0;
- while (i < sv->len && sv->cstr[i] != delim) {
- i++;
- }
-
- P_StringView tok;
- if (i < sv->len) {
- tok.cstr = sv->cstr;
- tok.len = i;
- p_strview_chop_left(sv, i + 1);
- return tok;
- }
-
- tok = *sv;
- p_strview_chop_left(sv, sv->len);
- return tok;
-}
-
-PODEF P_StringView
-p_strview_chop_type(P_StringView *sv, int(*istype)(int))
-{
- u32 i = 0;
- while (i < sv->len && istype(sv->cstr[i])) {
- i++;
- }
-
- P_StringView tok;
- if (i < sv->len) {
- tok.cstr = sv->cstr;
- tok.len = i;
- p_strview_chop_left(sv, i + 1);
- return tok;
- }
-
- tok = *sv;
- p_strview_chop_left(sv, sv->len);
- return tok;
-}
-
-
-PODEF void
-p_strview_trim_left(P_StringView *sv)
-{
- while (sv->len > 0 && p_is_space(sv->cstr[0])) {
- p_strview_chop_left(sv, 1);
- }
-}
-
-PODEF void
-p_strview_trim_right(P_StringView *sv)
-{
- while (sv->len > 0 && p_is_space(sv->cstr[sv->len-1])) {
- p_strview_chop_right(sv, 1);
- }
-}
-
-PODEF void
-p_strview_trim(P_StringView *sv)
-{
- p_strview_trim_left(sv);
- p_strview_trim_right(sv);
-}
-
-PODEF int
-p_is_space(int c)
-{
- /* Checks for: space, form feed (\f), line feed (\n),
- * carriage return (\r), horizontal tab (\t), vertical tab (\v) */
- return (c == ' ' || (c >= '\t' && c <= '\r'));
-}
-
-PODEF int
-p_is_digit(int c)
-{
- return (c >= '0' && c <= '9');
-}
-
-PODEF int
-p_is_alpha(int c)
-{
- return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
-}
-
-PODEF int
-p_is_alnum(int c)
-{
- return (p_is_alpha(c) || p_is_digit(c));
-}
-
-PODEF int
-p_is_hex(int c)
-{
- return (p_is_digit(c) ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F'));
-}
-
-PODEF int
-p_is_upper(int c)
-{
- return (c >= 'A' && c <= 'Z');
-}
-
-PODEF int
-p_is_lower(int c)
-{
- return (c >= 'a' && c <= 'z');
-}
-
-PODEF int
-p_to_lower(int c)
-{
- if (p_is_upper(c)) return (c + ('a' - 'A'));
- return c;
-}
-
-PODEF int
-p_to_upper(int c)
-{
- if (p_is_lower(c)) return (c - ('a' - 'A'));
- return c;
-}
diff --git a/Podium/p_string.h b/Podium/p_string.h
deleted file mode 100644
index 5c4077b..0000000
--- a/Podium/p_string.h
+++ /dev/null
@@ -1,38 +0,0 @@
-typedef struct {
- const char *cstr;
- u32 len;
-} P_StringView;
-
-typedef struct {
- P_StringView sv;
-} P_StringBuilder;
-
-/* Classic C string functions */
-PODEF char* p_find_char(char *buf, char needle);
-PODEF bool p_strcmp(const char *a, const char *b);
-PODEF int p_strlen(const char *a);
-PODEF int p_strtoi(const char *str);
-PODEF char* p_strtok(const char *str, char c);
-
-/* String views */
-PODEF P_StringView p_strview(const char *cstr);
-PODEF void p_strview_chop_left(P_StringView *sv, u32 n);
-PODEF void p_strview_chop_right(P_StringView *sv, u32 n);
-PODEF P_StringView p_strview_chop_delim(P_StringView *sv, char delim);
-PODEF P_StringView p_strview_chop_type(P_StringView *sv, int(*istype)(int));
-PODEF void p_strview_trim_left(P_StringView *sv);
-PODEF void p_strview_trim_right(P_StringView *sv);
-PODEF void p_strview_trim(P_StringView *sv);
-
-/* Classification */
-PODEF int p_is_space(int c);
-PODEF int p_is_digit(int c);
-PODEF int p_is_alpha(int c);
-PODEF int p_is_alnum(int c);
-PODEF int p_is_upper(int c);
-PODEF int p_is_lower(int c);
-PODEF int p_is_hex(int c);
-
-/* Transformation */
-PODEF int p_to_lower(int c);
-PODEF int p_to_upper(int c);
diff --git a/Podium/p_types.h b/Podium/p_types.h
deleted file mode 100644
index 1da81be..0000000
--- a/Podium/p_types.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef _PODIUM_TYPES_
-#define _PODIUM_TYPES_
-
-#define NANOS_PER_SEC (1000*1000*1000)
-#define P_PI_HALF 1.57079632679f
-#define P_PI 3.14159265f
-#define P_PI2 6.28318531f
-#define P_PI_POW2 9.86960440f
-
-#ifdef NDEBUG
- #define assert(x) ((void)0)
-#else
- #ifndef assert
- #define assert(x) \
- do { \
- if (!(x)) { \
- __builtin_trap(); \
- } \
- } while (0)
- #endif
-#endif
-
-#ifndef BUFSIZ
- #define BUFSIZ 8192
-#endif
-
-typedef unsigned char u8;
-typedef signed char i8;
-typedef unsigned short u16;
-typedef short i16;
-typedef unsigned int u32;
-typedef int i32;
-typedef unsigned long long u64;
-typedef long long i64;
-typedef float f32;
-typedef double f64;
-
-#ifndef __cplusplus
-#define bool _Bool
-#define false 0
-#define true 1
-#endif
-
-/* C++ uses static_assert, C11 uses _Static_assert */
-#ifdef __cplusplus
- #define STATIC_ASSERT static_assert
-#else
- #define STATIC_ASSERT _Static_assert
-#endif
-
-STATIC_ASSERT(sizeof(u8) == 1, "u8 must be 1 byte");
-STATIC_ASSERT(sizeof(u16) == 2, "u16 must be 2 bytes");
-STATIC_ASSERT(sizeof(u32) == 4, "u32 must be 4 bytes");
-STATIC_ASSERT(sizeof(u64) == 8, "u64 must be 8 bytes");
-
-STATIC_ASSERT(sizeof(i8) == 1, "i8 must be 1 byte");
-STATIC_ASSERT(sizeof(i16) == 2, "i16 must be 2 bytes");
-STATIC_ASSERT(sizeof(i32) == 4, "i32 must be 4 bytes");
-STATIC_ASSERT(sizeof(i64) == 8, "i64 must be 8 bytes");
-
-STATIC_ASSERT(sizeof(f32) == 4, "f32 must be 4 bytes");
-STATIC_ASSERT(sizeof(f64) == 8, "f64 must be 8 bytes");
-#define U8_MAX 255
-#define U16_MAX 65535
-#define U32_MAX 4294967295
-
-/* Architecture specific sizing */
-#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64)
- typedef u64 usize;
- typedef u64 uintptr;
- typedef u32 idx;
- STATIC_ASSERT(sizeof(usize) == 8, "usize must be 8 bytes on 64-bit");
-#else
- typedef u32 usize;
- typedef u32 uintptr;
- typedef u16 idx;
- STATIC_ASSERT(sizeof(usize) == 4, "usize must be 4 bytes on 32-bit");
-#endif
-
-#ifndef NULL
- #ifdef __cplusplus
- #define NULL 0
- #else
- #define NULL ((void*)0)
- #endif
-#endif
-
-#endif // _PODIUM_TYPES_
diff --git a/Podium/podium.c b/Podium/podium.c
deleted file mode 100644
index 306e337..0000000
--- a/Podium/podium.c
+++ /dev/null
@@ -1 +0,0 @@
-#define PODIUM_IMPLEMENTATION
diff --git a/Podium/podium.h b/Podium/podium.h
deleted file mode 100644
index d94b4e5..0000000
--- a/Podium/podium.h
+++ /dev/null
@@ -1,2269 +0,0 @@
-/* ===========================================================================
- * PODIUM - Kitchen Sink - Copyright (c) 2026 Vasco Alves
- *
- * ---------------------------------------------------------------------------
- * To stand on the shoulders of giants...
- * Giants must stand still!"
- * - Eskil Steenberg - "You should finish your software" – BSC 2025
- * ---------------------------------------------------------------------------
- *
- * PREFIX: P_ (types) or p_ (functions & variables)
- *
- * COMPILE TIME FLAGS
- * | Name | Description |
- * |-----------------|---------------------------------------------------------|
- * | PODIUM_WIN32 | Used to explicitly compile for Windows. |
- * | PODIUM_LINUX | Used to explicitly compile for Linux and FreeBSD. |
- *
- * MODULES
- * | Name | Description |
- * |-----------------|---------------------------------------------------------|
- * | P_MODULE_VULKAN | Gives access to vulkan related utilities. |
- * | P_MODULE_STRING | Include string manipulation utilities. |
- * | P_MODULE_MATH | Trigonometry and linear algebra functions. |
- * | P_MODULE_ALLOC | Memory allocators: Arena, Stack & Pool. |
- *
- * =========================================================================== */
-
-#ifndef _PODIUM_H_
-#define _PODIUM_H_
-
-#define PODIUM_MAJOR "0" // needs more revisions and use to reach 1.0 status
-#define PODIUM_MINOR "2" // vulkan module
-#define PODIUM_PATCH "2" // gamepad
-
-#define POAPI static inline
-#define PODEF static inline
-
-/*
- * Auto-detect platforms.
- */
-
-/* Windows */
-#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__)
- #define PODIUM_WIN32
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
-/* Apple */
-#elif defined(__APPLE__) || defined(__MACH__)
- #include <TargetConditionals.h>
- #define PODIUM_APPLE
- #if TARGET_OS_IPHONE
- #define PODIUM_IOS
- #else
- #define PODIUM_MACOS
- #endif
-/* Linux / BSD */
-#elif defined(__linux__) || defined(__FreeBSD__)
- #define PODIUM_LINUX
- #ifndef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 200112L
- #endif
-#endif
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <string.h> /* memcpy */
-#include <stdio.h> /* vsnprintf */
-
-/*
- * NOTE: The <REPLACE> comments are used by the build
- * script to know what includes to inline into the
- * final single header file!
- */
-
-/* --- Start of p_types.h --- */
-#ifndef _PODIUM_TYPES_
-#define _PODIUM_TYPES_
-
-#define NANOS_PER_SEC (1000*1000*1000)
-#define P_PI_HALF 1.57079632679f
-#define P_PI 3.14159265f
-#define P_PI2 6.28318531f
-#define P_PI_POW2 9.86960440f
-
-#ifdef NDEBUG
- #define assert(x) ((void)0)
-#else
- #ifndef assert
- #define assert(x) \
- do { \
- if (!(x)) { \
- __builtin_trap(); \
- } \
- } while (0)
- #endif
-#endif
-
-#ifndef BUFSIZ
- #define BUFSIZ 8192
-#endif
-
-typedef unsigned char u8;
-typedef signed char i8;
-typedef unsigned short u16;
-typedef short i16;
-typedef unsigned int u32;
-typedef int i32;
-typedef unsigned long long u64;
-typedef long long i64;
-typedef float f32;
-typedef double f64;
-
-#ifndef __cplusplus
-#define bool _Bool
-#define false 0
-#define true 1
-#endif
-
-/* C++ uses static_assert, C11 uses _Static_assert */
-#ifdef __cplusplus
- #define STATIC_ASSERT static_assert
-#else
- #define STATIC_ASSERT _Static_assert
-#endif
-
-STATIC_ASSERT(sizeof(u8) == 1, "u8 must be 1 byte");
-STATIC_ASSERT(sizeof(u16) == 2, "u16 must be 2 bytes");
-STATIC_ASSERT(sizeof(u32) == 4, "u32 must be 4 bytes");
-STATIC_ASSERT(sizeof(u64) == 8, "u64 must be 8 bytes");
-
-STATIC_ASSERT(sizeof(i8) == 1, "i8 must be 1 byte");
-STATIC_ASSERT(sizeof(i16) == 2, "i16 must be 2 bytes");
-STATIC_ASSERT(sizeof(i32) == 4, "i32 must be 4 bytes");
-STATIC_ASSERT(sizeof(i64) == 8, "i64 must be 8 bytes");
-
-STATIC_ASSERT(sizeof(f32) == 4, "f32 must be 4 bytes");
-STATIC_ASSERT(sizeof(f64) == 8, "f64 must be 8 bytes");
-#define U8_MAX 255
-#define U16_MAX 65535
-#define U32_MAX 4294967295
-
-/* Architecture specific sizing */
-#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64)
- typedef u64 usize;
- typedef u64 uintptr;
- typedef u32 idx;
- STATIC_ASSERT(sizeof(usize) == 8, "usize must be 8 bytes on 64-bit");
-#else
- typedef u32 usize;
- typedef u32 uintptr;
- typedef u16 idx;
- STATIC_ASSERT(sizeof(usize) == 4, "usize must be 4 bytes on 32-bit");
-#endif
-
-#ifndef NULL
- #ifdef __cplusplus
- #define NULL 0
- #else
- #define NULL ((void*)0)
- #endif
-#endif
-
-#endif // _PODIUM_TYPES_
-/* --- End of p_types.h --- */
-/* --- Start of p_log.h --- */
-/*
- * Logging!
- */
-
-#include <stdlib.h>
-
-#ifdef DEBUG
-#define LOG_DEBUG(...) PRINTF(__VA_ARGS__)
-#else
-#define LOG_DEBUG(...) ((void)0)
-#endif
-
-/* fatal and error always enabled */
-#define PFATAL(message, ...) p_log_printf(P_LOG_LEVEL_FATAL, message, ##__VA_ARGS__)
-#define PERROR(message, ...) p_log_printf(P_LOG_LEVEL_ERROR, message, ##__VA_ARGS__)
-
-/* warn and info enabled by default but can be disabled */
-#define P_LOG_WARN_ENABLED 1
-#define P_LOG_INFO_ENABLED 1
-
-#if P_LOG_WARN_ENABLED == 1
-#define PWARN(message, ...) p_log_printf(P_LOG_LEVEL_WARN, message, ##__VA_ARGS__)
-#else
-#define PWARN(message, ...)
-#endif
-
-#if P_LOG_INFO_ENABLED == 1
-#define PINFO(message, ...) p_log_printf(P_LOG_LEVEL_INFO, message, ##__VA_ARGS__)
-#else
-#define PINFO(message, ...)
-#endif
-
-#if P_LOG_DEBUG_ENABLED == 1
-#define PDEBUG(message, ...) p_log_printf(P_LOG_LEVEL_DEBUG, message, ##__VA_ARGS__)
-#else
-#define PDEBUG(message, ...)
-#endif
-
-#if P_LOG_TRACE_ENABLED == 1
-#define PTRACE(message, ...) p_log_printf(P_LOG_LEVEL_TRACE, message, ##__VA_ARGS__)
-#else
-#define PTRACE(message, ...)
-#endif
-
-typedef enum P_Log_Level {
- P_LOG_LEVEL_FATAL = 0,
- P_LOG_LEVEL_ERROR,
- P_LOG_LEVEL_WARN,
- P_LOG_LEVEL_INFO,
- P_LOG_LEVEL_DEBUG,
- P_LOG_LEVEL_TRACE,
- P_COUNT_LOG_LEVEL
-} P_Log_Level;
-
-#define P_PREFIX_LEN 7
-static const char *p_prefix[P_COUNT_LOG_LEVEL] = {
- [P_LOG_LEVEL_FATAL] = "[FATAL]",
- [P_LOG_LEVEL_ERROR] = "[ERROR]",
- [P_LOG_LEVEL_WARN] = "[WARNI]",
- [P_LOG_LEVEL_INFO] = "[INFOR]",
- [P_LOG_LEVEL_DEBUG] = "[DEBUG]",
- [P_LOG_LEVEL_TRACE] = "[TRACE]",
-};
-
-#define P_MAX_ALLOCS 512
-
-typedef struct P_DebugMemoryInfo {
- void *ptr;
- size_t size;
- const char *file;
- const char *func;
- int line;
-} P_DebugMemoryInfo;
-
-static uint64_t p_alloc_count = 0;
-static P_DebugMemoryInfo p_ptr_array[P_MAX_ALLOCS];
-
-static inline void *
-p_debug_malloc_impl(size_t size, const char *file, int line, const char *func)
-{
- void *ptr = malloc(size);
- printf("[ALLOC] %p (%zu bytes) -> %s:%d %s()\n", ptr, size, file, line, func);
-
- if (ptr) {
- if (p_alloc_count < P_MAX_ALLOCS) {
- p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){
- .ptr = ptr,
- .size = size,
- .file = file,
- .func = func,
- .line = line
- };
- } else {
- fprintf(stderr, "[ERROR] Debug allocator tracking capacity (%d) exceeded!\n", P_MAX_ALLOCS);
- }
- }
- return ptr;
-}
-
-static inline void
-p_debug_free_impl(void *ptr, const char *file, int line, const char *func)
-{
- printf("[FREE] %p -> %s:%d %s()\n", ptr, file, line, func);
-
- if (!ptr) return; // Standard C allows free(NULL)
-
- bool found = false;
- uint64_t index = 0;
-
- /* Find allocation metadata */
- for (index = 0; index < p_alloc_count; ++index) {
- if (p_ptr_array[index].ptr == ptr) {
- found = true;
- break;
- }
- }
-
- if (found) {
- /* Shift array left to remove tracked struct */
- for (uint64_t j = index; j < p_alloc_count - 1; ++j) {
- p_ptr_array[j] = p_ptr_array[j + 1];
- }
- p_alloc_count--;
- } else {
- fprintf(stderr, "[WARNING] Attempted to free untracked/double-freed pointer %p at %s:%d %s()\n",
- ptr, file, line, func);
- }
-
- free(ptr);
-}
-
-static inline void *
-p_debug_realloc_impl(void *ptr, size_t size, const char *file, int line, const char *func)
-{
- if (!ptr) {
- return p_debug_malloc_impl(size, file, line, func);
- }
- if (size == 0) {
- p_debug_free_impl(ptr, file, line, func);
- return NULL;
- }
-
- void *new_ptr = realloc(ptr, size);
- printf("[REALLOC] %p -> %p (%zu bytes) -> %s:%d %s()\n", ptr, new_ptr, size, file, line, func);
-
- if (new_ptr) {
- bool found = false;
- for (uint64_t i = 0; i < p_alloc_count; ++i) {
- if (p_ptr_array[i].ptr == ptr) {
- p_ptr_array[i].ptr = new_ptr;
- p_ptr_array[i].size = size;
- p_ptr_array[i].file = file;
- p_ptr_array[i].line = line;
- p_ptr_array[i].func = func;
- found = true;
- break;
- }
- }
- if (!found) {
- if (p_alloc_count < P_MAX_ALLOCS) {
- p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){
- .ptr = new_ptr,
- .size = size,
- .file = file,
- .func = func,
- .line = line
- };
- }
- }
- }
- return new_ptr;
-}
-
-static void
-p_debug_memory_report(void)
-{
- printf("\n==================== MEMORY REPORT ====================\n");
- printf("Remaining unfreed allocations: %lu\n", (unsigned long)p_alloc_count);
-
- for (uint64_t i = 0; i < p_alloc_count; ++i) {
- P_DebugMemoryInfo *info = &p_ptr_array[i];
- printf("[LEAK] %p (%zu bytes) allocated at %s:%d in %s()\n",
- info->ptr, info->size, info->file, info->line, info->func);
- }
- printf("=======================================================\n");
-}
-/* --- End of p_log.h --- */
-/* --- Start of p_ds.h --- */
-#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
-#define ARRAY_GROW_FACTOR 2
-
-typedef struct {
- u32 size;
- u32 capacity;
-} DynamicArrayHeader;
-
-#define DARRAY_INIT_CAPACITY 64
-#define p_darray_push(array, var) \
- do { \
- if (array == NULL) { \
- DynamicArrayHeader *header = \
- malloc(DARRAY_INIT_CAPACITY * sizeof *array + sizeof *header); \
- header->size = 0; \
- header->capacity = DARRAY_INIT_CAPACITY; \
- array = (void *)(header + 1); \
- } \
- DynamicArrayHeader *header = (DynamicArrayHeader *)(array) - 1; \
- if (header->size >= header->capacity - 1) { \
- unsigned long new_capacity = header->capacity * 2; \
- DynamicArrayHeader *new_header = \
- realloc(header, new_capacity * sizeof *array + sizeof *header); \
- if (!new_header) \
- break; \
- header = new_header; \
- array = (void *)(header + 1); \
- header->capacity = new_capacity; \
- } \
- (array)[header->size++] = var; \
- } while (0)
-
-#define p_darray_len(array) ((array) ? ((DynamicArrayHeader *)(array) - 1)->size : 0)
-#define p_darray_destroy(array) \
-{ \
- free((DynamicArrayHeader *)(array) - 1); \
-}
-
-#define p_darray_shrink(array) \
- do { \
- DynamicArrayHeader *header = (array) ? ((DynamicArrayHeader *)(array) - 1) : 0;\
- if (header) {\
- if (header->capacity > 4) {\
- unsigned long new_capacity = (header->capacity >> 1) + (header->capacity & 1); \
- void *new_header = realloc(header, new_capacity * sizeof *array + sizeof *header); \
- if (!new_header) break; \
- header = new_header; \
- array = (void *)(header + 1); \
- header->capacity = new_capacity; \
- }\
- }\
- } while (0)
-/* --- End of p_ds.h --- */
-
-/*
- * Main Platform Types (Keyboard, Events, Context, etc.)
- */
-
-typedef enum {
- P_KEYMOD_ALT = 0,
- P_KEYMOD_SHIFT,
- P_KEYMOD_CTRL,
- P_KEYMOD_CAPS,
-} P_KeyMod;
-
-typedef enum {
- P_KEY_UNKNOWN = 0,
- P_KEY_UP, P_KEY_DOWN, P_KEY_LEFT, P_KEY_RIGHT,
- P_KEY_SPACE, P_KEY_ESCAPE, P_KEY_ENTER,
- P_KEY_A, P_KEY_B, P_KEY_C, P_KEY_D, P_KEY_E, P_KEY_F, P_KEY_G, P_KEY_H, P_KEY_I,
- P_KEY_J, P_KEY_K, P_KEY_L, P_KEY_M, P_KEY_N, P_KEY_O, P_KEY_P, P_KEY_Q, P_KEY_R,
- P_KEY_S, P_KEY_T, P_KEY_U, P_KEY_V, P_KEY_W, P_KEY_X, P_KEY_Y, P_KEY_Z,
-} P_KeyCode;
-
-/* Platform event type */
-typedef enum {
- P_EVENT_NONE = 0,
- P_EVENT_KEY_DOWN,
- P_EVENT_KEY_UP,
- P_EVENT_WINDOW_CLOSE,
- P_EVENT_WINDOW_RESIZE,
- P_EVENT_POINTER,
- P_EVENT_CONTROLLER_CONNECTED,
- P_EVENT_CONTROLLER_DISCONNECTED,
-} P_EvenType;
-
-typedef enum {
- P_POINTER_MOVED = 0,
- P_POINTER_PRESSED,
- P_POINTER_RELEASED
-} P_PointerState;
-
-typedef struct {
- P_EvenType type;
- union {
- struct {P_KeyCode key; P_KeyMod mod; } key;
- struct { u32 width, height; } resize;
- struct { P_PointerState state; u32 button; u32 x, y; } pointer;
- };
-} P_Event;
-
-/*
- * Platform dependent functions to be implemented by each layer.
- */
-
-POAPI u64 p_get_time(void); // Get time in nanoseconds.
-POAPI void p_sleep_ns(i64 ns); // Sleep for nanoseconds.
-
-POAPI void p_stdout(void *msg, usize bytes); // Print buffer to stdout.
-PODEF void p_log_printf(P_Log_Level level, const char* src, ...); // Print buffer to stdout.
-
-
-POAPI void* p_file_alloc(const char *path, unsigned long *buf_size);
-POAPI bool p_file_exists(const char *path); // Check if file exists.
-POAPI usize p_file_size(const char *path); // Check file size.
-POAPI void p_file_load(const char *path, void *buf_ptr, unsigned long buf_size); // Load file to buffer.
-PODEF void p_file_write(const char *path, void *buf_ptr, unsigned long buf_size); // Write buffer to file.
-
-typedef struct P_Window_Impl P_Window;
-POAPI bool p_window_open(P_Window *win, int width, int height, const char *title); // Opens a window. Returns false on failure.
-POAPI void p_window_close(P_Window *win); // Close window.
-POAPI bool p_window_is_open(P_Window *win); // Check if window is open.
-POAPI void p_window_size(P_Window *win, int *window_width, int *window_height); // Get window size.
-POAPI void p_window_draw(P_Window *win, u32 *pixels, int width, int height); // Draw directly to the window's buffer. Normally much slower than using the GPU.
-POAPI bool p_window_poll_event(P_Window *win, P_Event *ev); // Returns true while there are events to poll. Write event data to a pointer.
-
-POAPI void p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc);
-POAPI void p_audio_quit();
-POAPI void p_audio_write(const i16 *samples, usize count);
-
-/*
- * The Vulkan Module is platform specific
- */
-
-#ifdef P_MODULE_VULKAN
-#include <vulkan/vulkan.h>
-POAPI char** p_vulkan_get_extensions();
-POAPI bool p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface);
-#endif
-
-/*
- * The Remaining Modules are PLATFORM INDEPENDENT!
- */
-
-#ifdef P_MODULE_STRING
-/* --- Start of p_string.h --- */
-typedef struct {
- const char *cstr;
- u32 len;
-} P_StringView;
-
-typedef struct {
- P_StringView sv;
-} P_StringBuilder;
-
-/* Classic C string functions */
-PODEF char* p_find_char(char *buf, char needle);
-PODEF bool p_strcmp(const char *a, const char *b);
-PODEF int p_strlen(const char *a);
-PODEF int p_strtoi(const char *str);
-PODEF char* p_strtok(const char *str, char c);
-
-/* String views */
-PODEF P_StringView p_strview(const char *cstr);
-PODEF void p_strview_chop_left(P_StringView *sv, u32 n);
-PODEF void p_strview_chop_right(P_StringView *sv, u32 n);
-PODEF P_StringView p_strview_chop_delim(P_StringView *sv, char delim);
-PODEF P_StringView p_strview_chop_type(P_StringView *sv, int(*istype)(int));
-PODEF void p_strview_trim_left(P_StringView *sv);
-PODEF void p_strview_trim_right(P_StringView *sv);
-PODEF void p_strview_trim(P_StringView *sv);
-
-/* Classification */
-PODEF int p_is_space(int c);
-PODEF int p_is_digit(int c);
-PODEF int p_is_alpha(int c);
-PODEF int p_is_alnum(int c);
-PODEF int p_is_upper(int c);
-PODEF int p_is_lower(int c);
-PODEF int p_is_hex(int c);
-
-/* Transformation */
-PODEF int p_to_lower(int c);
-PODEF int p_to_upper(int c);
-/* --- End of p_string.h --- */
-#endif
-
-#ifdef P_MODULE_MATH
-/* --- Start of p_math.h --- */
-typedef struct {int x, y; } Vec2i;
-typedef struct {float x, y; } Vec2f;
-typedef struct {float x, y, z; } Vec3f;
-typedef struct { float m[16];} P_Mat4; // column-major: m[col * 4 + row]
-PODEF int p_ceil(float x);
-PODEF float p_cosf(float x);
-PODEF float p_sinf(float x);
-
-PODEF Vec2f p_vec2f(float, float);
-PODEF Vec2f p_vec2f_add(Vec2f, Vec2f);
-PODEF float p_vec2f_cross(Vec2f, Vec2f);
-PODEF float p_vec2f_dot(Vec2f, Vec2f);
-PODEF Vec2f p_vec2f_mult(Vec2f a, float b);
-PODEF Vec2f p_vec2f_sub(Vec2f, Vec2f);
-PODEF Vec2i p_vec2i(float, float);
-PODEF Vec2i p_vec2i_add(Vec2i, Vec2i);
-PODEF float p_vec2i_cross(Vec2i, Vec2i);
-PODEF float p_vec2i_dot(Vec2i, Vec2i);
-PODEF Vec2i p_vec2i_mult(Vec2i a, float b);
-PODEF Vec2i p_vec2i_sub(Vec2i, Vec2i);
-
-PODEF Vec3f p_vec3f(float, float, float);
-
-PODEF P_Mat4 p_mat4_identity(void);
-PODEF P_Mat4 p_mat4_mul(P_Mat4 a, P_Mat4 b);
-PODEF P_Mat4 p_mat4_translate(Vec3f v);
-PODEF P_Mat4 p_mat4_translate_by(P_Mat4 m, Vec3f v);
-PODEF P_Mat4 p_mat4_rotate_x(float rad);
-PODEF P_Mat4 p_mat4_rotate_x_by(P_Mat4 m, float rad);
-PODEF P_Mat4 p_mat4_rotate_y(float rad);
-PODEF P_Mat4 p_mat4_rotate_y_by(P_Mat4 m, float rad);
-PODEF P_Mat4 p_mat4_rotate_z(float rad);
-PODEF P_Mat4 p_mat4_perspective(float fov_rad, float aspect, float near_z, float far_z);
-/* --- End of p_math.h --- */
-#endif
-
-#ifdef P_MODULE_ALLOC
-/* --- Start of p_allocators.h --- */
-typedef struct Arena {
- unsigned char *buf;
- usize buf_len;
- usize curr_offset;
- usize prev_offset;
-} Arena;
-
-PODEF void p_arena_create(Arena *a, void *backing_buffer, usize backing_buffer_length);
-PODEF void* p_arena_alloc_align(Arena *a, usize s, usize align);
-PODEF void* p_arena_alloc(Arena *a, usize s);
-PODEF void* p_arena_resize_align(Arena *a, void *old_memory, usize old_size, usize new_size, usize align);
-PODEF void* p_arena_resize(Arena *a, void *old_memory, usize old_size, usize new_size);
-PODEF void p_arena_free_all(Arena *a);
-PODEF void p_arena_destroy(Arena* a);
-
-typedef struct { u8 padding; } Stack_Allocation_Header;
-typedef struct Stack {
- unsigned char *buf;
- usize buf_len;
- usize offset;
-} Stack;
-
-PODEF void p_stack_create(Stack *s, void *backing_buffer, usize backing_buffer_length);
-PODEF usize calc_padding_with_header(uintptr ptr, uintptr alignment, usize header_size);
-PODEF void* p_stack_alloc(Stack *s, usize len, usize alignment);
-PODEF void p_stack_free(Stack *s, void *ptr);
-PODEF void p_stack_free_all(Stack* s);
-PODEF void p_stack_destroy(Stack* s);
-
-typedef struct Pool_Free_Node Pool_Free_Node;
-
-typedef struct Pool {
- unsigned char *buf;
- usize chunk_size;
- usize pool_size;
- Pool_Free_Node *head;
-} Pool;
-
-struct Pool_Free_Node { struct Pool_Free_Node *next; };
-PODEF void p_pool_create(Pool *p, void *buf, usize buf_len, usize chunk_size, usize chunk_align);
-PODEF void* p_pool_alloc(Pool *p);
-PODEF void p_pool_free(Pool *p, void *ptr);
-PODEF void p_pool_free_all(Pool *p);
-PODEF void p_pool_destroy(Pool *p);
-/* --- End of p_allocators.h --- */
-#endif
-
-#endif /* _PODIUM_H_ */
-
-#ifdef PODIUM_IMPLEMENTATION
-#undef PODIUM_IMPLEMENTATION
-
-#if defined(PODIUM_SDL)
-/* #include "p_platform_sdl.c" */
-#elif defined(PODIUM_WIN32)
-/* --- Start of p_platform_win32.c --- */
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <mmsystem.h>
-#include <xinput.h> /* gamepad support */
-
-typedef struct {
- HWAVEOUT wave_out;
- WAVEHDR wave_header;
-} P_Win32Ctx;
-
-struct P_Window_Impl {
- HWND hwnd;
- HDC hdc;
- BITMAPINFO bitmap_info;
- int width;
- int height;
- bool closed;
-};
-
-P_Win32Ctx p_ctx = {0};
-
-static inline P_KeyCode
-_win32_translate_vkey(WPARAM vk)
-{
- switch (vk) {
- case VK_LEFT: return P_KEY_LEFT;
- case VK_RIGHT: return P_KEY_RIGHT;
- case VK_UP: return P_KEY_UP;
- case VK_DOWN: return P_KEY_DOWN;
- case VK_SPACE: return P_KEY_SPACE;
- case VK_ESCAPE: return P_KEY_ESCAPE;
- case VK_RETURN: return P_KEY_ENTER;
- case 'A': return P_KEY_A;
- case 'B': return P_KEY_B;
- case 'C': return P_KEY_C;
- case 'D': return P_KEY_D;
- case 'E': return P_KEY_E;
- case 'F': return P_KEY_F;
- case 'G': return P_KEY_G;
- case 'H': return P_KEY_H;
- case 'I': return P_KEY_I;
- case 'J': return P_KEY_J;
- case 'K': return P_KEY_K;
- case 'L': return P_KEY_L;
- case 'M': return P_KEY_M;
- case 'N': return P_KEY_N;
- case 'O': return P_KEY_O;
- case 'P': return P_KEY_P;
- case 'Q': return P_KEY_Q;
- case 'R': return P_KEY_R;
- case 'S': return P_KEY_S;
- case 'T': return P_KEY_T;
- case 'U': return P_KEY_U;
- case 'V': return P_KEY_V;
- case 'W': return P_KEY_W;
- case 'X': return P_KEY_X;
- case 'Y': return P_KEY_Y;
- case 'Z': return P_KEY_Z;
- default: return P_KEY_UNKNOWN;
- }
-}
-
-POAPI u64
-p_get_time(void)
-{
- LARGE_INTEGER count, freq;
- QueryPerformanceCounter(&count);
- QueryPerformanceFrequency(&freq);
- return (u64)((count.QuadPart * 1000000000ULL) / freq.QuadPart);
-}
-
-POAPI void
-p_sleep_ns(i64 ns)
-{
- /* windows sleep is millisecond-based........ */
- Sleep((DWORD)(ns / 1000000));
-}
-
-POAPI void
-p_stdout(void *msg, usize bytes)
-{
- HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD bytes_written;
- WriteFile(stdout_handle, msg, bytes, &bytes_written, NULL);
-}
-
-POAPI bool
-p_file_exists(const char *path)
-{
- DWORD attr = GetFileAttributesA(path);
- return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY));
-}
-
-POAPI usize
-p_file_size(const char *path)
-{
- WIN32_FILE_ATTRIBUTE_DATA data;
- if (GetFileAttributesExA(path, GetFileExInfoStandard, &data)) {
- return data.nFileSizeLow;
- }
- return 0;
-}
-
-PODEF void
-p_file_load(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- HANDLE file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (file != INVALID_HANDLE_VALUE) {
- DWORD bytes_read;
- ReadFile(file, buf_ptr, buf_size, &bytes_read, NULL);
- CloseHandle(file);
- }
-}
-
-PODEF void
-p_file_write(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- HANDLE file = CreateFileA(path, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE) {
- DWORD bytes_written;
- WriteFile(file, buf_ptr, buf_size, &bytes_written, NULL);
- CloseHandle(file);
- }
-}
-
-static LRESULT CALLBACK
-_win32_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
- P_Window *win = (P_Window*)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
- switch (msg) {
- case WM_CLOSE:
- /* Handled in poll_event; mark as closed */
- if (win) win->closed = true;
- return 0;
- }
- return DefWindowProcA(hwnd, msg, wparam, lparam);
-}
-
-POAPI bool
-p_window_open(P_Window *win, int width, int height, const char *title)
-{
- HINSTANCE instance = GetModuleHandleA(NULL);
-
- WNDCLASSA wc = {0};
- wc.lpfnWndProc = _win32_wnd_proc;
- wc.hInstance = instance;
- wc.lpszClassName = "P_Window_Class";
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-
- RegisterClassA(&wc);
-
- win->hwnd = CreateWindowExA(0, wc.lpszClassName, title,
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT, width, height,
- NULL, NULL, instance, NULL);
-
- if (!win->hwnd) return false;
-
- SetWindowLongPtrA(win->hwnd, GWLP_USERDATA, (LONG_PTR)win);
- win->hdc = GetDC(win->hwnd);
- win->width = width;
- win->height = height;
- win->closed = false;
-
- return true;
-}
-
-POAPI void
-p_window_close(P_Window *win)
-{
- if (!win) return;
- if (win->hdc) ReleaseDC(win->hwnd, win->hdc);
- if (win->hwnd) DestroyWindow(win->hwnd);
- win->hdc = NULL;
- win->hwnd = NULL;
-}
-
-POAPI bool
-p_window_is_open(P_Window *win)
-{
- return win && win->hwnd != NULL;
-}
-
-POAPI void
-p_window_size(P_Window *win, int *window_width, int *window_height)
-{
- if (!win) return;
- RECT rect;
- GetClientRect(win->hwnd, &rect);
- *window_width = rect.right - rect.left;
- *window_height = rect.bottom - rect.top;
- win->width = *window_width;
- win->height = *window_height;
-}
-
-POAPI void
-p_window_draw(P_Window *win, u32 *pixels, int width, int height)
-{
- BITMAPINFO bmi = {0};
- bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = -height; /* top-down */
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
-
- StretchDIBits(win->hdc,
- 0, 0, win->width, win->height,
- 0, 0, width, height,
- pixels, &bmi, DIB_RGB_COLORS, SRCCOPY);
-}
-
-POAPI bool
-p_window_poll_event(P_Window *win, P_Event *ev)
-{
- if (win->closed) {
- win->closed = false;
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
- }
-
- MSG msg;
- while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
- switch (msg.message) {
-
- case WM_QUIT:
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
-
- /* Key press */
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- ev->type = P_EVENT_KEY_DOWN;
- ev->key.key = _win32_translate_vkey(msg.wParam);
- return true;
-
- /* Key release */
- case WM_KEYUP:
- case WM_SYSKEYUP:
- ev->type = P_EVENT_KEY_UP;
- ev->key.key = _win32_translate_vkey(msg.wParam);
- return true;
-
- /* Mouse movement */
- case WM_MOUSEMOVE:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_MOVED;
- ev->pointer.button = 0;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- /* Mouse buttons */
- case WM_LBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 1; /* 1 = LMB, matching X11 convention */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_LBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 1;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_RBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 3; /* 3 = RMB */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_RBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 3;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_MBUTTONDOWN:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = 2; /* 2 = MMB */
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- case WM_MBUTTONUP:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = 2;
- ev->pointer.x = (u32)(msg.lParam & 0xFFFF);
- ev->pointer.y = (u32)((msg.lParam >> 16) & 0xFFFF);
- return true;
-
- /* Window resize */
- case WM_SIZE:
- ev->type = P_EVENT_WINDOW_RESIZE;
- ev->resize.width = (u32)(msg.lParam & 0xFFFF);
- ev->resize.height = (u32)((msg.lParam >> 16) & 0xFFFF);
- win->width = ev->resize.width;
- win->height = ev->resize.height;
- return true;
-
- default:
- TranslateMessage(&msg);
- DispatchMessageA(&msg);
- break;
- }
- }
-
- ev->type = P_EVENT_NONE;
- return false;
-}
-
-
-POAPI void
-p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc)
-{
- (void)name; (void)desc; /* WinMM doesn't use a stream name */
-
- WAVEFORMATEX wfx = {0};
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = channels;
- wfx.nSamplesPerSec = sample_rate;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-
- if (waveOutOpen(&p_ctx.wave_out, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
- exit(1);
- }
-}
-
-POAPI void
-p_audio_quit()
-{
- if (p_ctx.wave_out) {
- waveOutReset(p_ctx.wave_out);
- waveOutClose(p_ctx.wave_out);
- p_ctx.wave_out = NULL;
- }
-}
-
-POAPI void
-p_audio_write(const i16 *samples, usize count)
-{
- if (!p_ctx.wave_out) return;
-
- WAVEHDR header = {0};
- header.lpData = (LPSTR)samples;
- header.dwBufferLength = (DWORD)(count * sizeof(i16));
-
- waveOutPrepareHeader(p_ctx.wave_out, &header, sizeof(WAVEHDR));
- waveOutWrite(p_ctx.wave_out, &header, sizeof(WAVEHDR));
-
- /* wait for playback to finish (synchronous, mirrors pa_simple_drain) */
- while (!(header.dwFlags & WHDR_DONE)) Sleep(1);
-
- waveOutUnprepareHeader(p_ctx.wave_out, &header, sizeof(WAVEHDR));
-}
-
-#ifdef P_MODULE_VULKAN
-
-#ifndef VK_USE_PLATFORM_WIN32_KHR
-#define VK_USE_PLATFORM_WIN32_KHR
-#endif
-#include <vulkan/vulkan_win32.h>
-
-POAPI char**
-p_vulkan_get_extensions()
-{
- char **darr = NULL;
- p_darray_push(darr, "VK_KHR_surface");
- p_darray_push(darr, "VK_KHR_win32_surface");
- return darr;
-}
-
-POAPI bool
-p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface)
-{
- if (!instance || !window || !window->hwnd || !out_surface) {
- return false;
- }
-
- VkWin32SurfaceCreateInfoKHR create_info = {0};
- create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = NULL;
- create_info.flags = 0;
- create_info.hwnd = window->hwnd;
- create_info.hinstance = GetModuleHandleA(NULL);
-
- VkResult result = vkCreateWin32SurfaceKHR(instance, &create_info, allocator, out_surface);
- return (result == VK_SUCCESS);
-}
-#endif
-/* --- End of p_platform_win32.c --- */
-#elif defined(PODIUM_LINUX)
-/* --- Start of p_platform_linux.c --- */
-/* linux */
-#include <time.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <errno.h>
-/* x11 */
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-/* pulse audio */
-#include <pulse/pulseaudio.h>
-#include <pulse/simple.h>
-#include <pulse/error.h>
-/* joystick */
-#include <linux/joystick.h>
-
-typedef struct {
- pa_simple *audio_stream;
-} P_LinuxCtx;
-
-struct P_Window_Impl {
- Display *display;
- XImage *image;
- Window window;
- GC gc;
- int screen;
- int width;
- int height;
-};
-
-P_LinuxCtx p_ctx = {0};
-
-static inline P_KeyCode
-_x11_translate_keycode(XEvent xev)
-{
- static KeySym ks;
- ks = XLookupKeysym(&xev.xkey, 0);
- switch (ks) {
- /* Arrow keys */
- case XK_Left: return P_KEY_LEFT;
- case XK_Right: return P_KEY_RIGHT;
- case XK_Up: return P_KEY_UP;
- case XK_Down: return P_KEY_DOWN;
- /* Common keys */
- case XK_space: return P_KEY_SPACE;
- case XK_Escape: return P_KEY_ESCAPE;
- case XK_Return: return P_KEY_ENTER;
- case XK_A: case XK_a: return P_KEY_A;
- case XK_B: case XK_b: return P_KEY_B;
- case XK_C: case XK_c: return P_KEY_C;
- case XK_D: case XK_d: return P_KEY_D;
- case XK_E: case XK_e: return P_KEY_E;
- case XK_F: case XK_f: return P_KEY_F;
- case XK_G: case XK_g: return P_KEY_G;
- case XK_H: case XK_h: return P_KEY_H;
- case XK_I: case XK_i: return P_KEY_I;
- case XK_J: case XK_j: return P_KEY_J;
- case XK_K: case XK_k: return P_KEY_K;
- case XK_L: case XK_l: return P_KEY_L;
- case XK_M: case XK_m: return P_KEY_M;
- case XK_N: case XK_n: return P_KEY_N;
- case XK_O: case XK_o: return P_KEY_O;
- case XK_P: case XK_p: return P_KEY_P;
- case XK_Q: case XK_q: return P_KEY_Q;
- case XK_R: case XK_r: return P_KEY_R;
- case XK_S: case XK_s: return P_KEY_S;
- case XK_T: case XK_t: return P_KEY_T;
- case XK_U: case XK_u: return P_KEY_U;
- case XK_V: case XK_v: return P_KEY_V;
- case XK_W: case XK_w: return P_KEY_W;
- case XK_X: case XK_x: return P_KEY_X;
- case XK_Y: case XK_y: return P_KEY_Y;
- case XK_Z: case XK_z: return P_KEY_Z;
- default: return P_KEY_UNKNOWN;
- }
-}
-
-POAPI u64
-p_get_time(void)
-{
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return NANOS_PER_SEC * ts.tv_sec + ts.tv_nsec;
-}
-
-POAPI void
-p_sleep_ns(i64 ns)
-{
- struct timespec ts;
- ts.tv_sec = ns / 1000000000L;
- ts.tv_nsec = ns % 1000000000L;
- clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
-}
-
-POAPI void
-p_stdout(void *msg, usize bytes)
-{
- write(1, msg, bytes);
-}
-
-POAPI bool
-p_file_exists(const char *path)
-{
- return (access(path, F_OK) == 0);
-}
-
-POAPI usize
-p_file_size(const char *path)
-{
- struct stat st;
- if (stat(path, &st) == 0) {
- return st.st_size;
- }
- return 0;
-}
-
-PODEF void
-p_file_load(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- int fd = open(path, O_RDONLY);
- if (fd >= 0) {
- read(fd, buf_ptr, (size_t)buf_size);
- close(fd);
- }
-}
-
-PODEF void
-p_file_write(const char *path, void *buf_ptr, unsigned long buf_size)
-{
- int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644);
- if (fd >= 0) {
- write(fd, buf_ptr, (size_t)buf_size);
- close(fd);
- }
-}
-
-POAPI bool
-p_window_open(P_Window *win, int width, int height, const char *title)
-{
- win->width = width;
- win->height = height;
-
- XInitThreads();
-
- win->display = XOpenDisplay(NULL);
- if (win->display == NULL) {
- PERROR("Cannot open display!");
- return false;
- }
-
- int screen = DefaultScreen(win->display);
- win->window = XCreateSimpleWindow(
- win->display,
- RootWindow(win->display, screen),
- 0, 0, width, height,
- 1,
- BlackPixel(win->display, screen),
- BlackPixel(win->display, screen)
- );
-
- win->screen = screen;
-
- XStoreName(win->display, win->window, title);
- XSelectInput(win->display, win->window,
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | StructureNotifyMask);
- XMapWindow(win->display, win->window);
-
- win->gc = DefaultGC(win->display, screen);
-
- Atom wm_delete = XInternAtom(win->display, "WM_DELETE_WINDOW", False);
- XSetWMProtocols(win->display, win->window, &wm_delete, 1);
-
- return true;
-}
-
-POAPI void
-p_window_close(P_Window *win)
-{
- if (!win) return;
-
- if (win->image) {
- // XDestroyImage(win->image);
- win->image = NULL;
- }
-
- if (win->display) {
- Display *dpy = win->display;
- Window w = win->window;
- win->display = NULL;
- win->window = 0;
-
- if (w) {
- XDestroyWindow(dpy, w);
- }
- XSync(dpy, False);
- }
-}
-
-POAPI bool
-p_window_is_open(P_Window *win)
-{
- return win && win->display != NULL;
-}
-
-POAPI void
-p_window_size(P_Window *win, int *window_width, int *window_height)
-{
- if (!win) return;
-
- XWindowAttributes attr;
- XGetWindowAttributes(win->display, win->window, &attr);
- *window_width = attr.width;
- *window_height = attr.height;
-
- win->width = attr.width;
- win->height = attr.height;
-}
-
-POAPI void
-p_window_draw(P_Window *win, u32 *pixels, int width, int height)
-{
- int screen = win->screen;
-
- win->image = XCreateImage(
- win->display,
- DefaultVisual(win->display, screen),
- DefaultDepth(win->display, screen),
- ZPixmap,
- 0,
- (char*)pixels,
- width,
- height,
- 32,
- width * 4
- );
-
- int window_width, window_height;
- p_window_size(win, &window_width, &window_height);
-
- XPutImage(
- win->display,
- win->window,
- win->gc,
- win->image,
- 0, 0,
- 0, 0,
- win->width,
- win->height);
-
- XFlush(win->display);
-}
-
-POAPI bool
-p_window_poll_event(P_Window *win, P_Event *ev)
-{
- if (XPending(win->display)) {
- static XEvent xev;
- XNextEvent(win->display, &xev);
-
- switch (xev.type) {
-
- case KeyPress:
- ev->type = P_EVENT_KEY_DOWN;
- ev->key.key = _x11_translate_keycode(xev);
- return true;
-
- case KeyRelease:
- ev->type = P_EVENT_KEY_UP;
- ev->key.key = _x11_translate_keycode(xev);
- return true;
-
- case ConfigureNotify:
- ev->type = P_EVENT_WINDOW_RESIZE;
- ev->resize.width = xev.xconfigure.width;
- ev->resize.height = xev.xconfigure.height;
- return true;
-
- case ClientMessage:
- if ((Atom)xev.xclient.data.l[0] ==
- XInternAtom(win->display, "WM_DELETE_WINDOW", False)) {
- ev->type = P_EVENT_WINDOW_CLOSE;
- return true;
- }
- break;
-
- case MotionNotify:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_MOVED;
- ev->pointer.button = 0;
- ev->pointer.x = xev.xmotion.x;
- ev->pointer.y = xev.xmotion.y;
- return true;
-
- case ButtonPress:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_PRESSED;
- ev->pointer.button = xev.xbutton.button; /* 1=LMB, 2=MMB, 3=RMB */
- ev->pointer.x = xev.xbutton.x;
- ev->pointer.y = xev.xbutton.y;
- return true;
-
- case ButtonRelease:
- ev->type = P_EVENT_POINTER;
- ev->pointer.state = P_POINTER_RELEASED;
- ev->pointer.button = xev.xbutton.button;
- ev->pointer.x = xev.xbutton.x;
- ev->pointer.y = xev.xbutton.y;
- return true;
- }
- }
-
- ev->type = P_EVENT_NONE;
- return false;
-}
-
-POAPI void
-p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc)
-{
- pa_sample_spec ss = {
- .format = PA_SAMPLE_S16LE,
- .rate = sample_rate,
- .channels = channels,
- };
-
- int error;
- p_ctx.audio_stream = pa_simple_new(
- NULL,
- name,
- PA_STREAM_PLAYBACK,
- NULL,
- desc,
- &ss,
- NULL,
- NULL,
- &error
- );
-
- if (!p_ctx.audio_stream) {
- PERROR("PulseAudio init failed: %s\n", pa_strerror(error));
- exit(1);
- }
-}
-
-POAPI void
-p_audio_quit()
-{
- if (p_ctx.audio_stream) {
- pa_simple_free(p_ctx.audio_stream);
- p_ctx.audio_stream = NULL;
- }
-}
-
-POAPI void
-p_audio_write(const i16 *samples, usize count)
-{
- if (!p_ctx.audio_stream) return;
-
- int error;
- if (pa_simple_write(p_ctx.audio_stream, samples, count * sizeof(i16), &error) < 0) {
- PERROR("PulseAudio write failed: %s\n", pa_strerror(error));
- }
-
- pa_simple_drain(p_ctx.audio_stream, &error);
-}
-
-#ifdef P_MODULE_VULKAN
-
-#ifndef VK_USE_PLATFORM_XLIB_KHR
-#define VK_USE_PLATFORM_XLIB_KHR
-#endif
-#include <vulkan/vulkan_xlib.h>
-
-POAPI char**
-p_vulkan_get_extensions()
-{
- char **darr = NULL;
- p_darray_push(darr, "VK_KHR_surface");
- p_darray_push(darr, "VK_KHR_xcb_surface");
- p_darray_push(darr, "VK_KHR_xlib_surface");
- return darr;
-}
-
-POAPI bool
-p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface)
-{
- if (!instance || !window || !window->display || !window->window || !out_surface) {
- return false;
- }
-
- VkXlibSurfaceCreateInfoKHR create_info = {0};
- create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = NULL;
- create_info.flags = 0;
- create_info.dpy = window->display;
- create_info.window = window->window;
-
- VkResult result = vkCreateXlibSurfaceKHR(instance, &create_info, allocator, out_surface);
-
- return (result == VK_SUCCESS);
-}
-#endif
-/* --- End of p_platform_linux.c --- */
-#endif /* linux */
-
-
-POAPI void* p_file_alloc(const char *path, unsigned long *buf_size) {
- if (p_file_exists(path) == false) {
- return NULL;
- }
-
- usize file_size = p_file_size(path);
- *buf_size = file_size;
-
- void *ptr = malloc(file_size);
- if (ptr) {
- p_file_load(path, ptr, file_size); // Load file to buffer.
- }
- return ptr;
-}
-
-
-/*
- * Import Module Code
- */
-
-#ifdef P_MODULE_STRING
-/* --- Start of p_string.c --- */
-PODEF char*
-p_find_char(char *buf, char needle)
-{
- while (buf && *buf != needle) buf++;
- return buf;
-}
-
-PODEF bool
-p_strcmp(const char *a, const char *b)
-{
- if (p_strlen(a) != p_strlen(b))
- return false;
-
- while (a && b && *a != '\0') {
- if (*(a++) != *(b++)) return false;
- }
-
- return true;
-}
-
-PODEF int
-p_strlen(const char *a)
-{
- int i = 0;
- while (*a++ != '\0') i++;
- return i;
-}
-
-PODEF int
-p_strtoi(const char *str)
-{
- int res = 0;
-
- while (*str) {
- if (*str >= '0' && *str <= '9') {
- res = res * 10 + (*str - '0');
- } else {
- return res;
- }
- str++;
- }
-
- return res;
-}
-
-PODEF char*
-p_strtok(const char *str, char c)
-{
- while (*str != c && *str++ != '\0');
- return (*str == c) ? (char*) ++str : 0;
-}
-
-PODEF P_StringView
-p_strview(const char *cstr)
-{
- P_StringView sv = {0};
- sv.cstr = cstr;
- sv.len = p_strlen(cstr);
- return sv;
-}
-
-PODEF void
-p_strview_chop_left(P_StringView *sv, u32 n)
-{
- if (n > sv->len) n = sv->len;
- sv->cstr += n;
- sv->len -= n;
-}
-
-PODEF void
-p_strview_chop_right(P_StringView *sv, u32 n)
-{
- if (n > sv->len) n = sv->len;
- sv->len -= n;
-}
-
-PODEF P_StringView
-p_strview_chop_delim(P_StringView *sv, char delim)
-{
- u32 i = 0;
- while (i < sv->len && sv->cstr[i] != delim) {
- i++;
- }
-
- P_StringView tok;
- if (i < sv->len) {
- tok.cstr = sv->cstr;
- tok.len = i;
- p_strview_chop_left(sv, i + 1);
- return tok;
- }
-
- tok = *sv;
- p_strview_chop_left(sv, sv->len);
- return tok;
-}
-
-PODEF P_StringView
-p_strview_chop_type(P_StringView *sv, int(*istype)(int))
-{
- u32 i = 0;
- while (i < sv->len && istype(sv->cstr[i])) {
- i++;
- }
-
- P_StringView tok;
- if (i < sv->len) {
- tok.cstr = sv->cstr;
- tok.len = i;
- p_strview_chop_left(sv, i + 1);
- return tok;
- }
-
- tok = *sv;
- p_strview_chop_left(sv, sv->len);
- return tok;
-}
-
-
-PODEF void
-p_strview_trim_left(P_StringView *sv)
-{
- while (sv->len > 0 && p_is_space(sv->cstr[0])) {
- p_strview_chop_left(sv, 1);
- }
-}
-
-PODEF void
-p_strview_trim_right(P_StringView *sv)
-{
- while (sv->len > 0 && p_is_space(sv->cstr[sv->len-1])) {
- p_strview_chop_right(sv, 1);
- }
-}
-
-PODEF void
-p_strview_trim(P_StringView *sv)
-{
- p_strview_trim_left(sv);
- p_strview_trim_right(sv);
-}
-
-PODEF int
-p_is_space(int c)
-{
- /* Checks for: space, form feed (\f), line feed (\n),
- * carriage return (\r), horizontal tab (\t), vertical tab (\v) */
- return (c == ' ' || (c >= '\t' && c <= '\r'));
-}
-
-PODEF int
-p_is_digit(int c)
-{
- return (c >= '0' && c <= '9');
-}
-
-PODEF int
-p_is_alpha(int c)
-{
- return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
-}
-
-PODEF int
-p_is_alnum(int c)
-{
- return (p_is_alpha(c) || p_is_digit(c));
-}
-
-PODEF int
-p_is_hex(int c)
-{
- return (p_is_digit(c) ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F'));
-}
-
-PODEF int
-p_is_upper(int c)
-{
- return (c >= 'A' && c <= 'Z');
-}
-
-PODEF int
-p_is_lower(int c)
-{
- return (c >= 'a' && c <= 'z');
-}
-
-PODEF int
-p_to_lower(int c)
-{
- if (p_is_upper(c)) return (c + ('a' - 'A'));
- return c;
-}
-
-PODEF int
-p_to_upper(int c)
-{
- if (p_is_lower(c)) return (c - ('a' - 'A'));
- return c;
-}
-/* --- End of p_string.c --- */
-#endif
-
-#ifdef P_MODULE_MATH
-/* --- Start of p_math.c --- */
-PODEF
-int p_ceil(float x)
-{
- int base = (int) x;
- return (x > base) ? base + 1 : base;
-}
-
-PODEF float
-p_cosf(float x)
-{
- x += 1.57079632679f;
-
- while (x > P_PI) x -= P_PI2;
- while (x < -P_PI) x += P_PI2;
-
- const float B = 4.0f / P_PI;
- const float C = -4.0f / P_PI_POW2;
-
- float y = B * x + C * x * (x < 0 ? -x : x);
-
- const float P = 0.225f;
- y = P * (y * (y < 0 ? -y : y) - y) + y;
-
- return y;
-}
-
-PODEF float
-p_sinf(float x)
-{
- while (x > P_PI) x -= P_PI2;
- while (x < -P_PI) x += P_PI2;
-
- const float B = 4.0f / P_PI;
- const float C = -4.0f / (P_PI_POW2);
-
- float y = B * x + C * x * (x < 0 ? -x : x);
-
- const float P = 0.225f;
- y = P * (y * (y < 0 ? -y : y) - y) + y;
-
- return y;
-}
-
-PODEF Vec2f
-p_vec2f(float x, float y)
-{
- return (Vec2f) { .x = x, .y = y };
-}
-
-PODEF Vec2f
-p_vec2f_add(Vec2f a, Vec2f b)
-{
- return (Vec2f) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- };
-}
-
-PODEF float
-p_vec2f_cross(Vec2f a, Vec2f b)
-{
- // axby − aybx
- return a.x * b.y - a.y * b.x;
-}
-
-PODEF float
-p_vec2f_dot(Vec2f a, Vec2f b)
-{
- // a · b = ax × bx + ay × by
- return a.x * b.x + a.y * b.y;
-}
-
-PODEF Vec2f
-p_vec2f_mult(Vec2f a, float b)
-{
- return (Vec2f) {
- .x = a.x * b,
- .y = a.y * b,
- };
-}
-
-PODEF Vec2f
-p_vec2f_sub(Vec2f a, Vec2f b)
-{
- return (Vec2f) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- };
-}
-
-PODEF Vec2i
-p_vec2i(float x, float y)
-{
- return (Vec2i) { .x = x, .y = y };
-}
-
-PODEF Vec2i
-p_vec2i_add(Vec2i a, Vec2i b)
-{
- return (Vec2i) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- };
-}
-
-PODEF float
-p_vec2i_cross(Vec2i a, Vec2i b)
-{
- // axby − aybx
- return a.x * b.y - a.y * b.x;
-}
-
-PODEF float
-p_vec2i_dot(Vec2i a, Vec2i b)
-{
- // a · b = ax × bx + ay × by
- return a.x * b.x + a.y * b.y;
-}
-
-PODEF Vec2i
-p_vec2i_mult(Vec2i a, float b)
-{
- return (Vec2i) {
- .x = a.x * b,
- .y = a.y * b,
- };
-}
-
-PODEF Vec2i
-p_vec2i_sub(Vec2i a, Vec2i b)
-{
- return (Vec2i) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- };
-}
-
-PODEF Vec3f
-p_vec3f(float x, float y, float z)
-{
- return (Vec3f) { .x = x, .y = y, .z = z };
-}
-
-PODEF P_Mat4
-p_mat4_identity(void)
-{
- P_Mat4 res = {0};
- res.m[0] = 1.0f;
- res.m[5] = 1.0f;
- res.m[10] = 1.0f;
- res.m[15] = 1.0f;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_mul(P_Mat4 a, P_Mat4 b)
-{
- P_Mat4 res = {0};
- for (int col = 0; col < 4; ++col) {
- for (int row = 0; row < 4; ++row) {
- float sum = 0.0f;
- for (int k = 0; k < 4; ++k) {
- sum += a.m[k * 4 + row] * b.m[col * 4 + k];
- }
- res.m[col * 4 + row] = sum;
- }
- }
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_translate(Vec3f v)
-{
- P_Mat4 res = p_mat4_identity();
- res.m[12] = v.x;
- res.m[13] = v.y;
- res.m[14] = v.z;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_translate_by(P_Mat4 m, Vec3f v)
-{
- P_Mat4 res = m;
- res.m[12] = m.m[0] * v.x + m.m[4] * v.y + m.m[8] * v.z + m.m[12];
- res.m[13] = m.m[1] * v.x + m.m[5] * v.y + m.m[9] * v.z + m.m[13];
- res.m[14] = m.m[2] * v.x + m.m[6] * v.y + m.m[10] * v.z + m.m[14];
- res.m[15] = m.m[3] * v.x + m.m[7] * v.y + m.m[11] * v.z + m.m[15];
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_x(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[5] = c;
- res.m[6] = s;
- res.m[9] = -s;
- res.m[10] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_x_by(P_Mat4 m, float rad)
-{
- return p_mat4_mul(m, p_mat4_rotate_x(rad));
-}
-
-PODEF P_Mat4
-p_mat4_rotate_y(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[0] = c;
- res.m[2] = -s;
- res.m[8] = s;
- res.m[10] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_rotate_y_by(P_Mat4 m, float rad)
-{
- return p_mat4_mul(m, p_mat4_rotate_y(rad));
-}
-
-PODEF P_Mat4
-p_mat4_rotate_z(float rad)
-{
- P_Mat4 res = p_mat4_identity();
- float c = p_cosf(rad);
- float s = p_sinf(rad);
- res.m[0] = c;
- res.m[1] = s;
- res.m[4] = -s;
- res.m[5] = c;
- return res;
-}
-
-PODEF P_Mat4
-p_mat4_perspective(float fov_rad, float aspect, float near_z, float far_z)
-{
- P_Mat4 res = {0};
- float tan_half_fov = p_sinf(fov_rad * 0.5f) / p_cosf(fov_rad * 0.5f);
-
- res.m[0] = 1.0f / (aspect * tan_half_fov);
- res.m[5] = 1.0f / tan_half_fov;
- res.m[10] = far_z / (near_z - far_z);
- res.m[11] = -1.0f;
- res.m[14] = (near_z * far_z) / (near_z - far_z);
- return res;
-}
-/* --- End of p_math.c --- */
-#endif
-
-#ifdef P_MODULE_ALLOC
-/* --- Start of p_allocators.c --- */
-PODEF bool
-is_power_of_two(uintptr x) {
- return (x & (x-1)) == 0;
-}
-
-PODEF uintptr
-align_forward(uintptr ptr, usize align)
-{
- uintptr p, a, remainder;
- assert(is_power_of_two(align));
-
- p = ptr;
- a = (uintptr)align;
- remainder = p & (a-1);
-
- return (remainder != 0) ? p + a - remainder : p;
-}
-
-PODEF void
-p_arena_create(Arena *a, void *backing_buffer, usize backing_buffer_length)
-{
- a->buf = (unsigned char *)backing_buffer;
- a->buf_len = backing_buffer_length;
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void*
-p_arena_alloc_align(Arena *a, usize s, usize align)
-{
-
- // Align 'curr_offset' forward to the specified alignment
- uintptr curr_ptr = (uintptr)a->buf + (uintptr)a->curr_offset;
- uintptr offset = align_forward(curr_ptr, align);
- offset -= (uintptr)a->buf; // Change to relative offset
-
- // Check to see if the backing memory has space left
- if (offset+s <= a->buf_len) {
- void *ptr = &a->buf[offset];
- a->prev_offset = offset;
- a->curr_offset = offset+s;
-
- memset(ptr, 0, s);
- return ptr;
- }
-
- return NULL;
-}
-
-PODEF void*
-p_arena_alloc(Arena *a, usize s) {
- return p_arena_alloc_align(a, s, DEFAULT_ALIGNMENT);
-}
-
-PODEF void*
-p_arena_resize_align(Arena *a, void *old_memory, usize old_size, usize new_size, usize align)
-{
- assert(is_power_of_two(align));
- unsigned char *old_mem = (unsigned char *)old_memory;
-
- if (old_mem == NULL || old_size == 0) {
- return p_arena_alloc_align(a, new_size, align);
- } else if (a->buf <= old_mem && old_mem < a->buf+a->buf_len) {
- if (a->buf+a->prev_offset == old_mem) {
- a->curr_offset = a->prev_offset + new_size;
- if (new_size > old_size) {
- // Zero the new memory by default
- memset(&a->buf[a->curr_offset], 0, new_size-old_size);
- }
- return old_memory;
- } else {
- void *new_memory = p_arena_alloc_align(a, new_size, align);
- size_t copy_size = old_size < new_size ? old_size : new_size;
- memmove(new_memory, old_memory, copy_size);
- return new_memory;
- }
-
- } else {
- assert(0 && "Memory is out of bounds of the buffer in this arena");
- return NULL;
- }
-}
-
-PODEF void*
-p_arena_resize(Arena *a, void *old_memory, usize old_size, usize new_size)
-{
- return p_arena_resize_align(a, old_memory, old_size, new_size, DEFAULT_ALIGNMENT);
-}
-
-PODEF void
-p_arena_free_all(Arena *a)
-{
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void
-p_arena_destroy(Arena* a)
-{
- a->buf_len = 0;
- a->curr_offset = 0;
- a->prev_offset = 0;
-}
-
-PODEF void
-p_stack_create(Stack *s, void *backing_buffer, usize backing_buffer_length)
-{
- s->buf = (unsigned char*) backing_buffer;
- s->buf_len = backing_buffer_length;
- s->offset = 0;
-}
-
-PODEF usize
-calc_padding_with_header(uintptr ptr, uintptr alignment, usize header_size)
-{
- uintptr p, a, modulo, padding, needed_space;
-
- assert(is_power_of_two(alignment));
-
- p = ptr;
- a = alignment;
- modulo = p & (a-1); // (p % a) as it assumes alignment is a power of two
-
- padding = 0;
- needed_space = 0;
-
- if (modulo != 0) { // Same logic as 'align_forward'
- padding = a - modulo;
- }
-
- needed_space = (uintptr)header_size;
-
- if (padding < needed_space) {
- needed_space -= padding;
-
- if ((needed_space & (a-1)) != 0) {
- padding += a * (1+(needed_space/a));
- } else {
- padding += a * (needed_space/a);
- }
- }
-
- return (usize)padding;
-}
-
-PODEF void*
-p_stack_alloc(Stack *s, usize len, usize alignment)
-{
- uintptr curr_addr, next_addr;
- usize padding;
- Stack_Allocation_Header *header;
-
- assert(is_power_of_two(alignment));
-
- if (alignment > 128) {
- // As the padding is 8 bits (1 byte), the largest alignment that can
- // be used is 128 bytes
- alignment = 128;
- }
-
- curr_addr = (uintptr)s->buf + (uintptr)s->offset;
- padding = calc_padding_with_header(curr_addr, (uintptr)alignment, sizeof(Stack_Allocation_Header));
- if (s->offset + padding + len > s->buf_len) {
- // Stack allocator is out of memory
- return NULL;
- }
- s->offset += padding;
-
- next_addr = curr_addr + (uintptr)padding;
- header = (Stack_Allocation_Header *)(next_addr - sizeof(Stack_Allocation_Header));
- header->padding = (u8)padding;
-
- s->offset += len;
-
- return memset((void *)next_addr, 0, len);
-}
-
-PODEF void
-p_stack_free(Stack *s, void *ptr)
-{
- if (ptr != NULL) {
- uintptr start, end, curr_addr;
- Stack_Allocation_Header *header;
- usize prev_offset;
-
- start = (uintptr)s->buf;
- end = start + (uintptr)s->buf_len;
- curr_addr = (uintptr)ptr;
-
- if (!(start <= curr_addr && curr_addr < end)) {
- assert(0 && "Out of bounds memory address passed to stack allocator (free)");
- return;
- }
-
- if (curr_addr >= start+(uintptr)s->offset) {
- // Allow double frees
- return;
- }
-
- header = (Stack_Allocation_Header *)(curr_addr - sizeof(Stack_Allocation_Header));
- prev_offset = (usize)(curr_addr - (uintptr)header->padding - start);
-
- s->offset = prev_offset;
- }
-}
-
-PODEF void
-p_stack_free_all(Stack* s)
-{
- s->offset = 0;
-}
-
-PODEF void
-p_stack_destroy(Stack* s)
-{
- s->buf = 0;
- s->buf_len = 0;
- s->offset = 0;
-}
-
-PODEF void
-p_pool_create(Pool *p, void *buf, usize buf_len, usize chunk_size, usize chunk_align)
-{
- /* align start */
- uintptr start = (uintptr) buf;
- uintptr aligned = align_forward(start, chunk_align);
- buf_len -= (aligned - start);
-
- /* align chunk usize */
- chunk_size = (usize) align_forward(chunk_size, chunk_align);
-
- assert(chunk_size >= sizeof(Pool_Free_Node) && "Chunk usize is too small");
- assert(buf_len >= chunk_size && "Backing buffer length is smaller than the chunk size");
-
- p->buf = (unsigned char *) buf;
- p->pool_size = buf_len;
- p->chunk_size = chunk_size;
- p->head = NULL;
-
- p_pool_free_all(p);
-}
-
-PODEF void*
-p_pool_alloc(Pool *p)
-{
- Pool_Free_Node *node = p->head;
-
- assert(node != NULL && "Pool allocator has no free memory");
-
- p->head = p->head->next;
-
- return memset(node, 0 , p->chunk_size);
-}
-
-PODEF void
-p_pool_free(Pool *p, void *ptr)
-{
- Pool_Free_Node *node;
-
- void *start = p->buf;
- void *end = &p->buf[p->pool_size];
-
- if (ptr == NULL) {
- return;
- }
-
- if (!(start <= ptr && ptr < end)) {
- assert(0 && "Memory is out of bounds of the buffer in this pool");
- return;
- }
-
- node = (Pool_Free_Node *)ptr;
- node->next = p->head;
- p->head = node;
-}
-
-PODEF void
-p_pool_free_all(Pool *p)
-{
- usize chunk_count = p->pool_size / p->chunk_size;
- usize i;
-
- for (i = 0; i < chunk_count; i++) {
- void *ptr = &p->buf[i * p->chunk_size];
- Pool_Free_Node *node = (Pool_Free_Node *)ptr;
-
- // Push free node onto thte free list
- node->next = p->head;
- p->head = node;
- }
-}
-
-PODEF void
-p_pool_destroy(Pool *p)
-{
- p->buf = NULL;
- p->pool_size = 0;
- p->chunk_size = 0;
- p->head = NULL;
-}
-
-/* --- End of p_allocators.c --- */
-#endif
-
-#define P_MAX_PRINTF_SIZE 1024
-PODEF void
-p_log_printf(P_Log_Level level, const char* src, ...)
-{
- static char out_message[P_MAX_PRINTF_SIZE];
- static u32 offset = P_PREFIX_LEN + 1;
-
- memcpy(out_message, p_prefix[level], P_PREFIX_LEN); /* prefixes have a fixed len */
- out_message[P_PREFIX_LEN] = ' '; /* write space */
-
- __builtin_va_list arg_ptr;
- va_start(arg_ptr, src);
- int len = vsnprintf(out_message+offset, P_MAX_PRINTF_SIZE-offset, src, arg_ptr); // append message
- va_end(arg_ptr);
-
- if (len < 0) len = 0;
- usize total_len = offset + len;
- if (total_len > P_MAX_PRINTF_SIZE) {
- total_len = P_MAX_PRINTF_SIZE;
- }
-
- p_stdout(out_message, total_len);
- p_stdout("\n", 1);
-}
-
-#endif // PODIUM_IMPLEMENTATION
diff --git a/Podium/podium_header.h b/Podium/podium_header.h
deleted file mode 100644
index 6407f62..0000000
--- a/Podium/podium_header.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/* ===========================================================================
- * PODIUM - Kitchen Sink - Copyright (c) 2026 Vasco Alves
- * ---------------------------------------------------------------------------
- * To stand on the shoulders of giants... Giants must stand still!"
- * ---------------------------------------------------------------------------
- * PREFIX: P_ (types) or p_ (functions & variables)
- * ---------------------------------------------------------------------------
- * COMPILE TIME FLAGS
- * ._________________________________________________________________________,
- * | Name | Description |
- * |-----------------|-------------------------------------------------------|
- * | PODIUM_WIN32 | Used to explicitly compile for Windows |
- * | PODIUM_LINUX | Used to explicitly compile for Linux and FreeBSD. |
- * '-------------------------------------------------------------------------'
- * MODULES
- * ._________________________________________________________________________,
- * | Name | Description |
- * |-----------------|-------------------------------------------------------|
- * | P_MODULE_VULKAN | Gives access to vulkan related utilities. |
- * | P_MODULE_STRING | Include string manipulation utilities. |
- * | P_MODULE_MATH | Trigonometry and linear algebra functions. |
- * | P_MODULE_ALLOC | Memory allocators: Arena, Stack & Pool. |
- * '-------------------------------------------------------------------------'
- * =========================================================================== */
-
-#ifndef _PODIUM_H_
-#define _PODIUM_H_
-
-#define PODIUM_MAJOR "0" // needs more revisions and use to reach 1.0 status
-#define PODIUM_MINOR "2" // vulkan module
-#define PODIUM_PATCH "2" // gamepad
-
-#define POAPI static inline
-#define PODEF static inline
-
-/*
- * Auto-detect platforms.
- */
-
-/* Windows */
-#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__)
- #ifndef PODIUM_WIN32
- #define PODIUM_WIN32
- #endif
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
-/* Apple */
-#elif defined(__APPLE__) || defined(__MACH__)
- #include <TargetConditionals.h>
- #ifndef PODIUM_APPLE
- #define PODIUM_APPLE
- #endif
- #if TARGET_OS_IPHONE
- #define PODIUM_IOS
- #else
- #define PODIUM_MACOS
- #endif
-/* Linux / BSD */
-#elif defined(__linux__) || defined(__FreeBSD__)
- #ifndef PODIUM_LINUX
- #define PODIUM_LINUX
- #endif
- #ifndef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 200112L
- #endif
-#endif
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <string.h> /* memcpy */
-#include <stdio.h> /* vsnprintf */
-
-/*
- * NOTE: The <REPLACE> comments are used by the build
- * script to know what includes to inline into the
- * final single header file!
- */
-
-#include "p_types.h" // <REPLACE>
-#include "p_log.h" // <REPLACE>
-#include "p_ds.h" // <REPLACE>
-
-/*
- * Main Platform Types (Keyboard, Events, Context, etc.)
- */
-
-typedef enum {
- P_KEYMOD_ALT = 0,
- P_KEYMOD_SHIFT,
- P_KEYMOD_CTRL,
- P_KEYMOD_CAPS,
-} P_KeyMod;
-
-typedef enum {
- P_KEY_UNKNOWN = 0,
- P_KEY_UP, P_KEY_DOWN, P_KEY_LEFT, P_KEY_RIGHT,
- P_KEY_SPACE, P_KEY_ESCAPE, P_KEY_ENTER,
- P_KEY_A, P_KEY_B, P_KEY_C, P_KEY_D, P_KEY_E, P_KEY_F, P_KEY_G, P_KEY_H, P_KEY_I,
- P_KEY_J, P_KEY_K, P_KEY_L, P_KEY_M, P_KEY_N, P_KEY_O, P_KEY_P, P_KEY_Q, P_KEY_R,
- P_KEY_S, P_KEY_T, P_KEY_U, P_KEY_V, P_KEY_W, P_KEY_X, P_KEY_Y, P_KEY_Z,
-} P_KeyCode;
-
-/* Platform event type */
-typedef enum {
- P_EVENT_NONE = 0,
- P_EVENT_KEY_DOWN,
- P_EVENT_KEY_UP,
- P_EVENT_WINDOW_CLOSE,
- P_EVENT_WINDOW_RESIZE,
- P_EVENT_POINTER,
- P_EVENT_CONTROLLER_CONNECTED,
- P_EVENT_CONTROLLER_DISCONNECTED,
-} P_EvenType;
-
-typedef enum {
- P_POINTER_MOVED = 0,
- P_POINTER_PRESSED,
- P_POINTER_RELEASED
-} P_PointerState;
-
-typedef struct {
- P_EvenType type;
- union {
- struct {P_KeyCode key; P_KeyMod mod; } key;
- struct { u32 width, height; } resize;
- struct { P_PointerState state; u32 button; u32 x, y; } pointer;
- };
-} P_Event;
-
-/*
- * Platform dependent functions to be implemented by each layer.
- */
-
-POAPI u64 p_get_time(void); // Get time in nanoseconds.
-POAPI void p_sleep_ns(i64 ns); // Sleep for nanoseconds.
-
-POAPI void p_stdout(void *msg, usize bytes); // Print buffer to stdout.
-PODEF void p_log_printf(P_Log_Level level, const char* src, ...); // Print buffer to stdout.
-
-
-POAPI void* p_file_alloc(const char *path, unsigned long *buf_size);
-POAPI bool p_file_exists(const char *path); // Check if file exists.
-POAPI usize p_file_size(const char *path); // Check file size.
-POAPI void p_file_load(const char *path, void *buf_ptr, unsigned long buf_size); // Load file to buffer.
-PODEF void p_file_write(const char *path, void *buf_ptr, unsigned long buf_size); // Write buffer to file.
-
-typedef struct P_Window_Impl P_Window;
-POAPI bool p_window_open(P_Window *win, int width, int height, const char *title); // Opens a window. Returns false on failure.
-POAPI void p_window_close(P_Window *win); // Close window.
-POAPI bool p_window_is_open(P_Window *win); // Check if window is open.
-POAPI void p_window_size(P_Window *win, int *window_width, int *window_height); // Get window size.
-POAPI void p_window_draw(P_Window *win, u32 *pixels, int width, int height); // Draw directly to the window's buffer. Normally much slower than using the GPU.
-POAPI bool p_window_poll_event(P_Window *win, P_Event *ev); // Returns true while there are events to poll. Write event data to a pointer.
-
-POAPI void p_audio_init(const int sample_rate, const int channels, const char *name, const char *desc);
-POAPI void p_audio_quit();
-POAPI void p_audio_write(const i16 *samples, usize count);
-
-/*
- * The Vulkan Module is platform specific
- */
-
-#ifdef P_MODULE_VULKAN
-#include <vulkan/vulkan.h>
-POAPI char** p_vulkan_get_extensions();
-POAPI bool p_vulkan_create_surface(P_Window *window, VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* out_surface);
-#endif
-
-/*
- * The Remaining Modules are PLATFORM INDEPENDENT!
- */
-
-#ifdef P_MODULE_STRING
-#include <p_string.h> // <REPLACE>
-#endif
-
-#ifdef P_MODULE_MATH
-#include <p_math.h> // <REPLACE>
-#endif
-
-#ifdef P_MODULE_ALLOC
-#include <p_allocators.h> // <REPLACE>
-#endif
-
-#endif /* _PODIUM_H_ */
-
-#ifdef PODIUM_IMPLEMENTATION
-#undef PODIUM_IMPLEMENTATION
-
-#if defined(PODIUM_SDL)
-/* #include "p_platform_sdl.c" */
-#elif defined(PODIUM_WIN32)
-#include "p_platform_win32.c" // <REPLACE>
-#elif defined(PODIUM_LINUX)
-#include "p_platform_linux.c" // <REPLACE>
-#endif /* linux */
-
-
-POAPI void* p_file_alloc(const char *path, unsigned long *buf_size) {
- if (p_file_exists(path) == false) {
- return NULL;
- }
-
- usize file_size = p_file_size(path);
- *buf_size = file_size;
-
- void *ptr = malloc(file_size);
- if (ptr) {
- p_file_load(path, ptr, file_size); // Load file to buffer.
- }
- return ptr;
-}
-
-
-/*
- * Import Module Code
- */
-
-#ifdef P_MODULE_STRING
-#include <p_string.c> // <REPLACE>
-#endif
-
-#ifdef P_MODULE_MATH
-#include <p_math.c> // <REPLACE>
-#endif
-
-#ifdef P_MODULE_ALLOC
-#include <p_allocators.c> // <REPLACE>
-#endif
-
-#define P_MAX_PRINTF_SIZE 1024
-PODEF void
-p_log_printf(P_Log_Level level, const char* src, ...)
-{
- static char out_message[P_MAX_PRINTF_SIZE];
- static u32 offset = P_PREFIX_LEN + 1;
-
- memcpy(out_message, p_prefix[level], P_PREFIX_LEN); /* prefixes have a fixed len */
- out_message[P_PREFIX_LEN] = ' '; /* write space */
-
- __builtin_va_list arg_ptr;
- va_start(arg_ptr, src);
- int len = vsnprintf(out_message+offset, P_MAX_PRINTF_SIZE-offset, src, arg_ptr); // append message
- va_end(arg_ptr);
-
- if (len < 0) len = 0;
- usize total_len = offset + len;
- if (total_len > P_MAX_PRINTF_SIZE) {
- total_len = P_MAX_PRINTF_SIZE;
- }
-
- p_stdout(out_message, total_len);
- p_stdout("\n", 1);
-}
-
-#endif // PODIUM_IMPLEMENTATION