2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
19 static char rcsid[] = "$Id: piggy.c,v 1.6 2001-11-08 10:30:28 bradleyb Exp $";
57 #include <Strings.h> // MacOS Toolbox header
62 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
64 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
65 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
69 #define DEFAULT_HAMFILE "d2demo.ham"
70 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_SHAREWARE
71 #define DEFAULT_SNDFILE "descent2.s11"
73 #define DEFAULT_HAMFILE "descent2.ham"
74 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_REGISTERED
75 #define DEFAULT_SNDFILE ((digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
76 #endif // end of ifdef SHAREWARE
78 ubyte *BitmapBits = NULL;
79 ubyte *SoundBits = NULL;
81 typedef struct BitmapFile {
85 typedef struct SoundFile {
89 hashtable AllBitmapsNames;
90 hashtable AllDigiSndNames;
92 int Num_bitmap_files = 0;
93 int Num_sound_files = 0;
95 digi_sound GameSounds[MAX_SOUND_FILES];
96 int SoundOffset[MAX_SOUND_FILES];
97 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
99 alias alias_list[MAX_ALIASES];
102 int Must_write_hamfile = 0;
103 int Num_bitmap_files_new = 0;
104 int Num_sound_files_new = 0;
105 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
106 static SoundFile AllSounds[ MAX_SOUND_FILES ];
108 int piggy_low_memory = 0;
110 int Piggy_bitmap_cache_size = 0;
111 int Piggy_bitmap_cache_next = 0;
112 ubyte * Piggy_bitmap_cache_data = NULL;
113 static int GameBitmapOffset[MAX_BITMAP_FILES];
114 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
115 ushort GameBitmapXlat[MAX_BITMAP_FILES];
117 #define PIGGY_BUFFER_SIZE (2400*1024)
120 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
123 #undef PIGGY_BUFFER_SIZE
124 #undef PIGGY_SMALL_BUFFER_SIZE
126 #define PIGGY_BUFFER_SIZE (2000*1024)
127 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
132 int piggy_page_flushed = 0;
134 #define DBM_FLAG_ABM 64
136 typedef struct DiskBitmapHeader {
138 ubyte dflags; //bits 0-5 anim frame num, bit 6 abm flag
139 ubyte width; //low 8 bits here, 4 more bits in wh_extra
140 ubyte height; //low 8 bits here, 4 more bits in wh_extra
141 ubyte wh_extra; //bits 0-3 width, bits 4-7 height
145 } __pack__ DiskBitmapHeader;
147 typedef struct DiskSoundHeader {
152 } __pack__ DiskSoundHeader;
157 extern short cd_VRefNum;
158 extern void ConcatPStr(StringPtr dst, StringPtr src);
159 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
160 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
163 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
166 void piggy_write_pigfile(char *filename);
167 static void write_int(int i,FILE *file);
169 void swap_0_255(grs_bitmap *bmp)
173 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
174 if(bmp->bm_data[i] == 0)
175 bmp->bm_data[i] = 255;
176 else if (bmp->bm_data[i] == 255)
182 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
185 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
187 temp.index = Num_bitmap_files;
191 if ( FindArg("-macdata") )
194 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
195 Num_bitmap_files_new++;
198 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
199 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
200 GameBitmaps[Num_bitmap_files] = *bmp;
202 GameBitmapOffset[Num_bitmap_files] = 0;
203 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
210 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
214 Assert( Num_sound_files < MAX_SOUND_FILES );
216 strncpy( AllSounds[Num_sound_files].name, name, 12 );
217 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
218 GameSounds[Num_sound_files] = *snd;
220 SoundOffset[Num_sound_files] = 0;
226 Num_sound_files_new++;
232 bitmap_index piggy_find_bitmap( char * name )
240 if ((t=strchr(name,'#'))!=NULL)
243 for (i=0;i<Num_aliases;i++)
244 if (stricmp(name,alias_list[i].alias_name)==0) {
245 if (t) { //extra stuff for ABMs
246 static char temp[FILENAME_LEN];
247 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
253 name=alias_list[i].file_name;
260 i = hashtable_search( &AllBitmapsNames, name );
269 int piggy_find_sound( char * name )
273 i = hashtable_search( &AllDigiSndNames, name );
281 CFILE * Piggy_fp = NULL;
283 #define FILENAME_LEN 13
285 char Current_pigfile[FILENAME_LEN] = "";
287 void piggy_close_file()
292 Current_pigfile[0] = 0;
296 int Pigfile_initialized=0;
298 #define PIGFILE_ID "PPIG" //PPIG
299 #define PIGFILE_VERSION 2
301 extern char CDROM_dir[];
303 int request_cd(void);
308 //copies a pigfile from the CD to the current dir
309 //retuns file handle of new pig
310 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
313 char sourcePathAndFileCStr[255] = "";
314 char destPathAndFileCStr[255] = "";
316 FILE* sourceFile = NULL;
317 FILE* destFile = NULL;
318 const int BUF_SIZE = 4096;
322 Str255 sourcePathAndFilePStr = "\p";
323 Str255 destPathAndFilePStr = "\p";
324 Str255 pigfileNamePStr = "\p";
325 HParamBlockRec theSourcePigHFSParams;
326 HParamBlockRec theDestPigHFSParams;
327 OSErr theErr = noErr;
328 char oldDirCStr[255] = "";
330 getcwd(oldDirCStr, 255);
332 show_boxed_message("Copying bitmap data from CD...");
333 gr_palette_load(gr_palette); //I don't think this line is really needed
336 //First, delete all PIG files currently in the directory
337 if( !FileFindFirst( "*.pig", &find ) )
342 } while( !FileFindNext( &find ) );
348 //Now, copy over new pig
349 songs_stop_redbook(); //so we can read off the cd
351 // make the source path "<cd volume>:Data:filename.pig"
352 //MWA ConvertCToPStr(filename, pigfileNamePStr);
354 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
355 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
358 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
359 strcat(sourcePathAndFileCStr, filename);
361 // make the destination path "<default directory>:Data:filename.pig"
362 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
363 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
364 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
365 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
367 strcpy(destPathAndFileCStr, ":Data:");
368 strcat(destPathAndFileCStr, filename);
370 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
371 strcpy(destPathAndFilePStr, destPathAndFileCStr);
372 c2pstr(sourcePathAndFilePStr);
373 c2pstr(destPathAndFilePStr);
376 // Open the source file
377 sourceFile = fopen(sourcePathAndFileCStr,"rb");
381 if (request_cd() == -1)
382 Error("Cannot load file <%s> from CD",filename);
385 } while (!sourceFile);
388 // Get the time stamp from the source file
389 theSourcePigHFSParams.fileParam.ioCompletion = nil;
390 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
391 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
392 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
393 theSourcePigHFSParams.fileParam.ioDirID = 0;
395 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
398 // Error getting file time stamp!! Why? JTS
399 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
402 // Copy the file over
405 // Open the destination file
406 destFile = fopen(destPathAndFileCStr,"wb");
409 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
412 // Copy bytes until the end of the source file
413 while (!feof(sourceFile))
418 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
419 if (ferror(sourceFile))
420 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
422 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
424 fwrite(buf,1,bytes_read,destFile);
425 if (ferror(destFile))
426 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
429 // close the source/dest files
430 if (fclose(sourceFile))
431 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
432 if (fclose(destFile))
433 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
435 // Get the current hfs data for the new file
436 theDestPigHFSParams.fileParam.ioCompletion = nil;
437 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
438 theDestPigHFSParams.fileParam.ioVRefNum = 0;
439 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
440 theDestPigHFSParams.fileParam.ioDirID = 0;
441 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
442 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
444 // Error getting file time stamp!! Why? JTS
445 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
448 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
449 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
450 theDestPigHFSParams.fileParam.ioVRefNum = 0;
451 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
452 theDestPigHFSParams.fileParam.ioDirID = 0;
454 // Copy the time stamp from the source file info
455 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
456 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
457 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
458 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
460 // Set the dest file's time stamp to the source file's time stamp values
461 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
463 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
465 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
468 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
470 return cfopen(destPathAndFileCStr, "rb");
473 #else //PC Version of copy_pigfile_from_cd is below
475 //copies a pigfile from the CD to the current dir
476 //retuns file handle of new pig
477 CFILE *copy_pigfile_from_cd(char *filename)
483 return cfopen(filename, "rb");
484 show_boxed_message("Copying bitmap data from CD...");
485 gr_palette_load(gr_palette); //I don't think this line is really needed
487 //First, delete all PIG files currently in the directory
489 if( !FileFindFirst( "*.pig", &find ) ) {
492 } while( !FileFindNext( &find ) );
496 //Now, copy over new pig
498 songs_stop_redbook(); //so we can read off the cd
500 //new code to unarj file
501 strcpy(name,CDROM_dir);
502 strcat(name,"descent2.sow");
505 // ret = unarj_specific_file(name,filename,filename);
510 if (ret != EXIT_SUCCESS) {
512 //delete file, so we don't leave partial file
516 if (request_cd() == -1)
518 //NOTE LINK TO ABOVE IF
519 Error("Cannot load file <%s> from CD",filename);
522 } while (ret != EXIT_SUCCESS);
524 return cfopen(filename, "rb");
527 #endif // end of ifdef MAC around copy_pigfile_from_cd
529 //initialize a pigfile, reading headers
530 //returns the size of all the bitmap data
531 void piggy_init_pigfile(char *filename)
535 char temp_name_read[16];
536 grs_bitmap temp_bitmap;
537 DiskBitmapHeader bmh;
538 int header_size, N_bitmaps, data_size, data_start;
540 char name[255]; // filename + path for the mac
543 piggy_close_file(); //close old pig if still open
545 #ifdef SHAREWARE //rename pigfile for shareware
546 if (stricmp(filename,DEFAULT_PIGFILE_REGISTERED)==0)
547 filename = DEFAULT_PIGFILE_SHAREWARE;
551 Piggy_fp = cfopen( filename, "rb" );
553 sprintf(name, ":Data:%s", filename);
554 Piggy_fp = cfopen( name, "rb" );
556 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
557 if (Piggy_fp == NULL)
559 Error("Cannot load required file <%s>",name);
561 #endif // end of if def shareware
567 return; //if editor, ok to not have pig, because we'll build one
569 Piggy_fp = copy_pigfile_from_cd(filename);
573 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
577 cfread(&pig_id, 1, 4, Piggy_fp);
578 pig_version = cfile_read_int(Piggy_fp);
579 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
580 cfclose(Piggy_fp); //out of date pig
581 Piggy_fp = NULL; //..so pretend it's not here
588 return; //if editor, ok to not have pig, because we'll build one
590 Error("Cannot load required file <%s>",filename);
594 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
596 N_bitmaps = cfile_read_int(Piggy_fp);
598 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
600 data_start = header_size + cftell(Piggy_fp);
602 data_size = cfilelength(Piggy_fp) - data_start;
604 Num_bitmap_files = 1;
606 for (i=0; i<N_bitmaps; i++ ) {
608 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
610 cfread(bmh.name, 8, 1, Piggy_fp);
611 bmh.dflags = cfile_read_byte(Piggy_fp);
612 bmh.width = cfile_read_byte(Piggy_fp);
613 bmh.height = cfile_read_byte(Piggy_fp);
614 bmh.wh_extra = cfile_read_byte(Piggy_fp);
615 bmh.flags = cfile_read_byte(Piggy_fp);
616 bmh.avg_color = cfile_read_byte(Piggy_fp);
617 bmh.offset = cfile_read_int(Piggy_fp);
619 memcpy( temp_name_read, bmh.name, 8 );
620 temp_name_read[8] = 0;
621 if ( bmh.dflags & DBM_FLAG_ABM )
622 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
624 strcpy( temp_name, temp_name_read );
625 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
626 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
627 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
628 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
629 temp_bitmap.avg_color = bmh.avg_color;
630 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
632 GameBitmapFlags[i+1] = 0;
633 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
634 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
635 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
636 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
637 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
639 GameBitmapOffset[i+1] = bmh.offset + data_start;
640 Assert( (i+1) == Num_bitmap_files );
641 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
645 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
646 Assert( Piggy_bitmap_cache_size > 0 );
648 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
650 if (piggy_low_memory)
651 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
654 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
655 if ( BitmapBits == NULL )
656 Error( "Not enough memory to load bitmaps\n" );
657 Piggy_bitmap_cache_data = BitmapBits;
658 Piggy_bitmap_cache_next = 0;
660 #if defined(MACINTOSH) && defined(SHAREWARE)
661 // load_exit_models();
664 Pigfile_initialized=1;
667 #define FILENAME_LEN 13
668 #define MAX_BITMAPS_PER_BRUSH 30
670 extern int compute_average_pixel(grs_bitmap *new);
672 //reads in a new pigfile (for new palette)
673 //returns the size of all the bitmap data
674 void piggy_new_pigfile(char *pigname)
678 char temp_name_read[16];
679 grs_bitmap temp_bitmap;
680 DiskBitmapHeader bmh;
681 int header_size, N_bitmaps, data_size, data_start;
682 int must_rewrite_pig = 0;
689 #ifdef SHAREWARE //rename pigfile for shareware
690 if (stricmp(pigname,DEFAULT_PIGFILE_REGISTERED)==0)
691 pigname = DEFAULT_PIGFILE_SHAREWARE;
694 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
695 return; //already have correct pig
697 if (!Pigfile_initialized) { //have we ever opened a pigfile?
698 piggy_init_pigfile(pigname); //..no, so do initialization stuff
702 piggy_close_file(); //close old pig if still open
704 Piggy_bitmap_cache_next = 0; //free up cache
706 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
709 Piggy_fp = cfopen( pigname, "rb" );
711 sprintf(name, ":Data:%s", pigname);
712 Piggy_fp = cfopen( name, "rb" );
714 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
715 if (Piggy_fp == NULL)
717 Error("Cannot load required file <%s>",name);
719 #endif // end of if def shareware
724 Piggy_fp = copy_pigfile_from_cd(pigname);
727 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
731 cfread(&pig_id, 1, 4, Piggy_fp);
732 pig_version = cfile_read_int(Piggy_fp);
733 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
734 cfclose(Piggy_fp); //out of date pig
735 Piggy_fp = NULL; //..so pretend it's not here
740 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
745 N_bitmaps = cfile_read_int(Piggy_fp);
747 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
749 data_start = header_size + cftell(Piggy_fp);
751 data_size = cfilelength(Piggy_fp) - data_start;
753 for (i=1; i<=N_bitmaps; i++ ) {
755 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
757 cfread(bmh.name, 8, 1, Piggy_fp);
758 bmh.dflags = cfile_read_byte(Piggy_fp);
759 bmh.width = cfile_read_byte(Piggy_fp);
760 bmh.height = cfile_read_byte(Piggy_fp);
761 bmh.wh_extra = cfile_read_byte(Piggy_fp);
762 bmh.flags = cfile_read_byte(Piggy_fp);
763 bmh.avg_color = cfile_read_byte(Piggy_fp);
764 bmh.offset = cfile_read_int(Piggy_fp);
766 memcpy( temp_name_read, bmh.name, 8 );
767 temp_name_read[8] = 0;
769 if ( bmh.dflags & DBM_FLAG_ABM )
770 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
772 strcpy( temp_name, temp_name_read );
774 //Make sure name matches
775 if (strcmp(temp_name,AllBitmaps[i].name)) {
776 //Int3(); //this pig is out of date. Delete it
780 strcpy(AllBitmaps[i].name,temp_name);
782 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
784 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
785 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
786 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
787 temp_bitmap.avg_color = bmh.avg_color;
788 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
790 GameBitmapFlags[i] = 0;
792 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
793 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
794 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
795 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
796 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
798 GameBitmapOffset[i] = bmh.offset + data_start;
800 GameBitmaps[i] = temp_bitmap;
804 N_bitmaps = 0; //no pigfile, so no bitmaps
808 Assert(N_bitmaps == Num_bitmap_files-1);
812 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
815 //re-read the bitmaps that aren't in this pig
817 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
820 p = strchr(AllBitmaps[i].name,'#');
822 if (p) { //this is an ABM
823 char abmname[FILENAME_LEN];
825 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
826 int iff_error; //reference parm to avoid warning message
828 char basename[FILENAME_LEN];
831 strcpy(basename,AllBitmaps[i].name);
832 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
834 sprintf( abmname, "%s.abm", basename );
836 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
838 if (iff_error != IFF_NO_ERROR) {
839 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
840 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
843 for (fnum=0;fnum<nframes; fnum++) {
847 sprintf( tempname, "%s#%d", basename, fnum );
849 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
850 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
851 //above makes assumption that supertransparent color is 254
853 if ( iff_has_transparency )
854 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
856 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
858 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
861 if ( FindArg("-macdata") )
862 swap_0_255( bm[fnum] );
864 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
866 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
867 size = *((int *) bm[fnum]->bm_data);
869 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
871 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
872 d_free(bm[fnum]->bm_data);
873 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
874 Piggy_bitmap_cache_next += size;
876 GameBitmaps[i+fnum] = *bm[fnum];
878 // -- mprintf( (0, "U" ));
882 i += nframes-1; //filled in multiple bitmaps
884 else { //this is a BBM
889 char bbmname[FILENAME_LEN];
892 MALLOC( new, grs_bitmap, 1 );
894 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
895 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
898 if (iff_error != IFF_NO_ERROR) {
899 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
900 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
903 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
904 //above makes assumption that supertransparent color is 254
906 if ( iff_has_transparency )
907 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
909 gr_remap_bitmap_good( new, newpal, -1, SuperX );
911 new->avg_color = compute_average_pixel(new);
914 if ( FindArg("-macdata") )
917 if ( !BigPig ) gr_bitmap_rle_compress( new );
919 if (new->bm_flags & BM_FLAG_RLE)
920 size = *((int *) new->bm_data);
922 size = new->bm_w * new->bm_h;
924 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
925 d_free(new->bm_data);
926 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
927 Piggy_bitmap_cache_next += size;
929 GameBitmaps[i] = *new;
933 // -- mprintf( (0, "U" ));
937 //@@Dont' do these things which are done when writing
938 //@@for (i=0; i < Num_bitmap_files; i++ ) {
939 //@@ bitmap_index bi;
941 //@@ PIGGY_PAGE_IN( bi );
944 //@@piggy_close_file();
946 piggy_write_pigfile(pigname);
948 Current_pigfile[0] = 0; //say no pig, to force reload
950 piggy_new_pigfile(pigname); //read in just-generated pig
954 #endif //ifdef EDITOR
958 ubyte bogus_data[64*64];
959 grs_bitmap bogus_bitmap;
960 ubyte bogus_bitmap_initialized=0;
961 digi_sound bogus_sound;
963 extern void bm_read_all(CFILE * fp);
965 #define HAMFILE_ID "HAM!" //HAM!
967 #define HAMFILE_VERSION 2
969 #define HAMFILE_VERSION 3
971 //version 1 -> 2: save marker_model_num
972 //version 2 -> 3: removed sound files
974 #define SNDFILE_ID "DSND" //DSND
975 #define SNDFILE_VERSION 1
979 CFILE * ham_fp = NULL;
987 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
989 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
990 ham_fp = cfopen( name, "rb" );
993 if (ham_fp == NULL) {
994 Must_write_hamfile = 1;
998 //make sure ham is valid type file & is up-to-date
999 cfread( &ham_id, 1, 4, ham_fp );
1000 ham_version = cfile_read_int(ham_fp);
1001 if (memcmp(ham_id, HAMFILE_ID, 4) || ham_version != HAMFILE_VERSION) {
1002 Must_write_hamfile = 1;
1003 cfclose(ham_fp); //out of date ham
1007 if (ham_version < 3) //mystery value
1008 cfseek(ham_fp, 4, SEEK_CUR);
1012 bm_read_all( ham_fp ); // Note connection to above if!!!
1013 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1018 for (i = 0; i < MAX_BITMAP_FILES; i++)
1019 GameBitmapXlat[i] = SWAPSHORT(GameBitmapXlat[i]);
1033 CFILE * snd_fp = NULL;
1040 DiskSoundHeader sndh;
1041 digi_sound temp_sound;
1042 char temp_name_read[16];
1049 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1051 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1052 snd_fp = cfopen( name, "rb");
1058 //make sure soundfile is valid type file & is up-to-date
1059 cfread( &snd_id, 1, 4, snd_fp );
1060 snd_version = cfile_read_int(snd_fp);
1061 if (memcmp(snd_id, SNDFILE_ID, 4) || snd_version != SNDFILE_VERSION) {
1062 cfclose(snd_fp); //out of date sound file
1066 N_sounds = cfile_read_int(snd_fp);
1068 sound_start = cftell(snd_fp);
1069 size = cfilelength(snd_fp) - sound_start;
1071 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1073 header_size = N_sounds*sizeof(DiskSoundHeader);
1077 for (i=0; i<N_sounds; i++ ) {
1078 cfread( sndh.name, 8, 1, snd_fp);
1079 sndh.length = cfile_read_int(snd_fp);
1080 sndh.data_length = cfile_read_int(snd_fp);
1081 sndh.offset = cfile_read_int(snd_fp);
1082 // cfread( &sndh, sizeof(DiskSoundHeader), 1, snd_fp );
1083 //size -= sizeof(DiskSoundHeader);
1084 temp_sound.length = sndh.length;
1085 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1086 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1087 memcpy( temp_name_read, sndh.name, 8 );
1088 temp_name_read[8] = 0;
1089 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1091 if (piggy_is_needed(i))
1092 #endif // note link to if.
1093 sbytes += sndh.length;
1094 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1097 SoundBits = d_malloc( sbytes + 16 );
1098 if ( SoundBits == NULL )
1099 Error( "Not enough memory to load sounds\n" );
1101 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1103 // piggy_read_sounds(snd_fp);
1110 int piggy_init(void)
1112 int ham_ok=0,snd_ok=0;
1115 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1116 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1118 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1119 GameSounds[i].length = 0;
1120 GameSounds[i].data = NULL;
1124 for (i=0; i<MAX_BITMAP_FILES; i++ )
1125 GameBitmapXlat[i] = i;
1127 if ( !bogus_bitmap_initialized ) {
1130 bogus_bitmap_initialized = 1;
1131 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1132 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1133 bogus_bitmap.bm_data = bogus_data;
1134 c = gr_find_closest_color( 0, 0, 63 );
1135 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1136 c = gr_find_closest_color( 63, 0, 0 );
1137 // Make a big red X !
1138 for (i=0; i<64; i++ ) {
1139 bogus_data[i*64+i] = c;
1140 bogus_data[i*64+(63-i)] = c;
1142 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1143 bogus_sound.length = 64*64;
1144 bogus_sound.data = bogus_data;
1145 GameBitmapOffset[0] = 0;
1148 if ( FindArg( "-bigpig" ))
1151 if ( FindArg( "-lowmem" ))
1152 piggy_low_memory = 1;
1154 if ( FindArg( "-nolowmem" ))
1155 piggy_low_memory = 0;
1157 if (piggy_low_memory)
1160 WIN(DDGRLOCK(dd_grd_curcanv));
1161 gr_set_curfont( SMALL_FONT );
1162 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1163 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1164 WIN(DDGRUNLOCK(dd_grd_curcanv));
1167 piggy_init_pigfile(DEFAULT_PIGFILE);
1170 ham_ok = read_hamfile();
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 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1331 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1332 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1333 piggy_bitmap_page_out_all();
1336 descent_critical_error = 0;
1337 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1338 if ( descent_critical_error ) {
1339 piggy_critical_error();
1342 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1345 //@@if ( bmp->bm_selector ) {
1346 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1347 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1348 //@@ Error( "Error modifying selector base in piggy.c\n" );
1355 if ( piggy_low_memory ) {
1357 GameBitmaps[org_i] = GameBitmaps[i];
1360 //@@Removed from John's code:
1362 //@@ if ( bmp->bm_selector ) {
1363 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1364 //@@ Error( "Error modifying selector base in piggy.c\n" );
1370 void piggy_bitmap_page_out_all()
1374 Piggy_bitmap_cache_next = 0;
1376 piggy_page_flushed++;
1381 for (i=0; i<Num_bitmap_files; i++ ) {
1382 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1383 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1384 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1388 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1391 void piggy_load_level_data()
1393 piggy_bitmap_page_out_all();
1399 void change_filename_ext( char *dest, char *src, char *ext );
1401 void piggy_write_pigfile(char *filename)
1404 int bitmap_data_start,data_offset;
1405 DiskBitmapHeader bmh;
1407 char subst_name[32];
1410 char tname[FILENAME_LEN];
1412 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1413 for (i=0; i < Num_bitmap_files; i++ ) {
1416 PIGGY_PAGE_IN( bi );
1418 // -- mprintf( (0, "\n" ));
1422 // -- mprintf( (0, "Creating %s...",filename ));
1424 pig_fp = fopen( filename, "wb" ); //open PIG file
1425 Assert( pig_fp!=NULL );
1427 write_int((int)PIGFILE_ID,pig_fp);
1428 write_int(PIGFILE_VERSION,pig_fp);
1431 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1434 bitmap_data_start = ftell(pig_fp);
1435 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1436 data_offset = bitmap_data_start;
1438 change_filename_ext(tname,filename,"lst");
1439 fp1 = fopen( tname, "wt" );
1440 change_filename_ext(tname,filename,"all");
1441 fp2 = fopen( tname, "wt" );
1443 for (i=1; i < Num_bitmap_files; i++ ) {
1449 p = strchr(AllBitmaps[i].name,'#');
1456 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1457 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1459 bmh.dflags = DBM_FLAG_ABM + n;
1463 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1464 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1468 bmp = &GameBitmaps[i];
1470 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1473 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1474 org_offset = ftell(pig_fp);
1475 bmh.offset = data_offset - bitmap_data_start;
1476 fseek( pig_fp, data_offset, SEEK_SET );
1478 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1479 size = (int *)bmp->bm_data;
1480 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1481 data_offset += *size;
1483 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1485 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1486 data_offset += bmp->bm_rowsize * bmp->bm_h;
1488 fprintf( fp1, ".\n" );
1490 fseek( pig_fp, org_offset, SEEK_SET );
1491 Assert( GameBitmaps[i].bm_w < 4096 );
1492 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1493 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1494 Assert( GameBitmaps[i].bm_h < 4096 );
1495 bmh.height = GameBitmaps[i].bm_h;
1496 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1497 bmh.flags = GameBitmaps[i].bm_flags;
1498 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1499 bitmap_index other_bitmap;
1500 other_bitmap = piggy_find_bitmap( subst_name );
1501 GameBitmapXlat[i] = other_bitmap.index;
1502 bmh.flags |= BM_FLAG_PAGED_OUT;
1503 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1504 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1506 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1508 bmh.avg_color=GameBitmaps[i].avg_color;
1509 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1514 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1515 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1522 static void write_int(int i,FILE *file)
1524 if (fwrite( &i, sizeof(i), 1, file) != 1)
1525 Error( "Error reading int in gamesave.c" );
1529 void piggy_dump_all()
1533 int org_offset,data_offset=0;
1534 DiskSoundHeader sndh;
1535 int sound_data_start=0;
1538 #ifdef NO_DUMP_SOUNDS
1539 Num_sound_files = 0;
1540 Num_sound_files_new = 0;
1543 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1546 fp1 = fopen( "ham.lst", "wt" );
1547 fp2 = fopen( "ham.all", "wt" );
1549 if (Must_write_hamfile || Num_bitmap_files_new) {
1551 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1553 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1554 Assert( ham_fp!=NULL );
1556 write_int((int)HAMFILE_ID,ham_fp);
1557 write_int(HAMFILE_VERSION,ham_fp);
1559 bm_write_all(ham_fp);
1560 xlat_offset = ftell(ham_fp);
1561 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1564 if (Num_bitmap_files_new)
1565 piggy_write_pigfile(DEFAULT_PIGFILE);
1567 //free up memeory used by new bitmaps
1568 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1569 d_free(GameBitmaps[i].bm_data);
1571 //next thing must be done after pig written
1572 fseek( ham_fp, xlat_offset, SEEK_SET );
1573 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1576 mprintf( (0, "\n" ));
1579 if (Num_sound_files_new) {
1581 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1582 // Now dump sound file
1583 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1584 Assert( ham_fp!=NULL );
1586 write_int((int)SNDFILE_ID,ham_fp);
1587 write_int(SNDFILE_VERSION,ham_fp);
1589 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1591 mprintf( (0, "\nDumping sounds..." ));
1593 sound_data_start = ftell(ham_fp);
1594 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1595 data_offset = sound_data_start;
1597 for (i=0; i < Num_sound_files; i++ ) {
1600 snd = &GameSounds[i];
1601 strcpy( sndh.name, AllSounds[i].name );
1602 sndh.length = GameSounds[i].length;
1603 sndh.offset = data_offset - sound_data_start;
1605 org_offset = ftell(ham_fp);
1606 fseek( ham_fp, data_offset, SEEK_SET );
1608 sndh.data_length = GameSounds[i].length;
1609 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1610 data_offset += snd->length;
1611 fseek( ham_fp, org_offset, SEEK_SET );
1612 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1614 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1615 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1619 mprintf( (0, "\n" ));
1622 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1623 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1624 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1629 // Never allow the game to run after building ham.
1643 d_free( SoundBits );
1645 hashtable_free( &AllBitmapsNames );
1646 hashtable_free( &AllDigiSndNames );
1650 int piggy_does_bitmap_exist_slow( char * name )
1654 for (i=0; i<Num_bitmap_files; i++ ) {
1655 if ( !strcmp( AllBitmaps[i].name, name) )
1662 #define NUM_GAUGE_BITMAPS 23
1663 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1664 "gauge01", "gauge01b",
1665 "gauge02", "gauge02b",
1666 "gauge06", "gauge06b",
1667 "targ01", "targ01b",
1668 "targ02", "targ02b",
1669 "targ03", "targ03b",
1670 "targ04", "targ04b",
1671 "targ05", "targ05b",
1672 "targ06", "targ06b",
1673 "gauge18", "gauge18b",
1679 int piggy_is_gauge_bitmap( char * base_name )
1682 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1683 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1690 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1694 char base_name[ 16 ];
1696 strcpy( subst_name, name );
1697 p = strchr( subst_name, '#' );
1699 frame = atoi( &p[1] );
1701 strcpy( base_name, subst_name );
1702 if ( !piggy_is_gauge_bitmap( base_name )) {
1703 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1704 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1706 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1712 strcpy( subst_name, name );
1719 // New Windows stuff
1721 // windows bitmap page in
1722 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1723 // 'video' memory. if that fails, page it in normally.
1725 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1730 // Essential when switching video modes!
1732 void piggy_bitmap_page_out_all_w()