diff options
-rw-r--r-- | src/SBaseCommon.cpp | 9 | ||||
-rw-r--r-- | src/SBaseFileTable.cpp | 122 | ||||
-rw-r--r-- | src/SFileAddFile.cpp | 22 | ||||
-rw-r--r-- | src/SFileAttributes.cpp | 2 | ||||
-rw-r--r-- | src/SFileCompactArchive.cpp | 6 | ||||
-rw-r--r-- | src/SFileCreateArchive.cpp | 4 | ||||
-rw-r--r-- | src/SFileFindFile.cpp | 2 | ||||
-rw-r--r-- | src/SFileListFile.cpp | 2 | ||||
-rw-r--r-- | src/SFileOpenArchive.cpp | 4 | ||||
-rw-r--r-- | src/StormCommon.h | 4 | ||||
-rw-r--r-- | src/StormLib.h | 12 | ||||
-rw-r--r-- | test/Test.cpp | 44 |
12 files changed, 141 insertions, 92 deletions
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index c0bfffb..2e9366f 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -843,7 +843,7 @@ TMPQHash * AllocateHashEntry( // Finds a free space in the MPQ where to store next data // The free space begins beyond the file that is stored at the fuhrtest // position in the MPQ. -void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos) +ULONGLONG FindFreeMpqSpace(TMPQArchive * ha) { TMPQHeader * pHeader = ha->pHeader; TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; @@ -854,8 +854,8 @@ void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos) // Parse the entire block table for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) { - // Only take existing files - if(pFileEntry->dwFlags & MPQ_FILE_EXISTS) + // Only take existing files with nonzero size + if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && (pFileEntry->dwCmpSize != 0)) { // If the end of the file is bigger than current MPQ table pos, update it if((pFileEntry->ByteOffset + pFileEntry->dwCmpSize) > FreeSpacePos) @@ -874,8 +874,7 @@ void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos) } // Give the free space position to the caller - if(pFreeSpacePos != NULL) - *pFreeSpacePos = FreeSpacePos; + return FreeSpacePos; } //----------------------------------------------------------------------------- diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 011badf..51d01e4 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -25,7 +25,7 @@ typedef struct _HET_TABLE_HEADER { DWORD dwTableSize; // Size of the entire HET table, including HET_TABLE_HEADER (in bytes) - DWORD dwMaxFileCount; // Maximum number of files in the MPQ + DWORD dwFileCount; // Number of occupied entries in the hash table DWORD dwHashTableSize; // Size of the hash table (in bytes) DWORD dwHashEntrySize; // Effective size of the hash entry (in bits) DWORD dwIndexSizeTotal; // Total size of file index (in bits) @@ -722,10 +722,10 @@ static void CreateHetHeader( PHET_TABLE_HEADER pHetHeader) { // Fill the BET header - pHetHeader->dwMaxFileCount = pHetTable->dwMaxFileCount; + pHetHeader->dwFileCount = pHetTable->dwFileCount; pHetHeader->dwHashTableSize = pHetTable->dwHashTableSize; pHetHeader->dwHashEntrySize = pHetTable->dwHashBitSize; - pHetHeader->dwIndexSizeTotal = GetNecessaryBitCount(pHetTable->dwMaxFileCount); + pHetHeader->dwIndexSizeTotal = GetNecessaryBitCount(pHetTable->dwHashTableSize); pHetHeader->dwIndexSizeExtra = 0; pHetHeader->dwIndexSize = pHetHeader->dwIndexSizeTotal; pHetHeader->dwIndexTableSize = ((pHetHeader->dwIndexSizeTotal * pHetTable->dwHashTableSize) + 7) / 8; @@ -736,7 +736,7 @@ static void CreateHetHeader( pHetHeader->dwIndexTableSize; } -TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bCreateEmpty) +TMPQHetTable * CreateHetTable(DWORD dwHashTableSize, DWORD dwFileCount, DWORD dwHashBitSize, bool bCreateEmpty) { TMPQHetTable * pHetTable; @@ -746,12 +746,22 @@ TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bC pHetTable->dwIndexSizeTotal = 0; pHetTable->dwIndexSizeExtra = 0; pHetTable->dwIndexSize = pHetTable->dwIndexSizeTotal; - pHetTable->dwMaxFileCount = dwMaxFileCount; - pHetTable->dwHashTableSize = (dwMaxFileCount * 4 / 3); pHetTable->dwHashBitSize = dwHashBitSize; - // Size of one index is calculated from max file count - pHetTable->dwIndexSizeTotal = GetNecessaryBitCount(dwMaxFileCount); + // If the hash table size is not entered, calculate an optimal + // hash table size as 4/3 of the current file count. + if(dwHashTableSize == 0) + { + dwHashTableSize = (dwFileCount * 4 / 3); + assert(dwFileCount != 0); + } + + // Store the hash table size and file count + pHetTable->dwHashTableSize = dwHashTableSize; + pHetTable->dwFileCount = dwFileCount; + + // Size of one index is calculated from hash table size + pHetTable->dwIndexSizeTotal = GetNecessaryBitCount(dwHashTableSize); pHetTable->dwIndexSizeExtra = 0; pHetTable->dwIndexSize = pHetTable->dwIndexSizeTotal; @@ -805,8 +815,12 @@ static TMPQHetTable * TranslateHetTable(TMPQExtTable * pExtTable) // Verify the size of the table in the header if(HetHeader.dwTableSize == pExtTable->dwDataSize) { + // The size of index table (in entries) is expected + // to be the same like the hash table size (in bytes) + assert(((HetHeader.dwIndexTableSize * 8) / HetHeader.dwIndexSize) == HetHeader.dwHashTableSize); + // Create translated table - pHetTable = CreateHetTable(HetHeader.dwMaxFileCount, HetHeader.dwHashEntrySize, false); + pHetTable = CreateHetTable(HetHeader.dwHashTableSize, HetHeader.dwFileCount, HetHeader.dwHashEntrySize, false); if(pHetTable != NULL) { // Copy the hash table size, index size and extra bits from the HET header @@ -909,7 +923,7 @@ DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName) // Go through HET table until we find a terminator while(pHetTable->pHetHashes[Index] != HET_ENTRY_FREE) { - // Did we find match ? + // Did we find a match ? if(pHetTable->pHetHashes[Index] == HetHash) { DWORD dwFileIndex = 0; @@ -919,7 +933,6 @@ DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName) pHetTable->dwIndexSize, &dwFileIndex, 4); - // // TODO: This condition only happens when we are opening a MPQ // where some files were deleted by StormLib. Perhaps @@ -952,6 +965,7 @@ DWORD AllocateHetEntry( ULONGLONG AndMask64; ULONGLONG OrMask64; ULONGLONG BetHash; + DWORD FileCountIncrement = 0; DWORD FreeHetIndex = HASH_ENTRY_FREE; DWORD dwFileIndex; DWORD StartIndex; @@ -978,29 +992,35 @@ DWORD AllocateHetEntry( // Go through HET table until we find a terminator for(;;) { - // Check for entries that might have been deleted - if(pHetTable->pHetHashes[Index] == HET_ENTRY_DELETED) + // Did we find a match ? + if(pHetTable->pHetHashes[Index] == HetHash) { - DWORD dwInvalidBetIndex = (1 << pHetTable->dwIndexSizeTotal) - 1; - DWORD dwBetIndex = 0; + DWORD dwFileIndex = 0; - // Verify the BET index. If it's really free, we can use it - dwFileIndex = (DWORD)(pFileEntry - ha->pFileTable); + // Get the index of the BetHash GetBits(pHetTable->pBetIndexes, pHetTable->dwIndexSizeTotal * Index, pHetTable->dwIndexSize, - &dwBetIndex, + &dwFileIndex, 4); - - if(dwBetIndex == dwInvalidBetIndex) + // + // TODO: This condition only happens when we are opening a MPQ + // where some files were deleted by StormLib. Perhaps + // we should not allow shrinking of the file table in MPQs v 4.0? + // assert(dwFileIndex <= ha->dwFileTableSize); + // + + // Verify the BetHash against the entry in the table of BET hashes + if(dwFileIndex <= ha->dwFileTableSize && ha->pFileTable[dwFileIndex].BetHash == BetHash) { FreeHetIndex = Index; break; } } - // Is that entry free ? - if(pHetTable->pHetHashes[Index] == HET_ENTRY_FREE) + // Check for entries that might have been deleted + if(pHetTable->pHetHashes[Index] == HET_ENTRY_DELETED || pHetTable->pHetHashes[Index] == HET_ENTRY_FREE) { + FileCountIncrement++; FreeHetIndex = Index; break; } @@ -1015,10 +1035,12 @@ DWORD AllocateHetEntry( // Fill the HET table entry dwFileIndex = (DWORD)(pFileEntry - ha->pFileTable); pHetTable->pHetHashes[FreeHetIndex] = HetHash; + pHetTable->dwFileCount += FileCountIncrement; SetBits(pHetTable->pBetIndexes, pHetTable->dwIndexSizeTotal * FreeHetIndex, pHetTable->dwIndexSize, &dwFileIndex, 4); + // Fill the file entry pFileEntry->BetHash = BetHash; pFileEntry->dwHetIndex = FreeHetIndex; @@ -1792,22 +1814,28 @@ void InvalidateInternalFiles(TMPQArchive * ha) { TFileEntry * pFileEntry; + // + // Note: We set the size of both (listfile) and (attributes) to zero. + // This causes allocating space for newly added files straight over + // (listfile)/(attributes), if these were the last ones in the MPQ + // + // Invalidate the (listfile), if not done yet - if(!(ha->dwFlags & MPQ_FLAG_INV_LISTFILE)) + if(!(ha->dwFlags & MPQ_FLAG_LISTFILE_INVALID)) { pFileEntry = GetFileEntryExact(ha, LISTFILE_NAME, LANG_NEUTRAL); if(pFileEntry != NULL) - FreeFileEntry(ha, pFileEntry); - ha->dwFlags |= MPQ_FLAG_INV_LISTFILE; + pFileEntry->dwFileSize = pFileEntry->dwCmpSize = 0; + ha->dwFlags |= MPQ_FLAG_LISTFILE_INVALID; } // Invalidate the (attributes), if not done yet - if(!(ha->dwFlags & MPQ_FLAG_INV_ATTRIBUTES)) + if(!(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_INVALID)) { pFileEntry = GetFileEntryExact(ha, ATTRIBUTES_NAME, LANG_NEUTRAL); if(pFileEntry != NULL) - FreeFileEntry(ha, pFileEntry); - ha->dwFlags |= MPQ_FLAG_INV_ATTRIBUTES; + pFileEntry->dwFileSize = pFileEntry->dwCmpSize = 0; + ha->dwFlags |= MPQ_FLAG_ATTRIBUTES_INVALID; } // Remember that the MPQ has been changed and it will be necessary @@ -2085,11 +2113,11 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, ULONGLONG FileSize) return pBlockTable; } -int LoadHetTable(TMPQArchive * ha) +TMPQHetTable * LoadHetTable(TMPQArchive * ha) { + TMPQHetTable * pHetTable = NULL; TMPQExtTable * pExtTable; TMPQHeader * pHeader = ha->pHeader; - int nError = ERROR_SUCCESS; // If the HET table position is not NULL, we expect // both HET and BET tables to be present. @@ -2099,22 +2127,13 @@ int LoadHetTable(TMPQArchive * ha) pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE); if(pExtTable != NULL) { - // If succeeded, we have to limit the maximum file count - // to the values saved in the HET table // If loading HET table fails, we ignore the result. - ha->pHetTable = TranslateHetTable(pExtTable); - if(ha->pHetTable != NULL) - ha->dwMaxFileCount = ha->pHetTable->dwMaxFileCount; - + pHetTable = TranslateHetTable(pExtTable); STORM_FREE(pExtTable); } - - // If the HET hable failed to load, it's corrupt. - if(ha->pHetTable == NULL) - nError = ERROR_FILE_CORRUPT; } - return nError; + return pHetTable; } TMPQBetTable * LoadBetTable(TMPQArchive * ha) @@ -2149,21 +2168,18 @@ int LoadAnyHashTable(TMPQArchive * ha) if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0) return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT); - // Try to load HET and/or classic hash table - LoadHetTable(ha); - - // Load the HASH table + // Try to load HET table (the new hash table) and the classic HASH table + ha->pHetTable = LoadHetTable(ha); ha->pHashTable = LoadHashTable(ha); - - // Set the maximum file count to the size of the hash table - // In case there is HET table, we have to keep the file limit - if(ha->pHetTable == NULL) - ha->dwMaxFileCount = pHeader->dwHashTableSize; - - // Did at least one succeed? if(ha->pHetTable == NULL && ha->pHashTable == NULL) return ERROR_FILE_CORRUPT; + // Set the maximum file count + if(ha->pHetTable != NULL && ha->pHashTable != NULL) + ha->dwMaxFileCount = STORMLIB_MIN(ha->pHetTable->dwHashTableSize, pHeader->dwHashTableSize); + else + ha->dwMaxFileCount = (ha->pHetTable != NULL) ? ha->pHetTable->dwHashTableSize : pHeader->dwHashTableSize; + // In theory, a MPQ could have bigger block table than hash table if(ha->pHeader->dwBlockTableSize > ha->dwMaxFileCount) { @@ -2445,7 +2461,7 @@ int SaveMPQTables(TMPQArchive * ha) assert(ha->dwFlags & MPQ_FLAG_CHANGED); // Find the space where the MPQ tables will be saved - FindFreeMpqSpace(ha, &TablePos); + TablePos = FindFreeMpqSpace(ha); // If the MPQ has HET table, we prepare a ready-to-save version if(nError == ERROR_SUCCESS && ha->pHetTable != NULL) diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 59a245a..775a969 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -386,7 +386,7 @@ int SFileAddFile_Init( if(nError == ERROR_SUCCESS) { // Find the position where the file will be stored - FindFreeMpqSpace(ha, &hf->MpqFilePos); + hf->MpqFilePos = FindFreeMpqSpace(ha); hf->RawFilePos = ha->MpqPos + hf->MpqFilePos; hf->bIsWriteHandle = true; @@ -418,15 +418,19 @@ int SFileAddFile_Init( } else { - // 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 - if(nError == ERROR_SUCCESS) + // Only if the file really exists + if(pFileEntry->dwFlags & MPQ_FILE_EXISTS) { - AllocateFileName(pFileEntry, szFileName); + // 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 + if(nError == ERROR_SUCCESS) + { + AllocateFileName(pFileEntry, szFileName); + } } } } diff --git a/src/SFileAttributes.cpp b/src/SFileAttributes.cpp index 865debc..995e5b1 100644 --- a/src/SFileAttributes.cpp +++ b/src/SFileAttributes.cpp @@ -363,7 +363,7 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) } if(nError == ERROR_SUCCESS) - ha->dwFlags &= ~MPQ_FLAG_INV_ATTRIBUTES; + ha->dwFlags &= ~MPQ_FLAG_ATTRIBUTES_INVALID; return nError; } diff --git a/src/SFileCompactArchive.cpp b/src/SFileCompactArchive.cpp index cc2df09..a726d43 100644 --- a/src/SFileCompactArchive.cpp +++ b/src/SFileCompactArchive.cpp @@ -625,12 +625,12 @@ bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount) if(ha->dwFlags & MPQ_FLAG_READ_ONLY) nError = ERROR_ACCESS_DENIED; - // The new limit must not be lower than the index of the last file entry in the table + // The new limit must be greater than the current file table size if(nError == ERROR_SUCCESS && ha->dwFileTableSize > dwMaxFileCount) nError = ERROR_DISK_FULL; // ALL file names must be known in order to be able - // to rebuild hash table size + // to rebuild hash table if(nError == ERROR_SUCCESS) { nError = CheckIfAllFilesKnown(ha, NULL, NULL); @@ -659,7 +659,7 @@ bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount) pOldHetTable = ha->pHetTable; // Create new one - ha->pHetTable = CreateHetTable(dwMaxFileCount, 0x40, true); + ha->pHetTable = CreateHetTable(0, dwMaxFileCount, 0x40, true); if(ha->pHetTable == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; } diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp index 39332a6..78ddd71 100644 --- a/src/SFileCreateArchive.cpp +++ b/src/SFileCreateArchive.cpp @@ -211,13 +211,13 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea nError = WriteNakedMPQHeader(ha); // Remember that the (listfile) and (attributes) need to be saved - ha->dwFlags |= MPQ_FLAG_CHANGED | MPQ_FLAG_INV_LISTFILE | MPQ_FLAG_INV_ATTRIBUTES; + ha->dwFlags |= MPQ_FLAG_CHANGED | MPQ_FLAG_LISTFILE_INVALID | MPQ_FLAG_ATTRIBUTES_INVALID; } // Create initial HET table, if the caller required an MPQ format 3.0 or newer if(nError == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3) { - ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true); + ha->pHetTable = CreateHetTable(0, ha->dwFileTableSize, 0x40, true); if(ha->pHetTable == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; } diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index 17c9e24..af7e6bc 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -140,7 +140,7 @@ static DWORD GetSearchTableItems(TMPQArchive * ha) while(ha != NULL) { // Append the number of files - dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwMaxFileCount + dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwFileCount : ha->pHeader->dwBlockTableSize; // Move to the patched archive ha = ha->haPatch; diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp index 224a288..2044125 100644 --- a/src/SFileListFile.cpp +++ b/src/SFileListFile.cpp @@ -398,7 +398,7 @@ int SListFileSaveToMpq(TMPQArchive * ha) // Free buffers if(nError == ERROR_SUCCESS) - ha->dwFlags &= ~MPQ_FLAG_INV_LISTFILE; + ha->dwFlags &= ~MPQ_FLAG_LISTFILE_INVALID; if(SortTable != NULL) STORM_FREE(SortTable); return nError; diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index a058136..bf8d19e 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -443,7 +443,7 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq) } // If the (listfile) has been invalidated, save it - if(ha->dwFlags & MPQ_FLAG_INV_LISTFILE) + if(ha->dwFlags & MPQ_FLAG_LISTFILE_INVALID) { nError = SListFileSaveToMpq(ha); if(nError != ERROR_SUCCESS) @@ -451,7 +451,7 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq) } // If the (attributes) has been invalidated, save it - if(ha->dwFlags & MPQ_FLAG_INV_ATTRIBUTES) + if(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_INVALID) { nError = SAttrFileSaveToMpq(ha); if(nError != ERROR_SUCCESS) diff --git a/src/StormCommon.h b/src/StormCommon.h index 766b692..dcc9c7f 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -170,7 +170,7 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry); DWORD AllocateHetEntry(TMPQArchive * ha, TFileEntry * pFileEntry); -void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos); +ULONGLONG FindFreeMpqSpace(TMPQArchive * ha); // Functions that loads and verifies MPQ data bitmap int LoadMpqDataBitmap(TMPQArchive * ha, ULONGLONG FileSize, bool * pbFileIsComplete); @@ -181,7 +181,7 @@ int LoadAnyHashTable(TMPQArchive * ha); int BuildFileTable(TMPQArchive * ha, ULONGLONG FileSize); int SaveMPQTables(TMPQArchive * ha); -TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bCreateEmpty); +TMPQHetTable * CreateHetTable(DWORD dwHashTableSize, DWORD dwFileCount, DWORD dwHashBitSize, bool bCreateEmpty); void FreeHetTable(TMPQHetTable * pHetTable); TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount); diff --git a/src/StormLib.h b/src/StormLib.h index 8488e3e..3f91478 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -131,14 +131,14 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x0816 // Current version of StormLib (8.21) -#define STORMLIB_VERSION_STRING "8.22" // String version of StormLib version +#define STORMLIB_VERSION 0x0817 // Current version of StormLib (8.23) +#define STORMLIB_VERSION_STRING "8.23" // String version of StormLib version #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') #define ID_MPK 0x1A4B504D // MPK archive header ID ('MPK\x1A') -#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file. +#define ERROR_AVI_FILE 10000 // Not a MPQ file, but an AVI file. #define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by SFileReadFile when can't find file key #define ERROR_CHECKSUM_ERROR 10002 // Returned by SFileReadFile when sector CRC doesn't match #define ERROR_INTERNAL_FILE 10003 // The given operation is not allowed on internal file @@ -176,8 +176,8 @@ extern "C" { #define MPQ_FLAG_PROTECTED 0x00000004 // Set on protected MPQs (like W3M maps) #define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000008 // Checking sector CRC when reading files #define MPQ_FLAG_NEED_FIX_SIZE 0x00000010 // Used during opening the archive -#define MPQ_FLAG_INV_LISTFILE 0x00000020 // If set, it means that the (listfile) has been invalidated -#define MPQ_FLAG_INV_ATTRIBUTES 0x00000040 // If set, it means that the (attributes) has been invalidated +#define MPQ_FLAG_LISTFILE_INVALID 0x00000020 // If set, it means that the (listfile) has been invalidated +#define MPQ_FLAG_ATTRIBUTES_INVALID 0x00000040 // If set, it means that the (attributes) has been invalidated // Values for TMPQArchive::dwSubType #define MPQ_SUBTYPE_MPQ 0x00000000 // The file is a MPQ file (Blizzard games) @@ -694,7 +694,7 @@ typedef struct _TMPQHetTable DWORD dwIndexSizeTotal; // Total size of one entry in pBetIndexes (in bits) DWORD dwIndexSizeExtra; // Extra bits in the entry in pBetIndexes DWORD dwIndexSize; // Effective size of one entry in pBetIndexes (in bits) - DWORD dwMaxFileCount; // Maximum number of files in the MPQ + DWORD dwFileCount; // Number of occupied entries in the HET table DWORD dwHashTableSize; // Number of entries in pBetHashes DWORD dwHashBitSize; // Effective number of bits in the hash } TMPQHetTable; diff --git a/test/Test.cpp b/test/Test.cpp index 3d8b785..c21a708 100644 --- a/test/Test.cpp +++ b/test/Test.cpp @@ -1229,23 +1229,53 @@ static int TestAddFilesToArchive(const TCHAR * szMpqName) LPCSTR szFileData = "0123456789"; char szAddedFile[128]; DWORD dwFileSize = 10; + int nIndex = 0; - CopyFile(_T("e:\\Ladik\\Incoming\\Tya's Zerg Defense.SC2Map"), _T("e:\\Multimedia\\MPQs\\Tya's Zerg Defense.SC2Map"), FALSE); +#ifdef _MSC_VER + CopyFile(MAKE_PATH("2013 - Starcraft II\\!maps\\Tya's Zerg Defense.SC2Map"), MAKE_PATH("Tya's Zerg Defense.SC2Map"), FALSE); +#endif + + if(SFileOpenArchive(szMpqName, 0, 0, &hMpq)) + { + SFileRemoveFile(hMpq, "BankList.xml", 0); + + sprintf(szAddedFile, "BankList.xml", nIndex++); + if(SFileCreateFile(hMpq, szAddedFile, 0, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) + { + SFileWriteFile(hFile, szFileData, dwFileSize, MPQ_COMPRESSION_ZLIB); + SFileFinishFile(hFile); + } +/* + sprintf(szAddedFile, "AddedFile%04u.txt", nIndex++); + if(SFileCreateFile(hMpq, szAddedFile, 0, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) + { + SFileWriteFile(hFile, szFileData, dwFileSize, MPQ_COMPRESSION_ZLIB); + SFileFinishFile(hFile); + } + + sprintf(szAddedFile, "AddedFile%04u.txt", nIndex++); + if(SFileCreateFile(hMpq, szAddedFile, 0, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) + { + SFileWriteFile(hFile, szFileData, dwFileSize, MPQ_COMPRESSION_ZLIB); + SFileFinishFile(hFile); + } +*/ + + SFileCloseArchive(hMpq); + } +/* for(int i = 0; i < 3; i++) { if(SFileOpenArchive(szMpqName, 0, 0, &hMpq)) { sprintf(szAddedFile, "AddedFile%04u.txt", i); + SFileRemoveFile(hFile, szAddedFile, 0); - if(SFileCreateFile(hMpq, szAddedFile, 0, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) - { - SFileWriteFile(hMpq, szFileData, dwFileSize, MPQ_COMPRESSION_ZLIB); - SFileFinishFile(hFile); - } + SFileCloseArchive(hMpq); } } - +*/ return ERROR_SUCCESS; } |