rework assert, wasm_alert, wasm_clear, expect

This commit is contained in:
krzosa
2024-12-30 19:48:40 +01:00
parent 578fa33605
commit 46084a3412
16 changed files with 150 additions and 95 deletions

View File

@@ -41,7 +41,7 @@ int main(int argc, char **argv) {
ok = os_systemf( ok = os_systemf(
"cl ../src/core_test/core_test_entry.c -Fe:core_test.exe -Fd:core_test.pdb" "cl ../src/core_test/core_test_entry.c -Fe:core_test.exe -Fd:core_test.pdb"
" -I ../src" " -I ../src"
" /Zi /FC /nologo /Oi" " /Zi /FC /nologo /Oi /O2"
" /WX /W3 /wd4200 /diagnostics:column" " /WX /W3 /wd4200 /diagnostics:column"
" /link /incremental:no" " /link /incremental:no"
); );

View File

@@ -104,6 +104,9 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
ctx2d.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`; ctx2d.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`;
ctx2d.fill(); ctx2d.fill();
}, },
wasm_clear: () => {
ctx2d.clearRect(0, 0, canvas.width, canvas.height);
},
wasm_set_clip: (x, y, w, h) => { wasm_set_clip: (x, y, w, h) => {
ctx2d.restore(); ctx2d.restore();
ctx2d.save(); ctx2d.save();
@@ -115,6 +118,11 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
return parseFloat(mem.read_cstr(str, len)); return parseFloat(mem.read_cstr(str, len));
}, },
wasm_trap: () => { throw new Error() }, wasm_trap: () => { throw new Error() },
wasm_alert: (str, len) => {
const string = mem.read_cstr(str,len);
console.log(string);
alert(string);
},
}; };
const program = await WebAssembly['instantiate'](binary, { "env": wasm_imports }); const program = await WebAssembly['instantiate'](binary, { "env": wasm_imports });

View File

@@ -2,8 +2,11 @@
#define fn_wasm_export __attribute__((visibility("default"))) #define fn_wasm_export __attribute__((visibility("default")))
#define fn_wasm_import #define fn_wasm_import
fn_wasm_import void wasm_alert(isize ptr, i32 len);
fn_wasm_import f64 wasm_parse_float(isize str, i32 len); fn_wasm_import f64 wasm_parse_float(isize str, i32 len);
fn_wasm_import void wasm_write_to_console(isize str, i32 len); fn_wasm_import void wasm_write_to_console(isize str, i32 len);
fn_wasm_import void wasm_clear();
fn_wasm_import void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a); fn_wasm_import void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a);
fn_wasm_import void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a); fn_wasm_import void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a);
fn_wasm_import f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size); fn_wasm_import f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size);
@@ -27,13 +30,16 @@ glb f64 wasm_last_time = 0;
fn void app_update(ma_arena_t *perm_arena, app_event_t *events, i32 event_count); fn void app_update(ma_arena_t *perm_arena, app_event_t *events, i32 event_count);
fn void alert(s8_t string) {
wasm_alert((isize)string.str, (i32)string.len);
}
fn void puts(const char *string) { fn void puts(const char *string) {
wasm_write_to_console((isize)string, (i32)str_len((char *)string)); wasm_write_to_console((isize)string, (i32)str_len((char *)string));
} }
fn double strtod(const char *str, char **end_unused) { fn double strtod(const char *str, char **end_unused) {
assertf(end_unused == NULL, "second parameter should be null!!"); assert(end_unused == NULL);
return wasm_parse_float((isize)str, str_len((char *)str)); return wasm_parse_float((isize)str, str_len((char *)str));
} }
@@ -183,14 +189,17 @@ fn_wasm_export void wasm_key_up(char *key, b32 ctrl, b32 shift, b32 alt, b32 met
fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) { fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
f64 delta_time = (time - wasm_last_time); f64 delta_time = (time - wasm_last_time);
v2f32_t window_size = (v2f32_t){width / dpr, height / dpr};
for (i32 i = 0; i < wasm_events.len; i += 1) { for (i32 i = 0; i < wasm_events.len; i += 1) {
wasm_events.data[i].dpr = dpr; wasm_events.data[i].dpr = dpr;
wasm_events.data[i].window_size = (v2f32_t){width / dpr, height / dpr}; wasm_events.data[i].window_size = window_size;
wasm_events.data[i].time = time; wasm_events.data[i].time = time;
wasm_events.data[i].delta_time = delta_time; wasm_events.data[i].delta_time = delta_time;
} }
wasm_dpr = dpr; wasm_dpr = dpr;
wasm_clear();
draw_rect(r2f64(0, 0, window_size.x, window_size.y), white_color_global);
app_update(&wasm_perm_arena, wasm_events.data, wasm_events.len); app_update(&wasm_perm_arena, wasm_events.data, wasm_events.len);
wasm_events.len = 0; wasm_events.len = 0;
@@ -199,12 +208,24 @@ fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
} }
fn_wasm_export void wasm_init(void) { fn_wasm_export void wasm_init(void) {
isize page_size = kib(64); {
isize page_count = __builtin_wasm_memory_size(0); isize page_size = kib(64);
u8 *memory = (u8 *)&__heap_base; isize page_count = __builtin_wasm_memory_size(0);
usize memory_size = page_count * (page_size) - (isize)memory; u8 *memory = (u8 *)&__heap_base;
wasm_perm_arena.data = memory; usize memory_size = page_count * (page_size) - (isize)memory;
wasm_perm_arena.commit = wasm_perm_arena.reserve = memory_size; wasm_perm_arena.data = memory;
wasm_perm_arena.commit = wasm_perm_arena.reserve = memory_size;
// init core
{
ma_push_arena_ex(&wasm_perm_arena, &core_desc.scratch[0], mib(1));
ma_push_arena_ex(&wasm_perm_arena, &core_desc.scratch[1], kib(256));
ma_push_arena_ex(&wasm_perm_arena, &core_desc.scratch[2], kib(64));
}
debugf("on_init, __builtin_wasm_memory_size(0) = %d(%d)", page_count, memory_size);
}
wasm_input_text_arena = ma_push_arena(&wasm_perm_arena, kib(1)); wasm_input_text_arena = ma_push_arena(&wasm_perm_arena, kib(1));
debugf("on_init, __builtin_wasm_memory_size(0) = %d(%d)", page_count, memory_size);
} }

