From 99101b4c52c61f04b98d6f5b5312dc74d5cea221 Mon Sep 17 00:00:00 2001 From: Sestain Date: Mon, 16 Mar 2026 10:20:48 +0200 Subject: [PATCH 1/3] Added support for Big-Endian DLCs --- Minecraft.Client/Common/DLC/DLCManager.cpp | 85 +++++++++++++++++++--- Minecraft.Client/Common/DLC/DLCManager.h | 25 +++++++ 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 931b0e1d9d..8eb672908c 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -387,22 +387,35 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD // // 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; + unsigned int uiVersion=readUInt32(pbData, false); uiCurrentByte+=sizeof(int); - if(uiVersion < CURRENT_DLC_VERSION_NUM) - { - if(pbData!=nullptr) delete [] pbData; - app.DebugPrintf("DLC version of %d is too old to be read\n", uiVersion); + bool bSwapEndian = false; + unsigned int uiVersionSwapped = SwapInt32(uiVersion); + if (uiVersion >= 0 && uiVersion <= CURRENT_DLC_VERSION_NUM) { + bSwapEndian = false; + } else if (uiVersionSwapped >= 0 && uiVersionSwapped <= CURRENT_DLC_VERSION_NUM) { + bSwapEndian = true; + } else { + if(pbData!=nullptr) delete [] pbData; + app.DebugPrintf("Unknown DLC version of %d\n", uiVersion); return false; } pack->SetDataPointer(pbData); - unsigned int uiParameterCount=*(unsigned int *)&pbData[uiCurrentByte]; + unsigned int uiParameterCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; //DWORD dwwchCount=0; + bool hasXMLVersion = false; for(unsigned int i=0;idwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType; + pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount; + char16_t* wchData = reinterpret_cast(pParams->wchData); + if (bSwapEndian) { + SwapUTF16Bytes(wchData, pParams->dwWchCount); + } + // Map DLC strings to application strings, then store the DLC index mapping to application index wstring parameterName(static_cast(pParams->wchData)); EDLCParameterType type = getParameterType(parameterName); @@ -414,14 +427,14 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; } //ulCurrentByte+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM); - - unsigned int uiFileCount=*(unsigned int *)&pbData[uiCurrentByte]; + unsigned int uiFileCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_DETAILS *pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte]; DWORD dwTemp=uiCurrentByte; for(unsigned int i=0;idwWchCount = bSwapEndian ? SwapInt32(pFile->dwWchCount) : pFile->dwWchCount; dwTemp+=sizeof(C4JStorage::DLC_FILE_DETAILS)+pFile->dwWchCount*sizeof(WCHAR); pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[dwTemp]; } @@ -430,27 +443,45 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD for(unsigned int i=0;idwType = bSwapEndian ? SwapInt32(pFile->dwType) : pFile->dwType; + pFile->uiFileSize = bSwapEndian ? SwapInt32(pFile->uiFileSize) : pFile->uiFileSize; + char16_t* wchFile = reinterpret_cast(pFile->wchFile); + if (bSwapEndian) { + SwapUTF16Bytes(wchFile, pFile->dwWchCount); + } + EDLCType type = static_cast(pFile->dwType); DLCFile *dlcFile = nullptr; DLCPack *dlcTexturePack = nullptr; + DLCPack *dlcSkinPack = nullptr; if(type == e_DLCType_TexturePack) { dlcTexturePack = new DLCPack(pack->getName(), pack->getLicenseMask()); } + else if(type == e_DLCType_SkinData) + { + dlcSkinPack = new DLCPack(pack->getName(), pack->getLicenseMask()); + } else if(type != e_DLCType_PackConfig) { dlcFile = pack->addFile(type,(WCHAR *)pFile->wchFile); } // Params - uiParameterCount=*(unsigned int *)pbTemp; + uiParameterCount=readUInt32(pbTemp, bSwapEndian); pbTemp+=sizeof(int); pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp; for(unsigned int j=0;jdwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType; + pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount; + char16_t* wchData = reinterpret_cast(pParams->wchData); + if (bSwapEndian) { + SwapUTF16Bytes(wchData, pParams->dwWchCount); + } auto it = parameterMapping.find(pParams->dwType); @@ -492,6 +523,42 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD } ++dwFilesProcessed; } + else if(dlcSkinPack != nullptr) + { + DWORD skinFilesProcessed = 0; + bool validPack = processDLCDataFile(skinFilesProcessed, pbTemp, pFile->uiFileSize, dlcSkinPack); + if(!validPack || skinFilesProcessed == 0) + { + delete dlcSkinPack; + dlcSkinPack = nullptr; + } + else + { + for(DWORD i = 0; i < dlcSkinPack->getSkinCount(); ++i) + { + DLCSkinFile* skinFile = dlcSkinPack->getSkinFile(i); + if(skinFile) + { + DLCFile* newFile = pack->addFile(DLCManager::e_DLCType_Skin, skinFile->getPath()); + + for(int param = 0; param < DLCManager::e_DLCParamType_Max; ++param) + { + auto value = skinFile->getParameterAsString(static_cast(param)); + if(!value.empty()) + { + newFile->addParameter(static_cast(param), value); + } + } + + app.vSkinNames.push_back(skinFile->getPath()); + } + } + + pack->addChildPack(dlcSkinPack); + } + + ++dwFilesProcessed; + } else if(dlcFile != nullptr) { // Data diff --git a/Minecraft.Client/Common/DLC/DLCManager.h b/Minecraft.Client/Common/DLC/DLCManager.h index d4dd2508ec..596fc66a44 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -20,6 +20,7 @@ class DLCManager e_DLCType_Audio, e_DLCType_ColourTable, e_DLCType_GameRulesHeader, + e_DLCType_SkinData, e_DLCType_Max, e_DLCType_All, @@ -94,6 +95,30 @@ class DLCManager bool readDLCDataFile(DWORD &dwFilesProcessed, const string &path, DLCPack *pack, bool fromArchive = false); DWORD retrievePackIDFromDLCDataFile(const string &path, DLCPack *pack); + static unsigned short SwapInt16(unsigned short value) { + return (value >> 8) | (value << 8); + } + + static unsigned int SwapInt32(unsigned int value) { + return ((value & 0xFF) << 24) | + ((value & 0xFF00) << 8) | + ((value & 0xFF0000) >> 8) | + ((value & 0xFF000000) >> 24); + } + + static void SwapUTF16Bytes(char16_t* buffer, size_t count) { + for (size_t i = 0; i < count; ++i) { + char16_t& c = buffer[i]; + c = (c >> 8) | (c << 8); + } + } + + static unsigned int readUInt32(unsigned char* ptr, bool endian) { + unsigned int val = *(unsigned int*)ptr; + if (endian) val = SwapInt32(val); + return val; + } + private: bool processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD dwLength, DLCPack *pack); From ac0b90528040fcac7efbeca60fe3fc43f4ca7af3 Mon Sep 17 00:00:00 2001 From: Sestain Date: Tue, 17 Mar 2026 20:10:13 +0200 Subject: [PATCH 2/3] Remove unused variable --- Minecraft.Client/Common/DLC/DLCManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 8eb672908c..9d4d37731b 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -406,7 +406,6 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; //DWORD dwwchCount=0; - bool hasXMLVersion = false; for(unsigned int i=0;idwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType; From 12347b13b0fe7b1f613e541b8f52b01ef36dc1ae Mon Sep 17 00:00:00 2001 From: Sestain Date: Wed, 18 Mar 2026 20:41:31 +0200 Subject: [PATCH 3/3] Remove the things made for other PR --- Minecraft.Client/Common/DLC/DLCManager.cpp | 41 ---------------------- Minecraft.Client/Common/DLC/DLCManager.h | 1 - 2 files changed, 42 deletions(-) diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 9d4d37731b..88a7756e5d 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -453,16 +453,11 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD DLCFile *dlcFile = nullptr; DLCPack *dlcTexturePack = nullptr; - DLCPack *dlcSkinPack = nullptr; if(type == e_DLCType_TexturePack) { dlcTexturePack = new DLCPack(pack->getName(), pack->getLicenseMask()); } - else if(type == e_DLCType_SkinData) - { - dlcSkinPack = new DLCPack(pack->getName(), pack->getLicenseMask()); - } else if(type != e_DLCType_PackConfig) { dlcFile = pack->addFile(type,(WCHAR *)pFile->wchFile); @@ -522,42 +517,6 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD } ++dwFilesProcessed; } - else if(dlcSkinPack != nullptr) - { - DWORD skinFilesProcessed = 0; - bool validPack = processDLCDataFile(skinFilesProcessed, pbTemp, pFile->uiFileSize, dlcSkinPack); - if(!validPack || skinFilesProcessed == 0) - { - delete dlcSkinPack; - dlcSkinPack = nullptr; - } - else - { - for(DWORD i = 0; i < dlcSkinPack->getSkinCount(); ++i) - { - DLCSkinFile* skinFile = dlcSkinPack->getSkinFile(i); - if(skinFile) - { - DLCFile* newFile = pack->addFile(DLCManager::e_DLCType_Skin, skinFile->getPath()); - - for(int param = 0; param < DLCManager::e_DLCParamType_Max; ++param) - { - auto value = skinFile->getParameterAsString(static_cast(param)); - if(!value.empty()) - { - newFile->addParameter(static_cast(param), value); - } - } - - app.vSkinNames.push_back(skinFile->getPath()); - } - } - - pack->addChildPack(dlcSkinPack); - } - - ++dwFilesProcessed; - } else if(dlcFile != nullptr) { // Data diff --git a/Minecraft.Client/Common/DLC/DLCManager.h b/Minecraft.Client/Common/DLC/DLCManager.h index 596fc66a44..7191ab0b68 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -20,7 +20,6 @@ class DLCManager e_DLCType_Audio, e_DLCType_ColourTable, e_DLCType_GameRulesHeader, - e_DLCType_SkinData, e_DLCType_Max, e_DLCType_All,