bool LoadFileIntoBuffer( const char *pFileName, CUtlBuffer &buf ) { struct _stat statBuf; if( _stat( pFileName, &statBuf ) != 0 ) { goto error; } buf.EnsureCapacity( statBuf.st_size ); FILE *fp; fp = fopen( pFileName, "rb" ); if( !fp ) { goto error; } int nBytesRead = fread( buf.Base(), 1, statBuf.st_size, fp ); fclose( fp ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); return true; error: printf( "Can't find file %s\n", pFileName ); return false; }
//----------------------------------------------------------------------------- // NOTE: This is an exact copy of code in BaseFileSystem.cpp which // has to be here because they want to call // the implementation of Open/Size/Read/Write in CBaseVMPIFileSystem //----------------------------------------------------------------------------- bool CBaseVMPIFileSystem::ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes, int nStartingByte, FSAllocFunc_t pfnAlloc ) { const char *pReadFlags = "rb"; if ( buf.IsText() && !buf.ContainsCRLF() ) { pReadFlags = "rt"; } FileHandle_t fp = Open( pFileName, buf.IsText() ? "rt" : "rb", pPath ); if ( !fp ) return false; int nBytesToRead = Size( fp ); if ( nMaxBytes > 0 ) { nBytesToRead = min( nMaxBytes, nBytesToRead ); } buf.EnsureCapacity( nBytesToRead + buf.TellPut() ); if ( nStartingByte != 0 ) { Seek( fp, nStartingByte, FILESYSTEM_SEEK_HEAD ); } int nBytesRead = Read( buf.PeekPut(), nBytesToRead, fp ); buf.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead ); Close( fp ); return (nBytesRead != 0); }
static bool LoadFile( char const* pFileName, CUtlBuffer& buf ) { FileHandle_t fp; // load the model if( (fp = g_pFileSystem->Open(pFileName, "rb" )) == NULL) return false; // Get the file size int size = g_pFileSystem->Size( fp ); if (size == 0) { g_pFileSystem->Close( fp ); return false; } buf.EnsureCapacity( size ); g_pFileSystem->Read( buf.PeekPut(), size, fp ); g_pFileSystem->Close( fp ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, size ); buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); return true; }
// build the final pool void GetTableAndPool( CUtlVector< unsigned int > &offsets, CUtlBuffer &buffer ) { offsets.Purge(); buffer.Purge(); offsets.EnsureCapacity( m_StringMap.GetNumStrings() ); buffer.EnsureCapacity( m_nOffset ); unsigned int currentOffset = 0; for ( int i = 0; i < m_StringMap.GetNumStrings(); i++ ) { offsets.AddToTail( currentOffset ); const char *pString = m_StringMap.String( i ); buffer.Put( pString, strlen( pString ) + 1 ); currentOffset += strlen( pString ) + 1; } Assert( currentOffset == m_nOffset ); // align string pool to end on dword boundary while ( buffer.TellMaxPut() & 0x03 ) { buffer.PutChar( '\0' ); m_nOffset++; } }
//----------------------------------------------------------------------------- // Purpose: Saves a bit string to the given file // Input : // Output : //----------------------------------------------------------------------------- void SaveBitString(const int *pInts, int nInts, CUtlBuffer& buf) { buf.EnsureCapacity( buf.TellPut() + (sizeof( int )*nInts) ); for (int i=0;i<nInts;i++) { buf.PutInt( pInts[i] ); } }
//----------------------------------------------------------------------------- // Does a texture have alpha? //----------------------------------------------------------------------------- static bool DoesTextureUseAlpha( const char *pTextureName, const char *pMaterialName ) { if ( IsX360() ) { // not supporting return false; } // Special textures start with '_'.. if ( pTextureName[0] == '_' ) return false; // The texture name doubles as the relative file name // It's assumed to have already been set by this point // Compute the cache name char pCacheFileName[MATERIAL_MAX_PATH]; Q_snprintf( pCacheFileName, sizeof( pCacheFileName ), "materials/%s.vtf", pTextureName ); CUtlBuffer buf; FileHandle_t fileHandle = g_pFullFileSystem->Open( pCacheFileName, "rb" ); if ( fileHandle == FILESYSTEM_INVALID_HANDLE) { Warning( "Material \"%s\": can't open texture \"%s\"\n", pMaterialName, pCacheFileName ); return false; } // Check the .vtf for an alpha channel IVTFTexture *pVTFTexture = CreateVTFTexture(); int nHeaderSize = VTFFileHeaderSize( VTF_MAJOR_VERSION ); buf.EnsureCapacity( nHeaderSize ); // read the header first.. it's faster!! g_pFullFileSystem->Read( buf.Base(), nHeaderSize, fileHandle ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, nHeaderSize ); // Unserialize the header bool bUsesAlpha = false; if (!pVTFTexture->Unserialize( buf, true )) { Warning( "Error reading material \"%s\"\n", pCacheFileName ); g_pFullFileSystem->Close(fileHandle); } else { if ( pVTFTexture->Flags() & (TEXTUREFLAGS_ONEBITALPHA | TEXTUREFLAGS_EIGHTBITALPHA) ) { bUsesAlpha = true; } } DestroyVTFTexture( pVTFTexture ); g_pFullFileSystem->Close( fileHandle ); return bUsesAlpha; }
// Assumed to be set up by calling code bool AsyncCaption_t::LoadFromFile( const char *pRelativePath ) { char pRelativePathFixed[MAX_PATH]; Q_strncpy( pRelativePathFixed, pRelativePath, sizeof(pRelativePathFixed) ); Q_FixSlashes( pRelativePathFixed ); Q_strlower( pRelativePathFixed ); pRelativePath = pRelativePathFixed; if ( Q_IsAbsolutePath( pRelativePath ) ) { Warning( "AsyncCaption_t::LoadFromFile: Fullpath encountered! %s\n", pRelativePath ); } FileHandle_t fh = g_pFullFileSystem->Open( pRelativePath, "rb", "GAME" ); if ( FILESYSTEM_INVALID_HANDLE == fh ) return false; MEM_ALLOC_CREDIT(); CUtlBuffer dirbuffer; // Read the header g_pFullFileSystem->Read( &m_Header, sizeof( m_Header ), fh ); if ( m_Header.magic != COMPILED_CAPTION_FILEID ) Error( "Invalid file id for %s\n", pRelativePath ); if ( m_Header.version != COMPILED_CAPTION_VERSION ) Error( "Invalid file version for %s\n", pRelativePath ); if ( m_Header.directorysize < 0 || m_Header.directorysize > 64 * 1024 ) Error( "Invalid directory size %d for %s\n", m_Header.directorysize, pRelativePath ); //if ( m_Header.blocksize != MAX_BLOCK_SIZE ) // Error( "Invalid block size %d, expecting %d for %s\n", m_Header.blocksize, MAX_BLOCK_SIZE, pchFullPath ); int directoryBytes = m_Header.directorysize * sizeof( CaptionLookup_t ); m_CaptionDirectory.EnsureCapacity( m_Header.directorysize ); dirbuffer.EnsureCapacity( directoryBytes ); g_pFullFileSystem->Read( dirbuffer.Base(), directoryBytes, fh ); g_pFullFileSystem->Close( fh ); m_CaptionDirectory.CopyArray( (const CaptionLookup_t *)dirbuffer.PeekGet(), m_Header.directorysize ); m_CaptionDirectory.RedoSort( true ); m_DataBaseFile = pRelativePath; return true; }
//----------------------------------------------------------------------------- // Rebuilds all of a MDL's components. //----------------------------------------------------------------------------- static bool GenerateModelFiles( const char *pMdlFilename ) { CUtlBuffer tempBuffer; int fileSize; int paddedSize; int swappedSize; // .mdl CUtlBuffer mdlBuffer; if ( !scriptlib->ReadFileToBuffer( pMdlFilename, mdlBuffer ) ) { return false; } if ( !Studio_ConvertStudioHdrToNewVersion( (studiohdr_t *)mdlBuffer.Base() )) { Msg("%s needs to be recompiled\n", pMdlFilename ); } // .vtx char szVtxFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVtxFilename, sizeof( szVtxFilename ) ); V_strncat( szVtxFilename, ".dx90.vtx", sizeof( szVtxFilename ) ); CUtlBuffer vtxBuffer; bool bHasVtx = ReadFileToBuffer( szVtxFilename, vtxBuffer, false, true ); // .vvd char szVvdFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVvdFilename, sizeof( szVvdFilename ) ); V_strncat( szVvdFilename, ".vvd", sizeof( szVvdFilename ) ); CUtlBuffer vvdBuffer; bool bHasVvd = ReadFileToBuffer( szVvdFilename, vvdBuffer, false, true ); if ( bHasVtx != bHasVvd ) { // paired resources, either mandates the other return false; } // a .mdl file that has .vtx/.vvd gets re-processed to cull lod data if ( bHasVtx && bHasVvd ) { // cull lod if needed IMdlStripInfo *pStripInfo = NULL; bool bResult = mdllib->StripModelBuffers( mdlBuffer, vvdBuffer, vtxBuffer, &pStripInfo ); if ( !bResult ) { return false; } if ( pStripInfo ) { // .vsi CUtlBuffer vsiBuffer; pStripInfo->Serialize( vsiBuffer ); pStripInfo->DeleteThis(); // save strip info for later processing char szVsiFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVsiFilename, sizeof( szVsiFilename ) ); V_strncat( szVsiFilename, ".vsi", sizeof( szVsiFilename ) ); WriteBufferToFile( szVsiFilename, vsiBuffer, false, WRITE_TO_DISK_ALWAYS ); } } // .ani processing may further update .mdl buffer char szAniFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szAniFilename, sizeof( szAniFilename ) ); V_strncat( szAniFilename, ".ani", sizeof( szAniFilename ) ); CUtlBuffer aniBuffer; bool bHasAni = ReadFileToBuffer( szAniFilename, aniBuffer, false, true ); if ( bHasAni ) { // Some vestigal .ani files exist in the tree, only process valid .ani if ( ((studiohdr_t*)mdlBuffer.Base())->numanimblocks != 0 ) { // .ani processing modifies .mdl buffer fileSize = aniBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; aniBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szAniFilename, sizeof( szAniFilename ) ); V_strncat( szAniFilename, ".360.ani", sizeof( szAniFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szAniFilename, tempBuffer.Base(), aniBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .ani buffer is replaced with swapped data aniBuffer.Purge(); aniBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szAniFilename, aniBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } } // .phy char szPhyFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szPhyFilename, sizeof( szPhyFilename ) ); V_strncat( szPhyFilename, ".phy", sizeof( szPhyFilename ) ); CUtlBuffer phyBuffer; bool bHasPhy = ReadFileToBuffer( szPhyFilename, phyBuffer, false, true ); if ( bHasPhy ) { fileSize = phyBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; phyBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szPhyFilename, sizeof( szPhyFilename ) ); V_strncat( szPhyFilename, ".360.phy", sizeof( szPhyFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szPhyFilename, tempBuffer.Base(), phyBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .phy buffer is replaced with swapped data phyBuffer.Purge(); phyBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szPhyFilename, phyBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } if ( bHasVtx ) { fileSize = vtxBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; vtxBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szVtxFilename, sizeof( szVtxFilename ) ); V_strncat( szVtxFilename, ".dx90.360.vtx", sizeof( szVtxFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szVtxFilename, tempBuffer.Base(), vtxBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .vtx buffer is replaced with swapped data vtxBuffer.Purge(); vtxBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szVtxFilename, vtxBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } if ( bHasVvd ) { fileSize = vvdBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; vvdBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szVvdFilename, sizeof( szVvdFilename ) ); V_strncat( szVvdFilename, ".360.vvd", sizeof( szVvdFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szVvdFilename, tempBuffer.Base(), vvdBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .vvd buffer is replaced with swapped data vvdBuffer.Purge(); vvdBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szVvdFilename, vvdBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } // swap and write final .mdl fileSize = mdlBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; mdlBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); char szMdlFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szMdlFilename, sizeof( szMdlFilename ) ); V_strncat( szMdlFilename, ".360.mdl", sizeof( szMdlFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szMdlFilename, tempBuffer.Base(), mdlBuffer.PeekGet(), fileSize, NULL, CompressFunc ); if ( swappedSize > 0 ) { // .mdl buffer is replaced with swapped data mdlBuffer.Purge(); mdlBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szMdlFilename, mdlBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } return true; }
void VMPI_DistributeLightData() { if ( !g_bUseMPI ) return; if ( g_bMPIMaster ) { const char *pVirtualFilename = "--plightdata--"; CUtlBuffer lightFaceData; // write out the light data lightFaceData.EnsureCapacity( pdlightdata->Count() + (numfaces * (MAXLIGHTMAPS+sizeof(int))) ); Q_memcpy( lightFaceData.PeekPut(), pdlightdata->Base(), pdlightdata->Count() ); lightFaceData.SeekPut( CUtlBuffer::SEEK_HEAD, pdlightdata->Count() ); // write out the relevant face info into the stream for ( int i = 0; i < numfaces; i++ ) { for ( int j = 0; j < MAXLIGHTMAPS; j++ ) { lightFaceData.PutChar(g_pFaces[i].styles[j]); } lightFaceData.PutInt(g_pFaces[i].lightofs); } VMPI_FileSystem_CreateVirtualFile( pVirtualFilename, lightFaceData.Base(), lightFaceData.TellMaxPut() ); char cPacketID[2] = { VMPI_VRAD_PACKET_ID, VMPI_SUBPACKETID_PLIGHTDATA_RESULTS }; VMPI_Send2Chunks( cPacketID, sizeof( cPacketID ), pVirtualFilename, strlen( pVirtualFilename ) + 1, VMPI_PERSISTENT ); } else { VMPI_SetCurrentStage( "VMPI_DistributeLightData" ); // Wait until we've received the filename from the master. while ( g_LightResultsFilename.Count() == 0 ) { VMPI_DispatchNextMessage(); } // Open FileHandle_t fp = g_pFileSystem->Open( g_LightResultsFilename.Base(), "rb", VMPI_VIRTUAL_FILES_PATH_ID ); if ( !fp ) Error( "Can't open '%s' to read lighting info.", g_LightResultsFilename.Base() ); int size = g_pFileSystem->Size( fp ); int faceSize = (numfaces*(MAXLIGHTMAPS+sizeof(int))); if ( size > faceSize ) { int lightSize = size - faceSize; CUtlBuffer faceData; pdlightdata->EnsureCount( lightSize ); faceData.EnsureCapacity( faceSize ); g_pFileSystem->Read( pdlightdata->Base(), lightSize, fp ); g_pFileSystem->Read( faceData.Base(), faceSize, fp ); g_pFileSystem->Close( fp ); faceData.SeekPut( CUtlBuffer::SEEK_HEAD, faceSize ); // write out the face data for ( int i = 0; i < numfaces; i++ ) { for ( int j = 0; j < MAXLIGHTMAPS; j++ ) { g_pFaces[i].styles[j] = faceData.GetChar(); } g_pFaces[i].lightofs = faceData.GetInt(); } } } }
//----------------------------------------------------------------------------- // FIXME: assumes that we don't need to do gamma correction. //----------------------------------------------------------------------------- bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height, ImageFormat srcFormat, ImageFormat dstFormat ) { TGAHeader_t header; // Fix the dstFormat to match what actually is going to go into the file switch( dstFormat ) { case IMAGE_FORMAT_RGB888: dstFormat = IMAGE_FORMAT_BGR888; break; #if defined( _X360 ) case IMAGE_FORMAT_LINEAR_RGB888: dstFormat = IMAGE_FORMAT_LINEAR_BGR888; break; #endif case IMAGE_FORMAT_RGBA8888: dstFormat = IMAGE_FORMAT_BGRA8888; break; } header.id_length = 0; // comment length header.colormap_type = 0; // ??? switch( dstFormat ) { case IMAGE_FORMAT_BGR888: #if defined( _X360 ) case IMAGE_FORMAT_LINEAR_BGR888: #endif header.image_type = 2; // 24/32 bit uncompressed TGA header.pixel_size = 24; break; case IMAGE_FORMAT_BGRA8888: header.image_type = 2; // 24/32 bit uncompressed TGA header.pixel_size = 32; break; case IMAGE_FORMAT_I8: header.image_type = 1; // 8 bit uncompressed TGA header.pixel_size = 8; break; default: return false; break; } header.colormap_index = 0; header.colormap_length = 0; header.colormap_size = 0; header.x_origin = 0; header.y_origin = 0; header.width = ( unsigned short )width; header.height = ( unsigned short )height; header.attributes = 0x20; // Makes it so we don't have to vertically flip the image buffer.PutChar( header.id_length ); buffer.PutChar( header.colormap_type ); buffer.PutChar( header.image_type ); fputLittleShort( header.colormap_index, buffer ); fputLittleShort( header.colormap_length, buffer ); buffer.PutChar( header.colormap_size ); fputLittleShort( header.x_origin, buffer ); fputLittleShort( header.y_origin, buffer ); fputLittleShort( header.width, buffer ); fputLittleShort( header.height, buffer ); buffer.PutChar( header.pixel_size ); buffer.PutChar( header.attributes ); int nSizeInBytes = width * height * ImageLoader::SizeInBytes( dstFormat ); buffer.EnsureCapacity( buffer.TellPut() + nSizeInBytes ); unsigned char *pDst = (unsigned char*)buffer.PeekPut(); if ( !ImageLoader::ConvertImageFormat( pImageData, srcFormat, pDst, dstFormat, width, height ) ) return false; buffer.SeekPut( CUtlBuffer::SEEK_CURRENT, nSizeInBytes ); return true; }
//----------------------------------------------------------------------------- // Converts a buffer from a CRLF buffer to a CR buffer (and back) // Returns false if no conversion was necessary (and outBuf is left untouched) // If the conversion occurs, outBuf will be cleared. //----------------------------------------------------------------------------- bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf ) { if ( !IsText() || !outBuf.IsText() ) return false; if ( ContainsCRLF() == outBuf.ContainsCRLF() ) return false; int nInCount = TellMaxPut(); outBuf.Purge(); outBuf.EnsureCapacity( nInCount ); bool bFromCRLF = ContainsCRLF(); // Start reading from the beginning int nGet = TellGet(); int nPut = TellPut(); int nGetDelta = 0; int nPutDelta = 0; const char *pBase = (const char*)Base(); int nCurrGet = 0; while ( nCurrGet < nInCount ) { const char *pCurr = &pBase[nCurrGet]; if ( bFromCRLF ) { const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet ); if ( !pNext ) { outBuf.Put( pCurr, nInCount - nCurrGet ); break; } int nBytes = (size_t)pNext - (size_t)pCurr; outBuf.Put( pCurr, nBytes ); outBuf.PutChar( '\n' ); nCurrGet += nBytes + 2; if ( nGet >= nCurrGet - 1 ) { --nGetDelta; } if ( nPut >= nCurrGet - 1 ) { --nPutDelta; } } else { const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet ); if ( !pNext ) { outBuf.Put( pCurr, nInCount - nCurrGet ); break; } int nBytes = (size_t)pNext - (size_t)pCurr; outBuf.Put( pCurr, nBytes ); outBuf.PutChar( '\r' ); outBuf.PutChar( '\n' ); nCurrGet += nBytes + 1; if ( nGet >= nCurrGet ) { ++nGetDelta; } if ( nPut >= nCurrGet ) { ++nPutDelta; } } } Assert( nPut + nPutDelta <= outBuf.TellMaxPut() ); outBuf.SeekGet( SEEK_HEAD, nGet + nGetDelta ); outBuf.SeekPut( SEEK_HEAD, nPut + nPutDelta ); return true; }
int main( int argc, char **argv ) { SpewOutputFunc( VTF2TGAOutputFunc ); CommandLine()->CreateCmdLine( argc, argv ); MathLib_Init( 2.2f, 2.2f, 0.0f, 1.0f, false, false, false, false ); InitDefaultFileSystem(); const char *pVTFFileName = CommandLine()->ParmValue( "-i" ); const char *pTGAFileName = CommandLine()->ParmValue( "-o" ); bool bGenerateMipLevels = CommandLine()->CheckParm( "-mip" ) != NULL; if ( !pVTFFileName ) { Usage(); } if ( !pTGAFileName ) { pTGAFileName = pVTFFileName; } char pCurrentDirectory[MAX_PATH]; if ( _getcwd( pCurrentDirectory, sizeof(pCurrentDirectory) ) == NULL ) { fprintf( stderr, "Unable to get the current directory\n" ); return -1; } Q_StripTrailingSlash( pCurrentDirectory ); char pBuf[MAX_PATH]; if ( !Q_IsAbsolutePath( pTGAFileName ) ) { Q_snprintf( pBuf, sizeof(pBuf), "%s\\%s", pCurrentDirectory, pTGAFileName ); } else { Q_strncpy( pBuf, pTGAFileName, sizeof(pBuf) ); } Q_FixSlashes( pBuf ); char pOutFileNameBase[MAX_PATH]; Q_StripExtension( pBuf, pOutFileNameBase, MAX_PATH ); char pActualVTFFileName[MAX_PATH]; Q_strncpy( pActualVTFFileName, pVTFFileName, MAX_PATH ); if ( !Q_strstr( pActualVTFFileName, ".vtf" ) ) { Q_strcat( pActualVTFFileName, ".vtf", MAX_PATH ); } FILE *vtfFp = fopen( pActualVTFFileName, "rb" ); if( !vtfFp ) { Error( "Can't open %s\n", pActualVTFFileName ); exit( -1 ); } fseek( vtfFp, 0, SEEK_END ); int srcVTFLength = ftell( vtfFp ); fseek( vtfFp, 0, SEEK_SET ); CUtlBuffer buf; buf.EnsureCapacity( srcVTFLength ); int nBytesRead = fread( buf.Base(), 1, srcVTFLength, vtfFp ); fclose( vtfFp ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); IVTFTexture *pTex = CreateVTFTexture(); if (!pTex->Unserialize( buf )) { Error( "*** Error reading in .VTF file %s\n", pActualVTFFileName ); exit(-1); } Msg( "vtf width: %d\n", pTex->Width() ); Msg( "vtf height: %d\n", pTex->Height() ); Msg( "vtf numFrames: %d\n", pTex->FrameCount() ); Msg( "TEXTUREFLAGS_POINTSAMPLE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_POINTSAMPLE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_TRILINEAR=%s\n", ( pTex->Flags() & TEXTUREFLAGS_TRILINEAR ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPT=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPT ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPU=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPU ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_BORDER=%s\n", ( pTex->Flags() & TEXTUREFLAGS_BORDER ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ANISOTROPIC=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ANISOTROPIC ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_HINT_DXT5=%s\n", ( pTex->Flags() & TEXTUREFLAGS_HINT_DXT5 ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SRGB=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SRGB ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NORMAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NORMAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOMIP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOMIP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOLOD=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOLOD ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ALL_MIPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ALL_MIPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_PROCEDURAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_PROCEDURAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ONEBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_EIGHTBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ENVMAP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ENVMAP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_RENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_RENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_DEPTHRENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_DEPTHRENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NODEBUGOVERRIDE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NODEBUGOVERRIDE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SINGLECOPY=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SINGLECOPY ) ? "true" : "false" ); Vector vecReflectivity = pTex->Reflectivity(); Msg( "vtf reflectivity: %f %f %f\n", vecReflectivity[0], vecReflectivity[1], vecReflectivity[2] ); Msg( "transparency: " ); if( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) { Msg( "eightbitalpha\n" ); } else if( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) { Msg( "onebitalpha\n" ); } else { Msg( "noalpha\n" ); } ImageFormat srcFormat = pTex->Format(); Msg( "vtf format: %s\n", ImageLoader::GetName( srcFormat ) ); int iTGANameLen = Q_strlen( pOutFileNameBase ); int iFaceCount = pTex->FaceCount(); int nFrameCount = pTex->FrameCount(); bool bIsCubeMap = pTex->IsCubeMap(); int iLastMipLevel = bGenerateMipLevels ? pTex->MipCount() - 1 : 0; for( int iFrame = 0; iFrame < nFrameCount; ++iFrame ) { for ( int iMipLevel = 0; iMipLevel <= iLastMipLevel; ++iMipLevel ) { int iWidth, iHeight, iDepth; pTex->ComputeMipLevelDimensions( iMipLevel, &iWidth, &iHeight, &iDepth ); for (int iCubeFace = 0; iCubeFace < iFaceCount; ++iCubeFace) { for ( int z = 0; z < iDepth; ++z ) { // Construct output filename char *pTempNameBuf = (char *)stackalloc( iTGANameLen + 13 ); Q_strncpy( pTempNameBuf, pOutFileNameBase, iTGANameLen + 1 ); char *pExt = Q_strrchr( pTempNameBuf, '.' ); if ( pExt ) { pExt = 0; } if ( bIsCubeMap ) { Assert( pTex->Depth() == 1 ); // shouldn't this be 1 instead of 0? static const char *pCubeFaceName[7] = { "rt", "lf", "bk", "ft", "up", "dn", "sph" }; Q_strcat( pTempNameBuf, pCubeFaceName[iCubeFace], iTGANameLen + 13 ); } if ( nFrameCount > 1 ) { char pTemp[4]; Q_snprintf( pTemp, 4, "%03d", iFrame ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( iLastMipLevel != 0 ) { char pTemp[8]; Q_snprintf( pTemp, 8, "_mip%d", iMipLevel ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( pTex->Depth() > 1 ) { char pTemp[6]; Q_snprintf( pTemp, 6, "_z%03d", z ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { Q_strcat( pTempNameBuf, ".pfm", iTGANameLen + 13 ); } else { Q_strcat( pTempNameBuf, ".tga", iTGANameLen + 13 ); } unsigned char *pSrcImage = pTex->ImageData( iFrame, iCubeFace, iMipLevel, 0, 0, z ); ImageFormat dstFormat; if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { dstFormat = IMAGE_FORMAT_RGB323232F; } else { if( ImageLoader::IsTransparent( srcFormat ) || (srcFormat == IMAGE_FORMAT_ATI1N ) || (srcFormat == IMAGE_FORMAT_ATI2N )) { dstFormat = IMAGE_FORMAT_BGRA8888; } else { dstFormat = IMAGE_FORMAT_BGR888; } } // dstFormat = IMAGE_FORMAT_RGBA8888; // dstFormat = IMAGE_FORMAT_RGB888; // dstFormat = IMAGE_FORMAT_BGRA8888; // dstFormat = IMAGE_FORMAT_BGR888; // dstFormat = IMAGE_FORMAT_BGRA5551; // dstFormat = IMAGE_FORMAT_BGR565; // dstFormat = IMAGE_FORMAT_BGRA4444; // printf( "dstFormat: %s\n", ImageLoader::GetName( dstFormat ) ); unsigned char *pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, dstFormat, false )]; if( !ImageLoader::ConvertImageFormat( pSrcImage, srcFormat, pDstImage, dstFormat, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( srcFormat ), ImageLoader::GetName( dstFormat ) ); exit( -1 ); } if( dstFormat != IMAGE_FORMAT_RGB323232F ) { if( ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGBA8888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGBA8888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGBA8888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGBA8888 ) ); } dstFormat = IMAGE_FORMAT_RGBA8888; } else if( !ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGB888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGB888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGB888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGB888 ) ); } dstFormat = IMAGE_FORMAT_RGB888; } CUtlBuffer outBuffer; TGAWriter::WriteToBuffer( pDstImage, outBuffer, iWidth, iHeight, dstFormat, dstFormat ); if ( !g_pFullFileSystem->WriteFile( pTempNameBuf, NULL, outBuffer ) ) { fprintf( stderr, "unable to write %s\n", pTempNameBuf ); } } else { PFMWrite( ( float * )pDstImage, pTempNameBuf, iWidth, iHeight ); } } } } } // leak leak leak leak leak, leak leak, leak leak (Blue Danube) return 0; }
bool xZipAddFile( const char* zipname, bool bPrecacheEntireFile, bool bProcessPrecacheHeader, bool bProcessPrecacheHeaderOnly ) { // Clean up the filename: char buffer[MAX_PATH]; strcpy(buffer, zipname); // Fix slashes and convert it to lower case: char *filename; for( filename = buffer; *filename; filename++ ) { if( *filename == '/' ) *filename = '\\'; else { *filename = (char)tolower(*filename); } } // Skip leading white space: for( filename = buffer; isspace(*filename); filename++ ) ; // Obliterate trailing white space: for(;;) { int len = (int)strlen( filename ); if( len <= 0 ) { printf("!!!! BAD FILENAME: \"%s\"\n", filename ); return false; } if( isspace( filename[len-1] ) ) filename[len-1]='\0'; else break; } // Ensure we don't already have this file: unsigned CRC = xZipCRCFilename( filename ); for( unsigned i=0; i < Header.DirectoryEntries; i++ ) { if( pDirectoryEntries[i].FilenameCRC == CRC ) { printf("!!!! NOT ADDING DUPLICATE FILENAME: \"%s\"\n", filename ); return false; } } // Attempt to open the file: FILE* hFile = fopen( filename, "rb" ); if( !hFile ) { printf("!!!! FAILED TO OPEN FILE: \"%s\"\n", filename ); return false; } // Get the length of the file: fseek(hFile,0,SEEK_END); unsigned fileSize = ftell(hFile); fseek(hFile,0,SEEK_SET); CUtlBuffer fileBuff; fileBuff.EnsureCapacity( fileSize ); fread( fileBuff.Base(), fileSize, 1, hFile ); fclose( hFile ); fileBuff.SeekPut( CUtlBuffer::SEEK_HEAD, fileSize ); return xZipAddFile( zipname, fileBuff, bPrecacheEntireFile, bProcessPrecacheHeader, bProcessPrecacheHeaderOnly ); }
//----------------------------------------------------------------------------- // Write the lighitng to bsp pak lump //----------------------------------------------------------------------------- void CVradStaticPropMgr::SerializeLighting() { char filename[MAX_PATH]; CUtlBuffer utlBuf; // illuminate them all int count = m_StaticProps.Count(); if ( !count ) { // nothing to do return; } char mapName[MAX_PATH]; Q_FileBase( source, mapName, sizeof( mapName ) ); int size; for (int i = 0; i < count; ++i) { sprintf( filename, "sp_%d.vhv", i ); int totalVertexes = 0; for ( int j=0; j<m_StaticProps[i].m_MeshData.Count(); j++ ) { totalVertexes += m_StaticProps[i].m_MeshData[j].m_Verts.Count(); } // allocate a buffer with enough padding for alignment size = sizeof( HardwareVerts::FileHeader_t ) + m_StaticProps[i].m_MeshData.Count()*sizeof(HardwareVerts::MeshHeader_t) + totalVertexes*4 + 2*512; utlBuf.EnsureCapacity( size ); Q_memset( utlBuf.Base(), 0, size ); HardwareVerts::FileHeader_t *pVhvHdr = (HardwareVerts::FileHeader_t *)utlBuf.Base(); // align to start of vertex data unsigned char *pVertexData = (unsigned char *)(sizeof( HardwareVerts::FileHeader_t ) + m_StaticProps[i].m_MeshData.Count()*sizeof(HardwareVerts::MeshHeader_t)); pVertexData = (unsigned char*)pVhvHdr + ALIGN_TO_POW2( (unsigned int)pVertexData, 512 ); // construct header pVhvHdr->m_nVersion = VHV_VERSION; pVhvHdr->m_nChecksum = m_StaticPropDict[m_StaticProps[i].m_ModelIdx].m_pStudioHdr->checksum; pVhvHdr->m_nVertexFlags = VERTEX_COLOR; pVhvHdr->m_nVertexSize = 4; pVhvHdr->m_nVertexes = totalVertexes; pVhvHdr->m_nMeshes = m_StaticProps[i].m_MeshData.Count(); for (int n=0; n<pVhvHdr->m_nMeshes; n++) { // construct mesh dictionary HardwareVerts::MeshHeader_t *pMesh = pVhvHdr->pMesh( n ); pMesh->m_nLod = m_StaticProps[i].m_MeshData[n].m_nLod; pMesh->m_nVertexes = m_StaticProps[i].m_MeshData[n].m_Verts.Count(); pMesh->m_nOffset = (unsigned int)pVertexData - (unsigned int)pVhvHdr; // construct vertexes for (int k=0; k<pMesh->m_nVertexes; k++) { Vector &vector = m_StaticProps[i].m_MeshData[n].m_Verts[k]; ColorRGBExp32 rgbColor; VectorToColorRGBExp32( vector, rgbColor ); unsigned char dstColor[4]; ConvertRGBExp32ToRGBA8888( &rgbColor, dstColor ); // b,g,r,a order pVertexData[0] = dstColor[2]; pVertexData[1] = dstColor[1]; pVertexData[2] = dstColor[0]; pVertexData[3] = dstColor[3]; pVertexData += 4; } } // align to end of file pVertexData = (unsigned char *)((unsigned int)pVertexData - (unsigned int)pVhvHdr); pVertexData = (unsigned char*)pVhvHdr + ALIGN_TO_POW2( (unsigned int)pVertexData, 512 ); AddBufferToPack( filename, (void*)pVhvHdr, pVertexData - (unsigned char*)pVhvHdr, false ); } }