1 /* $Id: piggy.c,v 1.56 2004-11-19 18:02:32 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.56 2004-11-19 18:02:32 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)
563 return cfopen(filename, "rb");
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);
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 ) {
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();
1412 switch (cfilelength(Piggy_fp)) {
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 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1439 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1440 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1441 piggy_bitmap_page_out_all();
1444 descent_critical_error = 0;
1445 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1446 if ( descent_critical_error ) {
1447 piggy_critical_error();
1450 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1453 switch (cfilelength(Piggy_fp)) {
1455 if (!FindArg("-macdata"))
1457 // otherwise, fall through...
1458 case MAC_ALIEN1_PIGSIZE:
1459 case MAC_ALIEN2_PIGSIZE:
1460 case MAC_FIRE_PIGSIZE:
1461 case MAC_GROUPA_PIGSIZE:
1462 case MAC_ICE_PIGSIZE:
1463 case MAC_WATER_PIGSIZE:
1470 //@@if ( bmp->bm_selector ) {
1471 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1472 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1473 //@@ Error( "Error modifying selector base in piggy.c\n" );
1480 if ( piggy_low_memory ) {
1482 GameBitmaps[org_i] = GameBitmaps[i];
1485 //@@Removed from John's code:
1487 //@@ if ( bmp->bm_selector ) {
1488 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1489 //@@ Error( "Error modifying selector base in piggy.c\n" );
1495 void piggy_bitmap_page_out_all()
1499 Piggy_bitmap_cache_next = 0;
1501 piggy_page_flushed++;
1506 for (i=0; i<Num_bitmap_files; i++ ) {
1507 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1508 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1509 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1513 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1516 void piggy_load_level_data()
1518 piggy_bitmap_page_out_all();
1524 void change_filename_ext( char *dest, char *src, char *ext );
1526 void piggy_write_pigfile(char *filename)
1529 int bitmap_data_start, data_offset;
1530 DiskBitmapHeader bmh;
1532 char subst_name[32];
1535 char tname[FILENAME_LEN];
1537 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1538 for (i=0; i < Num_bitmap_files; i++ ) {
1541 PIGGY_PAGE_IN( bi );
1543 // -- mprintf( (0, "\n" ));
1547 // -- mprintf( (0, "Creating %s...",filename ));
1549 pig_fp = fopen( filename, "wb" ); //open PIG file
1550 Assert( pig_fp!=NULL );
1552 write_int(PIGFILE_ID,pig_fp);
1553 write_int(PIGFILE_VERSION,pig_fp);
1556 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1559 bitmap_data_start = ftell(pig_fp);
1560 bitmap_data_start += (Num_bitmap_files - 1) * sizeof(DiskBitmapHeader);
1561 data_offset = bitmap_data_start;
1563 change_filename_ext(tname,filename,"lst");
1564 fp1 = fopen( tname, "wt" );
1565 change_filename_ext(tname,filename,"all");
1566 fp2 = fopen( tname, "wt" );
1568 for (i=1; i < Num_bitmap_files; i++ ) {
1574 p = strchr(AllBitmaps[i].name, '#');
1575 if (p) { // this is an ABM == animated bitmap
1581 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1582 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1583 Assert( n <= DBM_NUM_FRAMES );
1584 bmh.dflags = DBM_FLAG_ABM + n;
1588 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1589 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1593 bmp = &GameBitmaps[i];
1595 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1598 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1599 org_offset = ftell(pig_fp);
1600 bmh.offset = data_offset - bitmap_data_start;
1601 fseek( pig_fp, data_offset, SEEK_SET );
1603 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1604 size = (int *)bmp->bm_data;
1605 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1606 data_offset += *size;
1608 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1610 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1611 data_offset += bmp->bm_rowsize * bmp->bm_h;
1613 fprintf( fp1, ".\n" );
1615 fseek( pig_fp, org_offset, SEEK_SET );
1616 Assert( GameBitmaps[i].bm_w < 4096 );
1617 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1618 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1619 Assert( GameBitmaps[i].bm_h < 4096 );
1620 bmh.height = GameBitmaps[i].bm_h;
1621 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1622 bmh.flags = GameBitmaps[i].bm_flags;
1623 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1624 bitmap_index other_bitmap;
1625 other_bitmap = piggy_find_bitmap( subst_name );
1626 GameBitmapXlat[i] = other_bitmap.index;
1627 bmh.flags |= BM_FLAG_PAGED_OUT;
1628 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1629 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1631 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1633 bmh.avg_color=GameBitmaps[i].avg_color;
1634 fwrite(&bmh, sizeof(DiskBitmapHeader), 1, pig_fp); // Mark as a bitmap
1639 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1640 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1647 static void write_int(int i,FILE *file)
1649 if (fwrite( &i, sizeof(i), 1, file) != 1)
1650 Error( "Error reading int in gamesave.c" );
1654 void piggy_dump_all()
1658 int org_offset,data_offset=0;
1659 DiskSoundHeader sndh;
1660 int sound_data_start=0;
1663 #ifdef NO_DUMP_SOUNDS
1664 Num_sound_files = 0;
1665 Num_sound_files_new = 0;
1668 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1671 fp1 = fopen( "ham.lst", "wt" );
1672 fp2 = fopen( "ham.all", "wt" );
1674 if (Must_write_hamfile || Num_bitmap_files_new) {
1676 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1678 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1679 Assert( ham_fp!=NULL );
1681 write_int(HAMFILE_ID,ham_fp);
1682 write_int(HAMFILE_VERSION,ham_fp);
1684 bm_write_all(ham_fp);
1685 xlat_offset = ftell(ham_fp);
1686 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1689 if (Num_bitmap_files_new)
1690 piggy_write_pigfile(DEFAULT_PIGFILE);
1692 //free up memeory used by new bitmaps
1693 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1694 d_free(GameBitmaps[i].bm_data);
1696 //next thing must be done after pig written
1697 fseek( ham_fp, xlat_offset, SEEK_SET );
1698 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1701 mprintf( (0, "\n" ));
1704 if (Num_sound_files_new) {
1706 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1707 // Now dump sound file
1708 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1709 Assert( ham_fp!=NULL );
1711 write_int(SNDFILE_ID,ham_fp);
1712 write_int(SNDFILE_VERSION,ham_fp);
1714 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1716 mprintf( (0, "\nDumping sounds..." ));
1718 sound_data_start = ftell(ham_fp);
1719 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1720 data_offset = sound_data_start;
1722 for (i=0; i < Num_sound_files; i++ ) {
1725 snd = &GameSounds[i];
1726 strcpy( sndh.name, AllSounds[i].name );
1727 sndh.length = GameSounds[i].length;
1728 sndh.offset = data_offset - sound_data_start;
1730 org_offset = ftell(ham_fp);
1731 fseek( ham_fp, data_offset, SEEK_SET );
1733 sndh.data_length = GameSounds[i].length;
1734 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1735 data_offset += snd->length;
1736 fseek( ham_fp, org_offset, SEEK_SET );
1737 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1739 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1740 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1744 mprintf( (0, "\n" ));
1747 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1748 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1749 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1754 // Never allow the game to run after building ham.
1768 d_free( SoundBits );
1770 hashtable_free( &AllBitmapsNames );
1771 hashtable_free( &AllDigiSndNames );
1775 int piggy_does_bitmap_exist_slow( char * name )
1779 for (i=0; i<Num_bitmap_files; i++ ) {
1780 if ( !strcmp( AllBitmaps[i].name, name) )
1787 #define NUM_GAUGE_BITMAPS 23
1788 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1789 "gauge01", "gauge01b",
1790 "gauge02", "gauge02b",
1791 "gauge06", "gauge06b",
1792 "targ01", "targ01b",
1793 "targ02", "targ02b",
1794 "targ03", "targ03b",
1795 "targ04", "targ04b",
1796 "targ05", "targ05b",
1797 "targ06", "targ06b",
1798 "gauge18", "gauge18b",
1804 int piggy_is_gauge_bitmap( char * base_name )
1807 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1808 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1815 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1819 char base_name[ 16 ];
1821 strcpy( subst_name, name );
1822 p = strchr( subst_name, '#' );
1824 frame = atoi( &p[1] );
1826 strcpy( base_name, subst_name );
1827 if ( !piggy_is_gauge_bitmap( base_name )) {
1828 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1829 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1831 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1837 strcpy( subst_name, name );
1844 // New Windows stuff
1846 // windows bitmap page in
1847 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1848 // 'video' memory. if that fails, page it in normally.
1850 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1855 // Essential when switching video modes!
1857 void piggy_bitmap_page_out_all_w()
1865 * Functions for loading replacement textures
1866 * 1) From .pog files
1867 * 2) From descent.pig (for loading d1 levels)
1870 extern void change_filename_extension( char *dest, char *src, char *new_ext );
1871 extern char last_palette_loaded_pig[];
1873 void free_bitmap_replacements()
1875 if (Bitmap_replacement_data) {
1876 d_free(Bitmap_replacement_data);
1877 Bitmap_replacement_data = NULL;
1881 void load_bitmap_replacements(char *level_name)
1883 char ifile_name[FILENAME_LEN];
1887 //first, free up data allocated for old bitmaps
1888 free_bitmap_replacements();
1890 change_filename_extension(ifile_name, level_name, ".POG" );
1892 ifile = cfopen(ifile_name,"rb");
1895 int id,version,n_bitmaps;
1896 int bitmap_data_size;
1899 id = cfile_read_int(ifile);
1900 version = cfile_read_int(ifile);
1902 if (id != MAKE_SIG('G','O','P','D') || version != 1) {
1907 n_bitmaps = cfile_read_int(ifile);
1909 MALLOC( indices, ushort, n_bitmaps );
1911 for (i = 0; i < n_bitmaps; i++)
1912 indices[i] = cfile_read_short(ifile);
1914 bitmap_data_size = cfilelength(ifile) - cftell(ifile) - sizeof(DiskBitmapHeader) * n_bitmaps;
1915 MALLOC( Bitmap_replacement_data, ubyte, bitmap_data_size );
1917 for (i=0;i<n_bitmaps;i++) {
1918 DiskBitmapHeader bmh;
1919 grs_bitmap temp_bitmap;
1921 DiskBitmapHeader_read(&bmh, ifile);
1923 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1925 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1926 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1927 temp_bitmap.avg_color = bmh.avg_color;
1928 temp_bitmap.bm_data = Bitmap_replacement_data + bmh.offset;
1930 temp_bitmap.bm_flags |= bmh.flags & BM_FLAGS_TO_COPY;
1932 GameBitmaps[indices[i]] = temp_bitmap;
1933 // don't we need the following? GameBitmapOffset[indices[i]] = 0; // don't try to read bitmap from current pigfile
1936 cfread(Bitmap_replacement_data,1,bitmap_data_size,ifile);
1942 last_palette_loaded_pig[0]= 0; //force pig re-load
1944 texmerge_flush(); //for re-merging with new textures
1947 atexit(free_bitmap_replacements);
1950 /* calculate table to translate d1 bitmaps to current palette,
1951 * return -1 on error
1953 int get_d1_colormap( ubyte *d1_palette, ubyte *colormap )
1956 CFILE * palette_file = cfopen(D1_PALETTE, "rb");
1957 if (!palette_file || cfilelength(palette_file) != 9472)
1959 cfread( d1_palette, 256, 3, palette_file);
1960 cfclose( palette_file );
1961 build_colormap_good( d1_palette, colormap, freq );
1962 // don't change transparencies:
1963 colormap[254] = 254;
1964 colormap[255] = 255;
1968 #define JUST_IN_CASE 132 /* is enough for d1 pc registered */
1969 void bitmap_read_d1( grs_bitmap *bitmap, /* read into this bitmap */
1970 CFILE *d1_Piggy_fp, /* read from this file */
1971 int bitmap_data_start, /* specific to file */
1972 DiskBitmapHeader *bmh, /* header info for bitmap */
1973 ubyte **next_bitmap, /* where to write it (if 0, use malloc) */
1974 ubyte *d1_palette, /* what palette the bitmap has */
1975 ubyte *colormap) /* how to translate bitmap's colors */
1978 memset( bitmap, 0, sizeof(grs_bitmap) );
1980 bitmap->bm_w = bitmap->bm_rowsize = bmh->width + ((short) (bmh->wh_extra&0x0f)<<8);
1981 bitmap->bm_h = bmh->height + ((short) (bmh->wh_extra&0xf0)<<4);
1982 bitmap->avg_color = bmh->avg_color;
1983 bitmap->bm_flags |= bmh->flags & BM_FLAGS_TO_COPY;
1985 cfseek(d1_Piggy_fp, bitmap_data_start + bmh->offset, SEEK_SET);
1986 if (bmh->flags & BM_FLAG_RLE) {
1987 zsize = cfile_read_int(d1_Piggy_fp);
1988 cfseek(d1_Piggy_fp, -4, SEEK_CUR);
1990 zsize = bitmap->bm_h * bitmap->bm_w;
1993 bitmap->bm_data = *next_bitmap;
1994 *next_bitmap += zsize;
1996 bitmap->bm_data = d_malloc(zsize + JUST_IN_CASE);
1998 cfread(bitmap->bm_data, 1, zsize, d1_Piggy_fp);
1999 switch(cfilelength(d1_Piggy_fp)) {
2000 case D1_MAC_PIGSIZE:
2001 case D1_MAC_SHARE_PIGSIZE:
2002 if (bmh->flags & BM_FLAG_RLE)
2003 rle_swap_0_255(bitmap);
2007 if (bmh->flags & BM_FLAG_RLE)
2008 rle_remap(bitmap, colormap);
2010 gr_remap_bitmap_good(bitmap, d1_palette, TRANSPARENCY_COLOR, -1);
2011 if (bmh->flags & BM_FLAG_RLE) { // size of bitmap could have changed!
2013 memcpy(&new_size, bitmap->bm_data, 4);
2015 *next_bitmap += new_size - zsize;
2017 Assert( zsize + JUST_IN_CASE >= new_size );
2018 bitmap->bm_data = d_realloc(bitmap->bm_data, new_size);
2019 Assert(bitmap->bm_data);
2024 #define D1_MAX_TEXTURES 800
2025 #define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
2027 /* the inverse of the d2 Textures array, but for the descent 1 pigfile.
2028 * "Textures" looks up a d2 bitmap index given a d2 tmap_num.
2029 * "d1_tmap_nums" looks up a d1 tmap_num given a d1 bitmap. "-1" means "None".
2031 short *d1_tmap_nums = NULL;
2033 void free_d1_tmap_nums() {
2035 d_free(d1_tmap_nums);
2036 d1_tmap_nums = NULL;
2040 void bm_read_d1_tmap_nums(CFILE *d1pig)
2044 free_d1_tmap_nums();
2045 cfseek(d1pig, 8, SEEK_SET);
2046 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2047 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2048 d1_tmap_nums[i] = -1;
2049 for (i = 0; i < D1_MAX_TEXTURES; i++) {
2050 d1_index = cfile_read_short(d1pig);
2051 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2052 d1_tmap_nums[d1_index] = i;
2054 atexit(free_d1_tmap_nums);
2057 void remove_char( char * s, char c )
2064 #define REMOVE_EOL(s) remove_char((s),'\n')
2065 #define REMOVE_COMMENTS(s) remove_char((s),';')
2066 #define REMOVE_DOTS(s) remove_char((s),'.')
2067 char *space = { " \t" };
2068 char *equal_space = { " \t=" };
2070 // this function is at the same position in the d1 shareware piggy loading
2071 // algorithm as bm_load_sub in main/bmread.c
2072 int get_d1_bm_index(char *filename, CFILE *d1_pig) {
2074 DiskBitmapHeader bmh;
2075 if (strchr (filename, '.'))
2076 *strchr (filename, '.') = '\0'; // remove extension
2077 cfseek (d1_pig, 0, SEEK_SET);
2078 N_bitmaps = cfile_read_int (d1_pig);
2079 cfseek (d1_pig, 8, SEEK_SET);
2080 for (i = 1; i <= N_bitmaps; i++) {
2081 DiskBitmapHeader_d1_read(&bmh, d1_pig);
2082 if (!strnicmp(bmh.name, filename, 8))
2088 // imitate the algorithm of bm_init_use_tbl in main/bmread.c
2089 void read_d1_tmap_nums_from_hog(CFILE *d1_pig)
2091 #define LINEBUF_SIZE 600
2092 int reading_textures = 0;
2093 short texture_count = 0;
2094 char inputline[LINEBUF_SIZE];
2096 int bitmaps_tbl_is_binary = 0;
2099 bitmaps = cfopen ("bitmaps.tbl", "rb");
2101 bitmaps = cfopen ("bitmaps.bin", "rb");
2102 bitmaps_tbl_is_binary = 1;
2106 Warning ("Could not find bitmaps.* for reading d1 textures");
2110 free_d1_tmap_nums();
2111 MALLOC(d1_tmap_nums, short, D1_MAX_TMAP_NUM);
2112 for (i = 0; i < D1_MAX_TMAP_NUM; i++)
2113 d1_tmap_nums[i] = -1;
2114 atexit(free_d1_tmap_nums);
2116 while (cfgets (inputline, LINEBUF_SIZE, bitmaps)) {
2119 if (bitmaps_tbl_is_binary)
2120 decode_text_line((inputline));
2122 while (inputline[(i=strlen(inputline))-2]=='\\')
2123 cfgets(inputline+i-2,LINEBUF_SIZE-(i-2), bitmaps); // strip comments
2124 REMOVE_EOL(inputline);
2125 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
2126 if (strlen(inputline) == LINEBUF_SIZE-1) {
2127 Warning("Possible line truncation in BITMAPS.TBL");
2130 arg = strtok( inputline, space );
2131 if (arg && arg[0] == '@') {
2133 //Registered_only = 1;
2136 while (arg != NULL) {
2138 reading_textures = 0; // default
2139 if (!strcmp(arg, "$TEXTURES")) // BM_TEXTURES
2140 reading_textures = 1;
2141 else if (! stricmp(arg, "$ECLIP") // BM_ECLIP
2142 || ! stricmp(arg, "$WCLIP")) // BM_WCLIP
2144 else // not a special token, must be a bitmap!
2145 if (reading_textures) {
2146 while (*arg == '\t' || *arg == ' ')
2147 arg++;//remove unwanted blanks
2150 if (d1_tmap_num_unique(texture_count)) {
2151 int d1_index = get_d1_bm_index(arg, d1_pig);
2152 if (d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM) {
2153 d1_tmap_nums[d1_index] = texture_count;
2154 //int d2_index = d2_index_for_d1_index(d1_index);
2157 Assert (texture_count < D1_MAX_TEXTURES);
2161 arg = strtok (NULL, equal_space);
2167 /* If the given d1_index is the index of a bitmap we have to load
2168 * (because it is unique to descent 1), then returns the d2_index that
2169 * the given d1_index replaces.
2170 * Returns -1 if the given d1_index is not unique to descent 1.
2172 short d2_index_for_d1_index(short d1_index)
2174 Assert(d1_index >= 0 && d1_index < D1_MAX_TMAP_NUM);
2175 if (! d1_tmap_nums || d1_tmap_nums[d1_index] == -1
2176 || ! d1_tmap_num_unique(d1_tmap_nums[d1_index]))
2179 return Textures[convert_d1_tmap_num(d1_tmap_nums[d1_index])].index;
2182 #define D1_BITMAPS_SIZE 300000
2183 void load_d1_bitmap_replacements()
2185 CFILE * d1_Piggy_fp;
2186 DiskBitmapHeader bmh;
2187 int pig_data_start, bitmap_header_start, bitmap_data_start;
2189 short d1_index, d2_index;
2191 ubyte colormap[256];
2192 ubyte d1_palette[256*3];
2195 d1_Piggy_fp = cfopen( D1_PIGFILE, "rb" );
2197 #define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
2199 Warning(D1_PIG_LOAD_FAILED);
2203 //first, free up data allocated for old bitmaps
2204 free_bitmap_replacements();
2206 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2208 switch (cfilelength(d1_Piggy_fp)) {
2209 case D1_SHARE_BIG_PIGSIZE:
2210 case D1_SHARE_10_PIGSIZE:
2211 case D1_SHARE_PIGSIZE:
2212 case D1_10_BIG_PIGSIZE:
2215 // OK, now we need to read d1_tmap_nums by emulating d1's bm_init_use_tbl()
2216 read_d1_tmap_nums_from_hog(d1_Piggy_fp);
2219 Warning("Unknown size for " D1_PIGFILE);
2223 case D1_OEM_PIGSIZE:
2224 case D1_MAC_PIGSIZE:
2225 case D1_MAC_SHARE_PIGSIZE:
2226 pig_data_start = cfile_read_int(d1_Piggy_fp );
2227 bm_read_d1_tmap_nums(d1_Piggy_fp); //was: bm_read_all_d1(fp);
2228 //for (i = 0; i < 1800; i++) GameBitmapXlat[i] = cfile_read_short(d1_Piggy_fp);
2232 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2233 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2235 int N_sounds = cfile_read_int(d1_Piggy_fp);
2236 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2237 + N_sounds * sizeof(DiskSoundHeader);
2238 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2239 bitmap_data_start = bitmap_header_start + header_size;
2242 MALLOC( Bitmap_replacement_data, ubyte, D1_BITMAPS_SIZE);
2243 if (!Bitmap_replacement_data) {
2244 Warning(D1_PIG_LOAD_FAILED);
2247 atexit(free_bitmap_replacements);
2249 next_bitmap = Bitmap_replacement_data;
2251 for (d1_index = 1; d1_index <= N_bitmaps; d1_index++ ) {
2252 d2_index = d2_index_for_d1_index(d1_index);
2253 // only change bitmaps which are unique to d1
2254 if (d2_index != -1) {
2255 cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET);
2256 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2258 bitmap_read_d1( &GameBitmaps[d2_index], d1_Piggy_fp, bitmap_data_start, &bmh, &next_bitmap, d1_palette, colormap );
2259 Assert(next_bitmap - Bitmap_replacement_data < D1_BITMAPS_SIZE);
2260 GameBitmapOffset[d2_index] = 0; // don't try to read bitmap from current d2 pigfile
2261 GameBitmapFlags[d2_index] = bmh.flags;
2263 if ( (p = strchr(AllBitmaps[d2_index].name, '#')) /* d2 BM is animated */
2264 && !(bmh.dflags & DBM_FLAG_ABM) ) { /* d1 bitmap is not animated */
2265 int i, len = p - AllBitmaps[d2_index].name;
2266 for (i = 0; i < Num_bitmap_files; i++)
2267 if (i != d2_index && ! memcmp(AllBitmaps[d2_index].name, AllBitmaps[i].name, len)) {
2268 GameBitmaps[i] = GameBitmaps[d2_index];
2269 GameBitmapOffset[i] = 0;
2270 GameBitmapFlags[i] = bmh.flags;
2276 cfclose(d1_Piggy_fp);
2278 last_palette_loaded_pig[0]= 0; //force pig re-load
2280 texmerge_flush(); //for re-merging with new textures
2284 extern int extra_bitmap_num;
2287 * Find and load the named bitmap from descent.pig
2288 * similar to read_extra_bitmap_iff
2290 bitmap_index read_extra_bitmap_d1_pig(char *name)
2292 bitmap_index bitmap_num;
2293 grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
2295 bitmap_num.index = 0;
2299 DiskBitmapHeader bmh;
2300 int pig_data_start, bitmap_header_start, bitmap_data_start;
2302 ubyte colormap[256];
2303 ubyte d1_palette[256*3];
2305 d1_Piggy_fp = cfopen(D1_PIGFILE, "rb");
2309 Warning(D1_PIG_LOAD_FAILED);
2313 Assert( get_d1_colormap( d1_palette, colormap ) == 0 );
2315 switch (cfilelength(d1_Piggy_fp)) {
2316 case D1_SHARE_BIG_PIGSIZE:
2317 case D1_SHARE_10_PIGSIZE:
2318 case D1_SHARE_PIGSIZE:
2319 case D1_10_BIG_PIGSIZE:
2324 Warning("Unknown size for " D1_PIGFILE);
2328 case D1_OEM_PIGSIZE:
2329 case D1_MAC_PIGSIZE:
2330 case D1_MAC_SHARE_PIGSIZE:
2331 pig_data_start = cfile_read_int(d1_Piggy_fp );
2336 cfseek( d1_Piggy_fp, pig_data_start, SEEK_SET );
2337 N_bitmaps = cfile_read_int(d1_Piggy_fp);
2339 int N_sounds = cfile_read_int(d1_Piggy_fp);
2340 int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
2341 + N_sounds * sizeof(DiskSoundHeader);
2342 bitmap_header_start = pig_data_start + 2 * sizeof(int);
2343 bitmap_data_start = bitmap_header_start + header_size;
2346 for (i = 1; i <= N_bitmaps; i++)
2348 DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp);
2349 if (!strnicmp(bmh.name, name, 8))
2353 if (strnicmp(bmh.name, name, 8))
2355 con_printf(CON_DEBUG, "could not find bitmap %s\n", name);
2359 bitmap_read_d1( new, d1_Piggy_fp, bitmap_data_start, &bmh, 0, d1_palette, colormap );
2361 cfclose(d1_Piggy_fp);
2364 new->avg_color = 0; //compute_average_pixel(new);
2366 bitmap_num.index = extra_bitmap_num;
2368 GameBitmaps[extra_bitmap_num++] = *new;
2374 #ifndef FAST_FILE_IO
2376 * reads a bitmap_index structure from a CFILE
2378 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2380 bi->index = cfile_read_short(fp);
2384 * reads n bitmap_index structs from a CFILE
2386 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2390 for (i = 0; i < n; i++)
2391 bi[i].index = cfile_read_short(fp);
2394 #endif // FAST_FILE_IO