]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfile/cfilelist.cpp
Initial revision
[taylor/freespace2.git] / src / cfile / cfilelist.cpp
1 /*
2  * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code for doing directory lists and sorts
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:08  root
11  * Initial revision
12  *
13  * 
14  * 3     2/22/99 10:31p Andsager
15  * Get rid of unneeded includes.
16  * 
17  * 2     10/07/98 10:52a Dave
18  * Initial checkin.
19  * 
20  * 1     10/07/98 10:48a Dave
21  * 
22  * 6     5/13/98 10:22p John
23  * Added cfile functions to read/write rle compressed blocks of data.
24  * Made palman use it for .clr files.  Made alphacolors calculate on the
25  * fly rather than caching to/from disk.
26  * 
27  * 5     5/06/98 5:30p John
28  * Removed unused cfilearchiver.  Removed/replaced some unused/little used
29  * graphics functions, namely gradient_h and _v and pixel_sp.   Put in new
30  * DirectX header files and libs that fixed the Direct3D alpha blending
31  * problems.
32  * 
33  * 4     4/30/98 4:53p John
34  * Restructured and cleaned up cfile code.  Added capability to read off
35  * of CD-ROM drive and out of multiple pack files.
36  * 
37  * 3     4/10/98 12:18a Hoffoss
38  * Make pilot image search in pack file possible.
39  * 
40  * 2     3/30/98 10:36p Allender
41  * be sure to call _findclose() when done reading a file list
42  * 
43  * 1     12/28/97 11:48a John
44  *
45  * $NoKeywords: $
46  */
47
48 #include <stdlib.h>
49 #include <string.h>
50 #include <stdio.h>
51 #ifndef PLAT_UNIX
52 #include <io.h>
53 #include <direct.h>
54 #include <windows.h>
55 #include <winbase.h>            /* needed for memory mapping of file functions */
56 #endif
57
58 #include "pstypes.h"
59 #include "cfile.h"
60 //#include "outwnd.h"
61 //#include "vecmat.h"
62 //#include "timer.h"
63
64 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
65 //   n = number of filenames in list to sort
66 //   list = list of filenames to be sorted
67 //   sort = sorting method to use (one of the CF_SORT_* defines)
68 //   info = extra info for each file.  Only required if sorting by time, however if you
69 //          have extra file info, you should pass it as well to get it sorted too (so an
70 //          index into list is the same index for info for that file
71 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
72 {
73         int i, j, incr;
74         char *t;
75         file_list_info tt;
76
77         if (sort == CF_SORT_NAME) {
78                 incr = n / 2;
79                 while (incr > 0) {
80                         for (i=incr; i<n; i++) {
81                                 j = i - incr;
82                                 while (j >= 0) {
83                                         if (stricmp(list[j], list[j + incr]) > 0) {
84                                                 t = list[j];
85                                                 list[j] = list[j + incr];
86                                                 list[j + incr] = t;
87
88                                                 if (info) {
89                                                         tt = info[j];
90                                                         info[j] = info[j + incr];
91                                                         info[j + incr] = tt;
92                                                 }
93
94                                                 j -= incr;
95
96                                         } else
97                                                 break;
98                                 }
99                         }
100
101                         incr /= 2;
102                 }
103
104                 return;
105
106         } else if (sort == CF_SORT_TIME) {
107                 Assert(info);
108                 incr = n / 2;
109                 while (incr > 0) {
110                         for (i=incr; i<n; i++) {
111                                 j = i - incr;
112                                 while (j >= 0) {
113                                         if (info[j].write_time < info[j + incr].write_time) {
114                                                 t = list[j];
115                                                 list[j] = list[j + incr];
116                                                 list[j + incr] = t;
117
118                                                 tt = info[j];
119                                                 info[j] = info[j + incr];
120                                                 info[j + incr] = tt;
121                                                 j -= incr;
122
123                                         } else
124                                                 break;
125                                 }
126                         }
127
128                         incr /= 2;
129                 }
130
131                 return;
132         }
133
134         nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
135 }
136
137
138 //      cf_compress - Do Run Length Compression on a block of data. Targa format.
139 //
140 //      Usage:
141 //                              out                     Buffer to write it out to
142 //                              in                              Buffer to compress
143 //                              bytecount       Number of bytes input
144 int cf_compress(char *out, char *in, int bytecount )
145 {
146         int pixcount;           // number of pixels in the current packet
147         char *inputpixel=NULL;  // current input pixel position
148         char *matchpixel=NULL;  // pixel value to match for a run
149         char *flagbyte=NULL;            // location of last flag byte to set
150         int rlcount;            // current count in r.l. string 
151         int rlthresh;           // minimum valid run length
152         char *copyloc;          // location to begin copying at
153
154         // set the threshold -- the minimum valid run length
155         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
156         
157         // set the first pixel up
158
159         flagbyte = out; // place to put next flag if run
160         inputpixel = in;
161         pixcount = 1;
162         rlcount = 0;
163         copyloc = (char *)0;
164
165         // loop till data processing complete
166         do      {
167
168                 // if we have accumulated a 128-byte packet, process it
169                 if ( pixcount == 129 )  {
170                         *flagbyte = 127;
171
172                         // set the run flag if this is a run
173
174                         if ( rlcount >= rlthresh )      {
175                                         *flagbyte |= 0x80;
176                                         pixcount = 2;
177                         }
178
179                         // copy the data into place
180                         ++flagbyte;
181                         memmove( flagbyte, copyloc, pixcount-1 );
182                         flagbyte += pixcount-1;
183                         pixcount = 1;
184
185                         // set up for next packet
186                         continue;
187                 }
188
189                 // if zeroth byte, handle as special case
190                 if ( pixcount == 1 )    {
191                         rlcount = 0;
192                         copyloc = inputpixel;           /* point to 1st guy in packet */
193                         matchpixel = inputpixel;        /* set pointer to pix to match */
194                         pixcount = 2;
195                         inputpixel += 1;
196                         continue;
197                 }
198
199                 // assembling a packet -- look at next pixel
200
201                 // current pixel == match pixel?
202                 if ( *inputpixel == *matchpixel )       {
203
204                         //      establishing a run of enough length to
205                         //      save space by doing it
206                         //              -- write the non-run length packet
207                         //              -- start run-length packet
208
209                         if ( ++rlcount == rlthresh )    {
210                                 
211                                 //      close a non-run packet
212                                 
213                                 if ( pixcount > (rlcount+1) )   {
214                                         // write out length and do not set run flag
215
216                                         *flagbyte++ = (char)(pixcount - 2 - rlthresh);
217
218                                         memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
219                                         flagbyte += (pixcount-1-rlcount);
220
221                                         copyloc = inputpixel;
222                                         pixcount = rlcount + 1;
223                                 }
224                         }
225                 } else {
226
227                         // no match -- either break a run or continue without one
228                         //      if a run exists break it:
229                         //              write the bytes in the string (1+1)
230                         //              start the next string
231
232                         if ( rlcount >= rlthresh )      {
233
234                                 *flagbyte++ = (char)(0x80 | rlcount);
235                                 memmove(flagbyte, copyloc, 1 );
236                                 flagbyte += 1;
237                                 pixcount = 1;
238                                 continue;
239                         } else {
240
241                                 //      not a match and currently not a run
242                                 //              - save the current pixel
243                                 //              - reset the run-length flag
244                                 rlcount = 0;
245                                 matchpixel = inputpixel;
246                         }
247                 }
248                 pixcount++;
249                 inputpixel += 1;
250         } while ( inputpixel < (in + bytecount));
251
252         // quit this buffer without loosing any data
253         if ( --pixcount >= 1 )  {
254                 *flagbyte = (char)(pixcount - 1);
255                 if ( rlcount >= rlthresh )      {
256                         *flagbyte |= 0x80;
257                         pixcount = 1;
258                 }
259
260                 // copy the data into place
261                 ++flagbyte;
262                 memmove(flagbyte, copyloc, pixcount );
263                 flagbyte += pixcount;
264         }
265         return(flagbyte-out);
266 }
267
268
269 //      cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
270 //
271 //      Usage:
272 //                              out                     Buffer to write it out to
273 //                              in                              Buffer to compress
274 //                              bytecount       Number of bytes input
275 int cf_decompress(char *out, char *in )
276 {
277         int count;
278
279         char *param_out = out;
280
281         while(1)        {
282         
283                 count = int(*in++);
284                 int run_span = count & 0x80;
285
286                 count &= (~0x80);
287
288                 if ( count > 0 )        {
289                         if ( run_span ) {
290                                 // RLE'd data
291                                 ubyte c = *in++;
292
293                                 memset( out, c, count );
294                                 out += count;
295                         } else {
296                                 memmove( out, in, count );
297                                 in += count;
298                                 out += count;
299                         }
300                 }
301         }
302
303         return out - param_out;
304                         
305 }
306
307
308 // cfread() reads from a file and decompresses it
309 //
310 // returns:   returns the number of full elements read
311 //            
312 //
313 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
314 {
315         char *out = (char *)buf;
316         
317         while(1)        {
318
319                 byte count;
320
321                 if ( cfread( &count, 1, 1, cfile ) != 1 )       {
322                         break;
323                 }
324
325                 int run_span = count & 0x80;
326                 count &= (~0x80);
327                 count++;
328
329                 if ( count > 0 )        {
330                         if ( run_span ) {
331                                 // RLE'd data
332                                 byte c;
333                                 if ( cfread( &c, 1, 1, cfile ) != 1 )   {
334                                         break;
335                                 }
336                                 memset( out, c, count );
337                         } else {
338                                 if ( cfread( out, 1, count, cfile ) != count )  {
339                                         break;
340                                 }
341                         }
342                         out += count;
343                         if ( out >= (char *)buf + (elsize*nelem))       {
344                                 break;
345                         }
346                 } else {
347                         break;
348                 }
349         }
350
351         return (out - (char *)buf)/elsize;
352 }
353
354 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
355 {
356         char *in = (char *)param_buf;
357         int bytecount = (param_elsize * param_nelem );
358
359         int pixcount;           // number of pixels in the current packet
360         char *inputpixel=NULL;  // current input pixel position
361         char *matchpixel=NULL;  // pixel value to match for a run
362         int rlcount;            // current count in r.l. string 
363         int rlthresh;           // minimum valid run length
364         char *copyloc;          // location to begin copying at
365
366         // set the threshold -- the minimum valid run length
367         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
368         
369         // set the first pixel up
370
371         inputpixel = in;
372         pixcount = 1;
373         rlcount = 0;
374         copyloc = (char *)0;
375
376         // loop till data processing complete
377         do      {
378
379                 // if we have accumulated a 128-byte packet, process it
380                 if ( pixcount == 129 )  {
381                         ubyte code = 127;
382
383                         // set the run flag if this is a run
384
385                         if ( rlcount >= rlthresh )      {
386                                         code |= 0x80;
387                                         pixcount = 2;
388                         }
389
390                         cfwrite( &code, 1, 1, cfile );
391
392                         // copy the data into place
393                         cfwrite( copyloc, 1, pixcount-1, cfile );
394                         pixcount = 1;
395
396                         // set up for next packet
397                         continue;
398                 }
399
400                 // if zeroth byte, handle as special case
401                 if ( pixcount == 1 )    {
402                         rlcount = 0;
403                         copyloc = inputpixel;           /* point to 1st guy in packet */
404                         matchpixel = inputpixel;        /* set pointer to pix to match */
405                         pixcount = 2;
406                         inputpixel += 1;
407                         continue;
408                 }
409
410                 // assembling a packet -- look at next pixel
411
412                 // current pixel == match pixel?
413                 if ( *inputpixel == *matchpixel )       {
414
415                         //      establishing a run of enough length to
416                         //      save space by doing it
417                         //              -- write the non-run length packet
418                         //              -- start run-length packet
419
420                         if ( ++rlcount == rlthresh )    {
421                                 
422                                 //      close a non-run packet
423                                 
424                                 if ( pixcount > (rlcount+1) )   {
425                                         // write out length and do not set run flag
426
427                                         ubyte code = (ubyte)(pixcount - 2 - rlthresh);
428                                         cfwrite( &code, 1, 1, cfile );
429
430                                         cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
431                                         copyloc = inputpixel;
432                                         pixcount = rlcount + 1;
433                                 }
434                         }
435                 } else {
436
437                         // no match -- either break a run or continue without one
438                         //      if a run exists break it:
439                         //              write the bytes in the string (1+1)
440                         //              start the next string
441
442                         if ( rlcount >= rlthresh )      {
443
444                                 ubyte code = (ubyte)(0x80 | rlcount);
445                                 cfwrite( &code, 1, 1, cfile );
446                                 cfwrite( copyloc, 1, 1, cfile );
447                                 pixcount = 1;
448                                 continue;
449                         } else {
450
451                                 //      not a match and currently not a run
452                                 //              - save the current pixel
453                                 //              - reset the run-length flag
454                                 rlcount = 0;
455                                 matchpixel = inputpixel;
456                         }
457                 }
458                 pixcount++;
459                 inputpixel += 1;
460         } while ( inputpixel < (in + bytecount));
461
462         // quit this buffer without loosing any data
463         if ( --pixcount >= 1 )  {
464                 ubyte code = ubyte(pixcount - 1);
465
466                 // set the run flag if this is a run
467
468                 if ( rlcount >= rlthresh )      {
469                                 code |= 0x80;
470                                 pixcount = 1;
471                 }
472
473                 cfwrite( &code, 1, 1, cfile );
474
475                 // copy the data into place
476                 cfwrite( copyloc, 1, pixcount, cfile );
477         }
478
479         return param_nelem;
480 }