]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfile/cfilelist.cpp
merge in updated platform code
[taylor/freespace2.git] / src / cfile / cfilelist.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Code for doing directory lists and sorts
16  *
17  * $Log$
18  * Revision 1.3  2002/06/09 04:41:15  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/07 03:16:43  theoddone33
22  * The Great Newline Fix
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:08  root
25  * Initial import.
26  *
27  * 
28  * 3     2/22/99 10:31p Andsager
29  * Get rid of unneeded includes.
30  * 
31  * 2     10/07/98 10:52a Dave
32  * Initial checkin.
33  * 
34  * 1     10/07/98 10:48a Dave
35  * 
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.
40  * 
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
45  * problems.
46  * 
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.
50  * 
51  * 3     4/10/98 12:18a Hoffoss
52  * Make pilot image search in pack file possible.
53  * 
54  * 2     3/30/98 10:36p Allender
55  * be sure to call _findclose() when done reading a file list
56  * 
57  * 1     12/28/97 11:48a John
58  *
59  * $NoKeywords: $
60  */
61
62 #include <stdlib.h>
63 #include <string.h>
64 #include <stdio.h>
65 #ifndef PLAT_UNIX
66 #include <io.h>
67 #include <direct.h>
68 #include <windows.h>
69 #include <winbase.h>            /* needed for memory mapping of file functions */
70 #endif
71
72 #include "pstypes.h"
73 #include "cfile.h"
74 //#include "outwnd.h"
75 //#include "vecmat.h"
76 //#include "timer.h"
77
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 )
86 {
87         int i, j, incr;
88         char *t;
89         file_list_info tt;
90
91         if (sort == CF_SORT_NAME) {
92                 incr = n / 2;
93                 while (incr > 0) {
94                         for (i=incr; i<n; i++) {
95                                 j = i - incr;
96                                 while (j >= 0) {
97                                         if (SDL_strcasecmp(list[j], list[j + incr]) > 0) {
98                                                 t = list[j];
99                                                 list[j] = list[j + incr];
100                                                 list[j + incr] = t;
101
102                                                 if (info) {
103                                                         tt = info[j];
104                                                         info[j] = info[j + incr];
105                                                         info[j + incr] = tt;
106                                                 }
107
108                                                 j -= incr;
109
110                                         } else
111                                                 break;
112                                 }
113                         }
114
115                         incr /= 2;
116                 }
117
118                 return;
119
120         } else if (sort == CF_SORT_TIME) {
121                 SDL_assert(info);
122                 incr = n / 2;
123                 while (incr > 0) {
124                         for (i=incr; i<n; i++) {
125                                 j = i - incr;
126                                 while (j >= 0) {
127                                         if (info[j].write_time < info[j + incr].write_time) {
128                                                 t = list[j];
129                                                 list[j] = list[j + incr];
130                                                 list[j + incr] = t;
131
132                                                 tt = info[j];
133                                                 info[j] = info[j + incr];
134                                                 info[j + incr] = tt;
135                                                 j -= incr;
136
137                                         } else
138                                                 break;
139                                 }
140                         }
141
142                         incr /= 2;
143                 }
144
145                 return;
146         }
147
148         nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
149 }
150
151
152 //      cf_compress - Do Run Length Compression on a block of data. Targa format.
153 //
154 //      Usage:
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 )
159 {
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
167
168         // set the threshold -- the minimum valid run length
169         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
170         
171         // set the first pixel up
172
173         flagbyte = out; // place to put next flag if run
174         inputpixel = in;
175         pixcount = 1;
176         rlcount = 0;
177         copyloc = (char *)0;
178
179         // loop till data processing complete
180         do      {
181
182                 // if we have accumulated a 128-byte packet, process it
183                 if ( pixcount == 129 )  {
184                         *flagbyte = 127;
185
186                         // set the run flag if this is a run
187
188                         if ( rlcount >= rlthresh )      {
189                                         *flagbyte |= 0x80;
190                                         pixcount = 2;
191                         }
192
193                         // copy the data into place
194                         ++flagbyte;
195                         memmove( flagbyte, copyloc, pixcount-1 );
196                         flagbyte += pixcount-1;
197                         pixcount = 1;
198
199                         // set up for next packet
200                         continue;
201                 }
202
203                 // if zeroth byte, handle as special case
204                 if ( pixcount == 1 )    {
205                         rlcount = 0;
206                         copyloc = inputpixel;           /* point to 1st guy in packet */
207                         matchpixel = inputpixel;        /* set pointer to pix to match */
208                         pixcount = 2;
209                         inputpixel += 1;
210                         continue;
211                 }
212
213                 // assembling a packet -- look at next pixel
214
215                 // current pixel == match pixel?
216                 if ( *inputpixel == *matchpixel )       {
217
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
222
223                         if ( ++rlcount == rlthresh )    {
224                                 
225                                 //      close a non-run packet
226                                 
227                                 if ( pixcount > (rlcount+1) )   {
228                                         // write out length and do not set run flag
229
230                                         *flagbyte++ = (char)(pixcount - 2 - rlthresh);
231
232                                         memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
233                                         flagbyte += (pixcount-1-rlcount);
234
235                                         copyloc = inputpixel;
236                                         pixcount = rlcount + 1;
237                                 }
238                         }
239                 } else {
240
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
245
246                         if ( rlcount >= rlthresh )      {
247
248                                 *flagbyte++ = (char)(0x80 | rlcount);
249                                 memmove(flagbyte, copyloc, 1 );
250                                 flagbyte += 1;
251                                 pixcount = 1;
252                                 continue;
253                         } else {
254
255                                 //      not a match and currently not a run
256                                 //              - save the current pixel
257                                 //              - reset the run-length flag
258                                 rlcount = 0;
259                                 matchpixel = inputpixel;
260                         }
261                 }
262                 pixcount++;
263                 inputpixel += 1;
264         } while ( inputpixel < (in + bytecount));
265
266         // quit this buffer without loosing any data
267         if ( --pixcount >= 1 )  {
268                 *flagbyte = (char)(pixcount - 1);
269                 if ( rlcount >= rlthresh )      {
270                         *flagbyte |= 0x80;
271                         pixcount = 1;
272                 }
273
274                 // copy the data into place
275                 ++flagbyte;
276                 memmove(flagbyte, copyloc, pixcount );
277                 flagbyte += pixcount;
278         }
279         return(flagbyte-out);
280 }
281
282
283 //      cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
284 //
285 //      Usage:
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 )
290 {
291         int count;
292
293         char *param_out = out;
294
295         while(1)        {
296         
297                 count = int(*in++);
298                 int run_span = count & 0x80;
299
300                 count &= (~0x80);
301
302                 if ( count > 0 )        {
303                         if ( run_span ) {
304                                 // RLE'd data
305                                 ubyte c = *in++;
306
307                                 memset( out, c, count );
308                                 out += count;
309                         } else {
310                                 memmove( out, in, count );
311                                 in += count;
312                                 out += count;
313                         }
314                 }
315         }
316
317         return out - param_out;
318                         
319 }
320
321
322 // cfread() reads from a file and decompresses it
323 //
324 // returns:   returns the number of full elements read
325 //            
326 //
327 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
328 {
329         char *out = (char *)buf;
330         
331         while(1)        {
332
333                 ubyte count;
334
335                 if ( cfread( &count, 1, 1, cfile ) != 1 )       {
336                         break;
337                 }
338
339                 int run_span = count & 0x80;
340                 count &= (~0x80);
341                 count++;
342
343                 if ( count > 0 )        {
344                         if ( run_span ) {
345                                 // RLE'd data
346                                 ubyte c;
347                                 if ( cfread( &c, 1, 1, cfile ) != 1 )   {
348                                         break;
349                                 }
350                                 memset( out, c, count );
351                         } else {
352                                 if ( cfread( out, 1, count, cfile ) != count )  {
353                                         break;
354                                 }
355                         }
356                         out += count;
357                         if ( out >= (char *)buf + (elsize*nelem))       {
358                                 break;
359                         }
360                 } else {
361                         break;
362                 }
363         }
364
365         return (out - (char *)buf)/elsize;
366 }
367
368 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
369 {
370         char *in = (char *)param_buf;
371         int bytecount = (param_elsize * param_nelem );
372
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
379
380         // set the threshold -- the minimum valid run length
381         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
382         
383         // set the first pixel up
384
385         inputpixel = in;
386         pixcount = 1;
387         rlcount = 0;
388         copyloc = (char *)0;
389
390         // loop till data processing complete
391         do      {
392
393                 // if we have accumulated a 128-byte packet, process it
394                 if ( pixcount == 129 )  {
395                         ubyte code = 127;
396
397                         // set the run flag if this is a run
398
399                         if ( rlcount >= rlthresh )      {
400                                         code |= 0x80;
401                                         pixcount = 2;
402                         }
403
404                         cfwrite( &code, 1, 1, cfile );
405
406                         // copy the data into place
407                         cfwrite( copyloc, 1, pixcount-1, cfile );
408                         pixcount = 1;
409
410                         // set up for next packet
411                         continue;
412                 }
413
414                 // if zeroth byte, handle as special case
415                 if ( pixcount == 1 )    {
416                         rlcount = 0;
417                         copyloc = inputpixel;           /* point to 1st guy in packet */
418                         matchpixel = inputpixel;        /* set pointer to pix to match */
419                         pixcount = 2;
420                         inputpixel += 1;
421                         continue;
422                 }
423
424                 // assembling a packet -- look at next pixel
425
426                 // current pixel == match pixel?
427                 if ( *inputpixel == *matchpixel )       {
428
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
433
434                         if ( ++rlcount == rlthresh )    {
435                                 
436                                 //      close a non-run packet
437                                 
438                                 if ( pixcount > (rlcount+1) )   {
439                                         // write out length and do not set run flag
440
441                                         ubyte code = (ubyte)(pixcount - 2 - rlthresh);
442                                         cfwrite( &code, 1, 1, cfile );
443
444                                         cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
445                                         copyloc = inputpixel;
446                                         pixcount = rlcount + 1;
447                                 }
448                         }
449                 } else {
450
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
455
456                         if ( rlcount >= rlthresh )      {
457
458                                 ubyte code = (ubyte)(0x80 | rlcount);
459                                 cfwrite( &code, 1, 1, cfile );
460                                 cfwrite( copyloc, 1, 1, cfile );
461                                 pixcount = 1;
462                                 continue;
463                         } else {
464
465                                 //      not a match and currently not a run
466                                 //              - save the current pixel
467                                 //              - reset the run-length flag
468                                 rlcount = 0;
469                                 matchpixel = inputpixel;
470                         }
471                 }
472                 pixcount++;
473                 inputpixel += 1;
474         } while ( inputpixel < (in + bytecount));
475
476         // quit this buffer without loosing any data
477         if ( --pixcount >= 1 )  {
478                 ubyte code = ubyte(pixcount - 1);
479
480                 // set the run flag if this is a run
481
482                 if ( rlcount >= rlthresh )      {
483                                 code |= 0x80;
484                                 pixcount = 1;
485                 }
486
487                 cfwrite( &code, 1, 1, cfile );
488
489                 // copy the data into place
490                 cfwrite( copyloc, 1, pixcount, cfile );
491         }
492
493         return param_nelem;
494 }
495