aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2022-05-15 20:57:06 +0200
committerGitHub <noreply@github.com>2022-05-15 20:57:06 +0200
commit8f3f327697b392014cc084f4f3a3547ddb3a1b89 (patch)
tree5f6f348381c516aa3e307a41d24086da5b243acc
parent460354d98bc266507befe517f9f246d3b952abc9 (diff)
parent07f9be39a62b93fa3af07c2fc02dcd25edd2c00b (diff)
Merge pull request #255 from ladislav-zezula/LZ_SupportStarcraftBeta
Support for Starcraft BETA ADPCM compression
-rw-r--r--src/SCompression.cpp56
-rw-r--r--src/SFileOpenArchive.cpp18
-rw-r--r--src/SFileReadFile.cpp9
-rw-r--r--src/StormLib.h16
-rw-r--r--src/adpcm/adpcm.cpp184
-rw-r--r--src/adpcm/adpcm.h5
-rw-r--r--storm_dll/storm_test.cpp196
-rw-r--r--test/StormTest.cpp17
-rw-r--r--test/stormlib-test.txt175
9 files changed, 532 insertions, 144 deletions
diff --git a/src/SCompression.cpp b/src/SCompression.cpp
index 1d0f679..54c84b4 100644
--- a/src/SCompression.cpp
+++ b/src/SCompression.cpp
@@ -647,6 +647,24 @@ static int Decompress_ADPCM_stereo(void * pvOutBuffer, int * pcbOutBuffer, void
return 1;
}
+/******************************************************************************/
+/* */
+/* Support for ADPCM mono & stereo (Starcraft I BETA - like) */
+/* */
+/******************************************************************************/
+
+static int Decompress_ADPCM1_sc1b(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
+{
+ *pcbOutBuffer = DecompressADPCM_SC1B(pvOutBuffer, *pcbOutBuffer, pvInBuffer, cbInBuffer, 1);
+ return 1;
+}
+
+static int Decompress_ADPCM2_sc1b(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
+{
+ *pcbOutBuffer = DecompressADPCM_SC1B(pvOutBuffer, *pcbOutBuffer, pvInBuffer, cbInBuffer, 2);
+ return 1;
+}
+
/*****************************************************************************/
/* */
/* SCompImplode */
@@ -784,7 +802,7 @@ int WINAPI SCompCompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuff
else
{
// Fill the compressions array
- for(size_t i = 0; i < (sizeof(cmp_table) / sizeof(TCompressTable)); i++)
+ for(size_t i = 0; i < _countof(cmp_table); i++)
{
// If the mask agrees, insert the compression function to the array
if(uCompressionMask & cmp_table[i].uMask)
@@ -891,7 +909,17 @@ static TDecompressTable dcmp_table[] =
{MPQ_COMPRESSION_SPARSE, Decompress_SPARSE} // Sparse decompression
};
-int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
+// Decompression table specific for Starcraft I BETA
+// WAVE files are compressed by different ADPCM compression
+static TDecompressTable dcmp_table_sc1b[] =
+{
+ {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library
+ {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression
+ {0x10, Decompress_ADPCM1_sc1b}, // IMA ADPCM mono decompression
+ {0x20, Decompress_ADPCM2_sc1b}, // IMA ADPCM stereo decompression
+};
+
+static int SCompDecompressInternal(TDecompressTable * table, size_t table_length, void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
{
unsigned char * pbWorkBuffer = NULL;
unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer;
@@ -920,7 +948,7 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
}
// Get applied compression types and decrement data length
- uCompressionMask = uCompressionCopy = (unsigned char)*pbInBuffer++;
+ uCompressionMask = uCompressionCopy = (unsigned char)(*pbInBuffer++);
cbInBuffer--;
// Get current compressed data and length of it
@@ -931,12 +959,12 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
assert(uCompressionMask != MPQ_COMPRESSION_LZMA);
// Parse the compression mask
- for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++)
+ for(size_t i = 0; i < table_length; i++)
{
// If the mask agrees, insert the compression function to the array
- if(uCompressionMask & dcmp_table[i].uMask)
+ if(uCompressionMask & table[i].uMask)
{
- uCompressionCopy &= ~dcmp_table[i].uMask;
+ uCompressionCopy &= ~table[i].uMask;
nCompressCount++;
}
}
@@ -963,10 +991,10 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
nCompressIndex = nCompressCount - 1;
// Apply all decompressions
- for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++)
+ for(size_t i = 0; i < table_length; i++)
{
// Perform the (next) decompression
- if(uCompressionMask & dcmp_table[i].uMask)
+ if(uCompressionMask & table[i].uMask)
{
// Get the correct output buffer
pbOutput = (nCompressIndex & 1) ? pbWorkBuffer : pbOutBuffer;
@@ -974,7 +1002,7 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
// Perform the decompression
cbOutBuffer = *pcbOutBuffer;
- nResult = dcmp_table[i].Decompress(pbOutput, &cbOutBuffer, pbInput, cbInLength);
+ nResult = table[i].Decompress(pbOutput, &cbOutBuffer, pbInput, cbInLength);
if(nResult == 0 || cbOutBuffer == 0)
{
SetLastError(ERROR_FILE_CORRUPT);
@@ -997,6 +1025,16 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
return nResult;
}
+int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
+{
+ return SCompDecompressInternal(dcmp_table, _countof(dcmp_table), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer);
+}
+
+int WINAPI SCompDecompress_SC1B(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
+{
+ return SCompDecompressInternal(dcmp_table_sc1b, _countof(dcmp_table_sc1b), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer);
+}
+
int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer)
{
DECOMPRESS pfnDecompress1 = NULL;
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp
index 52e1a39..b85f24c 100644
--- a/src/SFileOpenArchive.cpp
+++ b/src/SFileOpenArchive.cpp
@@ -75,6 +75,20 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe
return MapTypeNotRecognized;
}
+static bool IsStarcraftBetaArchive(TMPQHeader * pHeader)
+{
+ // The archive must be version 1, with a standard header size
+ if(pHeader->dwID == ID_MPQ && pHeader->dwHeaderSize == MPQ_HEADER_SIZE_V1)
+ {
+ // Check for known archive sizes
+ return (pHeader->dwArchiveSize == 0x00028FB3 || // patch_rt.mpq
+ pHeader->dwArchiveSize == 0x0351853D || // StarDat.mpq
+ pHeader->dwArchiveSize == 0x0AEC8960); // INSTALL.exe
+
+ }
+ return false;
+}
+
static TMPQUserData * IsValidMpqUserData(ULONGLONG ByteOffset, ULONGLONG FileSize, void * pvUserData)
{
TMPQUserData * pUserData;
@@ -446,6 +460,10 @@ bool WINAPI SFileOpenArchive(
if(dwFlags & MPQ_OPEN_FORCE_LISTFILE)
ha->dwFlags |= MPQ_FLAG_LISTFILE_FORCE;
+ // StarDat.mpq from Starcraft I BETA: Enable special compression types
+ if(IsStarcraftBetaArchive(ha->pHeader))
+ ha->dwFlags |= MPQ_FLAG_STARCRAFT_BETA;
+
// Remember whether whis is a map for Warcraft III
if(MapType == MapTypeWarcraft3)
{
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 6ec04f3..8031ba7 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -173,9 +173,16 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset,
// Decompress the data
if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ {
nResult = SCompDecompress2(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ }
else
- nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ {
+ if(ha->dwFlags & MPQ_FLAG_STARCRAFT_BETA)
+ nResult = SCompDecompress_SC1B(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ else
+ nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ }
}
// Is the file compressed by PKWARE Data Compression Library ?
diff --git a/src/StormLib.h b/src/StormLib.h
index 048281d..1c4e199 100644
--- a/src/StormLib.h
+++ b/src/StormLib.h
@@ -192,13 +192,14 @@ extern "C" {
#define MPQ_FLAG_SAVING_TABLES 0x00000040 // If set, we are saving MPQ internal files and MPQ tables
#define MPQ_FLAG_PATCH 0x00000080 // If set, this MPQ is a patch archive
#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a Warcraft III map
-#define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles
-#define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles
-#define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit
-#define MPQ_FLAG_ATTRIBUTES_NONE 0x00001000 // Set when no (attributes) was found in InvalidateInternalFiles
-#define MPQ_FLAG_ATTRIBUTES_NEW 0x00002000 // Set when (attributes) invalidated by InvalidateInternalFiles
-#define MPQ_FLAG_SIGNATURE_NONE 0x00004000 // Set when no (signature) was found in InvalidateInternalFiles
-#define MPQ_FLAG_SIGNATURE_NEW 0x00008000 // Set when (signature) invalidated by InvalidateInternalFiles
+#define MPQ_FLAG_STARCRAFT_BETA 0x00000200 // If set, this MPQ is StarDat.mpq from Starcraft I BETA
+#define MPQ_FLAG_LISTFILE_NONE 0x00000400 // Set when no (listfile) was found in InvalidateInternalFiles
+#define MPQ_FLAG_LISTFILE_NEW 0x00000800 // Set when (listfile) invalidated by InvalidateInternalFiles
+#define MPQ_FLAG_LISTFILE_FORCE 0x00001000 // Save updated listfile on exit
+#define MPQ_FLAG_ATTRIBUTES_NONE 0x00002000 // Set when no (attributes) was found in InvalidateInternalFiles
+#define MPQ_FLAG_ATTRIBUTES_NEW 0x00004000 // Set when (attributes) invalidated by InvalidateInternalFiles
+#define MPQ_FLAG_SIGNATURE_NONE 0x00008000 // Set when no (signature) was found in InvalidateInternalFiles
+#define MPQ_FLAG_SIGNATURE_NEW 0x00010000 // Set when (signature) invalidated by InvalidateInternalFiles
// Values for TMPQArchive::dwSubType
#define MPQ_SUBTYPE_MPQ 0x00000000 // The file is a MPQ file (Blizzard games)
@@ -1111,6 +1112,7 @@ int WINAPI SCompExplode (void * pvOutBuffer, int * pcbOutBuffer, void * pv
int WINAPI SCompCompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel);
int WINAPI SCompDecompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
+int WINAPI SCompDecompress_SC1B(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
//-----------------------------------------------------------------------------
// Non-Windows support for SetLastError/GetLastError
diff --git a/src/adpcm/adpcm.cpp b/src/adpcm/adpcm.cpp
index fb0efbf..1725008 100644
--- a/src/adpcm/adpcm.cpp
+++ b/src/adpcm/adpcm.cpp
@@ -13,6 +13,7 @@
/* 10.01.13 3.00 Lad Refactored, beautified, documented :-) */
/*****************************************************************************/
+#include <assert.h>
#include <stddef.h>
#include "adpcm.h"
@@ -20,7 +21,7 @@
//-----------------------------------------------------------------------------
// Tables necessary dor decompression
-static int NextStepTable[] =
+static const int NextStepTable[] =
{
-1, 0, -1, 4, -1, 2, -1, 6,
-1, 1, -1, 5, -1, 3, -1, 7,
@@ -28,7 +29,7 @@ static int NextStepTable[] =
-1, 2, -1, 4, -1, 6, -1, 8
};
-static int StepSizeTable[] =
+static const int StepSizeTable[] =
{
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
@@ -127,10 +128,10 @@ static inline short GetNextStepIndex(int StepIndex, unsigned int EncodedSample)
return (short)StepIndex;
}
-static inline int UpdatePredictedSample(int PredictedSample, int EncodedSample, int Difference)
+static inline int UpdatePredictedSample(int PredictedSample, int EncodedSample, int Difference, int BitMask = 0x40)
{
// Is the sign bit set?
- if(EncodedSample & 0x40)
+ if(EncodedSample & BitMask)
{
PredictedSample -= Difference;
if(PredictedSample <= -32768)
@@ -187,8 +188,6 @@ int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cb
int MaxBitMask;
int StepSize;
-// _tprintf(_T("== CMPR Started ==============\n"));
-
// First byte in the output stream contains zero. The second one contains the compression level
os.WriteByteSample(0);
if(!os.WriteByteSample(BitShift))
@@ -290,7 +289,6 @@ int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cb
}
}
-// _tprintf(_T("== CMPR Ended ================\n"));
return os.LengthProcessed(pvOutBuffer);
}
@@ -311,12 +309,9 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
PredictedSamples[0] = PredictedSamples[1] = 0;
StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
-// _tprintf(_T("== DCMP Started ==============\n"));
-
// The first byte is always zero, the second one contains bit shift (compression level - 1)
is.ReadByteSample(BitShift);
is.ReadByteSample(BitShift);
-// _tprintf(_T("DCMP: BitShift = %u\n"), (unsigned int)(unsigned char)BitShift);
// Next, InitialSample value for each channel follows
for(int i = 0; i < ChannelCount; i++)
@@ -328,8 +323,6 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
if(!is.ReadWordSample(InitialSample))
return os.LengthProcessed(pvOutBuffer);
-// _tprintf(_T("DCMP: Loaded InitialSample[%u]: %04X\n"), i, (unsigned int)(unsigned short)InitialSample);
-
// Store the initial sample to our sample array
PredictedSamples[i] = InitialSample;
@@ -344,8 +337,6 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
// Keep reading as long as there is something in the input buffer
while(is.ReadByteSample(EncodedSample))
{
-// _tprintf(_T("DCMP: Loaded Encoded Sample: %02X\n"), (unsigned int)(unsigned char)EncodedSample);
-
// If we have two channels, we need to flip the channel index
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
@@ -354,7 +345,6 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
if(StepIndexes[ChannelIndex] != 0)
StepIndexes[ChannelIndex]--;
-// _tprintf(_T("DCMP: Writing Decoded Sample: %04lX\n"), (unsigned int)(unsigned short)PredictedSamples[ChannelIndex]);
if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
return os.LengthProcessed(pvOutBuffer);
}
@@ -365,8 +355,6 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
if(StepIndexes[ChannelIndex] > 0x58)
StepIndexes[ChannelIndex] = 0x58;
-// _tprintf(_T("DCMP: New value of StepIndex: %04lX\n"), (unsigned int)(unsigned short)StepIndexes[ChannelIndex]);
-
// Next pass, keep going on the same channel
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
}
@@ -381,21 +369,171 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
StepSize,
StepSize >> BitShift);
-// _tprintf(_T("DCMP: Writing decoded sample: %04X\n"), (unsigned int)(unsigned short)PredictedSamples[ChannelIndex]);
-
// Write the decoded sample to the output stream
if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
break;
// Calculates the step index to use for the next encode
StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndex, EncodedSample);
-// _tprintf(_T("DCMP: New step index: %04X\n"), (unsigned int)(unsigned short)StepIndexes[ChannelIndex]);
}
}
-// _tprintf(_T("DCMP: Total length written: %u\n"), (unsigned int)os.LengthProcessed(pvOutBuffer));
-// _tprintf(_T("== DCMP Ended ================\n"));
-
// Return total bytes written since beginning of the output buffer
return os.LengthProcessed(pvOutBuffer);
}
+
+//-----------------------------------------------------------------------------
+// ADPCM decompression present in Starcraft I BETA
+
+typedef struct _ADPCM_DATA
+{
+ const unsigned int * pValues;
+ int BitCount;
+ int field_8;
+ int field_C;
+ int field_10;
+
+} ADPCM_DATA, *PADPCM_DATA;
+
+static const unsigned int adpcm_values_2[] = {0x33, 0x66};
+static const unsigned int adpcm_values_3[] = {0x3A, 0x3A, 0x50, 0x70};
+static const unsigned int adpcm_values_4[] = {0x3A, 0x3A, 0x3A, 0x3A, 0x4D, 0x66, 0x80, 0x9A};
+static const unsigned int adpcm_values_6[] =
+{
+ 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
+ 0x46, 0x53, 0x60, 0x6D, 0x7A, 0x86, 0x93, 0xA0, 0xAD, 0xBA, 0xC6, 0xD3, 0xE0, 0xED, 0xFA, 0x106
+};
+
+static const unsigned int * InitAdpcmData(PADPCM_DATA pData, unsigned char BitCount)
+{
+ switch(BitCount)
+ {
+ case 2:
+ pData->pValues = adpcm_values_2;
+ break;
+
+ case 3:
+ pData->pValues = adpcm_values_3;
+ break;
+
+ case 4:
+ pData->pValues = adpcm_values_4;
+ break;
+
+ default:
+ pData->pValues = NULL;
+ break;
+
+ case 6:
+ pData->pValues = adpcm_values_6;
+ break;
+ }
+
+ pData->BitCount = BitCount;
+ pData->field_C = 0x20000;
+ pData->field_8 = 1 << BitCount;
+ pData->field_10 = (1 << BitCount) / 2;
+ return pData->pValues;
+}
+
+int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount)
+{
+ TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream
+ TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream
+ ADPCM_DATA AdpcmData;
+ int LowBitValues[MAX_ADPCM_CHANNEL_COUNT];
+ int UpperBits[MAX_ADPCM_CHANNEL_COUNT];
+ int BitMasks[MAX_ADPCM_CHANNEL_COUNT];
+ int PredictedSamples[MAX_ADPCM_CHANNEL_COUNT];
+ int ChannelIndex;
+ int ChannelIndexMax;
+ int OutputSample;
+ unsigned char BitCount;
+ unsigned char EncodedSample;
+ short InputValue16;
+ int reg_eax;
+ int Difference;
+
+ // The first byte contains number of bits
+ if(!is.ReadByteSample(BitCount))
+ return os.LengthProcessed(pvOutBuffer);
+ if(!InitAdpcmData(&AdpcmData, BitCount))
+ return os.LengthProcessed(pvOutBuffer);
+ assert(AdpcmData.pValues != NULL);
+
+ // Init bit values
+ for(int i = 0; i < ChannelCount; i++)
+ {
+ unsigned char OneByte;
+
+ if(!is.ReadByteSample(OneByte))
+ return os.LengthProcessed(pvOutBuffer);
+ LowBitValues[i] = OneByte & 0x01;
+ UpperBits[i] = OneByte >> 1;
+ }
+
+ //
+ for(int i = 0; i < ChannelCount; i++)
+ {
+ if(!is.ReadWordSample(InputValue16))
+ return os.LengthProcessed(pvOutBuffer);
+ BitMasks[i] = InputValue16 << AdpcmData.BitCount;
+ }
+
+ // Next, InitialSample value for each channel follows
+ for(int i = 0; i < ChannelCount; i++)
+ {
+ if(!is.ReadWordSample(InputValue16))
+ return os.LengthProcessed(pvOutBuffer);
+
+ PredictedSamples[i] = InputValue16;
+ os.WriteWordSample(InputValue16);
+ }
+
+ // Get the initial index
+ ChannelIndexMax = ChannelCount - 1;
+ ChannelIndex = 0;
+
+ // Keep reading as long as there is something in the input buffer
+ while(is.ReadByteSample(EncodedSample))
+ {
+ reg_eax = ((PredictedSamples[ChannelIndex] * 3) << 3) - PredictedSamples[ChannelIndex];
+ PredictedSamples[ChannelIndex] = ((reg_eax * 10) + 0x80) >> 8;
+
+ Difference = (((EncodedSample >> 1) + 1) * BitMasks[ChannelIndex] + AdpcmData.field_10) >> AdpcmData.BitCount;
+
+ PredictedSamples[ChannelIndex] = UpdatePredictedSample(PredictedSamples[ChannelIndex], EncodedSample, Difference, 0x01);
+
+ BitMasks[ChannelIndex] = (AdpcmData.pValues[EncodedSample >> 1] * BitMasks[ChannelIndex] + 0x80) >> 6;
+ if(BitMasks[ChannelIndex] < AdpcmData.field_8)
+ BitMasks[ChannelIndex] = AdpcmData.field_8;
+
+ if(BitMasks[ChannelIndex] > AdpcmData.field_C)
+ BitMasks[ChannelIndex] = AdpcmData.field_C;
+
+ reg_eax = (cbInBuffer - is.LengthProcessed(pvInBuffer)) >> ChannelIndexMax;
+ OutputSample = PredictedSamples[ChannelIndex];
+ if(reg_eax < UpperBits[ChannelIndex])
+ {
+ if(LowBitValues[ChannelIndex])
+ {
+ OutputSample += (UpperBits[ChannelIndex] - reg_eax);
+ if(OutputSample > 32767)
+ OutputSample = 32767;
+ }
+ else
+ {
+ OutputSample += (reg_eax - UpperBits[ChannelIndex]);
+ if(OutputSample < -32768)
+ OutputSample = -32768;
+ }
+ }
+
+ // Write the word sample and swap channel
+ os.WriteWordSample((short)(OutputSample));
+ ChannelIndex = (ChannelIndex + 1) % ChannelCount;
+ }
+
+ return os.LengthProcessed(pvOutBuffer);
+}
+
diff --git a/src/adpcm/adpcm.h b/src/adpcm/adpcm.h
index b1bf361..22a8095 100644
--- a/src/adpcm/adpcm.h
+++ b/src/adpcm/adpcm.h
@@ -20,7 +20,8 @@
//-----------------------------------------------------------------------------
// Public functions
-int CompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int nCmpType, int ChannelCount);
-int DecompressADPCM(void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int ChannelCount);
+int CompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int nCmpType, int ChannelCount);
+int DecompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int ChannelCount);
+int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount);
#endif // __ADPCM_H__
diff --git a/storm_dll/storm_test.cpp b/storm_dll/storm_test.cpp
index 397c4dd..0ac2c67 100644
--- a/storm_dll/storm_test.cpp
+++ b/storm_dll/storm_test.cpp
@@ -11,6 +11,7 @@
#define _CRT_NON_CONFORMING_SWPRINTFS
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
+#include <windows.h>
#ifdef _MSC_VER
#include <crtdbg.h>
@@ -20,8 +21,141 @@
#include "storm.h" // Header file for Storm.dll
//-----------------------------------------------------------------------------
+// List of files
+
+const char * IntToHexChar = "0123456789ABCDEF";
+
+LPCSTR ListFile[] =
+{
+ "music\\tdefeat.wav",
+ "setupdat\\inst.vis",
+ "setupdat\\audio\\mouseover.wav",
+ "files\\font\\font12.fnt",
+ "music\\zvict.wav",
+ "files\\readme.txt",
+ "music\\zerg2.wav",
+ "music\\zerg1.wav",
+ "setupdat\\inst_regs.ins",
+ "files\\font\\font50.fnt",
+ "files\\msv2all.vxp",
+ "setupdat\\scr_options.vis",
+ "setupdat\\font\\font16x.fnt",
+ "setupdat\\setup.vis",
+ "maps\\128x128_wasteland4.scm",
+ "setupdat\\scr_main.vis",
+ "music\\pvict.wav",
+ "music\\zdefeat.wav",
+ "files\\font\\font16x.fnt",
+ "setupdat\\nt\\comctl32.dll",
+ "setupdat\\debug.ins",
+ "setupdat\\inst.ins",
+ "music\\pdefeat.wav",
+ "files\\smackw32.dll",
+ "music\\tvict.wav",
+ "setupdat\\optvox.vis",
+ "setupdat\\gen\\maps.lst",
+ "files\\font\\font8.fnt",
+ "files\\mvoice.vxp",
+ "files\\font\\font14.fnt",
+ "files\\battle.snp",
+ "files\\storm.dll",
+ "maps\\128x128_ash4.scm",
+ "files\\font\\font32.fnt",
+ "setupdat\\normal.ins",
+ "files\\font\\font16.fnt",
+ "setupdat\\mainplay.vis",
+ "setupdat\\gendefs.ins",
+ "setupdat\\audio\\installermusic.wav",
+ "setupdat\\templates.ins",
+ "music\\terran1.wav",
+ "maps\\96x96_ash4.scm",
+ "setupdat\\defaults.vis",
+ "music\\prdyroom.wav",
+ "setupdat\\scr_blizzard.vis",
+ "setupdat\\scr_isp.vis",
+ "setupdat\\95\\comctl32.dll",
+ "files\\font\\font10.fnt",
+ "files\\local.dll",
+ "music\\terran3.wav",
+ "music\\terran2.wav",
+ "setupdat\\audio\\battlenetclick.wav",
+ "music\\zrdyroom.wav",
+ "setupdat\\starunin.exe",
+ "files\\vct32150.dll",
+ "maps\\96x96_wasteland4.scm",
+ "setupdat\\inst_sys.ins",
+ "music\\zerg3.wav",
+ "setupdat\\license.txt",
+ "music\\protoss2.wav",
+ "files\\starcraft.exe",
+ "music\\trdyroom.wav",
+ "maps\\96x96_space4.scm",
+ "files\\vfonts.vxp",
+ "setupdat\\installed.ins",
+ "music\\protoss1.wav",
+ "files\\stardat.mpq",
+ "setupdat\\font\\font16.fnt",
+ "smk\\starintr.smk",
+ "files\\vadagc.vxp",
+ "setupdat\\strings.ins",
+ "music\\title.wav",
+ "setupdat\\font\\font32.fnt",
+ "setupdat\\inst_files.ins",
+ "setupdat\\images\\install.pcx",
+ "files\\report bugs.url",
+ "setupdat\\single.ins",
+ "maps\\128x128_space4.scm",
+ "setupdat\\audio\\mousedown.wav",
+ NULL
+};
+
+//-----------------------------------------------------------------------------
// Main
+static void CalculateMD5(LPBYTE md5_digest, LPBYTE pbData, DWORD cbData)
+{
+ HCRYPTPROV hCryptProv = NULL;
+ HCRYPTHASH hCryptHash = NULL;
+
+ if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ if(CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash))
+ {
+ DWORD dwHashLen = 0x10;
+
+ CryptHashData(hCryptHash, pbData, cbData, 0);
+ CryptGetHashParam(hCryptHash, HP_HASHVAL, md5_digest, &dwHashLen, 0);
+ CryptDestroyHash(hCryptHash);
+ }
+
+ CryptReleaseContext(hCryptProv, 0);
+ }
+}
+
+template <typename XCHAR>
+DWORD BinaryToString(XCHAR * szBuffer, size_t cchBuffer, LPCVOID pvBinary, size_t cbBinary)
+{
+ LPCBYTE pbBinary = (LPCBYTE)pvBinary;
+
+ // The size of the string must be enough to hold the binary + EOS
+ if(cchBuffer < ((cbBinary * 2) + 1))
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ // Convert the string to the array of MD5
+ // Copy the blob data as text
+ for(size_t i = 0; i < cbBinary; i++)
+ {
+ *szBuffer++ = IntToHexChar[pbBinary[0] >> 0x04];
+ *szBuffer++ = IntToHexChar[pbBinary[0] & 0x0F];
+ pbBinary++;
+ }
+
+ // Terminate the string
+ *szBuffer = 0;
+ return ERROR_SUCCESS;
+}
+
+
int main(int argc, char * argv[])
{
LPCSTR szArchiveName;
@@ -29,10 +163,12 @@ int main(int argc, char * argv[])
LPCSTR szFormat;
HANDLE hMpq = NULL;
HANDLE hFile = NULL;
- BYTE Buffer[0x100];
+ LPBYTE pbBuffer = NULL;
DWORD dwBytesRead = 0;
DWORD dwFileSize = 0;
BOOL bResult;
+ BYTE md5_digest[0x10];
+ char md5_string[0x40];
// Check parameters
if(argc != 3)
@@ -46,34 +182,52 @@ int main(int argc, char * argv[])
szArchiveName = argv[1];
szFileName = argv[2];
+ // Break for kernel debugger
+ //__debugbreak();
+
// Put Storm.dll to the current folder before running this
- printf("[*] Opening archive '%s' ...\n", szArchiveName);
+ //printf("[*] Opening archive '%s' ...\n", szArchiveName);
if(StormOpenArchive(szArchiveName, 0, 0, &hMpq))
{
- printf("[*] Opening file '%s' ...\n", szFileName);
- if(StormOpenFileEx(hMpq, "staredit\\scenario.chk", 0, &hFile))
+ for(size_t i = 0; ListFile[i] != NULL; i++)
{
- printf("[*] Retrieving file size ... ");
- dwFileSize = StormGetFileSize(hFile, NULL);
- szFormat = (dwFileSize == INVALID_FILE_SIZE) ? ("(invalid)\n") : ("(%u bytes)\n");
- printf(szFormat, dwFileSize);
-
- printf("[*] Moving to begin of the file ...\n");
- StormSetFilePointer(hFile, 0, NULL, FILE_BEGIN);
-
- printf("[*] Reading file ... ");
- bResult = StormReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
- szFormat = (bResult == FALSE) ? ("(error %u)\n") : ("(OK)\n");
- printf(szFormat, GetLastError());
-
- printf("[*] Closing file ...\n");
- StormCloseFile(hFile);
+ //printf("[*] Opening file '%s' ...\n", ListFile[i]);
+ if(StormOpenFileEx(hMpq, ListFile[i], 0, &hFile))
+ {
+ //printf("[*] Retrieving file size ... ");
+ dwFileSize = StormGetFileSize(hFile, NULL);
+ szFormat = (dwFileSize == INVALID_FILE_SIZE) ? ("(invalid)\n") : ("(%u bytes)\n");
+ //printf(szFormat, dwFileSize);
+
+ // Allocate the buffer for the entire file
+ //printf("[*] Allocating buffer ...\n");
+ if((pbBuffer = new BYTE[dwFileSize]) != NULL)
+ {
+ //printf("[*] Moving to begin of the file ...\n");
+ StormSetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+
+ //printf("[*] Reading file ... ");
+ bResult = StormReadFile(hFile, pbBuffer, dwFileSize, &dwBytesRead, NULL);
+ szFormat = (bResult != FALSE && dwBytesRead == dwFileSize) ? ("(OK)\n") : ("(error %u)\n");
+ //printf(szFormat, GetLastError());
+
+ //printf("[*] Calculating MD5 ... ");
+ CalculateMD5(md5_digest, pbBuffer, dwFileSize);
+ BinaryToString(md5_string, _countof(md5_string), md5_digest, sizeof(md5_digest));
+ printf("%s *%s\n", md5_string, ListFile[i]);
+
+ delete[] pbBuffer;
+ }
+
+ //printf("[*] Closing file ...\n");
+ StormCloseFile(hFile);
+ }
}
- printf("[*] Closing archive ...\n");
+ //printf("[*] Closing archive ...\n");
StormCloseArchive(hMpq);
}
- printf("Done.\n\n");
+ //printf("Done.\n\n");
return 0;
}
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 128cd6b..f8b8f7d 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -2559,6 +2559,17 @@ static DWORD TestArchive(
if(dwCrc32 != pFileData->dwCrc32)
Logger.PrintError("Warning: CRC32 error on %s", szFileName);
}
+
+#ifdef _DEBUG
+/*
+ FILE * fp = fopen("e:\\out_file.wav", "wb");
+ if(fp)
+ {
+ fwrite(pFileData->FileData, 1, pFileData->dwFileSize, fp);
+ fclose(fp);
+ }
+*/
+#endif
}
}
@@ -4244,6 +4255,9 @@ static const TEST_INFO Test_Mpqs[] =
{
// Correct or damaged archives
{_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
+ {_T("MPQ_1997_v1_patch_rt_SC1B.mpq"), NULL, TEST_DATA("43fe7d362955be68a708486e399576a7", 10)}, // From Starcraft 1 BETA
+ {_T("MPQ_1997_v1_StarDat_SC1B.mpq"), NULL, TEST_DATA("0094b23f28cfff7386071ef3bd19a577", 2468)}, // From Starcraft 1 BETA
+ {_T("MPQ_1997_v1_INSTALL_SC1B.EXE_"), NULL, TEST_DATA("3248460c89bb6f8e3b8fc3e08de7ffbb", 79)}, // From Starcraft 1 BETA
{_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, TEST_DATA("255d87a62f3c9518f72cf723a1818946", 221), "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016)
{_T("MPQ_2018_v1_icon_error.w3m"), NULL, TEST_DATA("fcefa25fb50c391e8714f2562d1e10ff", 19), "file00000002.blp"},
{_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), Bliz, TEST_DATA("5ef18ef9a26b5704d8d46a344d976c89", 2)}, // File whose archive's (signature) file has flags = 0x90000000
@@ -4331,7 +4345,8 @@ int _tmain(int argc, TCHAR * argv[])
for(int i = 2; i < argc; i++)
{
- TestArchive(argv[i], Bliz, 0, "staredit\\scenario.chk", NULL);
+// TestArchive(argv[i], Bliz, 0, "sound\\zerg\\advisor\\zaderr05.wav", NULL);
+// TestArchive(argv[i], Bliz, 0, "music\\trdyroom.wav", NULL);
}
//
diff --git a/test/stormlib-test.txt b/test/stormlib-test.txt
index 34917cc..4a1bd2c 100644
--- a/test/stormlib-test.txt
+++ b/test/stormlib-test.txt
@@ -1,11 +1,92 @@
-Microsoft Windows [Version 10.0.19044.1415]
+Microsoft Windows [Version 10.0.19044.1706]
(c) Microsoft Corporation. All rights reserved.
-E:\Ladik\Appdir\StormLib>StormLib_test.exe
+E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release>StormLib_test.exe
==== Test Suite for StormLib version 9.23 ====
InitWorkDir: Work directory \Multimedia\MPQs (default)
LocalListFile (FLAT-MAP:ListFile_Blizzard.txt) succeeded.
LocalListFile (ListFile_Blizzard.txt) succeeded.
+FileStreamTest (MPQ_2013_v4_alternate-original.MPQ) succeeded.
+FileStreamTest (MPQ_2013_v4_alternate-original.MPQ) succeeded.
+FileStreamTest (MPQ_2013_v4_alternate-complete.MPQ) succeeded.
+FileStreamTest (part-file://MPQ_2009_v2_WoW_patch.MPQ.part) succeeded.
+FileStreamTest (blk4-file://streaming/model.MPQ.0) succeeded.
+FileStreamTest (mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE) succeeded.
+OpenMirrorFile (part-file://MPQ_2009_v1_patch-created.MPQ.part) succeeded.
+OpenMirrorFile (part-file://MPQ_2009_v1_patch-partial.MPQ.part) succeeded.
+OpenMirrorFile (part-file://MPQ_2009_v1_patch-complete.MPQ.part) succeeded.
+OpenMirrorFile (MPQ_2013_v4_alternate-created.MPQ) succeeded.
+OpenMirrorFile (MPQ_2013_v4_alternate-incomplete.MPQ) succeeded.
+OpenMirrorFile (MPQ_2013_v4_alternate-complete.MPQ) succeeded.
+TestMpq (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded.
+TestMpq (MPQ_1997_v1_patch_rt_SC1B.mpq) succeeded.
+TestMpq (MPQ_1997_v1_StarDat_SC1B.mpq) succeeded.
+TestMpq (MPQ_1997_v1_INSTALL_SC1B.EXE_) succeeded.
+TestMpq (MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq) succeeded.
+TestMpq (MPQ_2018_v1_icon_error.w3m) succeeded.
+TestMpq (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded.
+TestMpq (MPQ_2012_v2_EmptyMpq.MPQ) succeeded.
+TestMpq (MPQ_2013_v4_EmptyMpq.MPQ) succeeded.
+TestMpq (MPQ_2013_v4_patch-base-16357.MPQ) succeeded.
+TestMpq (MPQ_2011_v4_InvalidHetEntryCount.MPQ) succeeded.
+TestMpq (MPQ_2002_v1_BlockTableCut.MPQ) succeeded.
+TestMpq (MPQ_2010_v2_HasUserData.s2ma) succeeded.
+TestMpq (MPQ_2014_v1_AttributesOneEntryLess.w3x) succeeded.
+TestMpq (MPQ_2020_v1_AHF04patch.mix) succeeded.
+TestMpq (MPQ_2010_v3_expansion-locale-frFR.MPQ) succeeded.
+TestMpq (mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE) succeeded.
+TestMpq (MPx_2013_v1_LongwuOnline.mpk) succeeded.
+TestMpq (MPx_2013_v1_WarOfTheImmortals.sqp) succeeded.
+TestMpq (part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part) succeeded.
+TestMpq (blk4-file://streaming/model.MPQ.0) succeeded.
+TestMpq (MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x) succeeded.
+TestMpq (MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x) succeeded.
+TestMpq (MPQ_2002_v1_ProtectedMap_Spazzler.w3x) succeeded.
+TestMpq (MPQ_2014_v1_ProtectedMap_Spazzler2.w3x) succeeded.
+TestMpq (MPQ_2014_v1_ProtectedMap_Spazzler3.w3x) succeeded.
+TestMpq (MPQ_2002_v1_ProtectedMap_BOBA.w3m) succeeded.
+TestMpq (MPQ_2015_v1_ProtectedMap_KangTooJee.w3x) succeeded.
+TestMpq (MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x) succeeded.
+TestMpq (MPQ_2015_v1_ProtectedMap_Spazy.w3x) succeeded.
+TestMpq (MPQ_2015_v1_MessListFile.mpq) succeeded.
+TestMpq (MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x) succeeded.
+TestMpq (MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x) succeeded.
+TestMpq (MPQ_2016_v1_ProtectedMap_Somj2.w3x) succeeded.
+TestMpq (MPQ_2016_v1_WME4_4.w3x) succeeded.
+TestMpq (MPQ_2016_v1_SP_(4)Adrenaline.w3x) succeeded.
+TestMpq (MPQ_2016_v1_ProtectedMap_1.4.w3x) succeeded.
+TestMpq (MPQ_2016_v1_KoreanFile.w3m) succeeded.
+TestMpq (MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x) succeeded.
+TestMpq (MPQ_2017_v1_BigDummyFiles.w3x) succeeded.
+TestMpq (MPQ_2017_v1_TildeInFileName.mpq) succeeded.
+TestMpq (MPQ_2018_v1_EWIX_v8_7.w3x) succeeded.
+TestMpq (MPQ_2020_v4_FakeMpqHeaders.SC2Mod) succeeded.
+TestMpq (MPQ_2020_v4_NP_Protect_1.s2ma) succeeded.
+TestMpq (MPQ_2020_v4_NP_Protect_2.s2ma) succeeded.
+TestMpq (MPQ_2015_v1_flem1.w3x) succeeded.
+TestMpq (MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x) succeeded.
+TestMpq (MPQ_2021_v1_CantExtractCHK.scx) succeeded.
+TestMpq (MPQ_2022_v1_Sniper.scx) succeeded.
+TestMpq (MPQ_2022_v1_OcOc_Bound_2.scx) succeeded.
+PatchedMPQ (MPQ_1998_v1_StarCraft.mpq) succeeded.
+PatchedMPQ (MPQ_2012_v4_OldWorld.MPQ) succeeded.
+PatchedMPQ (MPQ_2013_v4_world.MPQ) succeeded.
+PatchedMPQ (MPQ_2013_v4_locale-enGB.MPQ) succeeded.
+PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded.
+PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded.
+PatchedMPQ (MPQ_2013_v4_Base3.SC2Maps) succeeded.
+PatchedMPQ (MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets) succeeded.
+PatchedMPQ (MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data) succeeded.
+PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded.
+PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
+VerifyFileHash succeeded.
VerifyFileHash succeeded.
VerifyFileHash succeeded.
VerifyFileHash succeeded.
@@ -90,78 +171,12 @@ VerifyFileHash succeeded.
VerifyFileHash succeeded.
VerifyFileHash succeeded.
VerifyFileHash succeeded.
-FileStreamTest (MPQ_2013_v4_alternate-original.MPQ) succeeded.
-FileStreamTest (MPQ_2013_v4_alternate-original.MPQ) succeeded.
-FileStreamTest (MPQ_2013_v4_alternate-complete.MPQ) succeeded.
-FileStreamTest (part-file://MPQ_2009_v2_WoW_patch.MPQ.part) succeeded.
-FileStreamTest (blk4-file://streaming/model.MPQ.0) succeeded.
-FileStreamTest (mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE) succeeded.
-OpenMirrorFile (part-file://MPQ_2009_v1_patch-created.MPQ.part) succeeded.
-OpenMirrorFile (part-file://MPQ_2009_v1_patch-partial.MPQ.part) succeeded.
-OpenMirrorFile (part-file://MPQ_2009_v1_patch-complete.MPQ.part) succeeded.
-OpenMirrorFile (MPQ_2013_v4_alternate-created.MPQ) succeeded.
-OpenMirrorFile (MPQ_2013_v4_alternate-incomplete.MPQ) succeeded.
-OpenMirrorFile (MPQ_2013_v4_alternate-complete.MPQ) succeeded.
-TestMpq (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded.
-TestMpq (MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq) succeeded.
-TestMpq (MPQ_2018_v1_icon_error.w3m) succeeded.
-TestMpq (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded.
-TestMpq (MPQ_2012_v2_EmptyMpq.MPQ) succeeded.
-TestMpq (MPQ_2013_v4_EmptyMpq.MPQ) succeeded.
-TestMpq (MPQ_2013_v4_patch-base-16357.MPQ) succeeded.
-TestMpq (MPQ_2011_v4_InvalidHetEntryCount.MPQ) succeeded.
-TestMpq (MPQ_2002_v1_BlockTableCut.MPQ) succeeded.
-TestMpq (MPQ_2010_v2_HasUserData.s2ma) succeeded.
-TestMpq (MPQ_2014_v1_AttributesOneEntryLess.w3x) succeeded.
-TestMpq (MPQ_2020_v1_AHF04patch.mix) succeeded.
-TestMpq (MPQ_2010_v3_expansion-locale-frFR.MPQ) succeeded.
-TestMpq (mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE) succeeded.
-TestMpq (MPx_2013_v1_LongwuOnline.mpk) succeeded.
-TestMpq (MPx_2013_v1_WarOfTheImmortals.sqp) succeeded.
-TestMpq (part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part) succeeded.
-TestMpq (blk4-file://streaming/model.MPQ.0) succeeded.
-TestMpq (MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x) succeeded.
-TestMpq (MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x) succeeded.
-TestMpq (MPQ_2002_v1_ProtectedMap_Spazzler.w3x) succeeded.
-TestMpq (MPQ_2014_v1_ProtectedMap_Spazzler2.w3x) succeeded.
-TestMpq (MPQ_2014_v1_ProtectedMap_Spazzler3.w3x) succeeded.
-TestMpq (MPQ_2002_v1_ProtectedMap_BOBA.w3m) succeeded.
-TestMpq (MPQ_2015_v1_ProtectedMap_KangTooJee.w3x) succeeded.
-TestMpq (MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x) succeeded.
-TestMpq (MPQ_2015_v1_ProtectedMap_Spazy.w3x) succeeded.
-TestMpq (MPQ_2015_v1_MessListFile.mpq) succeeded.
-TestMpq (MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x) succeeded.
-TestMpq (MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x) succeeded.
-TestMpq (MPQ_2016_v1_ProtectedMap_Somj2.w3x) succeeded.
-TestMpq (MPQ_2016_v1_WME4_4.w3x) succeeded.
-TestMpq (MPQ_2016_v1_SP_(4)Adrenaline.w3x) succeeded.
-TestMpq (MPQ_2016_v1_ProtectedMap_1.4.w3x) succeeded.
-TestMpq (MPQ_2016_v1_KoreanFile.w3m) succeeded.
-TestMpq (MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x) succeeded.
-TestMpq (MPQ_2017_v1_BigDummyFiles.w3x) succeeded.
-TestMpq (MPQ_2017_v1_TildeInFileName.mpq) succeeded.
-TestMpq (MPQ_2018_v1_EWIX_v8_7.w3x) succeeded.
-TestMpq (MPQ_2020_v4_FakeMpqHeaders.SC2Mod) succeeded.
-TestMpq (MPQ_2020_v4_NP_Protect_1.s2ma) succeeded.
-TestMpq (MPQ_2020_v4_NP_Protect_2.s2ma) succeeded.
-TestMpq (MPQ_2015_v1_flem1.w3x) succeeded.
-TestMpq (MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x) succeeded.
-TestMpq (MPQ_2021_v1_CantExtractCHK.scx) succeeded.
-PatchedMPQ (MPQ_1998_v1_StarCraft.mpq) succeeded.
-PatchedMPQ (MPQ_2012_v4_OldWorld.MPQ) succeeded.
-PatchedMPQ (MPQ_2013_v4_world.MPQ) succeeded.
-PatchedMPQ (MPQ_2013_v4_locale-enGB.MPQ) succeeded.
-PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded.
-PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded.
-PatchedMPQ (MPQ_2013_v4_Base3.SC2Maps) succeeded.
-PatchedMPQ (MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets) succeeded.
-PatchedMPQ (MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data) succeeded.
-PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded.
-PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded.
-FailMpqTest (flat-file://streaming/model.MPQ.0) succeeded.
OpenEachMpqTest ((10)DustwallowKeys.w3m) succeeded.
OpenEachMpqTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded.
OpenEachMpqTest (MPQ_1997_v1_Diablo1_single_0.sv) succeeded.
+OpenEachMpqTest (MPQ_1997_v1_patch_rt_SC1B.mpq) succeeded.
+OpenEachMpqTest (MPQ_1997_v1_StarDat.mpq) succeeded.
+OpenEachMpqTest (MPQ_1997_v1_StarDat_SC1B.mpq) succeeded.
OpenEachMpqTest (MPQ_1998_v1_StarCraft.mpq) succeeded.
OpenEachMpqTest (MPQ_1998_v1_StarDat.mpq) succeeded.
OpenEachMpqTest (MPQ_2002_v1_BlockTableCut.MPQ) succeeded.
@@ -230,6 +245,7 @@ OpenEachMpqTest (MPQ_2020_v4_NP_Protect_4.s2ma) succeeded.
OpenEachMpqTest (MPQ_2020_v4_ThreeFakeHeaders.s2ma) succeeded.
OpenEachMpqTest (MPQ_2021_v1_CrossLinkedFiles.w3x) succeeded.
OpenEachMpqTest (MPQ_2021_v4_BzipError.SC2Replay) succeeded.
+OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\1995 - Test MPQs\MPQ_2022_v1_MoeMoeMod.asi (error code: 11)
OpenEachMpqTest (hs-0-3604-Win-final.MPQ) succeeded.
OpenEachMpqTest (hs-0-5314-Win-final.MPQ) succeeded.
OpenEachMpqTest (hs-5314-5435-Win-final.MPQ) succeeded.
@@ -297,11 +313,15 @@ OpenEachMpqTest (imp.mpq) succeeded.
OpenEachMpqTest (pic.mpq) succeeded.
OpenEachMpqTest (sndfx.mpq) succeeded.
OpenEachMpqTest (special.mpq) succeeded.
+OpenEachMpqTest (patch_rt.mpq) succeeded.
+OpenEachMpqTest (StarDat.mpq) succeeded.
OpenEachMpqTest (BrooDat.mpq) succeeded.
OpenEachMpqTest (BroodWar.mpq) succeeded.
OpenEachMpqTest (Patch_rt.mpq) succeeded.
OpenEachMpqTest (StarCraft.mpq) succeeded.
OpenEachMpqTest (StarDat.mpq) succeeded.
+OpenEachMpqTest (StardatSW.mpq) succeeded.
+OpenEachMpqTest (StarDat_BETA.mpq) succeeded.
OpenEachMpqTest (War2Dat.mpq) succeeded.
OpenEachMpqTest (War2Patch.mpq) succeeded.
OpenEachMpqTest (d2char.mpq) succeeded.
@@ -2246,7 +2266,6 @@ OpenEachMpqTest (hs-6485-6898-Win-final.MPQ) succeeded.
OpenEachMpqTest (MPQ_1998_v1_StarDat.mpq) succeeded.
OpenEachMpqTest (MPQ_1999_v1_WeakSigned1.mpq) succeeded.
OpenEachMpqTest (MPQ_1999_v1_WeakSigned2.mpq) succeeded.
-OpenEachMpqTest (MPQ_2002_v1_StrongSignature.w3m) succeeded.
OpenEachMpqTest (MPQ_2009_v1_patch-complete.MPQ.part) succeeded.
OpenEachMpqTest (MPQ_2009_v1_patch-created.MPQ.part) succeeded.
OpenEachMpqTest (MPQ_2009_v1_patch-partial.MPQ.part) succeeded.
@@ -2254,7 +2273,6 @@ OpenEachMpqTest (MPQ_2009_v2_WoW_patch.MPQ.part) succeeded.
OpenEachMpqTest (MPQ_2011_v2_EncryptedMpq.MPQE) succeeded.
OpenEachMpqTest (MPQ_2013_v4_alternate-complete.MPQ) succeeded.
OpenEachMpqTest (MPQ_2013_v4_alternate-created.MPQ) succeeded.
-OpenEachMpqTest (MPQ_2013_v4_alternate-downloaded.MPQ) succeeded.
OpenEachMpqTest (MPQ_2013_v4_alternate-incomplete.MPQ) succeeded.
OpenEachMpqTest (MPQ_2013_v4_alternate-original.MPQ) succeeded.
OpenEachMpqTest (MPQ_2014_v1_out1.w3x) succeeded.
@@ -2279,11 +2297,8 @@ OpenEachMpqTest (StormLibTest_NoListFile.mpq) succeeded.
OpenEachMpqTest (StormLibTest_NonStdNames.mpq) succeeded.
OpenEachMpqTest (StormLibTest_ReadOnly.mpq) succeeded.
OpenEachMpqTest (StormLibTest_ReadWrite.mpq) succeeded.
-OpenEachMpqTest (TestArchiveCopy.mpq) succeeded.
-OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\Work\(1)TheDeathSheep.w3m (error code: 11)
-OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\Work\(10)DustwallowKeys#FFFF.w3m (error code: 11)
-OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\Work\(10)RagingStream.w3x (error code: 11)
-OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\Work\(2)BootyBay.w3m (error code: 11)
+OpenEachMpqTest (File00000003.mpq) succeeded.
+FailMpqTest (flat-file://streaming/model.MPQ.0) succeeded.
OpenCorruptMpqTest (MPQ_2013_vX_Battle.net.MPQ) succeeded.
ReadOnlyTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded.
ReadOnlyTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded.
@@ -2304,7 +2319,7 @@ ListFileTest (MPQ_2013_v4_SC2_EmptyMap.SC2Map) succeeded.
CreateEmptyMpq: The file "File00000000.xxx" is present, but it should not be
CreateEmptyMpq: The file "File00000000.xxx" is present, but it should not be
CreateGapsTest (StormLibTest_GapsTest.mpq) succeeded.
-NonStdNamesTest: Adding file " \ \ \ .txt" ... NonStdNamesTest: Adding file "Dir1 \Dir2 \File.txt ." ... NonStdNamesTest: Adding file "Dir1 \Dir2 \ . ." ... NonStdNamesTest (StormLibTest_NonStdNames.mpq) succeeded.
+NonStdNamesTest: Adding file " \ \ \ .txt" ... NonStdNamesTest: Adding file "Dir1 \Dir2 \File.txt ." ... NonStdNamesTest: Adding file "Dir1 \Dir2 \ . ." ... NonStdNamesTest (StormLibTest_NonStdNames.mpq) succeeded.
SignExistingMpq (MPQ_1998_v1_StarDat.mpq) succeeded.
ModifySignedTest (MPQ_1999_v1_WeakSignature.exe) succeeded.
CreateSignedMpq (MPQ_1999_v1_WeakSigned1.mpq) succeeded.
@@ -2324,4 +2339,4 @@ ListFilePos (StormLibTest_ListFilePos.mpq) succeeded.
BigMpqTest (StormLibTest_BigArchive_v4.mpq) succeeded.
ModifyTest (MPQ_2014_v4_Base.StormReplay) succeeded.
-E:\Ladik\Appdir\StormLib> \ No newline at end of file
+E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release> \ No newline at end of file