el patcho
authorhgn <hgodden00@gmail.com>
Fri, 15 Aug 2025 00:40:02 +0000 (00:40 +0000)
committerhgn <hgodden00@gmail.com>
Fri, 15 Aug 2025 00:40:02 +0000 (00:40 +0000)
13 files changed:
vg_async2.c
vg_engine.c
vg_engine.h
vg_kv.c
vg_kv.h
vg_loader.c
vg_loader.h
vg_log.c
vg_msg.c
vg_msg.h
vg_platform.h
vg_string.c
vg_tex.c

index cf6260bc22872bd0467aca39d2bbaba978a95f35..6debe925a11133cc4682ba530268b37c83962dae 100644 (file)
@@ -199,7 +199,7 @@ bool vg_async_process_next_task( vg_async_queue *queue )
             .buffer_size = task->buffer_size,
          };
 
-         _vg_async_context_push_groups( task->groups );
+         _vg_async_context_push_groups( task->groups, 0 );
          task->fn( (void *)task->buffer, &info );
          _vg_async_context_pop_groups();
          _vg_async_group_increment( task->groups, -1 );
index cdf31b6a341960105b192c11ac5b4f0a717b8e27..a04efc61392d8c4290afc408838f4dcae205a626 100644 (file)
@@ -88,13 +88,17 @@ VG_API vg_stack_allocator *_vg_temp_stack(void)
 }
 
 /* group control */
-VG_API void _vg_async_context_push_groups( u16 groups )
+VG_API void _vg_async_context_push_groups( u16 groups, bool exclusive )
 {
    struct vg_thread_context *context = SDL_TLSGet( vg.thread_tls );
 
    context->async_group_depth ++;
    VG_ASSERT( context->async_group_depth < VG_TEMP_STACK_MAX );
-   context->async_groups[ context->async_group_depth ] = groups | context->async_groups[ context->async_group_depth-1 ];
+
+   if( !exclusive )
+      groups |= context->async_groups[ context->async_group_depth-1 ];
+
+   context->async_groups[ context->async_group_depth ] = groups;
 }
 
 VG_API void _vg_async_context_pop_groups(void)
@@ -146,10 +150,12 @@ static void vg_call_exit( struct exit_task *in_args, vg_async_info *async )
 
 VG_API void _vg_add_exit_function( void( *fn )( void ) )
 {
+   _vg_async_context_push_groups( 0, 1 );
    vg_async_task *task = vg_create_task( &vg.exit_tasks, sizeof(struct exit_task), VG_ASYNC_CRIT, "engine exit (No info)" );
    struct exit_task *out_args = vg_task_buffer( &vg.exit_tasks, task );
    out_args->fn = fn;
    vg_task_send( &vg.exit_tasks, task, (vg_async_fn)vg_call_exit );
+   _vg_async_context_pop_groups();
 }
 
 #ifdef _WIN32
@@ -376,7 +382,9 @@ L_filter_frame:
    if( vg.fps_limit > 300 ) 
       vg.fps_limit = 300;
 
-   f64 min_frametime = 1.0/(f64)vg.fps_limit;
+   f64 min_frametime = 1.0/(f64)vg.fps_limit,
+       max_frametime = 1.0/(f64)24.0;
+
    if( vg.time_frame_delta < min_frametime )
    {
       /* TODO: we can use high res nanosleep on Linux here */
@@ -389,6 +397,9 @@ L_filter_frame:
       goto L_filter_frame;
    }
 
+   if( vg.time_frame_delta > max_frametime )
+      vg.time_frame_delta = max_frametime;
+
    /* New fame starts here 
     * --------------------------------------------------------------------------------------------------------------- */
 
@@ -397,6 +408,8 @@ L_filter_frame:
    vg.time += vg.time_delta;
 
    /* SDL event loop */
+   v2_zero( vg.mouse_wheel );
+   v2_zero( vg.mouse_delta );
    SDL_Event event;
    while( SDL_PollEvent( &event ) )
    {
@@ -460,84 +473,77 @@ L_filter_frame:
          ui_proc_utf8( &vg_ui.ctx, event.text.text );
    }
    vg.mouse_state = SDL_GetMouseState( &vg.mouse_pos[0], &vg.mouse_pos[1] );
-   v2_zero( vg.mouse_wheel );
-   v2_zero( vg.mouse_delta );
    _vg_window_swap();
 
    vg_audio_preupdate();
    vg_process_inputs();
    vg_steam_frame();
       
