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