]> icculus.org git repositories - btb/d2x.git/blob - main/piggy.c
simplify copying of bitmap flags
[btb/d2x.git] / main / piggy.c
1 /* $Id: piggy.c,v 1.33 2003-08-02 18:14:08 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.33 2003-08-02 18:14:08 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) Error ("Piggy_fp not defined in piggy_new_pigfile.");
1083         #endif
1084
1085         if (Piggy_fp) {
1086
1087                 N_bitmaps = cfile_read_int(Piggy_fp);
1088
1089                 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
1090
1091                 data_start = header_size + cftell(Piggy_fp);
1092
1093                 data_size = cfilelength(Piggy_fp) - data_start;
1094
1095                 for (i=1; i<=N_bitmaps; i++ )   {
1096                         DiskBitmapHeader_read(&bmh, Piggy_fp);
1097                         memcpy( temp_name_read, bmh.name, 8 );
1098                         temp_name_read[8] = 0;
1099         
1100                         if ( bmh.dflags & DBM_FLAG_ABM )        
1101                                 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
1102                         else
1103                                 strcpy( temp_name, temp_name_read );
1104         
1105                         //Make sure name matches
1106                         if (strcmp(temp_name,AllBitmaps[i].name)) {
1107                                 //Int3();       //this pig is out of date.  Delete it
1108                                 must_rewrite_pig=1;
1109                         }
1110         
1111                         strcpy(AllBitmaps[i].name,temp_name);
1112
1113                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1114         
1115                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1116                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1117                         temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
1118                         temp_bitmap.avg_color = bmh.avg_color;
1119                         temp_bitmap.bm_data = Piggy_bitmap_cache_data;
1120
1121                         GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
1122         
1123                         GameBitmapOffset[i] = bmh.offset + data_start;
1124         
1125                         GameBitmaps[i] = temp_bitmap;
1126                 }
1127         }
1128         else
1129                 N_bitmaps = 0;          //no pigfile, so no bitmaps
1130
1131         #ifndef EDITOR
1132
1133         Assert(N_bitmaps == Num_bitmap_files-1);
1134
1135         #else
1136
1137         if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
1138                 int size;
1139
1140                 //re-read the bitmaps that aren't in this pig
1141
1142                 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
1143                         char *p;
1144
1145                         p = strchr(AllBitmaps[i].name,'#');
1146
1147                         if (p) {                //this is an ABM
1148                                 char abmname[FILENAME_LEN];
1149                                 int fnum;
1150                                 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
1151                                 int iff_error;          //reference parm to avoid warning message
1152                                 ubyte newpal[768];
1153                                 char basename[FILENAME_LEN];
1154                                 int nframes;
1155                         
1156                                 strcpy(basename,AllBitmaps[i].name);
1157                                 basename[p-AllBitmaps[i].name] = 0;             //cut off "#nn" part
1158                                 
1159                                 sprintf( abmname, "%s.abm", basename );
1160
1161                                 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
1162
1163                                 if (iff_error != IFF_NO_ERROR)  {
1164                                         mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
1165                                         Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
1166                                 }
1167                         
1168                                 for (fnum=0;fnum<nframes; fnum++)       {
1169                                         char tempname[20];
1170                                         int SuperX;
1171
1172                                         sprintf( tempname, "%s#%d", basename, fnum );
1173
1174                                         //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1175                                         SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1176                                         //above makes assumption that supertransparent color is 254
1177
1178                                         if ( iff_has_transparency )
1179                                                 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
1180                                         else
1181                                                 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
1182
1183                                         bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
1184
1185 #ifdef EDITOR
1186                                         if ( FindArg("-macdata") )
1187                                                 swap_0_255( bm[fnum] );
1188 #endif
1189                                         if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
1190
1191                                         if (bm[fnum]->bm_flags & BM_FLAG_RLE)
1192                                                 size = *((int *) bm[fnum]->bm_data);
1193                                         else
1194                                                 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
1195
1196                                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
1197                                         d_free(bm[fnum]->bm_data);
1198                                         bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1199                                         Piggy_bitmap_cache_next += size;
1200
1201                                         GameBitmaps[i+fnum] = *bm[fnum];
1202
1203                                         // -- mprintf( (0, "U" ));
1204                                         d_free( bm[fnum] );
1205                                 }
1206
1207                                 i += nframes-1;         //filled in multiple bitmaps
1208                         }
1209                         else {          //this is a BBM
1210
1211                                 grs_bitmap * new;
1212                                 ubyte newpal[256*3];
1213                                 int iff_error;
1214                                 char bbmname[FILENAME_LEN];
1215                                 int SuperX;
1216
1217                                 MALLOC( new, grs_bitmap, 1 );
1218
1219                                 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
1220                                 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
1221
1222                                 new->bm_handle=0;
1223                                 if (iff_error != IFF_NO_ERROR)          {
1224                                         mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
1225                                         Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
1226                                 }
1227
1228                                 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1229                                 //above makes assumption that supertransparent color is 254
1230
1231                                 if ( iff_has_transparency )
1232                                         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
1233                                 else
1234                                         gr_remap_bitmap_good( new, newpal, -1, SuperX );
1235
1236                                 new->avg_color = compute_average_pixel(new);
1237
1238 #ifdef EDITOR
1239                                 if ( FindArg("-macdata") )
1240                                         swap_0_255( new );
1241 #endif
1242                                 if ( !BigPig )  gr_bitmap_rle_compress( new );
1243
1244                                 if (new->bm_flags & BM_FLAG_RLE)
1245                                         size = *((int *) new->bm_data);
1246                                 else
1247                                         size = new->bm_w * new->bm_h;
1248
1249                                 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
1250                                 d_free(new->bm_data);
1251                                 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1252                                 Piggy_bitmap_cache_next += size;
1253
1254                                 GameBitmaps[i] = *new;
1255         
1256                                 d_free( new );
1257
1258                                 // -- mprintf( (0, "U" ));
1259                         }
1260                 }
1261
1262                 //@@Dont' do these things which are done when writing
1263                 //@@for (i=0; i < Num_bitmap_files; i++ )       {
1264                 //@@    bitmap_index bi;
1265                 //@@    bi.index = i;
1266                 //@@    PIGGY_PAGE_IN( bi );
1267                 //@@}
1268                 //@@
1269                 //@@piggy_close_file();
1270
1271                 piggy_write_pigfile(pigname);
1272
1273                 Current_pigfile[0] = 0;                 //say no pig, to force reload
1274
1275                 piggy_new_pigfile(pigname);             //read in just-generated pig
1276
1277
1278         }
1279         #endif  //ifdef EDITOR
1280
1281 }
1282
1283 ubyte bogus_data[64*64];
1284 grs_bitmap bogus_bitmap;
1285 ubyte bogus_bitmap_initialized=0;
1286 digi_sound bogus_sound;
1287
1288 #define HAMFILE_ID              MAKE_SIG('!','M','A','H') //HAM!
1289 #define HAMFILE_VERSION 3
1290 //version 1 -> 2:  save marker_model_num
1291 //version 2 -> 3:  removed sound files
1292
1293 #define SNDFILE_ID              MAKE_SIG('D','N','S','D') //DSND
1294 #define SNDFILE_VERSION 1
1295
1296 int read_hamfile()
1297 {
1298         CFILE * ham_fp = NULL;
1299         int ham_id;
1300         int sound_offset = 0;
1301         #ifdef MACINTOSH
1302         char name[255];
1303         #endif
1304
1305         #ifndef MACINTOSH
1306         ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1307         #else
1308         sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1309         ham_fp = cfopen( name, "rb" );
1310         #endif
1311
1312         if (ham_fp == NULL) {
1313                 Must_write_hamfile = 1;
1314                 return 0;
1315         }
1316
1317         //make sure ham is valid type file & is up-to-date
1318         ham_id = cfile_read_int(ham_fp);
1319         Piggy_hamfile_version = cfile_read_int(ham_fp);
1320         if (ham_id != HAMFILE_ID)
1321                 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1322 #if 0
1323         if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1324                 Must_write_hamfile = 1;
1325                 cfclose(ham_fp);                                                //out of date ham
1326                 return 0;
1327         }
1328 #endif
1329
1330         if (Piggy_hamfile_version < 3) // hamfile contains sound info
1331                 sound_offset = cfile_read_int(ham_fp);
1332
1333         #ifndef EDITOR
1334         {
1335                 //int i;
1336
1337                 bm_read_all(ham_fp);
1338                 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1339                 // no swap here?
1340                 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1341                         //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1342                         //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1343                 //}
1344         }
1345         #endif
1346
1347         if (Piggy_hamfile_version < 3) {
1348                 int N_sounds;
1349                 int sound_start;
1350                 int header_size;
1351                 int i;
1352                 DiskSoundHeader sndh;
1353                 digi_sound temp_sound;
1354                 char temp_name_read[16];
1355                 int sbytes = 0;
1356
1357                 cfseek(ham_fp, sound_offset, SEEK_SET);
1358                 N_sounds = cfile_read_int(ham_fp);
1359
1360                 sound_start = cftell(ham_fp);
1361
1362                 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1363
1364                 //Read sounds
1365
1366                 for (i=0; i<N_sounds; i++ ) {
1367                         DiskSoundHeader_read(&sndh, ham_fp);
1368                         temp_sound.length = sndh.length;
1369                         temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1370                         SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1371                         memcpy( temp_name_read, sndh.name, 8 );
1372                         temp_name_read[8] = 0;
1373                         piggy_register_sound( &temp_sound, temp_name_read, 1 );
1374 #ifdef MACINTOSH
1375                         if (piggy_is_needed(i))
1376 #endif          // note link to if.
1377                                 sbytes += sndh.length;
1378                         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1379                 }
1380
1381                 SoundBits = d_malloc( sbytes + 16 );
1382                 if ( SoundBits == NULL )
1383                         Error( "Not enough memory to load sounds\n" );
1384
1385                 mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1386
1387                 //      piggy_read_sounds(ham_fp);
1388
1389         }
1390
1391         cfclose(ham_fp);
1392
1393         return 1;
1394
1395 }
1396
1397 int read_sndfile()
1398 {
1399         CFILE * snd_fp = NULL;
1400         int snd_id,snd_version;
1401         int N_sounds;
1402         int sound_start;
1403         int header_size;
1404         int i,size, length;
1405         DiskSoundHeader sndh;
1406         digi_sound temp_sound;
1407         char temp_name_read[16];
1408         int sbytes = 0;
1409         #ifdef MACINTOSH
1410         char name[255];
1411         #endif
1412
1413         #ifndef MACINTOSH
1414         snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1415         #else
1416         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1417         snd_fp = cfopen( name, "rb");
1418         #endif
1419         
1420         if (snd_fp == NULL)
1421                 return 0;
1422
1423         //make sure soundfile is valid type file & is up-to-date
1424         snd_id = cfile_read_int(snd_fp);
1425         snd_version = cfile_read_int(snd_fp);
1426         if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1427                 cfclose(snd_fp);                                                //out of date sound file
1428                 return 0;
1429         }
1430
1431         N_sounds = cfile_read_int(snd_fp);
1432
1433         sound_start = cftell(snd_fp);
1434         size = cfilelength(snd_fp) - sound_start;
1435         length = size;
1436         mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1437
1438         header_size = N_sounds*sizeof(DiskSoundHeader);
1439
1440         //Read sounds
1441
1442         for (i=0; i<N_sounds; i++ ) {
1443                 DiskSoundHeader_read(&sndh, snd_fp);
1444                 //size -= sizeof(DiskSoundHeader);
1445                 temp_sound.length = sndh.length;
1446                 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1447                 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1448                 memcpy( temp_name_read, sndh.name, 8 );
1449                 temp_name_read[8] = 0;
1450                 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1451                 #ifdef MACINTOSH
1452                 if (piggy_is_needed(i))
1453                 #endif          // note link to if.
1454                 sbytes += sndh.length;
1455                 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1456         }
1457
1458         SoundBits = d_malloc( sbytes + 16 );
1459         if ( SoundBits == NULL )
1460                 Error( "Not enough memory to load sounds\n" );
1461
1462         mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1463
1464 //      piggy_read_sounds(snd_fp);
1465
1466         cfclose(snd_fp);
1467
1468         return 1;
1469 }
1470
1471 int piggy_init(void)
1472 {
1473         int ham_ok=0,snd_ok=0;
1474         int i;
1475
1476         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1477         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1478
1479         for (i=0; i<MAX_SOUND_FILES; i++ )      {
1480                 GameSounds[i].length = 0;
1481                 GameSounds[i].data = NULL;
1482                 SoundOffset[i] = 0;
1483         }
1484
1485         for (i=0; i<MAX_BITMAP_FILES; i++ )     
1486                 GameBitmapXlat[i] = i;
1487
1488         if ( !bogus_bitmap_initialized )        {
1489                 int i;
1490                 ubyte c;
1491                 bogus_bitmap_initialized = 1;
1492                 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1493                 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1494                 bogus_bitmap.bm_data = bogus_data;
1495                 c = gr_find_closest_color( 0, 0, 63 );
1496                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1497                 c = gr_find_closest_color( 63, 0, 0 );
1498                 // Make a big red X !
1499                 for (i=0; i<64; i++ )   {
1500                         bogus_data[i*64+i] = c;
1501                         bogus_data[i*64+(63-i)] = c;
1502                 }
1503                 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1504                 bogus_sound.length = 64*64;
1505                 bogus_sound.data = bogus_data;
1506                 GameBitmapOffset[0] = 0;
1507         }
1508
1509         if ( FindArg( "-bigpig" ))
1510                 BigPig = 1;
1511
1512         if ( FindArg( "-lowmem" ))
1513                 piggy_low_memory = 1;
1514
1515         if ( FindArg( "-nolowmem" ))
1516                 piggy_low_memory = 0;
1517
1518         if (piggy_low_memory)
1519                 digi_lomem = 1;
1520
1521         WIN(DDGRLOCK(dd_grd_curcanv));
1522                 gr_set_curfont( SMALL_FONT );
1523                 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1524                 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1525         WIN(DDGRUNLOCK(dd_grd_curcanv));
1526
1527 #if 1 //def EDITOR //need for d1 mission briefings
1528         piggy_init_pigfile(DEFAULT_PIGFILE);
1529 #endif
1530
1531         snd_ok = ham_ok = read_hamfile();
1532
1533         if (Piggy_hamfile_version >= 3)
1534                 snd_ok = read_sndfile();
1535
1536         atexit(piggy_close);
1537
1538         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1539         return (ham_ok && snd_ok);               //read ok
1540 }
1541
1542 int piggy_is_needed(int soundnum)
1543 {
1544         int i;
1545
1546         if ( !digi_lomem ) return 1;
1547
1548         for (i=0; i<MAX_SOUNDS; i++ )   {
1549                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1550                         return 1;
1551         }
1552         return 0;
1553 }
1554
1555
1556 void piggy_read_sounds(void)
1557 {
1558         CFILE * fp = NULL;
1559         ubyte * ptr;
1560         int i, sbytes;
1561         #ifdef MACINTOSH
1562         char name[255];
1563         #endif
1564
1565         ptr = SoundBits;
1566         sbytes = 0;
1567
1568         #ifndef MACINTOSH
1569         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1570         #else
1571         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1572         fp = cfopen( name, "rb");
1573         #endif
1574
1575         if (fp == NULL)
1576                 return;
1577
1578         for (i=0; i<Num_sound_files; i++ )      {
1579                 digi_sound *snd = &GameSounds[i];
1580
1581                 if ( SoundOffset[i] > 0 )       {
1582                         if ( piggy_is_needed(i) )       {
1583                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1584
1585                                 // Read in the sound data!!!
1586                                 snd->data = ptr;
1587                                 ptr += snd->length;
1588                                 sbytes += snd->length;
1589                                 cfread( snd->data, snd->length, 1, fp );
1590                         }
1591                         else
1592                                 snd->data = (ubyte *) -1;
1593                 }
1594         }
1595
1596         cfclose(fp);
1597
1598         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1599
1600 }
1601
1602
1603 extern int descent_critical_error;
1604 extern unsigned descent_critical_deverror;
1605 extern unsigned descent_critical_errcode;
1606
1607 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1608 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1609 "Read fault", "General Failure" };
1610
1611 void piggy_critical_error()
1612 {
1613         grs_canvas * save_canv;
1614         grs_font * save_font;
1615         int i;
1616         save_canv = grd_curcanv;
1617         save_font = grd_curcanv->cv_font;
1618         gr_palette_load( gr_palette );
1619         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1620         if ( i == 1 )
1621                 exit(1);
1622         gr_set_current_canvas(save_canv);
1623         grd_curcanv->cv_font = save_font;
1624 }
1625
1626 void piggy_bitmap_page_in( bitmap_index bitmap )
1627 {
1628         grs_bitmap * bmp;
1629         int i,org_i,temp;
1630
1631         org_i = 0;
1632
1633         i = bitmap.index;
1634         Assert( i >= 0 );
1635         Assert( i < MAX_BITMAP_FILES );
1636         Assert( i < Num_bitmap_files );
1637         Assert( Piggy_bitmap_cache_size > 0 );
1638
1639         if ( i < 1 ) return;
1640         if ( i >= MAX_BITMAP_FILES ) return;
1641         if ( i >= Num_bitmap_files ) return;
1642
1643         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1644
1645         if ( piggy_low_memory ) {
1646                 org_i = i;
1647                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1648         }
1649
1650         bmp = &GameBitmaps[i];
1651
1652         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1653                 stop_time();
1654
1655         ReDoIt:
1656                 descent_critical_error = 0;
1657                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1658                 if ( descent_critical_error )   {
1659                         piggy_critical_error();
1660                         goto ReDoIt;
1661                 }
1662
1663                 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1664                 bmp->bm_flags = GameBitmapFlags[i];
1665
1666                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1667                         int zsize = 0;
1668                         descent_critical_error = 0;
1669                         zsize = cfile_read_int(Piggy_fp);
1670                         if ( descent_critical_error )   {
1671                                 piggy_critical_error();
1672                                 goto ReDoIt;
1673                         }
1674
1675                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1676                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1677                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1678                                 Int3();
1679                                 piggy_bitmap_page_out_all();
1680                                 goto ReDoIt;
1681                         }
1682                         descent_critical_error = 0;
1683                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1684                         if ( descent_critical_error )   {
1685                                 piggy_critical_error();
1686                                 goto ReDoIt;
1687                         }
1688
1689 #ifndef MACDATA
1690                         switch (cfilelength(Piggy_fp)) {
1691                         default:
1692                                 if (!FindArg("-macdata"))
1693                                         break;
1694                                 // otherwise, fall through...
1695                         case MAC_ALIEN1_PIGSIZE:
1696                         case MAC_ALIEN2_PIGSIZE:
1697                         case MAC_FIRE_PIGSIZE:
1698                         case MAC_GROUPA_PIGSIZE:
1699                         case MAC_ICE_PIGSIZE:
1700                         case MAC_WATER_PIGSIZE:
1701                                 rle_swap_0_255( bmp );
1702                                 memcpy(&zsize, bmp->bm_data, 4);
1703                                 break;
1704                         }
1705 #endif
1706
1707                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1708                         Piggy_bitmap_cache_next += zsize;
1709                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1710                                 Int3();
1711                                 piggy_bitmap_page_out_all();
1712                                 goto ReDoIt;
1713                         }
1714
1715                 } else {
1716                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1717                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1718                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1719                                 piggy_bitmap_page_out_all();
1720                                 goto ReDoIt;
1721                         }
1722                         descent_critical_error = 0;
1723                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1724                         if ( descent_critical_error )   {
1725                                 piggy_critical_error();
1726                                 goto ReDoIt;
1727                         }
1728                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1729
1730 #ifndef MACDATA
1731                         switch (cfilelength(Piggy_fp)) {
1732                         default:
1733                                 if (!FindArg("-macdata"))
1734                                         break;
1735                                 // otherwise, fall through...
1736                         case MAC_ALIEN1_PIGSIZE:
1737                         case MAC_ALIEN2_PIGSIZE:
1738                         case MAC_FIRE_PIGSIZE:
1739                         case MAC_GROUPA_PIGSIZE:
1740                         case MAC_ICE_PIGSIZE:
1741                         case MAC_WATER_PIGSIZE:
1742                                 swap_0_255( bmp );
1743                                 break;
1744                         }
1745 #endif
1746                 }
1747
1748                 //@@if ( bmp->bm_selector ) {
1749                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1750                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1751                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1752                 //@@#endif
1753                 //@@}
1754
1755                 start_time();
1756         }
1757
1758         if ( piggy_low_memory ) {
1759                 if ( org_i != i )
1760                         GameBitmaps[org_i] = GameBitmaps[i];
1761         }
1762
1763 //@@Removed from John's code:
1764 //@@#ifndef WINDOWS
1765 //@@    if ( bmp->bm_selector ) {
1766 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1767 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1768 //@@    }
1769 //@@#endif
1770
1771 }
1772
1773 void piggy_bitmap_page_out_all()
1774 {
1775         int i;
1776         
1777         Piggy_bitmap_cache_next = 0;
1778
1779         piggy_page_flushed++;
1780
1781         texmerge_flush();
1782         rle_cache_flush();
1783
1784         for (i=0; i<Num_bitmap_files; i++ )             {
1785                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1786                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1787                         GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1788                 }
1789         }
1790
1791         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1792 }
1793
1794 void piggy_load_level_data()
1795 {
1796         piggy_bitmap_page_out_all();
1797         paging_touch_all();
1798 }
1799
1800 #ifdef EDITOR
1801
1802 void change_filename_ext( char *dest, char *src, char *ext );
1803
1804 void piggy_write_pigfile(char *filename)
1805 {
1806         FILE *pig_fp;
1807         int bitmap_data_start,data_offset;
1808         DiskBitmapHeader bmh;
1809         int org_offset;
1810         char subst_name[32];
1811         int i;
1812         FILE *fp1,*fp2;
1813         char tname[FILENAME_LEN];
1814
1815         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1816         for (i=0; i < Num_bitmap_files; i++ )   {
1817                 bitmap_index bi;
1818                 bi.index = i;
1819                 PIGGY_PAGE_IN( bi );
1820         }
1821         // -- mprintf( (0, "\n" ));
1822
1823         piggy_close_file();
1824
1825         // -- mprintf( (0, "Creating %s...",filename ));
1826
1827         pig_fp = fopen( filename, "wb" );       //open PIG file
1828         Assert( pig_fp!=NULL );
1829
1830         write_int(PIGFILE_ID,pig_fp);
1831         write_int(PIGFILE_VERSION,pig_fp);
1832
1833         Num_bitmap_files--;
1834         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1835         Num_bitmap_files++;
1836
1837         bitmap_data_start = ftell(pig_fp);
1838         bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE; 
1839         data_offset = bitmap_data_start;
1840
1841         change_filename_ext(tname,filename,"lst");
1842         fp1 = fopen( tname, "wt" );
1843         change_filename_ext(tname,filename,"all");
1844         fp2 = fopen( tname, "wt" );
1845
1846         for (i=1; i < Num_bitmap_files; i++ )   {
1847                 int *size;
1848                 grs_bitmap *bmp;
1849
1850                 {               
1851                         char * p, *p1;
1852                         p = strchr(AllBitmaps[i].name,'#');
1853                         if (p)  {
1854                                 int n;
1855                                 p1 = p; p1++; 
1856                                 n = atoi(p1);
1857                                 *p = 0;
1858                                 if (fp2 && n==0)
1859                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1860                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1861                                 Assert( n <= 63 );
1862                                 bmh.dflags = DBM_FLAG_ABM + n;
1863                                 *p = '#';
1864                         }else {
1865                                 if (fp2)
1866                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1867                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1868                                 bmh.dflags = 0;
1869                         }
1870                 }
1871                 bmp = &GameBitmaps[i];
1872
1873                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1874
1875                 if (fp1)
1876                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1877                 org_offset = ftell(pig_fp);
1878                 bmh.offset = data_offset - bitmap_data_start;
1879                 fseek( pig_fp, data_offset, SEEK_SET );
1880
1881                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1882                         size = (int *)bmp->bm_data;
1883                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1884                         data_offset += *size;
1885                         if (fp1)
1886                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1887                 } else {
1888                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1889                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1890                         if (fp1)
1891                                 fprintf( fp1, ".\n" );
1892                 }
1893                 fseek( pig_fp, org_offset, SEEK_SET );
1894                 Assert( GameBitmaps[i].bm_w < 4096 );
1895                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1896                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1897                 Assert( GameBitmaps[i].bm_h < 4096 );
1898                 bmh.height = GameBitmaps[i].bm_h;
1899                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1900                 bmh.flags = GameBitmaps[i].bm_flags;
1901                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1902                         bitmap_index other_bitmap;
1903                         other_bitmap = piggy_find_bitmap( subst_name );
1904                         GameBitmapXlat[i] = other_bitmap.index;
1905                         bmh.flags |= BM_FLAG_PAGED_OUT;
1906                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1907                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1908                 } else  {
1909                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1910                 }
1911                 bmh.avg_color=GameBitmaps[i].avg_color;
1912                 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp );                    // Mark as a bitmap
1913         }
1914
1915         fclose(pig_fp);
1916
1917         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1918         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1919
1920         fclose(fp1);
1921         fclose(fp2);
1922
1923 }
1924
1925 static void write_int(int i,FILE *file)
1926 {
1927         if (fwrite( &i, sizeof(i), 1, file) != 1)
1928                 Error( "Error reading int in gamesave.c" );
1929
1930 }
1931
1932 void piggy_dump_all()
1933 {
1934         int i, xlat_offset;
1935         FILE * ham_fp;
1936         int org_offset,data_offset=0;
1937         DiskSoundHeader sndh;
1938         int sound_data_start=0;
1939         FILE *fp1,*fp2;
1940
1941         #ifdef NO_DUMP_SOUNDS
1942         Num_sound_files = 0;
1943         Num_sound_files_new = 0;
1944         #endif
1945
1946         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1947                 return;
1948
1949         fp1 = fopen( "ham.lst", "wt" );
1950         fp2 = fopen( "ham.all", "wt" );
1951
1952         if (Must_write_hamfile || Num_bitmap_files_new) {
1953
1954                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1955         
1956                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1957                 Assert( ham_fp!=NULL );
1958         
1959                 write_int(HAMFILE_ID,ham_fp);
1960                 write_int(HAMFILE_VERSION,ham_fp);
1961         
1962                 bm_write_all(ham_fp);
1963                 xlat_offset = ftell(ham_fp);
1964                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1965                 //Dump bitmaps
1966         
1967                 if (Num_bitmap_files_new)
1968                         piggy_write_pigfile(DEFAULT_PIGFILE);
1969         
1970                 //free up memeory used by new bitmaps
1971                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1972                         d_free(GameBitmaps[i].bm_data);
1973         
1974                 //next thing must be done after pig written
1975                 fseek( ham_fp, xlat_offset, SEEK_SET );
1976                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1977         
1978                 fclose(ham_fp);
1979                 mprintf( (0, "\n" ));
1980         }
1981         
1982         if (Num_sound_files_new) {
1983
1984                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1985                 // Now dump sound file
1986                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1987                 Assert( ham_fp!=NULL );
1988         
1989                 write_int(SNDFILE_ID,ham_fp);
1990                 write_int(SNDFILE_VERSION,ham_fp);
1991
1992                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1993         
1994                 mprintf( (0, "\nDumping sounds..." ));
1995         
1996                 sound_data_start = ftell(ham_fp);
1997                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1998                 data_offset = sound_data_start;
1999         
2000                 for (i=0; i < Num_sound_files; i++ )    {
2001                         digi_sound *snd;
2002         
2003                         snd = &GameSounds[i];
2004                         strcpy( sndh.name, AllSounds[i].name );
2005                         sndh.length = GameSounds[i].length;
2006                         sndh.offset = data_offset - sound_data_start;
2007         
2008                         org_offset = ftell(ham_fp);
2009                         fseek( ham_fp, data_offset, SEEK_SET );
2010         
2011                         sndh.data_length = GameSounds[i].length;
2012                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
2013                         data_offset += snd->length;
2014                         fseek( ham_fp, org_offset, SEEK_SET );
2015                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
2016         
2017                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
2018                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
2019                 }
2020
2021                 fclose(ham_fp);
2022                 mprintf( (0, "\n" ));
2023         }
2024
2025         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
2026         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
2027         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
2028
2029         fclose(fp1);
2030         fclose(fp2);
2031
2032         // Never allow the game to run after building ham.
2033         exit(0);
2034 }
2035
2036 #endif
2037
2038 void piggy_close()
2039 {
2040         piggy_close_file();
2041
2042         if (BitmapBits)
2043                 d_free(BitmapBits);
2044
2045         if ( SoundBits )
2046                 d_free( SoundBits );
2047
2048         hashtable_free( &AllBitmapsNames );
2049         hashtable_free( &AllDigiSndNames );
2050
2051 }
2052
2053 int piggy_does_bitmap_exist_slow( char * name )
2054 {
2055         int i;
2056
2057         for (i=0; i<Num_bitmap_files; i++ )     {
2058                 if ( !strcmp( AllBitmaps[i].name, name) )
2059                         return 1;
2060         }
2061         return 0;
2062 }
2063
2064
2065 #define NUM_GAUGE_BITMAPS 23
2066 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
2067         "gauge01", "gauge01b",
2068         "gauge02", "gauge02b",
2069         "gauge06", "gauge06b",
2070         "targ01", "targ01b",
2071         "targ02", "targ02b", 
2072         "targ03", "targ03b",
2073         "targ04", "targ04b",
2074         "targ05", "targ05b",
2075         "targ06", "targ06b",
2076         "gauge18", "gauge18b",
2077         "gauss1", "helix1",
2078         "phoenix1"
2079 };
2080
2081
2082 int piggy_is_gauge_bitmap( char * base_name )
2083 {
2084         int i;
2085         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
2086                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
2087                         return 1;
2088         }
2089
2090         return 0;       
2091 }
2092
2093 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
2094 {
2095         int frame;
2096         char * p;
2097         char base_name[ 16 ];
2098         
2099         strcpy( subst_name, name );
2100         p = strchr( subst_name, '#' );
2101         if ( p )        {
2102                 frame = atoi( &p[1] );
2103                 *p = 0;
2104                 strcpy( base_name, subst_name );
2105                 if ( !piggy_is_gauge_bitmap( base_name ))       {
2106                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
2107                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
2108                                 if ( frame & 1 ) {
2109                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
2110                                         return 1;
2111                                 }
2112                         }
2113                 }
2114         }
2115         strcpy( subst_name, name );
2116         return 0;
2117 }
2118
2119
2120
2121 #ifdef WINDOWS
2122 //      New Windows stuff
2123
2124 //      windows bitmap page in
2125 //              Page in a bitmap, if ddraw, then page it into a ddsurface in 
2126 //              'video' memory.  if that fails, page it in normally.
2127
2128 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
2129 {
2130 }
2131
2132
2133 //      Essential when switching video modes!
2134
2135 void piggy_bitmap_page_out_all_w()
2136 {
2137 }
2138
2139 #endif // WINDOWS
2140
2141
2142 /*
2143  * Functions for loading replacement textures
2144  *  1) From .pog files
2145  *  2) From descent.pig (for loading d1 levels)
2146  */
2147
2148 extern void change_filename_extension( char *dest, char *src, char *new_ext );
2149 extern char last_palette_loaded_pig[];
2150
2151 ubyte *Bitmap_replacement_data=NULL;
2152
2153 void free_bitmap_replacements()
2154 {
2155         if (Bitmap_replacement_data) {
2156                 d_free(Bitmap_replacement_data);
2157                 Bitmap_replacement_data = NULL;
2158         }
2159 }
2160
2161 void load_bitmap_replacements(char *level_name)
2162 {
2163         char ifile_name[FILENAME_LEN];
2164         CFILE *ifile;
2165         int i;
2166
2167         //first, free up data allocated for old bitmaps
2168         free_bitmap_replacements();
2169
2170         change_filename_extension(ifile_name, level_name, ".POG" );
2171
2172         ifile = cfopen(ifile_name,"rb");
2173
2174         if (ifile) {
2175                 int id,version,n_bitmaps;
2176                 int bitmap_data_size;
2177                 ushort *indices;
2178
2179                 id = cfile_read_int(ifile);
2180                 version = cfile_read_int(ifile);
2181
2182                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
2183                         cfclose(ifile);
2184                         return;
2185                 }
2186
2187                 n_bitmaps = cfile_read_int(ifile);
2188
2189                 MALLOC( indices, ushort, n_bitmaps );
2190
2191                 for (i = 0; i < n_bitmaps; i++)
2192                         indices[i] = cfile_read_short(ifile);
2193
2194                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - DISKBITMAPHEADER_SIZE * n_bitmaps;
2195                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
2196
2197                 for (i=0;i<n_bitmaps;i++) {
2198                         DiskBitmapHeader bmh;
2199                         grs_bitmap temp_bitmap;
2200
2201                         DiskBitmapHeader_read(&bmh, ifile);
2202
2203                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2204
2205                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2206                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2207                         temp_bitmap.avg_color = bmh.avg_color;
2208                         temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
2209
2210                         temp_bitmap.bm_flags |= bmh.flags & BM_FLAGS_TO_COPY;
2211
2212                         GameBitmaps[indices[i]] = temp_bitmap;
2213                 }
2214
2215                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
2216
2217                 d_free(indices);
2218
2219                 cfclose(ifile);
2220
2221                 last_palette_loaded_pig[0]= 0;  //force pig re-load
2222
2223                 texmerge_flush();       //for re-merging with new textures
2224         }
2225
2226         atexit(free_bitmap_replacements);
2227 }
2228
2229 #define FIRST_D1_TEXTURE 722
2230 #define LAST_D1_STATIC_TEXTURE 1042//1342 //afterwards, we have door frames and stuff
2231 #define FIRST_D2_TEXTURE 1243
2232
2233 void load_d1_bitmap_replacements()
2234 {
2235         CFILE * d1_Piggy_fp;
2236         grs_bitmap temp_bitmap;
2237         DiskBitmapHeader bmh;
2238         int pig_data_start, bitmap_header_start, bitmap_data_start;
2239         int N_bitmaps, zsize;
2240         int d1_index, d2_index;
2241         ubyte colormap[256];
2242         ubyte *next_bitmap; // to which address we write the next bitmap
2243
2244         d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2245
2246         if (!d1_Piggy_fp)
2247                 return; // use d2 bitmaps instead...
2248
2249         //first, free up data allocated for old bitmaps
2250         free_bitmap_replacements();
2251
2252         // read d1 palette, build colormap
2253         {
2254                 int freq[256];
2255                 ubyte d1_palette[256*3];
2256                 CFILE * palette_file = cfopen(D1_PALETTE, "rb" );
2257                 Assert( palette_file );
2258                 Assert( cfilelength( palette_file ) == 9472 );
2259                 cfread( d1_palette, 256, 3, palette_file);
2260                 cfclose( palette_file );
2261                 build_colormap_good( d1_palette, colormap, freq );
2262                 // don't change transparencies:
2263                 colormap[254] = 254;
2264                 colormap[255] = 255;
2265         }
2266
2267         switch (cfilelength(d1_Piggy_fp)) {
2268         case D1_SHAREWARE_10_PIGSIZE:
2269         case D1_SHAREWARE_PIGSIZE:
2270                 pig_data_start = 0;
2271                 break;
2272         default:
2273                 Int3();
2274         case D1_PIGSIZE:
2275         case D1_OEM_PIGSIZE:
2276         case D1_MAC_PIGSIZE:
2277         case D1_MAC_SHARE_PIGSIZE:
2278                 //int i;
2279                 pig_data_start = cfile_read_int(d1_Piggy_fp );
2280                 bm_read_all_d1( d1_Piggy_fp );
2281                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2282                 break;
2283         }
2284
2285         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2286         N_bitmaps = cfile_read_int(d1_Piggy_fp);
2287         {
2288                 int N_sounds = cfile_read_int(d1_Piggy_fp);
2289                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2290                         + N_sounds * DISKSOUNDHEADER_SIZE;
2291                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2292                 bitmap_data_start = bitmap_header_start + header_size;
2293         }
2294
2295         MALLOC( Bitmap_replacement_data, ubyte, cfilelength(d1_Piggy_fp) - bitmap_data_start ); // too much
2296         //TODO: handle case where b_r_d == 0! (have to convert textures, return, not bm_read_all_d1)
2297
2298         next_bitmap = Bitmap_replacement_data;
2299
2300         for (d1_index=1; d1_index<=N_bitmaps; d1_index++ ) {
2301                 // only change wall texture bitmaps
2302                 if (d1_index >= FIRST_D1_TEXTURE && d1_index <= LAST_D1_STATIC_TEXTURE) {
2303                         d2_index = d1_index + FIRST_D2_TEXTURE - FIRST_D1_TEXTURE;
2304
2305                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2306                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2307
2308                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2309
2310                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2311                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2312                         temp_bitmap.avg_color = bmh.avg_color;
2313
2314                         //GameBitmapFlags[convert_d1_bitmap_num(d1_index)] = 0;
2315
2316                         temp_bitmap.bm_flags |= bmh.flags & BM_FLAGS_TO_COPY;
2317
2318                         temp_bitmap.bm_data = next_bitmap;
2319
2320                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2321                         zsize = cfile_read_int(d1_Piggy_fp);
2322                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2323                         cfread(next_bitmap, 1, zsize, d1_Piggy_fp);
2324
2325                         switch(cfilelength(d1_Piggy_fp)) {
2326                         case D1_MAC_PIGSIZE:
2327                         case D1_MAC_SHARE_PIGSIZE:
2328                                 rle_swap_0_255(&temp_bitmap);
2329                         }
2330                         rle_remap(&temp_bitmap, colormap);
2331
2332                         GameBitmaps[d2_index] = temp_bitmap;
2333
2334                         memcpy(&zsize, temp_bitmap.bm_data, 4);
2335                         next_bitmap += zsize;
2336                 }
2337         }
2338
2339         cfclose(d1_Piggy_fp);
2340
2341         last_palette_loaded_pig[0]= 0;  //force pig re-load
2342
2343         texmerge_flush();       //for re-merging with new textures
2344
2345         atexit(free_bitmap_replacements);
2346 }
2347
2348
2349 extern int extra_bitmap_num;
2350
2351 /*
2352  * Find and load the named bitmap from descent.pig
2353  * similar to read_extra_bitmap_iff
2354  */
2355 bitmap_index read_extra_bitmap_d1_pig(char *name)
2356 {
2357         bitmap_index bitmap_num;
2358         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2359
2360         bitmap_num.index = 0;
2361
2362         {
2363                 CFILE *d1_Piggy_fp;
2364                 int i;
2365                 DiskBitmapHeader bmh;
2366                 int pig_data_start, bitmap_header_start, bitmap_data_start;
2367                 int N_bitmaps, zsize;
2368                 ubyte colormap[256];
2369
2370                 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2371                 if (!d1_Piggy_fp)
2372                 {
2373                         con_printf(CON_DEBUG, "could not open %s\n", D1_PIGFILE);
2374                         return bitmap_num;
2375                 }
2376
2377                 // read d1 palette, build colormap
2378                 {
2379                         int freq[256];
2380                         ubyte d1_palette[256*3];
2381                         CFILE * palette_file = cfopen(D1_PALETTE, "rb");
2382                         if (!palette_file || cfilelength(palette_file) != 9472)
2383                         {
2384                                 con_printf(CON_DEBUG, "could not open %s\n", D1_PALETTE);
2385                                 return bitmap_num;
2386                         }
2387                         cfread( d1_palette, 256, 3, palette_file);
2388                         cfclose( palette_file );
2389                         build_colormap_good( d1_palette, colormap, freq );
2390                         // don't change transparencies:
2391                         colormap[254] = 254;
2392                         colormap[255] = 255;
2393                 }
2394
2395                 switch (cfilelength(d1_Piggy_fp)) {
2396                 case D1_SHAREWARE_10_PIGSIZE:
2397                 case D1_SHAREWARE_PIGSIZE:
2398                         pig_data_start = 0;
2399                         break;
2400                 default:
2401                         Int3();
2402                 case D1_PIGSIZE:
2403                 case D1_OEM_PIGSIZE:
2404                 case D1_MAC_PIGSIZE:
2405                 case D1_MAC_SHARE_PIGSIZE:
2406                         pig_data_start = cfile_read_int(d1_Piggy_fp);
2407                         break;
2408                 }
2409
2410                 cfseek(d1_Piggy_fp, pig_data_start, SEEK_SET);
2411                 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2412                 {
2413                         int N_sounds = cfile_read_int(d1_Piggy_fp);
2414                         int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2415                                 + N_sounds * DISKSOUNDHEADER_SIZE;
2416                         bitmap_header_start = pig_data_start + 2 * sizeof(int);
2417                         bitmap_data_start = bitmap_header_start + header_size;
2418                 }
2419
2420                 for (i = 0; i < N_bitmaps; i++)
2421                 {
2422                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2423                         if (!strnicmp(bmh.name, name, 8))
2424                                 break;
2425                 }
2426
2427                 if (strnicmp(bmh.name, name, 8))
2428                 {
2429                         con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2430                         return bitmap_num;
2431                 }
2432
2433                 memset( new, 0, sizeof(grs_bitmap) );
2434
2435                 new->bm_w = new->bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2436                 new->bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2437                 new->avg_color = bmh.avg_color;
2438
2439                 new->bm_flags |= bmh.flags & BM_FLAGS_TO_COPY;
2440
2441                 if ( bmh.flags & BM_FLAG_RLE )
2442                 {
2443                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2444                         zsize = cfile_read_int(d1_Piggy_fp);
2445                 }
2446                 else
2447                         zsize = new->bm_w * new->bm_h;
2448                 new->bm_data = d_malloc(zsize);
2449                 cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2450                 cfread(new->bm_data, 1, zsize, d1_Piggy_fp);
2451
2452                 switch(cfilelength(d1_Piggy_fp)) {
2453                 case D1_MAC_PIGSIZE:
2454                 case D1_MAC_SHARE_PIGSIZE:
2455                         rle_swap_0_255(new);
2456                 }
2457                 rle_remap(new, colormap);
2458
2459                 cfclose(d1_Piggy_fp);
2460         }
2461
2462         new->avg_color = 0;     //compute_average_pixel(new);
2463
2464         bitmap_num.index = extra_bitmap_num;
2465
2466         GameBitmaps[extra_bitmap_num++] = *new;
2467
2468         return bitmap_num;
2469 }
2470
2471
2472 #ifndef FAST_FILE_IO
2473 /*
2474  * reads a bitmap_index structure from a CFILE
2475  */
2476 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2477 {
2478         bi->index = cfile_read_short(fp);
2479 }
2480
2481 /*
2482  * reads n bitmap_index structs from a CFILE
2483  */
2484 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2485 {
2486         int i;
2487
2488         for (i = 0; i < n; i++)
2489                 bi[i].index = cfile_read_short(fp);
2490         return i;
2491 }
2492
2493 /*
2494  * reads a DiskBitmapHeader structure from a CFILE
2495  */
2496 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
2497 {
2498         cfread(dbh->name, 8, 1, fp);
2499         dbh->dflags = cfile_read_byte(fp);
2500         dbh->width = cfile_read_byte(fp);
2501         dbh->height = cfile_read_byte(fp);
2502         dbh->wh_extra = cfile_read_byte(fp);
2503         dbh->flags = cfile_read_byte(fp);
2504         dbh->avg_color = cfile_read_byte(fp);
2505         dbh->offset = cfile_read_int(fp);
2506 }
2507
2508 /*
2509  * reads a DiskSoundHeader structure from a CFILE
2510  */
2511 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
2512 {
2513         cfread(dsh->name, 8, 1, fp);
2514         dsh->length = cfile_read_int(fp);
2515         dsh->data_length = cfile_read_int(fp);
2516         dsh->offset = cfile_read_int(fp);
2517 }
2518 #endif // FAST_FILE_IO
2519
2520 /*
2521  * reads a descent 1 DiskBitmapHeader structure from a CFILE
2522  */
2523 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
2524 {
2525         cfread(dbh->name, 8, 1, fp);
2526         dbh->dflags = cfile_read_byte(fp);
2527         dbh->width = cfile_read_byte(fp);
2528         dbh->height = cfile_read_byte(fp);
2529         dbh->wh_extra = 0;
2530         dbh->flags = cfile_read_byte(fp);
2531         dbh->avg_color = cfile_read_byte(fp);
2532         dbh->offset = cfile_read_int(fp);
2533 }