diff options
Diffstat (limited to 'dep/CascLib/src/CascRootFile_Diablo3.cpp')
-rw-r--r-- | dep/CascLib/src/CascRootFile_Diablo3.cpp | 151 |
1 files changed, 66 insertions, 85 deletions
diff --git a/dep/CascLib/src/CascRootFile_Diablo3.cpp b/dep/CascLib/src/CascRootFile_Diablo3.cpp index c29f13f74a9..c1d09c3ab23 100644 --- a/dep/CascLib/src/CascRootFile_Diablo3.cpp +++ b/dep/CascLib/src/CascRootFile_Diablo3.cpp @@ -64,11 +64,26 @@ typedef struct _DIABLO3_CORE_TOC_ENTRY } DIABLO3_CORE_TOC_ENTRY, *PDIABLO3_CORE_TOC_ENTRY; +// Structure for conversion DirectoryID -> Directory name +typedef struct _DIABLO3_ASSET_INFO +{ + const char * szDirectoryName; // Directory name + const char * szExtension; + +} DIABLO3_ASSET_INFO; +typedef const DIABLO3_ASSET_INFO * PDIABLO3_ASSET_INFO; + // In-memory structure of parsed directory data -typedef struct _DIABLO3_DIRECTORY +struct DIABLO3_DIRECTORY { - LPBYTE pbDirectoryData; // The begin of the directory data block - LPBYTE pbDirectoryEnd; // The end of the directory data block + DIABLO3_DIRECTORY() + { + pbAssetEntries = pbAssetIdxEntries = pbNamedEntries = NULL; + dwAssetEntries = dwAssetIdxEntries = dwNamedEntries = 0; + dwNodeIndex = 0; + } + + CASC_BLOB Data; // The complete copy of the directory data LPBYTE pbAssetEntries; // Pointer to asset entries without subitem number. Example: "SoundBank\SoundFile.smp" LPBYTE pbAssetIdxEntries; // Pointer to asset entries with subitem number LPBYTE pbNamedEntries; // Pointer to named entries. These are for files with arbitrary names, and they do not belong to an asset @@ -76,16 +91,7 @@ typedef struct _DIABLO3_DIRECTORY DWORD dwAssetIdxEntries; DWORD dwNamedEntries; DWORD dwNodeIndex; // Index of file node for this folder -} DIABLO3_DIRECTORY, *PDIABLO3_DIRECTORY; - -// Structure for conversion DirectoryID -> Directory name -typedef struct _DIABLO3_ASSET_INFO -{ - const char * szDirectoryName; // Directory name - const char * szExtension; - -} DIABLO3_ASSET_INFO; -typedef const DIABLO3_ASSET_INFO * PDIABLO3_ASSET_INFO; +}; //----------------------------------------------------------------------------- // Local variables @@ -175,16 +181,12 @@ struct TDiabloRoot : public TFileTreeRoot TDiabloRoot() : TFileTreeRoot(0) { memset(RootFolders, 0, sizeof(RootFolders)); - pFileIndices = NULL; - pbCoreTocFile = NULL; pbCoreTocData = NULL; + pFileIndices = NULL; nFileIndices = 0; - cbCoreTocFile = 0; // Map for searching a real file extension memset(&PackagesMap, 0, sizeof(CASC_MAP)); - pbPackagesDat = NULL; - cbPackagesDat = 0; // We have file names and return CKey as result of search dwFeatures |= (CASC_FEATURE_FILE_NAMES | CASC_FEATURE_ROOT_CKEY); @@ -212,26 +214,24 @@ struct TDiabloRoot : public TFileTreeRoot return (char *)PackagesMap.FindString(szFileName, szFileName + nLength); } - LPBYTE LoadFileToMemory(TCascStorage * hs, const char * szFileName, DWORD * pcbFileData) + DWORD LoadFileToMemory(TCascStorage * hs, const char * szFileName, CASC_BLOB & FileData) { PCASC_CKEY_ENTRY pCKeyEntry; - LPBYTE pbFileData = NULL; + DWORD dwErrCode = ERROR_FILE_NOT_FOUND; // Try to find CKey for the file pCKeyEntry = GetFile(hs, szFileName); if(pCKeyEntry != NULL) - pbFileData = LoadInternalFileToMemory(hs, pCKeyEntry, pcbFileData); - - return pbFileData; + dwErrCode = LoadInternalFileToMemory(hs, pCKeyEntry, FileData); + return dwErrCode; } - static LPBYTE CaptureDirectoryData( + static DWORD CaptureDirectoryData( DIABLO3_DIRECTORY & DirHeader, - LPBYTE pbDirectory, - DWORD cbDirectory) + CASC_BLOB & Directory) { - LPBYTE pbDirectoryData = pbDirectory; - LPBYTE pbDataEnd = pbDirectory + cbDirectory; + LPBYTE pbDirectory; + LPBYTE pbDataEnd; DWORD Signature = 0; // @@ -245,13 +245,15 @@ struct TDiabloRoot : public TFileTreeRoot // 7) Array of DIABLO3_NAMED_ENTRY entries // - // Prepare the header signature - memset(&DirHeader, 0, sizeof(DIABLO3_DIRECTORY)); + // Clone the input data + DirHeader.Data.MoveFrom(Directory); + pbDirectory = DirHeader.Data.pbData; + pbDataEnd = DirHeader.Data.End(); // Get the header signature pbDirectory = CaptureInteger32(pbDirectory, pbDataEnd, &Signature); if((pbDirectory == NULL) || (Signature != CASC_DIABLO3_ROOT_SIGNATURE && Signature != DIABLO3_SUBDIR_SIGNATURE)) - return NULL; + return ERROR_BAD_FORMAT; // Subdirectories have extra two arrays if(Signature == DIABLO3_SUBDIR_SIGNATURE) @@ -259,37 +261,33 @@ struct TDiabloRoot : public TFileTreeRoot // Capture the number of DIABLO3_ASSET_ENTRY items pbDirectory = CaptureInteger32(pbDirectory, pbDataEnd, &DirHeader.dwAssetEntries); if(pbDirectory == NULL) - return NULL; + return ERROR_BAD_FORMAT; // Capture the array of DIABLO3_ASSET_ENTRY pbDirectory = CaptureArray(pbDirectory, pbDataEnd, &DirHeader.pbAssetEntries, DIABLO3_ASSET_ENTRY, DirHeader.dwAssetEntries); if(pbDirectory == NULL) - return NULL; + return ERROR_BAD_FORMAT; // Capture the number of DIABLO3_ASSETIDX_ENTRY items pbDirectory = CaptureInteger32(pbDirectory, pbDataEnd, &DirHeader.dwAssetIdxEntries); if(pbDirectory == NULL) - return NULL; + return ERROR_BAD_FORMAT; // Capture the array of DIABLO3_ASSETIDX_ENTRY pbDirectory = CaptureArray(pbDirectory, pbDataEnd, &DirHeader.pbAssetIdxEntries, DIABLO3_ASSETIDX_ENTRY, DirHeader.dwAssetIdxEntries); if(pbDirectory == NULL) - return NULL; + return ERROR_BAD_FORMAT; } // Capture the number of DIABLO3_NAMED_ENTRY array pbDirectory = CaptureInteger32(pbDirectory, pbDataEnd, &DirHeader.dwNamedEntries); if(pbDirectory == NULL) - return NULL; + return ERROR_BAD_FORMAT; // Note: Do not capture the array here. We will do that later, // when we will be parsing the directory DirHeader.pbNamedEntries = pbDirectory; - - // Put the directory range - DirHeader.pbDirectoryData = pbDirectoryData; - DirHeader.pbDirectoryEnd = pbDirectoryData + cbDirectory; - return pbDirectory; + return ERROR_SUCCESS; } LPBYTE CaptureCoreTocHeader( @@ -357,22 +355,17 @@ struct TDiabloRoot : public TFileTreeRoot return NULL; } - int LoadDirectoryFile(TCascStorage * hs, DIABLO3_DIRECTORY & DirHeader, PCASC_CKEY_ENTRY pCKeyEntry) + DWORD LoadDirectoryFile(TCascStorage * hs, DIABLO3_DIRECTORY & DirHeader, PCASC_CKEY_ENTRY pCKeyEntry) { - LPBYTE pbData; - DWORD cbData = 0; + CASC_BLOB Data; + DWORD dwErrCode; - // Load the n-th folder - pbData = LoadInternalFileToMemory(hs, pCKeyEntry, &cbData); - if(pbData && cbData) - { - if(CaptureDirectoryData(DirHeader, pbData, cbData) == NULL) - { - // Clear the directory - CASC_FREE(pbData); - return ERROR_BAD_FORMAT; - } - } + // Load the n-th folder, if exists + dwErrCode = LoadInternalFileToMemory(hs, pCKeyEntry, Data); + if(dwErrCode == ERROR_SUCCESS && Data.cbData) + return CaptureDirectoryData(DirHeader, Data); + + // If the folder is not there, ignore the error return ERROR_SUCCESS; } @@ -546,7 +539,7 @@ struct TDiabloRoot : public TFileTreeRoot PCASC_CKEY_ENTRY pCKeyEntry; PCASC_FILE_NODE pFileNode; LPBYTE pbDataPtr = Directory.pbNamedEntries; - LPBYTE pbDataEnd = Directory.pbDirectoryEnd; + LPBYTE pbDataEnd = Directory.Data.End(); DWORD dwNodeIndex; // Parse all entries @@ -609,7 +602,7 @@ struct TDiabloRoot : public TFileTreeRoot for(size_t i = 0; i < DIABLO3_MAX_ROOT_FOLDERS; i++) { // Is this root folder loaded? - if(RootFolders[i].pbDirectoryData != NULL) + if(RootFolders[i].Data.pbData != NULL) { // Retrieve the parent name if(RootFolders[i].dwNodeIndex != 0) @@ -638,15 +631,15 @@ struct TDiabloRoot : public TFileTreeRoot DWORD CreateMapOfFileIndices(TCascStorage * hs, const char * szFileName) { PDIABLO3_CORE_TOC_HEADER pTocHeader = NULL; - LPBYTE pbCoreTocPtr = pbCoreTocFile; DWORD dwMaxFileIndex = 0; - DWORD dwErrCode = ERROR_CAN_NOT_COMPLETE; + DWORD dwErrCode; // Load the entire file to memory - pbCoreTocFile = pbCoreTocPtr = LoadFileToMemory(hs, szFileName, &cbCoreTocFile); - if(pbCoreTocFile && cbCoreTocFile) + dwErrCode = LoadFileToMemory(hs, szFileName, CoreTocFile); + if(dwErrCode == ERROR_SUCCESS && CoreTocFile.cbData) { - LPBYTE pbCoreTocEnd = pbCoreTocFile + cbCoreTocFile; + LPBYTE pbCoreTocPtr = CoreTocFile.pbData; + LPBYTE pbCoreTocEnd = CoreTocFile.End(); // Capture the header if((pbCoreTocPtr = CaptureCoreTocHeader(&pTocHeader, &dwMaxFileIndex, pbCoreTocPtr, pbCoreTocEnd)) == NULL) @@ -693,17 +686,18 @@ struct TDiabloRoot : public TFileTreeRoot // Packages.dat contains a list of full file names (without locale prefix). // They are not sorted, nor they correspond to file IDs. // Does the sort order mean something? Perhaps we could use them as listfile? - int CreateMapOfRealNames(TCascStorage * hs, const char * szFileName) + DWORD CreateMapOfRealNames(TCascStorage * hs, const char * szFileName) { DWORD Signature = 0; DWORD NumberOfNames = 0; + DWORD dwErrCode; // Load the entire file to memory - pbPackagesDat = LoadFileToMemory(hs, szFileName, &cbPackagesDat); - if(pbPackagesDat && cbPackagesDat) + dwErrCode = LoadFileToMemory(hs, szFileName, PackagesDat); + if(dwErrCode == ERROR_SUCCESS && PackagesDat.cbData) { - LPBYTE pbPackagesPtr = pbPackagesDat; - LPBYTE pbPackagesEnd = pbPackagesDat + cbPackagesDat; + LPBYTE pbPackagesPtr = PackagesDat.pbData; + LPBYTE pbPackagesEnd = PackagesDat.End(); // Get the header. There is just Signature + NumberOfNames if((pbPackagesPtr = CaptureInteger32(pbPackagesPtr, pbPackagesEnd, &Signature)) == NULL) @@ -768,21 +762,11 @@ struct TDiabloRoot : public TFileTreeRoot void FreeLoadingStuff() { - // Free the captured root sub-directories - for(size_t i = 0; i < DIABLO3_MAX_SUBDIRS; i++) - CASC_FREE(RootFolders[i].pbDirectoryData); - // Free the package map PackagesMap.Free(); // Free the array of file indices CASC_FREE(pFileIndices); - - // Free the loaded CoreTOC.dat file - CASC_FREE(pbCoreTocFile); - - // Free the loaded Packages.dat file - CASC_FREE(pbPackagesDat); } // Array of root directory subdirectories @@ -791,32 +775,29 @@ struct TDiabloRoot : public TFileTreeRoot // Array of DIABLO3_TOC_ENTRY structures, sorted by the file index // Used for converting FileIndex -> Asset+PlainName during loading PDIABLO3_CORE_TOC_ENTRY pFileIndices; - LPBYTE pbCoreTocFile; + CASC_BLOB CoreTocFile; LPBYTE pbCoreTocData; size_t nFileIndices; - DWORD cbCoreTocFile; // Map for searching a real file extension + CASC_BLOB PackagesDat; CASC_MAP PackagesMap; - LPBYTE pbPackagesDat; - DWORD cbPackagesDat; }; //----------------------------------------------------------------------------- // Public functions -DWORD RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile) +DWORD RootHandler_CreateDiablo3(TCascStorage * hs, CASC_BLOB & RootFile) { TDiabloRoot * pRootHandler = NULL; DIABLO3_DIRECTORY RootDirectory; DWORD dwErrCode = ERROR_BAD_FORMAT; // Verify the header of the ROOT file - if(TDiabloRoot::CaptureDirectoryData(RootDirectory, pbRootFile, cbRootFile) != NULL) + if((dwErrCode = TDiabloRoot::CaptureDirectoryData(RootDirectory, RootFile)) == ERROR_SUCCESS) { // Allocate the root handler object - pRootHandler = new TDiabloRoot(); - if(pRootHandler != NULL) + if((pRootHandler = new TDiabloRoot()) != NULL) { // Load the root directory. If load failed, we free the object dwErrCode = pRootHandler->Load(hs, RootDirectory); |