/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILECOMPONENTS_H #define CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILECOMPONENTS_H #pragma once #include "CryHeaders.h" namespace ChunkFile { // All chunk files use *little-endian* format to store file header and chunk. // Chunk data are stored in either little-endian or big-endian format, // see kBigEndianVersionFlag. struct FileHeader_0x744_0x745 { char signature[7]; char _pad_[1]; uint32 fileType; uint32 version; uint32 chunkTableOffset; enum EFileType { eFileType_Geom = 0xFFFF0000U, eFileType_Anim, }; static const char* GetExpectedSignature() { return "CryTek"; } bool HasValidSignature() const { return memcmp(GetExpectedSignature(), signature, sizeof(signature)) == 0; } void Set(uint32 a_chunkTableOffset) { memcpy(signature, GetExpectedSignature(), sizeof(signature)); _pad_[0] = 0; // We need to set eFileType_Geom or eFileType_Anim, but asking // the caller to provide us the type will complicate the code, so we // set eFileType_Geom only. It's ok because all our readers // don't differentiate between eFileType_Geom and eFileType_Anim. fileType = eFileType_Geom; version = 0x745; chunkTableOffset = a_chunkTableOffset; } void SwapEndianness() { SwapEndianBase(&fileType, 1); SwapEndianBase(&version, 1); SwapEndianBase(&chunkTableOffset, 1); } }; struct FileHeader_0x746 { char signature[4]; uint32 version; uint32 chunkCount; uint32 chunkTableOffset; static const char* GetExpectedSignature() { return "CrCh"; } static const char* GetExpectedSpeedTreeSignature() { return "STCh"; } bool HasValidSignature() const { return (memcmp(GetExpectedSignature(), signature, sizeof(signature)) == 0) || (memcmp(GetExpectedSpeedTreeSignature(), signature, sizeof(signature)) == 0); } void Set(int32 a_chunkCount, uint32 a_chunkTableOffset) { memcpy(signature, GetExpectedSignature(), sizeof(signature)); version = 0x746; chunkCount = a_chunkCount; chunkTableOffset = a_chunkTableOffset; } void SwapEndianness() { SwapEndianBase(&version, 1); SwapEndianBase(&chunkCount, 1); SwapEndianBase(&chunkTableOffset, 1); } }; struct ChunkHeader_0x744_0x745 { uint32 type; uint32 version; uint32 offsetInFile; uint32 id; enum { kBigEndianVersionFlag = 0x80000000U }; void SwapEndianness() { SwapEndianBase(&type, 1); SwapEndianBase(&version, 1); SwapEndianBase(&offsetInFile, 1); SwapEndianBase(&id, 1); } }; struct ChunkTableEntry_0x744 : public ChunkHeader_0x744_0x745 { void SwapEndianness() { ChunkHeader_0x744_0x745::SwapEndianness(); } }; struct ChunkTableEntry_0x745 : public ChunkHeader_0x744_0x745 { uint32 size; void SwapEndianness() { ChunkHeader_0x744_0x745::SwapEndianness(); SwapEndianBase(&size, 1); } }; struct ChunkTableEntry_0x746 { uint16 type; uint16 version; uint32 id; uint32 size; uint32 offsetInFile; enum { kBigEndianVersionFlag = 0x8000U }; void SwapEndianness() { SwapEndianBase(&type, 1); SwapEndianBase(&version, 1); SwapEndianBase(&id, 1); SwapEndianBase(&size, 1); SwapEndianBase(&offsetInFile, 1); } }; // We need this function to strip 0x744 & 0x745 chunk headers // from chunk data properly: some chunks in 0x744 and 0x745 formats // don't have chunk headers in their data. // 'chunkType' is expected to be provided in the 0x746 format. inline bool ChunkContainsHeader_0x744_0x745(const uint16 chunkType, const uint16 chunkVersion) { switch (chunkType) { case ChunkType_SourceInfo: return false; case ChunkType_Controller: return (chunkVersion != CONTROLLER_CHUNK_DESC_0827::VERSION && chunkVersion != CONTROLLER_CHUNK_DESC_0830::VERSION); case ChunkType_BoneNameList: return (chunkVersion != BONENAMELIST_CHUNK_DESC_0745::VERSION); case ChunkType_MeshMorphTarget: return (chunkVersion != MESHMORPHTARGET_CHUNK_DESC_0001::VERSION); case ChunkType_BoneInitialPos: return (chunkVersion != BONEINITIALPOS_CHUNK_DESC_0001::VERSION); default: return true; } } static inline uint16 ConvertChunkTypeTo0x746(uint32 type) { if (type <= 0xFFFF) { // Input type seems to be already in 0x746 format (or it's 0) return type; } // Input type seems to be in 0x745 format if ((type & 0xFFFF) >= 0xF000) { // Cannot fit into resulting 0x746 type (uint16) return 0; } if ((type & 0xFFFF0000U) == 0xCCCC0000U) { return 0x1000 + (type & 0x0FFF); } if ((type & 0xFFFF0000U) == 0xACDC0000U) { return 0x2000 + (type & 0x0FFF); } if ((type & 0xFFFF0000U) == 0xAAFC0000U) { return 0x3000 + (type & 0x0FFF); } // Unknown 0x745 chunk type return 0; } static inline uint32 ConvertChunkTypeTo0x745(uint32 type) { if (type > 0xFFFF) { // Input type seems to be already in 0x745 format return type; } // Input type seems to be in 0x746 format if ((type & 0xF000) == 0x1000) { return 0xCCCC0000U + (type & 0x0FFF); } if ((type & 0xF000) == 0x2000) { return 0xACDC0000U + (type & 0x0FFF); } if ((type & 0xF000) == 0x3000) { return 0xAAFC0000U + (type & 0x0FFF); } // Unknown 0x746 chunk type (or it's 0) return 0; } } // namespace ChunkFile #endif // CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILECOMPONENTS_H