aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascMndxRoot.h
blob: 23017642ff991d0e80f574c8b79437fd4f3b2041 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/*****************************************************************************/
/* CascMndxRoot.h                         Copyright (c) Ladislav Zezula 2014 */
/*---------------------------------------------------------------------------*/
/* Interface file for MNDX structures                                        */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 15.05.14  1.00  Lad  Created                                              */
/*****************************************************************************/

#ifndef __CASC_MNDX_ROOT__
#define __CASC_MNDX_ROOT__

class TFileNameDatabase;

#define CASC_MAX_ENTRIES(type) (0xFFFFFFFF / sizeof(type))

#define CASC_SEARCH_INITIALIZING    0
#define CASC_SEARCH_SEARCHING       2
#define CASC_SEARCH_FINISHED        4

typedef struct _TRIPLET
{
    DWORD BaseValue;
    DWORD Value2;
    DWORD Value3;
} TRIPLET, *PTRIPLET;

typedef struct _NAME_FRAG
{
    DWORD ItemIndex;                                // Back index to various tables
    DWORD NextIndex;                                // The following item index
    DWORD FragOffs;                                 // Higher 24 bits are 0xFFFFFF00 --> A single matching character
                                                    // Otherwise --> Offset to the name fragment table
} NAME_FRAG, *PNAME_FRAG;

typedef struct _PATH_STOP
{
    DWORD ItemIndex;
    DWORD field_4;
    DWORD field_8;
    DWORD field_C;
    DWORD field_10;
} PATH_STOP, *PPATH_STOP;

typedef union _ARRAY_POINTER
{
    LPBYTE Bytes;                                   // Pointer to an octet
    char * Chars;                                   // Pointer to a character
    PDWORD Uint32s;                                 // Pointer to a DWORD
    PTRIPLET Triplets;                              // Pointer to TRIPLET
    PNAME_FRAG NameFrags;                           // Pointer to name fragment entry
    PPATH_STOP PathStopPtr;                         // Pointer to path checkpoint
    PULONGLONG Int64Ptr;                            // Pointer to 64-bit integer

} ARRAY_POINTER, *PARRAY_POINTER;

// Simple access to various tables within TGenericArray
#define ByteArray     ArrayPointer.Bytes  
#define CharArray     ArrayPointer.Chars  
#define Uint32Array   ArrayPointer.Uint32s
#define TripletArray  ArrayPointer.Triplets
#define NameFragArray ArrayPointer.NameFrags

class TByteStream
{
    public:

    TByteStream();

    void ExchangeWith(TByteStream & Target);
    int GetBytes(DWORD cbByteCount, PARRAY_POINTER PtrArray);
    int SkipBytes(DWORD cbByteCount);
    int SetByteBuffer(LPBYTE pbNewMarData, DWORD cbNewMarData);
    int GetValue_DWORD(DWORD & Value);
    int GetValue_ItemCount(DWORD & NumberOfBytes, DWORD & ItemCount, DWORD ItemSize);
    int GetArray_DWORDs(PARRAY_POINTER PtrArray, DWORD ItemCount);
    int GetArray_Triplets(PARRAY_POINTER PtrArray, DWORD ItemCount);
    int GetArray_NameTable(PARRAY_POINTER PtrArray, DWORD ItemCount);
    int GetArray_BYTES(PARRAY_POINTER PtrArray, DWORD ItemCount);

    LPBYTE pbByteData;
    void * pvMappedFile;
    DWORD cbByteData;
    DWORD field_C;
    HANDLE hFile;
    HANDLE hMap;
};

class TGenericArray 
{
    public:

    TGenericArray();
    ~TGenericArray();

    int SetArrayValid();

    void ExchangeWith(TGenericArray & Target);
    void CopyFrom(TGenericArray & Source);

    void SetMaxItems_CHARS(DWORD NewMaxItemCount);
    void SetMaxItems_PATH_STOP(DWORD NewMaxItemCount);

    void InsertOneItem_CHAR(char OneChar);
    void InsertOneItem_PATH_STOP(PATH_STOP & NewItem);

    void sub_19583A0(DWORD NewItemCount);

    int LoadDwordsArray(TByteStream & InStream);
    int LoadTripletsArray(TByteStream & InStream);
    int LoadByteArray(TByteStream & InStream);
    int LoadFragmentInfos(TByteStream & InStream);
    int LoadStrings(TByteStream & InStream);

