1 // This software is not affiliated with Valve Corporation
2 // We are not affiliated, associated, authorized, endorsed by, or in any way officially
3 // connected with Valve Corporation, or any of its subsidiaries or its affiliates.
5 // All trademarks are property of their respective owners
7 // Abstract Valve file system
8 //=======================================================================================================================
10 // Initialize game directories / pakfile
11 void fs_set_gameinfo( const char *path
);
14 // Read asset as binary in full. Will search VPK, then searchpaths, or return NULL if not found
15 char *valve_fs_get( const char *path
);
18 //=======================================================================================================================
20 #ifdef VALVE_IMPLEMENTATION
22 struct valve_filesystem
26 char bindir
[ 512 ]; // TODO: This is currently not set?
31 FILE *current_archive
;
36 void fs_set_gameinfo( const char *path
)
38 struct valve_filesystem
*fs
= &fs_global
;
40 vdf_node
*info
= vdf_open_file( path
);
45 strcpy( fs
->gamedir
, path
);
46 csr_downlvl( fs
->gamedir
);
49 strcpy( fs
->exedir
, fs
->gamedir
);
50 csr_downlvl( fs
->exedir
);
52 // Get all search paths from file
53 vdf_node
*search_paths
= vdf_next(vdf_next(vdf_next( info
, "GameInfo", NULL
), "FileSystem", NULL
), "SearchPaths", NULL
);
55 kv_foreach( search_paths
, "Game", kv_game
)
57 if( kv_game
[0] == '|' ) continue; //TODO: deal with engine replacements?? maybe??
60 if( csr_path_is_abs( kv_game
) )
62 buf
= csr_malloc( strlen( kv_game
) + 2 );
63 strcpy( buf
, kv_game
);
68 buf
= csr_malloc( strlen( fs
->exedir
) + strlen( kv_game
) + 2 );
69 strcpy( buf
, fs
->exedir
);
70 strcat( buf
, kv_game
);
74 fs
->searchpaths
= csr_sb_reserve( fs
->searchpaths
, 1, sizeof( char * ) );
75 fs
->searchpaths
[ csr_sb_count( fs
->searchpaths
) ] = buf
;
76 csr_sb_use( fs
->searchpaths
);
83 for( int i
= 0; i
< csr_sb_count( fs
->searchpaths
); i
++ )
85 strcpy( pack_path
, fs
->searchpaths
[i
] );
86 strcat( pack_path
, "pak01_dir.vpk" );
88 if( (fs
->vpk
= (VPKHeader
*)csr_asset_read( pack_path
)) )
96 log_error( "Could not locate pak01_dir.vpk in %i searchpaths. Stock models will not load!\n", csr_sb_count( fs
->searchpaths
) );
99 log_info( "fs_info:\n" );
100 log_info( " gamedir: %s\n", fs
->gamedir
);
101 log_info( " exedir: %s\n", fs
->exedir
);
102 log_info( " bin: %s\n", fs
->bindir
);
103 log_info( " pack: %s\n", pack_path
);
104 log_info( " searchpaths:\n" );
106 for( int i
= 0; i
< csr_sb_count( fs
->searchpaths
); i
++ )
108 log_info( " '%s'\n", fs
->searchpaths
[i
] );
114 struct valve_filesystem
*fs
= &fs_global
;
116 for( int i
= 0; i
< csr_sb_count( fs
->searchpaths
); i
++ )
118 free( fs
->searchpaths
[ i
] );
120 csr_sb_free( fs
->searchpaths
);
121 fs
->searchpaths
= NULL
;
129 if( fs
->current_archive
)
131 fclose( fs
->current_archive
);
132 fs
->current_archive
= NULL
;
136 char *valve_fs_get( const char *path
)
138 struct valve_filesystem
*fs
= &fs_global
;
140 VPKDirectoryEntry
*entry
;
145 if( (entry
= vpk_find( fs
->vpk
, path
)) )
147 if( entry
->ArchiveIndex
!= fs
->current_idx
)
149 if( fs
->current_archive
)
151 fclose( fs
->current_archive
);
152 fs
->current_archive
= NULL
;
155 fs
->current_idx
= entry
->ArchiveIndex
;
158 if( !fs
->current_archive
)
160 sprintf( pak
, "%scsgo/pak01_%03hu.vpk", fs
->exedir
, fs
->current_idx
);
161 fs
->current_archive
= fopen( pak
, "rb" );
163 if( !fs
->current_archive
)
165 log_error( "Could not locate %s\n", pak
);
170 char *filebuf
= csr_malloc( entry
->EntryLength
);
172 fseek( fs
->current_archive
, entry
->EntryOffset
, SEEK_SET
);
173 if( fread( filebuf
, 1, entry
->EntryLength
, fs
->current_archive
) == entry
->EntryLength
)
185 // Use physical searchpaths
186 char path_buf
[ 512 ];
188 for( int i
= 0; i
< csr_sb_count( fs
->searchpaths
); i
++ )
190 strcpy( path_buf
, fs
->searchpaths
[ i
] );
191 strcat( path_buf
, path
);
194 if( (filebuf
= csr_asset_read( path_buf
)) )