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