View File

@@ -18,8 +18,9 @@
#endif #endif
#if PLATFORM_WASM #if PLATFORM_WASM
double strtod(const char *str, char **end_unused); fn double strtod(const char *str, char **end_unused);
void puts(const char *str); fn void puts(const char *str);
fn void alert(s8_t string);
#endif #endif
#if PLATFORM_CL #if PLATFORM_CL

View File

@@ -83,6 +83,7 @@ fn void *ma_push_size_ex(ma_arena_t *arena, usize size) {
} }
} }
if (new_len > arena->commit) { if (new_len > arena->commit) {
invalid_codepath;
return NULL; return NULL;
} }
} }
@@ -98,12 +99,16 @@ fn void *ma_push_size(ma_arena_t *arena, usize size) {
return result; return result;
} }
fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size) { fn void ma_push_arena_ex(ma_arena_t *allocator, ma_arena_t *result, usize size) {
ma_arena_t *result = ma_push_type(allocator, ma_arena_t);
result->data = (u8 *)ma_push_size(allocator, size); result->data = (u8 *)ma_push_size(allocator, size);
result->reserve = size; result->reserve = size;
result->commit = size; result->commit = size;
result->align = ma_default_alignment; result->align = ma_default_alignment;
}
fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size) {
ma_arena_t *result = ma_push_type(allocator, ma_arena_t);
ma_push_arena_ex(allocator, result, size);
return result; return result;
} }
@@ -151,7 +156,7 @@ fn ma_temp_t ma_begin_scratch_ex(ma_arena_t **conflicts, int conflict_count) {
} }
} }
assertf(unoccupied, "Failed to get free scratch memory, this is a fatal error, this shouldnt happen"); assert(unoccupied); // failed to get free scratch memory, this is a fatal error, this shouldnt happen
ma_temp_t result = ma_begin_temp(unoccupied); ma_temp_t result = ma_begin_temp(unoccupied);
return result; return result;
} }

View File

@@ -26,9 +26,10 @@ fn void ma_destroy(ma_arena_t *arena);
// //
// push // push
fn void *ma_push_size_ex(ma_arena_t *arena, usize size);
fn void *ma_push_size(ma_arena_t *arena, usize size); fn void *ma_push_size(ma_arena_t *arena, usize size);
fn void *ma_push_size_ex(ma_arena_t *arena, usize size);
fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size); fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size);
fn void ma_push_arena_ex(ma_arena_t *allocator, ma_arena_t *result, usize size);
#define ma_push_type(arena, Type) (Type *)ma_push_size((arena), sizeof(Type)) #define ma_push_type(arena, Type) (Type *)ma_push_size((arena), sizeof(Type))
#define ma_push_array(arena, Type, count) (Type *)ma_push_size((arena), sizeof(Type) * (count)) #define ma_push_array(arena, Type, count) (Type *)ma_push_size((arena), sizeof(Type) * (count))

