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.4 2001-01-31 15:17:57 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);
164 void swap_0_255(grs_bitmap *bmp)
168 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
169 if(bmp->bm_data[i] == 0)
170 bmp->bm_data[i] = 255;
171 else if (bmp->bm_data[i] == 255)
177 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
180 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
182 temp.index = Num_bitmap_files;
186 if ( FindArg("-macdata") )
189 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
190 Num_bitmap_files_new++;
193 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
194 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
195 GameBitmaps[Num_bitmap_files] = *bmp;
197 GameBitmapOffset[Num_bitmap_files] = 0;
198 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
205 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
209 Assert( Num_sound_files < MAX_SOUND_FILES );
211 strncpy( AllSounds[Num_sound_files].name, name, 12 );
212 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
213 GameSounds[Num_sound_files] = *snd;
215 SoundOffset[Num_sound_files] = 0;
221 Num_sound_files_new++;
227 bitmap_index piggy_find_bitmap( char * name )
235 if ((t=strchr(name,'#'))!=NULL)
238 for (i=0;i<Num_aliases;i++)
239 if (stricmp(name,alias_list[i].alias_name)==0) {
240 if (t) { //extra stuff for ABMs
241 static char temp[FILENAME_LEN];
242 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
248 name=alias_list[i].file_name;
255 i = hashtable_search( &AllBitmapsNames, name );
264 int piggy_find_sound( char * name )
268 i = hashtable_search( &AllDigiSndNames, name );
276 CFILE * Piggy_fp = NULL;
278 #define FILENAME_LEN 13
280 char Current_pigfile[FILENAME_LEN] = "";
282 void piggy_close_file()
287 Current_pigfile[0] = 0;
291 int Pigfile_initialized=0;
293 #define PIGFILE_ID "PPIG" //PPIG
294 #define PIGFILE_VERSION 2
296 extern char CDROM_dir[];
298 int request_cd(void);
303 //copies a pigfile from the CD to the current dir
304 //retuns file handle of new pig
305 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
308 char sourcePathAndFileCStr[255] = "";
309 char destPathAndFileCStr[255] = "";
311 FILE* sourceFile = NULL;
312 FILE* destFile = NULL;
313 const int BUF_SIZE = 4096;
317 Str255 sourcePathAndFilePStr = "\p";
318 Str255 destPathAndFilePStr = "\p";
319 Str255 pigfileNamePStr = "\p";
320 HParamBlockRec theSourcePigHFSParams;
321 HParamBlockRec theDestPigHFSParams;
322 OSErr theErr = noErr;
323 char oldDirCStr[255] = "";
325 getcwd(oldDirCStr, 255);
327 show_boxed_message("Copying bitmap data from CD...");
328 gr_palette_load(gr_palette); //I don't think this line is really needed
331 //First, delete all PIG files currently in the directory
332 if( !FileFindFirst( "*.pig", &find ) )
337 } while( !FileFindNext( &find ) );
343 //Now, copy over new pig
344 songs_stop_redbook(); //so we can read off the cd
346 // make the source path "<cd volume>:Data:filename.pig"
347 //MWA ConvertCToPStr(filename, pigfileNamePStr);
349 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
350 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
353 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
354 strcat(sourcePathAndFileCStr, filename);
356 // make the destination path "<default directory>:Data:filename.pig"
357 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
358 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
359 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
360 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
362 strcpy(destPathAndFileCStr, ":Data:");
363 strcat(destPathAndFileCStr, filename);
365 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
366 strcpy(destPathAndFilePStr, destPathAndFileCStr);
367 c2pstr(sourcePathAndFilePStr);
368 c2pstr(destPathAndFilePStr);
371 // Open the source file
372 sourceFile = fopen(sourcePathAndFileCStr,"rb");
376 if (request_cd() == -1)
377 Error("Cannot load file <%s> from CD",filename);
380 } while (!sourceFile);
383 // Get the time stamp from the source file
384 theSourcePigHFSParams.fileParam.ioCompletion = nil;
385 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
386 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
387 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
388 theSourcePigHFSParams.fileParam.ioDirID = 0;
390 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
393 // Error getting file time stamp!! Why? JTS
394 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
397 // Copy the file over
400 // Open the destination file
401 destFile = fopen(destPathAndFileCStr,"wb");
404 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
407 // Copy bytes until the end of the source file
408 while (!feof(sourceFile))
413 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
414 if (ferror(sourceFile))
415 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
417 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
419 fwrite(buf,1,bytes_read,destFile);
420 if (ferror(destFile))
421 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
424 // close the source/dest files
425 if (fclose(sourceFile))
426 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
427 if (fclose(destFile))
428 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
430 // Get the current hfs data for the new file
431 theDestPigHFSParams.fileParam.ioCompletion = nil;
432 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
433 theDestPigHFSParams.fileParam.ioVRefNum = 0;
434 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
435 theDestPigHFSParams.fileParam.ioDirID = 0;
436 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
437 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
439 // Error getting file time stamp!! Why? JTS
440 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
443 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
444 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
445 theDestPigHFSParams.fileParam.ioVRefNum = 0;
446 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
447 theDestPigHFSParams.fileParam.ioDirID = 0;
449 // Copy the time stamp from the source file info
450 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
451 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
452 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
453 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
455 // Set the dest file's time stamp to the source file's time stamp values
456 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
458 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
460 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
463 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
465 return cfopen(destPathAndFileCStr, "rb");
468 #else //PC Version of copy_pigfile_from_cd is below
470 //copies a pigfile from the CD to the current dir
471 //retuns file handle of new pig
472 CFILE *copy_pigfile_from_cd(char *filename)
478 return cfopen(filename, "rb");
479 show_boxed_message("Copying bitmap data from CD...");
480 gr_palette_load(gr_palette); //I don't think this line is really needed
482 //First, delete all PIG files currently in the directory
484 if( !FileFindFirst( "*.pig", &find ) ) {
487 } while( !FileFindNext( &find ) );
491 //Now, copy over new pig
493 songs_stop_redbook(); //so we can read off the cd
495 //new code to unarj file
496 strcpy(name,CDROM_dir);
497 strcat(name,"descent2.sow");
500 // ret = unarj_specific_file(name,filename,filename);
505 if (ret != EXIT_SUCCESS) {
507 //delete file, so we don't leave partial file
511 if (request_cd() == -1)
513 //NOTE LINK TO ABOVE IF
514 Error("Cannot load file <%s> from CD",filename);
517 } while (ret != EXIT_SUCCESS);
519 return cfopen(filename, "rb");
522 #endif // end of ifdef MAC around copy_pigfile_from_cd
524 //initialize a pigfile, reading headers
525 //returns the size of all the bitmap data
526 void piggy_init_pigfile(char *filename)
530 char temp_name_read[16];
531 grs_bitmap temp_bitmap;
532 DiskBitmapHeader bmh;
533 int header_size, N_bitmaps, data_size, data_start;
535 char name[255]; // filename + path for the mac
538 piggy_close_file(); //close old pig if still open
540 #ifdef SHAREWARE //rename pigfile for shareware
541 if (stricmp(filename,DEFAULT_PIGFILE_REGISTERED)==0)
542 filename = DEFAULT_PIGFILE_SHAREWARE;
546 Piggy_fp = cfopen( filename, "rb" );
548 sprintf(name, ":Data:%s", filename);
549 Piggy_fp = cfopen( name, "rb" );
551 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
552 if (Piggy_fp == NULL)
554 Error("Cannot load required file <%s>",name);
556 #endif // end of if def shareware
562 return; //if editor, ok to not have pig, because we'll build one
564 Piggy_fp = copy_pigfile_from_cd(filename);
568 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
572 cfread(&pig_id, 1, 4, Piggy_fp);
573 pig_version = cfile_read_int(Piggy_fp);
574 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
575 cfclose(Piggy_fp); //out of date pig
576 Piggy_fp = NULL; //..so pretend it's not here
583 return; //if editor, ok to not have pig, because we'll build one
585 Error("Cannot load required file <%s>",filename);
589 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
591 N_bitmaps = cfile_read_int(Piggy_fp);
593 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
595 data_start = header_size + cftell(Piggy_fp);
597 data_size = cfilelength(Piggy_fp) - data_start;
599 Num_bitmap_files = 1;
601 for (i=0; i<N_bitmaps; i++ ) {
603 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
605 cfread(bmh.name, 8, 1, Piggy_fp);
606 bmh.dflags = cfile_read_byte(Piggy_fp);
607 bmh.width = cfile_read_byte(Piggy_fp);
608 bmh.height = cfile_read_byte(Piggy_fp);
609 bmh.wh_extra = cfile_read_byte(Piggy_fp);
610 bmh.flags = cfile_read_byte(Piggy_fp);
611 bmh.avg_color = cfile_read_byte(Piggy_fp);
612 bmh.offset = cfile_read_int(Piggy_fp);
614 memcpy( temp_name_read, bmh.name, 8 );
615 temp_name_read[8] = 0;
616 if ( bmh.dflags & DBM_FLAG_ABM )
617 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
619 strcpy( temp_name, temp_name_read );
620 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
621 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
622 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
623 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
624 temp_bitmap.avg_color = bmh.avg_color;
625 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
627 GameBitmapFlags[i+1] = 0;
628 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
629 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
630 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
631 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
632 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
634 GameBitmapOffset[i+1] = bmh.offset + data_start;
635 Assert( (i+1) == Num_bitmap_files );
636 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
640 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
641 Assert( Piggy_bitmap_cache_size > 0 );
643 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
645 if (piggy_low_memory)
646 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
649 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
650 if ( BitmapBits == NULL )
651 Error( "Not enough memory to load bitmaps\n" );
652 Piggy_bitmap_cache_data = BitmapBits;
653 Piggy_bitmap_cache_next = 0;
655 #if defined(MACINTOSH) && defined(SHAREWARE)
656 // load_exit_models();
659 Pigfile_initialized=1;
662 #define FILENAME_LEN 13
663 #define MAX_BITMAPS_PER_BRUSH 30
665 extern int compute_average_pixel(grs_bitmap *new);
667 //reads in a new pigfile (for new palette)
668 //returns the size of all the bitmap data
669 void piggy_new_pigfile(char *pigname)
673 char temp_name_read[16];
674 grs_bitmap temp_bitmap;
675 DiskBitmapHeader bmh;
676 int header_size, N_bitmaps, data_size, data_start;
677 int must_rewrite_pig = 0;
684 #ifdef SHAREWARE //rename pigfile for shareware
685 if (stricmp(pigname,DEFAULT_PIGFILE_REGISTERED)==0)
686 pigname = DEFAULT_PIGFILE_SHAREWARE;
689 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
690 return; //already have correct pig
692 if (!Pigfile_initialized) { //have we ever opened a pigfile?
693 piggy_init_pigfile(pigname); //..no, so do initialization stuff
697 piggy_close_file(); //close old pig if still open
699 Piggy_bitmap_cache_next = 0; //free up cache
701 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
704 Piggy_fp = cfopen( pigname, "rb" );
706 sprintf(name, ":Data:%s", pigname);
707 Piggy_fp = cfopen( name, "rb" );
709 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
710 if (Piggy_fp == NULL)
712 Error("Cannot load required file <%s>",name);
714 #endif // end of if def shareware
719 Piggy_fp = copy_pigfile_from_cd(pigname);
722 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
726 cfread(&pig_id, 1, 4, Piggy_fp);
727 pig_version = cfile_read_int(Piggy_fp);
728 if (memcmp(pig_id, PIGFILE_ID, 4) || pig_version != PIGFILE_VERSION) {
729 cfclose(Piggy_fp); //out of date pig
730 Piggy_fp = NULL; //..so pretend it's not here
735 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
740 N_bitmaps = cfile_read_int(Piggy_fp);
742 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
744 data_start = header_size + cftell(Piggy_fp);
746 data_size = cfilelength(Piggy_fp) - data_start;
748 for (i=1; i<=N_bitmaps; i++ ) {
750 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
752 cfread(bmh.name, 8, 1, Piggy_fp);
753 bmh.dflags = cfile_read_byte(Piggy_fp);
754 bmh.width = cfile_read_byte(Piggy_fp);
755 bmh.height = cfile_read_byte(Piggy_fp);
756 bmh.wh_extra = cfile_read_byte(Piggy_fp);
757 bmh.flags = cfile_read_byte(Piggy_fp);
758 bmh.avg_color = cfile_read_byte(Piggy_fp);
759 bmh.offset = cfile_read_int(Piggy_fp);
761 memcpy( temp_name_read, bmh.name, 8 );
762 temp_name_read[8] = 0;
764 if ( bmh.dflags & DBM_FLAG_ABM )
765 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
767 strcpy( temp_name, temp_name_read );
769 //Make sure name matches
770 if (strcmp(temp_name,AllBitmaps[i].name)) {
771 //Int3(); //this pig is out of date. Delete it
775 strcpy(AllBitmaps[i].name,temp_name);
777 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
779 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
780 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
781 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
782 temp_bitmap.avg_color = bmh.avg_color;
783 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
785 GameBitmapFlags[i] = 0;
787 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
788 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
789 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
790 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
791 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
793 GameBitmapOffset[i] = bmh.offset + data_start;
795 GameBitmaps[i] = temp_bitmap;
799 N_bitmaps = 0; //no pigfile, so no bitmaps
803 Assert(N_bitmaps == Num_bitmap_files-1);
807 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
810 //re-read the bitmaps that aren't in this pig
812 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
815 p = strchr(AllBitmaps[i].name,'#');
817 if (p) { //this is an ABM
818 char abmname[FILENAME_LEN];
820 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
821 int iff_error; //reference parm to avoid warning message
823 char basename[FILENAME_LEN];
826 strcpy(basename,AllBitmaps[i].name);
827 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
829 sprintf( abmname, "%s.abm", basename );
831 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
833 if (iff_error != IFF_NO_ERROR) {
834 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
835 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
838 for (fnum=0;fnum<nframes; fnum++) {
842 sprintf( tempname, "%s#%d", basename, fnum );
844 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
845 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
846 //above makes assumption that supertransparent color is 254
848 if ( iff_has_transparency )
849 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
851 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
853 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
856 if ( FindArg("-macdata") )
857 swap_0_255( bm[fnum] );
859 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
861 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
862 size = *((int *) bm[fnum]->bm_data);
864 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
866 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
867 d_free(bm[fnum]->bm_data);
868 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
869 Piggy_bitmap_cache_next += size;
871 GameBitmaps[i+fnum] = *bm[fnum];
873 // -- mprintf( (0, "U" ));
877 i += nframes-1; //filled in multiple bitmaps
879 else { //this is a BBM
884 char bbmname[FILENAME_LEN];
887 MALLOC( new, grs_bitmap, 1 );
889 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
890 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
893 if (iff_error != IFF_NO_ERROR) {
894 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
895 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
898 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
899 //above makes assumption that supertransparent color is 254
901 if ( iff_has_transparency )
902 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
904 gr_remap_bitmap_good( new, newpal, -1, SuperX );
906 new->avg_color = compute_average_pixel(new);
909 if ( FindArg("-macdata") )
912 if ( !BigPig ) gr_bitmap_rle_compress( new );
914 if (new->bm_flags & BM_FLAG_RLE)
915 size = *((int *) new->bm_data);
917 size = new->bm_w * new->bm_h;
919 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
920 d_free(new->bm_data);
921 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
922 Piggy_bitmap_cache_next += size;
924 GameBitmaps[i] = *new;
928 // -- mprintf( (0, "U" ));
932 //@@Dont' do these things which are done when writing
933 //@@for (i=0; i < Num_bitmap_files; i++ ) {
934 //@@ bitmap_index bi;
936 //@@ PIGGY_PAGE_IN( bi );
939 //@@piggy_close_file();
941 piggy_write_pigfile(pigname);
943 Current_pigfile[0] = 0; //say no pig, to force reload
945 piggy_new_pigfile(pigname); //read in just-generated pig
949 #endif //ifdef EDITOR
953 ubyte bogus_data[64*64];
954 grs_bitmap bogus_bitmap;
955 ubyte bogus_bitmap_initialized=0;
956 digi_sound bogus_sound;
958 extern void bm_read_all(CFILE * fp);
960 #define HAMFILE_ID "HAM!" //HAM!
961 #define HAMFILE_VERSION 3
962 //version 1 -> 2: save marker_model_num
963 //version 2 -> 3: removed sound files
965 #define SNDFILE_ID "DSND" //DSND
966 #define SNDFILE_VERSION 1
970 CFILE * ham_fp = NULL;
978 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
980 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
981 ham_fp = cfopen( name, "rb" );
984 if (ham_fp == NULL) {
985 Must_write_hamfile = 1;
989 //make sure ham is valid type file & is up-to-date
990 cfread( &ham_id, 1, 4, ham_fp );
991 ham_version = cfile_read_int(ham_fp);
992 if (memcmp(ham_id, HAMFILE_ID, 4) || ham_version != HAMFILE_VERSION) {
993 Must_write_hamfile = 1;
994 cfclose(ham_fp); //out of date ham
1000 bm_read_all( ham_fp ); // Note connection to above if!!!
1001 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1006 for (i = 0; i < MAX_BITMAP_FILES; i++)
1007 GameBitmapXlat[i] = SWAPSHORT(GameBitmapXlat[i]);
1021 CFILE * snd_fp = NULL;
1028 DiskSoundHeader sndh;
1029 digi_sound temp_sound;
1030 char temp_name_read[16];
1037 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1039 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1040 snd_fp = cfopen( name, "rb");
1046 //make sure soundfile is valid type file & is up-to-date
1047 cfread( &snd_id, 1, 4, snd_fp );
1048 snd_version = cfile_read_int(snd_fp);
1049 if (memcmp(snd_id, SNDFILE_ID, 4) || snd_version != SNDFILE_VERSION) {
1050 cfclose(snd_fp); //out of date sound file
1054 N_sounds = cfile_read_int(snd_fp);
1056 sound_start = cftell(snd_fp);
1057 size = cfilelength(snd_fp) - sound_start;
1059 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1061 header_size = N_sounds*sizeof(DiskSoundHeader);
1065 for (i=0; i<N_sounds; i++ ) {
1066 cfread( sndh.name, 8, 1, snd_fp);
1067 sndh.length = cfile_read_int(snd_fp);
1068 sndh.data_length = cfile_read_int(snd_fp);
1069 sndh.offset = cfile_read_int(snd_fp);
1070 // cfread( &sndh, sizeof(DiskSoundHeader), 1, snd_fp );
1071 //size -= sizeof(DiskSoundHeader);
1072 temp_sound.length = sndh.length;
1073 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1074 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1075 memcpy( temp_name_read, sndh.name, 8 );
1076 temp_name_read[8] = 0;
1077 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1079 if (piggy_is_needed(i))
1080 #endif // note link to if.
1081 sbytes += sndh.length;
1082 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1085 SoundBits = d_malloc( sbytes + 16 );
1086 if ( SoundBits == NULL )
1087 Error( "Not enough memory to load sounds\n" );
1089 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1091 // piggy_read_sounds(snd_fp);
1098 int piggy_init(void)
1100 int ham_ok=0,snd_ok=0;
1103 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1104 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1106 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1107 GameSounds[i].length = 0;
1108 GameSounds[i].data = NULL;
1112 for (i=0; i<MAX_BITMAP_FILES; i++ )
1113 GameBitmapXlat[i] = i;
1115 if ( !bogus_bitmap_initialized ) {
1118 bogus_bitmap_initialized = 1;
1119 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1120 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1121 bogus_bitmap.bm_data = bogus_data;
1122 c = gr_find_closest_color( 0, 0, 63 );
1123 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1124 c = gr_find_closest_color( 63, 0, 0 );
1125 // Make a big red X !
1126 for (i=0; i<64; i++ ) {
1127 bogus_data[i*64+i] = c;
1128 bogus_data[i*64+(63-i)] = c;
1130 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1131 bogus_sound.length = 64*64;
1132 bogus_sound.data = bogus_data;
1133 GameBitmapOffset[0] = 0;
1136 if ( FindArg( "-bigpig" ))
1139 if ( FindArg( "-lowmem" ))
1140 piggy_low_memory = 1;
1142 if ( FindArg( "-nolowmem" ))
1143 piggy_low_memory = 0;
1145 if (piggy_low_memory)
1148 WIN(DDGRLOCK(dd_grd_curcanv));
1149 gr_set_curfont( SMALL_FONT );
1150 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1151 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1152 WIN(DDGRUNLOCK(dd_grd_curcanv));
1155 piggy_init_pigfile(DEFAULT_PIGFILE);
1158 ham_ok = read_hamfile();
1160 snd_ok = read_sndfile();
1162 atexit(piggy_close);
1164 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1165 return (ham_ok && snd_ok); //read ok
1168 int piggy_is_needed(int soundnum)
1172 if ( !digi_lomem ) return 1;
1174 for (i=0; i<MAX_SOUNDS; i++ ) {
1175 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1182 void piggy_read_sounds(void)
1195 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1197 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1198 fp = cfopen( name, "rb");
1204 for (i=0; i<Num_sound_files; i++ ) {
1205 digi_sound *snd = &GameSounds[i];
1207 if ( SoundOffset[i] > 0 ) {
1208 if ( piggy_is_needed(i) ) {
1209 cfseek( fp, SoundOffset[i], SEEK_SET );
1211 // Read in the sound data!!!
1214 sbytes += snd->length;
1215 cfread( snd->data, snd->length, 1, fp );
1218 snd->data = (ubyte *) -1;
1224 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1229 extern int descent_critical_error;
1230 extern unsigned descent_critical_deverror;
1231 extern unsigned descent_critical_errcode;
1233 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1234 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1235 "Read fault", "General Failure" };
1237 void piggy_critical_error()
1239 grs_canvas * save_canv;
1240 grs_font * save_font;
1242 save_canv = grd_curcanv;
1243 save_font = grd_curcanv->cv_font;
1244 gr_palette_load( gr_palette );
1245 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1248 gr_set_current_canvas(save_canv);
1249 grd_curcanv->cv_font = save_font;
1252 void piggy_bitmap_page_in( bitmap_index bitmap )
1261 Assert( i < MAX_BITMAP_FILES );
1262 Assert( i < Num_bitmap_files );
1263 Assert( Piggy_bitmap_cache_size > 0 );
1265 if ( i < 1 ) return;
1266 if ( i >= MAX_BITMAP_FILES ) return;
1267 if ( i >= Num_bitmap_files ) return;
1269 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1271 if ( piggy_low_memory ) {
1273 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1276 bmp = &GameBitmaps[i];
1278 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1282 descent_critical_error = 0;
1283 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1284 if ( descent_critical_error ) {
1285 piggy_critical_error();
1289 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1290 bmp->bm_flags = GameBitmapFlags[i];
1292 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1294 descent_critical_error = 0;
1295 zsize = cfile_read_int(Piggy_fp);
1296 if ( descent_critical_error ) {
1297 piggy_critical_error();
1301 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1302 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1303 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1305 piggy_bitmap_page_out_all();
1308 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1309 Piggy_bitmap_cache_next += sizeof(int);
1310 descent_critical_error = 0;
1311 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1312 if ( descent_critical_error ) {
1313 piggy_critical_error();
1316 Piggy_bitmap_cache_next += zsize-4;
1318 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1319 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1320 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1321 piggy_bitmap_page_out_all();
1324 descent_critical_error = 0;
1325 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1326 if ( descent_critical_error ) {
1327 piggy_critical_error();
1330 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1333 //@@if ( bmp->bm_selector ) {
1334 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1335 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1336 //@@ Error( "Error modifying selector base in piggy.c\n" );
1343 if ( piggy_low_memory ) {
1345 GameBitmaps[org_i] = GameBitmaps[i];
1348 //@@Removed from John's code:
1350 //@@ if ( bmp->bm_selector ) {
1351 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1352 //@@ Error( "Error modifying selector base in piggy.c\n" );
1358 void piggy_bitmap_page_out_all()
1362 Piggy_bitmap_cache_next = 0;
1364 piggy_page_flushed++;
1369 for (i=0; i<Num_bitmap_files; i++ ) {
1370 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1371 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1372 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1376 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1379 void piggy_load_level_data()
1381 piggy_bitmap_page_out_all();
1387 void change_filename_ext( char *dest, char *src, char *ext );
1389 void piggy_write_pigfile(char *filename)
1392 int bitmap_data_start,data_offset;
1393 DiskBitmapHeader bmh;
1395 char subst_name[32];
1398 char tname[FILENAME_LEN];
1400 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1401 for (i=0; i < Num_bitmap_files; i++ ) {
1404 PIGGY_PAGE_IN( bi );
1406 // -- mprintf( (0, "\n" ));
1410 // -- mprintf( (0, "Creating %s...",filename ));
1412 pig_fp = fopen( filename, "wb" ); //open PIG file
1413 Assert( pig_fp!=NULL );
1415 write_int(PIGFILE_ID,pig_fp);
1416 write_int(PIGFILE_VERSION,pig_fp);
1419 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1422 bitmap_data_start = ftell(pig_fp);
1423 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1424 data_offset = bitmap_data_start;
1426 change_filename_ext(tname,filename,"lst");
1427 fp1 = fopen( tname, "wt" );
1428 change_filename_ext(tname,filename,"all");
1429 fp2 = fopen( tname, "wt" );
1431 for (i=1; i < Num_bitmap_files; i++ ) {
1437 p = strchr(AllBitmaps[i].name,'#');
1444 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1445 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1447 bmh.dflags = DBM_FLAG_ABM + n;
1451 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1452 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1456 bmp = &GameBitmaps[i];
1458 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1461 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1462 org_offset = ftell(pig_fp);
1463 bmh.offset = data_offset - bitmap_data_start;
1464 fseek( pig_fp, data_offset, SEEK_SET );
1466 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1467 size = (int *)bmp->bm_data;
1468 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1469 data_offset += *size;
1471 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1473 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1474 data_offset += bmp->bm_rowsize * bmp->bm_h;
1476 fprintf( fp1, ".\n" );
1478 fseek( pig_fp, org_offset, SEEK_SET );
1479 Assert( GameBitmaps[i].bm_w < 4096 );
1480 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1481 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1482 Assert( GameBitmaps[i].bm_h < 4096 );
1483 bmh.height = GameBitmaps[i].bm_h;
1484 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1485 bmh.flags = GameBitmaps[i].bm_flags;
1486 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1487 bitmap_index other_bitmap;
1488 other_bitmap = piggy_find_bitmap( subst_name );
1489 GameBitmapXlat[i] = other_bitmap.index;
1490 bmh.flags |= BM_FLAG_PAGED_OUT;
1491 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1492 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1494 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1496 bmh.avg_color=GameBitmaps[i].avg_color;
1497 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1502 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1503 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1510 static void write_int(int i,FILE *file)
1512 if (fwrite( &i, sizeof(i), 1, file) != 1)
1513 Error( "Error reading int in gamesave.c" );
1517 void piggy_dump_all()
1521 int org_offset,data_offset;
1522 DiskSoundHeader sndh;
1523 int sound_data_start;
1526 #ifdef NO_DUMP_SOUNDS
1527 Num_sound_files = 0;
1528 Num_sound_files_new = 0;
1531 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1534 fp1 = fopen( "ham.lst", "wt" );
1535 fp2 = fopen( "ham.all", "wt" );
1537 if (Must_write_hamfile || Num_bitmap_files_new) {
1539 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1541 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1542 Assert( ham_fp!=NULL );
1544 write_int(HAMFILE_ID,ham_fp);
1545 write_int(HAMFILE_VERSION,ham_fp);
1547 bm_write_all(ham_fp);
1548 xlat_offset = ftell(ham_fp);
1549 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1552 if (Num_bitmap_files_new)
1553 piggy_write_pigfile(DEFAULT_PIGFILE);
1555 //free up memeory used by new bitmaps
1556 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1557 d_free(GameBitmaps[i].bm_data);
1559 //next thing must be done after pig written
1560 fseek( ham_fp, xlat_offset, SEEK_SET );
1561 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1564 mprintf( (0, "\n" ));
1567 if (Num_sound_files_new) {
1569 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1570 // Now dump sound file
1571 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1572 Assert( ham_fp!=NULL );
1574 write_int(SNDFILE_ID,ham_fp);
1575 write_int(SNDFILE_VERSION,ham_fp);
1577 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1579 mprintf( (0, "\nDumping sounds..." ));
1581 sound_data_start = ftell(ham_fp);
1582 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1583 data_offset = sound_data_start;
1585 for (i=0; i < Num_sound_files; i++ ) {
1588 snd = &GameSounds[i];
1589 strcpy( sndh.name, AllSounds[i].name );
1590 sndh.length = GameSounds[i].length;
1591 sndh.offset = data_offset - sound_data_start;
1593 org_offset = ftell(ham_fp);
1594 fseek( ham_fp, data_offset, SEEK_SET );
1596 sndh.data_length = GameSounds[i].length;
1597 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1598 data_offset += snd->length;
1599 fseek( ham_fp, org_offset, SEEK_SET );
1600 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1602 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1603 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1607 mprintf( (0, "\n" ));
1610 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1611 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1612 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1617 // Never allow the game to run after building ham.
1631 d_free( SoundBits );
1633 hashtable_free( &AllBitmapsNames );
1634 hashtable_free( &AllDigiSndNames );
1638 int piggy_does_bitmap_exist_slow( char * name )
1642 for (i=0; i<Num_bitmap_files; i++ ) {
1643 if ( !strcmp( AllBitmaps[i].name, name) )
1650 #define NUM_GAUGE_BITMAPS 23
1651 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1652 "gauge01", "gauge01b",
1653 "gauge02", "gauge02b",
1654 "gauge06", "gauge06b",
1655 "targ01", "targ01b",
1656 "targ02", "targ02b",
1657 "targ03", "targ03b",
1658 "targ04", "targ04b",
1659 "targ05", "targ05b",
1660 "targ06", "targ06b",
1661 "gauge18", "gauge18b",
1667 int piggy_is_gauge_bitmap( char * base_name )
1670 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1671 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1678 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1682 char base_name[ 16 ];
1684 strcpy( subst_name, name );
1685 p = strchr( subst_name, '#' );
1687 frame = atoi( &p[1] );
1689 strcpy( base_name, subst_name );
1690 if ( !piggy_is_gauge_bitmap( base_name )) {
1691 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1692 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1694 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1700 strcpy( subst_name, name );
1707 // New Windows stuff
1709 // windows bitmap page in
1710 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1711 // 'video' memory. if that fails, page it in normally.
1713 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1718 // Essential when switching video modes!
1720 void piggy_bitmap_page_out_all_w()