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