]> icculus.org git repositories - btb/d2x.git/blob - main/piggy.c
make console optional, other fixes
[btb/d2x.git] / main / piggy.c
1 /* $Id: piggy.c,v 1.31 2003-03-29 22:35:00 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Functions for managing the pig files.
18  *
19  * Old Log:
20  * Revision 1.16  1995/11/09  17:27:47  allender
21  * put in missing quote on new gauge name
22  *
23  * Revision 1.15  1995/11/08  17:28:03  allender
24  * add PC gauges to gauge list of non-substitutatble bitmaps
25  *
26  * Revision 1.14  1995/11/08  15:14:49  allender
27  * fixed horrible bug where the piggy cache size was incorrect
28  * for mac shareware
29  *
30  * Revision 1.13  1995/11/03  12:53:37  allender
31  * shareware changes
32  *
33  * Revision 1.12  1995/10/21  22:25:14  allender
34  * added bald guy cheat
35  *
36  * Revision 1.11  1995/10/20  22:42:15  allender
37  * changed load path of descent.pig to :data:descent.pig
38  *
39  * Revision 1.10  1995/10/20  00:08:01  allender
40  * put in event loop calls when loading data (hides it nicely
41  * from user) so TM can get it's strokes stuff
42  *
43  * Revision 1.9  1995/09/13  08:48:01  allender
44  * added lower memory requirement to load alternate bitmaps
45  *
46  * Revision 1.8  1995/08/16  09:39:13  allender
47  * moved "loading" text up a little
48  *
49  * Revision 1.7  1995/08/08  13:54:26  allender
50  * added macsys header file
51  *
52  * Revision 1.6  1995/07/12  12:49:56  allender
53  * total hack for bitmaps > 512 bytes wide -- check these by name
54  *
55  * Revision 1.5  1995/07/05  16:47:05  allender
56  * kitchen stuff
57  *
58  * Revision 1.4  1995/06/23  08:55:28  allender
59  * make "loading data" text y loc based off of curcanv
60  *
61  * Revision 1.3  1995/06/08  14:08:52  allender
62  * PPC aligned data sets
63  *
64  * Revision 1.2  1995/05/26  06:54:27  allender
65  * removed refences to sound data at end of pig file (since they will
66  * now be Macintosh snd resources for effects
67  *
68  * Revision 1.1  1995/05/16  15:29:51  allender
69  * Initial revision
70  *
71  * Revision 2.10  1995/10/07  13:17:26  john
72  * Made all bitmaps paged out by default.
73  *
74  * Revision 2.9  1995/04/14  14:05:24  john
75  * *** empty log message ***
76  *
77  * Revision 2.8  1995/04/12  13:39:37  john
78  * Fixed bug with -lowmem not working.
79  *
80  * Revision 2.7  1995/03/29  23:23:17  john
81  * Fixed major bug with sounds not building into pig right.
82  *
83  * Revision 2.6  1995/03/28  18:05:00  john
84  * Fixed it so you don't have to delete pig after changing bitmaps.tbl
85  *
86  * Revision 2.5  1995/03/16  23:13:06  john
87  * Fixed bug with piggy paging in bitmap not checking for disk
88  * error, hence bogifying textures if you pull the CD out.
89  *
90  * Revision 2.4  1995/03/14  16:22:27  john
91  * Added cdrom alternate directory stuff.
92  *
93  * Revision 2.3  1995/03/06  15:23:20  john
94  * New screen techniques.
95  *
96  * Revision 2.2  1995/02/27  13:13:40  john
97  * Removed floating point.
98  *
99  * Revision 2.1  1995/02/27  12:31:25  john
100  * Made work without editor.
101  *
102  * Revision 2.0  1995/02/27  11:28:02  john
103  * New version 2.0, which has no anonymous unions, builds with
104  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
105  *
106  * Revision 1.85  1995/02/09  12:54:24  john
107  * Made paged out bitmaps have bm_data be a valid pointer
108  * instead of NULL, in case anyone accesses it.
109  *
110  * Revision 1.84  1995/02/09  12:50:59  john
111  * Bullet-proofed the piggy loading code.
112  *
113  * Revision 1.83  1995/02/07  17:08:51  john
114  * Added some error handling stuff instead of asserts.
115  *
116  * Revision 1.82  1995/02/03  17:06:48  john
117  * Changed sound stuff to allow low memory usage.
118  * Also, changed so that Sounds isn't an array of digi_sounds, it
119  * is a ubyte pointing into GameSounds, this way the digi.c code that
120  * locks sounds won't accidentally unlock a sound that is already playing, but
121  * since it's Sounds[soundno] is different, it would erroneously be unlocked.
122  *
123  * Revision 1.81  1995/02/02  21:56:39  matt
124  * Added data for new gauge bitmaps
125  *
126  * Revision 1.80  1995/02/01  23:31:57  john
127  * Took out loading bar.
128  *
129  * Revision 1.79  1995/01/28  15:13:18  allender
130  * bumped up Piggy_bitmap_cache_size
131  *
132  * Revision 1.78  1995/01/26  12:30:43  john
133  * Took out prev.
134  *
135  * Revision 1.77  1995/01/26  12:12:17  john
136  * Made buffer be big for bitmaps.
137  *
138  * Revision 1.76  1995/01/25  20:15:38  john
139  * Made editor allocate all mem.
140  *
141  * Revision 1.75  1995/01/25  14:52:56  john
142  * Made bitmap buffer be 1.5 MB.
143  *
144  * Revision 1.74  1995/01/22  16:03:19  mike
145  * localization.
146  *
147  * Revision 1.73  1995/01/22  15:58:36  mike
148  * localization
149  *
150  * Revision 1.72  1995/01/18  20:51:20  john
151  * Took out warnings.
152  *
153  * Revision 1.71  1995/01/18  20:47:21  john
154  * Added code to allocate sounds & bitmaps into diff
155  * buffers, also made sounds not be compressed for registered.
156  *
157  * Revision 1.70  1995/01/18  15:08:41  john
158  * Added start/stop time around paging.
159  * Made paging clear screen around globe.
160  *
161  * Revision 1.69  1995/01/18  10:07:51  john
162  *
163  * Took out debugging mprintfs.
164  *
165  * Revision 1.68  1995/01/17  14:27:42  john
166  * y
167  *
168  * Revision 1.67  1995/01/17  12:14:39  john
169  * Made walls, object explosion vclips load at level start.
170  *
171  * Revision 1.66  1995/01/15  13:15:44  john
172  * Made so that paging always happens, lowmem just loads less.
173  * Also, make KB load print to hud.
174  *
175  * Revision 1.65  1995/01/15  11:56:28  john
176  * Working version of paging.
177  *
178  * Revision 1.64  1995/01/14  19:17:07  john
179  * First version of new bitmap paging code.
180  *
181  * Revision 1.63  1994/12/15  12:26:44  john
182  * Added -nolowmem function.
183  *
184  * Revision 1.62  1994/12/14  21:12:26  john
185  * Fixed bug with page fault when exiting and using
186  * -nosound.
187  *
188  * Revision 1.61  1994/12/14  11:35:31  john
189  * Evened out thermometer for pig read.
190  *
191  * Revision 1.60  1994/12/14  10:51:00  john
192  * Sped up sound loading.
193  *
194  * Revision 1.59  1994/12/14  10:12:08  john
195  * Sped up pig loading.
196  *
197  * Revision 1.58  1994/12/13  09:14:47  john
198  * *** empty log message ***
199  *
200  * Revision 1.57  1994/12/13  09:12:57  john
201  * Made the bar always fill up.
202  *
203  * Revision 1.56  1994/12/13  03:49:08  john
204  * Made -lowmem not load the unnecessary bitmaps.
205  *
206  * Revision 1.55  1994/12/06  16:06:35  john
207  * Took out piggy sorting.
208  *
209  * Revision 1.54  1994/12/06  15:11:14  john
210  * Fixed bug with reading pigs.
211  *
212  * Revision 1.53  1994/12/06  14:14:47  john
213  * Added code to set low mem based on memory.
214  *
215  * Revision 1.52  1994/12/06  14:01:10  john
216  * Fixed bug that was causing -lowmem all the time..
217  *
218  * Revision 1.51  1994/12/06  13:33:48  john
219  * Added lowmem option.
220  *
221  * Revision 1.50  1994/12/05  19:40:10  john
222  * If -nosound or no sound card selected, don't load sounds from pig.
223  *
224  * Revision 1.49  1994/12/05  12:17:44  john
225  * Added code that locks/unlocks digital sounds on demand.
226  *
227  * Revision 1.48  1994/12/05  11:39:03  matt
228  * Fixed little mistake
229  *
230  * Revision 1.47  1994/12/05  09:29:22  john
231  * Added clength to the sound field.
232  *
233  * Revision 1.46  1994/12/04  15:27:15  john
234  * Fixed my stupid bug that looked at -nosound instead of digi_driver_card
235  * to see whether or not to lock down sound memory.
236  *
237  * Revision 1.45  1994/12/03  14:17:00  john
238  * Took out my debug mprintf.
239  *
240  * Revision 1.44  1994/12/03  13:32:37  john
241  * Fixed bug with offscreen bitmap.
242  *
243  * Revision 1.43  1994/12/03  13:07:13  john
244  * Made the pig read/write compressed sounds.
245  *
246  * Revision 1.42  1994/12/03  11:48:51  matt
247  * Added option to not dump sounds to pigfile
248  *
249  * Revision 1.41  1994/12/02  20:02:20  matt
250  * Made sound files constant match constant for table
251  *
252  * Revision 1.40  1994/11/29  11:03:09  adam
253  * upped # of sounds
254  *
255  * Revision 1.39  1994/11/27  23:13:51  matt
256  * Made changes for new mprintf calling convention
257  *
258  * Revision 1.38  1994/11/20  18:40:34  john
259  * MAde the piggy.lst and piggy.all not dump for release.
260  *
261  * Revision 1.37  1994/11/19  23:54:45  mike
262  * up number of bitmaps for shareware version.
263  *
264  * Revision 1.36  1994/11/19  19:53:05  mike
265  * change MAX_BITMAP_FILES
266  *
267  * Revision 1.35  1994/11/19  10:42:56  matt
268  * Increased number of bitmaps for non-shareware version
269  *
270  * Revision 1.34  1994/11/19  09:11:52  john
271  * Added avg_color to bitmaps saved in pig.
272  *
273  * Revision 1.33  1994/11/19  00:07:05  john
274  * Fixed bug with 8 char sound filenames not getting read from pig.
275  *
276  * Revision 1.32  1994/11/18  22:24:54  john
277  * Added -bigpig command line that doesn't rle your pig.
278  *
279  * Revision 1.31  1994/11/18  21:56:53  john
280  * Added a better, leaner pig format.
281  *
282  * Revision 1.30  1994/11/16  12:06:16  john
283  * Fixed bug with calling .bbms abms.
284  *
285  * Revision 1.29  1994/11/16  12:00:56  john
286  * Added piggy.all dump.
287  *
288  * Revision 1.28  1994/11/10  21:16:02  adam
289  * nothing important
290  *
291  * Revision 1.27  1994/11/10  13:42:00  john
292  * Made sounds not lock down if using -nosound.
293  *
294  * Revision 1.26  1994/11/09  19:55:40  john
295  * Added full rle support with texture rle caching.
296  *
297  * Revision 1.25  1994/11/09  16:36:42  john
298  * First version with RLE bitmaps in Pig.
299  *
300  * Revision 1.24  1994/10/27  19:42:59  john
301  * Disable the piglet option.
302  *
303  * Revision 1.23  1994/10/27  18:51:40  john
304  * Added -piglet option that only loads needed textures for a
305  * mine.  Only saved ~1MB, and code still doesn't free textures
306  * before you load a new mine.
307  *
308  * Revision 1.22  1994/10/25  13:11:42  john
309  * Made the sounds sort. Dumped piggy.lst.
310  *
311  * Revision 1.21  1994/10/06  17:06:23  john
312  * Took out rle stuff.
313  *
314  * Revision 1.20  1994/10/06  15:45:36  adam
315  * bumped MAX_BITMAP_FILES again!
316  *
317  * Revision 1.19  1994/10/06  11:01:17  yuan
318  * Upped MAX_BITMAP_FILES
319  *
320  * Revision 1.18  1994/10/06  10:44:45  john
321  * Added diagnostic message and psuedo run-length-encoder
322  * to see how much memory we would save by storing bitmaps
323  * in a RLE method.  Also, I commented out the code that
324  * stores 4K bitmaps on a 4K boundry to reduce pig size
325  * a bit.
326  *
327  * Revision 1.17  1994/10/04  20:03:13  matt
328  * Upped maximum number of bitmaps
329  *
330  * Revision 1.16  1994/10/03  18:04:20  john
331  * Fixed bug with data_offset not set right for bitmaps
332  * that are 64x64 and not aligned on a 4k boundry.
333  *
334  * Revision 1.15  1994/09/28  11:30:55  john
335  * changed inferno.pig to descent.pig, changed the way it
336  * is read.
337  *
338  * Revision 1.14  1994/09/22  16:14:17  john
339  * Redid intro sequecing.
340  *
341  * Revision 1.13  1994/09/19  14:42:47  john
342  * Locked down sounds with Virtual memory.
343  *
344  * Revision 1.12  1994/09/10  17:31:52  mike
345  * Increase number of loadable bitmaps.
346  *
347  * Revision 1.11  1994/09/01  19:32:49  mike
348  * Boost texture map allocation.
349  *
350  * Revision 1.10  1994/08/16  11:51:02  john
351  * Added grwased pigs.
352  *
353  * Revision 1.9  1994/07/06  09:18:03  adam
354  * upped bitmap #s
355  *
356  * Revision 1.8  1994/06/20  22:02:15  matt
357  * Fixed bug from last change
358  *
359  * Revision 1.7  1994/06/20  21:33:18  matt
360  * Made bm.h not include sounds.h, to reduce dependencies
361  *
362  * Revision 1.6  1994/06/20  16:52:19  john
363  * cleaned up init output a bit.
364  *
365  * Revision 1.5  1994/06/08  14:20:57  john
366  * Made piggy dump before going into game.
367  *
368  * Revision 1.4  1994/06/02  18:59:22  matt
369  * Clear selector field of bitmap loaded from pig file
370  *
371  * Revision 1.3  1994/05/06  15:31:41  john
372  * Made name field a bit longer.
373  *
374  * Revision 1.2  1994/05/06  13:02:44  john
375  * Added piggy stuff; worked on supertransparency
376  *
377  * Revision 1.1  1994/05/06  11:47:26  john
378  * Initial revision
379  *
380  *
381  */
382
383
384 #ifdef HAVE_CONFIG_H
385 #include <conf.h>
386 #endif
387
388 #ifdef RCS
389 static char rcsid[] = "$Id: piggy.c,v 1.31 2003-03-29 22:35:00 btb Exp $";
390 #endif
391
392
393 #include <stdio.h>
394 #include <string.h>
395
396 #include "pstypes.h"
397 #include "strutil.h"
398 #include "inferno.h"
399 #include "gr.h"
400 #include "u_mem.h"
401 #include "iff.h"
402 #include "mono.h"
403 #include "error.h"
404 #include "sounds.h"
405 #include "songs.h"
406 #include "bm.h"
407 #include "bmread.h"
408 #include "hash.h"
409 #include "args.h"
410 #include "palette.h"
411 #include "gamefont.h"
412 #include "rle.h"
413 #include "screens.h"
414 #include "piggy.h"
415 #include "texmerge.h"
416 #include "paging.h"
417 #include "game.h"
418 #include "text.h"
419 #include "cfile.h"
420 #include "newmenu.h"
421 #include "byteswap.h"
422 #include "findfile.h"
423 #include "makesig.h"
424
425 #ifndef MACINTOSH
426 //      #include "unarj.h"
427 #else
428         #include <Strings.h>            // MacOS Toolbox header
429         #include <Files.h>
430         #include <unistd.h>
431 #endif
432
433 //#define NO_DUMP_SOUNDS        1   //if set, dump bitmaps but not sounds
434
435 #define DEFAULT_PIGFILE_REGISTERED      "groupa.pig"
436 #define DEFAULT_PIGFILE_SHAREWARE       "d2demo.pig"
437 #define DEFAULT_HAMFILE_REGISTERED      "descent2.ham"
438 #define DEFAULT_HAMFILE_SHAREWARE       "d2demo.ham"
439
440 #define D1_PALETTE "palette.256"
441
442 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
443 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
444 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
445
446 #define MAC_ALIEN1_PIGSIZE      5013035
447 #define MAC_ALIEN2_PIGSIZE      4909916
448 #define MAC_FIRE_PIGSIZE        4969035
449 #define MAC_GROUPA_PIGSIZE      4929684 // also used for mac shareware
450 #define MAC_ICE_PIGSIZE         4923425
451 #define MAC_WATER_PIGSIZE       4832403
452
453 ubyte *BitmapBits = NULL;
454 ubyte *SoundBits = NULL;
455
456 typedef struct BitmapFile {
457         char    name[15];
458 } BitmapFile;
459
460 typedef struct SoundFile {
461         char    name[15];
462 } SoundFile;
463
464 hashtable AllBitmapsNames;
465 hashtable AllDigiSndNames;
466
467 int Num_bitmap_files = 0;
468 int Num_sound_files = 0;
469
470 digi_sound GameSounds[MAX_SOUND_FILES];
471 int SoundOffset[MAX_SOUND_FILES];
472 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
473
474 alias alias_list[MAX_ALIASES];
475 int Num_aliases=0;
476
477 int Must_write_hamfile = 0;
478 int Num_bitmap_files_new = 0;
479 int Num_sound_files_new = 0;
480 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
481 static SoundFile AllSounds[ MAX_SOUND_FILES ];
482
483 int Piggy_hamfile_version = 0;
484
485 int piggy_low_memory = 0;
486
487 int Piggy_bitmap_cache_size = 0;
488 int Piggy_bitmap_cache_next = 0;
489 ubyte * Piggy_bitmap_cache_data = NULL;
490 static int GameBitmapOffset[MAX_BITMAP_FILES];
491 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
492 ushort GameBitmapXlat[MAX_BITMAP_FILES];
493
494 #define PIGGY_BUFFER_SIZE (2400*1024)
495
496 #ifdef MACINTOSH
497 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024)             // size of buffer when piggy_low_memory is set
498
499 #ifdef SHAREWARE
500 #undef PIGGY_BUFFER_SIZE
501 #undef PIGGY_SMALL_BUFFER_SIZE
502
503 #define PIGGY_BUFFER_SIZE (2000*1024)
504 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
505 #endif          // SHAREWARE
506
507 #endif
508
509 int piggy_page_flushed = 0;
510
511 #define DBM_FLAG_ABM            64
512
513 ubyte BigPig = 0;
514
515 #ifdef MACINTOSH
516         extern short    cd_VRefNum;
517         extern void             ConcatPStr(StringPtr dst, StringPtr src);
518         extern int              ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
519         extern int              ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
520 #endif
521
522 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
523
524 #ifdef EDITOR
525 void piggy_write_pigfile(char *filename);
526 static void write_int(int i,FILE *file);
527 #endif
528
529 void swap_0_255(grs_bitmap *bmp)
530 {
531         int i;
532
533         for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
534                 if(bmp->bm_data[i] == 0)
535                         bmp->bm_data[i] = 255;
536                 else if (bmp->bm_data[i] == 255)
537                         bmp->bm_data[i] = 0;
538         }
539 }
540
541 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
542 {
543         bitmap_index temp;
544         Assert( Num_bitmap_files < MAX_BITMAP_FILES );
545
546         temp.index = Num_bitmap_files;
547
548         if (!in_file)   {
549 #ifdef EDITOR
550                 if ( FindArg("-macdata") )
551                         swap_0_255( bmp );
552 #endif
553                 if ( !BigPig )  gr_bitmap_rle_compress( bmp );
554                 Num_bitmap_files_new++;
555         }
556
557         strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
558         hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
559         GameBitmaps[Num_bitmap_files] = *bmp;
560         if ( !in_file ) {
561                 GameBitmapOffset[Num_bitmap_files] = 0;
562                 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
563         }
564         Num_bitmap_files++;
565
566         return temp;
567 }
568
569 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
570 {
571         int i;
572
573         Assert( Num_sound_files < MAX_SOUND_FILES );
574
575         strncpy( AllSounds[Num_sound_files].name, name, 12 );
576         hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
577         GameSounds[Num_sound_files] = *snd;
578         if ( !in_file ) {
579                 SoundOffset[Num_sound_files] = 0;       
580         }
581
582         i = Num_sound_files;
583    
584         if (!in_file)
585                 Num_sound_files_new++;
586
587         Num_sound_files++;
588         return i;
589 }
590
591 bitmap_index piggy_find_bitmap( char * name )   
592 {
593         bitmap_index bmp;
594         int i;
595         char *t;
596
597         bmp.index = 0;
598
599         if ((t=strchr(name,'#'))!=NULL)
600                 *t=0;
601
602         for (i=0;i<Num_aliases;i++)
603                 if (stricmp(name,alias_list[i].alias_name)==0) {
604                         if (t) {                //extra stuff for ABMs
605                                 static char temp[FILENAME_LEN];
606                                 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
607                                 name = temp;
608                                 strcat(name,"#");
609                                 strcat(name,t+1);
610                         }
611                         else
612                                 name=alias_list[i].file_name; 
613                         break;
614                 }
615
616         if (t)
617                 *t = '#';
618
619         i = hashtable_search( &AllBitmapsNames, name );
620         Assert( i != 0 );
621         if ( i < 0 )
622                 return bmp;
623
624         bmp.index = i;
625         return bmp;
626 }
627
628 int piggy_find_sound( char * name )     
629 {
630         int i;
631
632         i = hashtable_search( &AllDigiSndNames, name );
633
634         if ( i < 0 )
635                 return 255;
636
637         return i;
638 }
639
640 CFILE * Piggy_fp = NULL;
641
642 #define FILENAME_LEN 13
643
644 char Current_pigfile[FILENAME_LEN] = "";
645
646 void piggy_close_file()
647 {
648         if ( Piggy_fp ) {
649                 cfclose( Piggy_fp );
650                 Piggy_fp        = NULL;
651                 Current_pigfile[0] = 0;
652         }
653 }
654
655 int Pigfile_initialized=0;
656
657 #define PIGFILE_ID              MAKE_SIG('G','I','P','P') //PPIG
658 #define PIGFILE_VERSION         2
659
660 extern char CDROM_dir[];
661
662 int request_cd(void);
663
664
665 #ifdef MACINTOSH
666
667 //copies a pigfile from the CD to the current dir
668 //retuns file handle of new pig
669 CFILE *copy_pigfile_from_cd(char *filename)             // MACINTOSH VERSION
670 {
671         // C Stuff
672         char                    sourcePathAndFileCStr[255] = "";
673         char                    destPathAndFileCStr[255]        = "";
674         FILEFINDSTRUCT  find;
675         FILE*                   sourceFile      = NULL;
676         FILE*                   destFile        = NULL;
677         const int               BUF_SIZE = 4096;
678         ubyte                   buf[BUF_SIZE];
679
680         // Mac Stuff
681         Str255                  sourcePathAndFilePStr = "\p";
682         Str255                  destPathAndFilePStr = "\p";
683         Str255                  pigfileNamePStr = "\p";
684         HParamBlockRec  theSourcePigHFSParams;
685         HParamBlockRec  theDestPigHFSParams;
686         OSErr                   theErr = noErr;
687         char                    oldDirCStr[255] = "";
688
689         getcwd(oldDirCStr, 255);
690         
691         show_boxed_message("Copying bitmap data from CD...");
692         gr_palette_load(gr_palette);    //I don't think this line is really needed
693
694         chdir(":Data");
695         //First, delete all PIG files currently in the directory
696         if( !FileFindFirst( "*.pig", &find ) )
697         {
698                 do
699                 {
700                         remove(find.name);
701                 } while( !FileFindNext( &find ) );
702                 
703                 FileFindClose();
704         }
705         chdir(oldDirCStr);
706
707         //Now, copy over new pig
708         songs_stop_redbook();           //so we can read off the cd
709
710         // make the source path "<cd volume>:Data:filename.pig"
711 //MWA   ConvertCToPStr(filename, pigfileNamePStr);
712
713 //MWA   ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:");        // volume ID is cd_VRefNum
714 //MWA   ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
715
716         strupr(filename);
717         strcpy(sourcePathAndFileCStr, "Descent II:Data:");
718         strcat(sourcePathAndFileCStr, filename);
719         
720         // make the destination path "<default directory>:Data:filename.pig"
721 //MWA   ConcatPStr(destPathAndFilePStr, "\p:Data:");
722 //MWA   ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
723 //MWA   ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
724 //MWA   ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
725
726         strcpy(destPathAndFileCStr, ":Data:");
727         strcat(destPathAndFileCStr, filename);
728
729         strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
730         strcpy(destPathAndFilePStr, destPathAndFileCStr);
731         c2pstr(sourcePathAndFilePStr);
732         c2pstr(destPathAndFilePStr);
733         
734         do {
735                 // Open the source file
736                 sourceFile = fopen(sourcePathAndFileCStr,"rb");
737
738                 if (!sourceFile) {
739
740                         if (request_cd() == -1)
741                                 Error("Cannot load file <%s> from CD",filename);
742                 }
743
744         } while (!sourceFile);
745
746
747         // Get the time stamp from the source file
748         theSourcePigHFSParams.fileParam.ioCompletion    = nil;
749         theSourcePigHFSParams.fileParam.ioNamePtr               = sourcePathAndFilePStr;
750         theSourcePigHFSParams.fileParam.ioVRefNum               = cd_VRefNum;
751         theSourcePigHFSParams.fileParam.ioFDirIndex     = 0;
752         theSourcePigHFSParams.fileParam.ioDirID         = 0;
753         
754         theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
755         if (theErr != noErr)
756         {
757                 // Error getting file time stamp!! Why? JTS
758                 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
759         }
760         
761         // Copy the file over
762         // C Stuff......
763         
764         // Open the destination file
765         destFile = fopen(destPathAndFileCStr,"wb");
766         if (!destFile)
767         {
768                 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
769         }
770         
771         // Copy bytes until the end of the source file
772         while (!feof(sourceFile))
773         {
774                 int bytes_read;
775                 int x;
776
777                 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
778                 if (ferror(sourceFile))
779                         Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
780
781 // Assert is bogus              Assert(bytes_read == BUF_SIZE || feof(sourceFile));
782
783                 fwrite(buf,1,bytes_read,destFile);
784                 if (ferror(destFile))
785                         Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
786         }
787
788         // close the source/dest files
789         if (fclose(sourceFile))
790                 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
791         if (fclose(destFile))
792                 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
793
794         // Get the current hfs data for the new file
795         theDestPigHFSParams.fileParam.ioCompletion      = nil;
796         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
797         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
798         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
799         theDestPigHFSParams.fileParam.ioDirID           = 0;
800         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
801         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
802         {
803                 // Error getting file time stamp!! Why? JTS
804                 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
805         }
806
807         // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
808         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
809         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
810         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
811         theDestPigHFSParams.fileParam.ioDirID           = 0;
812
813         // Copy the time stamp from the source file info
814         theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
815         theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
816         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
817         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
818         
819         // Set the dest file's time stamp to the source file's time stamp values
820         theErr = PBHSetFInfo(&theDestPigHFSParams, false);
821
822         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
823         {
824                 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
825         }
826
827         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
828
829         return cfopen(destPathAndFileCStr, "rb");
830 }
831
832 #else   //PC Version of copy_pigfile_from_cd is below
833
834 //copies a pigfile from the CD to the current dir
835 //retuns file handle of new pig
836 CFILE *copy_pigfile_from_cd(char *filename)
837 {
838         char name[80];
839         FILEFINDSTRUCT find;
840         int ret;
841
842         return cfopen(filename, "rb");
843         show_boxed_message("Copying bitmap data from CD...");
844         gr_palette_load(gr_palette);    //I don't think this line is really needed
845
846         //First, delete all PIG files currently in the directory
847
848         if( !FileFindFirst( "*.pig", &find ) ) {
849                 do      {
850                         remove(find.name);
851                 } while( !FileFindNext( &find ) );
852                 FileFindClose();
853         }
854
855         //Now, copy over new pig
856
857         songs_stop_redbook();           //so we can read off the cd
858
859         //new code to unarj file
860         strcpy(name,CDROM_dir);
861         strcat(name,"descent2.sow");
862
863         do {
864 //              ret = unarj_specific_file(name,filename,filename);
865 // DPH:FIXME
866
867                 ret = !EXIT_SUCCESS;
868
869                 if (ret != EXIT_SUCCESS) {
870
871                         //delete file, so we don't leave partial file
872                         remove(filename);
873
874                         #ifndef MACINTOSH
875                         if (request_cd() == -1)
876                         #endif
877                                 //NOTE LINK TO ABOVE IF
878                                 Error("Cannot load file <%s> from CD",filename);
879                 }
880
881         } while (ret != EXIT_SUCCESS);
882
883         return cfopen(filename, "rb");
884 }
885
886 #endif // end of ifdef MAC around copy_pigfile_from_cd
887
888 //initialize a pigfile, reading headers
889 //returns the size of all the bitmap data
890 void piggy_init_pigfile(char *filename)
891 {
892         int i;
893         char temp_name[16];
894         char temp_name_read[16];
895         grs_bitmap temp_bitmap;
896         DiskBitmapHeader bmh;
897         int header_size, N_bitmaps, data_size, data_start;
898         #ifdef MACINTOSH
899         char name[255];         // filename + path for the mac
900         #endif
901
902         piggy_close_file();             //close old pig if still open
903
904         //rename pigfile for shareware
905         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
906                 filename = DEFAULT_PIGFILE_SHAREWARE;
907
908         #ifndef MACINTOSH
909                 Piggy_fp = cfopen( filename, "rb" );
910         #else
911                 sprintf(name, ":Data:%s", filename);
912                 Piggy_fp = cfopen( name, "rb" );
913
914                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
915                         if (Piggy_fp == NULL)
916                         {
917                                 Error("Cannot load required file <%s>",name);
918                         }
919                 #endif  // end of if def shareware
920
921         #endif
922
923         if (!Piggy_fp) {
924                 #ifdef EDITOR
925                         return;         //if editor, ok to not have pig, because we'll build one
926                 #else
927                         Piggy_fp = copy_pigfile_from_cd(filename);
928                 #endif
929         }
930
931         if (Piggy_fp) {                         //make sure pig is valid type file & is up-to-date
932                 int pig_id,pig_version;
933
934                 pig_id = cfile_read_int(Piggy_fp);
935                 pig_version = cfile_read_int(Piggy_fp);
936                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
937                         cfclose(Piggy_fp);              //out of date pig
938                         Piggy_fp = NULL;                        //..so pretend it's not here
939                 }
940         }
941
942         if (!Piggy_fp) {
943
944                 #ifdef EDITOR
945                         return;         //if editor, ok to not have pig, because we'll build one
946                 #else
947                         Error("Cannot load required file <%s>",filename);
948                 #endif
949         }
950
951         strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
952
953         N_bitmaps = cfile_read_int(Piggy_fp);
954
955         header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
956
957         data_start = header_size + cftell(Piggy_fp);
958
959         data_size = cfilelength(Piggy_fp) - data_start;
960
961         Num_bitmap_files = 1;
962
963         for (i=0; i<N_bitmaps; i++ )    {
964                 DiskBitmapHeader_read(&bmh, Piggy_fp);
965                 memcpy( temp_name_read, bmh.name, 8 );
966                 temp_name_read[8] = 0;
967                 if ( bmh.dflags & DBM_FLAG_ABM )        
968                         sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
969                 else
970                         strcpy( temp_name, temp_name_read );
971                 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
972                 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
973                 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
974                 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
975                 temp_bitmap.avg_color = bmh.avg_color;
976                 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
977
978                 GameBitmapFlags[i+1] = 0;
979                 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
980                 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
981                 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
982                 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
983                 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
984
985                 GameBitmapOffset[i+1] = bmh.offset + data_start;
986                 Assert( (i+1) == Num_bitmap_files );
987                 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
988         }
989
990 #ifdef EDITOR
991         Piggy_bitmap_cache_size = data_size + (data_size/10);   //extra mem for new bitmaps
992         Assert( Piggy_bitmap_cache_size > 0 );
993 #else
994         Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
995         #ifdef MACINTOSH
996         if (piggy_low_memory)
997                 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
998         #endif
999 #endif
1000         BitmapBits = d_malloc( Piggy_bitmap_cache_size );
1001         if ( BitmapBits == NULL )
1002                 Error( "Not enough memory to load bitmaps\n" );
1003         Piggy_bitmap_cache_data = BitmapBits;
1004         Piggy_bitmap_cache_next = 0;
1005
1006         #if defined(MACINTOSH) && defined(SHAREWARE)
1007 //      load_exit_models();
1008         #endif
1009
1010         Pigfile_initialized=1;
1011 }
1012
1013 #define FILENAME_LEN 13
1014 #define MAX_BITMAPS_PER_BRUSH 30
1015
1016 extern int compute_average_pixel(grs_bitmap *new);
1017
1018 //reads in a new pigfile (for new palette)
1019 //returns the size of all the bitmap data
1020 void piggy_new_pigfile(char *pigname)
1021 {
1022         int i;
1023         char temp_name[16];
1024         char temp_name_read[16];
1025         grs_bitmap temp_bitmap;
1026         DiskBitmapHeader bmh;
1027         int header_size, N_bitmaps, data_size, data_start;
1028         int must_rewrite_pig = 0;
1029         #ifdef MACINTOSH
1030         char name[255];
1031         #endif
1032
1033         strlwr(pigname);
1034
1035         //rename pigfile for shareware
1036         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
1037                 pigname = DEFAULT_PIGFILE_SHAREWARE;
1038
1039         if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
1040                 return;         //already have correct pig
1041
1042         if (!Pigfile_initialized) {                     //have we ever opened a pigfile?
1043                 piggy_init_pigfile(pigname);            //..no, so do initialization stuff
1044                 return;
1045         }
1046         else
1047                 piggy_close_file();             //close old pig if still open
1048
1049         Piggy_bitmap_cache_next = 0;            //free up cache
1050
1051         strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
1052
1053         #ifndef MACINTOSH
1054                 Piggy_fp = cfopen( pigname, "rb" );
1055         #else
1056                 sprintf(name, ":Data:%s", pigname);
1057                 Piggy_fp = cfopen( name, "rb" );
1058
1059                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
1060                         if (Piggy_fp == NULL)
1061                         {
1062                                 Error("Cannot load required file <%s>",name);
1063                         }
1064                 #endif  // end of if def shareware
1065         #endif
1066
1067         #ifndef EDITOR
1068         if (!Piggy_fp)
1069                 Piggy_fp = copy_pigfile_from_cd(pigname);
1070         #endif
1071
1072         if (Piggy_fp) {  //make sure pig is valid type file & is up-to-date
1073                 int pig_id,pig_version;
1074
1075                 pig_id = cfile_read_int(Piggy_fp);
1076                 pig_version = cfile_read_int(Piggy_fp);
1077                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
1078                         cfclose(Piggy_fp);              //out of date pig
1079                         Piggy_fp = NULL;                        //..so pretend it's not here
1080                 }
1081         }
1082
1083         #ifndef EDITOR
1084         if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
1085         #endif
1086
1087         if (Piggy_fp) {
1088
1089                 N_bitmaps = cfile_read_int(Piggy_fp);
1090
1091                 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
1092
1093                 data_start = header_size + cftell(Piggy_fp);
1094
1095                 data_size = cfilelength(Piggy_fp) - data_start;
1096
1097                 for (i=1; i<=N_bitmaps; i++ )   {
1098                         DiskBitmapHeader_read(&bmh, Piggy_fp);
1099                         memcpy( temp_name_read, bmh.name, 8 );
1100                         temp_name_read[8] = 0;
1101         
1102                         if ( bmh.dflags & DBM_FLAG_ABM )        
1103                                 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
1104                         else
1105                                 strcpy( temp_name, temp_name_read );
1106         
1107                         //Make sure name matches
1108                         if (strcmp(temp_name,AllBitmaps[i].name)) {
1109                                 //Int3();       //this pig is out of date.  Delete it
1110                                 must_rewrite_pig=1;
1111                         }
1112         
1113                         strcpy(AllBitmaps[i].name,temp_name);
1114
1115                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1116         
1117                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1118                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1119                         temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
1120                         temp_bitmap.avg_color = bmh.avg_color;
1121                         temp_bitmap.bm_data = Piggy_bitmap_cache_data;
1122
1123                         GameBitmapFlags[i] = 0;
1124
1125                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
1126                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
1127                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
1128                         if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
1129                         if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
1130         
1131                         GameBitmapOffset[i] = bmh.offset + data_start;
1132         
1133                         GameBitmaps[i] = temp_bitmap;
1134                 }
1135         }
1136         else
1137                 N_bitmaps = 0;          //no pigfile, so no bitmaps
1138
1139         #ifndef EDITOR
1140
1141         Assert(N_bitmaps == Num_bitmap_files-1);
1142
1143         #else
1144
1145         if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
1146                 int size;
1147
1148                 //re-read the bitmaps that aren't in this pig
1149
1150                 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
1151                         char *p;
1152
1153                         p = strchr(AllBitmaps[i].name,'#');
1154
1155                         if (p) {                //this is an ABM
1156                                 char abmname[FILENAME_LEN];
1157                                 int fnum;
1158                                 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
1159                                 int iff_error;          //reference parm to avoid warning message
1160                                 ubyte newpal[768];
1161                                 char basename[FILENAME_LEN];
1162                                 int nframes;
1163                         
1164                                 strcpy(basename,AllBitmaps[i].name);
1165                                 basename[p-AllBitmaps[i].name] = 0;             //cut off "#nn" part
1166                                 
1167                                 sprintf( abmname, "%s.abm", basename );
1168
1169                                 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
1170
1171                                 if (iff_error != IFF_NO_ERROR)  {
1172                                         mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
1173                                         Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
1174                                 }
1175                         
1176                                 for (fnum=0;fnum<nframes; fnum++)       {
1177                                         char tempname[20];
1178                                         int SuperX;
1179
1180                                         sprintf( tempname, "%s#%d", basename, fnum );
1181
1182                                         //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1183                                         SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1184                                         //above makes assumption that supertransparent color is 254
1185
1186                                         if ( iff_has_transparency )
1187                                                 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
1188                                         else
1189                                                 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
1190
1191                                         bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
1192
1193 #ifdef EDITOR
1194                                         if ( FindArg("-macdata") )
1195                                                 swap_0_255( bm[fnum] );
1196 #endif
1197                                         if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
1198
1199                                         if (bm[fnum]->bm_flags & BM_FLAG_RLE)
1200                                                 size = *((int *) bm[fnum]->bm_data);
1201                                         else
1202                                                 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
1203
1204                                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
1205                                         d_free(bm[fnum]->bm_data);
1206                                         bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1207                                         Piggy_bitmap_cache_next += size;
1208
1209                                         GameBitmaps[i+fnum] = *bm[fnum];
1210
1211                                         // -- mprintf( (0, "U" ));
1212                                         d_free( bm[fnum] );
1213                                 }
1214
1215                                 i += nframes-1;         //filled in multiple bitmaps
1216                         }
1217                         else {          //this is a BBM
1218
1219                                 grs_bitmap * new;
1220                                 ubyte newpal[256*3];
1221                                 int iff_error;
1222                                 char bbmname[FILENAME_LEN];
1223                                 int SuperX;
1224
1225                                 MALLOC( new, grs_bitmap, 1 );
1226
1227                                 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
1228                                 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
1229
1230                                 new->bm_handle=0;
1231                                 if (iff_error != IFF_NO_ERROR)          {
1232                                         mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
1233                                         Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
1234                                 }
1235
1236                                 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1237                                 //above makes assumption that supertransparent color is 254
1238
1239                                 if ( iff_has_transparency )
1240                                         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
1241                                 else
1242                                         gr_remap_bitmap_good( new, newpal, -1, SuperX );
1243
1244                                 new->avg_color = compute_average_pixel(new);
1245
1246 #ifdef EDITOR
1247                                 if ( FindArg("-macdata") )
1248                                         swap_0_255( new );
1249 #endif
1250                                 if ( !BigPig )  gr_bitmap_rle_compress( new );
1251
1252                                 if (new->bm_flags & BM_FLAG_RLE)
1253                                         size = *((int *) new->bm_data);
1254                                 else
1255                                         size = new->bm_w * new->bm_h;
1256
1257                                 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
1258                                 d_free(new->bm_data);
1259                                 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1260                                 Piggy_bitmap_cache_next += size;
1261
1262                                 GameBitmaps[i] = *new;
1263         
1264                                 d_free( new );
1265
1266                                 // -- mprintf( (0, "U" ));
1267                         }
1268                 }
1269
1270                 //@@Dont' do these things which are done when writing
1271                 //@@for (i=0; i < Num_bitmap_files; i++ )       {
1272                 //@@    bitmap_index bi;
1273                 //@@    bi.index = i;
1274                 //@@    PIGGY_PAGE_IN( bi );
1275                 //@@}
1276                 //@@
1277                 //@@piggy_close_file();
1278
1279                 piggy_write_pigfile(pigname);
1280
1281                 Current_pigfile[0] = 0;                 //say no pig, to force reload
1282
1283                 piggy_new_pigfile(pigname);             //read in just-generated pig
1284
1285
1286         }
1287         #endif  //ifdef EDITOR
1288
1289 }
1290
1291 ubyte bogus_data[64*64];
1292 grs_bitmap bogus_bitmap;
1293 ubyte bogus_bitmap_initialized=0;
1294 digi_sound bogus_sound;
1295
1296 #define HAMFILE_ID              MAKE_SIG('!','M','A','H') //HAM!
1297 #define HAMFILE_VERSION 3
1298 //version 1 -> 2:  save marker_model_num
1299 //version 2 -> 3:  removed sound files
1300
1301 #define SNDFILE_ID              MAKE_SIG('D','N','S','D') //DSND
1302 #define SNDFILE_VERSION 1
1303
1304 int read_hamfile()
1305 {
1306         CFILE * ham_fp = NULL;
1307         int ham_id;
1308         int sound_offset = 0;
1309         #ifdef MACINTOSH
1310         char name[255];
1311         #endif
1312
1313         #ifndef MACINTOSH
1314         ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1315         #else
1316         sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1317         ham_fp = cfopen( name, "rb" );
1318         #endif
1319
1320         if (ham_fp == NULL) {
1321                 Must_write_hamfile = 1;
1322                 return 0;
1323         }
1324
1325         //make sure ham is valid type file & is up-to-date
1326         ham_id = cfile_read_int(ham_fp);
1327         Piggy_hamfile_version = cfile_read_int(ham_fp);
1328         if (ham_id != HAMFILE_ID)
1329                 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1330 #if 0
1331         if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1332                 Must_write_hamfile = 1;
1333                 cfclose(ham_fp);                                                //out of date ham
1334                 return 0;
1335         }
1336 #endif
1337
1338         if (Piggy_hamfile_version < 3) // hamfile contains sound info
1339                 sound_offset = cfile_read_int(ham_fp);
1340
1341         #ifndef EDITOR
1342         {
1343                 //int i;
1344
1345                 bm_read_all(ham_fp);
1346                 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1347                 // no swap here?
1348                 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1349                         //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1350                         //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1351                 //}
1352         }
1353         #endif
1354
1355         if (Piggy_hamfile_version < 3) {
1356                 int N_sounds;
1357                 int sound_start;
1358                 int header_size;
1359                 int i;
1360                 DiskSoundHeader sndh;
1361                 digi_sound temp_sound;
1362                 char temp_name_read[16];
1363                 int sbytes = 0;
1364
1365                 cfseek(ham_fp, sound_offset, SEEK_SET);
1366                 N_sounds = cfile_read_int(ham_fp);
1367
1368                 sound_start = cftell(ham_fp);
1369
1370                 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1371
1372                 //Read sounds
1373
1374                 for (i=0; i<N_sounds; i++ ) {
1375                         DiskSoundHeader_read(&sndh, ham_fp);
1376                         temp_sound.length = sndh.length;
1377                         temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1378                         SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1379                         memcpy( temp_name_read, sndh.name, 8 );
1380                         temp_name_read[8] = 0;
1381                         piggy_register_sound( &temp_sound, temp_name_read, 1 );
1382 #ifdef MACINTOSH
1383                         if (piggy_is_needed(i))
1384 #endif          // note link to if.
1385                                 sbytes += sndh.length;
1386                         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1387                 }
1388
1389                 SoundBits = d_malloc( sbytes + 16 );
1390                 if ( SoundBits == NULL )
1391                         Error( "Not enough memory to load sounds\n" );
1392
1393                 mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1394
1395                 //      piggy_read_sounds(ham_fp);
1396
1397         }
1398
1399         cfclose(ham_fp);
1400
1401         return 1;
1402
1403 }
1404
1405 int read_sndfile()
1406 {
1407         CFILE * snd_fp = NULL;
1408         int snd_id,snd_version;
1409         int N_sounds;
1410         int sound_start;
1411         int header_size;
1412         int i,size, length;
1413         DiskSoundHeader sndh;
1414         digi_sound temp_sound;
1415         char temp_name_read[16];
1416         int sbytes = 0;
1417         #ifdef MACINTOSH
1418         char name[255];
1419         #endif
1420
1421         #ifndef MACINTOSH
1422         snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1423         #else
1424         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1425         snd_fp = cfopen( name, "rb");
1426         #endif
1427         
1428         if (snd_fp == NULL)
1429                 return 0;
1430
1431         //make sure soundfile is valid type file & is up-to-date
1432         snd_id = cfile_read_int(snd_fp);
1433         snd_version = cfile_read_int(snd_fp);
1434         if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1435                 cfclose(snd_fp);                                                //out of date sound file
1436                 return 0;
1437         }
1438
1439         N_sounds = cfile_read_int(snd_fp);
1440
1441         sound_start = cftell(snd_fp);
1442         size = cfilelength(snd_fp) - sound_start;
1443         length = size;
1444         mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1445
1446         header_size = N_sounds*sizeof(DiskSoundHeader);
1447
1448         //Read sounds
1449
1450         for (i=0; i<N_sounds; i++ ) {
1451                 DiskSoundHeader_read(&sndh, snd_fp);
1452                 //size -= sizeof(DiskSoundHeader);
1453                 temp_sound.length = sndh.length;
1454                 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1455                 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1456                 memcpy( temp_name_read, sndh.name, 8 );
1457                 temp_name_read[8] = 0;
1458                 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1459                 #ifdef MACINTOSH
1460                 if (piggy_is_needed(i))
1461                 #endif          // note link to if.
1462                 sbytes += sndh.length;
1463                 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1464         }
1465
1466         SoundBits = d_malloc( sbytes + 16 );
1467         if ( SoundBits == NULL )
1468                 Error( "Not enough memory to load sounds\n" );
1469
1470         mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1471
1472 //      piggy_read_sounds(snd_fp);
1473
1474         cfclose(snd_fp);
1475
1476         return 1;
1477 }
1478
1479 int piggy_init(void)
1480 {
1481         int ham_ok=0,snd_ok=0;
1482         int i;
1483
1484         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1485         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1486
1487         for (i=0; i<MAX_SOUND_FILES; i++ )      {
1488                 GameSounds[i].length = 0;
1489                 GameSounds[i].data = NULL;
1490                 SoundOffset[i] = 0;
1491         }
1492
1493         for (i=0; i<MAX_BITMAP_FILES; i++ )     
1494                 GameBitmapXlat[i] = i;
1495
1496         if ( !bogus_bitmap_initialized )        {
1497                 int i;
1498                 ubyte c;
1499                 bogus_bitmap_initialized = 1;
1500                 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1501                 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1502                 bogus_bitmap.bm_data = bogus_data;
1503                 c = gr_find_closest_color( 0, 0, 63 );
1504                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1505                 c = gr_find_closest_color( 63, 0, 0 );
1506                 // Make a big red X !
1507                 for (i=0; i<64; i++ )   {
1508                         bogus_data[i*64+i] = c;
1509                         bogus_data[i*64+(63-i)] = c;
1510                 }
1511                 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1512                 bogus_sound.length = 64*64;
1513                 bogus_sound.data = bogus_data;
1514                 GameBitmapOffset[0] = 0;
1515         }
1516
1517         if ( FindArg( "-bigpig" ))
1518                 BigPig = 1;
1519
1520         if ( FindArg( "-lowmem" ))
1521                 piggy_low_memory = 1;
1522
1523         if ( FindArg( "-nolowmem" ))
1524                 piggy_low_memory = 0;
1525
1526         if (piggy_low_memory)
1527                 digi_lomem = 1;
1528
1529         WIN(DDGRLOCK(dd_grd_curcanv));
1530                 gr_set_curfont( SMALL_FONT );
1531                 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1532                 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1533         WIN(DDGRUNLOCK(dd_grd_curcanv));
1534
1535 #if 1 //def EDITOR //need for d1 mission briefings
1536         piggy_init_pigfile(DEFAULT_PIGFILE);
1537 #endif
1538
1539         snd_ok = ham_ok = read_hamfile();
1540
1541         if (Piggy_hamfile_version >= 3)
1542                 snd_ok = read_sndfile();
1543
1544         atexit(piggy_close);
1545
1546         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1547         return (ham_ok && snd_ok);               //read ok
1548 }
1549
1550 int piggy_is_needed(int soundnum)
1551 {
1552         int i;
1553
1554         if ( !digi_lomem ) return 1;
1555
1556         for (i=0; i<MAX_SOUNDS; i++ )   {
1557                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1558                         return 1;
1559         }
1560         return 0;
1561 }
1562
1563
1564 void piggy_read_sounds(void)
1565 {
1566         CFILE * fp = NULL;
1567         ubyte * ptr;
1568         int i, sbytes;
1569         #ifdef MACINTOSH
1570         char name[255];
1571         #endif
1572
1573         ptr = SoundBits;
1574         sbytes = 0;
1575
1576         #ifndef MACINTOSH
1577         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1578         #else
1579         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1580         fp = cfopen( name, "rb");
1581         #endif
1582
1583         if (fp == NULL)
1584                 return;
1585
1586         for (i=0; i<Num_sound_files; i++ )      {
1587                 digi_sound *snd = &GameSounds[i];
1588
1589                 if ( SoundOffset[i] > 0 )       {
1590                         if ( piggy_is_needed(i) )       {
1591                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1592
1593                                 // Read in the sound data!!!
1594                                 snd->data = ptr;
1595                                 ptr += snd->length;
1596                                 sbytes += snd->length;
1597                                 cfread( snd->data, snd->length, 1, fp );
1598                         }
1599                         else
1600                                 snd->data = (ubyte *) -1;
1601                 }
1602         }
1603
1604         cfclose(fp);
1605
1606         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1607
1608 }
1609
1610
1611 extern int descent_critical_error;
1612 extern unsigned descent_critical_deverror;
1613 extern unsigned descent_critical_errcode;
1614
1615 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1616 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1617 "Read fault", "General Failure" };
1618
1619 void piggy_critical_error()
1620 {
1621         grs_canvas * save_canv;
1622         grs_font * save_font;
1623         int i;
1624         save_canv = grd_curcanv;
1625         save_font = grd_curcanv->cv_font;
1626         gr_palette_load( gr_palette );
1627         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1628         if ( i == 1 )
1629                 exit(1);
1630         gr_set_current_canvas(save_canv);
1631         grd_curcanv->cv_font = save_font;
1632 }
1633
1634 void piggy_bitmap_page_in( bitmap_index bitmap )
1635 {
1636         grs_bitmap * bmp;
1637         int i,org_i,temp;
1638
1639         org_i = 0;
1640
1641         i = bitmap.index;
1642         Assert( i >= 0 );
1643         Assert( i < MAX_BITMAP_FILES );
1644         Assert( i < Num_bitmap_files );
1645         Assert( Piggy_bitmap_cache_size > 0 );
1646
1647         if ( i < 1 ) return;
1648         if ( i >= MAX_BITMAP_FILES ) return;
1649         if ( i >= Num_bitmap_files ) return;
1650
1651         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1652
1653         if ( piggy_low_memory ) {
1654                 org_i = i;
1655                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1656         }
1657
1658         bmp = &GameBitmaps[i];
1659
1660         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1661                 stop_time();
1662
1663         ReDoIt:
1664                 descent_critical_error = 0;
1665                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1666                 if ( descent_critical_error )   {
1667                         piggy_critical_error();
1668                         goto ReDoIt;
1669                 }
1670
1671                 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1672                 bmp->bm_flags = GameBitmapFlags[i];
1673
1674                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1675                         int zsize = 0;
1676                         descent_critical_error = 0;
1677                         zsize = cfile_read_int(Piggy_fp);
1678                         if ( descent_critical_error )   {
1679                                 piggy_critical_error();
1680                                 goto ReDoIt;
1681                         }
1682
1683                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1684                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1685                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1686                                 Int3();
1687                                 piggy_bitmap_page_out_all();
1688                                 goto ReDoIt;
1689                         }
1690                         descent_critical_error = 0;
1691                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1692                         if ( descent_critical_error )   {
1693                                 piggy_critical_error();
1694                                 goto ReDoIt;
1695                         }
1696
1697 #ifndef MACDATA
1698                         switch (cfilelength(Piggy_fp)) {
1699                         default:
1700                                 if (!FindArg("-macdata"))
1701                                         break;
1702                                 // otherwise, fall through...
1703                         case MAC_ALIEN1_PIGSIZE:
1704                         case MAC_ALIEN2_PIGSIZE:
1705                         case MAC_FIRE_PIGSIZE:
1706                         case MAC_GROUPA_PIGSIZE:
1707                         case MAC_ICE_PIGSIZE:
1708                         case MAC_WATER_PIGSIZE:
1709                                 rle_swap_0_255( bmp );
1710                                 memcpy(&zsize, bmp->bm_data, 4);
1711                                 break;
1712                         }
1713 #endif
1714
1715                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1716                         Piggy_bitmap_cache_next += zsize;
1717                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1718                                 Int3();
1719                                 piggy_bitmap_page_out_all();
1720                                 goto ReDoIt;
1721                         }
1722
1723                 } else {
1724                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1725                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1726                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1727                                 piggy_bitmap_page_out_all();
1728                                 goto ReDoIt;
1729                         }
1730                         descent_critical_error = 0;
1731                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1732                         if ( descent_critical_error )   {
1733                                 piggy_critical_error();
1734                                 goto ReDoIt;
1735                         }
1736                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1737
1738 #ifndef MACDATA
1739                         switch (cfilelength(Piggy_fp)) {
1740                         default:
1741                                 if (!FindArg("-macdata"))
1742                                         break;
1743                                 // otherwise, fall through...
1744                         case MAC_ALIEN1_PIGSIZE:
1745                         case MAC_ALIEN2_PIGSIZE:
1746                         case MAC_FIRE_PIGSIZE:
1747                         case MAC_GROUPA_PIGSIZE:
1748                         case MAC_ICE_PIGSIZE:
1749                         case MAC_WATER_PIGSIZE:
1750                                 swap_0_255( bmp );
1751                                 break;
1752                         }
1753 #endif
1754                 }
1755
1756                 //@@if ( bmp->bm_selector ) {
1757                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1758                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1759                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1760                 //@@#endif
1761                 //@@}
1762
1763                 start_time();
1764         }
1765
1766         if ( piggy_low_memory ) {
1767                 if ( org_i != i )
1768                         GameBitmaps[org_i] = GameBitmaps[i];
1769         }
1770
1771 //@@Removed from John's code:
1772 //@@#ifndef WINDOWS
1773 //@@    if ( bmp->bm_selector ) {
1774 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1775 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1776 //@@    }
1777 //@@#endif
1778
1779 }
1780
1781 void piggy_bitmap_page_out_all()
1782 {
1783         int i;
1784         
1785         Piggy_bitmap_cache_next = 0;
1786
1787         piggy_page_flushed++;
1788
1789         texmerge_flush();
1790         rle_cache_flush();
1791
1792         for (i=0; i<Num_bitmap_files; i++ )             {
1793                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1794                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1795                         GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1796                 }
1797         }
1798
1799         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1800 }
1801
1802 void piggy_load_level_data()
1803 {
1804         piggy_bitmap_page_out_all();
1805         paging_touch_all();
1806 }
1807
1808 #ifdef EDITOR
1809
1810 void change_filename_ext( char *dest, char *src, char *ext );
1811
1812 void piggy_write_pigfile(char *filename)
1813 {
1814         FILE *pig_fp;
1815         int bitmap_data_start,data_offset;
1816         DiskBitmapHeader bmh;
1817         int org_offset;
1818         char subst_name[32];
1819         int i;
1820         FILE *fp1,*fp2;
1821         char tname[FILENAME_LEN];
1822
1823         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1824         for (i=0; i < Num_bitmap_files; i++ )   {
1825                 bitmap_index bi;
1826                 bi.index = i;
1827                 PIGGY_PAGE_IN( bi );
1828         }
1829         // -- mprintf( (0, "\n" ));
1830
1831         piggy_close_file();
1832
1833         // -- mprintf( (0, "Creating %s...",filename ));
1834
1835         pig_fp = fopen( filename, "wb" );       //open PIG file
1836         Assert( pig_fp!=NULL );
1837
1838         write_int(PIGFILE_ID,pig_fp);
1839         write_int(PIGFILE_VERSION,pig_fp);
1840
1841         Num_bitmap_files--;
1842         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1843         Num_bitmap_files++;
1844
1845         bitmap_data_start = ftell(pig_fp);
1846         bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE; 
1847         data_offset = bitmap_data_start;
1848
1849         change_filename_ext(tname,filename,"lst");
1850         fp1 = fopen( tname, "wt" );
1851         change_filename_ext(tname,filename,"all");
1852         fp2 = fopen( tname, "wt" );
1853
1854         for (i=1; i < Num_bitmap_files; i++ )   {
1855                 int *size;
1856                 grs_bitmap *bmp;
1857
1858                 {               
1859                         char * p, *p1;
1860                         p = strchr(AllBitmaps[i].name,'#');
1861                         if (p)  {
1862                                 int n;
1863                                 p1 = p; p1++; 
1864                                 n = atoi(p1);
1865                                 *p = 0;
1866                                 if (fp2 && n==0)
1867                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1868                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1869                                 Assert( n <= 63 );
1870                                 bmh.dflags = DBM_FLAG_ABM + n;
1871                                 *p = '#';
1872                         }else {
1873                                 if (fp2)
1874                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1875                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1876                                 bmh.dflags = 0;
1877                         }
1878                 }
1879                 bmp = &GameBitmaps[i];
1880
1881                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1882
1883                 if (fp1)
1884                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1885                 org_offset = ftell(pig_fp);
1886                 bmh.offset = data_offset - bitmap_data_start;
1887                 fseek( pig_fp, data_offset, SEEK_SET );
1888
1889                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1890                         size = (int *)bmp->bm_data;
1891                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1892                         data_offset += *size;
1893                         if (fp1)
1894                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1895                 } else {
1896                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1897                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1898                         if (fp1)
1899                                 fprintf( fp1, ".\n" );
1900                 }
1901                 fseek( pig_fp, org_offset, SEEK_SET );
1902                 Assert( GameBitmaps[i].bm_w < 4096 );
1903                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1904                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1905                 Assert( GameBitmaps[i].bm_h < 4096 );
1906                 bmh.height = GameBitmaps[i].bm_h;
1907                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1908                 bmh.flags = GameBitmaps[i].bm_flags;
1909                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1910                         bitmap_index other_bitmap;
1911                         other_bitmap = piggy_find_bitmap( subst_name );
1912                         GameBitmapXlat[i] = other_bitmap.index;
1913                         bmh.flags |= BM_FLAG_PAGED_OUT;
1914                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1915                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1916                 } else  {
1917                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1918                 }
1919                 bmh.avg_color=GameBitmaps[i].avg_color;
1920                 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp );                    // Mark as a bitmap
1921         }
1922
1923         fclose(pig_fp);
1924
1925         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1926         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1927
1928         fclose(fp1);
1929         fclose(fp2);
1930
1931 }
1932
1933 static void write_int(int i,FILE *file)
1934 {
1935         if (fwrite( &i, sizeof(i), 1, file) != 1)
1936                 Error( "Error reading int in gamesave.c" );
1937
1938 }
1939
1940 void piggy_dump_all()
1941 {
1942         int i, xlat_offset;
1943         FILE * ham_fp;
1944         int org_offset,data_offset=0;
1945         DiskSoundHeader sndh;
1946         int sound_data_start=0;
1947         FILE *fp1,*fp2;
1948
1949         #ifdef NO_DUMP_SOUNDS
1950         Num_sound_files = 0;
1951         Num_sound_files_new = 0;
1952         #endif
1953
1954         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1955                 return;
1956
1957         fp1 = fopen( "ham.lst", "wt" );
1958         fp2 = fopen( "ham.all", "wt" );
1959
1960         if (Must_write_hamfile || Num_bitmap_files_new) {
1961
1962                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1963         
1964                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1965                 Assert( ham_fp!=NULL );
1966         
1967                 write_int(HAMFILE_ID,ham_fp);
1968                 write_int(HAMFILE_VERSION,ham_fp);
1969         
1970                 bm_write_all(ham_fp);
1971                 xlat_offset = ftell(ham_fp);
1972                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1973                 //Dump bitmaps
1974         
1975                 if (Num_bitmap_files_new)
1976                         piggy_write_pigfile(DEFAULT_PIGFILE);
1977         
1978                 //free up memeory used by new bitmaps
1979                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1980                         d_free(GameBitmaps[i].bm_data);
1981         
1982                 //next thing must be done after pig written
1983                 fseek( ham_fp, xlat_offset, SEEK_SET );
1984                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1985         
1986                 fclose(ham_fp);
1987                 mprintf( (0, "\n" ));
1988         }
1989         
1990         if (Num_sound_files_new) {
1991
1992                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1993                 // Now dump sound file
1994                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1995                 Assert( ham_fp!=NULL );
1996         
1997                 write_int(SNDFILE_ID,ham_fp);
1998                 write_int(SNDFILE_VERSION,ham_fp);
1999
2000                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
2001         
2002                 mprintf( (0, "\nDumping sounds..." ));
2003         
2004                 sound_data_start = ftell(ham_fp);
2005                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
2006                 data_offset = sound_data_start;
2007         
2008                 for (i=0; i < Num_sound_files; i++ )    {
2009                         digi_sound *snd;
2010         
2011                         snd = &GameSounds[i];
2012                         strcpy( sndh.name, AllSounds[i].name );
2013                         sndh.length = GameSounds[i].length;
2014                         sndh.offset = data_offset - sound_data_start;
2015         
2016                         org_offset = ftell(ham_fp);
2017                         fseek( ham_fp, data_offset, SEEK_SET );
2018         
2019                         sndh.data_length = GameSounds[i].length;
2020                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
2021                         data_offset += snd->length;
2022                         fseek( ham_fp, org_offset, SEEK_SET );
2023                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
2024         
2025                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
2026                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
2027                 }
2028
2029                 fclose(ham_fp);
2030                 mprintf( (0, "\n" ));
2031         }
2032
2033         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
2034         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
2035         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
2036
2037         fclose(fp1);
2038         fclose(fp2);
2039
2040         // Never allow the game to run after building ham.
2041         exit(0);
2042 }
2043
2044 #endif
2045
2046 void piggy_close()
2047 {
2048         piggy_close_file();
2049
2050         if (BitmapBits)
2051                 d_free(BitmapBits);
2052
2053         if ( SoundBits )
2054                 d_free( SoundBits );
2055
2056         hashtable_free( &AllBitmapsNames );
2057         hashtable_free( &AllDigiSndNames );
2058
2059 }
2060
2061 int piggy_does_bitmap_exist_slow( char * name )
2062 {
2063         int i;
2064
2065         for (i=0; i<Num_bitmap_files; i++ )     {
2066                 if ( !strcmp( AllBitmaps[i].name, name) )
2067                         return 1;
2068         }
2069         return 0;
2070 }
2071
2072
2073 #define NUM_GAUGE_BITMAPS 23
2074 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
2075         "gauge01", "gauge01b",
2076         "gauge02", "gauge02b",
2077         "gauge06", "gauge06b",
2078         "targ01", "targ01b",
2079         "targ02", "targ02b", 
2080         "targ03", "targ03b",
2081         "targ04", "targ04b",
2082         "targ05", "targ05b",
2083         "targ06", "targ06b",
2084         "gauge18", "gauge18b",
2085         "gauss1", "helix1",
2086         "phoenix1"
2087 };
2088
2089
2090 int piggy_is_gauge_bitmap( char * base_name )
2091 {
2092         int i;
2093         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
2094                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
2095                         return 1;
2096         }
2097
2098         return 0;       
2099 }
2100
2101 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
2102 {
2103         int frame;
2104         char * p;
2105         char base_name[ 16 ];
2106         
2107         strcpy( subst_name, name );
2108         p = strchr( subst_name, '#' );
2109         if ( p )        {
2110                 frame = atoi( &p[1] );
2111                 *p = 0;
2112                 strcpy( base_name, subst_name );
2113                 if ( !piggy_is_gauge_bitmap( base_name ))       {
2114                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
2115                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
2116                                 if ( frame & 1 ) {
2117                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
2118                                         return 1;
2119                                 }
2120                         }
2121                 }
2122         }
2123         strcpy( subst_name, name );
2124         return 0;
2125 }
2126
2127
2128
2129 #ifdef WINDOWS
2130 //      New Windows stuff
2131
2132 //      windows bitmap page in
2133 //              Page in a bitmap, if ddraw, then page it into a ddsurface in 
2134 //              'video' memory.  if that fails, page it in normally.
2135
2136 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
2137 {
2138 }
2139
2140
2141 //      Essential when switching video modes!
2142
2143 void piggy_bitmap_page_out_all_w()
2144 {
2145 }
2146
2147 #endif // WINDOWS
2148
2149
2150 /*
2151  * Functions for loading replacement textures
2152  *  1) From .pog files
2153  *  2) From descent.pig (for loading d1 levels)
2154  */
2155
2156 extern void change_filename_extension( char *dest, char *src, char *new_ext );
2157 extern char last_palette_loaded_pig[];
2158
2159 ubyte *Bitmap_replacement_data=NULL;
2160
2161 void free_bitmap_replacements()
2162 {
2163         if (Bitmap_replacement_data) {
2164                 d_free(Bitmap_replacement_data);
2165                 Bitmap_replacement_data = NULL;
2166         }
2167 }
2168
2169 void load_bitmap_replacements(char *level_name)
2170 {
2171         char ifile_name[FILENAME_LEN];
2172         CFILE *ifile;
2173         int i;
2174
2175         //first, free up data allocated for old bitmaps
2176         free_bitmap_replacements();
2177
2178         change_filename_extension(ifile_name, level_name, ".POG" );
2179
2180         ifile = cfopen(ifile_name,"rb");
2181
2182         if (ifile) {
2183                 int id,version,n_bitmaps;
2184                 int bitmap_data_size;
2185                 ushort *indices;
2186
2187                 id = cfile_read_int(ifile);
2188                 version = cfile_read_int(ifile);
2189
2190                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
2191                         cfclose(ifile);
2192                         return;
2193                 }
2194
2195                 n_bitmaps = cfile_read_int(ifile);
2196
2197                 MALLOC( indices, ushort, n_bitmaps );
2198
2199                 for (i = 0; i < n_bitmaps; i++)
2200                         indices[i] = cfile_read_short(ifile);
2201
2202                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - DISKBITMAPHEADER_SIZE * n_bitmaps;
2203                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
2204
2205                 for (i=0;i<n_bitmaps;i++) {
2206                         DiskBitmapHeader bmh;
2207                         grs_bitmap temp_bitmap;
2208
2209                         DiskBitmapHeader_read(&bmh, ifile);
2210
2211                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2212
2213                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2214                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2215                         temp_bitmap.avg_color = bmh.avg_color;
2216                         temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
2217
2218                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2219                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2220                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2221                         if ( bmh.flags & BM_FLAG_RLE ) temp_bitmap.bm_flags |= BM_FLAG_RLE;
2222                         if ( bmh.flags & BM_FLAG_RLE_BIG ) temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2223
2224                         GameBitmaps[indices[i]] = temp_bitmap;
2225                 }
2226
2227                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
2228
2229                 d_free(indices);
2230
2231                 cfclose(ifile);
2232
2233                 last_palette_loaded_pig[0]= 0;  //force pig re-load
2234
2235                 texmerge_flush();       //for re-merging with new textures
2236         }
2237
2238         atexit(free_bitmap_replacements);
2239 }
2240
2241 #define FIRST_D1_TEXTURE 722
2242 #define LAST_D1_STATIC_TEXTURE 1042//1342 //afterwards, we have door frames and stuff
2243 #define FIRST_D2_TEXTURE 1243
2244
2245 void load_d1_bitmap_replacements()
2246 {
2247         CFILE * d1_Piggy_fp;
2248         grs_bitmap temp_bitmap;
2249         DiskBitmapHeader bmh;
2250         int pig_data_start, bitmap_header_start, bitmap_data_start;
2251         int N_bitmaps, zsize;
2252         int d1_index, d2_index;
2253         ubyte colormap[256];
2254         ubyte *next_bitmap; // to which address we write the next bitmap
2255
2256         d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2257
2258         if (!d1_Piggy_fp)
2259                 return; // use d2 bitmaps instead...
2260
2261         //first, free up data allocated for old bitmaps
2262         free_bitmap_replacements();
2263
2264         // read d1 palette, build colormap
2265         {
2266                 int freq[256];
2267                 ubyte d1_palette[256*3];
2268                 CFILE * palette_file = cfopen(D1_PALETTE, "rb" );
2269                 Assert( palette_file );
2270                 Assert( cfilelength( palette_file ) == 9472 );
2271                 cfread( d1_palette, 256, 3, palette_file);
2272                 cfclose( palette_file );
2273                 build_colormap_good( d1_palette, colormap, freq );
2274                 // don't change transparencies:
2275                 colormap[254] = 254;
2276                 colormap[255] = 255;
2277         }
2278
2279         switch (cfilelength(d1_Piggy_fp)) {
2280         case D1_SHAREWARE_10_PIGSIZE:
2281         case D1_SHAREWARE_PIGSIZE:
2282                 pig_data_start = 0;
2283                 break;
2284         default:
2285                 Int3();
2286         case D1_PIGSIZE:
2287         case D1_OEM_PIGSIZE:
2288         case D1_MAC_PIGSIZE:
2289         case D1_MAC_SHARE_PIGSIZE:
2290                 //int i;
2291                 pig_data_start = cfile_read_int(d1_Piggy_fp );
2292                 bm_read_all_d1( d1_Piggy_fp );
2293                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2294                 break;
2295         }
2296
2297         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2298         N_bitmaps = cfile_read_int(d1_Piggy_fp);
2299         {
2300                 int N_sounds = cfile_read_int(d1_Piggy_fp);
2301                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2302                         + N_sounds * DISKSOUNDHEADER_SIZE;
2303                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2304                 bitmap_data_start = bitmap_header_start + header_size;
2305         }
2306
2307         MALLOC( Bitmap_replacement_data, ubyte, cfilelength(d1_Piggy_fp) - bitmap_data_start ); // too much
2308         //TODO: handle case where b_r_d == 0! (have to convert textures, return, not bm_read_all_d1)
2309
2310         next_bitmap = Bitmap_replacement_data;
2311
2312         for (d1_index=1; d1_index<=N_bitmaps; d1_index++ ) {
2313                 // only change wall texture bitmaps
2314                 if (d1_index >= FIRST_D1_TEXTURE && d1_index <= LAST_D1_STATIC_TEXTURE) {
2315                         d2_index = d1_index + FIRST_D2_TEXTURE - FIRST_D1_TEXTURE;
2316
2317                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2318                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2319
2320                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2321
2322                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2323                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2324                         temp_bitmap.avg_color = bmh.avg_color;
2325
2326                         //GameBitmapFlags[convert_d1_bitmap_num(d1_index)] = 0;
2327
2328                         if ( bmh.flags & BM_FLAG_TRANSPARENT )
2329                                 temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2330                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT )
2331                                 temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2332                         if ( bmh.flags & BM_FLAG_NO_LIGHTING )
2333                                 temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2334                         if ( bmh.flags & BM_FLAG_RLE )
2335                                 temp_bitmap.bm_flags |= BM_FLAG_RLE;
2336                         if ( bmh.flags & BM_FLAG_RLE_BIG )
2337                                 temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2338
2339                         temp_bitmap.bm_data = next_bitmap;
2340
2341                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2342                         zsize = cfile_read_int(d1_Piggy_fp);
2343                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2344                         cfread(next_bitmap, 1, zsize, d1_Piggy_fp);
2345
2346                         switch(cfilelength(d1_Piggy_fp)) {
2347                         case D1_MAC_PIGSIZE:
2348                         case D1_MAC_SHARE_PIGSIZE:
2349                                 rle_swap_0_255(&temp_bitmap);
2350                         }
2351                         rle_remap(&temp_bitmap, colormap);
2352
2353                         GameBitmaps[d2_index] = temp_bitmap;
2354
2355                         memcpy(&zsize, temp_bitmap.bm_data, 4);
2356                         next_bitmap += zsize;
2357                 }
2358         }
2359
2360         cfclose(d1_Piggy_fp);
2361
2362         last_palette_loaded_pig[0]= 0;  //force pig re-load
2363
2364         texmerge_flush();       //for re-merging with new textures
2365
2366         atexit(free_bitmap_replacements);
2367 }
2368
2369
2370 extern int extra_bitmap_num;
2371
2372 /*
2373  * Find and load the named bitmap from descent.pig
2374  * similar to read_extra_bitmap_iff
2375  */
2376 bitmap_index read_extra_bitmap_d1_pig(char *name)
2377 {
2378         bitmap_index bitmap_num;
2379         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2380
2381         bitmap_num.index = 0;
2382
2383         {
2384                 CFILE *d1_Piggy_fp;
2385                 int i;
2386                 DiskBitmapHeader bmh;
2387                 int pig_data_start, bitmap_header_start, bitmap_data_start;
2388                 int N_bitmaps, zsize;
2389                 ubyte colormap[256];
2390
2391                 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2392                 if (!d1_Piggy_fp)
2393                 {
2394                         con_printf(CON_DEBUG, "could not open %s\n", D1_PIGFILE);
2395                         return bitmap_num;
2396                 }
2397
2398                 // read d1 palette, build colormap
2399                 {
2400                         int freq[256];
2401                         ubyte d1_palette[256*3];
2402                         CFILE * palette_file = cfopen(D1_PALETTE, "rb");
2403                         if (!palette_file || cfilelength(palette_file) != 9472)
2404                         {
2405                                 con_printf(CON_DEBUG, "could not open %s\n", D1_PALETTE);
2406                                 return bitmap_num;
2407                         }
2408                         cfread( d1_palette, 256, 3, palette_file);
2409                         cfclose( palette_file );
2410                         build_colormap_good( d1_palette, colormap, freq );
2411                         // don't change transparencies:
2412                         colormap[254] = 254;
2413                         colormap[255] = 255;
2414                 }
2415
2416                 switch (cfilelength(d1_Piggy_fp)) {
2417                 case D1_SHAREWARE_10_PIGSIZE:
2418                 case D1_SHAREWARE_PIGSIZE:
2419                         pig_data_start = 0;
2420                         break;
2421                 default:
2422                         Int3();
2423                 case D1_PIGSIZE:
2424                 case D1_OEM_PIGSIZE:
2425                 case D1_MAC_PIGSIZE:
2426                 case D1_MAC_SHARE_PIGSIZE:
2427                         pig_data_start = cfile_read_int(d1_Piggy_fp);
2428                         break;
2429                 }
2430
2431                 cfseek(d1_Piggy_fp, pig_data_start, SEEK_SET);
2432                 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2433                 {
2434                         int N_sounds = cfile_read_int(d1_Piggy_fp);
2435                         int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2436                                 + N_sounds * DISKSOUNDHEADER_SIZE;
2437                         bitmap_header_start = pig_data_start + 2 * sizeof(int);
2438                         bitmap_data_start = bitmap_header_start + header_size;
2439                 }
2440
2441                 for (i = 0; i < N_bitmaps; i++)
2442                 {
2443                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2444                         if (!strnicmp(bmh.name, name, 8))
2445                                 break;
2446                 }
2447
2448                 if (strnicmp(bmh.name, name, 8))
2449                 {
2450                         con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2451                         return bitmap_num;
2452                 }
2453
2454                 memset( new, 0, sizeof(grs_bitmap) );
2455
2456                 new->bm_w = new->bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2457                 new->bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2458                 new->avg_color = bmh.avg_color;
2459
2460                 if ( bmh.flags & BM_FLAG_TRANSPARENT )
2461                         new->bm_flags |= BM_FLAG_TRANSPARENT;
2462                 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT )
2463                         new->bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2464                 if ( bmh.flags & BM_FLAG_NO_LIGHTING )
2465                         new->bm_flags |= BM_FLAG_NO_LIGHTING;
2466                 if ( bmh.flags & BM_FLAG_RLE )
2467                         new->bm_flags |= BM_FLAG_RLE;
2468                 if ( bmh.flags & BM_FLAG_RLE_BIG )
2469                         new->bm_flags |= BM_FLAG_RLE_BIG;
2470
2471                 if ( bmh.flags & BM_FLAG_RLE )
2472                 {
2473                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2474                         zsize = cfile_read_int(d1_Piggy_fp);
2475                 }
2476                 else
2477                         zsize = new->bm_w * new->bm_h;
2478                 new->bm_data = d_malloc(zsize);
2479                 cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2480                 cfread(new->bm_data, 1, zsize, d1_Piggy_fp);
2481
2482                 switch(cfilelength(d1_Piggy_fp)) {
2483                 case D1_MAC_PIGSIZE:
2484                 case D1_MAC_SHARE_PIGSIZE:
2485                         rle_swap_0_255(new);
2486                 }
2487                 rle_remap(new, colormap);
2488
2489                 cfclose(d1_Piggy_fp);
2490         }
2491
2492         new->avg_color = 0;     //compute_average_pixel(new);
2493
2494         bitmap_num.index = extra_bitmap_num;
2495
2496         GameBitmaps[extra_bitmap_num++] = *new;
2497
2498         return bitmap_num;
2499 }
2500
2501
2502 #ifndef FAST_FILE_IO
2503 /*
2504  * reads a bitmap_index structure from a CFILE
2505  */
2506 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2507 {
2508         bi->index = cfile_read_short(fp);
2509 }
2510
2511 /*
2512  * reads n bitmap_index structs from a CFILE
2513  */
2514 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2515 {
2516         int i;
2517
2518         for (i = 0; i < n; i++)
2519                 bi[i].index = cfile_read_short(fp);
2520         return i;
2521 }
2522
2523 /*
2524  * reads a DiskBitmapHeader structure from a CFILE
2525  */
2526 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
2527 {
2528         cfread(dbh->name, 8, 1, fp);
2529         dbh->dflags = cfile_read_byte(fp);
2530         dbh->width = cfile_read_byte(fp);
2531         dbh->height = cfile_read_byte(fp);
2532         dbh->wh_extra = cfile_read_byte(fp);
2533         dbh->flags = cfile_read_byte(fp);
2534         dbh->avg_color = cfile_read_byte(fp);
2535         dbh->offset = cfile_read_int(fp);
2536 }
2537
2538 /*
2539  * reads a DiskSoundHeader structure from a CFILE
2540  */
2541 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
2542 {
2543         cfread(dsh->name, 8, 1, fp);
2544         dsh->length = cfile_read_int(fp);
2545         dsh->data_length = cfile_read_int(fp);
2546         dsh->offset = cfile_read_int(fp);
2547 }
2548 #endif // FAST_FILE_IO
2549
2550 /*
2551  * reads a descent 1 DiskBitmapHeader structure from a CFILE
2552  */
2553 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
2554 {
2555         cfread(dbh->name, 8, 1, fp);
2556         dbh->dflags = cfile_read_byte(fp);
2557         dbh->width = cfile_read_byte(fp);
2558         dbh->height = cfile_read_byte(fp);
2559         dbh->wh_extra = 0;
2560         dbh->flags = cfile_read_byte(fp);
2561         dbh->avg_color = cfile_read_byte(fp);
2562         dbh->offset = cfile_read_int(fp);
2563 }