1 /* $Id: piggy.c,v 1.64 2006-02-26 02:29:06 chris Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Functions for managing the pig files.
27 static char rcsid[] = "$Id: piggy.c,v 1.64 2006-02-26 02:29:06 chris Exp $";
68 #include <Strings.h> // MacOS Toolbox header
73 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
75 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
76 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
77 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
78 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
80 #define D1_PALETTE "palette.256"
82 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
83 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
84 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
86 #define MAC_ALIEN1_PIGSIZE 5013035
87 #define MAC_ALIEN2_PIGSIZE 4909916
88 #define MAC_FIRE_PIGSIZE 4969035
89 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
90 #define MAC_ICE_PIGSIZE 4923425
91 #define MAC_WATER_PIGSIZE 4832403
93 ubyte *BitmapBits = NULL;
94 ubyte *SoundBits = NULL;
96 typedef struct BitmapFile {
100 typedef struct SoundFile {
104 hashtable AllBitmapsNames;
105 hashtable AllDigiSndNames;
107 int Num_bitmap_files = 0;
108 int Num_sound_files = 0;
110 digi_sound GameSounds[MAX_SOUND_FILES];
111 int SoundOffset[MAX_SOUND_FILES];
112 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
114 alias alias_list[MAX_ALIASES];
117 int Must_write_hamfile = 0;
118 int Num_bitmap_files_new = 0;
119 int Num_sound_files_new = 0;
120 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
121 static SoundFile AllSounds[ MAX_SOUND_FILES ];
123 int Piggy_hamfile_version = 0;
125 int piggy_low_memory = 0;
127 int Piggy_bitmap_cache_size = 0;
128 int Piggy_bitmap_cache_next = 0;
129 ubyte * Piggy_bitmap_cache_data = NULL;
130 static int GameBitmapOffset[MAX_BITMAP_FILES];
131 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
132 ushort GameBitmapXlat[MAX_BITMAP_FILES];
134 #define PIGGY_BUFFER_SIZE (2400*1024)
137 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
140 #undef PIGGY_BUFFER_SIZE
141 #undef PIGGY_SMALL_BUFFER_SIZE
143 #define PIGGY_BUFFER_SIZE (2000*1024)
144 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
149 int piggy_page_flushed = 0;
151 #define DBM_FLAG_ABM 64 // animated bitmap
152 #define DBM_NUM_FRAMES 63
154 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
155 | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
157 typedef struct DiskBitmapHeader {
159 ubyte dflags; // bits 0-5 anim frame num, bit 6 abm flag
160 ubyte width; // low 8 bits here, 4 more bits in wh_extra
161 ubyte height; // low 8 bits here, 4 more bits in wh_extra
162 ubyte wh_extra; // bits 0-3 width, bits 4-7 height
166 } __pack__ DiskBitmapHeader;
168 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
170 typedef struct DiskSoundHeader {
175 } __pack__ DiskSoundHeader;
178 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
179 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
182 * reads a DiskBitmapHeader structure from a CFILE
184 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
186 cfread(dbh->name, 8, 1, fp);
187 dbh->dflags = cfile_read_byte(fp);
188 dbh->width = cfile_read_byte(fp);
189 dbh->height = cfile_read_byte(fp);
190 dbh->wh_extra = cfile_read_byte(fp);
191 dbh->flags = cfile_read_byte(fp);
192 dbh->avg_color = cfile_read_byte(fp);
193 dbh->offset = cfile_read_int(fp);
197 * reads a DiskSoundHeader structure from a CFILE
199 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
201 cfread(dsh->name, 8, 1, fp);
202 dsh->length = cfile_read_int(fp);
203 dsh->data_length = cfile_read_int(fp);
204 dsh->offset = cfile_read_int(fp);
206 #endif // FAST_FILE_IO
209 * reads a descent 1 DiskBitmapHeader structure from a CFILE
211 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
213 cfread(dbh->name, 8, 1, fp);
214 dbh->dflags = cfile_read_byte(fp);
215 dbh->width = cfile_read_byte(fp);
216 dbh->height = cfile_read_byte(fp);
218 dbh->flags = cfile_read_byte(fp);
219 dbh->avg_color = cfile_read_byte(fp);
220 dbh->offset = cfile_read_int(fp);
226 extern short cd_VRefNum;
227 extern void ConcatPStr(StringPtr dst, StringPtr src);
228 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
229 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
232 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
235 void piggy_write_pigfile(char *filename);
236 static void write_int(int i,FILE *file);
239 void swap_0_255(grs_bitmap *bmp)
243 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
244 if(bmp->bm_data[i] == 0)
245 bmp->bm_data[i] = 255;
246 else if (bmp->bm_data[i] == 255)
251 char* piggy_game_bitmap_name(grs_bitmap *bmp)
253 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
255 int i = bmp-GameBitmaps; // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
256 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
257 return AllBitmaps[i].name;
262 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
265 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
267 temp.index = Num_bitmap_files;
271 if ( FindArg("-macdata") )
274 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
275 Num_bitmap_files_new++;
278 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
279 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
280 //GameBitmaps[Num_bitmap_files] = *bmp;
282 GameBitmapOffset[Num_bitmap_files] = 0;
283 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
290 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
294 Assert( Num_sound_files < MAX_SOUND_FILES );
296 strncpy( AllSounds[Num_sound_files].name, name, 12 );
297 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
298 GameSounds[Num_sound_files] = *snd;
300 SoundOffset[Num_sound_files] = 0;
306 Num_sound_files_new++;
312 bitmap_index piggy_find_bitmap( char * name )
320 if ((t=strchr(name,'#'))!=NULL)
323 for (i=0;i<Num_aliases;i++)
324 if (stricmp(name,alias_list[i].alias_name)==0) {
325 if (t) { //extra stuff for ABMs
326 static char temp[FILENAME_LEN];
327 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
333 name=alias_list[i].file_name;
340 i = hashtable_search( &AllBitmapsNames, name );
349 int piggy_find_sound( char * name )
353 i = hashtable_search( &AllDigiSndNames, name );
361 CFILE * Piggy_fp = NULL;
363 #define FILENAME_LEN 13
365 char Current_pigfile[FILENAME_LEN] = "";
367 void piggy_close_file()
372 Current_pigfile[0] = 0;
376 int Pigfile_initialized=0;
378 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
379 #define PIGFILE_VERSION 2
381 extern char CDROM_dir[];
383 int request_cd(void);
388 //copies a pigfile from the CD to the current dir
389 //retuns file handle of new pig
390 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
393 char sourcePathAndFileCStr[255] = "";
394 char destPathAndFileCStr[255] = "";
396 FILE* sourceFile = NULL;
397 FILE* destFile = NULL;
398 const int BUF_SIZE = 4096;
402 Str255 sourcePathAndFilePStr = "\p";
403 Str255 destPathAndFilePStr = "\p";
404 Str255 pigfileNamePStr = "\p";
405 HParamBlockRec theSourcePigHFSParams;
406 HParamBlockRec theDestPigHFSParams;
407 OSErr theErr = noErr;
408 char oldDirCStr[255] = "";
410 getcwd(oldDirCStr, 255);
412 show_boxed_message("Copying bitmap data from CD...");
413 gr_palette_load(gr_palette); //I don't think this line is really needed
416 //First, delete all PIG files currently in the directory
417 if( !FileFindFirst( "*.pig", &find ) )
422 } while( !FileFindNext( &find ) );
428 //Now, copy over new pig
429 songs_stop_redbook(); //so we can read off the cd
431 // make the source path "<cd volume>:Data:filename.pig"
432 //MWA ConvertCToPStr(filename, pigfileNamePStr);
434 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
435 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
438 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
439 strcat(sourcePathAndFileCStr, filename);
441 // make the destination path "<default directory>:Data:filename.pig"
442 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
443 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
444 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
445 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
447 strcpy(destPathAndFileCStr, ":Data:");
448 strcat(destPathAndFileCStr, filename);
450 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
451 strcpy(destPathAndFilePStr, destPathAndFileCStr);
452 c2pstr(sourcePathAndFilePStr);
453 c2pstr(destPathAndFilePStr);
456 // Open the source file
457 sourceFile = fopen(sourcePathAndFileCStr,"rb");
461 if (request_cd() == -1)
462 Error("Cannot load file <%s> from CD",filename);
465 } while (!sourceFile);
468 // Get the time stamp from the source file
469 theSourcePigHFSParams.fileParam.ioCompletion = nil;
470 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
471 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
472 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
473 theSourcePigHFSParams.fileParam.ioDirID = 0;
475 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
478 // Error getting file time stamp!! Why? JTS
479 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
482 // Copy the file over
485 // Open the destination file
486 destFile = fopen(destPathAndFileCStr,"wb");
489 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
492 // Copy bytes until the end of the source file
493 while (!feof(sourceFile))
498 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
499 if (ferror(sourceFile))
500 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
502 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
504 fwrite(buf,1,bytes_read,destFile);
505 if (ferror(destFile))
506 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
509 // close the source/dest files
510 if (fclose(sourceFile))
511 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
512 if (fclose(destFile))
513 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
515 // Get the current hfs data for the new file
516 theDestPigHFSParams.fileParam.ioCompletion = nil;
517 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
518 theDestPigHFSParams.fileParam.ioVRefNum = 0;
519 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
520 theDestPigHFSParams.fileParam.ioDirID = 0;
521 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
522 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
524 // Error getting file time stamp!! Why? JTS
525 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
528 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
529 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
530 theDestPigHFSParams.fileParam.ioVRefNum = 0;
531 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
532 theDestPigHFSParams.fileParam.ioDirID = 0;
534 // Copy the time stamp from the source file info
535 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
536 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
537 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
538 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
540 // Set the dest file's time stamp to the source file's time stamp values
541 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
543 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
545 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
548 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
550 return cfopen(destPathAndFileCStr, "rb");
553 #else //PC Version of copy_pigfile_from_cd is below
555 //copies a pigfile from the CD to the current dir
556 //retuns file handle of new pig
557 CFILE *copy_pigfile_from_cd(char *filename)
564 show_boxed_message("Copying bitmap data from CD...");
565 gr_palette_load(gr_palette); //I don't think this line is really needed
567 //First, delete all PIG files currently in the directory
569 if( !FileFindFirst( "*.pig", &find ) ) {
571 cfile_delete(find.name);
572 } while( !FileFindNext( &find ) );
576 //Now, copy over new pig
578 songs_stop_redbook(); //so we can read off the cd
580 //new code to unarj file
581 strcpy(name,CDROM_dir);
582 strcat(name,"descent2.sow");
585 // ret = unarj_specific_file(name,filename,filename);
590 if (ret != EXIT_SUCCESS) {
592 //delete file, so we don't leave partial file
593 cfile_delete(filename);
596 if (request_cd() == -1)
598 //NOTE LINK TO ABOVE IF
599 Error("Cannot load file <%s> from CD",filename);
602 } while (ret != EXIT_SUCCESS);
605 return cfopen(filename, "rb");
608 #endif // end of ifdef MAC around copy_pigfile_from_cd
610 //initialize a pigfile, reading headers
611 //returns the size of all the bitmap data
612 void piggy_init_pigfile(char *filename)
616 char temp_name_read[16];
617 DiskBitmapHeader bmh;
618 int header_size, N_bitmaps, data_size, data_start;
620 piggy_close_file(); //close old pig if still open
622 //rename pigfile for shareware
623 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
624 filename = DEFAULT_PIGFILE_SHAREWARE;
626 Piggy_fp = cfopen( filename, "rb" );
628 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
629 if (Piggy_fp == NULL)
631 Error("Cannot load required file <%s>",name);
633 #endif // end of if def shareware
637 return; //if editor, ok to not have pig, because we'll build one
639 Piggy_fp = copy_pigfile_from_cd(filename);
643 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
644 int pig_id,pig_version;
646 pig_id = cfile_read_int(Piggy_fp);
647 pig_version = cfile_read_int(Piggy_fp);
648 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
649 cfclose(Piggy_fp); //out of date pig
650 Piggy_fp = NULL; //..so pretend it's not here
657 return; //if editor, ok to not have pig, because we'll build one
659 Error("Cannot load required file <%s>",filename);
663 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
665 N_bitmaps = cfile_read_int(Piggy_fp);
667 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
669 data_start = header_size + cftell(Piggy_fp);
671 data_size = cfilelength(Piggy_fp) - data_start;
673 Num_bitmap_files = 1;
675 for (i=0; i<N_bitmaps; i++ )
678 grs_bitmap *bm = &GameBitmaps[i + 1];
680 DiskBitmapHeader_read(&bmh, Piggy_fp);
681 memcpy( temp_name_read, bmh.name, 8 );
682 temp_name_read[8] = 0;
683 if ( bmh.dflags & DBM_FLAG_ABM )
684 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
686 strcpy( temp_name, temp_name_read );
687 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
688 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
689 bm->bm_flags = BM_FLAG_PAGED_OUT;
690 bm->avg_color = bmh.avg_color;
692 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
694 GameBitmapOffset[i+1] = bmh.offset + data_start;
695 Assert( (i+1) == Num_bitmap_files );
696 piggy_register_bitmap(bm, temp_name, 1);
700 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
701 Assert( Piggy_bitmap_cache_size > 0 );
703 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
705 if (piggy_low_memory)
706 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
709 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
710 if ( BitmapBits == NULL )
711 Error( "Not enough memory to load bitmaps\n" );
712 Piggy_bitmap_cache_data = BitmapBits;
713 Piggy_bitmap_cache_next = 0;
715 #if defined(MACINTOSH) && defined(SHAREWARE)
716 // load_exit_models();
719 Pigfile_initialized=1;
722 #define FILENAME_LEN 13
723 #define MAX_BITMAPS_PER_BRUSH 30
725 extern int compute_average_pixel(grs_bitmap *new);
726 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
728 ubyte *Bitmap_replacement_data = NULL;
730 //reads in a new pigfile (for new palette)
731 //returns the size of all the bitmap data
732 void piggy_new_pigfile(char *pigname)
736 char temp_name_read[16];
737 DiskBitmapHeader bmh;
738 int header_size, N_bitmaps, data_size, data_start;
739 int must_rewrite_pig = 0;
743 //rename pigfile for shareware
744 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
745 pigname = DEFAULT_PIGFILE_SHAREWARE;
747 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
748 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
751 if (!Pigfile_initialized) { //have we ever opened a pigfile?
752 piggy_init_pigfile(pigname); //..no, so do initialization stuff
756 piggy_close_file(); //close old pig if still open
758 Piggy_bitmap_cache_next = 0; //free up cache
760 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
762 Piggy_fp = cfopen( pigname, "rb" );
764 #if defined(MACINTOSH) && defined(SHAREWARE) // if we are in the shareware version, we must have the pig by now.
765 if (Piggy_fp == NULL)
767 Error("Cannot load required file <%s>",name);
769 #endif // end of if def shareware
773 Piggy_fp = copy_pigfile_from_cd(pigname);
776 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
777 int pig_id,pig_version;
779 pig_id = cfile_read_int(Piggy_fp);
780 pig_version = cfile_read_int(Piggy_fp);
781 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
782 cfclose(Piggy_fp); //out of date pig
783 Piggy_fp = NULL; //..so pretend it's not here
789 Error("Cannot open correct version of <%s>", pigname);
794 N_bitmaps = cfile_read_int(Piggy_fp);
796 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
798 data_start = header_size + cftell(Piggy_fp);
800 data_size = cfilelength(Piggy_fp) - data_start;
802 for (i=1; i<=N_bitmaps; i++ )
804 grs_bitmap *bm = &GameBitmaps[i];
807 DiskBitmapHeader_read(&bmh, Piggy_fp);
808 memcpy( temp_name_read, bmh.name, 8 );
809 temp_name_read[8] = 0;
811 if ( bmh.dflags & DBM_FLAG_ABM )
812 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
814 strcpy( temp_name, temp_name_read );
816 //Make sure name matches
817 if (strcmp(temp_name,AllBitmaps[i].name)) {
818 //Int3(); //this pig is out of date. Delete it
822 strcpy(AllBitmaps[i].name,temp_name);
824 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
825 gr_set_bitmap_data(bm, NULL); // free ogl texture
826 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
827 bm->bm_flags = BM_FLAG_PAGED_OUT;
828 bm->avg_color = bmh.avg_color;
830 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
832 GameBitmapOffset[i] = bmh.offset + data_start;
836 N_bitmaps = 0; //no pigfile, so no bitmaps
840 Assert(N_bitmaps == Num_bitmap_files-1);
844 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
847 //re-read the bitmaps that aren't in this pig
849 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
852 p = strchr(AllBitmaps[i].name,'#');
854 if (p) { // this is an ABM == animated bitmap
855 char abmname[FILENAME_LEN];
857 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
858 int iff_error; //reference parm to avoid warning message
860 char basename[FILENAME_LEN];
863 strcpy(basename,AllBitmaps[i].name);
864 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
866 sprintf( abmname, "%s.abm", basename );
868 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
870 if (iff_error != IFF_NO_ERROR) {
871 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
872 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
875 for (fnum=0;fnum<nframes; fnum++) {
879 sprintf( tempname, "%s#%d", basename, fnum );
881 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
882 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
883 //above makes assumption that supertransparent color is 254
885 if ( iff_has_transparency )
886 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
888 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
890 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
893 if ( FindArg("-macdata") )
894 swap_0_255( bm[fnum] );
896 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
898 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
899 size = *((int *) bm[fnum]->bm_data);
901 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
903 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
904 d_free(bm[fnum]->bm_data);
905 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
906 Piggy_bitmap_cache_next += size;
908 GameBitmaps[i+fnum] = *bm[fnum];
910 // -- mprintf( (0, "U" ));
914 i += nframes-1; //filled in multiple bitmaps
916 else { //this is a BBM
921 char bbmname[FILENAME_LEN];
924 MALLOC( new, grs_bitmap, 1 );
926 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
927 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
930 if (iff_error != IFF_NO_ERROR) {
931 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
932 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
935 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
936 //above makes assumption that supertransparent color is 254
938 if ( iff_has_transparency )
939 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
941 gr_remap_bitmap_good( new, newpal, -1, SuperX );
943 new->avg_color = compute_average_pixel(new);
946 if ( FindArg("-macdata") )
949 if ( !BigPig ) gr_bitmap_rle_compress( new );
951 if (new->bm_flags & BM_FLAG_RLE)
952 size = *((int *) new->bm_data);
954 size = new->bm_w * new->bm_h;
956 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
957 d_free(new->bm_data);
958 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
959 Piggy_bitmap_cache_next += size;
961 GameBitmaps[i] = *new;
965 // -- mprintf( (0, "U" ));
969 //@@Dont' do these things which are done when writing
970 //@@for (i=0; i < Num_bitmap_files; i++ ) {
971 //@@ bitmap_index bi;
973 //@@ PIGGY_PAGE_IN( bi );
976 //@@piggy_close_file();
978 piggy_write_pigfile(pigname);
980 Current_pigfile[0] = 0; //say no pig, to force reload
982 piggy_new_pigfile(pigname); //read in just-generated pig
986 #endif //ifdef EDITOR
990 ubyte bogus_data[64*64];
991 ubyte bogus_bitmap_initialized=0;
992 digi_sound bogus_sound;
994 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
995 #define HAMFILE_VERSION 3
996 //version 1 -> 2: save marker_model_num
997 //version 2 -> 3: removed sound files
999 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
1000 #define SNDFILE_VERSION 1
1004 CFILE * ham_fp = NULL;
1006 int sound_offset = 0;
1008 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1010 if (ham_fp == NULL) {
1011 Must_write_hamfile = 1;
1015 //make sure ham is valid type file & is up-to-date
1016 ham_id = cfile_read_int(ham_fp);
1017 Piggy_hamfile_version = cfile_read_int(ham_fp);
1018 if (ham_id != HAMFILE_ID)
1019 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1021 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1022 Must_write_hamfile = 1;
1023 cfclose(ham_fp); //out of date ham
1028 if (Piggy_hamfile_version < 3) // hamfile contains sound info
1029 sound_offset = cfile_read_int(ham_fp);
1035 bm_read_all(ham_fp);
1036 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1038 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1039 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1040 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1045 if (Piggy_hamfile_version < 3) {
1050 DiskSoundHeader sndh;
1051 digi_sound temp_sound;
1052 char temp_name_read[16];
1055 cfseek(ham_fp, sound_offset, SEEK_SET);
1056 N_sounds = cfile_read_int(ham_fp);
1058 sound_start = cftell(ham_fp);
1060 header_size = N_sounds * sizeof(DiskSoundHeader);
1064 for (i=0; i<N_sounds; i++ ) {
1065 DiskSoundHeader_read(&sndh, ham_fp);
1066 temp_sound.length = sndh.length;
1067 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1068 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1069 memcpy( temp_name_read, sndh.name, 8 );
1070 temp_name_read[8] = 0;
1071 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1073 if (piggy_is_needed(i))
1074 #endif // note link to if.
1075 sbytes += sndh.length;
1076 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1079 SoundBits = d_malloc( sbytes + 16 );
1080 if ( SoundBits == NULL )
1081 Error( "Not enough memory to load sounds\n" );
1083 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1085 // piggy_read_sounds(ham_fp);
1097 CFILE * snd_fp = NULL;
1098 int snd_id,snd_version;
1103 DiskSoundHeader sndh;
1104 digi_sound temp_sound;
1105 char temp_name_read[16];
1108 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1113 //make sure soundfile is valid type file & is up-to-date
1114 snd_id = cfile_read_int(snd_fp);
1115 snd_version = cfile_read_int(snd_fp);
1116 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1117 cfclose(snd_fp); //out of date sound file
1121 N_sounds = cfile_read_int(snd_fp);
1123 sound_start = cftell(snd_fp);
1124 size = cfilelength(snd_fp) - sound_start;
1126 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1128 header_size = N_sounds*sizeof(DiskSoundHeader);
1132 for (i=0; i<N_sounds; i++ ) {
1133 DiskSoundHeader_read(&sndh, snd_fp);
1134 //size -= sizeof(DiskSoundHeader);
1135 temp_sound.length = sndh.length;
1136 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1137 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1138 memcpy( temp_name_read, sndh.name, 8 );
1139 temp_name_read[8] = 0;
1140 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1142 if (piggy_is_needed(i))
1143 #endif // note link to if.
1144 sbytes += sndh.length;
1145 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1148 SoundBits = d_malloc( sbytes + 16 );
1149 if ( SoundBits == NULL )
1150 Error( "Not enough memory to load sounds\n" );
1152 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1154 // piggy_read_sounds(snd_fp);
1161 int piggy_init(void)
1163 int ham_ok=0,snd_ok=0;
1166 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1167 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1169 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1170 GameSounds[i].length = 0;
1171 GameSounds[i].data = NULL;
1175 for (i=0; i<MAX_BITMAP_FILES; i++ )
1176 GameBitmapXlat[i] = i;
1178 if ( !bogus_bitmap_initialized ) {
1182 bogus_bitmap_initialized = 1;
1183 c = gr_find_closest_color( 0, 0, 63 );
1184 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1185 c = gr_find_closest_color( 63, 0, 0 );
1186 // Make a big red X !
1187 for (i=0; i<64; i++ ) {
1188 bogus_data[i*64+i] = c;
1189 bogus_data[i*64+(63-i)] = c;
1191 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
1192 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
1193 bogus_sound.length = 64*64;
1194 bogus_sound.data = bogus_data;
1195 GameBitmapOffset[0] = 0;
1198 if ( FindArg( "-bigpig" ))
1201 if ( FindArg( "-lowmem" ))
1202 piggy_low_memory = 1;
1204 if ( FindArg( "-nolowmem" ))
1205 piggy_low_memory = 0;
1207 if (piggy_low_memory)
1210 gr_set_curfont( SMALL_FONT );
1211 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1212 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1214 #if 1 //def EDITOR //need for d1 mission briefings
1215 piggy_init_pigfile(DEFAULT_PIGFILE);
1218 snd_ok = ham_ok = read_hamfile();
1220 if (Piggy_hamfile_version >= 3)
1221 snd_ok = read_sndfile();
1223 atexit(piggy_close);
1225 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1226 return (ham_ok && snd_ok); //read ok
1229 int piggy_is_needed(int soundnum)
1233 if ( !digi_lomem ) return 1;
1235 for (i=0; i<MAX_SOUNDS; i++ ) {
1236 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1243 void piggy_read_sounds(void)
1252 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1257 for (i=0; i<Num_sound_files; i++ ) {
1258 digi_sound *snd = &GameSounds[i];
1260 if ( SoundOffset[i] > 0 ) {
1261 if ( piggy_is_needed(i) ) {
1262 cfseek( fp, SoundOffset[i], SEEK_SET );
1264 // Read in the sound data!!!
1267 sbytes += snd->length;
1268 cfread( snd->data, snd->length, 1, fp );
1271 snd->data = (ubyte *) -1;
1277 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1282 extern int descent_critical_error;
1283 extern unsigned descent_critical_deverror;
1284 extern unsigned descent_critical_errcode;
1286 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1287 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1288 "Read fault", "General Failure" };
1290 void piggy_critical_error()
1292 grs_canvas * save_canv;
1293 grs_font * save_font;
1295 save_canv = grd_curcanv;
1296 save_font = grd_curcanv->cv_font;
1297 gr_palette_load( gr_palette );
1298 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1301 gr_set_current_canvas(save_canv);
1302 grd_curcanv->cv_font = save_font;
1305 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1307 void piggy_bitmap_page_in( bitmap_index bitmap )
1316 Assert( i < MAX_BITMAP_FILES );
1317 Assert( i < Num_bitmap_files );
1318 Assert( Piggy_bitmap_cache_size > 0 );
1320 if ( i < 1 ) return;
1321 if ( i >= MAX_BITMAP_FILES ) return;
1322 if ( i >= Num_bitmap_files ) return;
1324 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1326 if ( piggy_low_memory ) {
1328 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1331 bmp = &GameBitmaps[i];
1333 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1337 descent_critical_error = 0;
1338 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1339 if ( descent_critical_error ) {
1340 piggy_critical_error();
1344 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1346 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1347 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1348 descent_critical_error = 0;
1349 zsize = cfile_read_int(Piggy_fp);
1350 if ( descent_critical_error ) {
1351 piggy_critical_error();
1355 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1356 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1357 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1359 piggy_bitmap_page_out_all();
1362 descent_critical_error = 0;
1363 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1364 if ( descent_critical_error ) {
1365 piggy_critical_error();
1368 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1369 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1374 if (!FindArg("-macdata"))
1376 // otherwise, fall through...
1377 case MAC_ALIEN1_PIGSIZE:
1378 case MAC_ALIEN2_PIGSIZE:
1379 case MAC_FIRE_PIGSIZE:
1380 case MAC_GROUPA_PIGSIZE:
1381 case MAC_ICE_PIGSIZE:
1382 case MAC_WATER_PIGSIZE:
1383 rle_swap_0_255( bmp );
1384 memcpy(&zsize, bmp->bm_data, 4);
1389 Piggy_bitmap_cache_next += zsize;
1390 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1392 piggy_bitmap_page_out_all();
1397 int pigsize = cfilelength(Piggy_fp);
1398 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1399 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1400 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1401 piggy_bitmap_page_out_all();
1404 descent_critical_error = 0;
1405 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1406 if ( descent_critical_error ) {
1407 piggy_critical_error();
1410 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1411 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1416 if (!FindArg("-macdata"))
1418 // otherwise, fall through...
1419 case MAC_ALIEN1_PIGSIZE:
1420 case MAC_ALIEN2_PIGSIZE:
1421 case MAC_FIRE_PIGSIZE:
1422 case MAC_GROUPA_PIGSIZE:
1423 case MAC_ICE_PIGSIZE:
1424 case MAC_WATER_PIGSIZE:
1431 //@@if ( bmp->bm_selector ) {
1432 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1433 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1434 //@@ Error( "Error modifying selector base in piggy.c\n" );
1441 if ( piggy_low_memory ) {
1443 GameBitmaps[org_i] = GameBitmaps[i];
1446 //@@Removed from John's code:
1448 //@@ if ( bmp->bm_selector ) {
1449 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1450 //@@ Error( "Error modifying selector base in piggy.c\n" );
1456 void piggy_bitmap_page_out_all()
1460 Piggy_bitmap_cache_next = 0;
1462 piggy_page_flushed++;
1467 for (i=0; i<Num_bitmap_files; i++ ) {
1468 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1469 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1470 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1474 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1477 void piggy_load_level_data()
1479 piggy_bitmap_page_out_all();
1485 void piggy_write_pigfile(char *filename)
1488 int bitmap_data_start, data_offset;
1489 DiskBitmapHeader bmh;
1491 char subst_name[32];
1494 char tname[FILENAME_LEN];
1496 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1497 for (i=0; i < Num_bitmap_files; i++ ) {
1500 PIGGY_PAGE_IN( bi );
1502 // -- mprintf( (0, "\n" ));
1506 // -- mprintf( (0, "Creating %s...",filename ));
1508 pig_fp = fopen( filename, "wb" ); //open PIG file
1509 Assert( pig_fp!=NULL );
1511 write_int(PIGFILE_ID,pig_fp);
1512 write_int(PIGFILE_VERSION,pig_fp);
1515 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1518 bitmap_data_start = ftell(pig_fp);
1519 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1520 data_offset = bitmap_data_start;
1522 change_filename_extension(tname,filename,"lst");
1523 fp1 = fopen( tname, "wt" );
1524 change_filename_extension(tname,filename,"all");
1525 fp2 = fopen( tname, "wt" );
1527 for (i=1; i < Num_bitmap_files; i++ ) {
1533 p = strchr(AllBitmaps[i].name, '#');
1534 if (p) { // this is an ABM == animated bitmap
1540 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1541 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1542 Assert( n <= DBM_NUM_FRAMES );
1543 bmh.dflags = DBM_FLAG_ABM + n;
1547 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1548 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1552 bmp = &GameBitmaps[i];
1554 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1557 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1558 org_offset = ftell(pig_fp);
1559 bmh.offset = data_offset - bitmap_data_start;
1560 fseek( pig_fp, data_offset, SEEK_SET );
1562 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1563 size = (int *)bmp->bm_data;
1564 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1565 data_offset += *size;
1567 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1569 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1570 data_offset += bmp->bm_rowsize * bmp->bm_h;
1572 fprintf( fp1, ".\n" );
1574 fseek( pig_fp, org_offset, SEEK_SET );
1575 Assert( GameBitmaps[i].bm_w < 4096 );
1576 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1577 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1578 Assert( GameBitmaps[i].bm_h < 4096 );
1579 bmh.height = GameBitmaps[i].bm_h;
1580 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1581 bmh.flags = GameBitmaps[i].bm_flags;
1582 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1583 bitmap_index other_bitmap;
1584 other_bitmap = piggy_find_bitmap( subst_name );
1585 GameBitmapXlat[i] = other_bitmap.index;
1586 bmh.flags |= BM_FLAG_PAGED_OUT;
1587 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1588 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1590 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1592 bmh.avg_color=GameBitmaps[i].avg_color;
1593 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1598 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1599 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1606 static void write_int(int i,FILE *file)
1608 if (fwrite( &i, sizeof(i), 1, file) != 1)
1609 Error( "Error reading int in gamesave.c" );
1613 void piggy_dump_all()
1617 int org_offset,data_offset=0;
1618 DiskSoundHeader sndh;
1619 int sound_data_start=0;
1622 #ifdef NO_DUMP_SOUNDS
1623 Num_sound_files = 0;
1624 Num_sound_files_new = 0;
1627 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1630 fp1 = fopen( "ham.lst", "wt" );
1631 fp2 = fopen( "ham.all", "wt" );
1633 if (Must_write_hamfile || Num_bitmap_files_new) {
1635 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1637 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1638 Assert( ham_fp!=NULL );
1640 write_int(HAMFILE_ID,ham_fp);
1641 write_int(HAMFILE_VERSION,ham_fp);
1643 bm_write_all(ham_fp);
1644 xlat_offset = ftell(ham_fp);
1645 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1648 if (Num_bitmap_files_new)
1649 piggy_write_pigfile(DEFAULT_PIGFILE);
1651 //free up memeory used by new bitmaps
1652 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1653 d_free(GameBitmaps[i].bm_data);
1655 //next thing must be done after pig written
1656 fseek( ham_fp, xlat_offset, SEEK_SET );
1657 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1660 mprintf( (0, "\n" ));
1663 if (Num_sound_files_new) {
1665 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1666 // Now dump sound file
1667 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1668 Assert( ham_fp!=NULL );
1670 write_int(SNDFILE_ID,ham_fp);
1671 write_int(SNDFILE_VERSION,ham_fp);
1673 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1675 mprintf( (0, "\nDumping sounds..." ));
1677 sound_data_start = ftell(ham_fp);
1678 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1679 data_offset = sound_data_start;
1681 for (i=0; i < Num_sound_files; i++ ) {
1684 snd = &GameSounds[i];
1685 strcpy( sndh.name, AllSounds[i].name );
1686 sndh.length = GameSounds[i].length;
1687 sndh.offset = data_offset - sound_data_start;
1689 org_offset = ftell(ham_fp);
1690 fseek( ham_fp, data_offset, SEEK_SET );
1692 sndh.data_length = GameSounds[i].length;
1693 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1694 data_offset += snd->length;
1695 fseek( ham_fp, org_offset, SEEK_SET );
1696 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1698 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1699 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1703 mprintf( (0, "\n" ));
1706 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1707 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1708 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1713 // Never allow the game to run after building ham.
1727 d_free( SoundBits );
1729 hashtable_free( &AllBitmapsNames );
1730 hashtable_free( &AllDigiSndNames );
1734 int piggy_does_bitmap_exist_slow( char * name )
1738 for (i=0; i<Num_bitmap_files; i++ ) {
1739 if ( !strcmp( AllBitmaps[i].name, name) )
1746 #define NUM_GAUGE_BITMAPS 23
1747 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1748 "gauge01", "gauge01b",
1749 "gauge02", "gauge02b",
1750 "gauge06", "gauge06b",
1751 "targ01", "targ01b",
1752 "targ02", "targ02b",
1753 "targ03", "targ03b",
1754 "targ04", "targ04b",
1755 "targ05", "targ05b",
1756 "targ06", "targ06b",
1757 "gauge18", "gauge18b",
1763 int piggy_is_gauge_bitmap( char * base_name )
1766 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1767 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1774 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1778 char base_name[ 16 ];
1780 strcpy( subst_name, name );
1781 p = strchr( subst_name, '#' );
1783 frame = atoi( &p[1] );
1785 strcpy( base_name, subst_name );
1786 if ( !piggy_is_gauge_bitmap( base_name )) {
1787 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1788 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1790 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1796 strcpy( subst_name, name );
1803 * Functions for loading replacement textures
1804 * 1) From .pog files
1805 * 2) From descent.pig (for loading d1 levels)
1808 extern char last_palette_loaded_pig[];
1810 void free_bitmap_replacements()
1812 if (Bitmap_replacement_data) {
1813 d_free(Bitmap_replacement_data);
1814 Bitmap_replacement_data = NULL;
1818 void load_bitmap_replacements(char *level_name)
1820 char ifile_name[FILENAME_LEN];
1824 //first, free up data allocated for old bitmaps
1825 free_bitmap_replacements();
1827 change_filename_extension(ifile_name, level_name, ".POG" );
1829 ifile = cfopen(ifile_name,"rb");
1832 int id,version,n_bitmaps;
1833 int bitmap_data_size;
1836 id = cfile_read_int(ifile);
1837 version = cfile_read_int(ifile);
1839 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1844 n_bitmaps = cfile_read_int(ifile);
1846 MALLOC( indices, ushort, n_bitmaps );
1848 for (i = 0; i < n_bitmaps; i++)
1849 indices[i] = cfile_read_short(ifile);
1851 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1852 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1854 for (i=0;i<n_bitmaps;i++) {
1855 DiskBitmapHeader bmh;
1856 grs_bitmap *bm = &GameBitmaps[indices[i]];
1859 DiskBitmapHeader_read(&bmh, ifile);
1861 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1862 gr_set_bitmap_data(bm, NULL); // free ogl texture
1863 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1864 bm->avg_color = bmh.avg_color;
1865 bm->bm_data = (ubyte *) bmh.offset;
1867 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1869 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1872 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1874 for (i = 0; i < n_bitmaps; i++)
1876 grs_bitmap *bm = &GameBitmaps[indices[i]];
1877 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1884 last_palette_loaded_pig[0]= 0; //force pig re-load
1886 texmerge_flush(); //for re-merging with new textures
1889 atexit(free_bitmap_replacements);
1892 /* calculate table to translate d1 bitmaps to current palette,
1893 * return -1 on error
1895 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1898 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1899 if (!palette_file || cfilelength(palette_file) != 9472)
1901 cfread( d1_palette, 256, 3, palette_file);
1902 cfclose( palette_file );
1903 build_colormap_good( d1_palette, colormap, freq );
1904 // don't change transparencies:
1905 colormap[254] = 254;
1906 colormap[255] = 255;
1910 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1911 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1912 CFILE *d1_Piggy_fp, /* read from this file */
1913 int bitmap_data_start, /* specific to file */
1914 DiskBitmapHeader *bmh, /* header info for bitmap */
1915 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1916 ubyte *d1_palette, /* what palette the bitmap has */
1917 ubyte *colormap) /* how to translate bitmap's colors */
1919 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1923 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1924 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1925 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1926 bitmap->avg_color = bmh->avg_color;
1927 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1929 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1930 if (bmh->flags & BM_FLAG_RLE) {
1931 zsize = cfile_read_int(d1_Piggy_fp);
1932 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1934 zsize = bitmap->bm_h * bitmap->bm_w;
1937 data = *next_bitmap;
1938 *next_bitmap += zsize;
1940 data = d_malloc(zsize + JUST_IN_CASE);
1944 cfread(data, 1, zsize, d1_Piggy_fp);
1945 gr_set_bitmap_data(bitmap, data);
1947 case D1_MAC_PIGSIZE:
1948 case D1_MAC_SHARE_PIGSIZE:
1949 if (bmh->flags & BM_FLAG_RLE)
1950 rle_swap_0_255(bitmap);
1954 if (bmh->flags & BM_FLAG_RLE)
1955 rle_remap(bitmap, colormap);
1957 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
1958 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
1960 memcpy(&new_size, bitmap->bm_data, 4);
1962 *next_bitmap += new_size - zsize;
1964 Assert( zsize + JUST_IN_CASE >= new_size );
1965 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
1966 Assert(bitmap->bm_data);
1971 #define D1_MAX_TEXTURES 800
1972 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
1974 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
1975 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
1976 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
1978 short *d1_tmap_nums = NULL;
1980 void free_d1_tmap_nums() {
1982 d_free(d1_tmap_nums);
1983 d1_tmap_nums = NULL;
1987 void bm_read_d1_tmap_nums(CFILE *d1pig)
1991 free_d1_tmap_nums();
1992 cfseek(d1pig, 8, SEEK_SET);
1993 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
1994 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
1995 d1_tmap_nums[i] = -1;
1996 for (i = 0; i < D1_MAX_TEXTURES; i++) {
1997 d1_index = cfile_read_short(d1pig);
1998 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
1999 d1_tmap_nums[d1_index] = i;
2001 atexit(free_d1_tmap_nums);
2004 void remove_char( char * s, char c )
2011 #define REMOVE_EOL(s) remove_char((s),'\n')
2012 #define REMOVE_COMMENTS(s) remove_char((s),';')
2013 #define REMOVE_DOTS(s) remove_char((s),'.')
2014 char *space = { " \t" };
2015 char *equal_space = { " \t=" };
2017 // this function is at the same position in the d1 shareware piggy loading
2018 // algorithm as bm_load_sub in main/bmread.c
2019 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2021 DiskBitmapHeader bmh;
2022 if (strchr (filename, '.'))
2023 *strchr (filename, '.') = '\0'; // remove extension
2024 cfseek (d1_pig, 0, SEEK_SET);
2025 N_bitmaps = cfile_read_int (d1_pig);
2026 cfseek (d1_pig, 8, SEEK_SET);
2027 for (i = 1; i <= N_bitmaps; i++) {
2028 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2029 if (!strnicmp(bmh.name, filename, 8))
2035 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2036 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2038 #define LINEBUF_SIZE 600
2039 int reading_textures = 0;
2040 short texture_count = 0;
2041 char inputline[LINEBUF_SIZE];
2043 int bitmaps_tbl_is_binary = 0;
2046 bitmaps = cfopen ("bitmaps.tbl", "rb");
2048 bitmaps = cfopen ("bitmaps.bin", "rb");
2049 bitmaps_tbl_is_binary = 1;
2053 Warning ("Could not find bitmaps.* for reading d1 textures");
2057 free_d1_tmap_nums();
2058 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2059 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2060 d1_tmap_nums[i] = -1;
2061 atexit(free_d1_tmap_nums);
2063 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2066 if (bitmaps_tbl_is_binary)
2067 decode_text_line((inputline));
2069 while (inputline[(i=strlen(inputline))-2]=='\\')
2070 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2071 REMOVE_EOL(inputline);
2072 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2073 if (strlen(inputline) == LINEBUF_SIZE-1) {
2074 Warning("Possible line truncation in BITMAPS.TBL");
2077 arg = strtok( inputline, space );
2078 if (arg && arg[0] == '@') {
2080 //Registered_only = 1;
2083 while (arg != NULL) {
2085 reading_textures = 0; // default
2086 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2087 reading_textures = 1;
2088 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2089 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2091 else // not a special token, must be a bitmap!
2092 if (reading_textures) {
2093 while (*arg == '\t' || *arg == ' ')
2094 arg++;//remove unwanted blanks
2097 if (d1_tmap_num_unique(texture_count)) {
2098 int d1_index = get_d1_bm_index(arg, d1_pig);
2099 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2100 d1_tmap_nums[d1_index] = texture_count;
2101 //int d2_index = d2_index_for_d1_index(d1_index);
2104 Assert (texture_count < D1_MAX_TEXTURES);
2108 arg = strtok (NULL, equal_space);
2114 /* If the given d1_index is the index of a bitmap we have to load
2115 * (because it is unique to descent 1), then returns the d2_index that
2116 * the given d1_index replaces.
2117 * Returns -1 if the given d1_index is not unique to descent 1.
2119 short d2_index_for_d1_index(short d1_index)
2121 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2122 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2123 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2126 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2129 #define D1_BITMAPS_SIZE 300000
2130 void load_d1_bitmap_replacements()
2132 CFILE * d1_Piggy_fp;
2133 DiskBitmapHeader bmh;
2134 int pig_data_start, bitmap_header_start, bitmap_data_start;
2136 short d1_index, d2_index;
2138 ubyte colormap[256];
2139 ubyte d1_palette[256*3];
2143 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2145 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2147 Warning(D1_PIG_LOAD_FAILED);
2151 //first, free up data allocated for old bitmaps
2152 free_bitmap_replacements();
2154 if (get_d1_colormap( d1_palette, colormap ) != 0)
2155 Warning("Could not load descent 1 color palette");
2157 pigsize = cfilelength(d1_Piggy_fp);
2159 case D1_SHARE_BIG_PIGSIZE:
2160 case D1_SHARE_10_PIGSIZE:
2161 case D1_SHARE_PIGSIZE:
2162 case D1_10_BIG_PIGSIZE:
2165 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2166 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2169 Warning("Unknown size for " D1_PIGFILE);
2173 case D1_OEM_PIGSIZE:
2174 case D1_MAC_PIGSIZE:
2175 case D1_MAC_SHARE_PIGSIZE:
2176 pig_data_start = cfile_read_int(d1_Piggy_fp );
2177 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2178 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2182 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2183 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2185 int N_sounds = cfile_read_int(d1_Piggy_fp);
2186 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2187 + N_sounds * sizeof(DiskSoundHeader);
2188 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2189 bitmap_data_start = bitmap_header_start + header_size;
2192 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2193 if (!Bitmap_replacement_data) {
2194 Warning(D1_PIG_LOAD_FAILED);
2197 atexit(free_bitmap_replacements);
2199 next_bitmap = Bitmap_replacement_data;
2201 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2202 d2_index = d2_index_for_d1_index(d1_index);
2203 // only change bitmaps which are unique to d1
2204 if (d2_index != -1) {
2205 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2206 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2208 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2209 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2210 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2211 GameBitmapFlags[d2_index] = bmh.flags;
2213 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2214 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2215 int i, len = p - AllBitmaps[d2_index].name;
2216 for (i = 0; i < Num_bitmap_files; i++)
2217 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
2219 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
2220 GameBitmaps[i] = GameBitmaps[d2_index];
2221 GameBitmapOffset[i] = 0;
2222 GameBitmapFlags[i] = bmh.flags;
2228 cfclose(d1_Piggy_fp);
2230 last_palette_loaded_pig[0]= 0; //force pig re-load
2232 texmerge_flush(); //for re-merging with new textures
2236 extern int extra_bitmap_num;
2239 * Find and load the named bitmap from descent.pig
2240 * similar to read_extra_bitmap_iff
2242 bitmap_index read_extra_bitmap_d1_pig(char *name)
2244 bitmap_index bitmap_num;
2245 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2247 bitmap_num.index = 0;
2251 DiskBitmapHeader bmh;
2252 int pig_data_start, bitmap_header_start, bitmap_data_start;
2254 ubyte colormap[256];
2255 ubyte d1_palette[256*3];
2258 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2262 Warning(D1_PIG_LOAD_FAILED);
2266 if (get_d1_colormap( d1_palette, colormap ) != 0)
2267 Warning("Could not load descent 1 color palette");
2269 pigsize = cfilelength(d1_Piggy_fp);
2271 case D1_SHARE_BIG_PIGSIZE:
2272 case D1_SHARE_10_PIGSIZE:
2273 case D1_SHARE_PIGSIZE:
2274 case D1_10_BIG_PIGSIZE:
2279 Warning("Unknown size for " D1_PIGFILE);
2283 case D1_OEM_PIGSIZE:
2284 case D1_MAC_PIGSIZE:
2285 case D1_MAC_SHARE_PIGSIZE:
2286 pig_data_start = cfile_read_int(d1_Piggy_fp );
2291 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2292 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2294 int N_sounds = cfile_read_int(d1_Piggy_fp);
2295 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2296 + N_sounds * sizeof(DiskSoundHeader);
2297 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2298 bitmap_data_start = bitmap_header_start + header_size;
2301 for (i = 1; i <= N_bitmaps; i++)
2303 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2304 if (!strnicmp(bmh.name, name, 8))
2308 if (strnicmp(bmh.name, name, 8))
2310 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2314 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2316 cfclose(d1_Piggy_fp);
2319 new->avg_color = 0; //compute_average_pixel(new);
2321 bitmap_num.index = extra_bitmap_num;
2323 GameBitmaps[extra_bitmap_num++] = *new;
2329 #ifndef FAST_FILE_IO
2331 * reads a bitmap_index structure from a CFILE
2333 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2335 bi->index = cfile_read_short(fp);
2339 * reads n bitmap_index structs from a CFILE
2341 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2345 for (i = 0; i < n; i++)
2346 bi[i].index = cfile_read_short(fp);
2349 #endif // FAST_FILE_IO