#include "../../Minecraft.World/Platform/stdafx.h" #include #include #include #include "DLCManager.h" #include "DLCAudioFile.h" #if defined _XBOX || defined _WINDOWS64 #include "../../Minecraft.Client/Platform/Xbox/XML/ATGXmlParser.h" #include "../../Minecraft.Client/Platform/Xbox/XML/xmlFilesCallback.h" #endif namespace { constexpr std::size_t AUDIO_DLC_WCHAR_BIN_SIZE = 2; #if WCHAR_MAX > 0xFFFF static std::wstring ReadAudioDlcWString(const void *data) { const std::uint16_t *chars = static_cast(data); const std::uint16_t *end = chars; while(*end != 0) { ++end; } std::wstring out(static_cast(end - chars), 0); for(std::size_t i = 0; i < out.size(); ++i) { out[i] = static_cast(chars[i]); } return out; } #else static std::wstring ReadAudioDlcWString(const void *data) { return std::wstring(static_cast(data)); } #endif template T ReadAudioDlcValue(const std::uint8_t *data, unsigned int offset = 0) { T value; std::memcpy(&value, data + offset, sizeof(value)); return value; } template void ReadAudioDlcStruct(T *out, const std::uint8_t *data, unsigned int offset = 0) { std::memcpy(out, data + offset, sizeof(*out)); } inline unsigned int AudioParamAdvance(unsigned int wcharCount) { return static_cast(sizeof(C4JStorage::DLC_FILE_PARAM) + wcharCount * AUDIO_DLC_WCHAR_BIN_SIZE); } inline unsigned int AudioDetailAdvance(unsigned int wcharCount) { return static_cast(sizeof(C4JStorage::DLC_FILE_DETAILS) + wcharCount * AUDIO_DLC_WCHAR_BIN_SIZE); } inline std::wstring ReadAudioParamString(const std::uint8_t *data, unsigned int offset) { return ReadAudioDlcWString(data + offset + offsetof(C4JStorage::DLC_FILE_PARAM, wchData)); } } DLCAudioFile::DLCAudioFile(const std::wstring &path) : DLCFile(DLCManager::e_DLCType_Audio,path) { m_pbData = NULL; m_dataBytes = 0; } void DLCAudioFile::addData(std::uint8_t *pbData, std::uint32_t dataBytes) { m_pbData = pbData; m_dataBytes = dataBytes; processDLCDataFile(pbData,dataBytes); } std::uint8_t *DLCAudioFile::getData(std::uint32_t &dataBytes) { dataBytes = m_dataBytes; return m_pbData; } const WCHAR *DLCAudioFile::wchTypeNamesA[]= { L"CUENAME", L"CREDIT", }; DLCAudioFile::EAudioParameterType DLCAudioFile::getParameterType(const std::wstring ¶mName) { EAudioParameterType type = e_AudioParamType_Invalid; for(int i = 0; i < e_AudioParamType_Max; ++i) { if(paramName.compare(wchTypeNamesA[i]) == 0) { type = (EAudioParameterType)i; break; } } return type; } void DLCAudioFile::addParameter(EAudioType type, EAudioParameterType ptype, const std::wstring &value) { switch(ptype) { case e_AudioParamType_Credit: // If this parameter exists, then mark this as free //add it to the DLC credits list // we'll need to justify this text since we don't have a lot of room for lines of credits { // don't look for duplicate in the music credits //if(app.AlreadySeenCreditText(value)) break; int maximumChars = 55; bool bIsSDMode=!RenderManager.IsHiDef() && !RenderManager.IsWidescreen(); if(bIsSDMode) { maximumChars = 45; } switch(XGetLanguage()) { case XC_LANGUAGE_JAPANESE: case XC_LANGUAGE_TCHINESE: case XC_LANGUAGE_KOREAN: maximumChars = 35; break; } std::wstring creditValue = value; while (creditValue.length() > maximumChars) { unsigned int i = 1; while (i < creditValue.length() && (i + 1) <= maximumChars) { i++; } int iLast=(int)creditValue.find_last_of(L" ",i); switch(XGetLanguage()) { case XC_LANGUAGE_JAPANESE: case XC_LANGUAGE_TCHINESE: case XC_LANGUAGE_KOREAN: iLast = maximumChars; break; default: iLast=(int)creditValue.find_last_of(L" ",i); break; } // if a space was found, include the space on this line if(iLast!=i) { iLast++; } app.AddCreditText((creditValue.substr(0, iLast)).c_str()); creditValue = creditValue.substr(iLast); } app.AddCreditText(creditValue.c_str()); } break; case e_AudioParamType_Cuename: m_parameters[type].push_back(value); //m_parameters[(int)type] = value; break; } } bool DLCAudioFile::processDLCDataFile(std::uint8_t *pbData, std::uint32_t dataLength) { std::unordered_map parameterMapping; unsigned int uiCurrentByte=0; // File format defined in the AudioPacker // File format: Version 1 unsigned int uiVersion = ReadAudioDlcValue(pbData, uiCurrentByte); uiCurrentByte+=sizeof(int); if(uiVersion < CURRENT_AUDIO_VERSION_NUM) { if(pbData!=NULL) delete [] pbData; app.DebugPrintf("DLC version of %d is too old to be read\n", uiVersion); return false; } unsigned int uiParameterTypeCount = ReadAudioDlcValue(pbData, uiCurrentByte); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_PARAM paramBuf; ReadAudioDlcStruct(¶mBuf, pbData, uiCurrentByte); for(unsigned int i=0;i(pbData, uiCurrentByte); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_DETAILS fileBuf; ReadAudioDlcStruct(&fileBuf, pbData, uiCurrentByte); unsigned int tempByteOffset = uiCurrentByte; for(unsigned int i=0;i(pbTemp); pbTemp+=sizeof(int); ReadAudioDlcStruct(¶mBuf, pbTemp); for(unsigned int j=0;j=m_parameters[iWorldType].size()) { iIndex-=m_parameters[iWorldType].size(); iWorldType++; } return m_parameters[iWorldType].at(iIndex); }