aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascRootFile_Mndx.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2019-06-09 21:14:42 +0200
committerShauren <shauren.trinity@gmail.com>2019-06-09 21:14:42 +0200
commit138e822d859fd9ff9d79e1ce16823992ad43aec4 (patch)
treef1e22a1afbaa3457e6169146f350c91b9493f926 /dep/CascLib/src/CascRootFile_Mndx.cpp
parentc4f11447546836844ade509991b4219c88ebaaa3 (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@03a3bcaed285ab0d8ff0845a65ffe7d1fa653960
Diffstat (limited to 'dep/CascLib/src/CascRootFile_Mndx.cpp')
-rw-r--r--dep/CascLib/src/CascRootFile_Mndx.cpp2981
1 files changed, 0 insertions, 2981 deletions
diff --git a/dep/CascLib/src/CascRootFile_Mndx.cpp b/dep/CascLib/src/CascRootFile_Mndx.cpp
deleted file mode 100644
index 9dca8d30eb4..00000000000
--- a/dep/CascLib/src/CascRootFile_Mndx.cpp
+++ /dev/null
@@ -1,2981 +0,0 @@
-/*****************************************************************************/
-/* CascRootFile_MNDX.cpp Copyright (c) Ladislav Zezula 2014 */
-/*---------------------------------------------------------------------------*/
-/* Common functions for CascLib */
-/* Note: "HOTS" refers to Play.exe, v2.5.0.29049 (Heroes of the Storm Alpha) */
-/*---------------------------------------------------------------------------*/
-/* Date Ver Who Comment */
-/* -------- ---- --- ------- */
-/* 18.05.14 1.00 Lad The first version of CascRootFile_MNDX.cpp */
-/*****************************************************************************/
-
-#define __CASCLIB_SELF__
-#include "CascLib.h"
-#include "CascCommon.h"
-
-//-----------------------------------------------------------------------------
-// Local defines
-
-#define MNDX_MAR_SIGNATURE 0x0052414d // 'MAR\0'
-#define MAR_PACKAGE_NAMES 0 // MAR with package names only
-#define MAR_STRIPPED_NAMES 1 // MAR with names where packages were stripped
-#define MAR_FULL_NAMES 2 // MAR with full file names
-#define MAR_COUNT 3 // Maximum of 3 MAR files are supported
-
-#define MNDX_SEARCH_INITIALIZING 0
-#define MNDX_SEARCH_SEARCHING 2
-#define MNDX_SEARCH_FINISHED 4
-
-#define MNDX_MAX_ENTRIES(type) (0xFFFFFFFF / sizeof(type))
-
-#define MNDX_INVALID_SIZE_T ((size_t)(-1))
-
-#define MNDX_LAST_CKEY_ENTRY 0x80000000
-
-//-----------------------------------------------------------------------------
-// Local structures
-
-typedef union _SETBITS
-{
- struct
- {
- DWORD Lower08 : 8; // Number of set bits in the lower 1 byte
- DWORD Lower16 : 8; // Number of set bits in the lower 2 bytes
- DWORD Lower24 : 8; // Number of set bits in the lower 3 bytes
- DWORD Lower32 : 8; // Number of set bits in the 32-bit integer
- } u;
-
- DWORD SetBitsAll; // The total set bits mask
-
-} SETBITS, *PSETBITS;
-
-typedef struct _HASH_ENTRY
-{
- DWORD NodeIndex; // Index of the path node
- DWORD NextIndex; // ID of the first subnode in the hash table
-
- union
- {
- DWORD FragmentOffset; // Offset of the path fragment in the TPathFragmentTable
- DWORD ChildTableIndex; // Starting search index for the child database (if child database is present)
- char SingleChar; // If the upper 24 bits of the FragmentOffset is 0xFFFFFFFF, this single character
- };
- // Otherwise --> Offset to the name fragment table
-} HASH_ENTRY, *PHASH_ENTRY;
-
-typedef struct _FILE_MNDX_HEADER
-{
- DWORD Signature; // 'MNDX'
- DWORD HeaderVersion; // Must be <= 2
- DWORD FormatVersion;
-
-} FILE_MNDX_HEADER, *PFILE_MNDX_HEADER;
-
-typedef struct _MNDX_PACKAGE
-{
- char * szFileName; // Pointer to file name
- size_t nLength; // Length of the file name
- size_t nIndex; // Package index
-
-} MNDX_PACKAGE, *PMNDX_PACKAGE;
-
-// Root file entry for CASC storages with MNDX root file (Heroes of the Storm)
-// Corresponds to the in-file structure
-typedef struct _MNDX_CKEY_ENTRY
-{
- DWORD Flags; // High 8 bits: Flags, low 24 bits: package index
- BYTE CKey[MD5_HASH_SIZE]; // Content key for the file
- DWORD ContentSize; // Uncompressed file size, in bytes
-
-} MNDX_CKEY_ENTRY, *PMNDX_CKEY_ENTRY;
-
-typedef struct _FILE_MAR_INFO
-{
- DWORD MarIndex;
- DWORD MarDataSize;
- DWORD MarDataSizeHi;
- DWORD MarDataOffset;
- DWORD MarDataOffsetHi;
-} FILE_MAR_INFO, *PFILE_MAR_INFO;
-
-//-----------------------------------------------------------------------------
-// Local variables
-
-unsigned char table_1BA1818[0x800] =
-{
- 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
- 0x07, 0x07, 0x07, 0x01, 0x07, 0x02, 0x02, 0x01, 0x07, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x05, 0x05, 0x01, 0x05, 0x02, 0x02, 0x01, 0x05, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x05, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x06, 0x06, 0x01, 0x06, 0x02, 0x02, 0x01, 0x06, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x06, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x06, 0x05, 0x05, 0x01, 0x05, 0x02, 0x02, 0x01, 0x05, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x05, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x07, 0x07, 0x01, 0x07, 0x02, 0x02, 0x01, 0x07, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x05, 0x05, 0x01, 0x05, 0x02, 0x02, 0x01, 0x05, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x05, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x06, 0x06, 0x01, 0x06, 0x02, 0x02, 0x01, 0x06, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x06, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x06, 0x05, 0x05, 0x01, 0x05, 0x02, 0x02, 0x01, 0x05, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x05, 0x04, 0x04, 0x01, 0x04, 0x02, 0x02, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x07, 0x07, 0x07, 0x03, 0x07, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x02, 0x07, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x02, 0x07, 0x05, 0x05, 0x03, 0x05, 0x03, 0x03, 0x02,
- 0x07, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x02, 0x05, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x02, 0x07, 0x06, 0x06, 0x03, 0x06, 0x03, 0x03, 0x02,
- 0x07, 0x06, 0x06, 0x04, 0x06, 0x04, 0x04, 0x02, 0x06, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x02, 0x06, 0x05, 0x05, 0x03, 0x05, 0x03, 0x03, 0x02,
- 0x06, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x02, 0x05, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x07, 0x07, 0x07, 0x03, 0x07, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x02, 0x07, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x02, 0x07, 0x05, 0x05, 0x03, 0x05, 0x03, 0x03, 0x02,
- 0x07, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x02, 0x05, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x02, 0x07, 0x06, 0x06, 0x03, 0x06, 0x03, 0x03, 0x02,
- 0x07, 0x06, 0x06, 0x04, 0x06, 0x04, 0x04, 0x02, 0x06, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x02, 0x06, 0x05, 0x05, 0x03, 0x05, 0x03, 0x03, 0x02,
- 0x06, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x02, 0x05, 0x04, 0x04, 0x03, 0x04, 0x03, 0x03, 0x02,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04, 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x03,
- 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x04, 0x07, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x03,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x04, 0x07, 0x06, 0x06, 0x04, 0x06, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x03,
- 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x04, 0x06, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04, 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x03,
- 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x04, 0x07, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x03,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x04, 0x07, 0x06, 0x06, 0x04, 0x06, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x03,
- 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x04, 0x06, 0x05, 0x05, 0x04, 0x05, 0x04, 0x04, 0x03,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07, 0x07, 0x05, 0x07, 0x05, 0x05, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05,
- 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x06, 0x06, 0x05, 0x06, 0x05, 0x05, 0x04,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
-};
-
-//-----------------------------------------------------------------------------
-// Local functions - Number of set bits in an integer
-
-// HOTS: inlined
-static SETBITS GetNumberOfSetBits(DWORD Value32)
-{
- SETBITS SetBits;
-
- Value32 = ((Value32 >> 1) & 0x55555555) + (Value32 & 0x55555555);
- Value32 = ((Value32 >> 2) & 0x33333333) + (Value32 & 0x33333333);
- Value32 = ((Value32 >> 4) & 0x0F0F0F0F) + (Value32 & 0x0F0F0F0F);
- SetBits.SetBitsAll = Value32 * 0x01010101;
-
- return SetBits;
-}
-
-static DWORD GetNumberOfSetBits32(DWORD Value32)
-{
- return GetNumberOfSetBits(Value32).u.Lower32;
-}
-
-static LPBYTE CaptureData(LPBYTE pbRootPtr, LPBYTE pbRootEnd, void * pvBuffer, size_t cbLength)
-{
- // Check whether there is enough data in the buffer
- if((pbRootPtr + cbLength) > pbRootEnd)
- return NULL;
-
- // Copy the data
- memcpy(pvBuffer, pbRootPtr, cbLength);
- return pbRootPtr + cbLength;
-}
-
-//-----------------------------------------------------------------------------
-// The TPathStop structure
-
-struct TPathStop
-{
- TPathStop()
- {
- LoBitsIndex = 0;
- field_4 = 0;
- Count = 0;
- HiBitsIndex_PathFragment = CASC_INVALID_INDEX;
- field_10 = 0xFFFFFFFF;
- }
-
- TPathStop(DWORD arg_0, DWORD arg_4, DWORD arg_8)
- {
- LoBitsIndex = arg_0;
- field_4 = arg_4;
- Count = arg_8;
- HiBitsIndex_PathFragment = CASC_INVALID_INDEX;
- field_10 = 0xFFFFFFFF;
- }
-
- DWORD LoBitsIndex;
- DWORD field_4;
- DWORD Count;
- DWORD HiBitsIndex_PathFragment;
- DWORD field_10;
-};
-
-//-----------------------------------------------------------------------------
-// Basic array implementations
-
-class TByteStream
-{
- public:
-
- // HOTS: 01959990
- TByteStream()
- {
- pbByteData = NULL;
- pvMappedFile = NULL;
- cbByteData = 0;
- field_C = 0;
- hFile = 0;
- hMap = 0;
- }
-
- // HOTS: 19599F0
- template <typename T>
- int GetBytes(size_t length, T ** Pointer)
- {
- // Is there enough bytes in the array?
- if(length > cbByteData)
- return ERROR_BAD_FORMAT;
-
- // Give the buffer to the caller
- Pointer[0] = (T *)(pbByteData);
-
- // Move pointers
- pbByteData += length;
- cbByteData -= length;
- return ERROR_SUCCESS;
- }
-
- int CopyBytes(void * value, size_t length)
- {
- // Is there enough bytes in the array?
- if(length > cbByteData)
- return ERROR_BAD_FORMAT;
-
- // Give the buffer to the caller
- memcpy(value, pbByteData, length);
-
- // Move pointers
- pbByteData += length;
- cbByteData -= length;
- return ERROR_SUCCESS;
- }
-
- // HOTS: 1959A60
- int SkipBytes(size_t cbByteCount)
- {
- LPBYTE Pointer;
-
- return GetBytes<BYTE>(cbByteCount, &Pointer);
- }
-
- // HOTS: 1959AF0
- int SetByteBuffer(LPBYTE pbNewByteData, size_t cbNewByteData)
- {
- if(pbNewByteData != NULL || cbNewByteData == 0)
- {
- pbByteData = pbNewByteData;
- cbByteData = cbNewByteData;
- return ERROR_SUCCESS;
- }
-
- return ERROR_INVALID_PARAMETER;
- }
-
- // HOTS: 1957160 <DWORD>
- template <typename T>
- int GetValue(T & Value)
- {
- T * Pointer;
- int nError;
-
- nError = GetBytes(sizeof(T), (LPBYTE *)(&Pointer));
- if(nError != ERROR_SUCCESS)
- return nError;
-
- Value = Pointer[0];
- return ERROR_SUCCESS;
- }
-
- // Retrieves the item count in the array
- template <typename T>
- int GetArrayItemCount(DWORD & ArraySize, DWORD & ItemCount)
- {
- ULONGLONG ByteCount;
- int nError;
-
- // The first 8 bytes is the byte size of the array
- nError = GetValue<ULONGLONG>(ByteCount);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // Extract the number of bytes
- if(ByteCount > 0xFFFFFFFF || (ByteCount % sizeof(T)) != 0)
- return ERROR_BAD_FORMAT;
-
- // Give the result to the caller
- ItemCount = (DWORD)(ByteCount / sizeof(T));
- ArraySize = (DWORD)(ByteCount);
- return ERROR_SUCCESS;
- }
-
- // HOTS: 1957190: <DWORD>
- // HOTS: 19571E0: <BASEVALS>
- // HOTS: 1957230: <BYTE>
- // HOTS: 1957280: <HASH_ENTRY>
- template <typename T>
- int GetArray(T ** Pointer, size_t ItemCount)
- {
- int nError = ERROR_SUCCESS;
-
- // Verify parameters
- if(Pointer == NULL && ItemCount != 0)
- return ERROR_INVALID_PARAMETER;
- if(ItemCount > MNDX_MAX_ENTRIES(T))
- return ERROR_NOT_ENOUGH_MEMORY;
-
- // Allocate bytes for the array
- if (Pointer != NULL)
- {
- Pointer[0] = CASC_ALLOC(T, ItemCount);
- if (Pointer[0] == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- // Get the pointer to the array
- nError = CopyBytes(Pointer[0], sizeof(T) * ItemCount);
- }
-
- return nError;
- }
-
- LPBYTE pbByteData;
- void * pvMappedFile;
- size_t cbByteData;
- DWORD field_C;
- HANDLE hFile;
- HANDLE hMap;
-};
-
-//-----------------------------------------------------------------------------
-// TGenericArray interface/implementation
-
-template <typename T>
-class TGenericArray
-{
- public:
-
- TGenericArray()
- {
- ItemArray = NULL;
- ItemCount = 0;
- MaxItemCount = 0;
- bIsValidArray = false;
- }
-
- ~TGenericArray()
- {
- CASC_FREE(ItemArray);
- }
-
- T & operator[] (size_t index)
- {
- assert(index < ItemCount);
- return ItemArray[index];
- }
-
- // HOTS: 1957090 (SetDwordsValid)
- // HOTS: 19570B0 (SetBaseValsValid)
- // HOTS: 19570D0 (? SetBitsValid ?)
- // HOTS: 19570F0 (SetPathFragmentsValid)
- int SetArrayValid()
- {
- if(bIsValidArray != 0)
- return ERROR_ALREADY_EXISTS;
-
- bIsValidArray = true;
- return ERROR_SUCCESS;
- }
-
- // HOTS: 19575A0 (char)
- // HOTS: 1957600 (TPathStop)
- void SetMaxItems(DWORD NewMaxItemCount)
- {
- T * OldArray = ItemArray;
- T * NewArray;
-
- // Allocate new data buffer
- NewArray = CASC_ALLOC(T, NewMaxItemCount);
- if(NewArray != NULL)
- {
- // Copy the old items to the buffer
- for(size_t i = 0; i < ItemCount; i++)
- {
- NewArray[i] = ItemArray[i];
- }
- }
-
- ItemArray = NewArray;
- MaxItemCount = NewMaxItemCount;
- CASC_FREE(OldArray);
- }
-
- // HOTS: 19575A0 (char)
- // HOTS: 1957600 (TPathStop)
- void SetMaxItemsIf(DWORD NewMaxItemCount)
- {
- if(NewMaxItemCount > MaxItemCount)
- {
- if(MaxItemCount > (NewMaxItemCount / 2))
- {
- if(MaxItemCount <= (MNDX_MAX_ENTRIES(T) / 2))
- NewMaxItemCount = MaxItemCount + MaxItemCount;
- else
- NewMaxItemCount = MNDX_MAX_ENTRIES(T);
- }
-
- SetMaxItems(NewMaxItemCount);
- }
- }
-
- // HOTS: inline <char>
- // HOTS: 1958330 <TPathStop>
- void Insert(T NewItem)
- {
- // Make sure we have enough capacity for the new item
- SetMaxItemsIf(ItemCount + 1);
-
- // Put the character to the slot that has been reserved
- ItemArray[ItemCount++] = NewItem;
- }
-
- // HOTS: 19583A0 <TPathStop>
- void GrowArray(DWORD NewItemCount)
- {
- DWORD OldMaxItemCount = MaxItemCount;
-
- // Make sure we have enough capacity for new items
- SetMaxItemsIf(NewItemCount);
-
- // Initialize the newly inserted items
- for(DWORD i = OldMaxItemCount; i < NewItemCount; i++)
- {
- ItemArray[i] = T();
- }
-
- ItemCount = NewItemCount;
- }
-
- // HOTS: 1957440 <DWORD>
- // HOTS: 19574E0 <BASEVALS>
- // HOTS: 1957690 <BYTE>
- // HOTS: 1957700 <HASH_ENTRY>
- // HOTS: 195A220 <char>
- // HOTS: 1958580 <TBitStream, DWORD>
- int LoadFromStream(TByteStream & InStream)
- {
- DWORD NumberOfBytes;
- int nError;
-
- // Get and verify the number of items
- nError = InStream.GetArrayItemCount<T>(NumberOfBytes, ItemCount);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // Get the pointer to the array
- nError = InStream.GetArray<T>(&ItemArray, ItemCount);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = InStream.SkipBytes((0 - (DWORD)NumberOfBytes) & 0x07);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- return SetArrayValid();
- }
-
- T * ItemArray;
- DWORD ItemCount; // Number of items in the array
- DWORD MaxItemCount; // Capacity of the array
- bool bIsValidArray;
-};
-
-class TBitEntryArray : public TGenericArray<DWORD>
-{
- public:
-
- TBitEntryArray() : TGenericArray()
- {
- BitsPerEntry = 0;
- EntryBitMask = 0;
- TotalEntries = 0;
- }
-
- ~TBitEntryArray()
- {}
-
- DWORD GetItem(DWORD EntryIndex)
- {
- DWORD dwItemIndex = (EntryIndex * BitsPerEntry) >> 0x05;
- DWORD dwStartBit = (EntryIndex * BitsPerEntry) & 0x1F;
- DWORD dwEndBit = dwStartBit + BitsPerEntry;
- DWORD dwResult;
-
- // If the end bit index is greater than 32,
- // we also need to load from the next 32-bit item
- if(dwEndBit > 0x20)
- {
- dwResult = (ItemArray[dwItemIndex + 1] << (0x20 - dwStartBit)) | (ItemArray[dwItemIndex] >> dwStartBit);
- }
- else
- {
- dwResult = ItemArray[dwItemIndex] >> dwStartBit;
- }
-
- // Now we also need to mask the result by the bit mask
- return dwResult & EntryBitMask;
- }
-
- int LoadBitsFromStream(TByteStream & InStream)
- {
- ULONGLONG Value64 = 0;
- int nError;
-
- nError = LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = InStream.GetValue<DWORD>(BitsPerEntry);
- if(nError != ERROR_SUCCESS)
- return nError;
- if(BitsPerEntry > 0x20)
- return ERROR_BAD_FORMAT;
-
- nError = InStream.GetValue<DWORD>(EntryBitMask);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = InStream.GetValue<ULONGLONG>(Value64);
- if(nError != ERROR_SUCCESS)
- return nError;
- if(Value64 > 0xFFFFFFFF)
- return ERROR_BAD_FORMAT;
- TotalEntries = (DWORD)Value64;
-
- assert((BitsPerEntry * TotalEntries) / 32 <= ItemCount);
- return ERROR_SUCCESS;
- }
-
- DWORD BitsPerEntry;
- DWORD EntryBitMask;
- DWORD TotalEntries;
-};
-
-//-----------------------------------------------------------------------------
-// TSparseArray functions
-
-#define INDEX_TO_GROUP(val) (val >> 9)
-#define GROUP_TO_INDEX(grp) (grp << 9)
-
-// For each 0x200-th bit, this contains information about amount of "1" bits
-typedef struct _BASEVALS
-{
- DWORD BaseValue200; // Item value of every 0x200-th item
-
- DWORD AddValue40 : 7; // For each 0x40 items (above the base200),
- DWORD AddValue80 : 8; // we have extra shortcut to the item value
- DWORD AddValueC0 : 8; // that is to be added to BaseValue200
- DWORD AddValue100 : 9;
- DWORD AddValue140 : 9;
- DWORD AddValue180 : 9;
- DWORD AddValue1C0 : 9;
-
- DWORD __xalignment : 5; // Filling
-} BASEVALS, *PBASEVALS;
-
-class TSparseArray
-{
- public:
-
- TSparseArray()
- {
- TotalItemCount = 0;
- ValidItemCount = 0;
- }
-
- // HOTS: 1958630
- int LoadFromStream(TByteStream & InStream)
- {
- DWORD total_count = 0;
- DWORD valid_count = 0;
- int nError;
-
- nError = ItemBits.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = InStream.GetValue<DWORD>(total_count);
- if(nError != ERROR_SUCCESS)
- return nError;
- nError = InStream.GetValue<DWORD>(valid_count);
- if(nError != ERROR_SUCCESS)
- return nError;
- if(valid_count > total_count)
- return ERROR_FILE_CORRUPT;
-
- TotalItemCount = total_count;
- ValidItemCount = valid_count;
-
- nError = BaseVals.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = IndexToItem0.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = IndexToItem1.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- return ERROR_SUCCESS;
- }
-
- // Returns true if the array is empty
- bool IsEmpty()
- {
- return (TotalItemCount == 0);
- }
-
- // Returns true if the item at n-th position is present
- bool IsItemPresent(size_t index)
- {
- // (index >> 0x05) gives the DWORD, (1 << (ItemIndex & 0x1F)) gives the bit
- return (ItemBits[index >> 0x05] & (1 << (index & 0x1F))) ? true : false;
- }
-
- // Retrieves the value of the n-th item in the sparse array.
- // Note that for items that are not present, the value is equal
- // to the nearest lower present value
- DWORD GetItemValueAt(size_t index)
- {
- BASEVALS & SetBitsCount = BaseVals[index >> 0x09];
- DWORD IntValue;
- DWORD BitMask;
-
- //
- // Since we don't want to count bits for the entire array,
- // there are item value shortcuts every 0x200 items,
- // and then every 0x40 items above the 0x200 base
- //
-
- // 1) We have base value for every 0x200-th item
- IntValue = SetBitsCount.BaseValue200;
-
- // 2) Add the base value for each 0x40-th item above the 0x200 base
- switch(((index >> 0x06) & 0x07) - 1)
- {
- case 0: // Add the 1st value (7 bits)
- IntValue += SetBitsCount.AddValue40;
- break;
-
- case 1: // Add the 2nd value (8 bits)
- IntValue += SetBitsCount.AddValue80;
- break;
-
- case 2: // Add the 3rd value (8 bits)
- IntValue += SetBitsCount.AddValueC0;
- break;
-
- case 3: // Add the 4th value (9 bits)
- IntValue += SetBitsCount.AddValue100;
- break;
-
- case 4: // Add the 5th value (9 bits)
- IntValue += SetBitsCount.AddValue140;
- break;
-
- case 5: // Add the 6th value (9 bits)
- IntValue += SetBitsCount.AddValue180;
- break;
-
- case 6: // Add the 7th value (9 bits)
- IntValue += SetBitsCount.AddValue1C0;
- break;
- }
-
- // 3) Count the bits of the higher DWORD, if the index 0x20 - 0x30 above the 0x200 base
- if(index & 0x20)
- IntValue += GetNumberOfSetBits32(ItemBits[(index >> 0x05) - 1]);
-
- // 4) Count the bits in the current DWORD (masked by bit index mask)
- BitMask = (1 << (index & 0x1F)) - 1;
- return IntValue + GetNumberOfSetBits32(ItemBits[index >> 0x05] & BitMask);
- }
-
- DWORD FindGroup_Items0(DWORD index)
- {
- // Setup the group range to search
- DWORD minGroup = (IndexToItem0[INDEX_TO_GROUP(index) + 0]) >> 9;
- DWORD maxGroup = (IndexToItem0[INDEX_TO_GROUP(index) + 1] + 0x1FF) >> 9;
-
- // Search the groups and find the BASEVALS structure
- // For spans less than 10 groups, use sequential search, otherwise binary search.
- if ((maxGroup - minGroup) < 10)
- {
- // HOTS: 1959CF7
- while (index >= GROUP_TO_INDEX(minGroup) - BaseVals[minGroup + 1].BaseValue200 + 0x200)
- {
- // HOTS: 1959D14
- minGroup++;
- }
- }
- else
- {
- // HOTS: 1959D2E
- while ((minGroup + 1) < maxGroup)
- {
- // HOTS: 1959D38
- DWORD middleValue = (maxGroup + minGroup) >> 1;
-
- if (index < (maxGroup << 0x09) - BaseVals[maxGroup].BaseValue200)
- {
- // HOTS: 01959D4B
- maxGroup = middleValue;
- }
- else
- {
- // HOTS: 1959D50
- minGroup = middleValue;
- }
- }
- }
-
- return minGroup;
- }
-
- DWORD FindGroup_Items1(DWORD index)
- {
- DWORD groupIndex = (index >> 0x09);
- DWORD startValue = IndexToItem1[groupIndex] >> 9;
- DWORD nextValue = (IndexToItem1[groupIndex + 1] + 0x1FF) >> 9;
-
- // Find the BASEVALS structure which the start index belongs to
- // For less than 10 values, use sequential search. Otherwise, use binary search
- if ((nextValue - startValue) < 10)
- {
- // HOTS: 01959F94
- while (index >= BaseVals[startValue + 1].BaseValue200)
- {
- // HOTS: 1959FA3
- startValue++;
- }
- }
- else
- {
- // Binary search (HOTS: 1959FAD)
- if ((startValue + 1) < nextValue)
- {
- // HOTS: 1959FB4
- DWORD middleValue = (nextValue + startValue) >> 1;
-
- if (index < BaseVals[middleValue].BaseValue200)
- {
- // HOTS: 1959FC4
- nextValue = middleValue;
- }
- else
- {
- // HOTS: 1959FC8
- startValue = middleValue;
- }
- }
- }
-
- return startValue;
- }
-
- // Returns the value of Item0[index] (HOTS: 1959CB0)
- DWORD GetItem0(DWORD index)
- {
- SETBITS zeroBits;
- DWORD groupIndex;
- DWORD dwordIndex;
- DWORD itemIndex;
- DWORD bitGroup;
- DWORD edx = index;
-
-#ifdef _DEBUG
- //if (TotalItemCount > 0x200)
- //{
- // FILE * fp = fopen("e:\\Ladik\\Appdir\\CascLib\\doc\\mndx-sparse-array.txt", "wt");
- // Dump(fp);
- // fclose(fp);
- //}
-#endif
-
- // If the index is at begin of the group, we just return the start value
- if ((index & 0x1FF) == 0)
- return IndexToItem0[INDEX_TO_GROUP(index)];
-
- // Find the group where the index belongs to
- groupIndex = FindGroup_Items0(index);
-
- // HOTS: 1959D5F
- edx += BaseVals[groupIndex].BaseValue200 - (groupIndex << 0x09);
- dwordIndex = (groupIndex << 4);
-
- if (edx < 0x100 - BaseVals[groupIndex].AddValue100)
- {
- // HOTS: 1959D8C
- if (edx < 0x80 - BaseVals[groupIndex].AddValue80)
- {
- // HOTS: 01959DA2
- if (edx >= 0x40 - BaseVals[groupIndex].AddValue40)
- {
- // HOTS: 01959DB7
- dwordIndex += 2;
- edx = edx + BaseVals[groupIndex].AddValue40 - 0x40;
- }
- }
- else
- {
- // HOTS: 1959DC0
- if (edx < 0xC0 - BaseVals[groupIndex].AddValueC0)
- {
- // HOTS: 1959DD3
- dwordIndex += 4;
- edx = edx + BaseVals[groupIndex].AddValue80 - 0x80;
- }
- else
- {
- // HOTS: 1959DD3
- dwordIndex += 6;
- edx = edx + BaseVals[groupIndex].AddValueC0 - 0xC0;
- }
- }
- }
- else
- {
- // HOTS: 1959DE8
- if (edx < 0x180 - BaseVals[groupIndex].AddValue180)
- {
- // HOTS: 01959E00
- if (edx < 0x140 - BaseVals[groupIndex].AddValue140)
- {
- // HOTS: 1959E11
- dwordIndex += 8;
- edx = edx + BaseVals[groupIndex].AddValue100 - 0x100;
- }
- else
- {
- // HOTS: 1959E1D
- dwordIndex += 10;
- edx = edx + BaseVals[groupIndex].AddValue140 - 0x140;
- }
- }
- else
- {
- // HOTS: 1959E29
- if (edx < 0x1C0 - BaseVals[groupIndex].AddValue1C0)
- {
- // HOTS: 1959E3D
- dwordIndex += 12;
- edx = edx + BaseVals[groupIndex].AddValue180 - 0x180;
- }
- else
- {
- // HOTS: 1959E49
- dwordIndex += 14;
- edx = edx + BaseVals[groupIndex].AddValue1C0 - 0x1C0;
- }
- }
- }
-
- // HOTS: 1959E53:
- // Calculate the number of bits set in the value of "bitGroup"
- bitGroup = ~ItemBits[dwordIndex];
- zeroBits = GetNumberOfSetBits(bitGroup);
-
- if (edx >= zeroBits.u.Lower32)
- {
- // HOTS: 1959ea4
- bitGroup = ~ItemBits[++dwordIndex];
- edx = edx - zeroBits.u.Lower32;
- zeroBits = GetNumberOfSetBits(bitGroup);
- }
-
- // Re-calculate the item index
- itemIndex = (dwordIndex << 0x05);
-
- // HOTS: 1959eea
- if (edx < zeroBits.u.Lower16)
- {
- // HOTS: 1959EFC
- if (edx >= zeroBits.u.Lower08)
- {
- // HOTS: 1959F05
- bitGroup >>= 0x08;
- itemIndex += 0x08;
- edx -= zeroBits.u.Lower08;
- }
- }
- else
- {
- // HOTS: 1959F0D
- if (edx < zeroBits.u.Lower24)
- {
- // HOTS: 1959F19
- bitGroup >>= 0x10;
- itemIndex += 0x10;
- edx -= zeroBits.u.Lower16;
- }
- else
- {
- // HOTS: 1959F23
- bitGroup >>= 0x18;
- itemIndex += 0x18;
- edx -= zeroBits.u.Lower24;
- }
- }
-
- // HOTS: 1959f2b
- edx = edx << 0x08;
- bitGroup = bitGroup & 0xFF;
-
- // BUGBUG: Possible buffer overflow here. Happens when dwItemIndex >= 0x9C.
- // The same happens in Heroes of the Storm (build 29049), so I am not sure
- // if this is a bug or a case that never happens
- assert((bitGroup + edx) < sizeof(table_1BA1818));
- return table_1BA1818[bitGroup + edx] + itemIndex;
- }
-
- DWORD GetItem1(DWORD index)
- {
- SETBITS setBits;
- DWORD distFromBase;
- DWORD groupIndex;
- DWORD dwordIndex;
- DWORD itemIndex;
- DWORD bitGroup;
-
- // If the index is at begin of the group, we just return the start value
- if ((index & 0x1FF) == 0)
- return IndexToItem1[INDEX_TO_GROUP(index)];
-
- // Find the group where the index belongs to
- groupIndex = FindGroup_Items1(index);
-
- // Calculate the base200 dword index (HOTS: 1959FD4)
- distFromBase = index - BaseVals[groupIndex].BaseValue200;
- dwordIndex = groupIndex << 0x04;
-
- // Calculate the dword index including the sub-checkpoint
- if (distFromBase < BaseVals[groupIndex].AddValue100)
- {
- // HOTS: 1959FF1
- if (distFromBase < BaseVals[groupIndex].AddValue80)
- {
- // HOTS: 0195A000
- if (distFromBase >= BaseVals[groupIndex].AddValue40)
- {
- // HOTS: 195A007
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue40;
- dwordIndex += 2;
- }
- }
- else
- {
- // HOTS: 195A00E
- if (distFromBase < BaseVals[groupIndex].AddValueC0)
- {
- // HOTS: 195A01A
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue80;
- dwordIndex += 4;
- }
- else
- {
- // HOTS: 195A01F
- distFromBase = distFromBase - BaseVals[groupIndex].AddValueC0;
- dwordIndex += 6;
- }
- }
- }
- else
- {
- // HOTS: 195A026
- if (distFromBase < BaseVals[groupIndex].AddValue180)
- {
- // HOTS: 195A037
- if (distFromBase < BaseVals[groupIndex].AddValue140)
- {
- // HOTS: 195A041
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue100;
- dwordIndex += 8;
- }
- else
- {
- // HOTS: 195A048
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue140;
- dwordIndex += 10;
- }
- }
- else
- {
- // HOTS: 195A04D
- if (distFromBase < BaseVals[groupIndex].AddValue1C0)
- {
- // HOTS: 195A05A
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue180;
- dwordIndex += 12;
- }
- else
- {
- // HOTS: 195A061
- distFromBase = distFromBase - BaseVals[groupIndex].AddValue1C0;
- dwordIndex += 14;
- }
- }
- }
-
- // HOTS: 195A066
- bitGroup = ItemBits[dwordIndex];
- setBits = GetNumberOfSetBits(bitGroup);
-
- // Get total number of set bits in the bit group
- if (distFromBase >= setBits.u.Lower32)
- {
- // HOTS: 195A0B2
- bitGroup = ItemBits[++dwordIndex];
- distFromBase = distFromBase - setBits.u.Lower32;
- setBits = GetNumberOfSetBits(bitGroup);
- }
-
- // Calculate the item index
- itemIndex = (dwordIndex << 0x05);
-
- // Get the number of set bits in the lower word (HOTS: 195A0F6)
- if (distFromBase < setBits.u.Lower16)
- {
- // HOTS: 195A111
- if (distFromBase >= setBits.u.Lower08)
- {
- // HOTS: 195A111
- itemIndex = itemIndex + 0x08;
- bitGroup = bitGroup >> 0x08;
- distFromBase = distFromBase - setBits.u.Lower08;
- }
- }
- else
- {
- // HOTS: 195A119
- if (distFromBase < setBits.u.Lower24)
- {
- // HOTS: 195A125
- bitGroup = bitGroup >> 0x10;
- itemIndex = itemIndex + 0x10;
- distFromBase = distFromBase - setBits.u.Lower16;
- }
- else
- {
- // HOTS: 195A12F
- bitGroup = bitGroup >> 0x18;
- itemIndex = itemIndex + 0x18;
- distFromBase = distFromBase - setBits.u.Lower24;
- }
- }
-
- bitGroup = bitGroup & 0xFF;
- distFromBase = distFromBase << 0x08;
-
- // BUGBUG: Potential buffer overflow
- // Happens in Heroes of the Storm when index == 0x5B
- assert((bitGroup + distFromBase) < sizeof(table_1BA1818));
- return table_1BA1818[bitGroup + distFromBase] + itemIndex;
- }
-
-#ifdef _DEBUG
- void Dump(FILE * fp)
- {
- size_t * ArrayNormal;
- size_t * ArrayInvert;
- size_t IndexNormal = 0;
- size_t IndexInvert = 0;
-
- // Output numbers of set bits for every 0x200-th item
- fprintf(fp, "Number of set bits for every 0x200-th index\n"
- "========================================================\n"
- " Index Base200h +40 +80 +C0 +100 +140 +180 +1C0\n"
- "--------------------------------------------------------\n");
- for (size_t i = 0; i < BaseVals.ItemCount; i++)
- {
- fprintf(fp, "[%08zX]: %08x %04x %04x %04x %04x %04x %04x %04x\n", GROUP_TO_INDEX(i), BaseVals[i].BaseValue200,
- BaseVals[i].AddValue40,
- BaseVals[i].AddValue80,
- BaseVals[i].AddValueC0,
- BaseVals[i].AddValue100,
- BaseVals[i].AddValue140,
- BaseVals[i].AddValue180,
- BaseVals[i].AddValue1C0);
- }
- fprintf(fp, "\n");
-
- // Output values of Item1 and Item0 for every 0x200-th index
- fprintf(fp, "Item0 and Item1 for every 0x200-th index\n"
- "========================================\n"
- " Index Item0 Item1\n"
- "-----------------------------\n");
- for (size_t i = 0; i < IndexToItem0.ItemCount; i++)
- {
- fprintf(fp, "[%08zX]: %08x %08x\n", GROUP_TO_INDEX(i), IndexToItem0[i], IndexToItem1[i]);
- }
- fprintf(fp, "\n");
-
-
- // Output values of Item1 and Item0 for every index
- ArrayNormal = new size_t[TotalItemCount];
- ArrayInvert = new size_t[TotalItemCount];
- if (ArrayNormal && ArrayInvert)
- {
- // Invalidate both arrays
- memset(ArrayNormal, 0xFF, TotalItemCount * sizeof(size_t));
- memset(ArrayInvert, 0xFF, TotalItemCount * sizeof(size_t));
-
- // Load the both arrays
- for (size_t i = 0; i < TotalItemCount; i++)
- {
- if (IsItemPresent(i))
- ArrayNormal[IndexNormal++] = i;
- else
- ArrayInvert[IndexInvert++] = i;
- }
-
- // Output both arrays
- fprintf(fp, "Item0 and Item1 for every index\n"
- "========================================\n"
- " Index Item0 Item1\n"
- "-----------------------------\n");
- for (size_t i = 0; i < TotalItemCount; i++)
- {
- char NormalValue[0x20];
- char InvertValue[0x20];
-
- if (ArrayNormal[i] == MNDX_INVALID_SIZE_T && ArrayInvert[i] == MNDX_INVALID_SIZE_T)
- break;
- fprintf(fp, "[%08zX]: %8s %8s\n", i, DumpValue(InvertValue, _countof(InvertValue), ArrayInvert[i]), DumpValue(NormalValue, _countof(NormalValue), ArrayNormal[i]));
- }
- fprintf(fp, "\n");
- }
-
- // Free both arrays
- delete[] ArrayNormal;
- delete[] ArrayInvert;
-
- // Output array of all values
- fprintf(fp, "Item List: Index -> Value\n==========================\n");
- for (size_t i = 0; i < TotalItemCount; i++)
- {
- if (IsItemPresent(i))
- {
- fprintf(fp, "[%08zX]: %08x\n", i, GetItemValueAt(i));
- }
- else
- {
- fprintf(fp, "[%08zX]: NOT PRESENT\n", i);
- }
- }
- fprintf(fp, "\n");
- }
-
- char * DumpValue(char * szBuffer, size_t cchBuffer, size_t value)
- {
- CascStrPrintf(szBuffer, cchBuffer, (value != MNDX_INVALID_SIZE_T) ? "%08zX" : " - ", value);
- return szBuffer;
- }
-#endif
-
- TGenericArray<DWORD> ItemBits; // A bit array for each item. 1 if the item is present.
- size_t TotalItemCount; // Total number of items in the array
- size_t ValidItemCount; // Number of present items in the array
- TGenericArray<BASEVALS> BaseVals; // For each 0x200-th item, this contains the number of set bits up to that 0x200-th item
- TGenericArray<DWORD> IndexToItem0; // Mapping of index to invert item. An "invert" item is an item whose bit in "ItemBits" is zero.
- TGenericArray<DWORD> IndexToItem1; // Mapping of index to normal item. An "normal" item is an item whose bit in "ItemBits" is set.
-};
-
-//-----------------------------------------------------------------------------
-// TStruct40 functions
-
-class TStruct40
-{
- public:
-
- TStruct40()
- {
- NodeIndex = 0;
- ItemCount = 0;
- PathLength = 0;
- SearchPhase = MNDX_SEARCH_INITIALIZING;
- }
-
- // HOTS: 19586B0
- void BeginSearch()
- {
- // HOTS: 19586BD
- PathBuffer.ItemCount = 0;
- PathBuffer.SetMaxItemsIf(0x40);
-
- // HOTS: 19586E1
- // Set the new item count
- PathStops.GrowArray(0);
- PathStops.SetMaxItemsIf(4);
-
- PathLength = 0;
- NodeIndex = 0;
- ItemCount = 0;
- SearchPhase = MNDX_SEARCH_SEARCHING;
- }
-
- DWORD CalcHashValue(const char * szPath)
- {
- return (BYTE)(szPath[PathLength]) ^ (NodeIndex << 0x05) ^ NodeIndex;
- }
-
- TGenericArray<TPathStop> PathStops; // Array of path checkpoints
- TGenericArray<char> PathBuffer; // Buffer for building a file name
- DWORD NodeIndex; // ID of a path node being searched; starting with 0
- DWORD PathLength; // Length of the path in the PathBuffer
- DWORD ItemCount;
- DWORD SearchPhase; // 0 = initializing, 2 = searching, 4 = finished
-};
-
-//-----------------------------------------------------------------------------
-// Local functions - TMndxSearch
-
-class TMndxSearch
-{
- public:
-
- // HOTS: 01956EE0
- TMndxSearch()
- {
- szSearchMask = NULL;
- cchSearchMask = 0;
- szFoundPath = NULL;
- cchFoundPath = 0;
- nIndex = 0;
- }
-
- // HOTS: 01956F00
- ~TMndxSearch()
- {}
-
- // HOTS: 01956E70
- int SetSearchMask(
- const char * szNewSearchMask,
- size_t cchNewSearchMask)
- {
- if(szSearchMask == NULL && cchSearchMask != 0)
- return ERROR_INVALID_PARAMETER;
-
- Struct40.SearchPhase = MNDX_SEARCH_INITIALIZING;
-
- szSearchMask = szNewSearchMask;
- cchSearchMask = cchNewSearchMask;
- return ERROR_SUCCESS;
- }
-
- TStruct40 Struct40;
- const char * szSearchMask; // Search mask without wildcards
- size_t cchSearchMask; // Length of the search mask
- const char * szFoundPath; // Found path name
- size_t cchFoundPath; // Length of the found path name
- DWORD nIndex; // Index of the file name
-};
-
-//-----------------------------------------------------------------------------
-// TPathFragmentTable class. This class implements table of the path fragments.
-// These path fragments can either by terminated by zeros (ASCIIZ)
-// or can be marked by the external "PathMarks" structure
-
-class TPathFragmentTable
-{
- public:
-
- // HOTS: 0195A290
- TPathFragmentTable()
- {}
-
- // HOTS: inlined
- ~TPathFragmentTable()
- {}
-
- // HOTS: 195A180
- bool ComparePathFragment(TMndxSearch * pSearch, size_t nFragmentOffset)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
-
- // Do we have path fragment separators in an external structure?
- if(PathMarks.IsEmpty())
- {
- // Keep searching as long as the name matches with the fragment
- while(PathFragments[nFragmentOffset] == pSearch->szSearchMask[pStruct40->PathLength])
- {
- // Move to the next character
- pStruct40->PathLength++;
- nFragmentOffset++;
-
- // Is it the end of the fragment or end of the path?
- if(PathFragments[nFragmentOffset] == 0)
- return true;
- if(pStruct40->PathLength >= pSearch->cchSearchMask)
- return false;
- }
-
- return false;
- }
- else
- {
- // Keep searching as long as the name matches with the fragment
- while(PathFragments[nFragmentOffset] == pSearch->szSearchMask[pStruct40->PathLength])
- {
- // Move to the next character
- pStruct40->PathLength++;
-
- // Is it the end of the path fragment?
- if(PathMarks.IsItemPresent(nFragmentOffset++))
- return true;
- if(nFragmentOffset >= pSearch->cchSearchMask)
- return false;
- }
-
- return false;
- }
- }
-
- // HOTS: 195A3F0
- void CopyPathFragment(TMndxSearch * pSearch, size_t nFragmentOffset)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
-
- // Do we have path fragment separators in an external structure?
- if (PathMarks.IsEmpty())
- {
- // HOTS: 195A40C
- while (PathFragments[nFragmentOffset] != 0)
- {
- // Insert the character to the path being built
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset++]);
- }
- }
- else
- {
- // HOTS: 195A4B3
- while(!PathMarks.IsItemPresent(nFragmentOffset))
- {
- // Insert the character to the path being built
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset++]);
- }
- }
- }
-
- // HOTS: 195A570
- bool CompareAndCopyPathFragment(TMndxSearch * pSearch, size_t nFragmentOffset)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
-
- // Do we have path fragment separators in an external structure?
- if(PathMarks.IsEmpty())
- {
- // Keep copying as long as we don't reach the end of the search mask
- while(pStruct40->PathLength < pSearch->cchSearchMask)
- {
- // HOTS: 195A5A0
- if(PathFragments[nFragmentOffset] != pSearch->szSearchMask[pStruct40->PathLength])
- return false;
-
- // HOTS: 195A5B7
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset++]);
- pStruct40->PathLength++;
-
- // If we found the end of the fragment, return success
- if(PathFragments[nFragmentOffset] == 0)
- return true;
- }
-
- // HOTS: 195A660
- // Now we need to copy the rest of the fragment
- while(PathFragments[nFragmentOffset] != 0)
- {
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset]);
- nFragmentOffset++;
- }
- }
- else
- {
- // Keep copying as long as we don't reach the end of the search mask
- while(nFragmentOffset < pSearch->cchSearchMask)
- {
- if(PathFragments[nFragmentOffset] != pSearch->szSearchMask[pStruct40->PathLength])
- return false;
-
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset]);
- pStruct40->PathLength++;
-
- // If we found the end of the fragment, return success
- if(PathMarks.IsItemPresent(nFragmentOffset++))
- return true;
- }
-
- // Now we need to copy the rest of the fragment
- while(!PathMarks.IsItemPresent(nFragmentOffset))
- {
- // HOTS: 195A7A6
- pStruct40->PathBuffer.Insert(PathFragments[nFragmentOffset++]);
- }
- }
-
- return true;
- }
-
- // HOTS: 0195A820
- int LoadFromStream(TByteStream & InStream)
- {
- int nError;
-
- nError = PathFragments.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- return PathMarks.LoadFromStream(InStream);
- }
-
- TGenericArray<char> PathFragments;
- TSparseArray PathMarks;
-};
-
-//-----------------------------------------------------------------------------
-// TStruct10 functions
-
-class TStruct10
-{
- public:
-
- TStruct10()
- {
- field_0 = 0x03;
- field_4 = 0x200;
- field_8 = 0x1000;
- field_C = 0x20000;
- }
-
- // HOTS: 1956FD0
- int sub_1956FD0(DWORD dwBitMask)
- {
- switch(dwBitMask & 0xF80)
- {
- case 0x00:
- field_4 = 0x200;
- return ERROR_SUCCESS;
-
- case 0x80:
- field_4 = 0x80;
- return ERROR_SUCCESS;
-
- case 0x100:
- field_4 = 0x100;
- return ERROR_SUCCESS;
-
- case 0x200:
- field_4 = 0x200;
- return ERROR_SUCCESS;
-
- case 0x400:
- field_4 = 0x400;
- return ERROR_SUCCESS;
-
- case 0x800:
- field_4 = 0x800;
- return ERROR_SUCCESS;
- }
-
- return ERROR_INVALID_PARAMETER;
- }
-
- // HOTS: 1957050
- int sub_1957050(DWORD dwBitMask)
- {
- switch(dwBitMask & 0xF0000)
- {
- case 0x00:
- field_C = 0x20000;
- return ERROR_SUCCESS;
-
- case 0x10000:
- field_C = 0x10000;
- return ERROR_SUCCESS;
-
- case 0x20000:
- field_C = 0x20000;
- return ERROR_SUCCESS;
- }
-
- return ERROR_INVALID_PARAMETER;
- }
-
- // HOTS: 19572E0
- int sub_19572E0(DWORD dwBitMask)
- {
- DWORD dwSubMask;
- int nError;
-
- if(dwBitMask & 0xFFF00000)
- return ERROR_INVALID_PARAMETER;
-
- dwSubMask = dwBitMask & 0x7F;
- if(dwSubMask)
- field_0 = dwSubMask;
-
- nError = sub_1956FD0(dwBitMask);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- dwSubMask = dwBitMask & 0xF000;
- if(dwSubMask == 0 || dwSubMask == 0x1000)
- {
- field_8 = 0x1000;
- return sub_1957050(dwBitMask);
- }
-
- if(dwSubMask == 0x2000)
- {
- field_8 = 0x2000;
- return sub_1957050(dwBitMask);
- }
-
- return ERROR_INVALID_PARAMETER;
- }
-
- // HOTS: 1957800
- int sub_1957800(DWORD dwBitMask)
- {
- return sub_19572E0(dwBitMask);
- }
-
- DWORD field_0;
- DWORD field_4;
- DWORD field_8;
- DWORD field_C;
-};
-
-//-----------------------------------------------------------------------------
-// TFileNameDatabase interface/implementation
-
-class TFileNameDatabase
-{
- public:
-
- // HOTS: 01958730
- TFileNameDatabase()
- {
- HashTableMask = 0;
- field_214 = 0;
- pChildDB = NULL;
- }
-
- ~TFileNameDatabase()
- {
- delete pChildDB;
- }
-
- // Returns nonzero if the name fragment match is a single-char match
- bool IsPathFragmentSingleChar(HASH_ENTRY * pHashEntry)
- {
- return ((pHashEntry->FragmentOffset & 0xFFFFFF00) == 0xFFFFFF00);
- }
-
- // Returns true if the given collision path fragment is a string (aka more than 1 char)
- bool IsPathFragmentString(size_t index)
- {
- return CollisionHiBitsIndexes.IsItemPresent(index);
- }
-
- // HOTS: 1957350, inlined
- DWORD GetPathFragmentOffset1(DWORD index_lobits)
- {
- DWORD index_hibits = CollisionHiBitsIndexes.GetItemValueAt(index_lobits);
-
- return (HiBitsTable.GetItem(index_hibits) << 0x08) | LoBitsTable[index_lobits];
- }
-
- // Retrieves fragment_offset/subtable_index of the path fragment, with check for starting value
- DWORD GetPathFragmentOffset2(DWORD & index_hibits, DWORD index_lobits)
- {
- // If the hi-bits index is invalid, we need to get its starting value
- if (index_hibits == CASC_INVALID_INDEX)
- {
-/*
- printf("\n");
- for (DWORD i = 0; i < CollisionHiBitsIndexes.TotalItemCount; i++)
- {
- if (CollisionHiBitsIndexes.IsItemPresent(i))
- printf("[%02X] = %02X\n", i, CollisionHiBitsIndexes.GetIntValueAt(i));
- else
- printf("[%02X] = NOT_PRESENT\n", i);
- }
-*/
- index_hibits = CollisionHiBitsIndexes.GetItemValueAt(index_lobits);
- }
- else
- {
- index_hibits++;
- }
-
- // Now we use both NodeIndex and HiBits index for retrieving the path fragment index
- return (HiBitsTable.GetItem(index_hibits) << 0x08) | LoBitsTable[index_lobits];
- }
-
- // HOTS: 1956DA0
- int Load(LPBYTE pbMarData, size_t cbMarData)
- {
- TByteStream ByteStream;
- DWORD dwSignature;
- int nError;
-
- if(pbMarData == NULL && cbMarData != 0)
- return ERROR_INVALID_PARAMETER;
-
- nError = ByteStream.SetByteBuffer(pbMarData, cbMarData);
- if(nError == ERROR_SUCCESS)
- {
- // Get pointer to MAR signature
- nError = ByteStream.GetValue<DWORD>(dwSignature);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // Verify the signature
- if(dwSignature != MNDX_MAR_SIGNATURE)
- return ERROR_BAD_FORMAT;
-
- // HOTS: 1956E11
- nError = LoadFromStream(ByteStream);
- }
-
- return nError;
- }
-
- // HOTS: 19584B0
- int SetChildDatabase(TFileNameDatabase * pNewDB)
- {
- if(pNewDB != NULL && pChildDB == pNewDB)
- return ERROR_INVALID_PARAMETER;
-
- if(pChildDB != NULL)
- delete pChildDB;
- pChildDB = pNewDB;
- return ERROR_SUCCESS;
- }
-
- // HOTS: 1957970
- bool ComparePathFragment(TMndxSearch * pSearch)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- PHASH_ENTRY pHashEntry;
- DWORD ColTableIndex;
- DWORD HiBitsIndex;
- DWORD NodeIndex;
-
- // Calculate the item hash from the current char and fragment ID
- NodeIndex = pStruct40->CalcHashValue(pSearch->szSearchMask) & HashTableMask;
- pHashEntry = &HashTable[NodeIndex];
-
- // Does the hash value ID match?
- if(pHashEntry->NodeIndex == pStruct40->NodeIndex)
- {
- // Check if there is single character match
- if (!IsPathFragmentSingleChar(pHashEntry))
- {
- // Check if there is a name fragment match
- if (pChildDB != NULL)
- {
- if (!pChildDB->ComparePathFragmentByIndex(pSearch, pHashEntry->ChildTableIndex))
- return false;
- }
- else
- {
- if (!PathFragmentTable.ComparePathFragment(pSearch, pHashEntry->FragmentOffset))
- return false;
- }
- }
- else
- {
- pStruct40->PathLength++;
- }
-
- pStruct40->NodeIndex = pHashEntry->NextIndex;
- return true;
- }
-
- //
- // Conflict: Multiple node IDs give the same table index
- //
-
- // HOTS: 1957A0E
- ColTableIndex = CollisionTable.GetItem0(pStruct40->NodeIndex) + 1;
- pStruct40->NodeIndex = (ColTableIndex - pStruct40->NodeIndex - 1);
- HiBitsIndex = CASC_INVALID_INDEX;
-
- // HOTS: 1957A41:
- while(CollisionTable.IsItemPresent(ColTableIndex))
- {
- // HOTS: 1957A41
- // Check if the low 8 bits if the fragment offset contain a single character
- // or an offset to a name fragment
- if(IsPathFragmentString(pStruct40->NodeIndex))
- {
- DWORD FragmentOffset = GetPathFragmentOffset2(HiBitsIndex, pStruct40->NodeIndex);
- DWORD SavePathLength = pStruct40->PathLength; // HOTS: 1957A83
-
- // Do we have a child database?
- if(pChildDB != NULL)
- {
- // HOTS: 1957AEC
- if(pChildDB->ComparePathFragmentByIndex(pSearch, FragmentOffset))
- return true;
- }
- else
- {
- // HOTS: 1957AF7
- if(PathFragmentTable.ComparePathFragment(pSearch, FragmentOffset))
- return true;
- }
-
- // HOTS: 1957B0E
- // If there was partial match with the fragment, end the search
- if(pStruct40->PathLength != SavePathLength)
- return false;
- }
- else
- {
- // HOTS: 1957B1C
- if(LoBitsTable[pStruct40->NodeIndex] == pSearch->szSearchMask[pStruct40->PathLength])
- {
- pStruct40->PathLength++;
- return true;
- }
- }
-
- // HOTS: 1957B32
- pStruct40->NodeIndex++;
- ColTableIndex++;
- }
-
- return false;
- }
-
- // HOTS: 1957B80
- bool ComparePathFragmentByIndex(TMndxSearch * pSearch, DWORD TableIndex)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- PHASH_ENTRY pHashEntry;
- DWORD eax;
-
- // HOTS: 1957B95
- for (;;)
- {
- // Get the hasn table item
- pHashEntry = &HashTable[TableIndex & HashTableMask];
-
- //
- if (TableIndex == pHashEntry->NextIndex)
- {
- // HOTS: 01957BB4
- if (!IsPathFragmentSingleChar(pHashEntry))
- {
- // HOTS: 1957BC7
- if (pChildDB != NULL)
- {
- // HOTS: 1957BD3
- if (!pChildDB->ComparePathFragmentByIndex(pSearch, pHashEntry->ChildTableIndex))
- return false;
- }
- else
- {
- // HOTS: 1957BE0
- if (!PathFragmentTable.ComparePathFragment(pSearch, pHashEntry->FragmentOffset))
- return false;
- }
- }
- else
- {
- // HOTS: 1957BEE
- if (pSearch->szSearchMask[pStruct40->PathLength] != pHashEntry->SingleChar)
- return false;
- pStruct40->PathLength++;
- }
-
- // HOTS: 1957C05
- TableIndex = pHashEntry->NodeIndex;
- if (TableIndex == 0)
- return true;
-
- if (pStruct40->PathLength >= pSearch->cchSearchMask)
- return false;
- }
- else
- {
- // HOTS: 1957C30
- if (IsPathFragmentString(TableIndex))
- {
- DWORD FragmentOffset = GetPathFragmentOffset1(TableIndex);
-
- // HOTS: 1957C4C
- if (pChildDB != NULL)
- {
- // HOTS: 1957C58
- if (!pChildDB->ComparePathFragmentByIndex(pSearch, FragmentOffset))
- return false;
- }
- else
- {
- // HOTS: 1957350
- if (!PathFragmentTable.ComparePathFragment(pSearch, FragmentOffset))
- return false;
- }
- }
- else
- {
- // HOTS: 1957C8E
- if (LoBitsTable[TableIndex] != pSearch->szSearchMask[pStruct40->PathLength])
- return false;
-
- pStruct40->PathLength++;
- }
-
- // HOTS: 1957CB2
- if (TableIndex <= field_214)
- return true;
-
- if (pStruct40->PathLength >= pSearch->cchSearchMask)
- return false;
-
- eax = CollisionTable.GetItem1(TableIndex);
- TableIndex = (eax - TableIndex - 1);
- }
- }
- }
-
- // HOTS: 1958D70
- void CopyPathFragmentByIndex(TMndxSearch * pSearch, DWORD TableIndex)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- PHASH_ENTRY pHashEntry;
-
- // HOTS: 1958D84
- for (;;)
- {
- pHashEntry = &HashTable[TableIndex & HashTableMask];
- if (TableIndex == pHashEntry->NextIndex)
- {
- // HOTS: 1958DA6
- if (!IsPathFragmentSingleChar(pHashEntry))
- {
- // HOTS: 1958DBA
- if (pChildDB != NULL)
- {
- pChildDB->CopyPathFragmentByIndex(pSearch, pHashEntry->ChildTableIndex);
- }
- else
- {
- PathFragmentTable.CopyPathFragment(pSearch, pHashEntry->FragmentOffset);
- }
- }
- else
- {
- // HOTS: 1958DE7
- // Insert the low 8 bits to the path being built
- pStruct40->PathBuffer.Insert(pHashEntry->SingleChar);
- }
-
- // HOTS: 1958E71
- TableIndex = pHashEntry->NodeIndex;
- if (TableIndex == 0)
- return;
- }
- else
- {
- // HOTS: 1958E8E
- if (IsPathFragmentString(TableIndex))
- {
- DWORD FragmentOffset = GetPathFragmentOffset1(TableIndex);
-
- // HOTS: 1958EAF
- if (pChildDB != NULL)
- {
- pChildDB->CopyPathFragmentByIndex(pSearch, FragmentOffset);
- }
- else
- {
- PathFragmentTable.CopyPathFragment(pSearch, FragmentOffset);
- }
- }
- else
- {
- // HOTS: 1958F50
- // Insert one character to the path being built
- pStruct40->PathBuffer.Insert(LoBitsTable[TableIndex]);
- }
-
- // HOTS: 1958FDE
- if (TableIndex <= field_214)
- return;
-
- TableIndex = 0xFFFFFFFF - TableIndex + CollisionTable.GetItem1(TableIndex);
- }
- }
- }
-
- // HOTS: 1958B00
- bool CompareAndCopyPathFragment(TMndxSearch * pSearch)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- PHASH_ENTRY pHashEntry;
- DWORD HiBitsIndex;
- DWORD ColTableIndex;
- DWORD TableIndex;
-/*
- FILE * fp = fopen("E:\\PathFragmentTable.txt", "wt");
- if (fp != NULL)
- {
- for (DWORD i = 0; i < HashTable.ItemCount; i++)
- {
- FragOffs = HashTable[i].FragOffs;
- fprintf(fp, "%02x ('%c') %08X %08X %08X", i, (0x20 <= i && i < 0x80) ? i : 0x20, HashTable[i].ItemIndex, HashTable[i].NextIndex, FragOffs);
-
- if(FragOffs != 0x00800000)
- {
- if((FragOffs & 0xFFFFFF00) == 0xFFFFFF00)
- fprintf(fp, " '%c'", (char)(FragOffs & 0xFF));
- else
- fprintf(fp, " %s", &PathFragmentTable.PathFragments[FragOffs]);
- }
- fprintf(fp, "\n");
- }
-
- fclose(fp);
- }
-*/
- // Calculate the item hash from the current char and fragment ID
- TableIndex = pStruct40->CalcHashValue(pSearch->szSearchMask) & HashTableMask;
- pHashEntry = &HashTable[TableIndex];
-
- // Does the hash value ID match?
- if(pStruct40->NodeIndex == pHashEntry->NodeIndex)
- {
- // If the higher 24 bits are set, then the fragment is just one letter,
- // contained directly in the table.
- if(!IsPathFragmentSingleChar(pHashEntry))
- {
- // HOTS: 1958B59
- if (pChildDB != NULL)
- {
- if (!pChildDB->CompareAndCopyPathFragmentByIndex(pSearch, pHashEntry->ChildTableIndex))
- return false;
- }
- else
- {
- if (!PathFragmentTable.CompareAndCopyPathFragment(pSearch, pHashEntry->FragmentOffset))
- return false;
- }
- }
- else
- {
- // HOTS: 1958B88
- pStruct40->PathBuffer.Insert(pHashEntry->SingleChar);
- pStruct40->PathLength++;
- }
-
- // HOTS: 1958BCA
- pStruct40->NodeIndex = pHashEntry->NextIndex;
- return true;
- }
-
- // HOTS: 1958BE5
- ColTableIndex = CollisionTable.GetItem0(pStruct40->NodeIndex) + 1;
- pStruct40->NodeIndex = (ColTableIndex - pStruct40->NodeIndex - 1);
- HiBitsIndex = CASC_INVALID_INDEX;
-
- // Keep searching while we have a valid collision table entry
- while(CollisionTable.IsItemPresent(ColTableIndex))
- {
- // If we have high bits in the the bit at NodeIndex is set, it means that there is fragment offset
- // If not, the byte in LoBitsTable is the character
- if(IsPathFragmentString(pStruct40->NodeIndex))
- {
- DWORD FragmentOffset = GetPathFragmentOffset2(HiBitsIndex, pStruct40->NodeIndex);
- DWORD SavePathLength = pStruct40->PathLength; // HOTS: 1958C62
-
- // Do we have a child database?
- if(pChildDB != NULL)
- {
- // HOTS: 1958CCB
- if(pChildDB->CompareAndCopyPathFragmentByIndex(pSearch, FragmentOffset))
- return true;
- }
- else
- {
- // HOTS: 1958CD6
- if(PathFragmentTable.CompareAndCopyPathFragment(pSearch, FragmentOffset))
- return true;
- }
-
- // HOTS: 1958CED
- if(SavePathLength != pStruct40->PathLength)
- return false;
- }
- else
- {
- // HOTS: 1958CFB
- if(LoBitsTable[pStruct40->NodeIndex] == pSearch->szSearchMask[pStruct40->PathLength])
- {
- // HOTS: 1958D11
- pStruct40->PathBuffer.Insert(LoBitsTable[pStruct40->NodeIndex]);
- pStruct40->PathLength++;
- return true;
- }
- }
-
- // HOTS: 1958D11
- pStruct40->NodeIndex++;
- ColTableIndex++;
- }
-
- return false;
- }
-
- // HOTS: 1959010
- bool CompareAndCopyPathFragmentByIndex(TMndxSearch * pSearch, DWORD TableIndex)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- PHASH_ENTRY pHashEntry;
-
- // HOTS: 1959024
- for(;;)
- {
- pHashEntry = &HashTable[TableIndex & HashTableMask];
- if(TableIndex == pHashEntry->NextIndex)
- {
- // HOTS: 1959047
- if(!IsPathFragmentSingleChar(pHashEntry))
- {
- // HOTS: 195905A
- if(pChildDB != NULL)
- {
- if(!pChildDB->CompareAndCopyPathFragmentByIndex(pSearch, pHashEntry->ChildTableIndex))
- return false;
- }
- else
- {
- if(!PathFragmentTable.CompareAndCopyPathFragment(pSearch, pHashEntry->FragmentOffset))
- return false;
- }
- }
- else
- {
- // HOTS: 1959092
- if(pHashEntry->SingleChar != pSearch->szSearchMask[pStruct40->PathLength])
- return false;
-
- // Insert the low 8 bits to the path being built
- pStruct40->PathBuffer.Insert(pHashEntry->SingleChar);
- pStruct40->PathLength++;
- }
-
- // HOTS: 195912E
- TableIndex = pHashEntry->NodeIndex;
- if(TableIndex == 0)
- return true;
- }
- else
- {
- // HOTS: 1959147
- if(IsPathFragmentString(TableIndex))
- {
- // HOTS: 195917C
- DWORD FragmentOffset = GetPathFragmentOffset1(TableIndex);
-
- if(pChildDB != NULL)
- {
- if(!pChildDB->CompareAndCopyPathFragmentByIndex(pSearch, FragmentOffset))
- return false;
- }
- else
- {
- if(!PathFragmentTable.CompareAndCopyPathFragment(pSearch, FragmentOffset))
- return false;
- }
- }
- else
- {
- // HOTS: 195920E
- if(LoBitsTable[TableIndex] != pSearch->szSearchMask[pStruct40->PathLength])
- return false;
-
- // Insert one character to the path being built
- pStruct40->PathBuffer.Insert(LoBitsTable[TableIndex]);
- pStruct40->PathLength++;
- }
-
- // HOTS: 19592B6
- if(TableIndex <= field_214)
- return true;
-
- TableIndex = 0xFFFFFFFF - TableIndex + CollisionTable.GetItem1(TableIndex);
- }
-
- // HOTS: 19592D5
- if(pStruct40->PathLength >= pSearch->cchSearchMask)
- break;
- }
-
- CopyPathFragmentByIndex(pSearch, TableIndex);
- return true;
- }
-
- // HOTS: 1959460
- bool DoSearch(TMndxSearch * pSearch)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
- TPathStop * pPathStop;
- DWORD edi;
-
- // Perform action based on the search phase
- switch (pStruct40->SearchPhase)
- {
- case MNDX_SEARCH_INITIALIZING:
- {
- // HOTS: 1959489
- pStruct40->BeginSearch();
-
- // If the caller passed a part of the search path, we need to find that one
- while (pStruct40->PathLength < pSearch->cchSearchMask)
- {
- if (!CompareAndCopyPathFragment(pSearch))
- {
- pStruct40->SearchPhase = MNDX_SEARCH_FINISHED;
- return false;
- }
- }
-
- // HOTS: 19594b0
- TPathStop PathStop(pStruct40->NodeIndex, 0, pStruct40->PathBuffer.ItemCount);
- pStruct40->PathStops.Insert(PathStop);
- pStruct40->ItemCount = 1;
-
- if (FileNameIndexes.IsItemPresent(pStruct40->NodeIndex))
- {
- pSearch->szFoundPath = &pStruct40->PathBuffer[0];
- pSearch->cchFoundPath = pStruct40->PathBuffer.ItemCount;
- pSearch->nIndex = FileNameIndexes.GetItemValueAt(pStruct40->NodeIndex);
- return true;
- }
- }
- // No break here, go straight to the MNDX_SEARCH_SEARCHING
-
- case MNDX_SEARCH_SEARCHING:
- {
- // HOTS: 1959522
- for (;;)
- {
- // HOTS: 1959530
- if (pStruct40->ItemCount == pStruct40->PathStops.ItemCount)
- {
- TPathStop * pLastStop;
- DWORD ColTableIndex;
-
- pLastStop = &pStruct40->PathStops[pStruct40->PathStops.ItemCount - 1];
-
- ColTableIndex = CollisionTable.GetItem0(pLastStop->LoBitsIndex) + 1;
-
- // Insert a new structure
- TPathStop PathStop(ColTableIndex - pLastStop->LoBitsIndex - 1, ColTableIndex, 0);
- pStruct40->PathStops.Insert(PathStop);
- }
-
- // HOTS: 19595BD
- pPathStop = &pStruct40->PathStops[pStruct40->ItemCount];
-
- // HOTS: 19595CC
- if (CollisionTable.IsItemPresent(pPathStop->field_4++))
- {
- // HOTS: 19595F2
- pStruct40->ItemCount++;
-
- if (IsPathFragmentString(pPathStop->LoBitsIndex))
- {
- DWORD FragmentOffset = GetPathFragmentOffset2(pPathStop->HiBitsIndex_PathFragment, pPathStop->LoBitsIndex);
-
- // HOTS: 1959630
- if (pChildDB != NULL)
- {
- // HOTS: 1959649
- pChildDB->CopyPathFragmentByIndex(pSearch, FragmentOffset);
- }
- else
- {
- // HOTS: 1959654
- PathFragmentTable.CopyPathFragment(pSearch, FragmentOffset);
- }
- }
- else
- {
- // HOTS: 1959665
- // Insert one character to the path being built
- pStruct40->PathBuffer.Insert(LoBitsTable[pPathStop->LoBitsIndex]);
- }
-
- // HOTS: 19596AE
- pPathStop->Count = pStruct40->PathBuffer.ItemCount;
-
- // HOTS: 19596b6
- if (FileNameIndexes.IsItemPresent(pPathStop->LoBitsIndex))
- {
- // HOTS: 19596D1
- if (pPathStop->field_10 == 0xFFFFFFFF)
- {
- // HOTS: 19596D9
- pPathStop->field_10 = FileNameIndexes.GetItemValueAt(pPathStop->LoBitsIndex);
- }
- else
- {
- pPathStop->field_10++;
- }
-
- // HOTS: 1959755
- pSearch->szFoundPath = &pStruct40->PathBuffer[0];
- pSearch->cchFoundPath = pStruct40->PathBuffer.ItemCount;
- pSearch->nIndex = pPathStop->field_10;
- return true;
- }
- }
- else
- {
- // HOTS: 19596E9
- if (pStruct40->ItemCount == 1)
- {
- pStruct40->SearchPhase = MNDX_SEARCH_FINISHED;
- return false;
- }
-
- // HOTS: 19596F5
- pStruct40->PathStops[pStruct40->ItemCount - 1].LoBitsIndex++;
- edi = pStruct40->PathStops[pStruct40->ItemCount - 2].Count;
- pStruct40->PathBuffer.SetMaxItemsIf(edi);
-
- // HOTS: 1959749
- pStruct40->PathBuffer.ItemCount = edi;
- pStruct40->ItemCount--;
- }
- }
- }
-
- case MNDX_SEARCH_FINISHED:
- break;
- }
-
- return false;
- }
-
- // HOTS: 1957EF0
- bool FindFileInDatabase(TMndxSearch * pSearch)
- {
- TStruct40 * pStruct40 = &pSearch->Struct40;
-
- pStruct40->NodeIndex = 0;
- pStruct40->PathLength = 0;
- pStruct40->SearchPhase = MNDX_SEARCH_INITIALIZING;
-
- if(pSearch->cchSearchMask > 0)
- {
- while(pStruct40->PathLength < pSearch->cchSearchMask)
- {
- // HOTS: 01957F12
- if(!ComparePathFragment(pSearch))
- return false;
- }
- }
-
- // HOTS: 1957F26
- if(!FileNameIndexes.IsItemPresent(pStruct40->NodeIndex))
- return false;
-
- pSearch->szFoundPath = pSearch->szSearchMask;
- pSearch->cchFoundPath = pSearch->cchSearchMask;
- pSearch->nIndex = FileNameIndexes.GetItemValueAt(pStruct40->NodeIndex);
- return true;
- }
-
- // HOTS: 1959790
- int LoadFromStream(TByteStream & InStream)
- {
- DWORD dwBitMask;
- int nError;
-
- nError = CollisionTable.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = FileNameIndexes.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = CollisionHiBitsIndexes.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // HOTS: 019597CD
- nError = LoBitsTable.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = HiBitsTable.LoadBitsFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // HOTS: 019597F5
- nError = PathFragmentTable.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // HOTS: 0195980A
- if(CollisionHiBitsIndexes.ValidItemCount != 0 && PathFragmentTable.PathFragments.ItemCount == 0)
- {
- TFileNameDatabase * pNewDB;
-
- pNewDB = new TFileNameDatabase;
- if (pNewDB == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- nError = SetChildDatabase(pNewDB);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = pChildDB->LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
- }
-
- // HOTS: 0195986B
- nError = HashTable.LoadFromStream(InStream);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- HashTableMask = HashTable.ItemCount - 1;
-
- nError = InStream.GetValue<DWORD>(field_214);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- nError = InStream.GetValue<DWORD>(dwBitMask);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- return Struct10.sub_1957800(dwBitMask);
- }
-
- TSparseArray CollisionTable; // Table of valid collisions, indexed by NodeIndex
- TSparseArray FileNameIndexes; // Array of file name indexes
- TSparseArray CollisionHiBitsIndexes; // Table of indexes of high bits (above 8 bits) for collisions
-
- // This pair of arrays serves for fast conversion from node index to FragmentOffset / FragmentChar
- TGenericArray<BYTE> LoBitsTable; // Array of lower 8 bits of name fragment offset
- TBitEntryArray HiBitsTable; // Array of upper x bits of name fragment offset
-
- TPathFragmentTable PathFragmentTable;
- TFileNameDatabase * pChildDB;
-
- TGenericArray<HASH_ENTRY> HashTable; // Hash table for searching name fragments
-
- DWORD HashTableMask; // Mask to get hash table index from hash value
- DWORD field_214;
- TStruct10 Struct10;
-};
-
-//-----------------------------------------------------------------------------
-// Local functions - MAR file
-
-class TMndxMarFile
-{
- public:
-
- TMndxMarFile()
- {
- pDatabase = NULL;
- pbMarData = NULL;
- cbMarData = 0;
- }
-
- ~TMndxMarFile()
- {
- if(pDatabase != NULL)
- delete pDatabase;
- CASC_FREE(pbMarData);
- }
-
- // HOTS: 00E94180
- int LoadRootData(FILE_MAR_INFO & MarInfo, LPBYTE pbRootFile, LPBYTE pbRootEnd)
- {
- // Allocate the MAR data
- pbMarData = CASC_ALLOC(BYTE, MarInfo.MarDataSize);
- cbMarData = MarInfo.MarDataSize;
- if(pbMarData == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- // Capture the MAR data
- if(!CaptureData(pbRootFile + MarInfo.MarDataOffset, pbRootEnd, pbMarData, cbMarData))
- return ERROR_FILE_CORRUPT;
-
- // Create the file name database
- pDatabase = new TFileNameDatabase();
- if(pDatabase == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- return pDatabase->Load(pbMarData, cbMarData);
- }
-
- // HOTS: 1956C60
- int SearchFile(TMndxSearch * pSearch)
- {
- int nError = ERROR_SUCCESS;
-
- if(pDatabase == NULL)
- return ERROR_INVALID_PARAMETER;
-
- if(!pDatabase->FindFileInDatabase(pSearch))
- nError = ERROR_FILE_NOT_FOUND;
-
- return nError;
- }
-
- // HOTS: 1956CE0
- int DoSearch(TMndxSearch * pSearch, bool * pbFindResult)
- {
- int nError = ERROR_SUCCESS;
-
- if(pDatabase == NULL)
- return ERROR_INVALID_PARAMETER;
-
- *pbFindResult = pDatabase->DoSearch(pSearch);
- return nError;
- }
-
- // HOTS: 1956D20
- int GetFileNameCount(size_t * PtrFileNameCount)
- {
- if(pDatabase == NULL)
- return ERROR_INVALID_PARAMETER;
-
- PtrFileNameCount[0] = pDatabase->FileNameIndexes.ValidItemCount;
- return ERROR_SUCCESS;
- }
-
-// protected:
- TFileNameDatabase * pDatabase;
- LPBYTE pbMarData;
- size_t cbMarData;
-};
-
-//-----------------------------------------------------------------------------
-// Implementation of root file functions
-
-typedef struct _FILE_MNDX_INFO
-{
- BYTE RootFileName[MD5_HASH_SIZE]; // Name (aka MD5) of the root file
- DWORD HeaderVersion; // Must be <= 2
- DWORD FormatVersion;
- DWORD field_1C;
- DWORD field_20;
- DWORD MarInfoOffset; // Offset of the first MAR entry info
- DWORD MarInfoCount; // Number of the MAR info entries
- DWORD MarInfoSize; // Size of the MAR info entry
- DWORD CKeyEntriesOffset; // Offset of the CKey entries, relative to begin of the root file
- DWORD CKeyEntriesCount; // Number of CKeys (files) in the root file
- DWORD FileNameCount; // Number of unique file names. More files with the same name in the different packages can exist
- DWORD CKeyEntrySize; // Size of one CKey root entry
- TMndxMarFile * MarFiles[MAR_COUNT]; // File name list for the packages
-
-} FILE_MNDX_INFO, *PFILE_MNDX_INFO;
-
-struct TMndxHandler
-{
- public:
-
- //
- // Constructor and destructor
- //
-
- TMndxHandler()
- {
- memset(this, 0, sizeof(TMndxHandler));
- }
-
- ~TMndxHandler()
- {
- PMNDX_PACKAGE pPackage;
- size_t i;
-
- for(i = 0; i < MAR_COUNT; i++)
- delete MndxInfo.MarFiles[i];
- CASC_FREE(FileNameIndexToCKeyIndex);
- pCKeyEntries = NULL;
-
- for(i = 0; i < Packages.ItemCount(); i++)
- {
- pPackage = (PMNDX_PACKAGE)Packages.ItemAt(i);
- CASC_FREE(pPackage->szFileName);
- }
- Packages.Free();
- }
-
- //
- // Helper functions
- //
-
- static LPBYTE CaptureRootHeader(FILE_MNDX_HEADER & MndxHeader, LPBYTE pbRootPtr, LPBYTE pbRootEnd)
- {
- // Capture the root header
- pbRootPtr = CaptureData(pbRootPtr, pbRootEnd, &MndxHeader, sizeof(FILE_MNDX_HEADER));
- if (pbRootPtr == NULL)
- return NULL;
-
- // Check signature and version
- if (MndxHeader.Signature != CASC_MNDX_ROOT_SIGNATURE || MndxHeader.FormatVersion > 2 || MndxHeader.FormatVersion < 1)
- return NULL;
-
- // Passed
- return pbRootPtr + sizeof(FILE_MNDX_HEADER);
- }
-
- int LoadPackageNames()
- {
- TMndxMarFile * pMarFile = MndxInfo.MarFiles[MAR_PACKAGE_NAMES];
- TMndxSearch Search;
- PMNDX_PACKAGE pPackage;
- size_t nPackageCount = 0x40;
- bool bFindResult = false;
- int nError;
-
- // Prepare the file name search in the top level directory
- Search.SetSearchMask("", 0);
-
- // Allocate initial name list structure
- pMarFile->GetFileNameCount(&nPackageCount);
- nError = Packages.Create<MNDX_PACKAGE>(nPackageCount);
- if(nError != ERROR_SUCCESS)
- return nError;
-
- // Reset the package array
- Packages.Reset();
-
- // Keep searching as long as we find something
- while(pMarFile->DoSearch(&Search, &bFindResult) == ERROR_SUCCESS && bFindResult)
- {
- // Insert new package to the array
- assert(Search.nIndex < nPackageCount);
- pPackage = (PMNDX_PACKAGE)Packages.InsertAt(Search.nIndex);
- if (pPackage != NULL)
- {
- // The package mut not be initialized yet
- assert(pPackage->szFileName == NULL);
-
- // Allocate space for the file name
- pPackage->szFileName = CASC_ALLOC(char, Search.cchFoundPath + 1);
- if (pPackage->szFileName == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- // Fill the package structure
- memcpy(pPackage->szFileName, Search.szFoundPath, Search.cchFoundPath);
- pPackage->szFileName[Search.cchFoundPath] = 0;
- pPackage->nLength = Search.cchFoundPath;
- pPackage->nIndex = Search.nIndex;
- }
- }
-
- // Give the packages to the caller
- return ERROR_SUCCESS;
- }
-
- int Load(const FILE_MNDX_HEADER & MndxHeader, LPBYTE pbRootFile, LPBYTE pbRootEnd)
- {
- TMndxMarFile * pMarFile;
- FILE_MAR_INFO MarInfo;
- size_t nFilePointer = 0;
- DWORD i;
- int nError = ERROR_SUCCESS;
-
- // Copy the header into the MNDX info
- MndxInfo.HeaderVersion = MndxHeader.HeaderVersion;
- MndxInfo.FormatVersion = MndxHeader.FormatVersion;
- nFilePointer += sizeof(FILE_MNDX_HEADER);
-
- // Header version 2 has 2 extra fields that we need to load
- if(MndxInfo.HeaderVersion == 2)
- {
- if(!CaptureData(pbRootFile + nFilePointer, pbRootEnd, &MndxInfo.field_1C, sizeof(DWORD) + sizeof(DWORD)))
- return ERROR_FILE_CORRUPT;
- nFilePointer += sizeof(DWORD) + sizeof(DWORD);
- }
-
- // Load the rest of the file header
- if(!CaptureData(pbRootFile + nFilePointer, pbRootEnd, &MndxInfo.MarInfoOffset, 0x1C))
- return ERROR_FILE_CORRUPT;
-
- // Verify the structure
- if(MndxInfo.MarInfoCount > MAR_COUNT || MndxInfo.MarInfoSize != sizeof(FILE_MAR_INFO))
- return ERROR_FILE_CORRUPT;
-
- // Load all MAR infos
- for(i = 0; i < MndxInfo.MarInfoCount; i++)
- {
- // Capture the n-th MAR info
- nFilePointer = MndxInfo.MarInfoOffset + (MndxInfo.MarInfoSize * i);
- if(!CaptureData(pbRootFile + nFilePointer, pbRootEnd, &MarInfo, sizeof(FILE_MAR_INFO)))
- return ERROR_FILE_CORRUPT;
-
- // Allocate MAR_FILE structure
- pMarFile = new TMndxMarFile();
- if(pMarFile == NULL)
- {
- nError = ERROR_NOT_ENOUGH_MEMORY;
- break;
- }
-
- // Create the database from the MAR data
- nError = pMarFile->LoadRootData(MarInfo, pbRootFile, pbRootEnd);
- if(nError != ERROR_SUCCESS)
- break;
-
- // Assign the MAR file to the MNDX info structure
- MndxInfo.MarFiles[i] = pMarFile;
- }
-
- // All three MAR files must be loaded
- // HOTS: 00E9503B
- if(nError == ERROR_SUCCESS)
- {
- if(MndxInfo.MarFiles[MAR_PACKAGE_NAMES] == NULL || MndxInfo.MarFiles[MAR_STRIPPED_NAMES] == NULL || MndxInfo.MarFiles[MAR_FULL_NAMES] == NULL)
- nError = ERROR_BAD_FORMAT;
- if(MndxInfo.CKeyEntrySize != sizeof(MNDX_CKEY_ENTRY))
- nError = ERROR_BAD_FORMAT;
- }
-
- // Load the array of Ckey entries. All present files are in the array,
- // the same names (differentiated by package ID) are groupped together
- if(nError == ERROR_SUCCESS)
- {
- size_t CKeyEntriesSize;
- size_t FileNameCount = 0;
-
- pMarFile = MndxInfo.MarFiles[MAR_STRIPPED_NAMES];
- nError = ERROR_FILE_CORRUPT;
-
- // Capture the array of CKey entries
- if(pMarFile->GetFileNameCount(&FileNameCount) == ERROR_SUCCESS && FileNameCount == MndxInfo.FileNameCount)
- {
- CKeyEntriesSize = MndxInfo.CKeyEntriesCount * MndxInfo.CKeyEntrySize;
- if ((pbRootFile + MndxInfo.CKeyEntriesOffset + CKeyEntriesSize) <= pbRootEnd)
- {
- pCKeyEntries = (PMNDX_CKEY_ENTRY)(pbRootFile + MndxInfo.CKeyEntriesOffset);
- nError = ERROR_SUCCESS;
- }
- }
- }
-
- // Pick the CKey entries that are the first with a given name
- if(nError == ERROR_SUCCESS)
- {
- assert(MndxInfo.FileNameCount <= MndxInfo.CKeyEntriesCount);
- FileNameIndexToCKeyIndex = CASC_ALLOC(PMNDX_CKEY_ENTRY, MndxInfo.FileNameCount + 1);
- if(FileNameIndexToCKeyIndex != NULL)
- {
- PMNDX_CKEY_ENTRY pRootEntry = pCKeyEntries;
- DWORD nFileNameIndex = 0;
-
- // The first entry is always beginning of a file name group
- FileNameIndexToCKeyIndex[nFileNameIndex++] = pRootEntry;
-
- // Get the remaining file name groups
- for(i = 0; i < MndxInfo.CKeyEntriesCount; i++, pRootEntry++)
- {
- if (nFileNameIndex > MndxInfo.FileNameCount)
- break;
-
- if (pRootEntry->Flags & MNDX_LAST_CKEY_ENTRY)
- {
- FileNameIndexToCKeyIndex[nFileNameIndex++] = pRootEntry + 1;
- }
- }
-
- // Verify the final number of file names
- if ((nFileNameIndex - 1) != MndxInfo.FileNameCount)
- nError = ERROR_BAD_FORMAT;
- }
- else
- nError = ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Load the package names from the 0-th MAR file
- if(nError == ERROR_SUCCESS)
- {
- nError = LoadPackageNames();
- }
-
- return nError;
- }
-
- int LoadFileNames(TCascStorage * hs, CASC_FILE_TREE & FileTree)
- {
- PCASC_CKEY_ENTRY pCKeyEntry;
- PMNDX_CKEY_ENTRY pRootEntry;
- PMNDX_CKEY_ENTRY pRootEnd = pCKeyEntries + MndxInfo.CKeyEntriesCount;
- PMNDX_PACKAGE pPackage;
- TMndxMarFile * pMarFile = MndxInfo.MarFiles[MAR_STRIPPED_NAMES];
- TMndxSearch Search;
- char szFileName[MAX_PATH];
- bool bFindResult = false;
- int nError;
-
- // Setup the search mask
- Search.SetSearchMask("", 0);
-
- // Keep searching ad long as we found something
- while ((nError = pMarFile->DoSearch(&Search, &bFindResult)) == ERROR_SUCCESS && bFindResult)
- {
- // Sanity check
- assert(Search.cchFoundPath < MAX_PATH);
-
- // The found file name index must fall into range of file names
- if (Search.nIndex < MndxInfo.FileNameCount)
- {
- // Retrieve the first-in-group CKey entry of that name
- pRootEntry = FileNameIndexToCKeyIndex[Search.nIndex];
-
- // Now take all files of that name, prepend their package name and insert to file tree
- while(pRootEntry < pRootEnd)
- {
- // Find the appropriate CKey entry in the central storage
- pCKeyEntry = FindCKeyEntry_CKey(hs, pRootEntry->CKey);
- if (pCKeyEntry != NULL)
- {
- size_t nPackageIndex = pRootEntry->Flags & 0x00FFFFFF;
-
- // Retrieve the package for this entry
- pPackage = (PMNDX_PACKAGE)Packages.ItemAt(nPackageIndex);
- if (pPackage != NULL)
- {
- // Sanity check
- assert(pPackage->nIndex == nPackageIndex);
-
- // Merge the package name and file name
- MakeFileName(szFileName, _countof(szFileName), pPackage, &Search);
-
- // Insert the entry to the file tree
- FileTree.InsertByName(pCKeyEntry, szFileName);
- }
- }
-
- // Is this the last-in-group entry?
- if (pRootEntry->Flags & MNDX_LAST_CKEY_ENTRY)
- break;
- pRootEntry++;
- }
- }
- }
-
- return nError;
- }
-
- //
- // Helper functions
- //
-
- void MakeFileName(char * szBuffer, size_t cchBuffer, PMNDX_PACKAGE pPackage, TMndxSearch * pSearch)
- {
- char * szBufferEnd = szBuffer + cchBuffer - 1;
-
- // Buffer length check
- assert((pPackage->nLength + 1 + pSearch->cchFoundPath + 1) < cchBuffer);
-
- // Copy the package name
- if ((szBuffer + pPackage->nLength) < szBufferEnd)
- {
- memcpy(szBuffer, pPackage->szFileName, pPackage->nLength);
- szBuffer += pPackage->nLength;
- }
-
- // Append slash
- if ((szBuffer + 1) < szBufferEnd)
- *szBuffer++ = '/';
-
- // Append file name
- if ((szBuffer + pSearch->cchFoundPath) < szBufferEnd)
- {
- memcpy(szBuffer, pSearch->szFoundPath, pSearch->cchFoundPath);
- szBuffer += pSearch->cchFoundPath;
- }
-
- szBuffer[0] = 0;
- }
-
- protected:
-
- FILE_MNDX_INFO MndxInfo;
-
- PMNDX_CKEY_ENTRY * FileNameIndexToCKeyIndex;
- PMNDX_CKEY_ENTRY pCKeyEntries;
- CASC_ARRAY Packages; // Linear list of present packages
-};
-
-//-----------------------------------------------------------------------------
-// Handler definition for MNDX root file
-
-struct TRootHandler_MNDX : public TFileTreeRoot
-{
- public:
-
- TRootHandler_MNDX() : TFileTreeRoot(0)
- {
- // MNDX supports file names and CKeys
- dwFeatures |= CASC_FEATURE_FILE_NAMES | CASC_FEATURE_ROOT_CKEY;
- }
-
- int Load(TCascStorage * hs, const FILE_MNDX_HEADER & MndxHeader, LPBYTE pbRootFile, LPBYTE pbRootEnd)
- {
- TMndxHandler Handler;
- int nError;
-
- // Load and parse the entire MNDX structure
- nError = Handler.Load(MndxHeader, pbRootFile, pbRootEnd);
- if (nError == ERROR_SUCCESS)
- {
- // Search all file names and insert them into the file tree
- nError = Handler.LoadFileNames(hs, FileTree);
- }
-
- return nError;
- }
-};
-
-//-----------------------------------------------------------------------------
-// Public functions - MNDX info
-
-int RootHandler_CreateMNDX(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
-{
- TRootHandler_MNDX * pRootHandler = NULL;
- FILE_MNDX_HEADER MndxHeader;
- LPBYTE pbRootEnd = pbRootFile + cbRootFile;
- int nError = ERROR_BAD_FORMAT;
-
- // Verify the header of the ROOT file
- if(TMndxHandler::CaptureRootHeader(MndxHeader, pbRootFile, pbRootEnd) != NULL)
- {
- // Allocate the root handler object
- pRootHandler = new TRootHandler_MNDX();
- if(pRootHandler != NULL)
- {
- // Load the root directory. If load failed, we free the object
- nError = pRootHandler->Load(hs, MndxHeader, pbRootFile, pbRootEnd);
- if(nError != ERROR_SUCCESS)
- {
- delete pRootHandler;
- pRootHandler = NULL;
- }
- }
- }
-
- // Assign the root directory (or NULL) and return error
- hs->pRootHandler = pRootHandler;
- return nError;
-}