added D1_PIGFILE ("descent.pig") macro
[btb/d2x.git] / main / piggy.c
1 /* $Id: piggy.c,v 1.29 2003-03-25 10:17:05 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.29 2003-03-25 10:17:05 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 DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
441 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
442 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
443
444 #define MAC_ALIEN1_PIGSIZE      5013035
445 #define MAC_ALIEN2_PIGSIZE      4909916
446 #define MAC_FIRE_PIGSIZE        4969035
447 #define MAC_GROUPA_PIGSIZE      4929684 // also used for mac shareware
448 #define MAC_ICE_PIGSIZE         4923425
449 #define MAC_WATER_PIGSIZE       4832403
450
451 ubyte *BitmapBits = NULL;
452 ubyte *SoundBits = NULL;
453
454 typedef struct BitmapFile {
455         char    name[15];
456 } BitmapFile;
457
458 typedef struct SoundFile {
459         char    name[15];
460 } SoundFile;
461
462 hashtable AllBitmapsNames;
463 hashtable AllDigiSndNames;
464
465 int Num_bitmap_files = 0;
466 int Num_sound_files = 0;
467
468 digi_sound GameSounds[MAX_SOUND_FILES];
469 int SoundOffset[MAX_SOUND_FILES];
470 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
471
472 alias alias_list[MAX_ALIASES];
473 int Num_aliases=0;
474
475 int Must_write_hamfile = 0;
476 int Num_bitmap_files_new = 0;
477 int Num_sound_files_new = 0;
478 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
479 static SoundFile AllSounds[ MAX_SOUND_FILES ];
480
481 int Piggy_hamfile_version = 0;
482
483 int piggy_low_memory = 0;
484
485 int Piggy_bitmap_cache_size = 0;
486 int Piggy_bitmap_cache_next = 0;
487 ubyte * Piggy_bitmap_cache_data = NULL;
488 static int GameBitmapOffset[MAX_BITMAP_FILES];
489 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
490 ushort GameBitmapXlat[MAX_BITMAP_FILES];
491
492 #define PIGGY_BUFFER_SIZE (2400*1024)
493
494 #ifdef MACINTOSH
495 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024)             // size of buffer when piggy_low_memory is set
496
497 #ifdef SHAREWARE
498 #undef PIGGY_BUFFER_SIZE
499 #undef PIGGY_SMALL_BUFFER_SIZE
500
501 #define PIGGY_BUFFER_SIZE (2000*1024)
502 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
503 #endif          // SHAREWARE
504
505 #endif
506
507 int piggy_page_flushed = 0;
508
509 #define DBM_FLAG_ABM            64
510
511 ubyte BigPig = 0;
512
513 #ifdef MACINTOSH
514         extern short    cd_VRefNum;
515         extern void             ConcatPStr(StringPtr dst, StringPtr src);
516         extern int              ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
517         extern int              ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
518 #endif
519
520 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
521
522 #ifdef EDITOR
523 void piggy_write_pigfile(char *filename);
524 static void write_int(int i,FILE *file);
525 #endif
526
527 void swap_0_255(grs_bitmap *bmp)
528 {
529         int i;
530
531         for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
532                 if(bmp->bm_data[i] == 0)
533                         bmp->bm_data[i] = 255;
534                 else if (bmp->bm_data[i] == 255)
535                         bmp->bm_data[i] = 0;
536         }
537 }
538
539 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
540 {
541         bitmap_index temp;
542         Assert( Num_bitmap_files < MAX_BITMAP_FILES );
543
544         temp.index = Num_bitmap_files;
545
546         if (!in_file)   {
547 #ifdef EDITOR
548                 if ( FindArg("-macdata") )
549                         swap_0_255( bmp );
550 #endif
551                 if ( !BigPig )  gr_bitmap_rle_compress( bmp );
552                 Num_bitmap_files_new++;
553         }
554
555         strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
556         hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
557         GameBitmaps[Num_bitmap_files] = *bmp;
558         if ( !in_file ) {
559                 GameBitmapOffset[Num_bitmap_files] = 0;
560                 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
561         }
562         Num_bitmap_files++;
563
564         return temp;
565 }
566
567 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
568 {
569         int i;
570
571         Assert( Num_sound_files < MAX_SOUND_FILES );
572
573         strncpy( AllSounds[Num_sound_files].name, name, 12 );
574         hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
575         GameSounds[Num_sound_files] = *snd;
576         if ( !in_file ) {
577                 SoundOffset[Num_sound_files] = 0;       
578         }
579
580         i = Num_sound_files;
581    
582         if (!in_file)
583                 Num_sound_files_new++;
584
585         Num_sound_files++;
586         return i;
587 }
588
589 bitmap_index piggy_find_bitmap( char * name )   
590 {
591         bitmap_index bmp;
592         int i;
593         char *t;
594
595         bmp.index = 0;
596
597         if ((t=strchr(name,'#'))!=NULL)
598                 *t=0;
599
600         for (i=0;i<Num_aliases;i++)
601                 if (stricmp(name,alias_list[i].alias_name)==0) {
602                         if (t) {                //extra stuff for ABMs
603                                 static char temp[FILENAME_LEN];
604                                 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
605                                 name = temp;
606                                 strcat(name,"#");
607                                 strcat(name,t+1);
608                         }
609                         else
610                                 name=alias_list[i].file_name; 
611                         break;
612                 }
613
614         if (t)
615                 *t = '#';
616
617         i = hashtable_search( &AllBitmapsNames, name );
618         Assert( i != 0 );
619         if ( i < 0 )
620                 return bmp;
621
622         bmp.index = i;
623         return bmp;
624 }
625
626 int piggy_find_sound( char * name )     
627 {
628         int i;
629
630         i = hashtable_search( &AllDigiSndNames, name );
631
632         if ( i < 0 )
633                 return 255;
634
635         return i;
636 }
637
638 CFILE * Piggy_fp = NULL;
639
640 #define FILENAME_LEN 13
641
642 char Current_pigfile[FILENAME_LEN] = "";
643
644 void piggy_close_file()
645 {
646         if ( Piggy_fp ) {
647                 cfclose( Piggy_fp );
648                 Piggy_fp        = NULL;
649                 Current_pigfile[0] = 0;
650         }
651 }
652
653 int Pigfile_initialized=0;
654
655 #define PIGFILE_ID              MAKE_SIG('G','I','P','P') //PPIG
656 #define PIGFILE_VERSION         2
657
658 extern char CDROM_dir[];
659
660 int request_cd(void);
661
662
663 #ifdef MACINTOSH
664
665 //copies a pigfile from the CD to the current dir
666 //retuns file handle of new pig
667 CFILE *copy_pigfile_from_cd(char *filename)             // MACINTOSH VERSION
668 {
669         // C Stuff
670         char                    sourcePathAndFileCStr[255] = "";
671         char                    destPathAndFileCStr[255]        = "";
672         FILEFINDSTRUCT  find;
673         FILE*                   sourceFile      = NULL;
674         FILE*                   destFile        = NULL;
675         const int               BUF_SIZE = 4096;
676         ubyte                   buf[BUF_SIZE];
677
678         // Mac Stuff
679         Str255                  sourcePathAndFilePStr = "\p";
680         Str255                  destPathAndFilePStr = "\p";
681         Str255                  pigfileNamePStr = "\p";
682         HParamBlockRec  theSourcePigHFSParams;
683         HParamBlockRec  theDestPigHFSParams;
684         OSErr                   theErr = noErr;
685         char                    oldDirCStr[255] = "";
686
687         getcwd(oldDirCStr, 255);
688         
689         show_boxed_message("Copying bitmap data from CD...");
690         gr_palette_load(gr_palette);    //I don't think this line is really needed
691
692         chdir(":Data");
693         //First, delete all PIG files currently in the directory
694         if( !FileFindFirst( "*.pig", &find ) )
695         {
696                 do
697                 {
698                         remove(find.name);
699                 } while( !FileFindNext( &find ) );
700                 
701                 FileFindClose();
702         }
703         chdir(oldDirCStr);
704
705         //Now, copy over new pig
706         songs_stop_redbook();           //so we can read off the cd
707
708         // make the source path "<cd volume>:Data:filename.pig"
709 //MWA   ConvertCToPStr(filename, pigfileNamePStr);
710
711 //MWA   ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:");        // volume ID is cd_VRefNum
712 //MWA   ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
713
714         strupr(filename);
715         strcpy(sourcePathAndFileCStr, "Descent II:Data:");
716         strcat(sourcePathAndFileCStr, filename);
717         
718         // make the destination path "<default directory>:Data:filename.pig"
719 //MWA   ConcatPStr(destPathAndFilePStr, "\p:Data:");
720 //MWA   ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
721 //MWA   ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
722 //MWA   ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
723
724         strcpy(destPathAndFileCStr, ":Data:");
725         strcat(destPathAndFileCStr, filename);
726
727         strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
728         strcpy(destPathAndFilePStr, destPathAndFileCStr);
729         c2pstr(sourcePathAndFilePStr);
730         c2pstr(destPathAndFilePStr);
731         
732         do {
733                 // Open the source file
734                 sourceFile = fopen(sourcePathAndFileCStr,"rb");
735
736                 if (!sourceFile) {
737
738                         if (request_cd() == -1)
739                                 Error("Cannot load file <%s> from CD",filename);
740                 }
741
742         } while (!sourceFile);
743
744
745         // Get the time stamp from the source file
746         theSourcePigHFSParams.fileParam.ioCompletion    = nil;
747         theSourcePigHFSParams.fileParam.ioNamePtr               = sourcePathAndFilePStr;
748         theSourcePigHFSParams.fileParam.ioVRefNum               = cd_VRefNum;
749         theSourcePigHFSParams.fileParam.ioFDirIndex     = 0;
750         theSourcePigHFSParams.fileParam.ioDirID         = 0;
751         
752         theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
753         if (theErr != noErr)
754         {
755                 // Error getting file time stamp!! Why? JTS
756                 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
757         }
758         
759         // Copy the file over
760         // C Stuff......
761         
762         // Open the destination file
763         destFile = fopen(destPathAndFileCStr,"wb");
764         if (!destFile)
765         {
766                 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
767         }
768         
769         // Copy bytes until the end of the source file
770         while (!feof(sourceFile))
771         {
772                 int bytes_read;
773                 int x;
774
775                 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
776                 if (ferror(sourceFile))
777                         Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
778
779 // Assert is bogus              Assert(bytes_read == BUF_SIZE || feof(sourceFile));
780
781                 fwrite(buf,1,bytes_read,destFile);
782                 if (ferror(destFile))
783                         Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
784         }
785
786         // close the source/dest files
787         if (fclose(sourceFile))
788                 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
789         if (fclose(destFile))
790                 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
791
792         // Get the current hfs data for the new file
793         theDestPigHFSParams.fileParam.ioCompletion      = nil;
794         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
795         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
796         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
797         theDestPigHFSParams.fileParam.ioDirID           = 0;
798         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
799         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
800         {
801                 // Error getting file time stamp!! Why? JTS
802                 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
803         }
804
805         // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
806         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
807         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
808         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
809         theDestPigHFSParams.fileParam.ioDirID           = 0;
810
811         // Copy the time stamp from the source file info
812         theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
813         theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
814         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
815         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
816         
817         // Set the dest file's time stamp to the source file's time stamp values
818         theErr = PBHSetFInfo(&theDestPigHFSParams, false);
819
820         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
821         {
822                 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
823         }
824
825         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
826
827         return cfopen(destPathAndFileCStr, "rb");
828 }
829
830 #else   //PC Version of copy_pigfile_from_cd is below
831
832 //copies a pigfile from the CD to the current dir
833 //retuns file handle of new pig
834 CFILE *copy_pigfile_from_cd(char *filename)
835 {
836         char name[80];
837         FILEFINDSTRUCT find;
838         int ret;
839
840         return cfopen(filename, "rb");
841         show_boxed_message("Copying bitmap data from CD...");
842         gr_palette_load(gr_palette);    //I don't think this line is really needed
843
844         //First, delete all PIG files currently in the directory
845
846         if( !FileFindFirst( "*.pig", &find ) ) {
847                 do      {
848                         remove(find.name);
849                 } while( !FileFindNext( &find ) );
850                 FileFindClose();
851         }
852
853         //Now, copy over new pig
854
855         songs_stop_redbook();           //so we can read off the cd
856
857         //new code to unarj file
858         strcpy(name,CDROM_dir);
859         strcat(name,"descent2.sow");
860
861         do {
862 //              ret = unarj_specific_file(name,filename,filename);
863 // DPH:FIXME
864
865                 ret = !EXIT_SUCCESS;
866
867                 if (ret != EXIT_SUCCESS) {
868
869                         //delete file, so we don't leave partial file
870                         remove(filename);
871
872                         #ifndef MACINTOSH
873                         if (request_cd() == -1)
874                         #endif
875                                 //NOTE LINK TO ABOVE IF
876                                 Error("Cannot load file <%s> from CD",filename);
877                 }
878
879         } while (ret != EXIT_SUCCESS);
880
881         return cfopen(filename, "rb");
882 }
883
884 #endif // end of ifdef MAC around copy_pigfile_from_cd
885
886 //initialize a pigfile, reading headers
887 //returns the size of all the bitmap data
888 void piggy_init_pigfile(char *filename)
889 {
890         int i;
891         char temp_name[16];
892         char temp_name_read[16];
893         grs_bitmap temp_bitmap;
894         DiskBitmapHeader bmh;
895         int header_size, N_bitmaps, data_size, data_start;
896         #ifdef MACINTOSH
897         char name[255];         // filename + path for the mac
898         #endif
899
900         piggy_close_file();             //close old pig if still open
901
902         //rename pigfile for shareware
903         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
904                 filename = DEFAULT_PIGFILE_SHAREWARE;
905
906         #ifndef MACINTOSH
907                 Piggy_fp = cfopen( filename, "rb" );
908         #else
909                 sprintf(name, ":Data:%s", filename);
910                 Piggy_fp = cfopen( name, "rb" );
911
912                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
913                         if (Piggy_fp == NULL)
914                         {
915                                 Error("Cannot load required file <%s>",name);
916                         }
917                 #endif  // end of if def shareware
918
919         #endif
920
921         if (!Piggy_fp) {
922                 #ifdef EDITOR
923                         return;         //if editor, ok to not have pig, because we'll build one
924                 #else
925                         Piggy_fp = copy_pigfile_from_cd(filename);
926                 #endif
927         }
928
929         if (Piggy_fp) {                         //make sure pig is valid type file & is up-to-date
930                 int pig_id,pig_version;
931
932                 pig_id = cfile_read_int(Piggy_fp);
933                 pig_version = cfile_read_int(Piggy_fp);
934                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
935                         cfclose(Piggy_fp);              //out of date pig
936                         Piggy_fp = NULL;                        //..so pretend it's not here
937                 }
938         }
939
940         if (!Piggy_fp) {
941
942                 #ifdef EDITOR
943                         return;         //if editor, ok to not have pig, because we'll build one
944                 #else
945                         Error("Cannot load required file <%s>",filename);
946                 #endif
947         }
948
949         strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
950
951         N_bitmaps = cfile_read_int(Piggy_fp);
952
953         header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
954
955         data_start = header_size + cftell(Piggy_fp);
956
957         data_size = cfilelength(Piggy_fp) - data_start;
958
959         Num_bitmap_files = 1;
960
961         for (i=0; i<N_bitmaps; i++ )    {
962                 DiskBitmapHeader_read(&bmh, Piggy_fp);
963                 memcpy( temp_name_read, bmh.name, 8 );
964                 temp_name_read[8] = 0;
965                 if ( bmh.dflags & DBM_FLAG_ABM )        
966                         sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
967                 else
968                         strcpy( temp_name, temp_name_read );
969                 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
970                 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
971                 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
972                 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
973                 temp_bitmap.avg_color = bmh.avg_color;
974                 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
975
976                 GameBitmapFlags[i+1] = 0;
977                 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
978                 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
979                 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
980                 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
981                 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
982
983                 GameBitmapOffset[i+1] = bmh.offset + data_start;
984                 Assert( (i+1) == Num_bitmap_files );
985                 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
986         }
987
988 #ifdef EDITOR
989         Piggy_bitmap_cache_size = data_size + (data_size/10);   //extra mem for new bitmaps
990         Assert( Piggy_bitmap_cache_size > 0 );
991 #else
992         Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
993         #ifdef MACINTOSH
994         if (piggy_low_memory)
995                 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
996         #endif
997 #endif
998         BitmapBits = d_malloc( Piggy_bitmap_cache_size );
999         if ( BitmapBits == NULL )
1000                 Error( "Not enough memory to load bitmaps\n" );
1001         Piggy_bitmap_cache_data = BitmapBits;
1002         Piggy_bitmap_cache_next = 0;
1003
1004         #if defined(MACINTOSH) && defined(SHAREWARE)
1005 //      load_exit_models();
1006         #endif
1007
1008         Pigfile_initialized=1;
1009 }
1010
1011 #define FILENAME_LEN 13
1012 #define MAX_BITMAPS_PER_BRUSH 30
1013
1014 extern int compute_average_pixel(grs_bitmap *new);
1015
1016 //reads in a new pigfile (for new palette)
1017 //returns the size of all the bitmap data
1018 void piggy_new_pigfile(char *pigname)
1019 {
1020         int i;
1021         char temp_name[16];
1022         char temp_name_read[16];
1023         grs_bitmap temp_bitmap;
1024         DiskBitmapHeader bmh;
1025         int header_size, N_bitmaps, data_size, data_start;
1026         int must_rewrite_pig = 0;
1027         #ifdef MACINTOSH
1028         char name[255];
1029         #endif
1030
1031         strlwr(pigname);
1032
1033         //rename pigfile for shareware
1034         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
1035                 pigname = DEFAULT_PIGFILE_SHAREWARE;
1036
1037         if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
1038                 return;         //already have correct pig
1039
1040         if (!Pigfile_initialized) {                     //have we ever opened a pigfile?
1041                 piggy_init_pigfile(pigname);            //..no, so do initialization stuff
1042                 return;
1043         }
1044         else
1045                 piggy_close_file();             //close old pig if still open
1046
1047         Piggy_bitmap_cache_next = 0;            //free up cache
1048
1049         strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
1050
1051         #ifndef MACINTOSH
1052                 Piggy_fp = cfopen( pigname, "rb" );
1053         #else
1054                 sprintf(name, ":Data:%s", pigname);
1055                 Piggy_fp = cfopen( name, "rb" );
1056
1057                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
1058                         if (Piggy_fp == NULL)
1059                         {
1060                                 Error("Cannot load required file <%s>",name);
1061                         }
1062                 #endif  // end of if def shareware
1063         #endif
1064
1065         #ifndef EDITOR
1066         if (!Piggy_fp)
1067                 Piggy_fp = copy_pigfile_from_cd(pigname);
1068         #endif
1069
1070         if (Piggy_fp) {  //make sure pig is valid type file & is up-to-date
1071                 int pig_id,pig_version;
1072
1073                 pig_id = cfile_read_int(Piggy_fp);
1074                 pig_version = cfile_read_int(Piggy_fp);
1075                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
1076                         cfclose(Piggy_fp);              //out of date pig
1077                         Piggy_fp = NULL;                        //..so pretend it's not here
1078                 }
1079         }
1080
1081         #ifndef EDITOR
1082         if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
1083         #endif
1084
1085         if (Piggy_fp) {
1086
1087                 N_bitmaps = cfile_read_int(Piggy_fp);
1088
1089                 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
1090
1091                 data_start = header_size + cftell(Piggy_fp);
1092
1093                 data_size = cfilelength(Piggy_fp) - data_start;
1094
1095                 for (i=1; i<=N_bitmaps; i++ )   {
1096                         DiskBitmapHeader_read(&bmh, Piggy_fp);
1097                         memcpy( temp_name_read, bmh.name, 8 );
1098                         temp_name_read[8] = 0;
1099         
1100                         if ( bmh.dflags & DBM_FLAG_ABM )        
1101                                 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
1102                         else
1103                                 strcpy( temp_name, temp_name_read );
1104         
1105                         //Make sure name matches
1106                         if (strcmp(temp_name,AllBitmaps[i].name)) {
1107                                 //Int3();       //this pig is out of date.  Delete it
1108                                 must_rewrite_pig=1;
1109                         }
1110         
1111                         strcpy(AllBitmaps[i].name,temp_name);
1112
1113                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1114         
1115                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1116                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1117                         temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
1118                         temp_bitmap.avg_color = bmh.avg_color;
1119                         temp_bitmap.bm_data = Piggy_bitmap_cache_data;
1120
1121                         GameBitmapFlags[i] = 0;
1122
1123                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
1124                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
1125                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
1126                         if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
1127                         if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
1128         
1129                         GameBitmapOffset[i] = bmh.offset + data_start;
1130         
1131                         GameBitmaps[i] = temp_bitmap;
1132                 }
1133         }
1134         else
1135                 N_bitmaps = 0;          //no pigfile, so no bitmaps
1136
1137         #ifndef EDITOR
1138
1139         Assert(N_bitmaps == Num_bitmap_files-1);
1140
1141         #else
1142
1143         if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
1144                 int size;
1145
1146                 //re-read the bitmaps that aren't in this pig
1147
1148                 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
1149                         char *p;
1150
1151                         p = strchr(AllBitmaps[i].name,'#');
1152
1153                         if (p) {                //this is an ABM
1154                                 char abmname[FILENAME_LEN];
1155                                 int fnum;
1156                                 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
1157                                 int iff_error;          //reference parm to avoid warning message
1158                                 ubyte newpal[768];
1159                                 char basename[FILENAME_LEN];
1160                                 int nframes;
1161                         
1162                                 strcpy(basename,AllBitmaps[i].name);
1163                                 basename[p-AllBitmaps[i].name] = 0;             //cut off "#nn" part
1164                                 
1165                                 sprintf( abmname, "%s.abm", basename );
1166
1167                                 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
1168
1169                                 if (iff_error != IFF_NO_ERROR)  {
1170                                         mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
1171                                         Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
1172                                 }
1173                         
1174                                 for (fnum=0;fnum<nframes; fnum++)       {
1175                                         char tempname[20];
1176                                         int SuperX;
1177
1178                                         sprintf( tempname, "%s#%d", basename, fnum );
1179
1180                                         //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1181                                         SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1182                                         //above makes assumption that supertransparent color is 254
1183
1184                                         if ( iff_has_transparency )
1185                                                 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
1186                                         else
1187                                                 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
1188
1189                                         bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
1190
1191 #ifdef EDITOR
1192                                         if ( FindArg("-macdata") )
1193                                                 swap_0_255( bm[fnum] );
1194 #endif
1195                                         if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
1196
1197                                         if (bm[fnum]->bm_flags & BM_FLAG_RLE)
1198                                                 size = *((int *) bm[fnum]->bm_data);
1199                                         else
1200                                                 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
1201
1202                                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
1203                                         d_free(bm[fnum]->bm_data);
1204                                         bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1205                                         Piggy_bitmap_cache_next += size;
1206
1207                                         GameBitmaps[i+fnum] = *bm[fnum];
1208
1209                                         // -- mprintf( (0, "U" ));
1210                                         d_free( bm[fnum] );
1211                                 }
1212
1213                                 i += nframes-1;         //filled in multiple bitmaps
1214                         }
1215                         else {          //this is a BBM
1216
1217                                 grs_bitmap * new;
1218                                 ubyte newpal[256*3];
1219                                 int iff_error;
1220                                 char bbmname[FILENAME_LEN];
1221                                 int SuperX;
1222
1223                                 MALLOC( new, grs_bitmap, 1 );
1224
1225                                 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
1226                                 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
1227
1228                                 new->bm_handle=0;
1229                                 if (iff_error != IFF_NO_ERROR)          {
1230                                         mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
1231                                         Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
1232                                 }
1233
1234                                 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1235                                 //above makes assumption that supertransparent color is 254
1236
1237                                 if ( iff_has_transparency )
1238                                         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
1239                                 else
1240                                         gr_remap_bitmap_good( new, newpal, -1, SuperX );
1241
1242                                 new->avg_color = compute_average_pixel(new);
1243
1244 #ifdef EDITOR
1245                                 if ( FindArg("-macdata") )
1246                                         swap_0_255( new );
1247 #endif
1248                                 if ( !BigPig )  gr_bitmap_rle_compress( new );
1249
1250                                 if (new->bm_flags & BM_FLAG_RLE)
1251                                         size = *((int *) new->bm_data);
1252                                 else
1253                                         size = new->bm_w * new->bm_h;
1254
1255                                 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
1256                                 d_free(new->bm_data);
1257                                 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1258                                 Piggy_bitmap_cache_next += size;
1259
1260                                 GameBitmaps[i] = *new;
1261         
1262                                 d_free( new );
1263
1264                                 // -- mprintf( (0, "U" ));
1265                         }
1266                 }
1267
1268                 //@@Dont' do these things which are done when writing
1269                 //@@for (i=0; i < Num_bitmap_files; i++ )       {
1270                 //@@    bitmap_index bi;
1271                 //@@    bi.index = i;
1272                 //@@    PIGGY_PAGE_IN( bi );
1273                 //@@}
1274                 //@@
1275                 //@@piggy_close_file();
1276
1277                 piggy_write_pigfile(pigname);
1278
1279                 Current_pigfile[0] = 0;                 //say no pig, to force reload
1280
1281                 piggy_new_pigfile(pigname);             //read in just-generated pig
1282
1283
1284         }
1285         #endif  //ifdef EDITOR
1286
1287 }
1288
1289 ubyte bogus_data[64*64];
1290 grs_bitmap bogus_bitmap;
1291 ubyte bogus_bitmap_initialized=0;
1292 digi_sound bogus_sound;
1293
1294 #define HAMFILE_ID              MAKE_SIG('!','M','A','H') //HAM!
1295 #define HAMFILE_VERSION 3
1296 //version 1 -> 2:  save marker_model_num
1297 //version 2 -> 3:  removed sound files
1298
1299 #define SNDFILE_ID              MAKE_SIG('D','N','S','D') //DSND
1300 #define SNDFILE_VERSION 1
1301
1302 int read_hamfile()
1303 {
1304         CFILE * ham_fp = NULL;
1305         int ham_id;
1306         int sound_offset = 0;
1307         #ifdef MACINTOSH
1308         char name[255];
1309         #endif
1310
1311         #ifndef MACINTOSH
1312         ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1313         #else
1314         sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1315         ham_fp = cfopen( name, "rb" );
1316         #endif
1317
1318         if (ham_fp == NULL) {
1319                 Must_write_hamfile = 1;
1320                 return 0;
1321         }
1322
1323         //make sure ham is valid type file & is up-to-date
1324         ham_id = cfile_read_int(ham_fp);
1325         Piggy_hamfile_version = cfile_read_int(ham_fp);
1326         if (ham_id != HAMFILE_ID)
1327                 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1328 #if 0
1329         if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1330                 Must_write_hamfile = 1;
1331                 cfclose(ham_fp);                                                //out of date ham
1332                 return 0;
1333         }
1334 #endif
1335
1336         if (Piggy_hamfile_version < 3) // hamfile contains sound info
1337                 sound_offset = cfile_read_int(ham_fp);
1338
1339         #ifndef EDITOR
1340         {
1341                 //int i;
1342
1343                 bm_read_all(ham_fp);
1344                 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1345                 // no swap here?
1346                 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1347                         //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1348                         //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1349                 //}
1350         }
1351         #endif
1352
1353         if (Piggy_hamfile_version < 3) {
1354                 int N_sounds;
1355                 int sound_start;
1356                 int header_size;
1357                 int i;
1358                 DiskSoundHeader sndh;
1359                 digi_sound temp_sound;
1360                 char temp_name_read[16];
1361                 int sbytes = 0;
1362
1363                 cfseek(ham_fp, sound_offset, SEEK_SET);
1364                 N_sounds = cfile_read_int(ham_fp);
1365
1366                 sound_start = cftell(ham_fp);
1367
1368                 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1369
1370                 //Read sounds
1371
1372                 for (i=0; i<N_sounds; i++ ) {
1373                         DiskSoundHeader_read(&sndh, ham_fp);
1374                         temp_sound.length = sndh.length;
1375                         temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1376                         SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1377                         memcpy( temp_name_read, sndh.name, 8 );
1378                         temp_name_read[8] = 0;
1379                         piggy_register_sound( &temp_sound, temp_name_read, 1 );
1380 #ifdef MACINTOSH
1381                         if (piggy_is_needed(i))
1382 #endif          // note link to if.
1383                                 sbytes += sndh.length;
1384                         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1385                 }
1386
1387                 SoundBits = d_malloc( sbytes + 16 );
1388                 if ( SoundBits == NULL )
1389                         Error( "Not enough memory to load sounds\n" );
1390
1391                 mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1392
1393                 //      piggy_read_sounds(ham_fp);
1394
1395         }
1396
1397         cfclose(ham_fp);
1398
1399         return 1;
1400
1401 }
1402
1403 int read_sndfile()
1404 {
1405         CFILE * snd_fp = NULL;
1406         int snd_id,snd_version;
1407         int N_sounds;
1408         int sound_start;
1409         int header_size;
1410         int i,size, length;
1411         DiskSoundHeader sndh;
1412         digi_sound temp_sound;
1413         char temp_name_read[16];
1414         int sbytes = 0;
1415         #ifdef MACINTOSH
1416         char name[255];
1417         #endif
1418
1419         #ifndef MACINTOSH
1420         snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1421         #else
1422         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1423         snd_fp = cfopen( name, "rb");
1424         #endif
1425         
1426         if (snd_fp == NULL)
1427                 return 0;
1428
1429         //make sure soundfile is valid type file & is up-to-date
1430         snd_id = cfile_read_int(snd_fp);
1431         snd_version = cfile_read_int(snd_fp);
1432         if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1433                 cfclose(snd_fp);                                                //out of date sound file
1434                 return 0;
1435         }
1436
1437         N_sounds = cfile_read_int(snd_fp);
1438
1439         sound_start = cftell(snd_fp);
1440         size = cfilelength(snd_fp) - sound_start;
1441         length = size;
1442         mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1443
1444         header_size = N_sounds*sizeof(DiskSoundHeader);
1445
1446         //Read sounds
1447
1448         for (i=0; i<N_sounds; i++ ) {
1449                 DiskSoundHeader_read(&sndh, snd_fp);
1450                 //size -= sizeof(DiskSoundHeader);
1451                 temp_sound.length = sndh.length;
1452                 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1453                 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1454                 memcpy( temp_name_read, sndh.name, 8 );
1455                 temp_name_read[8] = 0;
1456                 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1457                 #ifdef MACINTOSH
1458                 if (piggy_is_needed(i))
1459                 #endif          // note link to if.
1460                 sbytes += sndh.length;
1461                 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1462         }
1463
1464         SoundBits = d_malloc( sbytes + 16 );
1465         if ( SoundBits == NULL )
1466                 Error( "Not enough memory to load sounds\n" );
1467
1468         mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1469
1470 //      piggy_read_sounds(snd_fp);
1471
1472         cfclose(snd_fp);
1473
1474         return 1;
1475 }
1476
1477 int piggy_init(void)
1478 {
1479         int ham_ok=0,snd_ok=0;
1480         int i;
1481
1482         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1483         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1484
1485         for (i=0; i<MAX_SOUND_FILES; i++ )      {
1486                 GameSounds[i].length = 0;
1487                 GameSounds[i].data = NULL;
1488                 SoundOffset[i] = 0;
1489         }
1490
1491         for (i=0; i<MAX_BITMAP_FILES; i++ )     
1492                 GameBitmapXlat[i] = i;
1493
1494         if ( !bogus_bitmap_initialized )        {
1495                 int i;
1496                 ubyte c;
1497                 bogus_bitmap_initialized = 1;
1498                 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1499                 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1500                 bogus_bitmap.bm_data = bogus_data;
1501                 c = gr_find_closest_color( 0, 0, 63 );
1502                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1503                 c = gr_find_closest_color( 63, 0, 0 );
1504                 // Make a big red X !
1505                 for (i=0; i<64; i++ )   {
1506                         bogus_data[i*64+i] = c;
1507                         bogus_data[i*64+(63-i)] = c;
1508                 }
1509                 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1510                 bogus_sound.length = 64*64;
1511                 bogus_sound.data = bogus_data;
1512                 GameBitmapOffset[0] = 0;
1513         }
1514
1515         if ( FindArg( "-bigpig" ))
1516                 BigPig = 1;
1517
1518         if ( FindArg( "-lowmem" ))
1519                 piggy_low_memory = 1;
1520
1521         if ( FindArg( "-nolowmem" ))
1522                 piggy_low_memory = 0;
1523
1524         if (piggy_low_memory)
1525                 digi_lomem = 1;
1526
1527         WIN(DDGRLOCK(dd_grd_curcanv));
1528                 gr_set_curfont( SMALL_FONT );
1529                 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1530                 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1531         WIN(DDGRUNLOCK(dd_grd_curcanv));
1532
1533 #if 1 //def EDITOR //need for d1 mission briefings
1534         piggy_init_pigfile(DEFAULT_PIGFILE);
1535 #endif
1536
1537         snd_ok = ham_ok = read_hamfile();
1538
1539         if (Piggy_hamfile_version >= 3)
1540                 snd_ok = read_sndfile();
1541
1542         atexit(piggy_close);
1543
1544         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1545         return (ham_ok && snd_ok);               //read ok
1546 }
1547
1548 int piggy_is_needed(int soundnum)
1549 {
1550         int i;
1551
1552         if ( !digi_lomem ) return 1;
1553
1554         for (i=0; i<MAX_SOUNDS; i++ )   {
1555                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1556                         return 1;
1557         }
1558         return 0;
1559 }
1560
1561
1562 void piggy_read_sounds(void)
1563 {
1564         CFILE * fp = NULL;
1565         ubyte * ptr;
1566         int i, sbytes;
1567         #ifdef MACINTOSH
1568         char name[255];
1569         #endif
1570
1571         ptr = SoundBits;
1572         sbytes = 0;
1573
1574         #ifndef MACINTOSH
1575         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1576         #else
1577         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1578         fp = cfopen( name, "rb");
1579         #endif
1580
1581         if (fp == NULL)
1582                 return;
1583
1584         for (i=0; i<Num_sound_files; i++ )      {
1585                 digi_sound *snd = &GameSounds[i];
1586
1587                 if ( SoundOffset[i] > 0 )       {
1588                         if ( piggy_is_needed(i) )       {
1589                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1590
1591                                 // Read in the sound data!!!
1592                                 snd->data = ptr;
1593                                 ptr += snd->length;
1594                                 sbytes += snd->length;
1595                                 cfread( snd->data, snd->length, 1, fp );
1596                         }
1597                         else
1598                                 snd->data = (ubyte *) -1;
1599                 }
1600         }
1601
1602         cfclose(fp);
1603
1604         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1605
1606 }
1607
1608
1609 extern int descent_critical_error;
1610 extern unsigned descent_critical_deverror;
1611 extern unsigned descent_critical_errcode;
1612
1613 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1614 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1615 "Read fault", "General Failure" };
1616
1617 void piggy_critical_error()
1618 {
1619         grs_canvas * save_canv;
1620         grs_font * save_font;
1621         int i;
1622         save_canv = grd_curcanv;
1623         save_font = grd_curcanv->cv_font;
1624         gr_palette_load( gr_palette );
1625         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1626         if ( i == 1 )
1627                 exit(1);
1628         gr_set_current_canvas(save_canv);
1629         grd_curcanv->cv_font = save_font;
1630 }
1631
1632 void piggy_bitmap_page_in( bitmap_index bitmap )
1633 {
1634         grs_bitmap * bmp;
1635         int i,org_i,temp;
1636
1637         org_i = 0;
1638
1639         i = bitmap.index;
1640         Assert( i >= 0 );
1641         Assert( i < MAX_BITMAP_FILES );
1642         Assert( i < Num_bitmap_files );
1643         Assert( Piggy_bitmap_cache_size > 0 );
1644
1645         if ( i < 1 ) return;
1646         if ( i >= MAX_BITMAP_FILES ) return;
1647         if ( i >= Num_bitmap_files ) return;
1648
1649         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1650
1651         if ( piggy_low_memory ) {
1652                 org_i = i;
1653                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1654         }
1655
1656         bmp = &GameBitmaps[i];
1657
1658         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1659                 stop_time();
1660
1661         ReDoIt:
1662                 descent_critical_error = 0;
1663                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1664                 if ( descent_critical_error )   {
1665                         piggy_critical_error();
1666                         goto ReDoIt;
1667                 }
1668
1669                 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1670                 bmp->bm_flags = GameBitmapFlags[i];
1671
1672                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1673                         int zsize = 0;
1674                         descent_critical_error = 0;
1675                         zsize = cfile_read_int(Piggy_fp);
1676                         if ( descent_critical_error )   {
1677                                 piggy_critical_error();
1678                                 goto ReDoIt;
1679                         }
1680
1681                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1682                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1683                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1684                                 Int3();
1685                                 piggy_bitmap_page_out_all();
1686                                 goto ReDoIt;
1687                         }
1688                         descent_critical_error = 0;
1689                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1690                         if ( descent_critical_error )   {
1691                                 piggy_critical_error();
1692                                 goto ReDoIt;
1693                         }
1694
1695 #ifndef MACDATA
1696                         switch (cfilelength(Piggy_fp)) {
1697                         default:
1698                                 if (!FindArg("-macdata"))
1699                                         break;
1700                                 // otherwise, fall through...
1701                         case MAC_ALIEN1_PIGSIZE:
1702                         case MAC_ALIEN2_PIGSIZE:
1703                         case MAC_FIRE_PIGSIZE:
1704                         case MAC_GROUPA_PIGSIZE:
1705                         case MAC_ICE_PIGSIZE:
1706                         case MAC_WATER_PIGSIZE:
1707                                 rle_swap_0_255( bmp );
1708                                 memcpy(&zsize, bmp->bm_data, 4);
1709                                 break;
1710                         }
1711 #endif
1712
1713                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1714                         Piggy_bitmap_cache_next += zsize;
1715                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1716                                 Int3();
1717                                 piggy_bitmap_page_out_all();
1718                                 goto ReDoIt;
1719                         }
1720
1721                 } else {
1722                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1723                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1724                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1725                                 piggy_bitmap_page_out_all();
1726                                 goto ReDoIt;
1727                         }
1728                         descent_critical_error = 0;
1729                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1730                         if ( descent_critical_error )   {
1731                                 piggy_critical_error();
1732                                 goto ReDoIt;
1733                         }
1734                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1735
1736 #ifndef MACDATA
1737                         switch (cfilelength(Piggy_fp)) {
1738                         default:
1739                                 if (!FindArg("-macdata"))
1740                                         break;
1741                                 // otherwise, fall through...
1742                         case MAC_ALIEN1_PIGSIZE:
1743                         case MAC_ALIEN2_PIGSIZE:
1744                         case MAC_FIRE_PIGSIZE:
1745                         case MAC_GROUPA_PIGSIZE:
1746                         case MAC_ICE_PIGSIZE:
1747                         case MAC_WATER_PIGSIZE:
1748                                 swap_0_255( bmp );
1749                                 break;
1750                         }
1751 #endif
1752                 }
1753
1754                 //@@if ( bmp->bm_selector ) {
1755                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1756                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1757                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1758                 //@@#endif
1759                 //@@}
1760
1761                 start_time();
1762         }
1763
1764         if ( piggy_low_memory ) {
1765                 if ( org_i != i )
1766                         GameBitmaps[org_i] = GameBitmaps[i];
1767         }
1768
1769 //@@Removed from John's code:
1770 //@@#ifndef WINDOWS
1771 //@@    if ( bmp->bm_selector ) {
1772 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1773 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1774 //@@    }
1775 //@@#endif
1776
1777 }
1778
1779 void piggy_bitmap_page_out_all()
1780 {
1781         int i;
1782         
1783         Piggy_bitmap_cache_next = 0;
1784
1785         piggy_page_flushed++;
1786
1787         texmerge_flush();
1788         rle_cache_flush();
1789
1790         for (i=0; i<Num_bitmap_files; i++ )             {
1791                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1792                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1793                         GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1794                 }
1795         }
1796
1797         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1798 }
1799
1800 void piggy_load_level_data()
1801 {
1802         piggy_bitmap_page_out_all();
1803         paging_touch_all();
1804 }
1805
1806 #ifdef EDITOR
1807
1808 void change_filename_ext( char *dest, char *src, char *ext );
1809
1810 void piggy_write_pigfile(char *filename)
1811 {
1812         FILE *pig_fp;
1813         int bitmap_data_start,data_offset;
1814         DiskBitmapHeader bmh;
1815         int org_offset;
1816         char subst_name[32];
1817         int i;
1818         FILE *fp1,*fp2;
1819         char tname[FILENAME_LEN];
1820
1821         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1822         for (i=0; i < Num_bitmap_files; i++ )   {
1823                 bitmap_index bi;
1824                 bi.index = i;
1825                 PIGGY_PAGE_IN( bi );
1826         }
1827         // -- mprintf( (0, "\n" ));
1828
1829         piggy_close_file();
1830
1831         // -- mprintf( (0, "Creating %s...",filename ));
1832
1833         pig_fp = fopen( filename, "wb" );       //open PIG file
1834         Assert( pig_fp!=NULL );
1835
1836         write_int(PIGFILE_ID,pig_fp);
1837         write_int(PIGFILE_VERSION,pig_fp);
1838
1839         Num_bitmap_files--;
1840         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1841         Num_bitmap_files++;
1842
1843         bitmap_data_start = ftell(pig_fp);
1844         bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE; 
1845         data_offset = bitmap_data_start;
1846
1847         change_filename_ext(tname,filename,"lst");
1848         fp1 = fopen( tname, "wt" );
1849         change_filename_ext(tname,filename,"all");
1850         fp2 = fopen( tname, "wt" );
1851
1852         for (i=1; i < Num_bitmap_files; i++ )   {
1853                 int *size;
1854                 grs_bitmap *bmp;
1855
1856                 {               
1857                         char * p, *p1;
1858                         p = strchr(AllBitmaps[i].name,'#');
1859                         if (p)  {
1860                                 int n;
1861                                 p1 = p; p1++; 
1862                                 n = atoi(p1);
1863                                 *p = 0;
1864                                 if (fp2 && n==0)
1865                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1866                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1867                                 Assert( n <= 63 );
1868                                 bmh.dflags = DBM_FLAG_ABM + n;
1869                                 *p = '#';
1870                         }else {
1871                                 if (fp2)
1872                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1873                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1874                                 bmh.dflags = 0;
1875                         }
1876                 }
1877                 bmp = &GameBitmaps[i];
1878
1879                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1880
1881                 if (fp1)
1882                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1883                 org_offset = ftell(pig_fp);
1884                 bmh.offset = data_offset - bitmap_data_start;
1885                 fseek( pig_fp, data_offset, SEEK_SET );
1886
1887                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1888                         size = (int *)bmp->bm_data;
1889                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1890                         data_offset += *size;
1891                         if (fp1)
1892                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1893                 } else {
1894                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1895                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1896                         if (fp1)
1897                                 fprintf( fp1, ".\n" );
1898                 }
1899                 fseek( pig_fp, org_offset, SEEK_SET );
1900                 Assert( GameBitmaps[i].bm_w < 4096 );
1901                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1902                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1903                 Assert( GameBitmaps[i].bm_h < 4096 );
1904                 bmh.height = GameBitmaps[i].bm_h;
1905                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1906                 bmh.flags = GameBitmaps[i].bm_flags;
1907                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1908                         bitmap_index other_bitmap;
1909                         other_bitmap = piggy_find_bitmap( subst_name );
1910                         GameBitmapXlat[i] = other_bitmap.index;
1911                         bmh.flags |= BM_FLAG_PAGED_OUT;
1912                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1913                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1914                 } else  {
1915                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1916                 }
1917                 bmh.avg_color=GameBitmaps[i].avg_color;
1918                 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp );                    // Mark as a bitmap
1919         }
1920
1921         fclose(pig_fp);
1922
1923         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1924         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1925
1926         fclose(fp1);
1927         fclose(fp2);
1928
1929 }
1930
1931 static void write_int(int i,FILE *file)
1932 {
1933         if (fwrite( &i, sizeof(i), 1, file) != 1)
1934                 Error( "Error reading int in gamesave.c" );
1935
1936 }
1937
1938 void piggy_dump_all()
1939 {
1940         int i, xlat_offset;
1941         FILE * ham_fp;
1942         int org_offset,data_offset=0;
1943         DiskSoundHeader sndh;
1944         int sound_data_start=0;
1945         FILE *fp1,*fp2;
1946
1947         #ifdef NO_DUMP_SOUNDS
1948         Num_sound_files = 0;
1949         Num_sound_files_new = 0;
1950         #endif
1951
1952         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1953                 return;
1954
1955         fp1 = fopen( "ham.lst", "wt" );
1956         fp2 = fopen( "ham.all", "wt" );
1957
1958         if (Must_write_hamfile || Num_bitmap_files_new) {
1959
1960                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1961         
1962                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1963                 Assert( ham_fp!=NULL );
1964         
1965                 write_int(HAMFILE_ID,ham_fp);
1966                 write_int(HAMFILE_VERSION,ham_fp);
1967         
1968                 bm_write_all(ham_fp);
1969                 xlat_offset = ftell(ham_fp);
1970                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1971                 //Dump bitmaps
1972         
1973                 if (Num_bitmap_files_new)
1974                         piggy_write_pigfile(DEFAULT_PIGFILE);
1975         
1976                 //free up memeory used by new bitmaps
1977                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1978                         d_free(GameBitmaps[i].bm_data);
1979         
1980                 //next thing must be done after pig written
1981                 fseek( ham_fp, xlat_offset, SEEK_SET );
1982                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1983         
1984                 fclose(ham_fp);
1985                 mprintf( (0, "\n" ));
1986         }
1987         
1988         if (Num_sound_files_new) {
1989
1990                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1991                 // Now dump sound file
1992                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1993                 Assert( ham_fp!=NULL );
1994         
1995                 write_int(SNDFILE_ID,ham_fp);
1996                 write_int(SNDFILE_VERSION,ham_fp);
1997
1998                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1999         
2000                 mprintf( (0, "\nDumping sounds..." ));
2001         
2002                 sound_data_start = ftell(ham_fp);
2003                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
2004                 data_offset = sound_data_start;
2005         
2006                 for (i=0; i < Num_sound_files; i++ )    {
2007                         digi_sound *snd;
2008         
2009                         snd = &GameSounds[i];
2010                         strcpy( sndh.name, AllSounds[i].name );
2011                         sndh.length = GameSounds[i].length;
2012                         sndh.offset = data_offset - sound_data_start;
2013         
2014                         org_offset = ftell(ham_fp);
2015                         fseek( ham_fp, data_offset, SEEK_SET );
2016         
2017                         sndh.data_length = GameSounds[i].length;
2018                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
2019                         data_offset += snd->length;
2020                         fseek( ham_fp, org_offset, SEEK_SET );
2021                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
2022         
2023                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
2024                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
2025                 }
2026
2027                 fclose(ham_fp);
2028                 mprintf( (0, "\n" ));
2029         }
2030
2031         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
2032         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
2033         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
2034
2035         fclose(fp1);
2036         fclose(fp2);
2037
2038         // Never allow the game to run after building ham.
2039         exit(0);
2040 }
2041
2042 #endif
2043
2044 void piggy_close()
2045 {
2046         piggy_close_file();
2047
2048         if (BitmapBits)
2049                 d_free(BitmapBits);
2050
2051         if ( SoundBits )
2052                 d_free( SoundBits );
2053
2054         hashtable_free( &AllBitmapsNames );
2055         hashtable_free( &AllDigiSndNames );
2056
2057 }
2058
2059 int piggy_does_bitmap_exist_slow( char * name )
2060 {
2061         int i;
2062
2063         for (i=0; i<Num_bitmap_files; i++ )     {
2064                 if ( !strcmp( AllBitmaps[i].name, name) )
2065                         return 1;
2066         }
2067         return 0;
2068 }
2069
2070
2071 #define NUM_GAUGE_BITMAPS 23
2072 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
2073         "gauge01", "gauge01b",
2074         "gauge02", "gauge02b",
2075         "gauge06", "gauge06b",
2076         "targ01", "targ01b",
2077         "targ02", "targ02b", 
2078         "targ03", "targ03b",
2079         "targ04", "targ04b",
2080         "targ05", "targ05b",
2081         "targ06", "targ06b",
2082         "gauge18", "gauge18b",
2083         "gauss1", "helix1",
2084         "phoenix1"
2085 };
2086
2087
2088 int piggy_is_gauge_bitmap( char * base_name )
2089 {
2090         int i;
2091         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
2092                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
2093                         return 1;
2094         }
2095
2096         return 0;       
2097 }
2098
2099 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
2100 {
2101         int frame;
2102         char * p;
2103         char base_name[ 16 ];
2104         
2105         strcpy( subst_name, name );
2106         p = strchr( subst_name, '#' );
2107         if ( p )        {
2108                 frame = atoi( &p[1] );
2109                 *p = 0;
2110                 strcpy( base_name, subst_name );
2111                 if ( !piggy_is_gauge_bitmap( base_name ))       {
2112                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
2113                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
2114                                 if ( frame & 1 ) {
2115                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
2116                                         return 1;
2117                                 }
2118                         }
2119                 }
2120         }
2121         strcpy( subst_name, name );
2122         return 0;
2123 }
2124
2125
2126
2127 #ifdef WINDOWS
2128 //      New Windows stuff
2129
2130 //      windows bitmap page in
2131 //              Page in a bitmap, if ddraw, then page it into a ddsurface in 
2132 //              'video' memory.  if that fails, page it in normally.
2133
2134 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
2135 {
2136 }
2137
2138
2139 //      Essential when switching video modes!
2140
2141 void piggy_bitmap_page_out_all_w()
2142 {
2143 }
2144
2145 #endif // WINDOWS
2146
2147
2148 /*
2149  * Functions for loading replacement textures
2150  *  1) From .pog files
2151  *  2) From descent.pig (for loading d1 levels)
2152  */
2153
2154 extern void change_filename_extension( char *dest, char *src, char *new_ext );
2155 extern char last_palette_loaded_pig[];
2156
2157 ubyte *Bitmap_replacement_data=NULL;
2158
2159 void free_bitmap_replacements()
2160 {
2161         if (Bitmap_replacement_data) {
2162                 d_free(Bitmap_replacement_data);
2163                 Bitmap_replacement_data = NULL;
2164         }
2165 }
2166
2167 void load_bitmap_replacements(char *level_name)
2168 {
2169         char ifile_name[FILENAME_LEN];
2170         CFILE *ifile;
2171         int i;
2172
2173         //first, free up data allocated for old bitmaps
2174         free_bitmap_replacements();
2175
2176         change_filename_extension(ifile_name, level_name, ".POG" );
2177
2178         ifile = cfopen(ifile_name,"rb");
2179
2180         if (ifile) {
2181                 int id,version,n_bitmaps;
2182                 int bitmap_data_size;
2183                 ushort *indices;
2184
2185                 id = cfile_read_int(ifile);
2186                 version = cfile_read_int(ifile);
2187
2188                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
2189                         cfclose(ifile);
2190                         return;
2191                 }
2192
2193                 n_bitmaps = cfile_read_int(ifile);
2194
2195                 MALLOC( indices, ushort, n_bitmaps );
2196
2197                 for (i = 0; i < n_bitmaps; i++)
2198                         indices[i] = cfile_read_short(ifile);
2199
2200                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - DISKBITMAPHEADER_SIZE * n_bitmaps;
2201                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
2202
2203                 for (i=0;i<n_bitmaps;i++) {
2204                         DiskBitmapHeader bmh;
2205                         grs_bitmap temp_bitmap;
2206
2207                         DiskBitmapHeader_read(&bmh, ifile);
2208
2209                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2210
2211                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2212                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2213                         temp_bitmap.avg_color = bmh.avg_color;
2214                         temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
2215
2216                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2217                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2218                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2219                         if ( bmh.flags & BM_FLAG_RLE ) temp_bitmap.bm_flags |= BM_FLAG_RLE;
2220                         if ( bmh.flags & BM_FLAG_RLE_BIG ) temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2221
2222                         GameBitmaps[indices[i]] = temp_bitmap;
2223                 }
2224
2225                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
2226
2227                 d_free(indices);
2228
2229                 cfclose(ifile);
2230
2231                 last_palette_loaded_pig[0]= 0;  //force pig re-load
2232
2233                 texmerge_flush();       //for re-merging with new textures
2234         }
2235
2236         atexit(free_bitmap_replacements);
2237 }
2238
2239 #define FIRST_D1_TEXTURE 722
2240 #define LAST_D1_STATIC_TEXTURE 1042//1342 //afterwards, we have door frames and stuff
2241 #define FIRST_D2_TEXTURE 1243
2242
2243 void load_d1_bitmap_replacements()
2244 {
2245         CFILE * d1_Piggy_fp;
2246         grs_bitmap temp_bitmap;
2247         DiskBitmapHeader bmh;
2248         int pig_data_start, bitmap_header_start, bitmap_data_start;
2249         int N_bitmaps, zsize;
2250         int d1_index, d2_index;
2251         ubyte colormap[256];
2252         ubyte *next_bitmap; // to which address we write the next bitmap
2253
2254         d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2255
2256         if (!d1_Piggy_fp)
2257                 return; // use d2 bitmaps instead...
2258
2259         //first, free up data allocated for old bitmaps
2260         free_bitmap_replacements();
2261
2262         // read d1 palette, build colormap
2263         {
2264                 int freq[256];
2265                 ubyte d1_palette[256*3];
2266                 CFILE * palette_file = cfopen( "palette.256", "rb" );
2267                 Assert( palette_file );
2268                 Assert( cfilelength( palette_file ) == 9472 );
2269                 cfread( d1_palette, 256, 3, palette_file);
2270                 cfclose( palette_file );
2271                 build_colormap_good( d1_palette, colormap, freq );
2272                 // don't change transparencies:
2273                 colormap[254] = 254;
2274                 colormap[255] = 255;
2275         }
2276
2277         switch (cfilelength(d1_Piggy_fp)) {
2278         case D1_SHAREWARE_10_PIGSIZE:
2279         case D1_SHAREWARE_PIGSIZE:
2280                 pig_data_start = 0;
2281                 break;
2282         default:
2283                 Int3();
2284         case D1_PIGSIZE:
2285         case D1_OEM_PIGSIZE:
2286         case D1_MAC_PIGSIZE:
2287         case D1_MAC_SHARE_PIGSIZE:
2288                 //int i;
2289                 pig_data_start = cfile_read_int(d1_Piggy_fp );
2290                 bm_read_all_d1( d1_Piggy_fp );
2291                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2292                 break;
2293         }
2294
2295         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2296         N_bitmaps = cfile_read_int(d1_Piggy_fp);
2297         {
2298                 int N_sounds = cfile_read_int(d1_Piggy_fp);
2299                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2300                         + N_sounds * DISKSOUNDHEADER_SIZE;
2301                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2302                 bitmap_data_start = bitmap_header_start + header_size;
2303         }
2304
2305         MALLOC( Bitmap_replacement_data, ubyte, cfilelength(d1_Piggy_fp) - bitmap_data_start ); // too much
2306         //TODO: handle case where b_r_d == 0! (have to convert textures, return, not bm_read_all_d1)
2307
2308         next_bitmap = Bitmap_replacement_data;
2309
2310         for (d1_index=1; d1_index<=N_bitmaps; d1_index++ ) {
2311                 // only change wall texture bitmaps
2312                 if (d1_index >= FIRST_D1_TEXTURE && d1_index <= LAST_D1_STATIC_TEXTURE) {
2313                         d2_index = d1_index + FIRST_D2_TEXTURE - FIRST_D1_TEXTURE;
2314
2315                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2316                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2317
2318                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2319
2320                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2321                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2322                         temp_bitmap.avg_color = bmh.avg_color;
2323
2324                         //GameBitmapFlags[convert_d1_bitmap_num(d1_index)] = 0;
2325
2326                         if ( bmh.flags & BM_FLAG_TRANSPARENT )
2327                                 temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2328                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT )
2329                                 temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2330                         if ( bmh.flags & BM_FLAG_NO_LIGHTING )
2331                                 temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2332                         if ( bmh.flags & BM_FLAG_RLE )
2333                                 temp_bitmap.bm_flags |= BM_FLAG_RLE;
2334                         if ( bmh.flags & BM_FLAG_RLE_BIG )
2335                                 temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2336
2337                         temp_bitmap.bm_data = next_bitmap;
2338
2339                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2340                         zsize = cfile_read_int(d1_Piggy_fp);
2341                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2342                         cfread(next_bitmap, 1, zsize, d1_Piggy_fp);
2343
2344                         switch(cfilelength(d1_Piggy_fp)) {
2345                         case D1_MAC_PIGSIZE:
2346                         case D1_MAC_SHARE_PIGSIZE:
2347                                 rle_swap_0_255(&temp_bitmap);
2348                         }
2349                         rle_remap(&temp_bitmap, colormap);
2350
2351                         GameBitmaps[d2_index] = temp_bitmap;
2352
2353                         memcpy(&zsize, temp_bitmap.bm_data, 4);
2354                         next_bitmap += zsize;
2355                 }
2356         }
2357
2358         cfclose(d1_Piggy_fp);
2359
2360         last_palette_loaded_pig[0]= 0;  //force pig re-load
2361
2362         texmerge_flush();       //for re-merging with new textures
2363
2364         atexit(free_bitmap_replacements);
2365 }
2366
2367
2368 extern int extra_bitmap_num;
2369
2370 /*
2371  * Find and load the named bitmap from descent.pig
2372  * similar to exitmodel_bm_load_sub
2373  */
2374 bitmap_index read_extra_d1_bitmap(char *name)
2375 {
2376         bitmap_index bitmap_num;
2377         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2378
2379         bitmap_num.index = 0;
2380
2381         {
2382                 CFILE *d1_Piggy_fp;
2383                 int i;
2384                 DiskBitmapHeader bmh;
2385                 int pig_data_start, bitmap_header_start, bitmap_data_start;
2386                 int N_bitmaps, zsize;
2387                 ubyte colormap[256];
2388
2389                 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2390                 if (!d1_Piggy_fp)
2391                 {
2392                         con_printf(CON_DEBUG, "could not open %s\n", D1_PIGFILE);
2393                         return bitmap_num;
2394                 }
2395
2396                 // read d1 palette, build colormap
2397                 {
2398                         int freq[256];
2399                         ubyte d1_palette[256*3];
2400                         CFILE * palette_file = cfopen( "palette.256", "rb" );
2401                         Assert( palette_file );
2402                         Assert( cfilelength( palette_file ) == 9472 );
2403                         cfread( d1_palette, 256, 3, palette_file);
2404                         cfclose( palette_file );
2405                         build_colormap_good( d1_palette, colormap, freq );
2406                         // don't change transparencies:
2407                         colormap[254] = 254;
2408                         colormap[255] = 255;
2409                 }
2410
2411                 switch (cfilelength(d1_Piggy_fp)) {
2412                 case D1_SHAREWARE_10_PIGSIZE:
2413                 case D1_SHAREWARE_PIGSIZE:
2414                         pig_data_start = 0;
2415                         break;
2416                 default:
2417                         Int3();
2418                 case D1_PIGSIZE:
2419                 case D1_OEM_PIGSIZE:
2420                 case D1_MAC_PIGSIZE:
2421                 case D1_MAC_SHARE_PIGSIZE:
2422                         pig_data_start = cfile_read_int(d1_Piggy_fp);
2423                         break;
2424                 }
2425
2426                 cfseek(d1_Piggy_fp, pig_data_start, SEEK_SET);
2427                 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2428                 {
2429                         int N_sounds = cfile_read_int(d1_Piggy_fp);
2430                         int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2431                                 + N_sounds * DISKSOUNDHEADER_SIZE;
2432                         bitmap_header_start = pig_data_start + 2 * sizeof(int);
2433                         bitmap_data_start = bitmap_header_start + header_size;
2434                 }
2435
2436                 for (i = 0; i < N_bitmaps; i++)
2437                 {
2438                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2439                         if (!strnicmp(bmh.name, name, 8))
2440                                 break;
2441                 }
2442
2443                 Assert(!strnicmp(bmh.name, name, 8));
2444
2445                 memset( new, 0, sizeof(grs_bitmap) );
2446
2447                 new->bm_w = new->bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2448                 new->bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2449                 new->avg_color = bmh.avg_color;
2450
2451                 if ( bmh.flags & BM_FLAG_TRANSPARENT )
2452                         new->bm_flags |= BM_FLAG_TRANSPARENT;
2453                 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT )
2454                         new->bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2455                 if ( bmh.flags & BM_FLAG_NO_LIGHTING )
2456                         new->bm_flags |= BM_FLAG_NO_LIGHTING;
2457                 if ( bmh.flags & BM_FLAG_RLE )
2458                         new->bm_flags |= BM_FLAG_RLE;
2459                 if ( bmh.flags & BM_FLAG_RLE_BIG )
2460                         new->bm_flags |= BM_FLAG_RLE_BIG;
2461
2462                 if ( bmh.flags & BM_FLAG_RLE )
2463                 {
2464                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2465                         zsize = cfile_read_int(d1_Piggy_fp);
2466                 }
2467                 else
2468                         zsize = new->bm_w * new->bm_h;
2469                 new->bm_data = d_malloc(zsize);
2470                 cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2471                 cfread(new->bm_data, 1, zsize, d1_Piggy_fp);
2472
2473                 switch(cfilelength(d1_Piggy_fp)) {
2474                 case D1_MAC_PIGSIZE:
2475                 case D1_MAC_SHARE_PIGSIZE:
2476                         rle_swap_0_255(new);
2477                 }
2478                 rle_remap(new, colormap);
2479
2480                 cfclose(d1_Piggy_fp);
2481         }
2482
2483         new->avg_color = 0;     //compute_average_pixel(new);
2484
2485         bitmap_num.index = extra_bitmap_num;
2486
2487         GameBitmaps[extra_bitmap_num++] = *new;
2488
2489         return bitmap_num;
2490 }
2491
2492
2493 #ifndef FAST_FILE_IO
2494 /*
2495  * reads a bitmap_index structure from a CFILE
2496  */
2497 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2498 {
2499         bi->index = cfile_read_short(fp);
2500 }
2501
2502 /*
2503  * reads n bitmap_index structs from a CFILE
2504  */
2505 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2506 {
2507         int i;
2508
2509         for (i = 0; i < n; i++)
2510                 bi[i].index = cfile_read_short(fp);
2511         return i;
2512 }
2513
2514 /*
2515  * reads a DiskBitmapHeader structure from a CFILE
2516  */
2517 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
2518 {
2519         cfread(dbh->name, 8, 1, fp);
2520         dbh->dflags = cfile_read_byte(fp);
2521         dbh->width = cfile_read_byte(fp);
2522         dbh->height = cfile_read_byte(fp);
2523         dbh->wh_extra = cfile_read_byte(fp);
2524         dbh->flags = cfile_read_byte(fp);
2525         dbh->avg_color = cfile_read_byte(fp);
2526         dbh->offset = cfile_read_int(fp);
2527 }
2528
2529 /*
2530  * reads a DiskSoundHeader structure from a CFILE
2531  */
2532 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
2533 {
2534         cfread(dsh->name, 8, 1, fp);
2535         dsh->length = cfile_read_int(fp);
2536         dsh->data_length = cfile_read_int(fp);
2537         dsh->offset = cfile_read_int(fp);
2538 }
2539 #endif // FAST_FILE_IO
2540
2541 /*
2542  * reads a descent 1 DiskBitmapHeader structure from a CFILE
2543  */
2544 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
2545 {
2546         cfread(dbh->name, 8, 1, fp);
2547         dbh->dflags = cfile_read_byte(fp);
2548         dbh->width = cfile_read_byte(fp);
2549         dbh->height = cfile_read_byte(fp);
2550         dbh->wh_extra = 0;
2551         dbh->flags = cfile_read_byte(fp);
2552         dbh->avg_color = cfile_read_byte(fp);
2553         dbh->offset = cfile_read_int(fp);
2554 }