2 * $Logfile: /Freespace2/code/CFile/CfileArchive.cpp $
7 * Low-level code for reading data out of large archive files or normal files. All
8 * reads/seeks come through here.
11 * Revision 1.1 2002/05/03 03:28:08 root
15 * 4 2/22/99 10:31p Andsager
16 * Get rid of unneeded includes.
18 * 3 1/06/99 2:24p Dave
19 * Stubs and release build fixes.
21 * 2 10/07/98 10:52a Dave
24 * 1 10/07/98 10:48a Dave
26 * 12 5/14/98 8:10p Lawrance
27 * Fix bug with trying to read past the end of a file (when from a
30 * 11 5/11/98 11:48a John
31 * fixed bug with memory mapped files
33 * 10 5/11/98 10:59a John
36 * 9 5/11/98 10:59a John
37 * Moved the low-level file reading code into cfilearchive.cpp.
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.
43 * 7 4/20/98 11:49a Hoffoss
44 * Fixed bug with directory name getting.
46 * 6 4/10/98 12:18a Hoffoss
47 * Make pilot image search in pack file possible.
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.
53 * 4 12/30/97 5:31p Lawrance
54 * fixed problem for people that didn't have a VP file
56 * 3 12/30/97 4:31p Sandeep
57 * Changed pakfile format
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.
63 * 1 12/28/97 11:48a John
68 #define _CFILE_INTERNAL
77 #include <winbase.h> /* needed for memory mapping of file functions */
85 #include "cfilearchive.h"
87 #define CHECK_POSITION
89 // Called once to setup the low-level reading code.
91 void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size )
93 Assert(cfile != NULL);
96 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
97 cb = &Cfile_block_list[cfile->id];
99 cb->lib_offset = offset;
100 cb->raw_position = 0;
104 if ( cb->lib_offset ) {
105 fseek( cb->fp, cb->lib_offset, SEEK_SET );
108 #if defined(CHECK_POSITION) && !defined(NDEBUG)
109 int raw_position = ftell(cb->fp) - cb->lib_offset;
110 Assert(raw_position == cb->raw_position);
117 // cfeof() Tests for end-of-file on a stream
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.
123 int cfeof(CFILE *cfile)
125 Assert(cfile != NULL);
128 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
129 cb = &Cfile_block_list[cfile->id];
135 // cfeof() not supported for memory-mapped files
138 Assert(cb->fp != NULL);
140 #if defined(CHECK_POSITION) && !defined(NDEBUG)
141 int raw_position = ftell(cb->fp) - cb->lib_offset;
142 Assert(raw_position == cb->raw_position);
145 if (cb->raw_position >= cb->size ) {
154 // cftell() returns offset into file
156 // returns: success ==> offset into the file
159 int cftell( CFILE * cfile )
161 Assert(cfile != NULL);
163 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
164 cb = &Cfile_block_list[cfile->id];
166 // Doesn't work for memory mapped files
169 Assert(cb->fp != NULL);
171 #if defined(CHECK_POSITION) && !defined(NDEBUG)
172 int raw_position = ftell(cb->fp) - cb->lib_offset;
173 Assert(raw_position == cb->raw_position);
176 return cb->raw_position;
180 // cfseek() moves the file pointer
182 // returns: success ==> 0
183 // error ==> non-zero
185 int cfseek( CFILE *cfile, int offset, int where )
188 Assert(cfile != NULL);
190 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
191 cb = &Cfile_block_list[cfile->id];
194 // TODO: seek to offset in memory mapped file
196 Assert( cb->fp != NULL );
202 goal_position = offset+cb->lib_offset;
206 goal_position = cb->raw_position+offset+cb->lib_offset;
210 goal_position = cb->size+offset+cb->lib_offset;
217 int result = fseek(cb->fp, goal_position, SEEK_SET );
218 cb->raw_position = goal_position - cb->lib_offset;
220 #if defined(CHECK_POSITION) && !defined(NDEBUG)
221 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
222 Assert(tmp_offset==cb->raw_position);
229 // cfread() reads from a file
231 // returns: returns the number of full elements read
234 int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
236 Assert(cfile != NULL);
238 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
241 cb = &Cfile_block_list[cfile->id];
243 // cfread() not supported for memory-mapped files
245 Assert(cb->fp != NULL);
247 int size = elsize*nelem;
253 if ( (cb->raw_position+size) > cb->size ) {
254 size = cb->size - cb->raw_position;
258 //mprintf(( "CFILE: EOF encountered in file\n" ));
261 int bytes_read = fread( buf, 1, size, cb->fp );
262 if ( bytes_read > 0 ) {
263 cb->raw_position += bytes_read;
266 #if defined(CHECK_POSITION) && !defined(NDEBUG)
267 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
268 Assert(tmp_offset==cb->raw_position);
271 return bytes_read / elsize;