]> icculus.org git repositories - btb/d2x.git/blob - main/piggy.c
Merge pull request #2 from btb/github-workflow-1
[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 "dxxerror.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, "%.8s#%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, "%.8s#%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, "%.8s.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, "%.8s.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 *)(size_t)(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 *)(size_t)(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
911 void piggy_cmd_play(int argc, char **argv)
912 {
913         int i;
914
915         if (argc == 1)
916         {
917                 con_printf(CON_NORMAL, "Available sounds:\n");
918                 for (i = 0; i < Num_sound_files; i++)
919                         con_printf(CON_NORMAL, "    %s\n", AllSounds[i].name);
920
921                 return;
922         }
923
924         i = piggy_find_sound(argv[1]);
925
926         if (i != 255)
927         {
928                 digi_start_sound( i, F1_0, 0xffff/2, 0, -1, -1, -1 );
929
930                 return;
931         }
932
933         con_printf(CON_NORMAL, "Sound %s not found.\n", argv[1]);
934 }
935
936
937 int piggy_init(void)
938 {
939         int ham_ok=0,snd_ok=0;
940         int i;
941
942         hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
943         hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
944
945         for (i=0; i<MAX_SOUND_FILES; i++ )      {
946                 GameSounds[i].length = 0;
947                 GameSounds[i].data = NULL;
948                 SoundOffset[i] = 0;
949         }
950
951         for (i=0; i<MAX_BITMAP_FILES; i++ )     
952                 GameBitmapXlat[i] = i;
953
954         if ( !bogus_bitmap_initialized )        {
955                 int i;
956                 ubyte c;
957
958                 bogus_bitmap_initialized = 1;
959                 c = gr_find_closest_color( 0, 0, 63 );
960                 for (i=0; i<4096; i++ ) bogus_data[i] = c;
961                 c = gr_find_closest_color( 63, 0, 0 );
962                 // Make a big red X !
963                 for (i=0; i<64; i++ )   {
964                         bogus_data[i*64+i] = c;
965                         bogus_data[i*64+(63-i)] = c;
966                 }
967                 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
968                 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
969                 bogus_sound.length = 64*64;
970                 bogus_sound.data = bogus_data;
971                 GameBitmapOffset[0] = 0;
972         }
973
974         if ( FindArg( "-bigpig" ))
975                 BigPig = 1;
976
977         if ( FindArg( "-lowmem" ))
978                 piggy_low_memory = 1;
979
980         if ( FindArg( "-nolowmem" ))
981                 piggy_low_memory = 0;
982
983         if (piggy_low_memory)
984                 digi_lomem = 1;
985
986         gr_set_curfont( SMALL_FONT );
987         gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
988         gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
989
990 #if 1 //def EDITOR //need for d1 mission briefings
991         piggy_init_pigfile(DEFAULT_PIGFILE);
992 #endif
993
994         snd_ok = ham_ok = read_hamfile();
995
996         if (Piggy_hamfile_version >= 3)
997                 snd_ok = read_sndfile();
998
999         cmd_addcommand("play", piggy_cmd_play, "");
1000
1001         atexit(piggy_close);
1002
1003         mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1004         return (ham_ok && snd_ok);               //read ok
1005 }
1006
1007 int piggy_is_needed(int soundnum)
1008 {
1009         int i;
1010
1011         if ( !digi_lomem ) return 1;
1012
1013         for (i=0; i<MAX_SOUNDS; i++ )   {
1014                 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1015                         return 1;
1016         }
1017         return 0;
1018 }
1019
1020
1021 void piggy_read_sounds(void)
1022 {
1023         CFILE * fp = NULL;
1024         ubyte * ptr;
1025         int i, sbytes;
1026
1027         ptr = SoundBits;
1028         sbytes = 0;
1029
1030         fp = cfopen( DEFAULT_SNDFILE, "rb" );
1031
1032         if (fp == NULL)
1033                 return;
1034
1035         for (i=0; i<Num_sound_files; i++ )      {
1036                 digi_sound *snd = &GameSounds[i];
1037
1038                 if ( SoundOffset[i] > 0 )       {
1039                         if ( piggy_is_needed(i) )       {
1040                                 cfseek( fp, SoundOffset[i], SEEK_SET );
1041
1042                                 // Read in the sound data!!!
1043                                 snd->data = ptr;
1044                                 ptr += snd->length;
1045                                 sbytes += snd->length;
1046                                 cfread( snd->data, snd->length, 1, fp );
1047                         }
1048                         else
1049                                 snd->data = (ubyte *) -1;
1050                 }
1051         }
1052
1053         cfclose(fp);
1054
1055         mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1056
1057 }
1058
1059
1060 extern int descent_critical_error;
1061 extern unsigned descent_critical_deverror;
1062 extern unsigned descent_critical_errcode;
1063
1064 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1065 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1066 "Read fault", "General Failure" };
1067
1068 void piggy_critical_error()
1069 {
1070         grs_canvas * save_canv;
1071         grs_font * save_font;
1072         int i;
1073         save_canv = grd_curcanv;
1074         save_font = grd_curcanv->cv_font;
1075         gr_palette_load( gr_palette );
1076         i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
1077         if ( i == 1 )
1078                 exit(1);
1079         gr_set_current_canvas(save_canv);
1080         grd_curcanv->cv_font = save_font;
1081 }
1082
1083 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1084
1085 void piggy_bitmap_page_in( bitmap_index bitmap )
1086 {
1087         grs_bitmap * bmp;
1088         int i,org_i,temp;
1089
1090         org_i = 0;
1091
1092         i = bitmap.index;
1093         Assert( i >= 0 );
1094         Assert( i < MAX_BITMAP_FILES );
1095         Assert( i < Num_bitmap_files );
1096         Assert( Piggy_bitmap_cache_size > 0 );
1097
1098         if ( i < 1 ) return;
1099         if ( i >= MAX_BITMAP_FILES ) return;
1100         if ( i >= Num_bitmap_files ) return;
1101
1102         if ( GameBitmapOffset[i] == 0 ) return;         // A read-from-disk bitmap!!!
1103
1104         if ( piggy_low_memory ) {
1105                 org_i = i;
1106                 i = GameBitmapXlat[i];          // Xlat for low-memory settings!
1107         }
1108
1109         bmp = &GameBitmaps[i];
1110
1111         if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )        {
1112                 stop_time();
1113
1114         ReDoIt:
1115                 descent_critical_error = 0;
1116                 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1117                 if ( descent_critical_error )   {
1118                         piggy_critical_error();
1119                         goto ReDoIt;
1120                 }
1121
1122                 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1123
1124                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1125                         int zsize = 0, pigsize = cfilelength(Piggy_fp);
1126                         descent_critical_error = 0;
1127                         zsize = cfile_read_int(Piggy_fp);
1128                         if ( descent_critical_error )   {
1129                                 piggy_critical_error();
1130                                 goto ReDoIt;
1131                         }
1132
1133                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1134                         //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1135                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1136                                 Int3();
1137                                 piggy_bitmap_page_out_all();
1138                                 goto ReDoIt;
1139                         }
1140                         descent_critical_error = 0;
1141                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1142                         if ( descent_critical_error )   {
1143                                 piggy_critical_error();
1144                                 goto ReDoIt;
1145                         }
1146                         *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1147                         gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1148
1149 #ifndef MACDATA
1150                         switch (pigsize) {
1151                         default:
1152                                 if (!FindArg("-macdata"))
1153                                         break;
1154                                 // otherwise, fall through...
1155                         case MAC_ALIEN1_PIGSIZE:
1156                         case MAC_ALIEN2_PIGSIZE:
1157                         case MAC_FIRE_PIGSIZE:
1158                         case MAC_GROUPA_PIGSIZE:
1159                         case MAC_ICE_PIGSIZE:
1160                         case MAC_WATER_PIGSIZE:
1161                                 rle_swap_0_255( bmp );
1162                                 memcpy(&zsize, bmp->bm_data, 4);
1163                                 break;
1164                         }
1165 #endif
1166
1167                         Piggy_bitmap_cache_next += zsize;
1168                         if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1169                                 Int3();
1170                                 piggy_bitmap_page_out_all();
1171                                 goto ReDoIt;
1172                         }
1173
1174                 } else {
1175                         int pigsize = cfilelength(Piggy_fp);
1176                         // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1177                         Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1178                         if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1179                                 piggy_bitmap_page_out_all();
1180                                 goto ReDoIt;
1181                         }
1182                         descent_critical_error = 0;
1183                         temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1184                         if ( descent_critical_error )   {
1185                                 piggy_critical_error();
1186                                 goto ReDoIt;
1187                         }
1188                         gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1189                         Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1190
1191 #ifndef MACDATA
1192                         switch (pigsize) {
1193                         default:
1194                                 if (!FindArg("-macdata"))
1195                                         break;
1196                                 // otherwise, fall through...
1197                         case MAC_ALIEN1_PIGSIZE:
1198                         case MAC_ALIEN2_PIGSIZE:
1199                         case MAC_FIRE_PIGSIZE:
1200                         case MAC_GROUPA_PIGSIZE:
1201                         case MAC_ICE_PIGSIZE:
1202                         case MAC_WATER_PIGSIZE:
1203                                 swap_0_255( bmp );
1204                                 break;
1205                         }
1206 #endif
1207                 }
1208
1209                 //@@if ( bmp->bm_selector ) {
1210                 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1211                 //@@    if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1212                 //@@            Error( "Error modifying selector base in piggy.c\n" );
1213                 //@@#endif
1214                 //@@}
1215
1216                 start_time();
1217         }
1218
1219         if ( piggy_low_memory ) {
1220                 if ( org_i != i )
1221                         GameBitmaps[org_i] = GameBitmaps[i];
1222         }
1223
1224 //@@Removed from John's code:
1225 //@@#ifndef WINDOWS
1226 //@@    if ( bmp->bm_selector ) {
1227 //@@            if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1228 //@@                    Error( "Error modifying selector base in piggy.c\n" );
1229 //@@    }
1230 //@@#endif
1231
1232 }
1233
1234 void piggy_bitmap_page_out_all()
1235 {
1236         int i;
1237         
1238         Piggy_bitmap_cache_next = 0;
1239
1240         piggy_page_flushed++;
1241
1242         texmerge_flush();
1243         rle_cache_flush();
1244
1245         for (i=0; i<Num_bitmap_files; i++ )             {
1246                 if ( GameBitmapOffset[i] > 0 )  {       // Don't page out bitmaps read from disk!!!
1247                         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1248                         gr_set_bitmap_data(&GameBitmaps[i], NULL);
1249                 }
1250         }
1251
1252         mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1253 }
1254
1255 void piggy_load_level_data()
1256 {
1257         piggy_bitmap_page_out_all();
1258         paging_touch_all();
1259 }
1260
1261 #ifdef EDITOR
1262
1263 void piggy_write_pigfile(char *filename)
1264 {
1265         FILE *pig_fp;
1266         int bitmap_data_start, data_offset;
1267         DiskBitmapHeader bmh;
1268         int org_offset;
1269         char subst_name[32];
1270         int i;
1271         FILE *fp1,*fp2;
1272         char tname[FILENAME_LEN];
1273
1274         // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1275         for (i=0; i < Num_bitmap_files; i++ )   {
1276                 bitmap_index bi;
1277                 bi.index = i;
1278                 PIGGY_PAGE_IN( bi );
1279         }
1280         // -- mprintf( (0, "\n" ));
1281
1282         piggy_close_file();
1283
1284         // -- mprintf( (0, "Creating %s...",filename ));
1285
1286         pig_fp = fopen( filename, "wb" );       //open PIG file
1287         Assert( pig_fp!=NULL );
1288
1289         write_int(PIGFILE_ID,pig_fp);
1290         write_int(PIGFILE_VERSION,pig_fp);
1291
1292         Num_bitmap_files--;
1293         fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1294         Num_bitmap_files++;
1295
1296         bitmap_data_start = (int)ftell(pig_fp);
1297         bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1298         data_offset = bitmap_data_start;
1299
1300         change_filename_extension(tname,filename,"lst");
1301         fp1 = fopen( tname, "wt" );
1302         change_filename_extension(tname,filename,"all");
1303         fp2 = fopen( tname, "wt" );
1304
1305         for (i=1; i < Num_bitmap_files; i++ )   {
1306                 int *size;
1307                 grs_bitmap *bmp;
1308
1309                 {               
1310                         char * p, *p1;
1311                         p = strchr(AllBitmaps[i].name, '#');
1312                         if (p) {   // this is an ABM == animated bitmap
1313                                 int n;
1314                                 p1 = p; p1++; 
1315                                 n = atoi(p1);
1316                                 *p = 0;
1317                                 if (fp2 && n==0)
1318                                         fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1319                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1320                                 Assert( n <= DBM_NUM_FRAMES );
1321                                 bmh.dflags = DBM_FLAG_ABM + n;
1322                                 *p = '#';
1323                         } else {
1324                                 if (fp2)
1325                                         fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1326                                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1327                                 bmh.dflags = 0;
1328                         }
1329                 }
1330                 bmp = &GameBitmaps[i];
1331
1332                 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1333
1334                 if (fp1)
1335                         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1336                 org_offset = (int)ftell(pig_fp);
1337                 bmh.offset = data_offset - bitmap_data_start;
1338                 fseek( pig_fp, data_offset, SEEK_SET );
1339
1340                 if ( bmp->bm_flags & BM_FLAG_RLE )      {
1341                         size = (int *)bmp->bm_data;
1342                         fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1343                         data_offset += *size;
1344                         if (fp1)
1345                                 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1346                 } else {
1347                         fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1348                         data_offset += bmp->bm_rowsize * bmp->bm_h;
1349                         if (fp1)
1350                                 fprintf( fp1, ".\n" );
1351                 }
1352                 fseek( pig_fp, org_offset, SEEK_SET );
1353                 Assert( GameBitmaps[i].bm_w < 4096 );
1354                 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1355                 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1356                 Assert( GameBitmaps[i].bm_h < 4096 );
1357                 bmh.height = GameBitmaps[i].bm_h;
1358                 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1359                 bmh.flags = GameBitmaps[i].bm_flags;
1360                 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
1361                         bitmap_index other_bitmap;
1362                         other_bitmap = piggy_find_bitmap( subst_name );
1363                         GameBitmapXlat[i] = other_bitmap.index;
1364                         bmh.flags |= BM_FLAG_PAGED_OUT;
1365                         //mprintf(( 0, "Skipping bitmap %d\n", i ));
1366                         //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1367                 } else  {
1368                         bmh.flags &= ~BM_FLAG_PAGED_OUT;
1369                 }
1370                 bmh.avg_color=GameBitmaps[i].avg_color;
1371                 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp);  // Mark as a bitmap
1372         }
1373
1374         fclose(pig_fp);
1375
1376         mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1377         fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1378
1379         fclose(fp1);
1380         fclose(fp2);
1381
1382 }
1383
1384 static void write_int(int i,FILE *file)
1385 {
1386         if (fwrite( &i, sizeof(i), 1, file) != 1)
1387                 Error( "Error reading int in gamesave.c" );
1388
1389 }
1390
1391 void piggy_dump_all()
1392 {
1393         int i, xlat_offset;
1394         FILE * ham_fp;
1395         int org_offset,data_offset=0;
1396         DiskSoundHeader sndh;
1397         int sound_data_start=0;
1398         FILE *fp1,*fp2;
1399
1400         #ifdef NO_DUMP_SOUNDS
1401         Num_sound_files = 0;
1402         Num_sound_files_new = 0;
1403         #endif
1404
1405         if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1406                 return;
1407
1408         fp1 = fopen( "ham.lst", "wt" );
1409         fp2 = fopen( "ham.all", "wt" );
1410
1411         if (Must_write_hamfile || Num_bitmap_files_new) {
1412
1413                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1414         
1415                 ham_fp = fopen( DEFAULT_HAMFILE, "wb" );                       //open HAM file
1416                 Assert( ham_fp!=NULL );
1417         
1418                 write_int(HAMFILE_ID,ham_fp);
1419                 write_int(HAMFILE_VERSION,ham_fp);
1420         
1421                 bm_write_all(ham_fp);
1422                 xlat_offset = (int)ftell(ham_fp);
1423                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1424                 //Dump bitmaps
1425         
1426                 if (Num_bitmap_files_new)
1427                         piggy_write_pigfile(DEFAULT_PIGFILE);
1428         
1429                 //free up memeory used by new bitmaps
1430                 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1431                         d_free(GameBitmaps[i].bm_data);
1432         
1433                 //next thing must be done after pig written
1434                 fseek( ham_fp, xlat_offset, SEEK_SET );
1435                 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1436         
1437                 fclose(ham_fp);
1438                 mprintf( (0, "\n" ));
1439         }
1440         
1441         if (Num_sound_files_new) {
1442
1443                 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1444                 // Now dump sound file
1445                 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1446                 Assert( ham_fp!=NULL );
1447         
1448                 write_int(SNDFILE_ID,ham_fp);
1449                 write_int(SNDFILE_VERSION,ham_fp);
1450
1451                 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1452         
1453                 mprintf( (0, "\nDumping sounds..." ));
1454         
1455                 sound_data_start = (int)ftell(ham_fp);
1456                 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1457                 data_offset = sound_data_start;
1458         
1459                 for (i=0; i < Num_sound_files; i++ )    {
1460                         digi_sound *snd;
1461         
1462                         snd = &GameSounds[i];
1463                         strcpy( sndh.name, AllSounds[i].name );
1464                         sndh.length = GameSounds[i].length;
1465                         sndh.offset = data_offset - sound_data_start;
1466         
1467                         org_offset = (int)ftell(ham_fp);
1468                         fseek( ham_fp, data_offset, SEEK_SET );
1469         
1470                         sndh.data_length = GameSounds[i].length;
1471                         fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1472                         data_offset += snd->length;
1473                         fseek( ham_fp, org_offset, SEEK_SET );
1474                         fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp );                    // Mark as a bitmap
1475         
1476                         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1477                         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1478                 }
1479
1480                 fclose(ham_fp);
1481                 mprintf( (0, "\n" ));
1482         }
1483
1484         fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1485         mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1486         fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1487
1488         fclose(fp1);
1489         fclose(fp2);
1490
1491         // Never allow the game to run after building ham.
1492         exit(0);
1493 }
1494
1495 #endif
1496
1497 void piggy_close()
1498 {
1499         piggy_close_file();
1500
1501         if (BitmapBits)
1502                 d_free(BitmapBits);
1503
1504         if ( SoundBits )
1505                 d_free( SoundBits );
1506
1507         hashtable_free( &AllBitmapsNames );
1508         hashtable_free( &AllDigiSndNames );
1509
1510 }
1511
1512 int piggy_does_bitmap_exist_slow( char * name )
1513 {
1514         int i;
1515
1516         for (i=0; i<Num_bitmap_files; i++ )     {
1517                 if ( !strcmp( AllBitmaps[i].name, name) )
1518                         return 1;
1519         }
1520         return 0;
1521 }
1522
1523
1524 #define NUM_GAUGE_BITMAPS 23
1525 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1526         "gauge01", "gauge01b",
1527         "gauge02", "gauge02b",
1528         "gauge06", "gauge06b",
1529         "targ01", "targ01b",
1530         "targ02", "targ02b", 
1531         "targ03", "targ03b",
1532         "targ04", "targ04b",
1533         "targ05", "targ05b",
1534         "targ06", "targ06b",
1535         "gauge18", "gauge18b",
1536         "gauss1", "helix1",
1537         "phoenix1"
1538 };
1539
1540
1541 int piggy_is_gauge_bitmap( char * base_name )
1542 {
1543         int i;
1544         for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
1545                 if ( !stricmp( base_name, gauge_bitmap_names[i] ))      
1546                         return 1;
1547         }
1548
1549         return 0;       
1550 }
1551
1552 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1553 {
1554         int frame;
1555         char * p;
1556         char base_name[ 16 ];
1557         
1558         strcpy( subst_name, name );
1559         p = strchr( subst_name, '#' );
1560         if ( p )        {
1561                 frame = atoi( &p[1] );
1562                 *p = 0;
1563                 strcpy( base_name, subst_name );
1564                 if ( !piggy_is_gauge_bitmap( base_name ))       {
1565                         sprintf( subst_name, "%s#%d", base_name, frame+1 );
1566                         if ( piggy_does_bitmap_exist_slow( subst_name )  )      {
1567                                 if ( frame & 1 ) {
1568                                         sprintf( subst_name, "%s#%d", base_name, frame-1 );
1569                                         return 1;
1570                                 }
1571                         }
1572                 }
1573         }
1574         strcpy( subst_name, name );
1575         return 0;
1576 }
1577
1578
1579
1580 /*
1581  * Functions for loading replacement textures
1582  *  1) From .pog files
1583  *  2) From descent.pig (for loading d1 levels)
1584  */
1585
1586 extern char last_palette_loaded_pig[];
1587
1588 void free_bitmap_replacements()
1589 {
1590         if (Bitmap_replacement_data) {
1591                 d_free(Bitmap_replacement_data);
1592                 Bitmap_replacement_data = NULL;
1593         }
1594 }
1595
1596 void load_bitmap_replacements(char *level_name)
1597 {
1598         char ifile_name[FILENAME_LEN];
1599         CFILE *ifile;
1600         int i;
1601
1602         //first, free up data allocated for old bitmaps
1603         free_bitmap_replacements();
1604
1605         change_filename_extension(ifile_name, level_name, ".POG" );
1606
1607         ifile = cfopen(ifile_name,"rb");
1608
1609         if (ifile) {
1610                 int id,version,n_bitmaps;
1611                 int bitmap_data_size;
1612                 ushort *indices;
1613
1614                 id = cfile_read_int(ifile);
1615                 version = cfile_read_int(ifile);
1616
1617                 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1618                         cfclose(ifile);
1619                         return;
1620                 }
1621
1622                 n_bitmaps = cfile_read_int(ifile);
1623
1624                 MALLOC( indices, ushort, n_bitmaps );
1625
1626                 for (i = 0; i < n_bitmaps; i++)
1627                         indices[i] = cfile_read_short(ifile);
1628
1629                 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1630                 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1631
1632                 for (i=0;i<n_bitmaps;i++) {
1633                         DiskBitmapHeader bmh;
1634                         grs_bitmap *bm = &GameBitmaps[indices[i]];
1635                         int width;
1636
1637                         DiskBitmapHeader_read(&bmh, ifile);
1638
1639                         width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1640                         gr_set_bitmap_data(bm, NULL);   // free ogl texture
1641                         gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1642                         bm->avg_color = bmh.avg_color;
1643                         bm->bm_data = (ubyte *) (size_t)bmh.offset;
1644
1645                         gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1646
1647                         GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1648                 }
1649
1650                 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1651
1652                 for (i = 0; i < n_bitmaps; i++)
1653                 {
1654                         grs_bitmap *bm = &GameBitmaps[indices[i]];
1655                         gr_set_bitmap_data(bm, Bitmap_replacement_data + (size_t) bm->bm_data);
1656                 }
1657
1658                 d_free(indices);
1659
1660                 cfclose(ifile);
1661
1662                 last_palette_loaded_pig[0]= 0;  //force pig re-load
1663
1664                 texmerge_flush();       //for re-merging with new textures
1665         }
1666
1667         atexit(free_bitmap_replacements);
1668 }
1669
1670 /* calculate table to translate d1 bitmaps to current palette,
1671  * return -1 on error
1672  */
1673 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1674 {
1675         int freq[256];
1676         CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1677         if (!palette_file || cfilelength(palette_file) != 9472)
1678                 return -1;
1679         cfread( d1_palette, 256, 3, palette_file);
1680         cfclose( palette_file );
1681         build_colormap_good( d1_palette, colormap, freq );
1682         // don't change transparencies:
1683         colormap[254] = 254;
1684         colormap[255] = 255;
1685         return 0;
1686 }
1687
1688 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1689 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1690                      CFILE *d1_Piggy_fp, /* read from this file */
1691                      int bitmap_data_start, /* specific to file */
1692                      DiskBitmapHeader *bmh, /* header info for bitmap */
1693                      ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1694                      ubyte *d1_palette, /* what palette the bitmap has */
1695                      ubyte *colormap) /* how to translate bitmap's colors */
1696 {
1697         int zsize, pigsize = cfilelength(d1_Piggy_fp);
1698         ubyte *data;
1699         int width;
1700
1701         width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1702         gr_set_bitmap_data(bitmap, NULL);       // free ogl texture
1703         gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1704         bitmap->avg_color = bmh->avg_color;
1705         gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1706
1707         cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1708         if (bmh->flags & BM_FLAG_RLE) {
1709                 zsize = cfile_read_int(d1_Piggy_fp);
1710                 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1711         } else
1712                 zsize = bitmap->bm_h * bitmap->bm_w;
1713
1714         if (next_bitmap) {
1715                 data = *next_bitmap;
1716                 *next_bitmap += zsize;
1717         } else {
1718                 data = d_malloc(zsize + JUST_IN_CASE);
1719         }
1720         if (!data) return;
1721
1722         cfread(data, 1, zsize, d1_Piggy_fp);
1723         gr_set_bitmap_data(bitmap, data);
1724         switch(pigsize) {
1725         case D1_MAC_PIGSIZE:
1726         case D1_MAC_SHARE_PIGSIZE:
1727                 if (bmh->flags & BM_FLAG_RLE)
1728                         rle_swap_0_255(bitmap);
1729                 else
1730                         swap_0_255(bitmap);
1731         }
1732         if (bmh->flags & BM_FLAG_RLE)
1733                 rle_remap(bitmap, colormap);
1734         else
1735                 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1736         if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1737                 int new_size;
1738                 memcpy(&new_size, bitmap->bm_data, 4);
1739                 if (next_bitmap) {
1740                         *next_bitmap += new_size - zsize;
1741                 } else {
1742                         Assert( zsize + JUST_IN_CASE >= new_size );
1743                         bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1744                         Assert(bitmap->bm_data);
1745                 }
1746         }
1747 }
1748
1749 #define D1_MAX_TEXTURES 800
1750 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1751
1752 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1753  * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1754  * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1755  */
1756 short *d1_tmap_nums = NULL;
1757
1758 void free_d1_tmap_nums() {
1759         if (d1_tmap_nums) {
1760                 d_free(d1_tmap_nums);
1761                 d1_tmap_nums = NULL;
1762         }
1763 }
1764
1765 void bm_read_d1_tmap_nums(CFILE *d1pig)
1766 {
1767         int i, d1_index;
1768
1769         free_d1_tmap_nums();
1770         cfseek(d1pig, 8, SEEK_SET);
1771         MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1772         for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1773                 d1_tmap_nums[i] = -1;
1774         for (i = 0; i < D1_MAX_TEXTURES; i++) {
1775                 d1_index = cfile_read_short(d1pig);
1776                 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1777                 d1_tmap_nums[d1_index] = i;
1778         }
1779         atexit(free_d1_tmap_nums);
1780 }
1781
1782 void remove_char( char * s, char c )
1783 {
1784         char *p;
1785         p = strchr(s,c);
1786         if (p) *p = '\0';
1787 }
1788
1789 #define REMOVE_EOL(s)           remove_char((s),'\n')
1790 #define REMOVE_COMMENTS(s)      remove_char((s),';')
1791 #define REMOVE_DOTS(s)          remove_char((s),'.')
1792 char *space = { " \t" };
1793 char *equal_space = { " \t=" };
1794
1795 // this function is at the same position in the d1 shareware piggy loading 
1796 // algorithm as bm_load_sub in main/bmread.c
1797 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
1798         int i, N_bitmaps;
1799         DiskBitmapHeader bmh;
1800         if (strchr (filename, '.'))
1801                 *strchr (filename, '.') = '\0'; // remove extension
1802         cfseek (d1_pig, 0, SEEK_SET);
1803         N_bitmaps = cfile_read_int (d1_pig);
1804         cfseek (d1_pig, 8, SEEK_SET);
1805         for (i = 1; i <= N_bitmaps; i++) {
1806                 DiskBitmapHeader_d1_read(&bmh, d1_pig);
1807                 if (!strnicmp(bmh.name, filename, 8))
1808                         return i;
1809         }
1810         return -1;
1811 }
1812
1813 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1814 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1815 {
1816 #define LINEBUF_SIZE 600
1817         int reading_textures = 0;
1818         short texture_count = 0;
1819         char inputline[LINEBUF_SIZE];
1820         CFILE * bitmaps;
1821         int bitmaps_tbl_is_binary = 0;
1822         int i;
1823
1824         bitmaps = cfopen ("bitmaps.tbl", "rb");
1825         if (!bitmaps) {
1826                 bitmaps = cfopen ("bitmaps.bin", "rb");
1827                 bitmaps_tbl_is_binary = 1;
1828         }
1829
1830         if (!bitmaps) {
1831                 Warning ("Could not find bitmaps.* for reading d1 textures");
1832                 return;
1833         }
1834
1835         free_d1_tmap_nums();
1836         MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1837         for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1838                 d1_tmap_nums[i] = -1;
1839         atexit(free_d1_tmap_nums);
1840
1841         while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1842                 char *arg;
1843
1844                 if (bitmaps_tbl_is_binary)
1845                         decode_text_line((inputline));
1846                 else
1847                         while (inputline[(i = (int)strlen(inputline)) - 2] == '\\')
1848                                 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
1849                 REMOVE_EOL(inputline);
1850                 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
1851                 if (strlen(inputline) == LINEBUF_SIZE-1) {
1852                         Warning("Possible line truncation in BITMAPS.TBL");
1853                         return;
1854                 }
1855                 arg = strtok( inputline, space );
1856                 if (arg && arg[0] == '@') {
1857                         arg++;
1858                         //Registered_only = 1;
1859                 }
1860
1861                 while (arg != NULL) {
1862                         if (*arg == '$')
1863                                 reading_textures = 0; // default
1864                         if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
1865                                 reading_textures = 1;
1866                         else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
1867                                    || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
1868                                         texture_count++;
1869                         else // not a special token, must be a bitmap!
1870                                 if (reading_textures) {
1871                                         while (*arg == '\t' || *arg == ' ')
1872                                                 arg++;//remove unwanted blanks
1873                                         if (*arg == '\0')
1874                                                 break;
1875                                         if (d1_tmap_num_unique(texture_count)) {
1876                                                 int d1_index = get_d1_bm_index(arg, d1_pig);
1877                                                 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
1878                                                         d1_tmap_nums[d1_index] = texture_count;
1879                                                         //int d2_index = d2_index_for_d1_index(d1_index);
1880                                                 }
1881                                 }
1882                                 Assert (texture_count < D1_MAX_TEXTURES);
1883                                 texture_count++;
1884                         }
1885
1886                         arg = strtok (NULL, equal_space);
1887                 }
1888         }
1889         cfclose (bitmaps);
1890 }
1891
1892 /* If the given d1_index is the index of a bitmap we have to load
1893  * (because it is unique to descent 1), then returns the d2_index that
1894  * the given d1_index replaces.
1895  * Returns -1 if the given d1_index is not unique to descent 1.
1896  */
1897 short d2_index_for_d1_index(short d1_index)
1898 {
1899         Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1900         if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
1901             || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
1902                 return -1;
1903
1904         return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1905 }
1906
1907 #define D1_BITMAPS_SIZE 300000
1908 void load_d1_bitmap_replacements()
1909 {
1910         CFILE * d1_Piggy_fp;
1911         DiskBitmapHeader bmh;
1912         int pig_data_start, bitmap_header_start, bitmap_data_start;
1913         int N_bitmaps;
1914         short d1_index, d2_index;
1915         ubyte* next_bitmap;
1916         ubyte colormap[256];
1917         ubyte d1_palette[256*3];
1918         char *p;
1919         int pigsize;
1920
1921         d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1922
1923 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1924         if (!d1_Piggy_fp) {
1925                 Warning(D1_PIG_LOAD_FAILED);
1926                 return;
1927         }
1928
1929         //first, free up data allocated for old bitmaps
1930         free_bitmap_replacements();
1931
1932         if (get_d1_colormap( d1_palette, colormap ) != 0)
1933                 Warning("Could not load descent 1 color palette");
1934
1935         pigsize = cfilelength(d1_Piggy_fp);
1936         switch (pigsize) {
1937         case D1_SHARE_BIG_PIGSIZE:
1938         case D1_SHARE_10_PIGSIZE:
1939         case D1_SHARE_PIGSIZE:
1940         case D1_10_BIG_PIGSIZE:
1941         case D1_10_PIGSIZE:
1942                 pig_data_start = 0;
1943                 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
1944                 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
1945                 break;
1946         default:
1947                 Warning("Unknown size for " D1_PIGFILE);
1948                 Int3();
1949                 // fall through
1950         case D1_PIGSIZE:
1951         case D1_OEM_PIGSIZE:
1952         case D1_MAC_PIGSIZE:
1953         case D1_MAC_SHARE_PIGSIZE:
1954                 pig_data_start = cfile_read_int(d1_Piggy_fp );
1955                 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
1956                 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
1957                 break;
1958         }
1959
1960         cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1961         N_bitmaps = cfile_read_int(d1_Piggy_fp);
1962         {
1963                 int N_sounds = cfile_read_int(d1_Piggy_fp);
1964                 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
1965                         + N_sounds * sizeof(DiskSoundHeader);
1966                 bitmap_header_start = pig_data_start + 2 * sizeof(int);
1967                 bitmap_data_start = bitmap_header_start + header_size;
1968         }
1969
1970         MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1971         if (!Bitmap_replacement_data) {
1972                 Warning(D1_PIG_LOAD_FAILED);
1973                 return;
1974         }
1975         atexit(free_bitmap_replacements);
1976
1977         next_bitmap = Bitmap_replacement_data;
1978
1979         for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
1980                 d2_index = d2_index_for_d1_index(d1_index);
1981                 // only change bitmaps which are unique to d1
1982                 if (d2_index != -1) {
1983                         cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
1984                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
1985
1986                         bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
1987                         Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
1988                         GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
1989                         GameBitmapFlags[d2_index] = bmh.flags;
1990
1991                         if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
1992                              && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
1993                                 int i, len = (int)(p - AllBitmaps[d2_index].name);
1994                                 for (i = 0; i < Num_bitmap_files; i++)
1995                                         if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
1996                                         {
1997                                                 gr_set_bitmap_data(&GameBitmaps[i], NULL);      // free ogl texture
1998                                                 GameBitmaps[i] = GameBitmaps[d2_index];
1999                                                 GameBitmapOffset[i] = 0;
2000                                                 GameBitmapFlags[i] = bmh.flags;
2001                                         }
2002                         }
2003                 }
2004         }
2005
2006         cfclose(d1_Piggy_fp);
2007
2008         last_palette_loaded_pig[0]= 0;  //force pig re-load
2009
2010         texmerge_flush();       //for re-merging with new textures
2011 }
2012
2013
2014 extern int extra_bitmap_num;
2015
2016 /*
2017  * Find and load the named bitmap from descent.pig
2018  * similar to read_extra_bitmap_iff
2019  */
2020 bitmap_index read_extra_bitmap_d1_pig(char *name)
2021 {
2022         bitmap_index bitmap_num;
2023         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2024
2025         bitmap_num.index = 0;
2026
2027         {
2028                 CFILE *d1_Piggy_fp;
2029                 DiskBitmapHeader bmh;
2030                 int pig_data_start, bitmap_header_start, bitmap_data_start;
2031                 int i, N_bitmaps;
2032                 ubyte colormap[256];
2033                 ubyte d1_palette[256*3];
2034                 int pigsize;
2035
2036                 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2037
2038                 if (!d1_Piggy_fp)
2039                 {
2040                         Warning(D1_PIG_LOAD_FAILED);
2041                         return bitmap_num;
2042                 }
2043
2044                 if (get_d1_colormap( d1_palette, colormap ) != 0)
2045                         Warning("Could not load descent 1 color palette");
2046
2047                 pigsize = cfilelength(d1_Piggy_fp);
2048                 switch (pigsize) {
2049                 case D1_SHARE_BIG_PIGSIZE:
2050                 case D1_SHARE_10_PIGSIZE:
2051                 case D1_SHARE_PIGSIZE:
2052                 case D1_10_BIG_PIGSIZE:
2053                 case D1_10_PIGSIZE:
2054                         pig_data_start = 0;
2055                         break;
2056                 default:
2057                         Warning("Unknown size for " D1_PIGFILE);
2058                         Int3();
2059                         // fall through
2060                 case D1_PIGSIZE:
2061                 case D1_OEM_PIGSIZE:
2062                 case D1_MAC_PIGSIZE:
2063                 case D1_MAC_SHARE_PIGSIZE:
2064                         pig_data_start = cfile_read_int(d1_Piggy_fp );
2065
2066                         break;
2067                 }
2068
2069                 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2070                 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2071                 {
2072                         int N_sounds = cfile_read_int(d1_Piggy_fp);
2073                         int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2074                                 + N_sounds * sizeof(DiskSoundHeader);
2075                         bitmap_header_start = pig_data_start + 2 * sizeof(int);
2076                         bitmap_data_start = bitmap_header_start + header_size;
2077                 }
2078
2079                 for (i = 1; i <= N_bitmaps; i++)
2080                 {
2081                         DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2082                         if (!strnicmp(bmh.name, name, 8))
2083                                 break;
2084                 }
2085
2086                 if (strnicmp(bmh.name, name, 8))
2087                 {
2088                         con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2089                         return bitmap_num;
2090                 }
2091
2092                 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2093
2094                 cfclose(d1_Piggy_fp);
2095         }
2096
2097         new->avg_color = 0;     //compute_average_pixel(new);
2098
2099         bitmap_num.index = extra_bitmap_num;
2100
2101         GameBitmaps[extra_bitmap_num++] = *new;
2102
2103         return bitmap_num;
2104 }
2105
2106
2107 #ifndef FAST_FILE_IO
2108 /*
2109  * reads a bitmap_index structure from a CFILE
2110  */
2111 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2112 {
2113         bi->index = cfile_read_short(fp);
2114 }
2115
2116 /*
2117  * reads n bitmap_index structs from a CFILE
2118  */
2119 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2120 {
2121         int i;
2122
2123         for (i = 0; i < n; i++)
2124                 bi[i].index = cfile_read_short(fp);
2125         return i;
2126 }
2127 #endif // FAST_FILE_IO