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