1 /* $Id: piggy.c,v 1.60 2005-01-10 17:47:27 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.60 2005-01-10 17:47:27 schaffner 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 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 extern void gr_set_bitmap_flags(grs_bitmap *pbm, int flags);
1350 void piggy_bitmap_page_in( bitmap_index bitmap )
1359 Assert( i < MAX_BITMAP_FILES );
1360 Assert( i < Num_bitmap_files );
1361 Assert( Piggy_bitmap_cache_size > 0 );
1363 if ( i < 1 ) return;
1364 if ( i >= MAX_BITMAP_FILES ) return;
1365 if ( i >= Num_bitmap_files ) return;
1367 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1369 if ( piggy_low_memory ) {
1371 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1374 bmp = &GameBitmaps[i];
1376 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1380 descent_critical_error = 0;
1381 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1382 if ( descent_critical_error ) {
1383 piggy_critical_error();
1387 gr_set_bitmap_flags(bmp, GameBitmapFlags[i]);
1389 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1390 int zsize = 0, pigsize = cfilelength(Piggy_fp);
1391 descent_critical_error = 0;
1392 zsize = cfile_read_int(Piggy_fp);
1393 if ( descent_critical_error ) {
1394 piggy_critical_error();
1398 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1399 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1400 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1402 piggy_bitmap_page_out_all();
1405 descent_critical_error = 0;
1406 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1407 if ( descent_critical_error ) {
1408 piggy_critical_error();
1411 *((int *) (Piggy_bitmap_cache_data + Piggy_bitmap_cache_next)) = INTEL_INT(zsize);
1412 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1417 if (!FindArg("-macdata"))
1419 // otherwise, fall through...
1420 case MAC_ALIEN1_PIGSIZE:
1421 case MAC_ALIEN2_PIGSIZE:
1422 case MAC_FIRE_PIGSIZE:
1423 case MAC_GROUPA_PIGSIZE:
1424 case MAC_ICE_PIGSIZE:
1425 case MAC_WATER_PIGSIZE:
1426 rle_swap_0_255( bmp );
1427 memcpy(&zsize, bmp->bm_data, 4);
1432 Piggy_bitmap_cache_next += zsize;
1433 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1435 piggy_bitmap_page_out_all();
1440 int pigsize = cfilelength(Piggy_fp);
1441 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1442 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1443 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1444 piggy_bitmap_page_out_all();
1447 descent_critical_error = 0;
1448 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1449 if ( descent_critical_error ) {
1450 piggy_critical_error();
1453 gr_set_bitmap_data(bmp, &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]);
1454 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1459 if (!FindArg("-macdata"))
1461 // otherwise, fall through...
1462 case MAC_ALIEN1_PIGSIZE:
1463 case MAC_ALIEN2_PIGSIZE:
1464 case MAC_FIRE_PIGSIZE:
1465 case MAC_GROUPA_PIGSIZE:
1466 case MAC_ICE_PIGSIZE:
1467 case MAC_WATER_PIGSIZE:
1474 //@@if ( bmp->bm_selector ) {
1475 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1476 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1477 //@@ Error( "Error modifying selector base in piggy.c\n" );
1484 if ( piggy_low_memory ) {
1486 GameBitmaps[org_i] = GameBitmaps[i];
1489 //@@Removed from John's code:
1491 //@@ if ( bmp->bm_selector ) {
1492 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1493 //@@ Error( "Error modifying selector base in piggy.c\n" );
1499 void piggy_bitmap_page_out_all()
1503 Piggy_bitmap_cache_next = 0;
1505 piggy_page_flushed++;
1510 for (i=0; i<Num_bitmap_files; i++ ) {
1511 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1512 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1513 gr_set_bitmap_data(&GameBitmaps[i], NULL);
1517 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1520 void piggy_load_level_data()
1522 piggy_bitmap_page_out_all();
1528 void change_filename_ext( char *dest, char *src, char *ext );
1530 void piggy_write_pigfile(char *filename)
1533 int bitmap_data_start, data_offset;
1534 DiskBitmapHeader bmh;
1536 char subst_name[32];
1539 char tname[FILENAME_LEN];
1541 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1542 for (i=0; i < Num_bitmap_files; i++ ) {
1545 PIGGY_PAGE_IN( bi );
1547 // -- mprintf( (0, "\n" ));
1551 // -- mprintf( (0, "Creating %s...",filename ));
1553 pig_fp = fopen( filename, "wb" ); //open PIG file
1554 Assert( pig_fp!=NULL );
1556 write_int(PIGFILE_ID,pig_fp);
1557 write_int(PIGFILE_VERSION,pig_fp);
1560 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1563 bitmap_data_start = ftell(pig_fp);
1564 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1565 data_offset = bitmap_data_start;
1567 change_filename_ext(tname,filename,"lst");
1568 fp1 = fopen( tname, "wt" );
1569 change_filename_ext(tname,filename,"all");
1570 fp2 = fopen( tname, "wt" );
1572 for (i=1; i < Num_bitmap_files; i++ ) {
1578 p = strchr(AllBitmaps[i].name, '#');
1579 if (p) { // this is an ABM == animated bitmap
1585 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1586 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1587 Assert( n <= DBM_NUM_FRAMES );
1588 bmh.dflags = DBM_FLAG_ABM + n;
1592 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1593 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1597 bmp = &GameBitmaps[i];
1599 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1602 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1603 org_offset = ftell(pig_fp);
1604 bmh.offset = data_offset - bitmap_data_start;
1605 fseek( pig_fp, data_offset, SEEK_SET );
1607 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1608 size = (int *)bmp->bm_data;
1609 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1610 data_offset += *size;
1612 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1614 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1615 data_offset += bmp->bm_rowsize * bmp->bm_h;
1617 fprintf( fp1, ".\n" );
1619 fseek( pig_fp, org_offset, SEEK_SET );
1620 Assert( GameBitmaps[i].bm_w < 4096 );
1621 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1622 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1623 Assert( GameBitmaps[i].bm_h < 4096 );
1624 bmh.height = GameBitmaps[i].bm_h;
1625 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1626 bmh.flags = GameBitmaps[i].bm_flags;
1627 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1628 bitmap_index other_bitmap;
1629 other_bitmap = piggy_find_bitmap( subst_name );
1630 GameBitmapXlat[i] = other_bitmap.index;
1631 bmh.flags |= BM_FLAG_PAGED_OUT;
1632 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1633 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1635 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1637 bmh.avg_color=GameBitmaps[i].avg_color;
1638 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1643 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1644 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1651 static void write_int(int i,FILE *file)
1653 if (fwrite( &i, sizeof(i), 1, file) != 1)
1654 Error( "Error reading int in gamesave.c" );
1658 void piggy_dump_all()
1662 int org_offset,data_offset=0;
1663 DiskSoundHeader sndh;
1664 int sound_data_start=0;
1667 #ifdef NO_DUMP_SOUNDS
1668 Num_sound_files = 0;
1669 Num_sound_files_new = 0;
1672 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1675 fp1 = fopen( "ham.lst", "wt" );
1676 fp2 = fopen( "ham.all", "wt" );
1678 if (Must_write_hamfile || Num_bitmap_files_new) {
1680 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1682 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1683 Assert( ham_fp!=NULL );
1685 write_int(HAMFILE_ID,ham_fp);
1686 write_int(HAMFILE_VERSION,ham_fp);
1688 bm_write_all(ham_fp);
1689 xlat_offset = ftell(ham_fp);
1690 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1693 if (Num_bitmap_files_new)
1694 piggy_write_pigfile(DEFAULT_PIGFILE);
1696 //free up memeory used by new bitmaps
1697 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1698 d_free(GameBitmaps[i].bm_data);
1700 //next thing must be done after pig written
1701 fseek( ham_fp, xlat_offset, SEEK_SET );
1702 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1705 mprintf( (0, "\n" ));
1708 if (Num_sound_files_new) {
1710 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1711 // Now dump sound file
1712 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1713 Assert( ham_fp!=NULL );
1715 write_int(SNDFILE_ID,ham_fp);
1716 write_int(SNDFILE_VERSION,ham_fp);
1718 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1720 mprintf( (0, "\nDumping sounds..." ));
1722 sound_data_start = ftell(ham_fp);
1723 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1724 data_offset = sound_data_start;
1726 for (i=0; i < Num_sound_files; i++ ) {
1729 snd = &GameSounds[i];
1730 strcpy( sndh.name, AllSounds[i].name );
1731 sndh.length = GameSounds[i].length;
1732 sndh.offset = data_offset - sound_data_start;
1734 org_offset = ftell(ham_fp);
1735 fseek( ham_fp, data_offset, SEEK_SET );
1737 sndh.data_length = GameSounds[i].length;
1738 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1739 data_offset += snd->length;
1740 fseek( ham_fp, org_offset, SEEK_SET );
1741 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1743 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1744 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1748 mprintf( (0, "\n" ));
1751 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1752 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1753 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1758 // Never allow the game to run after building ham.
1772 d_free( SoundBits );
1774 hashtable_free( &AllBitmapsNames );
1775 hashtable_free( &AllDigiSndNames );
1779 int piggy_does_bitmap_exist_slow( char * name )
1783 for (i=0; i<Num_bitmap_files; i++ ) {
1784 if ( !strcmp( AllBitmaps[i].name, name) )
1791 #define NUM_GAUGE_BITMAPS 23
1792 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1793 "gauge01", "gauge01b",
1794 "gauge02", "gauge02b",
1795 "gauge06", "gauge06b",
1796 "targ01", "targ01b",
1797 "targ02", "targ02b",
1798 "targ03", "targ03b",
1799 "targ04", "targ04b",
1800 "targ05", "targ05b",
1801 "targ06", "targ06b",
1802 "gauge18", "gauge18b",
1808 int piggy_is_gauge_bitmap( char * base_name )
1811 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1812 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1819 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1823 char base_name[ 16 ];
1825 strcpy( subst_name, name );
1826 p = strchr( subst_name, '#' );
1828 frame = atoi( &p[1] );
1830 strcpy( base_name, subst_name );
1831 if ( !piggy_is_gauge_bitmap( base_name )) {
1832 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1833 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1835 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1841 strcpy( subst_name, name );
1848 // New Windows stuff
1850 // windows bitmap page in
1851 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1852 // 'video' memory. if that fails, page it in normally.
1854 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1859 // Essential when switching video modes!
1861 void piggy_bitmap_page_out_all_w()
1869 * Functions for loading replacement textures
1870 * 1) From .pog files
1871 * 2) From descent.pig (for loading d1 levels)
1874 extern void change_filename_extension( char *dest, char *src, char *new_ext );
1875 extern char last_palette_loaded_pig[];
1877 void free_bitmap_replacements()
1879 if (Bitmap_replacement_data) {
1880 d_free(Bitmap_replacement_data);
1881 Bitmap_replacement_data = NULL;
1885 void load_bitmap_replacements(char *level_name)
1887 char ifile_name[FILENAME_LEN];
1891 //first, free up data allocated for old bitmaps
1892 free_bitmap_replacements();
1894 change_filename_extension(ifile_name, level_name, ".POG" );
1896 ifile = cfopen(ifile_name,"rb");
1899 int id,version,n_bitmaps;
1900 int bitmap_data_size;
1903 id = cfile_read_int(ifile);
1904 version = cfile_read_int(ifile);
1906 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1911 n_bitmaps = cfile_read_int(ifile);
1913 MALLOC( indices, ushort, n_bitmaps );
1915 for (i = 0; i < n_bitmaps; i++)
1916 indices[i] = cfile_read_short(ifile);
1918 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1919 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1921 for (i=0;i<n_bitmaps;i++) {
1922 DiskBitmapHeader bmh;
1923 grs_bitmap *bm = &GameBitmaps[indices[i]];
1926 DiskBitmapHeader_read(&bmh, ifile);
1928 width = bmh.width + ((short) (bmh.wh_extra & 0x0f) << 8);
1929 gr_set_bitmap_data(bm, NULL); // free ogl texture
1930 gr_init_bitmap(bm, 0, 0, 0, width, bmh.height + ((short) (bmh.wh_extra & 0xf0) << 4), width, NULL);
1931 bm->avg_color = bmh.avg_color;
1932 bm->bm_data = (ubyte *) bmh.offset;
1934 gr_set_bitmap_flags(bm, bmh.flags & BM_FLAGS_TO_COPY);
1936 GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1939 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1941 for (i = 0; i < n_bitmaps; i++)
1943 grs_bitmap *bm = &GameBitmaps[indices[i]];
1944 gr_set_bitmap_data(bm, Bitmap_replacement_data + (int) bm->bm_data);
1951 last_palette_loaded_pig[0]= 0; //force pig re-load
1953 texmerge_flush(); //for re-merging with new textures
1956 atexit(free_bitmap_replacements);
1959 /* calculate table to translate d1 bitmaps to current palette,
1960 * return -1 on error
1962 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1965 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1966 if (!palette_file || cfilelength(palette_file) != 9472)
1968 cfread( d1_palette, 256, 3, palette_file);
1969 cfclose( palette_file );
1970 build_colormap_good( d1_palette, colormap, freq );
1971 // don't change transparencies:
1972 colormap[254] = 254;
1973 colormap[255] = 255;
1977 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1978 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1979 CFILE *d1_Piggy_fp, /* read from this file */
1980 int bitmap_data_start, /* specific to file */
1981 DiskBitmapHeader *bmh, /* header info for bitmap */
1982 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1983 ubyte *d1_palette, /* what palette the bitmap has */
1984 ubyte *colormap) /* how to translate bitmap's colors */
1986 int zsize, pigsize = cfilelength(d1_Piggy_fp);
1990 width = bmh->width + ((short) (bmh->wh_extra & 0x0f) << 8);
1991 gr_set_bitmap_data(bitmap, NULL); // free ogl texture
1992 gr_init_bitmap(bitmap, 0, 0, 0, width, bmh->height + ((short) (bmh->wh_extra & 0xf0) << 4), width, NULL);
1993 bitmap->avg_color = bmh->avg_color;
1994 gr_set_bitmap_flags(bitmap, bmh->flags & BM_FLAGS_TO_COPY);
1996 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1997 if (bmh->flags & BM_FLAG_RLE) {
1998 zsize = cfile_read_int(d1_Piggy_fp);
1999 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
2001 zsize = bitmap->bm_h * bitmap->bm_w;
2004 data = *next_bitmap;
2005 *next_bitmap += zsize;
2007 data = d_malloc(zsize + JUST_IN_CASE);
2011 cfread(data, 1, zsize, d1_Piggy_fp);
2012 gr_set_bitmap_data(bitmap, data);
2014 case D1_MAC_PIGSIZE:
2015 case D1_MAC_SHARE_PIGSIZE:
2016 if (bmh->flags & BM_FLAG_RLE)
2017 rle_swap_0_255(bitmap);
2021 if (bmh->flags & BM_FLAG_RLE)
2022 rle_remap(bitmap, colormap);
2024 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
2025 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
2027 memcpy(&new_size, bitmap->bm_data, 4);
2029 *next_bitmap += new_size - zsize;
2031 Assert( zsize + JUST_IN_CASE >= new_size );
2032 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
2033 Assert(bitmap->bm_data);
2038 #define D1_MAX_TEXTURES 800
2039 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
2041 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
2042 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
2043 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
2045 short *d1_tmap_nums = NULL;
2047 void free_d1_tmap_nums() {
2049 d_free(d1_tmap_nums);
2050 d1_tmap_nums = NULL;
2054 void bm_read_d1_tmap_nums(CFILE *d1pig)
2058 free_d1_tmap_nums();
2059 cfseek(d1pig, 8, SEEK_SET);
2060 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2061 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2062 d1_tmap_nums[i] = -1;
2063 for (i = 0; i < D1_MAX_TEXTURES; i++) {
2064 d1_index = cfile_read_short(d1pig);
2065 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2066 d1_tmap_nums[d1_index] = i;
2068 atexit(free_d1_tmap_nums);
2071 void remove_char( char * s, char c )
2078 #define REMOVE_EOL(s) remove_char((s),'\n')
2079 #define REMOVE_COMMENTS(s) remove_char((s),';')
2080 #define REMOVE_DOTS(s) remove_char((s),'.')
2081 char *space = { " \t" };
2082 char *equal_space = { " \t=" };
2084 // this function is at the same position in the d1 shareware piggy loading
2085 // algorithm as bm_load_sub in main/bmread.c
2086 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2088 DiskBitmapHeader bmh;
2089 if (strchr (filename, '.'))
2090 *strchr (filename, '.') = '\0'; // remove extension
2091 cfseek (d1_pig, 0, SEEK_SET);
2092 N_bitmaps = cfile_read_int (d1_pig);
2093 cfseek (d1_pig, 8, SEEK_SET);
2094 for (i = 1; i <= N_bitmaps; i++) {
2095 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2096 if (!strnicmp(bmh.name, filename, 8))
2102 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2103 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2105 #define LINEBUF_SIZE 600
2106 int reading_textures = 0;
2107 short texture_count = 0;
2108 char inputline[LINEBUF_SIZE];
2110 int bitmaps_tbl_is_binary = 0;
2113 bitmaps = cfopen ("bitmaps.tbl", "rb");
2115 bitmaps = cfopen ("bitmaps.bin", "rb");
2116 bitmaps_tbl_is_binary = 1;
2120 Warning ("Could not find bitmaps.* for reading d1 textures");
2124 free_d1_tmap_nums();
2125 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2126 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2127 d1_tmap_nums[i] = -1;
2128 atexit(free_d1_tmap_nums);
2130 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2133 if (bitmaps_tbl_is_binary)
2134 decode_text_line((inputline));
2136 while (inputline[(i=strlen(inputline))-2]=='\\')
2137 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2138 REMOVE_EOL(inputline);
2139 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2140 if (strlen(inputline) == LINEBUF_SIZE-1) {
2141 Warning("Possible line truncation in BITMAPS.TBL");
2144 arg = strtok( inputline, space );
2145 if (arg && arg[0] == '@') {
2147 //Registered_only = 1;
2150 while (arg != NULL) {
2152 reading_textures = 0; // default
2153 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2154 reading_textures = 1;
2155 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2156 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2158 else // not a special token, must be a bitmap!
2159 if (reading_textures) {
2160 while (*arg == '\t' || *arg == ' ')
2161 arg++;//remove unwanted blanks
2164 if (d1_tmap_num_unique(texture_count)) {
2165 int d1_index = get_d1_bm_index(arg, d1_pig);
2166 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2167 d1_tmap_nums[d1_index] = texture_count;
2168 //int d2_index = d2_index_for_d1_index(d1_index);
2171 Assert (texture_count < D1_MAX_TEXTURES);
2175 arg = strtok (NULL, equal_space);
2181 /* If the given d1_index is the index of a bitmap we have to load
2182 * (because it is unique to descent 1), then returns the d2_index that
2183 * the given d1_index replaces.
2184 * Returns -1 if the given d1_index is not unique to descent 1.
2186 short d2_index_for_d1_index(short d1_index)
2188 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2189 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2190 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2193 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2196 #define D1_BITMAPS_SIZE 300000
2197 void load_d1_bitmap_replacements()
2199 CFILE * d1_Piggy_fp;
2200 DiskBitmapHeader bmh;
2201 int pig_data_start, bitmap_header_start, bitmap_data_start;
2203 short d1_index, d2_index;
2205 ubyte colormap[256];
2206 ubyte d1_palette[256*3];
2210 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2212 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2214 Warning(D1_PIG_LOAD_FAILED);
2218 //first, free up data allocated for old bitmaps
2219 free_bitmap_replacements();
2221 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2223 pigsize = cfilelength(d1_Piggy_fp);
2225 case D1_SHARE_BIG_PIGSIZE:
2226 case D1_SHARE_10_PIGSIZE:
2227 case D1_SHARE_PIGSIZE:
2228 case D1_10_BIG_PIGSIZE:
2231 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2232 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2235 Warning("Unknown size for " D1_PIGFILE);
2239 case D1_OEM_PIGSIZE:
2240 case D1_MAC_PIGSIZE:
2241 case D1_MAC_SHARE_PIGSIZE:
2242 pig_data_start = cfile_read_int(d1_Piggy_fp );
2243 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2244 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2248 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2249 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2251 int N_sounds = cfile_read_int(d1_Piggy_fp);
2252 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2253 + N_sounds * sizeof(DiskSoundHeader);
2254 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2255 bitmap_data_start = bitmap_header_start + header_size;
2258 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2259 if (!Bitmap_replacement_data) {
2260 Warning(D1_PIG_LOAD_FAILED);
2263 atexit(free_bitmap_replacements);
2265 next_bitmap = Bitmap_replacement_data;
2267 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2268 d2_index = d2_index_for_d1_index(d1_index);
2269 // only change bitmaps which are unique to d1
2270 if (d2_index != -1) {
2271 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2272 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2274 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2275 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2276 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2277 GameBitmapFlags[d2_index] = bmh.flags;
2279 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2280 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2281 int i, len = p - AllBitmaps[d2_index].name;
2282 for (i = 0; i < Num_bitmap_files; i++)
2283 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len))
2285 gr_set_bitmap_data(&GameBitmaps[i], NULL); // free ogl texture
2286 GameBitmaps[i] = GameBitmaps[d2_index];
2287 GameBitmapOffset[i] = 0;
2288 GameBitmapFlags[i] = bmh.flags;
2294 cfclose(d1_Piggy_fp);
2296 last_palette_loaded_pig[0]= 0; //force pig re-load
2298 texmerge_flush(); //for re-merging with new textures
2302 extern int extra_bitmap_num;
2305 * Find and load the named bitmap from descent.pig
2306 * similar to read_extra_bitmap_iff
2308 bitmap_index read_extra_bitmap_d1_pig(char *name)
2310 bitmap_index bitmap_num;
2311 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2313 bitmap_num.index = 0;
2317 DiskBitmapHeader bmh;
2318 int pig_data_start, bitmap_header_start, bitmap_data_start;
2320 ubyte colormap[256];
2321 ubyte d1_palette[256*3];
2324 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2328 Warning(D1_PIG_LOAD_FAILED);
2332 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2334 pigsize = cfilelength(d1_Piggy_fp);
2336 case D1_SHARE_BIG_PIGSIZE:
2337 case D1_SHARE_10_PIGSIZE:
2338 case D1_SHARE_PIGSIZE:
2339 case D1_10_BIG_PIGSIZE:
2344 Warning("Unknown size for " D1_PIGFILE);
2348 case D1_OEM_PIGSIZE:
2349 case D1_MAC_PIGSIZE:
2350 case D1_MAC_SHARE_PIGSIZE:
2351 pig_data_start = cfile_read_int(d1_Piggy_fp );
2356 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2357 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2359 int N_sounds = cfile_read_int(d1_Piggy_fp);
2360 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2361 + N_sounds * sizeof(DiskSoundHeader);
2362 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2363 bitmap_data_start = bitmap_header_start + header_size;
2366 for (i = 1; i <= N_bitmaps; i++)
2368 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2369 if (!strnicmp(bmh.name, name, 8))
2373 if (strnicmp(bmh.name, name, 8))
2375 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2379 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2381 cfclose(d1_Piggy_fp);
2384 new->avg_color = 0; //compute_average_pixel(new);
2386 bitmap_num.index = extra_bitmap_num;
2388 GameBitmaps[extra_bitmap_num++] = *new;
2394 #ifndef FAST_FILE_IO
2396 * reads a bitmap_index structure from a CFILE
2398 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2400 bi->index = cfile_read_short(fp);
2404 * reads n bitmap_index structs from a CFILE
2406 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2410 for (i = 0; i < n; i++)
2411 bi[i].index = cfile_read_short(fp);
2414 #endif // FAST_FILE_IO