1 /* $Id: piggy.c,v 1.22 2003-03-14 21:59:19 btb 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.
20 static char rcsid[] = "$Id: piggy.c,v 1.22 2003-03-14 21:59:19 btb Exp $";
59 #include <Strings.h> // MacOS Toolbox header
64 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
66 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
67 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
68 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
69 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
71 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
72 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
73 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
75 #define D1_SHAREWARE_PIGSIZE 2509799
76 #define D1_SHAREWARE_10_PIGSIZE 2529454
77 #define D1_PIGSIZE 4920305
78 #define D1_OEM_PIGSIZE 5039735
79 #define D1_MAC_PIGSIZE 3975533
80 #define D1_MAC_SHARE_PIGSIZE 2714487
81 #define MAC_ALIEN1_PIGSIZE 5013035
82 #define MAC_ALIEN2_PIGSIZE 4909916
83 #define MAC_FIRE_PIGSIZE 4969035
84 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
85 #define MAC_ICE_PIGSIZE 4923425
86 #define MAC_WATER_PIGSIZE 4832403
88 ubyte *BitmapBits = NULL;
89 ubyte *SoundBits = NULL;
91 typedef struct BitmapFile {
95 typedef struct SoundFile {
99 hashtable AllBitmapsNames;
100 hashtable AllDigiSndNames;
102 int Num_bitmap_files = 0;
103 int Num_sound_files = 0;
105 digi_sound GameSounds[MAX_SOUND_FILES];
106 int SoundOffset[MAX_SOUND_FILES];
107 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
109 alias alias_list[MAX_ALIASES];
112 int Must_write_hamfile = 0;
113 int Num_bitmap_files_new = 0;
114 int Num_sound_files_new = 0;
115 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
116 static SoundFile AllSounds[ MAX_SOUND_FILES ];
118 int Piggy_hamfile_version = 0;
120 int piggy_low_memory = 0;
122 int Piggy_bitmap_cache_size = 0;
123 int Piggy_bitmap_cache_next = 0;
124 ubyte * Piggy_bitmap_cache_data = NULL;
125 static int GameBitmapOffset[MAX_BITMAP_FILES];
126 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
127 ushort GameBitmapXlat[MAX_BITMAP_FILES];
129 #define PIGGY_BUFFER_SIZE (2400*1024)
132 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
135 #undef PIGGY_BUFFER_SIZE
136 #undef PIGGY_SMALL_BUFFER_SIZE
138 #define PIGGY_BUFFER_SIZE (2000*1024)
139 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
144 int piggy_page_flushed = 0;
146 #define DBM_FLAG_ABM 64
151 extern short cd_VRefNum;
152 extern void ConcatPStr(StringPtr dst, StringPtr src);
153 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
154 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
157 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
160 void piggy_write_pigfile(char *filename);
161 static void write_int(int i,FILE *file);
164 void swap_0_255(grs_bitmap *bmp)
168 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
169 if(bmp->bm_data[i] == 0)
170 bmp->bm_data[i] = 255;
171 else if (bmp->bm_data[i] == 255)
176 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
179 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
181 temp.index = Num_bitmap_files;
185 if ( FindArg("-macdata") )
188 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
189 Num_bitmap_files_new++;
192 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
193 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
194 GameBitmaps[Num_bitmap_files] = *bmp;
196 GameBitmapOffset[Num_bitmap_files] = 0;
197 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
204 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
208 Assert( Num_sound_files < MAX_SOUND_FILES );
210 strncpy( AllSounds[Num_sound_files].name, name, 12 );
211 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
212 GameSounds[Num_sound_files] = *snd;
214 SoundOffset[Num_sound_files] = 0;
220 Num_sound_files_new++;
226 bitmap_index piggy_find_bitmap( char * name )
234 if ((t=strchr(name,'#'))!=NULL)
237 for (i=0;i<Num_aliases;i++)
238 if (stricmp(name,alias_list[i].alias_name)==0) {
239 if (t) { //extra stuff for ABMs
240 static char temp[FILENAME_LEN];
241 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
247 name=alias_list[i].file_name;
254 i = hashtable_search( &AllBitmapsNames, name );
263 int piggy_find_sound( char * name )
267 i = hashtable_search( &AllDigiSndNames, name );
275 CFILE * Piggy_fp = NULL;
277 #define FILENAME_LEN 13
279 char Current_pigfile[FILENAME_LEN] = "";
281 void piggy_close_file()
286 Current_pigfile[0] = 0;
290 int Pigfile_initialized=0;
292 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
293 #define PIGFILE_VERSION 2
295 extern char CDROM_dir[];
297 int request_cd(void);
302 //copies a pigfile from the CD to the current dir
303 //retuns file handle of new pig
304 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
307 char sourcePathAndFileCStr[255] = "";
308 char destPathAndFileCStr[255] = "";
310 FILE* sourceFile = NULL;
311 FILE* destFile = NULL;
312 const int BUF_SIZE = 4096;
316 Str255 sourcePathAndFilePStr = "\p";
317 Str255 destPathAndFilePStr = "\p";
318 Str255 pigfileNamePStr = "\p";
319 HParamBlockRec theSourcePigHFSParams;
320 HParamBlockRec theDestPigHFSParams;
321 OSErr theErr = noErr;
322 char oldDirCStr[255] = "";
324 getcwd(oldDirCStr, 255);
326 show_boxed_message("Copying bitmap data from CD...");
327 gr_palette_load(gr_palette); //I don't think this line is really needed
330 //First, delete all PIG files currently in the directory
331 if( !FileFindFirst( "*.pig", &find ) )
336 } while( !FileFindNext( &find ) );
342 //Now, copy over new pig
343 songs_stop_redbook(); //so we can read off the cd
345 // make the source path "<cd volume>:Data:filename.pig"
346 //MWA ConvertCToPStr(filename, pigfileNamePStr);
348 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
349 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
352 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
353 strcat(sourcePathAndFileCStr, filename);
355 // make the destination path "<default directory>:Data:filename.pig"
356 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
357 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
358 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
359 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
361 strcpy(destPathAndFileCStr, ":Data:");
362 strcat(destPathAndFileCStr, filename);
364 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
365 strcpy(destPathAndFilePStr, destPathAndFileCStr);
366 c2pstr(sourcePathAndFilePStr);
367 c2pstr(destPathAndFilePStr);
370 // Open the source file
371 sourceFile = fopen(sourcePathAndFileCStr,"rb");
375 if (request_cd() == -1)
376 Error("Cannot load file <%s> from CD",filename);
379 } while (!sourceFile);
382 // Get the time stamp from the source file
383 theSourcePigHFSParams.fileParam.ioCompletion = nil;
384 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
385 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
386 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
387 theSourcePigHFSParams.fileParam.ioDirID = 0;
389 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
392 // Error getting file time stamp!! Why? JTS
393 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
396 // Copy the file over
399 // Open the destination file
400 destFile = fopen(destPathAndFileCStr,"wb");
403 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
406 // Copy bytes until the end of the source file
407 while (!feof(sourceFile))
412 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
413 if (ferror(sourceFile))
414 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
416 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
418 fwrite(buf,1,bytes_read,destFile);
419 if (ferror(destFile))
420 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
423 // close the source/dest files
424 if (fclose(sourceFile))
425 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
426 if (fclose(destFile))
427 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
429 // Get the current hfs data for the new file
430 theDestPigHFSParams.fileParam.ioCompletion = nil;
431 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
432 theDestPigHFSParams.fileParam.ioVRefNum = 0;
433 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
434 theDestPigHFSParams.fileParam.ioDirID = 0;
435 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
436 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
438 // Error getting file time stamp!! Why? JTS
439 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
442 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
443 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
444 theDestPigHFSParams.fileParam.ioVRefNum = 0;
445 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
446 theDestPigHFSParams.fileParam.ioDirID = 0;
448 // Copy the time stamp from the source file info
449 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
450 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
451 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
452 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
454 // Set the dest file's time stamp to the source file's time stamp values
455 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
457 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
459 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
462 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
464 return cfopen(destPathAndFileCStr, "rb");
467 #else //PC Version of copy_pigfile_from_cd is below
469 //copies a pigfile from the CD to the current dir
470 //retuns file handle of new pig
471 CFILE *copy_pigfile_from_cd(char *filename)
477 return cfopen(filename, "rb");
478 show_boxed_message("Copying bitmap data from CD...");
479 gr_palette_load(gr_palette); //I don't think this line is really needed
481 //First, delete all PIG files currently in the directory
483 if( !FileFindFirst( "*.pig", &find ) ) {
486 } while( !FileFindNext( &find ) );
490 //Now, copy over new pig
492 songs_stop_redbook(); //so we can read off the cd
494 //new code to unarj file
495 strcpy(name,CDROM_dir);
496 strcat(name,"descent2.sow");
499 // ret = unarj_specific_file(name,filename,filename);
504 if (ret != EXIT_SUCCESS) {
506 //delete file, so we don't leave partial file
510 if (request_cd() == -1)
512 //NOTE LINK TO ABOVE IF
513 Error("Cannot load file <%s> from CD",filename);
516 } while (ret != EXIT_SUCCESS);
518 return cfopen(filename, "rb");
521 #endif // end of ifdef MAC around copy_pigfile_from_cd
523 //initialize a pigfile, reading headers
524 //returns the size of all the bitmap data
525 void piggy_init_pigfile(char *filename)
529 char temp_name_read[16];
530 grs_bitmap temp_bitmap;
531 DiskBitmapHeader bmh;
532 int header_size, N_bitmaps, data_size, data_start;
534 char name[255]; // filename + path for the mac
537 piggy_close_file(); //close old pig if still open
539 //rename pigfile for shareware
540 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
541 filename = DEFAULT_PIGFILE_SHAREWARE;
544 Piggy_fp = cfopen( filename, "rb" );
546 sprintf(name, ":Data:%s", filename);
547 Piggy_fp = cfopen( name, "rb" );
549 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
550 if (Piggy_fp == NULL)
552 Error("Cannot load required file <%s>",name);
554 #endif // end of if def shareware
560 return; //if editor, ok to not have pig, because we'll build one
562 Piggy_fp = copy_pigfile_from_cd(filename);
566 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
567 int pig_id,pig_version;
569 pig_id = cfile_read_int(Piggy_fp);
570 pig_version = cfile_read_int(Piggy_fp);
571 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
572 cfclose(Piggy_fp); //out of date pig
573 Piggy_fp = NULL; //..so pretend it's not here
580 return; //if editor, ok to not have pig, because we'll build one
582 Error("Cannot load required file <%s>",filename);
586 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
588 N_bitmaps = cfile_read_int(Piggy_fp);
590 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
592 data_start = header_size + cftell(Piggy_fp);
594 data_size = cfilelength(Piggy_fp) - data_start;
596 Num_bitmap_files = 1;
598 for (i=0; i<N_bitmaps; i++ ) {
599 DiskBitmapHeader_read(&bmh, Piggy_fp);
600 memcpy( temp_name_read, bmh.name, 8 );
601 temp_name_read[8] = 0;
602 if ( bmh.dflags & DBM_FLAG_ABM )
603 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
605 strcpy( temp_name, temp_name_read );
606 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
607 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
608 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
609 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
610 temp_bitmap.avg_color = bmh.avg_color;
611 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
613 GameBitmapFlags[i+1] = 0;
614 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
615 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
616 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
617 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
618 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
620 GameBitmapOffset[i+1] = bmh.offset + data_start;
621 Assert( (i+1) == Num_bitmap_files );
622 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
626 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
627 Assert( Piggy_bitmap_cache_size > 0 );
629 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
631 if (piggy_low_memory)
632 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
635 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
636 if ( BitmapBits == NULL )
637 Error( "Not enough memory to load bitmaps\n" );
638 Piggy_bitmap_cache_data = BitmapBits;
639 Piggy_bitmap_cache_next = 0;
641 #if defined(MACINTOSH) && defined(SHAREWARE)
642 // load_exit_models();
645 Pigfile_initialized=1;
648 #define FILENAME_LEN 13
649 #define MAX_BITMAPS_PER_BRUSH 30
651 extern int compute_average_pixel(grs_bitmap *new);
653 //reads in a new pigfile (for new palette)
654 //returns the size of all the bitmap data
655 void piggy_new_pigfile(char *pigname)
659 char temp_name_read[16];
660 grs_bitmap temp_bitmap;
661 DiskBitmapHeader bmh;
662 int header_size, N_bitmaps, data_size, data_start;
663 int must_rewrite_pig = 0;
670 //rename pigfile for shareware
671 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
672 pigname = DEFAULT_PIGFILE_SHAREWARE;
674 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
675 return; //already have correct pig
677 if (!Pigfile_initialized) { //have we ever opened a pigfile?
678 piggy_init_pigfile(pigname); //..no, so do initialization stuff
682 piggy_close_file(); //close old pig if still open
684 Piggy_bitmap_cache_next = 0; //free up cache
686 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
689 Piggy_fp = cfopen( pigname, "rb" );
691 sprintf(name, ":Data:%s", pigname);
692 Piggy_fp = cfopen( name, "rb" );
694 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
695 if (Piggy_fp == NULL)
697 Error("Cannot load required file <%s>",name);
699 #endif // end of if def shareware
704 Piggy_fp = copy_pigfile_from_cd(pigname);
707 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
708 int pig_id,pig_version;
710 pig_id = cfile_read_int(Piggy_fp);
711 pig_version = cfile_read_int(Piggy_fp);
712 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
713 cfclose(Piggy_fp); //out of date pig
714 Piggy_fp = NULL; //..so pretend it's not here
719 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
724 N_bitmaps = cfile_read_int(Piggy_fp);
726 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
728 data_start = header_size + cftell(Piggy_fp);
730 data_size = cfilelength(Piggy_fp) - data_start;
732 for (i=1; i<=N_bitmaps; i++ ) {
733 DiskBitmapHeader_read(&bmh, Piggy_fp);
734 memcpy( temp_name_read, bmh.name, 8 );
735 temp_name_read[8] = 0;
737 if ( bmh.dflags & DBM_FLAG_ABM )
738 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
740 strcpy( temp_name, temp_name_read );
742 //Make sure name matches
743 if (strcmp(temp_name,AllBitmaps[i].name)) {
744 //Int3(); //this pig is out of date. Delete it
748 strcpy(AllBitmaps[i].name,temp_name);
750 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
752 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
753 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
754 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
755 temp_bitmap.avg_color = bmh.avg_color;
756 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
758 GameBitmapFlags[i] = 0;
760 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
761 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
762 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
763 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
764 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
766 GameBitmapOffset[i] = bmh.offset + data_start;
768 GameBitmaps[i] = temp_bitmap;
772 N_bitmaps = 0; //no pigfile, so no bitmaps
776 Assert(N_bitmaps == Num_bitmap_files-1);
780 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
783 //re-read the bitmaps that aren't in this pig
785 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
788 p = strchr(AllBitmaps[i].name,'#');
790 if (p) { //this is an ABM
791 char abmname[FILENAME_LEN];
793 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
794 int iff_error; //reference parm to avoid warning message
796 char basename[FILENAME_LEN];
799 strcpy(basename,AllBitmaps[i].name);
800 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
802 sprintf( abmname, "%s.abm", basename );
804 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
806 if (iff_error != IFF_NO_ERROR) {
807 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
808 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
811 for (fnum=0;fnum<nframes; fnum++) {
815 sprintf( tempname, "%s#%d", basename, fnum );
817 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
818 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
819 //above makes assumption that supertransparent color is 254
821 if ( iff_has_transparency )
822 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
824 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
826 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
829 if ( FindArg("-macdata") )
830 swap_0_255( bm[fnum] );
832 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
834 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
835 size = *((int *) bm[fnum]->bm_data);
837 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
839 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
840 d_free(bm[fnum]->bm_data);
841 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
842 Piggy_bitmap_cache_next += size;
844 GameBitmaps[i+fnum] = *bm[fnum];
846 // -- mprintf( (0, "U" ));
850 i += nframes-1; //filled in multiple bitmaps
852 else { //this is a BBM
857 char bbmname[FILENAME_LEN];
860 MALLOC( new, grs_bitmap, 1 );
862 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
863 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
866 if (iff_error != IFF_NO_ERROR) {
867 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
868 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
871 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
872 //above makes assumption that supertransparent color is 254
874 if ( iff_has_transparency )
875 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
877 gr_remap_bitmap_good( new, newpal, -1, SuperX );
879 new->avg_color = compute_average_pixel(new);
882 if ( FindArg("-macdata") )
885 if ( !BigPig ) gr_bitmap_rle_compress( new );
887 if (new->bm_flags & BM_FLAG_RLE)
888 size = *((int *) new->bm_data);
890 size = new->bm_w * new->bm_h;
892 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
893 d_free(new->bm_data);
894 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
895 Piggy_bitmap_cache_next += size;
897 GameBitmaps[i] = *new;
901 // -- mprintf( (0, "U" ));
905 //@@Dont' do these things which are done when writing
906 //@@for (i=0; i < Num_bitmap_files; i++ ) {
907 //@@ bitmap_index bi;
909 //@@ PIGGY_PAGE_IN( bi );
912 //@@piggy_close_file();
914 piggy_write_pigfile(pigname);
916 Current_pigfile[0] = 0; //say no pig, to force reload
918 piggy_new_pigfile(pigname); //read in just-generated pig
922 #endif //ifdef EDITOR
926 ubyte bogus_data[64*64];
927 grs_bitmap bogus_bitmap;
928 ubyte bogus_bitmap_initialized=0;
929 digi_sound bogus_sound;
931 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
932 #define HAMFILE_VERSION 3
933 //version 1 -> 2: save marker_model_num
934 //version 2 -> 3: removed sound files
936 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
937 #define SNDFILE_VERSION 1
941 CFILE * ham_fp = NULL;
943 int sound_offset = 0;
949 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
951 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
952 ham_fp = cfopen( name, "rb" );
955 if (ham_fp == NULL) {
956 Must_write_hamfile = 1;
960 //make sure ham is valid type file & is up-to-date
961 ham_id = cfile_read_int(ham_fp);
962 Piggy_hamfile_version = cfile_read_int(ham_fp);
963 if (ham_id != HAMFILE_ID)
964 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
966 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
967 Must_write_hamfile = 1;
968 cfclose(ham_fp); //out of date ham
973 if (Piggy_hamfile_version < 3) // hamfile contains sound info
974 sound_offset = cfile_read_int(ham_fp);
981 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
983 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
984 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
985 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
990 if (Piggy_hamfile_version < 3) {
995 DiskSoundHeader sndh;
996 digi_sound temp_sound;
997 char temp_name_read[16];
1000 cfseek(ham_fp, sound_offset, SEEK_SET);
1001 N_sounds = cfile_read_int(ham_fp);
1003 sound_start = cftell(ham_fp);
1005 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1009 for (i=0; i<N_sounds; i++ ) {
1010 DiskSoundHeader_read(&sndh, ham_fp);
1011 temp_sound.length = sndh.length;
1012 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1013 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1014 memcpy( temp_name_read, sndh.name, 8 );
1015 temp_name_read[8] = 0;
1016 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1018 if (piggy_is_needed(i))
1019 #endif // note link to if.
1020 sbytes += sndh.length;
1021 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1024 SoundBits = d_malloc( sbytes + 16 );
1025 if ( SoundBits == NULL )
1026 Error( "Not enough memory to load sounds\n" );
1028 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1030 // piggy_read_sounds(ham_fp);
1042 CFILE * snd_fp = NULL;
1043 int snd_id,snd_version;
1048 DiskSoundHeader sndh;
1049 digi_sound temp_sound;
1050 char temp_name_read[16];
1057 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1059 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1060 snd_fp = cfopen( name, "rb");
1066 //make sure soundfile is valid type file & is up-to-date
1067 snd_id = cfile_read_int(snd_fp);
1068 snd_version = cfile_read_int(snd_fp);
1069 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1070 cfclose(snd_fp); //out of date sound file
1074 N_sounds = cfile_read_int(snd_fp);
1076 sound_start = cftell(snd_fp);
1077 size = cfilelength(snd_fp) - sound_start;
1079 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1081 header_size = N_sounds*sizeof(DiskSoundHeader);
1085 for (i=0; i<N_sounds; i++ ) {
1086 DiskSoundHeader_read(&sndh, snd_fp);
1087 //size -= sizeof(DiskSoundHeader);
1088 temp_sound.length = sndh.length;
1089 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1090 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1091 memcpy( temp_name_read, sndh.name, 8 );
1092 temp_name_read[8] = 0;
1093 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1095 if (piggy_is_needed(i))
1096 #endif // note link to if.
1097 sbytes += sndh.length;
1098 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1101 SoundBits = d_malloc( sbytes + 16 );
1102 if ( SoundBits == NULL )
1103 Error( "Not enough memory to load sounds\n" );
1105 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1107 // piggy_read_sounds(snd_fp);
1114 int piggy_init(void)
1116 int ham_ok=0,snd_ok=0;
1119 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1120 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1122 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1123 GameSounds[i].length = 0;
1124 GameSounds[i].data = NULL;
1128 for (i=0; i<MAX_BITMAP_FILES; i++ )
1129 GameBitmapXlat[i] = i;
1131 if ( !bogus_bitmap_initialized ) {
1134 bogus_bitmap_initialized = 1;
1135 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1136 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1137 bogus_bitmap.bm_data = bogus_data;
1138 c = gr_find_closest_color( 0, 0, 63 );
1139 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1140 c = gr_find_closest_color( 63, 0, 0 );
1141 // Make a big red X !
1142 for (i=0; i<64; i++ ) {
1143 bogus_data[i*64+i] = c;
1144 bogus_data[i*64+(63-i)] = c;
1146 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1147 bogus_sound.length = 64*64;
1148 bogus_sound.data = bogus_data;
1149 GameBitmapOffset[0] = 0;
1152 if ( FindArg( "-bigpig" ))
1155 if ( FindArg( "-lowmem" ))
1156 piggy_low_memory = 1;
1158 if ( FindArg( "-nolowmem" ))
1159 piggy_low_memory = 0;
1161 if (piggy_low_memory)
1164 WIN(DDGRLOCK(dd_grd_curcanv));
1165 gr_set_curfont( SMALL_FONT );
1166 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1167 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1168 WIN(DDGRUNLOCK(dd_grd_curcanv));
1170 #if 1 //def EDITOR //need for d1 mission briefings
1171 piggy_init_pigfile(DEFAULT_PIGFILE);
1174 snd_ok = ham_ok = read_hamfile();
1176 if (Piggy_hamfile_version >= 3)
1177 snd_ok = read_sndfile();
1179 atexit(piggy_close);
1181 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1182 return (ham_ok && snd_ok); //read ok
1185 int piggy_is_needed(int soundnum)
1189 if ( !digi_lomem ) return 1;
1191 for (i=0; i<MAX_SOUNDS; i++ ) {
1192 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1199 void piggy_read_sounds(void)
1212 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1214 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1215 fp = cfopen( name, "rb");
1221 for (i=0; i<Num_sound_files; i++ ) {
1222 digi_sound *snd = &GameSounds[i];
1224 if ( SoundOffset[i] > 0 ) {
1225 if ( piggy_is_needed(i) ) {
1226 cfseek( fp, SoundOffset[i], SEEK_SET );
1228 // Read in the sound data!!!
1231 sbytes += snd->length;
1232 cfread( snd->data, snd->length, 1, fp );
1235 snd->data = (ubyte *) -1;
1241 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1246 extern int descent_critical_error;
1247 extern unsigned descent_critical_deverror;
1248 extern unsigned descent_critical_errcode;
1250 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1251 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1252 "Read fault", "General Failure" };
1254 void piggy_critical_error()
1256 grs_canvas * save_canv;
1257 grs_font * save_font;
1259 save_canv = grd_curcanv;
1260 save_font = grd_curcanv->cv_font;
1261 gr_palette_load( gr_palette );
1262 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1265 gr_set_current_canvas(save_canv);
1266 grd_curcanv->cv_font = save_font;
1269 void piggy_bitmap_page_in( bitmap_index bitmap )
1278 Assert( i < MAX_BITMAP_FILES );
1279 Assert( i < Num_bitmap_files );
1280 Assert( Piggy_bitmap_cache_size > 0 );
1282 if ( i < 1 ) return;
1283 if ( i >= MAX_BITMAP_FILES ) return;
1284 if ( i >= Num_bitmap_files ) return;
1286 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1288 if ( piggy_low_memory ) {
1290 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1293 bmp = &GameBitmaps[i];
1295 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1299 descent_critical_error = 0;
1300 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1301 if ( descent_critical_error ) {
1302 piggy_critical_error();
1306 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1307 bmp->bm_flags = GameBitmapFlags[i];
1309 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1311 descent_critical_error = 0;
1312 zsize = cfile_read_int(Piggy_fp);
1313 if ( descent_critical_error ) {
1314 piggy_critical_error();
1318 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1319 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1320 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1322 piggy_bitmap_page_out_all();
1325 descent_critical_error = 0;
1326 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1327 if ( descent_critical_error ) {
1328 piggy_critical_error();
1333 switch (cfilelength(Piggy_fp)) {
1335 if (!FindArg("-macdata"))
1337 // otherwise, fall through...
1338 case MAC_ALIEN1_PIGSIZE:
1339 case MAC_ALIEN2_PIGSIZE:
1340 case MAC_FIRE_PIGSIZE:
1341 case MAC_GROUPA_PIGSIZE:
1342 case MAC_ICE_PIGSIZE:
1343 case MAC_WATER_PIGSIZE:
1344 rle_swap_0_255( bmp );
1345 memcpy(&zsize, bmp->bm_data, 4);
1350 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1351 Piggy_bitmap_cache_next += zsize;
1352 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1354 piggy_bitmap_page_out_all();
1359 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1360 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1361 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1362 piggy_bitmap_page_out_all();
1365 descent_critical_error = 0;
1366 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1367 if ( descent_critical_error ) {
1368 piggy_critical_error();
1371 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1374 switch (cfilelength(Piggy_fp)) {
1376 if (!FindArg("-macdata"))
1378 // otherwise, fall through...
1379 case MAC_ALIEN1_PIGSIZE:
1380 case MAC_ALIEN2_PIGSIZE:
1381 case MAC_FIRE_PIGSIZE:
1382 case MAC_GROUPA_PIGSIZE:
1383 case MAC_ICE_PIGSIZE:
1384 case MAC_WATER_PIGSIZE:
1391 //@@if ( bmp->bm_selector ) {
1392 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1393 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1394 //@@ Error( "Error modifying selector base in piggy.c\n" );
1401 if ( piggy_low_memory ) {
1403 GameBitmaps[org_i] = GameBitmaps[i];
1406 //@@Removed from John's code:
1408 //@@ if ( bmp->bm_selector ) {
1409 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1410 //@@ Error( "Error modifying selector base in piggy.c\n" );
1416 void piggy_bitmap_page_out_all()
1420 Piggy_bitmap_cache_next = 0;
1422 piggy_page_flushed++;
1427 for (i=0; i<Num_bitmap_files; i++ ) {
1428 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1429 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1430 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1434 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1437 void piggy_load_level_data()
1439 piggy_bitmap_page_out_all();
1445 void change_filename_ext( char *dest, char *src, char *ext );
1447 void piggy_write_pigfile(char *filename)
1450 int bitmap_data_start,data_offset;
1451 DiskBitmapHeader bmh;
1453 char subst_name[32];
1456 char tname[FILENAME_LEN];
1458 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1459 for (i=0; i < Num_bitmap_files; i++ ) {
1462 PIGGY_PAGE_IN( bi );
1464 // -- mprintf( (0, "\n" ));
1468 // -- mprintf( (0, "Creating %s...",filename ));
1470 pig_fp = fopen( filename, "wb" ); //open PIG file
1471 Assert( pig_fp!=NULL );
1473 write_int(PIGFILE_ID,pig_fp);
1474 write_int(PIGFILE_VERSION,pig_fp);
1477 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1480 bitmap_data_start = ftell(pig_fp);
1481 bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE;
1482 data_offset = bitmap_data_start;
1484 change_filename_ext(tname,filename,"lst");
1485 fp1 = fopen( tname, "wt" );
1486 change_filename_ext(tname,filename,"all");
1487 fp2 = fopen( tname, "wt" );
1489 for (i=1; i < Num_bitmap_files; i++ ) {
1495 p = strchr(AllBitmaps[i].name,'#');
1502 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1503 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1505 bmh.dflags = DBM_FLAG_ABM + n;
1509 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1510 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1514 bmp = &GameBitmaps[i];
1516 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1519 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1520 org_offset = ftell(pig_fp);
1521 bmh.offset = data_offset - bitmap_data_start;
1522 fseek( pig_fp, data_offset, SEEK_SET );
1524 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1525 size = (int *)bmp->bm_data;
1526 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1527 data_offset += *size;
1529 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1531 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1532 data_offset += bmp->bm_rowsize * bmp->bm_h;
1534 fprintf( fp1, ".\n" );
1536 fseek( pig_fp, org_offset, SEEK_SET );
1537 Assert( GameBitmaps[i].bm_w < 4096 );
1538 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1539 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1540 Assert( GameBitmaps[i].bm_h < 4096 );
1541 bmh.height = GameBitmaps[i].bm_h;
1542 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1543 bmh.flags = GameBitmaps[i].bm_flags;
1544 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1545 bitmap_index other_bitmap;
1546 other_bitmap = piggy_find_bitmap( subst_name );
1547 GameBitmapXlat[i] = other_bitmap.index;
1548 bmh.flags |= BM_FLAG_PAGED_OUT;
1549 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1550 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1552 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1554 bmh.avg_color=GameBitmaps[i].avg_color;
1555 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp ); // Mark as a bitmap
1560 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1561 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1568 static void write_int(int i,FILE *file)
1570 if (fwrite( &i, sizeof(i), 1, file) != 1)
1571 Error( "Error reading int in gamesave.c" );
1575 void piggy_dump_all()
1579 int org_offset,data_offset=0;
1580 DiskSoundHeader sndh;
1581 int sound_data_start=0;
1584 #ifdef NO_DUMP_SOUNDS
1585 Num_sound_files = 0;
1586 Num_sound_files_new = 0;
1589 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1592 fp1 = fopen( "ham.lst", "wt" );
1593 fp2 = fopen( "ham.all", "wt" );
1595 if (Must_write_hamfile || Num_bitmap_files_new) {
1597 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1599 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1600 Assert( ham_fp!=NULL );
1602 write_int(HAMFILE_ID,ham_fp);
1603 write_int(HAMFILE_VERSION,ham_fp);
1605 bm_write_all(ham_fp);
1606 xlat_offset = ftell(ham_fp);
1607 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1610 if (Num_bitmap_files_new)
1611 piggy_write_pigfile(DEFAULT_PIGFILE);
1613 //free up memeory used by new bitmaps
1614 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1615 d_free(GameBitmaps[i].bm_data);
1617 //next thing must be done after pig written
1618 fseek( ham_fp, xlat_offset, SEEK_SET );
1619 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1622 mprintf( (0, "\n" ));
1625 if (Num_sound_files_new) {
1627 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1628 // Now dump sound file
1629 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1630 Assert( ham_fp!=NULL );
1632 write_int(SNDFILE_ID,ham_fp);
1633 write_int(SNDFILE_VERSION,ham_fp);
1635 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1637 mprintf( (0, "\nDumping sounds..." ));
1639 sound_data_start = ftell(ham_fp);
1640 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1641 data_offset = sound_data_start;
1643 for (i=0; i < Num_sound_files; i++ ) {
1646 snd = &GameSounds[i];
1647 strcpy( sndh.name, AllSounds[i].name );
1648 sndh.length = GameSounds[i].length;
1649 sndh.offset = data_offset - sound_data_start;
1651 org_offset = ftell(ham_fp);
1652 fseek( ham_fp, data_offset, SEEK_SET );
1654 sndh.data_length = GameSounds[i].length;
1655 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1656 data_offset += snd->length;
1657 fseek( ham_fp, org_offset, SEEK_SET );
1658 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1660 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1661 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1665 mprintf( (0, "\n" ));
1668 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1669 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1670 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1675 // Never allow the game to run after building ham.
1689 d_free( SoundBits );
1691 hashtable_free( &AllBitmapsNames );
1692 hashtable_free( &AllDigiSndNames );
1696 int piggy_does_bitmap_exist_slow( char * name )
1700 for (i=0; i<Num_bitmap_files; i++ ) {
1701 if ( !strcmp( AllBitmaps[i].name, name) )
1708 #define NUM_GAUGE_BITMAPS 23
1709 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1710 "gauge01", "gauge01b",
1711 "gauge02", "gauge02b",
1712 "gauge06", "gauge06b",
1713 "targ01", "targ01b",
1714 "targ02", "targ02b",
1715 "targ03", "targ03b",
1716 "targ04", "targ04b",
1717 "targ05", "targ05b",
1718 "targ06", "targ06b",
1719 "gauge18", "gauge18b",
1725 int piggy_is_gauge_bitmap( char * base_name )
1728 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1729 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1736 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1740 char base_name[ 16 ];
1742 strcpy( subst_name, name );
1743 p = strchr( subst_name, '#' );
1745 frame = atoi( &p[1] );
1747 strcpy( base_name, subst_name );
1748 if ( !piggy_is_gauge_bitmap( base_name )) {
1749 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1750 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1752 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1758 strcpy( subst_name, name );
1765 // New Windows stuff
1767 // windows bitmap page in
1768 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1769 // 'video' memory. if that fails, page it in normally.
1771 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1776 // Essential when switching video modes!
1778 void piggy_bitmap_page_out_all_w()
1784 #ifndef FAST_FILE_IO
1786 * reads a bitmap_index structure from a CFILE
1788 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
1790 bi->index = cfile_read_short(fp);
1794 * reads n bitmap_index structs from a CFILE
1796 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
1800 for (i = 0; i < n; i++)
1801 bi[i].index = cfile_read_short(fp);
1806 * reads a DiskBitmapHeader structure from a CFILE
1808 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
1810 cfread(dbh->name, 8, 1, fp);
1811 dbh->dflags = cfile_read_byte(fp);
1812 dbh->width = cfile_read_byte(fp);
1813 dbh->height = cfile_read_byte(fp);
1814 dbh->wh_extra = cfile_read_byte(fp);
1815 dbh->flags = cfile_read_byte(fp);
1816 dbh->avg_color = cfile_read_byte(fp);
1817 dbh->offset = cfile_read_int(fp);
1821 * reads a DiskSoundHeader structure from a CFILE
1823 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
1825 cfread(dsh->name, 8, 1, fp);
1826 dsh->length = cfile_read_int(fp);
1827 dsh->data_length = cfile_read_int(fp);
1828 dsh->offset = cfile_read_int(fp);
1830 #endif // FAST_FILE_IO