    int LoadDwordsArray_Copy(TByteStream & InStream);
    int LoadTripletsArray_Copy(TByteStream & InStream);
    int LoadBytes_Copy(TByteStream & InStream);
    int LoadFragmentInfos_Copy(TByteStream & InStream);
    int LoadStringsWithCopy(TByteStream & InStream);

    ARRAY_POINTER DataBuffer;
    ARRAY_POINTER FirstValid;

    ARRAY_POINTER ArrayPointer;
    DWORD ItemCount;                    // Number of items in the array
    DWORD MaxItemCount;                 // Capacity of the array
    bool  bIsValidArray;
};

class TBitEntryArray : public TGenericArray 
{
    public:

    TBitEntryArray();
    ~TBitEntryArray();

    DWORD GetBitEntry(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 = (Uint32Array[dwItemIndex + 1] << (0x20 - dwStartBit)) | (Uint32Array[dwItemIndex] >> dwStartBit);
        }
        else
        {
            dwResult = Uint32Array[dwItemIndex] >> dwStartBit;
        }

        // Now we also need to mask the result by the bit mask
        return dwResult & EntryBitMask;
    }

    void ExchangeWith(TBitEntryArray & Target);
    int LoadFromStream(TByteStream & InStream);
    int LoadFromStream_Exchange(TByteStream & InStream);

    DWORD BitsPerEntry;
    DWORD EntryBitMask;
    DWORD TotalEntries;
};

class TStruct40
{
    public:

    TStruct40();

    void InitSearchBuffers();

    TGenericArray array_00;
    TGenericArray PathStops;            // Array of path checkpoints
    DWORD ItemIndex;                    // Current name fragment: Index to various tables
    DWORD CharIndex;
    DWORD ItemCount;
    DWORD SearchPhase;                  // 0 = initializing, 2 = searching, 4 = finished
};

class TMndxFindResult
{
    public:

    TMndxFindResult();
    ~TMndxFindResult();

    int CreateStruct40();
    void FreeStruct40();

    int SetSearchPath(const char * szNewSearchPath, size_t cchNewSearchPath);

    const char * szSearchMask;          // Search mask without wioldcards
    size_t cchSearchMask;               // Length of the search mask
    DWORD field_8;
    const char * szFoundPath;           // Found path name
    size_t cchFoundPath;                // Length of the found path name
    DWORD FileNameIndex;                // Index of the file name
    TStruct40 * pStruct40;
};

class TSparseArray
{
    public:

    TSparseArray();

    void ExchangeWith(TSparseArray & TargetObject);
    int LoadFromStream(TByteStream & InStream);
    int LoadFromStream_Exchange(TByteStream & InStream);

    // Returns true if the item at n-th position is present
    DWORD IsItemPresent(DWORD ItemIndex)
    {
        return (ItemBits.Uint32Array[ItemIndex >> 0x05] & (1 << (ItemIndex & 0x1F)));
    }

    DWORD GetItemValue(DWORD ItemIndex);

    TGenericArray ItemBits;             // Bit array for each item (1 = item is present)
    DWORD TotalItemCount;               // Total number of items in the array
    DWORD ValidItemCount;               // Number of present items in the array
    TGenericArray BaseValues;           // Array of base values for item indexes >= 0x200
    TGenericArray ArrayDwords_38;
    TGenericArray ArrayDwords_50;
};

class TNameIndexStruct
{
    public:

    TNameIndexStruct();
    ~TNameIndexStruct();

    bool CheckNameFragment(TMndxFindResult * pStruct1C, DWORD dwFragOffs);
    bool CheckAndCopyNameFragment(TMndxFindResult * pStruct1C, DWORD dwFragOffs);
    void CopyNameFragment(TMndxFindResult * pStruct1C, DWORD dwFragOffs);

    void ExchangeWith(TNameIndexStruct & Target);
    int LoadFromStream(TByteStream & InStream);
    int LoadFromStream_Exchange(TByteStream & InStream);

    TGenericArray NameFragments;  
    TSparseArray Struct68;  
};

class TStruct10
{
    public:
    
    TStruct10();
    
