1 /* $Id: cfile.c,v 1.6 2002-08-01 23:28:57 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
30 typedef struct hogfile {
36 #define MAX_HOGFILES 300
38 hogfile HogFiles[MAX_HOGFILES];
39 char Hogfile_initialized = 0;
42 hogfile AltHogFiles[MAX_HOGFILES];
43 char AltHogfile_initialized = 0;
44 int AltNum_hogfiles = 0;
46 char AltHogFilename[64];
49 char AltHogdir_initialized = 0;
51 // routine to take a DOS path and turn it into a macintosh
52 // pathname. This routine is based on the fact that we should
53 // see a \ character in the dos path. The sequence .\ a tthe
54 // beginning of a path is turned into a :
57 void macify_dospath(char *dos_path, char *mac_path)
61 if (!strncmp(dos_path, ".\\", 2)) {
62 strcpy(mac_path, ":");
63 strcat(mac_path, &(dos_path[2]) );
65 strcpy(mac_path, dos_path);
67 while ( (p = strchr(mac_path, '\\')) != NULL)
73 void cfile_use_alternate_hogdir( char * path )
76 strcpy( AltHogDir, path );
77 AltHogdir_initialized = 1;
79 AltHogdir_initialized = 0;
83 //in case no one installs one
84 int default_error_counter=0;
86 //ptr to counter of how many critical errors
87 int *critical_error_counter_ptr=&default_error_counter;
89 //tell cfile about your critical error counter
90 void cfile_set_critical_error_counter_ptr(int *ptr)
92 critical_error_counter_ptr = ptr;
97 FILE * cfile_get_filehandle( char * filename, char * mode )
102 *critical_error_counter_ptr = 0;
103 fp = fopen( filename, mode );
104 if ( fp && *critical_error_counter_ptr ) {
108 if ( (fp==NULL) && (AltHogdir_initialized) ) {
109 strcpy( temp, AltHogDir );
111 strcat( temp, filename );
112 *critical_error_counter_ptr = 0;
113 fp = fopen( temp, mode );
114 if ( fp && *critical_error_counter_ptr ) {
122 //returns 1 if file loaded with no errors
123 int cfile_init_hogfile(char *fname, hogfile * hog_files, int * nfiles )
131 fp = cfile_get_filehandle( fname, "rb" );
132 if ( fp == NULL ) return 0;
134 fread( id, 3, 1, fp );
135 if ( strncmp( id, "DHF", 3 ) ) {
142 if ( *nfiles >= MAX_HOGFILES ) {
144 Error( "HOGFILE is limited to %d files.\n", MAX_HOGFILES );
146 i = fread( hog_files[*nfiles].name, 13, 1, fp );
147 if ( i != 1 ) { //eof here is ok
151 i = fread( &len, 4, 1, fp );
156 hog_files[*nfiles].length = INTEL_INT(len);
157 hog_files[*nfiles].offset = ftell( fp );
158 *nfiles = (*nfiles) + 1;
160 i = fseek( fp, INTEL_INT(len), SEEK_CUR );
164 //Specify the name of the hogfile. Returns 1 if hogfile found & had files
165 int cfile_init(char *hogname)
170 macify_dospath(hogname, mac_path);
173 Assert(Hogfile_initialized == 0);
176 if (cfile_init_hogfile(hogname, HogFiles, &Num_hogfiles )) {
177 strcpy( HogFilename, hogname );
179 if (cfile_init_hogfile(mac_path, HogFiles, &Num_hogfiles )) {
180 strcpy( HogFilename, mac_path );
182 Hogfile_initialized = 1;
186 return 0; //not loaded!
190 FILE * cfile_find_libfile(char * name, int * length)
195 if ( AltHogfile_initialized ) {
196 for (i=0; i<AltNum_hogfiles; i++ ) {
197 if ( !stricmp( AltHogFiles[i].name, name )) {
198 fp = cfile_get_filehandle( AltHogFilename, "rb" );
199 if ( fp == NULL ) return NULL;
200 fseek( fp, AltHogFiles[i].offset, SEEK_SET );
201 *length = AltHogFiles[i].length;
207 if ( !Hogfile_initialized ) {
208 //@@cfile_init_hogfile( "DESCENT2.HOG", HogFiles, &Num_hogfiles );
209 //@@Hogfile_initialized = 1;
211 //Int3(); //hogfile ought to be initialized
214 for (i=0; i<Num_hogfiles; i++ ) {
215 if ( !stricmp( HogFiles[i].name, name )) {
216 fp = cfile_get_filehandle( HogFilename, "rb" );
217 if ( fp == NULL ) return NULL;
218 fseek( fp, HogFiles[i].offset, SEEK_SET );
219 *length = HogFiles[i].length;
226 int cfile_use_alternate_hogfile( char * name )
232 macify_dospath(name, mac_path);
233 strcpy( AltHogFilename, mac_path);
235 strcpy( AltHogFilename, name );
237 cfile_init_hogfile( AltHogFilename, AltHogFiles, &AltNum_hogfiles );
238 AltHogfile_initialized = 1;
239 return (AltNum_hogfiles > 0);
241 AltHogfile_initialized = 0;
246 int cfexist( char * filename )
252 if (filename[0] != '\x01')
253 fp = cfile_get_filehandle( filename, "rb" ); // Check for non-hog file first...
255 fp = NULL; //don't look in dir, only in hogfile
264 fp = cfile_find_libfile(filename, &length );
267 return 2; // file found in hog
270 return 0; // Couldn't find it.
274 CFILE * cfopen(char * filename, char * mode )
280 if (stricmp( mode, "rb")) {
281 Error( "cfiles can only be opened with mode==rb\n" );
284 if (filename[0] != '\x01') {
288 macify_dospath(filename, mac_path);
289 fp = cfile_get_filehandle( mac_path, mode);
291 fp = cfile_get_filehandle( filename, mode ); // Check for non-hog file first...
294 fp = NULL; //don't look in dir, only in hogfile
299 fp = cfile_find_libfile(filename, &length );
301 return NULL; // No file found
302 cfile = d_malloc ( sizeof(CFILE) );
303 if ( cfile == NULL ) {
308 cfile->size = length;
309 cfile->lib_offset = ftell( fp );
310 cfile->raw_position = 0;
313 cfile = d_malloc ( sizeof(CFILE) );
314 if ( cfile == NULL ) {
319 cfile->size = filelength( fileno(fp) );
320 cfile->lib_offset = 0;
321 cfile->raw_position = 0;
326 int cfilelength( CFILE *fp )
331 int cfgetc( CFILE * fp )
335 if (fp->raw_position >= fp->size ) return EOF;
337 c = getc( fp->file );
341 // Assert( fp->raw_position==(ftell(fp->file)-fp->lib_offset) );
347 * read string terminated by zero or a platform's line ending.
348 * Martin: cleaned up line ending mess, and made it read
349 * zero-terminated strings (for descent 1 levels).
350 * assumed that no string has any zero's or other platform's line
352 * platform's line endings reference: UN*X: LF (10), Mac: CR (13),
355 char * cfgets( char * buf, size_t n, CFILE * fp )
361 for (i=0; i<n-1; i++ ) {
362 if (fp->raw_position >= fp->size ) {
366 c = fgetc( fp->file );
368 if (c == 0 || c == 10) // UN*X line ending or zero
370 if (c == 13) { // it could be Mac or DOS line ending
371 c = fgetc( fp->file );
372 if ( c == 10 ) { // DOS line ending
374 } else { // Mac line ending, undo last character read
375 fseek( fp->file, -1, SEEK_CUR);
385 size_t cfread( void * buf, size_t elsize, size_t nelem, CFILE * fp )
387 unsigned int i, size;
389 size = elsize * nelem;
390 if ( size < 1 ) return 0;
392 i = fread ( buf, 1, size, fp->file );
393 fp->raw_position += i;
398 int cftell( CFILE *fp )
400 return fp->raw_position;
403 int cfseek( CFILE *fp, long int offset, int where )
405 int c, goal_position;
409 goal_position = offset;
412 goal_position = fp->raw_position+offset;
415 goal_position = fp->size+offset;
420 c = fseek( fp->file, fp->lib_offset + goal_position, SEEK_SET );
421 fp->raw_position = ftell(fp->file)-fp->lib_offset;
425 void cfclose( CFILE * fp )
432 // routines to read basic data types from CFILE's. Put here to
433 // simplify mac/pc reading from cfiles.
435 int cfile_read_int(CFILE *file)
439 if (cfread( &i, sizeof(i), 1, file) != 1)
440 Error( "Error reading int in cfile_read_int()" );
446 short cfile_read_short(CFILE *file)
450 if (cfread( &s, sizeof(s), 1, file) != 1)
451 Error( "Error reading short in cfile_read_short()" );
457 byte cfile_read_byte(CFILE *file)
461 if (cfread( &b, sizeof(b), 1, file) != 1)
462 Error( "Error reading byte in cfile_read_byte()" );
467 fix cfile_read_fix(CFILE *file)
471 if (cfread( &f, sizeof(f), 1, file) != 1)
472 Error( "Error reading fix in cfile_read_fix()" );
474 f = (fix)INTEL_INT((int)f);
478 fixang cfile_read_fixang(CFILE *file)
482 if (cfread(&f, 2, 1, file) != 1)
483 Error("Error reading fixang in cfile_read_fixang()");
485 f = (fixang) INTEL_SHORT((int) f);
489 void cfile_read_vector(vms_vector *v, CFILE *file)
491 v->x = cfile_read_fix(file);
492 v->y = cfile_read_fix(file);
493 v->z = cfile_read_fix(file);
496 void cfile_read_angvec(vms_angvec *v, CFILE *file)
498 v->p = cfile_read_fixang(file);
499 v->b = cfile_read_fixang(file);
500 v->h = cfile_read_fixang(file);
503 void cfile_read_matrix(vms_matrix *m,CFILE *file)
505 cfile_read_vector(&m->rvec,file);
506 cfile_read_vector(&m->uvec,file);
507 cfile_read_vector(&m->fvec,file);