]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfile/cfilelist.cpp
clean up Windows #include's and use winsock2
[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
66 #include "pstypes.h"
67 #include "cfile.h"
68 //#include "outwnd.h"
69 //#include "vecmat.h"
70 //#include "timer.h"
71
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 )
80 {
81         int i, j, incr;
82         char *t;
83         file_list_info tt;
84
85         if (sort == CF_SORT_NAME) {
86                 incr = n / 2;
87                 while (incr > 0) {
88                         for (i=incr; i<n; i++) {
89                                 j = i - incr;
90                                 while (j >= 0) {
91                                         if (SDL_strcasecmp(list[j], list[j + incr]) > 0) {
92                                                 t = list[j];
93                                                 list[j] = list[j + incr];
94                                                 list[j + incr] = t;
95
96                                                 if (info) {
97                                                         tt = info[j];
98                                                         info[j] = info[j + incr];
99                                                         info[j + incr] = tt;
100                                                 }
101
102                                                 j -= incr;
103
104                                         } else
105                                                 break;
106                                 }
107                         }
108
109                         incr /= 2;
110                 }
111
112                 return;
113
114         } else if (sort == CF_SORT_TIME) {
115                 SDL_assert(info);
116                 incr = n / 2;
117                 while (incr > 0) {
118                         for (i=incr; i<n; i++) {
119                                 j = i - incr;
120                                 while (j >= 0) {
121                                         if (info[j].write_time < info[j + incr].write_time) {
122                                                 t = list[j];
123                                                 list[j] = list[j + incr];
124                                                 list[j + incr] = t;
125
126                                                 tt = info[j];
127                                                 info[j] = info[j + incr];
128                                                 info[j + incr] = tt;
129                                                 j -= incr;
130
131                                         } else
132                                                 break;
133                                 }
134                         }
135
136                         incr /= 2;
137                 }
138
139                 return;
140         }
141
142         nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
143 }
144
145
146 //      cf_compress - Do Run Length Compression on a block of data. Targa format.
147 //
148 //      Usage:
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 )
153 {
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
161
162         // set the threshold -- the minimum valid run length
163         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
164         
165         // set the first pixel up
166
167         flagbyte = out; // place to put next flag if run
168         inputpixel = in;
169         pixcount = 1;
170         rlcount = 0;
171         copyloc = (char *)0;
172
173         // loop till data processing complete
174         do      {
175
176                 // if we have accumulated a 128-byte packet, process it
177                 if ( pixcount == 129 )  {
178                         *flagbyte = 127;
179
180                         // set the run flag if this is a run
181
182                         if ( rlcount >= rlthresh )      {
183                                         *flagbyte |= 0x80;
184                                         pixcount = 2;
185                         }
186
187                         // copy the data into place
188                         ++flagbyte;
189                         memmove( flagbyte, copyloc, pixcount-1 );
190                         flagbyte += pixcount-1;
191                         pixcount = 1;
192
193                         // set up for next packet
194                         continue;
195                 }
196
197                 // if zeroth byte, handle as special case
198                 if ( pixcount == 1 )    {
199                         rlcount = 0;
200                         copyloc = inputpixel;           /* point to 1st guy in packet */
201                         matchpixel = inputpixel;        /* set pointer to pix to match */
202                         pixcount = 2;
203                         inputpixel += 1;
204                         continue;
205                 }
206
207                 // assembling a packet -- look at next pixel
208
209                 // current pixel == match pixel?
210                 if ( *inputpixel == *matchpixel )       {
211
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
216
217                         if ( ++rlcount == rlthresh )    {
218                                 
219                                 //      close a non-run packet
220                                 
221                                 if ( pixcount > (rlcount+1) )   {
222                                         // write out length and do not set run flag
223
224                                         *flagbyte++ = (char)(pixcount - 2 - rlthresh);
225
226                                         memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
227                                         flagbyte += (pixcount-1-rlcount);
228
229                                         copyloc = inputpixel;
230                                         pixcount = rlcount + 1;
231                                 }
232                         }
233                 } else {
234
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
239
240                         if ( rlcount >= rlthresh )      {
241
242                                 *flagbyte++ = (char)(0x80 | rlcount);
243                                 memmove(flagbyte, copyloc, 1 );
244                                 flagbyte += 1;
245                                 pixcount = 1;
246                                 continue;
247                         } else {
248
249                                 //      not a match and currently not a run
250                                 //              - save the current pixel
251                                 //              - reset the run-length flag
252                                 rlcount = 0;
253                                 matchpixel = inputpixel;
254                         }
255                 }
256                 pixcount++;
257                 inputpixel += 1;
258         } while ( inputpixel < (in + bytecount));
259
260         // quit this buffer without loosing any data
261         if ( --pixcount >= 1 )  {
262                 *flagbyte = (char)(pixcount - 1);
263                 if ( rlcount >= rlthresh )      {
264                         *flagbyte |= 0x80;
265                         pixcount = 1;
266                 }
267
268                 // copy the data into place
269                 ++flagbyte;
270                 memmove(flagbyte, copyloc, pixcount );
271                 flagbyte += pixcount;
272         }
273         return(flagbyte-out);
274 }
275
276
277 //      cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
278 //
279 //      Usage:
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 )
284 {
285         int count;
286
287         char *param_out = out;
288
289         while(1)        {
290         
291                 count = int(*in++);
292                 int run_span = count & 0x80;
293
294                 count &= (~0x80);
295
296                 if ( count > 0 )        {
297                         if ( run_span ) {
298                                 // RLE'd data
299                                 ubyte c = *in++;
300
301                                 memset( out, c, count );
302                                 out += count;
303                         } else {
304                                 memmove( out, in, count );
305                                 in += count;
306                                 out += count;
307                         }
308                 }
309         }
310
311         return out - param_out;
312                         
313 }
314
315
316 // cfread() reads from a file and decompresses it
317 //
318 // returns:   returns the number of full elements read
319 //            
320 //
321 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
322 {
323         char *out = (char *)buf;
324         
325         while(1)        {
326
327                 ubyte count;
328
329                 if ( cfread( &count, 1, 1, cfile ) != 1 )       {
330                         break;
331                 }
332
333                 int run_span = count & 0x80;
334                 count &= (~0x80);
335                 count++;
336
337                 if ( count > 0 )        {
338                         if ( run_span ) {
339                                 // RLE'd data
340                                 ubyte c;
341                                 if ( cfread( &c, 1, 1, cfile ) != 1 )   {
342                                         break;
343                                 }
344                                 memset( out, c, count );
345                         } else {
346                                 if ( cfread( out, 1, count, cfile ) != count )  {
347                                         break;
348                                 }
349                         }
350                         out += count;
351                         if ( out >= (char *)buf + (elsize*nelem))       {
352                                 break;
353                         }
354                 } else {
355                         break;
356                 }
357         }
358
359         return (out - (char *)buf)/elsize;
360 }
361
362 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
363 {
364         char *in = (char *)param_buf;
365         int bytecount = (param_elsize * param_nelem );
366
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
373
374         // set the threshold -- the minimum valid run length
375         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
376         
377         // set the first pixel up
378
379         inputpixel = in;
380         pixcount = 1;
381         rlcount = 0;
382         copyloc = (char *)0;
383
384         // loop till data processing complete
385         do      {
386
387                 // if we have accumulated a 128-byte packet, process it
388                 if ( pixcount == 129 )  {
389                         ubyte code = 127;
390
391                         // set the run flag if this is a run
392
393                         if ( rlcount >= rlthresh )      {
394                                         code |= 0x80;
395                                         pixcount = 2;
396                         }
397
398                         cfwrite( &code, 1, 1, cfile );
399
400                         // copy the data into place
401                         cfwrite( copyloc, 1, pixcount-1, cfile );
402                         pixcount = 1;
403
404                         // set up for next packet
405                         continue;
406                 }
407
408                 // if zeroth byte, handle as special case
409                 if ( pixcount == 1 )    {
410                         rlcount = 0;
411                         copyloc = inputpixel;           /* point to 1st guy in packet */
412                         matchpixel = inputpixel;        /* set pointer to pix to match */
413                         pixcount = 2;
414                         inputpixel += 1;
415                         continue;
416                 }
417
418                 // assembling a packet -- look at next pixel
419
420                 // current pixel == match pixel?
421                 if ( *inputpixel == *matchpixel )       {
422
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
427
428                         if ( ++rlcount == rlthresh )    {
429                                 
430                                 //      close a non-run packet
431                                 
432                                 if ( pixcount > (rlcount+1) )   {
433                                         // write out length and do not set run flag
434
435                                         ubyte code = (ubyte)(pixcount - 2 - rlthresh);
436                                         cfwrite( &code, 1, 1, cfile );
437
438                                         cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
439                                         copyloc = inputpixel;
440                                         pixcount = rlcount + 1;
441                                 }
442                         }
443                 } else {
444
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
449
450                         if ( rlcount >= rlthresh )      {
451
452                                 ubyte code = (ubyte)(0x80 | rlcount);
453                                 cfwrite( &code, 1, 1, cfile );
454                                 cfwrite( copyloc, 1, 1, cfile );
455                                 pixcount = 1;
456                                 continue;
457                         } else {
458
459                                 //      not a match and currently not a run
460                                 //              - save the current pixel
461                                 //              - reset the run-length flag
462                                 rlcount = 0;
463                                 matchpixel = inputpixel;
464                         }
465                 }
466                 pixcount++;
467                 inputpixel += 1;
468         } while ( inputpixel < (in + bytecount));
469
470         // quit this buffer without loosing any data
471         if ( --pixcount >= 1 )  {
472                 ubyte code = ubyte(pixcount - 1);
473
474                 // set the run flag if this is a run
475
476                 if ( rlcount >= rlthresh )      {
477                                 code |= 0x80;
478                                 pixcount = 1;
479                 }
480
481                 cfwrite( &code, 1, 1, cfile );
482
483                 // copy the data into place
484                 cfwrite( copyloc, 1, pixcount, cfile );
485         }
486
487         return param_nelem;
488 }
489