2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Functions for managing the pig files.
63 #include <Strings.h> // MacOS Toolbox header
68 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
70 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
71 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
72 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
73 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
75 #define D1_PALETTE "palette.256"
77 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
78 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
79 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
81 #define MAC_ALIEN1_PIGSIZE 5013035
82 #define MAC_ALIEN2_PIGSIZE 4909916
83 #define MAC_FIRE_PIGSIZE 4969035
84 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
85 #define MAC_ICE_PIGSIZE 4923425
86 #define MAC_WATER_PIGSIZE 4832403
88 ubyte *BitmapBits = NULL;
89 ubyte *SoundBits = NULL;
91 typedef struct BitmapFile {
95 typedef struct SoundFile {
99 hashtable AllBitmapsNames;
100 hashtable AllDigiSndNames;
102 int Num_bitmap_files = 0;
103 int Num_sound_files = 0;
105 digi_sound GameSounds[MAX_SOUND_FILES];
106 int SoundOffset[MAX_SOUND_FILES];
107 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
109 alias alias_list[MAX_ALIASES];
112 int Must_write_hamfile = 0;
113 int Num_bitmap_files_new = 0;
114 int Num_sound_files_new = 0;
115 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
116 static SoundFile AllSounds[ MAX_SOUND_FILES ];
118 int Piggy_hamfile_version = 0;
120 int piggy_low_memory = 0;
122 int Piggy_bitmap_cache_size = 0;
123 int Piggy_bitmap_cache_next = 0;
124 ubyte * Piggy_bitmap_cache_data = NULL;
125 static int GameBitmapOffset[MAX_BITMAP_FILES];
126 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
127 ushort GameBitmapXlat[MAX_BITMAP_FILES];
129 #define PIGGY_BUFFER_SIZE (2400*1024)
132 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
135 #undef PIGGY_BUFFER_SIZE
136 #undef PIGGY_SMALL_BUFFER_SIZE
138 #define PIGGY_BUFFER_SIZE (2000*1024)
139 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
144 int piggy_page_flushed = 0;
146 #define DBM_FLAG_ABM 64 // animated bitmap
147 #define DBM_NUM_FRAMES 63
149 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
150 | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
152 typedef struct DiskBitmapHeader {
154 ubyte dflags; // bits 0-5 anim frame num, bit 6 abm flag
155 ubyte width; // low 8 bits here, 4 more bits in wh_extra
156 ubyte height; // low 8 bits here, 4 more bits in wh_extra
157 ubyte wh_extra; // bits 0-3 width, bits 4-7 height
161 } __pack__ DiskBitmapHeader;
163 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
165 typedef struct DiskSoundHeader {
170 } __pack__ DiskSoundHeader;
173 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
174 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
177 * reads a DiskBitmapHeader structure from a CFILE
179 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
181 cfread(dbh->name, 8, 1, fp);
182 dbh->dflags = cfile_read_byte(fp);
183 dbh->width = cfile_read_byte(fp);
184 dbh->height = cfile_read_byte(fp);
185 dbh->wh_extra = cfile_read_byte(fp);
186 dbh->flags = cfile_read_byte(fp);
187 dbh->avg_color = cfile_read_byte(fp);
188 dbh->offset = cfile_read_int(fp);
192 * reads a DiskSoundHeader structure from a CFILE
194 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
196 cfread(dsh->name, 8, 1, fp);
197 dsh->length = cfile_read_int(fp);
198 dsh->data_length = cfile_read_int(fp);
199 dsh->offset = cfile_read_int(fp);
201 #endif // FAST_FILE_IO
204 * reads a descent 1 DiskBitmapHeader structure from a CFILE
206 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
208 cfread(dbh->name, 8, 1, fp);
209 dbh->dflags = cfile_read_byte(fp);
210 dbh->width = cfile_read_byte(fp);
211 dbh->height = cfile_read_byte(fp);
213 dbh->flags = cfile_read_byte(fp);
214 dbh->avg_color = cfile_read_byte(fp);
215 dbh->offset = cfile_read_int(fp);
221 extern short cd_VRefNum;
222 extern void ConcatPStr(StringPtr dst, StringPtr src);
223 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
224 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
227 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
230 void piggy_write_pigfile(char *filename);
231 static void write_int(int i,FILE *file);
234 void swap_0_255(grs_bitmap *bmp)
238 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
239 if(bmp->bm_data[i] == 0)
240 bmp->bm_data[i] = 255;
241 else if (bmp->bm_data[i] == 255)
246 char* piggy_game_bitmap_name(grs_bitmap *bmp)
248 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
250 int i = bmp-GameBitmaps; // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
251 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
252 return AllBitmaps[i].name;
257 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
260 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
262 temp.index = Num_bitmap_files;
266 if ( FindArg("-macdata") )
269 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
270 Num_bitmap_files_new++;
273 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
274 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
275 //GameBitmaps[Num_bitmap_files] = *bmp;
277 GameBitmapOffset[Num_bitmap_files] = 0;
278 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
285 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
289 Assert( Num_sound_files < MAX_SOUND_FILES );
291 strncpy( AllSounds[Num_sound_files].name, name, 12 );
292 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
293 GameSounds[Num_sound_files] = *snd;
295 SoundOffset[Num_sound_files] = 0;
301 Num_sound_files_new++;
307 bitmap_index piggy_find_bitmap( char * name )
315 if ((t=strchr(name,'#'))!=NULL)
318 for (i=0;i<Num_aliases;i++)
319 if (stricmp(name,alias_list[i].alias_name)==0) {
320 if (t) { //extra stuff for ABMs
321 static char temp[FILENAME_LEN];
322 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
328 name=alias_list[i].file_name;
335 i = hashtable_search( &AllBitmapsNames, name );
344 int piggy_find_sound( char * name )
348 i = hashtable_search( &AllDigiSndNames, name );
356 CFILE * Piggy_fp = NULL;
358 #define FILENAME_LEN 13
360 char Current_pigfile[FILENAME_LEN] = "";
362 void piggy_close_file()
367 Current_pigfile[0] = 0;
371 int Pigfile_initialized=0;
373 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
374 #define PIGFILE_VERSION 2
376 extern char CDROM_dir[];
378 int request_cd(void);
383 //copies a pigfile from the CD to the current dir
384 //retuns file handle of new pig
385 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
388 char sourcePathAndFileCStr[255] = "";
389 char destPathAndFileCStr[255] = "";
391 FILE* sourceFile = NULL;
392 FILE* destFile = NULL;
393 const int BUF_SIZE = 4096;
397 Str255 sourcePathAndFilePStr = "\p";
398 Str255 destPathAndFilePStr = "\p";
399 Str255 pigfileNamePStr = "\p";
400 HParamBlockRec theSourcePigHFSParams;
401 HParamBlockRec theDestPigHFSParams;
402 OSErr theErr = noErr;
403 char oldDirCStr[255] = "";
405 getcwd(oldDirCStr, 255);
407 show_boxed_message("Copying bitmap data from CD...");
408 gr_palette_load(gr_palette); //I don't think this line is really needed
411 //First, delete all PIG files currently in the directory
412 if( !FileFindFirst( "*.pig", &find ) )
417 } while( !FileFindNext( &find ) );
423 //Now, copy over new pig
424 songs_stop_redbook(); //so we can read off the cd
426 // make the source path "<cd volume>:Data:filename.pig"
427 //MWA ConvertCToPStr(filename, pigfileNamePStr);
429 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
430 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
433 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
434 strcat(sourcePathAndFileCStr, filename);
436 // make the destination path "<default directory>:Data:filename.pig"
437 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
438 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
439 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
440 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
442 strcpy(destPathAndFileCStr, ":Data:");
443 strcat(destPathAndFileCStr, filename);
445 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
446 strcpy(destPathAndFilePStr, destPathAndFileCStr);
447 c2pstr(sourcePathAndFilePStr);
448 c2pstr(destPathAndFilePStr);
451 // Open the source file
452 sourceFile = fopen(sourcePathAndFileCStr,"rb");
456 if (request_cd() == -1)
457 Error("Cannot load file <%s> from CD",filename);
460 } while (!sourceFile);
463 // Get the time stamp from the source file
464 theSourcePigHFSParams.fileParam.ioCompletion = nil;
465 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
466 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
467 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
468 theSourcePigHFSParams.fileParam.ioDirID = 0;
470 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
473 // Error getting file time stamp!! Why? JTS
474 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
477 // Copy the file over
480 // Open the destination file
481 destFile = fopen(destPathAndFileCStr,"wb");
484 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
487 // Copy bytes until the end of the source file
488 while (!feof(sourceFile))
493 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
494 if (ferror(sourceFile))
495 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
497 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
499 fwrite(buf,1,bytes_read,destFile);
500 if (ferror(destFile))
501 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
504 // close the source/dest files
505 if (fclose(sourceFile))
506 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
507 if (fclose(destFile))
508 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
510 // Get the current hfs data for the new file
511 theDestPigHFSParams.fileParam.ioCompletion = nil;
512 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
513 theDestPigHFSParams.fileParam.ioVRefNum = 0;
514 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
515 theDestPigHFSParams.fileParam.ioDirID = 0;
516 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
517 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
519 // Error getting file time stamp!! Why? JTS
520 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
523 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
524 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
525 theDestPigHFSParams.fileParam.ioVRefNum = 0;
526 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
527 theDestPigHFSParams.fileParam.ioDirID = 0;
529 // Copy the time stamp from the source file info
530 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
531 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
532 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
533 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
535 // Set the dest file's time stamp to the source file's time stamp values
536 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
538 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
540 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
543 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
545 return cfopen(destPathAndFileCStr, "rb");
548 #else //PC Version of copy_pigfile_from_cd is below
550 //copies a pigfile from the CD to the current dir
551 //retuns file handle of new pig
552 CFILE *copy_pigfile_from_cd(char *filename)
559 show_boxed_message("Copying bitmap data from CD...");
560 gr_palette_load(gr_palette); //I don't think this line is really needed
562 //First, delete all PIG files currently in the directory
564 if( !FileFindFirst( "*.pig", &find ) ) {
566 cfile_delete(find.name);
567 } while( !FileFindNext( &find ) );
571 //Now, copy over new pig
573 songs_stop_redbook(); //so we can read off the cd
575 //new code to unarj file
576 strcpy(name,CDROM_dir);
577 strcat(name,"descent2.sow");
580 // ret = unarj_specific_file(name,filename,filename);
585 if (ret != EXIT_SUCCESS) {
587 //delete file, so we don't leave partial file
588 cfile_delete(filename);
591 if (request_cd() == -1)
593 //NOTE LINK TO ABOVE IF
594 Error("Cannot load file <%s> from CD",filename);
597 } while (ret != EXIT_SUCCESS);
600 return cfopen(filename, "rb");
603 #endif // end of ifdef MAC around copy_pigfile_from_cd
605 //initialize a pigfile, reading headers
606 //returns the size of all the bitmap data
607 void piggy_init_pigfile(char *filename)
611 char temp_name_read[16];
612 DiskBitmapHeader bmh;
613 int header_size, N_bitmaps, data_size, data_start;
615 piggy_close_file(); //close old pig if still open
617 //rename pigfile for shareware
618 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
619 filename = DEFAULT_PIGFILE_SHAREWARE;
621 Piggy_fp = cfopen( filename, "rb" );
623 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
624 if (Piggy_fp == NULL)
626 Error("Cannot load required file <%s>",name);
628 #endif // end of if def shareware
632 return; //if editor, ok to not have pig, because we'll build one
634 Piggy_fp = copy_pigfile_from_cd(filename);
638 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
639 int pig_id,pig_version;
641 pig_id = cfile_read_int(Piggy_fp);
642 pig_version = cfile_read_int(Piggy_fp);
643 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
644 cfclose(Piggy_fp); //out of date pig
645 Piggy_fp = NULL; //..so pretend it's not here
652 return; //if editor, ok to not have pig, because we'll build one
654 Error("Cannot load required file <%s>",filename);
658 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
660 N_bitmaps = cfile_read_int(Piggy_fp);
662 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
664 data_start = header_size + cftell(Piggy_fp);
666 data_size = cfilelength(Piggy_fp) - data_start;
668 Num_bitmap_files = 1;
670 for (i=0; i<N_bitmaps; i++ )
673 grs_bitmap *bm = &GameBitmaps[i + 1];
675 DiskBitmapHeader_read(&bmh, Piggy_fp);
676 memcpy( temp_name_read, bmh.name, 8 );
677 temp_name_read[8] = 0;
678 if ( bmh.dflags & DBM_FLAG_ABM )
679 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
681 strcpy( temp_name, temp_name_read );
682 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
683 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
684 bm->bm_flags = BM_FLAG_PAGED_OUT;
685 bm->avg_color = bmh.avg_color;
687 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
689 GameBitmapOffset[i+1] = bmh.offset + data_start;
690 Assert( (i+1) == Num_bitmap_files );
691 piggy_register_bitmap(bm, temp_name, 1);
695 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
696 Assert( Piggy_bitmap_cache_size > 0 );
698 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
700 if (piggy_low_memory)
701 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
704 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
705 if ( BitmapBits == NULL )
706 Error( "Not enough memory to load bitmaps\n" );
707 Piggy_bitmap_cache_data = BitmapBits;
708 Piggy_bitmap_cache_next = 0;
710 #if defined(MACINTOSH) && defined(SHAREWARE)
711 // load_exit_models();
714 Pigfile_initialized=1;
717 #define FILENAME_LEN 13
718 #define MAX_BITMAPS_PER_BRUSH 30
720 extern int compute_average_pixel(grs_bitmap *new);
721 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
723 ubyte *Bitmap_replacement_data = NULL;
725 //reads in a new pigfile (for new palette)
726 //returns the size of all the bitmap data
727 void piggy_new_pigfile(char *pigname)
731 char temp_name_read[16];
732 DiskBitmapHeader bmh;
733 int header_size, N_bitmaps, data_size, data_start;
734 int must_rewrite_pig = 0;
738 //rename pigfile for shareware
739 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
740 pigname = DEFAULT_PIGFILE_SHAREWARE;
742 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
743 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
746 if (!Pigfile_initialized) { //have we ever opened a pigfile?
747 piggy_init_pigfile(pigname); //..no, so do initialization stuff
751 piggy_close_file(); //close old pig if still open
753 Piggy_bitmap_cache_next = 0; //free up cache
755 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
757 Piggy_fp = cfopen( pigname, "rb" );
759 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
760 if (Piggy_fp == NULL)
762 Error("Cannot load required file <%s>",name);
764 #endif // end of if def shareware
768 Piggy_fp = copy_pigfile_from_cd(pigname);
771 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
772 int pig_id,pig_version;
774 pig_id = cfile_read_int(Piggy_fp);
775 pig_version = cfile_read_int(Piggy_fp);
776 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
777 cfclose(Piggy_fp); //out of date pig
778 Piggy_fp = NULL; //..so pretend it's not here
784 Error("Cannot open correct version of <%s>", pigname);
789 N_bitmaps = cfile_read_int(Piggy_fp);
791 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
793 data_start = header_size + cftell(Piggy_fp);
795 data_size = cfilelength(Piggy_fp) - data_start;
797 for (i=1; i<=N_bitmaps; i++ )
799 grs_bitmap *bm = &GameBitmaps[i];
802 DiskBitmapHeader_read(&bmh, Piggy_fp);
803 memcpy( temp_name_read, bmh.name, 8 );
804 temp_name_read[8] = 0;
806 if ( bmh.dflags & DBM_FLAG_ABM )
807 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
809 strcpy( temp_name, temp_name_read );
811 //Make sure name matches
812 if (strcmp(temp_name,AllBitmaps[i].name)) {
813 //Int3(); //this pig is out of date. Delete it
817 strcpy(AllBitmaps[i].name,temp_name);
819 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
820 gr_set_bitmap_data(bm, NULL); // free ogl texture
821 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
822 bm->bm_flags = BM_FLAG_PAGED_OUT;
823 bm->avg_color = bmh.avg_color;
825 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
827 GameBitmapOffset[i] = bmh.offset + data_start;
831 N_bitmaps = 0; //no pigfile, so no bitmaps
835 Assert(N_bitmaps == Num_bitmap_files-1);
839 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
842 //re-read the bitmaps that aren't in this pig
844 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
847 p = strchr(AllBitmaps[i].name,'#');
849 if (p) { // this is an ABM == animated bitmap
850 char abmname[FILENAME_LEN];
852 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
853 int iff_error; //reference parm to avoid warning message
855 char basename[FILENAME_LEN];
858 strcpy(basename,AllBitmaps[i].name);
859 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
861 sprintf( abmname, "%s.abm", basename );
863 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
865 if (iff_error != IFF_NO_ERROR) {
866 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
867 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
870 for (fnum=0;fnum<nframes; fnum++) {
874 sprintf( tempname, "%s#%d", basename, fnum );
876 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
877 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
878 //above makes assumption that supertransparent color is 254
880 if ( iff_has_transparency )
881 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
883 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
885 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
888 if ( FindArg("-macdata") )
889 swap_0_255( bm[fnum] );
891 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
893 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
894 size = *((int *) bm[fnum]->bm_data);
896 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
898 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
899 d_free(bm[fnum]->bm_data);
900 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
901 Piggy_bitmap_cache_next += size;
903 GameBitmaps[i+fnum] = *bm[fnum];
905 // -- mprintf( (0, "U" ));
909 i += nframes-1; //filled in multiple bitmaps
911 else { //this is a BBM
916 char bbmname[FILENAME_LEN];
919 MALLOC( new, grs_bitmap, 1 );
921 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
922 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
925 if (iff_error != IFF_NO_ERROR) {
926 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
927 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
930 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
931 //above makes assumption that supertransparent color is 254
933 if ( iff_has_transparency )
934 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
936 gr_remap_bitmap_good( new, newpal, -1, SuperX );
938 new->avg_color = compute_average_pixel(new);
941 if ( FindArg("-macdata") )
944 if ( !BigPig ) gr_bitmap_rle_compress( new );
946 if (new->bm_flags & BM_FLAG_RLE)
947 size = *((int *) new->bm_data);
949 size = new->bm_w * new->bm_h;
951 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
952 d_free(new->bm_data);
953 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
954 Piggy_bitmap_cache_next += size;
956 GameBitmaps[i] = *new;
960 // -- mprintf( (0, "U" ));
964 //@@Dont' do these things which are done when writing
965 //@@for (i=0; i < Num_bitmap_files; i++ ) {
966 //@@ bitmap_index bi;
968 //@@ PIGGY_PAGE_IN( bi );
971 //@@piggy_close_file();
973 piggy_write_pigfile(pigname);
975 Current_pigfile[0] = 0; //say no pig, to force reload
977 piggy_new_pigfile(pigname); //read in just-generated pig
981 #endif //ifdef EDITOR
985 ubyte bogus_data[64*64];
986 ubyte bogus_bitmap_initialized=0;
987 digi_sound bogus_sound;
989 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
990 #define HAMFILE_VERSION 3
991 //version 1 -> 2: save marker_model_num
992 //version 2 -> 3: removed sound files
994 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
995 #define SNDFILE_VERSION 1
999 CFILE * ham_fp = NULL;
1001 int sound_offset = 0;
1003 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1005 if (ham_fp == NULL) {
1006 Must_write_hamfile = 1;
1010 //make sure ham is valid type file & is up-to-date
1011 ham_id = cfile_read_int(ham_fp);
1012 Piggy_hamfile_version = cfile_read_int(ham_fp);
1013 if (ham_id != HAMFILE_ID)
1014 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1016 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1017 Must_write_hamfile = 1;
1018 cfclose(ham_fp); //out of date ham
1023 if (Piggy_hamfile_version < 3) // hamfile contains sound info
1024 sound_offset = cfile_read_int(ham_fp);
1030 bm_read_all(ham_fp);
1031 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1033 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1034 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1035 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1040 if (Piggy_hamfile_version < 3) {
1045 DiskSoundHeader sndh;
1046 digi_sound temp_sound;
1047 char temp_name_read[16];
1050 cfseek(ham_fp, sound_offset, SEEK_SET);
1051 N_sounds = cfile_read_int(ham_fp);
1053 sound_start = cftell(ham_fp);
1055 header_size = N_sounds * sizeof(DiskSoundHeader);
1059 for (i=0; i<N_sounds; i++ ) {
1060 DiskSoundHeader_read(&sndh, ham_fp);
1061 temp_sound.length = sndh.length;
1062 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1063 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1064 memcpy( temp_name_read, sndh.name, 8 );
1065 temp_name_read[8] = 0;
1066 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1068 if (piggy_is_needed(i))
1069 #endif // note link to if.
1070 sbytes += sndh.length;
1071 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1074 SoundBits = d_malloc( sbytes + 16 );
1075 if ( SoundBits == NULL )
1076 Error( "Not enough memory to load sounds\n" );
1078 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1080 // piggy_read_sounds(ham_fp);
1092 CFILE * snd_fp = NULL;
1093 int snd_id,snd_version;
1098 DiskSoundHeader sndh;
1099 digi_sound temp_sound;
1100 char temp_name_read[16];
1103 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1108 //make sure soundfile is valid type file & is up-to-date
1109 snd_id = cfile_read_int(snd_fp);
1110 snd_version = cfile_read_int(snd_fp);
1111 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1112 cfclose(snd_fp); //out of date sound file
1116 N_sounds = cfile_read_int(snd_fp);
1118 sound_start = cftell(snd_fp);
1119 size = cfilelength(snd_fp) - sound_start;
1121 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1123 header_size = N_sounds*sizeof(DiskSoundHeader);
1127 for (i=0; i<N_sounds; i++ ) {
1128 DiskSoundHeader_read(&sndh, snd_fp);
1129 //size -= sizeof(DiskSoundHeader);
1130 temp_sound.length = sndh.length;
1131 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1132 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1133 memcpy( temp_name_read, sndh.name, 8 );
1134 temp_name_read[8] = 0;
1135 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1137 if (piggy_is_needed(i))
1138 #endif // note link to if.
1139 sbytes += sndh.length;
1140 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1143 SoundBits = d_malloc( sbytes + 16 );
1144 if ( SoundBits == NULL )
1145 Error( "Not enough memory to load sounds\n" );
1147 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1149 // piggy_read_sounds(snd_fp);
1156 int piggy_init(void)
1158 int ham_ok=0,snd_ok=0;
1161 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1162 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1164 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1165 GameSounds[i].length = 0;
1166 GameSounds[i].data = NULL;
1170 for (i=0; i<MAX_BITMAP_FILES; i++ )
1171 GameBitmapXlat[i] = i;
1173 if ( !bogus_bitmap_initialized ) {
1177 bogus_bitmap_initialized = 1;
1178 c = gr_find_closest_color( 0, 0, 63 );
1179 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1180 c = gr_find_closest_color( 63, 0, 0 );
1181 // Make a big red X !
1182 for (i=0; i<64; i++ ) {
1183 bogus_data[i*64+i] = c;
1184 bogus_data[i*64+(63-i)] = c;
1186 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
1187 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
1188 bogus_sound.length = 64*64;
1189 bogus_sound.data = bogus_data;
1190 GameBitmapOffset[0] = 0;
1193 if ( FindArg( "-bigpig" ))
1196 if ( FindArg( "-lowmem" ))
1197 piggy_low_memory = 1;
1199 if ( FindArg( "-nolowmem" ))
1200 piggy_low_memory = 0;
1202 if (piggy_low_memory)
1205 gr_set_curfont( SMALL_FONT );
1206 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1207 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1209 #if 1 //def EDITOR //need for d1 mission briefings
1210 piggy_init_pigfile(DEFAULT_PIGFILE);
1213 snd_ok = ham_ok = read_hamfile();
1215 if (Piggy_hamfile_version >= 3)
1216 snd_ok = read_sndfile();
1218 atexit(piggy_close);
1220 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1221 return (ham_ok && snd_ok); //read ok
1224 int piggy_is_needed(int soundnum)
1228 if ( !digi_lomem ) return 1;
1230 for (i=0; i<MAX_SOUNDS; i++ ) {
1231 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1238 void piggy_read_sounds(void)
1247 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1252 for (i=0; i<Num_sound_files; i++ ) {
1253 digi_sound *snd = &GameSounds[i];
1255 if ( SoundOffset[i] > 0 ) {
1256 if ( piggy_is_needed(i) ) {
1257 cfseek( fp, SoundOffset[i], SEEK_SET );
1259 // Read in the sound data!!!
1262 sbytes += snd->length;
1263 cfread( snd->data, snd->length, 1, fp );
1266 snd->data = (ubyte *) -1;
1272 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1277 extern int descent_critical_error;
1278 extern unsigned descent_critical_deverror;
1279 extern unsigned descent_critical_errcode;
1281 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1282 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1283 "Read fault", "General Failure" };
1285 void piggy_critical_error()
1287 grs_canvas * save_canv;
1288 grs_font * save_font;
1290 save_canv = grd_curcanv;
1291 save_font = grd_curcanv->cv_font;
1292 gr_palette_load( gr_palette );
1293 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1296 gr_set_current_canvas(save_canv);
1297 grd_curcanv->cv_font = save_font;
1300 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1302 void piggy_bitmap_page_in( bitmap_index bitmap )
1311 Assert( i < MAX_BITMAP_FILES );
1312 Assert( i < Num_bitmap_files );
1313 Assert( Piggy_bitmap_cache_size > 0 );
1315 if ( i < 1 ) return;
1316 if ( i >= MAX_BITMAP_FILES ) return;
1317 if ( i >= Num_bitmap_files ) return;
1319 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1321 if ( piggy_low_memory ) {
1323 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1326 bmp = &GameBitmaps[i];
1328 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1332 descent_critical_error = 0;
1333 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1334 if ( descent_critical_error ) {
1335 piggy_critical_error();
1339 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1341 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1342 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1343 descent_critical_error = 0;
1344 zsize = cfile_read_int(Piggy_fp);
1345 if ( descent_critical_error ) {
1346 piggy_critical_error();
1350 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1351 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1352 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1354 piggy_bitmap_page_out_all();
1357 descent_critical_error = 0;
1358 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1359 if ( descent_critical_error ) {
1360 piggy_critical_error();
1363 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1364 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1369 if (!FindArg("-macdata"))
1371 // otherwise, fall through...
1372 case MAC_ALIEN1_PIGSIZE:
1373 case MAC_ALIEN2_PIGSIZE:
1374 case MAC_FIRE_PIGSIZE:
1375 case MAC_GROUPA_PIGSIZE:
1376 case MAC_ICE_PIGSIZE:
1377 case MAC_WATER_PIGSIZE:
1378 rle_swap_0_255( bmp );
1379 memcpy(&zsize, bmp->bm_data, 4);
1384 Piggy_bitmap_cache_next += zsize;
1385 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1387 piggy_bitmap_page_out_all();
1392 int pigsize = cfilelength(Piggy_fp);
1393 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1394 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1395 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1396 piggy_bitmap_page_out_all();
1399 descent_critical_error = 0;
1400 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1401 if ( descent_critical_error ) {
1402 piggy_critical_error();
1405 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1406 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1411 if (!FindArg("-macdata"))
1413 // otherwise, fall through...
1414 case MAC_ALIEN1_PIGSIZE:
1415 case MAC_ALIEN2_PIGSIZE:
1416 case MAC_FIRE_PIGSIZE:
1417 case MAC_GROUPA_PIGSIZE:
1418 case MAC_ICE_PIGSIZE:
1419 case MAC_WATER_PIGSIZE:
1426 //@@if ( bmp->bm_selector ) {
1427 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1428 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1429 //@@ Error( "Error modifying selector base in piggy.c\n" );
1436 if ( piggy_low_memory ) {
1438 GameBitmaps[org_i] = GameBitmaps[i];
1441 //@@Removed from John's code:
1443 //@@ if ( bmp->bm_selector ) {
1444 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1445 //@@ Error( "Error modifying selector base in piggy.c\n" );
1451 void piggy_bitmap_page_out_all()
1455 Piggy_bitmap_cache_next = 0;
1457 piggy_page_flushed++;
1462 for (i=0; i<Num_bitmap_files; i++ ) {
1463 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1464 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1465 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1469 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1472 void piggy_load_level_data()
1474 piggy_bitmap_page_out_all();
1480 void piggy_write_pigfile(char *filename)
1483 int bitmap_data_start, data_offset;
1484 DiskBitmapHeader bmh;
1486 char subst_name[32];
1489 char tname[FILENAME_LEN];
1491 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1492 for (i=0; i < Num_bitmap_files; i++ ) {
1495 PIGGY_PAGE_IN( bi );
1497 // -- mprintf( (0, "\n" ));
1501 // -- mprintf( (0, "Creating %s...",filename ));
1503 pig_fp = fopen( filename, "wb" ); //open PIG file
1504 Assert( pig_fp!=NULL );
1506 write_int(PIGFILE_ID,pig_fp);
1507 write_int(PIGFILE_VERSION,pig_fp);
1510 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1513 bitmap_data_start = ftell(pig_fp);
1514 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1515 data_offset = bitmap_data_start;
1517 change_filename_extension(tname,filename,"lst");
1518 fp1 = fopen( tname, "wt" );
1519 change_filename_extension(tname,filename,"all");
1520 fp2 = fopen( tname, "wt" );
1522 for (i=1; i < Num_bitmap_files; i++ ) {
1528 p = strchr(AllBitmaps[i].name, '#');
1529 if (p) { // this is an ABM == animated bitmap
1535 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1536 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1537 Assert( n <= DBM_NUM_FRAMES );
1538 bmh.dflags = DBM_FLAG_ABM + n;
1542 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1543 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1547 bmp = &GameBitmaps[i];
1549 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1552 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1553 org_offset = ftell(pig_fp);
1554 bmh.offset = data_offset - bitmap_data_start;
1555 fseek( pig_fp, data_offset, SEEK_SET );
1557 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1558 size = (int *)bmp->bm_data;
1559 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1560 data_offset += *size;
1562 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1564 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1565 data_offset += bmp->bm_rowsize * bmp->bm_h;
1567 fprintf( fp1, ".\n" );
1569 fseek( pig_fp, org_offset, SEEK_SET );
1570 Assert( GameBitmaps[i].bm_w < 4096 );
1571 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1572 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1573 Assert( GameBitmaps[i].bm_h < 4096 );
1574 bmh.height = GameBitmaps[i].bm_h;
1575 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1576 bmh.flags = GameBitmaps[i].bm_flags;
1577 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1578 bitmap_index other_bitmap;
1579 other_bitmap = piggy_find_bitmap( subst_name );
1580 GameBitmapXlat[i] = other_bitmap.index;
1581 bmh.flags |= BM_FLAG_PAGED_OUT;
1582 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1583 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1585 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1587 bmh.avg_color=GameBitmaps[i].avg_color;
1588 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1593 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1594 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1601 static void write_int(int i,FILE *file)
1603 if (fwrite( &i, sizeof(i), 1, file) != 1)
1604 Error( "Error reading int in gamesave.c" );
1608 void piggy_dump_all()
1612 int org_offset,data_offset=0;
1613 DiskSoundHeader sndh;
1614 int sound_data_start=0;
1617 #ifdef NO_DUMP_SOUNDS
1618 Num_sound_files = 0;
1619 Num_sound_files_new = 0;
1622 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1625 fp1 = fopen( "ham.lst", "wt" );
1626 fp2 = fopen( "ham.all", "wt" );
1628 if (Must_write_hamfile || Num_bitmap_files_new) {
1630 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1632 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1633 Assert( ham_fp!=NULL );
1635 write_int(HAMFILE_ID,ham_fp);
1636 write_int(HAMFILE_VERSION,ham_fp);
1638 bm_write_all(ham_fp);
1639 xlat_offset = ftell(ham_fp);
1640 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1643 if (Num_bitmap_files_new)
1644 piggy_write_pigfile(DEFAULT_PIGFILE);
1646 //free up memeory used by new bitmaps
1647 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1648 d_free(GameBitmaps[i].bm_data);
1650 //next thing must be done after pig written
1651 fseek( ham_fp, xlat_offset, SEEK_SET );
1652 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1655 mprintf( (0, "\n" ));
1658 if (Num_sound_files_new) {
1660 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1661 // Now dump sound file
1662 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1663 Assert( ham_fp!=NULL );
1665 write_int(SNDFILE_ID,ham_fp);
1666 write_int(SNDFILE_VERSION,ham_fp);
1668 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1670 mprintf( (0, "\nDumping sounds..." ));
1672 sound_data_start = ftell(ham_fp);
1673 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1674 data_offset = sound_data_start;
1676 for (i=0; i < Num_sound_files; i++ ) {
1679 snd = &GameSounds[i];
1680 strcpy( sndh.name, AllSounds[i].name );
1681 sndh.length = GameSounds[i].length;
1682 sndh.offset = data_offset - sound_data_start;
1684 org_offset = ftell(ham_fp);
1685 fseek( ham_fp, data_offset, SEEK_SET );
1687 sndh.data_length = GameSounds[i].length;
1688 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1689 data_offset += snd->length;
1690 fseek( ham_fp, org_offset, SEEK_SET );
1691 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1693 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1694 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1698 mprintf( (0, "\n" ));
1701 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1702 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1703 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1708 // Never allow the game to run after building ham.
1722 d_free( SoundBits );
1724 hashtable_free( &AllBitmapsNames );
1725 hashtable_free( &AllDigiSndNames );
1729 int piggy_does_bitmap_exist_slow( char * name )
1733 for (i=0; i<Num_bitmap_files; i++ ) {
1734 if ( !strcmp( AllBitmaps[i].name, name) )
1741 #define NUM_GAUGE_BITMAPS 23
1742 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1743 "gauge01", "gauge01b",
1744 "gauge02", "gauge02b",
1745 "gauge06", "gauge06b",
1746 "targ01", "targ01b",
1747 "targ02", "targ02b",
1748 "targ03", "targ03b",
1749 "targ04", "targ04b",
1750 "targ05", "targ05b",
1751 "targ06", "targ06b",
1752 "gauge18", "gauge18b",
1758 int piggy_is_gauge_bitmap( char * base_name )
1761 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1762 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1769 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1773 char base_name[ 16 ];
1775 strcpy( subst_name, name );
1776 p = strchr( subst_name, '#' );
1778 frame = atoi( &p[1] );
1780 strcpy( base_name, subst_name );
1781 if ( !piggy_is_gauge_bitmap( base_name )) {
1782 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1783 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1785 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1791 strcpy( subst_name, name );
1798 * Functions for loading replacement textures
1799 * 1) From .pog files
1800 * 2) From descent.pig (for loading d1 levels)
1803 extern char last_palette_loaded_pig[];
1805 void free_bitmap_replacements()
1807 if (Bitmap_replacement_data) {
1808 d_free(Bitmap_replacement_data);
1809 Bitmap_replacement_data = NULL;
1813 void load_bitmap_replacements(char *level_name)
1815 char ifile_name[FILENAME_LEN];
1819 //first, free up data allocated for old bitmaps
1820 free_bitmap_replacements();
1822 change_filename_extension(ifile_name, level_name, ".POG" );
1824 ifile = cfopen(ifile_name,"rb");
1827 int id,version,n_bitmaps;
1828 int bitmap_data_size;
1831 id = cfile_read_int(ifile);
1832 version = cfile_read_int(ifile);
1834 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1839 n_bitmaps = cfile_read_int(ifile);
1841 MALLOC( indices, ushort, n_bitmaps );
1843 for (i = 0; i < n_bitmaps; i++)
1844 indices[i] = cfile_read_short(ifile);
1846 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1847 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1849 for (i=0;i<n_bitmaps;i++) {
1850 DiskBitmapHeader bmh;
1851 grs_bitmap *bm = &GameBitmaps[indices[i]];
1854 DiskBitmapHeader_read(&bmh, ifile);
1856 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1857 gr_set_bitmap_data(bm, NULL); // free ogl texture
1858 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1859 bm->avg_color = bmh.avg_color;
1860 bm->bm_data = (ubyte *) bmh.offset;
1862 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1864 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1867 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1869 for (i = 0; i < n_bitmaps; i++)
1871 grs_bitmap *bm = &GameBitmaps[indices[i]];
1872 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1879 last_palette_loaded_pig[0]= 0; //force pig re-load
1881 texmerge_flush(); //for re-merging with new textures
1884 atexit(free_bitmap_replacements);
1887 /* calculate table to translate d1 bitmaps to current palette,
1888 * return -1 on error
1890 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1893 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1894 if (!palette_file || cfilelength(palette_file) != 9472)
1896 cfread( d1_palette, 256, 3, palette_file);
1897 cfclose( palette_file );
1898 build_colormap_good( d1_palette, colormap, freq );
1899 // don't change transparencies:
1900 colormap[254] = 254;
1901 colormap[255] = 255;
1905 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1906 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1907 CFILE *d1_Piggy_fp, /* read from this file */
1908 int bitmap_data_start, /* specific to file */
1909 DiskBitmapHeader *bmh, /* header info for bitmap */
1910 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1911 ubyte *d1_palette, /* what palette the bitmap has */
1912 ubyte *colormap) /* how to translate bitmap's colors */
1914 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1918 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1919 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1920 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1921 bitmap->avg_color = bmh->avg_color;
1922 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1924 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1925 if (bmh->flags & BM_FLAG_RLE) {
1926 zsize = cfile_read_int(d1_Piggy_fp);
1927 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1929 zsize = bitmap->bm_h * bitmap->bm_w;
1932 data = *next_bitmap;
1933 *next_bitmap += zsize;
1935 data = d_malloc(zsize + JUST_IN_CASE);
1939 cfread(data, 1, zsize, d1_Piggy_fp);
1940 gr_set_bitmap_data(bitmap, data);
1942 case D1_MAC_PIGSIZE:
1943 case D1_MAC_SHARE_PIGSIZE:
1944 if (bmh->flags & BM_FLAG_RLE)
1945 rle_swap_0_255(bitmap);
1949 if (bmh->flags & BM_FLAG_RLE)
1950 rle_remap(bitmap, colormap);
1952 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1953 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1955 memcpy(&new_size, bitmap->bm_data, 4);
1957 *next_bitmap += new_size - zsize;
1959 Assert( zsize + JUST_IN_CASE >= new_size );
1960 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1961 Assert(bitmap->bm_data);
1966 #define D1_MAX_TEXTURES 800
1967 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1969 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1970 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1971 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1973 short *d1_tmap_nums = NULL;
1975 void free_d1_tmap_nums() {
1977 d_free(d1_tmap_nums);
1978 d1_tmap_nums = NULL;
1982 void bm_read_d1_tmap_nums(CFILE *d1pig)
1986 free_d1_tmap_nums();
1987 cfseek(d1pig, 8, SEEK_SET);
1988 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1989 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1990 d1_tmap_nums[i] = -1;
1991 for (i = 0; i < D1_MAX_TEXTURES; i++) {
1992 d1_index = cfile_read_short(d1pig);
1993 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1994 d1_tmap_nums[d1_index] = i;
1996 atexit(free_d1_tmap_nums);
1999 void remove_char( char * s, char c )
2006 #define REMOVE_EOL(s) remove_char((s),'\n')
2007 #define REMOVE_COMMENTS(s) remove_char((s),';')
2008 #define REMOVE_DOTS(s) remove_char((s),'.')
2009 char *space = { " \t" };
2010 char *equal_space = { " \t=" };
2012 // this function is at the same position in the d1 shareware piggy loading
2013 // algorithm as bm_load_sub in main/bmread.c
2014 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2016 DiskBitmapHeader bmh;
2017 if (strchr (filename, '.'))
2018 *strchr (filename, '.') = '\0'; // remove extension
2019 cfseek (d1_pig, 0, SEEK_SET);
2020 N_bitmaps = cfile_read_int (d1_pig);
2021 cfseek (d1_pig, 8, SEEK_SET);
2022 for (i = 1; i <= N_bitmaps; i++) {
2023 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2024 if (!strnicmp(bmh.name, filename, 8))
2030 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2031 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2033 #define LINEBUF_SIZE 600
2034 int reading_textures = 0;
2035 short texture_count = 0;
2036 char inputline[LINEBUF_SIZE];
2038 int bitmaps_tbl_is_binary = 0;
2041 bitmaps = cfopen ("bitmaps.tbl", "rb");
2043 bitmaps = cfopen ("bitmaps.bin", "rb");
2044 bitmaps_tbl_is_binary = 1;
2048 Warning ("Could not find bitmaps.* for reading d1 textures");
2052 free_d1_tmap_nums();
2053 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2054 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2055 d1_tmap_nums[i] = -1;
2056 atexit(free_d1_tmap_nums);
2058 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2061 if (bitmaps_tbl_is_binary)
2062 decode_text_line((inputline));
2064 while (inputline[(i=strlen(inputline))-2]=='\\')
2065 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2066 REMOVE_EOL(inputline);
2067 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2068 if (strlen(inputline) == LINEBUF_SIZE-1) {
2069 Warning("Possible line truncation in BITMAPS.TBL");
2072 arg = strtok( inputline, space );
2073 if (arg && arg[0] == '@') {
2075 //Registered_only = 1;
2078 while (arg != NULL) {
2080 reading_textures = 0; // default
2081 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2082 reading_textures = 1;
2083 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2084 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2086 else // not a special token, must be a bitmap!
2087 if (reading_textures) {
2088 while (*arg == '\t' || *arg == ' ')
2089 arg++;//remove unwanted blanks
2092 if (d1_tmap_num_unique(texture_count)) {
2093 int d1_index = get_d1_bm_index(arg, d1_pig);
2094 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2095 d1_tmap_nums[d1_index] = texture_count;
2096 //int d2_index = d2_index_for_d1_index(d1_index);
2099 Assert (texture_count < D1_MAX_TEXTURES);
2103 arg = strtok (NULL, equal_space);
2109 /* If the given d1_index is the index of a bitmap we have to load
2110 * (because it is unique to descent 1), then returns the d2_index that
2111 * the given d1_index replaces.
2112 * Returns -1 if the given d1_index is not unique to descent 1.
2114 short d2_index_for_d1_index(short d1_index)
2116 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2117 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2118 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2121 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2124 #define D1_BITMAPS_SIZE 300000
2125 void load_d1_bitmap_replacements()
2127 CFILE * d1_Piggy_fp;
2128 DiskBitmapHeader bmh;
2129 int pig_data_start, bitmap_header_start, bitmap_data_start;
2131 short d1_index, d2_index;
2133 ubyte colormap[256];
2134 ubyte d1_palette[256*3];
2138 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2140 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2142 Warning(D1_PIG_LOAD_FAILED);
2146 //first, free up data allocated for old bitmaps
2147 free_bitmap_replacements();
2149 if (get_d1_colormap( d1_palette, colormap ) != 0)
2150 Warning("Could not load descent 1 color palette");
2152 pigsize = cfilelength(d1_Piggy_fp);
2154 case D1_SHARE_BIG_PIGSIZE:
2155 case D1_SHARE_10_PIGSIZE:
2156 case D1_SHARE_PIGSIZE:
2157 case D1_10_BIG_PIGSIZE:
2160 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2161 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2164 Warning("Unknown size for " D1_PIGFILE);
2168 case D1_OEM_PIGSIZE:
2169 case D1_MAC_PIGSIZE:
2170 case D1_MAC_SHARE_PIGSIZE:
2171 pig_data_start = cfile_read_int(d1_Piggy_fp );
2172 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2173 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2177 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2178 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2180 int N_sounds = cfile_read_int(d1_Piggy_fp);
2181 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2182 + N_sounds * sizeof(DiskSoundHeader);
2183 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2184 bitmap_data_start = bitmap_header_start + header_size;
2187 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2188 if (!Bitmap_replacement_data) {
2189 Warning(D1_PIG_LOAD_FAILED);
2192 atexit(free_bitmap_replacements);
2194 next_bitmap = Bitmap_replacement_data;
2196 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2197 d2_index = d2_index_for_d1_index(d1_index);
2198 // only change bitmaps which are unique to d1
2199 if (d2_index != -1) {
2200 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2201 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2203 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2204 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2205 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2206 GameBitmapFlags[d2_index] = bmh.flags;
2208 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2209 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2210 int i, len = p - AllBitmaps[d2_index].name;
2211 for (i = 0; i < Num_bitmap_files; i++)
2212 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
2214 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
2215 GameBitmaps[i] = GameBitmaps[d2_index];
2216 GameBitmapOffset[i] = 0;
2217 GameBitmapFlags[i] = bmh.flags;
2223 cfclose(d1_Piggy_fp);
2225 last_palette_loaded_pig[0]= 0; //force pig re-load
2227 texmerge_flush(); //for re-merging with new textures
2231 extern int extra_bitmap_num;
2234 * Find and load the named bitmap from descent.pig
2235 * similar to read_extra_bitmap_iff
2237 bitmap_index read_extra_bitmap_d1_pig(char *name)
2239 bitmap_index bitmap_num;
2240 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2242 bitmap_num.index = 0;
2246 DiskBitmapHeader bmh;
2247 int pig_data_start, bitmap_header_start, bitmap_data_start;
2249 ubyte colormap[256];
2250 ubyte d1_palette[256*3];
2253 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2257 Warning(D1_PIG_LOAD_FAILED);
2261 if (get_d1_colormap( d1_palette, colormap ) != 0)
2262 Warning("Could not load descent 1 color palette");
2264 pigsize = cfilelength(d1_Piggy_fp);
2266 case D1_SHARE_BIG_PIGSIZE:
2267 case D1_SHARE_10_PIGSIZE:
2268 case D1_SHARE_PIGSIZE:
2269 case D1_10_BIG_PIGSIZE:
2274 Warning("Unknown size for " D1_PIGFILE);
2278 case D1_OEM_PIGSIZE:
2279 case D1_MAC_PIGSIZE:
2280 case D1_MAC_SHARE_PIGSIZE:
2281 pig_data_start = cfile_read_int(d1_Piggy_fp );
2286 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2287 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2289 int N_sounds = cfile_read_int(d1_Piggy_fp);
2290 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2291 + N_sounds * sizeof(DiskSoundHeader);
2292 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2293 bitmap_data_start = bitmap_header_start + header_size;
2296 for (i = 1; i <= N_bitmaps; i++)
2298 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2299 if (!strnicmp(bmh.name, name, 8))
2303 if (strnicmp(bmh.name, name, 8))
2305 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2309 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2311 cfclose(d1_Piggy_fp);
2314 new->avg_color = 0; //compute_average_pixel(new);
2316 bitmap_num.index = extra_bitmap_num;
2318 GameBitmaps[extra_bitmap_num++] = *new;
2324 #ifndef FAST_FILE_IO
2326 * reads a bitmap_index structure from a CFILE
2328 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2330 bi->index = cfile_read_short(fp);
2334 * reads n bitmap_index structs from a CFILE
2336 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2340 for (i = 0; i < n; i++)
2341 bi[i].index = cfile_read_short(fp);
2344 #endif // FAST_FILE_IO