Current News Archived News Search News Discussion Forum Old Forum Install Programs More Downloads... Troubleshooting Source Code Format Specs. Misc. Information Non-SF Stuff Links Small banner for links to this site: |
Added limits to buffering reads on larger blocks to keep memory usage down.
Move bitmasks for unsupported compression types from MPQ library to SComp.
diff --git a/SFmpqapi.cpp b/SFmpqapi.cpp
--- a/SFmpqapi.cpp
+++ b/SFmpqapi.cpp
char StormBasePath[MAX_PATH+1];
-#define UNSUPPORTED_COMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
-#define UNSUPPORTED_DECOMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
-
typedef BOOL (WINAPI* funcSCompCompress)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwWAVQuality);
typedef BOOL (WINAPI* funcSCompDecompress)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
funcSCompCompress stormSCompCompress = 0;
@@ -567,7 +564,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
}
DWORD dwMpqStart;
MPQARCHIVE *mpqOpenArc;
- dwMpqStart = mpqArcFile.lpBlockEntry->dwFileOffset;
+ dwMpqStart = mpqOpenArc->dwMPQStart + mpqArcFile.lpBlockEntry->dwFileOffset;
flen = mpqArcFile.lpBlockEntry->dwFullSize;
dwMpqStart = FindMpqHeaderAtLocation(hFile,dwMpqStart,flen);
if (dwMpqStart==0xFFFFFFFF) {
@@ -1198,6 +1195,8 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
DWORD BlockIndex = mpqOpenFile->lpHashEntry->dwBlockTableIndex;
if (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead>mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize) nNumberOfBytesToRead = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize-mpqOpenFile->dwFilePointer;
DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
+ if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK)
+ blockSize = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
DWORD dwBlockStart = mpqOpenFile->dwFilePointer - (mpqOpenFile->dwFilePointer % blockSize);
DWORD blockNum = dwBlockStart / blockSize;
DWORD nBlocks = (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead) / blockSize;
@@ -1215,12 +1214,18 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
if (lpOverlapped) lpOverlapped->InternalHigh = 0;
return FALSE;
}
- void *blk16Buffer = SFAlloc(blockSize * 16);
- if (!blk16Buffer) {
- SFFree(blkBuffer);
- if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
- if (lpOverlapped) lpOverlapped->InternalHigh = 0;
- return FALSE;
+ DWORD nBufferCount;
+ for (nBufferCount = 1; nBufferCount < nBlocks - blockNum && blockSize * nBufferCount < 65536; nBufferCount *= 2) {}
+ if (nBufferCount > nBlocks - blockNum) nBufferCount = nBlocks - blockNum;
+ void *blkLargeBuffer = NULL;
+ if (nBufferCount > 1) {
+ blkLargeBuffer = SFAlloc(blockSize * nBufferCount);
+ if (!blkLargeBuffer) {
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+ if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+ return FALSE;
+ }
}
DWORD dwCryptKey = mpqOpenFile->dwCryptKey;
//if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) dwCryptKey = HashString(mpqOpenFile->lpFileName,HASH_KEY);
@@ -1237,13 +1242,13 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4);
if (!dwBlockPtrTable) {
- SFFree(blk16Buffer);
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
if (lpOverlapped) lpOverlapped->InternalHigh = 0;
return FALSE;
}
- if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2))
+ if (((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) && !(mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK))
{
SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,FILE_BEGIN);
ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&nBytesRead,0);
@@ -1255,28 +1260,31 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
{
for (i=0;i<TotalBlocks+1;i++) {
if (i<TotalBlocks) dwBlockPtrTable[i] = i * blockSize;
- else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
+ else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize - HeaderLength;
}
}
mpqOpenFile->lpdwBlockOffsets = dwBlockPtrTable;
}
- BYTE *compbuffer = (BYTE *)SFAlloc(blockSize+3);
- if (!compbuffer) {
- SFFree(blk16Buffer);
- SFFree(blkBuffer);
- if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
- if (lpOverlapped) lpOverlapped->InternalHigh = 0;
- return FALSE;
+ BYTE *compbuffer = NULL;
+ if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) {
+ compbuffer = (BYTE *)SFAlloc(blockSize+3);
+ if (!compbuffer) {
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+ if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+ return FALSE;
+ }
}
DWORD blk=0,blki=0;
for (i=blockNum;i<nBlocks;i++) {
- if (blk==0) {
+ if (blk==0 && blkLargeBuffer) {
SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
blki=i;
- if (i+16>nBlocks) {
- if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (i+nBufferCount>nBlocks) {
+ if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@ -1285,9 +1293,9 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
}
else {
- if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[i+16]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[i+nBufferCount]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@ -1295,7 +1303,20 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
}
}
}
- memcpy(blkBuffer,((char *)blk16Buffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+ if (blkLargeBuffer) {
+ memcpy(blkBuffer,((char *)blkLargeBuffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+ }
+ else {
+ SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
+ blki=i;
+ if (ReadFile(mpqOpenArc->hFile,blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+ if (compbuffer) SFFree(compbuffer);
+ SFFree(blkBuffer);
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
+ if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
+ return FALSE;
+ }
+ }
if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT)
{
DecryptData((LPBYTE)blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],dwCryptKey+i);
@@ -1367,10 +1388,10 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
nNumberOfBytesToRead-=nNumberOfBytesToRead;
}
}
- blk = (blk+1) % 16;
+ blk = (blk+1) % nBufferCount;
}
- SFFree(compbuffer);
- SFFree(blk16Buffer);
+ if (compbuffer) SFFree(compbuffer);
+ if (blkLargeBuffer) SFFree(blkLargeBuffer);
SFFree(blkBuffer);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
diff --git a/SFmpqapi.h b/SFmpqapi.h
--- a/SFmpqapi.h
+++ b/SFmpqapi.h
// MpqAddFileToArchive flags
#define MAFA_EXISTS 0x80000000 //This flag will be added if not present
#define MAFA_UNKNOWN40000000 0x40000000 //Unknown flag
+#define MAFA_SINGLEBLOCK 0x01000000 //File is stored as a single unit rather than being split by the block size
#define MAFA_MODCRYPTKEY 0x00020000 //Used with MAFA_ENCRYPT. Uses an encryption key based on file position and size
#define MAFA_ENCRYPT 0x00010000 //Encrypts the file. The file is still accessible when using this, so the use of this has depreciated
#define MAFA_COMPRESS 0x00000200 //File is to be compressed when added. This is used for most of the compression methods
|