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.
48 #include <Strings.h> // MacOS Toolbox header
54 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
56 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
57 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
58 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
59 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
61 #define D1_PALETTE "palette.256"
63 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
64 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
65 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
67 #define MAC_ALIEN1_PIGSIZE 5013035
68 #define MAC_ALIEN2_PIGSIZE 4909916
69 #define MAC_FIRE_PIGSIZE 4969035
70 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
71 #define MAC_ICE_PIGSIZE 4923425
72 #define MAC_WATER_PIGSIZE 4832403
74 ubyte *BitmapBits = NULL;
75 ubyte *SoundBits = NULL;
77 typedef struct BitmapFile {
81 typedef struct SoundFile {
85 hashtable AllBitmapsNames;
86 hashtable AllDigiSndNames;
88 int Num_bitmap_files = 0;
89 int Num_sound_files = 0;
91 digi_sound GameSounds[MAX_SOUND_FILES];
92 int SoundOffset[MAX_SOUND_FILES];
93 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
95 alias alias_list[MAX_ALIASES];
98 int Must_write_hamfile = 0;
99 int Num_bitmap_files_new = 0;
100 int Num_sound_files_new = 0;
101 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
102 static SoundFile AllSounds[ MAX_SOUND_FILES ];
104 int Piggy_hamfile_version = 0;
106 int piggy_low_memory = 0;
108 int Piggy_bitmap_cache_size = 0;
109 int Piggy_bitmap_cache_next = 0;
110 ubyte * Piggy_bitmap_cache_data = NULL;
111 static int GameBitmapOffset[MAX_BITMAP_FILES];
112 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
113 ushort GameBitmapXlat[MAX_BITMAP_FILES];
115 #define PIGGY_BUFFER_SIZE (2400*1024)
118 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
121 #undef PIGGY_BUFFER_SIZE
122 #undef PIGGY_SMALL_BUFFER_SIZE
124 #define PIGGY_BUFFER_SIZE (2000*1024)
125 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
130 int piggy_page_flushed = 0;
132 #define DBM_FLAG_ABM 64 // animated bitmap
133 #define DBM_NUM_FRAMES 63
135 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
136 | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
138 typedef struct DiskBitmapHeader {
140 ubyte dflags; // bits 0-5 anim frame num, bit 6 abm flag
141 ubyte width; // low 8 bits here, 4 more bits in wh_extra
142 ubyte height; // low 8 bits here, 4 more bits in wh_extra
143 ubyte wh_extra; // bits 0-3 width, bits 4-7 height
147 } __pack__ DiskBitmapHeader;
149 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
151 typedef struct DiskSoundHeader {
156 } __pack__ DiskSoundHeader;
159 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
160 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
163 * reads a DiskBitmapHeader structure from a CFILE
165 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
167 cfread(dbh->name, 8, 1, fp);
168 dbh->dflags = cfile_read_byte(fp);
169 dbh->width = cfile_read_byte(fp);
170 dbh->height = cfile_read_byte(fp);
171 dbh->wh_extra = cfile_read_byte(fp);
172 dbh->flags = cfile_read_byte(fp);
173 dbh->avg_color = cfile_read_byte(fp);
174 dbh->offset = cfile_read_int(fp);
178 * reads a DiskSoundHeader structure from a CFILE
180 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
182 cfread(dsh->name, 8, 1, fp);
183 dsh->length = cfile_read_int(fp);
184 dsh->data_length = cfile_read_int(fp);
185 dsh->offset = cfile_read_int(fp);
187 #endif // FAST_FILE_IO
190 * reads a descent 1 DiskBitmapHeader structure from a CFILE
192 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
194 cfread(dbh->name, 8, 1, fp);
195 dbh->dflags = cfile_read_byte(fp);
196 dbh->width = cfile_read_byte(fp);
197 dbh->height = cfile_read_byte(fp);
199 dbh->flags = cfile_read_byte(fp);
200 dbh->avg_color = cfile_read_byte(fp);
201 dbh->offset = cfile_read_int(fp);
207 extern short cd_VRefNum;
208 extern void ConcatPStr(StringPtr dst, StringPtr src);
209 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
210 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
213 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
216 void piggy_write_pigfile(char *filename);
217 static void write_int(int i,FILE *file);
220 void swap_0_255(grs_bitmap *bmp)
224 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
225 if(bmp->bm_data[i] == 0)
226 bmp->bm_data[i] = 255;
227 else if (bmp->bm_data[i] == 255)
232 char* piggy_game_bitmap_name(grs_bitmap *bmp)
234 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
236 int i = (int)(bmp - GameBitmaps); // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
237 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
238 return AllBitmaps[i].name;
243 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
246 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
248 temp.index = Num_bitmap_files;
252 if ( FindArg("-macdata") )
255 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
256 Num_bitmap_files_new++;
259 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
260 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
261 //GameBitmaps[Num_bitmap_files] = *bmp;
263 GameBitmapOffset[Num_bitmap_files] = 0;
264 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
271 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
275 Assert( Num_sound_files < MAX_SOUND_FILES );
277 strncpy( AllSounds[Num_sound_files].name, name, 12 );
278 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
279 GameSounds[Num_sound_files] = *snd;
281 SoundOffset[Num_sound_files] = 0;
287 Num_sound_files_new++;
293 bitmap_index piggy_find_bitmap( char * name )
301 if ((t=strchr(name,'#'))!=NULL)
304 for (i=0;i<Num_aliases;i++)
305 if (stricmp(name,alias_list[i].alias_name)==0) {
306 if (t) { //extra stuff for ABMs
307 static char temp[FILENAME_LEN];
308 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
314 name=alias_list[i].file_name;
321 i = hashtable_search( &AllBitmapsNames, name );
330 int piggy_find_sound( char * name )
334 i = hashtable_search( &AllDigiSndNames, name );
342 CFILE * Piggy_fp = NULL;
344 #define FILENAME_LEN 13
346 char Current_pigfile[FILENAME_LEN] = "";
348 void piggy_close_file()
353 Current_pigfile[0] = 0;
357 int Pigfile_initialized=0;
359 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
360 #define PIGFILE_VERSION 2
363 //initialize a pigfile, reading headers
364 //returns the size of all the bitmap data
365 void piggy_init_pigfile(char *filename)
369 char temp_name_read[16];
370 DiskBitmapHeader bmh;
371 int header_size, N_bitmaps, data_size, data_start;
373 piggy_close_file(); //close old pig if still open
375 //rename pigfile for shareware
376 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
377 filename = DEFAULT_PIGFILE_SHAREWARE;
379 Piggy_fp = cfopen( filename, "rb" );
381 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
382 if (Piggy_fp == NULL)
384 Error("Cannot load required file <%s>",name);
386 #endif // end of if def shareware
390 return; //if editor, ok to not have pig, because we'll build one
392 Piggy_fp = cfopen(filename, "rb");
396 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
397 int pig_id,pig_version;
399 pig_id = cfile_read_int(Piggy_fp);
400 pig_version = cfile_read_int(Piggy_fp);
401 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
402 cfclose(Piggy_fp); //out of date pig
403 Piggy_fp = NULL; //..so pretend it's not here
410 return; //if editor, ok to not have pig, because we'll build one
412 Error("Cannot load required file <%s>",filename);
416 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
418 N_bitmaps = cfile_read_int(Piggy_fp);
420 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
422 data_start = header_size + cftell(Piggy_fp);
424 data_size = cfilelength(Piggy_fp) - data_start;
426 Num_bitmap_files = 1;
428 for (i=0; i<N_bitmaps; i++ )
431 grs_bitmap *bm = &GameBitmaps[i + 1];
433 DiskBitmapHeader_read(&bmh, Piggy_fp);
434 memcpy( temp_name_read, bmh.name, 8 );
435 temp_name_read[8] = 0;
436 if ( bmh.dflags & DBM_FLAG_ABM )
437 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
439 strcpy( temp_name, temp_name_read );
440 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
441 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
442 bm->bm_flags = BM_FLAG_PAGED_OUT;
443 bm->avg_color = bmh.avg_color;
445 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
447 GameBitmapOffset[i+1] = bmh.offset + data_start;
448 Assert( (i+1) == Num_bitmap_files );
449 piggy_register_bitmap(bm, temp_name, 1);
453 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
454 Assert( Piggy_bitmap_cache_size > 0 );
456 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
458 if (piggy_low_memory)
459 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
462 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
463 if ( BitmapBits == NULL )
464 Error( "Not enough memory to load bitmaps\n" );
465 Piggy_bitmap_cache_data = BitmapBits;
466 Piggy_bitmap_cache_next = 0;
468 #if defined(MACINTOSH) && defined(SHAREWARE)
469 // load_exit_models();
472 Pigfile_initialized=1;
475 #define FILENAME_LEN 13
476 #define MAX_BITMAPS_PER_BRUSH 30
478 extern int compute_average_pixel(grs_bitmap *new);
479 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
481 ubyte *Bitmap_replacement_data = NULL;
483 //reads in a new pigfile (for new palette)
484 //returns the size of all the bitmap data
485 void piggy_new_pigfile(char *pigname)
489 char temp_name_read[16];
490 DiskBitmapHeader bmh;
491 int header_size, N_bitmaps, data_size, data_start;
492 int must_rewrite_pig = 0;
496 //rename pigfile for shareware
497 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
498 pigname = DEFAULT_PIGFILE_SHAREWARE;
500 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
501 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
504 if (!Pigfile_initialized) { //have we ever opened a pigfile?
505 piggy_init_pigfile(pigname); //..no, so do initialization stuff
509 piggy_close_file(); //close old pig if still open
511 Piggy_bitmap_cache_next = 0; //free up cache
513 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
515 Piggy_fp = cfopen( pigname, "rb" );
517 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
518 if (Piggy_fp == NULL)
520 Error("Cannot load required file <%s>",name);
522 #endif // end of if def shareware
526 Piggy_fp = cfopen(pigname, "rb");
529 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
530 int pig_id,pig_version;
532 pig_id = cfile_read_int(Piggy_fp);
533 pig_version = cfile_read_int(Piggy_fp);
534 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
535 cfclose(Piggy_fp); //out of date pig
536 Piggy_fp = NULL; //..so pretend it's not here
542 Error("Cannot open correct version of <%s>", pigname);
547 N_bitmaps = cfile_read_int(Piggy_fp);
549 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
551 data_start = header_size + cftell(Piggy_fp);
553 data_size = cfilelength(Piggy_fp) - data_start;
555 for (i=1; i<=N_bitmaps; i++ )
557 grs_bitmap *bm = &GameBitmaps[i];
560 DiskBitmapHeader_read(&bmh, Piggy_fp);
561 memcpy( temp_name_read, bmh.name, 8 );
562 temp_name_read[8] = 0;
564 if ( bmh.dflags & DBM_FLAG_ABM )
565 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
567 strcpy( temp_name, temp_name_read );
569 //Make sure name matches
570 if (strcmp(temp_name,AllBitmaps[i].name)) {
571 //Int3(); //this pig is out of date. Delete it
575 strcpy(AllBitmaps[i].name,temp_name);
577 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
578 gr_set_bitmap_data(bm, NULL); // free ogl texture
579 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
580 bm->bm_flags = BM_FLAG_PAGED_OUT;
581 bm->avg_color = bmh.avg_color;
583 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
585 GameBitmapOffset[i] = bmh.offset + data_start;
589 N_bitmaps = 0; //no pigfile, so no bitmaps
593 Assert(N_bitmaps == Num_bitmap_files-1);
597 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
600 //re-read the bitmaps that aren't in this pig
602 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
605 p = strchr(AllBitmaps[i].name,'#');
607 if (p) { // this is an ABM == animated bitmap
608 char abmname[FILENAME_LEN];
610 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
611 int iff_error; //reference parm to avoid warning message
613 char basename[FILENAME_LEN];
616 strcpy(basename,AllBitmaps[i].name);
617 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
619 sprintf( abmname, "%s.abm", basename );
621 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
623 if (iff_error != IFF_NO_ERROR) {
624 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
625 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
628 for (fnum=0;fnum<nframes; fnum++) {
632 sprintf( tempname, "%s#%d", basename, fnum );
634 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
635 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
636 //above makes assumption that supertransparent color is 254
638 if ( iff_has_transparency )
639 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
641 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
643 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
646 if ( FindArg("-macdata") )
647 swap_0_255( bm[fnum] );
649 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
651 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
652 size = *((int *) bm[fnum]->bm_data);
654 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
656 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
657 d_free(bm[fnum]->bm_data);
658 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
659 Piggy_bitmap_cache_next += size;
661 GameBitmaps[i+fnum] = *bm[fnum];
663 // -- mprintf( (0, "U" ));
667 i += nframes-1; //filled in multiple bitmaps
669 else { //this is a BBM
674 char bbmname[FILENAME_LEN];
677 MALLOC( new, grs_bitmap, 1 );
679 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
680 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
683 if (iff_error != IFF_NO_ERROR) {
684 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
685 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
688 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
689 //above makes assumption that supertransparent color is 254
691 if ( iff_has_transparency )
692 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
694 gr_remap_bitmap_good( new, newpal, -1, SuperX );
696 new->avg_color = compute_average_pixel(new);
699 if ( FindArg("-macdata") )
702 if ( !BigPig ) gr_bitmap_rle_compress( new );
704 if (new->bm_flags & BM_FLAG_RLE)
705 size = *((int *) new->bm_data);
707 size = new->bm_w * new->bm_h;
709 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
710 d_free(new->bm_data);
711 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
712 Piggy_bitmap_cache_next += size;
714 GameBitmaps[i] = *new;
718 // -- mprintf( (0, "U" ));
722 //@@Dont' do these things which are done when writing
723 //@@for (i=0; i < Num_bitmap_files; i++ ) {
724 //@@ bitmap_index bi;
726 //@@ PIGGY_PAGE_IN( bi );
729 //@@piggy_close_file();
731 piggy_write_pigfile(pigname);
733 Current_pigfile[0] = 0; //say no pig, to force reload
735 piggy_new_pigfile(pigname); //read in just-generated pig
739 #endif //ifdef EDITOR
743 ubyte bogus_data[64*64];
744 ubyte bogus_bitmap_initialized=0;
745 digi_sound bogus_sound;
747 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
748 #define HAMFILE_VERSION 3
749 //version 1 -> 2: save marker_model_num
750 //version 2 -> 3: removed sound files
752 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
753 #define SNDFILE_VERSION 1
757 CFILE * ham_fp = NULL;
759 int sound_offset = 0;
761 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
763 if (ham_fp == NULL) {
764 Must_write_hamfile = 1;
768 //make sure ham is valid type file & is up-to-date
769 ham_id = cfile_read_int(ham_fp);
770 Piggy_hamfile_version = cfile_read_int(ham_fp);
771 if (ham_id != HAMFILE_ID)
772 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
774 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
775 Must_write_hamfile = 1;
776 cfclose(ham_fp); //out of date ham
781 if (Piggy_hamfile_version < 3) // hamfile contains sound info
782 sound_offset = cfile_read_int(ham_fp);
789 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
791 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
792 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
793 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
798 if (Piggy_hamfile_version < 3) {
803 DiskSoundHeader sndh;
804 digi_sound temp_sound;
805 char temp_name_read[16];
808 cfseek(ham_fp, sound_offset, SEEK_SET);
809 N_sounds = cfile_read_int(ham_fp);
811 sound_start = cftell(ham_fp);
813 header_size = N_sounds * sizeof(DiskSoundHeader);
817 for (i=0; i<N_sounds; i++ ) {
818 DiskSoundHeader_read(&sndh, ham_fp);
819 temp_sound.length = sndh.length;
820 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
821 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
822 memcpy( temp_name_read, sndh.name, 8 );
823 temp_name_read[8] = 0;
824 piggy_register_sound( &temp_sound, temp_name_read, 1 );
826 if (piggy_is_needed(i))
827 #endif // note link to if.
828 sbytes += sndh.length;
829 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
832 SoundBits = d_malloc( sbytes + 16 );
833 if ( SoundBits == NULL )
834 Error( "Not enough memory to load sounds\n" );
836 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
838 // piggy_read_sounds(ham_fp);
850 CFILE * snd_fp = NULL;
851 int snd_id,snd_version;
856 DiskSoundHeader sndh;
857 digi_sound temp_sound;
858 char temp_name_read[16];
861 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
866 //make sure soundfile is valid type file & is up-to-date
867 snd_id = cfile_read_int(snd_fp);
868 snd_version = cfile_read_int(snd_fp);
869 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
870 cfclose(snd_fp); //out of date sound file
874 N_sounds = cfile_read_int(snd_fp);
876 sound_start = cftell(snd_fp);
877 size = cfilelength(snd_fp) - sound_start;
879 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
881 header_size = N_sounds*sizeof(DiskSoundHeader);
885 for (i=0; i<N_sounds; i++ ) {
886 DiskSoundHeader_read(&sndh, snd_fp);
887 //size -= sizeof(DiskSoundHeader);
888 temp_sound.length = sndh.length;
889 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
890 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
891 memcpy( temp_name_read, sndh.name, 8 );
892 temp_name_read[8] = 0;
893 piggy_register_sound( &temp_sound, temp_name_read, 1 );
895 if (piggy_is_needed(i))
896 #endif // note link to if.
897 sbytes += sndh.length;
898 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
901 SoundBits = d_malloc( sbytes + 16 );
902 if ( SoundBits == NULL )
903 Error( "Not enough memory to load sounds\n" );
905 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
907 // piggy_read_sounds(snd_fp);
916 int ham_ok=0,snd_ok=0;
919 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
920 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
922 for (i=0; i<MAX_SOUND_FILES; i++ ) {
923 GameSounds[i].length = 0;
924 GameSounds[i].data = NULL;
928 for (i=0; i<MAX_BITMAP_FILES; i++ )
929 GameBitmapXlat[i] = i;
931 if ( !bogus_bitmap_initialized ) {
935 bogus_bitmap_initialized = 1;
936 c = gr_find_closest_color( 0, 0, 63 );
937 for (i=0; i<4096; i++ ) bogus_data[i] = c;
938 c = gr_find_closest_color( 63, 0, 0 );
939 // Make a big red X !
940 for (i=0; i<64; i++ ) {
941 bogus_data[i*64+i] = c;
942 bogus_data[i*64+(63-i)] = c;
944 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
945 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
946 bogus_sound.length = 64*64;
947 bogus_sound.data = bogus_data;
948 GameBitmapOffset[0] = 0;
951 if ( FindArg( "-bigpig" ))
954 if ( FindArg( "-lowmem" ))
955 piggy_low_memory = 1;
957 if ( FindArg( "-nolowmem" ))
958 piggy_low_memory = 0;
960 if (piggy_low_memory)
963 gr_set_curfont( SMALL_FONT );
964 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
965 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
967 #if 1 //def EDITOR //need for d1 mission briefings
968 piggy_init_pigfile(DEFAULT_PIGFILE);
971 snd_ok = ham_ok = read_hamfile();
973 if (Piggy_hamfile_version >= 3)
974 snd_ok = read_sndfile();
978 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
979 return (ham_ok && snd_ok); //read ok
982 int piggy_is_needed(int soundnum)
986 if ( !digi_lomem ) return 1;
988 for (i=0; i<MAX_SOUNDS; i++ ) {
989 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
996 void piggy_read_sounds(void)
1005 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1010 for (i=0; i<Num_sound_files; i++ ) {
1011 digi_sound *snd = &GameSounds[i];
1013 if ( SoundOffset[i] > 0 ) {
1014 if ( piggy_is_needed(i) ) {
1015 cfseek( fp, SoundOffset[i], SEEK_SET );
1017 // Read in the sound data!!!
1020 sbytes += snd->length;
1021 cfread( snd->data, snd->length, 1, fp );
1024 snd->data = (ubyte *) -1;
1030 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1035 extern int descent_critical_error;
1036 extern unsigned descent_critical_deverror;
1037 extern unsigned descent_critical_errcode;
1039 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1040 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1041 "Read fault", "General Failure" };
1043 void piggy_critical_error()
1045 grs_canvas * save_canv;
1046 grs_font * save_font;
1048 save_canv = grd_curcanv;
1049 save_font = grd_curcanv->cv_font;
1050 gr_palette_load( gr_palette );
1051 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1054 gr_set_current_canvas(save_canv);
1055 grd_curcanv->cv_font = save_font;
1058 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1060 void piggy_bitmap_page_in( bitmap_index bitmap )
1069 Assert( i < MAX_BITMAP_FILES );
1070 Assert( i < Num_bitmap_files );
1071 Assert( Piggy_bitmap_cache_size > 0 );
1073 if ( i < 1 ) return;
1074 if ( i >= MAX_BITMAP_FILES ) return;
1075 if ( i >= Num_bitmap_files ) return;
1077 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1079 if ( piggy_low_memory ) {
1081 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1084 bmp = &GameBitmaps[i];
1086 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1090 descent_critical_error = 0;
1091 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1092 if ( descent_critical_error ) {
1093 piggy_critical_error();
1097 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1099 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1100 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1101 descent_critical_error = 0;
1102 zsize = cfile_read_int(Piggy_fp);
1103 if ( descent_critical_error ) {
1104 piggy_critical_error();
1108 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1109 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1110 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1112 piggy_bitmap_page_out_all();
1115 descent_critical_error = 0;
1116 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1117 if ( descent_critical_error ) {
1118 piggy_critical_error();
1121 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1122 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1127 if (!FindArg("-macdata"))
1129 // otherwise, fall through...
1130 case MAC_ALIEN1_PIGSIZE:
1131 case MAC_ALIEN2_PIGSIZE:
1132 case MAC_FIRE_PIGSIZE:
1133 case MAC_GROUPA_PIGSIZE:
1134 case MAC_ICE_PIGSIZE:
1135 case MAC_WATER_PIGSIZE:
1136 rle_swap_0_255( bmp );
1137 memcpy(&zsize, bmp->bm_data, 4);
1142 Piggy_bitmap_cache_next += zsize;
1143 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1145 piggy_bitmap_page_out_all();
1150 int pigsize = cfilelength(Piggy_fp);
1151 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1152 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1153 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1154 piggy_bitmap_page_out_all();
1157 descent_critical_error = 0;
1158 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1159 if ( descent_critical_error ) {
1160 piggy_critical_error();
1163 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1164 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1169 if (!FindArg("-macdata"))
1171 // otherwise, fall through...
1172 case MAC_ALIEN1_PIGSIZE:
1173 case MAC_ALIEN2_PIGSIZE:
1174 case MAC_FIRE_PIGSIZE:
1175 case MAC_GROUPA_PIGSIZE:
1176 case MAC_ICE_PIGSIZE:
1177 case MAC_WATER_PIGSIZE:
1184 //@@if ( bmp->bm_selector ) {
1185 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1186 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1187 //@@ Error( "Error modifying selector base in piggy.c\n" );
1194 if ( piggy_low_memory ) {
1196 GameBitmaps[org_i] = GameBitmaps[i];
1199 //@@Removed from John's code:
1201 //@@ if ( bmp->bm_selector ) {
1202 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1203 //@@ Error( "Error modifying selector base in piggy.c\n" );
1209 void piggy_bitmap_page_out_all()
1213 Piggy_bitmap_cache_next = 0;
1215 piggy_page_flushed++;
1220 for (i=0; i<Num_bitmap_files; i++ ) {
1221 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1222 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1223 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1227 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1230 void piggy_load_level_data()
1232 piggy_bitmap_page_out_all();
1238 void piggy_write_pigfile(char *filename)
1241 int bitmap_data_start, data_offset;
1242 DiskBitmapHeader bmh;
1244 char subst_name[32];
1247 char tname[FILENAME_LEN];
1249 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1250 for (i=0; i < Num_bitmap_files; i++ ) {
1253 PIGGY_PAGE_IN( bi );
1255 // -- mprintf( (0, "\n" ));
1259 // -- mprintf( (0, "Creating %s...",filename ));
1261 pig_fp = fopen( filename, "wb" ); //open PIG file
1262 Assert( pig_fp!=NULL );
1264 write_int(PIGFILE_ID,pig_fp);
1265 write_int(PIGFILE_VERSION,pig_fp);
1268 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1271 bitmap_data_start = ftell(pig_fp);
1272 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1273 data_offset = bitmap_data_start;
1275 change_filename_extension(tname,filename,"lst");
1276 fp1 = fopen( tname, "wt" );
1277 change_filename_extension(tname,filename,"all");
1278 fp2 = fopen( tname, "wt" );
1280 for (i=1; i < Num_bitmap_files; i++ ) {
1286 p = strchr(AllBitmaps[i].name, '#');
1287 if (p) { // this is an ABM == animated bitmap
1293 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1294 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1295 Assert( n <= DBM_NUM_FRAMES );
1296 bmh.dflags = DBM_FLAG_ABM + n;
1300 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1301 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1305 bmp = &GameBitmaps[i];
1307 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1310 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1311 org_offset = ftell(pig_fp);
1312 bmh.offset = data_offset - bitmap_data_start;
1313 fseek( pig_fp, data_offset, SEEK_SET );
1315 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1316 size = (int *)bmp->bm_data;
1317 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1318 data_offset += *size;
1320 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1322 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1323 data_offset += bmp->bm_rowsize * bmp->bm_h;
1325 fprintf( fp1, ".\n" );
1327 fseek( pig_fp, org_offset, SEEK_SET );
1328 Assert( GameBitmaps[i].bm_w < 4096 );
1329 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1330 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1331 Assert( GameBitmaps[i].bm_h < 4096 );
1332 bmh.height = GameBitmaps[i].bm_h;
1333 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1334 bmh.flags = GameBitmaps[i].bm_flags;
1335 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1336 bitmap_index other_bitmap;
1337 other_bitmap = piggy_find_bitmap( subst_name );
1338 GameBitmapXlat[i] = other_bitmap.index;
1339 bmh.flags |= BM_FLAG_PAGED_OUT;
1340 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1341 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1343 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1345 bmh.avg_color=GameBitmaps[i].avg_color;
1346 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1351 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1352 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1359 static void write_int(int i,FILE *file)
1361 if (fwrite( &i, sizeof(i), 1, file) != 1)
1362 Error( "Error reading int in gamesave.c" );
1366 void piggy_dump_all()
1370 int org_offset,data_offset=0;
1371 DiskSoundHeader sndh;
1372 int sound_data_start=0;
1375 #ifdef NO_DUMP_SOUNDS
1376 Num_sound_files = 0;
1377 Num_sound_files_new = 0;
1380 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1383 fp1 = fopen( "ham.lst", "wt" );
1384 fp2 = fopen( "ham.all", "wt" );
1386 if (Must_write_hamfile || Num_bitmap_files_new) {
1388 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1390 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1391 Assert( ham_fp!=NULL );
1393 write_int(HAMFILE_ID,ham_fp);
1394 write_int(HAMFILE_VERSION,ham_fp);
1396 bm_write_all(ham_fp);
1397 xlat_offset = ftell(ham_fp);
1398 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1401 if (Num_bitmap_files_new)
1402 piggy_write_pigfile(DEFAULT_PIGFILE);
1404 //free up memeory used by new bitmaps
1405 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1406 d_free(GameBitmaps[i].bm_data);
1408 //next thing must be done after pig written
1409 fseek( ham_fp, xlat_offset, SEEK_SET );
1410 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1413 mprintf( (0, "\n" ));
1416 if (Num_sound_files_new) {
1418 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1419 // Now dump sound file
1420 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1421 Assert( ham_fp!=NULL );
1423 write_int(SNDFILE_ID,ham_fp);
1424 write_int(SNDFILE_VERSION,ham_fp);
1426 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1428 mprintf( (0, "\nDumping sounds..." ));
1430 sound_data_start = ftell(ham_fp);
1431 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1432 data_offset = sound_data_start;
1434 for (i=0; i < Num_sound_files; i++ ) {
1437 snd = &GameSounds[i];
1438 strcpy( sndh.name, AllSounds[i].name );
1439 sndh.length = GameSounds[i].length;
1440 sndh.offset = data_offset - sound_data_start;
1442 org_offset = ftell(ham_fp);
1443 fseek( ham_fp, data_offset, SEEK_SET );
1445 sndh.data_length = GameSounds[i].length;
1446 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1447 data_offset += snd->length;
1448 fseek( ham_fp, org_offset, SEEK_SET );
1449 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1451 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1452 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1456 mprintf( (0, "\n" ));
1459 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1460 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1461 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1466 // Never allow the game to run after building ham.
1480 d_free( SoundBits );
1482 hashtable_free( &AllBitmapsNames );
1483 hashtable_free( &AllDigiSndNames );
1487 int piggy_does_bitmap_exist_slow( char * name )
1491 for (i=0; i<Num_bitmap_files; i++ ) {
1492 if ( !strcmp( AllBitmaps[i].name, name) )
1499 #define NUM_GAUGE_BITMAPS 23
1500 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1501 "gauge01", "gauge01b",
1502 "gauge02", "gauge02b",
1503 "gauge06", "gauge06b",
1504 "targ01", "targ01b",
1505 "targ02", "targ02b",
1506 "targ03", "targ03b",
1507 "targ04", "targ04b",
1508 "targ05", "targ05b",
1509 "targ06", "targ06b",
1510 "gauge18", "gauge18b",
1516 int piggy_is_gauge_bitmap( char * base_name )
1519 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1520 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1527 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1531 char base_name[ 16 ];
1533 strcpy( subst_name, name );
1534 p = strchr( subst_name, '#' );
1536 frame = atoi( &p[1] );
1538 strcpy( base_name, subst_name );
1539 if ( !piggy_is_gauge_bitmap( base_name )) {
1540 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1541 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1543 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1549 strcpy( subst_name, name );
1556 * Functions for loading replacement textures
1557 * 1) From .pog files
1558 * 2) From descent.pig (for loading d1 levels)
1561 extern char last_palette_loaded_pig[];
1563 void free_bitmap_replacements()
1565 if (Bitmap_replacement_data) {
1566 d_free(Bitmap_replacement_data);
1567 Bitmap_replacement_data = NULL;
1571 void load_bitmap_replacements(char *level_name)
1573 char ifile_name[FILENAME_LEN];
1577 //first, free up data allocated for old bitmaps
1578 free_bitmap_replacements();
1580 change_filename_extension(ifile_name, level_name, ".POG" );
1582 ifile = cfopen(ifile_name,"rb");
1585 int id,version,n_bitmaps;
1586 int bitmap_data_size;
1589 id = cfile_read_int(ifile);
1590 version = cfile_read_int(ifile);
1592 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1597 n_bitmaps = cfile_read_int(ifile);
1599 MALLOC( indices, ushort, n_bitmaps );
1601 for (i = 0; i < n_bitmaps; i++)
1602 indices[i] = cfile_read_short(ifile);
1604 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1605 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1607 for (i=0;i<n_bitmaps;i++) {
1608 DiskBitmapHeader bmh;
1609 grs_bitmap *bm = &GameBitmaps[indices[i]];
1612 DiskBitmapHeader_read(&bmh, ifile);
1614 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1615 gr_set_bitmap_data(bm, NULL); // free ogl texture
1616 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1617 bm->avg_color = bmh.avg_color;
1618 bm->bm_data = (ubyte *) bmh.offset;
1620 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1622 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1625 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1627 for (i = 0; i < n_bitmaps; i++)
1629 grs_bitmap *bm = &GameBitmaps[indices[i]];
1630 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1637 last_palette_loaded_pig[0]= 0; //force pig re-load
1639 texmerge_flush(); //for re-merging with new textures
1642 atexit(free_bitmap_replacements);
1645 /* calculate table to translate d1 bitmaps to current palette,
1646 * return -1 on error
1648 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1651 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1652 if (!palette_file || cfilelength(palette_file) != 9472)
1654 cfread( d1_palette, 256, 3, palette_file);
1655 cfclose( palette_file );
1656 build_colormap_good( d1_palette, colormap, freq );
1657 // don't change transparencies:
1658 colormap[254] = 254;
1659 colormap[255] = 255;
1663 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1664 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1665 CFILE *d1_Piggy_fp, /* read from this file */
1666 int bitmap_data_start, /* specific to file */
1667 DiskBitmapHeader *bmh, /* header info for bitmap */
1668 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1669 ubyte *d1_palette, /* what palette the bitmap has */
1670 ubyte *colormap) /* how to translate bitmap's colors */
1672 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1676 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1677 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1678 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1679 bitmap->avg_color = bmh->avg_color;
1680 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1682 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1683 if (bmh->flags & BM_FLAG_RLE) {
1684 zsize = cfile_read_int(d1_Piggy_fp);
1685 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1687 zsize = bitmap->bm_h * bitmap->bm_w;
1690 data = *next_bitmap;
1691 *next_bitmap += zsize;
1693 data = d_malloc(zsize + JUST_IN_CASE);
1697 cfread(data, 1, zsize, d1_Piggy_fp);
1698 gr_set_bitmap_data(bitmap, data);
1700 case D1_MAC_PIGSIZE:
1701 case D1_MAC_SHARE_PIGSIZE:
1702 if (bmh->flags & BM_FLAG_RLE)
1703 rle_swap_0_255(bitmap);
1707 if (bmh->flags & BM_FLAG_RLE)
1708 rle_remap(bitmap, colormap);
1710 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1711 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1713 memcpy(&new_size, bitmap->bm_data, 4);
1715 *next_bitmap += new_size - zsize;
1717 Assert( zsize + JUST_IN_CASE >= new_size );
1718 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1719 Assert(bitmap->bm_data);
1724 #define D1_MAX_TEXTURES 800
1725 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1727 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1728 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1729 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1731 short *d1_tmap_nums = NULL;
1733 void free_d1_tmap_nums() {
1735 d_free(d1_tmap_nums);
1736 d1_tmap_nums = NULL;
1740 void bm_read_d1_tmap_nums(CFILE *d1pig)
1744 free_d1_tmap_nums();
1745 cfseek(d1pig, 8, SEEK_SET);
1746 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1747 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1748 d1_tmap_nums[i] = -1;
1749 for (i = 0; i < D1_MAX_TEXTURES; i++) {
1750 d1_index = cfile_read_short(d1pig);
1751 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1752 d1_tmap_nums[d1_index] = i;
1754 atexit(free_d1_tmap_nums);
1757 void remove_char( char * s, char c )
1764 #define REMOVE_EOL(s) remove_char((s),'\n')
1765 #define REMOVE_COMMENTS(s) remove_char((s),';')
1766 #define REMOVE_DOTS(s) remove_char((s),'.')
1767 char *space = { " \t" };
1768 char *equal_space = { " \t=" };
1770 // this function is at the same position in the d1 shareware piggy loading
1771 // algorithm as bm_load_sub in main/bmread.c
1772 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
1774 DiskBitmapHeader bmh;
1775 if (strchr (filename, '.'))
1776 *strchr (filename, '.') = '\0'; // remove extension
1777 cfseek (d1_pig, 0, SEEK_SET);
1778 N_bitmaps = cfile_read_int (d1_pig);
1779 cfseek (d1_pig, 8, SEEK_SET);
1780 for (i = 1; i <= N_bitmaps; i++) {
1781 DiskBitmapHeader_d1_read(&bmh, d1_pig);
1782 if (!strnicmp(bmh.name, filename, 8))
1788 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
1789 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
1791 #define LINEBUF_SIZE 600
1792 int reading_textures = 0;
1793 short texture_count = 0;
1794 char inputline[LINEBUF_SIZE];
1796 int bitmaps_tbl_is_binary = 0;
1799 bitmaps = cfopen ("bitmaps.tbl", "rb");
1801 bitmaps = cfopen ("bitmaps.bin", "rb");
1802 bitmaps_tbl_is_binary = 1;
1806 Warning ("Could not find bitmaps.* for reading d1 textures");
1810 free_d1_tmap_nums();
1811 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1812 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1813 d1_tmap_nums[i] = -1;
1814 atexit(free_d1_tmap_nums);
1816 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
1819 if (bitmaps_tbl_is_binary)
1820 decode_text_line((inputline));
1822 while (inputline[(i = (int)strlen(inputline)) - 2] == '\\')
1823 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
1824 REMOVE_EOL(inputline);
1825 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
1826 if (strlen(inputline) == LINEBUF_SIZE-1) {
1827 Warning("Possible line truncation in BITMAPS.TBL");
1830 arg = strtok( inputline, space );
1831 if (arg && arg[0] == '@') {
1833 //Registered_only = 1;
1836 while (arg != NULL) {
1838 reading_textures = 0; // default
1839 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
1840 reading_textures = 1;
1841 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
1842 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
1844 else // not a special token, must be a bitmap!
1845 if (reading_textures) {
1846 while (*arg == '\t' || *arg == ' ')
1847 arg++;//remove unwanted blanks
1850 if (d1_tmap_num_unique(texture_count)) {
1851 int d1_index = get_d1_bm_index(arg, d1_pig);
1852 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
1853 d1_tmap_nums[d1_index] = texture_count;
1854 //int d2_index = d2_index_for_d1_index(d1_index);
1857 Assert (texture_count < D1_MAX_TEXTURES);
1861 arg = strtok (NULL, equal_space);
1867 /* If the given d1_index is the index of a bitmap we have to load
1868 * (because it is unique to descent 1), then returns the d2_index that
1869 * the given d1_index replaces.
1870 * Returns -1 if the given d1_index is not unique to descent 1.
1872 short d2_index_for_d1_index(short d1_index)
1874 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1875 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
1876 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
1879 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
1882 #define D1_BITMAPS_SIZE 300000
1883 void load_d1_bitmap_replacements()
1885 CFILE * d1_Piggy_fp;
1886 DiskBitmapHeader bmh;
1887 int pig_data_start, bitmap_header_start, bitmap_data_start;
1889 short d1_index, d2_index;
1891 ubyte colormap[256];
1892 ubyte d1_palette[256*3];
1896 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
1898 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
1900 Warning(D1_PIG_LOAD_FAILED);
1904 //first, free up data allocated for old bitmaps
1905 free_bitmap_replacements();
1907 if (get_d1_colormap( d1_palette, colormap ) != 0)
1908 Warning("Could not load descent 1 color palette");
1910 pigsize = cfilelength(d1_Piggy_fp);
1912 case D1_SHARE_BIG_PIGSIZE:
1913 case D1_SHARE_10_PIGSIZE:
1914 case D1_SHARE_PIGSIZE:
1915 case D1_10_BIG_PIGSIZE:
1918 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
1919 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
1922 Warning("Unknown size for " D1_PIGFILE);
1926 case D1_OEM_PIGSIZE:
1927 case D1_MAC_PIGSIZE:
1928 case D1_MAC_SHARE_PIGSIZE:
1929 pig_data_start = cfile_read_int(d1_Piggy_fp );
1930 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
1931 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
1935 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
1936 N_bitmaps = cfile_read_int(d1_Piggy_fp);
1938 int N_sounds = cfile_read_int(d1_Piggy_fp);
1939 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
1940 + N_sounds * sizeof(DiskSoundHeader);
1941 bitmap_header_start = pig_data_start + 2 * sizeof(int);
1942 bitmap_data_start = bitmap_header_start + header_size;
1945 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
1946 if (!Bitmap_replacement_data) {
1947 Warning(D1_PIG_LOAD_FAILED);
1950 atexit(free_bitmap_replacements);
1952 next_bitmap = Bitmap_replacement_data;
1954 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
1955 d2_index = d2_index_for_d1_index(d1_index);
1956 // only change bitmaps which are unique to d1
1957 if (d2_index != -1) {
1958 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
1959 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
1961 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
1962 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
1963 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
1964 GameBitmapFlags[d2_index] = bmh.flags;
1966 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
1967 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
1968 int i, len = (int)(p - AllBitmaps[d2_index].name);
1969 for (i = 0; i < Num_bitmap_files; i++)
1970 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
1972 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
1973 GameBitmaps[i] = GameBitmaps[d2_index];
1974 GameBitmapOffset[i] = 0;
1975 GameBitmapFlags[i] = bmh.flags;
1981 cfclose(d1_Piggy_fp);
1983 last_palette_loaded_pig[0]= 0; //force pig re-load
1985 texmerge_flush(); //for re-merging with new textures
1989 extern int extra_bitmap_num;
1992 * Find and load the named bitmap from descent.pig
1993 * similar to read_extra_bitmap_iff
1995 bitmap_index read_extra_bitmap_d1_pig(char *name)
1997 bitmap_index bitmap_num;
1998 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2000 bitmap_num.index = 0;
2004 DiskBitmapHeader bmh;
2005 int pig_data_start, bitmap_header_start, bitmap_data_start;
2007 ubyte colormap[256];
2008 ubyte d1_palette[256*3];
2011 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2015 Warning(D1_PIG_LOAD_FAILED);
2019 if (get_d1_colormap( d1_palette, colormap ) != 0)
2020 Warning("Could not load descent 1 color palette");
2022 pigsize = cfilelength(d1_Piggy_fp);
2024 case D1_SHARE_BIG_PIGSIZE:
2025 case D1_SHARE_10_PIGSIZE:
2026 case D1_SHARE_PIGSIZE:
2027 case D1_10_BIG_PIGSIZE:
2032 Warning("Unknown size for " D1_PIGFILE);
2036 case D1_OEM_PIGSIZE:
2037 case D1_MAC_PIGSIZE:
2038 case D1_MAC_SHARE_PIGSIZE:
2039 pig_data_start = cfile_read_int(d1_Piggy_fp );
2044 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2045 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2047 int N_sounds = cfile_read_int(d1_Piggy_fp);
2048 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2049 + N_sounds * sizeof(DiskSoundHeader);
2050 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2051 bitmap_data_start = bitmap_header_start + header_size;
2054 for (i = 1; i <= N_bitmaps; i++)
2056 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2057 if (!strnicmp(bmh.name, name, 8))
2061 if (strnicmp(bmh.name, name, 8))
2063 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2067 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2069 cfclose(d1_Piggy_fp);
2072 new->avg_color = 0; //compute_average_pixel(new);
2074 bitmap_num.index = extra_bitmap_num;
2076 GameBitmaps[extra_bitmap_num++] = *new;
2082 #ifndef FAST_FILE_IO
2084 * reads a bitmap_index structure from a CFILE
2086 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2088 bi->index = cfile_read_short(fp);
2092 * reads n bitmap_index structs from a CFILE
2094 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2098 for (i = 0; i < n; i++)
2099 bi[i].index = cfile_read_short(fp);
2102 #endif // FAST_FILE_IO