aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascRootFile_Diablo3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/CascRootFile_Diablo3.cpp')
-rw-r--r--dep/CascLib/src/CascRootFile_Diablo3.cpp219
1 files changed, 82 insertions, 137 deletions
diff --git a/dep/CascLib/src/CascRootFile_Diablo3.cpp b/dep/CascLib/src/CascRootFile_Diablo3.cpp
index bbe369c7646..c29f13f74a9 100644
--- a/dep/CascLib/src/CascRootFile_Diablo3.cpp
+++ b/dep/CascLib/src/CascRootFile_Diablo3.cpp
@@ -195,33 +195,6 @@ struct TDiabloRoot : public TFileTreeRoot
FreeLoadingStuff();
}
- void AppendBackslashToTotalPath(PATH_BUFFER & PathBuffer)
- {
- if(PathBuffer.szPtr < PathBuffer.szEnd)
- {
- PathBuffer.szPtr[0] = '\\';
- PathBuffer.szPtr++;
- }
- }
-
- void AppendPathToTotalPath(PATH_BUFFER & PathBuffer, const char * szFileName, const char * szFileEnd)
- {
- char * szPathPtr = PathBuffer.szPtr;
- size_t nLength = (szFileEnd - szFileName);
-
- // Append the name
- if((szPathPtr + nLength) < PathBuffer.szEnd)
- {
- memcpy(szPathPtr, szFileName, nLength);
- szPathPtr += nLength;
- }
-
- // Append zero terminator
- if(szPathPtr < PathBuffer.szEnd)
- szPathPtr[0] = 0;
- PathBuffer.szPtr = szPathPtr;
- }
-
PDIABLO3_ASSET_INFO GetAssetInfo(DWORD dwAssetIndex)
{
if(dwAssetIndex < DIABLO3_ASSET_COUNT && Assets[dwAssetIndex].szDirectoryName != NULL)
@@ -404,52 +377,28 @@ struct TDiabloRoot : public TFileTreeRoot
}
bool CreateAssetFileName(
- PATH_BUFFER & PathBuffer,
+ CASC_PATH<char> & PathBuffer,
DWORD FileIndex,
DWORD SubIndex)
{
PDIABLO3_CORE_TOC_ENTRY pTocEntry;
PDIABLO3_ASSET_INFO pAssetInfo;
- const char * szPackageName = NULL;
- const char * szPlainName;
- const char * szFormat;
- char * szPathEnd = PathBuffer.szEnd;
- char * szPathPtr = PathBuffer.szPtr;
- size_t nLength = 0;
+ LPCSTR szPackageName = NULL;
+ LPCSTR szPlainName;
+ LPCSTR szFormat;
+ char szBuffer[MAX_PATH];
// Find and check the entry
pTocEntry = pFileIndices + FileIndex;
if(pTocEntry->FileIndex == FileIndex)
{
// Retrieve the asset information
+ szPlainName = (LPCSTR)(pbCoreTocData + pTocEntry->NameOffset);
pAssetInfo = GetAssetInfo(pTocEntry->AssetIndex);
-
- // Either use the asset info for getting the folder name or supply "Asset##"
- if(pAssetInfo != NULL)
- {
- CascStrCopy(szPathPtr, (szPathEnd - szPathPtr), pAssetInfo->szDirectoryName);
- szPathPtr += strlen(szPathPtr);
- }
- else
- {
- szPathPtr[0] = 'A';
- szPathPtr[1] = 's';
- szPathPtr[2] = 's';
- szPathPtr[3] = 'e';
- szPathPtr[4] = 't';
- szPathPtr[5] = (char)('0' + (pTocEntry->AssetIndex / 10));
- szPathPtr[6] = (char)('0' + (pTocEntry->AssetIndex % 10));
- szPathPtr += 7;
- }
-
- // Put the backslash
- if(szPathPtr < PathBuffer.szEnd)
- *szPathPtr++ = '\\';
// Construct the file name, up to the extension. Don't include the '.'
- szPlainName = (const char *)(pbCoreTocData + pTocEntry->NameOffset);
szFormat = (SubIndex != CASC_INVALID_INDEX) ? "%s\\%04u" : "%s";
- nLength = CascStrPrintf(szPathPtr, (szPathEnd - szPathPtr), szFormat, szPlainName, SubIndex);
+ CascStrPrintf(szBuffer, _countof(szBuffer), szFormat, szPlainName, SubIndex);
// Try to fixup the file extension from the package name.
// File extensions are not predictable because for subitems,
@@ -466,27 +415,41 @@ struct TDiabloRoot : public TFileTreeRoot
// We use the Base\Data_D3\PC\Misc\Packages.dat for real file extensions, where possible
//
- if(PackagesMap.IsInitialized() && pAssetInfo != NULL)
+ if(pAssetInfo != NULL)
{
// Retrieve the asset name
- szPackageName = FindPackageName(pAssetInfo->szDirectoryName, szPathPtr);
+ szPackageName = FindPackageName(pAssetInfo->szDirectoryName, szBuffer);
if(szPackageName != NULL)
{
- CascStrCopy(PathBuffer.szPtr, (PathBuffer.szEnd - PathBuffer.szPtr), szPackageName);
+ PathBuffer.AppendString(szPackageName, false);
return true;
}
+
+ // Append the directory name
+ PathBuffer.AppendString(pAssetInfo->szDirectoryName, false);
+ }
+ else
+ {
+ // Append generic name "Asset##" and continue
+ PathBuffer.AppendString("Asset", false);
+ PathBuffer.AppendChar((char)('0' + (pTocEntry->AssetIndex / 10)));
+ PathBuffer.AppendChar((char)('0' + (pTocEntry->AssetIndex % 10)));
}
- // Use the extension from the AssetInfo, if we have any
+ // Append the content of the buffer
+ PathBuffer.AppendString(szBuffer, true);
+
+ // If we have an extension, use it. Otherwise, supply "a##"
if(pAssetInfo != NULL && pAssetInfo->szExtension != NULL)
{
- szPathPtr[nLength++] = '.';
- CascStrCopy(szPathPtr + nLength, (szPathEnd - (szPathPtr + nLength)), pAssetInfo->szExtension);
- return true;
+ PathBuffer.AppendChar('.');
+ PathBuffer.AppendString(pAssetInfo->szExtension, false);
+ }
+ else
+ {
+ CascStrPrintf(szBuffer, _countof(szBuffer), ".a%02u", pTocEntry->AssetIndex);
+ PathBuffer.AppendString(szBuffer, false);
}
-
- // Otherwise, supply "a##"
- CascStrPrintf(szPathPtr + nLength, (szPathEnd - (szPathPtr + nLength)), ".a%02u", pTocEntry->AssetIndex);
return true;
}
@@ -494,13 +457,14 @@ struct TDiabloRoot : public TFileTreeRoot
}
// Parse the asset entries
- int ParseAssetEntries(
+ DWORD ParseAssetEntries(
TCascStorage * hs,
DIABLO3_DIRECTORY & Directory,
- PATH_BUFFER & PathBuffer)
+ CASC_PATH<char> & PathBuffer)
{
PDIABLO3_ASSET_ENTRY pEntry = (PDIABLO3_ASSET_ENTRY)Directory.pbAssetEntries;
PCASC_CKEY_ENTRY pCKeyEntry;
+ size_t nSavePos = PathBuffer.Save();
DWORD dwEntries = Directory.dwAssetEntries;
// Do nothing if there is no entries
@@ -516,8 +480,11 @@ struct TDiabloRoot : public TFileTreeRoot
if(CreateAssetFileName(PathBuffer, pEntry->FileIndex, CASC_INVALID_INDEX))
{
// Insert the entry to the file tree
- FileTree.InsertByName(pCKeyEntry, PathBuffer.szBegin);
+ FileTree.InsertByName(pCKeyEntry, PathBuffer);
}
+
+ // Restore the path buffer position
+ PathBuffer.Restore(nSavePos);
}
}
}
@@ -525,13 +492,14 @@ struct TDiabloRoot : public TFileTreeRoot
return ERROR_SUCCESS;
}
- int ParseAssetAndIdxEntries(
+ DWORD ParseAssetAndIdxEntries(
TCascStorage * hs,
DIABLO3_DIRECTORY & Directory,
- PATH_BUFFER & PathBuffer)
+ CASC_PATH<char> & PathBuffer)
{
PDIABLO3_ASSETIDX_ENTRY pEntry = (PDIABLO3_ASSETIDX_ENTRY)Directory.pbAssetIdxEntries;
PCASC_CKEY_ENTRY pCKeyEntry;
+ size_t nSavePos = PathBuffer.Save();
DWORD dwEntries = Directory.dwAssetIdxEntries;
// Do nothing if there is no entries
@@ -548,8 +516,11 @@ struct TDiabloRoot : public TFileTreeRoot
{
// Insert the entry to the file tree
// fprintf(fp, "%08u %04u %s\n", pEntry->FileIndex, pEntry->SubIndex, PathBuffer.szBegin);
- FileTree.InsertByName(pCKeyEntry, PathBuffer.szBegin);
+ FileTree.InsertByName(pCKeyEntry, PathBuffer);
}
+
+ // Restore the path buffer position
+ PathBuffer.Restore(nSavePos);
}
}
}
@@ -558,16 +529,16 @@ struct TDiabloRoot : public TFileTreeRoot
}
// Parse the named entries of all folders
- int ParseDirectory_Phase1(
+ DWORD ParseDirectory_Phase1(
TCascStorage * hs,
DIABLO3_DIRECTORY & Directory,
- PATH_BUFFER & PathBuffer,
+ CASC_PATH<char> & PathBuffer,
bool bIsRootDirectory)
{
DIABLO3_NAMED_ENTRY NamedEntry;
- char * szSavePtr = PathBuffer.szPtr;
size_t nFolderIndex = 0;
- int nError = ERROR_SUCCESS;
+ size_t nSavePos = PathBuffer.Save();
+ DWORD dwErrCode = ERROR_SUCCESS;
// Do nothing if there is no named headers
if(Directory.pbNamedEntries && Directory.dwNamedEntries)
@@ -587,33 +558,32 @@ struct TDiabloRoot : public TFileTreeRoot
return ERROR_BAD_FORMAT;
// Append the path fragment to the total path
- AppendPathToTotalPath(PathBuffer, NamedEntry.szFileName, NamedEntry.szFileEnd);
+ PathBuffer.AppendStringN(NamedEntry.szFileName, (NamedEntry.szFileEnd - NamedEntry.szFileName), true);
// Check whether the file exists in the storage
pCKeyEntry = FindCKeyEntry_CKey(hs, NamedEntry.pCKey->Value);
if(pCKeyEntry != NULL)
{
// Create file node belonging to this folder
- pFileNode = FileTree.InsertByName(pCKeyEntry, PathBuffer.szBegin);
+ pFileNode = FileTree.InsertByName(pCKeyEntry, PathBuffer);
dwNodeIndex = (DWORD)FileTree.IndexOf(pFileNode);
// If we are parsing root folder, we also need to load the data of the sub-folder file
if(bIsRootDirectory)
{
// Mark the node as directory
- AppendBackslashToTotalPath(PathBuffer);
pCKeyEntry->Flags |= CASC_CE_FOLDER_ENTRY;
pFileNode->Flags |= CFN_FLAG_FOLDER;
// Load the sub-directory file
- nError = LoadDirectoryFile(hs, RootFolders[nFolderIndex], pCKeyEntry);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = LoadDirectoryFile(hs, RootFolders[nFolderIndex], pCKeyEntry);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Parse the sub-directory file
- nError = ParseDirectory_Phase1(hs, RootFolders[nFolderIndex], PathBuffer, false);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = ParseDirectory_Phase1(hs, RootFolders[nFolderIndex], PathBuffer, false);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Also save the item pointer and increment the folder index
RootFolders[nFolderIndex].dwNodeIndex = dwNodeIndex;
@@ -621,20 +591,19 @@ struct TDiabloRoot : public TFileTreeRoot
}
// Restore the path pointer
- PathBuffer.szPtr = szSavePtr;
- szSavePtr[0] = 0;
+ PathBuffer.Restore(nSavePos);
}
}
}
- return nError;
+ return dwErrCode;
}
// Parse the nameless entries of all folders
int ParseDirectory_Phase2(TCascStorage * hs)
{
- PATH_BUFFER PathBuffer;
- char szPathBuffer[MAX_PATH];
+ CASC_PATH<char> PathBuffer;
+ char szBuffer[MAX_PATH];
// Parse each root subdirectory
for(size_t i = 0; i < DIABLO3_MAX_ROOT_FOLDERS; i++)
@@ -642,16 +611,11 @@ struct TDiabloRoot : public TFileTreeRoot
// Is this root folder loaded?
if(RootFolders[i].pbDirectoryData != NULL)
{
- PathBuffer.szBegin = szPathBuffer;
- PathBuffer.szPtr = szPathBuffer;
- PathBuffer.szEnd = szPathBuffer + MAX_PATH - 1;
- szPathBuffer[0] = 0;
-
// Retrieve the parent name
if(RootFolders[i].dwNodeIndex != 0)
{
- FileTree.PathAt(szPathBuffer, MAX_PATH, RootFolders[i].dwNodeIndex);
- PathBuffer.szPtr = PathBuffer.szBegin + strlen(szPathBuffer);
+ FileTree.PathAt(szBuffer, _countof(szBuffer), RootFolders[i].dwNodeIndex);
+ PathBuffer.SetPathRoot(szBuffer);
}
// Array of DIABLO3_ASSET_ENTRY entries.
@@ -671,12 +635,12 @@ struct TDiabloRoot : public TFileTreeRoot
// Creates an array of DIABLO3_CORE_TOC_ENTRY entries indexed by FileIndex
// Used as lookup table when we have FileIndex and need Asset+PlainName
- int CreateMapOfFileIndices(TCascStorage * hs, const char * szFileName)
+ DWORD CreateMapOfFileIndices(TCascStorage * hs, const char * szFileName)
{
PDIABLO3_CORE_TOC_HEADER pTocHeader = NULL;
LPBYTE pbCoreTocPtr = pbCoreTocFile;
DWORD dwMaxFileIndex = 0;
- int nError = ERROR_CAN_NOT_COMPLETE;
+ DWORD dwErrCode = ERROR_CAN_NOT_COMPLETE;
// Load the entire file to memory
pbCoreTocFile = pbCoreTocPtr = LoadFileToMemory(hs, szFileName, &cbCoreTocFile);
@@ -693,7 +657,7 @@ struct TDiabloRoot : public TFileTreeRoot
return ERROR_SUCCESS;
// Allocate and populate the array of DIABLO3_CORE_TOC_ENTRYs
- pFileIndices = CASC_ALLOC(DIABLO3_CORE_TOC_ENTRY, dwMaxFileIndex + 1);
+ pFileIndices = CASC_ALLOC<DIABLO3_CORE_TOC_ENTRY>(dwMaxFileIndex + 1);
if(pFileIndices != NULL)
{
// Initialize all entries to invalid
@@ -720,10 +684,10 @@ struct TDiabloRoot : public TFileTreeRoot
// Save the file to the root handler
pbCoreTocData = pbCoreTocPtr;
nFileIndices = dwMaxFileIndex;
- nError = ERROR_SUCCESS;
+ dwErrCode = ERROR_SUCCESS;
}
}
- return nError;
+ return dwErrCode;
}
// Packages.dat contains a list of full file names (without locale prefix).
@@ -740,19 +704,7 @@ struct TDiabloRoot : public TFileTreeRoot
{
LPBYTE pbPackagesPtr = pbPackagesDat;
LPBYTE pbPackagesEnd = pbPackagesDat + cbPackagesDat;
-/*
- LPBYTE pbPackagesPtr = pbPackagesDat + 8;
- FILE * fp = fopen("E:\\Packages.dat", "wt");
- if(fp != NULL)
- {
- while(pbPackagesPtr < pbPackagesEnd)
- {
- fprintf(fp, "%s\n", pbPackagesPtr);
- pbPackagesPtr = pbPackagesPtr + strlen((char *)pbPackagesPtr) + 1;
- }
- fclose(fp);
- }
-*/
+
// Get the header. There is just Signature + NumberOfNames
if((pbPackagesPtr = CaptureInteger32(pbPackagesPtr, pbPackagesEnd, &Signature)) == NULL)
return ERROR_BAD_FORMAT;
@@ -783,27 +735,20 @@ struct TDiabloRoot : public TFileTreeRoot
return ERROR_SUCCESS;
}
- int Load(TCascStorage * hs, DIABLO3_DIRECTORY & RootDirectory)
+ DWORD Load(TCascStorage * hs, DIABLO3_DIRECTORY & RootDirectory)
{
- PATH_BUFFER PathBuffer;
- char szPathBuffer[MAX_PATH];
- int nError;
-
- // Initialize path buffer and go parse the directory
- PathBuffer.szBegin = szPathBuffer;
- PathBuffer.szPtr = szPathBuffer;
- PathBuffer.szEnd = szPathBuffer + MAX_PATH;
- szPathBuffer[0] = 0;
+ CASC_PATH<char> PathBuffer;
+ DWORD dwErrCode;
// Always parse the named entries first. They always point to a file.
// These are entries with arbitrary names, and they do not belong to an asset
- nError = ParseDirectory_Phase1(hs, RootDirectory, PathBuffer, true);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = ParseDirectory_Phase1(hs, RootDirectory, PathBuffer, true);
+ if(dwErrCode == ERROR_SUCCESS)
{
// The asset entries in the ROOT file don't contain file names, but indices.
// To convert a file index to a file name, we need to load and parse the "Base\\CoreTOC.dat" file.
- nError = CreateMapOfFileIndices(hs, "Base\\CoreTOC.dat");
- if(nError == ERROR_SUCCESS)
+ dwErrCode = CreateMapOfFileIndices(hs, "Base\\CoreTOC.dat");
+ if(dwErrCode == ERROR_SUCCESS)
{
// The file "Base\Data_D3\PC\Misc\Packages.dat" contains the file names
// (without level-0 and level-1 directory).
@@ -818,7 +763,7 @@ struct TDiabloRoot : public TFileTreeRoot
FreeLoadingStuff();
}
- return nError;
+ return dwErrCode;
}
void FreeLoadingStuff()
@@ -860,11 +805,11 @@ struct TDiabloRoot : public TFileTreeRoot
//-----------------------------------------------------------------------------
// Public functions
-int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
+DWORD RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
{
TDiabloRoot * pRootHandler = NULL;
DIABLO3_DIRECTORY RootDirectory;
- int nError = ERROR_BAD_FORMAT;
+ DWORD dwErrCode = ERROR_BAD_FORMAT;
// Verify the header of the ROOT file
if(TDiabloRoot::CaptureDirectoryData(RootDirectory, pbRootFile, cbRootFile) != NULL)
@@ -874,8 +819,8 @@ int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRoot
if(pRootHandler != NULL)
{
// Load the root directory. If load failed, we free the object
- nError = pRootHandler->Load(hs, RootDirectory);
- if(nError != ERROR_SUCCESS)
+ dwErrCode = pRootHandler->Load(hs, RootDirectory);
+ if(dwErrCode != ERROR_SUCCESS)
{
delete pRootHandler;
pRootHandler = NULL;
@@ -885,5 +830,5 @@ int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRoot
// Assign the root directory (or NULL) and return error
hs->pRootHandler = pRootHandler;
- return nError;
+ return dwErrCode;
}