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