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/CfileList.cpp $
15 * Code for doing directory lists and sorts
18 * Revision 1.3 2002/06/09 04:41:15 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:43 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:08 root
28 * 3 2/22/99 10:31p Andsager
29 * Get rid of unneeded includes.
31 * 2 10/07/98 10:52a Dave
34 * 1 10/07/98 10:48a Dave
36 * 6 5/13/98 10:22p John
37 * Added cfile functions to read/write rle compressed blocks of data.
38 * Made palman use it for .clr files. Made alphacolors calculate on the
39 * fly rather than caching to/from disk.
41 * 5 5/06/98 5:30p John
42 * Removed unused cfilearchiver. Removed/replaced some unused/little used
43 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
44 * DirectX header files and libs that fixed the Direct3D alpha blending
47 * 4 4/30/98 4:53p John
48 * Restructured and cleaned up cfile code. Added capability to read off
49 * of CD-ROM drive and out of multiple pack files.
51 * 3 4/10/98 12:18a Hoffoss
52 * Make pilot image search in pack file possible.
54 * 2 3/30/98 10:36p Allender
55 * be sure to call _findclose() when done reading a file list
57 * 1 12/28/97 11:48a John
69 #include <winbase.h> /* needed for memory mapping of file functions */
78 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
79 // n = number of filenames in list to sort
80 // list = list of filenames to be sorted
81 // sort = sorting method to use (one of the CF_SORT_* defines)
82 // info = extra info for each file. Only required if sorting by time, however if you
83 // have extra file info, you should pass it as well to get it sorted too (so an
84 // index into list is the same index for info for that file
85 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
91 if (sort == CF_SORT_NAME) {
94 for (i=incr; i<n; i++) {
97 if (SDL_strcasecmp(list[j], list[j + incr]) > 0) {
99 list[j] = list[j + incr];
104 info[j] = info[j + incr];
120 } else if (sort == CF_SORT_TIME) {
124 for (i=incr; i<n; i++) {
127 if (info[j].write_time < info[j + incr].write_time) {
129 list[j] = list[j + incr];
133 info[j] = info[j + incr];
148 nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
152 // cf_compress - Do Run Length Compression on a block of data. Targa format.
155 // out Buffer to write it out to
156 // in Buffer to compress
157 // bytecount Number of bytes input
158 int cf_compress(char *out, char *in, int bytecount )
160 int pixcount; // number of pixels in the current packet
161 char *inputpixel=NULL; // current input pixel position
162 char *matchpixel=NULL; // pixel value to match for a run
163 char *flagbyte=NULL; // location of last flag byte to set
164 int rlcount; // current count in r.l. string
165 int rlthresh; // minimum valid run length
166 char *copyloc; // location to begin copying at
168 // set the threshold -- the minimum valid run length
169 rlthresh = 2; // Require a 2 pixel span before rle'ing
171 // set the first pixel up
173 flagbyte = out; // place to put next flag if run
179 // loop till data processing complete
182 // if we have accumulated a 128-byte packet, process it
183 if ( pixcount == 129 ) {
186 // set the run flag if this is a run
188 if ( rlcount >= rlthresh ) {
193 // copy the data into place
195 memmove( flagbyte, copyloc, pixcount-1 );
196 flagbyte += pixcount-1;
199 // set up for next packet
203 // if zeroth byte, handle as special case
204 if ( pixcount == 1 ) {
206 copyloc = inputpixel; /* point to 1st guy in packet */
207 matchpixel = inputpixel; /* set pointer to pix to match */
213 // assembling a packet -- look at next pixel
215 // current pixel == match pixel?
216 if ( *inputpixel == *matchpixel ) {
218 // establishing a run of enough length to
219 // save space by doing it
220 // -- write the non-run length packet
221 // -- start run-length packet
223 if ( ++rlcount == rlthresh ) {
225 // close a non-run packet
227 if ( pixcount > (rlcount+1) ) {
228 // write out length and do not set run flag
230 *flagbyte++ = (char)(pixcount - 2 - rlthresh);
232 memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
233 flagbyte += (pixcount-1-rlcount);
235 copyloc = inputpixel;
236 pixcount = rlcount + 1;
241 // no match -- either break a run or continue without one
242 // if a run exists break it:
243 // write the bytes in the string (1+1)
244 // start the next string
246 if ( rlcount >= rlthresh ) {
248 *flagbyte++ = (char)(0x80 | rlcount);
249 memmove(flagbyte, copyloc, 1 );
255 // not a match and currently not a run
256 // - save the current pixel
257 // - reset the run-length flag
259 matchpixel = inputpixel;
264 } while ( inputpixel < (in + bytecount));
266 // quit this buffer without loosing any data
267 if ( --pixcount >= 1 ) {
268 *flagbyte = (char)(pixcount - 1);
269 if ( rlcount >= rlthresh ) {
274 // copy the data into place
276 memmove(flagbyte, copyloc, pixcount );
277 flagbyte += pixcount;
279 return(flagbyte-out);
283 // cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
286 // out Buffer to write it out to
287 // in Buffer to compress
288 // bytecount Number of bytes input
289 int cf_decompress(char *out, char *in )
293 char *param_out = out;
298 int run_span = count & 0x80;
307 memset( out, c, count );
310 memmove( out, in, count );
317 return out - param_out;
322 // cfread() reads from a file and decompresses it
324 // returns: returns the number of full elements read
327 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
329 char *out = (char *)buf;
335 if ( cfread( &count, 1, 1, cfile ) != 1 ) {
339 int run_span = count & 0x80;
347 if ( cfread( &c, 1, 1, cfile ) != 1 ) {
350 memset( out, c, count );
352 if ( cfread( out, 1, count, cfile ) != count ) {
357 if ( out >= (char *)buf + (elsize*nelem)) {
365 return (out - (char *)buf)/elsize;
368 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
370 char *in = (char *)param_buf;
371 int bytecount = (param_elsize * param_nelem );
373 int pixcount; // number of pixels in the current packet
374 char *inputpixel=NULL; // current input pixel position
375 char *matchpixel=NULL; // pixel value to match for a run
376 int rlcount; // current count in r.l. string
377 int rlthresh; // minimum valid run length
378 char *copyloc; // location to begin copying at
380 // set the threshold -- the minimum valid run length
381 rlthresh = 2; // Require a 2 pixel span before rle'ing
383 // set the first pixel up
390 // loop till data processing complete
393 // if we have accumulated a 128-byte packet, process it
394 if ( pixcount == 129 ) {
397 // set the run flag if this is a run
399 if ( rlcount >= rlthresh ) {
404 cfwrite( &code, 1, 1, cfile );
406 // copy the data into place
407 cfwrite( copyloc, 1, pixcount-1, cfile );
410 // set up for next packet
414 // if zeroth byte, handle as special case
415 if ( pixcount == 1 ) {
417 copyloc = inputpixel; /* point to 1st guy in packet */
418 matchpixel = inputpixel; /* set pointer to pix to match */
424 // assembling a packet -- look at next pixel
426 // current pixel == match pixel?
427 if ( *inputpixel == *matchpixel ) {
429 // establishing a run of enough length to
430 // save space by doing it
431 // -- write the non-run length packet
432 // -- start run-length packet
434 if ( ++rlcount == rlthresh ) {
436 // close a non-run packet
438 if ( pixcount > (rlcount+1) ) {
439 // write out length and do not set run flag
441 ubyte code = (ubyte)(pixcount - 2 - rlthresh);
442 cfwrite( &code, 1, 1, cfile );
444 cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
445 copyloc = inputpixel;
446 pixcount = rlcount + 1;
451 // no match -- either break a run or continue without one
452 // if a run exists break it:
453 // write the bytes in the string (1+1)
454 // start the next string
456 if ( rlcount >= rlthresh ) {
458 ubyte code = (ubyte)(0x80 | rlcount);
459 cfwrite( &code, 1, 1, cfile );
460 cfwrite( copyloc, 1, 1, cfile );
465 // not a match and currently not a run
466 // - save the current pixel
467 // - reset the run-length flag
469 matchpixel = inputpixel;
474 } while ( inputpixel < (in + bytecount));
476 // quit this buffer without loosing any data
477 if ( --pixcount >= 1 ) {
478 ubyte code = ubyte(pixcount - 1);
480 // set the run flag if this is a run
482 if ( rlcount >= rlthresh ) {
487 cfwrite( &code, 1, 1, cfile );
489 // copy the data into place
490 cfwrite( copyloc, 1, pixcount, cfile );