int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask) { TRootHandler_WoW6 * pRootHandler; LPBYTE pbRootFileEnd = pbRootFile + cbRootFile; int nError; // Verify the size if(pbRootFile == NULL || cbRootFile <= sizeof(PFILE_LOCALE_BLOCK)) nError = ERROR_FILE_CORRUPT; // Allocate the root handler object hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_WoW6, 1); if(pRootHandler == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Fill-in the handler functions memset(pRootHandler, 0, sizeof(TRootHandler_WoW6)); pRootHandler->Insert = (ROOT_INSERT)WowHandler_Insert; pRootHandler->Search = (ROOT_SEARCH)WowHandler_Search; pRootHandler->EndSearch = (ROOT_ENDSEARCH)WowHandler_EndSearch; pRootHandler->GetKey = (ROOT_GETKEY)WowHandler_GetKey; pRootHandler->Close = (ROOT_CLOSE)WowHandler_Close; #ifdef _DEBUG pRootHandler->Dump = TRootHandlerWoW6_Dump; // Support for ROOT file dump #endif // _DEBUG // Count the files that are going to be loaded ParseWowRootFile(pRootHandler, ParseRoot_CountFiles, pbRootFile, pbRootFileEnd, dwLocaleMask); pRootHandler->dwTotalFileCount += CASC_EXTRA_FILES; // Create linear table that will contain all root items nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, pRootHandler->dwTotalFileCount); if(nError != ERROR_SUCCESS) return nError; // Create sorted table that will contain all root items to lookup by FileDataId nError = Array_Create(&pRootHandler->FileDataIdLookupTable, PCASC_FILE_ENTRY, pRootHandler->dwTotalFileCount); if (nError != ERROR_SUCCESS) return nError; // Create the map of FileHash ->FileEntry pRootHandler->pRootMap = Map_Create(pRootHandler->dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash)); if(pRootHandler->pRootMap == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Parse the root file again and insert all files to the map ParseWowRootFile(pRootHandler, ParseRoot_AddRootEntries, pbRootFile, pbRootFileEnd, dwLocaleMask); // Sort entries by FileDataId for searches qsort_pointer_array((void**)pRootHandler->FileDataIdLookupTable.ItemArray, pRootHandler->FileDataIdLookupTable.ItemCount, &FileDataIdCompare, NULL); return ERROR_SUCCESS; }
// Create empty project AProject *AProject_Create (const char *OutputName) { AProject *pProject; geBoolean NoErrors; char OutputNameAndExt[MAX_PATH]; assert (OutputName != NULL); pProject = GE_RAM_ALLOCATE_STRUCT (AProject); if (pProject == NULL) { geErrorLog_AddString (GE_ERR_MEMORY_RESOURCE, "Allocating project structure",NULL); return NULL; } // Initialize defaults // Output pProject->Output.Filename = NULL; pProject->Output.Fmt = ApjOutput_Binary; // Paths pProject->Paths.ForceRelative = GE_TRUE; pProject->Paths.Materials = NULL; // Body pProject->Body.Filename = NULL; pProject->Body.Fmt = ApjBody_Max; // Materials pProject->Materials.Count = 0; pProject->Materials.Items = NULL; // Motions pProject->Motions.Count = 0; pProject->Motions.Items = NULL; FilePath_SetExt (OutputName, ".act", OutputNameAndExt); // Allocate required memory NoErrors = ((pProject->Output.Filename = Util_Strdup (OutputNameAndExt)) != NULL) && ((pProject->Paths.Materials = Util_Strdup ("")) != NULL) && ((pProject->Paths.TempFiles = Util_Strdup (".\\BldTemp")) != NULL) && ((pProject->Body.Filename = Util_Strdup ("")) != NULL); // Build motion and material arrays. Initially empty. NoErrors = NoErrors && ((pProject->Materials.Items = Array_Create (1, sizeof (ApjMaterialEntry))) != NULL); NoErrors = NoErrors && ((pProject->Motions.Items = Array_Create (1, sizeof (ApjMotionEntry))) != NULL); // if unsuccessful, destroy any allocated data if (!NoErrors) { geErrorLog_AddString (GE_ERR_MEMORY_RESOURCE, "Initializing project structure",NULL); if (pProject != NULL) { AProject_Destroy (&pProject); } } return pProject; }
int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile) { TRootHandler_Diablo3 * pRootHandler; PCASC_MAP pPackageMap = NULL; LPBYTE pbRootFileEnd = pbRootFile + cbRootFile; LPBYTE pbPackagesDat = NULL; DWORD dwTotalFileCount; DWORD cbPackagesDat = 0; int nError; // Allocate the root handler object hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_Diablo3, 1); if(pRootHandler == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Fill-in the handler functions memset(pRootHandler, 0, sizeof(TRootHandler_Diablo3)); pRootHandler->Insert = (ROOT_INSERT)D3Handler_Insert; pRootHandler->Search = (ROOT_SEARCH)D3Handler_Search; pRootHandler->EndSearch = (ROOT_ENDSEARCH)D3Handler_EndSearch; pRootHandler->GetKey = (ROOT_GETKEY)D3Handler_GetKey; pRootHandler->Close = (ROOT_CLOSE)D3Handler_Close; pRootHandler->GetFileId = (ROOT_GETFILEID)D3Handler_GetFileId; // Fill-in the flags pRootHandler->dwRootFlags |= ROOT_FLAG_HAS_NAMES; // Scan the total number of files in the root directories // Reserve space for extra files dwTotalFileCount = ScanDirectoryFile(hs, pbRootFile, pbRootFileEnd); if(dwTotalFileCount == 0) return ERROR_FILE_CORRUPT; dwTotalFileCount += CASC_EXTRA_FILES; // Allocate the global linear file table // Note: This is about 18 MB of memory for Diablo III PTR build 30013 nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, dwTotalFileCount); if(nError != ERROR_SUCCESS) return nError; // Allocate global buffer for file names. // The size of the buffer was taken from Diablo III build 30013 nError = Array_Create(&pRootHandler->FileNames, char, 0x01000000); if(nError != ERROR_SUCCESS) return nError; // Create map of ROOT_ENTRY -> FileEntry pRootHandler->pRootMap = Map_Create(dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash)); if(pRootHandler->pRootMap == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Parse the ROOT file and insert all entries in the file table nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFileEnd, DIABLO3_INVALID_INDEX); if(nError == ERROR_SUCCESS) { size_t dwRootEntries = pRootHandler->FileTable.ItemCount; // We expect the number of level-0 to be less than maximum assert(dwRootEntries < DIABLO3_MAX_SUBDIRS); // Now parse the all root items and load them for(DWORD i = 0; i < dwRootEntries; i++) { PCASC_FILE_ENTRY pRootEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, i); // Load the entire file to memory pbRootFile = LoadFileToMemory(hs, pRootEntry->EncodingKey.Value, &cbRootFile); if(pbRootFile != NULL) { nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFile + cbRootFile, i); CASC_FREE(pbRootFile); } } } // Note: The file "Base\Data_D3\PC\Misc\Packages.dat" contains the names // of the files (without level-0 and level-1 directory). We can use these // names for supplying the missing extensions if(nError == ERROR_SUCCESS) { // Load the entire file to memory pbPackagesDat = LoadFileToMemory(hs, "Base\\Data_D3\\PC\\Misc\\Packages.dat", &cbPackagesDat); if(pbPackagesDat != NULL) { pPackageMap = CreatePackageMap(pbPackagesDat, pbPackagesDat + cbPackagesDat); } } // Vast majorify of files at this moment don't have names. // We can load the Base\CoreTOC.dat file in order // to get directory asset indexes, file names and extensions if(nError == ERROR_SUCCESS) { LPBYTE pbCoreTOC; DWORD cbCoreTOC = 0; // Load the entire file to memory pbCoreTOC = LoadFileToMemory(hs, "Base\\CoreTOC.dat", &cbCoreTOC); if(pbCoreTOC != NULL) { ParseCoreTOC(pRootHandler, pPackageMap, pbCoreTOC, pbCoreTOC + cbCoreTOC); CASC_FREE(pbCoreTOC); } } // Free the packages map if(pPackageMap != NULL) Map_Free(pPackageMap); if(pbPackagesDat != NULL) CASC_FREE(pbPackagesDat); return nError; }