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
72 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
73 // n = number of filenames in list to sort
74 // list = list of filenames to be sorted
75 // sort = sorting method to use (one of the CF_SORT_* defines)
76 // info = extra info for each file. Only required if sorting by time, however if you
77 // have extra file info, you should pass it as well to get it sorted too (so an
78 // index into list is the same index for info for that file
79 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
85 if (sort == CF_SORT_NAME) {
88 for (i=incr; i<n; i++) {
91 if (SDL_strcasecmp(list[j], list[j + incr]) > 0) {
93 list[j] = list[j + incr];
98 info[j] = info[j + incr];
114 } else if (sort == CF_SORT_TIME) {
118 for (i=incr; i<n; i++) {
121 if (info[j].write_time < info[j + incr].write_time) {
123 list[j] = list[j + incr];
127 info[j] = info[j + incr];
142 nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
146 // cf_compress - Do Run Length Compression on a block of data. Targa format.
149 // out Buffer to write it out to
150 // in Buffer to compress
151 // bytecount Number of bytes input
152 int cf_compress(char *out, char *in, int bytecount )
154 int pixcount; // number of pixels in the current packet
155 char *inputpixel=NULL; // current input pixel position
156 char *matchpixel=NULL; // pixel value to match for a run
157 char *flagbyte=NULL; // location of last flag byte to set
158 int rlcount; // current count in r.l. string
159 int rlthresh; // minimum valid run length
160 char *copyloc; // location to begin copying at
162 // set the threshold -- the minimum valid run length
163 rlthresh = 2; // Require a 2 pixel span before rle'ing
165 // set the first pixel up
167 flagbyte = out; // place to put next flag if run
173 // loop till data processing complete
176 // if we have accumulated a 128-byte packet, process it
177 if ( pixcount == 129 ) {
180 // set the run flag if this is a run
182 if ( rlcount >= rlthresh ) {
187 // copy the data into place
189 memmove( flagbyte, copyloc, pixcount-1 );
190 flagbyte += pixcount-1;
193 // set up for next packet
197 // if zeroth byte, handle as special case
198 if ( pixcount == 1 ) {
200 copyloc = inputpixel; /* point to 1st guy in packet */
201 matchpixel = inputpixel; /* set pointer to pix to match */
207 // assembling a packet -- look at next pixel
209 // current pixel == match pixel?
210 if ( *inputpixel == *matchpixel ) {
212 // establishing a run of enough length to
213 // save space by doing it
214 // -- write the non-run length packet
215 // -- start run-length packet
217 if ( ++rlcount == rlthresh ) {
219 // close a non-run packet
221 if ( pixcount > (rlcount+1) ) {
222 // write out length and do not set run flag
224 *flagbyte++ = (char)(pixcount - 2 - rlthresh);
226 memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
227 flagbyte += (pixcount-1-rlcount);
229 copyloc = inputpixel;
230 pixcount = rlcount + 1;
235 // no match -- either break a run or continue without one
236 // if a run exists break it:
237 // write the bytes in the string (1+1)
238 // start the next string
240 if ( rlcount >= rlthresh ) {
242 *flagbyte++ = (char)(0x80 | rlcount);
243 memmove(flagbyte, copyloc, 1 );
249 // not a match and currently not a run
250 // - save the current pixel
251 // - reset the run-length flag
253 matchpixel = inputpixel;
258 } while ( inputpixel < (in + bytecount));
260 // quit this buffer without loosing any data
261 if ( --pixcount >= 1 ) {
262 *flagbyte = (char)(pixcount - 1);
263 if ( rlcount >= rlthresh ) {
268 // copy the data into place
270 memmove(flagbyte, copyloc, pixcount );
271 flagbyte += pixcount;
273 return(flagbyte-out);
277 // cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
280 // out Buffer to write it out to
281 // in Buffer to compress
282 // bytecount Number of bytes input
283 int cf_decompress(char *out, char *in )
287 char *param_out = out;
292 int run_span = count & 0x80;
301 memset( out, c, count );
304 memmove( out, in, count );
311 return out - param_out;
316 // cfread() reads from a file and decompresses it
318 // returns: returns the number of full elements read
321 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
323 char *out = (char *)buf;
329 if ( cfread( &count, 1, 1, cfile ) != 1 ) {
333 int run_span = count & 0x80;
341 if ( cfread( &c, 1, 1, cfile ) != 1 ) {
344 memset( out, c, count );
346 if ( cfread( out, 1, count, cfile ) != count ) {
351 if ( out >= (char *)buf + (elsize*nelem)) {
359 return (out - (char *)buf)/elsize;
362 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
364 char *in = (char *)param_buf;
365 int bytecount = (param_elsize * param_nelem );
367 int pixcount; // number of pixels in the current packet
368 char *inputpixel=NULL; // current input pixel position
369 char *matchpixel=NULL; // pixel value to match for a run
370 int rlcount; // current count in r.l. string
371 int rlthresh; // minimum valid run length
372 char *copyloc; // location to begin copying at
374 // set the threshold -- the minimum valid run length
375 rlthresh = 2; // Require a 2 pixel span before rle'ing
377 // set the first pixel up
384 // loop till data processing complete
387 // if we have accumulated a 128-byte packet, process it
388 if ( pixcount == 129 ) {
391 // set the run flag if this is a run
393 if ( rlcount >= rlthresh ) {
398 cfwrite( &code, 1, 1, cfile );
400 // copy the data into place
401 cfwrite( copyloc, 1, pixcount-1, cfile );
404 // set up for next packet
408 // if zeroth byte, handle as special case
409 if ( pixcount == 1 ) {
411 copyloc = inputpixel; /* point to 1st guy in packet */
412 matchpixel = inputpixel; /* set pointer to pix to match */
418 // assembling a packet -- look at next pixel
420 // current pixel == match pixel?
421 if ( *inputpixel == *matchpixel ) {
423 // establishing a run of enough length to
424 // save space by doing it
425 // -- write the non-run length packet
426 // -- start run-length packet
428 if ( ++rlcount == rlthresh ) {
430 // close a non-run packet
432 if ( pixcount > (rlcount+1) ) {
433 // write out length and do not set run flag
435 ubyte code = (ubyte)(pixcount - 2 - rlthresh);
436 cfwrite( &code, 1, 1, cfile );
438 cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
439 copyloc = inputpixel;
440 pixcount = rlcount + 1;
445 // no match -- either break a run or continue without one
446 // if a run exists break it:
447 // write the bytes in the string (1+1)
448 // start the next string
450 if ( rlcount >= rlthresh ) {
452 ubyte code = (ubyte)(0x80 | rlcount);
453 cfwrite( &code, 1, 1, cfile );
454 cfwrite( copyloc, 1, 1, cfile );
459 // not a match and currently not a run
460 // - save the current pixel
461 // - reset the run-length flag
463 matchpixel = inputpixel;
468 } while ( inputpixel < (in + bytecount));
470 // quit this buffer without loosing any data
471 if ( --pixcount >= 1 ) {
472 ubyte code = ubyte(pixcount - 1);
474 // set the run flag if this is a run
476 if ( rlcount >= rlthresh ) {
481 cfwrite( &code, 1, 1, cfile );
483 // copy the data into place
484 cfwrite( copyloc, 1, pixcount, cfile );