-   if( 1 )
+   /* Update loop
+    * ----------------------------------------------------------------------------------------------------------- */
    {
-      /* Update loop
-       * ----------------------------------------------------------------------------------------------------------- */
-      {
-         _vg_profiler_enter_block( vg.profiler, "update" );
-         vg.gameloop_stage = k_gameloop_update;
-         callback_fn( (vg_event_info[]){{ .type = k_vg_event_pre_update }} );
+      _vg_profiler_enter_block( vg.profiler, "update" );
+      vg.gameloop_stage = k_gameloop_update;
+      callback_fn( (vg_event_info[]){{ .type = k_vg_event_pre_update }} );
 
-         /* Fixed update loop */
-         vg.gameloop_stage = k_gameloop_update_fixed;
-         vg.fixed_iterations = 0;
-         vg_lines.enabled = vg_lines.render;
-         vg.time_fixed_accumulator += vg.time_delta;
-
-         while( vg.time_fixed_accumulator >= vg.time_fixed_delta )
-         {
-            callback_fn( (vg_event_info[]){{ .type = k_vg_event_fixed_update }} );
-            vg_lines.enabled = 0;
-            vg.time_fixed_accumulator -= vg.time_fixed_delta;
+      /* Fixed update loop */
+      vg.gameloop_stage = k_gameloop_update_fixed;
+      vg.fixed_iterations = 0;
+      vg_lines.enabled = vg_lines.render;
+      vg.time_fixed_accumulator += vg.time_delta;
 
-            vg.fixed_iterations ++;
-            if( vg.fixed_iterations == 8 )
-               break;
-         }
-         vg_lines.enabled = vg_lines.render;
-         vg.time_fixed_extrapolate = vg.time_fixed_accumulator / vg.time_fixed_delta;
+      while( vg.time_fixed_accumulator >= vg.time_fixed_delta )
+      {
+         callback_fn( (vg_event_info[]){{ .type = k_vg_event_fixed_update }} );
+         vg_lines.enabled = 0;
+         vg.time_fixed_accumulator -= vg.time_fixed_delta;
 
-         vg.gameloop_stage = k_gameloop_update;
-         callback_fn( (vg_event_info[]){{ .type = k_vg_event_post_update }} );
-         _vg_profiler_exit_block( vg.profiler );
+         vg.fixed_iterations ++;
+         if( vg.fixed_iterations == 8 )
+            break;
       }
+      vg_lines.enabled = vg_lines.render;
+      vg.time_fixed_extrapolate = vg.time_fixed_accumulator / vg.time_fixed_delta;
+
+      vg.gameloop_stage = k_gameloop_update;
+      callback_fn( (vg_event_info[]){{ .type = k_vg_event_post_update }} );
+      _vg_profiler_exit_block( vg.profiler );
+   }
 
+   if( vg_loader.loading_count == 0 )
+   {
       /* Render loop
        * ------------------------------------------------------------------------------------------------------------ */
+      _vg_profiler_enter_block( vg.profiler, "render" );
+      vg.gameloop_stage = k_gameloop_rendering;
+      callback_fn( (vg_event_info[]){{ .type = k_vg_event_render }} );
+      _vg_profiler_exit_block( vg.profiler );
+
+      /* ui --------------------------------------------------- */
+      vg.gameloop_stage = k_gameloop_ui;
+
+      ui_prerender( &vg_ui.ctx );
+      vg_ui_set_screen( _vg_window.w, _vg_window.h );
+      ui_update_mouse( &vg_ui.ctx, (ui_px[2]){ vg.mouse_pos[0], vg.mouse_pos[1] }, vg.mouse_state );
+
+      if( vg_console.enabled )
+         ui_ignore_input_frames( &vg_ui.ctx, 10 );
+      callback_fn( (vg_event_info[]){{ .type = k_vg_event_gui, .gui = { .ctx = &vg_ui.ctx } }} );
+      if( vg_console.enabled )
       {
-         /* render  -------------------------------------------------- */
-         _vg_profiler_enter_block( vg.profiler, "render" );
-         vg.gameloop_stage = k_gameloop_rendering;
-         callback_fn( (vg_event_info[]){{ .type = k_vg_event_render }} );
-         _vg_profiler_exit_block( vg.profiler );
-
-         /* ui --------------------------------------------------- */
-         vg.gameloop_stage = k_gameloop_ui;
-
-         ui_prerender( &vg_ui.ctx );
-         vg_ui_set_screen( _vg_window.w, _vg_window.h );
-         ui_update_mouse( &vg_ui.ctx, (ui_px[2]){ vg.mouse_pos[0], vg.mouse_pos[1] }, vg.mouse_state );
-
-         if( vg_console.enabled )
-            ui_ignore_input_frames( &vg_ui.ctx, 10 );
-         callback_fn( (vg_event_info[]){{ .type = k_vg_event_gui, .gui = { .ctx = &vg_ui.ctx } }} );
-         if( vg_console.enabled )
-         {
-            ui_ignore_input_frames( &vg_ui.ctx, 0 );
-            ui_capture_mouse( &vg_ui.ctx, 1 );
-            vg_console_draw( &vg_ui.ctx );
-         }
-
-         _vg_settings_gui( &vg_ui.ctx );
-         vg_framebuffer_ui( &vg_ui.ctx );
-         _vg_magi_render( &vg_ui.ctx );
-         ui_postrender( &vg_ui.ctx, vg.time_frame_delta );
-         vg_ui_post_update();
+         ui_ignore_input_frames( &vg_ui.ctx, 0 );
+         ui_capture_mouse( &vg_ui.ctx, 1 );
+         vg_console_draw( &vg_ui.ctx );
       }
+
+      _vg_settings_gui( &vg_ui.ctx );
+      vg_framebuffer_ui( &vg_ui.ctx );
+      _vg_magi_render( &vg_ui.ctx );
+      ui_postrender( &vg_ui.ctx, vg.time_frame_delta );
+      vg_ui_post_update();
    }
    else
-   {
       vg_loader_render();
-   }
 
    if( vg.loader_ring > 0.01f )
    {
index 54a519b03aa90dee5c08bbd6f8b71ce68c175258..d7df2eac84268dbf30d2172097b22495b926d08f 100644 (file)
@@ -76,7 +76,7 @@ VG_API bool _vg_thread_has_flags( u32 flags );
 VG_API void _vg_thread_set_flags( u32 flags );
 VG_API const c8 *_vg_thread_prefix(void);
 
-VG_API void _vg_async_context_push_groups( u16 groups );
+VG_API void _vg_async_context_push_groups( u16 groups, bool exclusive );
 VG_API void _vg_async_context_pop_groups(void);
 VG_API u16 _vg_async_context_get_groups(void);
 
diff --git a/vg_kv.c b/vg_kv.c
index 382a2a66d187a3324a2d0bdc9fbd9fe0fb943379..8142bee16a1c4ec4962a4c64b8d685d4517d0be7 100644 (file)
--- a/vg_kv.c
+++ b/vg_kv.c
@@ -4,10 +4,7 @@ static vg_kv *vg_kvs_newkv( vg_kvs *kvs )
    if( (kvs->kv_page_count == VG_KV_PAGE_COUNT) || (kvs->kv_page_offset == 0) )
    {
       u32 page_size = sizeof(vg_kv)*VG_KV_PAGE_COUNT;
-
-      // FIXME FIXME: 64 is causing issues with metadata enabled buffers!!!!!!!!!!!!!!!!!!!!!!
-      // kv_page = vg_stack_allocate( kvs->stack, page_size, 64, "KV Page" );
-       kv_page = vg_stack_allocate( kvs->stack, page_size, 8, "KV Page" );
+      kv_page = vg_stack_allocate( kvs->stack, page_size, 64, "KV Page" );
       vg_zero_mem( kv_page, page_size );
       kvs->kv_page_offset = vg_stack_offset( kvs->stack, kv_page );
       kvs->kv_page_count = 0;
@@ -79,6 +76,181 @@ u32 vg_kv_append( vg_kvs *kvs, u32 parent_offset, const c8 *key, const c8 *value
    return kv_offset;
 }
 
+/* 
+ * Navigating, and read/writing the KV tree
+ * --------------------------------------------------------------------------------------------------------------------
+ */
+u32 vg_kv_type( vg_kvs *kvs, u32 kv_offset )
+{
+   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+   return (kv->key_info >> 30) & 0x3;
+}
+
+const c8 *vg_kv_key( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
+{
+   if( kv_offset == 0 )
+      return NULL;
+
+   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+   u32 length = (kv->key_info >> 20) & 0x3FF;
+   if( out_length )
+      *out_length = length;
+   return length? vg_stack_pointer( kvs->stack, kv->key_offset ): NULL;
+}
+
+const c8 *vg_kv_value( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
+{
+   if( kv_offset == 0 )
+      return NULL;
+   if( vg_kv_type( kvs, kv_offset ) == k_vg_kv_type_frame )
+      return NULL;
+   else
+   {
+      vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+      if( out_length )
+         *out_length = kv->value.length;
+      return vg_stack_pointer( kvs->stack, kv->key_offset + kv->value.offset_from_key );
+   }
+}
+
+u32 vg_kv_next( vg_kvs *kvs, u32 kv_offset )
+{
+   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+   return kv->brother_offset;
+}
+
+u32 vg_kv_child( vg_kvs *kvs, u32 root_offset, u32 index )
+{
+   if( vg_kv_type( kvs, root_offset ) == k_vg_kv_type_frame )
+   {
+      vg_kv *parent = vg_stack_pointer( kvs->stack, root_offset );
+      u32 offset = parent->first_child_offset;
+
+      for( u32 i=0; (i<index) && offset; i ++ )
+      {
+         vg_kv *kv = vg_stack_pointer( kvs->stack, offset );
+         offset = kv->brother_offset;
+      }
+      return offset;
+   }
+   else return 0;
+}
+
+u32 vg_kv_find( vg_kvs *kvs, u32 root_offset, const c8 *key )
+{
+   if( root_offset == 0 )
+      root_offset = kvs->root_offset;
+
+   u32 hash = vg_strdjb2( key );
+   u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
+   while( child_offset )
+   {
+      vg_kv *kv = vg_stack_pointer( kvs->stack, child_offset );
+      u32 key_length;
+      const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
+      if( ((kv->key_info ^ hash) & 0xFFFFF) == 0 )
+      {
+         u32 key_length;
+         const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
+         if( child_key )
+         {
+            for( u32 i=0; i<key_length; i ++ )
+               if( child_key[i] != key[i] )
+                  goto next;
+
+            return child_offset;
+         }
+      }
+
+ next:child_offset = vg_kv_next( kvs, child_offset );
+   }
+   return 0;
+}
+
+bool vg_kv_read_vu32( vg_kvs *kvs, u32 root_offset, const c8 *key, u32 *default_value, u32 *out_value, u32 len )
+{
+   bool good = 1;
+   vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
+   for( u32 i=0; i<len; i ++ )
+   {
+      u64 value = 0;
+      if( vg_strp_u64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (u32)value;
+      else
+      {
+         good = 0;
+         if( default_value ) out_value[ i ] = default_value[ i ];
+         else                out_value[ i ] = 0;
+      }
+   }
+   return good;
+}
+
+bool vg_kv_read_vf32( vg_kvs *kvs, u32 root_offset, const c8 *key, f32 *default_value, f32 *out_value, u32 len )
+{
+   bool good = 1;
+   vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
+   for( u32 i=0; i<len; i ++ )
+   {
+      f64 value = 0.0;
+      if( vg_strp_f64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (f32)value;
+      else
+      {
+         good = 0;
+         if( default_value ) out_value[ i ] = default_value[ i ];
+         else                out_value[ i ] = 0.0f;
+      }
+   }
+   return good;
+}
+
+const c8 *vg_kv_read_string( vg_kvs *kvs, u32 root_offset, const c8 *key, const c8 *default_value )
+{
+   const c8 *value = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL );
+   return value? value: default_value;
+}
+
+u32 vg_kv_append_vu32( vg_kvs *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len )
+{
+   c8 formatted[ 1024 ];
+   vg_str value_str;
+   vg_strnull( &value_str, formatted, sizeof(formatted) );
+
+   for( u32 i=0; i<len; i++ )
+   {
+      vg_strcatu64( &value_str, values[i], 10 );
+      if( i+1!=len )
+         vg_strcatch( &value_str, ' ' );
+   }
+
+   if( !vg_strgood( &value_str ) )
+      return 0;
+
+   return vg_kv_append( kvs, parent_offset, key, formatted );
+}
+
+u32 vg_kv_append_vf32( vg_kvs *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len )
+{
+   c8 formatted[ 1024 ];
+   vg_str value_str;
+   vg_strnull( &value_str, formatted, sizeof(formatted) );
+
+   for( u32 i=0; i<len; i++ )
+   {
+      vg_strcatf64( &value_str, values[i], 10, 5 );
+      if( i+1!=len )
+         vg_strcatch( &value_str, ' ' );
+   }
+
+   if( !vg_strgood( &value_str ) )
+      return 0;
+
+   return vg_kv_append( kvs, parent_offset, key, formatted );
+}
+
+/* 
+ * Parsing from formatted stream
+ * --------------------------------------------------------------------------------------------------------------------
+ */
 void vg_kv_parser_init( vg_kv_parser *parser, vg_kvs *out_kvs, u32 root_offset )
 {
    VG_ASSERT( out_kvs->stack );
@@ -89,7 +261,7 @@ void vg_kv_parser_init( vg_kv_parser *parser, vg_kvs *out_kvs, u32 root_offset )
    parser->frame_stack[0].frame_offset = root_offset;
 }
 
-void vg_kv_link( vg_kv_parser *parser, u32 offset, u32 depth )
+static void vg_kv_parser_link( vg_kv_parser *parser, u32 offset, u32 depth )
 {
    u32 parent_offset = parser->frame_stack[ depth ].frame_offset;
    vg_kv *parent = vg_stack_pointer( parser->kvs->stack, parent_offset );
@@ -146,7 +318,7 @@ void vg_kv_parse_stream( vg_kv_parser *parser, vg_stream *in_stream )
                kv->value.length = parser->token0_length;
                parser->token1_length = 0;
 
-               vg_kv_link( parser, vg_stack_offset( parser->kvs->stack, kv ), parser->depth );
+               vg_kv_parser_link( parser, vg_stack_offset( parser->kvs->stack, kv ), parser->depth );
             }
             else
             {
@@ -178,7 +350,7 @@ void vg_kv_parse_stream( vg_kv_parser *parser, vg_stream *in_stream )
                parser->depth ++;
                parser->frame_stack[ parser->depth ].latest_child_offset = 0;
                parser->frame_stack[ parser->depth ].frame_offset = id;
-               vg_kv_link( parser, id, depth );
+               vg_kv_parser_link( parser, id, depth );
                parser->token1_length = 0;
             }
             else if( c == '}' )
@@ -225,98 +397,32 @@ void vg_kv_parse_stream( vg_kv_parser *parser, vg_stream *in_stream )
    }
 } 
 
-u32 vg_kv_type( vg_kvs *kvs, u32 kv_offset )
-{
-   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
-   return (kv->key_info >> 30) & 0x3;
-}
-
-const c8 *vg_kv_key( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
-{
-   if( kv_offset == 0 )
-      return NULL;
-
-   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
-   u32 length = (kv->key_info >> 20) & 0x3FF;
-   if( out_length )
-      *out_length = length;
-   return length? vg_stack_pointer( kvs->stack, kv->key_offset ): NULL;
-}
-
-const c8 *vg_kv_value( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
-{
-   if( kv_offset == 0 )
-      return NULL;
-
-   if( vg_kv_type( kvs, kv_offset ) == 0x0 )
-      return NULL;
-   else
-   {
-      vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
-      if( out_length )
-         *out_length = kv->value.length;
-      return vg_stack_pointer( kvs->stack, kv->key_offset + kv->value.offset_from_key );
-   }
-}
-
-u32 vg_kv_next( vg_kvs *kvs, u32 kv_offset )
+void vg_kv_parser_print_info( vg_kv_parser *parser )
 {
-   vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
-   return kv->brother_offset;
+   vg_low( "KV stats\n"
+           "  bytes pages: %u\n"
+           "  bytes strings: %u\n"
+           "  source characters: %u. compression ratio: %.2f%%\n", parser->kvs->stat_memory_pages,
+           parser->stat_memory_strings,
+           parser->stat_source_characters, 
+           (f32)(parser->stat_memory_strings+parser->kvs->stat_memory_pages) /
+                                             (f32)parser->stat_source_characters * 100.0f );
 }
 
-u32 vg_kv_child( vg_kvs *kvs, u32 root_offset, u32 index )
+/* 
+ * Writing KVS to a stream (formatted)
+ * --------------------------------------------------------------------------------------------------------------------
+ */
+void vg_kv_write_init( vg_kv_write *w, vg_stream *stream )
 {
-   if( vg_kv_type( kvs, root_offset ) == 0x0 )
-   {
-      vg_kv *parent = vg_stack_pointer( kvs->stack, root_offset );
-      u32 offset = parent->first_child_offset;
-
-      for( u32 i=0; (i<index) && offset; i ++ )
-      {
-         vg_kv *kv = vg_stack_pointer( kvs->stack, offset );
-         offset = kv->brother_offset;
-      }
-      return offset;
-   }
-   else return 0;
-}
-
-u32 vg_kv_find( vg_kvs *kvs, u32 root_offset, const c8 *key )
-{
-   if( root_offset == 0 )
-      root_offset = kvs->root_offset;
-
-   u32 hash = vg_strdjb2( key );
-   u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
-   while( child_offset )
-   {
-      vg_kv *kv = vg_stack_pointer( kvs->stack, child_offset );
-      u32 key_length;
-      const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
-      if( ((kv->key_info ^ hash) & 0xFFFFF) == 0 )
-      {
-         u32 key_length;
-         const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
-         if( child_key )
-         {
-            for( u32 i=0; i<key_length; i ++ )
-               if( child_key[i] != key[i] )
-                  goto next;
-
-            return child_offset;
-         }
-      }
-
- next:child_offset = vg_kv_next( kvs, child_offset );
-   }
-   return 0;
+   vg_zero_mem( w, sizeof(vg_kv_write) );
+   w->stream = stream;
 }
 
 static void vg_kv_write_indent( vg_kv_write *w )
 {
    for( u32 i=0; i<w->depth; i ++ )
-      fputc( ' ', w->fp );
+      vg_stream_write( w->stream, (c8[]){ ' ' }, 1 );
 }
 
 static void vg_kv_write_string( vg_kv_write *w, const c8 *string, u32 length )
@@ -349,9 +455,9 @@ static void vg_kv_write_string( vg_kv_write *w, const c8 *string, u32 length )
       }
    }
 
-   if( delim ) fputc( delim, w->fp );
-   for( u32 j=0; j<i; j ++ ) fputc( string[j], w->fp );
-   if( delim ) fputc( delim, w->fp );
+   if( delim ) vg_stream_write( w->stream, (c8[]){ delim }, 1 );
+   vg_stream_write( w->stream, string, i );
+   if( delim ) vg_stream_write( w->stream, (c8[]){ delim }, 1 );
 }
 
 void vg_kv_write_block( vg_kv_write *w, const c8 *name, u32 name_length )
@@ -360,12 +466,11 @@ void vg_kv_write_block( vg_kv_write *w, const c8 *name, u32 name_length )
    if( name )
    {
       vg_kv_write_string( w, name, name_length );
-      fputc( '\n', w->fp );
+      vg_stream_write( w->stream, (c8[]){ '\n' }, 1 );
       vg_kv_write_indent( w );
    }
 
-   fputc( '{', w->fp );
-   fputc( '\n', w->fp );
+   vg_stream_write( w->stream, (c8[]){ '{', '\n' }, 2 );
    w->depth ++;
 }
 
@@ -373,37 +478,24 @@ void vg_kv_end_block( vg_kv_write *w )
 {
    w->depth --;
    vg_kv_write_indent( w );
-   fputc( '}', w->fp );
-   fputc( '\n', w->fp );
+   vg_stream_write( w->stream, (c8[]){ '}', '\n' }, 2 );
 }
 
 void vg_kv_write_kv( vg_kv_write *w, const c8 *key, u32 key_len, const c8 *value, u32 value_len )
 {
    vg_kv_write_indent( w );
    vg_kv_write_string( w, key, key_len );
-   fputc( ' ', w->fp );
+   vg_stream_write( w->stream, (c8[]){ ' ' }, 1 );
    vg_kv_write_string( w, value, value_len );
-   fputc( '\n', w->fp );
+   vg_stream_write( w->stream, (c8[]){ '\n' }, 1 );
 }
 
-void vg_kv_parser_print_info( vg_kv_parser *parser )
-{
-   vg_low( "KV stats\n"
-           "  bytes pages: %u\n"
-           "  bytes strings: %u\n"
-           "  source characters: %u. compression ratio: %.2f%%\n", parser->kvs->stat_memory_pages,
-           parser->stat_memory_strings,
-           parser->stat_source_characters, 
-           (f32)(parser->stat_memory_strings+parser->kvs->stat_memory_pages) /
-                                             (f32)parser->stat_source_characters * 100.0f );
-}
-
-void vg_kv_print_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
+void vg_kv_write_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
 {
    if( root_offset == 0 )
       root_offset = kvs->root_offset;
 
-   VG_ASSERT( vg_kv_type( kvs, root_offset ) == 0x0 );
+   VG_ASSERT( vg_kv_type( kvs, root_offset ) == k_vg_kv_type_frame );
 
    u32 root_len;
    const c8 *root_str = vg_kv_key( kvs, root_offset, &root_len );
@@ -412,8 +504,8 @@ void vg_kv_print_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
    u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
    while( child_offset )
    {
-      if( vg_kv_type( kvs, child_offset ) == 0x0 )
-         vg_kv_print_tree( w, kvs, child_offset );
+      if( vg_kv_type( kvs, child_offset ) == k_vg_kv_type_frame )
+         vg_kv_write_tree( w, kvs, child_offset );
       else
       {
          u32 key_len;
@@ -432,76 +524,31 @@ void vg_kv_print_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
    vg_kv_end_block( w );
 }
 
-bool vg_kv_read_vu32( vg_kvs *kvs, u32 root_offset, const c8 *key, u32 *default_value, u32 *out_value, u32 len )
-{
-   bool good = 1;
-   vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
-   for( u32 i=0; i<len; i ++ )
-   {
-      u64 value = 0;
-      if( vg_strp_u64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (u32)value;
-      else
-      {
-         good = 0;
-         if( default_value ) out_value[ i ] = default_value[ i ];
-         else                out_value[ i ] = 0;
-      }
-   }
-   return good;
-}
-
-bool vg_kv_read_vf32( vg_kvs *kvs, u32 root_offset, const c8 *key, f32 *default_value, f32 *out_value, u32 len )
-{
-   bool good = 1;
-   vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
-   for( u32 i=0; i<len; i ++ )
-   {
-      f64 value = 0.0;
-      if( vg_strp_f64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (f32)value;
-      else
-      {
-         good = 0;
-         if( default_value ) out_value[ i ] = default_value[ i ];
-         else                out_value[ i ] = 0.0f;
-      }
-   }
-   return good;
-}
-
-u32 vg_kv_append_vu32( vg_kvs *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len )
+bool vg_kv_read_file( vg_kvs *kvs, const c8 *path, vg_stack_allocator *stack )
 {
-   c8 formatted[ 1024 ];
-   vg_str value_str;
-   vg_strnull( &value_str, formatted, sizeof(formatted) );
-
-   for( u32 i=0; i<len; i++ )
+   vg_stream stream;
+   if( vg_file_stream_open( &stream, path, VG_STREAM_READ ) )
    {
-      vg_strcatu64( &value_str, values[i], 10 );
-      if( i+1!=len )
-         vg_strcatch( &value_str, ' ' );
+      vg_kvs_init( kvs, stack );
+      vg_kv_parser parser;
+      vg_kv_parser_init( &parser, kvs, 0 );
+      vg_kv_parse_stream( &parser, &stream );
+      vg_file_stream_close( &stream );
+      return 1;
    }
-
-   if( !vg_strgood( &value_str ) )
-      return 0;
-
-   return vg_kv_append( kvs, parent_offset, key, formatted );
+   else return 0;
 }
 
-u32 vg_kv_append_vf32( vg_kvs *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len )
+bool vg_kv_write_file( vg_kvs *kvs, const c8 *path )
 {
-   c8 formatted[ 1024 ];
-   vg_str value_str;
-   vg_strnull( &value_str, formatted, sizeof(formatted) );
-
-   for( u32 i=0; i<len; i++ )
+   vg_stream stream;
+   if( vg_file_stream_open( &stream, path, VG_STREAM_WRITE ) )
    {
-      vg_strcatf64( &value_str, values[i], 10, 5 );
-      if( i+1!=len )
-         vg_strcatch( &value_str, ' ' );
+      vg_kv_write writer;
+      vg_kv_write_init( &writer, &stream );
+      vg_kv_write_tree( &writer, kvs, 0 );
+      vg_file_stream_close( &stream );
+      return 1;
    }
-
-   if( !vg_strgood( &value_str ) )
-      return 0;
-
-   return vg_kv_append( kvs, parent_offset, key, formatted );
+   else return 0;
 }
diff --git a/vg_kv.h b/vg_kv.h
index c76b9c03baf79fb45c3a833117b8f464bfe387c1..0d96b829919dd606df7d97cd313983f13fcd67f1 100644 (file)
--- a/vg_kv.h
+++ b/vg_kv.h
@@ -19,12 +19,19 @@ void vg_kvs_init( vg_kvs *kvs, vg_stack_allocator *stack );
  */
 void vg_kv_parser_init( vg_kv_parser *parser, vg_kvs *out_kvs, u32 root_offset );
 void vg_kv_parse_stream( vg_kv_parser *parser, vg_stream *in_stream );
-void vg_kv_link( vg_kv_parser *parser, u32 offset, u32 depth );
+void vg_kv_parser_print_info( vg_kv_parser *parser );
 
 /* returns the type of this KV.
  *  0: frame
  *  1: kv pair
  */
+enum vg_kv_type
+{
+   k_vg_kv_type_frame   = 0,
+   k_vg_kv_type_pair    = 1,
+   k_vg_kv_type_unused2 = 2,
+   k_vg_kv_type_unused3 = 3
+};
 u32 vg_kv_type( vg_kvs *kvs, u32 kv_offset );
 
 /* get key / values associated with KV pair or only key for a frame. */
@@ -38,6 +45,7 @@ u32 vg_kv_find( vg_kvs *kvs, u32 root_offset, const c8 *key );
 
 bool vg_kv_read_vu32( vg_kvs *kvs, u32 root_offset, const c8 *key, u32 *default_value, u32 *out_value, u32 len );
 bool vg_kv_read_vf32( vg_kvs *kvs, u32 root_offset, const c8 *key, f32 *default_value, f32 *out_value, u32 len );
+const c8 *vg_kv_read_string( vg_kvs *kvs, u32 root_offset, const c8 *key, const c8 *default_value );
 
 /* editing kvs
  *  if value is NULL, it appends a named frame
@@ -50,13 +58,16 @@ u32 vg_kv_append_vu32( vg_kvs *kvs, u32 parent_offset, const c8 *key, u32 *value
 u32 vg_kv_append_vf32( vg_kvs *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len );
 
 /* Writing KV files. w should be initialized with depth 0, and fp to a valid C stream pointer */
+void vg_kv_write_init( vg_kv_write *w, vg_stream *stream );
 void vg_kv_write_block( vg_kv_write *w, const c8 *name, u32 name_length );
 void vg_kv_end_block( vg_kv_write *w );
 void vg_kv_write_kv( vg_kv_write *w, const c8 *key, u32 key_len, const c8 *value, u32 value_len );
 
-/* Just for analysis */
-void vg_kv_parser_print_info( vg_kv_parser *parser );
-void vg_kv_print_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset );
+void vg_kv_write_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset );
+
+/* Helpers */
+bool vg_kv_read_file( vg_kvs *kvs, const c8 *path, vg_stack_allocator *stack );
+bool vg_kv_write_file( vg_kvs *kvs, const c8 *path );
 
 struct vg_kv_parser
 {
@@ -106,7 +117,7 @@ struct vg_kv
 
 struct vg_kv_write
 {
-   FILE *fp;
+   vg_stream *stream;
    u32 depth;
 };
 
index ddde5bc486df461bc6759538bc8cf14c9ddbdad2..340975a5c9ad50a926b0bde3a01a6f9cf5c84d9f 100644 (file)
@@ -22,6 +22,17 @@ VG_API void _vg_loader_set_user_information( const c8 *information )
    vg_loader.information_for_user = information;
 }
 
+VG_API void _vg_loader_increment( i32 inc )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_OPENGL ) );
+   vg_loader.loading_count += inc;
+}
+
+VG_API bool _vg_loader_visible(void)
+{
+   return vg_loader.loading_count > 0;
+}
+
 void vg_loader_render_ring( f32 opacity )
 {
    VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_OPENGL ) );
