1 /* $Id: piggy.c,v 1.59 2004-12-02 16:27:29 schaffner 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.59 2004-12-02 16:27:29 schaffner Exp $";
67 #include <Strings.h> // MacOS Toolbox header
72 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
74 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
75 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
76 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
77 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
79 #define D1_PALETTE "palette.256"
81 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
82 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
83 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
85 #define MAC_ALIEN1_PIGSIZE 5013035
86 #define MAC_ALIEN2_PIGSIZE 4909916
87 #define MAC_FIRE_PIGSIZE 4969035
88 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
89 #define MAC_ICE_PIGSIZE 4923425
90 #define MAC_WATER_PIGSIZE 4832403
92 ubyte *BitmapBits = NULL;
93 ubyte *SoundBits = NULL;
95 typedef struct BitmapFile {
99 typedef struct SoundFile {
103 hashtable AllBitmapsNames;
104 hashtable AllDigiSndNames;
106 int Num_bitmap_files = 0;
107 int Num_sound_files = 0;
109 digi_sound GameSounds[MAX_SOUND_FILES];
110 int SoundOffset[MAX_SOUND_FILES];
111 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
113 alias alias_list[MAX_ALIASES];
116 int Must_write_hamfile = 0;
117 int Num_bitmap_files_new = 0;
118 int Num_sound_files_new = 0;
119 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
120 static SoundFile AllSounds[ MAX_SOUND_FILES ];
122 int Piggy_hamfile_version = 0;
124 int piggy_low_memory = 0;
126 int Piggy_bitmap_cache_size = 0;
127 int Piggy_bitmap_cache_next = 0;
128 ubyte * Piggy_bitmap_cache_data = NULL;
129 static int GameBitmapOffset[MAX_BITMAP_FILES];
130 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
131 ushort GameBitmapXlat[MAX_BITMAP_FILES];
133 #define PIGGY_BUFFER_SIZE (2400*1024)
136 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
139 #undef PIGGY_BUFFER_SIZE
140 #undef PIGGY_SMALL_BUFFER_SIZE
142 #define PIGGY_BUFFER_SIZE (2000*1024)
143 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
148 int piggy_page_flushed = 0;
150 #define DBM_FLAG_ABM 64 // animated bitmap
151 #define DBM_NUM_FRAMES 63
153 #define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
154 | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG)
156 typedef struct DiskBitmapHeader {
158 ubyte dflags; // bits 0-5 anim frame num, bit 6 abm flag
159 ubyte width; // low 8 bits here, 4 more bits in wh_extra
160 ubyte height; // low 8 bits here, 4 more bits in wh_extra
161 ubyte wh_extra; // bits 0-3 width, bits 4-7 height
165 } __pack__ DiskBitmapHeader;
167 #define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
169 typedef struct DiskSoundHeader {
174 } __pack__ DiskSoundHeader;
177 #define DiskBitmapHeader_read(dbh, fp) cfread(dbh, sizeof(DiskBitmapHeader), 1, fp)
178 #define DiskSoundHeader_read(dsh, fp) cfread(dsh, sizeof(DiskSoundHeader), 1, fp)
181 * reads a DiskBitmapHeader structure from a CFILE
183 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
185 cfread(dbh->name, 8, 1, fp);
186 dbh->dflags = cfile_read_byte(fp);
187 dbh->width = cfile_read_byte(fp);
188 dbh->height = cfile_read_byte(fp);
189 dbh->wh_extra = cfile_read_byte(fp);
190 dbh->flags = cfile_read_byte(fp);
191 dbh->avg_color = cfile_read_byte(fp);
192 dbh->offset = cfile_read_int(fp);
196 * reads a DiskSoundHeader structure from a CFILE
198 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
200 cfread(dsh->name, 8, 1, fp);
201 dsh->length = cfile_read_int(fp);
202 dsh->data_length = cfile_read_int(fp);
203 dsh->offset = cfile_read_int(fp);
205 #endif // FAST_FILE_IO
208 * reads a descent 1 DiskBitmapHeader structure from a CFILE
210 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
212 cfread(dbh->name, 8, 1, fp);
213 dbh->dflags = cfile_read_byte(fp);
214 dbh->width = cfile_read_byte(fp);
215 dbh->height = cfile_read_byte(fp);
217 dbh->flags = cfile_read_byte(fp);
218 dbh->avg_color = cfile_read_byte(fp);
219 dbh->offset = cfile_read_int(fp);
225 extern short cd_VRefNum;
226 extern void ConcatPStr(StringPtr dst, StringPtr src);
227 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
228 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
231 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
234 void piggy_write_pigfile(char *filename);
235 static void write_int(int i,FILE *file);
238 void swap_0_255(grs_bitmap *bmp)
242 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
243 if(bmp->bm_data[i] == 0)
244 bmp->bm_data[i] = 255;
245 else if (bmp->bm_data[i] == 255)
250 char* piggy_game_bitmap_name(grs_bitmap *bmp)
252 if (bmp >= GameBitmaps && bmp < &GameBitmaps[MAX_BITMAP_FILES])
254 int i = bmp-GameBitmaps; // i = (bmp - GameBitmaps) / sizeof(grs_bitmap);
255 Assert (bmp == &GameBitmaps[i] && i >= 0 && i < MAX_BITMAP_FILES);
256 return AllBitmaps[i].name;
261 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
264 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
266 temp.index = Num_bitmap_files;
270 if ( FindArg("-macdata") )
273 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
274 Num_bitmap_files_new++;
277 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
278 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
279 GameBitmaps[Num_bitmap_files] = *bmp;
281 GameBitmapOffset[Num_bitmap_files] = 0;
282 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
289 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
293 Assert( Num_sound_files < MAX_SOUND_FILES );
295 strncpy( AllSounds[Num_sound_files].name, name, 12 );
296 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
297 GameSounds[Num_sound_files] = *snd;
299 SoundOffset[Num_sound_files] = 0;
305 Num_sound_files_new++;
311 bitmap_index piggy_find_bitmap( char * name )
319 if ((t=strchr(name,'#'))!=NULL)
322 for (i=0;i<Num_aliases;i++)
323 if (stricmp(name,alias_list[i].alias_name)==0) {
324 if (t) { //extra stuff for ABMs
325 static char temp[FILENAME_LEN];
326 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
332 name=alias_list[i].file_name;
339 i = hashtable_search( &AllBitmapsNames, name );
348 int piggy_find_sound( char * name )
352 i = hashtable_search( &AllDigiSndNames, name );
360 CFILE * Piggy_fp = NULL;
362 #define FILENAME_LEN 13
364 char Current_pigfile[FILENAME_LEN] = "";
366 void piggy_close_file()
371 Current_pigfile[0] = 0;
375 int Pigfile_initialized=0;
377 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
378 #define PIGFILE_VERSION 2
380 extern char CDROM_dir[];
382 int request_cd(void);
387 //copies a pigfile from the CD to the current dir
388 //retuns file handle of new pig
389 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
392 char sourcePathAndFileCStr[255] = "";
393 char destPathAndFileCStr[255] = "";
395 FILE* sourceFile = NULL;
396 FILE* destFile = NULL;
397 const int BUF_SIZE = 4096;
401 Str255 sourcePathAndFilePStr = "\p";
402 Str255 destPathAndFilePStr = "\p";
403 Str255 pigfileNamePStr = "\p";
404 HParamBlockRec theSourcePigHFSParams;
405 HParamBlockRec theDestPigHFSParams;
406 OSErr theErr = noErr;
407 char oldDirCStr[255] = "";
409 getcwd(oldDirCStr, 255);
411 show_boxed_message("Copying bitmap data from CD...");
412 gr_palette_load(gr_palette); //I don't think this line is really needed
415 //First, delete all PIG files currently in the directory
416 if( !FileFindFirst( "*.pig", &find ) )
421 } while( !FileFindNext( &find ) );
427 //Now, copy over new pig
428 songs_stop_redbook(); //so we can read off the cd
430 // make the source path "<cd volume>:Data:filename.pig"
431 //MWA ConvertCToPStr(filename, pigfileNamePStr);
433 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
434 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
437 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
438 strcat(sourcePathAndFileCStr, filename);
440 // make the destination path "<default directory>:Data:filename.pig"
441 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
442 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
443 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
444 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
446 strcpy(destPathAndFileCStr, ":Data:");
447 strcat(destPathAndFileCStr, filename);
449 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
450 strcpy(destPathAndFilePStr, destPathAndFileCStr);
451 c2pstr(sourcePathAndFilePStr);
452 c2pstr(destPathAndFilePStr);
455 // Open the source file
456 sourceFile = fopen(sourcePathAndFileCStr,"rb");
460 if (request_cd() == -1)
461 Error("Cannot load file <%s> from CD",filename);
464 } while (!sourceFile);
467 // Get the time stamp from the source file
468 theSourcePigHFSParams.fileParam.ioCompletion = nil;
469 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
470 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
471 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
472 theSourcePigHFSParams.fileParam.ioDirID = 0;
474 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
477 // Error getting file time stamp!! Why? JTS
478 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
481 // Copy the file over
484 // Open the destination file
485 destFile = fopen(destPathAndFileCStr,"wb");
488 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
491 // Copy bytes until the end of the source file
492 while (!feof(sourceFile))
497 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
498 if (ferror(sourceFile))
499 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
501 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
503 fwrite(buf,1,bytes_read,destFile);
504 if (ferror(destFile))
505 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
508 // close the source/dest files
509 if (fclose(sourceFile))
510 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
511 if (fclose(destFile))
512 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
514 // Get the current hfs data for the new file
515 theDestPigHFSParams.fileParam.ioCompletion = nil;
516 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
517 theDestPigHFSParams.fileParam.ioVRefNum = 0;
518 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
519 theDestPigHFSParams.fileParam.ioDirID = 0;
520 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
521 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
523 // Error getting file time stamp!! Why? JTS
524 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
527 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
528 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
529 theDestPigHFSParams.fileParam.ioVRefNum = 0;
530 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
531 theDestPigHFSParams.fileParam.ioDirID = 0;
533 // Copy the time stamp from the source file info
534 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
535 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
536 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
537 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
539 // Set the dest file's time stamp to the source file's time stamp values
540 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
542 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
544 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
547 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
549 return cfopen(destPathAndFileCStr, "rb");
552 #else //PC Version of copy_pigfile_from_cd is below
554 //copies a pigfile from the CD to the current dir
555 //retuns file handle of new pig
556 CFILE *copy_pigfile_from_cd(char *filename)
563 show_boxed_message("Copying bitmap data from CD...");
564 gr_palette_load(gr_palette); //I don't think this line is really needed
566 //First, delete all PIG files currently in the directory
568 if( !FileFindFirst( "*.pig", &find ) ) {
570 cfile_delete(find.name);
571 } while( !FileFindNext( &find ) );
575 //Now, copy over new pig
577 songs_stop_redbook(); //so we can read off the cd
579 //new code to unarj file
580 strcpy(name,CDROM_dir);
581 strcat(name,"descent2.sow");
584 // ret = unarj_specific_file(name,filename,filename);
589 if (ret != EXIT_SUCCESS) {
591 //delete file, so we don't leave partial file
592 cfile_delete(filename);
595 if (request_cd() == -1)
597 //NOTE LINK TO ABOVE IF
598 Error("Cannot load file <%s> from CD",filename);
601 } while (ret != EXIT_SUCCESS);
604 return cfopen(filename, "rb");
607 #endif // end of ifdef MAC around copy_pigfile_from_cd
609 //initialize a pigfile, reading headers
610 //returns the size of all the bitmap data
611 void piggy_init_pigfile(char *filename)
615 char temp_name_read[16];
616 grs_bitmap temp_bitmap;
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++ ) {
685 DiskBitmapHeader_read(&bmh, Piggy_fp);
686 memcpy( temp_name_read, bmh.name, 8 );
687 temp_name_read[8] = 0;
688 if ( bmh.dflags & DBM_FLAG_ABM )
689 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
691 strcpy( temp_name, temp_name_read );
692 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
693 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
694 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
695 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
696 temp_bitmap.avg_color = bmh.avg_color;
697 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
699 GameBitmapFlags[i+1] = bmh.flags & BM_FLAGS_TO_COPY;
701 GameBitmapOffset[i+1] = bmh.offset + data_start;
702 Assert( (i+1) == Num_bitmap_files );
703 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
707 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
708 Assert( Piggy_bitmap_cache_size > 0 );
710 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
712 if (piggy_low_memory)
713 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
716 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
717 if ( BitmapBits == NULL )
718 Error( "Not enough memory to load bitmaps\n" );
719 Piggy_bitmap_cache_data = BitmapBits;
720 Piggy_bitmap_cache_next = 0;
722 #if defined(MACINTOSH) && defined(SHAREWARE)
723 // load_exit_models();
726 Pigfile_initialized=1;
729 #define FILENAME_LEN 13
730 #define MAX_BITMAPS_PER_BRUSH 30
732 extern int compute_average_pixel(grs_bitmap *new);
734 ubyte *Bitmap_replacement_data = NULL;
736 //reads in a new pigfile (for new palette)
737 //returns the size of all the bitmap data
738 void piggy_new_pigfile(char *pigname)
742 char temp_name_read[16];
743 grs_bitmap temp_bitmap;
744 DiskBitmapHeader bmh;
745 int header_size, N_bitmaps, data_size, data_start;
746 int must_rewrite_pig = 0;
753 //rename pigfile for shareware
754 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
755 pigname = DEFAULT_PIGFILE_SHAREWARE;
757 if (strnicmp(Current_pigfile, pigname, sizeof(Current_pigfile)) == 0 // correct pig already loaded
758 && !Bitmap_replacement_data) // no need to reload: no bitmaps were altered
761 if (!Pigfile_initialized) { //have we ever opened a pigfile?
762 piggy_init_pigfile(pigname); //..no, so do initialization stuff
766 piggy_close_file(); //close old pig if still open
768 Piggy_bitmap_cache_next = 0; //free up cache
770 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
773 Piggy_fp = cfopen( pigname, "rb" );
775 sprintf(name, ":Data:%s", pigname);
776 Piggy_fp = cfopen( name, "rb" );
778 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
779 if (Piggy_fp == NULL)
781 Error("Cannot load required file <%s>",name);
783 #endif // end of if def shareware
788 Piggy_fp = copy_pigfile_from_cd(pigname);
791 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
792 int pig_id,pig_version;
794 pig_id = cfile_read_int(Piggy_fp);
795 pig_version = cfile_read_int(Piggy_fp);
796 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
797 cfclose(Piggy_fp); //out of date pig
798 Piggy_fp = NULL; //..so pretend it's not here
804 Error("Cannot open correct version of <%s>", pigname);
809 N_bitmaps = cfile_read_int(Piggy_fp);
811 header_size = N_bitmaps * sizeof(DiskBitmapHeader);
813 data_start = header_size + cftell(Piggy_fp);
815 data_size = cfilelength(Piggy_fp) - data_start;
817 for (i=1; i<=N_bitmaps; i++ ) {
818 DiskBitmapHeader_read(&bmh, Piggy_fp);
819 memcpy( temp_name_read, bmh.name, 8 );
820 temp_name_read[8] = 0;
822 if ( bmh.dflags & DBM_FLAG_ABM )
823 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & DBM_NUM_FRAMES );
825 strcpy( temp_name, temp_name_read );
827 //Make sure name matches
828 if (strcmp(temp_name,AllBitmaps[i].name)) {
829 //Int3(); //this pig is out of date. Delete it
833 strcpy(AllBitmaps[i].name,temp_name);
835 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
837 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
838 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
839 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
840 temp_bitmap.avg_color = bmh.avg_color;
841 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
843 GameBitmapFlags[i] = bmh.flags & BM_FLAGS_TO_COPY;
845 GameBitmapOffset[i] = bmh.offset + data_start;
847 GameBitmaps[i] = temp_bitmap;
851 N_bitmaps = 0; //no pigfile, so no bitmaps
855 Assert(N_bitmaps == Num_bitmap_files-1);
859 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
862 //re-read the bitmaps that aren't in this pig
864 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
867 p = strchr(AllBitmaps[i].name,'#');
869 if (p) { // this is an ABM == animated bitmap
870 char abmname[FILENAME_LEN];
872 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
873 int iff_error; //reference parm to avoid warning message
875 char basename[FILENAME_LEN];
878 strcpy(basename,AllBitmaps[i].name);
879 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
881 sprintf( abmname, "%s.abm", basename );
883 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
885 if (iff_error != IFF_NO_ERROR) {
886 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
887 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
890 for (fnum=0;fnum<nframes; fnum++) {
894 sprintf( tempname, "%s#%d", basename, fnum );
896 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
897 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
898 //above makes assumption that supertransparent color is 254
900 if ( iff_has_transparency )
901 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
903 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
905 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
908 if ( FindArg("-macdata") )
909 swap_0_255( bm[fnum] );
911 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
913 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
914 size = *((int *) bm[fnum]->bm_data);
916 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
918 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
919 d_free(bm[fnum]->bm_data);
920 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
921 Piggy_bitmap_cache_next += size;
923 GameBitmaps[i+fnum] = *bm[fnum];
925 // -- mprintf( (0, "U" ));
929 i += nframes-1; //filled in multiple bitmaps
931 else { //this is a BBM
936 char bbmname[FILENAME_LEN];
939 MALLOC( new, grs_bitmap, 1 );
941 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
942 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
945 if (iff_error != IFF_NO_ERROR) {
946 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
947 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
950 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
951 //above makes assumption that supertransparent color is 254
953 if ( iff_has_transparency )
954 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
956 gr_remap_bitmap_good( new, newpal, -1, SuperX );
958 new->avg_color = compute_average_pixel(new);
961 if ( FindArg("-macdata") )
964 if ( !BigPig ) gr_bitmap_rle_compress( new );
966 if (new->bm_flags & BM_FLAG_RLE)
967 size = *((int *) new->bm_data);
969 size = new->bm_w * new->bm_h;
971 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
972 d_free(new->bm_data);
973 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
974 Piggy_bitmap_cache_next += size;
976 GameBitmaps[i] = *new;
980 // -- mprintf( (0, "U" ));
984 //@@Dont' do these things which are done when writing
985 //@@for (i=0; i < Num_bitmap_files; i++ ) {
986 //@@ bitmap_index bi;
988 //@@ PIGGY_PAGE_IN( bi );
991 //@@piggy_close_file();
993 piggy_write_pigfile(pigname);
995 Current_pigfile[0] = 0; //say no pig, to force reload
997 piggy_new_pigfile(pigname); //read in just-generated pig
1001 #endif //ifdef EDITOR
1005 ubyte bogus_data[64*64];
1006 grs_bitmap bogus_bitmap;
1007 ubyte bogus_bitmap_initialized=0;
1008 digi_sound bogus_sound;
1010 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
1011 #define HAMFILE_VERSION 3
1012 //version 1 -> 2: save marker_model_num
1013 //version 2 -> 3: removed sound files
1015 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
1016 #define SNDFILE_VERSION 1
1020 CFILE * ham_fp = NULL;
1022 int sound_offset = 0;
1028 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1030 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1031 ham_fp = cfopen( name, "rb" );
1034 if (ham_fp == NULL) {
1035 Must_write_hamfile = 1;
1039 //make sure ham is valid type file & is up-to-date
1040 ham_id = cfile_read_int(ham_fp);
1041 Piggy_hamfile_version = cfile_read_int(ham_fp);
1042 if (ham_id != HAMFILE_ID)
1043 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1045 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1046 Must_write_hamfile = 1;
1047 cfclose(ham_fp); //out of date ham
1052 if (Piggy_hamfile_version < 3) // hamfile contains sound info
1053 sound_offset = cfile_read_int(ham_fp);
1059 bm_read_all(ham_fp);
1060 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1062 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1063 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1064 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1069 if (Piggy_hamfile_version < 3) {
1074 DiskSoundHeader sndh;
1075 digi_sound temp_sound;
1076 char temp_name_read[16];
1079 cfseek(ham_fp, sound_offset, SEEK_SET);
1080 N_sounds = cfile_read_int(ham_fp);
1082 sound_start = cftell(ham_fp);
1084 header_size = N_sounds * sizeof(DiskSoundHeader);
1088 for (i=0; i<N_sounds; i++ ) {
1089 DiskSoundHeader_read(&sndh, ham_fp);
1090 temp_sound.length = sndh.length;
1091 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1092 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1093 memcpy( temp_name_read, sndh.name, 8 );
1094 temp_name_read[8] = 0;
1095 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1097 if (piggy_is_needed(i))
1098 #endif // note link to if.
1099 sbytes += sndh.length;
1100 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1103 SoundBits = d_malloc( sbytes + 16 );
1104 if ( SoundBits == NULL )
1105 Error( "Not enough memory to load sounds\n" );
1107 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1109 // piggy_read_sounds(ham_fp);
1121 CFILE * snd_fp = NULL;
1122 int snd_id,snd_version;
1127 DiskSoundHeader sndh;
1128 digi_sound temp_sound;
1129 char temp_name_read[16];
1136 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1138 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1139 snd_fp = cfopen( name, "rb");
1145 //make sure soundfile is valid type file & is up-to-date
1146 snd_id = cfile_read_int(snd_fp);
1147 snd_version = cfile_read_int(snd_fp);
1148 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1149 cfclose(snd_fp); //out of date sound file
1153 N_sounds = cfile_read_int(snd_fp);
1155 sound_start = cftell(snd_fp);
1156 size = cfilelength(snd_fp) - sound_start;
1158 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1160 header_size = N_sounds*sizeof(DiskSoundHeader);
1164 for (i=0; i<N_sounds; i++ ) {
1165 DiskSoundHeader_read(&sndh, snd_fp);
1166 //size -= sizeof(DiskSoundHeader);
1167 temp_sound.length = sndh.length;
1168 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1169 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1170 memcpy( temp_name_read, sndh.name, 8 );
1171 temp_name_read[8] = 0;
1172 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1174 if (piggy_is_needed(i))
1175 #endif // note link to if.
1176 sbytes += sndh.length;
1177 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1180 SoundBits = d_malloc( sbytes + 16 );
1181 if ( SoundBits == NULL )
1182 Error( "Not enough memory to load sounds\n" );
1184 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1186 // piggy_read_sounds(snd_fp);
1193 int piggy_init(void)
1195 int ham_ok=0,snd_ok=0;
1198 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1199 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1201 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1202 GameSounds[i].length = 0;
1203 GameSounds[i].data = NULL;
1207 for (i=0; i<MAX_BITMAP_FILES; i++ )
1208 GameBitmapXlat[i] = i;
1210 if ( !bogus_bitmap_initialized ) {
1213 bogus_bitmap_initialized = 1;
1214 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1215 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1216 bogus_bitmap.bm_data = bogus_data;
1217 c = gr_find_closest_color( 0, 0, 63 );
1218 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1219 c = gr_find_closest_color( 63, 0, 0 );
1220 // Make a big red X !
1221 for (i=0; i<64; i++ ) {
1222 bogus_data[i*64+i] = c;
1223 bogus_data[i*64+(63-i)] = c;
1225 piggy_register_bitmap( &bogus_bitmap, "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 WIN(DDGRLOCK(dd_grd_curcanv));
1244 gr_set_curfont( SMALL_FONT );
1245 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1246 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1247 WIN(DDGRUNLOCK(dd_grd_curcanv));
1249 #if 1 //def EDITOR //need for d1 mission briefings
1250 piggy_init_pigfile(DEFAULT_PIGFILE);
1253 snd_ok = ham_ok = read_hamfile();
1255 if (Piggy_hamfile_version >= 3)
1256 snd_ok = read_sndfile();
1258 atexit(piggy_close);
1260 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1261 return (ham_ok && snd_ok); //read ok
1264 int piggy_is_needed(int soundnum)
1268 if ( !digi_lomem ) return 1;
1270 for (i=0; i<MAX_SOUNDS; i++ ) {
1271 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1278 void piggy_read_sounds(void)
1291 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1293 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1294 fp = cfopen( name, "rb");
1300 for (i=0; i<Num_sound_files; i++ ) {
1301 digi_sound *snd = &GameSounds[i];
1303 if ( SoundOffset[i] > 0 ) {
1304 if ( piggy_is_needed(i) ) {
1305 cfseek( fp, SoundOffset[i], SEEK_SET );
1307 // Read in the sound data!!!
1310 sbytes += snd->length;
1311 cfread( snd->data, snd->length, 1, fp );
1314 snd->data = (ubyte *) -1;
1320 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1325 extern int descent_critical_error;
1326 extern unsigned descent_critical_deverror;
1327 extern unsigned descent_critical_errcode;
1329 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1330 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1331 "Read fault", "General Failure" };
1333 void piggy_critical_error()
1335 grs_canvas * save_canv;
1336 grs_font * save_font;
1338 save_canv = grd_curcanv;
1339 save_font = grd_curcanv->cv_font;
1340 gr_palette_load( gr_palette );
1341 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1344 gr_set_current_canvas(save_canv);
1345 grd_curcanv->cv_font = save_font;
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 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1386 bmp->bm_flags = GameBitmapFlags[i];
1388 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1389 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1390 descent_critical_error = 0;
1391 zsize = cfile_read_int(Piggy_fp);
1392 if ( descent_critical_error ) {
1393 piggy_critical_error();
1397 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1398 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1399 if ( Piggy_bitmap_cache_next+zsize >= 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+4], 1, zsize-4, Piggy_fp );
1406 if ( descent_critical_error ) {
1407 piggy_critical_error();
1414 if (!FindArg("-macdata"))
1416 // otherwise, fall through...
1417 case MAC_ALIEN1_PIGSIZE:
1418 case MAC_ALIEN2_PIGSIZE:
1419 case MAC_FIRE_PIGSIZE:
1420 case MAC_GROUPA_PIGSIZE:
1421 case MAC_ICE_PIGSIZE:
1422 case MAC_WATER_PIGSIZE:
1423 rle_swap_0_255( bmp );
1424 memcpy(&zsize, bmp->bm_data, 4);
1429 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
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 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1456 if (!FindArg("-macdata"))
1458 // otherwise, fall through...
1459 case MAC_ALIEN1_PIGSIZE:
1460 case MAC_ALIEN2_PIGSIZE:
1461 case MAC_FIRE_PIGSIZE:
1462 case MAC_GROUPA_PIGSIZE:
1463 case MAC_ICE_PIGSIZE:
1464 case MAC_WATER_PIGSIZE:
1471 //@@if ( bmp->bm_selector ) {
1472 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1473 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1474 //@@ Error( "Error modifying selector base in piggy.c\n" );
1481 if ( piggy_low_memory ) {
1483 GameBitmaps[org_i] = GameBitmaps[i];
1486 //@@Removed from John's code:
1488 //@@ if ( bmp->bm_selector ) {
1489 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1490 //@@ Error( "Error modifying selector base in piggy.c\n" );
1496 void piggy_bitmap_page_out_all()
1500 Piggy_bitmap_cache_next = 0;
1502 piggy_page_flushed++;
1507 for (i=0; i<Num_bitmap_files; i++ ) {
1508 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1509 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1510 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1514 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1517 void piggy_load_level_data()
1519 piggy_bitmap_page_out_all();
1525 void change_filename_ext( char *dest, char *src, char *ext );
1527 void piggy_write_pigfile(char *filename)
1530 int bitmap_data_start, data_offset;
1531 DiskBitmapHeader bmh;
1533 char subst_name[32];
1536 char tname[FILENAME_LEN];
1538 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1539 for (i=0; i < Num_bitmap_files; i++ ) {
1542 PIGGY_PAGE_IN( bi );
1544 // -- mprintf( (0, "\n" ));
1548 // -- mprintf( (0, "Creating %s...",filename ));
1550 pig_fp = fopen( filename, "wb" ); //open PIG file
1551 Assert( pig_fp!=NULL );
1553 write_int(PIGFILE_ID,pig_fp);
1554 write_int(PIGFILE_VERSION,pig_fp);
1557 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1560 bitmap_data_start = ftell(pig_fp);
1561 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1562 data_offset = bitmap_data_start;
1564 change_filename_ext(tname,filename,"lst");
1565 fp1 = fopen( tname, "wt" );
1566 change_filename_ext(tname,filename,"all");
1567 fp2 = fopen( tname, "wt" );
1569 for (i=1; i < Num_bitmap_files; i++ ) {
1575 p = strchr(AllBitmaps[i].name, '#');
1576 if (p) { // this is an ABM == animated bitmap
1582 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1583 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1584 Assert( n <= DBM_NUM_FRAMES );
1585 bmh.dflags = DBM_FLAG_ABM + n;
1589 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1590 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1594 bmp = &GameBitmaps[i];
1596 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1599 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1600 org_offset = ftell(pig_fp);
1601 bmh.offset = data_offset - bitmap_data_start;
1602 fseek( pig_fp, data_offset, SEEK_SET );
1604 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1605 size = (int *)bmp->bm_data;
1606 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1607 data_offset += *size;
1609 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1611 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1612 data_offset += bmp->bm_rowsize * bmp->bm_h;
1614 fprintf( fp1, ".\n" );
1616 fseek( pig_fp, org_offset, SEEK_SET );
1617 Assert( GameBitmaps[i].bm_w < 4096 );
1618 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1619 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1620 Assert( GameBitmaps[i].bm_h < 4096 );
1621 bmh.height = GameBitmaps[i].bm_h;
1622 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1623 bmh.flags = GameBitmaps[i].bm_flags;
1624 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1625 bitmap_index other_bitmap;
1626 other_bitmap = piggy_find_bitmap( subst_name );
1627 GameBitmapXlat[i] = other_bitmap.index;
1628 bmh.flags |= BM_FLAG_PAGED_OUT;
1629 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1630 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1632 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1634 bmh.avg_color=GameBitmaps[i].avg_color;
1635 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1640 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1641 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1648 static void write_int(int i,FILE *file)
1650 if (fwrite( &i, sizeof(i), 1, file) != 1)
1651 Error( "Error reading int in gamesave.c" );
1655 void piggy_dump_all()
1659 int org_offset,data_offset=0;
1660 DiskSoundHeader sndh;
1661 int sound_data_start=0;
1664 #ifdef NO_DUMP_SOUNDS
1665 Num_sound_files = 0;
1666 Num_sound_files_new = 0;
1669 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1672 fp1 = fopen( "ham.lst", "wt" );
1673 fp2 = fopen( "ham.all", "wt" );
1675 if (Must_write_hamfile || Num_bitmap_files_new) {
1677 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1679 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1680 Assert( ham_fp!=NULL );
1682 write_int(HAMFILE_ID,ham_fp);
1683 write_int(HAMFILE_VERSION,ham_fp);
1685 bm_write_all(ham_fp);
1686 xlat_offset = ftell(ham_fp);
1687 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1690 if (Num_bitmap_files_new)
1691 piggy_write_pigfile(DEFAULT_PIGFILE);
1693 //free up memeory used by new bitmaps
1694 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1695 d_free(GameBitmaps[i].bm_data);
1697 //next thing must be done after pig written
1698 fseek( ham_fp, xlat_offset, SEEK_SET );
1699 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1702 mprintf( (0, "\n" ));
1705 if (Num_sound_files_new) {
1707 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1708 // Now dump sound file
1709 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1710 Assert( ham_fp!=NULL );
1712 write_int(SNDFILE_ID,ham_fp);
1713 write_int(SNDFILE_VERSION,ham_fp);
1715 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1717 mprintf( (0, "\nDumping sounds..." ));
1719 sound_data_start = ftell(ham_fp);
1720 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1721 data_offset = sound_data_start;
1723 for (i=0; i < Num_sound_files; i++ ) {
1726 snd = &GameSounds[i];
1727 strcpy( sndh.name, AllSounds[i].name );
1728 sndh.length = GameSounds[i].length;
1729 sndh.offset = data_offset - sound_data_start;
1731 org_offset = ftell(ham_fp);
1732 fseek( ham_fp, data_offset, SEEK_SET );
1734 sndh.data_length = GameSounds[i].length;
1735 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1736 data_offset += snd->length;
1737 fseek( ham_fp, org_offset, SEEK_SET );
1738 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1740 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1741 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1745 mprintf( (0, "\n" ));
1748 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1749 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1750 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1755 // Never allow the game to run after building ham.
1769 d_free( SoundBits );
1771 hashtable_free( &AllBitmapsNames );
1772 hashtable_free( &AllDigiSndNames );
1776 int piggy_does_bitmap_exist_slow( char * name )
1780 for (i=0; i<Num_bitmap_files; i++ ) {
1781 if ( !strcmp( AllBitmaps[i].name, name) )
1788 #define NUM_GAUGE_BITMAPS 23
1789 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1790 "gauge01", "gauge01b",
1791 "gauge02", "gauge02b",
1792 "gauge06", "gauge06b",
1793 "targ01", "targ01b",
1794 "targ02", "targ02b",
1795 "targ03", "targ03b",
1796 "targ04", "targ04b",
1797 "targ05", "targ05b",
1798 "targ06", "targ06b",
1799 "gauge18", "gauge18b",
1805 int piggy_is_gauge_bitmap( char * base_name )
1808 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1809 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1816 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1820 char base_name[ 16 ];
1822 strcpy( subst_name, name );
1823 p = strchr( subst_name, '#' );
1825 frame = atoi( &p[1] );
1827 strcpy( base_name, subst_name );
1828 if ( !piggy_is_gauge_bitmap( base_name )) {
1829 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1830 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1832 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1838 strcpy( subst_name, name );
1845 // New Windows stuff
1847 // windows bitmap page in
1848 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1849 // 'video' memory. if that fails, page it in normally.
1851 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1856 // Essential when switching video modes!
1858 void piggy_bitmap_page_out_all_w()
1866 * Functions for loading replacement textures
1867 * 1) From .pog files
1868 * 2) From descent.pig (for loading d1 levels)
1871 extern void change_filename_extension( char *dest, char *src, char *new_ext );
1872 extern char last_palette_loaded_pig[];
1874 void free_bitmap_replacements()
1876 if (Bitmap_replacement_data) {
1877 d_free(Bitmap_replacement_data);
1878 Bitmap_replacement_data = NULL;
1882 void load_bitmap_replacements(char *level_name)
1884 char ifile_name[FILENAME_LEN];
1888 //first, free up data allocated for old bitmaps
1889 free_bitmap_replacements();
1891 change_filename_extension(ifile_name, level_name, ".POG" );
1893 ifile = cfopen(ifile_name,"rb");
1896 int id,version,n_bitmaps;
1897 int bitmap_data_size;
1900 id = cfile_read_int(ifile);
1901 version = cfile_read_int(ifile);
1903 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1908 n_bitmaps = cfile_read_int(ifile);
1910 MALLOC( indices, ushort, n_bitmaps );
1912 for (i = 0; i < n_bitmaps; i++)
1913 indices[i] = cfile_read_short(ifile);
1915 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1916 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1918 for (i=0;i<n_bitmaps;i++) {
1919 DiskBitmapHeader bmh;
1920 grs_bitmap temp_bitmap;
1922 DiskBitmapHeader_read(&bmh, ifile);
1924 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1926 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1927 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1928 temp_bitmap.avg_color = bmh.avg_color;
1929 temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
1931 temp_bitmap.bm_flags |= bmh.flags & BM_FLAGS_TO_COPY;
1933 GameBitmaps[indices[i]] = temp_bitmap;
1934 // don't we need the following? GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1937 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1943 last_palette_loaded_pig[0]= 0; //force pig re-load
1945 texmerge_flush(); //for re-merging with new textures
1948 atexit(free_bitmap_replacements);
1951 /* calculate table to translate d1 bitmaps to current palette,
1952 * return -1 on error
1954 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1957 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1958 if (!palette_file || cfilelength(palette_file) != 9472)
1960 cfread( d1_palette, 256, 3, palette_file);
1961 cfclose( palette_file );
1962 build_colormap_good( d1_palette, colormap, freq );
1963 // don't change transparencies:
1964 colormap[254] = 254;
1965 colormap[255] = 255;
1969 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1970 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1971 CFILE *d1_Piggy_fp, /* read from this file */
1972 int bitmap_data_start, /* specific to file */
1973 DiskBitmapHeader *bmh, /* header info for bitmap */
1974 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1975 ubyte *d1_palette, /* what palette the bitmap has */
1976 ubyte *colormap) /* how to translate bitmap's colors */
1978 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1979 memset( bitmap, 0, sizeof(grs_bitmap) );
1981 bitmap->bm_w = bitmap->bm_rowsize = bmh->width + ((short) (bmh->wh_extra&0x0f)<<8);
1982 bitmap->bm_h = bmh->height + ((short) (bmh->wh_extra&0xf0)<<4);
1983 bitmap->avg_color = bmh->avg_color;
1984 bitmap->bm_flags |= bmh->flags & BM_FLAGS_TO_COPY;
1986 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1987 if (bmh->flags & BM_FLAG_RLE) {
1988 zsize = cfile_read_int(d1_Piggy_fp);
1989 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1991 zsize = bitmap->bm_h * bitmap->bm_w;
1994 bitmap->bm_data = *next_bitmap;
1995 *next_bitmap += zsize;
1997 bitmap->bm_data = d_malloc(zsize + JUST_IN_CASE);
1999 cfread(bitmap->bm_data, 1, zsize, d1_Piggy_fp);
2001 case D1_MAC_PIGSIZE:
2002 case D1_MAC_SHARE_PIGSIZE:
2003 if (bmh->flags & BM_FLAG_RLE)
2004 rle_swap_0_255(bitmap);
2008 if (bmh->flags & BM_FLAG_RLE)
2009 rle_remap(bitmap, colormap);
2011 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
2012 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
2014 memcpy(&new_size, bitmap->bm_data, 4);
2016 *next_bitmap += new_size - zsize;
2018 Assert( zsize + JUST_IN_CASE >= new_size );
2019 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
2020 Assert(bitmap->bm_data);
2025 #define D1_MAX_TEXTURES 800
2026 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
2028 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
2029 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
2030 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
2032 short *d1_tmap_nums = NULL;
2034 void free_d1_tmap_nums() {
2036 d_free(d1_tmap_nums);
2037 d1_tmap_nums = NULL;
2041 void bm_read_d1_tmap_nums(CFILE *d1pig)
2045 free_d1_tmap_nums();
2046 cfseek(d1pig, 8, SEEK_SET);
2047 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2048 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2049 d1_tmap_nums[i] = -1;
2050 for (i = 0; i < D1_MAX_TEXTURES; i++) {
2051 d1_index = cfile_read_short(d1pig);
2052 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2053 d1_tmap_nums[d1_index] = i;
2055 atexit(free_d1_tmap_nums);
2058 void remove_char( char * s, char c )
2065 #define REMOVE_EOL(s) remove_char((s),'\n')
2066 #define REMOVE_COMMENTS(s) remove_char((s),';')
2067 #define REMOVE_DOTS(s) remove_char((s),'.')
2068 char *space = { " \t" };
2069 char *equal_space = { " \t=" };
2071 // this function is at the same position in the d1 shareware piggy loading
2072 // algorithm as bm_load_sub in main/bmread.c
2073 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2075 DiskBitmapHeader bmh;
2076 if (strchr (filename, '.'))
2077 *strchr (filename, '.') = '\0'; // remove extension
2078 cfseek (d1_pig, 0, SEEK_SET);
2079 N_bitmaps = cfile_read_int (d1_pig);
2080 cfseek (d1_pig, 8, SEEK_SET);
2081 for (i = 1; i <= N_bitmaps; i++) {
2082 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2083 if (!strnicmp(bmh.name, filename, 8))
2089 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2090 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2092 #define LINEBUF_SIZE 600
2093 int reading_textures = 0;
2094 short texture_count = 0;
2095 char inputline[LINEBUF_SIZE];
2097 int bitmaps_tbl_is_binary = 0;
2100 bitmaps = cfopen ("bitmaps.tbl", "rb");
2102 bitmaps = cfopen ("bitmaps.bin", "rb");
2103 bitmaps_tbl_is_binary = 1;
2107 Warning ("Could not find bitmaps.* for reading d1 textures");
2111 free_d1_tmap_nums();
2112 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2113 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2114 d1_tmap_nums[i] = -1;
2115 atexit(free_d1_tmap_nums);
2117 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2120 if (bitmaps_tbl_is_binary)
2121 decode_text_line((inputline));
2123 while (inputline[(i=strlen(inputline))-2]=='\\')
2124 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2125 REMOVE_EOL(inputline);
2126 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2127 if (strlen(inputline) == LINEBUF_SIZE-1) {
2128 Warning("Possible line truncation in BITMAPS.TBL");
2131 arg = strtok( inputline, space );
2132 if (arg && arg[0] == '@') {
2134 //Registered_only = 1;
2137 while (arg != NULL) {
2139 reading_textures = 0; // default
2140 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2141 reading_textures = 1;
2142 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2143 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2145 else // not a special token, must be a bitmap!
2146 if (reading_textures) {
2147 while (*arg == '\t' || *arg == ' ')
2148 arg++;//remove unwanted blanks
2151 if (d1_tmap_num_unique(texture_count)) {
2152 int d1_index = get_d1_bm_index(arg, d1_pig);
2153 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2154 d1_tmap_nums[d1_index] = texture_count;
2155 //int d2_index = d2_index_for_d1_index(d1_index);
2158 Assert (texture_count < D1_MAX_TEXTURES);
2162 arg = strtok (NULL, equal_space);
2168 /* If the given d1_index is the index of a bitmap we have to load
2169 * (because it is unique to descent 1), then returns the d2_index that
2170 * the given d1_index replaces.
2171 * Returns -1 if the given d1_index is not unique to descent 1.
2173 short d2_index_for_d1_index(short d1_index)
2175 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2176 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2177 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2180 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2183 #define D1_BITMAPS_SIZE 300000
2184 void load_d1_bitmap_replacements()
2186 CFILE * d1_Piggy_fp;
2187 DiskBitmapHeader bmh;
2188 int pig_data_start, bitmap_header_start, bitmap_data_start;
2190 short d1_index, d2_index;
2192 ubyte colormap[256];
2193 ubyte d1_palette[256*3];
2197 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2199 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2201 Warning(D1_PIG_LOAD_FAILED);
2205 //first, free up data allocated for old bitmaps
2206 free_bitmap_replacements();
2208 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2210 pigsize = cfilelength(d1_Piggy_fp);
2212 case D1_SHARE_BIG_PIGSIZE:
2213 case D1_SHARE_10_PIGSIZE:
2214 case D1_SHARE_PIGSIZE:
2215 case D1_10_BIG_PIGSIZE:
2218 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2219 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2222 Warning("Unknown size for " D1_PIGFILE);
2226 case D1_OEM_PIGSIZE:
2227 case D1_MAC_PIGSIZE:
2228 case D1_MAC_SHARE_PIGSIZE:
2229 pig_data_start = cfile_read_int(d1_Piggy_fp );
2230 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2231 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2235 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2236 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2238 int N_sounds = cfile_read_int(d1_Piggy_fp);
2239 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2240 + N_sounds * sizeof(DiskSoundHeader);
2241 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2242 bitmap_data_start = bitmap_header_start + header_size;
2245 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2246 if (!Bitmap_replacement_data) {
2247 Warning(D1_PIG_LOAD_FAILED);
2250 atexit(free_bitmap_replacements);
2252 next_bitmap = Bitmap_replacement_data;
2254 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2255 d2_index = d2_index_for_d1_index(d1_index);
2256 // only change bitmaps which are unique to d1
2257 if (d2_index != -1) {
2258 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2259 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2261 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2262 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2263 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2264 GameBitmapFlags[d2_index] = bmh.flags;
2266 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2267 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2268 int i, len = p - AllBitmaps[d2_index].name;
2269 for (i = 0; i < Num_bitmap_files; i++)
2270 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len)) {
2271 GameBitmaps[i] = GameBitmaps[d2_index];
2272 GameBitmapOffset[i] = 0;
2273 GameBitmapFlags[i] = bmh.flags;
2279 cfclose(d1_Piggy_fp);
2281 last_palette_loaded_pig[0]= 0; //force pig re-load
2283 texmerge_flush(); //for re-merging with new textures
2287 extern int extra_bitmap_num;
2290 * Find and load the named bitmap from descent.pig
2291 * similar to read_extra_bitmap_iff
2293 bitmap_index read_extra_bitmap_d1_pig(char *name)
2295 bitmap_index bitmap_num;
2296 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2298 bitmap_num.index = 0;
2302 DiskBitmapHeader bmh;
2303 int pig_data_start, bitmap_header_start, bitmap_data_start;
2305 ubyte colormap[256];
2306 ubyte d1_palette[256*3];
2309 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2313 Warning(D1_PIG_LOAD_FAILED);
2317 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2319 pigsize = cfilelength(d1_Piggy_fp);
2321 case D1_SHARE_BIG_PIGSIZE:
2322 case D1_SHARE_10_PIGSIZE:
2323 case D1_SHARE_PIGSIZE:
2324 case D1_10_BIG_PIGSIZE:
2329 Warning("Unknown size for " D1_PIGFILE);
2333 case D1_OEM_PIGSIZE:
2334 case D1_MAC_PIGSIZE:
2335 case D1_MAC_SHARE_PIGSIZE:
2336 pig_data_start = cfile_read_int(d1_Piggy_fp );
2341 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2342 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2344 int N_sounds = cfile_read_int(d1_Piggy_fp);
2345 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2346 + N_sounds * sizeof(DiskSoundHeader);
2347 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2348 bitmap_data_start = bitmap_header_start + header_size;
2351 for (i = 1; i <= N_bitmaps; i++)
2353 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2354 if (!strnicmp(bmh.name, name, 8))
2358 if (strnicmp(bmh.name, name, 8))
2360 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2364 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2366 cfclose(d1_Piggy_fp);
2369 new->avg_color = 0; //compute_average_pixel(new);
2371 bitmap_num.index = extra_bitmap_num;
2373 GameBitmaps[extra_bitmap_num++] = *new;
2379 #ifndef FAST_FILE_IO
2381 * reads a bitmap_index structure from a CFILE
2383 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2385 bi->index = cfile_read_short(fp);
2389 * reads n bitmap_index structs from a CFILE
2391 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2395 for (i = 0; i < n; i++)
2396 bi[i].index = cfile_read_short(fp);
2399 #endif // FAST_FILE_IO