be7e319ed39e9b3904caa3dd3d72946c2db1ffb3
[csRadar.git] / vfilesys.h
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.
4 //
5 // All trademarks are property of their respective owners
6
7 // Abstract Valve file system
8 //=======================================================================================================================
9
10 // Initialize game directories / pakfile
11 void fs_set_gameinfo( const char *path );
12 void fs_exit(void);
13
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 );
16
17 // Implementation
18 //=======================================================================================================================
19
20 #ifdef VALVE_IMPLEMENTATION
21
22 struct valve_filesystem
23 {
24 char gamedir[ 512 ];
25 char exedir[ 512 ];
26 char bindir[ 512 ]; // TODO: This is currently not set?
27
28 VPKHeader *vpk;
29 char **searchpaths;
30
31 FILE *current_archive;
32 u16 current_idx;
33 }
34 fs_global;
35
36 void fs_set_gameinfo( const char *path )
37 {
38 struct valve_filesystem *fs = &fs_global;
39
40 vdf_node *info = vdf_open_file( path );
41 if( !info )
42 return;
43
44 // Set gamedir
45 strcpy( fs->gamedir, path );
46 csr_path_winunix( fs->gamedir );
47 *csr_findext( fs->gamedir, '/' ) = 0x00;
48
49 // Set exe dir
50 strcpy( fs->exedir, fs->gamedir );
51 strcat( fs->exedir, "../" );
52
53 // Get all search paths from file
54 vdf_node *search_paths = vdf_next(vdf_next(vdf_next( info, "GameInfo", NULL ), "FileSystem", NULL ), "SearchPaths", NULL );
55
56 kv_foreach( search_paths, "Game", kv_game )
57 {
58 if( kv_game[0] == '|' ) continue; //TODO: deal with engine replacements?? maybe??
59
60 char *buf;
61 if( csr_path_is_abs( kv_game ) )
62 {
63 buf = csr_malloc( strlen( kv_game ) + 2 );
64 strcpy( buf, kv_game );
65 strcat( buf, "/" );
66 }
67 else
68 {
69 buf = csr_malloc( strlen( fs->exedir ) + strlen( kv_game ) + 2 );
70 strcpy( buf, fs->exedir );
71 strcat( buf, kv_game );
72 strcat( buf, "/" );
73 }
74
75 fs->searchpaths = csr_sb_reserve( fs->searchpaths, 1, sizeof( char * ) );
76 fs->searchpaths[ csr_sb_count( fs->searchpaths ) ] = buf;
77 csr_sb_use( fs->searchpaths );
78 }
79
80 vdf_free_r( info );
81
82 // Look for pak01_dir
83 char pack_path[512];
84 for( int i = 0; i < csr_sb_count( fs->searchpaths ); i ++ )
85 {
86 strcpy( pack_path, fs->searchpaths[i] );
87 strcat( pack_path, "pak01_dir.vpk" );
88
89 if( (fs->vpk = (VPKHeader *)csr_asset_read( pack_path )) )
90 {
91 break;
92 }
93 }
94
95 if( !fs->vpk )
96 {
97 log_error( "Could not locate pak01_dir.vpk in %i searchpaths. Stock models will not load!", csr_sb_count( fs->searchpaths ) );
98 }
99
100 log_info( "fs_info:\n" );
101 log_info( " gamedir: %s\n", fs->gamedir );
102 log_info( " exedir: %s\n", fs->exedir );
103 log_info( " bin: %s\n", fs->bindir );
104 log_info( " pack: %s\n", pack_path );
105 log_info( " searchpaths:\n" );
106
107 for( int i = 0; i < csr_sb_count( fs->searchpaths ); i ++ )
108 {
109 log_info( " '%s'\n", fs->searchpaths[i] );
110 }
111 }
112
113 void fs_exit(void)
114 {
115 struct valve_filesystem *fs = &fs_global;
116
117 for( int i = 0; i < csr_sb_count( fs->searchpaths ); i ++ )
118 {
119 free( fs->searchpaths[ i ] );
120 }
121 csr_sb_free( fs->searchpaths );
122 fs->searchpaths = NULL;
123
124 if( fs->vpk )
125 {
126 vpk_free( fs->vpk );
127 fs->vpk = NULL;
128 }
129
130 if( fs->current_archive )
131 {
132 fclose( fs->current_archive );
133 fs->current_archive = NULL;
134 }
135 }
136
137 char *valve_fs_get( const char *path )
138 {
139 struct valve_filesystem *fs = &fs_global;
140
141 VPKDirectoryEntry *entry;
142 char pak[ 533 ];
143
144 if( fs->vpk )
145 {
146 if( (entry = vpk_find( fs->vpk, path )) )
147 {
148 if( entry->ArchiveIndex != fs->current_idx )
149 {
150 if( fs->current_archive )
151 {
152 fclose( fs->current_archive );
153 fs->current_archive = NULL;
154 }
155
156 fs->current_idx = entry->ArchiveIndex;
157 }
158
159 if( !fs->current_archive )
160 {
161 sprintf( pak, "%scsgo/pak01_%03hu.vpk", fs->exedir, fs->current_idx );
162 fs->current_archive = fopen( pak, "rb" );
163
164 if( !fs->current_archive )
165 {
166 log_error( "Could not locate %s\n", pak );
167 return NULL;
168 }
169 }
170
171 char *filebuf = csr_malloc( entry->EntryLength );
172
173 fseek( fs->current_archive, entry->EntryOffset, SEEK_SET );
174 if( fread( filebuf, 1, entry->EntryLength, fs->current_archive ) == entry->EntryLength )
175 {
176 return filebuf;
177 }
178 else
179 {
180 free( filebuf );
181 return NULL;
182 }
183 }
184 }
185
186 // Use physical searchpaths
187 char path_buf[ 512 ];
188
189 for( int i = 0; i < csr_sb_count( fs->searchpaths ); i ++ )
190 {
191 strcpy( path_buf, fs->searchpaths[ i ] );
192 strcat( path_buf, path );
193
194 char *filebuf;
195 if( (filebuf = csr_asset_read( path_buf )) )
196 {
197 return filebuf;
198 }
199 }
200
201 return NULL;
202 }
203
204 #endif