+}
+
+/*
+ * Async thread which scans local files for boards, as well as scheduling
+ * synchronous calls to the workshop
+ */
+VG_STATIC void workshop_scan_thread( void *_args )
+{
+ vg_linear_clear( vg_mem.scratch );
+
+ for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
+ struct registry_board *reg = &global_skateshop.registry[i];
+ reg->state = k_registry_board_state_indexed_absent;
+ }
+
+ /*
+ * Local disk scan
+ */
+ vg_info( "Scanning models/boards/*.mdl\n" );
+ tinydir_dir dir;
+ tinydir_open( &dir, "models/boards" );
+
+ while( dir.has_next ){
+ tinydir_file file;
+ tinydir_readfile( &dir, &file );
+
+ if( file.is_reg ){
+ u32 hash = vg_strdjb2( file.name );
+
+ for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
+ struct registry_board *reg = &global_skateshop.registry[i];
+
+ if( const_str_eq( hash, file.name, reg->filename ) ){
+ reg->state = k_registry_board_state_indexed;
+ goto next_file;
+ }
+ }
+
+ if( global_skateshop.t1_registry_count == SKATESHOP_REGISTRY_MAX ){
+ vg_error( "You have too many boards installed!\n" );
+ break;
+ }
+
+ vg_info( "new listing!: %s\n", file.name );
+
+ struct registry_board *reg =
+ &global_skateshop.registry[global_skateshop.t1_registry_count ++];
+
+ reg->cache_ptr = NULL;
+ vg_strncpy( file.name, reg->filename, 64, k_strncpy_always_add_null );
+ vg_strncpy( file.name, reg->workshop.title,
+ 64, k_strncpy_always_add_null );
+ reg->filename_hash = hash;
+ reg->workshop_id = 0;
+ reg->state = k_registry_board_state_indexed;
+ reg->workshop.author = 0;
+ strcpy( reg->workshop.author_name, "custom" );
+ }
+
+next_file: tinydir_next( &dir );
+ }
+
+ tinydir_close(&dir);
+
+ if( steam_ready ) workshop_steam_scan();