move bitmap replacement functions to piggy.c
[btb/d2x.git] / main / piggy.c
1 /* $Id: piggy.c,v 1.26 2003-03-22 03:19:50 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Functions for managing the pig files.
18  *
19  * Old Log:
20  * Revision 1.16  1995/11/09  17:27:47  allender
21  * put in missing quote on new gauge name
22  *
23  * Revision 1.15  1995/11/08  17:28:03  allender
24  * add PC gauges to gauge list of non-substitutatble bitmaps
25  *
26  * Revision 1.14  1995/11/08  15:14:49  allender
27  * fixed horrible bug where the piggy cache size was incorrect
28  * for mac shareware
29  *
30  * Revision 1.13  1995/11/03  12:53:37  allender
31  * shareware changes
32  *
33  * Revision 1.12  1995/10/21  22:25:14  allender
34  * added bald guy cheat
35  *
36  * Revision 1.11  1995/10/20  22:42:15  allender
37  * changed load path of descent.pig to :data:descent.pig
38  *
39  * Revision 1.10  1995/10/20  00:08:01  allender
40  * put in event loop calls when loading data (hides it nicely
41  * from user) so TM can get it's strokes stuff
42  *
43  * Revision 1.9  1995/09/13  08:48:01  allender
44  * added lower memory requirement to load alternate bitmaps
45  *
46  * Revision 1.8  1995/08/16  09:39:13  allender
47  * moved "loading" text up a little
48  *
49  * Revision 1.7  1995/08/08  13:54:26  allender
50  * added macsys header file
51  *
52  * Revision 1.6  1995/07/12  12:49:56  allender
53  * total hack for bitmaps > 512 bytes wide -- check these by name
54  *
55  * Revision 1.5  1995/07/05  16:47:05  allender
56  * kitchen stuff
57  *
58  * Revision 1.4  1995/06/23  08:55:28  allender
59  * make "loading data" text y loc based off of curcanv
60  *
61  * Revision 1.3  1995/06/08  14:08:52  allender
62  * PPC aligned data sets
63  *
64  * Revision 1.2  1995/05/26  06:54:27  allender
65  * removed refences to sound data at end of pig file (since they will
66  * now be Macintosh snd resources for effects
67  *
68  * Revision 1.1  1995/05/16  15:29:51  allender
69  * Initial revision
70  *
71  * Revision 2.10  1995/10/07  13:17:26  john
72  * Made all bitmaps paged out by default.
73  *
74  * Revision 2.9  1995/04/14  14:05:24  john
75  * *** empty log message ***
76  *
77  * Revision 2.8  1995/04/12  13:39:37  john
78  * Fixed bug with -lowmem not working.
79  *
80  * Revision 2.7  1995/03/29  23:23:17  john
81  * Fixed major bug with sounds not building into pig right.
82  *
83  * Revision 2.6  1995/03/28  18:05:00  john
84  * Fixed it so you don't have to delete pig after changing bitmaps.tbl
85  *
86  * Revision 2.5  1995/03/16  23:13:06  john
87  * Fixed bug with piggy paging in bitmap not checking for disk
88  * error, hence bogifying textures if you pull the CD out.
89  *
90  * Revision 2.4  1995/03/14  16:22:27  john
91  * Added cdrom alternate directory stuff.
92  *
93  * Revision 2.3  1995/03/06  15:23:20  john
94  * New screen techniques.
95  *
96  * Revision 2.2  1995/02/27  13:13:40  john
97  * Removed floating point.
98  *
99  * Revision 2.1  1995/02/27  12:31:25  john
100  * Made work without editor.
101  *
102  * Revision 2.0  1995/02/27  11:28:02  john
103  * New version 2.0, which has no anonymous unions, builds with
104  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
105  *
106  * Revision 1.85  1995/02/09  12:54:24  john
107  * Made paged out bitmaps have bm_data be a valid pointer
108  * instead of NULL, in case anyone accesses it.
109  *
110  * Revision 1.84  1995/02/09  12:50:59  john
111  * Bullet-proofed the piggy loading code.
112  *
113  * Revision 1.83  1995/02/07  17:08:51  john
114  * Added some error handling stuff instead of asserts.
115  *
116  * Revision 1.82  1995/02/03  17:06:48  john
117  * Changed sound stuff to allow low memory usage.
118  * Also, changed so that Sounds isn't an array of digi_sounds, it
119  * is a ubyte pointing into GameSounds, this way the digi.c code that
120  * locks sounds won't accidentally unlock a sound that is already playing, but
121  * since it's Sounds[soundno] is different, it would erroneously be unlocked.
122  *
123  * Revision 1.81  1995/02/02  21:56:39  matt
124  * Added data for new gauge bitmaps
125  *
126  * Revision 1.80  1995/02/01  23:31:57  john
127  * Took out loading bar.
128  *
129  * Revision 1.79  1995/01/28  15:13:18  allender
130  * bumped up Piggy_bitmap_cache_size
131  *
132  * Revision 1.78  1995/01/26  12:30:43  john
133  * Took out prev.
134  *
135  * Revision 1.77  1995/01/26  12:12:17  john
136  * Made buffer be big for bitmaps.
137  *
138  * Revision 1.76  1995/01/25  20:15:38  john
139  * Made editor allocate all mem.
140  *
141  * Revision 1.75  1995/01/25  14:52:56  john
142  * Made bitmap buffer be 1.5 MB.
143  *
144  * Revision 1.74  1995/01/22  16:03:19  mike
145  * localization.
146  *
147  * Revision 1.73  1995/01/22  15:58:36  mike
148  * localization
149  *
150  * Revision 1.72  1995/01/18  20:51:20  john
151  * Took out warnings.
152  *
153  * Revision 1.71  1995/01/18  20:47:21  john
154  * Added code to allocate sounds & bitmaps into diff
155  * buffers, also made sounds not be compressed for registered.
156  *
157  * Revision 1.70  1995/01/18  15:08:41  john
158  * Added start/stop time around paging.
159  * Made paging clear screen around globe.
160  *
161  * Revision 1.69  1995/01/18  10:07:51  john
162  *
163  * Took out debugging mprintfs.
164  *
165  * Revision 1.68  1995/01/17  14:27:42  john
166  * y
167  *
168  * Revision 1.67  1995/01/17  12:14:39  john
169  * Made walls, object explosion vclips load at level start.
170  *
171  * Revision 1.66  1995/01/15  13:15:44  john
172  * Made so that paging always happens, lowmem just loads less.
173  * Also, make KB load print to hud.
174  *
175  * Revision 1.65  1995/01/15  11:56:28  john
176  * Working version of paging.
177  *
178  * Revision 1.64  1995/01/14  19:17:07  john
179  * First version of new bitmap paging code.
180  *
181  * Revision 1.63  1994/12/15  12:26:44  john
182  * Added -nolowmem function.
183  *
184  * Revision 1.62  1994/12/14  21:12:26  john
185  * Fixed bug with page fault when exiting and using
186  * -nosound.
187  *
188  * Revision 1.61  1994/12/14  11:35:31  john
189  * Evened out thermometer for pig read.
190  *
191  * Revision 1.60  1994/12/14  10:51:00  john
192  * Sped up sound loading.
193  *
194  * Revision 1.59  1994/12/14  10:12:08  john
195  * Sped up pig loading.
196  *
197  * Revision 1.58  1994/12/13  09:14:47  john
198  * *** empty log message ***
199  *
200  * Revision 1.57  1994/12/13  09:12:57  john
201  * Made the bar always fill up.
202  *
203  * Revision 1.56  1994/12/13  03:49:08  john
204  * Made -lowmem not load the unnecessary bitmaps.
205  *
206  * Revision 1.55  1994/12/06  16:06:35  john
207  * Took out piggy sorting.
208  *
209  * Revision 1.54  1994/12/06  15:11:14  john
210  * Fixed bug with reading pigs.
211  *
212  * Revision 1.53  1994/12/06  14:14:47  john
213  * Added code to set low mem based on memory.
214  *
215  * Revision 1.52  1994/12/06  14:01:10  john
216  * Fixed bug that was causing -lowmem all the time..
217  *
218  * Revision 1.51  1994/12/06  13:33:48  john
219  * Added lowmem option.
220  *
221  * Revision 1.50  1994/12/05  19:40:10  john
222  * If -nosound or no sound card selected, don't load sounds from pig.
223  *
224  * Revision 1.49  1994/12/05  12:17:44  john
225  * Added code that locks/unlocks digital sounds on demand.
226  *
227  * Revision 1.48  1994/12/05  11:39:03  matt
228  * Fixed little mistake
229  *
230  * Revision 1.47  1994/12/05  09:29:22  john
231  * Added clength to the sound field.
232  *
233  * Revision 1.46  1994/12/04  15:27:15  john
234  * Fixed my stupid bug that looked at -nosound instead of digi_driver_card
235  * to see whether or not to lock down sound memory.
236  *
237  * Revision 1.45  1994/12/03  14:17:00  john
238  * Took out my debug mprintf.
239  *
240  * Revision 1.44  1994/12/03  13:32:37  john
241  * Fixed bug with offscreen bitmap.
242  *
243  * Revision 1.43  1994/12/03  13:07:13  john
244  * Made the pig read/write compressed sounds.
245  *
246  * Revision 1.42  1994/12/03  11:48:51  matt
247  * Added option to not dump sounds to pigfile
248  *
249  * Revision 1.41  1994/12/02  20:02:20  matt
250  * Made sound files constant match constant for table
251  *
252  * Revision 1.40  1994/11/29  11:03:09  adam
253  * upped # of sounds
254  *
255  * Revision 1.39  1994/11/27  23:13:51  matt
256  * Made changes for new mprintf calling convention
257  *
258  * Revision 1.38  1994/11/20  18:40:34  john
259  * MAde the piggy.lst and piggy.all not dump for release.
260  *
261  * Revision 1.37  1994/11/19  23:54:45  mike
262  * up number of bitmaps for shareware version.
263  *
264  * Revision 1.36  1994/11/19  19:53:05  mike
265  * change MAX_BITMAP_FILES
266  *
267  * Revision 1.35  1994/11/19  10:42:56  matt
268  * Increased number of bitmaps for non-shareware version
269  *
270  * Revision 1.34  1994/11/19  09:11:52  john
271  * Added avg_color to bitmaps saved in pig.
272  *
273  * Revision 1.33  1994/11/19  00:07:05  john
274  * Fixed bug with 8 char sound filenames not getting read from pig.
275  *
276  * Revision 1.32  1994/11/18  22:24:54  john
277  * Added -bigpig command line that doesn't rle your pig.
278  *
279  * Revision 1.31  1994/11/18  21:56:53  john
280  * Added a better, leaner pig format.
281  *
282  * Revision 1.30  1994/11/16  12:06:16  john
283  * Fixed bug with calling .bbms abms.
284  *
285  * Revision 1.29  1994/11/16  12:00:56  john
286  * Added piggy.all dump.
287  *
288  * Revision 1.28  1994/11/10  21:16:02  adam
289  * nothing important
290  *
291  * Revision 1.27  1994/11/10  13:42:00  john
292  * Made sounds not lock down if using -nosound.
293  *
294  * Revision 1.26  1994/11/09  19:55:40  john
295  * Added full rle support with texture rle caching.
296  *
297  * Revision 1.25  1994/11/09  16:36:42  john
298  * First version with RLE bitmaps in Pig.
299  *
300  * Revision 1.24  1994/10/27  19:42:59  john
301  * Disable the piglet option.
302  *
303  * Revision 1.23  1994/10/27  18:51:40  john
304  * Added -piglet option that only loads needed textures for a
305  * mine.  Only saved ~1MB, and code still doesn't free textures
306  * before you load a new mine.
307  *
308  * Revision 1.22  1994/10/25  13:11:42  john
309  * Made the sounds sort. Dumped piggy.lst.
310  *
311  * Revision 1.21  1994/10/06  17:06:23  john
312  * Took out rle stuff.
313  *
314  * Revision 1.20  1994/10/06  15:45:36  adam
315  * bumped MAX_BITMAP_FILES again!
316  *
317  * Revision 1.19  1994/10/06  11:01:17  yuan
318  * Upped MAX_BITMAP_FILES
319  *
320  * Revision 1.18  1994/10/06  10:44:45  john
321  * Added diagnostic message and psuedo run-length-encoder
322  * to see how much memory we would save by storing bitmaps
323  * in a RLE method.  Also, I commented out the code that
324  * stores 4K bitmaps on a 4K boundry to reduce pig size
325  * a bit.
326  *
327  * Revision 1.17  1994/10/04  20:03:13  matt
328  * Upped maximum number of bitmaps
329  *
330  * Revision 1.16  1994/10/03  18:04:20  john
331  * Fixed bug with data_offset not set right for bitmaps
332  * that are 64x64 and not aligned on a 4k boundry.
333  *
334  * Revision 1.15  1994/09/28  11:30:55  john
335  * changed inferno.pig to descent.pig, changed the way it
336  * is read.
337  *
338  * Revision 1.14  1994/09/22  16:14:17  john
339  * Redid intro sequecing.
340  *
341  * Revision 1.13  1994/09/19  14:42:47  john
342  * Locked down sounds with Virtual memory.
343  *
344  * Revision 1.12  1994/09/10  17:31:52  mike
345  * Increase number of loadable bitmaps.
346  *
347  * Revision 1.11  1994/09/01  19:32:49  mike
348  * Boost texture map allocation.
349  *
350  * Revision 1.10  1994/08/16  11:51:02  john
351  * Added grwased pigs.
352  *
353  * Revision 1.9  1994/07/06  09:18:03  adam
354  * upped bitmap #s
355  *
356  * Revision 1.8  1994/06/20  22:02:15  matt
357  * Fixed bug from last change
358  *
359  * Revision 1.7  1994/06/20  21:33:18  matt
360  * Made bm.h not include sounds.h, to reduce dependencies
361  *
362  * Revision 1.6  1994/06/20  16:52:19  john
363  * cleaned up init output a bit.
364  *
365  * Revision 1.5  1994/06/08  14:20:57  john
366  * Made piggy dump before going into game.
367  *
368  * Revision 1.4  1994/06/02  18:59:22  matt
369  * Clear selector field of bitmap loaded from pig file
370  *
371  * Revision 1.3  1994/05/06  15:31:41  john
372  * Made name field a bit longer.
373  *
374  * Revision 1.2  1994/05/06  13:02:44  john
375  * Added piggy stuff; worked on supertransparency
376  *
377  * Revision 1.1  1994/05/06  11:47:26  john
378  * Initial revision
379  *
380  *
381  */
382
383
384 #ifdef HAVE_CONFIG_H
385 #include <conf.h>
386 #endif
387
388 #ifdef RCS
389 static char rcsid[] = "$Id: piggy.c,v 1.26 2003-03-22 03:19:50 btb Exp $";
390 #endif
391
392
393 #include <stdio.h>
394 #include <string.h>
395
396 #include "pstypes.h"
397 #include "strutil.h"
398 #include "inferno.h"
399 #include "gr.h"
400 #include "u_mem.h"
401 #include "iff.h"
402 #include "mono.h"
403 #include "error.h"
404 #include "sounds.h"
405 #include "songs.h"
406 #include "bm.h"
407 #include "bmread.h"
408 #include "hash.h"
409 #include "args.h"
410 #include "palette.h"
411 #include "gamefont.h"
412 #include "rle.h"
413 #include "screens.h"
414 #include "piggy.h"
415 #include "texmerge.h"
416 #include "paging.h"
417 #include "game.h"
418 #include "text.h"
419 #include "cfile.h"
420 #include "newmenu.h"
421 #include "byteswap.h"
422 #include "findfile.h"
423 #include "makesig.h"
424
425 #ifndef MACINTOSH
426 //      #include "unarj.h"
427 #else
428         #include <Strings.h>            // MacOS Toolbox header
429         #include <Files.h>
430         #include <unistd.h>
431 #endif
432
433 //#define NO_DUMP_SOUNDS        1   //if set, dump bitmaps but not sounds
434
435 #define DEFAULT_PIGFILE_REGISTERED      "groupa.pig"
436 #define DEFAULT_PIGFILE_SHAREWARE       "d2demo.pig"
437 #define DEFAULT_HAMFILE_REGISTERED      "descent2.ham"
438 #define DEFAULT_HAMFILE_SHAREWARE       "d2demo.ham"
439
440 #define 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 #define D1_SHAREWARE_10_PIGSIZE 2529454 // v1.0 - 1.2
445 #define D1_SHAREWARE_PIGSIZE    2509799 // v1.4
446 #define D1_PIGSIZE              4920305
447 #define D1_OEM_PIGSIZE          5039735 // Destination: Saturn
448 #define D1_MAC_PIGSIZE          3975533
449 #define D1_MAC_SHARE_PIGSIZE    2714487
450 #define MAC_ALIEN1_PIGSIZE      5013035
451 #define MAC_ALIEN2_PIGSIZE      4909916
452 #define MAC_FIRE_PIGSIZE        4969035
453 #define MAC_GROUPA_PIGSIZE      4929684 // also used for mac shareware
454 #define MAC_ICE_PIGSIZE         4923425
455 #define MAC_WATER_PIGSIZE       4832403
456
457 ubyte *BitmapBits = NULL;
458 ubyte *SoundBits = NULL;
459
460 typedef struct BitmapFile {
461         char    name[15];
462 } BitmapFile;
463
464 typedef struct SoundFile {
465         char    name[15];
466 } SoundFile;
467
468 hashtable AllBitmapsNames;
469 hashtable AllDigiSndNames;
470
471 int Num_bitmap_files = 0;
472 int Num_sound_files = 0;
473
474 digi_sound GameSounds[MAX_SOUND_FILES];
475 int SoundOffset[MAX_SOUND_FILES];
476 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
477
478 alias alias_list[MAX_ALIASES];
479 int Num_aliases=0;
480
481 int Must_write_hamfile = 0;
482 int Num_bitmap_files_new = 0;
483 int Num_sound_files_new = 0;
484 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
485 static SoundFile AllSounds[ MAX_SOUND_FILES ];
486
487 int Piggy_hamfile_version = 0;
488
489 int piggy_low_memory = 0;
490
491 int Piggy_bitmap_cache_size = 0;
492 int Piggy_bitmap_cache_next = 0;
493 ubyte * Piggy_bitmap_cache_data = NULL;
494 static int GameBitmapOffset[MAX_BITMAP_FILES];
495 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
496 ushort GameBitmapXlat[MAX_BITMAP_FILES];
497
498 #define PIGGY_BUFFER_SIZE (2400*1024)
499
500 #ifdef MACINTOSH
501 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024)             // size of buffer when piggy_low_memory is set
502
503 #ifdef SHAREWARE
504 #undef PIGGY_BUFFER_SIZE
505 #undef PIGGY_SMALL_BUFFER_SIZE
506
507 #define PIGGY_BUFFER_SIZE (2000*1024)
508 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
509 #endif          // SHAREWARE
510
511 #endif
512
513 int piggy_page_flushed = 0;
514
515 #define DBM_FLAG_ABM            64
516
517 ubyte BigPig = 0;
518
519 #ifdef MACINTOSH
520         extern short    cd_VRefNum;
521         extern void             ConcatPStr(StringPtr dst, StringPtr src);
522         extern int              ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
523         extern int              ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
524 #endif
525
526 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
527
528 #ifdef EDITOR
529 void piggy_write_pigfile(char *filename);
530 static void write_int(int i,FILE *file);
531 #endif
532
533 void swap_0_255(grs_bitmap *bmp)
534 {
535         int i;
536
537         for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
538                 if(bmp->bm_data[i] == 0)
539                         bmp->bm_data[i] = 255;
540                 else if (bmp->bm_data[i] == 255)
541                         bmp->bm_data[i] = 0;
542         }
543 }
544
545 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
546 {
547         bitmap_index temp;
548         Assert( Num_bitmap_files < MAX_BITMAP_FILES );
549
550         temp.index = Num_bitmap_files;
551
552         if (!in_file)   {
553 #ifdef EDITOR
554                 if ( FindArg("-macdata") )
555                         swap_0_255( bmp );
556 #endif
557                 if ( !BigPig )  gr_bitmap_rle_compress( bmp );
558                 Num_bitmap_files_new++;
559         }
560
561         strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
562         hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
563         GameBitmaps[Num_bitmap_files] = *bmp;
564         if ( !in_file ) {
565                 GameBitmapOffset[Num_bitmap_files] = 0;
566                 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
567         }
568         Num_bitmap_files++;
569
570         return temp;
571 }
572
573 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
574 {
575         int i;
576
577         Assert( Num_sound_files < MAX_SOUND_FILES );
578
579         strncpy( AllSounds[Num_sound_files].name, name, 12 );
580         hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
581         GameSounds[Num_sound_files] = *snd;
582         if ( !in_file ) {
583                 SoundOffset[Num_sound_files] = 0;       
584         }
585
586         i = Num_sound_files;
587    
588         if (!in_file)
589                 Num_sound_files_new++;
590
591         Num_sound_files++;
592         return i;
593 }
594
595 bitmap_index piggy_find_bitmap( char * name )   
596 {
597         bitmap_index bmp;
598         int i;
599         char *t;
600
601         bmp.index = 0;
602
603         if ((t=strchr(name,'#'))!=NULL)
604                 *t=0;
605
606         for (i=0;i<Num_aliases;i++)
607                 if (stricmp(name,alias_list[i].alias_name)==0) {
608                         if (t) {                //extra stuff for ABMs
609                                 static char temp[FILENAME_LEN];
610                                 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
611                                 name = temp;
612                                 strcat(name,"#");
613                                 strcat(name,t+1);
614                         }
615                         else
616                                 name=alias_list[i].file_name; 
617                         break;
618                 }
619
620         if (t)
621                 *t = '#';
622
623         i = hashtable_search( &AllBitmapsNames, name );
624         Assert( i != 0 );
625         if ( i < 0 )
626                 return bmp;
627
628         bmp.index = i;
629         return bmp;
630 }
631
632 int piggy_find_sound( char * name )     
633 {
634         int i;
635
636         i = hashtable_search( &AllDigiSndNames, name );
637
638         if ( i < 0 )
639                 return 255;
640
641         return i;
642 }
643
644 CFILE * Piggy_fp = NULL;
645
646 #define FILENAME_LEN 13
647
648 char Current_pigfile[FILENAME_LEN] = "";
649
650 void piggy_close_file()
651 {
652         if ( Piggy_fp ) {
653                 cfclose( Piggy_fp );
654                 Piggy_fp        = NULL;
655                 Current_pigfile[0] = 0;
656         }
657 }
658
659 int Pigfile_initialized=0;
660
661 #define PIGFILE_ID              MAKE_SIG('G','I','P','P') //PPIG
662 #define PIGFILE_VERSION         2
663
664 extern char CDROM_dir[];
665
666 int request_cd(void);
667
668
669 #ifdef MACINTOSH
670
671 //copies a pigfile from the CD to the current dir
672 //retuns file handle of new pig
673 CFILE *copy_pigfile_from_cd(char *filename)             // MACINTOSH VERSION
674 {
675         // C Stuff
676         char                    sourcePathAndFileCStr[255] = "";
677         char                    destPathAndFileCStr[255]        = "";
678         FILEFINDSTRUCT  find;
679         FILE*                   sourceFile      = NULL;
680         FILE*                   destFile        = NULL;
681         const int               BUF_SIZE = 4096;
682         ubyte                   buf[BUF_SIZE];
683
684         // Mac Stuff
685         Str255                  sourcePathAndFilePStr = "\p";
686         Str255                  destPathAndFilePStr = "\p";
687         Str255                  pigfileNamePStr = "\p";
688         HParamBlockRec  theSourcePigHFSParams;
689         HParamBlockRec  theDestPigHFSParams;
690         OSErr                   theErr = noErr;
691         char                    oldDirCStr[255] = "";
692
693         getcwd(oldDirCStr, 255);
694         
695         show_boxed_message("Copying bitmap data from CD...");
696         gr_palette_load(gr_palette);    //I don't think this line is really needed
697
698         chdir(":Data");
699         //First, delete all PIG files currently in the directory
700         if( !FileFindFirst( "*.pig", &find ) )
701         {
702                 do
703                 {
704                         remove(find.name);
705                 } while( !FileFindNext( &find ) );
706                 
707                 FileFindClose();
708         }
709         chdir(oldDirCStr);
710
711         //Now, copy over new pig
712         songs_stop_redbook();           //so we can read off the cd
713
714         // make the source path "<cd volume>:Data:filename.pig"
715 //MWA   ConvertCToPStr(filename, pigfileNamePStr);
716
717 //MWA   ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:");        // volume ID is cd_VRefNum
718 //MWA   ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
719
720         strupr(filename);
721         strcpy(sourcePathAndFileCStr, "Descent II:Data:");
722         strcat(sourcePathAndFileCStr, filename);
723         
724         // make the destination path "<default directory>:Data:filename.pig"
725 //MWA   ConcatPStr(destPathAndFilePStr, "\p:Data:");
726 //MWA   ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
727 //MWA   ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
728 //MWA   ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
729
730         strcpy(destPathAndFileCStr, ":Data:");
731         strcat(destPathAndFileCStr, filename);
732
733         strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
734         strcpy(destPathAndFilePStr, destPathAndFileCStr);
735         c2pstr(sourcePathAndFilePStr);
736         c2pstr(destPathAndFilePStr);
737         
738         do {
739                 // Open the source file
740                 sourceFile = fopen(sourcePathAndFileCStr,"rb");
741
742                 if (!sourceFile) {
743
744                         if (request_cd() == -1)
745                                 Error("Cannot load file <%s> from CD",filename);
746                 }
747
748         } while (!sourceFile);
749
750
751         // Get the time stamp from the source file
752         theSourcePigHFSParams.fileParam.ioCompletion    = nil;
753         theSourcePigHFSParams.fileParam.ioNamePtr               = sourcePathAndFilePStr;
754         theSourcePigHFSParams.fileParam.ioVRefNum               = cd_VRefNum;
755         theSourcePigHFSParams.fileParam.ioFDirIndex     = 0;
756         theSourcePigHFSParams.fileParam.ioDirID         = 0;
757         
758         theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
759         if (theErr != noErr)
760         {
761                 // Error getting file time stamp!! Why? JTS
762                 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
763         }
764         
765         // Copy the file over
766         // C Stuff......
767         
768         // Open the destination file
769         destFile = fopen(destPathAndFileCStr,"wb");
770         if (!destFile)
771         {
772                 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
773         }
774         
775         // Copy bytes until the end of the source file
776         while (!feof(sourceFile))
777         {
778                 int bytes_read;
779                 int x;
780
781                 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
782                 if (ferror(sourceFile))
783                         Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
784
785 // Assert is bogus              Assert(bytes_read == BUF_SIZE || feof(sourceFile));
786
787                 fwrite(buf,1,bytes_read,destFile);
788                 if (ferror(destFile))
789                         Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
790         }
791
792         // close the source/dest files
793         if (fclose(sourceFile))
794                 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
795         if (fclose(destFile))
796                 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
797
798         // Get the current hfs data for the new file
799         theDestPigHFSParams.fileParam.ioCompletion      = nil;
800         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
801         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
802         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
803         theDestPigHFSParams.fileParam.ioDirID           = 0;
804         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
805         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
806         {
807                 // Error getting file time stamp!! Why? JTS
808                 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
809         }
810
811         // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
812         theDestPigHFSParams.fileParam.ioNamePtr         = destPathAndFilePStr;
813         theDestPigHFSParams.fileParam.ioVRefNum         = 0;
814         theDestPigHFSParams.fileParam.ioFDirIndex       = 0;
815         theDestPigHFSParams.fileParam.ioDirID           = 0;
816
817         // Copy the time stamp from the source file info
818         theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
819         theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
820         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
821         theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
822         
823         // Set the dest file's time stamp to the source file's time stamp values
824         theErr = PBHSetFInfo(&theDestPigHFSParams, false);
825
826         if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
827         {
828                 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
829         }
830
831         theErr = PBHGetFInfo(&theDestPigHFSParams, false);
832
833         return cfopen(destPathAndFileCStr, "rb");
834 }
835
836 #else   //PC Version of copy_pigfile_from_cd is below
837
838 //copies a pigfile from the CD to the current dir
839 //retuns file handle of new pig
840 CFILE *copy_pigfile_from_cd(char *filename)
841 {
842         char name[80];
843         FILEFINDSTRUCT find;
844         int ret;
845
846         return cfopen(filename, "rb");
847         show_boxed_message("Copying bitmap data from CD...");
848         gr_palette_load(gr_palette);    //I don't think this line is really needed
849
850         //First, delete all PIG files currently in the directory
851
852         if( !FileFindFirst( "*.pig", &find ) ) {
853                 do      {
854                         remove(find.name);
855                 } while( !FileFindNext( &find ) );
856                 FileFindClose();
857         }
858
859         //Now, copy over new pig
860
861         songs_stop_redbook();           //so we can read off the cd
862
863         //new code to unarj file
864         strcpy(name,CDROM_dir);
865         strcat(name,"descent2.sow");
866
867         do {
868 //              ret = unarj_specific_file(name,filename,filename);
869 // DPH:FIXME
870
871                 ret = !EXIT_SUCCESS;
872
873                 if (ret != EXIT_SUCCESS) {
874
875                         //delete file, so we don't leave partial file
876                         remove(filename);
877
878                         #ifndef MACINTOSH
879                         if (request_cd() == -1)
880                         #endif
881                                 //NOTE LINK TO ABOVE IF
882                                 Error("Cannot load file <%s> from CD",filename);
883                 }
884
885         } while (ret != EXIT_SUCCESS);
886
887         return cfopen(filename, "rb");
888 }
889
890 #endif // end of ifdef MAC around copy_pigfile_from_cd
891
892 //initialize a pigfile, reading headers
893 //returns the size of all the bitmap data
894 void piggy_init_pigfile(char *filename)
895 {
896         int i;
897         char temp_name[16];
898         char temp_name_read[16];
899         grs_bitmap temp_bitmap;
900         DiskBitmapHeader bmh;
901         int header_size, N_bitmaps, data_size, data_start;
902         #ifdef MACINTOSH
903         char name[255];         // filename + path for the mac
904         #endif
905
906         piggy_close_file();             //close old pig if still open
907
908         //rename pigfile for shareware
909         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
910                 filename = DEFAULT_PIGFILE_SHAREWARE;
911
912         #ifndef MACINTOSH
913                 Piggy_fp = cfopen( filename, "rb" );
914         #else
915                 sprintf(name, ":Data:%s", filename);
916                 Piggy_fp = cfopen( name, "rb" );
917
918                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
919                         if (Piggy_fp == NULL)
920                         {
921                                 Error("Cannot load required file <%s>",name);
922                         }
923                 #endif  // end of if def shareware
924
925         #endif
926
927         if (!Piggy_fp) {
928                 #ifdef EDITOR
929                         return;         //if editor, ok to not have pig, because we'll build one
930                 #else
931                         Piggy_fp = copy_pigfile_from_cd(filename);
932                 #endif
933         }
934
935         if (Piggy_fp) {                         //make sure pig is valid type file & is up-to-date
936                 int pig_id,pig_version;
937
938                 pig_id = cfile_read_int(Piggy_fp);
939                 pig_version = cfile_read_int(Piggy_fp);
940                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
941                         cfclose(Piggy_fp);              //out of date pig
942                         Piggy_fp = NULL;                        //..so pretend it's not here
943                 }
944         }
945
946         if (!Piggy_fp) {
947
948                 #ifdef EDITOR
949                         return;         //if editor, ok to not have pig, because we'll build one
950                 #else
951                         Error("Cannot load required file <%s>",filename);
952                 #endif
953         }
954
955         strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
956
957         N_bitmaps = cfile_read_int(Piggy_fp);
958
959         header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
960
961         data_start = header_size + cftell(Piggy_fp);
962
963         data_size = cfilelength(Piggy_fp) - data_start;
964
965         Num_bitmap_files = 1;
966
967         for (i=0; i<N_bitmaps; i++ )    {
968                 DiskBitmapHeader_read(&bmh, Piggy_fp);
969                 memcpy( temp_name_read, bmh.name, 8 );
970                 temp_name_read[8] = 0;
971                 if ( bmh.dflags & DBM_FLAG_ABM )        
972                         sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
973                 else
974                         strcpy( temp_name, temp_name_read );
975                 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
976                 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
977                 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
978                 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
979                 temp_bitmap.avg_color = bmh.avg_color;
980                 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
981
982                 GameBitmapFlags[i+1] = 0;
983                 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
984                 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
985                 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
986                 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
987                 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
988
989                 GameBitmapOffset[i+1] = bmh.offset + data_start;
990                 Assert( (i+1) == Num_bitmap_files );
991                 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
992         }
993
994 #ifdef EDITOR
995         Piggy_bitmap_cache_size = data_size + (data_size/10);   //extra mem for new bitmaps
996         Assert( Piggy_bitmap_cache_size > 0 );
997 #else
998         Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
999         #ifdef MACINTOSH
1000         if (piggy_low_memory)
1001                 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
1002         #endif
1003 #endif
1004         BitmapBits = d_malloc( Piggy_bitmap_cache_size );
1005         if ( BitmapBits == NULL )
1006                 Error( "Not enough memory to load bitmaps\n" );
1007         Piggy_bitmap_cache_data = BitmapBits;
1008         Piggy_bitmap_cache_next = 0;
1009
1010         #if defined(MACINTOSH) && defined(SHAREWARE)
1011 //      load_exit_models();
1012         #endif
1013
1014         Pigfile_initialized=1;
1015 }
1016
1017 #define FILENAME_LEN 13
1018 #define MAX_BITMAPS_PER_BRUSH 30
1019
1020 extern int compute_average_pixel(grs_bitmap *new);
1021
1022 //reads in a new pigfile (for new palette)
1023 //returns the size of all the bitmap data
1024 void piggy_new_pigfile(char *pigname)
1025 {
1026         int i;
1027         char temp_name[16];
1028         char temp_name_read[16];
1029         grs_bitmap temp_bitmap;
1030         DiskBitmapHeader bmh;
1031         int header_size, N_bitmaps, data_size, data_start;
1032         int must_rewrite_pig = 0;
1033         #ifdef MACINTOSH
1034         char name[255];
1035         #endif
1036
1037         strlwr(pigname);
1038
1039         //rename pigfile for shareware
1040         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
1041                 pigname = DEFAULT_PIGFILE_SHAREWARE;
1042
1043         if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
1044                 return;         //already have correct pig
1045
1046         if (!Pigfile_initialized) {                     //have we ever opened a pigfile?
1047                 piggy_init_pigfile(pigname);            //..no, so do initialization stuff
1048                 return;
1049         }
1050         else
1051                 piggy_close_file();             //close old pig if still open
1052
1053         Piggy_bitmap_cache_next = 0;            //free up cache
1054
1055         strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
1056
1057         #ifndef MACINTOSH
1058                 Piggy_fp = cfopen( pigname, "rb" );
1059         #else
1060                 sprintf(name, ":Data:%s", pigname);
1061                 Piggy_fp = cfopen( name, "rb" );
1062
1063                 #ifdef SHAREWARE        // if we are in the shareware version, we must have the pig by now.
1064                         if (Piggy_fp == NULL)
1065                         {
1066                                 Error("Cannot load required file <%s>",name);
1067                         }
1068                 #endif  // end of if def shareware
1069         #endif
1070
1071         #ifndef EDITOR
1072         if (!Piggy_fp)
1073                 Piggy_fp = copy_pigfile_from_cd(pigname);
1074         #endif
1075
1076         if (Piggy_fp) {  //make sure pig is valid type file & is up-to-date
1077                 int pig_id,pig_version;
1078
1079                 pig_id = cfile_read_int(Piggy_fp);
1080                 pig_version = cfile_read_int(Piggy_fp);
1081                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
1082                         cfclose(Piggy_fp);              //out of date pig
1083                         Piggy_fp = NULL;                        //..so pretend it's not here
1084                 }
1085         }
1086
1087         #ifndef EDITOR
1088         if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
1089         #endif
1090
1091         if (Piggy_fp) {
1092
1093                 N_bitmaps = cfile_read_int(Piggy_fp);
1094
1095                 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
1096
1097                 data_start = header_size + cftell(Piggy_fp);
1098
1099                 data_size = cfilelength(Piggy_fp) - data_start;
1100
1101                 for (i=1; i<=N_bitmaps; i++ )   {
1102                         DiskBitmapHeader_read(&bmh, Piggy_fp);
1103                         memcpy( temp_name_read, bmh.name, 8 );
1104                         temp_name_read[8] = 0;
1105         
1106                         if ( bmh.dflags & DBM_FLAG_ABM )        
1107                                 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
1108                         else
1109                                 strcpy( temp_name, temp_name_read );
1110         
1111                         //Make sure name matches
1112                         if (strcmp(temp_name,AllBitmaps[i].name)) {
1113                                 //Int3();       //this pig is out of date.  Delete it
1114                                 must_rewrite_pig=1;
1115                         }
1116         
1117                         strcpy(AllBitmaps[i].name,temp_name);
1118
1119                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1120         
1121                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1122                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1123                         temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
1124                         temp_bitmap.avg_color = bmh.avg_color;
1125                         temp_bitmap.bm_data = Piggy_bitmap_cache_data;
1126
1127                         GameBitmapFlags[i] = 0;
1128
1129                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
1130                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
1131                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
1132                         if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
1133                         if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
1134         
1135                         GameBitmapOffset[i] = bmh.offset + data_start;
1136         
1137                         GameBitmaps[i] = temp_bitmap;
1138                 }
1139         }
1140         else
1141                 N_bitmaps = 0;          //no pigfile, so no bitmaps
1142
1143         #ifndef EDITOR
1144
1145         Assert(N_bitmaps == Num_bitmap_files-1);
1146
1147         #else
1148
1149         if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
1150                 int size;
1151
1152                 //re-read the bitmaps that aren't in this pig
1153
1154                 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
1155                         char *p;
1156
1157                         p = strchr(AllBitmaps[i].name,'#');
1158
1159                         if (p) {                //this is an ABM
1160                                 char abmname[FILENAME_LEN];
1161                                 int fnum;
1162                                 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
1163                                 int iff_error;          //reference parm to avoid warning message
1164                                 ubyte newpal[768];
1165                                 char basename[FILENAME_LEN];
1166                                 int nframes;
1167                         
1168                                 strcpy(basename,AllBitmaps[i].name);
1169                                 basename[p-AllBitmaps[i].name] = 0;             //cut off "#nn" part
1170                                 
1171                                 sprintf( abmname, "%s.abm", basename );
1172
1173                                 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
1174
1175                                 if (iff_error != IFF_NO_ERROR)  {
1176                                         mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
1177                                         Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
1178                                 }
1179                         
1180                                 for (fnum=0;fnum<nframes; fnum++)       {
1181                                         char tempname[20];
1182                                         int SuperX;
1183
1184                                         sprintf( tempname, "%s#%d", basename, fnum );
1185
1186                                         //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1187                                         SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1188                                         //above makes assumption that supertransparent color is 254
1189
1190                                         if ( iff_has_transparency )
1191                                                 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
1192                                         else
1193                                                 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
1194
1195                                         bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
1196
1197 #ifdef EDITOR
1198                                         if ( FindArg("-macdata") )
1199                                                 swap_0_255( bm[fnum] );
1200 #endif
1201                                         if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
1202
1203                                         if (bm[fnum]->bm_flags & BM_FLAG_RLE)
1204                                                 size = *((int *) bm[fnum]->bm_data);
1205                                         else
1206                                                 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
1207
1208                                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
1209                                         d_free(bm[fnum]->bm_data);
1210                                         bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1211                                         Piggy_bitmap_cache_next += size;
1212
1213                                         GameBitmaps[i+fnum] = *bm[fnum];
1214
1215                                         // -- mprintf( (0, "U" ));
1216                                         d_free( bm[fnum] );
1217                                 }
1218
1219                                 i += nframes-1;         //filled in multiple bitmaps
1220                         }
1221                         else {          //this is a BBM
1222
1223                                 grs_bitmap * new;
1224                                 ubyte newpal[256*3];
1225                                 int iff_error;
1226                                 char bbmname[FILENAME_LEN];
1227                                 int SuperX;
1228
1229                                 MALLOC( new, grs_bitmap, 1 );
1230
1231                                 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
1232                                 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
1233
1234                                 new->bm_handle=0;
1235                                 if (iff_error != IFF_NO_ERROR)          {
1236                                         mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
1237                                         Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
1238                                 }
1239
1240                                 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1241                                 //above makes assumption that supertransparent color is 254
1242
1243                                 if ( iff_has_transparency )
1244                                         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
1245                                 else
1246                                         gr_remap_bitmap_good( new, newpal, -1, SuperX );
1247
1248                                 new->avg_color = compute_average_pixel(new);
1249
1250 #ifdef EDITOR
1251                                 if ( FindArg("-macdata") )
1252                                         swap_0_255( new );
1253 #endif
1254                                 if ( !BigPig )  gr_bitmap_rle_compress( new );
1255
1256                                 if (new->bm_flags & BM_FLAG_RLE)
1257                                         size = *((int *) new->bm_data);
1258                                 else
1259                                         size = new->bm_w * new->bm_h;
1260
1261                                 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
1262                                 d_free(new->bm_data);
1263                                 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1264                                 Piggy_bitmap_cache_next += size;
1265
1266                                 GameBitmaps[i] = *new;
1267         
1268                                 d_free( new );
1269
1270                                 // -- mprintf( (0, "U" ));
1271                         }
1272                 }
1273
1274                 //@@Dont' do these things which are done when writing
1275                 //@@for (i=0; i < Num_bitmap_files; i++ )       {
1276                 //@@    bitmap_index bi;
1277                 //@@    bi.index = i;
1278                 //@@    PIGGY_PAGE_IN( bi );
1279                 //@@}
1280                 //@@
1281                 //@@piggy_close_file();
1282
1283                 piggy_write_pigfile(pigname);
1284
1285                 Current_pigfile[0] = 0;                 //say no pig, to force reload
1286
1287                 piggy_new_pigfile(pigname);             //read in just-generated pig
1288
1289
1290         }
1291         #endif  //ifdef EDITOR
1292
1293 }
1294
1295 ubyte bogus_data[64*64];
1296 grs_bitmap bogus_bitmap;
1297 ubyte bogus_bitmap_initialized=0;
1298 digi_sound bogus_sound;
1299
1300 #define HAMFILE_ID              MAKE_SIG('!','M','A','H') //HAM!
1301 #define HAMFILE_VERSION 3
1302 //version 1 -> 2:  save marker_model_num
1303 //version 2 -> 3:  removed sound files
1304
1305 #define SNDFILE_ID              MAKE_SIG('D','N','S','D') //DSND
1306 #define SNDFILE_VERSION 1
1307
1308 int read_hamfile()
1309 {
1310         CFILE * ham_fp = NULL;
1311         int ham_id;
1312         int sound_offset = 0;
1313         #ifdef MACINTOSH
1314         char name[255];
1315         #endif
1316
1317         #ifndef MACINTOSH
1318         ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1319         #else
1320         sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1321         ham_fp = cfopen( name, "rb" );
1322         #endif
1323
1324         if (ham_fp == NULL) {
1325                 Must_write_hamfile = 1;
1326                 return 0;
1327         }
1328
1329         //make sure ham is valid type file & is up-to-date
1330         ham_id = cfile_read_int(ham_fp);
1331         Piggy_hamfile_version = cfile_read_int(ham_fp);
1332         if (ham_id != HAMFILE_ID)
1333                 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1334 #if 0
1335         if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1336                 Must_write_hamfile = 1;
1337                 cfclose(ham_fp);                                                //out of date ham
1338                 return 0;
1339         }
1340 #endif
1341
1342         if (Piggy_hamfile_version < 3) // hamfile contains sound info
1343                 sound_offset = cfile_read_int(ham_fp);
1344
1345         #ifndef EDITOR
1346         {
1347                 //int i;
1348
1349                 bm_read_all(ham_fp);
1350                 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1351                 // no swap here?
1352                 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1353                         //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1354                         //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1355                 //}
1356         }
1357         #endif
1358
1359         if (Piggy_hamfile_version < 3) {
1360                 int N_sounds;
1361                 int sound_start;
1362                 int header_size;
1363                 int i;
1364                 DiskSoundHeader sndh;
1365                 digi_sound temp_sound;
1366                 char temp_name_read[16];
1367                 int sbytes = 0;
1368
1369                 cfseek(ham_fp, sound_offset, SEEK_SET);
1370                 N_sounds = cfile_read_int(ham_fp);
1371
1372                 sound_start = cftell(ham_fp);
1373
1374                 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1375
1376                 //Read sounds
1377
1378                 for (i=0; i<N_sounds; i++ ) {
1379                         DiskSoundHeader_read(&sndh, ham_fp);
1380                         temp_sound.length = sndh.length;
1381                         temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1382                         SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1383                         memcpy( temp_name_read, sndh.name, 8 );
1384                         temp_name_read[8] = 0;
1385                         piggy_register_sound( &temp_sound, temp_name_read, 1 );
1386 #ifdef MACINTOSH
1387                         if (piggy_is_needed(i))
1388 #endif          // note link to if.
1389                                 sbytes += sndh.length;
1390                         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1391                 }
1392
1393                 SoundBits = d_malloc( sbytes + 16 );
1394                 if ( SoundBits == NULL )
1395                         Error( "Not enough memory to load sounds\n" );
1396
1397                 mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1398
1399                 //      piggy_read_sounds(ham_fp);
1400
1401         }
1402
1403         cfclose(ham_fp);
1404
1405         return 1;
1406
1407 }
1408
1409 int read_sndfile()
1410 {
1411         CFILE * snd_fp = NULL;
1412         int snd_id,snd_version;
1413         int N_sounds;
1414         int sound_start;
1415         int header_size;
1416         int i,size, length;
1417         DiskSoundHeader sndh;
1418         digi_sound temp_sound;
1419         char temp_name_read[16];
1420         int sbytes = 0;
1421         #ifdef MACINTOSH
1422         char name[255];
1423         #endif
1424
1425         #ifndef MACINTOSH
1426         snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1427         #else
1428         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1429         snd_fp = cfopen( name, "rb");
1430         #endif
1431         
1432         if (snd_fp == NULL)
1433                 return 0;
1434
1435         //make sure soundfile is valid type file & is up-to-date
1436         snd_id = cfile_read_int(snd_fp);
1437         snd_version = cfile_read_int(snd_fp);
1438         if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1439                 cfclose(snd_fp);                                                //out of date sound file
1440                 return 0;
1441         }
1442
1443         N_sounds = cfile_read_int(snd_fp);
1444
1445         sound_start = cftell(snd_fp);
1446         size = cfilelength(snd_fp) - sound_start;
1447         length = size;
1448         mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1449
1450         header_size = N_sounds*sizeof(DiskSoundHeader);
1451
1452         //Read sounds
1453
1454         for (i=0; i<N_sounds; i++ ) {
1455                 DiskSoundHeader_read(&sndh, snd_fp);
1456                 //size -= sizeof(DiskSoundHeader);
1457                 temp_sound.length = sndh.length;
1458                 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1459                 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1460                 memcpy( temp_name_read, sndh.name, 8 );
1461                 temp_name_read[8] = 0;
1462                 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1463                 #ifdef MACINTOSH
1464                 if (piggy_is_needed(i))
1465                 #endif          // note link to if.
1466                 sbytes += sndh.length;
1467                 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1468         }
1469
1470         SoundBits = d_malloc( sbytes + 16 );
1471         if ( SoundBits == NULL )
1472                 Error( "Not enough memory to load sounds\n" );
1473
1474         mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1475
1476 //      piggy_read_sounds(snd_fp);
1477
1478         cfclose(snd_fp);
1479
1480         return 1;
1481 }
1482
1483 int piggy_init(void)
1484 {
1485         int ham_ok=0,snd_ok=0;
1486         int i;
1487
1488         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1489         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1490
1491         for (i=0; i<MAX_SOUND_FILES; i++ )      {
1492                 GameSounds[i].length = 0;
1493                 GameSounds[i].data = NULL;
1494                 SoundOffset[i] = 0;
1495         }
1496
1497         for (i=0; i<MAX_BITMAP_FILES; i++ )     
1498                 GameBitmapXlat[i] = i;
1499
1500         if ( !bogus_bitmap_initialized )        {
1501                 int i;
1502                 ubyte c;
1503                 bogus_bitmap_initialized = 1;
1504                 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1505                 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1506                 bogus_bitmap.bm_data = bogus_data;
1507                 c = gr_find_closest_color( 0, 0, 63 );
1508                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1509                 c = gr_find_closest_color( 63, 0, 0 );
1510                 // Make a big red X !
1511                 for (i=0; i<64; i++ )   {
1512                         bogus_data[i*64+i] = c;
1513                         bogus_data[i*64+(63-i)] = c;
1514                 }
1515                 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1516                 bogus_sound.length = 64*64;
1517                 bogus_sound.data = bogus_data;
1518                 GameBitmapOffset[0] = 0;
1519         }
1520
1521         if ( FindArg( "-bigpig" ))
1522                 BigPig = 1;
1523
1524         if ( FindArg( "-lowmem" ))
1525                 piggy_low_memory = 1;
1526
1527         if ( FindArg( "-nolowmem" ))
1528                 piggy_low_memory = 0;
1529
1530         if (piggy_low_memory)
1531                 digi_lomem = 1;
1532
1533         WIN(DDGRLOCK(dd_grd_curcanv));
1534                 gr_set_curfont( SMALL_FONT );
1535                 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1536                 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1537         WIN(DDGRUNLOCK(dd_grd_curcanv));
1538
1539 #if 1 //def EDITOR //need for d1 mission briefings
1540         piggy_init_pigfile(DEFAULT_PIGFILE);
1541 #endif
1542
1543         snd_ok = ham_ok = read_hamfile();
1544
1545         if (Piggy_hamfile_version >= 3)
1546                 snd_ok = read_sndfile();
1547
1548         atexit(piggy_close);
1549
1550         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1551         return (ham_ok && snd_ok);               //read ok
1552 }
1553
1554 int piggy_is_needed(int soundnum)
1555 {
1556         int i;
1557
1558         if ( !digi_lomem ) return 1;
1559
1560         for (i=0; i<MAX_SOUNDS; i++ )   {
1561                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1562                         return 1;
1563         }
1564         return 0;
1565 }
1566
1567
1568 void piggy_read_sounds(void)
1569 {
1570         CFILE * fp = NULL;
1571         ubyte * ptr;
1572         int i, sbytes;
1573         #ifdef MACINTOSH
1574         char name[255];
1575         #endif
1576
1577         ptr = SoundBits;
1578         sbytes = 0;
1579
1580         #ifndef MACINTOSH
1581         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1582         #else
1583         sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1584         fp = cfopen( name, "rb");
1585         #endif
1586
1587         if (fp == NULL)
1588                 return;
1589
1590         for (i=0; i<Num_sound_files; i++ )      {
1591                 digi_sound *snd = &GameSounds[i];
1592
1593                 if ( SoundOffset[i] > 0 )       {
1594                         if ( piggy_is_needed(i) )       {
1595                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1596
1597                                 // Read in the sound data!!!
1598                                 snd->data = ptr;
1599                                 ptr += snd->length;
1600                                 sbytes += snd->length;
1601                                 cfread( snd->data, snd->length, 1, fp );
1602                         }
1603                         else
1604                                 snd->data = (ubyte *) -1;
1605                 }
1606         }
1607
1608         cfclose(fp);
1609
1610         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1611
1612 }
1613
1614
1615 extern int descent_critical_error;
1616 extern unsigned descent_critical_deverror;
1617 extern unsigned descent_critical_errcode;
1618
1619 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1620 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1621 "Read fault", "General Failure" };
1622
1623 void piggy_critical_error()
1624 {
1625         grs_canvas * save_canv;
1626         grs_font * save_font;
1627         int i;
1628         save_canv = grd_curcanv;
1629         save_font = grd_curcanv->cv_font;
1630         gr_palette_load( gr_palette );
1631         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1632         if ( i == 1 )
1633                 exit(1);
1634         gr_set_current_canvas(save_canv);
1635         grd_curcanv->cv_font = save_font;
1636 }
1637
1638 void piggy_bitmap_page_in( bitmap_index bitmap )
1639 {
1640         grs_bitmap * bmp;
1641         int i,org_i,temp;
1642
1643         org_i = 0;
1644
1645         i = bitmap.index;
1646         Assert( i >= 0 );
1647         Assert( i < MAX_BITMAP_FILES );
1648         Assert( i < Num_bitmap_files );
1649         Assert( Piggy_bitmap_cache_size > 0 );
1650
1651         if ( i < 1 ) return;
1652         if ( i >= MAX_BITMAP_FILES ) return;
1653         if ( i >= Num_bitmap_files ) return;
1654
1655         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1656
1657         if ( piggy_low_memory ) {
1658                 org_i = i;
1659                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1660         }
1661
1662         bmp = &GameBitmaps[i];
1663
1664         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1665                 stop_time();
1666
1667         ReDoIt:
1668                 descent_critical_error = 0;
1669                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1670                 if ( descent_critical_error )   {
1671                         piggy_critical_error();
1672                         goto ReDoIt;
1673                 }
1674
1675                 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1676                 bmp->bm_flags = GameBitmapFlags[i];
1677
1678                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1679                         int zsize = 0;
1680                         descent_critical_error = 0;
1681                         zsize = cfile_read_int(Piggy_fp);
1682                         if ( descent_critical_error )   {
1683                                 piggy_critical_error();
1684                                 goto ReDoIt;
1685                         }
1686
1687                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1688                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1689                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1690                                 Int3();
1691                                 piggy_bitmap_page_out_all();
1692                                 goto ReDoIt;
1693                         }
1694                         descent_critical_error = 0;
1695                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1696                         if ( descent_critical_error )   {
1697                                 piggy_critical_error();
1698                                 goto ReDoIt;
1699                         }
1700
1701 #ifndef MACDATA
1702                         switch (cfilelength(Piggy_fp)) {
1703                         default:
1704                                 if (!FindArg("-macdata"))
1705                                         break;
1706                                 // otherwise, fall through...
1707                         case MAC_ALIEN1_PIGSIZE:
1708                         case MAC_ALIEN2_PIGSIZE:
1709                         case MAC_FIRE_PIGSIZE:
1710                         case MAC_GROUPA_PIGSIZE:
1711                         case MAC_ICE_PIGSIZE:
1712                         case MAC_WATER_PIGSIZE:
1713                                 rle_swap_0_255( bmp );
1714                                 memcpy(&zsize, bmp->bm_data, 4);
1715                                 break;
1716                         }
1717 #endif
1718
1719                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1720                         Piggy_bitmap_cache_next += zsize;
1721                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1722                                 Int3();
1723                                 piggy_bitmap_page_out_all();
1724                                 goto ReDoIt;
1725                         }
1726
1727                 } else {
1728                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1729                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1730                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1731                                 piggy_bitmap_page_out_all();
1732                                 goto ReDoIt;
1733                         }
1734                         descent_critical_error = 0;
1735                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1736                         if ( descent_critical_error )   {
1737                                 piggy_critical_error();
1738                                 goto ReDoIt;
1739                         }
1740                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1741
1742 #ifndef MACDATA
1743                         switch (cfilelength(Piggy_fp)) {
1744                         default:
1745                                 if (!FindArg("-macdata"))
1746                                         break;
1747                                 // otherwise, fall through...
1748                         case MAC_ALIEN1_PIGSIZE:
1749                         case MAC_ALIEN2_PIGSIZE:
1750                         case MAC_FIRE_PIGSIZE:
1751                         case MAC_GROUPA_PIGSIZE:
1752                         case MAC_ICE_PIGSIZE:
1753                         case MAC_WATER_PIGSIZE:
1754                                 swap_0_255( bmp );
1755                                 break;
1756                         }
1757 #endif
1758                 }
1759
1760                 //@@if ( bmp->bm_selector ) {
1761                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1762                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1763                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1764                 //@@#endif
1765                 //@@}
1766
1767                 start_time();
1768         }
1769
1770         if ( piggy_low_memory ) {
1771                 if ( org_i != i )
1772                         GameBitmaps[org_i] = GameBitmaps[i];
1773         }
1774
1775 //@@Removed from John's code:
1776 //@@#ifndef WINDOWS
1777 //@@    if ( bmp->bm_selector ) {
1778 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1779 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1780 //@@    }
1781 //@@#endif
1782
1783 }
1784
1785 void piggy_bitmap_page_out_all()
1786 {
1787         int i;
1788         
1789         Piggy_bitmap_cache_next = 0;
1790
1791         piggy_page_flushed++;
1792
1793         texmerge_flush();
1794         rle_cache_flush();
1795
1796         for (i=0; i<Num_bitmap_files; i++ )             {
1797                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1798                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1799                         GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1800                 }
1801         }
1802
1803         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1804 }
1805
1806 void piggy_load_level_data()
1807 {
1808         piggy_bitmap_page_out_all();
1809         paging_touch_all();
1810 }
1811
1812 #ifdef EDITOR
1813
1814 void change_filename_ext( char *dest, char *src, char *ext );
1815
1816 void piggy_write_pigfile(char *filename)
1817 {
1818         FILE *pig_fp;
1819         int bitmap_data_start,data_offset;
1820         DiskBitmapHeader bmh;
1821         int org_offset;
1822         char subst_name[32];
1823         int i;
1824         FILE *fp1,*fp2;
1825         char tname[FILENAME_LEN];
1826
1827         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1828         for (i=0; i < Num_bitmap_files; i++ )   {
1829                 bitmap_index bi;
1830                 bi.index = i;
1831                 PIGGY_PAGE_IN( bi );
1832         }
1833         // -- mprintf( (0, "\n" ));
1834
1835         piggy_close_file();
1836
1837         // -- mprintf( (0, "Creating %s...",filename ));
1838
1839         pig_fp = fopen( filename, "wb" );       //open PIG file
1840         Assert( pig_fp!=NULL );
1841
1842         write_int(PIGFILE_ID,pig_fp);
1843         write_int(PIGFILE_VERSION,pig_fp);
1844
1845         Num_bitmap_files--;
1846         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1847         Num_bitmap_files++;
1848
1849         bitmap_data_start = ftell(pig_fp);
1850         bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE; 
1851         data_offset = bitmap_data_start;
1852
1853         change_filename_ext(tname,filename,"lst");
1854         fp1 = fopen( tname, "wt" );
1855         change_filename_ext(tname,filename,"all");
1856         fp2 = fopen( tname, "wt" );
1857
1858         for (i=1; i < Num_bitmap_files; i++ )   {
1859                 int *size;
1860                 grs_bitmap *bmp;
1861
1862                 {               
1863                         char * p, *p1;
1864                         p = strchr(AllBitmaps[i].name,'#');
1865                         if (p)  {
1866                                 int n;
1867                                 p1 = p; p1++; 
1868                                 n = atoi(p1);
1869                                 *p = 0;
1870                                 if (fp2 && n==0)
1871                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1872                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1873                                 Assert( n <= 63 );
1874                                 bmh.dflags = DBM_FLAG_ABM + n;
1875                                 *p = '#';
1876                         }else {
1877                                 if (fp2)
1878                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1879                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1880                                 bmh.dflags = 0;
1881                         }
1882                 }
1883                 bmp = &GameBitmaps[i];
1884
1885                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1886
1887                 if (fp1)
1888                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1889                 org_offset = ftell(pig_fp);
1890                 bmh.offset = data_offset - bitmap_data_start;
1891                 fseek( pig_fp, data_offset, SEEK_SET );
1892
1893                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1894                         size = (int *)bmp->bm_data;
1895                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1896                         data_offset += *size;
1897                         if (fp1)
1898                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1899                 } else {
1900                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1901                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1902                         if (fp1)
1903                                 fprintf( fp1, ".\n" );
1904                 }
1905                 fseek( pig_fp, org_offset, SEEK_SET );
1906                 Assert( GameBitmaps[i].bm_w < 4096 );
1907                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1908                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1909                 Assert( GameBitmaps[i].bm_h < 4096 );
1910                 bmh.height = GameBitmaps[i].bm_h;
1911                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1912                 bmh.flags = GameBitmaps[i].bm_flags;
1913                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1914                         bitmap_index other_bitmap;
1915                         other_bitmap = piggy_find_bitmap( subst_name );
1916                         GameBitmapXlat[i] = other_bitmap.index;
1917                         bmh.flags |= BM_FLAG_PAGED_OUT;
1918                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1919                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1920                 } else  {
1921                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1922                 }
1923                 bmh.avg_color=GameBitmaps[i].avg_color;
1924                 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp );                    // Mark as a bitmap
1925         }
1926
1927         fclose(pig_fp);
1928
1929         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1930         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1931
1932         fclose(fp1);
1933         fclose(fp2);
1934
1935 }
1936
1937 static void write_int(int i,FILE *file)
1938 {
1939         if (fwrite( &i, sizeof(i), 1, file) != 1)
1940                 Error( "Error reading int in gamesave.c" );
1941
1942 }
1943
1944 void piggy_dump_all()
1945 {
1946         int i, xlat_offset;
1947         FILE * ham_fp;
1948         int org_offset,data_offset=0;
1949         DiskSoundHeader sndh;
1950         int sound_data_start=0;
1951         FILE *fp1,*fp2;
1952
1953         #ifdef NO_DUMP_SOUNDS
1954         Num_sound_files = 0;
1955         Num_sound_files_new = 0;
1956         #endif
1957
1958         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1959                 return;
1960
1961         fp1 = fopen( "ham.lst", "wt" );
1962         fp2 = fopen( "ham.all", "wt" );
1963
1964         if (Must_write_hamfile || Num_bitmap_files_new) {
1965
1966                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1967         
1968                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1969                 Assert( ham_fp!=NULL );
1970         
1971                 write_int(HAMFILE_ID,ham_fp);
1972                 write_int(HAMFILE_VERSION,ham_fp);
1973         
1974                 bm_write_all(ham_fp);
1975                 xlat_offset = ftell(ham_fp);
1976                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1977                 //Dump bitmaps
1978         
1979                 if (Num_bitmap_files_new)
1980                         piggy_write_pigfile(DEFAULT_PIGFILE);
1981         
1982                 //free up memeory used by new bitmaps
1983                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1984                         d_free(GameBitmaps[i].bm_data);
1985         
1986                 //next thing must be done after pig written
1987                 fseek( ham_fp, xlat_offset, SEEK_SET );
1988                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1989         
1990                 fclose(ham_fp);
1991                 mprintf( (0, "\n" ));
1992         }
1993         
1994         if (Num_sound_files_new) {
1995
1996                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1997                 // Now dump sound file
1998                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1999                 Assert( ham_fp!=NULL );
2000         
2001                 write_int(SNDFILE_ID,ham_fp);
2002                 write_int(SNDFILE_VERSION,ham_fp);
2003
2004                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
2005         
2006                 mprintf( (0, "\nDumping sounds..." ));
2007         
2008                 sound_data_start = ftell(ham_fp);
2009                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
2010                 data_offset = sound_data_start;
2011         
2012                 for (i=0; i < Num_sound_files; i++ )    {
2013                         digi_sound *snd;
2014         
2015                         snd = &GameSounds[i];
2016                         strcpy( sndh.name, AllSounds[i].name );
2017                         sndh.length = GameSounds[i].length;
2018                         sndh.offset = data_offset - sound_data_start;
2019         
2020                         org_offset = ftell(ham_fp);
2021                         fseek( ham_fp, data_offset, SEEK_SET );
2022         
2023                         sndh.data_length = GameSounds[i].length;
2024                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
2025                         data_offset += snd->length;
2026                         fseek( ham_fp, org_offset, SEEK_SET );
2027                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
2028         
2029                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
2030                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
2031                 }
2032
2033                 fclose(ham_fp);
2034                 mprintf( (0, "\n" ));
2035         }
2036
2037         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
2038         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
2039         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
2040
2041         fclose(fp1);
2042         fclose(fp2);
2043
2044         // Never allow the game to run after building ham.
2045         exit(0);
2046 }
2047
2048 #endif
2049
2050 void piggy_close()
2051 {
2052         piggy_close_file();
2053
2054         if (BitmapBits)
2055                 d_free(BitmapBits);
2056
2057         if ( SoundBits )
2058                 d_free( SoundBits );
2059
2060         hashtable_free( &AllBitmapsNames );
2061         hashtable_free( &AllDigiSndNames );
2062
2063 }
2064
2065 int piggy_does_bitmap_exist_slow( char * name )
2066 {
2067         int i;
2068
2069         for (i=0; i<Num_bitmap_files; i++ )     {
2070                 if ( !strcmp( AllBitmaps[i].name, name) )
2071                         return 1;
2072         }
2073         return 0;
2074 }
2075
2076
2077 #define NUM_GAUGE_BITMAPS 23
2078 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
2079         "gauge01", "gauge01b",
2080         "gauge02", "gauge02b",
2081         "gauge06", "gauge06b",
2082         "targ01", "targ01b",
2083         "targ02", "targ02b", 
2084         "targ03", "targ03b",
2085         "targ04", "targ04b",
2086         "targ05", "targ05b",
2087         "targ06", "targ06b",
2088         "gauge18", "gauge18b",
2089         "gauss1", "helix1",
2090         "phoenix1"
2091 };
2092
2093
2094 int piggy_is_gauge_bitmap( char * base_name )
2095 {
2096         int i;
2097         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
2098                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
2099                         return 1;
2100         }
2101
2102         return 0;       
2103 }
2104
2105 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
2106 {
2107         int frame;
2108         char * p;
2109         char base_name[ 16 ];
2110         
2111         strcpy( subst_name, name );
2112         p = strchr( subst_name, '#' );
2113         if ( p )        {
2114                 frame = atoi( &p[1] );
2115                 *p = 0;
2116                 strcpy( base_name, subst_name );
2117                 if ( !piggy_is_gauge_bitmap( base_name ))       {
2118                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
2119                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
2120                                 if ( frame & 1 ) {
2121                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
2122                                         return 1;
2123                                 }
2124                         }
2125                 }
2126         }
2127         strcpy( subst_name, name );
2128         return 0;
2129 }
2130
2131
2132
2133 #ifdef WINDOWS
2134 //      New Windows stuff
2135
2136 //      windows bitmap page in
2137 //              Page in a bitmap, if ddraw, then page it into a ddsurface in 
2138 //              'video' memory.  if that fails, page it in normally.
2139
2140 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
2141 {
2142 }
2143
2144
2145 //      Essential when switching video modes!
2146
2147 void piggy_bitmap_page_out_all_w()
2148 {
2149 }
2150
2151 #endif // WINDOWS
2152
2153
2154 /*
2155  * Functions for loading replacement textures
2156  *  1) From .pog files
2157  *  2) From descent.pig (for loading d1 levels)
2158  */
2159
2160 extern void change_filename_extension( char *dest, char *src, char *new_ext );
2161 extern char last_palette_loaded_pig[];
2162
2163 ubyte *Bitmap_replacement_data=NULL;
2164
2165 void free_bitmap_replacements()
2166 {
2167         if (Bitmap_replacement_data) {
2168                 d_free(Bitmap_replacement_data);
2169                 Bitmap_replacement_data = NULL;
2170         }
2171 }
2172
2173 void load_bitmap_replacements(char *level_name)
2174 {
2175         char ifile_name[FILENAME_LEN];
2176         CFILE *ifile;
2177         int i;
2178
2179         //first, free up data allocated for old bitmaps
2180         free_bitmap_replacements();
2181
2182         change_filename_extension(ifile_name, level_name, ".POG" );
2183
2184         ifile = cfopen(ifile_name,"rb");
2185
2186         if (ifile) {
2187                 int id,version,n_bitmaps;
2188                 int bitmap_data_size;
2189                 ushort *indices;
2190
2191                 id = cfile_read_int(ifile);
2192                 version = cfile_read_int(ifile);
2193
2194                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
2195                         cfclose(ifile);
2196                         return;
2197                 }
2198
2199                 n_bitmaps = cfile_read_int(ifile);
2200
2201                 MALLOC( indices, ushort, n_bitmaps );
2202
2203                 for (i = 0; i < n_bitmaps; i++)
2204                         indices[i] = cfile_read_short(ifile);
2205
2206                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - DISKBITMAPHEADER_SIZE * n_bitmaps;
2207                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
2208
2209                 for (i=0;i<n_bitmaps;i++) {
2210                         DiskBitmapHeader bmh;
2211                         grs_bitmap temp_bitmap;
2212
2213                         DiskBitmapHeader_read(&bmh, ifile);
2214
2215                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2216
2217                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2218                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2219                         temp_bitmap.avg_color = bmh.avg_color;
2220                         temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
2221
2222                         if ( bmh.flags & BM_FLAG_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2223                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2224                         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2225                         if ( bmh.flags & BM_FLAG_RLE ) temp_bitmap.bm_flags |= BM_FLAG_RLE;
2226                         if ( bmh.flags & BM_FLAG_RLE_BIG ) temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2227
2228                         GameBitmaps[indices[i]] = temp_bitmap;
2229                 }
2230
2231                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
2232
2233                 d_free(indices);
2234
2235                 cfclose(ifile);
2236
2237                 last_palette_loaded_pig[0]= 0;  //force pig re-load
2238
2239                 texmerge_flush();       //for re-merging with new textures
2240         }
2241
2242         atexit(free_bitmap_replacements);
2243 }
2244
2245 #define FIRST_D1_TEXTURE 722
2246 #define LAST_D1_STATIC_TEXTURE 1042//1342 //afterwards, we have door frames and stuff
2247 #define FIRST_D2_TEXTURE 1243
2248
2249 void load_d1_bitmap_replacements()
2250 {
2251         CFILE * d1_Piggy_fp;
2252         grs_bitmap temp_bitmap;
2253         DiskBitmapHeader bmh;
2254         int pig_data_start, bitmap_header_start, bitmap_data_start;
2255         int N_bitmaps, zsize;
2256         int d1_index, d2_index;
2257         ubyte colormap[256];
2258         ubyte *next_bitmap; // to which address we write the next bitmap
2259
2260 #ifndef MACINTOSH
2261         d1_Piggy_fp = cfopen( "descent.pig", "rb" );
2262 #else
2263         d1_Piggy_fp = cfopen( "Data:Descent.pig", "rb" );
2264 #endif  // end of ifndef/else MACINTOSH
2265
2266         if (!d1_Piggy_fp)
2267                 return; // use d2 bitmaps instead...
2268
2269         //first, free up data allocated for old bitmaps
2270         free_bitmap_replacements();
2271
2272         // read d1 palette, build colormap
2273         {
2274                 int freq[256];
2275                 ubyte d1_palette[256*3];
2276                 CFILE * palette_file = cfopen( "palette.256", "rb" );
2277                 Assert( palette_file );
2278                 Assert( cfilelength( palette_file ) == 9472 );
2279                 cfread( d1_palette, 256, 3, palette_file);
2280                 cfclose( palette_file );
2281                 build_colormap_good( d1_palette, colormap, freq );
2282                 // don't change transparencies:
2283                 colormap[254] = 254;
2284                 colormap[255] = 255;
2285         }
2286
2287
2288         if (0) //TODO: put here cfilelength(d1_Piggy_fp) == D1_PIG_SHARE
2289                 pig_data_start = 0;
2290         else {
2291                 //int i;
2292                 pig_data_start = cfile_read_int(d1_Piggy_fp );
2293                 bm_read_all_d1( d1_Piggy_fp );
2294                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2295         }
2296         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2297         N_bitmaps = cfile_read_int(d1_Piggy_fp);
2298         {
2299                 int N_sounds = cfile_read_int(d1_Piggy_fp);
2300                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2301                         + N_sounds * DISKSOUNDHEADER_SIZE;
2302                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2303                 bitmap_data_start = bitmap_header_start + header_size;
2304         }
2305
2306         MALLOC( Bitmap_replacement_data, ubyte, cfilelength(d1_Piggy_fp) - bitmap_data_start ); // too much
2307         //TODO: handle case where b_r_d == 0! (have to convert textures, return, not bm_read_all_d1)
2308
2309         next_bitmap = Bitmap_replacement_data;
2310
2311         for (d1_index=1; d1_index<=N_bitmaps; d1_index++ ) {
2312                 // only change wall texture bitmaps
2313                 if (d1_index >= FIRST_D1_TEXTURE && d1_index <= LAST_D1_STATIC_TEXTURE) {
2314                         d2_index = d1_index + FIRST_D2_TEXTURE - FIRST_D1_TEXTURE;
2315
2316                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2317                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2318
2319                         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
2320
2321                         temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
2322                         temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
2323                         temp_bitmap.avg_color = bmh.avg_color;
2324
2325                         //GameBitmapFlags[convert_d1_bitmap_num(d1_index)] = 0;
2326
2327                         if ( bmh.flags & BM_FLAG_TRANSPARENT )
2328                                 temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT;
2329                         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT )
2330                                 temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT;
2331                         if ( bmh.flags & BM_FLAG_NO_LIGHTING )
2332                                 temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING;
2333                         if ( bmh.flags & BM_FLAG_RLE )
2334                                 temp_bitmap.bm_flags |= BM_FLAG_RLE;
2335                         if ( bmh.flags & BM_FLAG_RLE_BIG )
2336                                 temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG;
2337
2338                         temp_bitmap.bm_data = next_bitmap;
2339
2340                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2341                         zsize = cfile_read_int(d1_Piggy_fp);
2342                         cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET);
2343                         cfread(next_bitmap, 1, zsize, d1_Piggy_fp);
2344
2345                         switch(cfilelength(d1_Piggy_fp)) {
2346                         case D1_MAC_PIGSIZE:
2347                         case D1_MAC_SHARE_PIGSIZE:
2348                                 rle_swap_0_255(&temp_bitmap);
2349                         }
2350                         rle_remap(&temp_bitmap, colormap);
2351
2352                         GameBitmaps[d2_index] = temp_bitmap;
2353
2354                         memcpy(&zsize, temp_bitmap.bm_data, 4);
2355                         next_bitmap += zsize;
2356                 }
2357         }
2358
2359         cfclose(d1_Piggy_fp);
2360
2361         last_palette_loaded_pig[0]= 0;  //force pig re-load
2362
2363         texmerge_flush();       //for re-merging with new textures
2364
2365         atexit(free_bitmap_replacements);
2366 }
2367
2368
2369 #ifndef FAST_FILE_IO
2370 /*
2371  * reads a bitmap_index structure from a CFILE
2372  */
2373 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2374 {
2375         bi->index = cfile_read_short(fp);
2376 }
2377
2378 /*
2379  * reads n bitmap_index structs from a CFILE
2380  */
2381 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2382 {
2383         int i;
2384
2385         for (i = 0; i < n; i++)
2386                 bi[i].index = cfile_read_short(fp);
2387         return i;
2388 }
2389
2390 /*
2391  * reads a DiskBitmapHeader structure from a CFILE
2392  */
2393 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
2394 {
2395         cfread(dbh->name, 8, 1, fp);
2396         dbh->dflags = cfile_read_byte(fp);
2397         dbh->width = cfile_read_byte(fp);
2398         dbh->height = cfile_read_byte(fp);
2399         dbh->wh_extra = cfile_read_byte(fp);
2400         dbh->flags = cfile_read_byte(fp);
2401         dbh->avg_color = cfile_read_byte(fp);
2402         dbh->offset = cfile_read_int(fp);
2403 }
2404
2405 /*
2406  * reads a DiskSoundHeader structure from a CFILE
2407  */
2408 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
2409 {
2410         cfread(dsh->name, 8, 1, fp);
2411         dsh->length = cfile_read_int(fp);
2412         dsh->data_length = cfile_read_int(fp);
2413         dsh->offset = cfile_read_int(fp);
2414 }
2415 #endif // FAST_FILE_IO
2416
2417 /*
2418  * reads a descent 1 DiskBitmapHeader structure from a CFILE
2419  */
2420 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
2421 {
2422         cfread(dbh->name, 8, 1, fp);
2423         dbh->dflags = cfile_read_byte(fp);
2424         dbh->width = cfile_read_byte(fp);
2425         dbh->height = cfile_read_byte(fp);
2426         dbh->wh_extra = 0;
2427         dbh->flags = cfile_read_byte(fp);
2428         dbh->avg_color = cfile_read_byte(fp);
2429         dbh->offset = cfile_read_int(fp);
2430 }