aboutsummaryrefslogtreecommitdiff
path: root/src/SFileCreateArchive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFileCreateArchive.cpp')
-rw-r--r--src/SFileCreateArchive.cpp48
1 files changed, 27 insertions, 21 deletions
diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp
index 78ddd71..2b51efa 100644
--- a/src/SFileCreateArchive.cpp
+++ b/src/SFileCreateArchive.cpp
@@ -57,6 +57,7 @@ static int WriteNakedMPQHeader(TMPQArchive * ha)
// Write it to the file
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_1);
+ BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_2);
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_3);
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_4);
if(!FileStream_Write(ha->pStream, &ha->MpqPos, &Header, dwBytesToWrite))
@@ -68,19 +69,27 @@ static int WriteNakedMPQHeader(TMPQArchive * ha)
//-----------------------------------------------------------------------------
// Creates a new MPQ archive.
-bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
+bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwCreateFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
{
SFILE_CREATE_MPQ CreateInfo;
// Fill the create structure
memset(&CreateInfo, 0, sizeof(SFILE_CREATE_MPQ));
CreateInfo.cbSize = sizeof(SFILE_CREATE_MPQ);
- CreateInfo.dwMpqVersion = (dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> FLAGS_TO_FORMAT_SHIFT;
+ CreateInfo.dwMpqVersion = (dwCreateFlags & MPQ_CREATE_ARCHIVE_VMASK) >> FLAGS_TO_FORMAT_SHIFT;
CreateInfo.dwStreamFlags = STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE;
- CreateInfo.dwAttrFlags = (dwFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_ATTRIBUTE_ALL : 0;
+ CreateInfo.dwFileFlags1 = (dwCreateFlags & MPQ_CREATE_LISTFILE) ? MPQ_FILE_EXISTS : 0;
+ CreateInfo.dwFileFlags2 = (dwCreateFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_FILE_EXISTS : 0;
+ CreateInfo.dwAttrFlags = (dwCreateFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_ATTRIBUTE_ALL : 0;
CreateInfo.dwSectorSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000;
CreateInfo.dwRawChunkSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_4) ? 0x4000 : 0;
CreateInfo.dwMaxFileCount = dwMaxFileCount;
+
+ // Backward compatibility: SFileCreateArchive always used to add (listfile)
+ // We would break loads of applications if we change that
+ CreateInfo.dwFileFlags1 = MPQ_FILE_EXISTS;
+
+ // Let the main function create the archive
return SFileCreateArchive2(szMpqName, &CreateInfo, phMpq);
}
@@ -93,7 +102,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
HANDLE hMpq = NULL;
DWORD dwBlockTableSize = 0; // Initial block table size
DWORD dwHashTableSize = 0;
- DWORD dwMaxFileCount;
+ DWORD dwReservedFiles = 0; // Number of reserved file entries
int nError = ERROR_SUCCESS;
// Check the parameters, if they are valid
@@ -109,8 +118,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
(pCreateInfo->pvUserData != NULL || pCreateInfo->cbUserData != 0) ||
(pCreateInfo->dwAttrFlags & ~MPQ_ATTRIBUTE_ALL) ||
(pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1)) ||
- (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1)) ||
- (pCreateInfo->dwMaxFileCount < 4))
+ (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return false;
@@ -142,15 +150,14 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
return false;
}
- // Increment the maximum amount of files to have space
- // for listfile and attributes file
- dwMaxFileCount = pCreateInfo->dwMaxFileCount;
- if(pCreateInfo->dwAttrFlags != 0)
- dwMaxFileCount++;
- dwMaxFileCount++;
+ // Increment the maximum amount of files to have space for (listfile) and (attributes)
+ if(pCreateInfo->dwMaxFileCount && pCreateInfo->dwFileFlags1)
+ dwReservedFiles++;
+ if(pCreateInfo->dwMaxFileCount && pCreateInfo->dwFileFlags2 && pCreateInfo->dwAttrFlags)
+ dwReservedFiles++;
// If file count is not zero, initialize the hash table size
- dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);
+ dwHashTableSize = GetHashTableSizeForFileCount(pCreateInfo->dwMaxFileCount + dwReservedFiles);
// Retrieve the file size and round it up to 0x200 bytes
FileStream_GetSize(pStream, &MpqPos);
@@ -180,14 +187,13 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
ha->UserDataPos = MpqPos;
ha->MpqPos = MpqPos;
ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData;
- ha->dwMaxFileCount = dwMaxFileCount;
+ ha->dwMaxFileCount = dwHashTableSize;
ha->dwFileTableSize = 0;
+ ha->dwReservedFiles = dwReservedFiles;
ha->dwFileFlags1 = pCreateInfo->dwFileFlags1;
ha->dwFileFlags2 = pCreateInfo->dwFileFlags2;
- ha->dwFlags = 0;
-
- // Setup the attributes
ha->dwAttrFlags = pCreateInfo->dwAttrFlags;
+ ha->dwFlags = 0;
pStream = NULL;
// Fill the MPQ header
@@ -215,21 +221,21 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
}
// 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)
+ if(nError == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3 && pCreateInfo->dwMaxFileCount != 0)
{
- ha->pHetTable = CreateHetTable(0, ha->dwFileTableSize, 0x40, true);
+ ha->pHetTable = CreateHetTable(ha->dwFileTableSize, 0x40, NULL);
if(ha->pHetTable == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Create initial hash table
- if(nError == ERROR_SUCCESS)
+ if(nError == ERROR_SUCCESS && dwHashTableSize != 0)
{
nError = CreateHashTable(ha, dwHashTableSize);
}
// Create initial file table
- if(nError == ERROR_SUCCESS)
+ if(nError == ERROR_SUCCESS && ha->dwMaxFileCount != 0)
{
ha->pFileTable = STORM_ALLOC(TFileEntry, ha->dwMaxFileCount);
if(ha->pFileTable != NULL)