BVB Source Codes

CRYENGINE Show ChunkFileReaders.cpp Source code

Return Download CRYENGINE: download ChunkFileReaders.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name: ChunkFileParsers.h
  5. //  Created:   2013/11/18 by Sergey Sokov
  6. //
  7. ////////////////////////////////////////////////////////////////////////////
  8.  
  9. #include "StdAfx.h"
  10. #include <Cry3DEngine/CGF/CryHeaders.h>
  11. #include "ChunkFileReaders.h"
  12.  
  13. namespace ChunkFile
  14. {
  15.  
  16. //////////////////////////////////////////////////////////////////////////
  17.  
  18. CryFileReader::CryFileReader()
  19. {
  20. }
  21.  
  22. CryFileReader::~CryFileReader()
  23. {
  24.         Close();
  25. }
  26.  
  27. bool CryFileReader::Open(const char* filename)
  28. {
  29.         Close();
  30.  
  31.         if (filename == 0 || filename[0] == 0)
  32.         {
  33.                 return false;
  34.         }
  35.  
  36.         if (!m_f.Open(filename, "rb"))
  37.         {
  38.                 return false;
  39.         }
  40.  
  41.         m_offset = 0;
  42.  
  43.         return true;
  44. }
  45.  
  46. void CryFileReader::Close()
  47. {
  48.         m_f.Close();
  49. }
  50.  
  51. int32 CryFileReader::GetSize()
  52. {
  53.         return m_f.GetLength();
  54. }
  55.  
  56. bool CryFileReader::SetPos(int32 pos)
  57. {
  58.         if (pos < 0)
  59.         {
  60.                 return false;
  61.         }
  62.         m_offset = pos;
  63.         return m_f.Seek(m_offset, SEEK_SET) == 0;
  64. }
  65.  
  66. bool CryFileReader::Read(void* buffer, size_t size)
  67. {
  68.         return m_f.ReadRaw(buffer, size) == size;
  69. }
  70.  
  71. //////////////////////////////////////////////////////////////////////////
  72.  
  73. MemoryReader::MemoryReader()
  74.         : m_ptr(0)
  75.         , m_size(0)
  76. {
  77. }
  78.  
  79. MemoryReader::~MemoryReader()
  80. {
  81. }
  82.  
  83. bool MemoryReader::Start(void* ptr, int32 size)
  84. {
  85.         if (ptr == 0 || size <= 0)
  86.         {
  87.                 return false;
  88.         }
  89.  
  90.         m_ptr = (char*)ptr;
  91.         m_size = size;
  92.         m_offset = 0;
  93.  
  94.         return true;
  95. }
  96.  
  97. void MemoryReader::Close()
  98. {
  99. }
  100.  
  101. int32 MemoryReader::GetSize()
  102. {
  103.         return m_size;
  104. }
  105.  
  106. bool MemoryReader::SetPos(int32 pos)
  107. {
  108.         if (pos < 0 || pos > m_size)
  109.         {
  110.                 return false;
  111.         }
  112.         m_offset = pos;
  113.         return true;
  114. }
  115.  
  116. bool MemoryReader::Read(void* buffer, size_t size)
  117. {
  118.         if (!m_ptr)
  119.         {
  120.                 return false;
  121.         }
  122.  
  123.         if (size <= 0)
  124.         {
  125.                 return true;
  126.         }
  127.  
  128.         if ((size_t)m_offset + size > (size_t)m_size)
  129.         {
  130.                 return false;
  131.         }
  132.  
  133.         memcpy(buffer, &m_ptr[m_offset], size);
  134.         m_offset += size;
  135.  
  136.         return true;
  137. }
  138.  
  139. //////////////////////////////////////////////////////////////////////////
  140.  
  141. namespace
  142. {
  143. class ChunkListRef
  144. {
  145.         std::vector<IChunkFile::ChunkDesc>& m_chunks;
  146.  
  147. public:
  148.         ChunkListRef(std::vector<IChunkFile::ChunkDesc>& chunks)
  149.                 : m_chunks(chunks)
  150.         {
  151.         }
  152.  
  153.         void Clear()
  154.         {
  155.                 for (size_t i = 0; i < m_chunks.size(); ++i)
  156.                 {
  157.                         if (m_chunks[i].data)
  158.                         {
  159.                                 delete[] (char*)m_chunks[i].data;
  160.                                 m_chunks[i].data = 0;
  161.                         }
  162.                 }
  163.                 m_chunks.clear();
  164.         }
  165.  
  166.         void Create(size_t count)
  167.         {
  168.                 Clear();
  169.                 m_chunks.resize(count);
  170.                 for (size_t i = 0; i < count; ++i)
  171.                 {
  172.                         m_chunks[i].data = 0;
  173.                         m_chunks[i].size = 0;
  174.                 }
  175.         }
  176.  
  177.         void Sort()
  178.         {
  179.                 std::sort(m_chunks.begin(), m_chunks.end(), IChunkFile::ChunkDesc::LessOffset);
  180.         }
  181.  
  182.         size_t GetCount() const
  183.         {
  184.                 return m_chunks.size();
  185.         }
  186.  
  187.         IChunkFile::ChunkDesc& Get(size_t index)
  188.         {
  189.                 return m_chunks[index];
  190.         }
  191. };
  192.  
  193. class ChunkPtrListRef
  194. {
  195.         std::vector<IChunkFile::ChunkDesc*>& m_chunks;
  196.  
  197. public:
  198.         ChunkPtrListRef(std::vector<IChunkFile::ChunkDesc*>& chunks)
  199.                 : m_chunks(chunks)
  200.         {
  201.         }
  202.  
  203.         void Clear()
  204.         {
  205.                 for (size_t i = 0; i < m_chunks.size(); ++i)
  206.                 {
  207.                         if (m_chunks[i])
  208.                         {
  209.                                 if (m_chunks[i]->data)
  210.                                 {
  211.                                         delete[] (char*)(m_chunks[i]->data);
  212.                                         m_chunks[i]->data = 0;
  213.                                 }
  214.                                 delete m_chunks[i];
  215.                         }
  216.                 }
  217.                 m_chunks.clear();
  218.         }
  219.  
  220.         void Create(size_t count)
  221.         {
  222.                 Clear();
  223.                 m_chunks.resize(count, 0);
  224.                 for (size_t i = 0; i < count; ++i)
  225.                 {
  226.                         m_chunks[i] = new IChunkFile::ChunkDesc;
  227.                         m_chunks[i]->data = 0;
  228.                         m_chunks[i]->size = 0;
  229.                 }
  230.         }
  231.  
  232.         void Sort()
  233.         {
  234.                 std::sort(m_chunks.begin(), m_chunks.end(), IChunkFile::ChunkDesc::LessOffsetByPtr);
  235.         }
  236.  
  237.         size_t GetCount() const
  238.         {
  239.                 return m_chunks.size();
  240.         }
  241.  
  242.         IChunkFile::ChunkDesc& Get(size_t index)
  243.         {
  244.                 return *m_chunks[index];
  245.         }
  246. };
  247. } // namespace
  248.  
  249. //////////////////////////////////////////////////////////////////////////
  250.  
  251. template<class TListRef>
  252. static const char* GetChunkTableEntries_0x744_0x745_Tpl(IReader* pReader, TListRef& chunks)
  253. {
  254.         chunks.Clear();
  255.  
  256.         ChunkFile::FileHeader_0x744_0x745 header;
  257.  
  258.         if (!pReader->SetPos(0) ||
  259.             !pReader->Read(&header, sizeof(header)))
  260.         {
  261.                 return "Cannot read header of chunk file";
  262.         }
  263.  
  264.         if (!header.HasValidSignature())
  265.         {
  266.                 return "Unknown signature in chunk file";
  267.         }
  268.  
  269.         if (SYSTEM_IS_BIG_ENDIAN)
  270.         {
  271.                 header.SwapEndianness();
  272.         }
  273.  
  274.         if (header.version != 0x744 && header.version != 0x745)
  275.         {
  276.                 return "Version of chunk file is neither 0x744 nor 0x745";
  277.         }
  278.  
  279.         if (header.fileType != header.eFileType_Geom && header.fileType != header.eFileType_Anim)
  280.         {
  281.                 return "Type of chunk file is neither FileType_Geom nor FileType_Anim";
  282.         }
  283.  
  284.         uint32 chunkCount = 0;
  285.         {
  286.                 if (!pReader->SetPos(header.chunkTableOffset) ||
  287.                     !pReader->Read(&chunkCount, sizeof(chunkCount)))
  288.                 {
  289.                         return "Failed to read # of chunks";
  290.                 }
  291.  
  292.                 if (SYSTEM_IS_BIG_ENDIAN)
  293.                 {
  294.                         SwapEndianBase(&chunkCount, 1);
  295.                 }
  296.  
  297.                 if (chunkCount > 1000000)
  298.                 {
  299.                         return "Invalid # of chunks in file";
  300.                 }
  301.         }
  302.  
  303.         if (chunkCount <= 0)
  304.         {
  305.                 return 0;
  306.         }
  307.  
  308.         chunks.Create(chunkCount);
  309.  
  310.         if (header.version == 0x744)
  311.         {
  312.                 std::vector<ChunkFile::ChunkTableEntry_0x744> srcChunks;
  313.                 srcChunks.resize(chunkCount);
  314.  
  315.                 if (!pReader->Read(&srcChunks[0], sizeof(srcChunks[0]) * srcChunks.size()))
  316.                 {
  317.                         return "Failed to read chunk entries from file";
  318.                 }
  319.  
  320.                 if (SYSTEM_IS_BIG_ENDIAN)
  321.                 {
  322.                         for (uint32 i = 0; i < chunkCount; ++i)
  323.                         {
  324.                                 srcChunks[i].SwapEndianness();
  325.                         }
  326.                 }
  327.  
  328.                 for (uint32 i = 0; i < chunkCount; ++i)
  329.                 {
  330.                         IChunkFile::ChunkDesc& cd = chunks.Get(i);
  331.  
  332.                         cd.chunkType = (ChunkTypes)ConvertChunkTypeTo0x746(srcChunks[i].type);
  333.                         cd.chunkVersion = srcChunks[i].version & ~ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag;
  334.                         cd.chunkId = srcChunks[i].id;
  335.                         cd.fileOffset = srcChunks[i].offsetInFile;
  336.                         cd.bSwapEndian = (srcChunks[i].version & ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag) ? SYSTEM_IS_LITTLE_ENDIAN : SYSTEM_IS_BIG_ENDIAN;
  337.                 }
  338.  
  339.                 chunks.Sort();
  340.  
  341.                 const uint32 endOfChunkData = (header.chunkTableOffset < chunks.Get(0).fileOffset)
  342.                                               ? (uint32)pReader->GetSize()
  343.                                               : header.chunkTableOffset;
  344.  
  345.                 for (uint32 i = 0; i < chunkCount; ++i)
  346.                 {
  347.                         // calculate chunk size based on the next (by offset in file) chunk or
  348.                         // on the end of the chunk data portion of the file
  349.  
  350.                         const size_t nextOffsetInFile = (i + 1 < chunkCount)
  351.                                                         ? chunks.Get(i + 1).fileOffset
  352.                                                         : endOfChunkData;
  353.  
  354.                         chunks.Get(i).size = nextOffsetInFile - chunks.Get(i).fileOffset;
  355.                 }
  356.         }
  357.         else // header.version == 0x745
  358.         {
  359.                 std::vector<ChunkFile::ChunkTableEntry_0x745> srcChunks;
  360.                 srcChunks.resize(chunkCount);
  361.  
  362.                 if (!pReader->Read(&srcChunks[0], sizeof(srcChunks[0]) * srcChunks.size()))
  363.                 {
  364.                         return "Failed to read chunk entries from file.";
  365.                 }
  366.  
  367.                 if (SYSTEM_IS_BIG_ENDIAN)
  368.                 {
  369.                         for (uint32 i = 0; i < chunkCount; ++i)
  370.                         {
  371.                                 srcChunks[i].SwapEndianness();
  372.                         }
  373.                 }
  374.  
  375.                 for (uint32 i = 0; i < chunkCount; ++i)
  376.                 {
  377.                         IChunkFile::ChunkDesc& cd = chunks.Get(i);
  378.  
  379.                         cd.chunkType = (ChunkTypes)ConvertChunkTypeTo0x746(srcChunks[i].type);
  380.                         cd.chunkVersion = srcChunks[i].version & ~ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag;
  381.                         cd.chunkId = srcChunks[i].id;
  382.                         cd.fileOffset = srcChunks[i].offsetInFile;
  383.                         cd.size = srcChunks[i].size;
  384.                         cd.bSwapEndian = (srcChunks[i].version & ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag) ? SYSTEM_IS_LITTLE_ENDIAN : SYSTEM_IS_BIG_ENDIAN;
  385.                 }
  386.         }
  387.  
  388.         const uint32 fileSize = (uint32)pReader->GetSize();
  389.  
  390.         for (uint32 i = 0; i < chunkCount; ++i)
  391.         {
  392.                 const IChunkFile::ChunkDesc& cd = chunks.Get(i);
  393.  
  394.                 if (cd.size + cd.fileOffset > fileSize)
  395.                 {
  396.                         return "Data in chunk file are corrupted";
  397.                 }
  398.         }
  399.  
  400.         return 0;
  401. }
  402.  
  403. template<class TListRef>
  404. static const char* GetChunkTableEntries_0x746_Tpl(IReader* pReader, TListRef& chunks)
  405. {
  406.         chunks.Clear();
  407.  
  408.         ChunkFile::FileHeader_0x746 header;
  409.  
  410.         if (!pReader->SetPos(0) ||
  411.             !pReader->Read(&header, sizeof(header)))
  412.         {
  413.                 return "Cannot read header from file.";
  414.         }
  415.  
  416.         if (!header.HasValidSignature())
  417.         {
  418.                 return "Unknown signature in chunk file";
  419.         }
  420.  
  421.         if (SYSTEM_IS_BIG_ENDIAN)
  422.         {
  423.                 header.SwapEndianness();
  424.         }
  425.  
  426.         if (header.version != 0x746)
  427.         {
  428.                 return "Version of chunk file is not 0x746";
  429.         }
  430.  
  431.         if (header.chunkCount > 10000000)
  432.         {
  433.                 return "Invalid # of chunks in file.";
  434.         }
  435.  
  436.         if (header.chunkCount <= 0)
  437.         {
  438.                 return 0;
  439.         }
  440.  
  441.         chunks.Create(header.chunkCount);
  442.  
  443.         std::vector<ChunkFile::ChunkTableEntry_0x746> srcChunks;
  444.         srcChunks.resize(header.chunkCount);
  445.  
  446.         if (!pReader->SetPos(header.chunkTableOffset) ||
  447.             !pReader->Read(&srcChunks[0], sizeof(srcChunks[0]) * srcChunks.size()))
  448.         {
  449.                 return "Failed to read chunk entries from file";
  450.         }
  451.  
  452.         if (SYSTEM_IS_BIG_ENDIAN)
  453.         {
  454.                 for (uint32 i = 0; i < header.chunkCount; ++i)
  455.                 {
  456.                         srcChunks[i].SwapEndianness();
  457.                 }
  458.         }
  459.  
  460.         for (size_t i = 0, n = chunks.GetCount(); i < n; ++i)
  461.         {
  462.                 IChunkFile::ChunkDesc& cd = chunks.Get(i);
  463.  
  464.                 cd.chunkType = (ChunkTypes)srcChunks[i].type;
  465.                 cd.chunkVersion = srcChunks[i].version & ~ChunkFile::ChunkTableEntry_0x746::kBigEndianVersionFlag;
  466.                 cd.chunkId = srcChunks[i].id;
  467.                 cd.size = srcChunks[i].size;
  468.                 cd.fileOffset = srcChunks[i].offsetInFile;
  469.                 cd.bSwapEndian = (srcChunks[i].version & ChunkFile::ChunkTableEntry_0x746::kBigEndianVersionFlag) ? SYSTEM_IS_LITTLE_ENDIAN : SYSTEM_IS_BIG_ENDIAN;
  470.         }
  471.  
  472.         return 0;
  473. }
  474.  
  475. template<class TListRef>
  476. static const char* StripChunkHeaders_0x744_0x745_Tpl(IReader* pReader, TListRef& chunks)
  477. {
  478.         for (size_t i = 0, n = chunks.GetCount(); i < n; ++i)
  479.         {
  480.                 IChunkFile::ChunkDesc& ct = chunks.Get(i);
  481.  
  482.                 if (ChunkFile::ChunkContainsHeader_0x744_0x745(ct.chunkType, ct.chunkVersion))
  483.                 {
  484.                         ChunkFile::ChunkHeader_0x744_0x745 ch;
  485.                         if (ct.size < sizeof(ch))
  486.                         {
  487.                                 return "Damaged data: reported size of chunk data is less that size of the chunk header";
  488.                         }
  489.  
  490.                         // Validation
  491.                         {
  492.                                 if (!pReader->SetPos(ct.fileOffset) ||
  493.                                     !pReader->Read(&ch, sizeof(ch)))
  494.                                 {
  495.                                         return "Failed to read chunk header from file";
  496.                                 }
  497.  
  498.                                 if (SYSTEM_IS_BIG_ENDIAN)
  499.                                 {
  500.                                         ch.SwapEndianness();
  501.                                 }
  502.  
  503.                                 ch.version &= ~ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag;
  504.  
  505.                                 if (ConvertChunkTypeTo0x746(ch.type) != ct.chunkType ||
  506.                                     ch.version != ct.chunkVersion ||
  507.                                     ch.id != ct.chunkId)
  508.                                 {
  509.                                         return "Data in a chunk header don't match data in the chunk table";
  510.                                 }
  511.  
  512.                                 // The following check is commented out because we have (on 2013/11/25)
  513.                                 // big number of .cgf files in Crysis 3 that fail to pass the check.
  514.                                 //if (ch.offsetInFile != ct.fileOffset)
  515.                                 //{
  516.                                 //      return "File offset data in a chunk header don't match data in the chunk table";
  517.                                 //}
  518.                         }
  519.  
  520.                         ct.fileOffset += sizeof(ch);
  521.                         ct.size -= sizeof(ch);
  522.  
  523.                         if (ct.data)
  524.                         {
  525.                                 ct.data = ((char*)ct.data) + sizeof(ch);
  526.                         }
  527.                 }
  528.  
  529.                 if (ct.size < 0)
  530.                 {
  531.                         return "A negative-length chunk found in file";
  532.                 }
  533.         }
  534.  
  535.         return 0;
  536. }
  537.  
  538. const char* GetChunkTableEntries_0x744_0x745(IReader* pReader, std::vector<IChunkFile::ChunkDesc>& chunks)
  539. {
  540.         ChunkListRef c(chunks);
  541.         return GetChunkTableEntries_0x744_0x745_Tpl(pReader, c);
  542. }
  543.  
  544. const char* GetChunkTableEntries_0x744_0x745(IReader* pReader, std::vector<IChunkFile::ChunkDesc*>& chunks)
  545. {
  546.         ChunkPtrListRef c(chunks);
  547.         return GetChunkTableEntries_0x744_0x745_Tpl(pReader, c);
  548. }
  549.  
  550. const char* GetChunkTableEntries_0x746(IReader* pReader, std::vector<IChunkFile::ChunkDesc>& chunks)
  551. {
  552.         ChunkListRef c(chunks);
  553.         return GetChunkTableEntries_0x746_Tpl(pReader, c);
  554. }
  555.  
  556. const char* GetChunkTableEntries_0x746(IReader* pReader, std::vector<IChunkFile::ChunkDesc*>& chunks)
  557. {
  558.         ChunkPtrListRef c(chunks);
  559.         return GetChunkTableEntries_0x746_Tpl(pReader, c);
  560. }
  561.  
  562. const char* StripChunkHeaders_0x744_0x745(IReader* pReader, std::vector<IChunkFile::ChunkDesc>& chunks)
  563. {
  564.         ChunkListRef c(chunks);
  565.         return StripChunkHeaders_0x744_0x745_Tpl(pReader, c);
  566. }
  567.  
  568. const char* StripChunkHeaders_0x744_0x745(IReader* pReader, std::vector<IChunkFile::ChunkDesc*>& chunks)
  569. {
  570.         ChunkPtrListRef c(chunks);
  571.         return StripChunkHeaders_0x744_0x745_Tpl(pReader, c);
  572. }
  573.  
  574. }  // namespace ChunkFile
  575.  
downloadChunkFileReaders.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top