diff options
author | Shauren <shauren.trinity@gmail.com> | 2012-07-05 14:16:44 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2012-07-05 14:16:44 +0200 |
commit | 32ba32c4ebe56ba931c8638460c24cd57ae29a75 (patch) | |
tree | 2f757648b85ec8989a7dfc573b954b9b4d718650 /dep/StormLib/src/SFileAddFile.cpp | |
parent | c95905ddbb22e2b5b5362b790aa851ef10d4e27e (diff) | |
parent | ed6f3e2deff55f913f9646db5f540b7704088478 (diff) |
Merge branch '4.x' of github.com:TrinityCore/TrinityCore into 4.3.4
Diffstat (limited to 'dep/StormLib/src/SFileAddFile.cpp')
-rw-r--r-- | dep/StormLib/src/SFileAddFile.cpp | 139 |
1 files changed, 107 insertions, 32 deletions
diff --git a/dep/StormLib/src/SFileAddFile.cpp b/dep/StormLib/src/SFileAddFile.cpp index e908d644990..dda47370bd1 100644 --- a/dep/StormLib/src/SFileAddFile.cpp +++ b/dep/StormLib/src/SFileAddFile.cpp @@ -13,6 +13,33 @@ #include "StormCommon.h" //----------------------------------------------------------------------------- +// Local structures + +#define FILE_SIGNATURE_RIFF 0x46464952 +#define FILE_SIGNATURE_WAVE 0x45564157 +#define FILE_SIGNATURE_FMT 0x20746D66 +#define AUDIO_FORMAT_PCM 1 + +typedef struct _WAVE_FILE_HEADER +{ + DWORD dwChunkId; // 0x52494646 ("RIFF") + DWORD dwChunkSize; // Size of that chunk, in bytes + DWORD dwFormat; // Must be 0x57415645 ("WAVE") + + // Format sub-chunk + DWORD dwSubChunk1Id; // 0x666d7420 ("fmt ") + DWORD dwSubChunk1Size; // 0x16 for PCM + USHORT wAudioFormat; // 1 = PCM. Other value means some sort of compression + USHORT wChannels; // Number of channels + DWORD dwSampleRate; // 8000, 44100, etc. + DWORD dwBytesRate; // SampleRate * NumChannels * BitsPerSample/8 + USHORT wBlockAlign; // NumChannels * BitsPerSample/8 + USHORT wBitsPerSample; // 8 bits = 8, 16 bits = 16, etc. + + // Followed by "data" sub-chunk (we don't care) +} WAVE_FILE_HEADER, *PWAVE_FILE_HEADER; + +//----------------------------------------------------------------------------- // Local variables // Data compression for SFileAddFile @@ -27,6 +54,29 @@ static void * pvUserData = NULL; #define LOSSY_COMPRESSION_MASK (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN) +static int IsWaveFile( + LPBYTE pbFileData, + DWORD cbFileData, + LPDWORD pdwChannels) +{ + PWAVE_FILE_HEADER pWaveHdr = (PWAVE_FILE_HEADER)pbFileData; + + if(cbFileData > sizeof(WAVE_FILE_HEADER)) + { + if(pWaveHdr->dwChunkId == FILE_SIGNATURE_RIFF && pWaveHdr->dwFormat == FILE_SIGNATURE_WAVE) + { + if(pWaveHdr->dwSubChunk1Id == FILE_SIGNATURE_FMT && pWaveHdr->wAudioFormat == AUDIO_FORMAT_PCM) + { + *pdwChannels = pWaveHdr->wChannels; + return true; + } + } + } + + return false; +} + + static int WriteDataToMpqFile( TMPQArchive * ha, TMPQFile * hf, @@ -86,16 +136,6 @@ static int WriteDataToMpqFile( // Set the position in the file ByteOffset = hf->RawFilePos + pFileEntry->dwCmpSize; - // If the file is compressed, allocate buffer for the compressed data. - // Note that we allocate buffer that is a bit longer than sector size, - // for case if the compression method performs a buffer overrun - if((pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) && pbCompressed == NULL) - { - pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100); - if(pbCompressed == NULL) - nError = ERROR_NOT_ENOUGH_MEMORY; - } - // Update CRC32 and MD5 of the file md5_process((hash_state *)hf->hctx, hf->pbFileSector, dwBytesInSector); hf->dwCrc32 = crc32(hf->dwCrc32, hf->pbFileSector, dwBytesInSector); @@ -106,7 +146,18 @@ static int WriteDataToMpqFile( int nOutBuffer = (int)dwBytesInSector; int nInBuffer = (int)dwBytesInSector; - assert(pbCompressed != NULL); + // If the file is compressed, allocate buffer for the compressed data. + // Note that we allocate buffer that is a bit longer than sector size, + // for case if the compression method performs a buffer overrun + if(pbCompressed == NULL) + { + pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100); + if(pbCompressed == NULL) + { + nError = ERROR_NOT_ENOUGH_MEMORY; + break; + } + } // // Note that both SCompImplode and SCompCompress give original buffer, @@ -319,11 +370,17 @@ int SFileAddFile_Init( // flags get to this point // - // Adjust file flags for too-small files - if(dwFileSize < 0x04) - dwFlags &= ~(MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY); - if(dwFileSize < 0x20) - dwFlags &= ~(MPQ_FILE_COMPRESSED | MPQ_FILE_SECTOR_CRC); + // Sestor CRC is not allowed with single unit files + if(dwFlags & MPQ_FILE_SINGLE_UNIT) + dwFlags &= ~MPQ_FILE_SECTOR_CRC; + + // Sector CRC is not allowed if the file is not compressed + if(!(dwFlags & MPQ_FILE_COMPRESSED)) + dwFlags &= ~MPQ_FILE_SECTOR_CRC; + + // Fix Key is not allowed if the file is not enrypted + if(!(dwFlags & MPQ_FILE_ENCRYPTED)) + dwFlags &= ~MPQ_FILE_FIX_KEY; // If the MPQ is of version 3.0 or higher, we ignore file locale. // This is because HET and BET tables have no known support for it @@ -371,12 +428,9 @@ int SFileAddFile_Init( } else { - // If the file is marked as deleted, it's OK - if(!(pFileEntry->dwFlags & MPQ_FILE_DELETE_MARKER)) - { - if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0) - nError = ERROR_ALREADY_EXISTS; - } + // If the file exists and "replace existing" is not set, fail it + if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0) + nError = ERROR_ALREADY_EXISTS; // If the file entry already contains a file // and it is a pseudo-name, replace it @@ -459,7 +513,7 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d } // Allocate patch info, if the data is patch - if(hf->pPatchInfo == NULL && IsPatchData(pvData, dwSize, &hf->dwPatchedFileSize)) + if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize)) { // Set the MPQ_FILE_PATCH_FILE flag hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE; @@ -782,6 +836,9 @@ bool WINAPI SFileAddFileEx( DWORD dwBytesRemaining = 0; DWORD dwBytesToRead; DWORD dwSectorSize = 0x1000; + DWORD dwChannels = 0; + bool bIsAdpcmCompression = false; + bool bIsFirstSector = true; int nError = ERROR_SUCCESS; // Check parameters @@ -791,7 +848,7 @@ bool WINAPI SFileAddFileEx( // Open added file if(nError == ERROR_SUCCESS) { - pStream = FileStream_OpenFile(szFileName, false); + pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pStream == NULL) nError = GetLastError(); } @@ -799,7 +856,7 @@ bool WINAPI SFileAddFileEx( // Get the file size and file time if(nError == ERROR_SUCCESS) { - FileStream_GetLastWriteTime(pStream, &FileTime); + FileStream_GetTime(pStream, &FileTime); FileStream_GetSize(pStream, FileSize); // Files bigger than 4GB cannot be added to MPQ @@ -821,16 +878,19 @@ bool WINAPI SFileAddFileEx( { // When the compression for next blocks is set to default, // we will copy the compression for the first sector - if(dwCompressionNext == 0xFFFFFFFF) + if(dwCompressionNext == MPQ_COMPRESSION_NEXT_SAME) dwCompressionNext = dwCompression; - // If the caller wants ADPCM compression, we make sure that the first sector is not - // compressed with lossy compression - if(dwCompressionNext & (MPQ_COMPRESSION_WAVE_MONO | MPQ_COMPRESSION_WAVE_STEREO)) + // If the caller wants ADPCM compression, we make sure + // that the first sector is not compressed with lossy compression + if(dwCompressionNext & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO)) { // The first compression must not be WAVE - if(dwCompression & (MPQ_COMPRESSION_WAVE_MONO | MPQ_COMPRESSION_WAVE_STEREO)) + if(dwCompression & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO)) dwCompression = MPQ_COMPRESSION_PKWARE; + + dwCompressionNext &= ~(MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO); + bIsAdpcmCompression = true; } // Initiate adding file to the MPQ @@ -853,6 +913,21 @@ bool WINAPI SFileAddFileEx( break; } + // If the file being added is a WAVE file, we check number of channels + if(bIsFirstSector && bIsAdpcmCompression) + { + // The file must really be a wave file, otherwise it's data corruption + if(!IsWaveFile(pbFileData, dwBytesToRead, &dwChannels)) + { + nError = ERROR_BAD_FORMAT; + break; + } + + // Setup the compression according to number of channels + dwCompressionNext |= (dwChannels == 1) ? MPQ_COMPRESSION_ADPCM_MONO : MPQ_COMPRESSION_ADPCM_STEREO; + bIsFirstSector = false; + } + // Add the file sectors to the MPQ if(!SFileWriteFile(hMpqFile, pbFileData, dwBytesToRead, dwCompression)) { @@ -920,12 +995,12 @@ bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szA case MPQ_WAVE_QUALITY_MEDIUM: // WaveCompressionLevel = 4; - dwCompression = MPQ_COMPRESSION_WAVE_STEREO | MPQ_COMPRESSION_HUFFMANN; + dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN; break; case MPQ_WAVE_QUALITY_LOW: // WaveCompressionLevel = 2; - dwCompression = MPQ_COMPRESSION_WAVE_STEREO | MPQ_COMPRESSION_HUFFMANN; + dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN; break; } |