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