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, "%.8s#%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, "%.8s#%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, "%.8s.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, "%.8s.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 *)(size_t)(sndh.offset + header_size + sound_start);
817 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
818 memcpy( temp_name_read, sndh.name, 8 );
819 temp_name_read[8] = 0;
820 piggy_register_sound( &temp_sound, temp_name_read, 1 );
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 *)(size_t)(sndh.offset + header_size + sound_start);
886 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
887 memcpy( temp_name_read, sndh.name, 8 );
888 temp_name_read[8] = 0;
889 piggy_register_sound( &temp_sound, temp_name_read, 1 );
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);
911 void piggy_cmd_play(int argc, char **argv)
917 con_printf(CON_NORMAL, "Available sounds:\n");
918 for (i = 0; i < Num_sound_files; i++)
919 con_printf(CON_NORMAL, " %s\n", AllSounds[i].name);
924 i = piggy_find_sound(argv[1]);
928 digi_start_sound( i, F1_0, 0xffff/2, 0, -1, -1, -1 );
933 con_printf(CON_NORMAL, "Sound %s not found.\n", argv[1]);
939 int ham_ok=0,snd_ok=0;
942 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
943 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
945 for (i=0; i<MAX_SOUND_FILES; i++ ) {
946 GameSounds[i].length = 0;
947 GameSounds[i].data = NULL;
951 for (i=0; i<MAX_BITMAP_FILES; i++ )
952 GameBitmapXlat[i] = i;
954 if ( !bogus_bitmap_initialized ) {
958 bogus_bitmap_initialized = 1;
959 c = gr_find_closest_color( 0, 0, 63 );
960 for (i=0; i<4096; i++ ) bogus_data[i] = c;
961 c = gr_find_closest_color( 63, 0, 0 );
962 // Make a big red X !
963 for (i=0; i<64; i++ ) {
964 bogus_data[i*64+i] = c;
965 bogus_data[i*64+(63-i)] = c;
967 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
968 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
969 bogus_sound.length = 64*64;
970 bogus_sound.data = bogus_data;
971 GameBitmapOffset[0] = 0;
974 if ( FindArg( "-bigpig" ))
977 if ( FindArg( "-lowmem" ))
978 piggy_low_memory = 1;
980 if ( FindArg( "-nolowmem" ))
981 piggy_low_memory = 0;
983 if (piggy_low_memory)
986 gr_set_curfont( SMALL_FONT );
987 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
988 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
990 #if 1 //def EDITOR //need for d1 mission briefings
991 piggy_init_pigfile(DEFAULT_PIGFILE);
994 snd_ok = ham_ok = read_hamfile();
996 if (Piggy_hamfile_version >= 3)
997 snd_ok = read_sndfile();
999 cmd_addcommand("play", piggy_cmd_play, "");
1001 atexit(piggy_close);
1003 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1004 return (ham_ok && snd_ok); //read ok
1007 int piggy_is_needed(int soundnum)
1011 if ( !digi_lomem ) return 1;
1013 for (i=0; i<MAX_SOUNDS; i++ ) {
1014 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1021 void piggy_read_sounds(void)
1030 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1035 for (i=0; i<Num_sound_files; i++ ) {
1036 digi_sound *snd = &GameSounds[i];
1038 if ( SoundOffset[i] > 0 ) {
1039 if ( piggy_is_needed(i) ) {
1040 cfseek( fp, SoundOffset[i], SEEK_SET );
1042 // Read in the sound data!!!
1045 sbytes += snd->length;
1046 cfread( snd->data, snd->length, 1, fp );
1049 snd->data = (ubyte *) -1;
1055 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1060 extern int descent_critical_error;
1061 extern unsigned descent_critical_deverror;
1062 extern unsigned descent_critical_errcode;
1064 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1065 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1066 "Read fault", "General Failure" };
1068 void piggy_critical_error()
1070 grs_canvas * save_canv;
1071 grs_font * save_font;
1073 save_canv = grd_curcanv;
1074 save_font = grd_curcanv->cv_font;
1075 gr_palette_load( gr_palette );
1076 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1079 gr_set_current_canvas(save_canv);
1080 grd_curcanv->cv_font = save_font;
1083 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1085 void piggy_bitmap_page_in( bitmap_index bitmap )
1094 Assert( i < MAX_BITMAP_FILES );
1095 Assert( i < Num_bitmap_files );
1096 Assert( Piggy_bitmap_cache_size > 0 );
1098 if ( i < 1 ) return;
1099 if ( i >= MAX_BITMAP_FILES ) return;
1100 if ( i >= Num_bitmap_files ) return;
1102 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1104 if ( piggy_low_memory ) {
1106 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1109 bmp = &GameBitmaps[i];
1111 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1115 descent_critical_error = 0;
1116 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1117 if ( descent_critical_error ) {
1118 piggy_critical_error();
1122 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1124 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1125 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1126 descent_critical_error = 0;
1127 zsize = cfile_read_int(Piggy_fp);
1128 if ( descent_critical_error ) {
1129 piggy_critical_error();
1133 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1134 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1135 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1137 piggy_bitmap_page_out_all();
1140 descent_critical_error = 0;
1141 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1142 if ( descent_critical_error ) {
1143 piggy_critical_error();
1146 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1147 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1152 if (!FindArg("-macdata"))
1154 // otherwise, fall through...
1155 case MAC_ALIEN1_PIGSIZE:
1156 case MAC_ALIEN2_PIGSIZE:
1157 case MAC_FIRE_PIGSIZE:
1158 case MAC_GROUPA_PIGSIZE:
1159 case MAC_ICE_PIGSIZE:
1160 case MAC_WATER_PIGSIZE:
1161 rle_swap_0_255( bmp );
1162 memcpy(&zsize, bmp->bm_data, 4);
1167 Piggy_bitmap_cache_next += zsize;
1168 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1170 piggy_bitmap_page_out_all();
1175 int pigsize = cfilelength(Piggy_fp);
1176 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1177 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1178 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1179 piggy_bitmap_page_out_all();
1182 descent_critical_error = 0;
1183 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1184 if ( descent_critical_error ) {
1185 piggy_critical_error();
1188 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1189 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1194 if (!FindArg("-macdata"))
1196 // otherwise, fall through...
1197 case MAC_ALIEN1_PIGSIZE:
1198 case MAC_ALIEN2_PIGSIZE:
1199 case MAC_FIRE_PIGSIZE:
1200 case MAC_GROUPA_PIGSIZE:
1201 case MAC_ICE_PIGSIZE:
1202 case MAC_WATER_PIGSIZE:
1209 //@@if ( bmp->bm_selector ) {
1210 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1211 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1212 //@@ Error( "Error modifying selector base in piggy.c\n" );
1219 if ( piggy_low_memory ) {
1221 GameBitmaps[org_i] = GameBitmaps[i];
1224 //@@Removed from John's code:
1226 //@@ if ( bmp->bm_selector ) {
1227 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1228 //@@ Error( "Error modifying selector base in piggy.c\n" );
1234 void piggy_bitmap_page_out_all()
1238 Piggy_bitmap_cache_next = 0;
1240 piggy_page_flushed++;
1245 for (i=0; i<Num_bitmap_files; i++ ) {
1246 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1247 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1248 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1252 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1255 void piggy_load_level_data()
1257 piggy_bitmap_page_out_all();
1263 void piggy_write_pigfile(char *filename)
1266 int bitmap_data_start, data_offset;
1267 DiskBitmapHeader bmh;
1269 char subst_name[32];
1272 char tname[FILENAME_LEN];
1274 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1275 for (i=0; i < Num_bitmap_files; i++ ) {
1278 PIGGY_PAGE_IN( bi );
1280 // -- mprintf( (0, "\n" ));
1284 // -- mprintf( (0, "Creating %s...",filename ));
1286 pig_fp = fopen( filename, "wb" ); //open PIG file
1287 Assert( pig_fp!=NULL );
1289 write_int(PIGFILE_ID,pig_fp);
1290 write_int(PIGFILE_VERSION,pig_fp);
1293 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1296 bitmap_data_start = (int)ftell(pig_fp);
1297 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1298 data_offset = bitmap_data_start;
1300 change_filename_extension(tname,filename,"lst");
1301 fp1 = fopen( tname, "wt" );
1302 change_filename_extension(tname,filename,"all");
1303 fp2 = fopen( tname, "wt" );
1305 for (i=1; i < Num_bitmap_files; i++ ) {
1311 p = strchr(AllBitmaps[i].name, '#');
1312 if (p) { // this is an ABM == animated bitmap
1318 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1319 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1320 Assert( n <= DBM_NUM_FRAMES );
1321 bmh.dflags = DBM_FLAG_ABM + n;
1325 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1326 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1330 bmp = &GameBitmaps[i];
1332 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1335 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1336 org_offset = (int)ftell(pig_fp);
1337 bmh.offset = data_offset - bitmap_data_start;
1338 fseek( pig_fp, data_offset, SEEK_SET );
1340 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1341 size = (int *)bmp->bm_data;
1342 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1343 data_offset += *size;
1345 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1347 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1348 data_offset += bmp->bm_rowsize * bmp->bm_h;
1350 fprintf( fp1, ".\n" );
1352 fseek( pig_fp, org_offset, SEEK_SET );
1353 Assert( GameBitmaps[i].bm_w < 4096 );
1354 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1355 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1356 Assert( GameBitmaps[i].bm_h < 4096 );
1357 bmh.height = GameBitmaps[i].bm_h;
1358 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1359 bmh.flags = GameBitmaps[i].bm_flags;
1360 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1361 bitmap_index other_bitmap;
1362 other_bitmap = piggy_find_bitmap( subst_name );
1363 GameBitmapXlat[i] = other_bitmap.index;
1364 bmh.flags |= BM_FLAG_PAGED_OUT;
1365 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1366 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1368 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1370 bmh.avg_color=GameBitmaps[i].avg_color;
1371 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1376 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1377 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1384 static void write_int(int i,FILE *file)
1386 if (fwrite( &i, sizeof(i), 1, file) != 1)
1387 Error( "Error reading int in gamesave.c" );
1391 void piggy_dump_all()
1395 int org_offset,data_offset=0;
1396 DiskSoundHeader sndh;
1397 int sound_data_start=0;
1400 #ifdef NO_DUMP_SOUNDS
1401 Num_sound_files = 0;
1402 Num_sound_files_new = 0;
1405 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1408 fp1 = fopen( "ham.lst", "wt" );
1409 fp2 = fopen( "ham.all", "wt" );
1411 if (Must_write_hamfile || Num_bitmap_files_new) {
1413 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1415 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1416 Assert( ham_fp!=NULL );
1418 write_int(HAMFILE_ID,ham_fp);
1419 write_int(HAMFILE_VERSION,ham_fp);
1421 bm_write_all(ham_fp);
1422 xlat_offset = (int)ftell(ham_fp);
1423 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1426 if (Num_bitmap_files_new)
1427 piggy_write_pigfile(DEFAULT_PIGFILE);
1429 //free up memeory used by new bitmaps
1430 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1431 d_free(GameBitmaps[i].bm_data);
1433 //next thing must be done after pig written
1434 fseek( ham_fp, xlat_offset, SEEK_SET );
1435 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1438 mprintf( (0, "\n" ));
1441 if (Num_sound_files_new) {
1443 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1444 // Now dump sound file
1445 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1446 Assert( ham_fp!=NULL );
1448 write_int(SNDFILE_ID,ham_fp);
1449 write_int(SNDFILE_VERSION,ham_fp);
1451 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1453 mprintf( (0, "\nDumping sounds..." ));
1455 sound_data_start = (int)ftell(ham_fp);
1456 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1457 data_offset = sound_data_start;
1459 for (i=0; i < Num_sound_files; i++ ) {
1462 snd = &GameSounds[i];
1463 strcpy( sndh.name, AllSounds[i].name );
1464 sndh.length = GameSounds[i].length;
1465 sndh.offset = data_offset - sound_data_start;
1467 org_offset = (int)ftell(ham_fp);
1468 fseek( ham_fp, data_offset, SEEK_SET );
1470 sndh.data_length = GameSounds[i].length;
1471 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1472 data_offset += snd->length;
1473 fseek( ham_fp, org_offset, SEEK_SET );
1474 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1476 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1477 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1481 mprintf( (0, "\n" ));
1484 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1485 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1486 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1491 // Never allow the game to run after building ham.
1505 d_free( SoundBits );
1507 hashtable_free( &AllBitmapsNames );
1508 hashtable_free( &AllDigiSndNames );
1512 int piggy_does_bitmap_exist_slow( char * name )
1516 for (i=0; i<Num_bitmap_files; i++ ) {
1517 if ( !strcmp( AllBitmaps[i].name, name) )
1524 #define NUM_GAUGE_BITMAPS 23
1525 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1526 "gauge01", "gauge01b",
1527 "gauge02", "gauge02b",
1528 "gauge06", "gauge06b",
1529 "targ01", "targ01b",
1530 "targ02", "targ02b",
1531 "targ03", "targ03b",
1532 "targ04", "targ04b",
1533 "targ05", "targ05b",
1534 "targ06", "targ06b",
1535 "gauge18", "gauge18b",
1541 int piggy_is_gauge_bitmap( char * base_name )
1544 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1545 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1552 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1556 char base_name[ 16 ];
1558 strcpy( subst_name, name );
1559 p = strchr( subst_name, '#' );
1561 frame = atoi( &p[1] );
1563 strcpy( base_name, subst_name );
1564 if ( !piggy_is_gauge_bitmap( base_name )) {
1565 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1566 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1568 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1574 strcpy( subst_name, name );
1581 * Functions for loading replacement textures
1582 * 1) From .pog files
1583 * 2) From descent.pig (for loading d1 levels)
1586 extern char last_palette_loaded_pig[];
1588 void free_bitmap_replacements()
1590 if (Bitmap_replacement_data) {
1591 d_free(Bitmap_replacement_data);
1592 Bitmap_replacement_data = NULL;
1596 void load_bitmap_replacements(char *level_name)
1598 char ifile_name[FILENAME_LEN];
1602 //first, free up data allocated for old bitmaps
1603 free_bitmap_replacements();
1605 change_filename_extension(ifile_name, level_name, ".POG" );
1607 ifile = cfopen(ifile_name,"rb");
1610 int id,version,n_bitmaps;
1611 int bitmap_data_size;
1614 id = cfile_read_int(ifile);
1615 version = cfile_read_int(ifile);
1617 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1622 n_bitmaps = cfile_read_int(ifile);
1624 MALLOC( indices, ushort, n_bitmaps );
1626 for (i = 0; i < n_bitmaps; i++)
1627 indices[i] = cfile_read_short(ifile);
1629 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1630 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1632 for (i=0;i<n_bitmaps;i++) {
1633 DiskBitmapHeader bmh;
1634 grs_bitmap *bm = &GameBitmaps[indices[i]];
1637 DiskBitmapHeader_read(&bmh, ifile);
1639 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1640 gr_set_bitmap_data(bm, NULL); // free ogl texture
1641 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1642 bm->avg_color = bmh.avg_color;
1643 bm->bm_data = (ubyte *) (size_t)bmh.offset;
1645 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1647 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1650 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1652 for (i = 0; i < n_bitmaps; i++)
1654 grs_bitmap *bm = &GameBitmaps[indices[i]];
1655 gr_set_bitmap_data(bm, Bitmap_replacement_data + (size_t) bm->bm_data);
1662 last_palette_loaded_pig[0]= 0; //force pig re-load
1664 texmerge_flush(); //for re-merging with new textures
1667 atexit(free_bitmap_replacements);
1670 /* calculate table to translate d1 bitmaps to current palette,
1671 * return -1 on error
1673 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1676 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1677 if (!palette_file || cfilelength(palette_file) != 9472)
1679 cfread( d1_palette, 256, 3, palette_file);
1680 cfclose( palette_file );
1681 build_colormap_good( d1_palette, colormap, freq );
1682 // don't change transparencies:
1683 colormap[254] = 254;
1684 colormap[255] = 255;
1688 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1689 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1690 CFILE *d1_Piggy_fp, /* read from this file */
1691 int bitmap_data_start, /* specific to file */
1692 DiskBitmapHeader *bmh, /* header info for bitmap */
1693 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1694 ubyte *d1_palette, /* what palette the bitmap has */
1695 ubyte *colormap) /* how to translate bitmap's colors */
1697 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1701 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1702 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1703 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1704 bitmap->avg_color = bmh->avg_color;
1705 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1707 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1708 if (bmh->flags & BM_FLAG_RLE) {
1709 zsize = cfile_read_int(d1_Piggy_fp);
1710 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1712 zsize = bitmap->bm_h * bitmap->bm_w;
1715 data = *next_bitmap;
1716 *next_bitmap += zsize;
1718 data = d_malloc(zsize + JUST_IN_CASE);
1722 cfread(data, 1, zsize, d1_Piggy_fp);
1723 gr_set_bitmap_data(bitmap, data);
1725 case D1_MAC_PIGSIZE:
1726 case D1_MAC_SHARE_PIGSIZE:
1727 if (bmh->flags & BM_FLAG_RLE)
1728 rle_swap_0_255(bitmap);
1732 if (bmh->flags & BM_FLAG_RLE)
1733 rle_remap(bitmap, colormap);
1735 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1736 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1738 memcpy(&new_size, bitmap->bm_data, 4);
1740 *next_bitmap += new_size - zsize;
1742 Assert( zsize + JUST_IN_CASE >= new_size );
1743 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1744 Assert(bitmap->bm_data);
1749 #define D1_MAX_TEXTURES 800
1750 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1752 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1753 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1754 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1756 short *d1_tmap_nums = NULL;
1758 void free_d1_tmap_nums() {
1760 d_free(d1_tmap_nums);
1761 d1_tmap_nums = NULL;
1765 void bm_read_d1_tmap_nums(CFILE *d1pig)
1769 free_d1_tmap_nums();
1770 cfseek(d1pig, 8, SEEK_SET);
1771 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1772 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1773 d1_tmap_nums[i] = -1;
1774 for (i = 0; i < D1_MAX_TEXTURES; i++) {
1775 d1_index = cfile_read_short(d1pig);
1776 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1777 d1_tmap_nums[d1_index] = i;
1779 atexit(free_d1_tmap_nums);
1782 void remove_char( char * s, char c )
1789 #define REMOVE_EOL(s) remove_char((s),'\n')
1790 #define REMOVE_COMMENTS(s) remove_char((s),';')
1791 #define REMOVE_DOTS(s) remove_char((s),'.')
1792 char *space = { " \t" };
1793 char *equal_space = { " \t=" };
1795 // this function is at the same position in the d1 shareware piggy loading
1796 // algorithm as bm_load_sub in main/bmread.c
1797 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
1799 DiskBitmapHeader bmh;
1800 if (strchr (filename, '.'))
1801 *strchr (filename, '.') = '\0'; // remove extension
1802 cfseek (d1_pig, 0, SEEK_SET);
1803 N_bitmaps = cfile_read_int (d1_pig);
1804 cfseek (d1_pig, 8, SEEK_SET);
1805 for (i = 1; i <= N_bitmaps; i++) {
1806 DiskBitmapHeader_d1_read(&bmh, d1_pig);
1807 if (!strnicmp(bmh.name, filename, 8))
1813 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1814 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1816 #define LINEBUF_SIZE 600
1817 int reading_textures = 0;
1818 short texture_count = 0;
1819 char inputline[LINEBUF_SIZE];
1821 int bitmaps_tbl_is_binary = 0;
1824 bitmaps = cfopen ("bitmaps.tbl", "rb");
1826 bitmaps = cfopen ("bitmaps.bin", "rb");
1827 bitmaps_tbl_is_binary = 1;
1831 Warning ("Could not find bitmaps.* for reading d1 textures");
1835 free_d1_tmap_nums();
1836 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1837 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1838 d1_tmap_nums[i] = -1;
1839 atexit(free_d1_tmap_nums);
1841 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1844 if (bitmaps_tbl_is_binary)
1845 decode_text_line((inputline));
1847 while (inputline[(i = (int)strlen(inputline)) - 2] == '\\')
1848 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
1849 REMOVE_EOL(inputline);
1850 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
1851 if (strlen(inputline) == LINEBUF_SIZE-1) {
1852 Warning("Possible line truncation in BITMAPS.TBL");
1855 arg = strtok( inputline, space );
1856 if (arg && arg[0] == '@') {
1858 //Registered_only = 1;
1861 while (arg != NULL) {
1863 reading_textures = 0; // default
1864 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
1865 reading_textures = 1;
1866 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
1867 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
1869 else // not a special token, must be a bitmap!
1870 if (reading_textures) {
1871 while (*arg == '\t' || *arg == ' ')
1872 arg++;//remove unwanted blanks
1875 if (d1_tmap_num_unique(texture_count)) {
1876 int d1_index = get_d1_bm_index(arg, d1_pig);
1877 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
1878 d1_tmap_nums[d1_index] = texture_count;
1879 //int d2_index = d2_index_for_d1_index(d1_index);
1882 Assert (texture_count < D1_MAX_TEXTURES);
1886 arg = strtok (NULL, equal_space);
1892 /* If the given d1_index is the index of a bitmap we have to load
1893 * (because it is unique to descent 1), then returns the d2_index that
1894 * the given d1_index replaces.
1895 * Returns -1 if the given d1_index is not unique to descent 1.
1897 short d2_index_for_d1_index(short d1_index)
1899 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1900 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
1901 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
1904 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1907 #define D1_BITMAPS_SIZE 300000
1908 void load_d1_bitmap_replacements()
1910 CFILE * d1_Piggy_fp;
1911 DiskBitmapHeader bmh;
1912 int pig_data_start, bitmap_header_start, bitmap_data_start;
1914 short d1_index, d2_index;
1916 ubyte colormap[256];
1917 ubyte d1_palette[256*3];
1921 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1923 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1925 Warning(D1_PIG_LOAD_FAILED);
1929 //first, free up data allocated for old bitmaps
1930 free_bitmap_replacements();
1932 if (get_d1_colormap( d1_palette, colormap ) != 0)
1933 Warning("Could not load descent 1 color palette");
1935 pigsize = cfilelength(d1_Piggy_fp);
1937 case D1_SHARE_BIG_PIGSIZE:
1938 case D1_SHARE_10_PIGSIZE:
1939 case D1_SHARE_PIGSIZE:
1940 case D1_10_BIG_PIGSIZE:
1943 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
1944 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
1947 Warning("Unknown size for " D1_PIGFILE);
1951 case D1_OEM_PIGSIZE:
1952 case D1_MAC_PIGSIZE:
1953 case D1_MAC_SHARE_PIGSIZE:
1954 pig_data_start = cfile_read_int(d1_Piggy_fp );
1955 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
1956 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
1960 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1961 N_bitmaps = cfile_read_int(d1_Piggy_fp);
1963 int N_sounds = cfile_read_int(d1_Piggy_fp);
1964 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
1965 + N_sounds * sizeof(DiskSoundHeader);
1966 bitmap_header_start = pig_data_start + 2 * sizeof(int);
1967 bitmap_data_start = bitmap_header_start + header_size;
1970 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1971 if (!Bitmap_replacement_data) {
1972 Warning(D1_PIG_LOAD_FAILED);
1975 atexit(free_bitmap_replacements);
1977 next_bitmap = Bitmap_replacement_data;
1979 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
1980 d2_index = d2_index_for_d1_index(d1_index);
1981 // only change bitmaps which are unique to d1
1982 if (d2_index != -1) {
1983 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
1984 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
1986 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
1987 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
1988 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
1989 GameBitmapFlags[d2_index] = bmh.flags;
1991 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
1992 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
1993 int i, len = (int)(p - AllBitmaps[d2_index].name);
1994 for (i = 0; i < Num_bitmap_files; i++)
1995 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
1997 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
1998 GameBitmaps[i] = GameBitmaps[d2_index];
1999 GameBitmapOffset[i] = 0;
2000 GameBitmapFlags[i] = bmh.flags;
2006 cfclose(d1_Piggy_fp);
2008 last_palette_loaded_pig[0]= 0; //force pig re-load
2010 texmerge_flush(); //for re-merging with new textures
2014 extern int extra_bitmap_num;
2017 * Find and load the named bitmap from descent.pig
2018 * similar to read_extra_bitmap_iff
2020 bitmap_index read_extra_bitmap_d1_pig(char *name)
2022 bitmap_index bitmap_num;
2023 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2025 bitmap_num.index = 0;
2029 DiskBitmapHeader bmh;
2030 int pig_data_start, bitmap_header_start, bitmap_data_start;
2032 ubyte colormap[256];
2033 ubyte d1_palette[256*3];
2036 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2040 Warning(D1_PIG_LOAD_FAILED);
2044 if (get_d1_colormap( d1_palette, colormap ) != 0)
2045 Warning("Could not load descent 1 color palette");
2047 pigsize = cfilelength(d1_Piggy_fp);
2049 case D1_SHARE_BIG_PIGSIZE:
2050 case D1_SHARE_10_PIGSIZE:
2051 case D1_SHARE_PIGSIZE:
2052 case D1_10_BIG_PIGSIZE:
2057 Warning("Unknown size for " D1_PIGFILE);
2061 case D1_OEM_PIGSIZE:
2062 case D1_MAC_PIGSIZE:
2063 case D1_MAC_SHARE_PIGSIZE:
2064 pig_data_start = cfile_read_int(d1_Piggy_fp );
2069 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2070 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2072 int N_sounds = cfile_read_int(d1_Piggy_fp);
2073 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2074 + N_sounds * sizeof(DiskSoundHeader);
2075 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2076 bitmap_data_start = bitmap_header_start + header_size;
2079 for (i = 1; i <= N_bitmaps; i++)
2081 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2082 if (!strnicmp(bmh.name, name, 8))
2086 if (strnicmp(bmh.name, name, 8))
2088 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2092 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2094 cfclose(d1_Piggy_fp);
2097 new->avg_color = 0; //compute_average_pixel(new);
2099 bitmap_num.index = extra_bitmap_num;
2101 GameBitmaps[extra_bitmap_num++] = *new;
2107 #ifndef FAST_FILE_IO
2109 * reads a bitmap_index structure from a CFILE
2111 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2113 bi->index = cfile_read_short(fp);
2117 * reads n bitmap_index structs from a CFILE
2119 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2123 for (i = 0; i < n; i++)
2124 bi[i].index = cfile_read_short(fp);
2127 #endif // FAST_FILE_IO