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.8 2002-07-26 09:22:05 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 DiskBitmapHeader {
139 ubyte dflags; //bits 0-5 anim frame num, bit 6 abm flag
140 ubyte width; //low 8 bits here, 4 more bits in wh_extra
141 ubyte height; //low 8 bits here, 4 more bits in wh_extra
142 ubyte wh_extra; //bits 0-3 width, bits 4-7 height
146 } __pack__ DiskBitmapHeader;
148 typedef struct DiskSoundHeader {
153 } __pack__ DiskSoundHeader;
158 extern short cd_VRefNum;
159 extern void ConcatPStr(StringPtr dst, StringPtr src);
160 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
161 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
164 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
167 void piggy_write_pigfile(char *filename);
168 static void write_int(int i,FILE *file);
170 void swap_0_255(grs_bitmap *bmp)
174 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
175 if(bmp->bm_data[i] == 0)
176 bmp->bm_data[i] = 255;
177 else if (bmp->bm_data[i] == 255)
183 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
186 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
188 temp.index = Num_bitmap_files;
192 if ( FindArg("-macdata") )
195 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
196 Num_bitmap_files_new++;
199 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
200 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
201 GameBitmaps[Num_bitmap_files] = *bmp;
203 GameBitmapOffset[Num_bitmap_files] = 0;
204 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
211 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
215 Assert( Num_sound_files < MAX_SOUND_FILES );
217 strncpy( AllSounds[Num_sound_files].name, name, 12 );
218 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
219 GameSounds[Num_sound_files] = *snd;
221 SoundOffset[Num_sound_files] = 0;
227 Num_sound_files_new++;
233 bitmap_index piggy_find_bitmap( char * name )
241 if ((t=strchr(name,'#'))!=NULL)
244 for (i=0;i<Num_aliases;i++)
245 if (stricmp(name,alias_list[i].alias_name)==0) {
246 if (t) { //extra stuff for ABMs
247 static char temp[FILENAME_LEN];
248 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
254 name=alias_list[i].file_name;
261 i = hashtable_search( &AllBitmapsNames, name );
270 int piggy_find_sound( char * name )
274 i = hashtable_search( &AllDigiSndNames, name );
282 CFILE * Piggy_fp = NULL;
284 #define FILENAME_LEN 13
286 char Current_pigfile[FILENAME_LEN] = "";
288 void piggy_close_file()
293 Current_pigfile[0] = 0;
297 int Pigfile_initialized=0;
299 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
300 #define PIGFILE_VERSION 2
302 extern char CDROM_dir[];
304 int request_cd(void);
309 //copies a pigfile from the CD to the current dir
310 //retuns file handle of new pig
311 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
314 char sourcePathAndFileCStr[255] = "";
315 char destPathAndFileCStr[255] = "";
317 FILE* sourceFile = NULL;
318 FILE* destFile = NULL;
319 const int BUF_SIZE = 4096;
323 Str255 sourcePathAndFilePStr = "\p";
324 Str255 destPathAndFilePStr = "\p";
325 Str255 pigfileNamePStr = "\p";
326 HParamBlockRec theSourcePigHFSParams;
327 HParamBlockRec theDestPigHFSParams;
328 OSErr theErr = noErr;
329 char oldDirCStr[255] = "";
331 getcwd(oldDirCStr, 255);
333 show_boxed_message("Copying bitmap data from CD...");
334 gr_palette_load(gr_palette); //I don't think this line is really needed
337 //First, delete all PIG files currently in the directory
338 if( !FileFindFirst( "*.pig", &find ) )
343 } while( !FileFindNext( &find ) );
349 //Now, copy over new pig
350 songs_stop_redbook(); //so we can read off the cd
352 // make the source path "<cd volume>:Data:filename.pig"
353 //MWA ConvertCToPStr(filename, pigfileNamePStr);
355 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
356 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
359 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
360 strcat(sourcePathAndFileCStr, filename);
362 // make the destination path "<default directory>:Data:filename.pig"
363 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
364 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
365 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
366 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
368 strcpy(destPathAndFileCStr, ":Data:");
369 strcat(destPathAndFileCStr, filename);
371 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
372 strcpy(destPathAndFilePStr, destPathAndFileCStr);
373 c2pstr(sourcePathAndFilePStr);
374 c2pstr(destPathAndFilePStr);
377 // Open the source file
378 sourceFile = fopen(sourcePathAndFileCStr,"rb");
382 if (request_cd() == -1)
383 Error("Cannot load file <%s> from CD",filename);
386 } while (!sourceFile);
389 // Get the time stamp from the source file
390 theSourcePigHFSParams.fileParam.ioCompletion = nil;
391 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
392 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
393 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
394 theSourcePigHFSParams.fileParam.ioDirID = 0;
396 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
399 // Error getting file time stamp!! Why? JTS
400 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
403 // Copy the file over
406 // Open the destination file
407 destFile = fopen(destPathAndFileCStr,"wb");
410 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
413 // Copy bytes until the end of the source file
414 while (!feof(sourceFile))
419 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
420 if (ferror(sourceFile))
421 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
423 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
425 fwrite(buf,1,bytes_read,destFile);
426 if (ferror(destFile))
427 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
430 // close the source/dest files
431 if (fclose(sourceFile))
432 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
433 if (fclose(destFile))
434 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
436 // Get the current hfs data for the new file
437 theDestPigHFSParams.fileParam.ioCompletion = nil;
438 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
439 theDestPigHFSParams.fileParam.ioVRefNum = 0;
440 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
441 theDestPigHFSParams.fileParam.ioDirID = 0;
442 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
443 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
445 // Error getting file time stamp!! Why? JTS
446 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
449 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
450 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
451 theDestPigHFSParams.fileParam.ioVRefNum = 0;
452 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
453 theDestPigHFSParams.fileParam.ioDirID = 0;
455 // Copy the time stamp from the source file info
456 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
457 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
458 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
459 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
461 // Set the dest file's time stamp to the source file's time stamp values
462 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
464 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
466 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
469 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
471 return cfopen(destPathAndFileCStr, "rb");
474 #else //PC Version of copy_pigfile_from_cd is below
476 //copies a pigfile from the CD to the current dir
477 //retuns file handle of new pig
478 CFILE *copy_pigfile_from_cd(char *filename)
484 return cfopen(filename, "rb");
485 show_boxed_message("Copying bitmap data from CD...");
486 gr_palette_load(gr_palette); //I don't think this line is really needed
488 //First, delete all PIG files currently in the directory
490 if( !FileFindFirst( "*.pig", &find ) ) {
493 } while( !FileFindNext( &find ) );
497 //Now, copy over new pig
499 songs_stop_redbook(); //so we can read off the cd
501 //new code to unarj file
502 strcpy(name,CDROM_dir);
503 strcat(name,"descent2.sow");
506 // ret = unarj_specific_file(name,filename,filename);
511 if (ret != EXIT_SUCCESS) {
513 //delete file, so we don't leave partial file
517 if (request_cd() == -1)
519 //NOTE LINK TO ABOVE IF
520 Error("Cannot load file <%s> from CD",filename);
523 } while (ret != EXIT_SUCCESS);
525 return cfopen(filename, "rb");
528 #endif // end of ifdef MAC around copy_pigfile_from_cd
530 //initialize a pigfile, reading headers
531 //returns the size of all the bitmap data
532 void piggy_init_pigfile(char *filename)
536 char temp_name_read[16];
537 grs_bitmap temp_bitmap;
538 DiskBitmapHeader bmh;
539 int header_size, N_bitmaps, data_size, data_start;
541 char name[255]; // filename + path for the mac
544 piggy_close_file(); //close old pig if still open
546 #ifdef SHAREWARE //rename pigfile for shareware
547 if (stricmp(filename,DEFAULT_PIGFILE_REGISTERED)==0)
548 filename = DEFAULT_PIGFILE_SHAREWARE;
552 Piggy_fp = cfopen( filename, "rb" );
554 sprintf(name, ":Data:%s", filename);
555 Piggy_fp = cfopen( name, "rb" );
557 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
558 if (Piggy_fp == NULL)
560 Error("Cannot load required file <%s>",name);
562 #endif // end of if def shareware
568 return; //if editor, ok to not have pig, because we'll build one
570 Piggy_fp = copy_pigfile_from_cd(filename);
574 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
575 int pig_id,pig_version;
577 pig_id = cfile_read_int(Piggy_fp);
578 pig_version = cfile_read_int(Piggy_fp);
579 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
580 cfclose(Piggy_fp); //out of date pig
581 Piggy_fp = NULL; //..so pretend it's not here
588 return; //if editor, ok to not have pig, because we'll build one
590 Error("Cannot load required file <%s>",filename);
594 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
596 N_bitmaps = cfile_read_int(Piggy_fp);
598 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
600 data_start = header_size + cftell(Piggy_fp);
602 data_size = cfilelength(Piggy_fp) - data_start;
604 Num_bitmap_files = 1;
606 for (i=0; i<N_bitmaps; i++ ) {
608 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
610 cfread(bmh.name, 8, 1, Piggy_fp);
611 bmh.dflags = cfile_read_byte(Piggy_fp);
612 bmh.width = cfile_read_byte(Piggy_fp);
613 bmh.height = cfile_read_byte(Piggy_fp);
614 bmh.wh_extra = cfile_read_byte(Piggy_fp);
615 bmh.flags = cfile_read_byte(Piggy_fp);
616 bmh.avg_color = cfile_read_byte(Piggy_fp);
617 bmh.offset = cfile_read_int(Piggy_fp);
619 memcpy( temp_name_read, bmh.name, 8 );
620 temp_name_read[8] = 0;
621 if ( bmh.dflags & DBM_FLAG_ABM )
622 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
624 strcpy( temp_name, temp_name_read );
625 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
626 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
627 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
628 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
629 temp_bitmap.avg_color = bmh.avg_color;
630 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
632 GameBitmapFlags[i+1] = 0;
633 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
634 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
635 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
636 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
637 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
639 GameBitmapOffset[i+1] = bmh.offset + data_start;
640 Assert( (i+1) == Num_bitmap_files );
641 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
645 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
646 Assert( Piggy_bitmap_cache_size > 0 );
648 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
650 if (piggy_low_memory)
651 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
654 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
655 if ( BitmapBits == NULL )
656 Error( "Not enough memory to load bitmaps\n" );
657 Piggy_bitmap_cache_data = BitmapBits;
658 Piggy_bitmap_cache_next = 0;
660 #if defined(MACINTOSH) && defined(SHAREWARE)
661 // load_exit_models();
664 Pigfile_initialized=1;
667 #define FILENAME_LEN 13
668 #define MAX_BITMAPS_PER_BRUSH 30
670 extern int compute_average_pixel(grs_bitmap *new);
672 //reads in a new pigfile (for new palette)
673 //returns the size of all the bitmap data
674 void piggy_new_pigfile(char *pigname)
678 char temp_name_read[16];
679 grs_bitmap temp_bitmap;
680 DiskBitmapHeader bmh;
681 int header_size, N_bitmaps, data_size, data_start;
682 int must_rewrite_pig = 0;
689 #ifdef SHAREWARE //rename pigfile for shareware
690 if (stricmp(pigname,DEFAULT_PIGFILE_REGISTERED)==0)
691 pigname = DEFAULT_PIGFILE_SHAREWARE;
694 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
695 return; //already have correct pig
697 if (!Pigfile_initialized) { //have we ever opened a pigfile?
698 piggy_init_pigfile(pigname); //..no, so do initialization stuff
702 piggy_close_file(); //close old pig if still open
704 Piggy_bitmap_cache_next = 0; //free up cache
706 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
709 Piggy_fp = cfopen( pigname, "rb" );
711 sprintf(name, ":Data:%s", pigname);
712 Piggy_fp = cfopen( name, "rb" );
714 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
715 if (Piggy_fp == NULL)
717 Error("Cannot load required file <%s>",name);
719 #endif // end of if def shareware
724 Piggy_fp = copy_pigfile_from_cd(pigname);
727 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
728 int pig_id,pig_version;
730 pig_id = cfile_read_int(Piggy_fp);
731 pig_version = cfile_read_int(Piggy_fp);
732 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
733 cfclose(Piggy_fp); //out of date pig
734 Piggy_fp = NULL; //..so pretend it's not here
739 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
744 N_bitmaps = cfile_read_int(Piggy_fp);
746 header_size = N_bitmaps*sizeof(DiskBitmapHeader);
748 data_start = header_size + cftell(Piggy_fp);
750 data_size = cfilelength(Piggy_fp) - data_start;
752 for (i=1; i<=N_bitmaps; i++ ) {
754 cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp );
756 cfread(bmh.name, 8, 1, Piggy_fp);
757 bmh.dflags = cfile_read_byte(Piggy_fp);
758 bmh.width = cfile_read_byte(Piggy_fp);
759 bmh.height = cfile_read_byte(Piggy_fp);
760 bmh.wh_extra = cfile_read_byte(Piggy_fp);
761 bmh.flags = cfile_read_byte(Piggy_fp);
762 bmh.avg_color = cfile_read_byte(Piggy_fp);
763 bmh.offset = cfile_read_int(Piggy_fp);
765 memcpy( temp_name_read, bmh.name, 8 );
766 temp_name_read[8] = 0;
768 if ( bmh.dflags & DBM_FLAG_ABM )
769 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
771 strcpy( temp_name, temp_name_read );
773 //Make sure name matches
774 if (strcmp(temp_name,AllBitmaps[i].name)) {
775 //Int3(); //this pig is out of date. Delete it
779 strcpy(AllBitmaps[i].name,temp_name);
781 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
783 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
784 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
785 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
786 temp_bitmap.avg_color = bmh.avg_color;
787 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
789 GameBitmapFlags[i] = 0;
791 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
792 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
793 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
794 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
795 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
797 GameBitmapOffset[i] = bmh.offset + data_start;
799 GameBitmaps[i] = temp_bitmap;
803 N_bitmaps = 0; //no pigfile, so no bitmaps
807 Assert(N_bitmaps == Num_bitmap_files-1);
811 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
814 //re-read the bitmaps that aren't in this pig
816 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
819 p = strchr(AllBitmaps[i].name,'#');
821 if (p) { //this is an ABM
822 char abmname[FILENAME_LEN];
824 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
825 int iff_error; //reference parm to avoid warning message
827 char basename[FILENAME_LEN];
830 strcpy(basename,AllBitmaps[i].name);
831 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
833 sprintf( abmname, "%s.abm", basename );
835 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
837 if (iff_error != IFF_NO_ERROR) {
838 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
839 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
842 for (fnum=0;fnum<nframes; fnum++) {
846 sprintf( tempname, "%s#%d", basename, fnum );
848 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
849 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
850 //above makes assumption that supertransparent color is 254
852 if ( iff_has_transparency )
853 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
855 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
857 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
860 if ( FindArg("-macdata") )
861 swap_0_255( bm[fnum] );
863 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
865 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
866 size = *((int *) bm[fnum]->bm_data);
868 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
870 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
871 d_free(bm[fnum]->bm_data);
872 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
873 Piggy_bitmap_cache_next += size;
875 GameBitmaps[i+fnum] = *bm[fnum];
877 // -- mprintf( (0, "U" ));
881 i += nframes-1; //filled in multiple bitmaps
883 else { //this is a BBM
888 char bbmname[FILENAME_LEN];
891 MALLOC( new, grs_bitmap, 1 );
893 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
894 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
897 if (iff_error != IFF_NO_ERROR) {
898 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
899 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
902 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
903 //above makes assumption that supertransparent color is 254
905 if ( iff_has_transparency )
906 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
908 gr_remap_bitmap_good( new, newpal, -1, SuperX );
910 new->avg_color = compute_average_pixel(new);
913 if ( FindArg("-macdata") )
916 if ( !BigPig ) gr_bitmap_rle_compress( new );
918 if (new->bm_flags & BM_FLAG_RLE)
919 size = *((int *) new->bm_data);
921 size = new->bm_w * new->bm_h;
923 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
924 d_free(new->bm_data);
925 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
926 Piggy_bitmap_cache_next += size;
928 GameBitmaps[i] = *new;
932 // -- mprintf( (0, "U" ));
936 //@@Dont' do these things which are done when writing
937 //@@for (i=0; i < Num_bitmap_files; i++ ) {
938 //@@ bitmap_index bi;
940 //@@ PIGGY_PAGE_IN( bi );
943 //@@piggy_close_file();
945 piggy_write_pigfile(pigname);
947 Current_pigfile[0] = 0; //say no pig, to force reload
949 piggy_new_pigfile(pigname); //read in just-generated pig
953 #endif //ifdef EDITOR
957 ubyte bogus_data[64*64];
958 grs_bitmap bogus_bitmap;
959 ubyte bogus_bitmap_initialized=0;
960 digi_sound bogus_sound;
962 extern void bm_read_all(CFILE * fp);
964 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
966 #define HAMFILE_VERSION 2
968 #define HAMFILE_VERSION 3
970 //version 1 -> 2: save marker_model_num
971 //version 2 -> 3: removed sound files
973 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
974 #define SNDFILE_VERSION 1
978 CFILE * ham_fp = NULL;
979 int ham_id,ham_version;
985 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
987 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
988 ham_fp = cfopen( name, "rb" );
991 if (ham_fp == NULL) {
992 Must_write_hamfile = 1;
996 //make sure ham is valid type file & is up-to-date
997 ham_id = cfile_read_int(ham_fp);
998 ham_version = cfile_read_int(ham_fp);
999 if (ham_id != HAMFILE_ID || ham_version != HAMFILE_VERSION) {
1000 Must_write_hamfile = 1;
1001 cfclose(ham_fp); //out of date ham
1005 if (ham_version < 3) //mystery value
1006 cfseek(ham_fp, 4, SEEK_CUR);
1010 bm_read_all( ham_fp ); // Note connection to above if!!!
1011 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1016 for (i = 0; i < MAX_BITMAP_FILES; i++)
1017 GameBitmapXlat[i] = SWAPSHORT(GameBitmapXlat[i]);
1031 CFILE * snd_fp = NULL;
1032 int snd_id,snd_version;
1037 DiskSoundHeader sndh;
1038 digi_sound temp_sound;
1039 char temp_name_read[16];
1046 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1048 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1049 snd_fp = cfopen( name, "rb");
1055 //make sure soundfile is valid type file & is up-to-date
1056 snd_id = cfile_read_int(snd_fp);
1057 snd_version = cfile_read_int(snd_fp);
1058 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1059 cfclose(snd_fp); //out of date sound file
1063 N_sounds = cfile_read_int(snd_fp);
1065 sound_start = cftell(snd_fp);
1066 size = cfilelength(snd_fp) - sound_start;
1068 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1070 header_size = N_sounds*sizeof(DiskSoundHeader);
1074 for (i=0; i<N_sounds; i++ ) {
1075 cfread( sndh.name, 8, 1, snd_fp);
1076 sndh.length = cfile_read_int(snd_fp);
1077 sndh.data_length = cfile_read_int(snd_fp);
1078 sndh.offset = cfile_read_int(snd_fp);
1079 // cfread( &sndh, sizeof(DiskSoundHeader), 1, snd_fp );
1080 //size -= sizeof(DiskSoundHeader);
1081 temp_sound.length = sndh.length;
1082 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1083 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1084 memcpy( temp_name_read, sndh.name, 8 );
1085 temp_name_read[8] = 0;
1086 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1088 if (piggy_is_needed(i))
1089 #endif // note link to if.
1090 sbytes += sndh.length;
1091 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1094 SoundBits = d_malloc( sbytes + 16 );
1095 if ( SoundBits == NULL )
1096 Error( "Not enough memory to load sounds\n" );
1098 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1100 // piggy_read_sounds(snd_fp);
1107 int piggy_init(void)
1109 int ham_ok=0,snd_ok=0;
1112 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1113 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1115 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1116 GameSounds[i].length = 0;
1117 GameSounds[i].data = NULL;
1121 for (i=0; i<MAX_BITMAP_FILES; i++ )
1122 GameBitmapXlat[i] = i;
1124 if ( !bogus_bitmap_initialized ) {
1127 bogus_bitmap_initialized = 1;
1128 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1129 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1130 bogus_bitmap.bm_data = bogus_data;
1131 c = gr_find_closest_color( 0, 0, 63 );
1132 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1133 c = gr_find_closest_color( 63, 0, 0 );
1134 // Make a big red X !
1135 for (i=0; i<64; i++ ) {
1136 bogus_data[i*64+i] = c;
1137 bogus_data[i*64+(63-i)] = c;
1139 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1140 bogus_sound.length = 64*64;
1141 bogus_sound.data = bogus_data;
1142 GameBitmapOffset[0] = 0;
1145 if ( FindArg( "-bigpig" ))
1148 if ( FindArg( "-lowmem" ))
1149 piggy_low_memory = 1;
1151 if ( FindArg( "-nolowmem" ))
1152 piggy_low_memory = 0;
1154 if (piggy_low_memory)
1157 WIN(DDGRLOCK(dd_grd_curcanv));
1158 gr_set_curfont( SMALL_FONT );
1159 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1160 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1161 WIN(DDGRUNLOCK(dd_grd_curcanv));
1164 piggy_init_pigfile(DEFAULT_PIGFILE);
1167 ham_ok = read_hamfile();
1169 snd_ok = read_sndfile();
1171 atexit(piggy_close);
1173 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1174 return (ham_ok && snd_ok); //read ok
1177 int piggy_is_needed(int soundnum)
1181 if ( !digi_lomem ) return 1;
1183 for (i=0; i<MAX_SOUNDS; i++ ) {
1184 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1191 void piggy_read_sounds(void)
1204 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1206 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1207 fp = cfopen( name, "rb");
1213 for (i=0; i<Num_sound_files; i++ ) {
1214 digi_sound *snd = &GameSounds[i];
1216 if ( SoundOffset[i] > 0 ) {
1217 if ( piggy_is_needed(i) ) {
1218 cfseek( fp, SoundOffset[i], SEEK_SET );
1220 // Read in the sound data!!!
1223 sbytes += snd->length;
1224 cfread( snd->data, snd->length, 1, fp );
1227 snd->data = (ubyte *) -1;
1233 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1238 extern int descent_critical_error;
1239 extern unsigned descent_critical_deverror;
1240 extern unsigned descent_critical_errcode;
1242 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1243 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1244 "Read fault", "General Failure" };
1246 void piggy_critical_error()
1248 grs_canvas * save_canv;
1249 grs_font * save_font;
1251 save_canv = grd_curcanv;
1252 save_font = grd_curcanv->cv_font;
1253 gr_palette_load( gr_palette );
1254 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1257 gr_set_current_canvas(save_canv);
1258 grd_curcanv->cv_font = save_font;
1261 void piggy_bitmap_page_in( bitmap_index bitmap )
1270 Assert( i < MAX_BITMAP_FILES );
1271 Assert( i < Num_bitmap_files );
1272 Assert( Piggy_bitmap_cache_size > 0 );
1274 if ( i < 1 ) return;
1275 if ( i >= MAX_BITMAP_FILES ) return;
1276 if ( i >= Num_bitmap_files ) return;
1278 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1280 if ( piggy_low_memory ) {
1282 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1285 bmp = &GameBitmaps[i];
1287 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1291 descent_critical_error = 0;
1292 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1293 if ( descent_critical_error ) {
1294 piggy_critical_error();
1298 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1299 bmp->bm_flags = GameBitmapFlags[i];
1301 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1303 descent_critical_error = 0;
1304 zsize = cfile_read_int(Piggy_fp);
1305 if ( descent_critical_error ) {
1306 piggy_critical_error();
1310 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1311 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1312 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1314 piggy_bitmap_page_out_all();
1317 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1318 Piggy_bitmap_cache_next += sizeof(int);
1319 descent_critical_error = 0;
1320 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
1321 if ( descent_critical_error ) {
1322 piggy_critical_error();
1325 Piggy_bitmap_cache_next += zsize-4;
1327 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1328 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1329 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1330 piggy_bitmap_page_out_all();
1333 descent_critical_error = 0;
1334 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1335 if ( descent_critical_error ) {
1336 piggy_critical_error();
1339 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1342 //@@if ( bmp->bm_selector ) {
1343 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1344 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1345 //@@ Error( "Error modifying selector base in piggy.c\n" );
1352 if ( piggy_low_memory ) {
1354 GameBitmaps[org_i] = GameBitmaps[i];
1357 //@@Removed from John's code:
1359 //@@ if ( bmp->bm_selector ) {
1360 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1361 //@@ Error( "Error modifying selector base in piggy.c\n" );
1367 void piggy_bitmap_page_out_all()
1371 Piggy_bitmap_cache_next = 0;
1373 piggy_page_flushed++;
1378 for (i=0; i<Num_bitmap_files; i++ ) {
1379 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1380 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1381 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1385 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1388 void piggy_load_level_data()
1390 piggy_bitmap_page_out_all();
1396 void change_filename_ext( char *dest, char *src, char *ext );
1398 void piggy_write_pigfile(char *filename)
1401 int bitmap_data_start,data_offset;
1402 DiskBitmapHeader bmh;
1404 char subst_name[32];
1407 char tname[FILENAME_LEN];
1409 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1410 for (i=0; i < Num_bitmap_files; i++ ) {
1413 PIGGY_PAGE_IN( bi );
1415 // -- mprintf( (0, "\n" ));
1419 // -- mprintf( (0, "Creating %s...",filename ));
1421 pig_fp = fopen( filename, "wb" ); //open PIG file
1422 Assert( pig_fp!=NULL );
1424 write_int(PIGFILE_ID,pig_fp);
1425 write_int(PIGFILE_VERSION,pig_fp);
1428 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1431 bitmap_data_start = ftell(pig_fp);
1432 bitmap_data_start += (Num_bitmap_files-1)*sizeof(DiskBitmapHeader);
1433 data_offset = bitmap_data_start;
1435 change_filename_ext(tname,filename,"lst");
1436 fp1 = fopen( tname, "wt" );
1437 change_filename_ext(tname,filename,"all");
1438 fp2 = fopen( tname, "wt" );
1440 for (i=1; i < Num_bitmap_files; i++ ) {
1446 p = strchr(AllBitmaps[i].name,'#');
1453 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1454 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1456 bmh.dflags = DBM_FLAG_ABM + n;
1460 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1461 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1465 bmp = &GameBitmaps[i];
1467 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1470 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1471 org_offset = ftell(pig_fp);
1472 bmh.offset = data_offset - bitmap_data_start;
1473 fseek( pig_fp, data_offset, SEEK_SET );
1475 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1476 size = (int *)bmp->bm_data;
1477 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1478 data_offset += *size;
1480 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1482 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1483 data_offset += bmp->bm_rowsize * bmp->bm_h;
1485 fprintf( fp1, ".\n" );
1487 fseek( pig_fp, org_offset, SEEK_SET );
1488 Assert( GameBitmaps[i].bm_w < 4096 );
1489 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1490 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1491 Assert( GameBitmaps[i].bm_h < 4096 );
1492 bmh.height = GameBitmaps[i].bm_h;
1493 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1494 bmh.flags = GameBitmaps[i].bm_flags;
1495 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1496 bitmap_index other_bitmap;
1497 other_bitmap = piggy_find_bitmap( subst_name );
1498 GameBitmapXlat[i] = other_bitmap.index;
1499 bmh.flags |= BM_FLAG_PAGED_OUT;
1500 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1501 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1503 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1505 bmh.avg_color=GameBitmaps[i].avg_color;
1506 fwrite( &bmh, sizeof(DiskBitmapHeader), 1, pig_fp ); // Mark as a bitmap
1511 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1512 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1519 static void write_int(int i,FILE *file)
1521 if (fwrite( &i, sizeof(i), 1, file) != 1)
1522 Error( "Error reading int in gamesave.c" );
1526 void piggy_dump_all()
1530 int org_offset,data_offset=0;
1531 DiskSoundHeader sndh;
1532 int sound_data_start=0;
1535 #ifdef NO_DUMP_SOUNDS
1536 Num_sound_files = 0;
1537 Num_sound_files_new = 0;
1540 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1543 fp1 = fopen( "ham.lst", "wt" );
1544 fp2 = fopen( "ham.all", "wt" );
1546 if (Must_write_hamfile || Num_bitmap_files_new) {
1548 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1550 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1551 Assert( ham_fp!=NULL );
1553 write_int(HAMFILE_ID,ham_fp);
1554 write_int(HAMFILE_VERSION,ham_fp);
1556 bm_write_all(ham_fp);
1557 xlat_offset = ftell(ham_fp);
1558 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1561 if (Num_bitmap_files_new)
1562 piggy_write_pigfile(DEFAULT_PIGFILE);
1564 //free up memeory used by new bitmaps
1565 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1566 d_free(GameBitmaps[i].bm_data);
1568 //next thing must be done after pig written
1569 fseek( ham_fp, xlat_offset, SEEK_SET );
1570 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1573 mprintf( (0, "\n" ));
1576 if (Num_sound_files_new) {
1578 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1579 // Now dump sound file
1580 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1581 Assert( ham_fp!=NULL );
1583 write_int(SNDFILE_ID,ham_fp);
1584 write_int(SNDFILE_VERSION,ham_fp);
1586 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
1588 mprintf( (0, "\nDumping sounds..." ));
1590 sound_data_start = ftell(ham_fp);
1591 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
1592 data_offset = sound_data_start;
1594 for (i=0; i < Num_sound_files; i++ ) {
1597 snd = &GameSounds[i];
1598 strcpy( sndh.name, AllSounds[i].name );
1599 sndh.length = GameSounds[i].length;
1600 sndh.offset = data_offset - sound_data_start;
1602 org_offset = ftell(ham_fp);
1603 fseek( ham_fp, data_offset, SEEK_SET );
1605 sndh.data_length = GameSounds[i].length;
1606 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
1607 data_offset += snd->length;
1608 fseek( ham_fp, org_offset, SEEK_SET );
1609 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
1611 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
1612 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
1616 mprintf( (0, "\n" ));
1619 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
1620 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
1621 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
1626 // Never allow the game to run after building ham.
1640 d_free( SoundBits );
1642 hashtable_free( &AllBitmapsNames );
1643 hashtable_free( &AllDigiSndNames );
1647 int piggy_does_bitmap_exist_slow( char * name )
1651 for (i=0; i<Num_bitmap_files; i++ ) {
1652 if ( !strcmp( AllBitmaps[i].name, name) )
1659 #define NUM_GAUGE_BITMAPS 23
1660 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
1661 "gauge01", "gauge01b",
1662 "gauge02", "gauge02b",
1663 "gauge06", "gauge06b",
1664 "targ01", "targ01b",
1665 "targ02", "targ02b",
1666 "targ03", "targ03b",
1667 "targ04", "targ04b",
1668 "targ05", "targ05b",
1669 "targ06", "targ06b",
1670 "gauge18", "gauge18b",
1676 int piggy_is_gauge_bitmap( char * base_name )
1679 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
1680 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
1687 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
1691 char base_name[ 16 ];
1693 strcpy( subst_name, name );
1694 p = strchr( subst_name, '#' );
1696 frame = atoi( &p[1] );
1698 strcpy( base_name, subst_name );
1699 if ( !piggy_is_gauge_bitmap( base_name )) {
1700 sprintf( subst_name, "%s#%d", base_name, frame+1 );
1701 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
1703 sprintf( subst_name, "%s#%d", base_name, frame-1 );
1709 strcpy( subst_name, name );
1716 // New Windows stuff
1718 // windows bitmap page in
1719 // Page in a bitmap, if ddraw, then page it into a ddsurface in
1720 // 'video' memory. if that fails, page it in normally.
1722 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
1727 // Essential when switching video modes!
1729 void piggy_bitmap_page_out_all_w()
1736 * reads a bitmap_index structure from a CFILE
1738 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
1740 bi->index = cfile_read_short(fp);