    void CopyFrom(TStruct10 & Target);
    int sub_1956FD0(DWORD dwBitMask);
    int sub_1957050(DWORD dwBitMask);
    int sub_19572E0(DWORD dwBitMask);
    int sub_1957800(DWORD dwBitMask);

    DWORD field_0;
    DWORD field_4;
    DWORD field_8;
    DWORD field_C;
};

class TFileNameDatabasePtr
{
    public:

    TFileNameDatabasePtr();
    ~TFileNameDatabasePtr();

    int FindFileInDatabase(TMndxFindResult * pStruct1C);
    int sub_1956CE0(TMndxFindResult * pStruct1C, bool * pbFindResult);

    int GetFileNameCount(PDWORD PtrFileNameCount);
    int CreateDatabase(LPBYTE pbMarData, DWORD cbMarData);
    int SetDatabase(TFileNameDatabase * pNewDB);

    TFileNameDatabase * pDB;
};

class TFileNameDatabase
{
    public:
    
    TFileNameDatabase();

    void ExchangeWith(TFileNameDatabase & Target);
    int LoadFromStream(TByteStream & InStream);
    int LoadFromStream_Exchange(TByteStream & InStream);

    DWORD sub_1959CB0(DWORD dwHashValue);
    DWORD sub_1959F50(DWORD arg_0);

    // Retrieves the name fragment distance
    // HOTS: 19573D0/inlined
    DWORD GetNameFragmentOffsetEx(DWORD LoBitsIndex, DWORD HiBitsIndex)
    {
        return (FrgmDist_HiBits.GetBitEntry(HiBitsIndex) << 0x08) | FrgmDist_LoBits.ByteArray[LoBitsIndex];
    }

    // HOTS: 1957350, inlined
    DWORD GetNameFragmentOffset(DWORD LoBitsIndex)
    {
        return GetNameFragmentOffsetEx(LoBitsIndex, Struct68_D0.GetItemValue(LoBitsIndex));
    }

    bool sub_1957B80(TMndxFindResult * pStruct1C, DWORD dwKey);
    bool CheckNextPathFragment(TMndxFindResult * pStruct1C);
    bool FindFileInDatabase(TMndxFindResult * pStruct1C);

    void sub_1958D70(TMndxFindResult * pStruct1C, DWORD arg_4);
    bool sub_1959010(TMndxFindResult * pStruct1C, DWORD arg_4);
    bool sub_1958B00(TMndxFindResult * pStruct1C);
    bool sub_1959460(TMndxFindResult * pStruct1C);

    TSparseArray Struct68_00;
    TSparseArray FileNameIndexes;               // Array of file name indexes
    TSparseArray Struct68_D0;

    // This pair of arrays serves for fast conversion from name hash to fragment offset
    TGenericArray  FrgmDist_LoBits;             // Array of lower 8 bits of name fragment offset
    TBitEntryArray FrgmDist_HiBits;             // Array of upper x bits of name fragment offset

    TNameIndexStruct IndexStruct_174;
    TFileNameDatabasePtr NextDB;

    TGenericArray NameFragTable;

    DWORD NameFragIndexMask;
    DWORD field_214;
    TStruct10 Struct10;
    TByteStream MarStream;
};

typedef struct _MAR_FILE
{
    TFileNameDatabasePtr * pDatabasePtr;
    LPBYTE pbMarData;
    DWORD cbMarData;
} MAR_FILE, *PMAR_FILE;

//-----------------------------------------------------------------------------
// Macros

// Returns nonzero if the name fragment match is a single-char match
inline bool IS_SINGLE_CHAR_MATCH(TGenericArray & Table, DWORD ItemIndex)
{
    return ((Table.NameFragArray[ItemIndex].FragOffs & 0xFFFFFF00) == 0xFFFFFF00);
}

//-----------------------------------------------------------------------------
// CASC functions related to MNDX

int  LoadMndxRootFile(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
PCASC_PACKAGE FindMndxPackage(TCascStorage * hs, const char * szFileName);
int  SearchMndxInfo(PCASC_MNDX_INFO pMndxInfo, const char * szFileName, DWORD dwPackage, PCASC_ROOT_KEY_INFO pFoundInfo);
bool DoStorageSearch_MNDX(TCascSearch * pSearch, PCASC_FIND_DATA pFindData);
void FreeMndxInfo(PCASC_MNDX_INFO pMndxInfo);

#endif  // __CASC_MNDX_ROOT__