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.2 2001-01-20 13:49:17 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 )
1259 Assert( i < MAX_BITMAP_FILES );
1260 Assert( i < Num_bitmap_files );
1261 Assert( Piggy_bitmap_cache_size > 0 );
1263 if ( i < 1 ) return;
1264 if ( i >= MAX_BITMAP_FILES ) return;
1265 if ( i >= Num_bitmap_files ) return;
1267 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1269 if ( piggy_low_memory ) {
1271 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1274 bmp = &GameBitmaps[i];
1276 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1280 descent_critical_error = 0;
1281 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1282 if ( descent_critical_error ) {
1283 piggy_critical_error();
1287 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1288 bmp->bm_flags = GameBitmapFlags[i];
1290 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1292 descent_critical_error = 0;
1293 zsize = cfile_read_int(Piggy_fp);
1294 if ( descent_critical_error ) {
1295 piggy_critical_error();
1299 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1300 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1301 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1303 piggy_bitmap_page_out_all();
1306 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1307 Piggy_bitmap_cache_next += sizeof(int);
1308 descent_critical_error = 0;
1309 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1310 if ( descent_critical_error ) {
1311 piggy_critical_error();
1314 Piggy_bitmap_cache_next += zsize-4;
1316 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1317 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1318 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1319 piggy_bitmap_page_out_all();
1322 descent_critical_error = 0;
1323 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1324 if ( descent_critical_error ) {
1325 piggy_critical_error();
1328 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1331 //@@if ( bmp->bm_selector ) {
1332 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1333 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1334 //@@ Error( "Error modifying selector base in piggy.c\n" );
1341 if ( piggy_low_memory ) {
1343 GameBitmaps[org_i] = GameBitmaps[i];
1346 //@@Removed from John's code:
1348 //@@ if ( bmp->bm_selector ) {
1349 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1350 //@@ Error( "Error modifying selector base in piggy.c\n" );
1356 void piggy_bitmap_page_out_all()
1360 Piggy_bitmap_cache_next = 0;
1362 piggy_page_flushed++;
1367 for (i=0; i<Num_bitmap_files; i++ ) {
1368 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1369 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1370 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1374 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1377 void piggy_load_level_data()
1379 piggy_bitmap_page_out_all();
1385 void change_filename_ext( char *dest, char *src, char *ext );
1387 void piggy_write_pigfile(char *filename)
1390 int bitmap_data_start,data_offset;
1391 DiskBitmapHeader bmh;
1393 char subst_name[32];
1396 char tname[FILENAME_LEN];
1398 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1399 for (i=0; i < Num_bitmap_files; i++ ) {
1402 PIGGY_PAGE_IN( bi );
1404 // -- mprintf( (0, "\n" ));
1408 // -- mprintf( (0, "Creating %s...",filename ));
1410 pig_fp = fopen( filename, "wb" ); //open PIG file
1411 Assert( pig_fp!=NULL );
1413 write_int(PIGFILE_ID,pig_fp);
1414 write_int(PIGFILE_VERSION,pig_fp);
1417 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1420 bitmap_data_start = ftell(pig_fp);
1421 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1422 data_offset = bitmap_data_start;
1424 change_filename_ext(tname,filename,"lst");
1425 fp1 = fopen( tname, "wt" );
1426 change_filename_ext(tname,filename,"all");
1427 fp2 = fopen( tname, "wt" );
1429 for (i=1; i < Num_bitmap_files; i++ ) {
1435 p = strchr(AllBitmaps[i].name,'#');
1442 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1443 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1445 bmh.dflags = DBM_FLAG_ABM + n;
1449 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1450 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1454 bmp = &GameBitmaps[i];
1456 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1459 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1460 org_offset = ftell(pig_fp);
1461 bmh.offset = data_offset - bitmap_data_start;
1462 fseek( pig_fp, data_offset, SEEK_SET );
1464 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1465 size = (int *)bmp->bm_data;
1466 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1467 data_offset += *size;
1469 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1471 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1472 data_offset += bmp->bm_rowsize * bmp->bm_h;
1474 fprintf( fp1, ".\n" );
1476 fseek( pig_fp, org_offset, SEEK_SET );
1477 Assert( GameBitmaps[i].bm_w < 4096 );
1478 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1479 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1480 Assert( GameBitmaps[i].bm_h < 4096 );
1481 bmh.height = GameBitmaps[i].bm_h;
1482 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1483 bmh.flags = GameBitmaps[i].bm_flags;
1484 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1485 bitmap_index other_bitmap;
1486 other_bitmap = piggy_find_bitmap( subst_name );
1487 GameBitmapXlat[i] = other_bitmap.index;
1488 bmh.flags |= BM_FLAG_PAGED_OUT;
1489 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1490 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1492 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1494 bmh.avg_color=GameBitmaps[i].avg_color;
1495 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1500 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1501 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1508 static void write_int(int i,FILE *file)
1510 if (fwrite( &i, sizeof(i), 1, file) != 1)
1511 Error( "Error reading int in gamesave.c" );
1515 void piggy_dump_all()
1519 int org_offset,data_offset;
1520 DiskSoundHeader sndh;
1521 int sound_data_start;
1524 #ifdef NO_DUMP_SOUNDS
1525 Num_sound_files = 0;
1526 Num_sound_files_new = 0;
1529 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1532 fp1 = fopen( "ham.lst", "wt" );
1533 fp2 = fopen( "ham.all", "wt" );
1535 if (Must_write_hamfile || Num_bitmap_files_new) {
1537 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1539 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1540 Assert( ham_fp!=NULL );
1542 write_int(HAMFILE_ID,ham_fp);
1543 write_int(HAMFILE_VERSION,ham_fp);
1545 bm_write_all(ham_fp);
1546 xlat_offset = ftell(ham_fp);
1547 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1550 if (Num_bitmap_files_new)
1551 piggy_write_pigfile(DEFAULT_PIGFILE);
1553 //free up memeory used by new bitmaps
1554 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1555 d_free(GameBitmaps[i].bm_data);
1557 //next thing must be done after pig written
1558 fseek( ham_fp, xlat_offset, SEEK_SET );
1559 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1562 mprintf( (0, "\n" ));
1565 if (Num_sound_files_new) {
1567 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1568 // Now dump sound file
1569 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1570 Assert( ham_fp!=NULL );
1572 write_int(SNDFILE_ID,ham_fp);
1573 write_int(SNDFILE_VERSION,ham_fp);
1575 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1577 mprintf( (0, "\nDumping sounds..." ));
1579 sound_data_start = ftell(ham_fp);
1580 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1581 data_offset = sound_data_start;
1583 for (i=0; i < Num_sound_files; i++ ) {
1586 snd = &GameSounds[i];
1587 strcpy( sndh.name, AllSounds[i].name );
1588 sndh.length = GameSounds[i].length;
1589 sndh.offset = data_offset - sound_data_start;
1591 org_offset = ftell(ham_fp);
1592 fseek( ham_fp, data_offset, SEEK_SET );
1594 sndh.data_length = GameSounds[i].length;
1595 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1596 data_offset += snd->length;
1597 fseek( ham_fp, org_offset, SEEK_SET );
1598 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1600 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1601 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1605 mprintf( (0, "\n" ));
1608 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1609 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1610 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1615 // Never allow the game to run after building ham.
1629 d_free( SoundBits );
1631 hashtable_free( &AllBitmapsNames );
1632 hashtable_free( &AllDigiSndNames );
1636 int piggy_does_bitmap_exist_slow( char * name )
1640 for (i=0; i<Num_bitmap_files; i++ ) {
1641 if ( !strcmp( AllBitmaps[i].name, name) )
1648 #define NUM_GAUGE_BITMAPS 23
1649 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1650 "gauge01", "gauge01b",
1651 "gauge02", "gauge02b",
1652 "gauge06", "gauge06b",
1653 "targ01", "targ01b",
1654 "targ02", "targ02b",
1655 "targ03", "targ03b",
1656 "targ04", "targ04b",
1657 "targ05", "targ05b",
1658 "targ06", "targ06b",
1659 "gauge18", "gauge18b",
1665 int piggy_is_gauge_bitmap( char * base_name )
1668 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1669 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1676 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1680 char base_name[ 16 ];
1682 strcpy( subst_name, name );
1683 p = strchr( subst_name, '#' );
1685 frame = atoi( &p[1] );
1687 strcpy( base_name, subst_name );
1688 if ( !piggy_is_gauge_bitmap( base_name )) {
1689 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1690 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1692 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1698 strcpy( subst_name, name );
1705 // New Windows stuff
1707 // windows bitmap page in
1708 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1709 // 'video' memory. if that fails, page it in normally.
1711 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1716 // Essential when switching video modes!
1718 void piggy_bitmap_page_out_all_w()