2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/CFile/CfileArchive.cpp $
15 * Low-level code for reading data out of large archive files or normal files. All
16 * reads/seeks come through here.
19 * Revision 1.2 2002/06/09 04:41:15 relnev
20 * added copyright header
22 * Revision 1.1.1.1 2002/05/03 03:28:08 root
26 * 4 2/22/99 10:31p Andsager
27 * Get rid of unneeded includes.
29 * 3 1/06/99 2:24p Dave
30 * Stubs and release build fixes.
32 * 2 10/07/98 10:52a Dave
35 * 1 10/07/98 10:48a Dave
37 * 12 5/14/98 8:10p Lawrance
38 * Fix bug with trying to read past the end of a file (when from a
41 * 11 5/11/98 11:48a John
42 * fixed bug with memory mapped files
44 * 10 5/11/98 10:59a John
47 * 9 5/11/98 10:59a John
48 * Moved the low-level file reading code into cfilearchive.cpp.
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.
54 * 7 4/20/98 11:49a Hoffoss
55 * Fixed bug with directory name getting.
57 * 6 4/10/98 12:18a Hoffoss
58 * Make pilot image search in pack file possible.
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.
64 * 4 12/30/97 5:31p Lawrance
65 * fixed problem for people that didn't have a VP file
67 * 3 12/30/97 4:31p Sandeep
68 * Changed pakfile format
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.
74 * 1 12/28/97 11:48a John
79 #define _CFILE_INTERNAL
88 #include <winbase.h> /* needed for memory mapping of file functions */
96 #include "cfilearchive.h"
98 #define CHECK_POSITION
100 // Called once to setup the low-level reading code.
102 void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size )
104 SDL_assert(cfile != NULL);
107 SDL_assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
108 cb = &Cfile_block_list[cfile->id];
110 cb->lib_offset = offset;
111 cb->raw_position = 0;
115 if ( cb->lib_offset ) {
116 fseek( cb->fp, cb->lib_offset, SEEK_SET );
119 #if defined(CHECK_POSITION) && !defined(NDEBUG)
120 int raw_position = ftell(cb->fp) - cb->lib_offset;
121 SDL_assert(raw_position == cb->raw_position);
128 // cfeof() Tests for end-of-file on a stream
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.
134 int cfeof(CFILE *cfile)
136 SDL_assert(cfile != NULL);
139 SDL_assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
140 cb = &Cfile_block_list[cfile->id];
144 // cfeof() not supported for memory-mapped files
145 SDL_assert( !cb->data );
147 SDL_assert(cb->fp != NULL);
149 #if defined(CHECK_POSITION) && !defined(NDEBUG)
150 int raw_position = ftell(cb->fp) - cb->lib_offset;
151 SDL_assert(raw_position == cb->raw_position);
154 if (cb->raw_position >= cb->size ) {
163 // cftell() returns offset into file
165 // returns: success ==> offset into the file
168 int cftell( CFILE * cfile )
170 SDL_assert(cfile != NULL);
172 SDL_assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
173 cb = &Cfile_block_list[cfile->id];
175 // Doesn't work for memory mapped files
176 SDL_assert( !cb->data );
178 SDL_assert(cb->fp != NULL);
180 #if defined(CHECK_POSITION) && !defined(NDEBUG)
181 int raw_position = ftell(cb->fp) - cb->lib_offset;
182 SDL_assert(raw_position == cb->raw_position);
185 return cb->raw_position;
189 // cfseek() moves the file pointer
191 // returns: success ==> 0
192 // error ==> non-zero
194 int cfseek( CFILE *cfile, int offset, int where )
197 SDL_assert(cfile != NULL);
199 SDL_assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
200 cb = &Cfile_block_list[cfile->id];
203 // TODO: seek to offset in memory mapped file
204 SDL_assert( !cb->data );
205 SDL_assert( cb->fp != NULL );
211 goal_position = offset+cb->lib_offset;
215 goal_position = cb->raw_position+offset+cb->lib_offset;
219 goal_position = cb->size+offset+cb->lib_offset;
226 int result = fseek(cb->fp, goal_position, SEEK_SET );
227 cb->raw_position = goal_position - cb->lib_offset;
229 #if defined(CHECK_POSITION) && !defined(NDEBUG)
230 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
231 SDL_assert(tmp_offset==cb->raw_position);
238 // cfread() reads from a file
240 // returns: returns the number of full elements read
243 int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
245 SDL_assert(cfile != NULL);
246 SDL_assert(buf != NULL);
247 SDL_assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
250 cb = &Cfile_block_list[cfile->id];
252 // cfread() not supported for memory-mapped files
253 SDL_assert( !cb->data );
254 SDL_assert(cb->fp != NULL);
256 int size = elsize*nelem;
258 SDL_assert(nelem > 0);
259 SDL_assert(elsize > 0);
260 SDL_assert(size > 0);
262 if ( (cb->raw_position+size) > cb->size ) {
263 size = cb->size - cb->raw_position;
267 //mprintf(( "CFILE: EOF encountered in file\n" ));
270 int bytes_read = fread( buf, 1, size, cb->fp );
271 if ( bytes_read > 0 ) {
272 cb->raw_position += bytes_read;
275 #if defined(CHECK_POSITION) && !defined(NDEBUG)
276 int tmp_offset = ftell(cb->fp) - cb->lib_offset;
277 SDL_assert(tmp_offset==cb->raw_position);
280 return bytes_read / elsize;