1 /* $Id: piggy.c,v 1.63 2005-08-02 06:13:56 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.63 2005-08-02 06:13:56 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 char name[255]; // filename + path for the mac
623 piggy_close_file(); //close old pig if still open
625 //rename pigfile for shareware
626 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
627 filename = DEFAULT_PIGFILE_SHAREWARE;
630 Piggy_fp = cfopen( filename, "rb" );
632 sprintf(name, ":Data:%s", filename);
633 Piggy_fp = cfopen( name, "rb" );
635 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
636 if (Piggy_fp == NULL)
638 Error("Cannot load required file <%s>",name);
640 #endif // end of if def shareware
646 return; //if editor, ok to not have pig, because we'll build one
648 Piggy_fp = copy_pigfile_from_cd(filename);
652 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
653 int pig_id,pig_version;
655 pig_id = cfile_read_int(Piggy_fp);
656 pig_version = cfile_read_int(Piggy_fp);
657 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
658 cfclose(Piggy_fp); //out of date pig
659 Piggy_fp = NULL; //..so pretend it's not here
666 return; //if editor, ok to not have pig, because we'll build one
668 Error("Cannot load required file <%s>",filename);
672 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
674 N_bitmaps = cfile_read_int(Piggy_fp);
676 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
678 data_start = header_size + cftell(Piggy_fp);
680 data_size = cfilelength(Piggy_fp) - data_start;
682 Num_bitmap_files = 1;
684 for (i=0; i<N_bitmaps; i++ )
687 grs_bitmap *bm = &GameBitmaps[i + 1];
689 DiskBitmapHeader_read(&bmh, Piggy_fp);
690 memcpy( temp_name_read, bmh.name, 8 );
691 temp_name_read[8] = 0;
692 if ( bmh.dflags & DBM_FLAG_ABM )
693 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
695 strcpy( temp_name, temp_name_read );
696 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
697 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
698 bm->bm_flags = BM_FLAG_PAGED_OUT;
699 bm->avg_color = bmh.avg_color;
701 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
703 GameBitmapOffset[i+1] = bmh.offset + data_start;
704 Assert( (i+1) == Num_bitmap_files );
705 piggy_register_bitmap(bm, temp_name, 1);
709 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
710 Assert( Piggy_bitmap_cache_size > 0 );
712 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
714 if (piggy_low_memory)
715 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
718 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
719 if ( BitmapBits == NULL )
720 Error( "Not enough memory to load bitmaps\n" );
721 Piggy_bitmap_cache_data = BitmapBits;
722 Piggy_bitmap_cache_next = 0;
724 #if defined(MACINTOSH) && defined(SHAREWARE)
725 // load_exit_models();
728 Pigfile_initialized=1;
731 #define FILENAME_LEN 13
732 #define MAX_BITMAPS_PER_BRUSH 30
734 extern int compute_average_pixel(grs_bitmap *new);
735 extern void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data);
737 ubyte *Bitmap_replacement_data = NULL;
739 //reads in a new pigfile (for new palette)
740 //returns the size of all the bitmap data
741 void piggy_new_pigfile(char *pigname)
745 char temp_name_read[16];
746 DiskBitmapHeader bmh;
747 int header_size, N_bitmaps, data_size, data_start;
748 int must_rewrite_pig = 0;
755 //rename pigfile for shareware
756 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
757 pigname = DEFAULT_PIGFILE_SHAREWARE;
759 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
760 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
763 if (!Pigfile_initialized) { //have we ever opened a pigfile?
764 piggy_init_pigfile(pigname); //..no, so do initialization stuff
768 piggy_close_file(); //close old pig if still open
770 Piggy_bitmap_cache_next = 0; //free up cache
772 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
775 Piggy_fp = cfopen( pigname, "rb" );
777 sprintf(name, ":Data:%s", pigname);
778 Piggy_fp = cfopen( name, "rb" );
780 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
781 if (Piggy_fp == NULL)
783 Error("Cannot load required file <%s>",name);
785 #endif // end of if def shareware
790 Piggy_fp = copy_pigfile_from_cd(pigname);
793 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
794 int pig_id,pig_version;
796 pig_id = cfile_read_int(Piggy_fp);
797 pig_version = cfile_read_int(Piggy_fp);
798 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
799 cfclose(Piggy_fp); //out of date pig
800 Piggy_fp = NULL; //..so pretend it's not here
806 Error("Cannot open correct version of <%s>", pigname);
811 N_bitmaps = cfile_read_int(Piggy_fp);
813 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
815 data_start = header_size + cftell(Piggy_fp);
817 data_size = cfilelength(Piggy_fp) - data_start;
819 for (i=1; i<=N_bitmaps; i++ )
821 grs_bitmap *bm = &GameBitmaps[i];
824 DiskBitmapHeader_read(&bmh, Piggy_fp);
825 memcpy( temp_name_read, bmh.name, 8 );
826 temp_name_read[8] = 0;
828 if ( bmh.dflags & DBM_FLAG_ABM )
829 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
831 strcpy( temp_name, temp_name_read );
833 //Make sure name matches
834 if (strcmp(temp_name,AllBitmaps[i].name)) {
835 //Int3(); //this pig is out of date. Delete it
839 strcpy(AllBitmaps[i].name,temp_name);
841 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
842 gr_set_bitmap_data(bm, NULL); // free ogl texture
843 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
844 bm->bm_flags = BM_FLAG_PAGED_OUT;
845 bm->avg_color = bmh.avg_color;
847 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
849 GameBitmapOffset[i] = bmh.offset + data_start;
853 N_bitmaps = 0; //no pigfile, so no bitmaps
857 Assert(N_bitmaps == Num_bitmap_files-1);
861 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
864 //re-read the bitmaps that aren't in this pig
866 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
869 p = strchr(AllBitmaps[i].name,'#');
871 if (p) { // this is an ABM == animated bitmap
872 char abmname[FILENAME_LEN];
874 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
875 int iff_error; //reference parm to avoid warning message
877 char basename[FILENAME_LEN];
880 strcpy(basename,AllBitmaps[i].name);
881 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
883 sprintf( abmname, "%s.abm", basename );
885 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
887 if (iff_error != IFF_NO_ERROR) {
888 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
889 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
892 for (fnum=0;fnum<nframes; fnum++) {
896 sprintf( tempname, "%s#%d", basename, fnum );
898 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
899 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
900 //above makes assumption that supertransparent color is 254
902 if ( iff_has_transparency )
903 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
905 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
907 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
910 if ( FindArg("-macdata") )
911 swap_0_255( bm[fnum] );
913 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
915 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
916 size = *((int *) bm[fnum]->bm_data);
918 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
920 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
921 d_free(bm[fnum]->bm_data);
922 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
923 Piggy_bitmap_cache_next += size;
925 GameBitmaps[i+fnum] = *bm[fnum];
927 // -- mprintf( (0, "U" ));
931 i += nframes-1; //filled in multiple bitmaps
933 else { //this is a BBM
938 char bbmname[FILENAME_LEN];
941 MALLOC( new, grs_bitmap, 1 );
943 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
944 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
947 if (iff_error != IFF_NO_ERROR) {
948 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
949 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
952 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
953 //above makes assumption that supertransparent color is 254
955 if ( iff_has_transparency )
956 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
958 gr_remap_bitmap_good( new, newpal, -1, SuperX );
960 new->avg_color = compute_average_pixel(new);
963 if ( FindArg("-macdata") )
966 if ( !BigPig ) gr_bitmap_rle_compress( new );
968 if (new->bm_flags & BM_FLAG_RLE)
969 size = *((int *) new->bm_data);
971 size = new->bm_w * new->bm_h;
973 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
974 d_free(new->bm_data);
975 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
976 Piggy_bitmap_cache_next += size;
978 GameBitmaps[i] = *new;
982 // -- mprintf( (0, "U" ));
986 //@@Dont' do these things which are done when writing
987 //@@for (i=0; i < Num_bitmap_files; i++ ) {
988 //@@ bitmap_index bi;
990 //@@ PIGGY_PAGE_IN( bi );
993 //@@piggy_close_file();
995 piggy_write_pigfile(pigname);
997 Current_pigfile[0] = 0; //say no pig, to force reload
999 piggy_new_pigfile(pigname); //read in just-generated pig
1003 #endif //ifdef EDITOR
1007 ubyte bogus_data[64*64];
1008 ubyte bogus_bitmap_initialized=0;
1009 digi_sound bogus_sound;
1011 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
1012 #define HAMFILE_VERSION 3
1013 //version 1 -> 2: save marker_model_num
1014 //version 2 -> 3: removed sound files
1016 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
1017 #define SNDFILE_VERSION 1
1021 CFILE * ham_fp = NULL;
1023 int sound_offset = 0;
1029 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1031 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1032 ham_fp = cfopen( name, "rb" );
1035 if (ham_fp == NULL) {
1036 Must_write_hamfile = 1;
1040 //make sure ham is valid type file & is up-to-date
1041 ham_id = cfile_read_int(ham_fp);
1042 Piggy_hamfile_version = cfile_read_int(ham_fp);
1043 if (ham_id != HAMFILE_ID)
1044 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1046 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1047 Must_write_hamfile = 1;
1048 cfclose(ham_fp); //out of date ham
1053 if (Piggy_hamfile_version < 3) // hamfile contains sound info
1054 sound_offset = cfile_read_int(ham_fp);
1060 bm_read_all(ham_fp);
1061 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1063 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1064 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1065 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1070 if (Piggy_hamfile_version < 3) {
1075 DiskSoundHeader sndh;
1076 digi_sound temp_sound;
1077 char temp_name_read[16];
1080 cfseek(ham_fp, sound_offset, SEEK_SET);
1081 N_sounds = cfile_read_int(ham_fp);
1083 sound_start = cftell(ham_fp);
1085 header_size = N_sounds * sizeof(DiskSoundHeader);
1089 for (i=0; i<N_sounds; i++ ) {
1090 DiskSoundHeader_read(&sndh, ham_fp);
1091 temp_sound.length = sndh.length;
1092 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1093 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1094 memcpy( temp_name_read, sndh.name, 8 );
1095 temp_name_read[8] = 0;
1096 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1098 if (piggy_is_needed(i))
1099 #endif // note link to if.
1100 sbytes += sndh.length;
1101 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1104 SoundBits = d_malloc( sbytes + 16 );
1105 if ( SoundBits == NULL )
1106 Error( "Not enough memory to load sounds\n" );
1108 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1110 // piggy_read_sounds(ham_fp);
1122 CFILE * snd_fp = NULL;
1123 int snd_id,snd_version;
1128 DiskSoundHeader sndh;
1129 digi_sound temp_sound;
1130 char temp_name_read[16];
1137 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1139 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1140 snd_fp = cfopen( name, "rb");
1146 //make sure soundfile is valid type file & is up-to-date
1147 snd_id = cfile_read_int(snd_fp);
1148 snd_version = cfile_read_int(snd_fp);
1149 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1150 cfclose(snd_fp); //out of date sound file
1154 N_sounds = cfile_read_int(snd_fp);
1156 sound_start = cftell(snd_fp);
1157 size = cfilelength(snd_fp) - sound_start;
1159 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1161 header_size = N_sounds*sizeof(DiskSoundHeader);
1165 for (i=0; i<N_sounds; i++ ) {
1166 DiskSoundHeader_read(&sndh, snd_fp);
1167 //size -= sizeof(DiskSoundHeader);
1168 temp_sound.length = sndh.length;
1169 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1170 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1171 memcpy( temp_name_read, sndh.name, 8 );
1172 temp_name_read[8] = 0;
1173 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1175 if (piggy_is_needed(i))
1176 #endif // note link to if.
1177 sbytes += sndh.length;
1178 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1181 SoundBits = d_malloc( sbytes + 16 );
1182 if ( SoundBits == NULL )
1183 Error( "Not enough memory to load sounds\n" );
1185 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1187 // piggy_read_sounds(snd_fp);
1194 int piggy_init(void)
1196 int ham_ok=0,snd_ok=0;
1199 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1200 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1202 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1203 GameSounds[i].length = 0;
1204 GameSounds[i].data = NULL;
1208 for (i=0; i<MAX_BITMAP_FILES; i++ )
1209 GameBitmapXlat[i] = i;
1211 if ( !bogus_bitmap_initialized ) {
1215 bogus_bitmap_initialized = 1;
1216 c = gr_find_closest_color( 0, 0, 63 );
1217 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1218 c = gr_find_closest_color( 63, 0, 0 );
1219 // Make a big red X !
1220 for (i=0; i<64; i++ ) {
1221 bogus_data[i*64+i] = c;
1222 bogus_data[i*64+(63-i)] = c;
1224 gr_init_bitmap(&GameBitmaps[Num_bitmap_files], 0, 0, 0, 64, 64, 64, bogus_data);
1225 piggy_register_bitmap(&GameBitmaps[Num_bitmap_files], "bogus", 1);
1226 bogus_sound.length = 64*64;
1227 bogus_sound.data = bogus_data;
1228 GameBitmapOffset[0] = 0;
1231 if ( FindArg( "-bigpig" ))
1234 if ( FindArg( "-lowmem" ))
1235 piggy_low_memory = 1;
1237 if ( FindArg( "-nolowmem" ))
1238 piggy_low_memory = 0;
1240 if (piggy_low_memory)
1243 gr_set_curfont( SMALL_FONT );
1244 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1245 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1247 #if 1 //def EDITOR //need for d1 mission briefings
1248 piggy_init_pigfile(DEFAULT_PIGFILE);
1251 snd_ok = ham_ok = read_hamfile();
1253 if (Piggy_hamfile_version >= 3)
1254 snd_ok = read_sndfile();
1256 atexit(piggy_close);
1258 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1259 return (ham_ok && snd_ok); //read ok
1262 int piggy_is_needed(int soundnum)
1266 if ( !digi_lomem ) return 1;
1268 for (i=0; i<MAX_SOUNDS; i++ ) {
1269 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1276 void piggy_read_sounds(void)
1289 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1291 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1292 fp = cfopen( name, "rb");
1298 for (i=0; i<Num_sound_files; i++ ) {
1299 digi_sound *snd = &GameSounds[i];
1301 if ( SoundOffset[i] > 0 ) {
1302 if ( piggy_is_needed(i) ) {
1303 cfseek( fp, SoundOffset[i], SEEK_SET );
1305 // Read in the sound data!!!
1308 sbytes += snd->length;
1309 cfread( snd->data, snd->length, 1, fp );
1312 snd->data = (ubyte *) -1;
1318 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1323 extern int descent_critical_error;
1324 extern unsigned descent_critical_deverror;
1325 extern unsigned descent_critical_errcode;
1327 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1328 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1329 "Read fault", "General Failure" };
1331 void piggy_critical_error()
1333 grs_canvas * save_canv;
1334 grs_font * save_font;
1336 save_canv = grd_curcanv;
1337 save_font = grd_curcanv->cv_font;
1338 gr_palette_load( gr_palette );
1339 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1342 gr_set_current_canvas(save_canv);
1343 grd_curcanv->cv_font = save_font;
1346 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1348 void piggy_bitmap_page_in( bitmap_index bitmap )
1357 Assert( i < MAX_BITMAP_FILES );
1358 Assert( i < Num_bitmap_files );
1359 Assert( Piggy_bitmap_cache_size > 0 );
1361 if ( i < 1 ) return;
1362 if ( i >= MAX_BITMAP_FILES ) return;
1363 if ( i >= Num_bitmap_files ) return;
1365 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1367 if ( piggy_low_memory ) {
1369 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1372 bmp = &GameBitmaps[i];
1374 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1378 descent_critical_error = 0;
1379 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1380 if ( descent_critical_error ) {
1381 piggy_critical_error();
1385 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1387 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1388 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1389 descent_critical_error = 0;
1390 zsize = cfile_read_int(Piggy_fp);
1391 if ( descent_critical_error ) {
1392 piggy_critical_error();
1396 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1397 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1398 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1400 piggy_bitmap_page_out_all();
1403 descent_critical_error = 0;
1404 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1405 if ( descent_critical_error ) {
1406 piggy_critical_error();
1409 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1410 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1415 if (!FindArg("-macdata"))
1417 // otherwise, fall through...
1418 case MAC_ALIEN1_PIGSIZE:
1419 case MAC_ALIEN2_PIGSIZE:
1420 case MAC_FIRE_PIGSIZE:
1421 case MAC_GROUPA_PIGSIZE:
1422 case MAC_ICE_PIGSIZE:
1423 case MAC_WATER_PIGSIZE:
1424 rle_swap_0_255( bmp );
1425 memcpy(&zsize, bmp->bm_data, 4);
1430 Piggy_bitmap_cache_next += zsize;
1431 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1433 piggy_bitmap_page_out_all();
1438 int pigsize = cfilelength(Piggy_fp);
1439 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1440 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1441 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1442 piggy_bitmap_page_out_all();
1445 descent_critical_error = 0;
1446 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1447 if ( descent_critical_error ) {
1448 piggy_critical_error();
1451 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1452 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1457 if (!FindArg("-macdata"))
1459 // otherwise, fall through...
1460 case MAC_ALIEN1_PIGSIZE:
1461 case MAC_ALIEN2_PIGSIZE:
1462 case MAC_FIRE_PIGSIZE:
1463 case MAC_GROUPA_PIGSIZE:
1464 case MAC_ICE_PIGSIZE:
1465 case MAC_WATER_PIGSIZE:
1472 //@@if ( bmp->bm_selector ) {
1473 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1474 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1475 //@@ Error( "Error modifying selector base in piggy.c\n" );
1482 if ( piggy_low_memory ) {
1484 GameBitmaps[org_i] = GameBitmaps[i];
1487 //@@Removed from John's code:
1489 //@@ if ( bmp->bm_selector ) {
1490 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1491 //@@ Error( "Error modifying selector base in piggy.c\n" );
1497 void piggy_bitmap_page_out_all()
1501 Piggy_bitmap_cache_next = 0;
1503 piggy_page_flushed++;
1508 for (i=0; i<Num_bitmap_files; i++ ) {
1509 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1510 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1511 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1515 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1518 void piggy_load_level_data()
1520 piggy_bitmap_page_out_all();
1526 void change_filename_ext( char *dest, char *src, char *ext );
1528 void piggy_write_pigfile(char *filename)
1531 int bitmap_data_start, data_offset;
1532 DiskBitmapHeader bmh;
1534 char subst_name[32];
1537 char tname[FILENAME_LEN];
1539 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1540 for (i=0; i < Num_bitmap_files; i++ ) {
1543 PIGGY_PAGE_IN( bi );
1545 // -- mprintf( (0, "\n" ));
1549 // -- mprintf( (0, "Creating %s...",filename ));
1551 pig_fp = fopen( filename, "wb" ); //open PIG file
1552 Assert( pig_fp!=NULL );
1554 write_int(PIGFILE_ID,pig_fp);
1555 write_int(PIGFILE_VERSION,pig_fp);
1558 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1561 bitmap_data_start = ftell(pig_fp);
1562 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1563 data_offset = bitmap_data_start;
1565 change_filename_ext(tname,filename,"lst");
1566 fp1 = fopen( tname, "wt" );
1567 change_filename_ext(tname,filename,"all");
1568 fp2 = fopen( tname, "wt" );
1570 for (i=1; i < Num_bitmap_files; i++ ) {
1576 p = strchr(AllBitmaps[i].name, '#');
1577 if (p) { // this is an ABM == animated bitmap
1583 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1584 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1585 Assert( n <= DBM_NUM_FRAMES );
1586 bmh.dflags = DBM_FLAG_ABM + n;
1590 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1591 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1595 bmp = &GameBitmaps[i];
1597 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1600 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1601 org_offset = ftell(pig_fp);
1602 bmh.offset = data_offset - bitmap_data_start;
1603 fseek( pig_fp, data_offset, SEEK_SET );
1605 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1606 size = (int *)bmp->bm_data;
1607 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1608 data_offset += *size;
1610 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1612 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1613 data_offset += bmp->bm_rowsize * bmp->bm_h;
1615 fprintf( fp1, ".\n" );
1617 fseek( pig_fp, org_offset, SEEK_SET );
1618 Assert( GameBitmaps[i].bm_w < 4096 );
1619 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1620 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1621 Assert( GameBitmaps[i].bm_h < 4096 );
1622 bmh.height = GameBitmaps[i].bm_h;
1623 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1624 bmh.flags = GameBitmaps[i].bm_flags;
1625 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1626 bitmap_index other_bitmap;
1627 other_bitmap = piggy_find_bitmap( subst_name );
1628 GameBitmapXlat[i] = other_bitmap.index;
1629 bmh.flags |= BM_FLAG_PAGED_OUT;
1630 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1631 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1633 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1635 bmh.avg_color=GameBitmaps[i].avg_color;
1636 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1641 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1642 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1649 static void write_int(int i,FILE *file)
1651 if (fwrite( &i, sizeof(i), 1, file) != 1)
1652 Error( "Error reading int in gamesave.c" );
1656 void piggy_dump_all()
1660 int org_offset,data_offset=0;
1661 DiskSoundHeader sndh;
1662 int sound_data_start=0;
1665 #ifdef NO_DUMP_SOUNDS
1666 Num_sound_files = 0;
1667 Num_sound_files_new = 0;
1670 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1673 fp1 = fopen( "ham.lst", "wt" );
1674 fp2 = fopen( "ham.all", "wt" );
1676 if (Must_write_hamfile || Num_bitmap_files_new) {
1678 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1680 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1681 Assert( ham_fp!=NULL );
1683 write_int(HAMFILE_ID,ham_fp);
1684 write_int(HAMFILE_VERSION,ham_fp);
1686 bm_write_all(ham_fp);
1687 xlat_offset = ftell(ham_fp);
1688 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1691 if (Num_bitmap_files_new)
1692 piggy_write_pigfile(DEFAULT_PIGFILE);
1694 //free up memeory used by new bitmaps
1695 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1696 d_free(GameBitmaps[i].bm_data);
1698 //next thing must be done after pig written
1699 fseek( ham_fp, xlat_offset, SEEK_SET );
1700 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1703 mprintf( (0, "\n" ));
1706 if (Num_sound_files_new) {
1708 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1709 // Now dump sound file
1710 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1711 Assert( ham_fp!=NULL );
1713 write_int(SNDFILE_ID,ham_fp);
1714 write_int(SNDFILE_VERSION,ham_fp);
1716 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1718 mprintf( (0, "\nDumping sounds..." ));
1720 sound_data_start = ftell(ham_fp);
1721 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1722 data_offset = sound_data_start;
1724 for (i=0; i < Num_sound_files; i++ ) {
1727 snd = &GameSounds[i];
1728 strcpy( sndh.name, AllSounds[i].name );
1729 sndh.length = GameSounds[i].length;
1730 sndh.offset = data_offset - sound_data_start;
1732 org_offset = ftell(ham_fp);
1733 fseek( ham_fp, data_offset, SEEK_SET );
1735 sndh.data_length = GameSounds[i].length;
1736 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1737 data_offset += snd->length;
1738 fseek( ham_fp, org_offset, SEEK_SET );
1739 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1741 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1742 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1746 mprintf( (0, "\n" ));
1749 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1750 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1751 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1756 // Never allow the game to run after building ham.
1770 d_free( SoundBits );
1772 hashtable_free( &AllBitmapsNames );
1773 hashtable_free( &AllDigiSndNames );
1777 int piggy_does_bitmap_exist_slow( char * name )
1781 for (i=0; i<Num_bitmap_files; i++ ) {
1782 if ( !strcmp( AllBitmaps[i].name, name) )
1789 #define NUM_GAUGE_BITMAPS 23
1790 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1791 "gauge01", "gauge01b",
1792 "gauge02", "gauge02b",
1793 "gauge06", "gauge06b",
1794 "targ01", "targ01b",
1795 "targ02", "targ02b",
1796 "targ03", "targ03b",
1797 "targ04", "targ04b",
1798 "targ05", "targ05b",
1799 "targ06", "targ06b",
1800 "gauge18", "gauge18b",
1806 int piggy_is_gauge_bitmap( char * base_name )
1809 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1810 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1817 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1821 char base_name[ 16 ];
1823 strcpy( subst_name, name );
1824 p = strchr( subst_name, '#' );
1826 frame = atoi( &p[1] );
1828 strcpy( base_name, subst_name );
1829 if ( !piggy_is_gauge_bitmap( base_name )) {
1830 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1831 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1833 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1839 strcpy( subst_name, name );
1846 * Functions for loading replacement textures
1847 * 1) From .pog files
1848 * 2) From descent.pig (for loading d1 levels)
1851 extern void change_filename_extension( char *dest, char *src, char *new_ext );
1852 extern char last_palette_loaded_pig[];
1854 void free_bitmap_replacements()
1856 if (Bitmap_replacement_data) {
1857 d_free(Bitmap_replacement_data);
1858 Bitmap_replacement_data = NULL;
1862 void load_bitmap_replacements(char *level_name)
1864 char ifile_name[FILENAME_LEN];
1868 //first, free up data allocated for old bitmaps
1869 free_bitmap_replacements();
1871 change_filename_extension(ifile_name, level_name, ".POG" );
1873 ifile = cfopen(ifile_name,"rb");
1876 int id,version,n_bitmaps;
1877 int bitmap_data_size;
1880 id = cfile_read_int(ifile);
1881 version = cfile_read_int(ifile);
1883 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1888 n_bitmaps = cfile_read_int(ifile);
1890 MALLOC( indices, ushort, n_bitmaps );
1892 for (i = 0; i < n_bitmaps; i++)
1893 indices[i] = cfile_read_short(ifile);
1895 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1896 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1898 for (i=0;i<n_bitmaps;i++) {
1899 DiskBitmapHeader bmh;
1900 grs_bitmap *bm = &GameBitmaps[indices[i]];
1903 DiskBitmapHeader_read(&bmh, ifile);
1905 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1906 gr_set_bitmap_data(bm, NULL); // free ogl texture
1907 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1908 bm->avg_color = bmh.avg_color;
1909 bm->bm_data = (ubyte *) bmh.offset;
1911 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1913 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1916 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1918 for (i = 0; i < n_bitmaps; i++)
1920 grs_bitmap *bm = &GameBitmaps[indices[i]];
1921 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1928 last_palette_loaded_pig[0]= 0; //force pig re-load
1930 texmerge_flush(); //for re-merging with new textures
1933 atexit(free_bitmap_replacements);
1936 /* calculate table to translate d1 bitmaps to current palette,
1937 * return -1 on error
1939 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1942 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1943 if (!palette_file || cfilelength(palette_file) != 9472)
1945 cfread( d1_palette, 256, 3, palette_file);
1946 cfclose( palette_file );
1947 build_colormap_good( d1_palette, colormap, freq );
1948 // don't change transparencies:
1949 colormap[254] = 254;
1950 colormap[255] = 255;
1954 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1955 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1956 CFILE *d1_Piggy_fp, /* read from this file */
1957 int bitmap_data_start, /* specific to file */
1958 DiskBitmapHeader *bmh, /* header info for bitmap */
1959 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1960 ubyte *d1_palette, /* what palette the bitmap has */
1961 ubyte *colormap) /* how to translate bitmap's colors */
1963 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1967 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1968 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1969 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1970 bitmap->avg_color = bmh->avg_color;
1971 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1973 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1974 if (bmh->flags & BM_FLAG_RLE) {
1975 zsize = cfile_read_int(d1_Piggy_fp);
1976 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1978 zsize = bitmap->bm_h * bitmap->bm_w;
1981 data = *next_bitmap;
1982 *next_bitmap += zsize;
1984 data = d_malloc(zsize + JUST_IN_CASE);
1988 cfread(data, 1, zsize, d1_Piggy_fp);
1989 gr_set_bitmap_data(bitmap, data);
1991 case D1_MAC_PIGSIZE:
1992 case D1_MAC_SHARE_PIGSIZE:
1993 if (bmh->flags & BM_FLAG_RLE)
1994 rle_swap_0_255(bitmap);
1998 if (bmh->flags & BM_FLAG_RLE)
1999 rle_remap(bitmap, colormap);
2001 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
2002 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
2004 memcpy(&new_size, bitmap->bm_data, 4);
2006 *next_bitmap += new_size - zsize;
2008 Assert( zsize + JUST_IN_CASE >= new_size );
2009 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
2010 Assert(bitmap->bm_data);
2015 #define D1_MAX_TEXTURES 800
2016 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
2018 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
2019 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
2020 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
2022 short *d1_tmap_nums = NULL;
2024 void free_d1_tmap_nums() {
2026 d_free(d1_tmap_nums);
2027 d1_tmap_nums = NULL;
2031 void bm_read_d1_tmap_nums(CFILE *d1pig)
2035 free_d1_tmap_nums();
2036 cfseek(d1pig, 8, SEEK_SET);
2037 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2038 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2039 d1_tmap_nums[i] = -1;
2040 for (i = 0; i < D1_MAX_TEXTURES; i++) {
2041 d1_index = cfile_read_short(d1pig);
2042 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2043 d1_tmap_nums[d1_index] = i;
2045 atexit(free_d1_tmap_nums);
2048 void remove_char( char * s, char c )
2055 #define REMOVE_EOL(s) remove_char((s),'\n')
2056 #define REMOVE_COMMENTS(s) remove_char((s),';')
2057 #define REMOVE_DOTS(s) remove_char((s),'.')
2058 char *space = { " \t" };
2059 char *equal_space = { " \t=" };
2061 // this function is at the same position in the d1 shareware piggy loading
2062 // algorithm as bm_load_sub in main/bmread.c
2063 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2065 DiskBitmapHeader bmh;
2066 if (strchr (filename, '.'))
2067 *strchr (filename, '.') = '\0'; // remove extension
2068 cfseek (d1_pig, 0, SEEK_SET);
2069 N_bitmaps = cfile_read_int (d1_pig);
2070 cfseek (d1_pig, 8, SEEK_SET);
2071 for (i = 1; i <= N_bitmaps; i++) {
2072 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2073 if (!strnicmp(bmh.name, filename, 8))
2079 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2080 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2082 #define LINEBUF_SIZE 600
2083 int reading_textures = 0;
2084 short texture_count = 0;
2085 char inputline[LINEBUF_SIZE];
2087 int bitmaps_tbl_is_binary = 0;
2090 bitmaps = cfopen ("bitmaps.tbl", "rb");
2092 bitmaps = cfopen ("bitmaps.bin", "rb");
2093 bitmaps_tbl_is_binary = 1;
2097 Warning ("Could not find bitmaps.* for reading d1 textures");
2101 free_d1_tmap_nums();
2102 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2103 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2104 d1_tmap_nums[i] = -1;
2105 atexit(free_d1_tmap_nums);
2107 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2110 if (bitmaps_tbl_is_binary)
2111 decode_text_line((inputline));
2113 while (inputline[(i=strlen(inputline))-2]=='\\')
2114 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2115 REMOVE_EOL(inputline);
2116 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2117 if (strlen(inputline) == LINEBUF_SIZE-1) {
2118 Warning("Possible line truncation in BITMAPS.TBL");
2121 arg = strtok( inputline, space );
2122 if (arg && arg[0] == '@') {
2124 //Registered_only = 1;
2127 while (arg != NULL) {
2129 reading_textures = 0; // default
2130 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2131 reading_textures = 1;
2132 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2133 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2135 else // not a special token, must be a bitmap!
2136 if (reading_textures) {
2137 while (*arg == '\t' || *arg == ' ')
2138 arg++;//remove unwanted blanks
2141 if (d1_tmap_num_unique(texture_count)) {
2142 int d1_index = get_d1_bm_index(arg, d1_pig);
2143 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2144 d1_tmap_nums[d1_index] = texture_count;
2145 //int d2_index = d2_index_for_d1_index(d1_index);
2148 Assert (texture_count < D1_MAX_TEXTURES);
2152 arg = strtok (NULL, equal_space);
2158 /* If the given d1_index is the index of a bitmap we have to load
2159 * (because it is unique to descent 1), then returns the d2_index that
2160 * the given d1_index replaces.
2161 * Returns -1 if the given d1_index is not unique to descent 1.
2163 short d2_index_for_d1_index(short d1_index)
2165 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2166 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2167 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2170 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2173 #define D1_BITMAPS_SIZE 300000
2174 void load_d1_bitmap_replacements()
2176 CFILE * d1_Piggy_fp;
2177 DiskBitmapHeader bmh;
2178 int pig_data_start, bitmap_header_start, bitmap_data_start;
2180 short d1_index, d2_index;
2182 ubyte colormap[256];
2183 ubyte d1_palette[256*3];
2187 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2189 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2191 Warning(D1_PIG_LOAD_FAILED);
2195 //first, free up data allocated for old bitmaps
2196 free_bitmap_replacements();
2198 if (get_d1_colormap( d1_palette, colormap ) != 0)
2199 Warning("Could not load descent 1 color palette");
2201 pigsize = cfilelength(d1_Piggy_fp);
2203 case D1_SHARE_BIG_PIGSIZE:
2204 case D1_SHARE_10_PIGSIZE:
2205 case D1_SHARE_PIGSIZE:
2206 case D1_10_BIG_PIGSIZE:
2209 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2210 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2213 Warning("Unknown size for " D1_PIGFILE);
2217 case D1_OEM_PIGSIZE:
2218 case D1_MAC_PIGSIZE:
2219 case D1_MAC_SHARE_PIGSIZE:
2220 pig_data_start = cfile_read_int(d1_Piggy_fp );
2221 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2222 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2226 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2227 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2229 int N_sounds = cfile_read_int(d1_Piggy_fp);
2230 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2231 + N_sounds * sizeof(DiskSoundHeader);
2232 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2233 bitmap_data_start = bitmap_header_start + header_size;
2236 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2237 if (!Bitmap_replacement_data) {
2238 Warning(D1_PIG_LOAD_FAILED);
2241 atexit(free_bitmap_replacements);
2243 next_bitmap = Bitmap_replacement_data;
2245 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2246 d2_index = d2_index_for_d1_index(d1_index);
2247 // only change bitmaps which are unique to d1
2248 if (d2_index != -1) {
2249 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2250 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2252 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2253 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2254 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2255 GameBitmapFlags[d2_index] = bmh.flags;
2257 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2258 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2259 int i, len = p - AllBitmaps[d2_index].name;
2260 for (i = 0; i < Num_bitmap_files; i++)
2261 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
2263 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
2264 GameBitmaps[i] = GameBitmaps[d2_index];
2265 GameBitmapOffset[i] = 0;
2266 GameBitmapFlags[i] = bmh.flags;
2272 cfclose(d1_Piggy_fp);
2274 last_palette_loaded_pig[0]= 0; //force pig re-load
2276 texmerge_flush(); //for re-merging with new textures
2280 extern int extra_bitmap_num;
2283 * Find and load the named bitmap from descent.pig
2284 * similar to read_extra_bitmap_iff
2286 bitmap_index read_extra_bitmap_d1_pig(char *name)
2288 bitmap_index bitmap_num;
2289 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2291 bitmap_num.index = 0;
2295 DiskBitmapHeader bmh;
2296 int pig_data_start, bitmap_header_start, bitmap_data_start;
2298 ubyte colormap[256];
2299 ubyte d1_palette[256*3];
2302 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2306 Warning(D1_PIG_LOAD_FAILED);
2310 if (get_d1_colormap( d1_palette, colormap ) != 0)
2311 Warning("Could not load descent 1 color palette");
2313 pigsize = cfilelength(d1_Piggy_fp);
2315 case D1_SHARE_BIG_PIGSIZE:
2316 case D1_SHARE_10_PIGSIZE:
2317 case D1_SHARE_PIGSIZE:
2318 case D1_10_BIG_PIGSIZE:
2323 Warning("Unknown size for " D1_PIGFILE);
2327 case D1_OEM_PIGSIZE:
2328 case D1_MAC_PIGSIZE:
2329 case D1_MAC_SHARE_PIGSIZE:
2330 pig_data_start = cfile_read_int(d1_Piggy_fp );
2335 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2336 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2338 int N_sounds = cfile_read_int(d1_Piggy_fp);
2339 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2340 + N_sounds * sizeof(DiskSoundHeader);
2341 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2342 bitmap_data_start = bitmap_header_start + header_size;
2345 for (i = 1; i <= N_bitmaps; i++)
2347 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2348 if (!strnicmp(bmh.name, name, 8))
2352 if (strnicmp(bmh.name, name, 8))
2354 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2358 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2360 cfclose(d1_Piggy_fp);
2363 new->avg_color = 0; //compute_average_pixel(new);
2365 bitmap_num.index = extra_bitmap_num;
2367 GameBitmaps[extra_bitmap_num++] = *new;
2373 #ifndef FAST_FILE_IO
2375 * reads a bitmap_index structure from a CFILE
2377 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2379 bi->index = cfile_read_short(fp);
2383 * reads n bitmap_index structs from a CFILE
2385 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2389 for (i = 0; i < n; i++)
2390 bi[i].index = cfile_read_short(fp);
2393 #endif // FAST_FILE_IO