FS2_Open
Open source remastering of the Freespace 2 engine
cfile.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 #define _CFILE_INTERNAL
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <errno.h>
17 
18 #ifdef _WIN32
19 #include <io.h>
20 #include <direct.h>
21 #include <windows.h>
22 #include <winbase.h> /* needed for memory mapping of file functions */
23 #endif
24 
25 #ifdef SCP_UNIX
26 #include <sys/stat.h>
27 #include <glob.h>
28 #include <sys/mman.h>
29 #endif
30 
31 #include "cfile/cfile.h"
32 #include "cfile/cfilearchive.h"
33 #include "cfile/cfilesystem.h"
34 #include "osapi/osapi.h"
35 #include "parse/encrypt.h"
36 
37 
39 #ifdef SCP_UNIX
40 char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
41 #endif
42 
43 // During cfile_init, verify that Pathtypes[n].index == n for each item
44 // Each path must have a valid parent that can be tracable all the way back to the root
45 // so that we can create directories when we need to.
46 //
47 // Please make sure extensions are all lower-case, or we'll break unix compatibility
48 //
50  // What type this is Path Extensions Parent type
51  { CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
52  // Root must be index 1!!
53  { CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
54  { CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
55  { CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
56  { CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
57  { CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
58  { CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
59  { CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
60  { CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
61  { CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
62  { CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
63  { CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
64  { CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
65  { CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
66  { CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
67  { CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
68  { CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
69  { CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
70  { CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg", CF_TYPE_DATA },
71  { CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
72  { CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
73  { CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
74  { CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
75  { CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
76  { CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
77  { CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
78  { CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
79  { CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
80  { CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
81  { CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
82  { CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
83  { CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg", CF_TYPE_DATA },
84  { CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
85  { CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
86  { CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
87  { CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
88  { CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
89 };
90 
91 
92 #define CFILE_STACK_MAX 8
93 
94 int cfile_inited = 0;
95 static int Cfile_stack_pos = 0;
96 
97 static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
98 
100 static CFILE Cfile_list[MAX_CFILE_BLOCKS];
101 
102 static const char *Cfile_cdrom_dir = NULL;
103 
104 //
105 // Function prototypes for internally-called functions
106 //
107 static int cfget_cfile_block();
108 static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE * fp, int type);
109 static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, int offset, int size);
110 
111 #if defined _WIN32
112 static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type);
113 #elif defined SCP_UNIX
114 static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type);
115 #endif
116 
117 static void cf_chksum_long_init();
118 
119 static void dump_opened_files()
120 {
121  for (int i = 0; i < MAX_CFILE_BLOCKS; i++) {
122  auto cb = &Cfile_block_list[i];
123  if (cb->type != CFILE_BLOCK_UNUSED) {
124  mprintf((" %s:%d\n", cb->source_file, cb->line_num));
125  }
126  }
127 }
128 
129 static void cfile_close()
130 {
131  mprintf(("Still opened files:\n"));
132  dump_opened_files();
133 
135 }
136 
137 #ifdef SCP_UNIX
138  #define MIN_NUM_PATH_COMPONENTS 2 /* Directory + file */
139 #else
140  #define MIN_NUM_PATH_COMPONENTS 3 /* Drive + directory + file */
141 #endif
142 
150 static bool cfile_in_root_dir(const char *exe_path)
151 {
152  int new_token;
153  int token_count = 0;
154  const char *p = exe_path;
155 
156  Assert(exe_path != NULL);
157 
158  do {
159  new_token = 0;
160  while (*p == DIR_SEPARATOR_CHAR) {
161  p++;
162  }
163 
164  while ((*p != '\0') && (*p != DIR_SEPARATOR_CHAR)) {
165  new_token = 1;
166  p++;
167  }
168  token_count += new_token;
169  } while (*p != '\0');
170 
171  return (token_count < MIN_NUM_PATH_COMPONENTS);
172 }
173 
183 int cfile_init(const char *exe_dir, const char *cdrom_dir)
184 {
185  int i;
186 
187  encrypt_init(); /* initialize encryption */
188 
189  if (cfile_inited) {
190  return 0;
191  }
192 
194 
195  strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
196  buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
197  i = strlen(buf);
198 
199  /* Determine if we in a root directory? */
200  if (cfile_in_root_dir(buf)) {
201  MessageBox((HWND)NULL,
202  "FreeSpace2/Fred2 cannot be run from a drive root directory!",
203  "Error", MB_OK);
204  return 1;
205  }
206 
207  // This needs to be set here because cf_build_secondary_filelist assumes it to be true
208  cfile_inited = 1;
209 
210  /*
211  * Determine the executable's directory. Note that DIR_SEPARATOR_CHAR
212  * is guaranteed to be found in the string else cfile_in_root_dir()
213  * would have failed.
214  */
215 
216  char *p;
217 
218  p = strrchr(buf, DIR_SEPARATOR_CHAR);
219  *p = '\0';
220 
221  cfile_chdir(buf);
222 
223  // set root directory
224  strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN - 1);
225 #ifdef SCP_UNIX
226  snprintf(Cfile_user_dir, CFILE_ROOT_DIRECTORY_LEN - 1, "%s/%s/",
228 #endif
229 
230  for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
231  Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
232  }
233 
234  // 32 bit CRC table init
235  cf_chksum_long_init();
236 
237  Cfile_cdrom_dir = cdrom_dir;
238  cf_build_secondary_filelist(Cfile_cdrom_dir);
239 
240  atexit(cfile_close);
241 
242  return 0;
243 }
244 
245 // Call this if pack files got added or removed or the
246 // cdrom changed. This will refresh the list of filenames
247 // stored in packfiles and on the cdrom.
249 {
250  cf_build_secondary_filelist(Cfile_cdrom_dir);
251 }
252 
253 
254 
255 #ifdef _WIN32
256 // Changes to a drive if valid.. 1=A, 2=B, etc
257 // If flag, then changes to it.
258 // Returns 0 if not-valid, 1 if valid.
259 int cfile_chdrive( int DriveNum, int flag )
260 {
261  int Valid = 0;
262  int n, org;
263 
264  org = -1;
265  if (!flag)
266  org = _getdrive();
267 
268  _chdrive( DriveNum );
269  n = _getdrive();
270 
271 
272  if (n == DriveNum )
273  Valid = 1;
274 
275  if ( (!flag) && (n != org) )
276  _chdrive( org );
277 
278  return Valid;
279 
280 }
281 #endif // _WIN32
282 
293 static int _cfile_chdir(const char *new_dir, const char *cur_dir __UNUSED)
294 {
295  int status;
296  const char *path = NULL;
297  const char no_dir[] = "\\.";
298 
299 #ifdef _WIN32
300  const char *colon = strchr(new_dir, ':');
301 
302  if (colon) {
303  if (!cfile_chdrive(tolower(*(colon - 1)) - 'a' + 1, 1))
304  return 1;
305 
306  path = colon + 1;
307  } else
308 #endif /* _WIN32 */
309  {
310  path = new_dir;
311  }
312 
313  if (*path == '\0') {
314  path = no_dir;
315  }
316 
317  /* This chdir might get a critical error! */
318  status = _chdir(path);
319  if (status != 0) {
320 #ifdef _WIN32
321  cfile_chdrive(tolower(cur_dir[0]) - 'a' + 1, 1);
322 #endif /* _WIN32 */
323  return 2;
324  }
325 
326  return 0;
327 }
328 
343 {
344  char dir[CFILE_ROOT_DIRECTORY_LEN];
345  char OriginalDirectory[CFILE_ROOT_DIRECTORY_LEN];
346 
347  _getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
348 
349  Assert(Cfile_stack_pos < CFILE_STACK_MAX);
350 
351  if (Cfile_stack_pos >= CFILE_STACK_MAX) {
352  return -1;
353  }
354 
355  strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory,
357 
358  cf_create_default_path_string(dir, sizeof(dir) - 1, type, NULL);
359 
360  return _cfile_chdir(dir, OriginalDirectory);
361 }
362 
372 int cfile_chdir(const char *dir)
373 {
374  char OriginalDirectory[CFILE_ROOT_DIRECTORY_LEN];
375 
376  _getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
377 
378  return _cfile_chdir(dir, OriginalDirectory);
379 }
380 
382 {
383  Assert(Cfile_stack_pos);
384 
385  if ( !Cfile_stack_pos )
386  return -1;
387 
388  Cfile_stack_pos--;
389  return cfile_chdir(Cfile_stack[Cfile_stack_pos]);
390 }
391 
392 // flush (delete all files in) the passed directory (by type), return the # of files deleted
393 // NOTE : WILL NOT DELETE READ-ONLY FILES
395 {
396  int del_count;
397 
398  Assert( CF_TYPE_SPECIFIED(dir_type) );
399 
400  // attempt to change the directory to the passed type
401  if(cfile_push_chdir(dir_type)){
402  return 0;
403  }
404 
405  // proceed to delete the files
406  del_count = 0;
407 #if defined _WIN32
408  int find_handle;
409  _finddata_t find;
410  find_handle = _findfirst( "*", &find );
411  if (find_handle != -1) {
412  do {
413  if (!(find.attrib & _A_SUBDIR) && !(find.attrib & _A_RDONLY)) {
414  // delete the file
415  cf_delete(find.name,dir_type);
416 
417  // increment the deleted count
418  del_count++;
419  }
420  } while (!_findnext(find_handle, &find));
421  _findclose( find_handle );
422  }
423 #elif defined SCP_UNIX
424  glob_t globinfo;
425  memset(&globinfo, 0, sizeof(globinfo));
426  int status = glob("*", 0, NULL, &globinfo);
427  if (status == 0) {
428  for (unsigned int i = 0; i < globinfo.gl_pathc; i++) {
429  // Determine if this is a regular file
430  struct stat statbuf;
431 
432  stat(globinfo.gl_pathv[i], &statbuf);
433  if (S_ISREG(statbuf.st_mode)) {
434  // delete the file
435  cf_delete(globinfo.gl_pathv[i], dir_type);
436 
437  // increment the deleted count
438  del_count++;
439  }
440  }
441  globfree(&globinfo);
442  }
443 #endif
444 
445  // pop the directory back
446  cfile_pop_dir();
447 
448  // return the # of files deleted
449  return del_count;
450 }
451 
452 
453 // add the given extention to a filename (or filepath) if it doesn't already have this
454 // extension.
455 // filename = name of filename or filepath to process
456 // ext = extension to add. Must start with the period
457 // Returns: new filename or filepath with extension.
458 char *cf_add_ext(const char *filename, const char *ext)
459 {
460  int flen, elen;
461  static char path[MAX_PATH_LEN];
462 
463  flen = strlen(filename);
464  elen = strlen(ext);
465  Assert(flen < MAX_PATH_LEN);
466  strcpy_s(path, filename);
467  if ((flen < 4) || stricmp(path + flen - elen, ext)) {
468  Assert(flen + elen < MAX_PATH_LEN);
469  strcat_s(path, ext);
470  }
471 
472  return path;
473 }
474 
483 int cf_delete(const char *filename, int path_type)
484 {
485  char longname[MAX_PATH_LEN];
486 
487  Assert(CF_TYPE_SPECIFIED(path_type));
488 
489  cf_create_default_path_string(longname, sizeof(longname) - 1,
490  path_type, filename);
491 
492  return (_unlink(longname) != -1);
493 }
494 
495 
496 // Same as _access function to read a file's access bits
497 int cf_access(const char *filename, int dir_type, int mode)
498 {
499  char longname[MAX_PATH_LEN];
500 
501  Assert( CF_TYPE_SPECIFIED(dir_type) );
502 
503  cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, filename );
504 
505  return access(longname,mode);
506 }
507 
508 
509 // Returns 1 if the file exists, 0 if not.
510 // Checks only the file system.
511 // cf_find_file_location checks the filesystem before VPs
512 // If offset is 0, it was found in the filesystem, so offset is boolean false
513 // If offset equates to boolean true, it was found in a VP and the logic will negate the function return
514 int cf_exists(const char *filename, int dir_type)
515 {
516  int offset = 1;
517 
518  if ( (filename == NULL) || !strlen(filename) )
519  return 0;
520 
521  return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
522 }
523 
524 // Goober5000
525 // Returns !0 if the file exists, 0 if not.
526 // Checks both the file system and the VPs.
527 int cf_exists_full(const char *filename, int dir_type)
528 {
529  if ( (filename == NULL) || !strlen(filename) )
530  return 0;
531 
532  return cf_find_file_location(filename, dir_type, 0, NULL, NULL, NULL);
533 }
534 
535 // same as the above, but with extension check
536 int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, const char **ext_list)
537 {
538  if ( (filename == NULL) || !strlen(filename) )
539  return 0;
540 
541  if ( (num_ext <= 0) || (ext_list == NULL) )
542  return 0;
543 
544  return (cf_find_file_location_ext(filename, num_ext, ext_list, dir_type, 0, NULL, NULL, NULL) != -1);
545 }
546 
547 #ifdef _WIN32
548 void cf_attrib(const char *filename, int set, int clear, int dir_type)
549 {
550  char longname[MAX_PATH_LEN];
551 
552  Assert( CF_TYPE_SPECIFIED(dir_type) );
553 
554  cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, filename );
555 
556  FILE *fp = fopen(longname, "rb");
557  if (fp) {
558  fclose(fp);
559 
560  DWORD z = GetFileAttributes(longname);
561  SetFileAttributes(longname, z | set & ~clear);
562  }
563 
564 }
565 #endif
566 
567 int cf_rename(const char *old_name, const char *name, int dir_type)
568 {
569  Assert( CF_TYPE_SPECIFIED(dir_type) );
570 
571  int ret_code;
572  char old_longname[_MAX_PATH];
573  char new_longname[_MAX_PATH];
574 
575  cf_create_default_path_string( old_longname, sizeof(old_longname)-1, dir_type, old_name );
576  cf_create_default_path_string( new_longname, sizeof(old_longname)-1, dir_type, name );
577 
578  ret_code = rename(old_longname, new_longname );
579  if(ret_code != 0){
580  switch(errno){
581  case EACCES :
582  return CF_RENAME_FAIL_ACCESS;
583  case ENOENT :
584  default:
585  return CF_RENAME_FAIL_EXIST;
586  }
587  }
588 
589  return CF_RENAME_SUCCESS;
590 
591 
592 }
593 
594 // Creates the directory path if it doesn't exist. Even creates all its
595 // parent paths.
596 void cf_create_directory( int dir_type )
597 {
598  int num_dirs = 0;
599  int dir_tree[CF_MAX_PATH_TYPES];
600  char longname[MAX_PATH_LEN];
601 
602  Assert( CF_TYPE_SPECIFIED(dir_type) );
603 
604  int current_dir = dir_type;
605 
606  do {
607  Assert( num_dirs < CF_MAX_PATH_TYPES ); // Invalid Pathtypes data?
608 
609  dir_tree[num_dirs++] = current_dir;
610  current_dir = Pathtypes[current_dir].parent_index;
611 
612  } while( current_dir != CF_TYPE_ROOT );
613 
614 
615  int i;
616 
617  for (i=num_dirs-1; i>=0; i-- ) {
618  cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
619 
620  if ( _mkdir(longname)==0 ) {
621  mprintf(( "CFILE: Created new directory '%s'\n", longname ));
622  }
623  }
624 
625 
626 }
627 
628 
629 extern int game_cd_changed();
630 
631 // cfopen()
632 //
633 // parameters: *filepath ==> name of file to open (may be path+name)
634 // *mode ==> specifies how file should be opened (eg "rb" for read binary)
635 // passing NULL to mode deletes the file if it exists and returns NULL
636 // type ==> one of: CFILE_NORMAL
637 // CFILE_MEMORY_MAPPED
638 // dir_type => override extension check, value is one of CF_TYPE* #defines
639 //
640 // NOTE: type parameter is an optional parameter. The default value is CFILE_NORMAL
641 //
642 //
643 // returns: success ==> address of CFILE structure
644 // error ==> NULL
645 //
646 
647 CFILE *_cfopen(const char* source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
648 {
649  /* Bobboau, what is this doing here? 31 is way too short... - Goober5000
650  if( strlen(file_path) > 31 )
651  Error(LOCATION, "file name %s too long, \nmust be less than 31 charicters", file_path);*/
652 
653  char longname[_MAX_PATH];
654 
655  if ( !cfile_inited ) {
656  Int3();
657  return NULL;
658  }
659 
660  //================================================
661  // Check that all the parameters make sense
662  Assert(file_path && strlen(file_path));
663  Assert( mode != NULL );
664 
665  // Can only open read-only binary files in memory mapped mode.
666  if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") ) {
667  Int3();
668  return NULL;
669  }
670 
671  //===========================================================
672  // If in write mode, just try to open the file straight off
673  // the harddisk. No fancy packfile stuff here!
674 
675  if ( strchr(mode,'w') || strchr(mode,'+') || strchr(mode,'a') ) {
676  // For write-only files, require a full path or a path type
677 #ifdef SCP_UNIX
678  if ( strpbrk(file_path, "/") ) {
679 #else
680  if ( strpbrk(file_path,"/\\:") ) {
681 #endif
682  // Full path given?
683  strcpy_s(longname, file_path );
684  } else {
685  // Path type given?
686  Assert( dir_type != CF_TYPE_ANY );
687 
688  // Create the directory if necessary
689  cf_create_directory( dir_type );
690 
691  cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, file_path );
692  }
693  Assert( !(type & CFILE_MEMORY_MAPPED) );
694 
695  // JOHN: TODO, you should create the path if it doesn't exist.
696 
697  //WMC - For some godawful reason, fread does not return the correct number of bytes read
698  //in text mode, which messes up FS2_Open's raw_position indicator in fgets. As a consequence, you
699  //_must_ open files that are gonna be read in binary mode.
700 
701  char happy_mode[8];
702  if(strcspn(mode, "ra+") != strlen(mode) && (strchr(mode, 't') || !strchr(mode, 'b')))
703  {
704  //*****BEGIN PROCESSING OF MODE*****
705  //Copies all 'mode' characters over, except for t, and adds b if needed.
706  unsigned int max = sizeof(happy_mode) - 2; //space for null and 'b'
707  bool need_b = true;
708  unsigned int i;
709  for( i = 0; i < strlen(mode); i++)
710  {
711  if(i > max)
712  break;
713 
714  if(mode[i] != 't')
715  happy_mode[i] = mode[i];
716 
717  if(mode[i] == 'b')
718  need_b = false;
719  }
720  happy_mode[i] = '\0';
721  if(need_b)
722  strcat_s(happy_mode, "b");
723  //*****END PROCESSING OF MODE*****
724  }
725  else
726  {
727  strcpy_s(happy_mode, mode);
728  }
729 
730  FILE *fp = fopen(longname, happy_mode);
731  if (fp) {
732  return cf_open_fill_cfblock(source, line, fp, dir_type);
733  }
734  return NULL;
735  }
736 
737 
738  //================================================
739  // Search for file on disk, on cdrom, or in a packfile
740 
741  int offset, size;
742  char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
743  strcpy_s(copy_file_path, file_path);
744 
745 
746  if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize ) ) {
747 
748  // Fount it, now create a cfile out of it
749  nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
750 
751  if ( type & CFILE_MEMORY_MAPPED ) {
752 
753  // Can't open memory mapped files out of pack files
754  if ( offset == 0 ) {
755 #if defined _WIN32
756  HANDLE hFile;
757 
758  hFile = CreateFile(longname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
759 
760  if (hFile != INVALID_HANDLE_VALUE) {
761  return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
762  }
763 #elif defined SCP_UNIX
764  FILE *fp = fopen( longname, "rb" );
765  if (fp) {
766  return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
767  }
768 #endif
769  }
770 
771  } else {
772 
773  FILE *fp = fopen( longname, "rb" );
774 
775  if ( fp ) {
776  if ( offset ) {
777  // Found it in a pack file
778  return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size );
779  } else {
780  // Found it in a normal file
781  return cf_open_fill_cfblock(source, line, fp, dir_type);
782  }
783  }
784  }
785 
786  }
787 
788  return NULL;
789 }
790 
791 // cfopen_ext()
792 //
793 // parameters: *filepath ==> name of file to open (may be path+name)
794 // *mode ==> specifies how file should be opened (eg "rb" for read binary)
795 // passing NULL to mode deletes the file if it exists and returns NULL
796 
797 // dir_type => override extension check, value is one of CF_TYPE* #defines
798 //
799 // returns: success ==> address of CFILE structure
800 // error ==> NULL
801 //
802 CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const int size, const int offset, int dir_type)
803 {
804  if ( !cfile_inited) {
805  Int3();
806  return NULL;
807  }
808 
809  Assert( file_path && strlen(file_path) );
810  Assert( mode != NULL );
811  Assert( offset >= 0 );
812 
813  // cfopen_special() only supports reading files, not creating them
814  if ( strchr(mode, 'w') ) {
815  Int3();
816  return NULL;
817  }
818 
819  // "file_path" should already be a fully qualified path, so just try to open it
820  FILE *fp = fopen( file_path, "rb" );
821 
822  if ( !fp )
823  return NULL;
824 
825  if ( offset ) {
826  // it's in a pack file
827  return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
828  } else {
829  // it's a normal file
830  return cf_open_fill_cfblock(source, line, fp, dir_type);
831  }
832 }
833 
834 
835 // ------------------------------------------------------------------------
836 // ctmpfile()
837 //
838 // Open up a temporary file. A unique name is automatically generated. The
839 // file will be automatically deleted when file is closed.
840 //
841 // return: NULL => tmp file could not be opened
842 // pointer to CFILE => tmp file successfully opened
843 //
845 {
846  FILE *fp;
847  fp = tmpfile();
848  if ( fp )
849  return cf_open_fill_cfblock(LOCATION, fp, 0);
850  else
851  return NULL;
852 }
853 
854 
855 
856 // cfget_cfile_block() will try to find an empty Cfile_block structure in the
857 // Cfile_block_list[] array and return the index.
858 //
859 // returns: success ==> index in Cfile_block_list[] array
860 // failure ==> -1
861 //
862 static int cfget_cfile_block()
863 {
864  int i;
865  Cfile_block *cb;
866 
867  for ( i = 0; i < MAX_CFILE_BLOCKS; i++ ) {
868  cb = &Cfile_block_list[i];
869  if ( cb->type == CFILE_BLOCK_UNUSED ) {
870  cb->data = NULL;
871  cb->fp = NULL;
872  cb->type = CFILE_BLOCK_USED;
873  return i;
874  }
875  }
876 
877  // If we've reached this point, a free Cfile_block could not be found
878  nprintf(("Warning","A free Cfile_block could not be found.\n"));
879 
880  // Dump a list of all opened files
881  mprintf(("Out of cfile blocks! Currently opened files:\n"));
882  dump_opened_files();
883 
884  Assertion(false, "There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
885  "This is probably caused by a programming or scripting error where a file does not get closed."); // out of free cfile blocks
886  return -1;
887 }
888 
889 
890 // cfclose() closes the file
891 //
892 // returns: success ==> 0
893 // failure ==> EOF
894 //
896 {
897  int result;
898 
899  Assert(cfile != NULL);
900  Cfile_block *cb;
901  Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
902  cb = &Cfile_block_list[cfile->id];
903 
904  result = 0;
905  if ( cb->data ) {
906  // close memory mapped file
907 #if defined _WIN32
908  result = UnmapViewOfFile((void*)cb->data);
909  Assert(result);
910  result = CloseHandle(cb->hInFile);
911  Assert(result); // Ensure file handle is closed properly
912  result = CloseHandle(cb->hMapFile);
913  Assert(result); // Ensure file handle is closed properly
914  result = 0;
915 #elif defined SCP_UNIX
916  // FIXME: result is wrong after munmap() but it is successful
917  //result = munmap(cb->data, cb->data_length);
918  //Assert(result);
919  munmap(cb->data, cb->data_length);
920  if ( cb->fp != NULL)
921  result = fclose(cb->fp);
922 #endif
923 
924  } else if ( cb->fp != NULL ) {
925  Assert(cb->fp != NULL);
926  result = fclose(cb->fp);
927  } else {
928  // VP do nothing
929  }
930 
931  cb->type = CFILE_BLOCK_UNUSED;
932  return result;
933 }
934 
936 {
937  //Was a valid pointer passed?
938  if(cfile == NULL)
939  return 0;
940 
941  //Does it have a valid ID?
942  if(cfile->id < 0 || cfile->id >= MAX_CFILE_BLOCKS)
943  return 0;
944 
945  //Is it used?
946  Cfile_block *cb = &Cfile_block_list[cfile->id];
947  if(cb->type != CFILE_BLOCK_USED && (cb->fp != NULL || cb->data != NULL))
948  return 0;
949 
950  //It's good, as near as we can tell.
951  return 1;
952 }
953 
954 
955 
956 
957 // cf_open_fill_cfblock() will fill up a Cfile_block element in the Cfile_block_list[] array
958 // for the case of a file being opened by cf_open();
959 //
960 // returns: success ==> ptr to CFILE structure.
961 // error ==> NULL
962 //
963 static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int type)
964 {
965  int cfile_block_index;
966 
967  cfile_block_index = cfget_cfile_block();
968  if ( cfile_block_index == -1 ) {
969  fclose(fp);
970  return NULL;
971  } else {
972  CFILE *cfp;
973  Cfile_block *cfbp;
974  cfbp = &Cfile_block_list[cfile_block_index];
975  cfp = &Cfile_list[cfile_block_index];
976  cfp->id = cfile_block_index;
977  cfp->version = 0;
978  cfbp->data = NULL;
979  cfbp->fp = fp;
980  cfbp->dir_type = type;
981  cfbp->max_read_len = 0;
982 
983  cfbp->source_file = source;
984  cfbp->line_num = line;
985 
986  int pos = ftell(fp);
987  if(pos == -1L)
988  pos = 0;
989  cf_init_lowlevel_read_code(cfp,0,filelength(fileno(fp)), 0 );
990 
991  return cfp;
992  }
993 }
994 
995 
996 // cf_open_packed_cfblock() will fill up a Cfile_block element in the Cfile_block_list[] array
997 // for the case of a file being opened by cf_open();
998 //
999 // returns: success ==> ptr to CFILE structure.
1000 // error ==> NULL
1001 //
1002 static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, int offset, int size)
1003 {
1004  // Found it in a pack file
1005  int cfile_block_index;
1006 
1007  cfile_block_index = cfget_cfile_block();
1008  if ( cfile_block_index == -1 ) {
1009  fclose(fp);
1010  return NULL;
1011  } else {
1012  CFILE *cfp;
1013  Cfile_block *cfbp;
1014  cfbp = &Cfile_block_list[cfile_block_index];
1015 
1016  cfp = &Cfile_list[cfile_block_index];
1017  cfp->id = cfile_block_index;
1018  cfp->version = 0;
1019  cfbp->data = NULL;
1020  cfbp->fp = fp;
1021  cfbp->dir_type = type;
1022  cfbp->max_read_len = 0;
1023 
1024  cfbp->source_file = source;
1025  cfbp->line_num = line;
1026 
1027  cf_init_lowlevel_read_code(cfp,offset, size, 0 );
1028 
1029  return cfp;
1030  }
1031 
1032 }
1033 
1034 
1035 
1036 // cf_open_mapped_fill_cfblock() will fill up a Cfile_block element in the Cfile_block_list[] array
1037 // for the case of a file being opened by cf_open_mapped();
1038 //
1039 // returns: ptr CFILE structure.
1040 //
1041 #if defined _WIN32
1042 static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type)
1043 #elif defined SCP_UNIX
1044 static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type)
1045 #endif
1046 {
1047  int cfile_block_index;
1048 
1049  cfile_block_index = cfget_cfile_block();
1050  if ( cfile_block_index == -1 ) {
1051 #ifdef SCP_UNIX
1052  fclose(fp);
1053 #endif
1054  return NULL;
1055  }
1056  else {
1057  CFILE *cfp;
1059  cfbp = &Cfile_block_list[cfile_block_index];
1060 
1061  cfp = &Cfile_list[cfile_block_index];
1063  cfp->version = 0;
1064  cfbp->max_read_len = 0;
1065  cfbp->fp = NULL;
1066 #if defined _WIN32
1067  cfbp->hInFile = hFile;
1068 #endif
1069  cfbp->dir_type = type;
1070 
1072  cfbp->line_num = line;
1073 
1074  cf_init_lowlevel_read_code(cfp, 0, 0, 0 );
1075 #if defined _WIN32
1076  cfbp->hMapFile = CreateFileMapping(cfbp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
1077  if (cfbp->hMapFile == NULL) {
1078  nprintf(("Error", "Could not create file-mapping object.\n"));
1079  return NULL;
1080  }
1081 
1082  cfbp->data = (ubyte*)MapViewOfFile(cfbp->hMapFile, FILE_MAP_READ, 0, 0, 0);
1083  Assert( cfbp->data != NULL );
1084 #elif defined SCP_UNIX
1085  cfbp->fp = fp;
1086  cfbp->data_length = filelength( fileno(fp) );
1087  cfbp->data = mmap(NULL, // start
1088  cfbp->data_length, // length
1089  PROT_READ, // prot
1090  MAP_SHARED, // flags
1091  fileno(fp), // fd
1092  0); // offset
1093  Assert( cfbp->data != NULL );
1094 #endif
1095 
1096  return cfp;
1097  }
1098 }
1099 
1101 {
1102  return Cfile_block_list[cfile->id].dir_type;
1103 }
1104 
1105 // cf_returndata() returns the data pointer for a memory-mapped file that is associated
1106 // with the CFILE structure passed as a parameter
1107 //
1108 //
1109 
1111 {
1112  Assert(cfile != NULL);
1113  Cfile_block *cb;
1114  Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
1115  cb = &Cfile_block_list[cfile->id];
1116  Assert(cb->data != NULL);
1117  return cb->data;
1118 }
1119 
1120 
1121 
1122 // version number of opened file. Will be 0 unless you put something else here after you
1123 // open a file. Once set, you can use minimum version numbers with the read functions.
1125 {
1126  Assert(cfile != NULL);
1127 
1128  cfile->version = version;
1129 }
1130 
1131 // cutoff point where cfread() will throw an error when it hits this limit
1132 // if 'len' is 0 then this check will be disabled
1134 {
1135  Assert( cfile != NULL );
1136  Assert( (cfile->id >= 0) && (cfile->id < MAX_CFILE_BLOCKS) );
1137 
1138  Cfile_block *cb = &Cfile_block_list[cfile->id];
1139 
1140  if (len) {
1141  cb->max_read_len = cb->raw_position + len;
1142  } else {
1143  cb->max_read_len = 0;
1144  }
1145 }
1146 
1147 // routines to read basic data types from CFILE's. Put here to
1148 // simplify mac/pc reading from cfiles.
1149 
1150 float cfread_float(CFILE *file, int ver, float deflt)
1151 {
1152  float f;
1153 
1154  if (file->version < ver)
1155  return deflt;
1156 
1157  if (cfread( &f, sizeof(f), 1, file) != 1)
1158  return deflt;
1159 
1160  f = INTEL_FLOAT(&f);
1161  return f;
1162 }
1163 
1164 int cfread_int(CFILE *file, int ver, int deflt)
1165 {
1166  int i;
1167 
1168  if (file->version < ver)
1169  return deflt;
1170 
1171  if (cfread( &i, sizeof(i), 1, file) != 1)
1172  return deflt;
1173 
1174  i = INTEL_INT(i);
1175  return i;
1176 }
1177 
1178 uint cfread_uint(CFILE *file, int ver, uint deflt)
1179 {
1180  uint i;
1181 
1182  if (file->version < ver)
1183  return deflt;
1184 
1185  if (cfread( &i, sizeof(i), 1, file) != 1)
1186  return deflt;
1187 
1188  i = INTEL_INT(i);
1189  return i;
1190 }
1191 
1192 short cfread_short(CFILE *file, int ver, short deflt)
1193 {
1194  short s;
1195 
1196  if (file->version < ver)
1197  return deflt;
1198 
1199  if (cfread( &s, sizeof(s), 1, file) != 1)
1200  return deflt;
1201 
1202  s = INTEL_SHORT(s);
1203  return s;
1204 }
1205 
1206 ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
1207 {
1208  ushort s;
1209 
1210  if (file->version < ver)
1211  return deflt;
1212 
1213  if (cfread( &s, sizeof(s), 1, file) != 1)
1214  return deflt;
1215 
1216  s = INTEL_SHORT(s);
1217  return s;
1218 }
1219 
1220 ubyte cfread_ubyte(CFILE *file, int ver, ubyte deflt)
1221 {
1222  ubyte b;
1223 
1224  if (file->version < ver)
1225  return deflt;
1226 
1227  if (cfread( &b, sizeof(b), 1, file) != 1)
1228  return deflt;
1229 
1230  return b;
1231 }
1232 
1233 void cfread_vector(vec3d *vec, CFILE *file, int ver, vec3d *deflt)
1234 {
1235  if (file->version < ver) {
1236  if (deflt)
1237  *vec = *deflt;
1238  else
1239  vec->xyz.x = vec->xyz.y = vec->xyz.z = 0.0f;
1240 
1241  return;
1242  }
1243 
1244  vec->xyz.x = cfread_float(file, ver, deflt ? deflt->xyz.x : 0.0f);
1245  vec->xyz.y = cfread_float(file, ver, deflt ? deflt->xyz.y : 0.0f);
1246  vec->xyz.z = cfread_float(file, ver, deflt ? deflt->xyz.z : 0.0f);
1247 }
1248 
1249 void cfread_angles(angles *ang, CFILE *file, int ver, angles *deflt)
1250 {
1251  if (file->version < ver) {
1252  if (deflt)
1253  *ang = *deflt;
1254  else
1255  ang->p = ang->b = ang->h = 0.0f;
1256 
1257  return;
1258  }
1259 
1260  ang->p = cfread_float(file, ver, deflt ? deflt->p : 0.0f);
1261  ang->b = cfread_float(file, ver, deflt ? deflt->b : 0.0f);
1262  ang->h = cfread_float(file, ver, deflt ? deflt->h : 0.0f);
1263 }
1264 
1265 char cfread_char(CFILE *file, int ver, char deflt)
1266 {
1267  char b;
1268 
1269  if (file->version < ver)
1270  return deflt;
1271 
1272  if (cfread( &b, sizeof(b), 1, file) != 1)
1273  return deflt;
1274 
1275  return b;
1276 }
1277 
1278 void cfread_string(char *buf, int n, CFILE *file)
1279 {
1280  char c;
1281 
1282  do {
1283  c = cfread_char(file);
1284  if ( n > 0 ) {
1285  *buf++ = c;
1286  n--;
1287  }
1288  } while (c != 0 );
1289 }
1290 
1291 void cfread_string_len(char *buf,int n, CFILE *file)
1292 {
1293  int len;
1294  len = cfread_int(file);
1295  Assertion( (len < n), "len: %i, n: %i", len, n );
1296  if (len)
1297  cfread(buf, len, 1, file);
1298 
1299  buf[len] = 0;
1300 }
1301 
1302 // equivalent write functions of above read functions follow
1303 
1304 int cfwrite_float(float f, CFILE *file)
1305 {
1306  f = INTEL_FLOAT(&f);
1307  return cfwrite(&f, sizeof(f), 1, file);
1308 }
1309 
1310 int cfwrite_int(int i, CFILE *file)
1311 {
1312  i = INTEL_INT(i);
1313  return cfwrite(&i, sizeof(i), 1, file);
1314 }
1315 
1316 int cfwrite_uint(uint i, CFILE *file)
1317 {
1318  i = INTEL_INT(i);
1319  return cfwrite(&i, sizeof(i), 1, file);
1320 }
1321 
1322 int cfwrite_short(short s, CFILE *file)
1323 {
1324  s = INTEL_SHORT(s);
1325  return cfwrite(&s, sizeof(s), 1, file);
1326 }
1327 
1329 {
1330  s = INTEL_SHORT(s);
1331  return cfwrite(&s, sizeof(s), 1, file);
1332 }
1333 
1335 {
1336  return cfwrite(&b, sizeof(b), 1, file);
1337 }
1338 
1340 {
1341  if(!cfwrite_float(vec->xyz.x, file)){
1342  return 0;
1343  }
1344  if(!cfwrite_float(vec->xyz.y, file)){
1345  return 0;
1346  }
1347  return cfwrite_float(vec->xyz.z, file);
1348 }
1349 
1350 int cfwrite_angles(angles *ang, CFILE *file)
1351 {
1352  if(!cfwrite_float(ang->p, file)){
1353  return 0;
1354  }
1355  if(!cfwrite_float(ang->b, file)){
1356  return 0;
1357  }
1358  return cfwrite_float(ang->h, file);
1359 }
1360 
1361 int cfwrite_char(char b, CFILE *file)
1362 {
1363  return cfwrite( &b, sizeof(b), 1, file);
1364 }
1365 
1366 int cfwrite_string(const char *buf, CFILE *file)
1367 {
1368  if ( (!buf) || (buf && !buf[0]) ) {
1369  return cfwrite_char(0, file);
1370  }
1371  int len = strlen(buf);
1372  if(!cfwrite(buf, len, 1, file)){
1373  return 0;
1374  }
1375  return cfwrite_char(0, file); // write out NULL termination
1376 }
1377 
1378 int cfwrite_string_len(const char *buf, CFILE *file)
1379 {
1380  int len = strlen(buf);
1381 
1382  if(!cfwrite_int(len, file)){
1383  return 0;
1384  }
1385  if (len){
1386  return cfwrite(buf,len,1,file);
1387  }
1388 
1389  return 1;
1390 }
1391 
1392 // Get the filelength
1394 {
1395  Assert(cfile != NULL);
1396  Cfile_block *cb;
1397  Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
1398  cb = &Cfile_block_list[cfile->id];
1399 
1400  // TODO: return length of memory mapped file
1401  Assert( !cb->data );
1402 
1403  Assert(cb->fp != NULL);
1404 
1405  // cb->size gets set at cfopen
1406  return cb->size;
1407 }
1408 
1409 // cfwrite() writes to the file
1410 //
1411 // returns: number of full elements actually written
1412 //
1413 //
1414 int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
1415 {
1416  if(!cf_is_valid(cfile))
1417  return 0;
1418 
1419  if(buf == NULL || elsize == 0 || nelem == 0)
1420  return 0;
1421 
1422  Cfile_block *cb = &Cfile_block_list[cfile->id];
1423 
1424  if(cb->lib_offset != 0)
1425  {
1426  Error(LOCATION, "Attempt to write to a VP file (unsupported)");
1427  return 0;
1428  }
1429 
1430  if(cb->data != NULL)
1431  {
1432  Warning(LOCATION, "Writing is not supported for mem-mapped files");
1433  return EOF;
1434  }
1435 
1436  size_t bytes_written = 0;
1437  size_t size = elsize * nelem;
1438 
1439  bytes_written = fwrite(buf, 1, size, cb->fp);
1440 
1441  //WMC - update filesize and position
1442  if (bytes_written > 0) {
1443  cb->size += bytes_written;
1444  cb->raw_position += bytes_written;
1445  }
1446 
1447 #if defined(CHECK_SIZE) && !defined(NDEBUG)
1448  Assert( cb->size == filelength(fileno(cb->fp)) );
1449 #endif
1450 
1451  return ((int)bytes_written / elsize);
1452 }
1453 
1454 
1455 // cfputc() writes a character to a file
1456 //
1457 // returns: success ==> returns character written
1458 // error ==> EOF
1459 //
1460 int cfputc(int c, CFILE *cfile)
1461 {
1462  if(!cf_is_valid(cfile))
1463  return EOF;
1464 
1465  Cfile_block *cb = &Cfile_block_list[cfile->id];
1466 
1467  if(cb->lib_offset != 0)
1468  {
1469  Error(LOCATION, "Attempt to write character to a VP file (unsupported)");
1470  return EOF;
1471  }
1472 
1473  if(cb->data != NULL)
1474  {
1475  Warning(LOCATION, "Writing is not supported for mem-mapped files");
1476  return EOF;
1477  }
1478 
1479  // writing not supported for memory-mapped files
1480  Assert( !cb->data );
1481 
1482  int result = fputc(c, cb->fp);
1483 
1484  //WMC - update filesize and position
1485  if(result != EOF)
1486  {
1487  cb->size += 1;
1488  cb->raw_position += 1;
1489  }
1490 
1491 #if defined(CHECK_SIZE) && !defined(NDEBUG)
1492  Assert( cb->size == filelength(fileno(cb->fp)) );
1493 #endif
1494 
1495  return result;
1496 }
1497 
1498 
1499 // cfputs() writes a string to a file
1500 //
1501 // returns: success ==> non-negative value
1502 // error ==> EOF
1503 //
1504 int cfputs(const char *str, CFILE *cfile)
1505 {
1506  if(!cf_is_valid(cfile))
1507  return EOF;
1508 
1509  if(str == NULL)
1510  return EOF;
1511 
1512  Cfile_block *cb = &Cfile_block_list[cfile->id];
1513 
1514  if(cb->lib_offset != 0)
1515  {
1516  Error(LOCATION, "Attempt to write character to a VP file (unsupported)");
1517  return EOF;
1518  }
1519 
1520  if(cb->data != NULL)
1521  {
1522  Warning(LOCATION, "Writing is not supported for mem-mapped files");
1523  return EOF;
1524  }
1525 
1526  int result = fputs(str, cb->fp);
1527 
1528  //WMC - update filesize and position
1529  if(result != EOF)
1530  {
1531  cb->size += strlen(str);
1532  cb->raw_position += strlen(str);
1533  }
1534 
1535 #if defined(CHECK_SIZE) && !defined(NDEBUG)
1536  Assert( cb->size == filelength(fileno(cb->fp)) );
1537 #endif
1538 
1539  return result;
1540 }
1541 
1542 
1543 // cfgetc() reads a character from a file
1544 //
1545 // returns: success ==> returns character read
1546 // error ==> EOF
1547 //
1549 {
1550  char tmp;
1551 
1552  int result = cfread(&tmp, 1, 1, cfile );
1553  if ( result == 1 ) {
1554  result = char(tmp);
1555  } else {
1556  result = CF_EOF;
1557  }
1558 
1559  return result;
1560 }
1561 
1562 
1563 
1564 
1565 
1566 // cfgets() reads a string from a file
1567 //
1568 // returns: success ==> returns pointer to string
1569 // error ==> NULL
1570 //
1571 char *cfgets(char *buf, int n, CFILE *cfile)
1572 {
1573  Assert(cfile != NULL);
1574  Assert(buf != NULL);
1575  Assert(n > 0 );
1576 
1577  char * t = buf;
1578  int i, c;
1579 
1580  for (i=0; i<n-1; i++ ) {
1581  do {
1582  char tmp_c;
1583 
1584  int ret = cfread( &tmp_c, 1, 1, cfile );
1585  if ( ret != 1 ) {
1586  *buf = 0;
1587  if ( buf > t ) {
1588  return t;
1589  } else {
1590  return NULL;
1591  }
1592  }
1593  c = int(tmp_c);
1594  } while ( c == 13 );
1595  *buf++ = char(c);
1596  if ( c=='\n' ) break;
1597  }
1598  *buf++ = 0;
1599 
1600  return t;
1601 }
1602 
1603 
1604 // 16 and 32 bit checksum stuff ----------------------------------------------------------
1605 
1606 // CRC code for mission validation. given to us by Kevin Bentley on 7/20/98. Some sort of
1607 // checksumming code that he wrote a while ago.
1608 #define CRC32_POLYNOMIAL 0xEDB88320
1609 static uint CRCTable[256];
1610 
1611 #define CF_CHKSUM_SAMPLE_SIZE 512
1612 
1613 // update cur_chksum with the chksum of the new_data of size new_data_size
1615 {
1616  ubyte *ptr = buffer;
1617  uint sum1, sum2;
1618 
1619  sum1 = sum2 = (int)(seed);
1620 
1621  while(size--) {
1622  sum1 += *ptr++;
1623  if (sum1 >= 255 ) sum1 -= 255;
1624  sum2 += sum1;
1625  }
1626  sum2 %= 255;
1627 
1628  return (ushort)((sum1 << 8) + sum2);
1629 }
1630 
1631 // update cur_chksum with the chksum of the new_data of size new_data_size
1633 {
1634  uint crc;
1635  ubyte *p;
1636 
1637  p = buffer;
1638  crc = seed;
1639 
1640  while (size--)
1641  crc = (crc >> 8) ^ CRCTable[(crc ^ *p++) & 0xff];
1642 
1643  return crc;
1644 }
1645 
1646 static void cf_chksum_long_init()
1647 {
1648  int i, j;
1649  uint crc;
1650 
1651  for (i = 0; i < 256; i++) {
1652  crc = i;
1653 
1654  for (j = 8; j > 0; j--) {
1655  if (crc & 1)
1656  crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
1657  else
1658  crc >>= 1;
1659  }
1660 
1661  CRCTable[i] = crc;
1662  }
1663 }
1664 
1665 // single function convenient to use for both short and long checksums
1666 // NOTE : only one of chk_short or chk_long must be non-NULL (indicating which checksum to perform)
1667 static int cf_chksum_do(CFILE *cfile, ushort *chk_short, uint *chk_long, int max_size)
1668 {
1669  ubyte cf_buffer[CF_CHKSUM_SAMPLE_SIZE];
1670  int is_long;
1671  int cf_len = 0;
1672  int cf_total;
1673  int read_size;
1674 
1675  // determine whether we're doing a short or long checksum
1676  is_long = 0;
1677  if(chk_short){
1678  Assert(!chk_long);
1679  *chk_short = 0;
1680  } else {
1681  Assert(chk_long);
1682  is_long = 1;
1683  *chk_long = 0;
1684  }
1685 
1686  // if max_size is -1, set it to be the size of the file
1687  if(max_size < 0){
1688  cfseek(cfile, 0, SEEK_SET);
1689  max_size = cfilelength(cfile);
1690  }
1691 
1692  cf_total = 0;
1693  do {
1694  // determine how much we want to read
1695  if((max_size - cf_total) >= CF_CHKSUM_SAMPLE_SIZE){
1696  read_size = CF_CHKSUM_SAMPLE_SIZE;
1697  } else {
1698  read_size = max_size - cf_total;
1699  }
1700 
1701  // read in some buffer
1702  cf_len = cfread(cf_buffer, 1, read_size, cfile);
1703 
1704  // total we've read so far
1705  cf_total += cf_len;
1706 
1707  // add the checksum
1708  if(cf_len > 0){
1709  // do the proper short or long checksum
1710  if(is_long){
1711  *chk_long = cf_add_chksum_long(*chk_long, cf_buffer, cf_len);
1712  } else {
1713  *chk_short = cf_add_chksum_short(*chk_short, cf_buffer, cf_len);
1714  }
1715  }
1716  } while((cf_len > 0) && (cf_total < max_size));
1717 
1718  return 1;
1719 }
1720 
1721 // get the chksum of a pack file (VP)
1722 int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
1723 {
1724  const int safe_size = 2097152; // 2 Meg
1725  const int header_offset = 32; // skip 32bytes for header (header is currently smaller than this though)
1726 
1727  ubyte cf_buffer[CF_CHKSUM_SAMPLE_SIZE];
1728  int cf_len = 0;
1729  int cf_total;
1730  int read_size;
1731  int max_size;
1732 
1733  if (chk_long == NULL) {
1734  Int3();
1735  return 0;
1736  }
1737 
1738  FILE *fp = fopen(filename, "rb");
1739 
1740  if (fp == NULL) {
1741  *chk_long = 0;
1742  return 0;
1743  }
1744 
1745  *chk_long = 0;
1746 
1747  // get the max size
1748  fseek(fp, 0, SEEK_END);
1749  max_size = ftell(fp);
1750 
1751  // maybe do a chksum of the entire file
1752  if (full) {
1753  fseek(fp, 0, SEEK_SET);
1754  }
1755  // othewise it's only a partial check
1756  else {
1757  CLAMP(max_size, 0, safe_size);
1758 
1759  Assertion(max_size > header_offset,
1760  "max_size (%d) > header_offset in packfile %s", max_size, filename);
1761  max_size -= header_offset;
1762 
1763  fseek(fp, -(max_size), SEEK_END);
1764  }
1765 
1766  cf_total = 0;
1767 
1768  do {
1769  // determine how much we want to read
1770  if ( (max_size - cf_total) >= CF_CHKSUM_SAMPLE_SIZE )
1771  read_size = CF_CHKSUM_SAMPLE_SIZE;
1772  else
1773  read_size = max_size - cf_total;
1774 
1775  // read in some buffer
1776  cf_len = fread(cf_buffer, 1, read_size, fp);
1777 
1778  // total we've read so far
1779  cf_total += cf_len;
1780 
1781  // add the checksum
1782  if (cf_len > 0)
1783  *chk_long = cf_add_chksum_long((*chk_long), cf_buffer, cf_len);
1784  } while ( (cf_len > 0) && (cf_total < max_size) );
1785 
1786  fclose(fp);
1787 
1788  return 1;
1789 }
1790 // get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
1791 int cf_chksum_short(const char *filename, ushort *chksum, int max_size, int cf_type)
1792 {
1793  int ret_val;
1794  CFILE *cfile = NULL;
1795 
1796  // zero the checksum
1797  *chksum = 0;
1798 
1799  // attempt to open the file
1800  cfile = cfopen(filename,"rt",CFILE_NORMAL,cf_type);
1801  if(cfile == NULL){
1802  return 0;
1803  }
1804 
1805  // call the overloaded cf_chksum function()
1806  ret_val = cf_chksum_do(cfile, chksum, NULL, max_size);
1807 
1808  // close the file down
1809  cfclose(cfile);
1810  cfile = NULL;
1811 
1812  // return the result
1813  return ret_val;
1814 }
1815 
1816 // get the 2 byte checksum of the passed file - return 0 if operation failed, 1 if succeeded
1817 // NOTE : preserves current file position
1818 int cf_chksum_short(CFILE *file, ushort *chksum, int max_size)
1819 {
1820  int ret_code;
1821  int start_pos;
1822 
1823  // Returns current position of file.
1824  start_pos = cftell(file);
1825  if(start_pos == -1){
1826  return 0;
1827  }
1828 
1829  // move to the beginning of the file
1830  if(cfseek(file, 0, CF_SEEK_SET)){
1831  return 0;
1832  }
1833  ret_code = cf_chksum_do(file, chksum, NULL, max_size);
1834  // move back to the start position
1835  cfseek(file, start_pos, CF_SEEK_SET);
1836 
1837  return ret_code;
1838 }
1839 
1840 // get the 32 bit CRC checksum of the passed filename - return 0 if operation failed, 1 if succeeded
1841 int cf_chksum_long(const char *filename, uint *chksum, int max_size, int cf_type)
1842 {
1843  int ret_val;
1844  CFILE *cfile = NULL;
1845 
1846  // zero the checksum
1847  *chksum = 0;
1848 
1849  // attempt to open the file
1850  cfile = cfopen(filename,"rt",CFILE_NORMAL,cf_type);
1851  if(cfile == NULL){
1852  return 0;
1853  }
1854 
1855  // call the overloaded cf_chksum function()
1856  ret_val = cf_chksum_do(cfile, NULL, chksum, max_size);
1857 
1858  // close the file down
1859  cfclose(cfile);
1860  cfile = NULL;
1861 
1862  // return the result
1863  return ret_val;
1864 }
1865 
1866 // get the 32 bit CRC checksum of the passed file - return 0 if operation failed, 1 if succeeded
1867 // NOTE : preserves current file position
1868 int cf_chksum_long(CFILE *file, uint *chksum, int max_size)
1869 {
1870  int ret_code;
1871  int start_pos;
1872 
1873  // Returns current position of file.
1874  start_pos = cftell(file);
1875  if(start_pos == -1){
1876  return 0;
1877  }
1878 
1879  // move to the beginning of the file
1880  if(cfseek(file, 0, CF_SEEK_SET)){
1881  return 0;
1882  }
1883  ret_code = cf_chksum_do(file, NULL, chksum, max_size);
1884  // move back to the start position
1885  cfseek(file, start_pos, CF_SEEK_SET);
1886 
1887  return ret_code;
1888 }
1889 
1890 
1891 // Flush the open file buffer
1892 //
1893 // exit: 0 - success
1894 // 1 - failure
1895 int cflush(CFILE *cfile)
1896 {
1897  Assert(cfile != NULL);
1898  Cfile_block *cb;
1899  Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
1900  cb = &Cfile_block_list[cfile->id];
1901 
1902  // not supported for memory mapped files
1903  Assert( !cb->data );
1904 
1905  Assert(cb->fp != NULL);
1906 
1907  int result = fflush(cb->fp);
1908 
1909  //WMC - update filesize
1910  cb->size = filelength(fileno(cb->fp));
1911 
1912  return result;
1913 }
#define __UNUSED
Definition: clang.h:23
int filelength(int fd)
GLuint64EXT * result
Definition: Glext.h:10775
void cfread_angles(angles *ang, CFILE *file, int ver, angles *deflt)
Definition: cfile.cpp:1249
cfbp dir_type
Definition: cfile.cpp:1069
int cf_is_valid(CFILE *cfile)
Definition: cfile.cpp:935
#define CF_TYPE_FONT
Definition: cfile.h:64
int cfwrite_ushort(ushort s, CFILE *file)
Definition: cfile.cpp:1328
#define CFILE_NORMAL
Definition: cfile.h:89
void * HWND
Definition: config.h:104
int i
Definition: multi_pxo.cpp:466
#define CF_TYPE_SINGLE_PLAYERS
Definition: cfile.h:70
float p
Definition: pstypes.h:111
int cf_get_dir_type(CFILE *cfile)
Definition: cfile.cpp:1100
int cf_delete(const char *filename, int path_type)
Delete the specified file.
Definition: cfile.cpp:483
#define MAX_CFILE_BLOCKS
Definition: cfilearchive.h:47
#define CF_TYPE_VOICE_DEBRIEFINGS
Definition: cfile.h:57
void cf_set_max_read_len(CFILE *cfile, size_t len)
Definition: cfile.cpp:1133
int raw_position
Definition: cfilearchive.h:38
#define CF_TYPE_PLAYERS
Definition: cfile.h:67
#define CF_RENAME_FAIL_ACCESS
Definition: cfile.h:248
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
void cf_attrib(const char *name, int set, int clear, int type)
int cfwrite_ubyte(ubyte b, CFILE *file)
Definition: cfile.cpp:1334
#define CF_TYPE_HUD
Definition: cfile.h:66
CFILE * _cfopen_special(const char *source, int line, const char *file_path, const char *mode, const int size, const int offset, int dir_type)
Definition: cfile.cpp:802
#define CF_EOF
Definition: cfile.h:22
int cfwrite_uint(uint i, CFILE *file)
Definition: cfile.cpp:1316
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
int cflush(CFILE *cfile)
Definition: cfile.cpp:1895
Definition: pstypes.h:88
#define mprintf(args)
Definition: pstypes.h:238
#define DIR_SEPARATOR_CHAR
Definition: pstypes.h:43
#define CF_TYPE_VOICE_SPECIAL
Definition: cfile.h:59
#define _MAX_PATH
Definition: config.h:221
#define CFILE_MEMORY_MAPPED
Definition: cfile.h:90
struct vec3d::@225::@227 xyz
int cfile_pop_dir()
Definition: cfile.cpp:381
GLclampf f
Definition: Glext.h:7097
#define INTEL_SHORT(x)
Definition: pstypes.h:389
const char * Osreg_user_dir
void cf_free_secondary_filelist()
Definition: cfile.h:28
#define Assertion(expr, msg,...)
Definition: clang.h:41
#define CF_SEEK_SET
Definition: cfile.h:24
void cfread_string(char *buf, int n, CFILE *file)
Definition: cfile.cpp:1278
void cfile_refresh()
Definition: cfile.cpp:248
#define CFILE_STACK_MAX
Definition: cfile.cpp:92
int cfwrite_angles(angles *ang, CFILE *file)
Definition: cfile.cpp:1350
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out=0, char *pack_filename=NULL, int *size=NULL, int *offset=NULL, bool localize=false)
GLenum mode
Definition: Glext.h:5794
#define CF_TYPE_PLAYER_IMAGES
Definition: cfile.h:68
#define CF_TYPE_SQUAD_IMAGES
Definition: cfile.h:69
#define CF_TYPE_TEXT
Definition: cfile.h:48
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize)
size_t max_read_len
Definition: cfilearchive.h:41
void encrypt_init()
Definition: encrypt.cpp:453
const char * detect_home(void)
Definition: osapi.cpp:101
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define CF_TYPE_MULTI_CACHE
Definition: cfile.h:73
int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
Definition: cfile.cpp:1722
void * data
Definition: cfilearchive.h:29
GLenum type
Definition: Gl.h:1492
Cfile_block * cfbp
Definition: cfile.cpp:1058
#define CLAMP(x, min, max)
Definition: pstypes.h:488
size_t data_length
Definition: cfilearchive.h:35
int _getcwd(char *buffer, unsigned int len)
#define CF_TYPE_ROOT
Definition: cfile.h:45
int cfwrite_char(char b, CFILE *file)
Definition: cfile.cpp:1361
int cfile_push_chdir(int type)
Push current directory onto a 'stack' and change to a new directory.
Definition: cfile.cpp:342
#define CRC32_POLYNOMIAL
Definition: cfile.cpp:1608
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
GLintptr offset
Definition: Glext.h:5497
cfp version
Definition: cfile.cpp:1063
int cf_find_file_location(const char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize=false)
#define CF_CHKSUM_SAMPLE_SIZE
Definition: cfile.cpp:1611
int cfile_inited
Definition: cfile.cpp:94
unsigned int uint
Definition: pstypes.h:64
#define cfopen(...)
Definition: cfile.h:134
#define nprintf(args)
Definition: pstypes.h:239
int _mkdir(const char *path)
char * cfgets(char *buf, int n, CFILE *cfile)
Definition: cfile.cpp:1571
int cfwrite_float(float f, CFILE *file)
Definition: cfile.cpp:1304
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES]
Definition: cfile.cpp:49
#define CF_TYPE_MULTI_PLAYERS
Definition: cfile.h:71
#define DIR_SEPARATOR_STR
Definition: pstypes.h:44
int cf_exists_full(const char *filename, int dir_type)
Definition: cfile.cpp:527
char * filename
#define CF_TYPE_VOICE_CMD_BRIEF
Definition: cfile.h:56
int _chdir(const char *path)
int cfile_flush_dir(int dir_type)
Definition: cfile.cpp:394
int cfwrite_string(const char *buf, CFILE *file)
Definition: cfile.cpp:1366
#define CF_TYPE_TABLES
Definition: cfile.h:50
#define CF_RENAME_FAIL_EXIST
Definition: cfile.h:249
GLdouble GLdouble z
Definition: Glext.h:5451
Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS]
Definition: cfile.cpp:99
uint cf_add_chksum_long(uint seed, ubyte *buffer, int size)
Definition: cfile.cpp:1632
#define CF_TYPE_VOICE_BRIEFINGS
Definition: cfile.h:55
int cfwrite_string_len(const char *buf, CFILE *file)
Write a fixed length string (not including its null terminator), with the length stored in file...
Definition: cfile.cpp:1378
int parent_index
Definition: cfilesystem.h:26
GLuint buffer
Definition: Glext.h:5492
#define MB_OK
Definition: config.h:179
GLdouble s
Definition: Glext.h:5321
int cfputc(int c, CFILE *cfile)
Definition: cfile.cpp:1460
int cf_rename(const char *old_name, const char *name, int dir_type)
Definition: cfile.cpp:567
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
Definition: cfile.cpp:1414
#define CF_TYPE_INTEL_ANIMS
Definition: cfile.h:78
short cfread_short(CFILE *file, int ver, short deflt)
Definition: cfile.cpp:1192
int id
Definition: cfile.h:29
cfp
Definition: cfile.cpp:1061
#define _unlink(s)
Definition: config.h:225
unsigned long DWORD
Definition: config.h:90
int game_cd_changed()
Definition: fredstubs.cpp:171
#define CF_TYPE_INTERFACE
Definition: cfile.h:63
int cfile_chdir(const char *dir)
Change to the specified directory.
Definition: cfile.cpp:372
Definition: cfile.h:354
cfbp fp
Definition: cfile.cpp:1065
GLdouble GLdouble t
Definition: Glext.h:5329
int cfwrite_int(int i, CFILE *file)
Definition: cfile.cpp:1310
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
void cf_set_version(CFILE *cfile, int version)
Definition: cfile.cpp:1124
int cf_chksum_short(const char *filename, ushort *chksum, int max_size, int cf_type)
Definition: cfile.cpp:1791
vec3d vec
Definition: lua.cpp:2173
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int cf_chksum_long(const char *filename, uint *chksum, int max_size, int cf_type)
Definition: cfile.cpp:1841
#define CF_TYPE_INVALID
Definition: cfile.h:44
#define CF_TYPE_MOVIES
Definition: cfile.h:62
ubyte cfread_ubyte(CFILE *file, int ver, ubyte deflt)
Definition: cfile.cpp:1220
#define CF_TYPE_CACHE
Definition: cfile.h:72
#define INTEL_INT(x)
Definition: pstypes.h:388
GLuint const GLchar * name
Definition: Glext.h:5608
#define INTEL_FLOAT(x)
Definition: pstypes.h:391
void cfread_vector(vec3d *vec, CFILE *file, int ver, vec3d *deflt)
Definition: cfile.cpp:1233
#define MAX_PATH_LEN
Definition: pstypes.h:325
char * cf_add_ext(const char *filename, const char *ext)
Definition: cfile.cpp:458
void cf_build_secondary_filelist(const char *cdrom_dir)
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
#define CF_TYPE_DATA
Definition: cfile.h:46
int cftell(CFILE *fp)
#define CF_TYPE_VOICE
Definition: cfile.h:54
cfile_block_index
Definition: cfile.cpp:1049
int cfputs(const char *str, CFILE *cfile)
Definition: cfile.cpp:1504
#define strcat_s(...)
Definition: safe_strings.h:68
char cfread_char(CFILE *file, int ver, char deflt)
Definition: cfile.cpp:1265
#define CF_TYPE_CBANIMS
Definition: cfile.h:77
#define CF_TYPE_MUSIC
Definition: cfile.h:61
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN]
Definition: cfile.cpp:38
cf_init_lowlevel_read_code(cfp, 0, 0, 0)
int cfwrite_short(short s, CFILE *file)
Definition: cfile.cpp:1322
#define MIN_NUM_PATH_COMPONENTS
Definition: cfile.cpp:140
#define CF_TYPE_SPECIFIED(path_type)
Definition: cfile.h:86
unsigned short ushort
Definition: pstypes.h:63
CFILE * ctmpfile()
Definition: cfile.cpp:844
#define CFILE_ROOT_DIRECTORY_LEN
Definition: cfile.h:110
GLsizei const GLchar ** path
Definition: Glext.h:6795
#define CF_TYPE_MISSIONS
Definition: cfile.h:74
GLfloat GLfloat p
Definition: Glext.h:8373
int version
Definition: cfile.h:30
#define LOCATION
Definition: pstypes.h:245
int MessageBox(HWND h, const char *s1, const char *s2, int i)
#define CF_TYPE_MAPS
Definition: cfile.h:47
const char * source_file
Definition: cfilearchive.h:43
#define CF_TYPE_CONFIG
Definition: cfile.h:75
#define CF_TYPE_DEMOS
Definition: cfile.h:76
#define CFILE_BLOCK_UNUSED
Definition: cfilearchive.h:22
hull_check pos
Definition: lua.cpp:5050
ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
Definition: cfile.cpp:1206
void cf_create_directory(int dir_type)
Definition: cfile.cpp:596
#define CF_TYPE_EFFECTS
Definition: cfile.h:65
#define CF_TYPE_SOUNDS_8B22K
Definition: cfile.h:52
GLenum access
Definition: Glext.h:10767
#define CF_TYPE_FICTION
Definition: cfile.h:80
int cfread_int(CFILE *file, int ver, int deflt)
Definition: cfile.cpp:1164
#define CF_TYPE_SOUNDS_16B11K
Definition: cfile.h:53
float cfread_float(CFILE *file, int ver, float deflt)
Definition: cfile.cpp:1150
GLsizei GLsizei GLchar * source
Definition: Glext.h:5625
#define CF_MAX_PATH_TYPES
Definition: cfile.h:82
GLenum GLsizei len
Definition: Glext.h:6283
void * cf_returndata(CFILE *cfile)
Definition: cfile.cpp:1110
#define CF_TYPE_SCRIPTS
Definition: cfile.h:79
int cfwrite_vector(vec3d *vec, CFILE *file)
Definition: cfile.cpp:1339
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
void * HANDLE
Definition: config.h:106
#define CF_TYPE_VOICE_PERSONAS
Definition: cfile.h:58
float h
Definition: pstypes.h:111
#define CF_TYPE_VOICE_TRAINING
Definition: cfile.h:60
#define CF_TYPE_ANY
Definition: cfile.h:42
#define CFILE_BLOCK_USED
Definition: cfilearchive.h:23
int cfgetc(CFILE *cfile)
Definition: cfile.cpp:1548
#define stricmp(s1, s2)
Definition: config.h:271
#define CF_TYPE_MODELS
Definition: cfile.h:49
int cfilelength(CFILE *cfile)
Definition: cfile.cpp:1393
#define CF_RENAME_SUCCESS
Definition: cfile.h:247
#define CF_TYPE_SOUNDS
Definition: cfile.h:51
const GLubyte * c
Definition: Glext.h:8376
int cf_exists(const char *filename, int dir_type)
Definition: cfile.cpp:514
int cf_access(const char *filename, int dir_type, int mode)
Definition: cfile.cpp:497
float b
Definition: pstypes.h:111
uint cfread_uint(CFILE *file, int ver, uint deflt)
Definition: cfile.cpp:1178
int cfile_init(const char *exe_dir, const char *cdrom_dir)
Initialize the cfile system. Called once at application start.
Definition: cfile.cpp:183
int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, const char **ext_list)
Definition: cfile.cpp:536
CFILE * _cfopen(const char *source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
Definition: cfile.cpp:647
ushort cf_add_chksum_short(ushort seed, ubyte *buffer, int size)
Definition: cfile.cpp:1614
void cfread_string_len(char *buf, int n, CFILE *file)
Read a fixed length string that is not null-terminated, with the length stored in file...
Definition: cfile.cpp:1291
#define strcpy_s(...)
Definition: safe_strings.h:67
int cfseek(CFILE *fp, int offset, int where)