]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfile/cfilearchive.cpp
added copyright header
[taylor/freespace2.git] / src / cfile / cfilearchive.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/CFile/CfileArchive.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Low-level code for reading data out of large archive files or normal files.  All
16  * reads/seeks come through here.
17  *
18  * $Log$
19  * Revision 1.2  2002/06/09 04:41:15  relnev
20  * added copyright header
21  *
22  * Revision 1.1.1.1  2002/05/03 03:28:08  root
23  * Initial import.
24  *
25  * 
26  * 4     2/22/99 10:31p Andsager
27  * Get rid of unneeded includes.
28  * 
29  * 3     1/06/99 2:24p Dave
30  * Stubs and release build fixes.
31  * 
32  * 2     10/07/98 10:52a Dave
33  * Initial checkin.
34  * 
35  * 1     10/07/98 10:48a Dave
36  * 
37  * 12    5/14/98 8:10p Lawrance
38  * Fix bug with trying to read past the end of a file (when from a
39  * packfile).
40  * 
41  * 11    5/11/98 11:48a John
42  * fixed bug with memory mapped files
43  * 
44  * 10    5/11/98 10:59a John
45  * added in debug code
46  * 
47  * 9     5/11/98 10:59a John
48  * Moved the low-level file reading code into cfilearchive.cpp.
49  * 
50  * 8     4/30/98 4:53p John
51  * Restructured and cleaned up cfile code.  Added capability to read off
52  * of CD-ROM drive and out of multiple pack files.
53  * 
54  * 7     4/20/98 11:49a Hoffoss
55  * Fixed bug with directory name getting.
56  * 
57  * 6     4/10/98 12:18a Hoffoss
58  * Make pilot image search in pack file possible.
59  * 
60  * 5     1/19/98 9:37p Allender
61  * Great Compiler Warning Purge of Jan, 1998.  Used pragma's in a couple
62  * of places since I was unsure of what to do with code.
63  * 
64  * 4     12/30/97 5:31p Lawrance
65  * fixed problem for people that didn't have a VP file
66  * 
67  * 3     12/30/97 4:31p Sandeep
68  * Changed pakfile format
69  * 
70  * 2     12/28/97 12:42p John
71  * Put in support for reading archive files; Made missionload use the
72  * cf_get_file_list function.   Moved demos directory out of data tree.
73  * 
74  * 1     12/28/97 11:48a John
75  *
76  * $NoKeywords: $
77  */
78
79 #define _CFILE_INTERNAL 
80
81 #include <stdlib.h>
82 #include <string.h>
83 #include <stdio.h>
84 #ifndef PLAT_UNIX
85 #include <io.h>
86 #include <direct.h>
87 #include <windows.h>
88 #include <winbase.h>            /* needed for memory mapping of file functions */
89 #endif
90
91 #include "pstypes.h"
92 #include "cfile.h"
93 //#include "outwnd.h"
94 //#include "vecmat.h"
95 //#include "timer.h"
96 #include "cfilearchive.h"
97
98 #define CHECK_POSITION
99
100 // Called once to setup the low-level reading code.
101
102 void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size )
103 {
104         Assert(cfile != NULL);
105
106         Cfile_block *cb;
107         Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
108         cb = &Cfile_block_list[cfile->id];      
109
110         cb->lib_offset = offset;
111         cb->raw_position = 0;
112         cb->size = size;
113
114         if ( cb->fp )   {
115                 if ( cb->lib_offset )   {
116                         fseek( cb->fp, cb->lib_offset, SEEK_SET );
117                 }
118
119                 #if defined(CHECK_POSITION) && !defined(NDEBUG)
120                         int raw_position = ftell(cb->fp) - cb->lib_offset;
121                         Assert(raw_position == cb->raw_position);
122                 #endif
123         }
124 }
125
126
127
128 // cfeof() Tests for end-of-file on a stream
129 //
130 // returns a nonzero value after the first read operation that attempts to read
131 // past the end of the file. It returns 0 if the current position is not end of file.
132 // There is no error return.
133
134 int cfeof(CFILE *cfile)
135 {
136         Assert(cfile != NULL);
137
138         Cfile_block *cb;
139         Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
140         cb = &Cfile_block_list[cfile->id];      
141
142         int result;
143
144         result = 0;
145
146         // cfeof() not supported for memory-mapped files
147         Assert( !cb->data );
148
149         Assert(cb->fp != NULL);
150
151         #if defined(CHECK_POSITION) && !defined(NDEBUG)
152         int raw_position = ftell(cb->fp) - cb->lib_offset;
153         Assert(raw_position == cb->raw_position);
154         #endif
155                 
156         if (cb->raw_position >= cb->size ) {
157                 result = 1;
158         } else {
159                 result = 0;
160         }
161
162         return result;  
163 }
164
165 // cftell() returns offset into file
166 //
167 // returns:  success ==> offset into the file
168 //           error   ==> -1
169 //
170 int cftell( CFILE * cfile )
171 {
172         Assert(cfile != NULL);
173         Cfile_block *cb;
174         Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
175         cb = &Cfile_block_list[cfile->id];      
176
177         // Doesn't work for memory mapped files
178         Assert( !cb->data );
179
180         Assert(cb->fp != NULL);
181
182         #if defined(CHECK_POSITION) && !defined(NDEBUG)
183         int raw_position = ftell(cb->fp) - cb->lib_offset;
184         Assert(raw_position == cb->raw_position);
185         #endif
186
187         return cb->raw_position;
188 }
189
190
191 // cfseek() moves the file pointer
192 //
193 // returns:   success ==> 0
194 //            error   ==> non-zero
195 //
196 int cfseek( CFILE *cfile, int offset, int where )
197 {
198
199         Assert(cfile != NULL);
200         Cfile_block *cb;
201         Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
202         cb = &Cfile_block_list[cfile->id];      
203
204
205         // TODO: seek to offset in memory mapped file
206         Assert( !cb->data );
207         Assert( cb->fp != NULL );
208         
209         int goal_position;
210
211         switch( where ) {
212         case CF_SEEK_SET:
213                 goal_position = offset+cb->lib_offset;
214                 break;
215         case CF_SEEK_CUR:       
216                 {
217                         goal_position = cb->raw_position+offset+cb->lib_offset;
218                 }
219                 break;
220         case CF_SEEK_END:
221                 goal_position = cb->size+offset+cb->lib_offset;
222                 break;
223         default:
224                 Int3();
225                 return 1;
226         }       
227
228         int result = fseek(cb->fp, goal_position, SEEK_SET );
229         cb->raw_position = goal_position - cb->lib_offset;
230
231         #if defined(CHECK_POSITION) && !defined(NDEBUG)
232                 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
233                 Assert(tmp_offset==cb->raw_position);
234         #endif
235
236         return result;  
237 }
238
239
240 // cfread() reads from a file
241 //
242 // returns:   returns the number of full elements read
243 //            
244 //
245 int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
246 {
247         Assert(cfile != NULL);
248         Assert(buf != NULL);
249         Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
250
251         Cfile_block *cb;
252         cb = &Cfile_block_list[cfile->id];      
253
254         // cfread() not supported for memory-mapped files
255         Assert( !cb->data );
256         Assert(cb->fp != NULL);
257
258         int size = elsize*nelem;
259
260         Assert(nelem > 0);
261         Assert(elsize > 0);
262         Assert(size > 0);
263
264         if ( (cb->raw_position+size) > cb->size ) {
265                 size = cb->size - cb->raw_position;
266                 if ( size < 1 ) {
267                         return 0;
268                 }
269                 //mprintf(( "CFILE: EOF encountered in file\n" ));
270         }
271
272         int bytes_read = fread( buf, 1, size, cb->fp );
273         if ( bytes_read > 0 )   {
274                 cb->raw_position += bytes_read;
275         }               
276
277         #if defined(CHECK_POSITION) && !defined(NDEBUG)
278                 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
279                 Assert(tmp_offset==cb->raw_position);
280         #endif
281
282         return bytes_read / elsize;
283
284 }
285