1 /* $Id: piggy.c,v 1.19 2002-12-31 21:51:37 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.19 2002-12-31 21:51:37 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 MAC_D2DEMO_PIG_SIZE 4929684
77 ubyte *BitmapBits = NULL;
78 ubyte *SoundBits = NULL;
80 typedef struct BitmapFile {
84 typedef struct SoundFile {
88 hashtable AllBitmapsNames;
89 hashtable AllDigiSndNames;
91 int Num_bitmap_files = 0;
92 int Num_sound_files = 0;
94 digi_sound GameSounds[MAX_SOUND_FILES];
95 int SoundOffset[MAX_SOUND_FILES];
96 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
98 alias alias_list[MAX_ALIASES];
101 int Must_write_hamfile = 0;
102 int Num_bitmap_files_new = 0;
103 int Num_sound_files_new = 0;
104 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
105 static SoundFile AllSounds[ MAX_SOUND_FILES ];
107 int Piggy_hamfile_version = 0;
109 int piggy_low_memory = 0;
111 int Piggy_bitmap_cache_size = 0;
112 int Piggy_bitmap_cache_next = 0;
113 ubyte * Piggy_bitmap_cache_data = NULL;
114 static int GameBitmapOffset[MAX_BITMAP_FILES];
115 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
116 ushort GameBitmapXlat[MAX_BITMAP_FILES];
118 #define PIGGY_BUFFER_SIZE (2400*1024)
121 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
124 #undef PIGGY_BUFFER_SIZE
125 #undef PIGGY_SMALL_BUFFER_SIZE
127 #define PIGGY_BUFFER_SIZE (2000*1024)
128 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
133 int piggy_page_flushed = 0;
135 #define DBM_FLAG_ABM 64
140 extern short cd_VRefNum;
141 extern void ConcatPStr(StringPtr dst, StringPtr src);
142 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
143 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
146 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
149 void piggy_write_pigfile(char *filename);
150 static void write_int(int i,FILE *file);
153 void swap_0_255(grs_bitmap *bmp)
157 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
158 if(bmp->bm_data[i] == 0)
159 bmp->bm_data[i] = 255;
160 else if (bmp->bm_data[i] == 255)
165 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
168 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
170 temp.index = Num_bitmap_files;
174 if ( FindArg("-macdata") )
177 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
178 Num_bitmap_files_new++;
181 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
182 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
183 GameBitmaps[Num_bitmap_files] = *bmp;
185 GameBitmapOffset[Num_bitmap_files] = 0;
186 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
193 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
197 Assert( Num_sound_files < MAX_SOUND_FILES );
199 strncpy( AllSounds[Num_sound_files].name, name, 12 );
200 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
201 GameSounds[Num_sound_files] = *snd;
203 SoundOffset[Num_sound_files] = 0;
209 Num_sound_files_new++;
215 bitmap_index piggy_find_bitmap( char * name )
223 if ((t=strchr(name,'#'))!=NULL)
226 for (i=0;i<Num_aliases;i++)
227 if (stricmp(name,alias_list[i].alias_name)==0) {
228 if (t) { //extra stuff for ABMs
229 static char temp[FILENAME_LEN];
230 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
236 name=alias_list[i].file_name;
243 i = hashtable_search( &AllBitmapsNames, name );
252 int piggy_find_sound( char * name )
256 i = hashtable_search( &AllDigiSndNames, name );
264 CFILE * Piggy_fp = NULL;
266 #define FILENAME_LEN 13
268 char Current_pigfile[FILENAME_LEN] = "";
270 void piggy_close_file()
275 Current_pigfile[0] = 0;
279 int Pigfile_initialized=0;
281 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
282 #define PIGFILE_VERSION 2
284 extern char CDROM_dir[];
286 int request_cd(void);
291 //copies a pigfile from the CD to the current dir
292 //retuns file handle of new pig
293 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
296 char sourcePathAndFileCStr[255] = "";
297 char destPathAndFileCStr[255] = "";
299 FILE* sourceFile = NULL;
300 FILE* destFile = NULL;
301 const int BUF_SIZE = 4096;
305 Str255 sourcePathAndFilePStr = "\p";
306 Str255 destPathAndFilePStr = "\p";
307 Str255 pigfileNamePStr = "\p";
308 HParamBlockRec theSourcePigHFSParams;
309 HParamBlockRec theDestPigHFSParams;
310 OSErr theErr = noErr;
311 char oldDirCStr[255] = "";
313 getcwd(oldDirCStr, 255);
315 show_boxed_message("Copying bitmap data from CD...");
316 gr_palette_load(gr_palette); //I don't think this line is really needed
319 //First, delete all PIG files currently in the directory
320 if( !FileFindFirst( "*.pig", &find ) )
325 } while( !FileFindNext( &find ) );
331 //Now, copy over new pig
332 songs_stop_redbook(); //so we can read off the cd
334 // make the source path "<cd volume>:Data:filename.pig"
335 //MWA ConvertCToPStr(filename, pigfileNamePStr);
337 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
338 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
341 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
342 strcat(sourcePathAndFileCStr, filename);
344 // make the destination path "<default directory>:Data:filename.pig"
345 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
346 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
347 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
348 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
350 strcpy(destPathAndFileCStr, ":Data:");
351 strcat(destPathAndFileCStr, filename);
353 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
354 strcpy(destPathAndFilePStr, destPathAndFileCStr);
355 c2pstr(sourcePathAndFilePStr);
356 c2pstr(destPathAndFilePStr);
359 // Open the source file
360 sourceFile = fopen(sourcePathAndFileCStr,"rb");
364 if (request_cd() == -1)
365 Error("Cannot load file <%s> from CD",filename);
368 } while (!sourceFile);
371 // Get the time stamp from the source file
372 theSourcePigHFSParams.fileParam.ioCompletion = nil;
373 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
374 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
375 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
376 theSourcePigHFSParams.fileParam.ioDirID = 0;
378 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
381 // Error getting file time stamp!! Why? JTS
382 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
385 // Copy the file over
388 // Open the destination file
389 destFile = fopen(destPathAndFileCStr,"wb");
392 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
395 // Copy bytes until the end of the source file
396 while (!feof(sourceFile))
401 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
402 if (ferror(sourceFile))
403 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
405 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
407 fwrite(buf,1,bytes_read,destFile);
408 if (ferror(destFile))
409 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
412 // close the source/dest files
413 if (fclose(sourceFile))
414 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
415 if (fclose(destFile))
416 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
418 // Get the current hfs data for the new file
419 theDestPigHFSParams.fileParam.ioCompletion = nil;
420 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
421 theDestPigHFSParams.fileParam.ioVRefNum = 0;
422 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
423 theDestPigHFSParams.fileParam.ioDirID = 0;
424 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
425 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
427 // Error getting file time stamp!! Why? JTS
428 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
431 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
432 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
433 theDestPigHFSParams.fileParam.ioVRefNum = 0;
434 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
435 theDestPigHFSParams.fileParam.ioDirID = 0;
437 // Copy the time stamp from the source file info
438 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
439 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
440 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
441 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
443 // Set the dest file's time stamp to the source file's time stamp values
444 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
446 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
448 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
451 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
453 return cfopen(destPathAndFileCStr, "rb");
456 #else //PC Version of copy_pigfile_from_cd is below
458 //copies a pigfile from the CD to the current dir
459 //retuns file handle of new pig
460 CFILE *copy_pigfile_from_cd(char *filename)
466 return cfopen(filename, "rb");
467 show_boxed_message("Copying bitmap data from CD...");
468 gr_palette_load(gr_palette); //I don't think this line is really needed
470 //First, delete all PIG files currently in the directory
472 if( !FileFindFirst( "*.pig", &find ) ) {
475 } while( !FileFindNext( &find ) );
479 //Now, copy over new pig
481 songs_stop_redbook(); //so we can read off the cd
483 //new code to unarj file
484 strcpy(name,CDROM_dir);
485 strcat(name,"descent2.sow");
488 // ret = unarj_specific_file(name,filename,filename);
493 if (ret != EXIT_SUCCESS) {
495 //delete file, so we don't leave partial file
499 if (request_cd() == -1)
501 //NOTE LINK TO ABOVE IF
502 Error("Cannot load file <%s> from CD",filename);
505 } while (ret != EXIT_SUCCESS);
507 return cfopen(filename, "rb");
510 #endif // end of ifdef MAC around copy_pigfile_from_cd
512 //initialize a pigfile, reading headers
513 //returns the size of all the bitmap data
514 void piggy_init_pigfile(char *filename)
518 char temp_name_read[16];
519 grs_bitmap temp_bitmap;
520 DiskBitmapHeader bmh;
521 int header_size, N_bitmaps, data_size, data_start;
523 char name[255]; // filename + path for the mac
526 piggy_close_file(); //close old pig if still open
528 //rename pigfile for shareware
529 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
530 filename = DEFAULT_PIGFILE_SHAREWARE;
533 Piggy_fp = cfopen( filename, "rb" );
535 sprintf(name, ":Data:%s", filename);
536 Piggy_fp = cfopen( name, "rb" );
538 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
539 if (Piggy_fp == NULL)
541 Error("Cannot load required file <%s>",name);
543 #endif // end of if def shareware
549 return; //if editor, ok to not have pig, because we'll build one
551 Piggy_fp = copy_pigfile_from_cd(filename);
555 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
556 int pig_id,pig_version;
558 pig_id = cfile_read_int(Piggy_fp);
559 pig_version = cfile_read_int(Piggy_fp);
560 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
561 cfclose(Piggy_fp); //out of date pig
562 Piggy_fp = NULL; //..so pretend it's not here
569 return; //if editor, ok to not have pig, because we'll build one
571 Error("Cannot load required file <%s>",filename);
575 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
577 N_bitmaps = cfile_read_int(Piggy_fp);
579 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
581 data_start = header_size + cftell(Piggy_fp);
583 data_size = cfilelength(Piggy_fp) - data_start;
585 Num_bitmap_files = 1;
587 for (i=0; i<N_bitmaps; i++ ) {
588 DiskBitmapHeader_read(&bmh, Piggy_fp);
589 memcpy( temp_name_read, bmh.name, 8 );
590 temp_name_read[8] = 0;
591 if ( bmh.dflags & DBM_FLAG_ABM )
592 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
594 strcpy( temp_name, temp_name_read );
595 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
596 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
597 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
598 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
599 temp_bitmap.avg_color = bmh.avg_color;
600 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
602 GameBitmapFlags[i+1] = 0;
603 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
604 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
605 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
606 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
607 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
609 GameBitmapOffset[i+1] = bmh.offset + data_start;
610 Assert( (i+1) == Num_bitmap_files );
611 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
615 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
616 Assert( Piggy_bitmap_cache_size > 0 );
618 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
620 if (piggy_low_memory)
621 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
624 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
625 if ( BitmapBits == NULL )
626 Error( "Not enough memory to load bitmaps\n" );
627 Piggy_bitmap_cache_data = BitmapBits;
628 Piggy_bitmap_cache_next = 0;
630 #if defined(MACINTOSH) && defined(SHAREWARE)
631 // load_exit_models();
634 Pigfile_initialized=1;
637 #define FILENAME_LEN 13
638 #define MAX_BITMAPS_PER_BRUSH 30
640 extern int compute_average_pixel(grs_bitmap *new);
642 //reads in a new pigfile (for new palette)
643 //returns the size of all the bitmap data
644 void piggy_new_pigfile(char *pigname)
648 char temp_name_read[16];
649 grs_bitmap temp_bitmap;
650 DiskBitmapHeader bmh;
651 int header_size, N_bitmaps, data_size, data_start;
652 int must_rewrite_pig = 0;
659 //rename pigfile for shareware
660 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
661 pigname = DEFAULT_PIGFILE_SHAREWARE;
663 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
664 return; //already have correct pig
666 if (!Pigfile_initialized) { //have we ever opened a pigfile?
667 piggy_init_pigfile(pigname); //..no, so do initialization stuff
671 piggy_close_file(); //close old pig if still open
673 Piggy_bitmap_cache_next = 0; //free up cache
675 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
678 Piggy_fp = cfopen( pigname, "rb" );
680 sprintf(name, ":Data:%s", pigname);
681 Piggy_fp = cfopen( name, "rb" );
683 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
684 if (Piggy_fp == NULL)
686 Error("Cannot load required file <%s>",name);
688 #endif // end of if def shareware
693 Piggy_fp = copy_pigfile_from_cd(pigname);
696 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
697 int pig_id,pig_version;
699 pig_id = cfile_read_int(Piggy_fp);
700 pig_version = cfile_read_int(Piggy_fp);
701 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
702 cfclose(Piggy_fp); //out of date pig
703 Piggy_fp = NULL; //..so pretend it's not here
708 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
713 N_bitmaps = cfile_read_int(Piggy_fp);
715 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
717 data_start = header_size + cftell(Piggy_fp);
719 data_size = cfilelength(Piggy_fp) - data_start;
721 for (i=1; i<=N_bitmaps; i++ ) {
722 DiskBitmapHeader_read(&bmh, Piggy_fp);
723 memcpy( temp_name_read, bmh.name, 8 );
724 temp_name_read[8] = 0;
726 if ( bmh.dflags & DBM_FLAG_ABM )
727 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
729 strcpy( temp_name, temp_name_read );
731 //Make sure name matches
732 if (strcmp(temp_name,AllBitmaps[i].name)) {
733 //Int3(); //this pig is out of date. Delete it
737 strcpy(AllBitmaps[i].name,temp_name);
739 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
741 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
742 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
743 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
744 temp_bitmap.avg_color = bmh.avg_color;
745 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
747 GameBitmapFlags[i] = 0;
749 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
750 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
751 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
752 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
753 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
755 GameBitmapOffset[i] = bmh.offset + data_start;
757 GameBitmaps[i] = temp_bitmap;
761 N_bitmaps = 0; //no pigfile, so no bitmaps
765 Assert(N_bitmaps == Num_bitmap_files-1);
769 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
772 //re-read the bitmaps that aren't in this pig
774 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
777 p = strchr(AllBitmaps[i].name,'#');
779 if (p) { //this is an ABM
780 char abmname[FILENAME_LEN];
782 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
783 int iff_error; //reference parm to avoid warning message
785 char basename[FILENAME_LEN];
788 strcpy(basename,AllBitmaps[i].name);
789 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
791 sprintf( abmname, "%s.abm", basename );
793 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
795 if (iff_error != IFF_NO_ERROR) {
796 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
797 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
800 for (fnum=0;fnum<nframes; fnum++) {
804 sprintf( tempname, "%s#%d", basename, fnum );
806 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
807 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
808 //above makes assumption that supertransparent color is 254
810 if ( iff_has_transparency )
811 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
813 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
815 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
818 if ( FindArg("-macdata") )
819 swap_0_255( bm[fnum] );
821 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
823 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
824 size = *((int *) bm[fnum]->bm_data);
826 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
828 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
829 d_free(bm[fnum]->bm_data);
830 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
831 Piggy_bitmap_cache_next += size;
833 GameBitmaps[i+fnum] = *bm[fnum];
835 // -- mprintf( (0, "U" ));
839 i += nframes-1; //filled in multiple bitmaps
841 else { //this is a BBM
846 char bbmname[FILENAME_LEN];
849 MALLOC( new, grs_bitmap, 1 );
851 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
852 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
855 if (iff_error != IFF_NO_ERROR) {
856 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
857 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
860 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
861 //above makes assumption that supertransparent color is 254
863 if ( iff_has_transparency )
864 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
866 gr_remap_bitmap_good( new, newpal, -1, SuperX );
868 new->avg_color = compute_average_pixel(new);
871 if ( FindArg("-macdata") )
874 if ( !BigPig ) gr_bitmap_rle_compress( new );
876 if (new->bm_flags & BM_FLAG_RLE)
877 size = *((int *) new->bm_data);
879 size = new->bm_w * new->bm_h;
881 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
882 d_free(new->bm_data);
883 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
884 Piggy_bitmap_cache_next += size;
886 GameBitmaps[i] = *new;
890 // -- mprintf( (0, "U" ));
894 //@@Dont' do these things which are done when writing
895 //@@for (i=0; i < Num_bitmap_files; i++ ) {
896 //@@ bitmap_index bi;
898 //@@ PIGGY_PAGE_IN( bi );
901 //@@piggy_close_file();
903 piggy_write_pigfile(pigname);
905 Current_pigfile[0] = 0; //say no pig, to force reload
907 piggy_new_pigfile(pigname); //read in just-generated pig
911 #endif //ifdef EDITOR
915 ubyte bogus_data[64*64];
916 grs_bitmap bogus_bitmap;
917 ubyte bogus_bitmap_initialized=0;
918 digi_sound bogus_sound;
920 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
921 #define HAMFILE_VERSION 3
922 //version 1 -> 2: save marker_model_num
923 //version 2 -> 3: removed sound files
925 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
926 #define SNDFILE_VERSION 1
930 CFILE * ham_fp = NULL;
932 int sound_offset = 0;
938 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
940 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
941 ham_fp = cfopen( name, "rb" );
944 if (ham_fp == NULL) {
945 Must_write_hamfile = 1;
949 //make sure ham is valid type file & is up-to-date
950 ham_id = cfile_read_int(ham_fp);
951 Piggy_hamfile_version = cfile_read_int(ham_fp);
952 if (ham_id != HAMFILE_ID)
953 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
955 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
956 Must_write_hamfile = 1;
957 cfclose(ham_fp); //out of date ham
962 if (Piggy_hamfile_version < 3) // hamfile contains sound info
963 sound_offset = cfile_read_int(ham_fp);
970 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
972 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
973 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
974 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
979 if (Piggy_hamfile_version < 3) {
984 DiskSoundHeader sndh;
985 digi_sound temp_sound;
986 char temp_name_read[16];
989 cfseek(ham_fp, sound_offset, SEEK_SET);
990 N_sounds = cfile_read_int(ham_fp);
992 sound_start = cftell(ham_fp);
994 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
998 for (i=0; i<N_sounds; i++ ) {
999 DiskSoundHeader_read(&sndh, ham_fp);
1000 temp_sound.length = sndh.length;
1001 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1002 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1003 memcpy( temp_name_read, sndh.name, 8 );
1004 temp_name_read[8] = 0;
1005 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1007 if (piggy_is_needed(i))
1008 #endif // note link to if.
1009 sbytes += sndh.length;
1010 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1013 SoundBits = d_malloc( sbytes + 16 );
1014 if ( SoundBits == NULL )
1015 Error( "Not enough memory to load sounds\n" );
1017 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1019 // piggy_read_sounds(ham_fp);
1031 CFILE * snd_fp = NULL;
1032 int snd_id,snd_version;
1037 DiskSoundHeader sndh;
1038 digi_sound temp_sound;
1039 char temp_name_read[16];
1046 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1048 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1049 snd_fp = cfopen( name, "rb");
1055 //make sure soundfile is valid type file & is up-to-date
1056 snd_id = cfile_read_int(snd_fp);
1057 snd_version = cfile_read_int(snd_fp);
1058 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1059 cfclose(snd_fp); //out of date sound file
1063 N_sounds = cfile_read_int(snd_fp);
1065 sound_start = cftell(snd_fp);
1066 size = cfilelength(snd_fp) - sound_start;
1068 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1070 header_size = N_sounds*sizeof(DiskSoundHeader);
1074 for (i=0; i<N_sounds; i++ ) {
1075 DiskSoundHeader_read(&sndh, snd_fp);
1076 //size -= sizeof(DiskSoundHeader);
1077 temp_sound.length = sndh.length;
1078 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1079 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1080 memcpy( temp_name_read, sndh.name, 8 );
1081 temp_name_read[8] = 0;
1082 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1084 if (piggy_is_needed(i))
1085 #endif // note link to if.
1086 sbytes += sndh.length;
1087 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1090 SoundBits = d_malloc( sbytes + 16 );
1091 if ( SoundBits == NULL )
1092 Error( "Not enough memory to load sounds\n" );
1094 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1096 // piggy_read_sounds(snd_fp);
1103 int piggy_init(void)
1105 int ham_ok=0,snd_ok=0;
1108 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1109 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1111 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1112 GameSounds[i].length = 0;
1113 GameSounds[i].data = NULL;
1117 for (i=0; i<MAX_BITMAP_FILES; i++ )
1118 GameBitmapXlat[i] = i;
1120 if ( !bogus_bitmap_initialized ) {
1123 bogus_bitmap_initialized = 1;
1124 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1125 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1126 bogus_bitmap.bm_data = bogus_data;
1127 c = gr_find_closest_color( 0, 0, 63 );
1128 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1129 c = gr_find_closest_color( 63, 0, 0 );
1130 // Make a big red X !
1131 for (i=0; i<64; i++ ) {
1132 bogus_data[i*64+i] = c;
1133 bogus_data[i*64+(63-i)] = c;
1135 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1136 bogus_sound.length = 64*64;
1137 bogus_sound.data = bogus_data;
1138 GameBitmapOffset[0] = 0;
1141 if ( FindArg( "-bigpig" ))
1144 if ( FindArg( "-lowmem" ))
1145 piggy_low_memory = 1;
1147 if ( FindArg( "-nolowmem" ))
1148 piggy_low_memory = 0;
1150 if (piggy_low_memory)
1153 WIN(DDGRLOCK(dd_grd_curcanv));
1154 gr_set_curfont( SMALL_FONT );
1155 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1156 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1157 WIN(DDGRUNLOCK(dd_grd_curcanv));
1160 piggy_init_pigfile(DEFAULT_PIGFILE);
1163 snd_ok = ham_ok = read_hamfile();
1165 if (Piggy_hamfile_version >= 3)
1166 snd_ok = read_sndfile();
1168 atexit(piggy_close);
1170 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1171 return (ham_ok && snd_ok); //read ok
1174 int piggy_is_needed(int soundnum)
1178 if ( !digi_lomem ) return 1;
1180 for (i=0; i<MAX_SOUNDS; i++ ) {
1181 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1188 void piggy_read_sounds(void)
1201 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1203 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1204 fp = cfopen( name, "rb");
1210 for (i=0; i<Num_sound_files; i++ ) {
1211 digi_sound *snd = &GameSounds[i];
1213 if ( SoundOffset[i] > 0 ) {
1214 if ( piggy_is_needed(i) ) {
1215 cfseek( fp, SoundOffset[i], SEEK_SET );
1217 // Read in the sound data!!!
1220 sbytes += snd->length;
1221 cfread( snd->data, snd->length, 1, fp );
1224 snd->data = (ubyte *) -1;
1230 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1235 extern int descent_critical_error;
1236 extern unsigned descent_critical_deverror;
1237 extern unsigned descent_critical_errcode;
1239 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1240 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1241 "Read fault", "General Failure" };
1243 void piggy_critical_error()
1245 grs_canvas * save_canv;
1246 grs_font * save_font;
1248 save_canv = grd_curcanv;
1249 save_font = grd_curcanv->cv_font;
1250 gr_palette_load( gr_palette );
1251 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1254 gr_set_current_canvas(save_canv);
1255 grd_curcanv->cv_font = save_font;
1258 void piggy_bitmap_page_in( bitmap_index bitmap )
1267 Assert( i < MAX_BITMAP_FILES );
1268 Assert( i < Num_bitmap_files );
1269 Assert( Piggy_bitmap_cache_size > 0 );
1271 if ( i < 1 ) return;
1272 if ( i >= MAX_BITMAP_FILES ) return;
1273 if ( i >= Num_bitmap_files ) return;
1275 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1277 if ( piggy_low_memory ) {
1279 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1282 bmp = &GameBitmaps[i];
1284 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1288 descent_critical_error = 0;
1289 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1290 if ( descent_critical_error ) {
1291 piggy_critical_error();
1295 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1296 bmp->bm_flags = GameBitmapFlags[i];
1298 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1300 descent_critical_error = 0;
1301 zsize = cfile_read_int(Piggy_fp);
1302 if ( descent_critical_error ) {
1303 piggy_critical_error();
1307 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1308 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1309 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1311 piggy_bitmap_page_out_all();
1314 descent_critical_error = 0;
1315 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1316 if ( descent_critical_error ) {
1317 piggy_critical_error();
1322 if (FindArg("-macdata") || cfilelength(Piggy_fp) == MAC_D2DEMO_PIG_SIZE) {
1323 rle_swap_0_255( bmp );
1324 zsize = *((int *)bmp->bm_data);
1328 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1329 Piggy_bitmap_cache_next += zsize;
1330 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1332 piggy_bitmap_page_out_all();
1337 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1338 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1339 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1340 piggy_bitmap_page_out_all();
1343 descent_critical_error = 0;
1344 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1345 if ( descent_critical_error ) {
1346 piggy_critical_error();
1349 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1352 if (FindArg("-macdata") || cfilelength(Piggy_fp) == MAC_D2DEMO_PIG_SIZE)
1359 //@@if ( bmp->bm_selector ) {
1360 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1361 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1362 //@@ Error( "Error modifying selector base in piggy.c\n" );
1369 if ( piggy_low_memory ) {
1371 GameBitmaps[org_i] = GameBitmaps[i];
1374 //@@Removed from John's code:
1376 //@@ if ( bmp->bm_selector ) {
1377 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1378 //@@ Error( "Error modifying selector base in piggy.c\n" );
1384 void piggy_bitmap_page_out_all()
1388 Piggy_bitmap_cache_next = 0;
1390 piggy_page_flushed++;
1395 for (i=0; i<Num_bitmap_files; i++ ) {
1396 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1397 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1398 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1402 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1405 void piggy_load_level_data()
1407 piggy_bitmap_page_out_all();
1413 void change_filename_ext( char *dest, char *src, char *ext );
1415 void piggy_write_pigfile(char *filename)
1418 int bitmap_data_start,data_offset;
1419 DiskBitmapHeader bmh;
1421 char subst_name[32];
1424 char tname[FILENAME_LEN];
1426 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1427 for (i=0; i < Num_bitmap_files; i++ ) {
1430 PIGGY_PAGE_IN( bi );
1432 // -- mprintf( (0, "\n" ));
1436 // -- mprintf( (0, "Creating %s...",filename ));
1438 pig_fp = fopen( filename, "wb" ); //open PIG file
1439 Assert( pig_fp!=NULL );
1441 write_int(PIGFILE_ID,pig_fp);
1442 write_int(PIGFILE_VERSION,pig_fp);
1445 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1448 bitmap_data_start = ftell(pig_fp);
1449 bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE;
1450 data_offset = bitmap_data_start;
1452 change_filename_ext(tname,filename,"lst");
1453 fp1 = fopen( tname, "wt" );
1454 change_filename_ext(tname,filename,"all");
1455 fp2 = fopen( tname, "wt" );
1457 for (i=1; i < Num_bitmap_files; i++ ) {
1463 p = strchr(AllBitmaps[i].name,'#');
1470 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1471 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1473 bmh.dflags = DBM_FLAG_ABM + n;
1477 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1478 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1482 bmp = &GameBitmaps[i];
1484 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1487 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1488 org_offset = ftell(pig_fp);
1489 bmh.offset = data_offset - bitmap_data_start;
1490 fseek( pig_fp, data_offset, SEEK_SET );
1492 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1493 size = (int *)bmp->bm_data;
1494 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1495 data_offset += *size;
1497 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1499 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1500 data_offset += bmp->bm_rowsize * bmp->bm_h;
1502 fprintf( fp1, ".\n" );
1504 fseek( pig_fp, org_offset, SEEK_SET );
1505 Assert( GameBitmaps[i].bm_w < 4096 );
1506 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1507 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1508 Assert( GameBitmaps[i].bm_h < 4096 );
1509 bmh.height = GameBitmaps[i].bm_h;
1510 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1511 bmh.flags = GameBitmaps[i].bm_flags;
1512 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1513 bitmap_index other_bitmap;
1514 other_bitmap = piggy_find_bitmap( subst_name );
1515 GameBitmapXlat[i] = other_bitmap.index;
1516 bmh.flags |= BM_FLAG_PAGED_OUT;
1517 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1518 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1520 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1522 bmh.avg_color=GameBitmaps[i].avg_color;
1523 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp ); // Mark as a bitmap
1528 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1529 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1536 static void write_int(int i,FILE *file)
1538 if (fwrite( &i, sizeof(i), 1, file) != 1)
1539 Error( "Error reading int in gamesave.c" );
1543 void piggy_dump_all()
1547 int org_offset,data_offset=0;
1548 DiskSoundHeader sndh;
1549 int sound_data_start=0;
1552 #ifdef NO_DUMP_SOUNDS
1553 Num_sound_files = 0;
1554 Num_sound_files_new = 0;
1557 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1560 fp1 = fopen( "ham.lst", "wt" );
1561 fp2 = fopen( "ham.all", "wt" );
1563 if (Must_write_hamfile || Num_bitmap_files_new) {
1565 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1567 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1568 Assert( ham_fp!=NULL );
1570 write_int(HAMFILE_ID,ham_fp);
1571 write_int(HAMFILE_VERSION,ham_fp);
1573 bm_write_all(ham_fp);
1574 xlat_offset = ftell(ham_fp);
1575 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1578 if (Num_bitmap_files_new)
1579 piggy_write_pigfile(DEFAULT_PIGFILE);
1581 //free up memeory used by new bitmaps
1582 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1583 d_free(GameBitmaps[i].bm_data);
1585 //next thing must be done after pig written
1586 fseek( ham_fp, xlat_offset, SEEK_SET );
1587 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1590 mprintf( (0, "\n" ));
1593 if (Num_sound_files_new) {
1595 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1596 // Now dump sound file
1597 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1598 Assert( ham_fp!=NULL );
1600 write_int(SNDFILE_ID,ham_fp);
1601 write_int(SNDFILE_VERSION,ham_fp);
1603 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1605 mprintf( (0, "\nDumping sounds..." ));
1607 sound_data_start = ftell(ham_fp);
1608 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1609 data_offset = sound_data_start;
1611 for (i=0; i < Num_sound_files; i++ ) {
1614 snd = &GameSounds[i];
1615 strcpy( sndh.name, AllSounds[i].name );
1616 sndh.length = GameSounds[i].length;
1617 sndh.offset = data_offset - sound_data_start;
1619 org_offset = ftell(ham_fp);
1620 fseek( ham_fp, data_offset, SEEK_SET );
1622 sndh.data_length = GameSounds[i].length;
1623 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1624 data_offset += snd->length;
1625 fseek( ham_fp, org_offset, SEEK_SET );
1626 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1628 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1629 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1633 mprintf( (0, "\n" ));
1636 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1637 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1638 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1643 // Never allow the game to run after building ham.
1657 d_free( SoundBits );
1659 hashtable_free( &AllBitmapsNames );
1660 hashtable_free( &AllDigiSndNames );
1664 int piggy_does_bitmap_exist_slow( char * name )
1668 for (i=0; i<Num_bitmap_files; i++ ) {
1669 if ( !strcmp( AllBitmaps[i].name, name) )
1676 #define NUM_GAUGE_BITMAPS 23
1677 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1678 "gauge01", "gauge01b",
1679 "gauge02", "gauge02b",
1680 "gauge06", "gauge06b",
1681 "targ01", "targ01b",
1682 "targ02", "targ02b",
1683 "targ03", "targ03b",
1684 "targ04", "targ04b",
1685 "targ05", "targ05b",
1686 "targ06", "targ06b",
1687 "gauge18", "gauge18b",
1693 int piggy_is_gauge_bitmap( char * base_name )
1696 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1697 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1704 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1708 char base_name[ 16 ];
1710 strcpy( subst_name, name );
1711 p = strchr( subst_name, '#' );
1713 frame = atoi( &p[1] );
1715 strcpy( base_name, subst_name );
1716 if ( !piggy_is_gauge_bitmap( base_name )) {
1717 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1718 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1720 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1726 strcpy( subst_name, name );
1733 // New Windows stuff
1735 // windows bitmap page in
1736 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1737 // 'video' memory. if that fails, page it in normally.
1739 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1744 // Essential when switching video modes!
1746 void piggy_bitmap_page_out_all_w()
1752 #ifndef FAST_FILE_IO
1754 * reads a bitmap_index structure from a CFILE
1756 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
1758 bi->index = cfile_read_short(fp);
1762 * reads n bitmap_index structs from a CFILE
1764 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
1768 for (i = 0; i < n; i++)
1769 bi[i].index = cfile_read_short(fp);
1774 * reads a DiskBitmapHeader structure from a CFILE
1776 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
1778 cfread(dbh->name, 8, 1, fp);
1779 dbh->dflags = cfile_read_byte(fp);
1780 dbh->width = cfile_read_byte(fp);
1781 dbh->height = cfile_read_byte(fp);
1782 dbh->wh_extra = cfile_read_byte(fp);
1783 dbh->flags = cfile_read_byte(fp);
1784 dbh->avg_color = cfile_read_byte(fp);
1785 dbh->offset = cfile_read_int(fp);
1789 * reads a DiskSoundHeader structure from a CFILE
1791 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
1793 cfread(dsh->name, 8, 1, fp);
1794 dsh->length = cfile_read_int(fp);
1795 dsh->data_length = cfile_read_int(fp);
1796 dsh->offset = cfile_read_int(fp);