--- /dev/null
+#ifndef VG_LOG_C
+#include <stdarg.h>
+#include <string.h>
+#include <malloc.h>
+#include "vg_stdint.h"
+#include "vg_platform.h"
+#include "vg_log.h"
+
+#ifndef _WIN32
+ #include <execinfo.h>
+#endif
+
+static void _vg_log_append_line( const char *str ){
+ if( vg_log.log_line_count < vg_list_size( vg_log.log ) )
+ vg_log.log_line_count ++;
+
+ char *dest = vg_log.log[ vg_log.log_line_current ++ ];
+ vg_strncpy( str, dest, vg_list_size(vg_log.log[0]), k_strncpy_allow_cutoff );
+
+ if( vg_log.log_line_current >= vg_list_size( vg_log.log ) )
+ vg_log.log_line_current = 0;
+}
+
+static void _vg_logx_va( FILE *file,
+ const char *location, const char *prefix,
+ const char *colour,
+ const char *fmt, va_list args )
+{
+
+ /* @model.h:2000 info| dwahjdiawdjaiwdwadwa djaidjwa\n
+ * | djwaidwaj waodawh a\n
+ * | dwajdkiawjdiw
+ */
+
+#ifdef VG_GAME
+ SDL_AtomicLock( &log_print_sl );
+#endif
+
+ char buffer[4096];
+
+ vsnprintf( buffer, vg_list_size(buffer), fmt, args );
+
+ const char *line = buffer;
+ char logline[96];
+
+ for( u32 i=0; i<vg_list_size(buffer); i++ ){
+ char c = buffer[i];
+
+ if( c == '\0' || c == '\n' ){
+ buffer[i] = '\0';
+
+ const char *line_prefix = "",
+ *line_location = "";
+
+ if( line == buffer ) {
+ line_prefix = prefix;
+ line_location = location;
+ }
+
+ snprintf( logline, 96, "%s%7s" KNRM "|%s %s",
+ colour, line_prefix, colour, line );
+ _vg_log_append_line( logline );
+
+ if( location ){
+#ifdef VG_GAME
+ const char *thread_colours[] = {
+ KGRN, KMAG, KCYN, KYEL, KBLU
+ };
+
+ const char *colour = thread_colours[
+ (vg_thread_purpose() % vg_list_size( thread_colours ))];
+
+ fprintf( file, "%s[%u]"KNRM"%.32s",
+ colour, vg_thread_purpose(), line_location );
+#else
+ fprintf( file, KNRM "%.32s", line_location );
+#endif
+ }
+
+ fputs( logline, file );
+ fputc( '\n', file );
+ fputs( KNRM, file );
+
+ if( c == '\0' ) break;
+ if( buffer[i+1] == '\0' ) break;
+ line = buffer+i+1;
+ }
+ }
+
+#ifdef VG_GAME
+ SDL_AtomicUnlock( &log_print_sl );
+#endif
+}
+
+static void vg_logx( FILE *file,
+ const char *location, const char *prefix,
+ const char *colour,
+ const char *fmt, ... ){
+
+ va_list args;
+ va_start( args, fmt );
+ _vg_logx_va( file,
+#ifdef VG_LOG_SOURCE_INFO
+ location,
+#else
+ NULL,
+#endif
+ prefix, colour, fmt, args );
+ va_end( args );
+}
+
+static void vg_print_backtrace(void){
+#ifndef _WIN32
+
+ void *array[20];
+ char **strings;
+ int size, i;
+
+ size = backtrace( array, 20 );
+ strings = backtrace_symbols( array, size );
+
+ if( strings != NULL ){
+ vg_error( "---------------- gnu backtrace -------------\n" );
+
+ for( int i=0; i<size; i++ )
+ vg_info( "%s\n", strings[i] );
+
+ vg_error( "---------------- gnu backtrace -------------\n" );
+ }
+
+ free( strings );
+
+#endif
+}
+
+#endif /* VG_LOG_C */