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