1 /* $Id: piggy.c,v 1.16 2002-08-15 05:49:23 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.16 2002-08-15 05:49:23 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 int Gr_transparency_color = 255;
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 if (cfilelength(Piggy_fp) == 4929684) // mac version of d2demo.pig
576 Gr_transparency_color = 0;
578 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
580 N_bitmaps = cfile_read_int(Piggy_fp);
582 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
584 data_start = header_size + cftell(Piggy_fp);
586 data_size = cfilelength(Piggy_fp) - data_start;
588 Num_bitmap_files = 1;
590 for (i=0; i<N_bitmaps; i++ ) {
591 DiskBitmapHeader_read(&bmh, Piggy_fp);
592 memcpy( temp_name_read, bmh.name, 8 );
593 temp_name_read[8] = 0;
594 if ( bmh.dflags & DBM_FLAG_ABM )
595 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
597 strcpy( temp_name, temp_name_read );
598 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
599 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
600 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
601 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
602 temp_bitmap.avg_color = bmh.avg_color;
603 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
605 GameBitmapFlags[i+1] = 0;
606 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
607 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
608 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
609 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
610 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
612 GameBitmapOffset[i+1] = bmh.offset + data_start;
613 Assert( (i+1) == Num_bitmap_files );
614 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
618 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
619 Assert( Piggy_bitmap_cache_size > 0 );
621 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
623 if (piggy_low_memory)
624 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
627 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
628 if ( BitmapBits == NULL )
629 Error( "Not enough memory to load bitmaps\n" );
630 Piggy_bitmap_cache_data = BitmapBits;
631 Piggy_bitmap_cache_next = 0;
633 #if defined(MACINTOSH) && defined(SHAREWARE)
634 // load_exit_models();
637 Pigfile_initialized=1;
640 #define FILENAME_LEN 13
641 #define MAX_BITMAPS_PER_BRUSH 30
643 extern int compute_average_pixel(grs_bitmap *new);
645 //reads in a new pigfile (for new palette)
646 //returns the size of all the bitmap data
647 void piggy_new_pigfile(char *pigname)
651 char temp_name_read[16];
652 grs_bitmap temp_bitmap;
653 DiskBitmapHeader bmh;
654 int header_size, N_bitmaps, data_size, data_start;
655 int must_rewrite_pig = 0;
662 //rename pigfile for shareware
663 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
664 pigname = DEFAULT_PIGFILE_SHAREWARE;
666 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
667 return; //already have correct pig
669 if (!Pigfile_initialized) { //have we ever opened a pigfile?
670 piggy_init_pigfile(pigname); //..no, so do initialization stuff
674 piggy_close_file(); //close old pig if still open
676 Piggy_bitmap_cache_next = 0; //free up cache
678 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
681 Piggy_fp = cfopen( pigname, "rb" );
683 sprintf(name, ":Data:%s", pigname);
684 Piggy_fp = cfopen( name, "rb" );
686 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
687 if (Piggy_fp == NULL)
689 Error("Cannot load required file <%s>",name);
691 #endif // end of if def shareware
696 Piggy_fp = copy_pigfile_from_cd(pigname);
699 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
700 int pig_id,pig_version;
702 pig_id = cfile_read_int(Piggy_fp);
703 pig_version = cfile_read_int(Piggy_fp);
704 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
705 cfclose(Piggy_fp); //out of date pig
706 Piggy_fp = NULL; //..so pretend it's not here
711 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
714 if (cfilelength(Piggy_fp) == 4929684) // mac version of d2demo.pig
715 Gr_transparency_color = 0;
719 N_bitmaps = cfile_read_int(Piggy_fp);
721 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
723 data_start = header_size + cftell(Piggy_fp);
725 data_size = cfilelength(Piggy_fp) - data_start;
727 for (i=1; i<=N_bitmaps; i++ ) {
728 DiskBitmapHeader_read(&bmh, Piggy_fp);
729 memcpy( temp_name_read, bmh.name, 8 );
730 temp_name_read[8] = 0;
732 if ( bmh.dflags & DBM_FLAG_ABM )
733 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
735 strcpy( temp_name, temp_name_read );
737 //Make sure name matches
738 if (strcmp(temp_name,AllBitmaps[i].name)) {
739 //Int3(); //this pig is out of date. Delete it
743 strcpy(AllBitmaps[i].name,temp_name);
745 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
747 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
748 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
749 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
750 temp_bitmap.avg_color = bmh.avg_color;
751 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
753 GameBitmapFlags[i] = 0;
755 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
756 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
757 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
758 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
759 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
761 GameBitmapOffset[i] = bmh.offset + data_start;
763 GameBitmaps[i] = temp_bitmap;
767 N_bitmaps = 0; //no pigfile, so no bitmaps
771 Assert(N_bitmaps == Num_bitmap_files-1);
775 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
778 //re-read the bitmaps that aren't in this pig
780 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
783 p = strchr(AllBitmaps[i].name,'#');
785 if (p) { //this is an ABM
786 char abmname[FILENAME_LEN];
788 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
789 int iff_error; //reference parm to avoid warning message
791 char basename[FILENAME_LEN];
794 strcpy(basename,AllBitmaps[i].name);
795 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
797 sprintf( abmname, "%s.abm", basename );
799 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
801 if (iff_error != IFF_NO_ERROR) {
802 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
803 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
806 for (fnum=0;fnum<nframes; fnum++) {
810 sprintf( tempname, "%s#%d", basename, fnum );
812 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
813 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
814 //above makes assumption that supertransparent color is 254
816 if ( iff_has_transparency )
817 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
819 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
821 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
824 if ( FindArg("-macdata") )
825 swap_0_255( bm[fnum] );
827 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
829 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
830 size = *((int *) bm[fnum]->bm_data);
832 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
834 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
835 d_free(bm[fnum]->bm_data);
836 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
837 Piggy_bitmap_cache_next += size;
839 GameBitmaps[i+fnum] = *bm[fnum];
841 // -- mprintf( (0, "U" ));
845 i += nframes-1; //filled in multiple bitmaps
847 else { //this is a BBM
852 char bbmname[FILENAME_LEN];
855 MALLOC( new, grs_bitmap, 1 );
857 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
858 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
861 if (iff_error != IFF_NO_ERROR) {
862 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
863 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
866 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
867 //above makes assumption that supertransparent color is 254
869 if ( iff_has_transparency )
870 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
872 gr_remap_bitmap_good( new, newpal, -1, SuperX );
874 new->avg_color = compute_average_pixel(new);
877 if ( FindArg("-macdata") )
880 if ( !BigPig ) gr_bitmap_rle_compress( new );
882 if (new->bm_flags & BM_FLAG_RLE)
883 size = *((int *) new->bm_data);
885 size = new->bm_w * new->bm_h;
887 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
888 d_free(new->bm_data);
889 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
890 Piggy_bitmap_cache_next += size;
892 GameBitmaps[i] = *new;
896 // -- mprintf( (0, "U" ));
900 //@@Dont' do these things which are done when writing
901 //@@for (i=0; i < Num_bitmap_files; i++ ) {
902 //@@ bitmap_index bi;
904 //@@ PIGGY_PAGE_IN( bi );
907 //@@piggy_close_file();
909 piggy_write_pigfile(pigname);
911 Current_pigfile[0] = 0; //say no pig, to force reload
913 piggy_new_pigfile(pigname); //read in just-generated pig
917 #endif //ifdef EDITOR
921 ubyte bogus_data[64*64];
922 grs_bitmap bogus_bitmap;
923 ubyte bogus_bitmap_initialized=0;
924 digi_sound bogus_sound;
926 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
927 #define HAMFILE_VERSION 3
928 //version 1 -> 2: save marker_model_num
929 //version 2 -> 3: removed sound files
931 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
932 #define SNDFILE_VERSION 1
936 CFILE * ham_fp = NULL;
938 int sound_offset = 0;
944 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
946 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
947 ham_fp = cfopen( name, "rb" );
950 if (ham_fp == NULL) {
951 Must_write_hamfile = 1;
955 //make sure ham is valid type file & is up-to-date
956 ham_id = cfile_read_int(ham_fp);
957 Piggy_hamfile_version = cfile_read_int(ham_fp);
958 if (ham_id != HAMFILE_ID)
959 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
961 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
962 Must_write_hamfile = 1;
963 cfclose(ham_fp); //out of date ham
968 if (Piggy_hamfile_version < 3) // hamfile contains sound info
969 sound_offset = cfile_read_int(ham_fp);
976 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
978 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
979 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
980 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
985 if (Piggy_hamfile_version < 3) {
990 DiskSoundHeader sndh;
991 digi_sound temp_sound;
992 char temp_name_read[16];
995 cfseek(ham_fp, sound_offset, SEEK_SET);
996 N_sounds = cfile_read_int(ham_fp);
998 sound_start = cftell(ham_fp);
1000 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1004 for (i=0; i<N_sounds; i++ ) {
1005 DiskSoundHeader_read(&sndh, ham_fp);
1006 temp_sound.length = sndh.length;
1007 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1008 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1009 memcpy( temp_name_read, sndh.name, 8 );
1010 temp_name_read[8] = 0;
1011 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1013 if (piggy_is_needed(i))
1014 #endif // note link to if.
1015 sbytes += sndh.length;
1016 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1019 SoundBits = d_malloc( sbytes + 16 );
1020 if ( SoundBits == NULL )
1021 Error( "Not enough memory to load sounds\n" );
1023 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1025 // piggy_read_sounds(ham_fp);
1037 CFILE * snd_fp = NULL;
1038 int snd_id,snd_version;
1043 DiskSoundHeader sndh;
1044 digi_sound temp_sound;
1045 char temp_name_read[16];
1052 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1054 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1055 snd_fp = cfopen( name, "rb");
1061 //make sure soundfile is valid type file & is up-to-date
1062 snd_id = cfile_read_int(snd_fp);
1063 snd_version = cfile_read_int(snd_fp);
1064 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1065 cfclose(snd_fp); //out of date sound file
1069 N_sounds = cfile_read_int(snd_fp);
1071 sound_start = cftell(snd_fp);
1072 size = cfilelength(snd_fp) - sound_start;
1074 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1076 header_size = N_sounds*sizeof(DiskSoundHeader);
1080 for (i=0; i<N_sounds; i++ ) {
1081 DiskSoundHeader_read(&sndh, snd_fp);
1082 //size -= sizeof(DiskSoundHeader);
1083 temp_sound.length = sndh.length;
1084 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1085 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1086 memcpy( temp_name_read, sndh.name, 8 );
1087 temp_name_read[8] = 0;
1088 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1090 if (piggy_is_needed(i))
1091 #endif // note link to if.
1092 sbytes += sndh.length;
1093 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1096 SoundBits = d_malloc( sbytes + 16 );
1097 if ( SoundBits == NULL )
1098 Error( "Not enough memory to load sounds\n" );
1100 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1102 // piggy_read_sounds(snd_fp);
1109 int piggy_init(void)
1111 int ham_ok=0,snd_ok=0;
1114 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1115 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1117 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1118 GameSounds[i].length = 0;
1119 GameSounds[i].data = NULL;
1123 for (i=0; i<MAX_BITMAP_FILES; i++ )
1124 GameBitmapXlat[i] = i;
1126 if ( !bogus_bitmap_initialized ) {
1129 bogus_bitmap_initialized = 1;
1130 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1131 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1132 bogus_bitmap.bm_data = bogus_data;
1133 c = gr_find_closest_color( 0, 0, 63 );
1134 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1135 c = gr_find_closest_color( 63, 0, 0 );
1136 // Make a big red X !
1137 for (i=0; i<64; i++ ) {
1138 bogus_data[i*64+i] = c;
1139 bogus_data[i*64+(63-i)] = c;
1141 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1142 bogus_sound.length = 64*64;
1143 bogus_sound.data = bogus_data;
1144 GameBitmapOffset[0] = 0;
1147 if ( FindArg( "-bigpig" ))
1150 if ( FindArg( "-lowmem" ))
1151 piggy_low_memory = 1;
1153 if ( FindArg( "-nolowmem" ))
1154 piggy_low_memory = 0;
1156 if (piggy_low_memory)
1159 WIN(DDGRLOCK(dd_grd_curcanv));
1160 gr_set_curfont( SMALL_FONT );
1161 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1162 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1163 WIN(DDGRUNLOCK(dd_grd_curcanv));
1166 piggy_init_pigfile(DEFAULT_PIGFILE);
1169 snd_ok = ham_ok = read_hamfile();
1171 if (Piggy_hamfile_version >= 3)
1172 snd_ok = read_sndfile();
1174 atexit(piggy_close);
1176 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1177 return (ham_ok && snd_ok); //read ok
1180 int piggy_is_needed(int soundnum)
1184 if ( !digi_lomem ) return 1;
1186 for (i=0; i<MAX_SOUNDS; i++ ) {
1187 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1194 void piggy_read_sounds(void)
1207 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1209 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1210 fp = cfopen( name, "rb");
1216 for (i=0; i<Num_sound_files; i++ ) {
1217 digi_sound *snd = &GameSounds[i];
1219 if ( SoundOffset[i] > 0 ) {
1220 if ( piggy_is_needed(i) ) {
1221 cfseek( fp, SoundOffset[i], SEEK_SET );
1223 // Read in the sound data!!!
1226 sbytes += snd->length;
1227 cfread( snd->data, snd->length, 1, fp );
1230 snd->data = (ubyte *) -1;
1236 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1241 extern int descent_critical_error;
1242 extern unsigned descent_critical_deverror;
1243 extern unsigned descent_critical_errcode;
1245 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1246 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1247 "Read fault", "General Failure" };
1249 void piggy_critical_error()
1251 grs_canvas * save_canv;
1252 grs_font * save_font;
1254 save_canv = grd_curcanv;
1255 save_font = grd_curcanv->cv_font;
1256 gr_palette_load( gr_palette );
1257 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1260 gr_set_current_canvas(save_canv);
1261 grd_curcanv->cv_font = save_font;
1264 void piggy_bitmap_page_in( bitmap_index bitmap )
1273 Assert( i < MAX_BITMAP_FILES );
1274 Assert( i < Num_bitmap_files );
1275 Assert( Piggy_bitmap_cache_size > 0 );
1277 if ( i < 1 ) return;
1278 if ( i >= MAX_BITMAP_FILES ) return;
1279 if ( i >= Num_bitmap_files ) return;
1281 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1283 if ( piggy_low_memory ) {
1285 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1288 bmp = &GameBitmaps[i];
1290 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1294 descent_critical_error = 0;
1295 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1296 if ( descent_critical_error ) {
1297 piggy_critical_error();
1301 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1302 bmp->bm_flags = GameBitmapFlags[i];
1304 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1306 descent_critical_error = 0;
1307 zsize = cfile_read_int(Piggy_fp);
1308 if ( descent_critical_error ) {
1309 piggy_critical_error();
1313 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1314 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1315 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1317 piggy_bitmap_page_out_all();
1320 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1321 Piggy_bitmap_cache_next += sizeof(int);
1322 descent_critical_error = 0;
1323 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1324 if ( descent_critical_error ) {
1325 piggy_critical_error();
1328 Piggy_bitmap_cache_next += zsize-4;
1330 if (Gr_transparency_color == 0)
1331 rle_swap_0_255( bmp );
1334 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1335 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1336 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1337 piggy_bitmap_page_out_all();
1340 descent_critical_error = 0;
1341 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1342 if ( descent_critical_error ) {
1343 piggy_critical_error();
1346 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1348 if (Gr_transparency_color == 0)
1355 //@@if ( bmp->bm_selector ) {
1356 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1357 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1358 //@@ Error( "Error modifying selector base in piggy.c\n" );
1365 if ( piggy_low_memory ) {
1367 GameBitmaps[org_i] = GameBitmaps[i];
1370 //@@Removed from John's code:
1372 //@@ if ( bmp->bm_selector ) {
1373 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1374 //@@ Error( "Error modifying selector base in piggy.c\n" );
1380 void piggy_bitmap_page_out_all()
1384 Piggy_bitmap_cache_next = 0;
1386 piggy_page_flushed++;
1391 for (i=0; i<Num_bitmap_files; i++ ) {
1392 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1393 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1394 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1398 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1401 void piggy_load_level_data()
1403 piggy_bitmap_page_out_all();
1409 void change_filename_ext( char *dest, char *src, char *ext );
1411 void piggy_write_pigfile(char *filename)
1414 int bitmap_data_start,data_offset;
1415 DiskBitmapHeader bmh;
1417 char subst_name[32];
1420 char tname[FILENAME_LEN];
1422 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1423 for (i=0; i < Num_bitmap_files; i++ ) {
1426 PIGGY_PAGE_IN( bi );
1428 // -- mprintf( (0, "\n" ));
1432 // -- mprintf( (0, "Creating %s...",filename ));
1434 pig_fp = fopen( filename, "wb" ); //open PIG file
1435 Assert( pig_fp!=NULL );
1437 write_int(PIGFILE_ID,pig_fp);
1438 write_int(PIGFILE_VERSION,pig_fp);
1441 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1444 bitmap_data_start = ftell(pig_fp);
1445 bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE;
1446 data_offset = bitmap_data_start;
1448 change_filename_ext(tname,filename,"lst");
1449 fp1 = fopen( tname, "wt" );
1450 change_filename_ext(tname,filename,"all");
1451 fp2 = fopen( tname, "wt" );
1453 for (i=1; i < Num_bitmap_files; i++ ) {
1459 p = strchr(AllBitmaps[i].name,'#');
1466 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1467 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1469 bmh.dflags = DBM_FLAG_ABM + n;
1473 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1474 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1478 bmp = &GameBitmaps[i];
1480 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1483 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1484 org_offset = ftell(pig_fp);
1485 bmh.offset = data_offset - bitmap_data_start;
1486 fseek( pig_fp, data_offset, SEEK_SET );
1488 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1489 size = (int *)bmp->bm_data;
1490 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1491 data_offset += *size;
1493 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1495 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1496 data_offset += bmp->bm_rowsize * bmp->bm_h;
1498 fprintf( fp1, ".\n" );
1500 fseek( pig_fp, org_offset, SEEK_SET );
1501 Assert( GameBitmaps[i].bm_w < 4096 );
1502 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1503 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1504 Assert( GameBitmaps[i].bm_h < 4096 );
1505 bmh.height = GameBitmaps[i].bm_h;
1506 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1507 bmh.flags = GameBitmaps[i].bm_flags;
1508 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1509 bitmap_index other_bitmap;
1510 other_bitmap = piggy_find_bitmap( subst_name );
1511 GameBitmapXlat[i] = other_bitmap.index;
1512 bmh.flags |= BM_FLAG_PAGED_OUT;
1513 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1514 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1516 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1518 bmh.avg_color=GameBitmaps[i].avg_color;
1519 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp ); // Mark as a bitmap
1524 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1525 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1532 static void write_int(int i,FILE *file)
1534 if (fwrite( &i, sizeof(i), 1, file) != 1)
1535 Error( "Error reading int in gamesave.c" );
1539 void piggy_dump_all()
1543 int org_offset,data_offset=0;
1544 DiskSoundHeader sndh;
1545 int sound_data_start=0;
1548 #ifdef NO_DUMP_SOUNDS
1549 Num_sound_files = 0;
1550 Num_sound_files_new = 0;
1553 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1556 fp1 = fopen( "ham.lst", "wt" );
1557 fp2 = fopen( "ham.all", "wt" );
1559 if (Must_write_hamfile || Num_bitmap_files_new) {
1561 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1563 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1564 Assert( ham_fp!=NULL );
1566 write_int(HAMFILE_ID,ham_fp);
1567 write_int(HAMFILE_VERSION,ham_fp);
1569 bm_write_all(ham_fp);
1570 xlat_offset = ftell(ham_fp);
1571 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1574 if (Num_bitmap_files_new)
1575 piggy_write_pigfile(DEFAULT_PIGFILE);
1577 //free up memeory used by new bitmaps
1578 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1579 d_free(GameBitmaps[i].bm_data);
1581 //next thing must be done after pig written
1582 fseek( ham_fp, xlat_offset, SEEK_SET );
1583 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1586 mprintf( (0, "\n" ));
1589 if (Num_sound_files_new) {
1591 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1592 // Now dump sound file
1593 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1594 Assert( ham_fp!=NULL );
1596 write_int(SNDFILE_ID,ham_fp);
1597 write_int(SNDFILE_VERSION,ham_fp);
1599 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1601 mprintf( (0, "\nDumping sounds..." ));
1603 sound_data_start = ftell(ham_fp);
1604 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1605 data_offset = sound_data_start;
1607 for (i=0; i < Num_sound_files; i++ ) {
1610 snd = &GameSounds[i];
1611 strcpy( sndh.name, AllSounds[i].name );
1612 sndh.length = GameSounds[i].length;
1613 sndh.offset = data_offset - sound_data_start;
1615 org_offset = ftell(ham_fp);
1616 fseek( ham_fp, data_offset, SEEK_SET );
1618 sndh.data_length = GameSounds[i].length;
1619 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1620 data_offset += snd->length;
1621 fseek( ham_fp, org_offset, SEEK_SET );
1622 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1624 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1625 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1629 mprintf( (0, "\n" ));
1632 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1633 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1634 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1639 // Never allow the game to run after building ham.
1653 d_free( SoundBits );
1655 hashtable_free( &AllBitmapsNames );
1656 hashtable_free( &AllDigiSndNames );
1660 int piggy_does_bitmap_exist_slow( char * name )
1664 for (i=0; i<Num_bitmap_files; i++ ) {
1665 if ( !strcmp( AllBitmaps[i].name, name) )
1672 #define NUM_GAUGE_BITMAPS 23
1673 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1674 "gauge01", "gauge01b",
1675 "gauge02", "gauge02b",
1676 "gauge06", "gauge06b",
1677 "targ01", "targ01b",
1678 "targ02", "targ02b",
1679 "targ03", "targ03b",
1680 "targ04", "targ04b",
1681 "targ05", "targ05b",
1682 "targ06", "targ06b",
1683 "gauge18", "gauge18b",
1689 int piggy_is_gauge_bitmap( char * base_name )
1692 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1693 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1700 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1704 char base_name[ 16 ];
1706 strcpy( subst_name, name );
1707 p = strchr( subst_name, '#' );
1709 frame = atoi( &p[1] );
1711 strcpy( base_name, subst_name );
1712 if ( !piggy_is_gauge_bitmap( base_name )) {
1713 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1714 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1716 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1722 strcpy( subst_name, name );
1729 // New Windows stuff
1731 // windows bitmap page in
1732 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1733 // 'video' memory. if that fails, page it in normally.
1735 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1740 // Essential when switching video modes!
1742 void piggy_bitmap_page_out_all_w()
1748 #ifndef FAST_FILE_IO
1750 * reads a bitmap_index structure from a CFILE
1752 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
1754 bi->index = cfile_read_short(fp);
1758 * reads n bitmap_index structs from a CFILE
1760 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
1764 for (i = 0; i < n; i++)
1765 bi[i].index = cfile_read_short(fp);
1770 * reads a DiskBitmapHeader structure from a CFILE
1772 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
1774 cfread(dbh->name, 8, 1, fp);
1775 dbh->dflags = cfile_read_byte(fp);
1776 dbh->width = cfile_read_byte(fp);
1777 dbh->height = cfile_read_byte(fp);
1778 dbh->wh_extra = cfile_read_byte(fp);
1779 dbh->flags = cfile_read_byte(fp);
1780 dbh->avg_color = cfile_read_byte(fp);
1781 dbh->offset = cfile_read_int(fp);
1785 * reads a DiskSoundHeader structure from a CFILE
1787 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
1789 cfread(dsh->name, 8, 1, fp);
1790 dsh->length = cfile_read_int(fp);
1791 dsh->data_length = cfile_read_int(fp);
1792 dsh->offset = cfile_read_int(fp);