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