From: hgn Date: Sun, 5 Oct 2025 19:05:54 +0000 (+0000) Subject: thingies X-Git-Url: https://skaterift.com/git/?a=commitdiff_plain;h=cc7231b076af7fec7b83199f81f93cb561d503b8;p=vg.git thingies --- diff --git a/async.kv b/async.kv new file mode 100644 index 0000000..51f5f87 --- /dev/null +++ b/async.kv @@ -0,0 +1,7 @@ +add source/foundation/async.c + +hook +{ + event START + function _async_init +} diff --git a/bootstrap.sh b/bootstrap.sh index 86c6f1a..9438346 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -2,7 +2,6 @@ mkdir -p bin/vg.metacompiler-linux-x86_64-zig-cc/ && taskset -c 0-1 zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unused-function -O0 -ggdb \ -std=c11 -D_DEFAULT_SOURCE \ -include "common_api.h" \ - source/terminal/main.c \ source/foundation/options.c \ source/foundation/logging.c \ source/foundation/allocator_heap.c \ diff --git a/foundation.kv b/foundation.kv index fb1c376..20a0e3c 100644 --- a/foundation.kv +++ b/foundation.kv @@ -1,7 +1,24 @@ include include/ include source/ + +event +{ + name OPTIONS + prototype "void" +} +event +{ + name START + prototype "void" +} + add source/foundation/options.c add source/foundation/logging.c +{ + hook OPTIONS + function _log_options +} + add source/foundation/allocator_heap.c add source/foundation/allocator_stack.c add source/foundation/allocator_pool.c @@ -12,7 +29,6 @@ add source/foundation/string.c add source/foundation/keyvalues.c add source/foundation/buffer_operations.c add source/foundation/temporary.c -add source/foundation/async.c { if linux @@ -33,11 +49,79 @@ add source/foundation/async.c { if game_engine - add source/engine/main.c - add source/engine/ui.c + { + add source/engine/main.c + hook + { + event OPTIONS + function _engine_options + } + } + + { + add source/engine/ui.c + hook + { + event START + function _engine_ui_init + } + } + + { + add source/engine/input.c + hook + { + event START + function _input_init + } + ccmd + { + name bind + function _input_bind_ccmd + description "Bind device input to a button, action or axis" + + parameter + { + description "Device input alias" + } + + parameter + { + description "button,action,axis name" + } + } + ccmd + { + name unbind + description "Unbind all bindings that match" + function _input_unbind_ccmd + + parameter + { + description "binding" + } + } + } + + { + add source/console_core.c + hook + { + event START + function _console_init + } + } + + { + add source/engine/console.c + hook + { + event START + function _engine_console_init + } + } + add source/engine/shader.c - add source/engine/console.c - add source/console_core.c input_layer { name console @@ -49,10 +133,12 @@ add source/foundation/async.c layer_mask console } + append async.kv thread { name main queue_size_m 40 + flag MAIN } thread { @@ -72,34 +158,6 @@ add source/foundation/async.c append graphics.kv append glfw3.kv - add source/engine/input.c - ccmd - { - name bind - function _input_bind_ccmd - description "Bind device input to a button, action or axis" - - parameter - { - description "Device input alias" - } - - parameter - { - description "button,action,axis name" - } - } - ccmd - { - name unbind - description "Unbind all bindings that match" - function _input_unbind_ccmd - - parameter - { - description "binding" - } - } ccmd { @@ -222,11 +280,16 @@ add source/foundation/async.c { type vertex add shaders/blit.vs - + uniform { - type sampler2D - alias uTexMain + type vec2 + alias uInverseRatio + } + uniform + { + type int + alias uFlip } } @@ -234,6 +297,12 @@ add source/foundation/async.c { type fragment add shaders/blit_tex.fs + + uniform + { + type sampler2D + alias uTexMain + } } } @@ -245,12 +314,6 @@ add source/foundation/async.c cheat 1 description "This is just a test variable!" } - - event - { - name ENGINE_INIT - prototype "void" - } event { name ENGINE_FIXED_UPDATE @@ -271,4 +334,10 @@ add source/foundation/async.c name ENGINE_UI prototype "void" } + + hook + { + event START + function "_shaders_compile" + } } diff --git a/include/common_api.h b/include/common_api.h index 2c3c7b7..985bba4 100644 --- a/include/common_api.h +++ b/include/common_api.h @@ -3,6 +3,13 @@ #define API #define IMPL +#define VG_PRE_MAIN \ + _exit_init(); \ + _log_init(); \ + _options_init( argc, argv ); \ + EVENT_CALL( OPTIONS ); \ + _options_check_end(); + /* Types * ------------------------------------------------------------------------------------------------------------------ */ typedef unsigned char u8; @@ -297,8 +304,7 @@ enum string_parse_result string_parse_string( struct stream *string, u32 *out_st struct stream *_log_event( u32 type, const c8 *code_location ); void _log_init(void); void _log_end_event(void); -void _log_set_journal_path( const c8 *path ); -void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 filter ); +void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 filter, bool accept_vt_codes ); /* Keyvalues * ------------------------------------------------------------------------------------------------------------------ */ diff --git a/include/opengl.h b/include/opengl.h index c30219b..b04c497 100644 --- a/include/opengl.h +++ b/include/opengl.h @@ -1,5 +1,7 @@ #include "vg/dep/glad.4.3/glad/glad.h" +#include "generated/shaders.h" -API GLuint compile_opengl_subshader( GLint type, const c8 *src, bool critical, const c8 *debug_path ); +API GLuint compile_opengl_subshader( GLint type, const c8 *sources[], u32 source_count, bool critical, const c8 *debug_path ); API bool link_opengl_program( GLuint program, bool critical ); -API GLuint compile_opengl_shader( const c8 *vs, const c8 *fs ); + +void _shader_bind( enum shader_id id ); diff --git a/shaders/blit.vs b/shaders/blit.vs index 06ffba6..e19a10f 100644 --- a/shaders/blit.vs +++ b/shaders/blit.vs @@ -1,10 +1,12 @@ layout (location=0) in vec2 a_co; out vec2 aUv; -uniform vec2 uInverseRatio; - void main() { gl_Position = vec4(a_co*2.0-1.0,0.0,1.0); - aUv = a_co * uInverseRatio; + + if( uFlip == 1 ) + aUv = vec2(a_co.x,1.0-a_co.y) * uInverseRatio; + else + aUv = a_co * uInverseRatio; } diff --git a/source/engine/console.c b/source/engine/console.c index 0920b69..005ff54 100644 --- a/source/engine/console.c +++ b/source/engine/console.c @@ -64,7 +64,7 @@ again:; void _engine_console_init(void) { - _log_add_listener( _log_listener, ($info | $ok | $warning | $error | $fatal | $shell) ); + _log_add_listener( _log_listener, ($info | $ok | $warning | $error | $fatal | $shell), 0 ); queue_init( &_console.input_history, _heap_allocate( BYTES_KB(2) ), BYTES_KB(2) ); queue_init( &_console.log_history, _heap_allocate( BYTES_KB(4) ), BYTES_KB(4) ); } diff --git a/source/engine/main.c b/source/engine/main.c index 8f4d938..20fc9fe 100644 --- a/source/engine/main.c +++ b/source/engine/main.c @@ -38,24 +38,19 @@ void _character_callback( GLFWwindow *window, u32 codepoint ) _engine_ui_input_character( codepoint ); } -i32 main( i32 argc, const c8 *argv[] ) +void _engine_options(void) { - _exit_init(); - _log_init(); - _options_init( argc, argv ); - const c8 *arg; if( _option_long( "high-performance", "Turn graphics to lowest quality" ) ) _engine.quality = k_quality_profile_low; - if( (arg = _option_long_argument( "log", "Log output to text file (without console colours)" )) ) - _log_set_journal_path( arg ); - //if( vg_long_opt( "no-steam", "Disable Steam integration (Good idea for pirating)" ) ) // _steam_api.disabled = 1; - - EVENT_CALL( ENGINE_INIT ); - _options_check_end(); +} + +i32 main( i32 argc, const c8 *argv[] ) +{ + VG_PRE_MAIN; ASSERT_CRITICAL( glfwInit() ); @@ -79,10 +74,7 @@ i32 main( i32 argc, const c8 *argv[] ) f64 next_frame_time = 0.0, fixed_time = 0.0, fixed_accumulator = 0.0; /* ------------- */ - _engine_ui_init(); - _input_init(); - _console_init(); - _engine_console_init(); + EVENT_CALL( START ); L_new_frame:; f64 now = glfwGetTime(); diff --git a/source/engine/shader.c b/source/engine/shader.c index 2d2b3b2..8183d3d 100644 --- a/source/engine/shader.c +++ b/source/engine/shader.c @@ -1,9 +1,6 @@ #include "opengl.h" -#include "generated/shaders.h" -GLuint _uniform_locations[ k_shader_uniform_count ]; - -GLuint compile_opengl_subshader( GLint type, const c8 *src, bool critical, const c8 *debug_path ) +GLuint compile_opengl_subshader( GLint type, const c8 *sources[], u32 source_count, bool critical, const c8 *name ) { GLuint shader = glCreateShader( type ); if( shader == 0 ) @@ -12,7 +9,7 @@ GLuint compile_opengl_subshader( GLint type, const c8 *src, bool critical, const _fatal_exit(); } - glShaderSource( shader, 2, (const char*[2]){ "#version 330 core\n", src }, NULL ); + glShaderSource( shader, source_count, sources, NULL ); glCompileShader( shader ); GLint status; @@ -30,7 +27,7 @@ GLuint compile_opengl_subshader( GLint type, const c8 *src, bool critical, const else if( type == GL_FRAGMENT_SHADER ) type_str = "GL_FRAGMENT_SHADER"; if( critical ) { - $log( $fatal, {"subshader compile error\n"}, {debug_path}, {": "}, {type_str}, {info} ); + $log( $fatal, {"subshader compile error\n"}, {name}, {": "}, {type_str}, {info} ); _fatal_exit(); } return 0; @@ -57,6 +54,7 @@ bool link_opengl_program( GLuint program, bool critical ) } } +#if 0 GLuint compile_opengl_shader( const c8 *vs, const c8 *fs ) { GLuint vert = compile_opengl_subshader( GL_VERTEX_SHADER, vs, 1, NULL ), @@ -69,6 +67,10 @@ GLuint compile_opengl_shader( const c8 *vs, const c8 *fs ) glDeleteShader( frag ); return program; } +#endif + +GLuint _shader_programs[ k_shader_count ]; +GLuint _uniform_locations[ k_shader_uniform_count ]; struct shader { @@ -93,3 +95,46 @@ struct shader }; #include "generated/shaders.c" + +void _shaders_compile(void) +{ + for( u32 i=0; isubshader_count; j ++ ) + { + struct subshader *subshader = &shader->subshaders[j]; + + const c8 *sources[32] = { "#version 330 core\n", NULL }; + u32 source_count = 1; + sources[ source_count ++ ] = subshader->source_uniforms; + sources[ source_count ++ ] = subshader->source_static; + + ASSERT_CRITICAL( subshader->type != k_subshader_geometry ); + sub_programs[j] = compile_opengl_subshader( + (subshader->type == k_subshader_vertex? GL_VERTEX_SHADER: GL_FRAGMENT_SHADER), + sources, source_count, 1, shader->name ); + glAttachShader( new_program, sub_programs[j] ); + } + + link_opengl_program( new_program, 1 ); + _shader_programs[i] = new_program; + + for( u32 j=0; jsubshader_count; j ++ ) + glDeleteShader( sub_programs[j] ); + + for( u32 j=0; juniform_count; j ++ ) + { + u32 index = shader->uniform_start+j; + _uniform_locations[ index ] = glGetUniformLocation( new_program, _uniform_aliases[ index ] ); + } + } +} + +void _shader_bind( enum shader_id id ) +{ + glUseProgram( _shader_programs[ id ] ); +} diff --git a/source/engine/ui.c b/source/engine/ui.c index 970cf84..931cb28 100644 --- a/source/engine/ui.c +++ b/source/engine/ui.c @@ -10,7 +10,6 @@ struct graphics_target _ui_surface = }; GLuint _ui_surface_texture; -GLuint _ui_blit_shader; GLuint quad_vao, quad_vbo; void _engine_ui_init(void) @@ -40,27 +39,6 @@ void _engine_ui_init(void) glBindVertexArray( quad_vao ); glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(f32)*2, (void*)0 ); glEnableVertexAttribArray( 0 ); - - const c8 *blit_vs = -"layout (location=0) in vec2 a_co;\n" -"out vec2 aUv;\n" -"uniform vec2 uInverseRatio;\n" -"void main()\n" -"{\n" -" gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n" -" aUv = vec2(a_co.x,1.0-a_co.y) * uInverseRatio;\n" -"}\n"; - - const c8 *blit_fs = -"out vec4 FragColor;\n" -"uniform sampler2D uTexMain;\n" -"in vec2 aUv;\n" -"void main()\n" -"{\n" -" FragColor = texture( uTexMain, aUv );\n" -"}\n"; - - _ui_blit_shader = compile_opengl_shader( blit_vs, blit_fs ); } void _engine_ui_pre_render(void) @@ -119,9 +97,10 @@ void _engine_ui_post_render(void) glBindTexture( GL_TEXTURE_2D, _ui_surface_texture ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 1920, 1080, GL_BGRA, GL_UNSIGNED_BYTE, _ui_surface.buffer ); - glUseProgram( _ui_blit_shader ); - glUniform1i( glGetUniformLocation( _ui_blit_shader, "uTexMain" ), 0 ); - glUniform2f( glGetUniformLocation( _ui_blit_shader, "uInverseRatio" ), (f64)_engine.w/1920.0, (f64)_engine.h/1080.0 ); + _shader_bind( k_shader_blit ); + _shader_blit_uTexMain( 0 ); + _shader_blit_uFlip( 1 ); + _shader_blit_uInverseRatio( (f32[2]){ (f64)_engine.w/1920.0, (f64)_engine.h/1080.0 } ); glBindVertexArray( quad_vao ); glDrawArrays( GL_TRIANGLES, 0, 6 ); } diff --git a/source/foundation/logging.c b/source/foundation/logging.c index a90917d..8fa4617 100644 --- a/source/foundation/logging.c +++ b/source/foundation/logging.c @@ -5,81 +5,127 @@ static struct stream _log_stream; static struct stream _stdout_stream; static struct stream _journal_stream; -static mtx_t _lock; -static bool _writing_event; + +#define OUTPUT_LINE_LENGTH 120 +#define VT_MAX_LENGTH 10 struct { - c8 line[ 121 ]; - u32 line_length; + bool writing_event; + mtx_t lock; + + c8 line[ OUTPUT_LINE_LENGTH + VT_MAX_LENGTH + 2 /* \n\0 */ ]; + u32 line_length, line_length_visual, vt_filter; - bool wait; u32 current_type; struct log_line_callback { u32 filter; + bool accept_vt_codes; void( *fn )( const c8 *line, u32 length, u32 type ); } callbacks[ 8 ]; u32 callback_count; } -_listeners; +_log; -void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 filter ) +void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 filter, bool accept_vt_codes ) { - ASSERT_CRITICAL( _listeners.callback_count < ARRAY_COUNT( _listeners.callbacks ) ); - struct log_line_callback *cb = &_listeners.callbacks[ _listeners.callback_count ++ ]; + ASSERT_CRITICAL( _log.callback_count < ARRAY_COUNT( _log.callbacks ) ); + struct log_line_callback *cb = &_log.callbacks[ _log.callback_count ++ ]; cb->fn = fn; cb->filter = filter; + cb->accept_vt_codes = accept_vt_codes; } static u32 _log_stream_passthrough( struct stream *stream, const void *buffer, u32 length ) { - // TODO: Allow colour codes into the line buffer, but those dont count towards line length. - // the AFTERWARDS, filter out the codes and send those to the listeners. for( u32 i=0; ifilter & _log.current_type) && cb->accept_vt_codes ) + cb->fn( _log.line, _log.line_length, _log.current_type ); + } - bool wrap = (_listeners.line_length == (ARRAY_COUNT( _listeners.line )-1)); - if( wrap || nl ) + /* Take out VT codes */ + u32 vt_filter; + u32 k = 0; + for( u32 j=0; j<_log.line_length; j ++ ) + { + u8 c = _log.line[ j ]; + if( vt_filter ) { - _listeners.line[ _listeners.line_length ] = 0; - - if( _journal_stream.flags & k_stream_write ) - stream_write( &_journal_stream, _listeners.line, _listeners.line_length ); - - for( u32 j=0; j<_listeners.callback_count; j ++ ) - { - struct log_line_callback *cb = &_listeners.callbacks[j]; - if( cb->filter & _listeners.current_type ) - cb->fn( _listeners.line, _listeners.line_length, _listeners.current_type ); - } - stream_write( &_stdout_stream, _listeners.line, _listeners.line_length ); - _listeners.line_length = 0; + if( c == 'm' ) vt_filter = 0; + else vt_filter ++; + continue; } - - if( _writing_event && (nl||wrap) ) + else { - while( _listeners.line_length < 33 ) - _listeners.line[ _listeners.line_length ++ ] = ' '; - _listeners.line[ _listeners.line_length ++ ] = '.'; + if( c == 0x1B ) vt_filter ++; + else _log.line[ k ++ ] = c; } } + _log.line_length = k; + _log.line[ k ] = 0; + + if( _journal_stream.flags & k_stream_write ) + stream_write( &_journal_stream, _log.line, _log.line_length ); + for( u32 j=0; j<_log.callback_count; j ++ ) + { + struct log_line_callback *cb = &_log.callbacks[j]; + if( (cb->filter & _log.current_type) && !cb->accept_vt_codes ) + cb->fn( _log.line, _log.line_length, _log.current_type ); + } + + _log.line_length = 0; + _log.line_length_visual = 0; + } + + if( _log.writing_event && wrap ) + { + while( _log.line_length < 33 ) + _log.line[ _log.line_length ++ ] = ' '; + _log.line[ _log.line_length ++ ] = '.'; + _log.line_length_visual = _log.line_length; } } @@ -87,34 +133,26 @@ static u32 _log_stream_passthrough( struct stream *stream, const void *buffer, u return length; } -void _log_set_journal_path( const c8 *path ) -{ - _journal_stream.posix_stream = fopen( path, "wb" ); - ASSERT_CRITICAL( _journal_stream.posix_stream ); - _journal_stream.offset = 0; - _journal_stream.buffer_length = 0; - _journal_stream.flags = k_stream_posix | k_stream_write; -} - struct stream *_log_event( u32 type, const c8 *code_location ) { - ASSERT_CRITICAL( mtx_lock( &_lock ) == thrd_success ); - _listeners.current_type = type; + ASSERT_CRITICAL( mtx_lock( &_log.lock ) == thrd_success ); + _log.current_type = type; struct stream *output = &_log_stream; string_append( output, KBLK, 0 ); - u32 line_start = output->offset; - - i32 s = buffer_last_index( code_location, '/', 0 ); - if( s != -1 ) + if( type != $raw ) { - string_append( output, "...", 0 ); - code_location += s+1; + i32 s = buffer_last_index( code_location, '/', 0 ); + if( s != -1 ) + { + string_append( output, "...", 0 ); + code_location += s+1; + } + string_append( output, code_location, 0 ); + while( _log.line_length_visual < 30 ) string_append_c8( output, ' ' ); } - string_append( output, code_location, 0 ); - while( (output->offset-line_start) < 30 ) string_append_c8( output, ' ' ); if( type == $error ) string_append( output, KRED "ERR|", 0 ); else if( type == $warning ) string_append( output, KYEL "WRN|", 0 ); else if( type == $ok ) string_append( output, KGRN "OK |", 0 ); @@ -124,23 +162,21 @@ struct stream *_log_event( u32 type, const c8 *code_location ) else if( type == $shell ) string_append( output, KBLU "SHL|", 0 ); string_append( output, KNRM, 0 ); - _writing_event = 1; + _log.writing_event = 1; return output; } void _log_end_event(void) { - _writing_event = 0; - + _log.writing_event = 0; struct stream *output = &_log_stream; string_append( output, "\n", 0 ); - - ASSERT_CRITICAL( mtx_unlock( &_lock ) == thrd_success ); + ASSERT_CRITICAL( mtx_unlock( &_log.lock ) == thrd_success ); } void _log_init(void) { - ASSERT_CRITICAL( mtx_init( &_lock, mtx_plain ) == thrd_success ); + ASSERT_CRITICAL( mtx_init( &_log.lock, mtx_plain ) == thrd_success ); _stdout_stream.posix_stream = stdout; _stdout_stream.offset = 0; _stdout_stream.buffer_length = 0; @@ -150,3 +186,16 @@ void _log_init(void) _log_stream.offset = 0; _log_stream.write_procedure = _log_stream_passthrough; } + +void _log_options(void) +{ + const c8 *arg; + if( (arg = _option_long_argument( "log", "Log output to text file (without console colours)" )) ) + { + _journal_stream.posix_stream = fopen( arg, "wb" ); + ASSERT_CRITICAL( _journal_stream.posix_stream ); + _journal_stream.offset = 0; + _journal_stream.buffer_length = 0; + _journal_stream.flags = k_stream_posix | k_stream_write; + } +} diff --git a/source/foundation/options.c b/source/foundation/options.c index c3eeedc..556d2a0 100644 --- a/source/foundation/options.c +++ b/source/foundation/options.c @@ -107,7 +107,7 @@ void _options_check_end(void) struct option *option = &_options.options[i]; const c8 *desc = option->desc? option->desc: ""; - struct stream *log = _log_event( $raw, NULL ); + struct stream *log = _log_event( $raw, $line ); u32 base_offset = log->offset; if( option->type == k_option_type_flag || option->type == k_option_type_option ) @@ -124,10 +124,9 @@ void _options_check_end(void) $v_string( log, {"="} ); } - while( log->offset < base_offset + 60 ) + while( log->offset < base_offset + 40 ) string_append_c8( log, ' ' ); string_append( log, desc, 0 ); - string_append_c8( log, '\n' ); _log_end_event(); } _normal_exit(); @@ -141,7 +140,7 @@ void _options_check_end(void) { if( argument->type == k_argument_singles ) { - for( u32 j=0; j<32; j ++ ) + for( u32 j=0; j<31; j ++ ) { if( !(argument->used & (0x1<name)}, {"_"}, {alias}, {",\n"} ); $v_string( &_shaders.uniform_aliases, {" [k_shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, {"] = \""}, {alias},{"\",\n"} ); - $v_string( &subshader->uniform_source, {"uniform "}, {type}, {" "}, {alias}, {"\\n"} ); + $v_string( &subshader->uniform_source, {"uniform "}, {type}, {" "}, {alias}, {";\\n"} ); - $v_string( &_shaders.uniform_func_protos, {"void _shader"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" );\n"} ); - $v_string( &_shaders.uniform_funcs, {"void _shader"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" )"}, + $v_string( &_shaders.uniform_func_protos, {"void _shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" );\n"} ); + $v_string( &_shaders.uniform_funcs, {"void _shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" )"}, {"{ "},{trans->call},{"( _uniform_locations["}, {"k_shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, {"], "},{trans->end},{" ); }\n"}); @@ -552,7 +552,7 @@ const c8 *platform_names[] = u64 processors = 4; const c8 *target_file_path = NULL; -i32 _terminal_init(void) +void _metacompiler_options(void) { const c8 *arg; if( _option_long( "tsan", "Build using thread sanitizer" ) ) @@ -589,12 +589,18 @@ i32 _terminal_init(void) target_file_path = _option(); ASSERT_CRITICAL( target_file_path ); - - return 0; } -i32 _terminal_main(void) +void (*_event_OPTIONS_subscribers[])( void ) = +{ + _metacompiler_options, + NULL +}; + +i32 main( i32 argc, const c8 *argv[] ) { + VG_PRE_MAIN; + buffer_copy( "project", 0, _metacompiler.project_name, sizeof(_metacompiler.project_name) ); u32 options = k_stream_null_terminate;