index eb17e1c6869f9e50aefcdbb059ce3483b03e0277..59b7c92340f8d0d84ec0d805deb0e79609a49f87 100644 (file)
@@ -21,7 +21,7 @@ struct vg_loader
    GLuint vao, vbo;
    const char *information_for_user;
 
-   u32 readyness;
+   u32 loading_count;
 }
 extern vg_loader;
 
@@ -31,4 +31,7 @@ VG_API void _vg_loader_set_user_information( const c8 *information );
 void vg_loader_render(void);
 void vg_loader_render_ring( f32 opacity );
 
+VG_API void _vg_loader_increment( i32 inc );
+VG_API bool _vg_loader_visible(void);
+
 #endif
index e8777d25bd9c04d50f5ee31b62129073827b126a..68ba4df6954a76c5a4b408677c7cedbb1e987ca2 100644 (file)
--- a/vg_log.c
+++ b/vg_log.c
@@ -124,7 +124,7 @@ void vg_fatal_error( const char *fmt, ... )
 {
    va_list args;
    va_start( args, fmt );
-   _vg_logx_va( stderr, NULL, "fatal", KRED, fmt, args );
+   _vg_logx_va( stderr, NULL, "sos", KRED, fmt, args );
    va_end( args );
    vg_fatal_exit( "VG Assertion (check STDOUT, or the text logfile if enabled)" );
 }
