/** * \brief Add directory to zip file. * \param[in] path Directory path that will be added to zip file. * \param[in,out] f File stream to write compressed files to. * \return On success true, otherwise false. */ PRIVATE wtBoolean Pak_addDirectoryToZipFile( const char *path, FILE *f ) { char temp[ 256 ]; char *ptr; zipHead_t *newZipNode = NULL; wt_strlcpy( temp, path, sizeof( temp ) ); if( strstr( temp, "*" ) == NULL ) { wt_strlcat( temp, "/*", sizeof( temp ) ); } // Look for files ptr = FS_FindFirst( temp ); do { wt_snprintf( temp, sizeof( temp ), "%s/%s", path, ptr ); if ( temp[strlen(temp)-1] == '.' ) { continue; } if( ! FS_CompareFileAttributes( temp, 0, FA_DIR ) ) { continue; } newZipNode = Pak_WriteLocalFileChunk( temp, f ); if( newZipNode == NULL ) { continue; } // add new zipHead_t to chain zipChainLast = linkList_addList( zipChainLast, newZipNode ); } while( (ptr = FS_FindNext()) != NULL ); FS_FindClose(); return true; }
/** * \brief Setup page file for decoding. * \param[in] pagefname Source buffer to convert from * \param[out] nBlocks Destination buffer to convert to. * \param[out] SpriteStart Offset index for sprite data. * \param[out] SoundStart Offset index for sound data. * \return On success true, otherwise false. */ PUBLIC wtBoolean PageFile_Setup( const char *pagefname, W32 *nBlocks, W32 *SpriteStart, W32 *SoundStart ) { W32 i; W32 size; void *buf = NULL; W32 *offsetptr; char *temp_fileName = NULL; PageList_t *page; W16 *lengthptr; W16 tval; W32 PMNumBlocks; W32 PMSpriteStart; W32 PMSoundStart; if( ! pagefname || ! *pagefname ) { fprintf( stderr, "[PageFile_Setup]: Invalid file name\n" ); goto PMSetupFailure; } temp_fileName = (char *) MM_MALLOC( strlen( pagefname ) + 1 ); if( temp_fileName == NULL ) { goto PMSetupFailure; } wt_strlcpy( temp_fileName, pagefname, strlen( pagefname ) + 1 ); /* Open page file */ file_handle_page = fopen( wt_strupr( temp_fileName ), "rb" ); if( file_handle_page == NULL ) { file_handle_page = fopen( wt_strlwr( temp_fileName ), "rb" ); if( file_handle_page == NULL ) { fprintf( stderr, "Could not open file (%s) for read!\n", temp_fileName ); goto PMSetupFailure; } } /* Read in header variables */ fread( &tval, sizeof( W16 ), 1, file_handle_page ); PMNumBlocks = LittleShort( tval ); fread( &tval, sizeof( W16 ), 1, file_handle_page ); PMSpriteStart = LittleShort( tval ); fread( &tval, sizeof( W16 ), 1, file_handle_page ); PMSoundStart = LittleShort( tval ); /* Allocate and clear the page list */ PMPages = (PageList_t *) MM_MALLOC( sizeof( PageList_t ) * PMNumBlocks ); if( PMPages == NULL ) { goto PMSetupFailure; } memset( PMPages, 0, sizeof( PageList_t ) * PMNumBlocks ); /* Read in the chunk offsets */ size = sizeof( W32 ) * PMNumBlocks; buf = MM_MALLOC( size ); if( buf == NULL ) { goto PMSetupFailure; } if( fread( buf, 1, size, file_handle_page ) == 0 ) { fprintf( stderr, "Could not read chunk offsets from file (%s)\n", temp_fileName ); } offsetptr = (PW32) buf; for( i = 0, page = PMPages; i < PMNumBlocks; i++, page++ ) { page->offset = LittleLong( *offsetptr++ ); } MM_FREE( buf ); /* Read in the chunk lengths */ size = sizeof( W16 ) * PMNumBlocks; buf = MM_MALLOC( size ); if( buf == NULL ) { goto PMSetupFailure; } if( fread( buf, 1, size, file_handle_page ) == 0 ) { fprintf( stderr, "Could not read chunk lengths from file (%s)\n", temp_fileName ); } lengthptr = (PW16)buf; for( i = 0, page = PMPages ; i < PMNumBlocks ; ++i, page++ ) { page->length = LittleShort( *lengthptr++ ); } MM_FREE( buf ); MM_FREE( temp_fileName ); *nBlocks = PMNumBlocks; *SpriteStart = PMSpriteStart; *SoundStart = PMSoundStart; return true; PMSetupFailure: MM_FREE( temp_fileName ); MM_FREE( PMPages ); MM_FREE( buf ); return false; }
/** * \brief Setup map files for decoding. * \param[in] headFileName Name of file with header offsets. * \param[in] mapFileName Name of file with map data. * \param[in,out] RLEWtag Run length encoded word tag. * \param[in,out] nTotalMaps Number of maps in file. * \return On success true, otherwise false. * \note Must call function MapFile_Shutdown() when done. */ PUBLIC wtBoolean MapFile_Setup( const char *headFileName, const char *mapFileName, W16 *RLEWtag, W32 *nTotalMaps ) { FILE *fileHandle; SW32 fileSize; char *tempFileName; W32 TotalMaps; tempFileName = (char *) MM_MALLOC( strlen( headFileName ) + 1 ); if( tempFileName == NULL ) { return false; } // // Load map head file to get offsets and tile info. // wt_strlcpy( tempFileName, headFileName, strlen( headFileName ) + 1 ); fileHandle = fopen( wt_strupr( tempFileName ), "rb" ); if( fileHandle == NULL ) { fileHandle = fopen( wt_strlwr( tempFileName ), "rb" ); if( fileHandle == NULL ) { fprintf( stderr, "Could not open file (%s) for read!\n", tempFileName ); MM_FREE( tempFileName ); return false; } } fileSize = FS_FileLength( fileHandle ); fread( RLEWtag, 2, 1, fileHandle ); for( TotalMaps = 0 ; TotalMaps < fileSize ; ++TotalMaps ) { fread( &headerOffsets[ TotalMaps ], 4, 1, fileHandle ); if( ! headerOffsets[ TotalMaps ] ) { break; } } fclose( fileHandle ); MM_FREE( tempFileName ); tempFileName = (char *) MM_MALLOC( strlen( mapFileName ) + 1 ); wt_strlcpy( tempFileName, mapFileName, strlen( mapFileName ) + 1 ); // // Open map data file. // map_file_handle = fopen( wt_strupr( tempFileName ), "rb"); if( NULL == map_file_handle ) { map_file_handle = fopen( wt_strlwr( tempFileName ), "rb"); if( NULL == map_file_handle ) { MM_FREE( tempFileName ); return false; } } *nTotalMaps = TotalMaps; MM_FREE( tempFileName ); return true; }
/** * \brief Add script file to zip file. * \param[in,out] fout File stream to write compressed files to. * \param[in] version Version to write into script file. * \return On success pointer to zlist structure, otherwise NULL. */ PRIVATE zipHead_t *Pak_addScriptToZipFile( FILE *fout, W8 version ) { W8 *data; zipHead_t *zentry; struct filestats fs; SW32 err; W32 retval; W32 scriptSize; W8 *compr; z_stream c_stream; /* compression stream */ scriptSize = sizeof( defaultscript ) / sizeof( defaultscript[ 0 ] ); defaultscript[ scriptSize - 5 ] = version + 48; data = (PW8) &defaultscript; zentry = (zipHead_t *) MM_MALLOC( sizeof( *zentry ) ); memset( zentry, 0, sizeof( *zentry ) ); zentry->versionmadeby = VMB_VFAT; zentry->versionneeded = 20; zentry->disknumstart = 0; zentry->compression_method = CM_DEFLATED; zentry->deletefile = 0; zentry->uncompressed_size = scriptSize; //FS_GetFileAttributes( filename, &fs ); zentry->timedate = UnixTimeToDosTime( &fs.lastwritetime ); // // Compression // c_stream.zalloc = (alloc_func)0; c_stream.zfree = (free_func)0; c_stream.opaque = (voidpf)0; err = deflateInit( &c_stream, Z_DEFAULT_COMPRESSION ); if( err != Z_OK ) { MM_FREE( zentry ); return NULL; } zentry->compressed_size = (zentry->uncompressed_size / 10) + 12 + zentry->uncompressed_size; compr = (PW8) MM_MALLOC( zentry->compressed_size ); c_stream.next_out = compr; c_stream.avail_out = (uInt)zentry->compressed_size; c_stream.next_in = data; c_stream.avail_in = (uInt)zentry->uncompressed_size; err = deflate( &c_stream, Z_FINISH ); if( err != Z_STREAM_END ) { MM_FREE( compr ); MM_FREE( zentry ); return NULL; } err = deflateEnd( &c_stream ); if( err != Z_OK ) { MM_FREE( compr ); MM_FREE( zentry ); return NULL; } // When using the deflate method, ZLib adds a 2 byte head // and a 4 byte tail. The head must be removed for zip // compatability and the tail is not necessary. zentry->compressed_size = c_stream.total_out - 6; // // End of compression // zentry->crc32 = crc32( 0, data, zentry->uncompressed_size ); wt_strlcpy( zentry->filename, SCRIPTNAME, sizeof( zentry->filename ) ); zentry->filename_length = strlen( zentry->filename ); zentry->offset = ftell( fout ); // // Write header to file // if( ! zip_WriteLocalChunk( zentry, fout ) ) { fprintf( stderr, "Error writing local header to zip file\n" ); MM_FREE( compr ); MM_FREE( zentry ); return NULL; } // // Write data to file // retval = fwrite( compr+2, 1, zentry->compressed_size, fout ); if( retval != zentry->compressed_size ) { fprintf( stderr, "Error writing data after local header to zip file\n" ); MM_FREE( compr ); MM_FREE( zentry ); return NULL; } MM_FREE( compr ); return zentry; }
/** * \brief Setup for audio decoding. * \param[in] aheadfname Audio header file name. * \param[in] audfname Audio file name. * \return On success true, otherwise false. */ PUBLIC wtBoolean AudioFile_Setup( const char *aheadfname, const char *audfname ) { char tempFileName[ 1024 ]; FILE *handle; SW32 length; SW32 count; /* Number of bytes read from file */ if( ! aheadfname || ! *aheadfname || ! audfname || ! *audfname ) { fprintf( stderr, "[AudioFile_Setup]: NULL file name!\n" ); return false; } // // Load audiohed.XXX (offsets and lengths for audio file) // wt_strlcpy( tempFileName, aheadfname, sizeof( tempFileName ) ); handle = fopen( wt_strupr( tempFileName ), "rb" ); if( handle == NULL ) { handle = fopen( wt_strlwr( tempFileName ), "rb" ); if( handle == NULL ) { fprintf( stderr, "Could not open file (%s) for read!\n", tempFileName ); return false; } } length = FS_FileLength( handle ); if( length < 4 ) { fclose( handle ); fprintf( stderr, "[AudioFile_Setup]: Incorrect audio header size on file: %s\n", tempFileName ); return false; } audiostarts = (PW32) MM_MALLOC( length ); if( audiostarts == NULL ) { fclose( handle ); return false; } count = fread( audiostarts, 1, length, handle ); if( count != length ) { fclose( handle ); fprintf( stderr, "[AudioFile_Setup]: Read error on file: (%s)", tempFileName ); return false; } fclose( handle ); // // Open the Audio data file // wt_strlcpy( tempFileName, audfname, sizeof( tempFileName ) ); audiohandle = fopen( wt_strupr( tempFileName ), "rb" ); if( audiohandle == NULL ) { audiohandle = fopen( wt_strlwr( tempFileName ), "rb" ); if( audiohandle == NULL ) { fprintf( stderr, "[AudioFile_Setup]: Could not open file (%s) for read!\n", tempFileName ); return false; } } return true; }