4jcraft/Minecraft.Client/Platform/Common/DLC/DLCManager.cpp
2026-03-12 16:42:36 +01:00

752 lines
20 KiB
C++

#include "../../Minecraft.World/Platform/stdafx.h"
#include <algorithm>
#include "DLCManager.h"
#include "DLCPack.h"
#include "DLCFile.h"
#include "../../Minecraft.World/Util/StringHelpers.h"
#include "../../Minecraft.Client/Minecraft.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h"
// 4jcraft, this is the size of wchar_t on disk
// the DLC was created on windows, with wchar_t beeing 2 bytes and UTF-16
static const size_t DLC_WCHAR_BIN_SIZE = 2;
#if WCHAR_MAX > 0xFFFF
// than sizeof(WCHAR) != DLC_WCHAR_BIN_SIZE
// e.g. Linux and all Posix/Unix systems with wchar_t beeing 4B/32bit
static_assert( sizeof(wchar_t) == 4, "wchar_t is not 4bytes but larger than 2bytes ???");
static inline std::wstring dlc_read_wstring(const void *data)
{
const uint16_t* p = (const uint16_t *)data;
// find the end (nullterminated)
const uint16_t* end = p;
while(*end) {
++end;
}
size_t len = end - p;
// allocate wstring with length len
// it will be nullterminated internally, do not worry.
std::wstring out(len, 0);
// and copy them into thje string
for(size_t i = 0; i < len; ++i) {
out[i] = (wchar_t) p[i];
}
return out;
}
#define DLC_WSTRING(ptr) dlc_read_wstring(ptr)
#else
// just in case.
static_assert( sizeof(wchar_t) == 2, "How did we get here? wide char smaller than 2 bytes");
// perfectly fine scince wchar_t will be 2 bytes (UCS-2/UTF-16)
#define DLC_WSTRING(ptr) std::wstring((wchar_t*)(ptr))
#endif
#define DLC_PARAM_ADV(n) (sizeof(C4JStorage::DLC_FILE_PARAM) + (n) * DLC_WCHAR_BIN_SIZE)
#define DLC_DETAIL_ADV(n) (sizeof(C4JStorage::DLC_FILE_DETAILS) + (n) * DLC_WCHAR_BIN_SIZE)
const WCHAR *DLCManager::wchTypeNamesA[]=
{
L"DISPLAYNAME",
L"THEMENAME",
L"FREE",
L"CREDIT",
L"CAPEPATH",
L"BOX",
L"ANIM",
L"PACKID",
L"NETHERPARTICLECOLOUR",
L"ENCHANTTEXTCOLOUR",
L"ENCHANTTEXTFOCUSCOLOUR",
L"DATAPATH",
L"PACKVERSION",
};
DLCManager::DLCManager()
{
//m_bNeedsUpdated = true;
m_bNeedsCorruptCheck = true;
}
DLCManager::~DLCManager()
{
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *pack = *it;
delete pack;
}
}
DLCManager::EDLCParameterType DLCManager::getParameterType(const std::wstring &paramName)
{
EDLCParameterType type = e_DLCParamType_Invalid;
for(DWORD i = 0; i < e_DLCParamType_Max; ++i)
{
if(paramName.compare(wchTypeNamesA[i]) == 0)
{
type = (EDLCParameterType)i;
break;
}
}
return type;
}
DWORD DLCManager::getPackCount(EDLCType type /*= e_DLCType_All*/)
{
DWORD packCount = 0;
if( type != e_DLCType_All )
{
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *pack = *it;
if( pack->getDLCItemsCount(type) > 0 )
{
++packCount;
}
}
}
else
{
packCount = (DWORD)m_packs.size();
}
return packCount;
}
void DLCManager::addPack(DLCPack *pack)
{
m_packs.push_back(pack);
}
void DLCManager::removePack(DLCPack *pack)
{
if(pack != NULL)
{
AUTO_VAR(it, find(m_packs.begin(),m_packs.end(),pack));
if(it != m_packs.end() ) m_packs.erase(it);
delete pack;
}
}
DLCPack *DLCManager::getPack(const std::wstring &name)
{
DLCPack *pack = NULL;
//DWORD currentIndex = 0;
DLCPack *currentPack = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
currentPack = *it;
std::wstring wsName=currentPack->getName();
if(wsName.compare(name) == 0)
{
pack = currentPack;
break;
}
}
return pack;
}
#ifdef _XBOX_ONE
DLCPack *DLCManager::getPackFromProductID(const std::wstring &productID)
{
DLCPack *pack = NULL;
//DWORD currentIndex = 0;
DLCPack *currentPack = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
currentPack = *it;
std::wstring wsName=currentPack->getPurchaseOfferId();
if(wsName.compare(productID) == 0)
{
pack = currentPack;
break;
}
}
return pack;
}
#endif
DLCPack *DLCManager::getPack(DWORD index, EDLCType type /*= e_DLCType_All*/)
{
DLCPack *pack = NULL;
if( type != e_DLCType_All )
{
DWORD currentIndex = 0;
DLCPack *currentPack = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
currentPack = *it;
if(currentPack->getDLCItemsCount(type)>0)
{
if(currentIndex == index)
{
pack = currentPack;
break;
}
++currentIndex;
}
}
}
else
{
if(index >= m_packs.size())
{
app.DebugPrintf("DLCManager: Trying to access a DLC pack beyond the range of valid packs\n");
__debugbreak();
}
pack = m_packs[index];
}
return pack;
}
DWORD DLCManager::getPackIndex(DLCPack *pack, bool &found, EDLCType type /*= e_DLCType_All*/)
{
DWORD foundIndex = 0;
found = false;
if(pack == NULL)
{
app.DebugPrintf("DLCManager: Attempting to find the index for a NULL pack\n");
//__debugbreak();
return foundIndex;
}
if( type != e_DLCType_All )
{
DWORD index = 0;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *thisPack = *it;
if(thisPack->getDLCItemsCount(type)>0)
{
if(thisPack == pack)
{
found = true;
foundIndex = index;
break;
}
++index;
}
}
}
else
{
DWORD index = 0;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *thisPack = *it;
if(thisPack == pack)
{
found = true;
foundIndex = index;
break;
}
++index;
}
}
return foundIndex;
}
DWORD DLCManager::getPackIndexContainingSkin(const std::wstring &path, bool &found)
{
DWORD foundIndex = 0;
found = false;
DWORD index = 0;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *pack = *it;
if(pack->getDLCItemsCount(e_DLCType_Skin)>0)
{
if(pack->doesPackContainSkin(path))
{
foundIndex = index;
found = true;
break;
}
++index;
}
}
return foundIndex;
}
DLCPack *DLCManager::getPackContainingSkin(const std::wstring &path)
{
DLCPack *foundPack = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *pack = *it;
if(pack->getDLCItemsCount(e_DLCType_Skin)>0)
{
if(pack->doesPackContainSkin(path))
{
foundPack = pack;
break;
}
}
}
return foundPack;
}
DLCSkinFile *DLCManager::getSkinFile(const std::wstring &path)
{
DLCSkinFile *foundSkinfile = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
DLCPack *pack = *it;
foundSkinfile=pack->getSkinFile(path);
if(foundSkinfile!=NULL)
{
break;
}
}
return foundSkinfile;
}
DWORD DLCManager::checkForCorruptDLCAndAlert(bool showMessage /*= true*/)
{
DWORD corruptDLCCount = m_dwUnnamedCorruptDLCCount;
DLCPack *pack = NULL;
DLCPack *firstCorruptPack = NULL;
for(AUTO_VAR(it, m_packs.begin()); it != m_packs.end(); ++it)
{
pack = *it;
if( pack->IsCorrupt() )
{
++corruptDLCCount;
if(firstCorruptPack == NULL) firstCorruptPack = pack;
}
}
// gotta fix this someday
if(corruptDLCCount > 0 && showMessage)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
if(corruptDLCCount == 1 && firstCorruptPack != NULL)
{
// pass in the pack format string
WCHAR wchFormat[132];
swprintf(wchFormat, 132, L"%ls\n\n%%ls", firstCorruptPack->getName().c_str());
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CORRUPT_DLC_TITLE, IDS_CORRUPT_DLC, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable(),wchFormat);
}
else
{
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CORRUPT_DLC_TITLE, IDS_CORRUPT_DLC_MULTIPLE, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
}
}
SetNeedsCorruptCheck(false);
return corruptDLCCount;
}
bool DLCManager::readDLCDataFile(DWORD &dwFilesProcessed, const std::wstring &path, DLCPack *pack, bool fromArchive)
{
return readDLCDataFile( dwFilesProcessed, wstringtofilename(path), pack, fromArchive);
}
bool DLCManager::readDLCDataFile(DWORD &dwFilesProcessed, const std::string &path, DLCPack *pack, bool fromArchive)
{
std::wstring wPath = convStringToWstring(path);
if (fromArchive && app.getArchiveFileSize(wPath) >= 0)
{
byteArray bytes = app.getArchiveFile(wPath);
return processDLCDataFile(dwFilesProcessed, bytes.data, bytes.length, pack);
}
else if (fromArchive) return false;
#ifdef _WINDOWS64
std::string finalPath = StorageManager.GetMountedPath(path.c_str());
if(finalPath.size() == 0) finalPath = path;
HANDLE file = CreateFile(finalPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#elif defined(_DURANGO)
std::wstring finalPath = StorageManager.GetMountedPath(wPath.c_str());
if(finalPath.size() == 0) finalPath = wPath;
HANDLE file = CreateFile(finalPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#else
HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#endif
if( file == INVALID_HANDLE_VALUE )
{
DWORD error = GetLastError();
app.DebugPrintf("Failed to open DLC data file with error code %d (%x)\n", error, error);
if( dwFilesProcessed == 0 ) removePack(pack);
assert(false);
return false;
}
DWORD bytesRead,dwFileSize = GetFileSize(file,NULL);
PBYTE pbData = (PBYTE) new BYTE[dwFileSize];
BOOL bSuccess = ReadFile(file,pbData,dwFileSize,&bytesRead,NULL);
if(bSuccess==FALSE)
{
// need to treat the file as corrupt, and flag it, so can't call fatal error
//app.FatalLoadError();
}
else
{
CloseHandle(file);
}
if(bSuccess==FALSE)
{
// Corrupt or some other error. In any case treat as corrupt
app.DebugPrintf("Failed to read %s from DLC content package\n", path.c_str());
pack->SetIsCorrupt( true );
SetNeedsCorruptCheck(true);
return false;
}
return processDLCDataFile(dwFilesProcessed, pbData, bytesRead, pack);
}
// a bunch of makros to reduce memcpy and offset boilerplate
#define DLC_READ_UINT(out, buf, off) memcpy(out, (buf) + (off), sizeof(unsigned int))
#define DLC_READ_PARAM(out, buf, off) memcpy((out), (buf) + (off), sizeof(C4JStorage::DLC_FILE_PARAM))
#define DLC_READ_DETAIL(out, buf, off) memcpy((out), (buf) + (off), sizeof(C4JStorage::DLC_FILE_DETAILS))
// for details, read in the function below
#define DLC_PARAM_WSTR(buf, off) DLC_WSTRING((buf) + (off) + offsetof(C4JStorage::DLC_FILE_PARAM, wchData))
#define DLC_DETAIL_WSTR(buf, off) DLC_WSTRING((buf) + (off) + offsetof(C4JStorage::DLC_FILE_DETAILS, wchFile))
bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD dwLength, DLCPack *pack)
{
std::unordered_map<int, DLCManager::EDLCParameterType> parameterMapping;
unsigned int uiCurrentByte=0;
// File format defined in the DLC_Creator
// File format: Version 2
// unsigned long, version number
// unsigned long, t = number of parameter types
// t * DLC_FILE_PARAM structs mapping strings to id's
// unsigned long, n = number of files
// n * DLC_FILE_DETAILS describing each file in the pack
// n * files of the form
// // unsigned long, p = number of parameters
// // p * DLC_FILE_PARAM describing each parameter for this file
// // ulFileSize bytes of data blob of the file added
// 4jcraft, some parts of this code changed, specifically:
// instead of casting a goddamn raw byte pointer and dereferencing it
// use memcpy, and access WSTRING with propper offset
// (scince bufferoffset after advancing by variable string length is not
// guaranteed to be properly aligned, so casting to a scalar/struct is UB)
// those casts coult be dangerous on e.g. ARM, because it doesnt handle
// missaligned loads, like x86/x64, so it would crash
// WHO TF USES HUNGARIAN NOTATION
unsigned int uiVersion;
DLC_READ_UINT(&uiVersion, pbData, uiCurrentByte);
uiCurrentByte+=sizeof(int);
if(uiVersion < CURRENT_DLC_VERSION_NUM)
{
if(pbData!=NULL) delete [] pbData;
app.DebugPrintf("DLC version of %d is too old to be read\n", uiVersion);
return false;
}
pack->SetDataPointer(pbData);
// safe, offset 4, aligned
unsigned int uiParameterCount;
DLC_READ_UINT(&uiParameterCount, pbData, uiCurrentByte);
uiCurrentByte+=sizeof(int);
C4JStorage::DLC_FILE_PARAM parBuf;
DLC_READ_PARAM(&parBuf, pbData, uiCurrentByte);
//DWORD dwwchCount=0;
for(unsigned int i=0;i<uiParameterCount;i++)
{
// Map DLC strings to application strings, then store the DLC index mapping to application index
std::wstring parameterName = DLC_PARAM_WSTR(pbData, uiCurrentByte);
DLCManager::EDLCParameterType type = DLCManager::getParameterType(parameterName);
if( type != DLCManager::e_DLCParamType_Invalid )
{
parameterMapping[parBuf.dwType] = type;
}
uiCurrentByte+= DLC_PARAM_ADV(parBuf.dwWchCount);
DLC_READ_PARAM(&parBuf, pbData, uiCurrentByte);
}
//ulCurrentByte+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM);
unsigned int uiFileCount;
DLC_READ_UINT(&uiFileCount, pbData, uiCurrentByte);
uiCurrentByte+=sizeof(int);
C4JStorage::DLC_FILE_DETAILS fileBuf;
DLC_READ_DETAIL(&fileBuf, pbData, uiCurrentByte);
DWORD dwTemp=uiCurrentByte;
for(unsigned int i=0;i<uiFileCount;i++)
{
dwTemp+=DLC_DETAIL_ADV(fileBuf.dwWchCount);
DLC_READ_DETAIL(&fileBuf, pbData, dwTemp);
}
PBYTE pbTemp = &pbData[dwTemp];//+ sizeof(C4JStorage::DLC_FILE_DETAILS)*ulFileCount;
DLC_READ_DETAIL(&fileBuf, pbData, uiCurrentByte);
for(unsigned int i=0;i<uiFileCount;i++)
{
DLCManager::EDLCType type = (DLCManager::EDLCType)fileBuf.dwType;
DLCFile *dlcFile = NULL;
DLCPack *dlcTexturePack = NULL;
if(type == e_DLCType_TexturePack)
{
dlcTexturePack = new DLCPack(pack->getName(), pack->getLicenseMask());
}
else if(type != e_DLCType_PackConfig)
{
dlcFile = pack->addFile(type, DLC_DETAIL_WSTR(pbData, uiCurrentByte));
}
// Params
unsigned int uiParamCount;
DLC_READ_UINT(&uiParamCount, pbTemp, 0);
pbTemp+=sizeof(int);
DLC_READ_PARAM(&parBuf, pbTemp, 0);
for(unsigned int j=0;j<uiParamCount;j++)
{
//DLCManager::EDLCParameterType paramType = DLCManager::e_DLCParamType_Invalid;
AUTO_VAR(it, parameterMapping.find( parBuf.dwType ));
if(it != parameterMapping.end() )
{
if(type == e_DLCType_PackConfig)
{
pack->addParameter(it->second, DLC_PARAM_WSTR(pbTemp, 0));
}
else
{
if(dlcFile != NULL) dlcFile->addParameter(it->second, DLC_PARAM_WSTR(pbTemp, 0));
else if(dlcTexturePack != NULL) dlcTexturePack->addParameter(it->second, DLC_PARAM_WSTR(pbTemp, 0));
}
}
pbTemp+=DLC_PARAM_ADV(parBuf.dwWchCount);
DLC_READ_PARAM(&parBuf, pbTemp, 0);
}
//pbTemp+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM);
if(dlcTexturePack != NULL)
{
DWORD texturePackFilesProcessed = 0;
bool validPack = processDLCDataFile(texturePackFilesProcessed,pbTemp,fileBuf.uiFileSize,dlcTexturePack);
pack->SetDataPointer(NULL); // If it's a child pack, it doesn't own the data
if(!validPack || texturePackFilesProcessed == 0)
{
delete dlcTexturePack;
dlcTexturePack = NULL;
}
else
{
pack->addChildPack(dlcTexturePack);
if(dlcTexturePack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0)
{
Minecraft::GetInstance()->skins->addTexturePackFromDLC(dlcTexturePack, dlcTexturePack->GetPackId() );
}
}
++dwFilesProcessed;
}
else if(dlcFile != NULL)
{
// Data
dlcFile->addData(pbTemp,fileBuf.uiFileSize);
// TODO - 4J Stu Remove the need for this vSkinNames vector, or manage it differently
switch(fileBuf.dwType)
{
case DLCManager::e_DLCType_Skin:
app.vSkinNames.push_back(DLC_DETAIL_WSTR(pbData, uiCurrentByte));
break;
}
++dwFilesProcessed;
}
// Move the pointer to the start of the next files data;
pbTemp+=fileBuf.uiFileSize;
uiCurrentByte+=DLC_DETAIL_ADV(fileBuf.dwWchCount);
DLC_READ_DETAIL(&fileBuf, pbData, uiCurrentByte);
}
if( pack->getDLCItemsCount(DLCManager::e_DLCType_GameRules) > 0
|| pack->getDLCItemsCount(DLCManager::e_DLCType_GameRulesHeader) > 0)
{
app.m_gameRules.loadGameRules(pack);
}
if(pack->getDLCItemsCount(DLCManager::e_DLCType_Audio) > 0)
{
//app.m_Audio.loadAudioDetails(pack);
}
// TODO Should be able to delete this data, but we can't yet due to how it is added to the Memory textures (MEM_file)
return true;
}
DWORD DLCManager::retrievePackIDFromDLCDataFile(const std::string &path, DLCPack *pack)
{
DWORD packId = 0;
std::wstring wPath = convStringToWstring(path);
#ifdef _WINDOWS64
std::string finalPath = StorageManager.GetMountedPath(path.c_str());
if(finalPath.size() == 0) finalPath = path;
HANDLE file = CreateFile(finalPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#elif defined(_DURANGO)
std::wstring finalPath = StorageManager.GetMountedPath(wPath.c_str());
if(finalPath.size() == 0) finalPath = wPath;
HANDLE file = CreateFile(finalPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#else
HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#endif
if( file == INVALID_HANDLE_VALUE )
{
return 0;
}
DWORD bytesRead;
DWORD dwFileSize = GetFileSize(file,NULL);
PBYTE pbData = (PBYTE) new BYTE[dwFileSize];
BOOL bSuccess = ReadFile(file,pbData,dwFileSize,&bytesRead,NULL);
if(bSuccess==FALSE)
{
// need to treat the file as corrupt, and flag it, so can't call fatal error
//app.FatalLoadError();
}
else
{
CloseHandle(file);
}
if(bSuccess==FALSE)
{
// Corrupt or some other error. In any case treat as corrupt
app.DebugPrintf("Failed to read %s from DLC content package\n", path.c_str());
delete [] pbData;
return 0;
}
packId=retrievePackID(pbData, bytesRead, pack);
delete [] pbData;
return packId;
}
DWORD DLCManager::retrievePackID(PBYTE pbData, DWORD dwLength, DLCPack *pack)
{
DWORD packId=0;
bool bPackIDSet=false;
std::unordered_map<int, DLCManager::EDLCParameterType> parameterMapping;
unsigned int uiCurrentByte=0;
// File format defined in the DLC_Creator
// File format: Version 2
// unsigned long, version number
// unsigned long, t = number of parameter types
// t * DLC_FILE_PARAM structs mapping strings to id's
// unsigned long, n = number of files
// n * DLC_FILE_DETAILS describing each file in the pack
// n * files of the form
// // unsigned long, p = number of parameters
// // p * DLC_FILE_PARAM describing each parameter for this file
// // ulFileSize bytes of data blob of the file added
unsigned int uiVersion=*(unsigned int *)pbData;
uiCurrentByte+=sizeof(int);
if(uiVersion < CURRENT_DLC_VERSION_NUM)
{
app.DebugPrintf("DLC version of %d is too old to be read\n", uiVersion);
return 0;
}
pack->SetDataPointer(pbData);
unsigned int uiParameterCount=*(unsigned int *)&pbData[uiCurrentByte];
uiCurrentByte+=sizeof(int);
C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte];
for(unsigned int i=0;i<uiParameterCount;i++)
{
// Map DLC strings to application strings, then store the DLC index mapping to application index
std::wstring parameterName = DLC_WSTRING(pParams->wchData);
DLCManager::EDLCParameterType type = DLCManager::getParameterType(parameterName);
if( type != DLCManager::e_DLCParamType_Invalid )
{
parameterMapping[pParams->dwType] = type;
}
uiCurrentByte+= DLC_PARAM_ADV(pParams->dwWchCount);
pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte];
}
unsigned int uiFileCount=*(unsigned int *)&pbData[uiCurrentByte];
uiCurrentByte+=sizeof(int);
C4JStorage::DLC_FILE_DETAILS *pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
DWORD dwTemp=uiCurrentByte;
for(unsigned int i=0;i<uiFileCount;i++)
{
dwTemp+=DLC_DETAIL_ADV(pFile->dwWchCount);
pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[dwTemp];
}
PBYTE pbTemp=((PBYTE )pFile);
pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
for(unsigned int i=0;i<uiFileCount;i++)
{
DLCManager::EDLCType type = (DLCManager::EDLCType)pFile->dwType;
// Params
uiParameterCount=*(unsigned int *)pbTemp;
pbTemp+=sizeof(int);
pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp;
for(unsigned int j=0;j<uiParameterCount;j++)
{
AUTO_VAR(it, parameterMapping.find( pParams->dwType ));
if(it != parameterMapping.end() )
{
if(type==e_DLCType_PackConfig)
{
if(it->second==e_DLCParamType_PackId)
{
std::wstring wsTemp = DLC_WSTRING(pParams->wchData);
std::wstringstream ss;
// 4J Stu - numbered using decimal to make it easier for artists/people to number manually
ss << std::dec << wsTemp.c_str();
ss >> packId;
bPackIDSet=true;
break;
}
}
}
pbTemp+=DLC_PARAM_ADV(pParams->dwWchCount);
pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp;
}
if(bPackIDSet) break;
// Move the pointer to the start of the next files data;
pbTemp+=pFile->uiFileSize;
uiCurrentByte+=DLC_DETAIL_ADV(pFile->dwWchCount);
pFile=(C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
}
parameterMapping.clear();
return packId;
}