index 0457bd2c7f5eb12b80cce1187669ac29989a1e48..1a0e1bc539ce684b9e13dbd41bf21d455bd7132c 100644 (file)
--- a/vg_msg.c
+++ b/vg_msg.c
@@ -446,6 +446,7 @@ int vg_msg_getkvvecf( vg_msg *msg, const char *key, u8 type,
 
    return 0;
 }
+#endif
 
 
 /* debug the thing */
@@ -460,12 +461,15 @@ void vg_msg_print( vg_msg *msg, u32 len )
    vg_msg_init( &b, msg->buf, len );
 
    vg_msg_cmd cmd;
-   while( vg_msg_next( &b, &cmd ) ){
-      if( cmd.code == k_vg_msg_frame ){
+   while( vg_msg_next( &b, &cmd ) )
+   {
+      if( cmd.code == k_vg_msg_frame )
+      {
          for( u32 i=0; i<b.cur.depth-1; i++ ) printf( "  " );
          printf( "'%s'{\n", cmd.key );
       }
-      else {
+      else 
+      {
          for( u32 i=0; i<b.cur.depth; i++ ) printf( "  " );
 
          if( cmd.code == k_vg_msg_endframe )
@@ -516,7 +520,6 @@ void vg_msg_print( vg_msg *msg, u32 len )
       }
    }
 }
-#endif
 
 #if defined( VG_MSG_TO_KVS )
 bool vg_kvs_append_from_legacy_msg2( vg_kvs *kvs, u32 root, void *buffer, u32 len )
index 897153e8912fe1da447aa91ca7780818a61d0473..516470d9369231a3ebe5df689e43ba539bfc2eb5 100644 (file)
--- a/vg_msg.h
+++ b/vg_msg.h
@@ -102,7 +102,6 @@ void vg_msg_wkvstr( vg_msg *msg, const char *key, const char *value );
 void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len );
 void vg_msg_wkvnum( vg_msg *msg, const char *key, u8 type, u8 count, void *data );
 
-void vg_msg_init( vg_msg *msg, u8 *buffer, u32 len );
 int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd );
 int vg_msg_skip_frame( vg_msg *msg );
 int vg_msg_seekframe( vg_msg *msg, const char *name );
