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