]> icculus.org git repositories - btb/d2x.git/blob - main/piggy.c
more header cleanup
[btb/d2x.git] / main / piggy.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Functions for managing the pig files.
17  *
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #ifndef MACINTOSH
29 //      #include "unarj.h"
30 #else
31 #include <Strings.h>            // MacOS Toolbox header
32 #include <Files.h>
33 #include <unistd.h>
34 #endif
35
36 #include "strutil.h"
37 #include "inferno.h"
38 #include "gr.h"
39 #include "u_mem.h"
40 #include "iff.h"
41 #include "mono.h"
42 #include "error.h"
43 #include "hash.h"
44 #include "args.h"
45 #include "cfile.h"
46 #include "byteswap.h"
47 #include "makesig.h"
48
49
50 //#define NO_DUMP_SOUNDS        1   //if set, dump bitmaps but not sounds
51
52 #define DEFAULT_PIGFILE_REGISTERED      "groupa.pig"
53 #define DEFAULT_PIGFILE_SHAREWARE       "d2demo.pig"
54 #define DEFAULT_HAMFILE_REGISTERED      "descent2.ham"
55 #define DEFAULT_HAMFILE_SHAREWARE       "d2demo.ham"
56
57 #define D1_PALETTE "palette.256"
58
59 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
60 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
61 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
62
63 #define MAC_ALIEN1_PIGSIZE      5013035
64 #define MAC_ALIEN2_PIGSIZE      4909916
65 #define MAC_FIRE_PIGSIZE        4969035
66 #define MAC_GROUPA_PIGSIZE      4929684 // also used for mac shareware
67 #define MAC_ICE_PIGSIZE         4923425
68 #define MAC_WATER_PIGSIZE       4832403
69
70 ubyte *BitmapBits = NULL;
71 ubyte *SoundBits = NULL;
72
73 typedef struct BitmapFile {
74         char    name[15];
75 } BitmapFile;
76
77 typedef struct SoundFile {
78         char    name[15];
79 } SoundFile;
80
81 hashtable AllBitmapsNames;
82 hashtable AllDigiSndNames;
83
84 int Num_bitmap_files = 0;
85 int Num_sound_files = 0;
86
87 digi_sound GameSounds[MAX_SOUND_FILES];
88 int SoundOffset[MAX_SOUND_FILES];
89 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
90
91 alias alias_list[MAX_ALIASES];
92 int Num_aliases=0;
93
94 int Must_write_hamfile = 0;
95 int Num_bitmap_files_new = 0;
96 int Num_sound_files_new = 0;
97 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
98 static SoundFile AllSounds[ MAX_SOUND_FILES ];
99
100 int Piggy_hamfile_version = 0;
101
102 int piggy_low_memory = 0;
103
104 int Piggy_bitmap_cache_size = 0;
105 int Piggy_bitmap_cache_next = 0;
106 ubyte * Piggy_bitmap_cache_data = NULL;
107 static int GameBitmapOffset[MAX_BITMAP_FILES];
108 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
109 ushort GameBitmapXlat[MAX_BITMAP_FILES];
110
111 #define PIGGY_BUFFER_SIZE (2400*1024)
112
113 #ifdef MACINTOSH
114 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024)             // size of buffer when piggy_low_memory is set
115
116 #ifdef SHAREWARE
117 #undef PIGGY_BUFFER_SIZE
118 #undef PIGGY_SMALL_BUFFER_SIZE
119
120 #define PIGGY_BUFFER_SIZE (2000*1024)
121 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
122 #endif          // SHAREWARE
123
124 #endif
125
126 int piggy_page_flushed = 0;
127
128 #define DBM_FLAG_ABM    64 // animated bitmap
129 #define DBM_NUM_FRAMES  63
130
131 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
132                          | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
133
134 typedef struct DiskBitmapHeader {
135         char name[8];
136         ubyte dflags;           // bits 0-5 anim frame num, bit 6 abm flag
137         ubyte width;            // low 8 bits here, 4 more bits in wh_extra
138         ubyte height;           // low 8 bits here, 4 more bits in wh_extra
139         ubyte wh_extra;         // bits 0-3 width, bits 4-7 height
140         ubyte flags;
141         ubyte avg_color;
142         int offset;
143 } __pack__ DiskBitmapHeader;
144
145 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
146
147 typedef struct DiskSoundHeader {
148         char name[8];
149         int length;
150         int data_length;
151         int offset;
152 } __pack__ DiskSoundHeader;
153
154 #ifdef FAST_FILE_IO
155 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
156 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
157 #else
158 /*
159  * reads a DiskBitmapHeader structure from a CFILE
160  */
161 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
162 {
163         cfread(dbh->name, 8, 1, fp);
164         dbh->dflags = cfile_read_byte(fp);
165         dbh->width = cfile_read_byte(fp);
166         dbh->height = cfile_read_byte(fp);
167         dbh->wh_extra = cfile_read_byte(fp);
168         dbh->flags = cfile_read_byte(fp);
169         dbh->avg_color = cfile_read_byte(fp);
170         dbh->offset = cfile_read_int(fp);
171 }
172
173 /*
174  * reads a DiskSoundHeader structure from a CFILE
175  */
176 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
177 {
178         cfread(dsh->name, 8, 1, fp);
179         dsh->length = cfile_read_int(fp);
180         dsh->data_length = cfile_read_int(fp);
181         dsh->offset = cfile_read_int(fp);
182 }
183 #endif // FAST_FILE_IO
184
185 /*
186  * reads a descent 1 DiskBitmapHeader structure from a CFILE
187  */
188 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
189 {
190         cfread(dbh->name, 8, 1, fp);
191         dbh->dflags = cfile_read_byte(fp);
192         dbh->width = cfile_read_byte(fp);
193         dbh->height = cfile_read_byte(fp);
194         dbh->wh_extra = 0;
195         dbh->flags = cfile_read_byte(fp);
196         dbh->avg_color = cfile_read_byte(fp);
197         dbh->offset = cfile_read_int(fp);
198 }
199
200 ubyte BigPig = 0;
201
202 #ifdef MACINTOSH
203         extern short    cd_VRefNum;
204         extern void             ConcatPStr(StringPtr dst, StringPtr src);
205         extern int              ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
206         extern int              ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
207 #endif
208
209 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
210
211 #ifdef EDITOR
212 void piggy_write_pigfile(char *filename);
213 static void write_int(int i,FILE *file);
214 #endif
215
216 void swap_0_255(grs_bitmap *bmp)
217 {
218         int i;
219
220         for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
221                 if(bmp->bm_data[i] == 0)
222                         bmp->bm_data[i] = 255;
223                 else if (bmp->bm_data[i] == 255)
224                         bmp->bm_data[i] = 0;
225         }
226 }
227
228 char* piggy_game_bitmap_name(grs_bitmap *bmp)
229 {
230         if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
231         {
232                 int i = (int)(bmp - GameBitmaps); // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
233                 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
234                 return AllBitmaps[i].name;
235         }
236         return NULL;
237 }
238
239 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
240 {
241         bitmap_index temp;
242         Assert( Num_bitmap_files < MAX_BITMAP_FILES );
243
244         temp.index = Num_bitmap_files;
245
246         if (!in_file)   {
247 #ifdef EDITOR
248                 if ( FindArg("-macdata") )
249                         swap_0_255( bmp );
250 #endif
251                 if ( !BigPig )  gr_bitmap_rle_compress( bmp );
252                 Num_bitmap_files_new++;
253         }
254
255         strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
256         hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
257         //GameBitmaps[Num_bitmap_files] = *bmp;
258         if ( !in_file ) {
259                 GameBitmapOffset[Num_bitmap_files] = 0;
260                 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
261         }
262         Num_bitmap_files++;
263
264         return temp;
265 }
266
267 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
268 {
269         int i;
270
271         Assert( Num_sound_files < MAX_SOUND_FILES );
272
273         strncpy( AllSounds[Num_sound_files].name, name, 12 );
274         hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
275         GameSounds[Num_sound_files] = *snd;
276         if ( !in_file ) {
277                 SoundOffset[Num_sound_files] = 0;       
278         }
279
280         i = Num_sound_files;
281    
282         if (!in_file)
283                 Num_sound_files_new++;
284
285         Num_sound_files++;
286         return i;
287 }
288
289 bitmap_index piggy_find_bitmap( char * name )   
290 {
291         bitmap_index bmp;
292         int i;
293         char *t;
294
295         bmp.index = 0;
296
297         if ((t=strchr(name,'#'))!=NULL)
298                 *t=0;
299
300         for (i=0;i<Num_aliases;i++)
301                 if (stricmp(name,alias_list[i].alias_name)==0) {
302                         if (t) {                //extra stuff for ABMs
303                                 static char temp[FILENAME_LEN];
304                                 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
305                                 name = temp;
306                                 strcat(name,"#");
307                                 strcat(name,t+1);
308                         }
309                         else
310                                 name=alias_list[i].file_name; 
311                         break;
312                 }
313
314         if (t)
315                 *t = '#';
316
317         i = hashtable_search( &AllBitmapsNames, name );
318         Assert( i != 0 );
319         if ( i < 0 )
320                 return bmp;
321
322         bmp.index = i;
323         return bmp;
324 }
325
326 int piggy_find_sound( char * name )     
327 {
328         int i;
329
330         i = hashtable_search( &AllDigiSndNames, name );
331
332         if ( i < 0 )
333                 return 255;
334
335         return i;
336 }
337
338 CFILE * Piggy_fp = NULL;
339
340 #define FILENAME_LEN 13
341
342 char Current_pigfile[FILENAME_LEN] = "";
343
344 void piggy_close_file()
345 {
346         if ( Piggy_fp ) {
347                 cfclose( Piggy_fp );
348                 Piggy_fp        = NULL;
349                 Current_pigfile[0] = 0;
350         }
351 }
352
353 int Pigfile_initialized=0;
354
355 #define PIGFILE_ID              MAKE_SIG('G','I','P','P') //PPIG
356 #define PIGFILE_VERSION         2
357
358
359 //initialize a pigfile, reading headers
360 //returns the size of all the bitmap data
361 void piggy_init_pigfile(char *filename)
362 {
363         int i;
364         char temp_name[16];
365         char temp_name_read[16];
366         DiskBitmapHeader bmh;
367         int header_size, N_bitmaps, data_size, data_start;
368
369         piggy_close_file();             //close old pig if still open
370
371         //rename pigfile for shareware
372         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
373                 filename = DEFAULT_PIGFILE_SHAREWARE;
374
375                 Piggy_fp = cfopen( filename, "rb" );
376
377 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
378                         if (Piggy_fp == NULL)
379                         {
380                                 Error("Cannot load required file <%s>",name);
381                         }
382 #endif  // end of if def shareware
383
384         if (!Piggy_fp) {
385                 #ifdef EDITOR
386                         return;         //if editor, ok to not have pig, because we'll build one
387                 #else
388                         Piggy_fp = cfopen(filename, "rb");
389                 #endif
390         }
391
392         if (Piggy_fp) {                         //make sure pig is valid type file & is up-to-date
393                 int pig_id,pig_version;
394
395                 pig_id = cfile_read_int(Piggy_fp);
396                 pig_version = cfile_read_int(Piggy_fp);
397                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
398                         cfclose(Piggy_fp);              //out of date pig
399                         Piggy_fp = NULL;                        //..so pretend it's not here
400                 }
401         }
402
403         if (!Piggy_fp) {
404
405                 #ifdef EDITOR
406                         return;         //if editor, ok to not have pig, because we'll build one
407                 #else
408                         Error("Cannot load required file <%s>",filename);
409                 #endif
410         }
411
412         strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
413
414         N_bitmaps = cfile_read_int(Piggy_fp);
415
416         header_size = N_bitmaps * sizeof(DiskBitmapHeader);
417
418         data_start = header_size + cftell(Piggy_fp);
419
420         data_size = cfilelength(Piggy_fp) - data_start;
421
422         Num_bitmap_files = 1;
423
424         for (i=0; i<N_bitmaps; i++ )
425     {
426                 int width;
427                 grs_bitmap *bm = &GameBitmaps[i + 1];
428                 
429                 DiskBitmapHeader_read(&bmh, Piggy_fp);
430                 memcpy( temp_name_read, bmh.name, 8 );
431                 temp_name_read[8] = 0;
432                 if ( bmh.dflags & DBM_FLAG_ABM )        
433                         sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
434                 else
435                         strcpy( temp_name, temp_name_read );
436                 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
437                 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
438                 bm->bm_flags = BM_FLAG_PAGED_OUT;
439                 bm->avg_color = bmh.avg_color;
440
441                 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
442
443                 GameBitmapOffset[i+1] = bmh.offset + data_start;
444                 Assert( (i+1) == Num_bitmap_files );
445                 piggy_register_bitmap(bm, temp_name, 1);
446         }
447
448 #ifdef EDITOR
449         Piggy_bitmap_cache_size = data_size + (data_size/10);   //extra mem for new bitmaps
450         Assert( Piggy_bitmap_cache_size > 0 );
451 #else
452         Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
453         #ifdef MACINTOSH
454         if (piggy_low_memory)
455                 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
456         #endif
457 #endif
458         BitmapBits = d_malloc( Piggy_bitmap_cache_size );
459         if ( BitmapBits == NULL )
460                 Error( "Not enough memory to load bitmaps\n" );
461         Piggy_bitmap_cache_data = BitmapBits;
462         Piggy_bitmap_cache_next = 0;
463
464         #if defined(MACINTOSH) && defined(SHAREWARE)
465 //      load_exit_models();
466         #endif
467
468         Pigfile_initialized=1;
469 }
470
471 #define FILENAME_LEN 13
472 #define MAX_BITMAPS_PER_BRUSH 30
473
474 extern int compute_average_pixel(grs_bitmap *new);
475 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
476
477 ubyte *Bitmap_replacement_data = NULL;
478
479 //reads in a new pigfile (for new palette)
480 //returns the size of all the bitmap data
481 void piggy_new_pigfile(char *pigname)
482 {
483         int i;
484         char temp_name[16];
485         char temp_name_read[16];
486         DiskBitmapHeader bmh;
487         int header_size, N_bitmaps, data_size, data_start;
488         int must_rewrite_pig = 0;
489
490         strlwr(pigname);
491
492         //rename pigfile for shareware
493         if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
494                 pigname = DEFAULT_PIGFILE_SHAREWARE;
495
496         if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
497             && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
498                 return;
499
500         if (!Pigfile_initialized) {                     //have we ever opened a pigfile?
501                 piggy_init_pigfile(pigname);            //..no, so do initialization stuff
502                 return;
503         }
504         else
505                 piggy_close_file();             //close old pig if still open
506
507         Piggy_bitmap_cache_next = 0;            //free up cache
508
509         strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
510
511                 Piggy_fp = cfopen( pigname, "rb" );
512
513 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
514                         if (Piggy_fp == NULL)
515                         {
516                                 Error("Cannot load required file <%s>",name);
517                         }
518 #endif  // end of if def shareware
519
520         #ifndef EDITOR
521         if (!Piggy_fp)
522                 Piggy_fp = cfopen(pigname, "rb");
523         #endif
524
525         if (Piggy_fp) {  //make sure pig is valid type file & is up-to-date
526                 int pig_id,pig_version;
527
528                 pig_id = cfile_read_int(Piggy_fp);
529                 pig_version = cfile_read_int(Piggy_fp);
530                 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
531                         cfclose(Piggy_fp);              //out of date pig
532                         Piggy_fp = NULL;                        //..so pretend it's not here
533                 }
534         }
535
536 #ifndef EDITOR
537         if (!Piggy_fp)
538                 Error("Cannot open correct version of <%s>", pigname);
539 #endif
540
541         if (Piggy_fp) {
542
543                 N_bitmaps = cfile_read_int(Piggy_fp);
544
545                 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
546
547                 data_start = header_size + cftell(Piggy_fp);
548
549                 data_size = cfilelength(Piggy_fp) - data_start;
550
551                 for (i=1; i<=N_bitmaps; i++ )
552                 {
553                         grs_bitmap *bm = &GameBitmaps[i];
554                         int width;
555                         
556                         DiskBitmapHeader_read(&bmh, Piggy_fp);
557                         memcpy( temp_name_read, bmh.name, 8 );
558                         temp_name_read[8] = 0;
559         
560                         if ( bmh.dflags & DBM_FLAG_ABM )        
561                                 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
562                         else
563                                 strcpy( temp_name, temp_name_read );
564         
565                         //Make sure name matches
566                         if (strcmp(temp_name,AllBitmaps[i].name)) {
567                                 //Int3();       //this pig is out of date.  Delete it
568                                 must_rewrite_pig=1;
569                         }
570         
571                         strcpy(AllBitmaps[i].name,temp_name);
572
573                         width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
574                         gr_set_bitmap_data(bm, NULL);   // free ogl texture
575                         gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
576                         bm->bm_flags = BM_FLAG_PAGED_OUT;
577                         bm->avg_color = bmh.avg_color;
578
579                         GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
580         
581                         GameBitmapOffset[i] = bmh.offset + data_start;
582                 }
583         }
584         else
585                 N_bitmaps = 0;          //no pigfile, so no bitmaps
586
587         #ifndef EDITOR
588
589         Assert(N_bitmaps == Num_bitmap_files-1);
590
591         #else
592
593         if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
594                 int size;
595
596                 //re-read the bitmaps that aren't in this pig
597
598                 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
599                         char *p;
600
601                         p = strchr(AllBitmaps[i].name,'#');
602
603                         if (p) {   // this is an ABM == animated bitmap
604                                 char abmname[FILENAME_LEN];
605                                 int fnum;
606                                 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
607                                 int iff_error;          //reference parm to avoid warning message
608                                 ubyte newpal[768];
609                                 char basename[FILENAME_LEN];
610                                 int nframes;
611                         
612                                 strcpy(basename,AllBitmaps[i].name);
613                                 basename[p-AllBitmaps[i].name] = 0;  //cut off "#nn" part
614                                 
615                                 sprintf( abmname, "%s.abm", basename );
616
617                                 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
618
619                                 if (iff_error != IFF_NO_ERROR)  {
620                                         mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
621                                         Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
622                                 }
623                         
624                                 for (fnum=0;fnum<nframes; fnum++)       {
625                                         char tempname[20];
626                                         int SuperX;
627
628                                         sprintf( tempname, "%s#%d", basename, fnum );
629
630                                         //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
631                                         SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
632                                         //above makes assumption that supertransparent color is 254
633
634                                         if ( iff_has_transparency )
635                                                 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
636                                         else
637                                                 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
638
639                                         bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
640
641 #ifdef EDITOR
642                                         if ( FindArg("-macdata") )
643                                                 swap_0_255( bm[fnum] );
644 #endif
645                                         if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
646
647                                         if (bm[fnum]->bm_flags & BM_FLAG_RLE)
648                                                 size = *((int *) bm[fnum]->bm_data);
649                                         else
650                                                 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
651
652                                         memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
653                                         d_free(bm[fnum]->bm_data);
654                                         bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
655                                         Piggy_bitmap_cache_next += size;
656
657                                         GameBitmaps[i+fnum] = *bm[fnum];
658
659                                         // -- mprintf( (0, "U" ));
660                                         d_free( bm[fnum] );
661                                 }
662
663                                 i += nframes-1;         //filled in multiple bitmaps
664                         }
665                         else {          //this is a BBM
666
667                                 grs_bitmap * new;
668                                 ubyte newpal[256*3];
669                                 int iff_error;
670                                 char bbmname[FILENAME_LEN];
671                                 int SuperX;
672
673                                 MALLOC( new, grs_bitmap, 1 );
674
675                                 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
676                                 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
677
678                                 new->bm_handle=0;
679                                 if (iff_error != IFF_NO_ERROR)          {
680                                         mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
681                                         Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
682                                 }
683
684                                 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
685                                 //above makes assumption that supertransparent color is 254
686
687                                 if ( iff_has_transparency )
688                                         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
689                                 else
690                                         gr_remap_bitmap_good( new, newpal, -1, SuperX );
691
692                                 new->avg_color = compute_average_pixel(new);
693
694 #ifdef EDITOR
695                                 if ( FindArg("-macdata") )
696                                         swap_0_255( new );
697 #endif
698                                 if ( !BigPig )  gr_bitmap_rle_compress( new );
699
700                                 if (new->bm_flags & BM_FLAG_RLE)
701                                         size = *((int *) new->bm_data);
702                                 else
703                                         size = new->bm_w * new->bm_h;
704
705                                 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
706                                 d_free(new->bm_data);
707                                 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
708                                 Piggy_bitmap_cache_next += size;
709
710                                 GameBitmaps[i] = *new;
711         
712                                 d_free( new );
713
714                                 // -- mprintf( (0, "U" ));
715                         }
716                 }
717
718                 //@@Dont' do these things which are done when writing
719                 //@@for (i=0; i < Num_bitmap_files; i++ )       {
720                 //@@    bitmap_index bi;
721                 //@@    bi.index = i;
722                 //@@    PIGGY_PAGE_IN( bi );
723                 //@@}
724                 //@@
725                 //@@piggy_close_file();
726
727                 piggy_write_pigfile(pigname);
728
729                 Current_pigfile[0] = 0;                 //say no pig, to force reload
730
731                 piggy_new_pigfile(pigname);             //read in just-generated pig
732
733
734         }
735         #endif  //ifdef EDITOR
736
737 }
738
739 ubyte bogus_data[64*64];
740 ubyte bogus_bitmap_initialized=0;
741 digi_sound bogus_sound;
742
743 #define HAMFILE_ID              MAKE_SIG('!','M','A','H') //HAM!
744 #define HAMFILE_VERSION 3
745 //version 1 -> 2:  save marker_model_num
746 //version 2 -> 3:  removed sound files
747
748 #define SNDFILE_ID              MAKE_SIG('D','N','S','D') //DSND
749 #define SNDFILE_VERSION 1
750
751 int read_hamfile()
752 {
753         CFILE * ham_fp = NULL;
754         int ham_id;
755         int sound_offset = 0;
756
757         ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
758
759         if (ham_fp == NULL) {
760                 Must_write_hamfile = 1;
761                 return 0;
762         }
763
764         //make sure ham is valid type file & is up-to-date
765         ham_id = cfile_read_int(ham_fp);
766         Piggy_hamfile_version = cfile_read_int(ham_fp);
767         if (ham_id != HAMFILE_ID)
768                 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
769 #if 0
770         if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
771                 Must_write_hamfile = 1;
772                 cfclose(ham_fp);                                                //out of date ham
773                 return 0;
774         }
775 #endif
776
777         if (Piggy_hamfile_version < 3) // hamfile contains sound info
778                 sound_offset = cfile_read_int(ham_fp);
779
780         #if 1 //ndef EDITOR
781         {
782                 //int i;
783
784                 bm_read_all(ham_fp);
785                 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
786                 // no swap here?
787                 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
788                         //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
789                         //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
790                 //}
791         }
792         #endif
793
794         if (Piggy_hamfile_version < 3) {
795                 int N_sounds;
796                 int sound_start;
797                 int header_size;
798                 int i;
799                 DiskSoundHeader sndh;
800                 digi_sound temp_sound;
801                 char temp_name_read[16];
802                 int sbytes = 0;
803
804                 cfseek(ham_fp, sound_offset, SEEK_SET);
805                 N_sounds = cfile_read_int(ham_fp);
806
807                 sound_start = cftell(ham_fp);
808
809                 header_size = N_sounds * sizeof(DiskSoundHeader);
810
811                 //Read sounds
812
813                 for (i=0; i<N_sounds; i++ ) {
814                         DiskSoundHeader_read(&sndh, ham_fp);
815                         temp_sound.length = sndh.length;
816                         temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
817                         SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
818                         memcpy( temp_name_read, sndh.name, 8 );
819                         temp_name_read[8] = 0;
820                         piggy_register_sound( &temp_sound, temp_name_read, 1 );
821 #ifdef MACINTOSH
822                         if (piggy_is_needed(i))
823 #endif          // note link to if.
824                                 sbytes += sndh.length;
825                         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
826                 }
827
828                 SoundBits = d_malloc( sbytes + 16 );
829                 if ( SoundBits == NULL )
830                         Error( "Not enough memory to load sounds\n" );
831
832                 mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
833
834                 //      piggy_read_sounds(ham_fp);
835
836         }
837
838         cfclose(ham_fp);
839
840         return 1;
841
842 }
843
844 int read_sndfile()
845 {
846         CFILE * snd_fp = NULL;
847         int snd_id,snd_version;
848         int N_sounds;
849         int sound_start;
850         int header_size;
851         int i,size, length;
852         DiskSoundHeader sndh;
853         digi_sound temp_sound;
854         char temp_name_read[16];
855         int sbytes = 0;
856
857         snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
858         
859         if (snd_fp == NULL)
860                 return 0;
861
862         //make sure soundfile is valid type file & is up-to-date
863         snd_id = cfile_read_int(snd_fp);
864         snd_version = cfile_read_int(snd_fp);
865         if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
866                 cfclose(snd_fp);                                                //out of date sound file
867                 return 0;
868         }
869
870         N_sounds = cfile_read_int(snd_fp);
871
872         sound_start = cftell(snd_fp);
873         size = cfilelength(snd_fp) - sound_start;
874         length = size;
875         mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
876
877         header_size = N_sounds*sizeof(DiskSoundHeader);
878
879         //Read sounds
880
881         for (i=0; i<N_sounds; i++ ) {
882                 DiskSoundHeader_read(&sndh, snd_fp);
883                 //size -= sizeof(DiskSoundHeader);
884                 temp_sound.length = sndh.length;
885                 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
886                 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
887                 memcpy( temp_name_read, sndh.name, 8 );
888                 temp_name_read[8] = 0;
889                 piggy_register_sound( &temp_sound, temp_name_read, 1 );
890                 #ifdef MACINTOSH
891                 if (piggy_is_needed(i))
892                 #endif          // note link to if.
893                 sbytes += sndh.length;
894                 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
895         }
896
897         SoundBits = d_malloc( sbytes + 16 );
898         if ( SoundBits == NULL )
899                 Error( "Not enough memory to load sounds\n" );
900
901         mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
902
903 //      piggy_read_sounds(snd_fp);
904
905         cfclose(snd_fp);
906
907         return 1;
908 }
909
910 int piggy_init(void)
911 {
912         int ham_ok=0,snd_ok=0;
913         int i;
914
915         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
916         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
917
918         for (i=0; i<MAX_SOUND_FILES; i++ )      {
919                 GameSounds[i].length = 0;
920                 GameSounds[i].data = NULL;
921                 SoundOffset[i] = 0;
922         }
923
924         for (i=0; i<MAX_BITMAP_FILES; i++ )     
925                 GameBitmapXlat[i] = i;
926
927         if ( !bogus_bitmap_initialized )        {
928                 int i;
929                 ubyte c;
930
931                 bogus_bitmap_initialized = 1;
932                 c = gr_find_closest_color( 0, 0, 63 );
933                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
934                 c = gr_find_closest_color( 63, 0, 0 );
935                 // Make a big red X !
936                 for (i=0; i<64; i++ )   {
937                         bogus_data[i*64+i] = c;
938                         bogus_data[i*64+(63-i)] = c;
939                 }
940                 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
941                 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
942                 bogus_sound.length = 64*64;
943                 bogus_sound.data = bogus_data;
944                 GameBitmapOffset[0] = 0;
945         }
946
947         if ( FindArg( "-bigpig" ))
948                 BigPig = 1;
949
950         if ( FindArg( "-lowmem" ))
951                 piggy_low_memory = 1;
952
953         if ( FindArg( "-nolowmem" ))
954                 piggy_low_memory = 0;
955
956         if (piggy_low_memory)
957                 digi_lomem = 1;
958
959                 gr_set_curfont( SMALL_FONT );
960                 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
961                 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
962
963 #if 1 //def EDITOR //need for d1 mission briefings
964         piggy_init_pigfile(DEFAULT_PIGFILE);
965 #endif
966
967         snd_ok = ham_ok = read_hamfile();
968
969         if (Piggy_hamfile_version >= 3)
970                 snd_ok = read_sndfile();
971
972         atexit(piggy_close);
973
974         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
975         return (ham_ok && snd_ok);               //read ok
976 }
977
978 int piggy_is_needed(int soundnum)
979 {
980         int i;
981
982         if ( !digi_lomem ) return 1;
983
984         for (i=0; i<MAX_SOUNDS; i++ )   {
985                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
986                         return 1;
987         }
988         return 0;
989 }
990
991
992 void piggy_read_sounds(void)
993 {
994         CFILE * fp = NULL;
995         ubyte * ptr;
996         int i, sbytes;
997
998         ptr = SoundBits;
999         sbytes = 0;
1000
1001         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1002
1003         if (fp == NULL)
1004                 return;
1005
1006         for (i=0; i<Num_sound_files; i++ )      {
1007                 digi_sound *snd = &GameSounds[i];
1008
1009                 if ( SoundOffset[i] > 0 )       {
1010                         if ( piggy_is_needed(i) )       {
1011                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1012
1013                                 // Read in the sound data!!!
1014                                 snd->data = ptr;
1015                                 ptr += snd->length;
1016                                 sbytes += snd->length;
1017                                 cfread( snd->data, snd->length, 1, fp );
1018                         }
1019                         else
1020                                 snd->data = (ubyte *) -1;
1021                 }
1022         }
1023
1024         cfclose(fp);
1025
1026         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1027
1028 }
1029
1030
1031 extern int descent_critical_error;
1032 extern unsigned descent_critical_deverror;
1033 extern unsigned descent_critical_errcode;
1034
1035 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1036 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1037 "Read fault", "General Failure" };
1038
1039 void piggy_critical_error()
1040 {
1041         grs_canvas * save_canv;
1042         grs_font * save_font;
1043         int i;
1044         save_canv = grd_curcanv;
1045         save_font = grd_curcanv->cv_font;
1046         gr_palette_load( gr_palette );
1047         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1048         if ( i == 1 )
1049                 exit(1);
1050         gr_set_current_canvas(save_canv);
1051         grd_curcanv->cv_font = save_font;
1052 }
1053
1054 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1055
1056 void piggy_bitmap_page_in( bitmap_index bitmap )
1057 {
1058         grs_bitmap * bmp;
1059         int i,org_i,temp;
1060
1061         org_i = 0;
1062
1063         i = bitmap.index;
1064         Assert( i >= 0 );
1065         Assert( i < MAX_BITMAP_FILES );
1066         Assert( i < Num_bitmap_files );
1067         Assert( Piggy_bitmap_cache_size > 0 );
1068
1069         if ( i < 1 ) return;
1070         if ( i >= MAX_BITMAP_FILES ) return;
1071         if ( i >= Num_bitmap_files ) return;
1072
1073         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1074
1075         if ( piggy_low_memory ) {
1076                 org_i = i;
1077                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1078         }
1079
1080         bmp = &GameBitmaps[i];
1081
1082         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1083                 stop_time();
1084
1085         ReDoIt:
1086                 descent_critical_error = 0;
1087                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1088                 if ( descent_critical_error )   {
1089                         piggy_critical_error();
1090                         goto ReDoIt;
1091                 }
1092
1093                 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1094
1095                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1096                         int zsize = 0, pigsize = cfilelength(Piggy_fp);
1097                         descent_critical_error = 0;
1098                         zsize = cfile_read_int(Piggy_fp);
1099                         if ( descent_critical_error )   {
1100                                 piggy_critical_error();
1101                                 goto ReDoIt;
1102                         }
1103
1104                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1105                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1106                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1107                                 Int3();
1108                                 piggy_bitmap_page_out_all();
1109                                 goto ReDoIt;
1110                         }
1111                         descent_critical_error = 0;
1112                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1113                         if ( descent_critical_error )   {
1114                                 piggy_critical_error();
1115                                 goto ReDoIt;
1116                         }
1117                         *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1118                         gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1119
1120 #ifndef MACDATA
1121                         switch (pigsize) {
1122                         default:
1123                                 if (!FindArg("-macdata"))
1124                                         break;
1125                                 // otherwise, fall through...
1126                         case MAC_ALIEN1_PIGSIZE:
1127                         case MAC_ALIEN2_PIGSIZE:
1128                         case MAC_FIRE_PIGSIZE:
1129                         case MAC_GROUPA_PIGSIZE:
1130                         case MAC_ICE_PIGSIZE:
1131                         case MAC_WATER_PIGSIZE:
1132                                 rle_swap_0_255( bmp );
1133                                 memcpy(&zsize, bmp->bm_data, 4);
1134                                 break;
1135                         }
1136 #endif
1137
1138                         Piggy_bitmap_cache_next += zsize;
1139                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1140                                 Int3();
1141                                 piggy_bitmap_page_out_all();
1142                                 goto ReDoIt;
1143                         }
1144
1145                 } else {
1146                         int pigsize = cfilelength(Piggy_fp);
1147                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1148                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1149                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1150                                 piggy_bitmap_page_out_all();
1151                                 goto ReDoIt;
1152                         }
1153                         descent_critical_error = 0;
1154                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1155                         if ( descent_critical_error )   {
1156                                 piggy_critical_error();
1157                                 goto ReDoIt;
1158                         }
1159                         gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1160                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1161
1162 #ifndef MACDATA
1163                         switch (pigsize) {
1164                         default:
1165                                 if (!FindArg("-macdata"))
1166                                         break;
1167                                 // otherwise, fall through...
1168                         case MAC_ALIEN1_PIGSIZE:
1169                         case MAC_ALIEN2_PIGSIZE:
1170                         case MAC_FIRE_PIGSIZE:
1171                         case MAC_GROUPA_PIGSIZE:
1172                         case MAC_ICE_PIGSIZE:
1173                         case MAC_WATER_PIGSIZE:
1174                                 swap_0_255( bmp );
1175                                 break;
1176                         }
1177 #endif
1178                 }
1179
1180                 //@@if ( bmp->bm_selector ) {
1181                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1182                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1183                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1184                 //@@#endif
1185                 //@@}
1186
1187                 start_time();
1188         }
1189
1190         if ( piggy_low_memory ) {
1191                 if ( org_i != i )
1192                         GameBitmaps[org_i] = GameBitmaps[i];
1193         }
1194
1195 //@@Removed from John's code:
1196 //@@#ifndef WINDOWS
1197 //@@    if ( bmp->bm_selector ) {
1198 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1199 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1200 //@@    }
1201 //@@#endif
1202
1203 }
1204
1205 void piggy_bitmap_page_out_all()
1206 {
1207         int i;
1208         
1209         Piggy_bitmap_cache_next = 0;
1210
1211         piggy_page_flushed++;
1212
1213         texmerge_flush();
1214         rle_cache_flush();
1215
1216         for (i=0; i<Num_bitmap_files; i++ )             {
1217                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1218                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1219                         gr_set_bitmap_data(&GameBitmaps[i], NULL);
1220                 }
1221         }
1222
1223         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1224 }
1225
1226 void piggy_load_level_data()
1227 {
1228         piggy_bitmap_page_out_all();
1229         paging_touch_all();
1230 }
1231
1232 #ifdef EDITOR
1233
1234 void piggy_write_pigfile(char *filename)
1235 {
1236         FILE *pig_fp;
1237         int bitmap_data_start, data_offset;
1238         DiskBitmapHeader bmh;
1239         int org_offset;
1240         char subst_name[32];
1241         int i;
1242         FILE *fp1,*fp2;
1243         char tname[FILENAME_LEN];
1244
1245         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1246         for (i=0; i < Num_bitmap_files; i++ )   {
1247                 bitmap_index bi;
1248                 bi.index = i;
1249                 PIGGY_PAGE_IN( bi );
1250         }
1251         // -- mprintf( (0, "\n" ));
1252
1253         piggy_close_file();
1254
1255         // -- mprintf( (0, "Creating %s...",filename ));
1256
1257         pig_fp = fopen( filename, "wb" );       //open PIG file
1258         Assert( pig_fp!=NULL );
1259
1260         write_int(PIGFILE_ID,pig_fp);
1261         write_int(PIGFILE_VERSION,pig_fp);
1262
1263         Num_bitmap_files--;
1264         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1265         Num_bitmap_files++;
1266
1267         bitmap_data_start = ftell(pig_fp);
1268         bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1269         data_offset = bitmap_data_start;
1270
1271         change_filename_extension(tname,filename,"lst");
1272         fp1 = fopen( tname, "wt" );
1273         change_filename_extension(tname,filename,"all");
1274         fp2 = fopen( tname, "wt" );
1275
1276         for (i=1; i < Num_bitmap_files; i++ )   {
1277                 int *size;
1278                 grs_bitmap *bmp;
1279
1280                 {               
1281                         char * p, *p1;
1282                         p = strchr(AllBitmaps[i].name, '#');
1283                         if (p) {   // this is an ABM == animated bitmap
1284                                 int n;
1285                                 p1 = p; p1++; 
1286                                 n = atoi(p1);
1287                                 *p = 0;
1288                                 if (fp2 && n==0)
1289                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1290                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1291                                 Assert( n <= DBM_NUM_FRAMES );
1292                                 bmh.dflags = DBM_FLAG_ABM + n;
1293                                 *p = '#';
1294                         } else {
1295                                 if (fp2)
1296                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1297                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1298                                 bmh.dflags = 0;
1299                         }
1300                 }
1301                 bmp = &GameBitmaps[i];
1302
1303                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1304
1305                 if (fp1)
1306                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1307                 org_offset = ftell(pig_fp);
1308                 bmh.offset = data_offset - bitmap_data_start;
1309                 fseek( pig_fp, data_offset, SEEK_SET );
1310
1311                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1312                         size = (int *)bmp->bm_data;
1313                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1314                         data_offset += *size;
1315                         if (fp1)
1316                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1317                 } else {
1318                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1319                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1320                         if (fp1)
1321                                 fprintf( fp1, ".\n" );
1322                 }
1323                 fseek( pig_fp, org_offset, SEEK_SET );
1324                 Assert( GameBitmaps[i].bm_w < 4096 );
1325                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1326                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1327                 Assert( GameBitmaps[i].bm_h < 4096 );
1328                 bmh.height = GameBitmaps[i].bm_h;
1329                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1330                 bmh.flags = GameBitmaps[i].bm_flags;
1331                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1332                         bitmap_index other_bitmap;
1333                         other_bitmap = piggy_find_bitmap( subst_name );
1334                         GameBitmapXlat[i] = other_bitmap.index;
1335                         bmh.flags |= BM_FLAG_PAGED_OUT;
1336                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1337                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1338                 } else  {
1339                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1340                 }
1341                 bmh.avg_color=GameBitmaps[i].avg_color;
1342                 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp);  // Mark as a bitmap
1343         }
1344
1345         fclose(pig_fp);
1346
1347         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1348         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1349
1350         fclose(fp1);
1351         fclose(fp2);
1352
1353 }
1354
1355 static void write_int(int i,FILE *file)
1356 {
1357         if (fwrite( &i, sizeof(i), 1, file) != 1)
1358                 Error( "Error reading int in gamesave.c" );
1359
1360 }
1361
1362 void piggy_dump_all()
1363 {
1364         int i, xlat_offset;
1365         FILE * ham_fp;
1366         int org_offset,data_offset=0;
1367         DiskSoundHeader sndh;
1368         int sound_data_start=0;
1369         FILE *fp1,*fp2;
1370
1371         #ifdef NO_DUMP_SOUNDS
1372         Num_sound_files = 0;
1373         Num_sound_files_new = 0;
1374         #endif
1375
1376         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1377                 return;
1378
1379         fp1 = fopen( "ham.lst", "wt" );
1380         fp2 = fopen( "ham.all", "wt" );
1381
1382         if (Must_write_hamfile || Num_bitmap_files_new) {
1383
1384                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1385         
1386                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1387                 Assert( ham_fp!=NULL );
1388         
1389                 write_int(HAMFILE_ID,ham_fp);
1390                 write_int(HAMFILE_VERSION,ham_fp);
1391         
1392                 bm_write_all(ham_fp);
1393                 xlat_offset = ftell(ham_fp);
1394                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1395                 //Dump bitmaps
1396         
1397                 if (Num_bitmap_files_new)
1398                         piggy_write_pigfile(DEFAULT_PIGFILE);
1399         
1400                 //free up memeory used by new bitmaps
1401                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1402                         d_free(GameBitmaps[i].bm_data);
1403         
1404                 //next thing must be done after pig written
1405                 fseek( ham_fp, xlat_offset, SEEK_SET );
1406                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1407         
1408                 fclose(ham_fp);
1409                 mprintf( (0, "\n" ));
1410         }
1411         
1412         if (Num_sound_files_new) {
1413
1414                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1415                 // Now dump sound file
1416                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1417                 Assert( ham_fp!=NULL );
1418         
1419                 write_int(SNDFILE_ID,ham_fp);
1420                 write_int(SNDFILE_VERSION,ham_fp);
1421
1422                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1423         
1424                 mprintf( (0, "\nDumping sounds..." ));
1425         
1426                 sound_data_start = ftell(ham_fp);
1427                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1428                 data_offset = sound_data_start;
1429         
1430                 for (i=0; i < Num_sound_files; i++ )    {
1431                         digi_sound *snd;
1432         
1433                         snd = &GameSounds[i];
1434                         strcpy( sndh.name, AllSounds[i].name );
1435                         sndh.length = GameSounds[i].length;
1436                         sndh.offset = data_offset - sound_data_start;
1437         
1438                         org_offset = ftell(ham_fp);
1439                         fseek( ham_fp, data_offset, SEEK_SET );
1440         
1441                         sndh.data_length = GameSounds[i].length;
1442                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1443                         data_offset += snd->length;
1444                         fseek( ham_fp, org_offset, SEEK_SET );
1445                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
1446         
1447                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1448                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1449                 }
1450
1451                 fclose(ham_fp);
1452                 mprintf( (0, "\n" ));
1453         }
1454
1455         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1456         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1457         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1458
1459         fclose(fp1);
1460         fclose(fp2);
1461
1462         // Never allow the game to run after building ham.
1463         exit(0);
1464 }
1465
1466 #endif
1467
1468 void piggy_close()
1469 {
1470         piggy_close_file();
1471
1472         if (BitmapBits)
1473                 d_free(BitmapBits);
1474
1475         if ( SoundBits )
1476                 d_free( SoundBits );
1477
1478         hashtable_free( &AllBitmapsNames );
1479         hashtable_free( &AllDigiSndNames );
1480
1481 }
1482
1483 int piggy_does_bitmap_exist_slow( char * name )
1484 {
1485         int i;
1486
1487         for (i=0; i<Num_bitmap_files; i++ )     {
1488                 if ( !strcmp( AllBitmaps[i].name, name) )
1489                         return 1;
1490         }
1491         return 0;
1492 }
1493
1494
1495 #define NUM_GAUGE_BITMAPS 23
1496 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1497         "gauge01", "gauge01b",
1498         "gauge02", "gauge02b",
1499         "gauge06", "gauge06b",
1500         "targ01", "targ01b",
1501         "targ02", "targ02b", 
1502         "targ03", "targ03b",
1503         "targ04", "targ04b",
1504         "targ05", "targ05b",
1505         "targ06", "targ06b",
1506         "gauge18", "gauge18b",
1507         "gauss1", "helix1",
1508         "phoenix1"
1509 };
1510
1511
1512 int piggy_is_gauge_bitmap( char * base_name )
1513 {
1514         int i;
1515         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
1516                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
1517                         return 1;
1518         }
1519
1520         return 0;       
1521 }
1522
1523 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1524 {
1525         int frame;
1526         char * p;
1527         char base_name[ 16 ];
1528         
1529         strcpy( subst_name, name );
1530         p = strchr( subst_name, '#' );
1531         if ( p )        {
1532                 frame = atoi( &p[1] );
1533                 *p = 0;
1534                 strcpy( base_name, subst_name );
1535                 if ( !piggy_is_gauge_bitmap( base_name ))       {
1536                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
1537                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
1538                                 if ( frame & 1 ) {
1539                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
1540                                         return 1;
1541                                 }
1542                         }
1543                 }
1544         }
1545         strcpy( subst_name, name );
1546         return 0;
1547 }
1548
1549
1550
1551 /*
1552  * Functions for loading replacement textures
1553  *  1) From .pog files
1554  *  2) From descent.pig (for loading d1 levels)
1555  */
1556
1557 extern char last_palette_loaded_pig[];
1558
1559 void free_bitmap_replacements()
1560 {
1561         if (Bitmap_replacement_data) {
1562                 d_free(Bitmap_replacement_data);
1563                 Bitmap_replacement_data = NULL;
1564         }
1565 }
1566
1567 void load_bitmap_replacements(char *level_name)
1568 {
1569         char ifile_name[FILENAME_LEN];
1570         CFILE *ifile;
1571         int i;
1572
1573         //first, free up data allocated for old bitmaps
1574         free_bitmap_replacements();
1575
1576         change_filename_extension(ifile_name, level_name, ".POG" );
1577
1578         ifile = cfopen(ifile_name,"rb");
1579
1580         if (ifile) {
1581                 int id,version,n_bitmaps;
1582                 int bitmap_data_size;
1583                 ushort *indices;
1584
1585                 id = cfile_read_int(ifile);
1586                 version = cfile_read_int(ifile);
1587
1588                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1589                         cfclose(ifile);
1590                         return;
1591                 }
1592
1593                 n_bitmaps = cfile_read_int(ifile);
1594
1595                 MALLOC( indices, ushort, n_bitmaps );
1596
1597                 for (i = 0; i < n_bitmaps; i++)
1598                         indices[i] = cfile_read_short(ifile);
1599
1600                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1601                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1602
1603                 for (i=0;i<n_bitmaps;i++) {
1604                         DiskBitmapHeader bmh;
1605                         grs_bitmap *bm = &GameBitmaps[indices[i]];
1606                         int width;
1607
1608                         DiskBitmapHeader_read(&bmh, ifile);
1609
1610                         width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1611                         gr_set_bitmap_data(bm, NULL);   // free ogl texture
1612                         gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1613                         bm->avg_color = bmh.avg_color;
1614                         bm->bm_data = (ubyte *) bmh.offset;
1615
1616                         gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1617
1618                         GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1619                 }
1620
1621                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1622
1623                 for (i = 0; i < n_bitmaps; i++)
1624                 {
1625                         grs_bitmap *bm = &GameBitmaps[indices[i]];
1626                         gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1627                 }
1628
1629                 d_free(indices);
1630
1631                 cfclose(ifile);
1632
1633                 last_palette_loaded_pig[0]= 0;  //force pig re-load
1634
1635                 texmerge_flush();       //for re-merging with new textures
1636         }
1637
1638         atexit(free_bitmap_replacements);
1639 }
1640
1641 /* calculate table to translate d1 bitmaps to current palette,
1642  * return -1 on error
1643  */
1644 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1645 {
1646         int freq[256];
1647         CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1648         if (!palette_file || cfilelength(palette_file) != 9472)
1649                 return -1;
1650         cfread( d1_palette, 256, 3, palette_file);
1651         cfclose( palette_file );
1652         build_colormap_good( d1_palette, colormap, freq );
1653         // don't change transparencies:
1654         colormap[254] = 254;
1655         colormap[255] = 255;
1656         return 0;
1657 }
1658
1659 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1660 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1661                      CFILE *d1_Piggy_fp, /* read from this file */
1662                      int bitmap_data_start, /* specific to file */
1663                      DiskBitmapHeader *bmh, /* header info for bitmap */
1664                      ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1665                      ubyte *d1_palette, /* what palette the bitmap has */
1666                      ubyte *colormap) /* how to translate bitmap's colors */
1667 {
1668         int zsize, pigsize = cfilelength(d1_Piggy_fp);
1669         ubyte *data;
1670         int width;
1671
1672         width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1673         gr_set_bitmap_data(bitmap, NULL);       // free ogl texture
1674         gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1675         bitmap->avg_color = bmh->avg_color;
1676         gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1677
1678         cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1679         if (bmh->flags & BM_FLAG_RLE) {
1680                 zsize = cfile_read_int(d1_Piggy_fp);
1681                 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1682         } else
1683                 zsize = bitmap->bm_h * bitmap->bm_w;
1684
1685         if (next_bitmap) {
1686                 data = *next_bitmap;
1687                 *next_bitmap += zsize;
1688         } else {
1689                 data = d_malloc(zsize + JUST_IN_CASE);
1690         }
1691         if (!data) return;
1692
1693         cfread(data, 1, zsize, d1_Piggy_fp);
1694         gr_set_bitmap_data(bitmap, data);
1695         switch(pigsize) {
1696         case D1_MAC_PIGSIZE:
1697         case D1_MAC_SHARE_PIGSIZE:
1698                 if (bmh->flags & BM_FLAG_RLE)
1699                         rle_swap_0_255(bitmap);
1700                 else
1701                         swap_0_255(bitmap);
1702         }
1703         if (bmh->flags & BM_FLAG_RLE)
1704                 rle_remap(bitmap, colormap);
1705         else
1706                 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1707         if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1708                 int new_size;
1709                 memcpy(&new_size, bitmap->bm_data, 4);
1710                 if (next_bitmap) {
1711                         *next_bitmap += new_size - zsize;
1712                 } else {
1713                         Assert( zsize + JUST_IN_CASE >= new_size );
1714                         bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1715                         Assert(bitmap->bm_data);
1716                 }
1717         }
1718 }
1719
1720 #define D1_MAX_TEXTURES 800
1721 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1722
1723 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1724  * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1725  * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1726  */
1727 short *d1_tmap_nums = NULL;
1728
1729 void free_d1_tmap_nums() {
1730         if (d1_tmap_nums) {
1731                 d_free(d1_tmap_nums);
1732                 d1_tmap_nums = NULL;
1733         }
1734 }
1735
1736 void bm_read_d1_tmap_nums(CFILE *d1pig)
1737 {
1738         int i, d1_index;
1739
1740         free_d1_tmap_nums();
1741         cfseek(d1pig, 8, SEEK_SET);
1742         MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1743         for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1744                 d1_tmap_nums[i] = -1;
1745         for (i = 0; i < D1_MAX_TEXTURES; i++) {
1746                 d1_index = cfile_read_short(d1pig);
1747                 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1748                 d1_tmap_nums[d1_index] = i;
1749         }
1750         atexit(free_d1_tmap_nums);
1751 }
1752
1753 void remove_char( char * s, char c )
1754 {
1755         char *p;
1756         p = strchr(s,c);
1757         if (p) *p = '\0';
1758 }
1759
1760 #define REMOVE_EOL(s)           remove_char((s),'\n')
1761 #define REMOVE_COMMENTS(s)      remove_char((s),';')
1762 #define REMOVE_DOTS(s)          remove_char((s),'.')
1763 char *space = { " \t" };
1764 char *equal_space = { " \t=" };
1765
1766 // this function is at the same position in the d1 shareware piggy loading 
1767 // algorithm as bm_load_sub in main/bmread.c
1768 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
1769         int i, N_bitmaps;
1770         DiskBitmapHeader bmh;
1771         if (strchr (filename, '.'))
1772                 *strchr (filename, '.') = '\0'; // remove extension
1773         cfseek (d1_pig, 0, SEEK_SET);
1774         N_bitmaps = cfile_read_int (d1_pig);
1775         cfseek (d1_pig, 8, SEEK_SET);
1776         for (i = 1; i <= N_bitmaps; i++) {
1777                 DiskBitmapHeader_d1_read(&bmh, d1_pig);
1778                 if (!strnicmp(bmh.name, filename, 8))
1779                         return i;
1780         }
1781         return -1;
1782 }
1783
1784 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1785 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1786 {
1787 #define LINEBUF_SIZE 600
1788         int reading_textures = 0;
1789         short texture_count = 0;
1790         char inputline[LINEBUF_SIZE];
1791         CFILE * bitmaps;
1792         int bitmaps_tbl_is_binary = 0;
1793         int i;
1794
1795         bitmaps = cfopen ("bitmaps.tbl", "rb");
1796         if (!bitmaps) {
1797                 bitmaps = cfopen ("bitmaps.bin", "rb");
1798                 bitmaps_tbl_is_binary = 1;
1799         }
1800
1801         if (!bitmaps) {
1802                 Warning ("Could not find bitmaps.* for reading d1 textures");
1803                 return;
1804         }
1805
1806         free_d1_tmap_nums();
1807         MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1808         for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1809                 d1_tmap_nums[i] = -1;
1810         atexit(free_d1_tmap_nums);
1811
1812         while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1813                 char *arg;
1814
1815                 if (bitmaps_tbl_is_binary)
1816                         decode_text_line((inputline));
1817                 else
1818                         while (inputline[(i = (int)strlen(inputline)) - 2] == '\\')
1819                                 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
1820                 REMOVE_EOL(inputline);
1821                 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
1822                 if (strlen(inputline) == LINEBUF_SIZE-1) {
1823                         Warning("Possible line truncation in BITMAPS.TBL");
1824                         return;
1825                 }
1826                 arg = strtok( inputline, space );
1827                 if (arg && arg[0] == '@') {
1828                         arg++;
1829                         //Registered_only = 1;
1830                 }
1831
1832                 while (arg != NULL) {
1833                         if (*arg == '$')
1834                                 reading_textures = 0; // default
1835                         if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
1836                                 reading_textures = 1;
1837                         else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
1838                                    || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
1839                                         texture_count++;
1840                         else // not a special token, must be a bitmap!
1841                                 if (reading_textures) {
1842                                         while (*arg == '\t' || *arg == ' ')
1843                                                 arg++;//remove unwanted blanks
1844                                         if (*arg == '\0')
1845                                                 break;
1846                                         if (d1_tmap_num_unique(texture_count)) {
1847                                                 int d1_index = get_d1_bm_index(arg, d1_pig);
1848                                                 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
1849                                                         d1_tmap_nums[d1_index] = texture_count;
1850                                                         //int d2_index = d2_index_for_d1_index(d1_index);
1851                                                 }
1852                                 }
1853                                 Assert (texture_count < D1_MAX_TEXTURES);
1854                                 texture_count++;
1855                         }
1856
1857                         arg = strtok (NULL, equal_space);
1858                 }
1859         }
1860         cfclose (bitmaps);
1861 }
1862
1863 /* If the given d1_index is the index of a bitmap we have to load
1864  * (because it is unique to descent 1), then returns the d2_index that
1865  * the given d1_index replaces.
1866  * Returns -1 if the given d1_index is not unique to descent 1.
1867  */
1868 short d2_index_for_d1_index(short d1_index)
1869 {
1870         Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1871         if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
1872             || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
1873                 return -1;
1874
1875         return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1876 }
1877
1878 #define D1_BITMAPS_SIZE 300000
1879 void load_d1_bitmap_replacements()
1880 {
1881         CFILE * d1_Piggy_fp;
1882         DiskBitmapHeader bmh;
1883         int pig_data_start, bitmap_header_start, bitmap_data_start;
1884         int N_bitmaps;
1885         short d1_index, d2_index;
1886         ubyte* next_bitmap;
1887         ubyte colormap[256];
1888         ubyte d1_palette[256*3];
1889         char *p;
1890         int pigsize;
1891
1892         d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1893
1894 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1895         if (!d1_Piggy_fp) {
1896                 Warning(D1_PIG_LOAD_FAILED);
1897                 return;
1898         }
1899
1900         //first, free up data allocated for old bitmaps
1901         free_bitmap_replacements();
1902
1903         if (get_d1_colormap( d1_palette, colormap ) != 0)
1904                 Warning("Could not load descent 1 color palette");
1905
1906         pigsize = cfilelength(d1_Piggy_fp);
1907         switch (pigsize) {
1908         case D1_SHARE_BIG_PIGSIZE:
1909         case D1_SHARE_10_PIGSIZE:
1910         case D1_SHARE_PIGSIZE:
1911         case D1_10_BIG_PIGSIZE:
1912         case D1_10_PIGSIZE:
1913                 pig_data_start = 0;
1914                 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
1915                 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
1916                 break;
1917         default:
1918                 Warning("Unknown size for " D1_PIGFILE);
1919                 Int3();
1920                 // fall through
1921         case D1_PIGSIZE:
1922         case D1_OEM_PIGSIZE:
1923         case D1_MAC_PIGSIZE:
1924         case D1_MAC_SHARE_PIGSIZE:
1925                 pig_data_start = cfile_read_int(d1_Piggy_fp );
1926                 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
1927                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
1928                 break;
1929         }
1930
1931         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1932         N_bitmaps = cfile_read_int(d1_Piggy_fp);
1933         {
1934                 int N_sounds = cfile_read_int(d1_Piggy_fp);
1935                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
1936                         + N_sounds * sizeof(DiskSoundHeader);
1937                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
1938                 bitmap_data_start = bitmap_header_start + header_size;
1939         }
1940
1941         MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1942         if (!Bitmap_replacement_data) {
1943                 Warning(D1_PIG_LOAD_FAILED);
1944                 return;
1945         }
1946         atexit(free_bitmap_replacements);
1947
1948         next_bitmap = Bitmap_replacement_data;
1949
1950         for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
1951                 d2_index = d2_index_for_d1_index(d1_index);
1952                 // only change bitmaps which are unique to d1
1953                 if (d2_index != -1) {
1954                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
1955                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
1956
1957                         bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
1958                         Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
1959                         GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
1960                         GameBitmapFlags[d2_index] = bmh.flags;
1961
1962                         if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
1963                              && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
1964                                 int i, len = (int)(p - AllBitmaps[d2_index].name);
1965                                 for (i = 0; i < Num_bitmap_files; i++)
1966                                         if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
1967                                         {
1968                                                 gr_set_bitmap_data(&GameBitmaps[i], NULL);      // free ogl texture
1969                                                 GameBitmaps[i] = GameBitmaps[d2_index];
1970                                                 GameBitmapOffset[i] = 0;
1971                                                 GameBitmapFlags[i] = bmh.flags;
1972                                         }
1973                         }
1974                 }
1975         }
1976
1977         cfclose(d1_Piggy_fp);
1978
1979         last_palette_loaded_pig[0]= 0;  //force pig re-load
1980
1981         texmerge_flush();       //for re-merging with new textures
1982 }
1983
1984
1985 extern int extra_bitmap_num;
1986
1987 /*
1988  * Find and load the named bitmap from descent.pig
1989  * similar to read_extra_bitmap_iff
1990  */
1991 bitmap_index read_extra_bitmap_d1_pig(char *name)
1992 {
1993         bitmap_index bitmap_num;
1994         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
1995
1996         bitmap_num.index = 0;
1997
1998         {
1999                 CFILE *d1_Piggy_fp;
2000                 DiskBitmapHeader bmh;
2001                 int pig_data_start, bitmap_header_start, bitmap_data_start;
2002                 int i, N_bitmaps;
2003                 ubyte colormap[256];
2004                 ubyte d1_palette[256*3];
2005                 int pigsize;
2006
2007                 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2008
2009                 if (!d1_Piggy_fp)
2010                 {
2011                         Warning(D1_PIG_LOAD_FAILED);
2012                         return bitmap_num;
2013                 }
2014
2015                 if (get_d1_colormap( d1_palette, colormap ) != 0)
2016                         Warning("Could not load descent 1 color palette");
2017
2018                 pigsize = cfilelength(d1_Piggy_fp);
2019                 switch (pigsize) {
2020                 case D1_SHARE_BIG_PIGSIZE:
2021                 case D1_SHARE_10_PIGSIZE:
2022                 case D1_SHARE_PIGSIZE:
2023                 case D1_10_BIG_PIGSIZE:
2024                 case D1_10_PIGSIZE:
2025                         pig_data_start = 0;
2026                         break;
2027                 default:
2028                         Warning("Unknown size for " D1_PIGFILE);
2029                         Int3();
2030                         // fall through
2031                 case D1_PIGSIZE:
2032                 case D1_OEM_PIGSIZE:
2033                 case D1_MAC_PIGSIZE:
2034                 case D1_MAC_SHARE_PIGSIZE:
2035                         pig_data_start = cfile_read_int(d1_Piggy_fp );
2036
2037                         break;
2038                 }
2039
2040                 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2041                 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2042                 {
2043                         int N_sounds = cfile_read_int(d1_Piggy_fp);
2044                         int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2045                                 + N_sounds * sizeof(DiskSoundHeader);
2046                         bitmap_header_start = pig_data_start + 2 * sizeof(int);
2047                         bitmap_data_start = bitmap_header_start + header_size;
2048                 }
2049
2050                 for (i = 1; i <= N_bitmaps; i++)
2051                 {
2052                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2053                         if (!strnicmp(bmh.name, name, 8))
2054                                 break;
2055                 }
2056
2057                 if (strnicmp(bmh.name, name, 8))
2058                 {
2059                         con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2060                         return bitmap_num;
2061                 }
2062
2063                 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2064
2065                 cfclose(d1_Piggy_fp);
2066         }
2067
2068         new->avg_color = 0;     //compute_average_pixel(new);
2069
2070         bitmap_num.index = extra_bitmap_num;
2071
2072         GameBitmaps[extra_bitmap_num++] = *new;
2073
2074         return bitmap_num;
2075 }
2076
2077
2078 #ifndef FAST_FILE_IO
2079 /*
2080  * reads a bitmap_index structure from a CFILE
2081  */
2082 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2083 {
2084         bi->index = cfile_read_short(fp);
2085 }
2086
2087 /*
2088  * reads n bitmap_index structs from a CFILE
2089  */
2090 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2091 {
2092         int i;
2093
2094         for (i = 0; i < n; i++)
2095                 bi[i].index = cfile_read_short(fp);
2096         return i;
2097 }
2098 #endif // FAST_FILE_IO