View File

@@ -46,6 +46,7 @@ typedef double f64;
#ifndef offsetof #ifndef offsetof
#define offsetof(st, m) ((usize)&(((st *)0)->m)) #define offsetof(st, m) ((usize)&(((st *)0)->m))
#endif #endif
#define expect(x) if (!(x))
#define kib(x) (1024ULL * (x##ULL)) #define kib(x) (1024ULL * (x##ULL))
#define mib(x) (1024ULL * kib(x)) #define mib(x) (1024ULL * kib(x))

View File

@@ -87,16 +87,6 @@ fn f64 f64_from_s8(s8_t string) {
return result; return result;
} }
fn void core_print_message(s8_t string) {
ma_temp_t scratch = ma_begin_scratch();
s8_t copy = s8_printf(scratch.arena, "%S\n", string);
#if PLATFORM_WINDOWS
OutputDebugStringA(copy.str);
#endif
puts(copy.str);
ma_end_scratch(scratch);
}
fn date_t date_now(void) { fn date_t date_now(void) {
date_t result = {0}; date_t result = {0};
#if PLATFORM_WASM #if PLATFORM_WASM

View File

@@ -35,6 +35,6 @@ THREAD_LOCAL core_desc_t core_desc = {
.log = { .log = {
.break_on_fatal = true, .break_on_fatal = true,
.log_proc = default_log_proc, .log_proc = default_log_proc,
.flags = log_flag_all, .flags = 0,
} }
}; };

View File

@@ -1,11 +1,11 @@
fn s8_t log_level_str(log_level_t level) { fn char *log_level_str(log_level_t level) {
switch(level) { switch(level) {
case log_level_debug: return s8_lit("DEBUG"); case log_level_debug: return "DEBUG";
case log_level_info: return s8_lit("INFO"); case log_level_info: return "INFO";
case log_level_warning: return s8_lit("WARN"); case log_level_warning: return "WARN";
case log_level_error: return s8_lit("ERROR"); case log_level_error: return "ERROR";
case log_level_fatal: return s8_lit("FATAL"); case log_level_fatal: return "FATAL";
default: return s8_lit("INVALID"); default: return "INVALID";
} }
} }
@@ -20,6 +20,17 @@ fn void log_basef(i32 module, log_level_t level, s8_t file_and_line, const char
ma_end_scratch(scratch); ma_end_scratch(scratch);
} }
fn void core_error_message(char *str) {
#if PLATFORM_WINDOWS
MessageBoxA(NULL, str, "fatal error", MB_OK);
fprintf(stderr, "%s", str);
#elif PLATFORM_WASM
alert(s8_from_char(str));
#else
fprintf(stderr, "%s", str);
#endif
}
fn void default_log_proc(log_event_t ev) { fn void default_log_proc(log_event_t ev) {
ma_temp_t scratch = ma_begin_scratch(); ma_temp_t scratch = ma_begin_scratch();
sb8_t *sb = sb8_serial_begin(scratch.arena); sb8_t *sb = sb8_serial_begin(scratch.arena);
@@ -27,7 +38,7 @@ fn void default_log_proc(log_event_t ev) {
sb8_printf(sb, "[%d] ", ev.module); sb8_printf(sb, "[%d] ", ev.module);
} }
if (core_desc.log.flags & log_flag_level) { if (core_desc.log.flags & log_flag_level) {
sb8_printf(sb, "%-5S ", log_level_str(ev.level)); sb8_printf(sb, "%-5s ", log_level_str(ev.level));
} }
date_t date = {0}; date_t date = {0};
{ {
@@ -47,23 +58,25 @@ fn void default_log_proc(log_event_t ev) {
sb8_printf(sb, "%-40S ", ev.file_and_line); sb8_printf(sb, "%-40S ", ev.file_and_line);
} }
sb8_printf(sb, " %S", ev.string); sb8_printf(sb, " %S\n", ev.string);
s8_t result = sb8_serial_end(sb); s8_t result = sb8_serial_end(sb);
core_print_message(result);
ma_end_scratch(scratch);
if (ev.level == log_level_fatal) { if (ev.level != log_level_fatal) {
if (core_desc.log.break_on_fatal) { IF_PLATFORM_WINDOWS(OutputDebugStringA(result.str);)
#if PLATFORM_WINDOWS puts(result.str);
if (IsDebuggerPresent()) } else {
#endif core_error_message(result.str);
#if PLATFORM_WASM
debug_break(); debug_break();
} else { #else
SWITCH_PLATFORM_WINDOWS_WASM_ELSE( if (core_desc.log.break_on_fatal) {
ExitProcess(1), debug_break();
debug_break(), } else {
exit(1) exit(1);
); }
} #endif
} }
ma_end_scratch(scratch);
} }

