summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-06-15 15:28:45 +0500
committerpryazha <pryadeiniv@mail.ru>2025-06-15 15:28:45 +0500
commite7f67b450d8034b532101445035d3b199e702621 (patch)
treed1193a6044d75800266cec11776358be7270cf8b
parent92850237f42cecfeba519bc15f7f5bb7a76cde5f (diff)
windows?
-rwxr-xr-xexample/build.sh17
-rwxr-xr-xexample/examplebin62744 -> 59280 bytes
-rw-r--r--example/example.c388
-rwxr-xr-xexample/example.exebin0 -> 315771 bytes
-rw-r--r--prb.h31
-rw-r--r--prb_arena.c48
-rw-r--r--prb_arena.h52
-rw-r--r--prb_linux.h69
-rw-r--r--prb_macros.h95
-rw-r--r--prb_math.c510
-rw-r--r--prb_math.h515
-rw-r--r--prb_string.c170
-rw-r--r--prb_string.h208
-rw-r--r--prb_sys.c52
-rw-r--r--prb_sys.h13
-rw-r--r--prb_types.h117
-rw-r--r--prb_windows.h75
17 files changed, 1078 insertions, 1282 deletions
diff --git a/example/build.sh b/example/build.sh
index 172aa69..de969e8 100755
--- a/example/build.sh
+++ b/example/build.sh
@@ -1,7 +1,14 @@
#!/bin/sh
-CFLAGS='-g -Wall'
-INCLUDE='-I..'
-LIBS='-lm'
+compiler='gcc'
+if [ $# -eq 1 ] ; then
+ if [ $1 = 'windows' ] ; then
+ compiler='x86_64-w64-mingw32-gcc'
+ fi
+fi
+cflags='-g -Wall'
+include='-I..'
+libs='-lm'
+path=`dirname $0`
set -x
-#tcc $CFLAGS $INCLUDE $LIBS -o example example.c && ./example
-gcc $CFLAGS $INCLUDE $LIBS -o example example.c && ./example
+cd $path
+$compiler $cflags $include -o example example.c $libs
diff --git a/example/example b/example/example
index cefef94..cdaf21e 100755
--- a/example/example
+++ b/example/example
Binary files differ
diff --git a/example/example.c b/example/example.c
index dc76ffb..6b0085a 100644
--- a/example/example.c
+++ b/example/example.c
@@ -1,276 +1,172 @@
#include "prb.h"
-typedef struct {
- S32 first;
- S32 second;
- B32 flags;
-} SomeStruct;
-
-typedef struct SLLNode {
- S32 val;
- struct SLLNode *next;
-} SLLNode;
-
-typedef struct DLLNode {
- S32 val;
- struct DLLNode *next;
- struct DLLNode *prev;
-} DLLNode;
-
-int main(void)
-{
- F32 verts[] = {
- 1.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 1.0f
- };
-
- ASSERT(v3a(1.0f).y);
-
- printf("OFFSETOF(SomeStruct, flags): %ld\n\n", OFFSETOF(SomeStruct, flags));
-
- F32 range_min = 0.0f,
- range_max = 1.0f,
- clamped_number = 1.5f,
- another_clamped_number = -0.2f;
-
- printf("CLAMPBOT(%f, %f): %f\n", range_min,
- another_clamped_number, CLAMPBOT(another_clamped_number, range_min));
- printf("CLAMPTOP(%f, %f): %f\n", range_max,
- clamped_number, CLAMPTOP(clamped_number, range_max));
+#define MAX_NODES 10
- printf("CLAMP(%f, %f, %f): %f\n", range_min, clamped_number, range_max,
- CLAMP(range_min, clamped_number, range_max));
- printf("CLAMP(%f, %f, %f): %f\n\n", range_min, another_clamped_number, range_max,
- CLAMP(range_min, another_clamped_number, range_max));
-
- F32 swap_test_first = 10.0f,
- swap_test_second = 20.0f;
+typedef struct {
+ i32 i32_element;
+ i16 i16_element;
+ u8 u8_element;
+} type_t;
- printf("Before SWAP: swap_test_first = %f, swap_test_second = %f\n",
- swap_test_first, swap_test_second);
- SWAP(F32, swap_test_first, swap_test_second);
- printf("After SWAP: swap_test_first = %f, swap_test_second = %f\n\n",
- swap_test_first, swap_test_second);
+typedef struct stack_node_t {
+ i32 value;
+ struct stack_node_t *next;
+} stack_node_t;
- SomeStruct some_stuct = { 10, 20, 30 };
- printf("SomeStruct: first: %d, second: %d, flags: %d\n",
- some_stuct.first, some_stuct.second, some_stuct.flags);
- MEM0(&some_stuct, sizeof(SomeStruct));
- printf("After MEM0(&some_stuct, sizeof(SomeStruct)):\n");
- printf("some_stuct: first: %d, second: %d, flags: %d\n\n",
- some_stuct.first, some_stuct.second, some_stuct.flags);
+typedef struct {
+ stack_node_t *first;
+ stack_node_t *last;
+} stack_t;
- some_stuct = (SomeStruct){ 10, 20, 30 };
- printf("some_stuct: first: %d, second: %d, flags: %d\n",
- some_stuct.first, some_stuct.second, some_stuct.flags);
- MEM0STRUCT(&some_stuct);
- printf("After MEM0STRUCT(&some_stuct):\n");
- printf("some_stuct: first: %d, second: %d, flags: %d\n\n",
- some_stuct.first, some_stuct.second, some_stuct.flags);
+typedef struct node_t {
+ i32 value;
+ struct node_t *next;
+ struct node_t *prev;
+} node_t;
- S32 dynamic_array_length = 10;
- U64 dynamic_array_size = dynamic_array_length*sizeof(S32);
- F32 *dynamic_array_first = malloc(dynamic_array_size);
- F32 *dynamic_array_second = malloc(dynamic_array_size);
+typedef struct {
+ node_t *first;
+ node_t *last;
+} list_t;
- printf("first dynamic array:\n");
- for (S32 i = 0; i < dynamic_array_length; ++i) {
- F32 *element = dynamic_array_first+i;
- *element = i+420;
- printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
- }
- printf("second dynamic array:\n");
- for (S32 i = 0; i < dynamic_array_length; ++i) {
- F32 *element = dynamic_array_second+i;
- printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
- }
- MEMCPY(dynamic_array_second, dynamic_array_first, dynamic_array_size);
- printf("After MEMCPY(dynamic_array_second, dynamic_array_first, dynamic_array_size):\n");
- printf("second dynamic array:\n");
- for (S32 i = 0; i < dynamic_array_length; ++i) {
- F32 *element = dynamic_array_second+i;
- printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
+i32 main(void)
+{
+ // os
+ printf("os: ");
+ switch (OS) {
+ case OS_LINUX:
+ printf("linux\n");
+ break;
+ case OS_WINDOWS:
+ printf("windows\n");
+ break;
+ default:
+ printf("unsupported\n");
+ return 1;
}
- S32 memory_match = MEMMATCH(dynamic_array_first, dynamic_array_second, dynamic_array_size);
- printf("And MEMMATCH(dynamic_array_first, dynamic_array_second, dynamic_array_size): %d\n\n", memory_match);
- free(dynamic_array_first);
- free(dynamic_array_second);
- printf("Linked Lists:\n");
- printf("Singly linked list: ");
- S32 list_length = 5;
- U64 list_size = list_length*sizeof(SLLNode);
- SLLNode *sllist = malloc(list_size);
- SLLNode *sllfirst = 0;
- SLLNode *slllast = 0;
- for (S32 i = 0; i < list_length; ++i) {
- SLLNode *new = sllist+i;
- new->val = i;
- SLLPUSH(sllfirst, slllast, new);
+ arena_t path_arena = alloc_arena(MAX_PATH);
+ char *dir = sys_getbindir(&path_arena);
+ printf("bin directory \"%s\"\n", dir);
+
+ // macros
+ u64 offset = offsetof(type_t, u8_element);
+ assert(offset == 6);
+ printf("offsetof(type_t, u8_element) = %lu\n", offset);
+ i32 clamped = clamp(0, -1, 1);
+ assert(clamped == 0);
+ printf("clamp(0, -1, 1) = %d\n", clamped);
+ clamped = clamp(0, 2, 1);
+ assert(clamped == 1);
+ printf("clamp(0, 2, 1) = %d\n", clamped);
+
+ i32 nums[] = {0, 1, 2, 3};
+ printf("mem0: [");
+ for (i32 i = 0; i < array_count(nums); ++i)
+ printf("%x%s", nums[i], (i == array_count(nums)-1) ? "" : ", ");
+ memzero(nums, sizeof(nums));
+ printf("] -> [");
+ for (i32 i = 0; i < array_count(nums); ++i) {
+ assert(!nums[i]);
+ printf("%x%s", nums[i], (i == array_count(nums)-1) ? "" : ", ");
}
- for (SLLNode *node = sllfirst; node; node = node->next)
- printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
- SLLPOP(sllfirst, slllast);
- printf("After SLLPOP(sllfirst, slllast): ");
- for (SLLNode *node = sllfirst; node; node = node->next)
- printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
- free(sllist);
+ printf("]\n");
- printf("Doubly linked list: ");
- list_length = 8;
- list_size = list_length*sizeof(DLLNode);
- DLLNode *dllist = malloc(list_size);
- DLLNode *dllfirst = 0;
- DLLNode *dlllast = 0;
- for (S32 i = 0; i < list_length; ++i) {
- DLLNode *new = dllist+i;
- new->val = i;
- DLLPUSHBACK(dllfirst, dlllast, new);
- }
- for (DLLNode *node = dllfirst; node; node = node->next)
- printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
- printf("Remove odd numbers: ");
- for (DLLNode *node = dllfirst; node; node = node->next)
- if (node->val % 2 == 1)
- DLLREMOVE(dllfirst, dlllast, node);
- for (DLLNode *node = dllfirst; node; node = node->next)
- printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
- free(dllist);
printf("\n");
- printf("I'm pretty sure the vectors are fine.\nAt least for the last few months :)\n\n");
+ printf("Singly linked list (stack for example):\n");
- printf("Matrices:\n");
- printf("Identity:\n");
- MAT4 m = MAT4_IDENTITY;
- printmat4(m);
- m = scalemat4(m, v3a(10.0f));
- m = translmat4(m, v3a(1.0f));
- m = translmat4(m, v3(0.0f, 68.0f, 0.0f));
- printmat4(m);
- printf("Determinant: %f\n", detmat4(m));
- printf("Transpose:\n"); printmat4(transpmat4(m));
- printf("mat4rotate(MAT4_IDENTITY, v3(0.0f, 45.0f, 0.0f)):\n");
- printmat4(rotatemat4(MAT4_IDENTITY, v3(0.0f, 45.0f, 0.0f)));
+ stack_node_t stack_nodes[MAX_NODES];
+ stack_t stack = {0};
+ for (i32 i = 0; i < MAX_NODES; ++i) {
+ stack_node_t *node = stack_nodes+i;
+ node->value = i;
+ sllpush(stack.first, stack.last, node);
+ }
- sys_printf("Example of using sys_printf without args\n");
- sys_printf("And with some of number : %x : <- like that or string : %s : for example\n", 69, "yeah");
+ for (stack_node_t *node = stack.first; node; node = node->next)
+ printf("%d%s", node->value, ((node->next) ? " -> " : "\n"));
- printf("Using Arenas:\n");
+ sllpop(stack.first, stack.last);
- Arena *a;
- U8 *df,
- *ds;
- Arena *tmpa;
+ printf("After pop:\n");
+ for (stack_node_t *node = stack.first; node; node = node->next)
+ printf("%d%s", node->value, ((node->next) ? " -> " : "\n"));
- a = alloc_arena(10);
- df = push_arena(a, 5);
- memset(df, 5, 5);
- ds = push_arena(a, 5);
- memset(ds, 10, 5);
-
- tmpa = alloc_arena(0);
-
- flsprint(FLSLIT("|"));
- for (S32 i = 0; i < 10; i++)
- flsprint(flspushf(tmpa, "%x%s", df[i], ((i+1) % 5 == 0) ? "|" : " "));
- flsprint(FLSLIT("\n"));
-
- release_arena(tmpa);
- release_arena(a);
-
- a = alloc_arena(0);
- SLLNode *first = 0;
- SLLNode *last = 0;
- S32 node_count = 10;
- for (S32 i = 0; i < node_count; ++i) {
- SLLNode *new = push_arena(a, sizeof(SLLNode));
- new->val = i;
- SLLPUSH(first, last, new);
+ node_t nodes[MAX_NODES];
+ list_t list = {0};
+ for (i32 i = 0; i < MAX_NODES; ++i) {
+ node_t *node = nodes+i;
+ node->value = i;
+ dllpushback(list.first, list.last, node);
}
- for (SLLNode *node = first; node; node = node->next)
- printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
- release_arena(a);
-
- a = alloc_arena(sizeof(verts));
- S32 verts_count = ARRCNT(verts);
- F32 *dynamic_verts = push_arena(a, sizeof(verts));
- MEM0(dynamic_verts, verts_count*sizeof(F32));
- for (S32 i = 0; i < verts_count; ++i) {
- F32 *vert = dynamic_verts+i;
- printf("%f%c", *vert, (i == verts_count-1) ? '\n' : ' ');
- }
- release_arena(a);
- printf("\n");
-
- Arena *str_arena = alloc_arena(0);
- printf("Strings:\n");
- char *cstr = "This is a C str\n";
- FLS str = flsfromcstr(cstr);
- str = flschopstart(str, 10);
- cstr = flstocstr(a, str);
- printf("%s", cstr);
- flsprint(str);
- FLS choped_str = flschopend(str, 3);
- flsprint(choped_str);
+
+ printf("Doubly linked list:\n");
+ for (node_t *node = list.first; node; node = node->next)
+ printf("%d%s", node->value, ((node->next) ? " -> " : "\n"));
+
+ printf("Remove odd numbers:\n");
+ for (node_t *node = list.first; node; node = node->next)
+ if (node->value % 2 == 1)
+ dllremove(list.first, list.last, node);
+
+ for (node_t *node = list.first; node; node = node->next)
+ printf("%d%s", node->value, ((node->next) ? " -> " : "\n"));
+
printf("\n");
- FLSList *list = flslist(str_arena);
- flslistpush(str_arena, list, str, 0);
- flslistpush(str_arena, list, flsfromcstr("test"), 0);
- flslistpush(str_arena, list, flsfromcstr("and this is also a test\n"), 0);
- flslistpush(str_arena, list, flsfromcstr("Kinda works!"), 1);
- printf("FLSList: ");
- flslistprint(list);
- release_arena(str_arena);
- flslistprint(list);
- str_arena = alloc_arena(KB(10));
- U32 memory_size = 512;
- U32 count = memory_size/sizeof(S32);
- S32 *some = push_arena(str_arena, memory_size);
- printf("str_arena(size): %ld\nMemory:\n", str_arena->cap);
- for (S32 i = 0; i < count; i++) {
- S32 *e = some+i;
- *e = 69;
- printf("%d: %d%c", i, *e, ((i == count-1) ? '\n' : ' '));
- }
- printf("Memory used: %lu\n", str_arena->used);
- printf("Remaining memory: %lu\n",
- str_arena->cap-str_arena->used);
+ printf("I'm pretty sure the vectors are fine\n");
+ printf("At least for the last few months :)\n\n");
- pop_arena(str_arena, memory_size);
+ printf("Arenas:\n");
- printf("After arena pop\n");
- printf("Memory used: %lu\n", str_arena->used);
- printf("Remaining memory: %lu\n",
- str_arena->cap-str_arena->used);
- printf("some ptr is %s\n", some ? "not null" : "null");
- printf("str_arena(size): %lu\nMemory:\n", str_arena->cap);
-
- FLS new_str = flspushf(str_arena, "Test of the formatted string: %d\n", 69);
- flsprint(new_str);
-
- list = flslist(str_arena);
- flslistpushf(str_arena, list, 0, "This is a list %d", 34);
- flslistpushf(str_arena, list, 0, " of formatted strings: %d", 35);
- flslistpushf(str_arena, list, 1, "And you can push to the start");
- /* TODO(pryazha): Think about simpler way of using string literals.
- * Maybe you don't need to, I dunno */
- flslistpushf(str_arena, list, 1, "The most interesting part is that you can include the whole string like that: %*s\n",
- FLSEXP(FLSLIT("Absolutely random string with absolutely random content (or not).")));
- flslistprint(list);
+ arena_t arena = alloc_arena(10);
+ u8 *first = push_arena(&arena, 5);
+ prb_memset(first, 5, 5);
+ u8 *second = push_arena(&arena, 5);
+ prb_memset(second, 10, 5);
+ printf("|");
+ for (i32 i = 0; i < 10; i++)
+ printf("%x%s", first[i], ((i+1) % 5 == 0) ? "|" : " ");
+ printf("\n");
+ release_arena(&arena);
- release_arena(str_arena);
+ printf("Strings:\n");
- a = alloc_arena(MB(1));
- flsprint(FLSLIT("build.sh content:\n"));
- FLS file_content = fls_read_entire_file(a, FLSLIT("build.sh"));
- if (file_content.p)
- flsprint(file_content);
+ arena_t str_arena = alloc_arena(0);
+ str8_list_t strlist = {0};
+ str8_list_push(&str_arena, &strlist, 0, str8lit("first "));
+ str8_list_push(&str_arena, &strlist, 0, str8lit("second "));
+ str8_list_push(&str_arena, &strlist, 0, str8lit("third\n"));
+ str8_print(str8lit("strlist: "));
+ str8_list_print(&strlist);
+
+ str8_t fstr = str8_pushf(&str_arena, "Formatted string: %d\n", 69);
+ str8_print(fstr);
+
+ memzero_struct(&strlist);
+ str8_list_pushf(&str_arena, &strlist, 0, "first %d -> ", 34);
+ str8_list_pushf(&str_arena, &strlist, 0, "second: %d -> ", 35);
+ str8_list_pushf(&str_arena, &strlist, 0, "sum: %d\n", 34+35);
+ str8_list_pushf(&str_arena, &strlist, 1, "%s", "To the front -> ");
+
+ str8_print(str8lit("Formatted string list:\n"));
+ str8_list_print(&strlist);
+
+ str8_t catstr = str8_list_join(&str_arena, &strlist);
+ str8_print(str8lit("Concatenated string list:\n"));
+ str8_print(catstr);
+
+ release_arena(&str_arena);
+
+ const char *filename = "build.sh";
+ arena = alloc_arena(megabytes(1));
+ u8 *content;
+ if (sys_read_file(&arena, &content, filename))
+ printf("%s content:\n%s", filename, content);
else
- flsprint(FLSLIT("failed to read build.sh\n"));
- release_arena(a);
+ printf("failed to read %s\n", filename);
+ release_arena(&arena);
return(0);
}
diff --git a/example/example.exe b/example/example.exe
new file mode 100755
index 0000000..ae02648
--- /dev/null
+++ b/example/example.exe
Binary files differ
diff --git a/prb.h b/prb.h
index f09df2d..fad7ff0 100644
--- a/prb.h
+++ b/prb.h
@@ -1,27 +1,30 @@
#ifndef PRB_H
#define PRB_H
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
#include <stdint.h>
+#include <math.h>
#include <stdarg.h>
-#include <unistd.h>
+#include <stddef.h>
+#include <stdio.h>
-#include "prb_macros.h"
#include "prb_types.h"
-
+#include "prb_macros.h"
#include "prb_math.h"
-#include "prb_math.c"
-
#include "prb_arena.h"
-#include "prb_arena.c"
-
+#include "prb_sys.h"
#include "prb_string.h"
-#include "prb_string.c"
-#include "prb_sys.h"
-#include "prb_sys.c"
+#define OS_NONE 0
+#define OS_WINDOWS 1
+#define OS_LINUX 2
+
+#if defined(__linux)
+#define OS OS_LINUX
+#include "prb_linux.h"
+#elif defined(__WIN64)
+#define OS OS_WINDOWS
+#include <windows.h>
+#include "prb_windows.h"
+#endif
#endif /* PRB_H */
diff --git a/prb_arena.c b/prb_arena.c
deleted file mode 100644
index 1938dec..0000000
--- a/prb_arena.c
+++ /dev/null
@@ -1,48 +0,0 @@
-Arena *alloc_arena(U64 cap)
-{
- Arena *a;
-
- /* TODO(pryazha): Use OS specific memory allocator
- * (like VirtualAlloc on Windows or mmap on Linux)
- */
- a = malloc(sizeof(Arena));
- ASSERT(a);
-
- if (!cap)
- cap = PRB_DEFAULT_ALLOC_SIZE;
-
- a->mem = malloc(cap);
- ASSERT(a->mem);
- a->cap = cap;
- a->used = 0;
-
- return a;
-}
-
-void release_arena(Arena *a)
-{
- free(a->mem);
- MEM0STRUCT(a);
- free(a);
-}
-
-void *push_arena(Arena *a, U64 size)
-{
- ASSERT(a);
- ASSERT(a->used+size <= a->cap);
-
- void *r;
-
- r = a->mem+a->used;
- a->used += size;
-
- return r;
-}
-
-void pop_arena(Arena *a, U64 size)
-{
- ASSERT(a);
- U64 clamped;
- clamped = CLAMPTOP(size, a->used);
- a->used = a->used-clamped;
-}
diff --git a/prb_arena.h b/prb_arena.h
index 2d3453f..0a6de9b 100644
--- a/prb_arena.h
+++ b/prb_arena.h
@@ -1,6 +1,48 @@
-#define PRB_DEFAULT_ALLOC_SIZE KB(4)
+#define DEFAULT_ARENA_SIZE kilobytes(4)
-Arena *alloc_arena(U64 cap);
-void release_arena(Arena *a);
-void *push_arena(Arena *a, U64 size);
-void pop_arena(Arena *a, U64 size);
+arena_t alloc_arena(u64 capacity)
+{
+ void *sys_alloc(u64 length);
+
+ /* TODO(pryazha): Find reasonable maximum capacity through testing */
+ assert(capacity <= (u64)gigabytes(16));
+
+ if (!capacity)
+ capacity = DEFAULT_ARENA_SIZE;
+
+ /* TODO(pryazha): Use OS specific memory allocator
+ * (like VirtualAlloc on Windows or mmap on Linux)
+ */
+ void *memory = sys_alloc(capacity);
+ assert(memory);
+
+ arena_t arena = {memory, capacity, 0};
+
+ return arena;
+}
+
+void release_arena(arena_t *arena)
+{
+ void sys_free(void *memory, u64 length);
+
+ assert(arena);
+ sys_free(arena->memory, arena->capacity);
+ arena->memory = 0;
+ arena->capacity = 0;
+ arena->used = 0;
+}
+
+void *push_arena(arena_t *arena, u64 size)
+{
+ assert(arena);
+ assert(arena->used + size <= arena->capacity);
+ void *memory = arena->memory + arena->used;
+ arena->used += size;
+ return memory;
+}
+
+void pop_arena(arena_t *arena, u64 size)
+{
+ assert(arena);
+ arena->used -= min(size, arena->used);
+}
diff --git a/prb_linux.h b/prb_linux.h
new file mode 100644
index 0000000..3acc229
--- /dev/null
+++ b/prb_linux.h
@@ -0,0 +1,69 @@
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+void *sys_alloc(u64 length)
+{
+ assert(length);
+ void *result = mmap(0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ return result;
+}
+
+void sys_free(void *memory, u64 length)
+{
+ assert(memory);
+ assert(length);
+ munmap(memory, length);
+}
+
+u64 sys_read_file(arena_t *arena, char **buffer, const char *filename)
+{
+ FILE *file = fopen(filename, "rb");
+ if (!file)
+ return 0;
+
+ if (fseek(file, 0, SEEK_END) == -1)
+ goto error;
+ long len = ftell(file);
+ if (!len || (len == -1))
+ goto error;
+ if (fseek(file, 0, SEEK_SET) == -1)
+ goto error;
+
+ *buffer = push_arena(arena, len + 1);
+ if (!fread(*buffer, 1, len, file)) {
+ pop_arena(arena, len + 1);
+ *buffer = 0;
+ goto error;
+ }
+ (*buffer)[len] = 0;
+ fclose(file);
+
+ return len;
+error:
+ fclose(file);
+ *buffer = 0;
+ return 0;
+}
+
+char *sys_getbindir(arena_t *arena)
+{
+ char path[MAX_PATH];
+ i64 len = readlink("/proc/self/exe", path, MAX_PATH - 1);
+ if (len <= 0)
+ return 0;
+
+ path[len] = 0;
+
+ char *dir = strrchr(path, '/');
+ assert(dir);
+ assert(dir > path);
+
+ len = dir - path;
+ dir = push_arena(arena, len + 1);
+ prb_memmove(dir, path, len);
+ dir[len] = 0;
+
+ return dir;
+}
diff --git a/prb_macros.h b/prb_macros.h
index 5a38ae4..8324919 100644
--- a/prb_macros.h
+++ b/prb_macros.h
@@ -1,55 +1,54 @@
-#ifndef PRB_MACROS_H
-#define PRB_MACROS_H
+/*
+#ifndef assert
+#define assert(expr) if (!(expr)) { *(int *)0 = 0; }
+#endif
+*/
+#include <assert.h>
-#define ASSERT(E) if (!(E)) { *(int *)0 = 0; }
+#define array_count(array) (sizeof(array)/sizeof(*(array)))
-#define ARRCNT(A) (sizeof(A)/sizeof(*(A)))
+#ifndef offsetof
+#define offsetof(type, element) ((size_t)(&(((type *)0)->element)))
+#endif
-#define OFFSETOF(T, E) ((size_t)(&(((T *)(0))->E)))
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
-#define MIN(A, B) (((A) < (B)) ? (A) : (B))
-#define MAX(A, B) (((A) > (B)) ? (A) : (B))
+#define clamp(a, x, b) \
+ (((x) < (a)) ? (a) : \
+ (((x) > (b)) ? (b) : (x)))
-#define CLAMP(A, X, B) (((X) < (A)) ? (A) : \
- (((X) > (B)) ? (B) : (X)))
-#define CLAMPTOP(A, B) MIN(A, B)
-#define CLAMPBOT(A, B) MAX(A, B)
-
-#define SWAP(T, A, B) { T tmp = A; A = B; B = tmp; }
+#define swap(type, a, b) { type tmp = (a); (a) = (b); (b) = tmp; }
/* NOTE(pryazha): Memory */
-#define MEM0(P, N) memset((P), 0, (N))
-#define MEM0STRUCT(P) MEM0((P), sizeof(*(P)))
-
-#define MEMCPY(D, S, N) memmove((D), (S), (N))
-
-#define MEMMATCH(A, B, N) (memcmp((A), (B), (N)) == 0)
-
-#define KB(N) N*1024
-#define MB(N) KB(N)*1024
-#define GB(N) MB(N)*1024
-
-/* NOTE(pryazha): Singly-linked list */
-#define SLLPUSH(F, L, N) \
- ((F) == 0 ? \
- ((F) = (L) = (N), (N)->next = 0) : \
- ((L)->next = (N), (L) = (N), (N)->next = 0))
-#define SLLPOP(F, L) \
- ((F) == (L) ? \
- ((F) = (L) = 0) : \
- ((F) = (F)->next))
-
-/* NOTE(pryazha): Doubly-linked list */
-#define DLLPUSHBACK_NP(F, L, N, next, prev) \
- ((F) == 0 ? \
- ((F) = (L) = (N), (N)->next = (N)->prev = 0) : \
- ((N)->prev = (L), (L)->next = (N), (L) = (N), (N)->next = 0))
-#define DLLPUSHBACK(F, L, N) DLLPUSHBACK_NP(F, L, N, next, prev)
-#define DLLPUSHFRONT(F, L, N) DLLPUSHBACK_NP(L, F, N, prev, next)
-#define DLLREMOVE(F, L, N) \
- ((F) == (N) ? \
- ((F) == (L) ? (F) = (L) = 0 : ((F) = (F)->next, (F)->prev = 0)) : \
- ((L) == (N) ? ((L) = (L)->prev, (L)->next = 0) : \
- ((N)->next->prev = (N)->prev, (N)->prev->next = (N)->next)))
-
-#endif /* PRB_MACROS_H */
+#define memzero(ptr, size) prb_memset((ptr), 0, (size))
+#define memzero_struct(ptr) memzero((ptr), sizeof(*(ptr)))
+
+#define kilobytes(n) n*1024
+#define megabytes(n) kilobytes(n)*1024
+#define gigabytes(n) megabytes(n)*1024
+
+/* NOTE(pryazha): Singly linked list */
+#define sllpush(first, last, node) \
+ ((first) == 0 ? \
+ ((first) = (last) = (node), (node)->next = 0) : \
+ ((last)->next = (node), (last) = (node), (node)->next = 0))
+#define sllpop(first, last) \
+ ((first) == (last) ? \
+ ((first) = (last) = 0) : \
+ ((first) = (first)->next))
+
+/* NOTE(pryazha): Doubly linked list */
+#define dllpushback_np(first, last, node, next, prev) \
+ ((first) == 0 ? \
+ ((first) = (last) = (node), (node)->next = (node)->prev = 0) : \
+ ((node)->prev = (last), (last)->next = (node), (last) = (node), (node)->next = 0))
+#define dllpushback(first, last, node) dllpushback_np(first, last, node, next, prev)
+#define dllpushfront(first, last, node) dllpushback_np(last, first, node, prev, next)
+
+#define dllremove(first, last, node) \
+ ((first) == (node) ? \
+ ((first) == (last) ? (first) = (last) = 0 : \
+ ((first) = (first)->next, (first)->prev = 0)) : \
+ ((last) == (node) ? ((last) = (last)->prev, (last)->next = 0) : \
+ ((node)->next->prev = (node)->prev, (node)->prev->next = (node)->next)))
diff --git a/prb_math.c b/prb_math.c
deleted file mode 100644
index 2efb091..0000000
--- a/prb_math.c
+++ /dev/null
@@ -1,510 +0,0 @@
-F32 f32sin(F32 a)
-{
- F32 r;
- r = sinf(a);
- return r;
-}
-
-F32 f32cos(F32 a)
-{
- F32 r;
- r = cosf(a);
- return r;
-}
-
-F32 f32tan(F32 a)
-{
- F32 r;
- r = tanf(a);
- return r;
-}
-
-F32 f32sqrt(F32 a)
-{
- F32 r;
- r = sqrtf(a);
- return r;
-}
-
-/* NOTE(pryazha): Vectors */
-V2 v2(F32 x, F32 y)
-{
- V2 r;
- r.x = x;
- r.y = y;
- return r;
-}
-
-V2 v2a(F32 x)
-{
- V2 r;
- r = v2(x, x);
- return r;
-}
-
-V2 invv2(V2 a)
-{
- V2 r;
- r = v2(-a.x, -a.y);
- return r;
-}
-
-V2 addv2(V2 a, V2 b)
-{
- V2 r;
- r = v2(a.x+b.x, a.y+b.y);
- return r;
-}
-
-V2 subv2(V2 a, V2 b)
-{
- V2 r;
- r = v2(a.x-b.x, a.y-b.y);
- return r;
-}
-
-V2 scalefv2(V2 a, F32 s)
-{
- V2 r;
- r = v2(a.x*s, a.y*s);
- return r;
-}
-
-V2 scalev2(V2 a, V2 s)
-{
- V2 r;
- r = v2(a.x*s.x, a.y*s.y);
- return r;
-}
-
-F32 dotv2(V2 a, V2 b)
-{
- F32 r;
- r = a.x*b.x+a.y*b.y;
- return r;
-}
-
-F32 len2v2(V2 a)
-{
- F32 r;
- r = dotv2(a, a);
- return r;
-}
-
-F32 lenv2(V2 a)
-{
- F32 r;
- r = f32sqrt(len2v2(a));
- return r;
-}
-
-V2 normv2(V2 a)
-{
- F32 len;
- V2 r;
-
- r = V2_ZERO;
- len = lenv2(a);
- if (len)
- r = v2(a.x/len, a.y/len);
-
- return r;
-}
-
-void printv2(V2 a)
-{
- fprintf(stdout, "{%f, %f}T\n", a.x, a.y);
-}
-
-V3 v3(F32 x, F32 y, F32 z)
-{
- V3 r;
- r.x = x;
- r.y = y;
- r.z = z;
- return r;
-}
-
-V3 v3a(F32 x)
-{
- V3 r;
- r = v3(x, x, x);
- return r;
-}
-
-V3 v3fromv2(V2 a)
-{
- V3 r;
- r = v3(a.x, a.y, 0.0f);
- return r;
-}
-
-V3 v3fromv4(V4 a)
-{
- V3 r;
- r = v3(a.x, a.y, a.z);
- return r;
-}
-
-V3 invv3(V3 a)
-{
- V3 r;
- r = v3(-a.x, -a.y, -a.z);
- return r;
-}
-
-V3 addv3(V3 a, V3 b)
-{
- V3 r;
- r = v3(a.x+b.x, a.y+b.y, a.z+b.z);
- return r;
-}
-
-V3 subv3(V3 a, V3 b)
-{
- V3 r;
- r = v3(a.x-b.x, a.y-b.y, a.z-b.z);
- return r;
-}
-
-V3 scalefv3(V3 a, F32 s)
-{
- V3 r;
- r = v3(a.x*s, a.y*s, a.z*s);
- return r;
-}
-
-V3 scalev3(V3 a, V3 s)
-{
- V3 r;
- r = v3(a.x*s.x, a.y*s.y, a.z*s.z);
- return r;
-}
-
-F32 dotv3(V3 a, V3 b)
-{
- F32 r;
- r = a.x*b.x + a.y*b.y + a.z*b.z;
- return r;
-}
-
-V3 crossv3(V3 left, V3 right)
-{
- V3 r;
- r = v3((left.y*right.z-right.y*left.z),
- (right.x*left.z-left.x*right.z),
- (left.x*right.y-right.x*left.y));
- return r;
-}
-
-F32 len2v3(V3 a)
-{
- F32 r;
- r = dotv3(a, a);
- return r;
-}
-
-F32 lenv3(V3 a)
-{
- F32 r;
- r = f32sqrt(len2v3(a));
- return r;
-}
-
-V3 normv3(V3 a)
-{
- F32 len;
- V3 r;
-
- r = V3_ZERO;
- len = lenv3(a);
- if (len)
- r = v3(a.x/len, a.y/len, a.z/len);
-
- return r;
-}
-
-void printv3(V3 a)
-{
- fprintf(stdout, "{%f, %f, %f}T\n", a.x, a.y, a.z);
-}
-
-V4 v4(F32 x, F32 y, F32 z, F32 w)
-{
- V4 r;
- r.x = x;
- r.y = y;
- r.z = z;
- r.w = w;
- return r;
-}
-
-V4 v4a(F32 x)
-{
- V4 r;
- r = v4(x, x, x, x);
- return r;
-}
-
-V4 v4fromv3(V3 a)
-{
- V4 r;
- r = v4(a.x, a.y, a.z, 0.0f);
- return r;
-}
-
-V4 invv4(V4 a)
-{
- V4 r;
- r = v4(-a.x, -a.y, -a.z, -a.w);
- return r;
-}
-
-V4 addv4(V4 a, V4 b)
-{
- V4 r;
- r = v4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
- return r;
-}
-
-V4 subv4(V4 a, V4 b)
-{
- V4 r;
- r = v4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
- return r;
-}
-
-V4 scalefv4(V4 a, F32 s)
-{
- V4 r;
- r = v4(a.x*s, a.y*s, a.z*s, a.w*s);
- return r;
-}
-
-V4 scalev4(V4 a, V4 s)
-{
- V4 r;
- r = v4(a.x*s.x, a.y*s.y, a.z*s.z, a.w*s.w);
- return r;
-}
-
-F32 dotv4(V4 a, V4 b)
-{
- F32 r;
- r = a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w;
- return r;
-}
-
-F32 len2v4(V4 a)
-{
- F32 r;
- r = dotv4(a, a);
- return r;
-}
-
-F32 lenv4(V4 a)
-{
- F32 r;
- r = f32sqrt(len2v4(a));
- return r;
-}
-
-V4 normv4(V4 a)
-{
- F32 len;
- V4 r;
-
- r = V4_ZERO;
- len = lenv4(a);
- if (len)
- r = v4(a.x/len, a.y/len, a.z/len, a.w/len);
-
- return r;
-}
-
-void printv4(V4 a)
-{
- fprintf(stdout, "{%f, %f, %f, %f}T\n", a.x, a.y, a.z, a.w);
-}
-
-/* NOTE(pryazha): Matrices */
-F32 detmat4(MAT4 m)
-{
- F32 r, m00minor, m01minor, m02minor, m03minor;
-
- F32 m00 = m.m0.x, m10 = m.m0.y, m20 = m.m0.z, m30 = m.m0.w;
- F32 m01 = m.m1.x, m11 = m.m1.y, m21 = m.m1.z, m31 = m.m1.w;
- F32 m02 = m.m2.x, m12 = m.m2.y, m22 = m.m2.z, m32 = m.m2.w;
- F32 m03 = m.m3.x, m13 = m.m3.y, m23 = m.m3.z, m33 = m.m3.w;
-
- m00minor = ((m11*m22*m33)+(m12*m23*m31)+(m21*m32*m13)-
- (m31*m22*m13)-(m21*m12*m33)-(m11*m32*m23));
-
- m01minor = ((m10*m22*m33)+(m12*m23*m30)+(m20*m32*m13)-
- (m13*m22*m30)-(m23*m32*m10)-(m12*m20*m33));
-
- m02minor = ((m10*m21*m33)+(m20*m31*m13)+(m11*m23*m31)-
- (m13*m21*m30)-(m23*m31*m10)-(m11*m20*m33));
-
- m03minor = ((m10*m21*m32)+(m20*m31*m12)+(m11*m22*m30)-
- (m12*m21*m30)-(m11*m20*m32)-(m22*m31*m10));
-
- r = m00*m00minor + m01*m01minor - m02*m02minor + m03*m03minor;
-
- return r;
-}
-
-MAT4 transpmat4(MAT4 m)
-{
- MAT4 r;
-
- r = m;
-
- SWAP(F32, r.m0.y, r.m1.x);
- SWAP(F32, r.m0.z, r.m2.x);
- SWAP(F32, r.m0.w, r.m3.x);
-
- SWAP(F32, r.m1.z, r.m2.y);
- SWAP(F32, r.m1.w, r.m3.y);
-
- SWAP(F32, r.m2.w, r.m3.z);
-
- return r;
-}
-
-MAT4 mulmat4(MAT4 left, MAT4 right)
-{
- F32 l00, l01, l02, l03;
- F32 l10, l11, l12, l13;
- F32 l20, l21, l22, l23;
- F32 l30, l31, l32, l33;
-
- F32 r00, r01, r02, r03;
- F32 r10, r11, r12, r13;
- F32 r20, r21, r22, r23;
- F32 r30, r31, r32, r33;
-
- MAT4 r;
-
- l00 = left.m0.x; l01 = left.m0.y; l02 = left.m0.z; l03 = left.m0.w;
- l10 = left.m1.x; l11 = left.m1.y; l12 = left.m1.z; l13 = left.m1.w;
- l20 = left.m2.x; l21 = left.m2.y; l22 = left.m2.z; l23 = left.m2.w;
- l30 = left.m3.x; l31 = left.m3.y; l32 = left.m3.z; l33 = left.m3.w;
-
- r00 = right.m0.x; r01 = right.m0.y; r02 = right.m0.z; r03 = right.m0.w;
- r10 = right.m1.x; r11 = right.m1.y; r12 = right.m1.z; r13 = right.m1.w;
- r20 = right.m2.x; r21 = right.m2.y; r22 = right.m2.z; r23 = right.m2.w;
- r30 = right.m3.x; r31 = right.m3.y; r32 = right.m3.z; r33 = right.m3.w;
-
- r.m0.x = l00*r00+l10*r01+l20*r02+l30*r03;
- r.m0.y = l01*r00+l11*r01+l21*r02+l31*r03;
- r.m0.z = l02*r00+l12*r01+l22*r02+l32*r03;
- r.m0.w = l03*r00+l13*r01+l23*r02+l33*r03;
-
- r.m1.x = l00*r10+l10*r11+l20*r12+l30*r13;
- r.m1.y = l01*r10+l11*r11+l21*r12+l31*r13;
- r.m1.z = l02*r10+l12*r11+l22*r12+l32*r13;
- r.m1.w = l03*r10+l13*r11+l23*r12+l33*r13;
-
- r.m2.x = l00*r20+l10*r21+l20*r22+l30*r23;
- r.m2.y = l01*r20+l11*r21+l21*r22+l31*r23;
- r.m2.z = l02*r20+l12*r21+l22*r22+l32*r23;
- r.m2.w = l03*r20+l13*r21+l23*r22+l33*r23;
-
- r.m3.x = l00*r30+l10*r31+l20*r32+l30*r33;
- r.m3.y = l01*r30+l11*r31+l21*r32+l31*r33;
- r.m3.z = l02*r30+l12*r31+l22*r32+l32*r33;
- r.m3.w = l03*r30+l13*r31+l23*r32+l33*r33;
-
- return r;
-}
-
-MAT4 translmat4(MAT4 m, V3 v)
-{
- MAT4 t, r;
-
- t = MAT4_IDENTITY;
- t.m3.x = v.x;
- t.m3.y = v.y;
- t.m3.z = v.z;
- r = mulmat4(t, m);
-
- return r;
-}
-
-MAT4 scalemat4(MAT4 m, V3 v)
-{
- MAT4 s, r;
-
- s = MAT4_IDENTITY;
- s.m0.x = v.x;
- s.m1.y = v.y;
- s.m2.z = v.z;
- r = mulmat4(s, m);
-
- return r;
-}
-
-MAT4 rotateaxismat4(V3 x, V3 y, V3 z)
-{
- MAT4 r;
-
- r = MAT4_IDENTITY;
- r.m0 = v4(x.x, x.y, x.z, 0.0f);
- r.m1 = v4(y.x, y.y, y.z, 0.0f);
- r.m2 = v4(z.x, z.y, z.z, 0.0f);
-
- return r;
-}
-
-/*
- * NOTE(pryazha): Angles in degrees
- * | 1 0 0 | | cy 0 sy | | cz -sz 0 | | cy*cz -cy*sz sy |
- * | 0 cx -sx |*| 0 1 0 |*| sz cz 0 |=| sx*sy*cz+cx*sz -sx*sy*sz+cx*cz -sx*cy |
- * | 0 sx cx | | -sy 0 cy | | 0 0 1 | | -cx*sy*cz+sx*sz cx*sy*sz+sx*cz cx*cy |
- */
-MAT4 rotatemat4(MAT4 m, V3 angles)
-{
- F32 angle, cx, sx, cy, sy, cz, sz;
- MAT4 rotate, r;
- V3 newx, newy, newz;
-
- angle = DEG2RAD*angles.x;
- cx = f32cos(angle);
- sx = f32sin(angle);
- angle = DEG2RAD*angles.y;
- cy = f32cos(angle);
- sy = f32sin(angle);
- angle = DEG2RAD*angles.z;
- cz = f32cos(angle);
- sz = f32sin(angle);
-
- newx = v3(cy*cz, sx*sy*cz+cx*sz, -cx*sy*cz+sx*sz);
- newy = v3(-cy*sz, -sx*sy*sz+cx*cz, cx*sy*sz+sx*cz);
- newz = v3(sy, -sx*cy, cx*cy);
- rotate = rotateaxismat4(newx, newy, newz);
-
- r = mulmat4(rotate, m);
-
- return r;
-}
-
-V4 mulmat4v4(MAT4 m, V4 v)
-{
- V4 r;
-
- r = v4(m.m0.x*v.x+m.m1.x*v.y+m.m2.x*v.z+m.m3.x*v.w,
- m.m0.y*v.x+m.m1.y*v.y+m.m2.y*v.z+m.m3.y*v.w,
- m.m0.z*v.x+m.m1.z*v.y+m.m2.z*v.z+m.m3.z*v.w,
- m.m0.w*v.x+m.m1.w*v.y+m.m2.w*v.z+m.m3.w*v.w);
-
- return r;
-}
-
-void printmat4(MAT4 m)
-{
- fprintf(stdout, "| %.4f %.4f %.4f %.4f |\n", m.m0.x, m.m1.x, m.m2.x, m.m3.x);
- fprintf(stdout, "| %.4f %.4f %.4f %.4f |\n", m.m0.y, m.m1.y, m.m2.y, m.m3.y);
- fprintf(stdout, "| %.4f %.4f %.4f %.4f |\n", m.m0.z, m.m1.z, m.m2.z, m.m3.z);
- fprintf(stdout, "| %.4f %.4f %.4f %.4f |\n\n", m.m0.w, m.m1.w, m.m2.w, m.m3.w);
-}
diff --git a/prb_math.h b/prb_math.h
index 52c6289..8f188f4 100644
--- a/prb_math.h
+++ b/prb_math.h
@@ -1,71 +1,444 @@
-#ifndef PRB_MATH_H
-#define PRB_MATH_H
-
-/* NOTE(pryazha): Numeric */
-#define F32PI 3.14159265359f
-
-#define DEG2RAD F32PI/180.0f
-#define RAD2DEG 182.0f/F32PI
-
-F32 f32sin(F32 a);
-F32 f32cos(F32 a);
-F32 f32tan(F32 a);
-F32 f32sqrt(F32 a);
-
-/* NOTE(pryazha): Vectors */
-V2 v2(F32 x, F32 y);
-V2 v2a(F32 x);
-V2 invv2(V2 a);
-V2 addv2(V2 a, V2 b);
-V2 subv2(V2 a, V2 b);
-V2 scalefv2(V2 a, F32 s);
-V2 scalev2(V2 a, V2 s);
-F32 dotv2(V2 a, V2 b);
-F32 len2v2(V2 a);
-F32 lenv2(V2 a);
-V2 normv2(V2 a);
-void printv2(V2 a);
-
-V3 v3(F32 x, F32 y, F32 z);
-V3 v3a(F32 x);
-V3 v3fromv2(V2 a);
-V3 v3fromv4(V4 a);
-V3 invv3(V3 a);
-V3 addv3(V3 a, V3 b);
-V3 subv3(V3 a, V3 b);
-V3 scalefv3(V3 a, F32 s);
-V3 scalev3(V3 a, V3 s);
-F32 dotv3(V3 a, V3 b);
-V3 crossv3(V3 l, V3 r);
-F32 len2v3(V3 a);
-F32 lenv3(V3 a);
-V3 normv3(V3 a);
-void printv3(V3 a);
-
-V4 v4(F32 x, F32 y, F32 z, F32 w);
-V4 v4a(F32 x);
-V4 v4fromv3(V3 a);
-V4 invv4(V4 a);
-V4 addv4(V4 a, V4 b);
-V4 subv4(V4 a, V4 b);
-V4 scalefv4(V4 a, F32 s);
-V4 scalev4(V4 a, V4 s);
-F32 dotv4(V4 a, V4 b);
-F32 len2v4(V4 a);
-F32 lenv4(V4 a);
-V4 normv4(V4 a);
-void printv4(V4 a);
-
-/* NOTE(pryazha): Matrices */
-F32 detmat4(MAT4 m);
-MAT4 transpmat4(MAT4 m);
-MAT4 mulmat4(MAT4 left, MAT4 right);
-MAT4 translmat4(MAT4 m, V3 v);
-MAT4 scalemat4(MAT4 m, V3 v);
-MAT4 rotateaxismat4(V3 x, V3 y, V3 z);
-/* NOTE(pryazha): Angles in degrees */
-MAT4 rotatemat4(MAT4 m, V3 angles);
-V4 mulmat4v4(MAT4 m, V4 v);
-void printmat4(MAT4 m);
-
-#endif /* PRB_MATH_H */
+#define V2_ZERO (v2){ 0.0f, 0.0f}
+#define V2_ONE (v2){ 1.0f, 1.0f}
+#define V2_RIGHT (v2){ 1.0f, 0.0f}
+#define V2_UP (v2){ 0.0f, 1.0f}
+#define V2_LEFT (v2){-1.0f, 0.0f}
+#define V2_DOWN (v2){ 0.0f, -1.0f }
+
+#define V3_ZERO (v3){ 0.0f, 0.0f, 0.0f}
+#define V3_ONE (v3){ 1.0f, 1.0f, 1.0f}
+#define V3_RIGHT (v3){ 1.0f, 0.0f, 0.0f}
+#define V3_UP (v3){ 0.0f, 1.0f, 0.0f}
+#define V3_LEFT (v3){-1.0f, 0.0f, 0.0f}
+#define V3_DOWN (v3){ 0.0f, -1.0f, 0.0f}
+#define V3_FORWARD (v3){ 0.0f, 0.0f, 1.0f}
+#define V3_BACKWARD (v3){ 0.0f, 0.0f, -1.0f}
+
+#define V4_ZERO (v4){0.0f, 0.0f, 0.0f, 0.0f}
+#define V4_ONE (v4){1.0f, 1.0f, 1.0f, 1.0f}
+
+#define MAT4_IDENTITY (mat4){ \
+ {1.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 1.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 1.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 1.0f}}
+
+#define F_PI 3.14159265359f
+
+#define deg2rad(angle) (F_PI/180.0f*(angle))
+
+#define QUAT_IDENTITY (v4){0.0f, 0.0f, 0.0f, 1.0f}
+
+/* TODO(pryazha): Implement trigonometry functions */
+f32 fsin(f32 a)
+{
+ f32 result = sinf(a);
+ return result;
+}
+
+f32 fcos(f32 a)
+{
+ f32 result = cosf(a);
+ return result;
+}
+
+f32 ftan(f32 a)
+{
+ f32 result = tanf(a);
+ return result;
+}
+
+f32 fsqrt(f32 a)
+{
+ f32 result = sqrtf(a);
+ return result;
+}
+
+// vectors
+v2 v2_fill(f32 x)
+{
+ v2 v = {x, x};
+ return v;
+}
+
+v2 v2_inv(v2 a)
+{
+ v2 v = {-a.x, -a.y};
+ return v;
+}
+
+v2 v2_add(v2 a, v2 b)
+{
+ v2 v = {a.x+b.x, a.y+b.y};
+ return v;
+}
+
+v2 v2_sub(v2 a, v2 b)
+{
+ v2 v = {a.x-b.x, a.y-b.y};
+ return v;
+}
+
+v2 v2_scalef(v2 a, f32 s)
+{
+ v2 v = {a.x*s, a.y*s};
+ return v;
+}
+
+v2 v2_scale(v2 a, v2 s)
+{
+ v2 v = {a.x*s.x, a.y*s.y};
+ return v;
+}
+
+f32 v2_dot(v2 a, v2 b)
+{
+ f32 v = a.x*b.x+a.y*b.y;
+ return v;
+}
+
+f32 v2_len2(v2 a)
+{
+ f32 v = v2_dot(a, a);
+ return v;
+}
+
+f32 v2_len(v2 a)
+{
+ f32 v = fsqrt(v2_len2(a));
+ return v;
+}
+
+v2 v2_norm(v2 a)
+{
+ v2 v = {0};
+ f32 len = v2_len(a);
+ if (len)
+ v = (v2){a.x/len, a.y/len};
+ return v;
+}
+
+v3 v3_fill(f32 x)
+{
+ v3 v = {x, x, x};
+ return v;
+}
+
+v3 v3_from_v2(v2 a)
+{
+ v3 v = {a.x, a.y, 0.0f};
+ return v;
+}
+
+v3 v3_from_v4(v4 a)
+{
+ v3 v = {a.x, a.y, a.z};
+ return v;
+}
+
+v3 v3_inv(v3 a)
+{
+ v3 v = {-a.x, -a.y, -a.z};
+ return v;
+}
+
+v3 v3_add(v3 a, v3 b)
+{
+ v3 v = {a.x+b.x, a.y+b.y, a.z+b.z};
+ return v;
+}
+
+v3 v3_sub(v3 a, v3 b)
+{
+ v3 v = {a.x-b.x, a.y-b.y, a.z-b.z};
+ return v;
+}
+
+v3 v3_scalef(v3 a, f32 s)
+{
+ v3 v = {a.x*s, a.y*s, a.z*s};
+ return v;
+}
+
+v3 v3_scale(v3 a, v3 s)
+{
+ v3 v = {a.x*s.x, a.y*s.y, a.z*s.z};
+ return v;
+}
+
+f32 v3_dot(v3 a, v3 b)
+{
+ f32 v = a.x*b.x+a.y*b.y+a.z*b.z;
+ return v;
+}
+
+v3 v3_cross(v3 l, v3 r)
+{
+ v3 v = {(l.y*r.z - r.y*l.z), (r.x*l.z - l.x*r.z), (l.x*r.y - r.x*l.y)};
+ return v;
+}
+
+f32 v3_len2(v3 a)
+{
+ f32 v = v3_dot(a, a);
+ return v;
+}
+
+f32 v3_len(v3 a)
+{
+ f32 v = fsqrt(v3_len2(a));
+ return v;
+}
+
+v3 v3_norm(v3 a)
+{
+ v3 v = V3_ZERO;
+ f32 len = v3_len(a);
+ if (len)
+ v = (v3){a.x/len, a.y/len, a.z/len};
+ return v;
+}
+
+v4 v4_fill(f32 x)
+{
+ v4 v = {x, x, x, x};
+ return v;
+}
+
+v4 v4_from_v3(v3 a)
+{
+ v4 v = {a.x, a.y, a.z, 0.0f};
+ return v;
+}
+
+v4 v4_inv(v4 a)
+{
+ v4 v = {-a.x, -a.y, -a.z, -a.w};
+ return v;
+}
+
+v4 v4_add(v4 a, v4 b)
+{
+ v4 v = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w};
+ return v;
+}
+
+v4 v4_sub(v4 a, v4 b)
+{
+ v4 v = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w};
+ return v;
+}
+
+v4 v4_scalef(v4 a, f32 s)
+{
+ v4 v = {a.x*s, a.y*s, a.z*s, a.w*s};
+ return v;
+}
+
+v4 v4_scale(v4 a, v4 s)
+{
+ v4 v = {a.x*s.x, a.y*s.y, a.z*s.z, a.w*s.w};
+ return v;
+}
+
+f32 v4_dot(v4 a, v4 b)
+{
+ f32 v = a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w;
+ return v;
+}
+
+f32 v4_len2(v4 a)
+{
+ f32 v = v4_dot(a, a);
+ return v;
+}
+
+f32 v4_len(v4 a)
+{
+ f32 v = fsqrt(v4_len2(a));
+ return v;
+}
+
+v4 v4_norm(v4 a)
+{
+ v4 v = V4_ZERO;
+ f32 len = v4_len(a);
+ if (len)
+ v = (v4){a.x/len, a.y/len, a.z/len, a.w/len};
+ return v;
+}
+
+// matrices
+f32 mat4_det(mat4 m)
+{
+ f32 m00 = m.c0.x, m10 = m.c0.y, m20 = m.c0.z, m30 = m.c0.w;
+ f32 m01 = m.c1.x, m11 = m.c1.y, m21 = m.c1.z, m31 = m.c1.w;
+ f32 m02 = m.c2.x, m12 = m.c2.y, m22 = m.c2.z, m32 = m.c2.w;
+ f32 m03 = m.c3.x, m13 = m.c3.y, m23 = m.c3.z, m33 = m.c3.w;
+
+ f32 m00minor = ((m11*m22*m33)+(m12*m23*m31)+(m21*m32*m13)-
+ (m31*m22*m13)-(m21*m12*m33)-(m11*m32*m23));
+
+ f32 m01minor = ((m10*m22*m33)+(m12*m23*m30)+(m20*m32*m13)-
+ (m13*m22*m30)-(m23*m32*m10)-(m12*m20*m33));
+
+ f32 m02minor = ((m10*m21*m33)+(m20*m31*m13)+(m11*m23*m31)-
+ (m13*m21*m30)-(m23*m31*m10)-(m11*m20*m33));
+
+ f32 m03minor = ((m10*m21*m32)+(m20*m31*m12)+(m11*m22*m30)-
+ (m12*m21*m30)-(m11*m20*m32)-(m22*m31*m10));
+
+ f32 result = m00*m00minor+m01*m01minor-m02*m02minor+m03*m03minor;
+
+ return result;
+}
+
+mat4 mat4_transp(mat4 m)
+{
+ swap(f32, m.c0.y, m.c1.x);
+ swap(f32, m.c0.z, m.c2.x);
+ swap(f32, m.c0.w, m.c3.x);
+
+ swap(f32, m.c1.z, m.c2.y);
+ swap(f32, m.c1.w, m.c3.y);
+
+ swap(f32, m.c2.w, m.c3.z);
+
+ return m;
+}
+
+mat4 mat4_mul(mat4 left, mat4 right)
+{
+ f32 l00 = left.c0.x, l01 = left.c0.y, l02 = left.c0.z, l03 = left.c0.w;
+ f32 l10 = left.c1.x, l11 = left.c1.y, l12 = left.c1.z, l13 = left.c1.w;
+ f32 l20 = left.c2.x, l21 = left.c2.y, l22 = left.c2.z, l23 = left.c2.w;
+ f32 l30 = left.c3.x, l31 = left.c3.y, l32 = left.c3.z, l33 = left.c3.w;
+
+ f32 r00 = right.c0.x, r01 = right.c0.y, r02 = right.c0.z, r03 = right.c0.w;
+ f32 r10 = right.c1.x, r11 = right.c1.y, r12 = right.c1.z, r13 = right.c1.w;
+ f32 r20 = right.c2.x, r21 = right.c2.y, r22 = right.c2.z, r23 = right.c2.w;
+ f32 r30 = right.c3.x, r31 = right.c3.y, r32 = right.c3.z, r33 = right.c3.w;
+
+ mat4 result = {
+ {
+ l00*r00+l10*r01+l20*r02+l30*r03,
+ l01*r00+l11*r01+l21*r02+l31*r03,
+ l02*r00+l12*r01+l22*r02+l32*r03,
+ l03*r00+l13*r01+l23*r02+l33*r03
+ },
+ {
+ l00*r10+l10*r11+l20*r12+l30*r13,
+ l01*r10+l11*r11+l21*r12+l31*r13,
+ l02*r10+l12*r11+l22*r12+l32*r13,
+ l03*r10+l13*r11+l23*r12+l33*r13
+ },
+ {
+ l00*r20+l10*r21+l20*r22+l30*r23,
+ l01*r20+l11*r21+l21*r22+l31*r23,
+ l02*r20+l12*r21+l22*r22+l32*r23,
+ l03*r20+l13*r21+l23*r22+l33*r23
+ },
+ {
+ l00*r30+l10*r31+l20*r32+l30*r33,
+ l01*r30+l11*r31+l21*r32+l31*r33,
+ l02*r30+l12*r31+l22*r32+l32*r33,
+ l03*r30+l13*r31+l23*r32+l33*r33
+ }
+ };
+
+ return result;
+}
+
+mat4 mat4_make_transl(v3 v)
+{
+ mat4 translate = {
+ {1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {v.x, v.y, v.z, 1.0f}
+ };
+ return translate;
+}
+
+mat4 mat4_make_scale(v3 v)
+{
+ mat4 scale = {
+ {v.x, 0.0f, 0.0f, 0.0f},
+ {0.0f, v.y, 0.0f, 0.0f},
+ {0.0f, 0.0f, v.z, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ return scale;
+}
+
+mat4 mat4_make_rotate(v3 x, v3 y, v3 z)
+{
+ mat4 rotate = {
+ {x.x, x.y, x.z, 0.0f},
+ {y.x, y.y, y.z, 0.0f},
+ {z.x, z.y, z.z, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ return rotate;
+}
+
+mat4 mat4_transl(mat4 m, v3 v)
+{
+ mat4 translate = mat4_make_transl(v);
+ mat4 result = mat4_mul(translate, m);
+ return result;
+}
+
+mat4 mat4_scale(mat4 m, v3 v)
+{
+ mat4 scale = mat4_make_scale(v);
+ mat4 result = mat4_mul(scale, m);
+ return result;
+}
+
+/*
+ * NOTE(pryazha): Angles in degrees
+ * | 1 0 0 | | cy 0 sy | | cz -sz 0 | | cy*cz -cy*sz sy |
+ * | 0 cx -sx |*| 0 1 0 |*| sz cz 0 |=| sx*sy*cz+cx*sz -sx*sy*sz+cx*cz -sx*cy |
+ * | 0 sx cx | | -sy 0 cy | | 0 0 1 | | -cx*sy*cz+sx*sz cx*sy*sz+sx*cz cx*cy |
+ */
+mat4 mat4_rotate(mat4 mat, v3 angles)
+{
+ f32 angle = deg2rad(angles.x);
+ f32 cx = fcos(angle);
+ f32 sx = fsin(angle);
+ angle = deg2rad(angles.y);
+ f32 cy = fcos(angle);
+ f32 sy = fsin(angle);
+ angle = deg2rad(angles.z);
+ f32 cz = fcos(angle);
+ f32 sz = fsin(angle);
+
+ v3 x = {cy*cz, sx*sy*cz+cx*sz, -cx*sy*cz+sx*sz};
+ v3 y = {-cy*sz, -sx*sy*sz+cx*cz, cx*sy*sz+sx*cz};
+ v3 z = {sy, -sx*cy, cx*cy};
+ mat4 rotate = mat4_make_rotate(x, y, z);
+
+ mat4 result = mat4_mul(rotate, mat);
+
+ return result;
+}
+
+v4 mat4_v4_mul(mat4 m, v4 v)
+{
+ v4 result = {
+ m.c0.x*v.x+m.c1.x*v.y+m.c2.x*v.z+m.c3.x*v.w,
+ m.c0.y*v.x+m.c1.y*v.y+m.c2.y*v.z+m.c3.y*v.w,
+ m.c0.z*v.x+m.c1.z*v.y+m.c2.z*v.z+m.c3.z*v.w,
+ m.c0.w*v.x+m.c1.w*v.y+m.c2.w*v.z+m.c3.w*v.w
+ };
+ return result;
+}
+
+i32 in_rect(v2 pos, rect_t rect)
+{
+ i32 result = (pos.x > rect.start.x) && (pos.x < rect.end.x) &&
+ (pos.y > rect.start.y) && (pos.y < rect.end.y);
+ return result;
+}
+
diff --git a/prb_string.c b/prb_string.c
deleted file mode 100644
index 06f4ed8..0000000
--- a/prb_string.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* NOTE(pryazha): Null-terminated strings */
-
-/* TODO(pryazha): Move to another file specific to OS you're in */
-void sys_vprintf(const char *fmt, va_list args)
-{
- vprintf(fmt, args);
-}
-
-void sys_printf(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- sys_vprintf(fmt, args);
- va_end(args);
-}
-
-/* NOTE(pryazha): Fixed-length strings */
-
-FLS fls(U8 *p, U64 len)
-{
- FLS r;
- r.p = p;
- r.len = len;
- return r;
-}
-
-FLS flsfromcstr(const char *cstr)
-{
- U8 *p;
- FLS r;
-
- p = (U8 *)cstr;
- for (; *p; ++p);
- r = flsrange((U8 *)cstr, p);
-
- return r;
-}
-
-char *flstocstr(Arena *a, FLS s)
-{
- U64 len;
- char *cstr;
-
- len = s.len+1;
- cstr = push_arena(a, len*sizeof(U8));
- MEMCPY(cstr, s.p, len*sizeof(U8));
- *(cstr+s.len) = 0;
-
- return cstr;
-}
-
-FLS flsrange(U8 *st_arenat, U8 *end)
-{
- FLS r;
- r.p = st_arenat;
- r.len = end-st_arenat;
- return r;
-}
-
-FLS flschopend(FLS s, U64 cnt)
-{
- U64 len;
- FLS r;
-
- len = s.len-CLAMPTOP(cnt, s.len);
- r = fls(s.p, len);
-
- return r;
-}
-
-FLS flschopstart(FLS s, U64 cnt)
-{
- U64 clamped, len;
- FLS r;
-
- clamped = CLAMPTOP(cnt, s.len);
- len = s.len-CLAMPTOP(cnt, s.len);
- r = fls(s.p+clamped, len);
-
- return r;
-}
-
-FLS flspushfv(Arena *a, const char *fmt, va_list args)
-{
- ASSERT(a);
-
- char tmp[1024];
- S32 n;
- FLS r;
-
- n = vsnprintf(tmp, 1024, fmt, args);
-
- MEM0(&r, sizeof(FLS));
-
- if (n > 0) {
- r.p = push_arena(a, n);
- MEMCPY(r.p, tmp, n);
- r.len = n;
- }
-
- return r;
-}
-
-FLS flspushf(Arena *a, const char *fmt, ...)
-{
- va_list args;
- FLS r;
-
- va_start(args, fmt);
- r = flspushfv(a, fmt, args);
- va_end(args);
-
- return r;
-}
-
-void flsprint(FLS s)
-{
- ASSERT(s.p);
- ASSERT(s.len);
-
- fwrite(s.p, sizeof(U8), s.len, stdout);
-}
-
-
-FLSList *flslist(Arena *a)
-{
- FLSList *l;
-
- l = push_arena(a, sizeof(FLSList));
- MEM0(l, sizeof(FLSList));
-
- return l;
-}
-
-void flslistpush(Arena *a, FLSList *l, FLS s, B32 front)
-{
- ASSERT(a);
- ASSERT(l);
-
- FLSNode *n;
-
- n = push_arena(a, sizeof(FLSNode));
- n->str = s;
-
- if (front)
- DLLPUSHFRONT(l->first, l->last, n);
- else
- DLLPUSHBACK(l->first, l->last, n);
- l->len += s.len;
- l->ncnt++;
-}
-
-void flslistpushf(Arena *a, FLSList *l, B32 front, const char *fmt, ...)
-{
- va_list args;
- FLS str;
-
- va_start(args, fmt);
- str = flspushfv(a, fmt, args);
- va_end(args);
-
- flslistpush(a, l, str, front);
-}
-
-void flslistprint(FLSList *l)
-{
- FLSNode *n;
- for (n = l->first; n; n = n->next)
- flsprint(n->str);
-}
diff --git a/prb_string.h b/prb_string.h
index 7df8246..344df11 100644
--- a/prb_string.h
+++ b/prb_string.h
@@ -1,40 +1,196 @@
-#ifndef PRB_STRING_H
-#define PRB_STRING_H
+void prb_memset(void *dest, i32 fill, u64 n)
+{
+ u8 *byte = dest;
+ while (n--)
+ *byte++ = fill;
+}
-/* NOTE(pryazha): I don't know wheter it's a good idea
- * to keep regular and fixed-length strings together, but
- * seems reasonable at the time.
- */
+void prb_memmove(void *dest, const void *src, u64 size)
+{
+ u8 *byte_dest = dest;
+ const u8 *byte_src = src;
+ while (size--)
+ *byte_dest++ = *byte_src++;
+}
-/* NOTE(pryazha): Null-terminated strings */
+i32 prb_memeq(const void *p1, const void *p2, u64 size)
+{
+ const u8 *byte_p1 = p1;
+ const u8 *byte_p2 = p2;
+ while (size--)
+ if (*byte_p1++ != *byte_p2++)
+ return 0;
+ return 1;
+}
-void sys_vprintf(const char *fmt, va_list args);
-void sys_printf(const char *fmt, ...);
+i32 streq(const char *str1, const char *str2)
+{
+ if (!str1 || !str2)
+ return 0;
+ while (*str1++ == *str2++)
+ if (!*str1)
+ return 1;
+ return 0;
+}
-/* NOTE(pryazha): Fixed-length strings */
+// fixed length strings
+#define str8lit(str) (str8_t){(u8 *)(str), sizeof(str) - 1}
+#define str8exp(str) (i32)((str).len), ((str).ptr)
-#define FLSLIT(s) fls((U8 *)(s), sizeof(s)-1)
-#define FLSEXP(s) (int)((s).len), ((s).p)
+#define MAX_FLS_BUFFER 1024
-FLS fls(U8 *p, U64 len);
+typedef struct {
+ u8 *ptr;
+ u64 len;
+} str8_t;
-FLS flsfromcstr(const char *cstr);
-char *flstocstr(Arena *a, FLS s);
+typedef struct str8_node_t {
+ str8_t str;
+ struct str8_node_t *next;
+ struct str8_node_t *prev;
+} str8_node_t;
-FLS flsrange(U8 *start, U8 *end);
-FLS flschopend(FLS s, U64 cnt);
-FLS flschopstart(FLS s, U64 cnt);
+typedef struct {
+ struct str8_node_t *first;
+ struct str8_node_t *last;
+ u64 len;
+ i32 cnt;
+} str8_list_t;
-FLS flspushfv(Arena *a, const char *fmt, va_list args);
-FLS flspushf(Arena *a, const char *fmt, ...);
+char *str8_to_cstr(arena_t *arena, str8_t str)
+{
+ u64 len = str.len + 1;
+ char *cstr = push_arena(arena, len);
+ prb_memmove(cstr, str.ptr, len);
+ cstr[str.len] = 0;
+ return cstr;
+}
-void flsprint(FLS s);
+i32 str8eq(str8_t str1, str8_t str2)
+{
+ if (str1.len != str2.len)
+ return 0;
+ for (u64 i = 0; i < str1.len; ++i)
+ if (str1.ptr[i] != str2.ptr[i])
+ return 0;
+ return 1;
+}
-FLSList *flslist(Arena *a);
+u8 *str8ch(str8_t str, i32 c)
+{
+ for (u64 i = 0; i < str.len; ++i)
+ if (str.ptr[i] == c)
+ return str.ptr + i;
+ return 0;
+}
-void flslistpush(Arena *a, FLSList *l, FLS s, B32 front);
-void flslistpushf(Arena *a, FLSList *l, B32 front, const char *fmt, ...);
+u8 *str8rch(str8_t str, i32 c)
+{
+ for (u64 i = str.len - 1; i > 0; --i)
+ if (str.ptr[i] == c)
+ return str.ptr + i;
+ return 0;
+}
-void flslistprint(FLSList *l);
+str8_t str8_range(u8 *start, u8 *end)
+{
+ assert(start);
+ assert(end);
+ assert(start < end);
+ str8_t result = {start, end - start};
+ return result;
+}
-#endif /* PRB_STRING_H */
+str8_t str8_getdir(str8_t str)
+{
+ assert(str.len);
+ u8 *slash = str8rch(str, '/');
+ if (!slash)
+ return str;
+ str8_t result = str8_range(str.ptr, slash);
+ return result;
+}
+
+str8_t str8_pushfv(arena_t *arena, const char *format, va_list args)
+{
+ char tmp[MAX_FLS_BUFFER];
+ i32 n = vsnprintf(tmp, MAX_FLS_BUFFER, format, args);
+ str8_t str = {0};
+ if (n > 0) {
+ u8 *ptr = push_arena(arena, n);
+ prb_memmove(ptr, tmp, n);
+ str = (str8_t){ptr, n};
+ str.ptr = ptr;
+ str.len = n;
+ }
+ return str;
+}
+
+str8_t str8_pushf(arena_t *arena, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ str8_t str = str8_pushfv(arena, format, args);
+ va_end(args);
+ return str;
+}
+
+void str8_print(str8_t str)
+{
+ assert(str.ptr);
+ assert(str.len);
+ printf("%.*s", str8exp(str));
+}
+
+void str8_printf(const char *format, ...)
+{
+
+ va_list args;
+ va_start(args, format);
+ arena_t temp = alloc_arena(MAX_FLS_BUFFER);
+ str8_t str = str8_pushfv(&temp, format, args);
+ va_end(args);
+ str8_print(str);
+ release_arena(&temp);
+}
+
+void str8_list_push(arena_t *arena, str8_list_t *list, i32 front, str8_t str)
+{
+ str8_node_t *node = push_arena(arena, sizeof(str8_node_t));
+ node->str = str;
+ if (front)
+ dllpushfront(list->first, list->last, node);
+ else
+ dllpushback(list->first, list->last, node);
+ list->len += str.len;
+ list->cnt++;
+}
+
+void str8_list_pushf(arena_t *arena, str8_list_t *list, i32 front, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ str8_t str = str8_pushfv(arena, format, args);
+ va_end(args);
+ str8_list_push(arena, list, front, str);
+}
+
+/* TODO(pryazha): Check if that works :) */
+str8_t str8_list_join(arena_t *arena, str8_list_t *list)
+{
+ assert(arena);
+ assert(list);
+ str8_t str = {arena->memory + arena->used, 0};
+ for (str8_node_t *node = list->first; node; node = node->next) {
+ u8 *ptr = push_arena(arena, node->str.len);
+ prb_memmove(ptr, node->str.ptr, node->str.len);
+ str.len += node->str.len;
+ }
+ return str;
+}
+
+void str8_list_print(str8_list_t *list)
+{
+ for (str8_node_t *node = list->first; node; node = node->next)
+ str8_print(node->str);
+}
diff --git a/prb_sys.c b/prb_sys.c
deleted file mode 100644
index 3747f18..0000000
--- a/prb_sys.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* TODO(pryazha): OS specific */
-FLS sys_read_entire_file_fls(Arena *a, const char *fname)
-{
- FILE *f;
- FLS r;
- S32 len;
-
- MEM0STRUCT(&r);
-
- f = fopen(fname, "rb");
- if (!f)
- return r;
-
- if (fseek(f, 0, SEEK_END) == -1)
- goto error;
- if ((len = ftell(f)) == -1)
- goto error;
- rewind(f);
-
- r.p = push_arena(a, len+1);
- if (!fread(r.p, len, 1, f))
- goto error;
- r.p[len] = 0;
- r.len = len+1;
-
- fclose(f);
-
- return r;
-error:
- fclose(f);
- return r;
-}
-
-#define PRGE_MAX_PATH 256
-
-char *sys_getbindir(Arena *a)
-{
- U64 size;
- char *path;
- ssize_t len;
-
- size = PRGE_MAX_PATH*sizeof(char);
- path = push_arena(a, size);
-
- len = readlink("/proc/self/exe", path, size-1);
- if (len <= 0)
- return path;
-
- path[len] = 0;
-
- return path;
-}
diff --git a/prb_sys.h b/prb_sys.h
index 45a6d6d..7250758 100644
--- a/prb_sys.h
+++ b/prb_sys.h
@@ -1,7 +1,10 @@
-#ifndef PRB_OS_IO_H
-#define PRB_OS_IO_H
+#define MAX_PATH 512
-FLS sys_read_entire_file_fls(Arena *arena, const char *fname);
-char *sys_getbindir(Arena *arena);
+extern void *sys_alloc(u64 length);
+extern void sys_free(void *memory, u64 length);
-#endif /* PRB_OS_IO_H */
+// TODO(pryazha): Try using exit_failure, seems reasonable. I/O (file mainly) is a concern though
+// extern void exit_failure(const char *format, ...);
+
+extern u64 sys_read_file(arena_t *arena, char **buffer, const char *filename);
+extern char *sys_getbindir(arena_t *arena);
diff --git a/prb_types.h b/prb_types.h
index 8760513..bf6cd43 100644
--- a/prb_types.h
+++ b/prb_types.h
@@ -1,96 +1,49 @@
-#ifndef PRB_TYPES_H
-#define PRB_TYPES_H
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
-typedef int8_t S8;
-typedef int16_t S16;
-typedef int32_t S32;
-typedef int64_t S64;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
-typedef uint8_t U8;
-typedef uint16_t U16;
-typedef uint32_t U32;
-typedef uint64_t U64;
-
-typedef S32 B32;
-
-typedef float F32;
-typedef double F64;
-
-/* NOTE(pryazha): The library only use right-handed coordiante system (for now) */
-
-#define V2_ZERO (V2){ 0.0f, 0.0f }
-#define V2_ONE (V2){ 1.0f, 1.0f }
-#define V2_RIGHT (V2){ 1.0f, 0.0f }
-#define V2_UP (V2){ 0.0f, 1.0f }
-#define V2_LEFT (V2){-1.0f, 0.0f }
-#define V2_DOWN (V2){ 0.0f, -1.0f }
+typedef float f32;
+typedef double f64;
typedef struct {
- F32 x;
- F32 y;
-} V2;
-
-#define V3_ZERO (V3){ 0.0f, 0.0f, 0.0f }
-#define V3_ONE (V3){ 1.0f, 1.0f, 1.0f }
-#define V3_RIGHT (V3){ 1.0f, 0.0f, 0.0f }
-#define V3_UP (V3){ 0.0f, 1.0f, 0.0f }
-#define V3_LEFT (V3){-1.0f, 0.0f, 0.0f }
-#define V3_DOWN (V3){ 0.0f, -1.0f, 0.0f }
-#define V3_FORWARD (V3){ 0.0f, 0.0f, 1.0f }
-#define V3_BACKWARD (V3){ 0.0f, 0.0f, -1.0f }
+ f32 x;
+ f32 y;
+} v2;
typedef struct {
- F32 x;
- F32 y;
- F32 z;
-} V3;
-
-#define V4_ZERO (V4){ 0.0f, 0.0f, 0.0f, 0.0f }
-#define V4_ONE (V4){ 1.0f, 1.0f, 1.0f, 1.0f }
+ f32 x;
+ f32 y;
+ f32 z;
+} v3;
typedef struct {
- F32 x;
- F32 y;
- F32 z;
- F32 w;
-} V4;
-
-#define MAT4_IDENTITY (MAT4) { \
- { 1.0f, 0.0f, 0.0f, 0.0f }, \
- { 0.0f, 1.0f, 0.0f, 0.0f }, \
- { 0.0f, 0.0f, 1.0f, 0.0f }, \
- { 0.0f, 0.0f, 0.0f, 1.0f } }
+ f32 x;
+ f32 y;
+ f32 z;
+ f32 w;
+} v4;
+// column-major
typedef struct {
- V4 m0;
- V4 m1;
- V4 m2;
- V4 m3;
-} MAT4;
+ v4 c0;
+ v4 c1;
+ v4 c2;
+ v4 c3;
+} mat4;
typedef struct {
- U8 *mem;
- U64 cap;
- U64 used;
-} Arena;
-
-/* NOTE(pryazha): Fixed-length string */
-typedef struct {
- U8 *p;
- U64 len;
-} FLS;
-
-typedef struct FLSNode {
- FLS str;
- struct FLSNode *next;
- struct FLSNode *prev;
-} FLSNode;
+ v2 start;
+ v2 end;
+} rect_t;
typedef struct {
- struct FLSNode *first;
- struct FLSNode *last;
- U64 len;
- U32 ncnt;
-} FLSList;
-
-#endif /* PRB_TYPES_H */
+ void *memory;
+ u64 capacity;
+ u64 used;
+} arena_t;
diff --git a/prb_windows.h b/prb_windows.h
new file mode 100644
index 0000000..aec7e9b
--- /dev/null
+++ b/prb_windows.h
@@ -0,0 +1,75 @@
+void *sys_alloc(u64 length)
+{
+ assert(length);
+ void *result = VirtualAlloc(0, length, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ return result;
+}
+
+void sys_free(void *memory, u64 length)
+{
+ assert(memory);
+ assert(length);
+ assert(VirtualFree(memory, 0, MEM_RELEASE));
+}
+
+u64 sys_read_file(arena_t *arena, char **buffer, const char *filename)
+{
+ *buffer = 0;
+
+ HANDLE file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
+ 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE) {
+ printf("error: failed to open file \"%s\"\n", filename);
+ return 0;
+ }
+
+ LARGE_INTEGER lisize;
+ if (!GetFileSizeEx(file, &lisize)) {
+ printf("error: failed to get size of the file \"%s\"", filename);
+ CloseHandle(file);
+ return 0;
+ }
+
+ u64 size = lisize.QuadPart;
+ if (!size) {
+ printf("error: file \"%s\" is empty", filename);
+ CloseHandle(file);
+ return 0;
+ }
+
+ *buffer = push_arena(arena, size + 1);
+
+ DWORD bytes_read;
+ if (!ReadFile(file, *buffer, size, &bytes_read, 0)) {
+ CloseHandle(file);
+ pop_arena(arena, size);
+ printf("error: failed to read file \"%s\", bytes read: %lu\n", filename, bytes_read);
+ return 0;
+ }
+ CloseHandle(file);
+
+ *(*buffer + size) = 0;
+
+ return size + 1;
+}
+
+char *sys_getbindir(arena_t *arena)
+{
+ char path[MAX_PATH];
+ u32 len = GetModuleFileName(0, path, MAX_PATH);
+ if (!len) {
+ printf("error: failed to get file path\n");
+ return 0;
+ }
+
+ char *dir = strrchr(path, '\\');
+ assert(dir);
+ assert(dir > path);
+
+ len = dir - path;
+ dir = push_arena(arena, len + 1);
+ prb_memmove(dir, path, len);
+ dir[len] = 0;
+
+ return dir;
+}