@@ -118,10 +117,11 @@ int vg_msg_getkvintg( vg_msg *msg, const char *key, u8 type, void *dst, void *de
 /* helper for reading string kvs. returns NULL if not found */
 const char *vg_msg_getkvstr( vg_msg *msg, const char *key );
 int vg_msg_getkvvecf( vg_msg *msg, const char *key, u8 type, void *v, void *default_value );
-void vg_msg_print( vg_msg *msg, u32 len );
 #endif
 
 #if defined( VG_MSG_TO_KVS )
+void vg_msg_init( vg_msg *msg, u8 *buffer, u32 len );
+void vg_msg_print( vg_msg *msg, u32 len );
 bool vg_kvs_append_from_legacy_msg2( vg_kvs *kvs, u32 root, void *buffer, u32 len );
 #endif
 
index 7f3ddb16bac7ce0da7be17bd5dd0eee4694a1c5d..e6dfd2beb5866fe97bddf6b501ff6df9179efeea 100644 (file)
@@ -95,7 +95,7 @@ void vg_fatal_error( const char *fmt, ... );
 
 #define VG_ASSERT( ITEM, ... ) \
  if( !( ITEM ) ) { \
-   vg_fatal_error( "Assertion failed: " VG_LOG_MCSTR(ITEM) "\n" VG_LOG_WHERE );\
+   vg_fatal_error( "Assertion failed: " VG_LOG_MCSTR(ITEM) "\n" VG_LOG_WHERE "\n" );\
  }
 
 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
index 449193e745836a5a05bb0053c7fee2b39d2000d5..2425a7f50e5af99ab18546f10f708e0bf14bc35c 100644 (file)
@@ -138,7 +138,7 @@ bool vg_str_flushfd( vg_str *str, int fd )
 }
 
 /*
- * Returns pointer to last instance of c8acter
+ * Returns pointer to last instance of character
  */
 c8 *vg_strch( vg_str *str, c8 c )
 {
@@ -467,18 +467,18 @@ vg_strp_info vg_strp_f64( vg_strp *p, f64 *value )
    return (got||got_decimal)? info: k_vg_strp_eof;
 }
 
