/* $Id: piggy.c,v 1.28 2003-03-25 09:54:12 btb Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for managing the pig files. * * Old Log: * Revision 1.16 1995/11/09 17:27:47 allender * put in missing quote on new gauge name * * Revision 1.15 1995/11/08 17:28:03 allender * add PC gauges to gauge list of non-substitutatble bitmaps * * Revision 1.14 1995/11/08 15:14:49 allender * fixed horrible bug where the piggy cache size was incorrect * for mac shareware * * Revision 1.13 1995/11/03 12:53:37 allender * shareware changes * * Revision 1.12 1995/10/21 22:25:14 allender * added bald guy cheat * * Revision 1.11 1995/10/20 22:42:15 allender * changed load path of descent.pig to :data:descent.pig * * Revision 1.10 1995/10/20 00:08:01 allender * put in event loop calls when loading data (hides it nicely * from user) so TM can get it's strokes stuff * * Revision 1.9 1995/09/13 08:48:01 allender * added lower memory requirement to load alternate bitmaps * * Revision 1.8 1995/08/16 09:39:13 allender * moved "loading" text up a little * * Revision 1.7 1995/08/08 13:54:26 allender * added macsys header file * * Revision 1.6 1995/07/12 12:49:56 allender * total hack for bitmaps > 512 bytes wide -- check these by name * * Revision 1.5 1995/07/05 16:47:05 allender * kitchen stuff * * Revision 1.4 1995/06/23 08:55:28 allender * make "loading data" text y loc based off of curcanv * * Revision 1.3 1995/06/08 14:08:52 allender * PPC aligned data sets * * Revision 1.2 1995/05/26 06:54:27 allender * removed refences to sound data at end of pig file (since they will * now be Macintosh snd resources for effects * * Revision 1.1 1995/05/16 15:29:51 allender * Initial revision * * Revision 2.10 1995/10/07 13:17:26 john * Made all bitmaps paged out by default. * * Revision 2.9 1995/04/14 14:05:24 john * *** empty log message *** * * Revision 2.8 1995/04/12 13:39:37 john * Fixed bug with -lowmem not working. * * Revision 2.7 1995/03/29 23:23:17 john * Fixed major bug with sounds not building into pig right. * * Revision 2.6 1995/03/28 18:05:00 john * Fixed it so you don't have to delete pig after changing bitmaps.tbl * * Revision 2.5 1995/03/16 23:13:06 john * Fixed bug with piggy paging in bitmap not checking for disk * error, hence bogifying textures if you pull the CD out. * * Revision 2.4 1995/03/14 16:22:27 john * Added cdrom alternate directory stuff. * * Revision 2.3 1995/03/06 15:23:20 john * New screen techniques. * * Revision 2.2 1995/02/27 13:13:40 john * Removed floating point. * * Revision 2.1 1995/02/27 12:31:25 john * Made work without editor. * * Revision 2.0 1995/02/27 11:28:02 john * New version 2.0, which has no anonymous unions, builds with * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. * * Revision 1.85 1995/02/09 12:54:24 john * Made paged out bitmaps have bm_data be a valid pointer * instead of NULL, in case anyone accesses it. * * Revision 1.84 1995/02/09 12:50:59 john * Bullet-proofed the piggy loading code. * * Revision 1.83 1995/02/07 17:08:51 john * Added some error handling stuff instead of asserts. * * Revision 1.82 1995/02/03 17:06:48 john * Changed sound stuff to allow low memory usage. * Also, changed so that Sounds isn't an array of digi_sounds, it * is a ubyte pointing into GameSounds, this way the digi.c code that * locks sounds won't accidentally unlock a sound that is already playing, but * since it's Sounds[soundno] is different, it would erroneously be unlocked. * * Revision 1.81 1995/02/02 21:56:39 matt * Added data for new gauge bitmaps * * Revision 1.80 1995/02/01 23:31:57 john * Took out loading bar. * * Revision 1.79 1995/01/28 15:13:18 allender * bumped up Piggy_bitmap_cache_size * * Revision 1.78 1995/01/26 12:30:43 john * Took out prev. * * Revision 1.77 1995/01/26 12:12:17 john * Made buffer be big for bitmaps. * * Revision 1.76 1995/01/25 20:15:38 john * Made editor allocate all mem. * * Revision 1.75 1995/01/25 14:52:56 john * Made bitmap buffer be 1.5 MB. * * Revision 1.74 1995/01/22 16:03:19 mike * localization. * * Revision 1.73 1995/01/22 15:58:36 mike * localization * * Revision 1.72 1995/01/18 20:51:20 john * Took out warnings. * * Revision 1.71 1995/01/18 20:47:21 john * Added code to allocate sounds & bitmaps into diff * buffers, also made sounds not be compressed for registered. * * Revision 1.70 1995/01/18 15:08:41 john * Added start/stop time around paging. * Made paging clear screen around globe. * * Revision 1.69 1995/01/18 10:07:51 john * * Took out debugging mprintfs. * * Revision 1.68 1995/01/17 14:27:42 john * y * * Revision 1.67 1995/01/17 12:14:39 john * Made walls, object explosion vclips load at level start. * * Revision 1.66 1995/01/15 13:15:44 john * Made so that paging always happens, lowmem just loads less. * Also, make KB load print to hud. * * Revision 1.65 1995/01/15 11:56:28 john * Working version of paging. * * Revision 1.64 1995/01/14 19:17:07 john * First version of new bitmap paging code. * * Revision 1.63 1994/12/15 12:26:44 john * Added -nolowmem function. * * Revision 1.62 1994/12/14 21:12:26 john * Fixed bug with page fault when exiting and using * -nosound. * * Revision 1.61 1994/12/14 11:35:31 john * Evened out thermometer for pig read. * * Revision 1.60 1994/12/14 10:51:00 john * Sped up sound loading. * * Revision 1.59 1994/12/14 10:12:08 john * Sped up pig loading. * * Revision 1.58 1994/12/13 09:14:47 john * *** empty log message *** * * Revision 1.57 1994/12/13 09:12:57 john * Made the bar always fill up. * * Revision 1.56 1994/12/13 03:49:08 john * Made -lowmem not load the unnecessary bitmaps. * * Revision 1.55 1994/12/06 16:06:35 john * Took out piggy sorting. * * Revision 1.54 1994/12/06 15:11:14 john * Fixed bug with reading pigs. * * Revision 1.53 1994/12/06 14:14:47 john * Added code to set low mem based on memory. * * Revision 1.52 1994/12/06 14:01:10 john * Fixed bug that was causing -lowmem all the time.. * * Revision 1.51 1994/12/06 13:33:48 john * Added lowmem option. * * Revision 1.50 1994/12/05 19:40:10 john * If -nosound or no sound card selected, don't load sounds from pig. * * Revision 1.49 1994/12/05 12:17:44 john * Added code that locks/unlocks digital sounds on demand. * * Revision 1.48 1994/12/05 11:39:03 matt * Fixed little mistake * * Revision 1.47 1994/12/05 09:29:22 john * Added clength to the sound field. * * Revision 1.46 1994/12/04 15:27:15 john * Fixed my stupid bug that looked at -nosound instead of digi_driver_card * to see whether or not to lock down sound memory. * * Revision 1.45 1994/12/03 14:17:00 john * Took out my debug mprintf. * * Revision 1.44 1994/12/03 13:32:37 john * Fixed bug with offscreen bitmap. * * Revision 1.43 1994/12/03 13:07:13 john * Made the pig read/write compressed sounds. * * Revision 1.42 1994/12/03 11:48:51 matt * Added option to not dump sounds to pigfile * * Revision 1.41 1994/12/02 20:02:20 matt * Made sound files constant match constant for table * * Revision 1.40 1994/11/29 11:03:09 adam * upped # of sounds * * Revision 1.39 1994/11/27 23:13:51 matt * Made changes for new mprintf calling convention * * Revision 1.38 1994/11/20 18:40:34 john * MAde the piggy.lst and piggy.all not dump for release. * * Revision 1.37 1994/11/19 23:54:45 mike * up number of bitmaps for shareware version. * * Revision 1.36 1994/11/19 19:53:05 mike * change MAX_BITMAP_FILES * * Revision 1.35 1994/11/19 10:42:56 matt * Increased number of bitmaps for non-shareware version * * Revision 1.34 1994/11/19 09:11:52 john * Added avg_color to bitmaps saved in pig. * * Revision 1.33 1994/11/19 00:07:05 john * Fixed bug with 8 char sound filenames not getting read from pig. * * Revision 1.32 1994/11/18 22:24:54 john * Added -bigpig command line that doesn't rle your pig. * * Revision 1.31 1994/11/18 21:56:53 john * Added a better, leaner pig format. * * Revision 1.30 1994/11/16 12:06:16 john * Fixed bug with calling .bbms abms. * * Revision 1.29 1994/11/16 12:00:56 john * Added piggy.all dump. * * Revision 1.28 1994/11/10 21:16:02 adam * nothing important * * Revision 1.27 1994/11/10 13:42:00 john * Made sounds not lock down if using -nosound. * * Revision 1.26 1994/11/09 19:55:40 john * Added full rle support with texture rle caching. * * Revision 1.25 1994/11/09 16:36:42 john * First version with RLE bitmaps in Pig. * * Revision 1.24 1994/10/27 19:42:59 john * Disable the piglet option. * * Revision 1.23 1994/10/27 18:51:40 john * Added -piglet option that only loads needed textures for a * mine. Only saved ~1MB, and code still doesn't free textures * before you load a new mine. * * Revision 1.22 1994/10/25 13:11:42 john * Made the sounds sort. Dumped piggy.lst. * * Revision 1.21 1994/10/06 17:06:23 john * Took out rle stuff. * * Revision 1.20 1994/10/06 15:45:36 adam * bumped MAX_BITMAP_FILES again! * * Revision 1.19 1994/10/06 11:01:17 yuan * Upped MAX_BITMAP_FILES * * Revision 1.18 1994/10/06 10:44:45 john * Added diagnostic message and psuedo run-length-encoder * to see how much memory we would save by storing bitmaps * in a RLE method. Also, I commented out the code that * stores 4K bitmaps on a 4K boundry to reduce pig size * a bit. * * Revision 1.17 1994/10/04 20:03:13 matt * Upped maximum number of bitmaps * * Revision 1.16 1994/10/03 18:04:20 john * Fixed bug with data_offset not set right for bitmaps * that are 64x64 and not aligned on a 4k boundry. * * Revision 1.15 1994/09/28 11:30:55 john * changed inferno.pig to descent.pig, changed the way it * is read. * * Revision 1.14 1994/09/22 16:14:17 john * Redid intro sequecing. * * Revision 1.13 1994/09/19 14:42:47 john * Locked down sounds with Virtual memory. * * Revision 1.12 1994/09/10 17:31:52 mike * Increase number of loadable bitmaps. * * Revision 1.11 1994/09/01 19:32:49 mike * Boost texture map allocation. * * Revision 1.10 1994/08/16 11:51:02 john * Added grwased pigs. * * Revision 1.9 1994/07/06 09:18:03 adam * upped bitmap #s * * Revision 1.8 1994/06/20 22:02:15 matt * Fixed bug from last change * * Revision 1.7 1994/06/20 21:33:18 matt * Made bm.h not include sounds.h, to reduce dependencies * * Revision 1.6 1994/06/20 16:52:19 john * cleaned up init output a bit. * * Revision 1.5 1994/06/08 14:20:57 john * Made piggy dump before going into game. * * Revision 1.4 1994/06/02 18:59:22 matt * Clear selector field of bitmap loaded from pig file * * Revision 1.3 1994/05/06 15:31:41 john * Made name field a bit longer. * * Revision 1.2 1994/05/06 13:02:44 john * Added piggy stuff; worked on supertransparency * * Revision 1.1 1994/05/06 11:47:26 john * Initial revision * * */ #ifdef HAVE_CONFIG_H #include #endif #ifdef RCS static char rcsid[] = "$Id: piggy.c,v 1.28 2003-03-25 09:54:12 btb Exp $"; #endif #include #include #include "pstypes.h" #include "strutil.h" #include "inferno.h" #include "gr.h" #include "u_mem.h" #include "iff.h" #include "mono.h" #include "error.h" #include "sounds.h" #include "songs.h" #include "bm.h" #include "bmread.h" #include "hash.h" #include "args.h" #include "palette.h" #include "gamefont.h" #include "rle.h" #include "screens.h" #include "piggy.h" #include "texmerge.h" #include "paging.h" #include "game.h" #include "text.h" #include "cfile.h" #include "newmenu.h" #include "byteswap.h" #include "findfile.h" #include "makesig.h" #ifndef MACINTOSH // #include "unarj.h" #else #include // MacOS Toolbox header #include #include #endif //#define NO_DUMP_SOUNDS 1 //if set, dump bitmaps but not sounds #define DEFAULT_PIGFILE_REGISTERED "groupa.pig" #define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig" #define DEFAULT_HAMFILE_REGISTERED "descent2.ham" #define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham" #define DEFAULT_PIGFILE (cfexist(DEFAULT_PIGFILE_REGISTERED)?DEFAULT_PIGFILE_REGISTERED:DEFAULT_PIGFILE_SHAREWARE) #define DEFAULT_HAMFILE (cfexist(DEFAULT_HAMFILE_REGISTERED)?DEFAULT_HAMFILE_REGISTERED:DEFAULT_HAMFILE_SHAREWARE) #define DEFAULT_SNDFILE ((Piggy_hamfile_version < 3)?DEFAULT_HAMFILE_SHAREWARE:(digi_sample_rate==SAMPLE_RATE_22K)?"descent2.s22":"descent2.s11") ubyte *BitmapBits = NULL; ubyte *SoundBits = NULL; typedef struct BitmapFile { char name[15]; } BitmapFile; typedef struct SoundFile { char name[15]; } SoundFile; hashtable AllBitmapsNames; hashtable AllDigiSndNames; int Num_bitmap_files = 0; int Num_sound_files = 0; digi_sound GameSounds[MAX_SOUND_FILES]; int SoundOffset[MAX_SOUND_FILES]; grs_bitmap GameBitmaps[MAX_BITMAP_FILES]; alias alias_list[MAX_ALIASES]; int Num_aliases=0; int Must_write_hamfile = 0; int Num_bitmap_files_new = 0; int Num_sound_files_new = 0; BitmapFile AllBitmaps[ MAX_BITMAP_FILES ]; static SoundFile AllSounds[ MAX_SOUND_FILES ]; int Piggy_hamfile_version = 0; int piggy_low_memory = 0; int Piggy_bitmap_cache_size = 0; int Piggy_bitmap_cache_next = 0; ubyte * Piggy_bitmap_cache_data = NULL; static int GameBitmapOffset[MAX_BITMAP_FILES]; static ubyte GameBitmapFlags[MAX_BITMAP_FILES]; ushort GameBitmapXlat[MAX_BITMAP_FILES]; #define PIGGY_BUFFER_SIZE (2400*1024) #ifdef MACINTOSH #define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when piggy_low_memory is set #ifdef SHAREWARE #undef PIGGY_BUFFER_SIZE #undef PIGGY_SMALL_BUFFER_SIZE #define PIGGY_BUFFER_SIZE (2000*1024) #define PIGGY_SMALL_BUFFER_SIZE (1100 * 1024) #endif // SHAREWARE #endif int piggy_page_flushed = 0; #define DBM_FLAG_ABM 64 ubyte BigPig = 0; #ifdef MACINTOSH extern short cd_VRefNum; extern void ConcatPStr(StringPtr dst, StringPtr src); extern int ConvertPToCStr(StringPtr inPStr, char* outCStrBuf); extern int ConvertCToPStr(char* inCStr, StringPtr outPStrBuf); #endif int piggy_is_substitutable_bitmap( char * name, char * subst_name ); #ifdef EDITOR void piggy_write_pigfile(char *filename); static void write_int(int i,FILE *file); #endif void swap_0_255(grs_bitmap *bmp) { int i; for (i = 0; i < bmp->bm_h * bmp->bm_w; i++) { if(bmp->bm_data[i] == 0) bmp->bm_data[i] = 255; else if (bmp->bm_data[i] == 255) bmp->bm_data[i] = 0; } } bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file ) { bitmap_index temp; Assert( Num_bitmap_files < MAX_BITMAP_FILES ); temp.index = Num_bitmap_files; if (!in_file) { #ifdef EDITOR if ( FindArg("-macdata") ) swap_0_255( bmp ); #endif if ( !BigPig ) gr_bitmap_rle_compress( bmp ); Num_bitmap_files_new++; } strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 ); hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files ); GameBitmaps[Num_bitmap_files] = *bmp; if ( !in_file ) { GameBitmapOffset[Num_bitmap_files] = 0; GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags; } Num_bitmap_files++; return temp; } int piggy_register_sound( digi_sound * snd, char * name, int in_file ) { int i; Assert( Num_sound_files < MAX_SOUND_FILES ); strncpy( AllSounds[Num_sound_files].name, name, 12 ); hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files ); GameSounds[Num_sound_files] = *snd; if ( !in_file ) { SoundOffset[Num_sound_files] = 0; } i = Num_sound_files; if (!in_file) Num_sound_files_new++; Num_sound_files++; return i; } bitmap_index piggy_find_bitmap( char * name ) { bitmap_index bmp; int i; char *t; bmp.index = 0; if ((t=strchr(name,'#'))!=NULL) *t=0; for (i=0;i:Data:filename.pig" //MWA ConvertCToPStr(filename, pigfileNamePStr); //MWA ConcatPStr(sourcePathAndFilePStr, "\pDescent II:Data:"); // volume ID is cd_VRefNum //MWA ConcatPStr(sourcePathAndFilePStr, pigfileNamePStr); strupr(filename); strcpy(sourcePathAndFileCStr, "Descent II:Data:"); strcat(sourcePathAndFileCStr, filename); // make the destination path ":Data:filename.pig" //MWA ConcatPStr(destPathAndFilePStr, "\p:Data:"); //MWA ConcatPStr(destPathAndFilePStr, pigfileNamePStr); //MWA ConvertPToCStr(sourcePathAndFilePStr, sourcePathAndFileCStr); //MWA ConvertPToCStr(destPathAndFilePStr, destPathAndFileCStr); strcpy(destPathAndFileCStr, ":Data:"); strcat(destPathAndFileCStr, filename); strcpy(sourcePathAndFilePStr, sourcePathAndFileCStr); strcpy(destPathAndFilePStr, destPathAndFileCStr); c2pstr(sourcePathAndFilePStr); c2pstr(destPathAndFilePStr); do { // Open the source file sourceFile = fopen(sourcePathAndFileCStr,"rb"); if (!sourceFile) { if (request_cd() == -1) Error("Cannot load file <%s> from CD",filename); } } while (!sourceFile); // Get the time stamp from the source file theSourcePigHFSParams.fileParam.ioCompletion = nil; theSourcePigHFSParams.fileParam.ioNamePtr = sourcePathAndFilePStr; theSourcePigHFSParams.fileParam.ioVRefNum = cd_VRefNum; theSourcePigHFSParams.fileParam.ioFDirIndex = 0; theSourcePigHFSParams.fileParam.ioDirID = 0; theErr = PBHGetFInfo(&theSourcePigHFSParams, false); if (theErr != noErr) { // Error getting file time stamp!! Why? JTS Error("Can't get old file time stamp: <%s>\n", sourcePathAndFileCStr); } // Copy the file over // C Stuff...... // Open the destination file destFile = fopen(destPathAndFileCStr,"wb"); if (!destFile) { Error("Cannot create file: <%s>\n", destPathAndFileCStr); } // Copy bytes until the end of the source file while (!feof(sourceFile)) { int bytes_read; int x; bytes_read = fread(buf,1,BUF_SIZE,sourceFile); if (ferror(sourceFile)) Error("Cannot read from file <%s>: %s", sourcePathAndFileCStr, strerror(errno)); // Assert is bogus Assert(bytes_read == BUF_SIZE || feof(sourceFile)); fwrite(buf,1,bytes_read,destFile); if (ferror(destFile)) Error("Cannot write to file <%s>: %s",destPathAndFileCStr, strerror(errno)); } // close the source/dest files if (fclose(sourceFile)) Error("Error closing file <%s>: %s", sourcePathAndFileCStr, strerror(errno)); if (fclose(destFile)) Error("Error closing file <%s>: %s", destPathAndFileCStr, strerror(errno)); // Get the current hfs data for the new file theDestPigHFSParams.fileParam.ioCompletion = nil; theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr; theDestPigHFSParams.fileParam.ioVRefNum = 0; theDestPigHFSParams.fileParam.ioFDirIndex = 0; theDestPigHFSParams.fileParam.ioDirID = 0; theErr = PBHGetFInfo(&theDestPigHFSParams, false); if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr)) { // Error getting file time stamp!! Why? JTS Error("Can't get destination pig file information: <%s>\n", destPathAndFileCStr); } // Reset this data !!!!! or else the relative pathname won't work, could use just filename instead but, oh well. theDestPigHFSParams.fileParam.ioNamePtr = destPathAndFilePStr; theDestPigHFSParams.fileParam.ioVRefNum = 0; theDestPigHFSParams.fileParam.ioFDirIndex = 0; theDestPigHFSParams.fileParam.ioDirID = 0; // Copy the time stamp from the source file info theDestPigHFSParams.fileParam.ioFlCrDat = theSourcePigHFSParams.fileParam.ioFlCrDat; theDestPigHFSParams.fileParam.ioFlMdDat = theSourcePigHFSParams.fileParam.ioFlMdDat; theDestPigHFSParams.fileParam.ioFlFndrInfo.fdType = 'PGGY'; theDestPigHFSParams.fileParam.ioFlFndrInfo.fdCreator = 'DCT2'; // Set the dest file's time stamp to the source file's time stamp values theErr = PBHSetFInfo(&theDestPigHFSParams, false); if ((theErr != noErr) || (theDestPigHFSParams.fileParam.ioResult != noErr)) { Error("Can't set destination pig file time stamp: <%s>\n", destPathAndFileCStr); } theErr = PBHGetFInfo(&theDestPigHFSParams, false); return cfopen(destPathAndFileCStr, "rb"); } #else //PC Version of copy_pigfile_from_cd is below //copies a pigfile from the CD to the current dir //retuns file handle of new pig CFILE *copy_pigfile_from_cd(char *filename) { char name[80]; FILEFINDSTRUCT find; int ret; return cfopen(filename, "rb"); show_boxed_message("Copying bitmap data from CD..."); gr_palette_load(gr_palette); //I don't think this line is really needed //First, delete all PIG files currently in the directory if( !FileFindFirst( "*.pig", &find ) ) { do { remove(find.name); } while( !FileFindNext( &find ) ); FileFindClose(); } //Now, copy over new pig songs_stop_redbook(); //so we can read off the cd //new code to unarj file strcpy(name,CDROM_dir); strcat(name,"descent2.sow"); do { // ret = unarj_specific_file(name,filename,filename); // DPH:FIXME ret = !EXIT_SUCCESS; if (ret != EXIT_SUCCESS) { //delete file, so we don't leave partial file remove(filename); #ifndef MACINTOSH if (request_cd() == -1) #endif //NOTE LINK TO ABOVE IF Error("Cannot load file <%s> from CD",filename); } } while (ret != EXIT_SUCCESS); return cfopen(filename, "rb"); } #endif // end of ifdef MAC around copy_pigfile_from_cd //initialize a pigfile, reading headers //returns the size of all the bitmap data void piggy_init_pigfile(char *filename) { int i; char temp_name[16]; char temp_name_read[16]; grs_bitmap temp_bitmap; DiskBitmapHeader bmh; int header_size, N_bitmaps, data_size, data_start; #ifdef MACINTOSH char name[255]; // filename + path for the mac #endif piggy_close_file(); //close old pig if still open //rename pigfile for shareware if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(filename)) filename = DEFAULT_PIGFILE_SHAREWARE; #ifndef MACINTOSH Piggy_fp = cfopen( filename, "rb" ); #else sprintf(name, ":Data:%s", filename); Piggy_fp = cfopen( name, "rb" ); #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now. if (Piggy_fp == NULL) { Error("Cannot load required file <%s>",name); } #endif // end of if def shareware #endif if (!Piggy_fp) { #ifdef EDITOR return; //if editor, ok to not have pig, because we'll build one #else Piggy_fp = copy_pigfile_from_cd(filename); #endif } if (Piggy_fp) { //make sure pig is valid type file & is up-to-date int pig_id,pig_version; pig_id = cfile_read_int(Piggy_fp); pig_version = cfile_read_int(Piggy_fp); if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) { cfclose(Piggy_fp); //out of date pig Piggy_fp = NULL; //..so pretend it's not here } } if (!Piggy_fp) { #ifdef EDITOR return; //if editor, ok to not have pig, because we'll build one #else Error("Cannot load required file <%s>",filename); #endif } strncpy(Current_pigfile,filename,sizeof(Current_pigfile)); N_bitmaps = cfile_read_int(Piggy_fp); header_size = N_bitmaps*DISKBITMAPHEADER_SIZE; data_start = header_size + cftell(Piggy_fp); data_size = cfilelength(Piggy_fp) - data_start; Num_bitmap_files = 1; for (i=0; i 0 ); #else Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE; #ifdef MACINTOSH if (piggy_low_memory) Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE; #endif #endif BitmapBits = d_malloc( Piggy_bitmap_cache_size ); if ( BitmapBits == NULL ) Error( "Not enough memory to load bitmaps\n" ); Piggy_bitmap_cache_data = BitmapBits; Piggy_bitmap_cache_next = 0; #if defined(MACINTOSH) && defined(SHAREWARE) // load_exit_models(); #endif Pigfile_initialized=1; } #define FILENAME_LEN 13 #define MAX_BITMAPS_PER_BRUSH 30 extern int compute_average_pixel(grs_bitmap *new); //reads in a new pigfile (for new palette) //returns the size of all the bitmap data void piggy_new_pigfile(char *pigname) { int i; char temp_name[16]; char temp_name_read[16]; grs_bitmap temp_bitmap; DiskBitmapHeader bmh; int header_size, N_bitmaps, data_size, data_start; int must_rewrite_pig = 0; #ifdef MACINTOSH char name[255]; #endif strlwr(pigname); //rename pigfile for shareware if (stricmp(DEFAULT_PIGFILE, DEFAULT_PIGFILE_SHAREWARE) == 0 && !cfexist(pigname)) pigname = DEFAULT_PIGFILE_SHAREWARE; if (strnicmp(Current_pigfile,pigname,sizeof(Current_pigfile))==0) return; //already have correct pig if (!Pigfile_initialized) { //have we ever opened a pigfile? piggy_init_pigfile(pigname); //..no, so do initialization stuff return; } else piggy_close_file(); //close old pig if still open Piggy_bitmap_cache_next = 0; //free up cache strncpy(Current_pigfile,pigname,sizeof(Current_pigfile)); #ifndef MACINTOSH Piggy_fp = cfopen( pigname, "rb" ); #else sprintf(name, ":Data:%s", pigname); Piggy_fp = cfopen( name, "rb" ); #ifdef SHAREWARE // if we are in the shareware version, we must have the pig by now. if (Piggy_fp == NULL) { Error("Cannot load required file <%s>",name); } #endif // end of if def shareware #endif #ifndef EDITOR if (!Piggy_fp) Piggy_fp = copy_pigfile_from_cd(pigname); #endif if (Piggy_fp) { //make sure pig is valid type file & is up-to-date int pig_id,pig_version; pig_id = cfile_read_int(Piggy_fp); pig_version = cfile_read_int(Piggy_fp); if (pig_id != PIGFILE_ID || pig_version != PIGFILE_VERSION) { cfclose(Piggy_fp); //out of date pig Piggy_fp = NULL; //..so pretend it's not here } } #ifndef EDITOR if (!Piggy_fp) Error ("Piggy_fp not defined in piggy_new_pigfile."); #endif if (Piggy_fp) { N_bitmaps = cfile_read_int(Piggy_fp); header_size = N_bitmaps*DISKBITMAPHEADER_SIZE; data_start = header_size + cftell(Piggy_fp); data_size = cfilelength(Piggy_fp) - data_start; for (i=1; i<=N_bitmaps; i++ ) { DiskBitmapHeader_read(&bmh, Piggy_fp); memcpy( temp_name_read, bmh.name, 8 ); temp_name_read[8] = 0; if ( bmh.dflags & DBM_FLAG_ABM ) sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 ); else strcpy( temp_name, temp_name_read ); //Make sure name matches if (strcmp(temp_name,AllBitmaps[i].name)) { //Int3(); //this pig is out of date. Delete it must_rewrite_pig=1; } strcpy(AllBitmaps[i].name,temp_name); memset( &temp_bitmap, 0, sizeof(grs_bitmap) ); temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8); temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4); temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT; temp_bitmap.avg_color = bmh.avg_color; temp_bitmap.bm_data = Piggy_bitmap_cache_data; GameBitmapFlags[i] = 0; if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_TRANSPARENT; if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i] |= BM_FLAG_SUPER_TRANSPARENT; if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i] |= BM_FLAG_NO_LIGHTING; if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i] |= BM_FLAG_RLE; if ( bmh.flags & BM_FLAG_RLE_BIG ) GameBitmapFlags[i] |= BM_FLAG_RLE_BIG; GameBitmapOffset[i] = bmh.offset + data_start; GameBitmaps[i] = temp_bitmap; } } else N_bitmaps = 0; //no pigfile, so no bitmaps #ifndef EDITOR Assert(N_bitmaps == Num_bitmap_files-1); #else if (must_rewrite_pig || (N_bitmaps < Num_bitmap_files-1)) { int size; //re-read the bitmaps that aren't in this pig for (i=N_bitmaps+1;iavg_color = compute_average_pixel(bm[fnum]); #ifdef EDITOR if ( FindArg("-macdata") ) swap_0_255( bm[fnum] ); #endif if ( !BigPig ) gr_bitmap_rle_compress( bm[fnum] ); if (bm[fnum]->bm_flags & BM_FLAG_RLE) size = *((int *) bm[fnum]->bm_data); else size = bm[fnum]->bm_w * bm[fnum]->bm_h; memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],bm[fnum]->bm_data,size); d_free(bm[fnum]->bm_data); bm[fnum]->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]; Piggy_bitmap_cache_next += size; GameBitmaps[i+fnum] = *bm[fnum]; // -- mprintf( (0, "U" )); d_free( bm[fnum] ); } i += nframes-1; //filled in multiple bitmaps } else { //this is a BBM grs_bitmap * new; ubyte newpal[256*3]; int iff_error; char bbmname[FILENAME_LEN]; int SuperX; MALLOC( new, grs_bitmap, 1 ); sprintf( bbmname, "%s.bbm", AllBitmaps[i].name ); iff_error = iff_read_bitmap(bbmname,new,BM_LINEAR,newpal); new->bm_handle=0; if (iff_error != IFF_NO_ERROR) { mprintf((1, "File %s - IFF error: %s",bbmname,iff_errormsg(iff_error))); Error("File %s - IFF error: %s",bbmname,iff_errormsg(iff_error)); } SuperX = (GameBitmapFlags[i]&BM_FLAG_SUPER_TRANSPARENT)?254:-1; //above makes assumption that supertransparent color is 254 if ( iff_has_transparency ) gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX ); else gr_remap_bitmap_good( new, newpal, -1, SuperX ); new->avg_color = compute_average_pixel(new); #ifdef EDITOR if ( FindArg("-macdata") ) swap_0_255( new ); #endif if ( !BigPig ) gr_bitmap_rle_compress( new ); if (new->bm_flags & BM_FLAG_RLE) size = *((int *) new->bm_data); else size = new->bm_w * new->bm_h; memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next],new->bm_data,size); d_free(new->bm_data); new->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]; Piggy_bitmap_cache_next += size; GameBitmaps[i] = *new; d_free( new ); // -- mprintf( (0, "U" )); } } //@@Dont' do these things which are done when writing //@@for (i=0; i < Num_bitmap_files; i++ ) { //@@ bitmap_index bi; //@@ bi.index = i; //@@ PIGGY_PAGE_IN( bi ); //@@} //@@ //@@piggy_close_file(); piggy_write_pigfile(pigname); Current_pigfile[0] = 0; //say no pig, to force reload piggy_new_pigfile(pigname); //read in just-generated pig } #endif //ifdef EDITOR } ubyte bogus_data[64*64]; grs_bitmap bogus_bitmap; ubyte bogus_bitmap_initialized=0; digi_sound bogus_sound; #define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM! #define HAMFILE_VERSION 3 //version 1 -> 2: save marker_model_num //version 2 -> 3: removed sound files #define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND #define SNDFILE_VERSION 1 int read_hamfile() { CFILE * ham_fp = NULL; int ham_id; int sound_offset = 0; #ifdef MACINTOSH char name[255]; #endif #ifndef MACINTOSH ham_fp = cfopen( DEFAULT_HAMFILE, "rb" ); #else sprintf(name, ":Data:%s", DEFAULT_HAMFILE ); ham_fp = cfopen( name, "rb" ); #endif if (ham_fp == NULL) { Must_write_hamfile = 1; return 0; } //make sure ham is valid type file & is up-to-date ham_id = cfile_read_int(ham_fp); Piggy_hamfile_version = cfile_read_int(ham_fp); if (ham_id != HAMFILE_ID) Error("Cannot open ham file %s\n", DEFAULT_HAMFILE); #if 0 if (ham_id != HAMFILE_ID || Piggy_hamfile_version != HAMFILE_VERSION) { Must_write_hamfile = 1; cfclose(ham_fp); //out of date ham return 0; } #endif if (Piggy_hamfile_version < 3) // hamfile contains sound info sound_offset = cfile_read_int(ham_fp); #ifndef EDITOR { //int i; bm_read_all(ham_fp); cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp ); // no swap here? //for (i = 0; i < MAX_BITMAP_FILES; i++) { //GameBitmapXlat[i] = INTEL_SHORT(GameBitmapXlat[i]); //printf("GameBitmapXlat[%d] = %d\n", i, GameBitmapXlat[i]); //} } #endif if (Piggy_hamfile_version < 3) { int N_sounds; int sound_start; int header_size; int i; DiskSoundHeader sndh; digi_sound temp_sound; char temp_name_read[16]; int sbytes = 0; cfseek(ham_fp, sound_offset, SEEK_SET); N_sounds = cfile_read_int(ham_fp); sound_start = cftell(ham_fp); header_size = N_sounds * DISKSOUNDHEADER_SIZE; //Read sounds for (i=0; icv_h-20, "%s...", TXT_LOADING_DATA ); WIN(DDGRUNLOCK(dd_grd_curcanv)); #if 1 //def EDITOR //need for d1 mission briefings piggy_init_pigfile(DEFAULT_PIGFILE); #endif snd_ok = ham_ok = read_hamfile(); if (Piggy_hamfile_version >= 3) snd_ok = read_sndfile(); atexit(piggy_close); mprintf ((0,"HamOk=%d SndOk=%d\n",ham_ok,snd_ok)); return (ham_ok && snd_ok); //read ok } int piggy_is_needed(int soundnum) { int i; if ( !digi_lomem ) return 1; for (i=0; i 0 ) { if ( piggy_is_needed(i) ) { cfseek( fp, SoundOffset[i], SEEK_SET ); // Read in the sound data!!! snd->data = ptr; ptr += snd->length; sbytes += snd->length; cfread( snd->data, snd->length, 1, fp ); } else snd->data = (ubyte *) -1; } } cfclose(fp); mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 )); } extern int descent_critical_error; extern unsigned descent_critical_deverror; extern unsigned descent_critical_errcode; char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \ "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \ "Read fault", "General Failure" }; void piggy_critical_error() { grs_canvas * save_canv; grs_font * save_font; int i; save_canv = grd_curcanv; save_font = grd_curcanv->cv_font; gr_palette_load( gr_palette ); i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A' ); if ( i == 1 ) exit(1); gr_set_current_canvas(save_canv); grd_curcanv->cv_font = save_font; } void piggy_bitmap_page_in( bitmap_index bitmap ) { grs_bitmap * bmp; int i,org_i,temp; org_i = 0; i = bitmap.index; Assert( i >= 0 ); Assert( i < MAX_BITMAP_FILES ); Assert( i < Num_bitmap_files ); Assert( Piggy_bitmap_cache_size > 0 ); if ( i < 1 ) return; if ( i >= MAX_BITMAP_FILES ) return; if ( i >= Num_bitmap_files ) return; if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!! if ( piggy_low_memory ) { org_i = i; i = GameBitmapXlat[i]; // Xlat for low-memory settings! } bmp = &GameBitmaps[i]; if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) { stop_time(); ReDoIt: descent_critical_error = 0; cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]; bmp->bm_flags = GameBitmapFlags[i]; if ( bmp->bm_flags & BM_FLAG_RLE ) { int zsize = 0; descent_critical_error = 0; zsize = cfile_read_int(Piggy_fp); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } // GET JOHN NOW IF YOU GET THIS ASSERT!!! //Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) { Int3(); piggy_bitmap_page_out_all(); goto ReDoIt; } descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next+4], 1, zsize-4, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } #ifndef MACDATA switch (cfilelength(Piggy_fp)) { default: if (!FindArg("-macdata")) break; // otherwise, fall through... case MAC_ALIEN1_PIGSIZE: case MAC_ALIEN2_PIGSIZE: case MAC_FIRE_PIGSIZE: case MAC_GROUPA_PIGSIZE: case MAC_ICE_PIGSIZE: case MAC_WATER_PIGSIZE: rle_swap_0_255( bmp ); memcpy(&zsize, bmp->bm_data, 4); break; } #endif memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) ); Piggy_bitmap_cache_next += zsize; if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) { Int3(); piggy_bitmap_page_out_all(); goto ReDoIt; } } else { // GET JOHN NOW IF YOU GET THIS ASSERT!!! Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) { piggy_bitmap_page_out_all(); goto ReDoIt; } descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w; #ifndef MACDATA switch (cfilelength(Piggy_fp)) { default: if (!FindArg("-macdata")) break; // otherwise, fall through... case MAC_ALIEN1_PIGSIZE: case MAC_ALIEN2_PIGSIZE: case MAC_FIRE_PIGSIZE: case MAC_GROUPA_PIGSIZE: case MAC_ICE_PIGSIZE: case MAC_WATER_PIGSIZE: swap_0_255( bmp ); break; } #endif } //@@if ( bmp->bm_selector ) { //@@#if !defined(WINDOWS) && !defined(MACINTOSH) //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data )) //@@ Error( "Error modifying selector base in piggy.c\n" ); //@@#endif //@@} start_time(); } if ( piggy_low_memory ) { if ( org_i != i ) GameBitmaps[org_i] = GameBitmaps[i]; } //@@Removed from John's code: //@@#ifndef WINDOWS //@@ if ( bmp->bm_selector ) { //@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data )) //@@ Error( "Error modifying selector base in piggy.c\n" ); //@@ } //@@#endif } void piggy_bitmap_page_out_all() { int i; Piggy_bitmap_cache_next = 0; piggy_page_flushed++; texmerge_flush(); rle_cache_flush(); for (i=0; i 0 ) { // Don't page out bitmaps read from disk!!! GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT; GameBitmaps[i].bm_data = Piggy_bitmap_cache_data; } } mprintf(( 0, "Flushing piggy bitmap cache\n" )); } void piggy_load_level_data() { piggy_bitmap_page_out_all(); paging_touch_all(); } #ifdef EDITOR void change_filename_ext( char *dest, char *src, char *ext ); void piggy_write_pigfile(char *filename) { FILE *pig_fp; int bitmap_data_start,data_offset; DiskBitmapHeader bmh; int org_offset; char subst_name[32]; int i; FILE *fp1,*fp2; char tname[FILENAME_LEN]; // -- mprintf( (0, "Paging in all piggy bitmaps..." )); for (i=0; i < Num_bitmap_files; i++ ) { bitmap_index bi; bi.index = i; PIGGY_PAGE_IN( bi ); } // -- mprintf( (0, "\n" )); piggy_close_file(); // -- mprintf( (0, "Creating %s...",filename )); pig_fp = fopen( filename, "wb" ); //open PIG file Assert( pig_fp!=NULL ); write_int(PIGFILE_ID,pig_fp); write_int(PIGFILE_VERSION,pig_fp); Num_bitmap_files--; fwrite( &Num_bitmap_files, sizeof(int), 1, pig_fp ); Num_bitmap_files++; bitmap_data_start = ftell(pig_fp); bitmap_data_start += (Num_bitmap_files-1)*DISKBITMAPHEADER_SIZE; data_offset = bitmap_data_start; change_filename_ext(tname,filename,"lst"); fp1 = fopen( tname, "wt" ); change_filename_ext(tname,filename,"all"); fp2 = fopen( tname, "wt" ); for (i=1; i < Num_bitmap_files; i++ ) { int *size; grs_bitmap *bmp; { char * p, *p1; p = strchr(AllBitmaps[i].name,'#'); if (p) { int n; p1 = p; p1++; n = atoi(p1); *p = 0; if (fp2 && n==0) fprintf( fp2, "%s.abm\n", AllBitmaps[i].name ); memcpy( bmh.name, AllBitmaps[i].name, 8 ); Assert( n <= 63 ); bmh.dflags = DBM_FLAG_ABM + n; *p = '#'; }else { if (fp2) fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name ); memcpy( bmh.name, AllBitmaps[i].name, 8 ); bmh.dflags = 0; } } bmp = &GameBitmaps[i]; Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) ); if (fp1) fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h ); org_offset = ftell(pig_fp); bmh.offset = data_offset - bitmap_data_start; fseek( pig_fp, data_offset, SEEK_SET ); if ( bmp->bm_flags & BM_FLAG_RLE ) { size = (int *)bmp->bm_data; fwrite( bmp->bm_data, sizeof(ubyte), *size, pig_fp ); data_offset += *size; if (fp1) fprintf( fp1, ", and is already compressed to %d bytes.\n", *size ); } else { fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, pig_fp ); data_offset += bmp->bm_rowsize * bmp->bm_h; if (fp1) fprintf( fp1, ".\n" ); } fseek( pig_fp, org_offset, SEEK_SET ); Assert( GameBitmaps[i].bm_w < 4096 ); bmh.width = (GameBitmaps[i].bm_w & 0xff); bmh.wh_extra = ((GameBitmaps[i].bm_w >> 8) & 0x0f); Assert( GameBitmaps[i].bm_h < 4096 ); bmh.height = GameBitmaps[i].bm_h; bmh.wh_extra |= ((GameBitmaps[i].bm_h >> 4) & 0xf0); bmh.flags = GameBitmaps[i].bm_flags; if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name )) { bitmap_index other_bitmap; other_bitmap = piggy_find_bitmap( subst_name ); GameBitmapXlat[i] = other_bitmap.index; bmh.flags |= BM_FLAG_PAGED_OUT; //mprintf(( 0, "Skipping bitmap %d\n", i )); //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name )); } else { bmh.flags &= ~BM_FLAG_PAGED_OUT; } bmh.avg_color=GameBitmaps[i].avg_color; fwrite( &bmh, DISKBITMAPHEADER_SIZE, 1, pig_fp ); // Mark as a bitmap } fclose(pig_fp); mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files )); fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ); fclose(fp1); fclose(fp2); } static void write_int(int i,FILE *file) { if (fwrite( &i, sizeof(i), 1, file) != 1) Error( "Error reading int in gamesave.c" ); } void piggy_dump_all() { int i, xlat_offset; FILE * ham_fp; int org_offset,data_offset=0; DiskSoundHeader sndh; int sound_data_start=0; FILE *fp1,*fp2; #ifdef NO_DUMP_SOUNDS Num_sound_files = 0; Num_sound_files_new = 0; #endif if (!Must_write_hamfile && (Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) ) return; fp1 = fopen( "ham.lst", "wt" ); fp2 = fopen( "ham.all", "wt" ); if (Must_write_hamfile || Num_bitmap_files_new) { mprintf( (0, "Creating %s...",DEFAULT_HAMFILE)); ham_fp = fopen( DEFAULT_HAMFILE, "wb" ); //open HAM file Assert( ham_fp!=NULL ); write_int(HAMFILE_ID,ham_fp); write_int(HAMFILE_VERSION,ham_fp); bm_write_all(ham_fp); xlat_offset = ftell(ham_fp); fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, ham_fp ); //Dump bitmaps if (Num_bitmap_files_new) piggy_write_pigfile(DEFAULT_PIGFILE); //free up memeory used by new bitmaps for (i=Num_bitmap_files-Num_bitmap_files_new;idata, sizeof(ubyte), snd->length, ham_fp ); data_offset += snd->length; fseek( ham_fp, org_offset, SEEK_SET ); fwrite( &sndh, sizeof(DiskSoundHeader), 1, ham_fp ); // Mark as a bitmap fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length ); fprintf( fp2, "%s.raw\n", AllSounds[i].name ); } fclose(ham_fp); mprintf( (0, "\n" )); } fprintf( fp1, "Total sound size: %d bytes\n", data_offset-sound_data_start); mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files )); fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files ); fclose(fp1); fclose(fp2); // Never allow the game to run after building ham. exit(0); } #endif void piggy_close() { piggy_close_file(); if (BitmapBits) d_free(BitmapBits); if ( SoundBits ) d_free( SoundBits ); hashtable_free( &AllBitmapsNames ); hashtable_free( &AllDigiSndNames ); } int piggy_does_bitmap_exist_slow( char * name ) { int i; for (i=0; i= FIRST_D1_TEXTURE && d1_index <= LAST_D1_STATIC_TEXTURE) { d2_index = d1_index + FIRST_D2_TEXTURE - FIRST_D1_TEXTURE; cfseek(d1_Piggy_fp, bitmap_header_start + (d1_index-1) * DISKBITMAPHEADER_D1_SIZE, SEEK_SET); DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp); memset( &temp_bitmap, 0, sizeof(grs_bitmap) ); temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8); temp_bitmap.bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4); temp_bitmap.avg_color = bmh.avg_color; //GameBitmapFlags[convert_d1_bitmap_num(d1_index)] = 0; if ( bmh.flags & BM_FLAG_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_TRANSPARENT; if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) temp_bitmap.bm_flags |= BM_FLAG_SUPER_TRANSPARENT; if ( bmh.flags & BM_FLAG_NO_LIGHTING ) temp_bitmap.bm_flags |= BM_FLAG_NO_LIGHTING; if ( bmh.flags & BM_FLAG_RLE ) temp_bitmap.bm_flags |= BM_FLAG_RLE; if ( bmh.flags & BM_FLAG_RLE_BIG ) temp_bitmap.bm_flags |= BM_FLAG_RLE_BIG; temp_bitmap.bm_data = next_bitmap; cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET); zsize = cfile_read_int(d1_Piggy_fp); cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET); cfread(next_bitmap, 1, zsize, d1_Piggy_fp); switch(cfilelength(d1_Piggy_fp)) { case D1_MAC_PIGSIZE: case D1_MAC_SHARE_PIGSIZE: rle_swap_0_255(&temp_bitmap); } rle_remap(&temp_bitmap, colormap); GameBitmaps[d2_index] = temp_bitmap; memcpy(&zsize, temp_bitmap.bm_data, 4); next_bitmap += zsize; } } cfclose(d1_Piggy_fp); last_palette_loaded_pig[0]= 0; //force pig re-load texmerge_flush(); //for re-merging with new textures atexit(free_bitmap_replacements); } extern int extra_bitmap_num; /* * Find and load the named bitmap from descent.pig * similar to exitmodel_bm_load_sub */ bitmap_index read_extra_d1_bitmap(char *name) { bitmap_index bitmap_num; grs_bitmap * new = &GameBitmaps[extra_bitmap_num]; bitmap_num.index = 0; { CFILE *d1_Piggy_fp; int i; DiskBitmapHeader bmh; int pig_data_start, bitmap_header_start, bitmap_data_start; int N_bitmaps, zsize; ubyte colormap[256]; d1_Piggy_fp = cfopen("descent.pig", "rb"); if (!d1_Piggy_fp) { con_printf(CON_DEBUG, "could not open descent.pig\n", name); return bitmap_num; } // read d1 palette, build colormap { int freq[256]; ubyte d1_palette[256*3]; CFILE * palette_file = cfopen( "palette.256", "rb" ); Assert( palette_file ); Assert( cfilelength( palette_file ) == 9472 ); cfread( d1_palette, 256, 3, palette_file); cfclose( palette_file ); build_colormap_good( d1_palette, colormap, freq ); // don't change transparencies: colormap[254] = 254; colormap[255] = 255; } switch (cfilelength(d1_Piggy_fp)) { case D1_SHAREWARE_10_PIGSIZE: case D1_SHAREWARE_PIGSIZE: pig_data_start = 0; break; default: Int3(); case D1_PIGSIZE: case D1_OEM_PIGSIZE: case D1_MAC_PIGSIZE: case D1_MAC_SHARE_PIGSIZE: pig_data_start = cfile_read_int(d1_Piggy_fp); break; } cfseek(d1_Piggy_fp, pig_data_start, SEEK_SET); N_bitmaps = cfile_read_int(d1_Piggy_fp); { int N_sounds = cfile_read_int(d1_Piggy_fp); int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE + N_sounds * DISKSOUNDHEADER_SIZE; bitmap_header_start = pig_data_start + 2 * sizeof(int); bitmap_data_start = bitmap_header_start + header_size; } for (i = 0; i < N_bitmaps; i++) { DiskBitmapHeader_d1_read(&bmh, d1_Piggy_fp); if (!strnicmp(bmh.name, name, 8)) break; } Assert(!strnicmp(bmh.name, name, 8)); memset( new, 0, sizeof(grs_bitmap) ); new->bm_w = new->bm_rowsize = bmh.width + ((short) (bmh.wh_extra&0x0f)<<8); new->bm_h = bmh.height + ((short) (bmh.wh_extra&0xf0)<<4); new->avg_color = bmh.avg_color; if ( bmh.flags & BM_FLAG_TRANSPARENT ) new->bm_flags |= BM_FLAG_TRANSPARENT; if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) new->bm_flags |= BM_FLAG_SUPER_TRANSPARENT; if ( bmh.flags & BM_FLAG_NO_LIGHTING ) new->bm_flags |= BM_FLAG_NO_LIGHTING; if ( bmh.flags & BM_FLAG_RLE ) new->bm_flags |= BM_FLAG_RLE; if ( bmh.flags & BM_FLAG_RLE_BIG ) new->bm_flags |= BM_FLAG_RLE_BIG; if ( bmh.flags & BM_FLAG_RLE ) { cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET); zsize = cfile_read_int(d1_Piggy_fp); } else zsize = new->bm_w * new->bm_h; new->bm_data = d_malloc(zsize); cfseek(d1_Piggy_fp, bitmap_data_start + bmh.offset, SEEK_SET); cfread(new->bm_data, 1, zsize, d1_Piggy_fp); switch(cfilelength(d1_Piggy_fp)) { case D1_MAC_PIGSIZE: case D1_MAC_SHARE_PIGSIZE: rle_swap_0_255(new); } rle_remap(new, colormap); cfclose(d1_Piggy_fp); } new->avg_color = 0; //compute_average_pixel(new); bitmap_num.index = extra_bitmap_num; GameBitmaps[extra_bitmap_num++] = *new; return bitmap_num; } #ifndef FAST_FILE_IO /* * reads a bitmap_index structure from a CFILE */ void bitmap_index_read(bitmap_index *bi, CFILE *fp) { bi->index = cfile_read_short(fp); } /* * reads n bitmap_index structs from a CFILE */ int bitmap_index_read_n(bitmap_index *bi, int n, CFILE *fp) { int i; for (i = 0; i < n; i++) bi[i].index = cfile_read_short(fp); return i; } /* * reads a DiskBitmapHeader structure from a CFILE */ void DiskBitmapHeader_read(DiskBitmapHeader *dbh, CFILE *fp) { cfread(dbh->name, 8, 1, fp); dbh->dflags = cfile_read_byte(fp); dbh->width = cfile_read_byte(fp); dbh->height = cfile_read_byte(fp); dbh->wh_extra = cfile_read_byte(fp); dbh->flags = cfile_read_byte(fp); dbh->avg_color = cfile_read_byte(fp); dbh->offset = cfile_read_int(fp); } /* * reads a DiskSoundHeader structure from a CFILE */ void DiskSoundHeader_read(DiskSoundHeader *dsh, CFILE *fp) { cfread(dsh->name, 8, 1, fp); dsh->length = cfile_read_int(fp); dsh->data_length = cfile_read_int(fp); dsh->offset = cfile_read_int(fp); } #endif // FAST_FILE_IO /* * reads a descent 1 DiskBitmapHeader structure from a CFILE */ void DiskBitmapHeader_d1_read(DiskBitmapHeader *dbh, CFILE *fp) { cfread(dbh->name, 8, 1, fp); dbh->dflags = cfile_read_byte(fp); dbh->width = cfile_read_byte(fp); dbh->height = cfile_read_byte(fp); dbh->wh_extra = 0; dbh->flags = cfile_read_byte(fp); dbh->avg_color = cfile_read_byte(fp); dbh->offset = cfile_read_int(fp); }