init
[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( 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 vpk_free( fs->vpk );
107 fs->vpk = NULL;
108
109 if( fs->current_archive )
110 {
111 fclose( fs->current_archive );
112 fs->current_archive = NULL;
113 }
114 }
115
116 char *valve_fs_get( const char *path )
117 {
118 struct valve_filesystem *fs = &fs_global;
119
120 VPKDirectoryEntry *entry;
121 char pak[ 533 ];
122
123 if( (entry = vpk_find( fs->vpk, path )) )
124 {
125 if( entry->ArchiveIndex != fs->current_idx )
126 {
127 if( fs->current_archive )
128 {
129 fclose( fs->current_archive );
130 fs->current_archive = NULL;
131 }
132
133 fs->current_idx = entry->ArchiveIndex;
134 }
135
136 if( !fs->current_archive )
137 {
138 sprintf( pak, "%scsgo/pak01_%03hu.vpk", fs->exedir, fs->current_idx );
139 fs->current_archive = fopen( pak, "rb" );
140
141 if( !fs->current_archive )
142 {
143 fprintf( stderr, "Could not locate %s\n", pak );
144 return NULL;
145 }
146 }
147
148 char *filebuf = csr_malloc( entry->EntryLength );
149
150 fseek( fs->current_archive, entry->EntryOffset, SEEK_SET );
151 if( fread( filebuf, 1, entry->EntryLength, fs->current_archive ) == entry->EntryLength )
152 {
153 return filebuf;
154 }
155 else
156 {
157 free( filebuf );
158 return NULL;
159 }
160 }
161 else
162 {
163 // Use physical searchpaths
164 char path_buf[ 512 ];
165
166 for( int i = 0; i < csr_sb_count( fs->searchpaths ); i ++ )
167 {
168 strcpy( path_buf, fs->searchpaths[ i ] );
169 strcat( path_buf, path );
170
171 char *filebuf;
172 if( (filebuf = csr_asset_read( path_buf )) )
173 {
174 return filebuf;
175 }
176 }
177
178 return NULL;
179 }
180 }