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.9 2002-07-27 22:39:57 btb Exp $";
58 #include <Strings.h> // MacOS Toolbox header
63 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
65 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
66 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
70 #define DEFAULT_HAMFILE "d2demo.ham"
71 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_SHAREWARE
72 #define DEFAULT_SNDFILE "descent2.s11"
74 #define DEFAULT_HAMFILE "descent2.ham"
75 #define DEFAULT_PIGFILE DEFAULT_PIGFILE_REGISTERED
76 #define DEFAULT_SNDFILE ((digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
77 #endif // end of ifdef SHAREWARE
79 ubyte *BitmapBits = NULL;
80 ubyte *SoundBits = NULL;
82 typedef struct BitmapFile {
86 typedef struct SoundFile {
90 hashtable AllBitmapsNames;
91 hashtable AllDigiSndNames;
93 int Num_bitmap_files = 0;
94 int Num_sound_files = 0;
96 digi_sound GameSounds[MAX_SOUND_FILES];
97 int SoundOffset[MAX_SOUND_FILES];
98 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
100 alias alias_list[MAX_ALIASES];
103 int Must_write_hamfile = 0;
104 int Num_bitmap_files_new = 0;
105 int Num_sound_files_new = 0;
106 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
107 static SoundFile AllSounds[ MAX_SOUND_FILES ];
109 int piggy_low_memory = 0;
111 int Piggy_bitmap_cache_size = 0;
112 int Piggy_bitmap_cache_next = 0;
113 ubyte * Piggy_bitmap_cache_data = NULL;
114 static int GameBitmapOffset[MAX_BITMAP_FILES];
115 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
116 ushort GameBitmapXlat[MAX_BITMAP_FILES];
118 #define PIGGY_BUFFER_SIZE (2400*1024)
121 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
124 #undef PIGGY_BUFFER_SIZE
125 #undef PIGGY_SMALL_BUFFER_SIZE
127 #define PIGGY_BUFFER_SIZE (2000*1024)
128 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
133 int piggy_page_flushed = 0;
135 #define DBM_FLAG_ABM 64
137 typedef struct DiskSoundHeader {
142 } __pack__ DiskSoundHeader;
147 extern short cd_VRefNum;
148 extern void ConcatPStr(StringPtr dst, StringPtr src);
149 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
150 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
153 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
156 void piggy_write_pigfile(char *filename);
157 static void write_int(int i,FILE *file);
159 void swap_0_255(grs_bitmap *bmp)
163 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
164 if(bmp->bm_data[i] == 0)
165 bmp->bm_data[i] = 255;
166 else if (bmp->bm_data[i] == 255)
172 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
175 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
177 temp.index = Num_bitmap_files;
181 if ( FindArg("-macdata") )
184 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
185 Num_bitmap_files_new++;
188 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
189 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
190 GameBitmaps[Num_bitmap_files] = *bmp;
192 GameBitmapOffset[Num_bitmap_files] = 0;
193 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
200 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
204 Assert( Num_sound_files < MAX_SOUND_FILES );
206 strncpy( AllSounds[Num_sound_files].name, name, 12 );
207 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
208 GameSounds[Num_sound_files] = *snd;
210 SoundOffset[Num_sound_files] = 0;
216 Num_sound_files_new++;
222 bitmap_index piggy_find_bitmap( char * name )
230 if ((t=strchr(name,'#'))!=NULL)
233 for (i=0;i<Num_aliases;i++)
234 if (stricmp(name,alias_list[i].alias_name)==0) {
235 if (t) { //extra stuff for ABMs
236 static char temp[FILENAME_LEN];
237 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
243 name=alias_list[i].file_name;
250 i = hashtable_search( &AllBitmapsNames, name );
259 int piggy_find_sound( char * name )
263 i = hashtable_search( &AllDigiSndNames, name );
271 CFILE * Piggy_fp = NULL;
273 #define FILENAME_LEN 13
275 char Current_pigfile[FILENAME_LEN] = "";
277 void piggy_close_file()
282 Current_pigfile[0] = 0;
286 int Pigfile_initialized=0;
288 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
289 #define PIGFILE_VERSION 2
291 extern char CDROM_dir[];
293 int request_cd(void);
298 //copies a pigfile from the CD to the current dir
299 //retuns file handle of new pig
300 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
303 char sourcePathAndFileCStr[255] = "";
304 char destPathAndFileCStr[255] = "";
306 FILE* sourceFile = NULL;
307 FILE* destFile = NULL;
308 const int BUF_SIZE = 4096;
312 Str255 sourcePathAndFilePStr = "\p";
313 Str255 destPathAndFilePStr = "\p";
314 Str255 pigfileNamePStr = "\p";
315 HParamBlockRec theSourcePigHFSParams;
316 HParamBlockRec theDestPigHFSParams;
317 OSErr theErr = noErr;
318 char oldDirCStr[255] = "";
320 getcwd(oldDirCStr, 255);
322 show_boxed_message("Copying bitmap data from CD...");
323 gr_palette_load(gr_palette); //I don't think this line is really needed
326 //First, delete all PIG files currently in the directory
327 if( !FileFindFirst( "*.pig", &find ) )
332 } while( !FileFindNext( &find ) );
338 //Now, copy over new pig
339 songs_stop_redbook(); //so we can read off the cd
341 // make the source path "<cd volume>:Data:filename.pig"
342 //MWA ConvertCToPStr(filename, pigfileNamePStr);
344 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
345 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
348 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
349 strcat(sourcePathAndFileCStr, filename);
351 // make the destination path "<default directory>:Data:filename.pig"
352 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
353 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
354 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
355 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
357 strcpy(destPathAndFileCStr, ":Data:");
358 strcat(destPathAndFileCStr, filename);
360 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
361 strcpy(destPathAndFilePStr, destPathAndFileCStr);
362 c2pstr(sourcePathAndFilePStr);
363 c2pstr(destPathAndFilePStr);
366 // Open the source file
367 sourceFile = fopen(sourcePathAndFileCStr,"rb");
371 if (request_cd() == -1)
372 Error("Cannot load file <%s> from CD",filename);
375 } while (!sourceFile);
378 // Get the time stamp from the source file
379 theSourcePigHFSParams.fileParam.ioCompletion = nil;
380 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
381 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
382 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
383 theSourcePigHFSParams.fileParam.ioDirID = 0;
385 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
388 // Error getting file time stamp!! Why? JTS
389 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
392 // Copy the file over
395 // Open the destination file
396 destFile = fopen(destPathAndFileCStr,"wb");
399 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
402 // Copy bytes until the end of the source file
403 while (!feof(sourceFile))
408 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
409 if (ferror(sourceFile))
410 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
412 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
414 fwrite(buf,1,bytes_read,destFile);
415 if (ferror(destFile))
416 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
419 // close the source/dest files
420 if (fclose(sourceFile))
421 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
422 if (fclose(destFile))
423 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
425 // Get the current hfs data for the new file
426 theDestPigHFSParams.fileParam.ioCompletion = nil;
427 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
428 theDestPigHFSParams.fileParam.ioVRefNum = 0;
429 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
430 theDestPigHFSParams.fileParam.ioDirID = 0;
431 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
432 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
434 // Error getting file time stamp!! Why? JTS
435 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
438 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
439 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
440 theDestPigHFSParams.fileParam.ioVRefNum = 0;
441 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
442 theDestPigHFSParams.fileParam.ioDirID = 0;
444 // Copy the time stamp from the source file info
445 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
446 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
447 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
448 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
450 // Set the dest file's time stamp to the source file's time stamp values
451 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
453 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
455 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
458 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
460 return cfopen(destPathAndFileCStr, "rb");
463 #else //PC Version of copy_pigfile_from_cd is below
465 //copies a pigfile from the CD to the current dir
466 //retuns file handle of new pig
467 CFILE *copy_pigfile_from_cd(char *filename)
473 return cfopen(filename, "rb");
474 show_boxed_message("Copying bitmap data from CD...");
475 gr_palette_load(gr_palette); //I don't think this line is really needed
477 //First, delete all PIG files currently in the directory
479 if( !FileFindFirst( "*.pig", &find ) ) {
482 } while( !FileFindNext( &find ) );
486 //Now, copy over new pig
488 songs_stop_redbook(); //so we can read off the cd
490 //new code to unarj file
491 strcpy(name,CDROM_dir);
492 strcat(name,"descent2.sow");
495 // ret = unarj_specific_file(name,filename,filename);
500 if (ret != EXIT_SUCCESS) {
502 //delete file, so we don't leave partial file
506 if (request_cd() == -1)
508 //NOTE LINK TO ABOVE IF
509 Error("Cannot load file <%s> from CD",filename);
512 } while (ret != EXIT_SUCCESS);
514 return cfopen(filename, "rb");
517 #endif // end of ifdef MAC around copy_pigfile_from_cd
519 //initialize a pigfile, reading headers
520 //returns the size of all the bitmap data
521 void piggy_init_pigfile(char *filename)
525 char temp_name_read[16];
526 grs_bitmap temp_bitmap;
527 DiskBitmapHeader bmh;
528 int header_size, N_bitmaps, data_size, data_start;
530 char name[255]; // filename + path for the mac
533 piggy_close_file(); //close old pig if still open
535 #ifdef SHAREWARE //rename pigfile for shareware
536 if (stricmp(filename,DEFAULT_PIGFILE_REGISTERED)==0)
537 filename = DEFAULT_PIGFILE_SHAREWARE;
541 Piggy_fp = cfopen( filename, "rb" );
543 sprintf(name, ":Data:%s", filename);
544 Piggy_fp = cfopen( name, "rb" );
546 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
547 if (Piggy_fp == NULL)
549 Error("Cannot load required file <%s>",name);
551 #endif // end of if def shareware
557 return; //if editor, ok to not have pig, because we'll build one
559 Piggy_fp = copy_pigfile_from_cd(filename);
563 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
564 int pig_id,pig_version;
566 pig_id = cfile_read_int(Piggy_fp);
567 pig_version = cfile_read_int(Piggy_fp);
568 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
569 cfclose(Piggy_fp); //out of date pig
570 Piggy_fp = NULL; //..so pretend it's not here
577 return; //if editor, ok to not have pig, because we'll build one
579 Error("Cannot load required file <%s>",filename);
583 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
585 N_bitmaps = cfile_read_int(Piggy_fp);
587 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
589 data_start = header_size + cftell(Piggy_fp);
591 data_size = cfilelength(Piggy_fp) - data_start;
593 Num_bitmap_files = 1;
595 for (i=0; i<N_bitmaps; i++ ) {
596 DiskBitmapHeader_read(&bmh, Piggy_fp);
597 memcpy( temp_name_read, bmh.name, 8 );
598 temp_name_read[8] = 0;
599 if ( bmh.dflags & DBM_FLAG_ABM )
600 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
602 strcpy( temp_name, temp_name_read );
603 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
604 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
605 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
606 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
607 temp_bitmap.avg_color = bmh.avg_color;
608 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
610 GameBitmapFlags[i+1] = 0;
611 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
612 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
613 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
614 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
615 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
617 GameBitmapOffset[i+1] = bmh.offset + data_start;
618 Assert( (i+1) == Num_bitmap_files );
619 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
623 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
624 Assert( Piggy_bitmap_cache_size > 0 );
626 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
628 if (piggy_low_memory)
629 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
632 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
633 if ( BitmapBits == NULL )
634 Error( "Not enough memory to load bitmaps\n" );
635 Piggy_bitmap_cache_data = BitmapBits;
636 Piggy_bitmap_cache_next = 0;
638 #if defined(MACINTOSH) && defined(SHAREWARE)
639 // load_exit_models();
642 Pigfile_initialized=1;
645 #define FILENAME_LEN 13
646 #define MAX_BITMAPS_PER_BRUSH 30
648 extern int compute_average_pixel(grs_bitmap *new);
650 //reads in a new pigfile (for new palette)
651 //returns the size of all the bitmap data
652 void piggy_new_pigfile(char *pigname)
656 char temp_name_read[16];
657 grs_bitmap temp_bitmap;
658 DiskBitmapHeader bmh;
659 int header_size, N_bitmaps, data_size, data_start;
660 int must_rewrite_pig = 0;
667 #ifdef SHAREWARE //rename pigfile for shareware
668 if (stricmp(pigname,DEFAULT_PIGFILE_REGISTERED)==0)
669 pigname = DEFAULT_PIGFILE_SHAREWARE;
672 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
673 return; //already have correct pig
675 if (!Pigfile_initialized) { //have we ever opened a pigfile?
676 piggy_init_pigfile(pigname); //..no, so do initialization stuff
680 piggy_close_file(); //close old pig if still open
682 Piggy_bitmap_cache_next = 0; //free up cache
684 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
687 Piggy_fp = cfopen( pigname, "rb" );
689 sprintf(name, ":Data:%s", pigname);
690 Piggy_fp = cfopen( name, "rb" );
692 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
693 if (Piggy_fp == NULL)
695 Error("Cannot load required file <%s>",name);
697 #endif // end of if def shareware
702 Piggy_fp = copy_pigfile_from_cd(pigname);
705 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
706 int pig_id,pig_version;
708 pig_id = cfile_read_int(Piggy_fp);
709 pig_version = cfile_read_int(Piggy_fp);
710 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
711 cfclose(Piggy_fp); //out of date pig
712 Piggy_fp = NULL; //..so pretend it's not here
717 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
722 N_bitmaps = cfile_read_int(Piggy_fp);
724 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
726 data_start = header_size + cftell(Piggy_fp);
728 data_size = cfilelength(Piggy_fp) - data_start;
730 for (i=1; i<=N_bitmaps; i++ ) {
731 DiskBitmapHeader_read(&bmh, Piggy_fp);
732 memcpy( temp_name_read, bmh.name, 8 );
733 temp_name_read[8] = 0;
735 if ( bmh.dflags & DBM_FLAG_ABM )
736 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
738 strcpy( temp_name, temp_name_read );
740 //Make sure name matches
741 if (strcmp(temp_name,AllBitmaps[i].name)) {
742 //Int3(); //this pig is out of date. Delete it
746 strcpy(AllBitmaps[i].name,temp_name);
748 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
750 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
751 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
752 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
753 temp_bitmap.avg_color = bmh.avg_color;
754 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
756 GameBitmapFlags[i] = 0;
758 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
759 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
760 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
761 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
762 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
764 GameBitmapOffset[i] = bmh.offset + data_start;
766 GameBitmaps[i] = temp_bitmap;
770 N_bitmaps = 0; //no pigfile, so no bitmaps
774 Assert(N_bitmaps == Num_bitmap_files-1);
778 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
781 //re-read the bitmaps that aren't in this pig
783 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
786 p = strchr(AllBitmaps[i].name,'#');
788 if (p) { //this is an ABM
789 char abmname[FILENAME_LEN];
791 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
792 int iff_error; //reference parm to avoid warning message
794 char basename[FILENAME_LEN];
797 strcpy(basename,AllBitmaps[i].name);
798 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
800 sprintf( abmname, "%s.abm", basename );
802 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
804 if (iff_error != IFF_NO_ERROR) {
805 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
806 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
809 for (fnum=0;fnum<nframes; fnum++) {
813 sprintf( tempname, "%s#%d", basename, fnum );
815 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
816 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
817 //above makes assumption that supertransparent color is 254
819 if ( iff_has_transparency )
820 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
822 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
824 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
827 if ( FindArg("-macdata") )
828 swap_0_255( bm[fnum] );
830 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
832 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
833 size = *((int *) bm[fnum]->bm_data);
835 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
837 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
838 d_free(bm[fnum]->bm_data);
839 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
840 Piggy_bitmap_cache_next += size;
842 GameBitmaps[i+fnum] = *bm[fnum];
844 // -- mprintf( (0, "U" ));
848 i += nframes-1; //filled in multiple bitmaps
850 else { //this is a BBM
855 char bbmname[FILENAME_LEN];
858 MALLOC( new, grs_bitmap, 1 );
860 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
861 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
864 if (iff_error != IFF_NO_ERROR) {
865 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
866 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
869 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
870 //above makes assumption that supertransparent color is 254
872 if ( iff_has_transparency )
873 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
875 gr_remap_bitmap_good( new, newpal, -1, SuperX );
877 new->avg_color = compute_average_pixel(new);
880 if ( FindArg("-macdata") )
883 if ( !BigPig ) gr_bitmap_rle_compress( new );
885 if (new->bm_flags & BM_FLAG_RLE)
886 size = *((int *) new->bm_data);
888 size = new->bm_w * new->bm_h;
890 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
891 d_free(new->bm_data);
892 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
893 Piggy_bitmap_cache_next += size;
895 GameBitmaps[i] = *new;
899 // -- mprintf( (0, "U" ));
903 //@@Dont' do these things which are done when writing
904 //@@for (i=0; i < Num_bitmap_files; i++ ) {
905 //@@ bitmap_index bi;
907 //@@ PIGGY_PAGE_IN( bi );
910 //@@piggy_close_file();
912 piggy_write_pigfile(pigname);
914 Current_pigfile[0] = 0; //say no pig, to force reload
916 piggy_new_pigfile(pigname); //read in just-generated pig
920 #endif //ifdef EDITOR
924 ubyte bogus_data[64*64];
925 grs_bitmap bogus_bitmap;
926 ubyte bogus_bitmap_initialized=0;
927 digi_sound bogus_sound;
929 extern void bm_read_all(CFILE * fp);
931 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
933 #define HAMFILE_VERSION 2
935 #define HAMFILE_VERSION 3
937 //version 1 -> 2: save marker_model_num
938 //version 2 -> 3: removed sound files
940 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
941 #define SNDFILE_VERSION 1
945 CFILE * ham_fp = NULL;
946 int ham_id,ham_version;
952 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
954 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
955 ham_fp = cfopen( name, "rb" );
958 if (ham_fp == NULL) {
959 Must_write_hamfile = 1;
963 //make sure ham is valid type file & is up-to-date
964 ham_id = cfile_read_int(ham_fp);
965 ham_version = cfile_read_int(ham_fp);
966 if (ham_id != HAMFILE_ID || ham_version != HAMFILE_VERSION) {
967 Must_write_hamfile = 1;
968 cfclose(ham_fp); //out of date ham
972 if (ham_version < 3) //mystery value
973 cfseek(ham_fp, 4, SEEK_CUR);
979 bm_read_all( ham_fp ); // Note connection to above if!!!
980 printf("position: %d\n", cftell(ham_fp));
981 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
982 for (i = 0; i < MAX_BITMAP_FILES; i++) {
983 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
984 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
997 CFILE * snd_fp = NULL;
998 int snd_id,snd_version;
1003 DiskSoundHeader sndh;
1004 digi_sound temp_sound;
1005 char temp_name_read[16];
1012 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1014 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1015 snd_fp = cfopen( name, "rb");
1021 //make sure soundfile is valid type file & is up-to-date
1022 snd_id = cfile_read_int(snd_fp);
1023 snd_version = cfile_read_int(snd_fp);
1024 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1025 cfclose(snd_fp); //out of date sound file
1029 N_sounds = cfile_read_int(snd_fp);
1031 sound_start = cftell(snd_fp);
1032 size = cfilelength(snd_fp) - sound_start;
1034 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1036 header_size = N_sounds*sizeof(DiskSoundHeader);
1040 for (i=0; i<N_sounds; i++ ) {
1041 cfread( sndh.name, 8, 1, snd_fp);
1042 sndh.length = cfile_read_int(snd_fp);
1043 sndh.data_length = cfile_read_int(snd_fp);
1044 sndh.offset = cfile_read_int(snd_fp);
1045 // cfread( &sndh, sizeof(DiskSoundHeader), 1, snd_fp );
1046 //size -= sizeof(DiskSoundHeader);
1047 temp_sound.length = sndh.length;
1048 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1049 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1050 memcpy( temp_name_read, sndh.name, 8 );
1051 temp_name_read[8] = 0;
1052 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1054 if (piggy_is_needed(i))
1055 #endif // note link to if.
1056 sbytes += sndh.length;
1057 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1060 SoundBits = d_malloc( sbytes + 16 );
1061 if ( SoundBits == NULL )
1062 Error( "Not enough memory to load sounds\n" );
1064 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1066 // piggy_read_sounds(snd_fp);
1073 int piggy_init(void)
1075 int ham_ok=0,snd_ok=0;
1078 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1079 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1081 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1082 GameSounds[i].length = 0;
1083 GameSounds[i].data = NULL;
1087 for (i=0; i<MAX_BITMAP_FILES; i++ )
1088 GameBitmapXlat[i] = i;
1090 if ( !bogus_bitmap_initialized ) {
1093 bogus_bitmap_initialized = 1;
1094 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1095 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1096 bogus_bitmap.bm_data = bogus_data;
1097 c = gr_find_closest_color( 0, 0, 63 );
1098 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1099 c = gr_find_closest_color( 63, 0, 0 );
1100 // Make a big red X !
1101 for (i=0; i<64; i++ ) {
1102 bogus_data[i*64+i] = c;
1103 bogus_data[i*64+(63-i)] = c;
1105 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1106 bogus_sound.length = 64*64;
1107 bogus_sound.data = bogus_data;
1108 GameBitmapOffset[0] = 0;
1111 if ( FindArg( "-bigpig" ))
1114 if ( FindArg( "-lowmem" ))
1115 piggy_low_memory = 1;
1117 if ( FindArg( "-nolowmem" ))
1118 piggy_low_memory = 0;
1120 if (piggy_low_memory)
1123 WIN(DDGRLOCK(dd_grd_curcanv));
1124 gr_set_curfont( SMALL_FONT );
1125 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1126 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1127 WIN(DDGRUNLOCK(dd_grd_curcanv));
1130 piggy_init_pigfile(DEFAULT_PIGFILE);
1133 ham_ok = read_hamfile();
1135 snd_ok = read_sndfile();
1137 atexit(piggy_close);
1139 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1140 return (ham_ok && snd_ok); //read ok
1143 int piggy_is_needed(int soundnum)
1147 if ( !digi_lomem ) return 1;
1149 for (i=0; i<MAX_SOUNDS; i++ ) {
1150 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1157 void piggy_read_sounds(void)
1170 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1172 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1173 fp = cfopen( name, "rb");
1179 for (i=0; i<Num_sound_files; i++ ) {
1180 digi_sound *snd = &GameSounds[i];
1182 if ( SoundOffset[i] > 0 ) {
1183 if ( piggy_is_needed(i) ) {
1184 cfseek( fp, SoundOffset[i], SEEK_SET );
1186 // Read in the sound data!!!
1189 sbytes += snd->length;
1190 cfread( snd->data, snd->length, 1, fp );
1193 snd->data = (ubyte *) -1;
1199 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1204 extern int descent_critical_error;
1205 extern unsigned descent_critical_deverror;
1206 extern unsigned descent_critical_errcode;
1208 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1209 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1210 "Read fault", "General Failure" };
1212 void piggy_critical_error()
1214 grs_canvas * save_canv;
1215 grs_font * save_font;
1217 save_canv = grd_curcanv;
1218 save_font = grd_curcanv->cv_font;
1219 gr_palette_load( gr_palette );
1220 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1223 gr_set_current_canvas(save_canv);
1224 grd_curcanv->cv_font = save_font;
1227 void piggy_bitmap_page_in( bitmap_index bitmap )
1236 Assert( i < MAX_BITMAP_FILES );
1237 Assert( i < Num_bitmap_files );
1238 Assert( Piggy_bitmap_cache_size > 0 );
1240 if ( i < 1 ) return;
1241 if ( i >= MAX_BITMAP_FILES ) return;
1242 if ( i >= Num_bitmap_files ) return;
1244 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1246 if ( piggy_low_memory ) {
1248 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1251 bmp = &GameBitmaps[i];
1253 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1257 descent_critical_error = 0;
1258 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1259 if ( descent_critical_error ) {
1260 piggy_critical_error();
1264 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1265 bmp->bm_flags = GameBitmapFlags[i];
1267 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1269 descent_critical_error = 0;
1270 zsize = cfile_read_int(Piggy_fp);
1271 if ( descent_critical_error ) {
1272 piggy_critical_error();
1276 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1277 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1278 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1280 piggy_bitmap_page_out_all();
1283 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1284 Piggy_bitmap_cache_next += sizeof(int);
1285 descent_critical_error = 0;
1286 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1287 if ( descent_critical_error ) {
1288 piggy_critical_error();
1291 Piggy_bitmap_cache_next += zsize-4;
1293 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1294 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1295 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1296 piggy_bitmap_page_out_all();
1299 descent_critical_error = 0;
1300 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1301 if ( descent_critical_error ) {
1302 piggy_critical_error();
1305 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1308 //@@if ( bmp->bm_selector ) {
1309 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1310 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1311 //@@ Error( "Error modifying selector base in piggy.c\n" );
1318 if ( piggy_low_memory ) {
1320 GameBitmaps[org_i] = GameBitmaps[i];
1323 //@@Removed from John's code:
1325 //@@ if ( bmp->bm_selector ) {
1326 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1327 //@@ Error( "Error modifying selector base in piggy.c\n" );
1333 void piggy_bitmap_page_out_all()
1337 Piggy_bitmap_cache_next = 0;
1339 piggy_page_flushed++;
1344 for (i=0; i<Num_bitmap_files; i++ ) {
1345 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1346 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1347 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1351 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1354 void piggy_load_level_data()
1356 piggy_bitmap_page_out_all();
1362 void change_filename_ext( char *dest, char *src, char *ext );
1364 void piggy_write_pigfile(char *filename)
1367 int bitmap_data_start,data_offset;
1368 DiskBitmapHeader bmh;
1370 char subst_name[32];
1373 char tname[FILENAME_LEN];
1375 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1376 for (i=0; i < Num_bitmap_files; i++ ) {
1379 PIGGY_PAGE_IN( bi );
1381 // -- mprintf( (0, "\n" ));
1385 // -- mprintf( (0, "Creating %s...",filename ));
1387 pig_fp = fopen( filename, "wb" ); //open PIG file
1388 Assert( pig_fp!=NULL );
1390 write_int(PIGFILE_ID,pig_fp);
1391 write_int(PIGFILE_VERSION,pig_fp);
1394 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1397 bitmap_data_start = ftell(pig_fp);
1398 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1399 data_offset = bitmap_data_start;
1401 change_filename_ext(tname,filename,"lst");
1402 fp1 = fopen( tname, "wt" );
1403 change_filename_ext(tname,filename,"all");
1404 fp2 = fopen( tname, "wt" );
1406 for (i=1; i < Num_bitmap_files; i++ ) {
1412 p = strchr(AllBitmaps[i].name,'#');
1419 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1420 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1422 bmh.dflags = DBM_FLAG_ABM + n;
1426 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1427 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1431 bmp = &GameBitmaps[i];
1433 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1436 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1437 org_offset = ftell(pig_fp);
1438 bmh.offset = data_offset - bitmap_data_start;
1439 fseek( pig_fp, data_offset, SEEK_SET );
1441 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1442 size = (int *)bmp->bm_data;
1443 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1444 data_offset += *size;
1446 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1448 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1449 data_offset += bmp->bm_rowsize * bmp->bm_h;
1451 fprintf( fp1, ".\n" );
1453 fseek( pig_fp, org_offset, SEEK_SET );
1454 Assert( GameBitmaps[i].bm_w < 4096 );
1455 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1456 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1457 Assert( GameBitmaps[i].bm_h < 4096 );
1458 bmh.height = GameBitmaps[i].bm_h;
1459 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1460 bmh.flags = GameBitmaps[i].bm_flags;
1461 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1462 bitmap_index other_bitmap;
1463 other_bitmap = piggy_find_bitmap( subst_name );
1464 GameBitmapXlat[i] = other_bitmap.index;
1465 bmh.flags |= BM_FLAG_PAGED_OUT;
1466 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1467 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1469 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1471 bmh.avg_color=GameBitmaps[i].avg_color;
1472 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1477 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1478 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1485 static void write_int(int i,FILE *file)
1487 if (fwrite( &i, sizeof(i), 1, file) != 1)
1488 Error( "Error reading int in gamesave.c" );
1492 void piggy_dump_all()
1496 int org_offset,data_offset=0;
1497 DiskSoundHeader sndh;
1498 int sound_data_start=0;
1501 #ifdef NO_DUMP_SOUNDS
1502 Num_sound_files = 0;
1503 Num_sound_files_new = 0;
1506 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1509 fp1 = fopen( "ham.lst", "wt" );
1510 fp2 = fopen( "ham.all", "wt" );
1512 if (Must_write_hamfile || Num_bitmap_files_new) {
1514 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1516 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1517 Assert( ham_fp!=NULL );
1519 write_int(HAMFILE_ID,ham_fp);
1520 write_int(HAMFILE_VERSION,ham_fp);
1522 bm_write_all(ham_fp);
1523 xlat_offset = ftell(ham_fp);
1524 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1527 if (Num_bitmap_files_new)
1528 piggy_write_pigfile(DEFAULT_PIGFILE);
1530 //free up memeory used by new bitmaps
1531 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1532 d_free(GameBitmaps[i].bm_data);
1534 //next thing must be done after pig written
1535 fseek( ham_fp, xlat_offset, SEEK_SET );
1536 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1539 mprintf( (0, "\n" ));
1542 if (Num_sound_files_new) {
1544 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1545 // Now dump sound file
1546 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1547 Assert( ham_fp!=NULL );
1549 write_int(SNDFILE_ID,ham_fp);
1550 write_int(SNDFILE_VERSION,ham_fp);
1552 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1554 mprintf( (0, "\nDumping sounds..." ));
1556 sound_data_start = ftell(ham_fp);
1557 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1558 data_offset = sound_data_start;
1560 for (i=0; i < Num_sound_files; i++ ) {
1563 snd = &GameSounds[i];
1564 strcpy( sndh.name, AllSounds[i].name );
1565 sndh.length = GameSounds[i].length;
1566 sndh.offset = data_offset - sound_data_start;
1568 org_offset = ftell(ham_fp);
1569 fseek( ham_fp, data_offset, SEEK_SET );
1571 sndh.data_length = GameSounds[i].length;
1572 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1573 data_offset += snd->length;
1574 fseek( ham_fp, org_offset, SEEK_SET );
1575 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1577 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1578 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1582 mprintf( (0, "\n" ));
1585 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1586 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1587 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1592 // Never allow the game to run after building ham.
1606 d_free( SoundBits );
1608 hashtable_free( &AllBitmapsNames );
1609 hashtable_free( &AllDigiSndNames );
1613 int piggy_does_bitmap_exist_slow( char * name )
1617 for (i=0; i<Num_bitmap_files; i++ ) {
1618 if ( !strcmp( AllBitmaps[i].name, name) )
1625 #define NUM_GAUGE_BITMAPS 23
1626 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1627 "gauge01", "gauge01b",
1628 "gauge02", "gauge02b",
1629 "gauge06", "gauge06b",
1630 "targ01", "targ01b",
1631 "targ02", "targ02b",
1632 "targ03", "targ03b",
1633 "targ04", "targ04b",
1634 "targ05", "targ05b",
1635 "targ06", "targ06b",
1636 "gauge18", "gauge18b",
1642 int piggy_is_gauge_bitmap( char * base_name )
1645 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1646 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1653 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1657 char base_name[ 16 ];
1659 strcpy( subst_name, name );
1660 p = strchr( subst_name, '#' );
1662 frame = atoi( &p[1] );
1664 strcpy( base_name, subst_name );
1665 if ( !piggy_is_gauge_bitmap( base_name )) {
1666 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1667 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1669 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1675 strcpy( subst_name, name );
1682 // New Windows stuff
1684 // windows bitmap page in
1685 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1686 // 'video' memory. if that fails, page it in normally.
1688 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1693 // Essential when switching video modes!
1695 void piggy_bitmap_page_out_all_w()
1702 * reads a bitmap_index structure from a CFILE
1704 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
1706 bi->index = cfile_read_short(fp);
1710 * reads a DiskBitmapHeader structure from a CFILE
1712 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
1714 cfread(dbh->name, 8, 1, fp);
1715 dbh->dflags = cfile_read_byte(fp);
1716 dbh->width = cfile_read_byte(fp);
1717 dbh->height = cfile_read_byte(fp);
1718 dbh->wh_extra = cfile_read_byte(fp);
1719 dbh->flags = cfile_read_byte(fp);
1720 dbh->avg_color = cfile_read_byte(fp);
1721 dbh->offset = cfile_read_int(fp);