1 /* $Id: piggy.c,v 1.24 2003-03-20 23:14:14 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Functions for managing the pig files.
20 * Revision 1.16 1995/11/09 17:27:47 allender
21 * put in missing quote on new gauge name
23 * Revision 1.15 1995/11/08 17:28:03 allender
24 * add PC gauges to gauge list of non-substitutatble bitmaps
26 * Revision 1.14 1995/11/08 15:14:49 allender
27 * fixed horrible bug where the piggy cache size was incorrect
30 * Revision 1.13 1995/11/03 12:53:37 allender
33 * Revision 1.12 1995/10/21 22:25:14 allender
34 * added bald guy cheat
36 * Revision 1.11 1995/10/20 22:42:15 allender
37 * changed load path of descent.pig to :data:descent.pig
39 * Revision 1.10 1995/10/20 00:08:01 allender
40 * put in event loop calls when loading data (hides it nicely
41 * from user) so TM can get it's strokes stuff
43 * Revision 1.9 1995/09/13 08:48:01 allender
44 * added lower memory requirement to load alternate bitmaps
46 * Revision 1.8 1995/08/16 09:39:13 allender
47 * moved "loading" text up a little
49 * Revision 1.7 1995/08/08 13:54:26 allender
50 * added macsys header file
52 * Revision 1.6 1995/07/12 12:49:56 allender
53 * total hack for bitmaps > 512 bytes wide -- check these by name
55 * Revision 1.5 1995/07/05 16:47:05 allender
58 * Revision 1.4 1995/06/23 08:55:28 allender
59 * make "loading data" text y loc based off of curcanv
61 * Revision 1.3 1995/06/08 14:08:52 allender
62 * PPC aligned data sets
64 * Revision 1.2 1995/05/26 06:54:27 allender
65 * removed refences to sound data at end of pig file (since they will
66 * now be Macintosh snd resources for effects
68 * Revision 1.1 1995/05/16 15:29:51 allender
71 * Revision 2.10 1995/10/07 13:17:26 john
72 * Made all bitmaps paged out by default.
74 * Revision 2.9 1995/04/14 14:05:24 john
75 * *** empty log message ***
77 * Revision 2.8 1995/04/12 13:39:37 john
78 * Fixed bug with -lowmem not working.
80 * Revision 2.7 1995/03/29 23:23:17 john
81 * Fixed major bug with sounds not building into pig right.
83 * Revision 2.6 1995/03/28 18:05:00 john
84 * Fixed it so you don't have to delete pig after changing bitmaps.tbl
86 * Revision 2.5 1995/03/16 23:13:06 john
87 * Fixed bug with piggy paging in bitmap not checking for disk
88 * error, hence bogifying textures if you pull the CD out.
90 * Revision 2.4 1995/03/14 16:22:27 john
91 * Added cdrom alternate directory stuff.
93 * Revision 2.3 1995/03/06 15:23:20 john
94 * New screen techniques.
96 * Revision 2.2 1995/02/27 13:13:40 john
97 * Removed floating point.
99 * Revision 2.1 1995/02/27 12:31:25 john
100 * Made work without editor.
102 * Revision 2.0 1995/02/27 11:28:02 john
103 * New version 2.0, which has no anonymous unions, builds with
104 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
106 * Revision 1.85 1995/02/09 12:54:24 john
107 * Made paged out bitmaps have bm_data be a valid pointer
108 * instead of NULL, in case anyone accesses it.
110 * Revision 1.84 1995/02/09 12:50:59 john
111 * Bullet-proofed the piggy loading code.
113 * Revision 1.83 1995/02/07 17:08:51 john
114 * Added some error handling stuff instead of asserts.
116 * Revision 1.82 1995/02/03 17:06:48 john
117 * Changed sound stuff to allow low memory usage.
118 * Also, changed so that Sounds isn't an array of digi_sounds, it
119 * is a ubyte pointing into GameSounds, this way the digi.c code that
120 * locks sounds won't accidentally unlock a sound that is already playing, but
121 * since it's Sounds[soundno] is different, it would erroneously be unlocked.
123 * Revision 1.81 1995/02/02 21:56:39 matt
124 * Added data for new gauge bitmaps
126 * Revision 1.80 1995/02/01 23:31:57 john
127 * Took out loading bar.
129 * Revision 1.79 1995/01/28 15:13:18 allender
130 * bumped up Piggy_bitmap_cache_size
132 * Revision 1.78 1995/01/26 12:30:43 john
135 * Revision 1.77 1995/01/26 12:12:17 john
136 * Made buffer be big for bitmaps.
138 * Revision 1.76 1995/01/25 20:15:38 john
139 * Made editor allocate all mem.
141 * Revision 1.75 1995/01/25 14:52:56 john
142 * Made bitmap buffer be 1.5 MB.
144 * Revision 1.74 1995/01/22 16:03:19 mike
147 * Revision 1.73 1995/01/22 15:58:36 mike
150 * Revision 1.72 1995/01/18 20:51:20 john
153 * Revision 1.71 1995/01/18 20:47:21 john
154 * Added code to allocate sounds & bitmaps into diff
155 * buffers, also made sounds not be compressed for registered.
157 * Revision 1.70 1995/01/18 15:08:41 john
158 * Added start/stop time around paging.
159 * Made paging clear screen around globe.
161 * Revision 1.69 1995/01/18 10:07:51 john
163 * Took out debugging mprintfs.
165 * Revision 1.68 1995/01/17 14:27:42 john
168 * Revision 1.67 1995/01/17 12:14:39 john
169 * Made walls, object explosion vclips load at level start.
171 * Revision 1.66 1995/01/15 13:15:44 john
172 * Made so that paging always happens, lowmem just loads less.
173 * Also, make KB load print to hud.
175 * Revision 1.65 1995/01/15 11:56:28 john
176 * Working version of paging.
178 * Revision 1.64 1995/01/14 19:17:07 john
179 * First version of new bitmap paging code.
181 * Revision 1.63 1994/12/15 12:26:44 john
182 * Added -nolowmem function.
184 * Revision 1.62 1994/12/14 21:12:26 john
185 * Fixed bug with page fault when exiting and using
188 * Revision 1.61 1994/12/14 11:35:31 john
189 * Evened out thermometer for pig read.
191 * Revision 1.60 1994/12/14 10:51:00 john
192 * Sped up sound loading.
194 * Revision 1.59 1994/12/14 10:12:08 john
195 * Sped up pig loading.
197 * Revision 1.58 1994/12/13 09:14:47 john
198 * *** empty log message ***
200 * Revision 1.57 1994/12/13 09:12:57 john
201 * Made the bar always fill up.
203 * Revision 1.56 1994/12/13 03:49:08 john
204 * Made -lowmem not load the unnecessary bitmaps.
206 * Revision 1.55 1994/12/06 16:06:35 john
207 * Took out piggy sorting.
209 * Revision 1.54 1994/12/06 15:11:14 john
210 * Fixed bug with reading pigs.
212 * Revision 1.53 1994/12/06 14:14:47 john
213 * Added code to set low mem based on memory.
215 * Revision 1.52 1994/12/06 14:01:10 john
216 * Fixed bug that was causing -lowmem all the time..
218 * Revision 1.51 1994/12/06 13:33:48 john
219 * Added lowmem option.
221 * Revision 1.50 1994/12/05 19:40:10 john
222 * If -nosound or no sound card selected, don't load sounds from pig.
224 * Revision 1.49 1994/12/05 12:17:44 john
225 * Added code that locks/unlocks digital sounds on demand.
227 * Revision 1.48 1994/12/05 11:39:03 matt
228 * Fixed little mistake
230 * Revision 1.47 1994/12/05 09:29:22 john
231 * Added clength to the sound field.
233 * Revision 1.46 1994/12/04 15:27:15 john
234 * Fixed my stupid bug that looked at -nosound instead of digi_driver_card
235 * to see whether or not to lock down sound memory.
237 * Revision 1.45 1994/12/03 14:17:00 john
238 * Took out my debug mprintf.
240 * Revision 1.44 1994/12/03 13:32:37 john
241 * Fixed bug with offscreen bitmap.
243 * Revision 1.43 1994/12/03 13:07:13 john
244 * Made the pig read/write compressed sounds.
246 * Revision 1.42 1994/12/03 11:48:51 matt
247 * Added option to not dump sounds to pigfile
249 * Revision 1.41 1994/12/02 20:02:20 matt
250 * Made sound files constant match constant for table
252 * Revision 1.40 1994/11/29 11:03:09 adam
255 * Revision 1.39 1994/11/27 23:13:51 matt
256 * Made changes for new mprintf calling convention
258 * Revision 1.38 1994/11/20 18:40:34 john
259 * MAde the piggy.lst and piggy.all not dump for release.
261 * Revision 1.37 1994/11/19 23:54:45 mike
262 * up number of bitmaps for shareware version.
264 * Revision 1.36 1994/11/19 19:53:05 mike
265 * change MAX_BITMAP_FILES
267 * Revision 1.35 1994/11/19 10:42:56 matt
268 * Increased number of bitmaps for non-shareware version
270 * Revision 1.34 1994/11/19 09:11:52 john
271 * Added avg_color to bitmaps saved in pig.
273 * Revision 1.33 1994/11/19 00:07:05 john
274 * Fixed bug with 8 char sound filenames not getting read from pig.
276 * Revision 1.32 1994/11/18 22:24:54 john
277 * Added -bigpig command line that doesn't rle your pig.
279 * Revision 1.31 1994/11/18 21:56:53 john
280 * Added a better, leaner pig format.
282 * Revision 1.30 1994/11/16 12:06:16 john
283 * Fixed bug with calling .bbms abms.
285 * Revision 1.29 1994/11/16 12:00:56 john
286 * Added piggy.all dump.
288 * Revision 1.28 1994/11/10 21:16:02 adam
291 * Revision 1.27 1994/11/10 13:42:00 john
292 * Made sounds not lock down if using -nosound.
294 * Revision 1.26 1994/11/09 19:55:40 john
295 * Added full rle support with texture rle caching.
297 * Revision 1.25 1994/11/09 16:36:42 john
298 * First version with RLE bitmaps in Pig.
300 * Revision 1.24 1994/10/27 19:42:59 john
301 * Disable the piglet option.
303 * Revision 1.23 1994/10/27 18:51:40 john
304 * Added -piglet option that only loads needed textures for a
305 * mine. Only saved ~1MB, and code still doesn't free textures
306 * before you load a new mine.
308 * Revision 1.22 1994/10/25 13:11:42 john
309 * Made the sounds sort. Dumped piggy.lst.
311 * Revision 1.21 1994/10/06 17:06:23 john
312 * Took out rle stuff.
314 * Revision 1.20 1994/10/06 15:45:36 adam
315 * bumped MAX_BITMAP_FILES again!
317 * Revision 1.19 1994/10/06 11:01:17 yuan
318 * Upped MAX_BITMAP_FILES
320 * Revision 1.18 1994/10/06 10:44:45 john
321 * Added diagnostic message and psuedo run-length-encoder
322 * to see how much memory we would save by storing bitmaps
323 * in a RLE method. Also, I commented out the code that
324 * stores 4K bitmaps on a 4K boundry to reduce pig size
327 * Revision 1.17 1994/10/04 20:03:13 matt
328 * Upped maximum number of bitmaps
330 * Revision 1.16 1994/10/03 18:04:20 john
331 * Fixed bug with data_offset not set right for bitmaps
332 * that are 64x64 and not aligned on a 4k boundry.
334 * Revision 1.15 1994/09/28 11:30:55 john
335 * changed inferno.pig to descent.pig, changed the way it
338 * Revision 1.14 1994/09/22 16:14:17 john
339 * Redid intro sequecing.
341 * Revision 1.13 1994/09/19 14:42:47 john
342 * Locked down sounds with Virtual memory.
344 * Revision 1.12 1994/09/10 17:31:52 mike
345 * Increase number of loadable bitmaps.
347 * Revision 1.11 1994/09/01 19:32:49 mike
348 * Boost texture map allocation.
350 * Revision 1.10 1994/08/16 11:51:02 john
351 * Added grwased pigs.
353 * Revision 1.9 1994/07/06 09:18:03 adam
356 * Revision 1.8 1994/06/20 22:02:15 matt
357 * Fixed bug from last change
359 * Revision 1.7 1994/06/20 21:33:18 matt
360 * Made bm.h not include sounds.h, to reduce dependencies
362 * Revision 1.6 1994/06/20 16:52:19 john
363 * cleaned up init output a bit.
365 * Revision 1.5 1994/06/08 14:20:57 john
366 * Made piggy dump before going into game.
368 * Revision 1.4 1994/06/02 18:59:22 matt
369 * Clear selector field of bitmap loaded from pig file
371 * Revision 1.3 1994/05/06 15:31:41 john
372 * Made name field a bit longer.
374 * Revision 1.2 1994/05/06 13:02:44 john
375 * Added piggy stuff; worked on supertransparency
377 * Revision 1.1 1994/05/06 11:47:26 john
389 static char rcsid[] = "$Id: piggy.c,v 1.24 2003-03-20 23:14:14 btb Exp $";
411 #include "gamefont.h"
415 #include "texmerge.h"
421 #include "byteswap.h"
422 #include "findfile.h"
426 // #include "unarj.h"
428 #include <Strings.h> // MacOS Toolbox header
433 //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds
435 #define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
436 #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
437 #define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
438 #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
440 #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE)
441 #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE)
442 #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11")
444 #define D1_SHAREWARE_10_PIGSIZE 2529454 // v1.0 - 1.2
445 #define D1_SHAREWARE_PIGSIZE 2509799 // v1.4
446 #define D1_PIGSIZE 4920305
447 #define D1_OEM_PIGSIZE 5039735 // Destination: Saturn
448 #define D1_MAC_PIGSIZE 3975533
449 #define D1_MAC_SHARE_PIGSIZE 2714487
450 #define MAC_ALIEN1_PIGSIZE 5013035
451 #define MAC_ALIEN2_PIGSIZE 4909916
452 #define MAC_FIRE_PIGSIZE 4969035
453 #define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
454 #define MAC_ICE_PIGSIZE 4923425
455 #define MAC_WATER_PIGSIZE 4832403
457 ubyte *BitmapBits = NULL;
458 ubyte *SoundBits = NULL;
460 typedef struct BitmapFile {
464 typedef struct SoundFile {
468 hashtable AllBitmapsNames;
469 hashtable AllDigiSndNames;
471 int Num_bitmap_files = 0;
472 int Num_sound_files = 0;
474 digi_sound GameSounds[MAX_SOUND_FILES];
475 int SoundOffset[MAX_SOUND_FILES];
476 grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
478 alias alias_list[MAX_ALIASES];
481 int Must_write_hamfile = 0;
482 int Num_bitmap_files_new = 0;
483 int Num_sound_files_new = 0;
484 BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
485 static SoundFile AllSounds[ MAX_SOUND_FILES ];
487 int Piggy_hamfile_version = 0;
489 int piggy_low_memory = 0;
491 int Piggy_bitmap_cache_size = 0;
492 int Piggy_bitmap_cache_next = 0;
493 ubyte * Piggy_bitmap_cache_data = NULL;
494 static int GameBitmapOffset[MAX_BITMAP_FILES];
495 static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
496 ushort GameBitmapXlat[MAX_BITMAP_FILES];
498 #define PIGGY_BUFFER_SIZE (2400*1024)
501 #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set
504 #undef PIGGY_BUFFER_SIZE
505 #undef PIGGY_SMALL_BUFFER_SIZE
507 #define PIGGY_BUFFER_SIZE (2000*1024)
508 #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024)
513 int piggy_page_flushed = 0;
515 #define DBM_FLAG_ABM 64
520 extern short cd_VRefNum;
521 extern void ConcatPStr(StringPtr dst, StringPtr src);
522 extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf);
523 extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf);
526 int piggy_is_substitutable_bitmap( char * name, char * subst_name );
529 void piggy_write_pigfile(char *filename);
530 static void write_int(int i,FILE *file);
533 void swap_0_255(grs_bitmap *bmp)
537 for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) {
538 if(bmp->bm_data[i] == 0)
539 bmp->bm_data[i] = 255;
540 else if (bmp->bm_data[i] == 255)
545 bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
548 Assert( Num_bitmap_files < MAX_BITMAP_FILES );
550 temp.index = Num_bitmap_files;
554 if ( FindArg("-macdata") )
557 if ( !BigPig ) gr_bitmap_rle_compress( bmp );
558 Num_bitmap_files_new++;
561 strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
562 hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
563 GameBitmaps[Num_bitmap_files] = *bmp;
565 GameBitmapOffset[Num_bitmap_files] = 0;
566 GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
573 int piggy_register_sound( digi_sound * snd, char * name, int in_file )
577 Assert( Num_sound_files < MAX_SOUND_FILES );
579 strncpy( AllSounds[Num_sound_files].name, name, 12 );
580 hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
581 GameSounds[Num_sound_files] = *snd;
583 SoundOffset[Num_sound_files] = 0;
589 Num_sound_files_new++;
595 bitmap_index piggy_find_bitmap( char * name )
603 if ((t=strchr(name,'#'))!=NULL)
606 for (i=0;i<Num_aliases;i++)
607 if (stricmp(name,alias_list[i].alias_name)==0) {
608 if (t) { //extra stuff for ABMs
609 static char temp[FILENAME_LEN];
610 _splitpath(alias_list[i].file_name, NULL, NULL, temp, NULL );
616 name=alias_list[i].file_name;
623 i = hashtable_search( &AllBitmapsNames, name );
632 int piggy_find_sound( char * name )
636 i = hashtable_search( &AllDigiSndNames, name );
644 CFILE * Piggy_fp = NULL;
646 #define FILENAME_LEN 13
648 char Current_pigfile[FILENAME_LEN] = "";
650 void piggy_close_file()
655 Current_pigfile[0] = 0;
659 int Pigfile_initialized=0;
661 #define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
662 #define PIGFILE_VERSION 2
664 extern char CDROM_dir[];
666 int request_cd(void);
671 //copies a pigfile from the CD to the current dir
672 //retuns file handle of new pig
673 CFILE *copy_pigfile_from_cd(char *filename) // MACINTOSH VERSION
676 char sourcePathAndFileCStr[255] = "";
677 char destPathAndFileCStr[255] = "";
679 FILE* sourceFile = NULL;
680 FILE* destFile = NULL;
681 const int BUF_SIZE = 4096;
685 Str255 sourcePathAndFilePStr = "\p";
686 Str255 destPathAndFilePStr = "\p";
687 Str255 pigfileNamePStr = "\p";
688 HParamBlockRec theSourcePigHFSParams;
689 HParamBlockRec theDestPigHFSParams;
690 OSErr theErr = noErr;
691 char oldDirCStr[255] = "";
693 getcwd(oldDirCStr, 255);
695 show_boxed_message("Copying bitmap data from CD...");
696 gr_palette_load(gr_palette); //I don't think this line is really needed
699 //First, delete all PIG files currently in the directory
700 if( !FileFindFirst( "*.pig", &find ) )
705 } while( !FileFindNext( &find ) );
711 //Now, copy over new pig
712 songs_stop_redbook(); //so we can read off the cd
714 // make the source path "<cd volume>:Data:filename.pig"
715 //MWA ConvertCToPStr(filename, pigfileNamePStr);
717 //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum
718 //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr);
721 strcpy(sourcePathAndFileCStr, "Descent II:Data:");
722 strcat(sourcePathAndFileCStr, filename);
724 // make the destination path "<default directory>:Data:filename.pig"
725 //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:");
726 //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr);
727 //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr);
728 //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr);
730 strcpy(destPathAndFileCStr, ":Data:");
731 strcat(destPathAndFileCStr, filename);
733 strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr);
734 strcpy(destPathAndFilePStr, destPathAndFileCStr);
735 c2pstr(sourcePathAndFilePStr);
736 c2pstr(destPathAndFilePStr);
739 // Open the source file
740 sourceFile = fopen(sourcePathAndFileCStr,"rb");
744 if (request_cd() == -1)
745 Error("Cannot load file <%s> from CD",filename);
748 } while (!sourceFile);
751 // Get the time stamp from the source file
752 theSourcePigHFSParams.fileParam.ioCompletion = nil;
753 theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr;
754 theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum;
755 theSourcePigHFSParams.fileParam.ioFDirIndex = 0;
756 theSourcePigHFSParams.fileParam.ioDirID = 0;
758 theErr = PBHGetFInfo(&theSourcePigHFSParams, false);
761 // Error getting file time stamp!! Why? JTS
762 Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr);
765 // Copy the file over
768 // Open the destination file
769 destFile = fopen(destPathAndFileCStr,"wb");
772 Error("Cannot create file: <%s>\n", destPathAndFileCStr);
775 // Copy bytes until the end of the source file
776 while (!feof(sourceFile))
781 bytes_read = fread(buf,1,BUF_SIZE,sourceFile);
782 if (ferror(sourceFile))
783 Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
785 // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile));
787 fwrite(buf,1,bytes_read,destFile);
788 if (ferror(destFile))
789 Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno));
792 // close the source/dest files
793 if (fclose(sourceFile))
794 Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno));
795 if (fclose(destFile))
796 Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno));
798 // Get the current hfs data for the new file
799 theDestPigHFSParams.fileParam.ioCompletion = nil;
800 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
801 theDestPigHFSParams.fileParam.ioVRefNum = 0;
802 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
803 theDestPigHFSParams.fileParam.ioDirID = 0;
804 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
805 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
807 // Error getting file time stamp!! Why? JTS
808 Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr);
811 // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well.
812 theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr;
813 theDestPigHFSParams.fileParam.ioVRefNum = 0;
814 theDestPigHFSParams.fileParam.ioFDirIndex = 0;
815 theDestPigHFSParams.fileParam.ioDirID = 0;
817 // Copy the time stamp from the source file info
818 theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat;
819 theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat;
820 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY';
821 theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2';
823 // Set the dest file's time stamp to the source file's time stamp values
824 theErr = PBHSetFInfo(&theDestPigHFSParams, false);
826 if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr))
828 Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr);
831 theErr = PBHGetFInfo(&theDestPigHFSParams, false);
833 return cfopen(destPathAndFileCStr, "rb");
836 #else //PC Version of copy_pigfile_from_cd is below
838 //copies a pigfile from the CD to the current dir
839 //retuns file handle of new pig
840 CFILE *copy_pigfile_from_cd(char *filename)
846 return cfopen(filename, "rb");
847 show_boxed_message("Copying bitmap data from CD...");
848 gr_palette_load(gr_palette); //I don't think this line is really needed
850 //First, delete all PIG files currently in the directory
852 if( !FileFindFirst( "*.pig", &find ) ) {
855 } while( !FileFindNext( &find ) );
859 //Now, copy over new pig
861 songs_stop_redbook(); //so we can read off the cd
863 //new code to unarj file
864 strcpy(name,CDROM_dir);
865 strcat(name,"descent2.sow");
868 // ret = unarj_specific_file(name,filename,filename);
873 if (ret != EXIT_SUCCESS) {
875 //delete file, so we don't leave partial file
879 if (request_cd() == -1)
881 //NOTE LINK TO ABOVE IF
882 Error("Cannot load file <%s> from CD",filename);
885 } while (ret != EXIT_SUCCESS);
887 return cfopen(filename, "rb");
890 #endif // end of ifdef MAC around copy_pigfile_from_cd
892 //initialize a pigfile, reading headers
893 //returns the size of all the bitmap data
894 void piggy_init_pigfile(char *filename)
898 char temp_name_read[16];
899 grs_bitmap temp_bitmap;
900 DiskBitmapHeader bmh;
901 int header_size, N_bitmaps, data_size, data_start;
903 char name[255]; // filename + path for the mac
906 piggy_close_file(); //close old pig if still open
908 //rename pigfile for shareware
909 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename))
910 filename = DEFAULT_PIGFILE_SHAREWARE;
913 Piggy_fp = cfopen( filename, "rb" );
915 sprintf(name, ":Data:%s", filename);
916 Piggy_fp = cfopen( name, "rb" );
918 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
919 if (Piggy_fp == NULL)
921 Error("Cannot load required file <%s>",name);
923 #endif // end of if def shareware
929 return; //if editor, ok to not have pig, because we'll build one
931 Piggy_fp = copy_pigfile_from_cd(filename);
935 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
936 int pig_id,pig_version;
938 pig_id = cfile_read_int(Piggy_fp);
939 pig_version = cfile_read_int(Piggy_fp);
940 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
941 cfclose(Piggy_fp); //out of date pig
942 Piggy_fp = NULL; //..so pretend it's not here
949 return; //if editor, ok to not have pig, because we'll build one
951 Error("Cannot load required file <%s>",filename);
955 strncpy(Current_pigfile,filename,sizeof(Current_pigfile));
957 N_bitmaps = cfile_read_int(Piggy_fp);
959 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
961 data_start = header_size + cftell(Piggy_fp);
963 data_size = cfilelength(Piggy_fp) - data_start;
965 Num_bitmap_files = 1;
967 for (i=0; i<N_bitmaps; i++ ) {
968 DiskBitmapHeader_read(&bmh, Piggy_fp);
969 memcpy( temp_name_read, bmh.name, 8 );
970 temp_name_read[8] = 0;
971 if ( bmh.dflags & DBM_FLAG_ABM )
972 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
974 strcpy( temp_name, temp_name_read );
975 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
976 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
977 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
978 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
979 temp_bitmap.avg_color = bmh.avg_color;
980 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
982 GameBitmapFlags[i+1] = 0;
983 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
984 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
985 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
986 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
987 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i+1] |= BM_FLAG_RLE_BIG;
989 GameBitmapOffset[i+1] = bmh.offset + data_start;
990 Assert( (i+1) == Num_bitmap_files );
991 piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
995 Piggy_bitmap_cache_size = data_size + (data_size/10); //extra mem for new bitmaps
996 Assert( Piggy_bitmap_cache_size > 0 );
998 Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
1000 if (piggy_low_memory)
1001 Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE;
1004 BitmapBits = d_malloc( Piggy_bitmap_cache_size );
1005 if ( BitmapBits == NULL )
1006 Error( "Not enough memory to load bitmaps\n" );
1007 Piggy_bitmap_cache_data = BitmapBits;
1008 Piggy_bitmap_cache_next = 0;
1010 #if defined(MACINTOSH) && defined(SHAREWARE)
1011 // load_exit_models();
1014 Pigfile_initialized=1;
1017 #define FILENAME_LEN 13
1018 #define MAX_BITMAPS_PER_BRUSH 30
1020 extern int compute_average_pixel(grs_bitmap *new);
1022 //reads in a new pigfile (for new palette)
1023 //returns the size of all the bitmap data
1024 void piggy_new_pigfile(char *pigname)
1028 char temp_name_read[16];
1029 grs_bitmap temp_bitmap;
1030 DiskBitmapHeader bmh;
1031 int header_size, N_bitmaps, data_size, data_start;
1032 int must_rewrite_pig = 0;
1039 //rename pigfile for shareware
1040 if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname))
1041 pigname = DEFAULT_PIGFILE_SHAREWARE;
1043 if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0)
1044 return; //already have correct pig
1046 if (!Pigfile_initialized) { //have we ever opened a pigfile?
1047 piggy_init_pigfile(pigname); //..no, so do initialization stuff
1051 piggy_close_file(); //close old pig if still open
1053 Piggy_bitmap_cache_next = 0; //free up cache
1055 strncpy(Current_pigfile,pigname,sizeof(Current_pigfile));
1058 Piggy_fp = cfopen( pigname, "rb" );
1060 sprintf(name, ":Data:%s", pigname);
1061 Piggy_fp = cfopen( name, "rb" );
1063 #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now.
1064 if (Piggy_fp == NULL)
1066 Error("Cannot load required file <%s>",name);
1068 #endif // end of if def shareware
1073 Piggy_fp = copy_pigfile_from_cd(pigname);
1076 if (Piggy_fp) { //make sure pig is valid type file & is up-to-date
1077 int pig_id,pig_version;
1079 pig_id = cfile_read_int(Piggy_fp);
1080 pig_version = cfile_read_int(Piggy_fp);
1081 if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) {
1082 cfclose(Piggy_fp); //out of date pig
1083 Piggy_fp = NULL; //..so pretend it's not here
1088 if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile.");
1093 N_bitmaps = cfile_read_int(Piggy_fp);
1095 header_size = N_bitmaps*DISKBITMAPHEADER_SIZE;
1097 data_start = header_size + cftell(Piggy_fp);
1099 data_size = cfilelength(Piggy_fp) - data_start;
1101 for (i=1; i<=N_bitmaps; i++ ) {
1102 DiskBitmapHeader_read(&bmh, Piggy_fp);
1103 memcpy( temp_name_read, bmh.name, 8 );
1104 temp_name_read[8] = 0;
1106 if ( bmh.dflags & DBM_FLAG_ABM )
1107 sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
1109 strcpy( temp_name, temp_name_read );
1111 //Make sure name matches
1112 if (strcmp(temp_name,AllBitmaps[i].name)) {
1113 //Int3(); //this pig is out of date. Delete it
1117 strcpy(AllBitmaps[i].name,temp_name);
1119 memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
1121 temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8);
1122 temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4);
1123 temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
1124 temp_bitmap.avg_color = bmh.avg_color;
1125 temp_bitmap.bm_data = Piggy_bitmap_cache_data;
1127 GameBitmapFlags[i] = 0;
1129 if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT;
1130 if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT;
1131 if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING;
1132 if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE;
1133 if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG;
1135 GameBitmapOffset[i] = bmh.offset + data_start;
1137 GameBitmaps[i] = temp_bitmap;
1141 N_bitmaps = 0; //no pigfile, so no bitmaps
1145 Assert(N_bitmaps == Num_bitmap_files-1);
1149 if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) {
1152 //re-read the bitmaps that aren't in this pig
1154 for (i=N_bitmaps+1;i<Num_bitmap_files;i++) {
1157 p = strchr(AllBitmaps[i].name,'#');
1159 if (p) { //this is an ABM
1160 char abmname[FILENAME_LEN];
1162 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
1163 int iff_error; //reference parm to avoid warning message
1165 char basename[FILENAME_LEN];
1168 strcpy(basename,AllBitmaps[i].name);
1169 basename[p-AllBitmaps[i].name] = 0; //cut off "#nn" part
1171 sprintf( abmname, "%s.abm", basename );
1173 iff_error = iff_read_animbrush(abmname,bm,MAX_BITMAPS_PER_BRUSH,&nframes,newpal);
1175 if (iff_error != IFF_NO_ERROR) {
1176 mprintf((1,"File %s - IFF error: %s",abmname,iff_errormsg(iff_error)));
1177 Error("File %s - IFF error: %s",abmname,iff_errormsg(iff_error));
1180 for (fnum=0;fnum<nframes; fnum++) {
1184 sprintf( tempname, "%s#%d", basename, fnum );
1186 //SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1187 SuperX = (GameBitmapFlags[i+fnum]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1188 //above makes assumption that supertransparent color is 254
1190 if ( iff_has_transparency )
1191 gr_remap_bitmap_good( bm[fnum], newpal, iff_transparent_color, SuperX );
1193 gr_remap_bitmap_good( bm[fnum], newpal, -1, SuperX );
1195 bm[fnum]->avg_color = compute_average_pixel(bm[fnum]);
1198 if ( FindArg("-macdata") )
1199 swap_0_255( bm[fnum] );
1201 if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] );
1203 if (bm[fnum]->bm_flags & BM_FLAG_RLE)
1204 size = *((int *) bm[fnum]->bm_data);
1206 size = bm[fnum]->bm_w * bm[fnum]->bm_h;
1208 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size);
1209 d_free(bm[fnum]->bm_data);
1210 bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1211 Piggy_bitmap_cache_next += size;
1213 GameBitmaps[i+fnum] = *bm[fnum];
1215 // -- mprintf( (0, "U" ));
1219 i += nframes-1; //filled in multiple bitmaps
1221 else { //this is a BBM
1224 ubyte newpal[256*3];
1226 char bbmname[FILENAME_LEN];
1229 MALLOC( new, grs_bitmap, 1 );
1231 sprintf( bbmname, "%s.bbm", AllBitmaps[i].name );
1232 iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal);
1235 if (iff_error != IFF_NO_ERROR) {
1236 mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)));
1237 Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error));
1240 SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
1241 //above makes assumption that supertransparent color is 254
1243 if ( iff_has_transparency )
1244 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
1246 gr_remap_bitmap_good( new, newpal, -1, SuperX );
1248 new->avg_color = compute_average_pixel(new);
1251 if ( FindArg("-macdata") )
1254 if ( !BigPig ) gr_bitmap_rle_compress( new );
1256 if (new->bm_flags & BM_FLAG_RLE)
1257 size = *((int *) new->bm_data);
1259 size = new->bm_w * new->bm_h;
1261 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size);
1262 d_free(new->bm_data);
1263 new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1264 Piggy_bitmap_cache_next += size;
1266 GameBitmaps[i] = *new;
1270 // -- mprintf( (0, "U" ));
1274 //@@Dont' do these things which are done when writing
1275 //@@for (i=0; i < Num_bitmap_files; i++ ) {
1276 //@@ bitmap_index bi;
1278 //@@ PIGGY_PAGE_IN( bi );
1281 //@@piggy_close_file();
1283 piggy_write_pigfile(pigname);
1285 Current_pigfile[0] = 0; //say no pig, to force reload
1287 piggy_new_pigfile(pigname); //read in just-generated pig
1291 #endif //ifdef EDITOR
1295 ubyte bogus_data[64*64];
1296 grs_bitmap bogus_bitmap;
1297 ubyte bogus_bitmap_initialized=0;
1298 digi_sound bogus_sound;
1300 #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
1301 #define HAMFILE_VERSION 3
1302 //version 1 -> 2: save marker_model_num
1303 //version 2 -> 3: removed sound files
1305 #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
1306 #define SNDFILE_VERSION 1
1310 CFILE * ham_fp = NULL;
1312 int sound_offset = 0;
1318 ham_fp = cfopen( DEFAULT_HAMFILE, "rb" );
1320 sprintf(name, ":Data:%s", DEFAULT_HAMFILE );
1321 ham_fp = cfopen( name, "rb" );
1324 if (ham_fp == NULL) {
1325 Must_write_hamfile = 1;
1329 //make sure ham is valid type file & is up-to-date
1330 ham_id = cfile_read_int(ham_fp);
1331 Piggy_hamfile_version = cfile_read_int(ham_fp);
1332 if (ham_id != HAMFILE_ID)
1333 Error("Cannot open ham file %s\n", DEFAULT_HAMFILE);
1335 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) {
1336 Must_write_hamfile = 1;
1337 cfclose(ham_fp); //out of date ham
1342 if (Piggy_hamfile_version < 3) // hamfile contains sound info
1343 sound_offset = cfile_read_int(ham_fp);
1349 bm_read_all(ham_fp);
1350 cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1352 //for (i = 0; i < MAX_BITMAP_FILES; i++) {
1353 //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]);
1354 //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]);
1359 if (Piggy_hamfile_version < 3) {
1364 DiskSoundHeader sndh;
1365 digi_sound temp_sound;
1366 char temp_name_read[16];
1369 cfseek(ham_fp, sound_offset, SEEK_SET);
1370 N_sounds = cfile_read_int(ham_fp);
1372 sound_start = cftell(ham_fp);
1374 header_size = N_sounds * DISKSOUNDHEADER_SIZE;
1378 for (i=0; i<N_sounds; i++ ) {
1379 DiskSoundHeader_read(&sndh, ham_fp);
1380 temp_sound.length = sndh.length;
1381 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1382 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1383 memcpy( temp_name_read, sndh.name, 8 );
1384 temp_name_read[8] = 0;
1385 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1387 if (piggy_is_needed(i))
1388 #endif // note link to if.
1389 sbytes += sndh.length;
1390 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1393 SoundBits = d_malloc( sbytes + 16 );
1394 if ( SoundBits == NULL )
1395 Error( "Not enough memory to load sounds\n" );
1397 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1399 // piggy_read_sounds(ham_fp);
1411 CFILE * snd_fp = NULL;
1412 int snd_id,snd_version;
1417 DiskSoundHeader sndh;
1418 digi_sound temp_sound;
1419 char temp_name_read[16];
1426 snd_fp = cfopen( DEFAULT_SNDFILE, "rb" );
1428 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1429 snd_fp = cfopen( name, "rb");
1435 //make sure soundfile is valid type file & is up-to-date
1436 snd_id = cfile_read_int(snd_fp);
1437 snd_version = cfile_read_int(snd_fp);
1438 if (snd_id != SNDFILE_ID || snd_version != SNDFILE_VERSION) {
1439 cfclose(snd_fp); //out of date sound file
1443 N_sounds = cfile_read_int(snd_fp);
1445 sound_start = cftell(snd_fp);
1446 size = cfilelength(snd_fp) - sound_start;
1448 mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
1450 header_size = N_sounds*sizeof(DiskSoundHeader);
1454 for (i=0; i<N_sounds; i++ ) {
1455 DiskSoundHeader_read(&sndh, snd_fp);
1456 //size -= sizeof(DiskSoundHeader);
1457 temp_sound.length = sndh.length;
1458 temp_sound.data = (ubyte *)(sndh.offset + header_size + sound_start);
1459 SoundOffset[Num_sound_files] = sndh.offset + header_size + sound_start;
1460 memcpy( temp_name_read, sndh.name, 8 );
1461 temp_name_read[8] = 0;
1462 piggy_register_sound( &temp_sound, temp_name_read, 1 );
1464 if (piggy_is_needed(i))
1465 #endif // note link to if.
1466 sbytes += sndh.length;
1467 //mprintf(( 0, "%d bytes of sound\n", sbytes ));
1470 SoundBits = d_malloc( sbytes + 16 );
1471 if ( SoundBits == NULL )
1472 Error( "Not enough memory to load sounds\n" );
1474 mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
1476 // piggy_read_sounds(snd_fp);
1483 int piggy_init(void)
1485 int ham_ok=0,snd_ok=0;
1488 hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
1489 hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
1491 for (i=0; i<MAX_SOUND_FILES; i++ ) {
1492 GameSounds[i].length = 0;
1493 GameSounds[i].data = NULL;
1497 for (i=0; i<MAX_BITMAP_FILES; i++ )
1498 GameBitmapXlat[i] = i;
1500 if ( !bogus_bitmap_initialized ) {
1503 bogus_bitmap_initialized = 1;
1504 memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
1505 bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
1506 bogus_bitmap.bm_data = bogus_data;
1507 c = gr_find_closest_color( 0, 0, 63 );
1508 for (i=0; i<4096; i++ ) bogus_data[i] = c;
1509 c = gr_find_closest_color( 63, 0, 0 );
1510 // Make a big red X !
1511 for (i=0; i<64; i++ ) {
1512 bogus_data[i*64+i] = c;
1513 bogus_data[i*64+(63-i)] = c;
1515 piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
1516 bogus_sound.length = 64*64;
1517 bogus_sound.data = bogus_data;
1518 GameBitmapOffset[0] = 0;
1521 if ( FindArg( "-bigpig" ))
1524 if ( FindArg( "-lowmem" ))
1525 piggy_low_memory = 1;
1527 if ( FindArg( "-nolowmem" ))
1528 piggy_low_memory = 0;
1530 if (piggy_low_memory)
1533 WIN(DDGRLOCK(dd_grd_curcanv));
1534 gr_set_curfont( SMALL_FONT );
1535 gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
1536 gr_printf( 0x8000, grd_curcanv->cv_h-20, "%s...", TXT_LOADING_DATA );
1537 WIN(DDGRUNLOCK(dd_grd_curcanv));
1539 #if 1 //def EDITOR //need for d1 mission briefings
1540 piggy_init_pigfile(DEFAULT_PIGFILE);
1543 snd_ok = ham_ok = read_hamfile();
1545 if (Piggy_hamfile_version >= 3)
1546 snd_ok = read_sndfile();
1548 atexit(piggy_close);
1550 mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok));
1551 return (ham_ok && snd_ok); //read ok
1554 int piggy_is_needed(int soundnum)
1558 if ( !digi_lomem ) return 1;
1560 for (i=0; i<MAX_SOUNDS; i++ ) {
1561 if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
1568 void piggy_read_sounds(void)
1581 fp = cfopen( DEFAULT_SNDFILE, "rb" );
1583 sprintf( name, ":Data:%s", DEFAULT_SNDFILE );
1584 fp = cfopen( name, "rb");
1590 for (i=0; i<Num_sound_files; i++ ) {
1591 digi_sound *snd = &GameSounds[i];
1593 if ( SoundOffset[i] > 0 ) {
1594 if ( piggy_is_needed(i) ) {
1595 cfseek( fp, SoundOffset[i], SEEK_SET );
1597 // Read in the sound data!!!
1600 sbytes += snd->length;
1601 cfread( snd->data, snd->length, 1, fp );
1604 snd->data = (ubyte *) -1;
1610 mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
1615 extern int descent_critical_error;
1616 extern unsigned descent_critical_deverror;
1617 extern unsigned descent_critical_errcode;
1619 char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
1620 "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
1621 "Read fault", "General Failure" };
1623 void piggy_critical_error()
1625 grs_canvas * save_canv;
1626 grs_font * save_font;
1628 save_canv = grd_curcanv;
1629 save_font = grd_curcanv->cv_font;
1630 gr_palette_load( gr_palette );
1631 i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' );
1634 gr_set_current_canvas(save_canv);
1635 grd_curcanv->cv_font = save_font;
1638 void piggy_bitmap_page_in( bitmap_index bitmap )
1647 Assert( i < MAX_BITMAP_FILES );
1648 Assert( i < Num_bitmap_files );
1649 Assert( Piggy_bitmap_cache_size > 0 );
1651 if ( i < 1 ) return;
1652 if ( i >= MAX_BITMAP_FILES ) return;
1653 if ( i >= Num_bitmap_files ) return;
1655 if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!!
1657 if ( piggy_low_memory ) {
1659 i = GameBitmapXlat[i]; // Xlat for low-memory settings!
1662 bmp = &GameBitmaps[i];
1664 if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) {
1668 descent_critical_error = 0;
1669 cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
1670 if ( descent_critical_error ) {
1671 piggy_critical_error();
1675 bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
1676 bmp->bm_flags = GameBitmapFlags[i];
1678 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1680 descent_critical_error = 0;
1681 zsize = cfile_read_int(Piggy_fp);
1682 if ( descent_critical_error ) {
1683 piggy_critical_error();
1687 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1688 //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
1689 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1691 piggy_bitmap_page_out_all();
1694 descent_critical_error = 0;
1695 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp );
1696 if ( descent_critical_error ) {
1697 piggy_critical_error();
1702 switch (cfilelength(Piggy_fp)) {
1704 if (!FindArg("-macdata"))
1706 // otherwise, fall through...
1707 case MAC_ALIEN1_PIGSIZE:
1708 case MAC_ALIEN2_PIGSIZE:
1709 case MAC_FIRE_PIGSIZE:
1710 case MAC_GROUPA_PIGSIZE:
1711 case MAC_ICE_PIGSIZE:
1712 case MAC_WATER_PIGSIZE:
1713 rle_swap_0_255( bmp );
1714 memcpy(&zsize, bmp->bm_data, 4);
1719 memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
1720 Piggy_bitmap_cache_next += zsize;
1721 if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
1723 piggy_bitmap_page_out_all();
1728 // GET JOHN NOW IF YOU GET THIS ASSERT!!!
1729 Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );
1730 if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
1731 piggy_bitmap_page_out_all();
1734 descent_critical_error = 0;
1735 temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
1736 if ( descent_critical_error ) {
1737 piggy_critical_error();
1740 Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
1743 switch (cfilelength(Piggy_fp)) {
1745 if (!FindArg("-macdata"))
1747 // otherwise, fall through...
1748 case MAC_ALIEN1_PIGSIZE:
1749 case MAC_ALIEN2_PIGSIZE:
1750 case MAC_FIRE_PIGSIZE:
1751 case MAC_GROUPA_PIGSIZE:
1752 case MAC_ICE_PIGSIZE:
1753 case MAC_WATER_PIGSIZE:
1760 //@@if ( bmp->bm_selector ) {
1761 //@@#if !defined(WINDOWS) && !defined(MACINTOSH)
1762 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1763 //@@ Error( "Error modifying selector base in piggy.c\n" );
1770 if ( piggy_low_memory ) {
1772 GameBitmaps[org_i] = GameBitmaps[i];
1775 //@@Removed from John's code:
1777 //@@ if ( bmp->bm_selector ) {
1778 //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
1779 //@@ Error( "Error modifying selector base in piggy.c\n" );
1785 void piggy_bitmap_page_out_all()
1789 Piggy_bitmap_cache_next = 0;
1791 piggy_page_flushed++;
1796 for (i=0; i<Num_bitmap_files; i++ ) {
1797 if ( GameBitmapOffset[i] > 0 ) { // Don't page out bitmaps read from disk!!!
1798 GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
1799 GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
1803 mprintf(( 0, "Flushing piggy bitmap cache\n" ));
1806 void piggy_load_level_data()
1808 piggy_bitmap_page_out_all();
1814 void change_filename_ext( char *dest, char *src, char *ext );
1816 void piggy_write_pigfile(char *filename)
1819 int bitmap_data_start,data_offset;
1820 DiskBitmapHeader bmh;
1822 char subst_name[32];
1825 char tname[FILENAME_LEN];
1827 // -- mprintf( (0, "Paging in all piggy bitmaps..." ));
1828 for (i=0; i < Num_bitmap_files; i++ ) {
1831 PIGGY_PAGE_IN( bi );
1833 // -- mprintf( (0, "\n" ));
1837 // -- mprintf( (0, "Creating %s...",filename ));
1839 pig_fp = fopen( filename, "wb" ); //open PIG file
1840 Assert( pig_fp!=NULL );
1842 write_int(PIGFILE_ID,pig_fp);
1843 write_int(PIGFILE_VERSION,pig_fp);
1846 fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp );
1849 bitmap_data_start = ftell(pig_fp);
1850 bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE;
1851 data_offset = bitmap_data_start;
1853 change_filename_ext(tname,filename,"lst");
1854 fp1 = fopen( tname, "wt" );
1855 change_filename_ext(tname,filename,"all");
1856 fp2 = fopen( tname, "wt" );
1858 for (i=1; i < Num_bitmap_files; i++ ) {
1864 p = strchr(AllBitmaps[i].name,'#');
1871 fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
1872 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1874 bmh.dflags = DBM_FLAG_ABM + n;
1878 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
1879 memcpy( bmh.name, AllBitmaps[i].name, 8 );
1883 bmp = &GameBitmaps[i];
1885 Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
1888 fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
1889 org_offset = ftell(pig_fp);
1890 bmh.offset = data_offset - bitmap_data_start;
1891 fseek( pig_fp, data_offset, SEEK_SET );
1893 if ( bmp->bm_flags & BM_FLAG_RLE ) {
1894 size = (int *)bmp->bm_data;
1895 fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp );
1896 data_offset += *size;
1898 fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
1900 fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp );
1901 data_offset += bmp->bm_rowsize * bmp->bm_h;
1903 fprintf( fp1, ".\n" );
1905 fseek( pig_fp, org_offset, SEEK_SET );
1906 Assert( GameBitmaps[i].bm_w < 4096 );
1907 bmh.width = (GameBitmaps[i].bm_w & 0xff);
1908 bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f);
1909 Assert( GameBitmaps[i].bm_h < 4096 );
1910 bmh.height = GameBitmaps[i].bm_h;
1911 bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0);
1912 bmh.flags = GameBitmaps[i].bm_flags;
1913 if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) {
1914 bitmap_index other_bitmap;
1915 other_bitmap = piggy_find_bitmap( subst_name );
1916 GameBitmapXlat[i] = other_bitmap.index;
1917 bmh.flags |= BM_FLAG_PAGED_OUT;
1918 //mprintf(( 0, "Skipping bitmap %d\n", i ));
1919 //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
1921 bmh.flags &= ~BM_FLAG_PAGED_OUT;
1923 bmh.avg_color=GameBitmaps[i].avg_color;
1924 fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp ); // Mark as a bitmap
1929 mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
1930 fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
1937 static void write_int(int i,FILE *file)
1939 if (fwrite( &i, sizeof(i), 1, file) != 1)
1940 Error( "Error reading int in gamesave.c" );
1944 void piggy_dump_all()
1948 int org_offset,data_offset=0;
1949 DiskSoundHeader sndh;
1950 int sound_data_start=0;
1953 #ifdef NO_DUMP_SOUNDS
1954 Num_sound_files = 0;
1955 Num_sound_files_new = 0;
1958 if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
1961 fp1 = fopen( "ham.lst", "wt" );
1962 fp2 = fopen( "ham.all", "wt" );
1964 if (Must_write_hamfile || Num_bitmap_files_new) {
1966 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1968 ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file
1969 Assert( ham_fp!=NULL );
1971 write_int(HAMFILE_ID,ham_fp);
1972 write_int(HAMFILE_VERSION,ham_fp);
1974 bm_write_all(ham_fp);
1975 xlat_offset = ftell(ham_fp);
1976 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1979 if (Num_bitmap_files_new)
1980 piggy_write_pigfile(DEFAULT_PIGFILE);
1982 //free up memeory used by new bitmaps
1983 for (i=Num_bitmap_files-Num_bitmap_files_new;i<Num_bitmap_files;i++)
1984 d_free(GameBitmaps[i].bm_data);
1986 //next thing must be done after pig written
1987 fseek( ham_fp, xlat_offset, SEEK_SET );
1988 fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp );
1991 mprintf( (0, "\n" ));
1994 if (Num_sound_files_new) {
1996 mprintf( (0, "Creating %s...",DEFAULT_HAMFILE));
1997 // Now dump sound file
1998 ham_fp = fopen( DEFAULT_SNDFILE, "wb" );
1999 Assert( ham_fp!=NULL );
2001 write_int(SNDFILE_ID,ham_fp);
2002 write_int(SNDFILE_VERSION,ham_fp);
2004 fwrite( &Num_sound_files, sizeof(int), 1, ham_fp );
2006 mprintf( (0, "\nDumping sounds..." ));
2008 sound_data_start = ftell(ham_fp);
2009 sound_data_start += Num_sound_files*sizeof(DiskSoundHeader);
2010 data_offset = sound_data_start;
2012 for (i=0; i < Num_sound_files; i++ ) {
2015 snd = &GameSounds[i];
2016 strcpy( sndh.name, AllSounds[i].name );
2017 sndh.length = GameSounds[i].length;
2018 sndh.offset = data_offset - sound_data_start;
2020 org_offset = ftell(ham_fp);
2021 fseek( ham_fp, data_offset, SEEK_SET );
2023 sndh.data_length = GameSounds[i].length;
2024 fwrite( snd->data, sizeof(ubyte), snd->length, ham_fp );
2025 data_offset += snd->length;
2026 fseek( ham_fp, org_offset, SEEK_SET );
2027 fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap
2029 fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
2030 fprintf( fp2, "%s.raw\n", AllSounds[i].name );
2034 mprintf( (0, "\n" ));
2037 fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start);
2038 mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
2039 fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
2044 // Never allow the game to run after building ham.
2058 d_free( SoundBits );
2060 hashtable_free( &AllBitmapsNames );
2061 hashtable_free( &AllDigiSndNames );
2065 int piggy_does_bitmap_exist_slow( char * name )
2069 for (i=0; i<Num_bitmap_files; i++ ) {
2070 if ( !strcmp( AllBitmaps[i].name, name) )
2077 #define NUM_GAUGE_BITMAPS 23
2078 char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = {
2079 "gauge01", "gauge01b",
2080 "gauge02", "gauge02b",
2081 "gauge06", "gauge06b",
2082 "targ01", "targ01b",
2083 "targ02", "targ02b",
2084 "targ03", "targ03b",
2085 "targ04", "targ04b",
2086 "targ05", "targ05b",
2087 "targ06", "targ06b",
2088 "gauge18", "gauge18b",
2094 int piggy_is_gauge_bitmap( char * base_name )
2097 for (i=0; i<NUM_GAUGE_BITMAPS; i++ ) {
2098 if ( !stricmp( base_name, gauge_bitmap_names[i] ))
2105 int piggy_is_substitutable_bitmap( char * name, char * subst_name )
2109 char base_name[ 16 ];
2111 strcpy( subst_name, name );
2112 p = strchr( subst_name, '#' );
2114 frame = atoi( &p[1] );
2116 strcpy( base_name, subst_name );
2117 if ( !piggy_is_gauge_bitmap( base_name )) {
2118 sprintf( subst_name, "%s#%d", base_name, frame+1 );
2119 if ( piggy_does_bitmap_exist_slow( subst_name ) ) {
2121 sprintf( subst_name, "%s#%d", base_name, frame-1 );
2127 strcpy( subst_name, name );
2134 // New Windows stuff
2136 // windows bitmap page in
2137 // Page in a bitmap, if ddraw, then page it into a ddsurface in
2138 // 'video' memory. if that fails, page it in normally.
2140 void piggy_bitmap_page_in_w( bitmap_index bitmap, int ddraw )
2145 // Essential when switching video modes!
2147 void piggy_bitmap_page_out_all_w()
2153 #ifndef FAST_FILE_IO
2155 * reads a bitmap_index structure from a CFILE
2157 void bitmap_index_read(bitmap_index *bi, CFILE *fp)
2159 bi->index = cfile_read_short(fp);
2163 * reads n bitmap_index structs from a CFILE
2165 int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp)
2169 for (i = 0; i < n; i++)
2170 bi[i].index = cfile_read_short(fp);
2175 * reads a DiskBitmapHeader structure from a CFILE
2177 void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp)
2179 cfread(dbh->name, 8, 1, fp);
2180 dbh->dflags = cfile_read_byte(fp);
2181 dbh->width = cfile_read_byte(fp);
2182 dbh->height = cfile_read_byte(fp);
2183 dbh->wh_extra = cfile_read_byte(fp);
2184 dbh->flags = cfile_read_byte(fp);
2185 dbh->avg_color = cfile_read_byte(fp);
2186 dbh->offset = cfile_read_int(fp);
2190 * reads a DiskSoundHeader structure from a CFILE
2192 void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp)
2194 cfread(dsh->name, 8, 1, fp);
2195 dsh->length = cfile_read_int(fp);
2196 dsh->data_length = cfile_read_int(fp);
2197 dsh->offset = cfile_read_int(fp);
2199 #endif // FAST_FILE_IO
2202 * reads a descent 1 DiskBitmapHeader structure from a CFILE
2204 void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp)
2206 cfread(dbh->name, 8, 1, fp);
2207 dbh->dflags = cfile_read_byte(fp);
2208 dbh->width = cfile_read_byte(fp);
2209 dbh->height = cfile_read_byte(fp);
2211 dbh->flags = cfile_read_byte(fp);
2212 dbh->avg_color = cfile_read_byte(fp);
2213 dbh->offset = cfile_read_int(fp);