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.
31 #include <Strings.h> // MacOS Toolbox header
50 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
52 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
53 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
54 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
55 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
57 #define D1_PALETTE "palette.256"
59 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
60 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
61 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
63 #define MAC_ALIEN1_PIGSIZE 5013035
64 #define MAC_ALIEN2_PIGSIZE 4909916
65 #define MAC_FIRE_PIGSIZE 4969035
66 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
67 #define MAC_ICE_PIGSIZE 4923425
68 #define MAC_WATER_PIGSIZE 4832403
70 ubyte *BitmapBits = NULL;
71 ubyte *SoundBits = NULL;
73 typedef struct BitmapFile {
77 typedef struct SoundFile {
81 hashtable AllBitmapsNames;
82 hashtable AllDigiSndNames;
84 int Num_bitmap_files = 0;
85 int Num_sound_files = 0;
87 digi_sound GameSounds[MAX_SOUND_FILES];
88 int SoundOffset[MAX_SOUND_FILES];
89 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
91 alias alias_list[MAX_ALIASES];
94 int Must_write_hamfile = 0;
95 int Num_bitmap_files_new = 0;
96 int Num_sound_files_new = 0;
97 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
98 static SoundFile AllSounds[ MAX_SOUND_FILES ];
100 int Piggy_hamfile_version = 0;
102 int piggy_low_memory = 0;
104 int Piggy_bitmap_cache_size = 0;
105 int Piggy_bitmap_cache_next = 0;
106 ubyte * Piggy_bitmap_cache_data = NULL;
107 static int GameBitmapOffset[MAX_BITMAP_FILES];
108 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
109 ushort GameBitmapXlat[MAX_BITMAP_FILES];
111 #define PIGGY_BUFFER_SIZE (2400*1024)
114 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
117 #undef PIGGY_BUFFER_SIZE
118 #undef PIGGY_SMALL_BUFFER_SIZE
120 #define PIGGY_BUFFER_SIZE (2000*1024)
121 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
126 int piggy_page_flushed = 0;
128 #define DBM_FLAG_ABM 64 // animated bitmap
129 #define DBM_NUM_FRAMES 63
131 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
132 | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
134 typedef struct DiskBitmapHeader {
136 ubyte dflags; // bits 0-5 anim frame num, bit 6 abm flag
137 ubyte width; // low 8 bits here, 4 more bits in wh_extra
138 ubyte height; // low 8 bits here, 4 more bits in wh_extra
139 ubyte wh_extra; // bits 0-3 width, bits 4-7 height
143 } __pack__ DiskBitmapHeader;
145 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
147 typedef struct DiskSoundHeader {
152 } __pack__ DiskSoundHeader;
155 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
156 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
159 * reads a DiskBitmapHeader structure from a CFILE
161 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
163 cfread(dbh->name, 8, 1, fp);
164 dbh->dflags = cfile_read_byte(fp);
165 dbh->width = cfile_read_byte(fp);
166 dbh->height = cfile_read_byte(fp);
167 dbh->wh_extra = cfile_read_byte(fp);
168 dbh->flags = cfile_read_byte(fp);
169 dbh->avg_color = cfile_read_byte(fp);
170 dbh->offset = cfile_read_int(fp);
174 * reads a DiskSoundHeader structure from a CFILE
176 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
178 cfread(dsh->name, 8, 1, fp);
179 dsh->length = cfile_read_int(fp);
180 dsh->data_length = cfile_read_int(fp);
181 dsh->offset = cfile_read_int(fp);
183 #endif // FAST_FILE_IO
186 * reads a descent 1 DiskBitmapHeader structure from a CFILE
188 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
190 cfread(dbh->name, 8, 1, fp);
191 dbh->dflags = cfile_read_byte(fp);
192 dbh->width = cfile_read_byte(fp);
193 dbh->height = cfile_read_byte(fp);
195 dbh->flags = cfile_read_byte(fp);
196 dbh->avg_color = cfile_read_byte(fp);
197 dbh->offset = cfile_read_int(fp);
203 extern short cd_VRefNum;
204 extern void ConcatPStr(StringPtr dst, StringPtr src);
205 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
206 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
209 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
212 void piggy_write_pigfile(char *filename);
213 static void write_int(int i,FILE *file);
216 void swap_0_255(grs_bitmap *bmp)
220 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
221 if(bmp->bm_data[i] == 0)
222 bmp->bm_data[i] = 255;
223 else if (bmp->bm_data[i] == 255)
228 char* piggy_game_bitmap_name(grs_bitmap *bmp)
230 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
232 int i = (int)(bmp - GameBitmaps); // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
233 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
234 return AllBitmaps[i].name;
239 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
242 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
244 temp.index = Num_bitmap_files;
248 if ( FindArg("-macdata") )
251 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
252 Num_bitmap_files_new++;
255 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
256 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
257 //GameBitmaps[Num_bitmap_files] = *bmp;
259 GameBitmapOffset[Num_bitmap_files] = 0;
260 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
267 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
271 Assert( Num_sound_files < MAX_SOUND_FILES );
273 strncpy( AllSounds[Num_sound_files].name, name, 12 );
274 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
275 GameSounds[Num_sound_files] = *snd;
277 SoundOffset[Num_sound_files] = 0;
283 Num_sound_files_new++;
289 bitmap_index piggy_find_bitmap( char * name )
297 if ((t=strchr(name,'#'))!=NULL)
300 for (i=0;i<Num_aliases;i++)
301 if (stricmp(name,alias_list[i].alias_name)==0) {
302 if (t) { //extra stuff for ABMs
303 static char temp[FILENAME_LEN];
304 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
310 name=alias_list[i].file_name;
317 i = hashtable_search( &AllBitmapsNames, name );
326 int piggy_find_sound( char * name )
330 i = hashtable_search( &AllDigiSndNames, name );
338 CFILE * Piggy_fp = NULL;
340 #define FILENAME_LEN 13
342 char Current_pigfile[FILENAME_LEN] = "";
344 void piggy_close_file()
349 Current_pigfile[0] = 0;
353 int Pigfile_initialized=0;
355 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
356 #define PIGFILE_VERSION 2
359 //initialize a pigfile, reading headers
360 //returns the size of all the bitmap data
361 void piggy_init_pigfile(char *filename)
365 char temp_name_read[16];
366 DiskBitmapHeader bmh;
367 int header_size, N_bitmaps, data_size, data_start;
369 piggy_close_file(); //close old pig if still open
371 //rename pigfile for shareware
372 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
373 filename = DEFAULT_PIGFILE_SHAREWARE;
375 Piggy_fp = cfopen( filename, "rb" );
377 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
378 if (Piggy_fp == NULL)
380 Error("Cannot load required file <%s>",name);
382 #endif // end of if def shareware
386 return; //if editor, ok to not have pig, because we'll build one
388 Piggy_fp = cfopen(filename, "rb");
392 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
393 int pig_id,pig_version;
395 pig_id = cfile_read_int(Piggy_fp);
396 pig_version = cfile_read_int(Piggy_fp);
397 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
398 cfclose(Piggy_fp); //out of date pig
399 Piggy_fp = NULL; //..so pretend it's not here
406 return; //if editor, ok to not have pig, because we'll build one
408 Error("Cannot load required file <%s>",filename);
412 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
414 N_bitmaps = cfile_read_int(Piggy_fp);
416 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
418 data_start = header_size + cftell(Piggy_fp);
420 data_size = cfilelength(Piggy_fp) - data_start;
422 Num_bitmap_files = 1;
424 for (i=0; i<N_bitmaps; i++ )
427 grs_bitmap *bm = &GameBitmaps[i + 1];
429 DiskBitmapHeader_read(&bmh, Piggy_fp);
430 memcpy( temp_name_read, bmh.name, 8 );
431 temp_name_read[8] = 0;
432 if ( bmh.dflags & DBM_FLAG_ABM )
433 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
435 strcpy( temp_name, temp_name_read );
436 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
437 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
438 bm->bm_flags = BM_FLAG_PAGED_OUT;
439 bm->avg_color = bmh.avg_color;
441 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
443 GameBitmapOffset[i+1] = bmh.offset + data_start;
444 Assert( (i+1) == Num_bitmap_files );
445 piggy_register_bitmap(bm, temp_name, 1);
449 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
450 Assert( Piggy_bitmap_cache_size > 0 );
452 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
454 if (piggy_low_memory)
455 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
458 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
459 if ( BitmapBits == NULL )
460 Error( "Not enough memory to load bitmaps\n" );
461 Piggy_bitmap_cache_data = BitmapBits;
462 Piggy_bitmap_cache_next = 0;
464 #if defined(MACINTOSH) && defined(SHAREWARE)
465 // load_exit_models();
468 Pigfile_initialized=1;
471 #define FILENAME_LEN 13
472 #define MAX_BITMAPS_PER_BRUSH 30
474 extern int compute_average_pixel(grs_bitmap *new);
475 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
477 ubyte *Bitmap_replacement_data = NULL;
479 //reads in a new pigfile (for new palette)
480 //returns the size of all the bitmap data
481 void piggy_new_pigfile(char *pigname)
485 char temp_name_read[16];
486 DiskBitmapHeader bmh;
487 int header_size, N_bitmaps, data_size, data_start;
488 int must_rewrite_pig = 0;
492 //rename pigfile for shareware
493 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
494 pigname = DEFAULT_PIGFILE_SHAREWARE;
496 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
497 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
500 if (!Pigfile_initialized) { //have we ever opened a pigfile?
501 piggy_init_pigfile(pigname); //..no, so do initialization stuff
505 piggy_close_file(); //close old pig if still open
507 Piggy_bitmap_cache_next = 0; //free up cache
509 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
511 Piggy_fp = cfopen( pigname, "rb" );
513 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
514 if (Piggy_fp == NULL)
516 Error("Cannot load required file <%s>",name);
518 #endif // end of if def shareware
522 Piggy_fp = cfopen(pigname, "rb");
525 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
526 int pig_id,pig_version;
528 pig_id = cfile_read_int(Piggy_fp);
529 pig_version = cfile_read_int(Piggy_fp);
530 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
531 cfclose(Piggy_fp); //out of date pig
532 Piggy_fp = NULL; //..so pretend it's not here
538 Error("Cannot open correct version of <%s>", pigname);
543 N_bitmaps = cfile_read_int(Piggy_fp);
545 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
547 data_start = header_size + cftell(Piggy_fp);
549 data_size = cfilelength(Piggy_fp) - data_start;
551 for (i=1; i<=N_bitmaps; i++ )
553 grs_bitmap *bm = &GameBitmaps[i];
556 DiskBitmapHeader_read(&bmh, Piggy_fp);
557 memcpy( temp_name_read, bmh.name, 8 );
558 temp_name_read[8] = 0;
560 if ( bmh.dflags & DBM_FLAG_ABM )
561 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
563 strcpy( temp_name, temp_name_read );
565 //Make sure name matches
566 if (strcmp(temp_name,AllBitmaps[i].name)) {
567 //Int3(); //this pig is out of date. Delete it
571 strcpy(AllBitmaps[i].name,temp_name);
573 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
574 gr_set_bitmap_data(bm, NULL); // free ogl texture
575 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
576 bm->bm_flags = BM_FLAG_PAGED_OUT;
577 bm->avg_color = bmh.avg_color;
579 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
581 GameBitmapOffset[i] = bmh.offset + data_start;
585 N_bitmaps = 0; //no pigfile, so no bitmaps
589 Assert(N_bitmaps == Num_bitmap_files-1);
593 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
596 //re-read the bitmaps that aren't in this pig
598 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
601 p = strchr(AllBitmaps[i].name,'#');
603 if (p) { // this is an ABM == animated bitmap
604 char abmname[FILENAME_LEN];
606 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
607 int iff_error; //reference parm to avoid warning message
609 char basename[FILENAME_LEN];
612 strcpy(basename,AllBitmaps[i].name);
613 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
615 sprintf( abmname, "%s.abm", basename );
617 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
619 if (iff_error != IFF_NO_ERROR) {
620 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
621 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
624 for (fnum=0;fnum<nframes; fnum++) {
628 sprintf( tempname, "%s#%d", basename, fnum );
630 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
631 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
632 //above makes assumption that supertransparent color is 254
634 if ( iff_has_transparency )
635 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
637 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
639 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
642 if ( FindArg("-macdata") )
643 swap_0_255( bm[fnum] );
645 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
647 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
648 size = *((int *) bm[fnum]->bm_data);
650 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
652 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
653 d_free(bm[fnum]->bm_data);
654 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
655 Piggy_bitmap_cache_next += size;
657 GameBitmaps[i+fnum] = *bm[fnum];
659 // -- mprintf( (0, "U" ));
663 i += nframes-1; //filled in multiple bitmaps
665 else { //this is a BBM
670 char bbmname[FILENAME_LEN];
673 MALLOC( new, grs_bitmap, 1 );
675 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
676 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
679 if (iff_error != IFF_NO_ERROR) {
680 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
681 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
684 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
685 //above makes assumption that supertransparent color is 254
687 if ( iff_has_transparency )
688 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
690 gr_remap_bitmap_good( new, newpal, -1, SuperX );
692 new->avg_color = compute_average_pixel(new);
695 if ( FindArg("-macdata") )
698 if ( !BigPig ) gr_bitmap_rle_compress( new );
700 if (new->bm_flags & BM_FLAG_RLE)
701 size = *((int *) new->bm_data);
703 size = new->bm_w * new->bm_h;
705 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
706 d_free(new->bm_data);
707 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
708 Piggy_bitmap_cache_next += size;
710 GameBitmaps[i] = *new;
714 // -- mprintf( (0, "U" ));
718 //@@Dont' do these things which are done when writing
719 //@@for (i=0; i < Num_bitmap_files; i++ ) {
720 //@@ bitmap_index bi;
722 //@@ PIGGY_PAGE_IN( bi );
725 //@@piggy_close_file();
727 piggy_write_pigfile(pigname);
729 Current_pigfile[0] = 0; //say no pig, to force reload
731 piggy_new_pigfile(pigname); //read in just-generated pig
735 #endif //ifdef EDITOR
739 ubyte bogus_data[64*64];
740 ubyte bogus_bitmap_initialized=0;
741 digi_sound bogus_sound;
743 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
744 #define HAMFILE_VERSION 3
745 //version 1 -> 2: save marker_model_num
746 //version 2 -> 3: removed sound files
748 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
749 #define SNDFILE_VERSION 1
753 CFILE * ham_fp = NULL;
755 int sound_offset = 0;
757 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
759 if (ham_fp == NULL) {
760 Must_write_hamfile = 1;
764 //make sure ham is valid type file & is up-to-date
765 ham_id = cfile_read_int(ham_fp);
766 Piggy_hamfile_version = cfile_read_int(ham_fp);
767 if (ham_id != HAMFILE_ID)
768 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
770 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
771 Must_write_hamfile = 1;
772 cfclose(ham_fp); //out of date ham
777 if (Piggy_hamfile_version < 3) // hamfile contains sound info
778 sound_offset = cfile_read_int(ham_fp);
785 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
787 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
788 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
789 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
794 if (Piggy_hamfile_version < 3) {
799 DiskSoundHeader sndh;
800 digi_sound temp_sound;
801 char temp_name_read[16];
804 cfseek(ham_fp, sound_offset, SEEK_SET);
805 N_sounds = cfile_read_int(ham_fp);
807 sound_start = cftell(ham_fp);
809 header_size = N_sounds * sizeof(DiskSoundHeader);
813 for (i=0; i<N_sounds; i++ ) {
814 DiskSoundHeader_read(&sndh, ham_fp);
815 temp_sound.length = sndh.length;
816 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
817 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
818 memcpy( temp_name_read, sndh.name, 8 );
819 temp_name_read[8] = 0;
820 piggy_register_sound( &temp_sound, temp_name_read, 1 );
822 if (piggy_is_needed(i))
823 #endif // note link to if.
824 sbytes += sndh.length;
825 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
828 SoundBits = d_malloc( sbytes + 16 );
829 if ( SoundBits == NULL )
830 Error( "Not enough memory to load sounds\n" );
832 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
834 // piggy_read_sounds(ham_fp);
846 CFILE * snd_fp = NULL;
847 int snd_id,snd_version;
852 DiskSoundHeader sndh;
853 digi_sound temp_sound;
854 char temp_name_read[16];
857 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
862 //make sure soundfile is valid type file & is up-to-date
863 snd_id = cfile_read_int(snd_fp);
864 snd_version = cfile_read_int(snd_fp);
865 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
866 cfclose(snd_fp); //out of date sound file
870 N_sounds = cfile_read_int(snd_fp);
872 sound_start = cftell(snd_fp);
873 size = cfilelength(snd_fp) - sound_start;
875 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
877 header_size = N_sounds*sizeof(DiskSoundHeader);
881 for (i=0; i<N_sounds; i++ ) {
882 DiskSoundHeader_read(&sndh, snd_fp);
883 //size -= sizeof(DiskSoundHeader);
884 temp_sound.length = sndh.length;
885 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
886 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
887 memcpy( temp_name_read, sndh.name, 8 );
888 temp_name_read[8] = 0;
889 piggy_register_sound( &temp_sound, temp_name_read, 1 );
891 if (piggy_is_needed(i))
892 #endif // note link to if.
893 sbytes += sndh.length;
894 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
897 SoundBits = d_malloc( sbytes + 16 );
898 if ( SoundBits == NULL )
899 Error( "Not enough memory to load sounds\n" );
901 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
903 // piggy_read_sounds(snd_fp);
912 int ham_ok=0,snd_ok=0;
915 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
916 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
918 for (i=0; i<MAX_SOUND_FILES; i++ ) {
919 GameSounds[i].length = 0;
920 GameSounds[i].data = NULL;
924 for (i=0; i<MAX_BITMAP_FILES; i++ )
925 GameBitmapXlat[i] = i;
927 if ( !bogus_bitmap_initialized ) {
931 bogus_bitmap_initialized = 1;
932 c = gr_find_closest_color( 0, 0, 63 );
933 for (i=0; i<4096; i++ ) bogus_data[i] = c;
934 c = gr_find_closest_color( 63, 0, 0 );
935 // Make a big red X !
936 for (i=0; i<64; i++ ) {
937 bogus_data[i*64+i] = c;
938 bogus_data[i*64+(63-i)] = c;
940 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
941 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
942 bogus_sound.length = 64*64;
943 bogus_sound.data = bogus_data;
944 GameBitmapOffset[0] = 0;
947 if ( FindArg( "-bigpig" ))
950 if ( FindArg( "-lowmem" ))
951 piggy_low_memory = 1;
953 if ( FindArg( "-nolowmem" ))
954 piggy_low_memory = 0;
956 if (piggy_low_memory)
959 gr_set_curfont( SMALL_FONT );
960 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
961 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
963 #if 1 //def EDITOR //need for d1 mission briefings
964 piggy_init_pigfile(DEFAULT_PIGFILE);
967 snd_ok = ham_ok = read_hamfile();
969 if (Piggy_hamfile_version >= 3)
970 snd_ok = read_sndfile();
974 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
975 return (ham_ok && snd_ok); //read ok
978 int piggy_is_needed(int soundnum)
982 if ( !digi_lomem ) return 1;
984 for (i=0; i<MAX_SOUNDS; i++ ) {
985 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
992 void piggy_read_sounds(void)
1001 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1006 for (i=0; i<Num_sound_files; i++ ) {
1007 digi_sound *snd = &GameSounds[i];
1009 if ( SoundOffset[i] > 0 ) {
1010 if ( piggy_is_needed(i) ) {
1011 cfseek( fp, SoundOffset[i], SEEK_SET );
1013 // Read in the sound data!!!
1016 sbytes += snd->length;
1017 cfread( snd->data, snd->length, 1, fp );
1020 snd->data = (ubyte *) -1;
1026 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1031 extern int descent_critical_error;
1032 extern unsigned descent_critical_deverror;
1033 extern unsigned descent_critical_errcode;
1035 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1036 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1037 "Read fault", "General Failure" };
1039 void piggy_critical_error()
1041 grs_canvas * save_canv;
1042 grs_font * save_font;
1044 save_canv = grd_curcanv;
1045 save_font = grd_curcanv->cv_font;
1046 gr_palette_load( gr_palette );
1047 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1050 gr_set_current_canvas(save_canv);
1051 grd_curcanv->cv_font = save_font;
1054 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1056 void piggy_bitmap_page_in( bitmap_index bitmap )
1065 Assert( i < MAX_BITMAP_FILES );
1066 Assert( i < Num_bitmap_files );
1067 Assert( Piggy_bitmap_cache_size > 0 );
1069 if ( i < 1 ) return;
1070 if ( i >= MAX_BITMAP_FILES ) return;
1071 if ( i >= Num_bitmap_files ) return;
1073 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1075 if ( piggy_low_memory ) {
1077 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1080 bmp = &GameBitmaps[i];
1082 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1086 descent_critical_error = 0;
1087 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1088 if ( descent_critical_error ) {
1089 piggy_critical_error();
1093 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1095 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1096 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1097 descent_critical_error = 0;
1098 zsize = cfile_read_int(Piggy_fp);
1099 if ( descent_critical_error ) {
1100 piggy_critical_error();
1104 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1105 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1106 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1108 piggy_bitmap_page_out_all();
1111 descent_critical_error = 0;
1112 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1113 if ( descent_critical_error ) {
1114 piggy_critical_error();
1117 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1118 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1123 if (!FindArg("-macdata"))
1125 // otherwise, fall through...
1126 case MAC_ALIEN1_PIGSIZE:
1127 case MAC_ALIEN2_PIGSIZE:
1128 case MAC_FIRE_PIGSIZE:
1129 case MAC_GROUPA_PIGSIZE:
1130 case MAC_ICE_PIGSIZE:
1131 case MAC_WATER_PIGSIZE:
1132 rle_swap_0_255( bmp );
1133 memcpy(&zsize, bmp->bm_data, 4);
1138 Piggy_bitmap_cache_next += zsize;
1139 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1141 piggy_bitmap_page_out_all();
1146 int pigsize = cfilelength(Piggy_fp);
1147 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1148 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1149 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1150 piggy_bitmap_page_out_all();
1153 descent_critical_error = 0;
1154 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1155 if ( descent_critical_error ) {
1156 piggy_critical_error();
1159 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1160 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1165 if (!FindArg("-macdata"))
1167 // otherwise, fall through...
1168 case MAC_ALIEN1_PIGSIZE:
1169 case MAC_ALIEN2_PIGSIZE:
1170 case MAC_FIRE_PIGSIZE:
1171 case MAC_GROUPA_PIGSIZE:
1172 case MAC_ICE_PIGSIZE:
1173 case MAC_WATER_PIGSIZE:
1180 //@@if ( bmp->bm_selector ) {
1181 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1182 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1183 //@@ Error( "Error modifying selector base in piggy.c\n" );
1190 if ( piggy_low_memory ) {
1192 GameBitmaps[org_i] = GameBitmaps[i];
1195 //@@Removed from John's code:
1197 //@@ if ( bmp->bm_selector ) {
1198 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1199 //@@ Error( "Error modifying selector base in piggy.c\n" );
1205 void piggy_bitmap_page_out_all()
1209 Piggy_bitmap_cache_next = 0;
1211 piggy_page_flushed++;
1216 for (i=0; i<Num_bitmap_files; i++ ) {
1217 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1218 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1219 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1223 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1226 void piggy_load_level_data()
1228 piggy_bitmap_page_out_all();
1234 void piggy_write_pigfile(char *filename)
1237 int bitmap_data_start, data_offset;
1238 DiskBitmapHeader bmh;
1240 char subst_name[32];
1243 char tname[FILENAME_LEN];
1245 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1246 for (i=0; i < Num_bitmap_files; i++ ) {
1249 PIGGY_PAGE_IN( bi );
1251 // -- mprintf( (0, "\n" ));
1255 // -- mprintf( (0, "Creating %s...",filename ));
1257 pig_fp = fopen( filename, "wb" ); //open PIG file
1258 Assert( pig_fp!=NULL );
1260 write_int(PIGFILE_ID,pig_fp);
1261 write_int(PIGFILE_VERSION,pig_fp);
1264 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1267 bitmap_data_start = ftell(pig_fp);
1268 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1269 data_offset = bitmap_data_start;
1271 change_filename_extension(tname,filename,"lst");
1272 fp1 = fopen( tname, "wt" );
1273 change_filename_extension(tname,filename,"all");
1274 fp2 = fopen( tname, "wt" );
1276 for (i=1; i < Num_bitmap_files; i++ ) {
1282 p = strchr(AllBitmaps[i].name, '#');
1283 if (p) { // this is an ABM == animated bitmap
1289 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1290 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1291 Assert( n <= DBM_NUM_FRAMES );
1292 bmh.dflags = DBM_FLAG_ABM + n;
1296 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1297 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1301 bmp = &GameBitmaps[i];
1303 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1306 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1307 org_offset = ftell(pig_fp);
1308 bmh.offset = data_offset - bitmap_data_start;
1309 fseek( pig_fp, data_offset, SEEK_SET );
1311 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1312 size = (int *)bmp->bm_data;
1313 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1314 data_offset += *size;
1316 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1318 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1319 data_offset += bmp->bm_rowsize * bmp->bm_h;
1321 fprintf( fp1, ".\n" );
1323 fseek( pig_fp, org_offset, SEEK_SET );
1324 Assert( GameBitmaps[i].bm_w < 4096 );
1325 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1326 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1327 Assert( GameBitmaps[i].bm_h < 4096 );
1328 bmh.height = GameBitmaps[i].bm_h;
1329 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1330 bmh.flags = GameBitmaps[i].bm_flags;
1331 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1332 bitmap_index other_bitmap;
1333 other_bitmap = piggy_find_bitmap( subst_name );
1334 GameBitmapXlat[i] = other_bitmap.index;
1335 bmh.flags |= BM_FLAG_PAGED_OUT;
1336 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1337 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1339 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1341 bmh.avg_color=GameBitmaps[i].avg_color;
1342 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1347 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1348 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1355 static void write_int(int i,FILE *file)
1357 if (fwrite( &i, sizeof(i), 1, file) != 1)
1358 Error( "Error reading int in gamesave.c" );
1362 void piggy_dump_all()
1366 int org_offset,data_offset=0;
1367 DiskSoundHeader sndh;
1368 int sound_data_start=0;
1371 #ifdef NO_DUMP_SOUNDS
1372 Num_sound_files = 0;
1373 Num_sound_files_new = 0;
1376 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1379 fp1 = fopen( "ham.lst", "wt" );
1380 fp2 = fopen( "ham.all", "wt" );
1382 if (Must_write_hamfile || Num_bitmap_files_new) {
1384 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1386 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1387 Assert( ham_fp!=NULL );
1389 write_int(HAMFILE_ID,ham_fp);
1390 write_int(HAMFILE_VERSION,ham_fp);
1392 bm_write_all(ham_fp);
1393 xlat_offset = ftell(ham_fp);
1394 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1397 if (Num_bitmap_files_new)
1398 piggy_write_pigfile(DEFAULT_PIGFILE);
1400 //free up memeory used by new bitmaps
1401 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1402 d_free(GameBitmaps[i].bm_data);
1404 //next thing must be done after pig written
1405 fseek( ham_fp, xlat_offset, SEEK_SET );
1406 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1409 mprintf( (0, "\n" ));
1412 if (Num_sound_files_new) {
1414 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1415 // Now dump sound file
1416 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1417 Assert( ham_fp!=NULL );
1419 write_int(SNDFILE_ID,ham_fp);
1420 write_int(SNDFILE_VERSION,ham_fp);
1422 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1424 mprintf( (0, "\nDumping sounds..." ));
1426 sound_data_start = ftell(ham_fp);
1427 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1428 data_offset = sound_data_start;
1430 for (i=0; i < Num_sound_files; i++ ) {
1433 snd = &GameSounds[i];
1434 strcpy( sndh.name, AllSounds[i].name );
1435 sndh.length = GameSounds[i].length;
1436 sndh.offset = data_offset - sound_data_start;
1438 org_offset = ftell(ham_fp);
1439 fseek( ham_fp, data_offset, SEEK_SET );
1441 sndh.data_length = GameSounds[i].length;
1442 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1443 data_offset += snd->length;
1444 fseek( ham_fp, org_offset, SEEK_SET );
1445 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1447 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1448 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1452 mprintf( (0, "\n" ));
1455 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1456 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1457 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1462 // Never allow the game to run after building ham.
1476 d_free( SoundBits );
1478 hashtable_free( &AllBitmapsNames );
1479 hashtable_free( &AllDigiSndNames );
1483 int piggy_does_bitmap_exist_slow( char * name )
1487 for (i=0; i<Num_bitmap_files; i++ ) {
1488 if ( !strcmp( AllBitmaps[i].name, name) )
1495 #define NUM_GAUGE_BITMAPS 23
1496 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1497 "gauge01", "gauge01b",
1498 "gauge02", "gauge02b",
1499 "gauge06", "gauge06b",
1500 "targ01", "targ01b",
1501 "targ02", "targ02b",
1502 "targ03", "targ03b",
1503 "targ04", "targ04b",
1504 "targ05", "targ05b",
1505 "targ06", "targ06b",
1506 "gauge18", "gauge18b",
1512 int piggy_is_gauge_bitmap( char * base_name )
1515 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1516 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1523 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1527 char base_name[ 16 ];
1529 strcpy( subst_name, name );
1530 p = strchr( subst_name, '#' );
1532 frame = atoi( &p[1] );
1534 strcpy( base_name, subst_name );
1535 if ( !piggy_is_gauge_bitmap( base_name )) {
1536 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1537 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1539 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1545 strcpy( subst_name, name );
1552 * Functions for loading replacement textures
1553 * 1) From .pog files
1554 * 2) From descent.pig (for loading d1 levels)
1557 extern char last_palette_loaded_pig[];
1559 void free_bitmap_replacements()
1561 if (Bitmap_replacement_data) {
1562 d_free(Bitmap_replacement_data);
1563 Bitmap_replacement_data = NULL;
1567 void load_bitmap_replacements(char *level_name)
1569 char ifile_name[FILENAME_LEN];
1573 //first, free up data allocated for old bitmaps
1574 free_bitmap_replacements();
1576 change_filename_extension(ifile_name, level_name, ".POG" );
1578 ifile = cfopen(ifile_name,"rb");
1581 int id,version,n_bitmaps;
1582 int bitmap_data_size;
1585 id = cfile_read_int(ifile);
1586 version = cfile_read_int(ifile);
1588 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1593 n_bitmaps = cfile_read_int(ifile);
1595 MALLOC( indices, ushort, n_bitmaps );
1597 for (i = 0; i < n_bitmaps; i++)
1598 indices[i] = cfile_read_short(ifile);
1600 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1601 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1603 for (i=0;i<n_bitmaps;i++) {
1604 DiskBitmapHeader bmh;
1605 grs_bitmap *bm = &GameBitmaps[indices[i]];
1608 DiskBitmapHeader_read(&bmh, ifile);
1610 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1611 gr_set_bitmap_data(bm, NULL); // free ogl texture
1612 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1613 bm->avg_color = bmh.avg_color;
1614 bm->bm_data = (ubyte *) bmh.offset;
1616 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1618 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1621 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1623 for (i = 0; i < n_bitmaps; i++)
1625 grs_bitmap *bm = &GameBitmaps[indices[i]];
1626 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1633 last_palette_loaded_pig[0]= 0; //force pig re-load
1635 texmerge_flush(); //for re-merging with new textures
1638 atexit(free_bitmap_replacements);
1641 /* calculate table to translate d1 bitmaps to current palette,
1642 * return -1 on error
1644 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1647 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1648 if (!palette_file || cfilelength(palette_file) != 9472)
1650 cfread( d1_palette, 256, 3, palette_file);
1651 cfclose( palette_file );
1652 build_colormap_good( d1_palette, colormap, freq );
1653 // don't change transparencies:
1654 colormap[254] = 254;
1655 colormap[255] = 255;
1659 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1660 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1661 CFILE *d1_Piggy_fp, /* read from this file */
1662 int bitmap_data_start, /* specific to file */
1663 DiskBitmapHeader *bmh, /* header info for bitmap */
1664 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1665 ubyte *d1_palette, /* what palette the bitmap has */
1666 ubyte *colormap) /* how to translate bitmap's colors */
1668 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1672 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1673 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1674 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1675 bitmap->avg_color = bmh->avg_color;
1676 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1678 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1679 if (bmh->flags & BM_FLAG_RLE) {
1680 zsize = cfile_read_int(d1_Piggy_fp);
1681 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1683 zsize = bitmap->bm_h * bitmap->bm_w;
1686 data = *next_bitmap;
1687 *next_bitmap += zsize;
1689 data = d_malloc(zsize + JUST_IN_CASE);
1693 cfread(data, 1, zsize, d1_Piggy_fp);
1694 gr_set_bitmap_data(bitmap, data);
1696 case D1_MAC_PIGSIZE:
1697 case D1_MAC_SHARE_PIGSIZE:
1698 if (bmh->flags & BM_FLAG_RLE)
1699 rle_swap_0_255(bitmap);
1703 if (bmh->flags & BM_FLAG_RLE)
1704 rle_remap(bitmap, colormap);
1706 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1707 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1709 memcpy(&new_size, bitmap->bm_data, 4);
1711 *next_bitmap += new_size - zsize;
1713 Assert( zsize + JUST_IN_CASE >= new_size );
1714 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1715 Assert(bitmap->bm_data);
1720 #define D1_MAX_TEXTURES 800
1721 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1723 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1724 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1725 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1727 short *d1_tmap_nums = NULL;
1729 void free_d1_tmap_nums() {
1731 d_free(d1_tmap_nums);
1732 d1_tmap_nums = NULL;
1736 void bm_read_d1_tmap_nums(CFILE *d1pig)
1740 free_d1_tmap_nums();
1741 cfseek(d1pig, 8, SEEK_SET);
1742 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1743 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1744 d1_tmap_nums[i] = -1;
1745 for (i = 0; i < D1_MAX_TEXTURES; i++) {
1746 d1_index = cfile_read_short(d1pig);
1747 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1748 d1_tmap_nums[d1_index] = i;
1750 atexit(free_d1_tmap_nums);
1753 void remove_char( char * s, char c )
1760 #define REMOVE_EOL(s) remove_char((s),'\n')
1761 #define REMOVE_COMMENTS(s) remove_char((s),';')
1762 #define REMOVE_DOTS(s) remove_char((s),'.')
1763 char *space = { " \t" };
1764 char *equal_space = { " \t=" };
1766 // this function is at the same position in the d1 shareware piggy loading
1767 // algorithm as bm_load_sub in main/bmread.c
1768 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
1770 DiskBitmapHeader bmh;
1771 if (strchr (filename, '.'))
1772 *strchr (filename, '.') = '\0'; // remove extension
1773 cfseek (d1_pig, 0, SEEK_SET);
1774 N_bitmaps = cfile_read_int (d1_pig);
1775 cfseek (d1_pig, 8, SEEK_SET);
1776 for (i = 1; i <= N_bitmaps; i++) {
1777 DiskBitmapHeader_d1_read(&bmh, d1_pig);
1778 if (!strnicmp(bmh.name, filename, 8))
1784 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1785 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1787 #define LINEBUF_SIZE 600
1788 int reading_textures = 0;
1789 short texture_count = 0;
1790 char inputline[LINEBUF_SIZE];
1792 int bitmaps_tbl_is_binary = 0;
1795 bitmaps = cfopen ("bitmaps.tbl", "rb");
1797 bitmaps = cfopen ("bitmaps.bin", "rb");
1798 bitmaps_tbl_is_binary = 1;
1802 Warning ("Could not find bitmaps.* for reading d1 textures");
1806 free_d1_tmap_nums();
1807 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1808 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1809 d1_tmap_nums[i] = -1;
1810 atexit(free_d1_tmap_nums);
1812 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1815 if (bitmaps_tbl_is_binary)
1816 decode_text_line((inputline));
1818 while (inputline[(i = (int)strlen(inputline)) - 2] == '\\')
1819 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
1820 REMOVE_EOL(inputline);
1821 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
1822 if (strlen(inputline) == LINEBUF_SIZE-1) {
1823 Warning("Possible line truncation in BITMAPS.TBL");
1826 arg = strtok( inputline, space );
1827 if (arg && arg[0] == '@') {
1829 //Registered_only = 1;
1832 while (arg != NULL) {
1834 reading_textures = 0; // default
1835 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
1836 reading_textures = 1;
1837 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
1838 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
1840 else // not a special token, must be a bitmap!
1841 if (reading_textures) {
1842 while (*arg == '\t' || *arg == ' ')
1843 arg++;//remove unwanted blanks
1846 if (d1_tmap_num_unique(texture_count)) {
1847 int d1_index = get_d1_bm_index(arg, d1_pig);
1848 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
1849 d1_tmap_nums[d1_index] = texture_count;
1850 //int d2_index = d2_index_for_d1_index(d1_index);
1853 Assert (texture_count < D1_MAX_TEXTURES);
1857 arg = strtok (NULL, equal_space);
1863 /* If the given d1_index is the index of a bitmap we have to load
1864 * (because it is unique to descent 1), then returns the d2_index that
1865 * the given d1_index replaces.
1866 * Returns -1 if the given d1_index is not unique to descent 1.
1868 short d2_index_for_d1_index(short d1_index)
1870 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1871 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
1872 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
1875 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1878 #define D1_BITMAPS_SIZE 300000
1879 void load_d1_bitmap_replacements()
1881 CFILE * d1_Piggy_fp;
1882 DiskBitmapHeader bmh;
1883 int pig_data_start, bitmap_header_start, bitmap_data_start;
1885 short d1_index, d2_index;
1887 ubyte colormap[256];
1888 ubyte d1_palette[256*3];
1892 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1894 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1896 Warning(D1_PIG_LOAD_FAILED);
1900 //first, free up data allocated for old bitmaps
1901 free_bitmap_replacements();
1903 if (get_d1_colormap( d1_palette, colormap ) != 0)
1904 Warning("Could not load descent 1 color palette");
1906 pigsize = cfilelength(d1_Piggy_fp);
1908 case D1_SHARE_BIG_PIGSIZE:
1909 case D1_SHARE_10_PIGSIZE:
1910 case D1_SHARE_PIGSIZE:
1911 case D1_10_BIG_PIGSIZE:
1914 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
1915 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
1918 Warning("Unknown size for " D1_PIGFILE);
1922 case D1_OEM_PIGSIZE:
1923 case D1_MAC_PIGSIZE:
1924 case D1_MAC_SHARE_PIGSIZE:
1925 pig_data_start = cfile_read_int(d1_Piggy_fp );
1926 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
1927 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
1931 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1932 N_bitmaps = cfile_read_int(d1_Piggy_fp);
1934 int N_sounds = cfile_read_int(d1_Piggy_fp);
1935 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
1936 + N_sounds * sizeof(DiskSoundHeader);
1937 bitmap_header_start = pig_data_start + 2 * sizeof(int);
1938 bitmap_data_start = bitmap_header_start + header_size;
1941 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1942 if (!Bitmap_replacement_data) {
1943 Warning(D1_PIG_LOAD_FAILED);
1946 atexit(free_bitmap_replacements);
1948 next_bitmap = Bitmap_replacement_data;
1950 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
1951 d2_index = d2_index_for_d1_index(d1_index);
1952 // only change bitmaps which are unique to d1
1953 if (d2_index != -1) {
1954 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
1955 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
1957 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
1958 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
1959 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
1960 GameBitmapFlags[d2_index] = bmh.flags;
1962 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
1963 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
1964 int i, len = (int)(p - AllBitmaps[d2_index].name);
1965 for (i = 0; i < Num_bitmap_files; i++)
1966 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
1968 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
1969 GameBitmaps[i] = GameBitmaps[d2_index];
1970 GameBitmapOffset[i] = 0;
1971 GameBitmapFlags[i] = bmh.flags;
1977 cfclose(d1_Piggy_fp);
1979 last_palette_loaded_pig[0]= 0; //force pig re-load
1981 texmerge_flush(); //for re-merging with new textures
1985 extern int extra_bitmap_num;
1988 * Find and load the named bitmap from descent.pig
1989 * similar to read_extra_bitmap_iff
1991 bitmap_index read_extra_bitmap_d1_pig(char *name)
1993 bitmap_index bitmap_num;
1994 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
1996 bitmap_num.index = 0;
2000 DiskBitmapHeader bmh;
2001 int pig_data_start, bitmap_header_start, bitmap_data_start;
2003 ubyte colormap[256];
2004 ubyte d1_palette[256*3];
2007 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2011 Warning(D1_PIG_LOAD_FAILED);
2015 if (get_d1_colormap( d1_palette, colormap ) != 0)
2016 Warning("Could not load descent 1 color palette");
2018 pigsize = cfilelength(d1_Piggy_fp);
2020 case D1_SHARE_BIG_PIGSIZE:
2021 case D1_SHARE_10_PIGSIZE:
2022 case D1_SHARE_PIGSIZE:
2023 case D1_10_BIG_PIGSIZE:
2028 Warning("Unknown size for " D1_PIGFILE);
2032 case D1_OEM_PIGSIZE:
2033 case D1_MAC_PIGSIZE:
2034 case D1_MAC_SHARE_PIGSIZE:
2035 pig_data_start = cfile_read_int(d1_Piggy_fp );
2040 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2041 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2043 int N_sounds = cfile_read_int(d1_Piggy_fp);
2044 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2045 + N_sounds * sizeof(DiskSoundHeader);
2046 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2047 bitmap_data_start = bitmap_header_start + header_size;
2050 for (i = 1; i <= N_bitmaps; i++)
2052 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2053 if (!strnicmp(bmh.name, name, 8))
2057 if (strnicmp(bmh.name, name, 8))
2059 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2063 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2065 cfclose(d1_Piggy_fp);
2068 new->avg_color = 0; //compute_average_pixel(new);
2070 bitmap_num.index = extra_bitmap_num;
2072 GameBitmaps[extra_bitmap_num++] = *new;
2078 #ifndef FAST_FILE_IO
2080 * reads a bitmap_index structure from a CFILE
2082 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2084 bi->index = cfile_read_short(fp);
2088 * reads n bitmap_index structs from a CFILE
2090 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2094 for (i = 0; i < n; i++)
2095 bi[i].index = cfile_read_short(fp);
2098 #endif // FAST_FILE_IO