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.
16 * Functions for managing the pig files.
63 #include <Strings.h> // MacOS Toolbox header
68 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
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"
75 #define D1_PALETTE "palette.256"
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")
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
88 ubyte *BitmapBits = NULL;
89 ubyte *SoundBits = NULL;
91 typedef struct BitmapFile {
95 typedef struct SoundFile {
99 hashtable AllBitmapsNames;
100 hashtable AllDigiSndNames;
102 int Num_bitmap_files = 0;
103 int Num_sound_files = 0;
105 digi_sound GameSounds[MAX_SOUND_FILES];
106 int SoundOffset[MAX_SOUND_FILES];
107 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
109 alias alias_list[MAX_ALIASES];
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 ];
118 int Piggy_hamfile_version = 0;
120 int piggy_low_memory = 0;
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];
129 #define PIGGY_BUFFER_SIZE (2400*1024)
132 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
135 #undef PIGGY_BUFFER_SIZE
136 #undef PIGGY_SMALL_BUFFER_SIZE
138 #define PIGGY_BUFFER_SIZE (2000*1024)
139 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
144 int piggy_page_flushed = 0;
146 #define DBM_FLAG_ABM 64 // animated bitmap
147 #define DBM_NUM_FRAMES 63
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)
152 typedef struct DiskBitmapHeader {
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
161 } __pack__ DiskBitmapHeader;
163 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
165 typedef struct DiskSoundHeader {
170 } __pack__ DiskSoundHeader;
173 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
174 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
177 * reads a DiskBitmapHeader structure from a CFILE
179 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
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);
192 * reads a DiskSoundHeader structure from a CFILE
194 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
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);
201 #endif // FAST_FILE_IO
204 * reads a descent 1 DiskBitmapHeader structure from a CFILE
206 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
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);
213 dbh->flags = cfile_read_byte(fp);
214 dbh->avg_color = cfile_read_byte(fp);
215 dbh->offset = cfile_read_int(fp);
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);
227 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
230 void piggy_write_pigfile(char *filename);
231 static void write_int(int i,FILE *file);
234 void swap_0_255(grs_bitmap *bmp)
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)
246 char* piggy_game_bitmap_name(grs_bitmap *bmp)
248 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
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;
257 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
260 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
262 temp.index = Num_bitmap_files;
266 if ( FindArg("-macdata") )
269 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
270 Num_bitmap_files_new++;
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;
277 GameBitmapOffset[Num_bitmap_files] = 0;
278 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
285 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
289 Assert( Num_sound_files < MAX_SOUND_FILES );
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;
295 SoundOffset[Num_sound_files] = 0;
301 Num_sound_files_new++;
307 bitmap_index piggy_find_bitmap( char * name )
315 if ((t=strchr(name,'#'))!=NULL)
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 );
328 name=alias_list[i].file_name;
335 i = hashtable_search( &AllBitmapsNames, name );
344 int piggy_find_sound( char * name )
348 i = hashtable_search( &AllDigiSndNames, name );
356 CFILE * Piggy_fp = NULL;
358 #define FILENAME_LEN 13
360 char Current_pigfile[FILENAME_LEN] = "";
362 void piggy_close_file()
367 Current_pigfile[0] = 0;
371 int Pigfile_initialized=0;
373 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
374 #define PIGFILE_VERSION 2
377 //initialize a pigfile, reading headers
378 //returns the size of all the bitmap data
379 void piggy_init_pigfile(char *filename)
383 char temp_name_read[16];
384 DiskBitmapHeader bmh;
385 int header_size, N_bitmaps, data_size, data_start;
387 piggy_close_file(); //close old pig if still open
389 //rename pigfile for shareware
390 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
391 filename = DEFAULT_PIGFILE_SHAREWARE;
393 Piggy_fp = cfopen( filename, "rb" );
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)
398 Error("Cannot load required file <%s>",name);
400 #endif // end of if def shareware
404 return; //if editor, ok to not have pig, because we'll build one
406 Piggy_fp = cfopen(filename, "rb");
410 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
411 int pig_id,pig_version;
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
424 return; //if editor, ok to not have pig, because we'll build one
426 Error("Cannot load required file <%s>",filename);
430 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
432 N_bitmaps = cfile_read_int(Piggy_fp);
434 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
436 data_start = header_size + cftell(Piggy_fp);
438 data_size = cfilelength(Piggy_fp) - data_start;
440 Num_bitmap_files = 1;
442 for (i=0; i<N_bitmaps; i++ )
445 grs_bitmap *bm = &GameBitmaps[i + 1];
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 );
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;
459 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
461 GameBitmapOffset[i+1] = bmh.offset + data_start;
462 Assert( (i+1) == Num_bitmap_files );
463 piggy_register_bitmap(bm, temp_name, 1);
467 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
468 Assert( Piggy_bitmap_cache_size > 0 );
470 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
472 if (piggy_low_memory)
473 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
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;
482 #if defined(MACINTOSH) && defined(SHAREWARE)
483 // load_exit_models();
486 Pigfile_initialized=1;
489 #define FILENAME_LEN 13
490 #define MAX_BITMAPS_PER_BRUSH 30
492 extern int compute_average_pixel(grs_bitmap *new);
493 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
495 ubyte *Bitmap_replacement_data = NULL;
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)
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;
510 //rename pigfile for shareware
511 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
512 pigname = DEFAULT_PIGFILE_SHAREWARE;
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
518 if (!Pigfile_initialized) { //have we ever opened a pigfile?
519 piggy_init_pigfile(pigname); //..no, so do initialization stuff
523 piggy_close_file(); //close old pig if still open
525 Piggy_bitmap_cache_next = 0; //free up cache
527 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
529 Piggy_fp = cfopen( pigname, "rb" );
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)
534 Error("Cannot load required file <%s>",name);
536 #endif // end of if def shareware
540 Piggy_fp = cfopen(pigname, "rb");
543 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
544 int pig_id,pig_version;
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
556 Error("Cannot open correct version of <%s>", pigname);
561 N_bitmaps = cfile_read_int(Piggy_fp);
563 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
565 data_start = header_size + cftell(Piggy_fp);
567 data_size = cfilelength(Piggy_fp) - data_start;
569 for (i=1; i<=N_bitmaps; i++ )
571 grs_bitmap *bm = &GameBitmaps[i];
574 DiskBitmapHeader_read(&bmh, Piggy_fp);
575 memcpy( temp_name_read, bmh.name, 8 );
576 temp_name_read[8] = 0;
578 if ( bmh.dflags & DBM_FLAG_ABM )
579 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
581 strcpy( temp_name, temp_name_read );
583 //Make sure name matches
584 if (strcmp(temp_name,AllBitmaps[i].name)) {
585 //Int3(); //this pig is out of date. Delete it
589 strcpy(AllBitmaps[i].name,temp_name);
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;
597 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
599 GameBitmapOffset[i] = bmh.offset + data_start;
603 N_bitmaps = 0; //no pigfile, so no bitmaps
607 Assert(N_bitmaps == Num_bitmap_files-1);
611 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
614 //re-read the bitmaps that aren't in this pig
616 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
619 p = strchr(AllBitmaps[i].name,'#');
621 if (p) { // this is an ABM == animated bitmap
622 char abmname[FILENAME_LEN];
624 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
625 int iff_error; //reference parm to avoid warning message
627 char basename[FILENAME_LEN];
630 strcpy(basename,AllBitmaps[i].name);
631 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
633 sprintf( abmname, "%s.abm", basename );
635 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
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));
642 for (fnum=0;fnum<nframes; fnum++) {
646 sprintf( tempname, "%s#%d", basename, fnum );
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
652 if ( iff_has_transparency )
653 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
655 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
657 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
660 if ( FindArg("-macdata") )
661 swap_0_255( bm[fnum] );
663 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
665 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
666 size = *((int *) bm[fnum]->bm_data);
668 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
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;
675 GameBitmaps[i+fnum] = *bm[fnum];
677 // -- mprintf( (0, "U" ));
681 i += nframes-1; //filled in multiple bitmaps
683 else { //this is a BBM
688 char bbmname[FILENAME_LEN];
691 MALLOC( new, grs_bitmap, 1 );
693 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
694 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
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));
702 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
703 //above makes assumption that supertransparent color is 254
705 if ( iff_has_transparency )
706 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
708 gr_remap_bitmap_good( new, newpal, -1, SuperX );
710 new->avg_color = compute_average_pixel(new);
713 if ( FindArg("-macdata") )
716 if ( !BigPig ) gr_bitmap_rle_compress( new );
718 if (new->bm_flags & BM_FLAG_RLE)
719 size = *((int *) new->bm_data);
721 size = new->bm_w * new->bm_h;
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;
728 GameBitmaps[i] = *new;
732 // -- mprintf( (0, "U" ));
736 //@@Dont' do these things which are done when writing
737 //@@for (i=0; i < Num_bitmap_files; i++ ) {
738 //@@ bitmap_index bi;
740 //@@ PIGGY_PAGE_IN( bi );
743 //@@piggy_close_file();
745 piggy_write_pigfile(pigname);
747 Current_pigfile[0] = 0; //say no pig, to force reload
749 piggy_new_pigfile(pigname); //read in just-generated pig
753 #endif //ifdef EDITOR
757 ubyte bogus_data[64*64];
758 ubyte bogus_bitmap_initialized=0;
759 digi_sound bogus_sound;
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
766 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
767 #define SNDFILE_VERSION 1
771 CFILE * ham_fp = NULL;
773 int sound_offset = 0;
775 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
777 if (ham_fp == NULL) {
778 Must_write_hamfile = 1;
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);
788 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
789 Must_write_hamfile = 1;
790 cfclose(ham_fp); //out of date ham
795 if (Piggy_hamfile_version < 3) // hamfile contains sound info
796 sound_offset = cfile_read_int(ham_fp);
803 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
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]);
812 if (Piggy_hamfile_version < 3) {
817 DiskSoundHeader sndh;
818 digi_sound temp_sound;
819 char temp_name_read[16];
822 cfseek(ham_fp, sound_offset, SEEK_SET);
823 N_sounds = cfile_read_int(ham_fp);
825 sound_start = cftell(ham_fp);
827 header_size = N_sounds * sizeof(DiskSoundHeader);
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 );
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 ));
846 SoundBits = d_malloc( sbytes + 16 );
847 if ( SoundBits == NULL )
848 Error( "Not enough memory to load sounds\n" );
850 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
852 // piggy_read_sounds(ham_fp);
864 CFILE * snd_fp = NULL;
865 int snd_id,snd_version;
870 DiskSoundHeader sndh;
871 digi_sound temp_sound;
872 char temp_name_read[16];
875 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
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
888 N_sounds = cfile_read_int(snd_fp);
890 sound_start = cftell(snd_fp);
891 size = cfilelength(snd_fp) - sound_start;
893 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
895 header_size = N_sounds*sizeof(DiskSoundHeader);
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 );
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 ));
915 SoundBits = d_malloc( sbytes + 16 );
916 if ( SoundBits == NULL )
917 Error( "Not enough memory to load sounds\n" );
919 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
921 // piggy_read_sounds(snd_fp);
930 int ham_ok=0,snd_ok=0;
933 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
934 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
936 for (i=0; i<MAX_SOUND_FILES; i++ ) {
937 GameSounds[i].length = 0;
938 GameSounds[i].data = NULL;
942 for (i=0; i<MAX_BITMAP_FILES; i++ )
943 GameBitmapXlat[i] = i;
945 if ( !bogus_bitmap_initialized ) {
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;
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;
965 if ( FindArg( "-bigpig" ))
968 if ( FindArg( "-lowmem" ))
969 piggy_low_memory = 1;
971 if ( FindArg( "-nolowmem" ))
972 piggy_low_memory = 0;
974 if (piggy_low_memory)
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 );
981 #if 1 //def EDITOR //need for d1 mission briefings
982 piggy_init_pigfile(DEFAULT_PIGFILE);
985 snd_ok = ham_ok = read_hamfile();
987 if (Piggy_hamfile_version >= 3)
988 snd_ok = read_sndfile();
992 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
993 return (ham_ok && snd_ok); //read ok
996 int piggy_is_needed(int soundnum)
1000 if ( !digi_lomem ) return 1;
1002 for (i=0; i<MAX_SOUNDS; i++ ) {
1003 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1010 void piggy_read_sounds(void)
1019 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1024 for (i=0; i<Num_sound_files; i++ ) {
1025 digi_sound *snd = &GameSounds[i];
1027 if ( SoundOffset[i] > 0 ) {
1028 if ( piggy_is_needed(i) ) {
1029 cfseek( fp, SoundOffset[i], SEEK_SET );
1031 // Read in the sound data!!!
1034 sbytes += snd->length;
1035 cfread( snd->data, snd->length, 1, fp );
1038 snd->data = (ubyte *) -1;
1044 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1049 extern int descent_critical_error;
1050 extern unsigned descent_critical_deverror;
1051 extern unsigned descent_critical_errcode;
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" };
1057 void piggy_critical_error()
1059 grs_canvas * save_canv;
1060 grs_font * save_font;
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' );
1068 gr_set_current_canvas(save_canv);
1069 grd_curcanv->cv_font = save_font;
1072 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1074 void piggy_bitmap_page_in( bitmap_index bitmap )
1083 Assert( i < MAX_BITMAP_FILES );
1084 Assert( i < Num_bitmap_files );
1085 Assert( Piggy_bitmap_cache_size > 0 );
1087 if ( i < 1 ) return;
1088 if ( i >= MAX_BITMAP_FILES ) return;
1089 if ( i >= Num_bitmap_files ) return;
1091 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1093 if ( piggy_low_memory ) {
1095 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1098 bmp = &GameBitmaps[i];
1100 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1104 descent_critical_error = 0;
1105 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1106 if ( descent_critical_error ) {
1107 piggy_critical_error();
1111 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
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();
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 ) {
1126 piggy_bitmap_page_out_all();
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();
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]);
1141 if (!FindArg("-macdata"))
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);
1156 Piggy_bitmap_cache_next += zsize;
1157 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1159 piggy_bitmap_page_out_all();
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();
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();
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;
1183 if (!FindArg("-macdata"))
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:
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" );
1208 if ( piggy_low_memory ) {
1210 GameBitmaps[org_i] = GameBitmaps[i];
1213 //@@Removed from John's code:
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" );
1223 void piggy_bitmap_page_out_all()
1227 Piggy_bitmap_cache_next = 0;
1229 piggy_page_flushed++;
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);
1241 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1244 void piggy_load_level_data()
1246 piggy_bitmap_page_out_all();
1252 void piggy_write_pigfile(char *filename)
1255 int bitmap_data_start, data_offset;
1256 DiskBitmapHeader bmh;
1258 char subst_name[32];
1261 char tname[FILENAME_LEN];
1263 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1264 for (i=0; i < Num_bitmap_files; i++ ) {
1267 PIGGY_PAGE_IN( bi );
1269 // -- mprintf( (0, "\n" ));
1273 // -- mprintf( (0, "Creating %s...",filename ));
1275 pig_fp = fopen( filename, "wb" ); //open PIG file
1276 Assert( pig_fp!=NULL );
1278 write_int(PIGFILE_ID,pig_fp);
1279 write_int(PIGFILE_VERSION,pig_fp);
1282 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1285 bitmap_data_start = ftell(pig_fp);
1286 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1287 data_offset = bitmap_data_start;
1289 change_filename_extension(tname,filename,"lst");
1290 fp1 = fopen( tname, "wt" );
1291 change_filename_extension(tname,filename,"all");
1292 fp2 = fopen( tname, "wt" );
1294 for (i=1; i < Num_bitmap_files; i++ ) {
1300 p = strchr(AllBitmaps[i].name, '#');
1301 if (p) { // this is an ABM == animated bitmap
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;
1314 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1315 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1319 bmp = &GameBitmaps[i];
1321 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
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 );
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;
1334 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1336 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1337 data_offset += bmp->bm_rowsize * bmp->bm_h;
1339 fprintf( fp1, ".\n" );
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 ));
1357 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1359 bmh.avg_color=GameBitmaps[i].avg_color;
1360 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1365 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1366 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1373 static void write_int(int i,FILE *file)
1375 if (fwrite( &i, sizeof(i), 1, file) != 1)
1376 Error( "Error reading int in gamesave.c" );
1380 void piggy_dump_all()
1384 int org_offset,data_offset=0;
1385 DiskSoundHeader sndh;
1386 int sound_data_start=0;
1389 #ifdef NO_DUMP_SOUNDS
1390 Num_sound_files = 0;
1391 Num_sound_files_new = 0;
1394 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1397 fp1 = fopen( "ham.lst", "wt" );
1398 fp2 = fopen( "ham.all", "wt" );
1400 if (Must_write_hamfile || Num_bitmap_files_new) {
1402 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1404 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1405 Assert( ham_fp!=NULL );
1407 write_int(HAMFILE_ID,ham_fp);
1408 write_int(HAMFILE_VERSION,ham_fp);
1410 bm_write_all(ham_fp);
1411 xlat_offset = ftell(ham_fp);
1412 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1415 if (Num_bitmap_files_new)
1416 piggy_write_pigfile(DEFAULT_PIGFILE);
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);
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 );
1427 mprintf( (0, "\n" ));
1430 if (Num_sound_files_new) {
1432 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1433 // Now dump sound file
1434 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1435 Assert( ham_fp!=NULL );
1437 write_int(SNDFILE_ID,ham_fp);
1438 write_int(SNDFILE_VERSION,ham_fp);
1440 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1442 mprintf( (0, "\nDumping sounds..." ));
1444 sound_data_start = ftell(ham_fp);
1445 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1446 data_offset = sound_data_start;
1448 for (i=0; i < Num_sound_files; i++ ) {
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;
1456 org_offset = ftell(ham_fp);
1457 fseek( ham_fp, data_offset, SEEK_SET );
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
1465 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1466 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1470 mprintf( (0, "\n" ));
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 );
1480 // Never allow the game to run after building ham.
1494 d_free( SoundBits );
1496 hashtable_free( &AllBitmapsNames );
1497 hashtable_free( &AllDigiSndNames );
1501 int piggy_does_bitmap_exist_slow( char * name )
1505 for (i=0; i<Num_bitmap_files; i++ ) {
1506 if ( !strcmp( AllBitmaps[i].name, name) )
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",
1530 int piggy_is_gauge_bitmap( char * base_name )
1533 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1534 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1541 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1545 char base_name[ 16 ];
1547 strcpy( subst_name, name );
1548 p = strchr( subst_name, '#' );
1550 frame = atoi( &p[1] );
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 ) ) {
1557 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1563 strcpy( subst_name, name );
1570 * Functions for loading replacement textures
1571 * 1) From .pog files
1572 * 2) From descent.pig (for loading d1 levels)
1575 extern char last_palette_loaded_pig[];
1577 void free_bitmap_replacements()
1579 if (Bitmap_replacement_data) {
1580 d_free(Bitmap_replacement_data);
1581 Bitmap_replacement_data = NULL;
1585 void load_bitmap_replacements(char *level_name)
1587 char ifile_name[FILENAME_LEN];
1591 //first, free up data allocated for old bitmaps
1592 free_bitmap_replacements();
1594 change_filename_extension(ifile_name, level_name, ".POG" );
1596 ifile = cfopen(ifile_name,"rb");
1599 int id,version,n_bitmaps;
1600 int bitmap_data_size;
1603 id = cfile_read_int(ifile);
1604 version = cfile_read_int(ifile);
1606 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1611 n_bitmaps = cfile_read_int(ifile);
1613 MALLOC( indices, ushort, n_bitmaps );
1615 for (i = 0; i < n_bitmaps; i++)
1616 indices[i] = cfile_read_short(ifile);
1618 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1619 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1621 for (i=0;i<n_bitmaps;i++) {
1622 DiskBitmapHeader bmh;
1623 grs_bitmap *bm = &GameBitmaps[indices[i]];
1626 DiskBitmapHeader_read(&bmh, ifile);
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;
1634 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1636 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1639 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1641 for (i = 0; i < n_bitmaps; i++)
1643 grs_bitmap *bm = &GameBitmaps[indices[i]];
1644 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1651 last_palette_loaded_pig[0]= 0; //force pig re-load
1653 texmerge_flush(); //for re-merging with new textures
1656 atexit(free_bitmap_replacements);
1659 /* calculate table to translate d1 bitmaps to current palette,
1660 * return -1 on error
1662 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1665 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1666 if (!palette_file || cfilelength(palette_file) != 9472)
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;
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 */
1686 int zsize, pigsize = cfilelength(d1_Piggy_fp);
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);
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);
1701 zsize = bitmap->bm_h * bitmap->bm_w;
1704 data = *next_bitmap;
1705 *next_bitmap += zsize;
1707 data = d_malloc(zsize + JUST_IN_CASE);
1711 cfread(data, 1, zsize, d1_Piggy_fp);
1712 gr_set_bitmap_data(bitmap, data);
1714 case D1_MAC_PIGSIZE:
1715 case D1_MAC_SHARE_PIGSIZE:
1716 if (bmh->flags & BM_FLAG_RLE)
1717 rle_swap_0_255(bitmap);
1721 if (bmh->flags & BM_FLAG_RLE)
1722 rle_remap(bitmap, colormap);
1724 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1725 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1727 memcpy(&new_size, bitmap->bm_data, 4);
1729 *next_bitmap += new_size - zsize;
1731 Assert( zsize + JUST_IN_CASE >= new_size );
1732 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1733 Assert(bitmap->bm_data);
1738 #define D1_MAX_TEXTURES 800
1739 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
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".
1745 short *d1_tmap_nums = NULL;
1747 void free_d1_tmap_nums() {
1749 d_free(d1_tmap_nums);
1750 d1_tmap_nums = NULL;
1754 void bm_read_d1_tmap_nums(CFILE *d1pig)
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;
1768 atexit(free_d1_tmap_nums);
1771 void remove_char( char * s, char c )
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=" };
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) {
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))
1802 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1803 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1805 #define LINEBUF_SIZE 600
1806 int reading_textures = 0;
1807 short texture_count = 0;
1808 char inputline[LINEBUF_SIZE];
1810 int bitmaps_tbl_is_binary = 0;
1813 bitmaps = cfopen ("bitmaps.tbl", "rb");
1815 bitmaps = cfopen ("bitmaps.bin", "rb");
1816 bitmaps_tbl_is_binary = 1;
1820 Warning ("Could not find bitmaps.* for reading d1 textures");
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);
1830 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1833 if (bitmaps_tbl_is_binary)
1834 decode_text_line((inputline));
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");
1844 arg = strtok( inputline, space );
1845 if (arg && arg[0] == '@') {
1847 //Registered_only = 1;
1850 while (arg != NULL) {
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
1858 else // not a special token, must be a bitmap!
1859 if (reading_textures) {
1860 while (*arg == '\t' || *arg == ' ')
1861 arg++;//remove unwanted blanks
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);
1871 Assert (texture_count < D1_MAX_TEXTURES);
1875 arg = strtok (NULL, equal_space);
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.
1886 short d2_index_for_d1_index(short d1_index)
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]))
1893 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1896 #define D1_BITMAPS_SIZE 300000
1897 void load_d1_bitmap_replacements()
1899 CFILE * d1_Piggy_fp;
1900 DiskBitmapHeader bmh;
1901 int pig_data_start, bitmap_header_start, bitmap_data_start;
1903 short d1_index, d2_index;
1905 ubyte colormap[256];
1906 ubyte d1_palette[256*3];
1910 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1912 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1914 Warning(D1_PIG_LOAD_FAILED);
1918 //first, free up data allocated for old bitmaps
1919 free_bitmap_replacements();
1921 if (get_d1_colormap( d1_palette, colormap ) != 0)
1922 Warning("Could not load descent 1 color palette");
1924 pigsize = cfilelength(d1_Piggy_fp);
1926 case D1_SHARE_BIG_PIGSIZE:
1927 case D1_SHARE_10_PIGSIZE:
1928 case D1_SHARE_PIGSIZE:
1929 case D1_10_BIG_PIGSIZE:
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);
1936 Warning("Unknown size for " D1_PIGFILE);
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);
1949 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1950 N_bitmaps = cfile_read_int(d1_Piggy_fp);
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;
1959 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1960 if (!Bitmap_replacement_data) {
1961 Warning(D1_PIG_LOAD_FAILED);
1964 atexit(free_bitmap_replacements);
1966 next_bitmap = Bitmap_replacement_data;
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);
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;
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))
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;
1995 cfclose(d1_Piggy_fp);
1997 last_palette_loaded_pig[0]= 0; //force pig re-load
1999 texmerge_flush(); //for re-merging with new textures
2003 extern int extra_bitmap_num;
2006 * Find and load the named bitmap from descent.pig
2007 * similar to read_extra_bitmap_iff
2009 bitmap_index read_extra_bitmap_d1_pig(char *name)
2011 bitmap_index bitmap_num;
2012 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2014 bitmap_num.index = 0;
2018 DiskBitmapHeader bmh;
2019 int pig_data_start, bitmap_header_start, bitmap_data_start;
2021 ubyte colormap[256];
2022 ubyte d1_palette[256*3];
2025 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2029 Warning(D1_PIG_LOAD_FAILED);
2033 if (get_d1_colormap( d1_palette, colormap ) != 0)
2034 Warning("Could not load descent 1 color palette");
2036 pigsize = cfilelength(d1_Piggy_fp);
2038 case D1_SHARE_BIG_PIGSIZE:
2039 case D1_SHARE_10_PIGSIZE:
2040 case D1_SHARE_PIGSIZE:
2041 case D1_10_BIG_PIGSIZE:
2046 Warning("Unknown size for " D1_PIGFILE);
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 );
2058 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2059 N_bitmaps = cfile_read_int(d1_Piggy_fp);
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;
2068 for (i = 1; i <= N_bitmaps; i++)
2070 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2071 if (!strnicmp(bmh.name, name, 8))
2075 if (strnicmp(bmh.name, name, 8))
2077 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2081 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2083 cfclose(d1_Piggy_fp);
2086 new->avg_color = 0; //compute_average_pixel(new);
2088 bitmap_num.index = extra_bitmap_num;
2090 GameBitmaps[extra_bitmap_num++] = *new;
2096 #ifndef FAST_FILE_IO
2098 * reads a bitmap_index structure from a CFILE
2100 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2102 bi->index = cfile_read_short(fp);
2106 * reads n bitmap_index structs from a CFILE
2108 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2112 for (i = 0; i < n; i++)
2113 bi[i].index = cfile_read_short(fp);
2116 #endif // FAST_FILE_IO