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.
16 static char rcsid[] = "$Id: piggy.c,v 1.1.1.1 2001-01-19 03:30:02 bradleyb Exp $";
55 #include <Strings.h> // MacOS Toolbox header
60 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
62 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
63 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
67 #define DEFAULT_HAMFILE "d2demo.ham"
68 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_SHAREWARE
69 #define DEFAULT_SNDFILE "descent2.s11"
71 #define DEFAULT_HAMFILE "descent2.ham"
72 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_REGISTERED
73 #define DEFAULT_SNDFILE ((digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
74 #endif // end of ifdef SHAREWARE
76 ubyte *BitmapBits = NULL;
77 ubyte *SoundBits = NULL;
79 typedef struct BitmapFile {
83 typedef struct SoundFile {
87 hashtable AllBitmapsNames;
88 hashtable AllDigiSndNames;
90 int Num_bitmap_files = 0;
91 int Num_sound_files = 0;
93 digi_sound GameSounds[MAX_SOUND_FILES];
94 int SoundOffset[MAX_SOUND_FILES];
95 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
97 alias alias_list[MAX_ALIASES];
100 int Must_write_hamfile = 0;
101 int Num_bitmap_files_new = 0;
102 int Num_sound_files_new = 0;
103 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
104 static SoundFile AllSounds[ MAX_SOUND_FILES ];
106 int piggy_low_memory = 0;
108 int Piggy_bitmap_cache_size = 0;
109 int Piggy_bitmap_cache_next = 0;
110 ubyte * Piggy_bitmap_cache_data = NULL;
111 static int GameBitmapOffset[MAX_BITMAP_FILES];
112 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
113 ushort GameBitmapXlat[MAX_BITMAP_FILES];
115 #define PIGGY_BUFFER_SIZE (2400*1024)
118 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
121 #undef PIGGY_BUFFER_SIZE
122 #undef PIGGY_SMALL_BUFFER_SIZE
124 #define PIGGY_BUFFER_SIZE (2000*1024)
125 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
130 int piggy_page_flushed = 0;
132 #define DBM_FLAG_ABM 64
134 typedef struct DiskBitmapHeader {
136 ubyte dflags; //bits 0-5 anim frame num, bit 6 abm flag
137 ubyte width; //low 8 bits here, 4 more bits in wh_extra
138 ubyte height; //low 8 bits here, 4 more bits in wh_extra
139 ubyte wh_extra; //bits 0-3 width, bits 4-7 height
143 } __pack__ DiskBitmapHeader;
145 typedef struct DiskSoundHeader {
150 } __pack__ DiskSoundHeader;
155 extern short cd_VRefNum;
156 extern void ConcatPStr(StringPtr dst, StringPtr src);
157 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
158 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
162 void swap_0_255(grs_bitmap *bmp)
166 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
167 if(bmp->bm_data[i] == 0)
168 bmp->bm_data[i] = 255;
169 else if (bmp->bm_data[i] == 255)
175 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
178 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
180 temp.index = Num_bitmap_files;
184 if ( args_find("-macdata") )
187 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
188 Num_bitmap_files_new++;
191 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
192 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
193 GameBitmaps[Num_bitmap_files] = *bmp;
195 GameBitmapOffset[Num_bitmap_files] = 0;
196 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
203 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
207 Assert( Num_sound_files < MAX_SOUND_FILES );
209 strncpy( AllSounds[Num_sound_files].name, name, 12 );
210 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
211 GameSounds[Num_sound_files] = *snd;
213 SoundOffset[Num_sound_files] = 0;
219 Num_sound_files_new++;
225 bitmap_index piggy_find_bitmap( char * name )
233 if ((t=strchr(name,'#'))!=NULL)
236 for (i=0;i<Num_aliases;i++)
237 if (stricmp(name,alias_list[i].alias_name)==0) {
238 if (t) { //extra stuff for ABMs
239 static char temp[FILENAME_LEN];
240 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
246 name=alias_list[i].file_name;
253 i = hashtable_search( &AllBitmapsNames, name );
262 int piggy_find_sound( char * name )
266 i = hashtable_search( &AllDigiSndNames, name );
274 CFILE * Piggy_fp = NULL;
276 #define FILENAME_LEN 13
278 char Current_pigfile[FILENAME_LEN] = "";
280 void piggy_close_file()
285 Current_pigfile[0] = 0;
289 int Pigfile_initialized=0;
291 #define PIGFILE_ID "PPIG" //PPIG
292 #define PIGFILE_VERSION 2
294 extern char CDROM_dir[];
296 int request_cd(void);
301 //copies a pigfile from the CD to the current dir
302 //retuns file handle of new pig
303 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
306 char sourcePathAndFileCStr[255] = "";
307 char destPathAndFileCStr[255] = "";
309 FILE* sourceFile = NULL;
310 FILE* destFile = NULL;
311 const int BUF_SIZE = 4096;
315 Str255 sourcePathAndFilePStr = "\p";
316 Str255 destPathAndFilePStr = "\p";
317 Str255 pigfileNamePStr = "\p";
318 HParamBlockRec theSourcePigHFSParams;
319 HParamBlockRec theDestPigHFSParams;
320 OSErr theErr = noErr;
321 char oldDirCStr[255] = "";
323 getcwd(oldDirCStr, 255);
325 show_boxed_message("Copying bitmap data from CD...");
326 gr_palette_load(gr_palette); //I don't think this line is really needed
329 //First, delete all PIG files currently in the directory
330 if( !FileFindFirst( "*.pig", &find ) )
335 } while( !FileFindNext( &find ) );
341 //Now, copy over new pig
342 songs_stop_redbook(); //so we can read off the cd
344 // make the source path "<cd volume>:Data:filename.pig"
345 //MWA ConvertCToPStr(filename, pigfileNamePStr);
347 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
348 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
351 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
352 strcat(sourcePathAndFileCStr, filename);
354 // make the destination path "<default directory>:Data:filename.pig"
355 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
356 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
357 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
358 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
360 strcpy(destPathAndFileCStr, ":Data:");
361 strcat(destPathAndFileCStr, filename);
363 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
364 strcpy(destPathAndFilePStr, destPathAndFileCStr);
365 c2pstr(sourcePathAndFilePStr);
366 c2pstr(destPathAndFilePStr);
369 // Open the source file
370 sourceFile = fopen(sourcePathAndFileCStr,"rb");
374 if (request_cd() == -1)
375 Error("Cannot load file <%s> from CD",filename);
378 } while (!sourceFile);
381 // Get the time stamp from the source file
382 theSourcePigHFSParams.fileParam.ioCompletion = nil;
383 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
384 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
385 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
386 theSourcePigHFSParams.fileParam.ioDirID = 0;
388 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
391 // Error getting file time stamp!! Why? JTS
392 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
395 // Copy the file over
398 // Open the destination file
399 destFile = fopen(destPathAndFileCStr,"wb");
402 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
405 // Copy bytes until the end of the source file
406 while (!feof(sourceFile))
411 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
412 if (ferror(sourceFile))
413 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
415 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
417 fwrite(buf,1,bytes_read,destFile);
418 if (ferror(destFile))
419 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
422 // close the source/dest files
423 if (fclose(sourceFile))
424 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
425 if (fclose(destFile))
426 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
428 // Get the current hfs data for the new file
429 theDestPigHFSParams.fileParam.ioCompletion = nil;
430 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
431 theDestPigHFSParams.fileParam.ioVRefNum = 0;
432 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
433 theDestPigHFSParams.fileParam.ioDirID = 0;
434 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
435 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
437 // Error getting file time stamp!! Why? JTS
438 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
441 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
442 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
443 theDestPigHFSParams.fileParam.ioVRefNum = 0;
444 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
445 theDestPigHFSParams.fileParam.ioDirID = 0;
447 // Copy the time stamp from the source file info
448 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
449 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
450 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
451 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
453 // Set the dest file's time stamp to the source file's time stamp values
454 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
456 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
458 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
461 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
463 return cfopen(destPathAndFileCStr, "rb");
466 #else //PC Version of copy_pigfile_from_cd is below
468 //copies a pigfile from the CD to the current dir
469 //retuns file handle of new pig
470 CFILE *copy_pigfile_from_cd(char *filename)
476 return cfopen(filename, "rb");
477 show_boxed_message("Copying bitmap data from CD...");
478 gr_palette_load(gr_palette); //I don't think this line is really needed
480 //First, delete all PIG files currently in the directory
482 if( !FileFindFirst( "*.pig", &find ) ) {
485 } while( !FileFindNext( &find ) );
489 //Now, copy over new pig
491 songs_stop_redbook(); //so we can read off the cd
493 //new code to unarj file
494 strcpy(name,CDROM_dir);
495 strcat(name,"descent2.sow");
498 // ret = unarj_specific_file(name,filename,filename);
503 if (ret != EXIT_SUCCESS) {
505 //delete file, so we don't leave partial file
509 if (request_cd() == -1)
511 //NOTE LINK TO ABOVE IF
512 Error("Cannot load file <%s> from CD",filename);
515 } while (ret != EXIT_SUCCESS);
517 return cfopen(filename, "rb");
520 #endif // end of ifdef MAC around copy_pigfile_from_cd
522 //initialize a pigfile, reading headers
523 //returns the size of all the bitmap data
524 void piggy_init_pigfile(char *filename)
528 char temp_name_read[16];
529 grs_bitmap temp_bitmap;
530 DiskBitmapHeader bmh;
531 int header_size, N_bitmaps, data_size, data_start;
533 char name[255]; // filename + path for the mac
536 piggy_close_file(); //close old pig if still open
538 #ifdef SHAREWARE //rename pigfile for shareware
539 if (stricmp(filename,DEFAULT_PIGFILE_REGISTERED)==0)
540 filename = DEFAULT_PIGFILE_SHAREWARE;
544 Piggy_fp = cfopen( filename, "rb" );
546 sprintf(name, ":Data:%s", filename);
547 Piggy_fp = cfopen( name, "rb" );
549 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
550 if (Piggy_fp == NULL)
552 Error("Cannot load required file <%s>",name);
554 #endif // end of if def shareware
560 return; //if editor, ok to not have pig, because we'll build one
562 Piggy_fp = copy_pigfile_from_cd(filename);
566 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
570 cfread(&pig_id, 1, 4, Piggy_fp);
571 pig_version = cfile_read_int(Piggy_fp);
572 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
573 cfclose(Piggy_fp); //out of date pig
574 Piggy_fp = NULL; //..so pretend it's not here
581 return; //if editor, ok to not have pig, because we'll build one
583 Error("Cannot load required file <%s>",filename);
587 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
589 N_bitmaps = cfile_read_int(Piggy_fp);
591 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
593 data_start = header_size + cftell(Piggy_fp);
595 data_size = cfilelength(Piggy_fp) - data_start;
597 Num_bitmap_files = 1;
599 for (i=0; i<N_bitmaps; i++ ) {
601 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
603 cfread(bmh.name, 8, 1, Piggy_fp);
604 bmh.dflags = cfile_read_byte(Piggy_fp);
605 bmh.width = cfile_read_byte(Piggy_fp);
606 bmh.height = cfile_read_byte(Piggy_fp);
607 bmh.wh_extra = cfile_read_byte(Piggy_fp);
608 bmh.flags = cfile_read_byte(Piggy_fp);
609 bmh.avg_color = cfile_read_byte(Piggy_fp);
610 bmh.offset = cfile_read_int(Piggy_fp);
612 memcpy( temp_name_read, bmh.name, 8 );
613 temp_name_read[8] = 0;
614 if ( bmh.dflags & DBM_FLAG_ABM )
615 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
617 strcpy( temp_name, temp_name_read );
618 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
619 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
620 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
621 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
622 temp_bitmap.avg_color = bmh.avg_color;
623 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
625 GameBitmapFlags[i+1] = 0;
626 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
627 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
628 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
629 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
630 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
632 GameBitmapOffset[i+1] = bmh.offset + data_start;
633 Assert( (i+1) == Num_bitmap_files );
634 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
638 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
639 Assert( Piggy_bitmap_cache_size > 0 );
641 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
643 if (piggy_low_memory)
644 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
647 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
648 if ( BitmapBits == NULL )
649 Error( "Not enough memory to load bitmaps\n" );
650 Piggy_bitmap_cache_data = BitmapBits;
651 Piggy_bitmap_cache_next = 0;
653 #if defined(MACINTOSH) && defined(SHAREWARE)
654 // load_exit_models();
657 Pigfile_initialized=1;
660 #define FILENAME_LEN 13
661 #define MAX_BITMAPS_PER_BRUSH 30
663 extern int compute_average_pixel(grs_bitmap *new);
665 //reads in a new pigfile (for new palette)
666 //returns the size of all the bitmap data
667 void piggy_new_pigfile(char *pigname)
671 char temp_name_read[16];
672 grs_bitmap temp_bitmap;
673 DiskBitmapHeader bmh;
674 int header_size, N_bitmaps, data_size, data_start;
675 int must_rewrite_pig = 0;
682 #ifdef SHAREWARE //rename pigfile for shareware
683 if (stricmp(pigname,DEFAULT_PIGFILE_REGISTERED)==0)
684 pigname = DEFAULT_PIGFILE_SHAREWARE;
687 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
688 return; //already have correct pig
690 if (!Pigfile_initialized) { //have we ever opened a pigfile?
691 piggy_init_pigfile(pigname); //..no, so do initialization stuff
695 piggy_close_file(); //close old pig if still open
697 Piggy_bitmap_cache_next = 0; //free up cache
699 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
702 Piggy_fp = cfopen( pigname, "rb" );
704 sprintf(name, ":Data:%s", pigname);
705 Piggy_fp = cfopen( name, "rb" );
707 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
708 if (Piggy_fp == NULL)
710 Error("Cannot load required file <%s>",name);
712 #endif // end of if def shareware
717 Piggy_fp = copy_pigfile_from_cd(pigname);
720 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
724 cfread(&pig_id, 1, 4, Piggy_fp);
725 pig_version = cfile_read_int(Piggy_fp);
726 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
727 cfclose(Piggy_fp); //out of date pig
728 Piggy_fp = NULL; //..so pretend it's not here
733 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
738 N_bitmaps = cfile_read_int(Piggy_fp);
740 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
742 data_start = header_size + cftell(Piggy_fp);
744 data_size = cfilelength(Piggy_fp) - data_start;
746 for (i=1; i<=N_bitmaps; i++ ) {
748 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
750 cfread(bmh.name, 8, 1, Piggy_fp);
751 bmh.dflags = cfile_read_byte(Piggy_fp);
752 bmh.width = cfile_read_byte(Piggy_fp);
753 bmh.height = cfile_read_byte(Piggy_fp);
754 bmh.wh_extra = cfile_read_byte(Piggy_fp);
755 bmh.flags = cfile_read_byte(Piggy_fp);
756 bmh.avg_color = cfile_read_byte(Piggy_fp);
757 bmh.offset = cfile_read_int(Piggy_fp);
759 memcpy( temp_name_read, bmh.name, 8 );
760 temp_name_read[8] = 0;
762 if ( bmh.dflags & DBM_FLAG_ABM )
763 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
765 strcpy( temp_name, temp_name_read );
767 //Make sure name matches
768 if (strcmp(temp_name,AllBitmaps[i].name)) {
769 //Int3(); //this pig is out of date. Delete it
773 strcpy(AllBitmaps[i].name,temp_name);
775 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
777 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
778 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
779 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
780 temp_bitmap.avg_color = bmh.avg_color;
781 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
783 GameBitmapFlags[i] = 0;
785 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
786 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
787 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
788 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
789 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
791 GameBitmapOffset[i] = bmh.offset + data_start;
793 GameBitmaps[i] = temp_bitmap;
797 N_bitmaps = 0; //no pigfile, so no bitmaps
801 Assert(N_bitmaps == Num_bitmap_files-1);
805 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
808 //re-read the bitmaps that aren't in this pig
810 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
813 p = strchr(AllBitmaps[i].name,'#');
815 if (p) { //this is an ABM
816 char abmname[FILENAME_LEN];
818 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
819 int iff_error; //reference parm to avoid warning message
821 char basename[FILENAME_LEN];
824 strcpy(basename,AllBitmaps[i].name);
825 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
827 sprintf( abmname, "%s.abm", basename );
829 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
831 if (iff_error != IFF_NO_ERROR) {
832 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
833 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
836 for (fnum=0;fnum<nframes; fnum++) {
840 sprintf( tempname, "%s#%d", basename, fnum );
842 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
843 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
844 //above makes assumption that supertransparent color is 254
846 if ( iff_has_transparency )
847 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
849 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
851 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
854 if ( args_find("-macdata") )
855 swap_0_255( bm[fnum] );
857 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
859 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
860 size = *((int *) bm[fnum]->bm_data);
862 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
864 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
865 d_free(bm[fnum]->bm_data);
866 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
867 Piggy_bitmap_cache_next += size;
869 GameBitmaps[i+fnum] = *bm[fnum];
871 // -- mprintf( (0, "U" ));
875 i += nframes-1; //filled in multiple bitmaps
877 else { //this is a BBM
882 char bbmname[FILENAME_LEN];
885 MALLOC( new, grs_bitmap, 1 );
887 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
888 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
891 if (iff_error != IFF_NO_ERROR) {
892 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
893 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
896 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
897 //above makes assumption that supertransparent color is 254
899 if ( iff_has_transparency )
900 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
902 gr_remap_bitmap_good( new, newpal, -1, SuperX );
904 new->avg_color = compute_average_pixel(new);
907 if ( args_find("-macdata") )
910 if ( !BigPig ) gr_bitmap_rle_compress( new );
912 if (new->bm_flags & BM_FLAG_RLE)
913 size = *((int *) new->bm_data);
915 size = new->bm_w * new->bm_h;
917 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
918 d_free(new->bm_data);
919 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
920 Piggy_bitmap_cache_next += size;
922 GameBitmaps[i] = *new;
926 // -- mprintf( (0, "U" ));
930 //@@Dont' do these things which are done when writing
931 //@@for (i=0; i < Num_bitmap_files; i++ ) {
932 //@@ bitmap_index bi;
934 //@@ PIGGY_PAGE_IN( bi );
937 //@@piggy_close_file();
939 piggy_write_pigfile(pigname);
941 Current_pigfile[0] = 0; //say no pig, to force reload
943 piggy_new_pigfile(pigname); //read in just-generated pig
947 #endif //ifdef EDITOR
951 ubyte bogus_data[64*64];
952 grs_bitmap bogus_bitmap;
953 ubyte bogus_bitmap_initialized=0;
954 digi_sound bogus_sound;
956 extern void bm_read_all(CFILE * fp);
958 #define HAMFILE_ID "HAM!" //HAM!
959 #define HAMFILE_VERSION 3
960 //version 1 -> 2: save marker_model_num
961 //version 2 -> 3: removed sound files
963 #define SNDFILE_ID "DSND" //DSND
964 #define SNDFILE_VERSION 1
968 CFILE * ham_fp = NULL;
976 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
978 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
979 ham_fp = cfopen( name, "rb" );
982 if (ham_fp == NULL) {
983 Must_write_hamfile = 1;
987 //make sure ham is valid type file & is up-to-date
988 cfread( &ham_id, 1, 4, ham_fp );
989 ham_version = cfile_read_int(ham_fp);
990 if (memcmp(ham_id, HAMFILE_ID, 4) || ham_version != HAMFILE_VERSION) {
991 Must_write_hamfile = 1;
992 cfclose(ham_fp); //out of date ham
998 bm_read_all( ham_fp ); // Note connection to above if!!!
999 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1004 for (i = 0; i < MAX_BITMAP_FILES; i++)
1005 GameBitmapXlat[i] = SWAPSHORT(GameBitmapXlat[i]);
1019 CFILE * snd_fp = NULL;
1026 DiskSoundHeader sndh;
1027 digi_sound temp_sound;
1028 char temp_name_read[16];
1035 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1037 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1038 snd_fp = cfopen( name, "rb");
1044 //make sure soundfile is valid type file & is up-to-date
1045 cfread( &snd_id, 1, 4, snd_fp );
1046 snd_version = cfile_read_int(snd_fp);
1047 if (memcmp(snd_id, SNDFILE_ID, 4) || snd_version != SNDFILE_VERSION) {
1048 cfclose(snd_fp); //out of date sound file
1052 N_sounds = cfile_read_int(snd_fp);
1054 sound_start = cftell(snd_fp);
1055 size = cfilelength(snd_fp) - sound_start;
1057 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1059 header_size = N_sounds*sizeof(DiskSoundHeader);
1063 for (i=0; i<N_sounds; i++ ) {
1064 cfread( sndh.name, 8, 1, snd_fp);
1065 sndh.length = cfile_read_int(snd_fp);
1066 sndh.data_length = cfile_read_int(snd_fp);
1067 sndh.offset = cfile_read_int(snd_fp);
1068 // cfread( &sndh, sizeof(DiskSoundHeader), 1, snd_fp );
1069 //size -= sizeof(DiskSoundHeader);
1070 temp_sound.length = sndh.length;
1071 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1072 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1073 memcpy( temp_name_read, sndh.name, 8 );
1074 temp_name_read[8] = 0;
1075 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1077 if (piggy_is_needed(i))
1078 #endif // note link to if.
1079 sbytes += sndh.length;
1080 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1083 SoundBits = d_malloc( sbytes + 16 );
1084 if ( SoundBits == NULL )
1085 Error( "Not enough memory to load sounds\n" );
1087 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1089 // piggy_read_sounds(snd_fp);
1096 int piggy_init(void)
1098 int ham_ok=0,snd_ok=0;
1101 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1102 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1104 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1105 GameSounds[i].length = 0;
1106 GameSounds[i].data = NULL;
1110 for (i=0; i<MAX_BITMAP_FILES; i++ )
1111 GameBitmapXlat[i] = i;
1113 if ( !bogus_bitmap_initialized ) {
1116 bogus_bitmap_initialized = 1;
1117 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1118 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1119 bogus_bitmap.bm_data = bogus_data;
1120 c = gr_find_closest_color( 0, 0, 63 );
1121 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1122 c = gr_find_closest_color( 63, 0, 0 );
1123 // Make a big red X !
1124 for (i=0; i<64; i++ ) {
1125 bogus_data[i*64+i] = c;
1126 bogus_data[i*64+(63-i)] = c;
1128 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1129 bogus_sound.length = 64*64;
1130 bogus_sound.data = bogus_data;
1131 GameBitmapOffset[0] = 0;
1134 if ( args_find( "-bigpig" ))
1137 if ( args_find( "-lowmem" ))
1138 piggy_low_memory = 1;
1140 if ( args_find( "-nolowmem" ))
1141 piggy_low_memory = 0;
1143 if (piggy_low_memory)
1146 WIN(DDGRLOCK(dd_grd_curcanv));
1147 gr_set_curfont( SMALL_FONT );
1148 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1149 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1150 WIN(DDGRUNLOCK(dd_grd_curcanv));
1153 piggy_init_pigfile(DEFAULT_PIGFILE);
1156 ham_ok = read_hamfile();
1158 snd_ok = read_sndfile();
1160 atexit(piggy_close);
1162 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1163 return (ham_ok && snd_ok); //read ok
1166 int piggy_is_needed(int soundnum)
1170 if ( !digi_lomem ) return 1;
1172 for (i=0; i<MAX_SOUNDS; i++ ) {
1173 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1180 void piggy_read_sounds(void)
1193 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1195 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1196 fp = cfopen( name, "rb");
1202 for (i=0; i<Num_sound_files; i++ ) {
1203 digi_sound *snd = &GameSounds[i];
1205 if ( SoundOffset[i] > 0 ) {
1206 if ( piggy_is_needed(i) ) {
1207 cfseek( fp, SoundOffset[i], SEEK_SET );
1209 // Read in the sound data!!!
1212 sbytes += snd->length;
1213 cfread( snd->data, snd->length, 1, fp );
1216 snd->data = (ubyte *) -1;
1222 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1227 extern int descent_critical_error;
1228 extern unsigned descent_critical_deverror;
1229 extern unsigned descent_critical_errcode;
1231 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1232 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1233 "Read fault", "General Failure" };
1235 void piggy_critical_error()
1237 grs_canvas * save_canv;
1238 grs_font * save_font;
1240 save_canv = grd_curcanv;
1241 save_font = grd_curcanv->cv_font;
1242 gr_palette_load( gr_palette );
1243 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1246 gr_set_current_canvas(save_canv);
1247 grd_curcanv->cv_font = save_font;
1250 void piggy_bitmap_page_in( bitmap_index bitmap )
1257 Assert( i < MAX_BITMAP_FILES );
1258 Assert( i < Num_bitmap_files );
1259 Assert( Piggy_bitmap_cache_size > 0 );
1261 if ( i < 1 ) return;
1262 if ( i >= MAX_BITMAP_FILES ) return;
1263 if ( i >= Num_bitmap_files ) return;
1265 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1267 if ( piggy_low_memory ) {
1269 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1272 bmp = &GameBitmaps[i];
1274 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1278 descent_critical_error = 0;
1279 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1280 if ( descent_critical_error ) {
1281 piggy_critical_error();
1285 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1286 bmp->bm_flags = GameBitmapFlags[i];
1288 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1290 descent_critical_error = 0;
1291 zsize = cfile_read_int(Piggy_fp);
1292 if ( descent_critical_error ) {
1293 piggy_critical_error();
1297 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1298 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1299 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1301 piggy_bitmap_page_out_all();
1304 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1305 Piggy_bitmap_cache_next += sizeof(int);
1306 descent_critical_error = 0;
1307 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1308 if ( descent_critical_error ) {
1309 piggy_critical_error();
1312 Piggy_bitmap_cache_next += zsize-4;
1314 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1315 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1316 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1317 piggy_bitmap_page_out_all();
1320 descent_critical_error = 0;
1321 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1322 if ( descent_critical_error ) {
1323 piggy_critical_error();
1326 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1329 //@@if ( bmp->bm_selector ) {
1330 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1331 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1332 //@@ Error( "Error modifying selector base in piggy.c\n" );
1339 if ( piggy_low_memory ) {
1341 GameBitmaps[org_i] = GameBitmaps[i];
1344 //@@Removed from John's code:
1346 //@@ if ( bmp->bm_selector ) {
1347 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1348 //@@ Error( "Error modifying selector base in piggy.c\n" );
1354 void piggy_bitmap_page_out_all()
1358 Piggy_bitmap_cache_next = 0;
1360 piggy_page_flushed++;
1365 for (i=0; i<Num_bitmap_files; i++ ) {
1366 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1367 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1368 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1372 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1375 void piggy_load_level_data()
1377 piggy_bitmap_page_out_all();
1383 void change_filename_ext( char *dest, char *src, char *ext );
1385 void piggy_write_pigfile(char *filename)
1388 int bitmap_data_start,data_offset;
1389 DiskBitmapHeader bmh;
1391 char subst_name[32];
1394 char tname[FILENAME_LEN];
1396 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1397 for (i=0; i < Num_bitmap_files; i++ ) {
1400 PIGGY_PAGE_IN( bi );
1402 // -- mprintf( (0, "\n" ));
1406 // -- mprintf( (0, "Creating %s...",filename ));
1408 pig_fp = fopen( filename, "wb" ); //open PIG file
1409 Assert( pig_fp!=NULL );
1411 write_int(PIGFILE_ID,pig_fp);
1412 write_int(PIGFILE_VERSION,pig_fp);
1415 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1418 bitmap_data_start = ftell(pig_fp);
1419 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1420 data_offset = bitmap_data_start;
1422 change_filename_ext(tname,filename,"lst");
1423 fp1 = fopen( tname, "wt" );
1424 change_filename_ext(tname,filename,"all");
1425 fp2 = fopen( tname, "wt" );
1427 for (i=1; i < Num_bitmap_files; i++ ) {
1433 p = strchr(AllBitmaps[i].name,'#');
1440 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1441 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1443 bmh.dflags = DBM_FLAG_ABM + n;
1447 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1448 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1452 bmp = &GameBitmaps[i];
1454 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1457 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1458 org_offset = ftell(pig_fp);
1459 bmh.offset = data_offset - bitmap_data_start;
1460 fseek( pig_fp, data_offset, SEEK_SET );
1462 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1463 size = (int *)bmp->bm_data;
1464 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1465 data_offset += *size;
1467 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1469 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1470 data_offset += bmp->bm_rowsize * bmp->bm_h;
1472 fprintf( fp1, ".\n" );
1474 fseek( pig_fp, org_offset, SEEK_SET );
1475 Assert( GameBitmaps[i].bm_w < 4096 );
1476 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1477 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1478 Assert( GameBitmaps[i].bm_h < 4096 );
1479 bmh.height = GameBitmaps[i].bm_h;
1480 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1481 bmh.flags = GameBitmaps[i].bm_flags;
1482 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1483 bitmap_index other_bitmap;
1484 other_bitmap = piggy_find_bitmap( subst_name );
1485 GameBitmapXlat[i] = other_bitmap.index;
1486 bmh.flags |= BM_FLAG_PAGED_OUT;
1487 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1488 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1490 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1492 bmh.avg_color=GameBitmaps[i].avg_color;
1493 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1498 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1499 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1506 static void write_int(int i,FILE *file)
1508 if (fwrite( &i, sizeof(i), 1, file) != 1)
1509 Error( "Error reading int in gamesave.c" );
1513 void piggy_dump_all()
1517 int org_offset,data_offset;
1518 DiskSoundHeader sndh;
1519 int sound_data_start;
1522 #ifdef NO_DUMP_SOUNDS
1523 Num_sound_files = 0;
1524 Num_sound_files_new = 0;
1527 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1530 fp1 = fopen( "ham.lst", "wt" );
1531 fp2 = fopen( "ham.all", "wt" );
1533 if (Must_write_hamfile || Num_bitmap_files_new) {
1535 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1537 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1538 Assert( ham_fp!=NULL );
1540 write_int(HAMFILE_ID,ham_fp);
1541 write_int(HAMFILE_VERSION,ham_fp);
1543 bm_write_all(ham_fp);
1544 xlat_offset = ftell(ham_fp);
1545 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1548 if (Num_bitmap_files_new)
1549 piggy_write_pigfile(DEFAULT_PIGFILE);
1551 //free up memeory used by new bitmaps
1552 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1553 d_free(GameBitmaps[i].bm_data);
1555 //next thing must be done after pig written
1556 fseek( ham_fp, xlat_offset, SEEK_SET );
1557 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1560 mprintf( (0, "\n" ));
1563 if (Num_sound_files_new) {
1565 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1566 // Now dump sound file
1567 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1568 Assert( ham_fp!=NULL );
1570 write_int(SNDFILE_ID,ham_fp);
1571 write_int(SNDFILE_VERSION,ham_fp);
1573 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1575 mprintf( (0, "\nDumping sounds..." ));
1577 sound_data_start = ftell(ham_fp);
1578 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1579 data_offset = sound_data_start;
1581 for (i=0; i < Num_sound_files; i++ ) {
1584 snd = &GameSounds[i];
1585 strcpy( sndh.name, AllSounds[i].name );
1586 sndh.length = GameSounds[i].length;
1587 sndh.offset = data_offset - sound_data_start;
1589 org_offset = ftell(ham_fp);
1590 fseek( ham_fp, data_offset, SEEK_SET );
1592 sndh.data_length = GameSounds[i].length;
1593 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1594 data_offset += snd->length;
1595 fseek( ham_fp, org_offset, SEEK_SET );
1596 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1598 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1599 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1603 mprintf( (0, "\n" ));
1606 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1607 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1608 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1613 // Never allow the game to run after building ham.
1627 d_free( SoundBits );
1629 hashtable_free( &AllBitmapsNames );
1630 hashtable_free( &AllDigiSndNames );
1634 int piggy_does_bitmap_exist_slow( char * name )
1638 for (i=0; i<Num_bitmap_files; i++ ) {
1639 if ( !strcmp( AllBitmaps[i].name, name) )
1646 #define NUM_GAUGE_BITMAPS 23
1647 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1648 "gauge01", "gauge01b",
1649 "gauge02", "gauge02b",
1650 "gauge06", "gauge06b",
1651 "targ01", "targ01b",
1652 "targ02", "targ02b",
1653 "targ03", "targ03b",
1654 "targ04", "targ04b",
1655 "targ05", "targ05b",
1656 "targ06", "targ06b",
1657 "gauge18", "gauge18b",
1663 int piggy_is_gauge_bitmap( char * base_name )
1666 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1667 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1674 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1678 char base_name[ 16 ];
1680 strcpy( subst_name, name );
1681 p = strchr( subst_name, '#' );
1683 frame = atoi( &p[1] );
1685 strcpy( base_name, subst_name );
1686 if ( !piggy_is_gauge_bitmap( base_name )) {
1687 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1688 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1690 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1696 strcpy( subst_name, name );
1703 // New Windows stuff
1705 // windows bitmap page in
1706 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1707 // 'video' memory. if that fails, page it in normally.
1709 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1714 // Essential when switching video modes!
1716 void piggy_bitmap_page_out_all_w()