-static u32 vg_strcatu64_internal( c8 reverse_buffer[64], u64 value, u64 base, u32 max_c8acters )
+static u32 vg_strcatu64_internal( c8 reverse_buffer[64], u64 value, u64 base, u32 max_characters )
 {
    VG_ASSERT( base >= 2 );
 
-   if( max_c8acters == 0 )
-      max_c8acters = 64;
+   if( max_characters == 0 )
+      max_characters = 64;
 
    const c8 *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if( value )
    {
       u32 i = 0;
-      while( value && (i<max_c8acters) )
+      while( value && (i<max_characters) )
       {
          reverse_buffer[ i ++ ] = digits[ (u32)(value % base) ];
          value /= base;
@@ -492,7 +492,7 @@ static u32 vg_strcatu64_internal( c8 reverse_buffer[64], u64 value, u64 base, u3
    }
 }
 
-void vg_strcati64r( vg_str *str, i64 value, u64 base, u32 width, c8 blank_c8acter )
+void vg_strcati64r( vg_str *str, i64 value, u64 base, u32 width, c8 blank_character )
 {
    VG_ASSERT( base >= 2 );
 
@@ -508,7 +508,7 @@ void vg_strcati64r( vg_str *str, i64 value, u64 base, u32 width, c8 blank_c8acte
       padding = width - digits;
 
    for( u32 i=0; i<padding; i ++ )
-      vg_strcatch( str, blank_c8acter );
+      vg_strcatch( str, blank_character );
 
    for( u32 i=0; i<digits; i ++ )
       vg_strcatch( str, temp[ digits -1 -i ] );
@@ -551,7 +551,8 @@ void vg_strcatf64( vg_str *str, f64 value, u64 base, u32 decimal_places )
    for( u32 i=0; i<(decimal_places-1); i ++ )
       m *= 10;
 
-   u64 decimal_part = (u64)((f64)m * value + 0.5),
+   // decimal part gets +1.0f because anything less than 1 does not have leading 0s when printing it in the u64 print
+   u64 decimal_part = (u64)((f64)m * (value+1.0f) + 0.5),
        normal_part  = (u64)value;
 
    vg_strcatu64( str, normal_part, base );
index 8d911739e3e8655b28eaf19ec93dba216e52da6e..7acd81cd911efaee0cf10aa5671b3e2a4be39bfe 100644 (file)
--- a/vg_tex.c
+++ b/vg_tex.c
@@ -265,11 +265,6 @@ VG_API_INTERNAL static void _vg_tex_upload( struct tex_upload_task *in_args, vg_
    u32 flags = in_args->flags;
    vg_tex *tex = in_args->tex;
 
-   u32 pixel_format = 0;
-   if( in_args->channels == 3 ) pixel_format = GL_RGB;
-   else if( in_args->channels == 4 ) pixel_format = GL_RGBA;
-   else vg_fatal_error( "Can't upload texture with '%u' channels.\n", in_args->channels );
-
    if( flags & VG_TEX_ERROR )
    {
       tex->name  = (flags & VG_TEX_CUBEMAP)? _vg_tex.errorcube: _vg_tex.error2d;
@@ -277,6 +272,11 @@ VG_API_INTERNAL static void _vg_tex_upload( struct tex_upload_task *in_args, vg_
    }
    else
    {
+      u32 pixel_format = 0;
+      if( in_args->channels == 3 ) pixel_format = GL_RGB;
+      else if( in_args->channels == 4 ) pixel_format = GL_RGBA;
+      else vg_fatal_error( "Can't upload texture with '%u' channels.\n", in_args->channels );
+
       glGenTextures( 1, &tex->name );
 
       u32 filter_min = 0,
@@ -359,7 +359,7 @@ VG_API bool _vg_tex_load_stream( vg_tex *out_tex, vg_stream *in_stream, u32 flag
    u32 size = vg_qoi_stream_init( &qoi, in_stream );
    if( size )
    {
-      _vg_async_context_push_groups( VG_ASYNC_GROUP_OPENGL );
+      _vg_async_context_push_groups( VG_ASYNC_GROUP_OPENGL, 0 );
       struct tex_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof( struct tex_upload_task ) + size );
       vg_qoi_stream_decode( &qoi, in_stream, out_args->image_buffer, flags & VG_TEX_FLIP_V? 1: 0 );
       out_args->tex = out_tex;
@@ -392,7 +392,7 @@ VG_API void _vg_tex_load( vg_tex *out_tex, const c8 *path, u32 flags )
 
    if( error )
    {
-      _vg_async_context_push_groups( VG_ASYNC_GROUP_OPENGL );
+      _vg_async_context_push_groups( VG_ASYNC_GROUP_OPENGL, 0 );
       struct tex_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof( struct tex_upload_task ) );
       out_args->tex = out_tex;
       out_args->width = 0;
@@ -406,7 +406,10 @@ VG_API void _vg_tex_load( vg_tex *out_tex, const c8 *path, u32 flags )
 
 VG_API u32  vg_tex_name( GLuint target, vg_tex *tex )
 {
-   if( !tex ) return (target == GL_TEXTURE_2D)? _vg_tex.error2d: _vg_tex.errorcube;
+   if( !tex ) 
+   {
+      return (target == GL_TEXTURE_2D)? _vg_tex.error2d: _vg_tex.errorcube;
+   }
    if( tex->flags & VG_TEX_COMPLETE ) return tex->name;
    else                               return (target == GL_TEXTURE_2D)? _vg_tex.error2d: _vg_tex.errorcube;
 }