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.5 2001-10-25 02:19:31 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!
966 #define HAMFILE_VERSION 3
967 //version 1 -> 2: save marker_model_num
968 //version 2 -> 3: removed sound files
970 #define SNDFILE_ID "DSND" //DSND
971 #define SNDFILE_VERSION 1
975 CFILE * ham_fp = NULL;
983 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
985 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
986 ham_fp = cfopen( name, "rb" );
989 if (ham_fp == NULL) {
990 Must_write_hamfile = 1;
994 //make sure ham is valid type file & is up-to-date
995 cfread( &ham_id, 1, 4, ham_fp );
996 ham_version = cfile_read_int(ham_fp);
997 if (memcmp(ham_id, HAMFILE_ID, 4) || ham_version != HAMFILE_VERSION) {
998 Must_write_hamfile = 1;
999 cfclose(ham_fp); //out of date ham
1005 bm_read_all( ham_fp ); // Note connection to above if!!!
1006 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1011 for (i = 0; i < MAX_BITMAP_FILES; i++)
1012 GameBitmapXlat[i] = SWAPSHORT(GameBitmapXlat[i]);
1026 CFILE * snd_fp = NULL;
1033 DiskSoundHeader sndh;
1034 digi_sound temp_sound;
1035 char temp_name_read[16];
1042 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1044 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1045 snd_fp = cfopen( name, "rb");
1051 //make sure soundfile is valid type file & is up-to-date
1052 cfread( &snd_id, 1, 4, snd_fp );
1053 snd_version = cfile_read_int(snd_fp);
1054 if (memcmp(snd_id, SNDFILE_ID, 4) || snd_version != SNDFILE_VERSION) {
1055 cfclose(snd_fp); //out of date sound file
1059 N_sounds = cfile_read_int(snd_fp);
1061 sound_start = cftell(snd_fp);
1062 size = cfilelength(snd_fp) - sound_start;
1064 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1066 header_size = N_sounds*sizeof(DiskSoundHeader);
1070 for (i=0; i<N_sounds; i++ ) {
1071 cfread( sndh.name, 8, 1, snd_fp);
1072 sndh.length = cfile_read_int(snd_fp);
1073 sndh.data_length = cfile_read_int(snd_fp);
1074 sndh.offset = cfile_read_int(snd_fp);
1075 // cfread( &sndh, sizeof(DiskSoundHeader), 1, 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 ham_ok = read_hamfile();
1165 snd_ok = read_sndfile();
1167 atexit(piggy_close);
1169 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1170 return (ham_ok && snd_ok); //read ok
1173 int piggy_is_needed(int soundnum)
1177 if ( !digi_lomem ) return 1;
1179 for (i=0; i<MAX_SOUNDS; i++ ) {
1180 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1187 void piggy_read_sounds(void)
1200 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1202 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1203 fp = cfopen( name, "rb");
1209 for (i=0; i<Num_sound_files; i++ ) {
1210 digi_sound *snd = &GameSounds[i];
1212 if ( SoundOffset[i] > 0 ) {
1213 if ( piggy_is_needed(i) ) {
1214 cfseek( fp, SoundOffset[i], SEEK_SET );
1216 // Read in the sound data!!!
1219 sbytes += snd->length;
1220 cfread( snd->data, snd->length, 1, fp );
1223 snd->data = (ubyte *) -1;
1229 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1234 extern int descent_critical_error;
1235 extern unsigned descent_critical_deverror;
1236 extern unsigned descent_critical_errcode;
1238 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1239 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1240 "Read fault", "General Failure" };
1242 void piggy_critical_error()
1244 grs_canvas * save_canv;
1245 grs_font * save_font;
1247 save_canv = grd_curcanv;
1248 save_font = grd_curcanv->cv_font;
1249 gr_palette_load( gr_palette );
1250 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1253 gr_set_current_canvas(save_canv);
1254 grd_curcanv->cv_font = save_font;
1257 void piggy_bitmap_page_in( bitmap_index bitmap )
1266 Assert( i < MAX_BITMAP_FILES );
1267 Assert( i < Num_bitmap_files );
1268 Assert( Piggy_bitmap_cache_size > 0 );
1270 if ( i < 1 ) return;
1271 if ( i >= MAX_BITMAP_FILES ) return;
1272 if ( i >= Num_bitmap_files ) return;
1274 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1276 if ( piggy_low_memory ) {
1278 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1281 bmp = &GameBitmaps[i];
1283 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1287 descent_critical_error = 0;
1288 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1289 if ( descent_critical_error ) {
1290 piggy_critical_error();
1294 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1295 bmp->bm_flags = GameBitmapFlags[i];
1297 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1299 descent_critical_error = 0;
1300 zsize = cfile_read_int(Piggy_fp);
1301 if ( descent_critical_error ) {
1302 piggy_critical_error();
1306 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1307 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1308 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1310 piggy_bitmap_page_out_all();
1313 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1314 Piggy_bitmap_cache_next += sizeof(int);
1315 descent_critical_error = 0;
1316 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1317 if ( descent_critical_error ) {
1318 piggy_critical_error();
1321 Piggy_bitmap_cache_next += zsize-4;
1323 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1324 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1325 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1326 piggy_bitmap_page_out_all();
1329 descent_critical_error = 0;
1330 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1331 if ( descent_critical_error ) {
1332 piggy_critical_error();
1335 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1338 //@@if ( bmp->bm_selector ) {
1339 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1340 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1341 //@@ Error( "Error modifying selector base in piggy.c\n" );
1348 if ( piggy_low_memory ) {
1350 GameBitmaps[org_i] = GameBitmaps[i];
1353 //@@Removed from John's code:
1355 //@@ if ( bmp->bm_selector ) {
1356 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1357 //@@ Error( "Error modifying selector base in piggy.c\n" );
1363 void piggy_bitmap_page_out_all()
1367 Piggy_bitmap_cache_next = 0;
1369 piggy_page_flushed++;
1374 for (i=0; i<Num_bitmap_files; i++ ) {
1375 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1376 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1377 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1381 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1384 void piggy_load_level_data()
1386 piggy_bitmap_page_out_all();
1392 void change_filename_ext( char *dest, char *src, char *ext );
1394 void piggy_write_pigfile(char *filename)
1397 int bitmap_data_start,data_offset;
1398 DiskBitmapHeader bmh;
1400 char subst_name[32];
1403 char tname[FILENAME_LEN];
1405 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1406 for (i=0; i < Num_bitmap_files; i++ ) {
1409 PIGGY_PAGE_IN( bi );
1411 // -- mprintf( (0, "\n" ));
1415 // -- mprintf( (0, "Creating %s...",filename ));
1417 pig_fp = fopen( filename, "wb" ); //open PIG file
1418 Assert( pig_fp!=NULL );
1420 write_int((int)PIGFILE_ID,pig_fp);
1421 write_int(PIGFILE_VERSION,pig_fp);
1424 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1427 bitmap_data_start = ftell(pig_fp);
1428 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1429 data_offset = bitmap_data_start;
1431 change_filename_ext(tname,filename,"lst");
1432 fp1 = fopen( tname, "wt" );
1433 change_filename_ext(tname,filename,"all");
1434 fp2 = fopen( tname, "wt" );
1436 for (i=1; i < Num_bitmap_files; i++ ) {
1442 p = strchr(AllBitmaps[i].name,'#');
1449 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1450 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1452 bmh.dflags = DBM_FLAG_ABM + n;
1456 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1457 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1461 bmp = &GameBitmaps[i];
1463 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1466 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1467 org_offset = ftell(pig_fp);
1468 bmh.offset = data_offset - bitmap_data_start;
1469 fseek( pig_fp, data_offset, SEEK_SET );
1471 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1472 size = (int *)bmp->bm_data;
1473 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1474 data_offset += *size;
1476 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1478 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1479 data_offset += bmp->bm_rowsize * bmp->bm_h;
1481 fprintf( fp1, ".\n" );
1483 fseek( pig_fp, org_offset, SEEK_SET );
1484 Assert( GameBitmaps[i].bm_w < 4096 );
1485 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1486 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1487 Assert( GameBitmaps[i].bm_h < 4096 );
1488 bmh.height = GameBitmaps[i].bm_h;
1489 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1490 bmh.flags = GameBitmaps[i].bm_flags;
1491 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1492 bitmap_index other_bitmap;
1493 other_bitmap = piggy_find_bitmap( subst_name );
1494 GameBitmapXlat[i] = other_bitmap.index;
1495 bmh.flags |= BM_FLAG_PAGED_OUT;
1496 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1497 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1499 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1501 bmh.avg_color=GameBitmaps[i].avg_color;
1502 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1507 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1508 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1515 static void write_int(int i,FILE *file)
1517 if (fwrite( &i, sizeof(i), 1, file) != 1)
1518 Error( "Error reading int in gamesave.c" );
1522 void piggy_dump_all()
1526 int org_offset,data_offset=0;
1527 DiskSoundHeader sndh;
1528 int sound_data_start=0;
1531 #ifdef NO_DUMP_SOUNDS
1532 Num_sound_files = 0;
1533 Num_sound_files_new = 0;
1536 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1539 fp1 = fopen( "ham.lst", "wt" );
1540 fp2 = fopen( "ham.all", "wt" );
1542 if (Must_write_hamfile || Num_bitmap_files_new) {
1544 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1546 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1547 Assert( ham_fp!=NULL );
1549 write_int((int)HAMFILE_ID,ham_fp);
1550 write_int(HAMFILE_VERSION,ham_fp);
1552 bm_write_all(ham_fp);
1553 xlat_offset = ftell(ham_fp);
1554 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1557 if (Num_bitmap_files_new)
1558 piggy_write_pigfile(DEFAULT_PIGFILE);
1560 //free up memeory used by new bitmaps
1561 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1562 d_free(GameBitmaps[i].bm_data);
1564 //next thing must be done after pig written
1565 fseek( ham_fp, xlat_offset, SEEK_SET );
1566 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1569 mprintf( (0, "\n" ));
1572 if (Num_sound_files_new) {
1574 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1575 // Now dump sound file
1576 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1577 Assert( ham_fp!=NULL );
1579 write_int((int)SNDFILE_ID,ham_fp);
1580 write_int(SNDFILE_VERSION,ham_fp);
1582 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1584 mprintf( (0, "\nDumping sounds..." ));
1586 sound_data_start = ftell(ham_fp);
1587 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1588 data_offset = sound_data_start;
1590 for (i=0; i < Num_sound_files; i++ ) {
1593 snd = &GameSounds[i];
1594 strcpy( sndh.name, AllSounds[i].name );
1595 sndh.length = GameSounds[i].length;
1596 sndh.offset = data_offset - sound_data_start;
1598 org_offset = ftell(ham_fp);
1599 fseek( ham_fp, data_offset, SEEK_SET );
1601 sndh.data_length = GameSounds[i].length;
1602 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1603 data_offset += snd->length;
1604 fseek( ham_fp, org_offset, SEEK_SET );
1605 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1607 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1608 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1612 mprintf( (0, "\n" ));
1615 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1616 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1617 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1622 // Never allow the game to run after building ham.
1636 d_free( SoundBits );
1638 hashtable_free( &AllBitmapsNames );
1639 hashtable_free( &AllDigiSndNames );
1643 int piggy_does_bitmap_exist_slow( char * name )
1647 for (i=0; i<Num_bitmap_files; i++ ) {
1648 if ( !strcmp( AllBitmaps[i].name, name) )
1655 #define NUM_GAUGE_BITMAPS 23
1656 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1657 "gauge01", "gauge01b",
1658 "gauge02", "gauge02b",
1659 "gauge06", "gauge06b",
1660 "targ01", "targ01b",
1661 "targ02", "targ02b",
1662 "targ03", "targ03b",
1663 "targ04", "targ04b",
1664 "targ05", "targ05b",
1665 "targ06", "targ06b",
1666 "gauge18", "gauge18b",
1672 int piggy_is_gauge_bitmap( char * base_name )
1675 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1676 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1683 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1687 char base_name[ 16 ];
1689 strcpy( subst_name, name );
1690 p = strchr( subst_name, '#' );
1692 frame = atoi( &p[1] );
1694 strcpy( base_name, subst_name );
1695 if ( !piggy_is_gauge_bitmap( base_name )) {
1696 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1697 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1699 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1705 strcpy( subst_name, name );
1712 // New Windows stuff
1714 // windows bitmap page in
1715 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1716 // 'video' memory. if that fails, page it in normally.
1718 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1723 // Essential when switching video modes!
1725 void piggy_bitmap_page_out_all_w()