View File

@@ -52,23 +52,27 @@ struct logger_t {
b32 break_on_fatal; b32 break_on_fatal;
}; };
fn void log_base(i32 module, log_level_t level, s8_t file_and_line, s8_t string); ///////////////////////////////
fn void log_basef(i32 module, log_level_t level, s8_t file_and_line, const char *str, ...); // main api
fn s8_t log_level_str(log_level_t level);
#define debugf(...) log_basef(module_null, log_level_debug, S8_FILE_AND_LINE, __VA_ARGS__) #define debugf(...) log_basef(module_null, log_level_debug, S8_FILE_AND_LINE, __VA_ARGS__)
#define errorf(MODULE, ...) log_basef(MODULE, log_level_error, S8_FILE_AND_LINE, __VA_ARGS__) #define errorf(MODULE, ...) log_basef(MODULE, log_level_error, S8_FILE_AND_LINE, __VA_ARGS__)
#define fatalf(...) (log_basef(module_null, log_level_fatal, S8_FILE_AND_LINE, __VA_ARGS__), 0) #define fatalf(...) (log_basef(module_null, log_level_fatal, S8_FILE_AND_LINE, __VA_ARGS__), 0)
#define assert(x) (!(x) && fatalf("condition doesn't hold: " #x)) fn void core_error_message(char *str);
#define assertf(x, ...) (!(x) && fatalf("condition doesn't hold: " __VA_ARGS__)) #define program_version "---"
#if PLATFORM_DEBUG_ASSERT
#if PLATFORM_CL #define assert(x) (!(x) && (core_error_message(FILE_AND_LINE ": internal program error! assertion failed, program version: " program_version), debug_break()))
#define debug__break() __debugbreak()
#else #else
#define debug__break() __builtin_trap() #define assert(x) (void)(x)
#endif #endif
#define debug_break() (debug__break(), 0) #define not_implemented assert(!"not implemented!")
#define invalid_codepath assert(!"invalid code path!")
fn void log_base(i32 module, log_level_t level, s8_t file_and_line, s8_t string);
fn void log_basef(i32 module, log_level_t level, s8_t file_and_line, const char *str, ...);
/* /*

View File

@@ -64,6 +64,10 @@
#define PLATFORM_ADDRESS_SANITIZER 0 #define PLATFORM_ADDRESS_SANITIZER 0
#endif #endif
#ifndef PLATFORM_DEBUG_ASSERT
#define PLATFORM_DEBUG_ASSERT 1
#endif
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
#define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) WINDOWS #define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) WINDOWS
#elif PLATFORM_WASM #elif PLATFORM_WASM
@@ -72,7 +76,19 @@
#define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) ELSE #define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) ELSE
#endif #endif
#if PLATFORM_CL #if PLATFORM_CL
#pragma warning(disable: 4116) #pragma warning(disable: 4116)
#endif #endif
#if PLATFORM_CL
#define debug__break() __debugbreak()
#else
#define debug__break() __builtin_trap()
#endif
#define debug_break() (debug__break(), 0)
#if PLATFORM_WINDOWS
#define IF_PLATFORM_WINDOWS(x) x
#else
#define IF_PLATFORM_WINDOWS(x)
#endif

View File

@@ -69,8 +69,8 @@ fn s8_t s8_from_char(char *string) {
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string) { fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string) {
u16 *buffer = ma_push_array(ma, u16, string.len + 1); u16 *buffer = ma_push_array(ma, u16, string.len + 1);
i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len); i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len);
assert(len < string.len); assert(len <= string.len); // @todo: verify
return (s16_t){buffer,len}; return (s16_t){buffer, len};
} }
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) { fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
@@ -78,18 +78,15 @@ fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
char *buffer = ma_push_array(ma, char, buffer_size); char *buffer = ma_push_array(ma, char, buffer_size);
i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len); i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len);
assert(len < buffer_size); assert(len < buffer_size);
return (s8_t){buffer,len}; return (s8_t){buffer, len};
} }
fn s8_t s8_copy(ma_arena_t *ma, s8_t string) { fn s8_t s8_copy(ma_arena_t *ma, s8_t string) {
char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1)); char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1));
if (copy) { memory_copy(copy, string.str, string.len);
memory_copy(copy, string.str, string.len); copy[string.len] = 0;
copy[string.len] = 0; s8_t result = s8(copy, string.len);
s8_t result = s8(copy, string.len); return result;
return result;
}
return (s8_t){0};
} }
s8_t s8_copy_char(ma_arena_t *ma, char *s) { s8_t s8_copy_char(ma_arena_t *ma, char *s) {
@@ -207,8 +204,8 @@ s8_t s8_skip_past(s8_t string, s8_t a) {
fn s8_t s8_slice(s8_t string, int64_t first_index, int64_t one_past_last_index) { fn s8_t s8_slice(s8_t string, int64_t first_index, int64_t one_past_last_index) {
if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1; if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1;
if (first_index < 0) first_index = string.len + first_index; if (first_index < 0) first_index = string.len + first_index;
assert(first_index < one_past_last_index && "s8_slice, first_index is bigger then one_past_last_index"); assert(first_index < one_past_last_index);
assert(string.len > 0 && "Slicing string of length 0! Might be an error!"); assert(string.len > 0);
s8_t result = string; s8_t result = string;
if (string.len > 0) { if (string.len > 0) {
if (one_past_last_index > first_index) { if (one_past_last_index > first_index) {
@@ -476,10 +473,7 @@ fn u64 u64_from_s8(s8_t s, u64 base) {
u64 acc = 0; u64 acc = 0;
for (i64 i = 0; i < s.len; i++) { for (i64 i = 0; i < s.len; i++) {
u64 num = u64_from_hexchar(s.str[i]); u64 num = u64_from_hexchar(s.str[i]);
if (num >= base) { assert(num < base);
fatalf("failed to convert string into number, didn't expect: %c", s.str[i]);
break;
}
acc *= base; acc *= base;
acc += num; acc += num;
} }

View File

@@ -368,7 +368,8 @@ fn void ti__deserial_data_ex(ma_arena_t *arena, parser_t *par, void *p, type_t *
lex_t *ident = parser_expect(par, lex_kind_ident); lex_t *ident = parser_expect(par, lex_kind_ident);
parser_expect(par, lex_kind_colon); parser_expect(par, lex_kind_colon);
assert(s8_equal(ident->string, mem->name));
expect (s8_equal(ident->string, mem->name)) fatalf("expected identifier: %S, got instead %S", mem->name, ident->string);
ti__deserial_data_ex(arena, par, mem_p, mem->type); ti__deserial_data_ex(arena, par, mem_p, mem->type);
parser_expect(par, lex_kind_comma); parser_expect(par, lex_kind_comma);

View File

@@ -5,25 +5,24 @@
// #include "debug.c" // #include "debug.c"
// #include "ui2.c" // #include "ui2.c"
ma_arena_t *frame_arena; f64 delta_time;
void app_update(ma_arena_t *perm_arena, app_event_t *events, i32 event_count) { void app_update(ma_arena_t *perm_arena, app_event_t *events, i32 event_count) {
if (frame_arena == NULL) { if (event_count) delta_time = events[0].delta_time;
frame_arena = ma_push_arena(perm_arena, kib(32)); draw_textf(v2f64(0,0), "delta time: %f", delta_time);
}
f64 pos = 0.0; ma_scratch_scope(temp) {
f64 offset = get_font_height() + 8; f64 offset = get_font_height() + 8;
for (i32 i = 0; i < event_count; i += 1) { f64 pos = offset;
s8_t string = ti_serial_data(frame_arena, events + i, app_event_t); for (i32 i = 0; i < event_count; i += 1) {
sb8_t split = s8_split(frame_arena, string, s8_lit("\n"), s8_split_none); s8_t string = ti_serial_data(temp.arena, events + i, app_event_t);
sb8_t split = s8_split(temp.arena, string, s8_lit("\n"), s8_split_none);
for (sb8_node_t *it = split.first; it; it = it->next) { for (sb8_node_t *it = split.first; it; it = it->next) {
draw_text((v2f64_t){0, pos}, white_color_global, it->string); draw_text((v2f64_t){0, pos}, black_color_global, it->string);
pos += offset; pos += offset;
}
} }
} }
ma_set0(frame_arena);
} }

View File

@@ -1,6 +1,7 @@
[ ] platform [ ] platform
[ ] app [ ] app
[ ] wasm [ ] wasm
[x] exit function: maybe using alert
[ ] win32 [ ] win32
[ ] hot reload / plugins [ ] hot reload / plugins
[ ] linux [ ] linux
@@ -13,7 +14,7 @@
[ ] revisit api [ ] revisit api
[ ] core [ ] core
[ ] revisit api [x] revisit api
[ ] s8_bin [ ] s8_bin
[ ] bin_write_begin - serialize binary data (sb8_bin_write?) [ ] bin_write_begin - serialize binary data (sb8_bin_write?)
bin_write_end bin_write_end