BVB Source Codes

CRYENGINE Show ChunkFile.cpp Source code

Return Download CRYENGINE: download ChunkFile.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:   ChunkFile.h
  5. //  Created:     2004/11/15/11 by Timur
  6. //
  7. ////////////////////////////////////////////////////////////////////////////
  8.  
  9. #include "StdAfx.h"
  10. #include "ChunkFile.h"
  11. #include "ChunkFileReaders.h"
  12. #include "ChunkFileWriters.h"
  13.  
  14. #if !defined(FUNCTION_PROFILER_3DENGINE)
  15.         #define FUNCTION_PROFILER_3DENGINE
  16. #endif
  17.  
  18. #if !defined(LOADING_TIME_PROFILE_SECTION)
  19.         #define LOADING_TIME_PROFILE_SECTION
  20. #endif
  21.  
  22. namespace
  23. {
  24. inline bool ChunkLessOffset(const IChunkFile::ChunkDesc* const p0, const IChunkFile::ChunkDesc* const p1)
  25. {
  26.         return IChunkFile::ChunkDesc::LessOffset(*p0, *p1);
  27. }
  28. }
  29.  
  30. CChunkFile::CChunkFile()
  31.         : m_pInternalData(NULL)
  32. {
  33.         Clear();
  34. }
  35.  
  36. CChunkFile::~CChunkFile()
  37. {
  38.         Clear();
  39. }
  40.  
  41. void CChunkFile::Clear()
  42. {
  43.         ReleaseMemoryBuffer();
  44.         ReleaseChunks();
  45.  
  46.         m_nLastChunkId = 0;
  47.         m_pInternalData = NULL;
  48.         m_bLoaded = false;
  49. }
  50.  
  51. //////////////////////////////////////////////////////////////////////////
  52. CChunkFile::ChunkDesc* CChunkFile::GetChunk(int nChunkIdx)
  53. {
  54.         assert(nChunkIdx >= 0 && nChunkIdx < (int)m_chunks.size());
  55.         return m_chunks[nChunkIdx];
  56. }
  57.  
  58. const CChunkFile::ChunkDesc* CChunkFile::GetChunk(int nChunkIdx) const
  59. {
  60.         assert(nChunkIdx >= 0 && nChunkIdx < (int)m_chunks.size());
  61.         return m_chunks[nChunkIdx];
  62. }
  63.  
  64. // number of chunks
  65. int CChunkFile::NumChunks() const
  66. {
  67.         return (int)m_chunks.size();
  68. }
  69.  
  70. //////////////////////////////////////////////////////////////////////////
  71. int CChunkFile::AddChunk(ChunkTypes chunkType, int chunkVersion, EEndianness eEndianness, const void* chunkData, int chunkSize)
  72. {
  73.         ChunkDesc* const pChunk = new ChunkDesc;
  74.  
  75.         pChunk->bSwapEndian = (eEndianness == eEndianness_NonNative);
  76.  
  77.         // This block of code is used for debugging only
  78.         if (false)
  79.         {
  80.                 for (size_t i = 0, n = m_chunks.size(); i < n; ++i)
  81.                 {
  82.                         if (m_chunks[i]->bSwapEndian != pChunk->bSwapEndian)
  83.                         {
  84.                                 break;
  85.                         }
  86.                 }
  87.         }
  88.  
  89.         pChunk->chunkType = chunkType;
  90.         pChunk->chunkVersion = chunkVersion;
  91.  
  92.         const int chunkId = ++m_nLastChunkId;
  93.         pChunk->chunkId = chunkId;
  94.  
  95.         pChunk->data = new char[chunkSize];
  96.         pChunk->size = chunkSize;
  97.         memcpy(pChunk->data, chunkData, chunkSize);
  98.  
  99.         m_chunks.push_back(pChunk);
  100.         m_chunkIdMap[chunkId] = pChunk;
  101.  
  102.         return chunkId;
  103. }
  104.  
  105. //////////////////////////////////////////////////////////////////////////
  106. void CChunkFile::DeleteChunkById(int nChunkId)
  107. {
  108.         for (size_t i = 0, n = m_chunks.size(); i < n; ++i)
  109.         {
  110.                 if (m_chunks[i]->chunkId == nChunkId)
  111.                 {
  112.                         m_chunkIdMap.erase(nChunkId);
  113.                         if (m_chunks[i]->data)
  114.                         {
  115.                                 delete[] (char*)m_chunks[i]->data;
  116.                                 m_chunks[i]->data = 0;
  117.                         }
  118.                         delete m_chunks[i];
  119.                         m_chunks.erase(m_chunks.begin() + i);
  120.                         return;
  121.                 }
  122.         }
  123. }
  124.  
  125. //////////////////////////////////////////////////////////////////////////
  126. void CChunkFile::DeleteChunksByType(ChunkTypes nChunkType)
  127. {
  128.         size_t j = 0;
  129.         for (size_t i = 0, n = m_chunks.size(); i < n; ++i)
  130.         {
  131.                 if (m_chunks[i]->chunkType == nChunkType)
  132.                 {
  133.                         m_chunkIdMap.erase(m_chunks[i]->chunkId);
  134.                         if (m_chunks[i]->data)
  135.                         {
  136.                                 delete[] (char*)m_chunks[i]->data;
  137.                                 m_chunks[i]->data = 0;
  138.                         }
  139.                         delete m_chunks[i];
  140.                 }
  141.                 else
  142.                 {
  143.                         m_chunks[j] = m_chunks[i];
  144.                         ++j;
  145.                 }
  146.         }
  147.         m_chunks.resize(j);
  148. }
  149.  
  150. //////////////////////////////////////////////////////////////////////////
  151. void CChunkFile::ReleaseChunks()
  152. {
  153.         m_bLoaded = false;
  154.         for (size_t i = 0; i < m_chunks.size(); ++i)
  155.         {
  156.                 if (m_chunks[i]->data)
  157.                 {
  158.                         delete[] (char*) m_chunks[i]->data;
  159.                 }
  160.                 delete m_chunks[i];
  161.         }
  162.         m_chunks.clear();
  163.         m_chunkIdMap.clear();
  164. }
  165.  
  166. //////////////////////////////////////////////////////////////////////////
  167. CChunkFile::ChunkDesc* CChunkFile::FindChunkByType(ChunkTypes nChunkType)
  168. {
  169.         for (size_t i = 0; i < m_chunks.size(); ++i)
  170.         {
  171.                 if (m_chunks[i]->chunkType == nChunkType)
  172.                 {
  173.                         return m_chunks[i];
  174.                 }
  175.         }
  176.         return 0;
  177. }
  178.  
  179. //////////////////////////////////////////////////////////////////////////
  180. CChunkFile::ChunkDesc* CChunkFile::FindChunkById(int nChunkId)
  181. {
  182.         ChunkIdMap::iterator it = m_chunkIdMap.find(nChunkId);
  183.         if (it != m_chunkIdMap.end())
  184.         {
  185.                 return it->second;
  186.         }
  187.         return 0;
  188. }
  189.  
  190. //////////////////////////////////////////////////////////////////////////
  191. bool CChunkFile::Write(const char* filename)
  192. {
  193.         if (m_chunks.empty())
  194.         {
  195.                 m_LastError.Format("Writing *empty* chunk files is not supported (file '%s')", filename);
  196.                 return false;
  197.         }
  198.  
  199.         // Validate requested endianness. Kept here for debug.
  200.         if (false)
  201.         {
  202.                 bool bHasSwapEndianTrue = false;
  203.                 bool bHasSwapEndianFalse = false;
  204.                 for (size_t i = 0; i < m_chunks.size(); ++i)
  205.                 {
  206.                         const ChunkDesc& cd = *m_chunks[i];
  207.                         if (cd.bSwapEndian)
  208.                         {
  209.                                 bHasSwapEndianTrue = true;
  210.                         }
  211.                         else
  212.                         {
  213.                                 bHasSwapEndianFalse = true;
  214.                         }
  215.                 }
  216.                 if (bHasSwapEndianTrue && bHasSwapEndianFalse)
  217.                 {
  218.                         //Warning("Writing chunk files with *mixed* endianness is not supported (file '%s')", filename);
  219.                 }
  220.         }
  221.  
  222.         ChunkFile::OsFileWriter writer;
  223.  
  224.         if (!writer.Create(filename))
  225.         {
  226.                 m_LastError.Format("Failed to open '%s' for writing", filename);
  227.                 return false;
  228.         }
  229.  
  230.         ChunkFile::MemorylessChunkFileWriter wr(ChunkFile::MemorylessChunkFileWriter::eChunkFileFormat_0x746, &writer);
  231.         wr.SetAlignment(4);
  232.  
  233.         while (wr.StartPass())
  234.         {
  235.                 for (size_t i = 0; i < m_chunks.size(); ++i)
  236.                 {
  237.                         const ChunkDesc& cd = *m_chunks[i];
  238.                         wr.StartChunk((cd.bSwapEndian ? eEndianness_NonNative : eEndianness_Native), cd.chunkType, cd.chunkVersion, cd.chunkId);
  239.                         wr.AddChunkData(cd.data, cd.size);
  240.                 }
  241.         }
  242.  
  243.         if (!wr.HasWrittenSuccessfully())
  244.         {
  245.                 m_LastError.Format("Failed to write '%s'", filename);
  246.                 return false;
  247.         }
  248.  
  249.         return true;
  250. }
  251.  
  252. //////////////////////////////////////////////////////////////////////////
  253. bool CChunkFile::WriteToMemoryBuffer(void** pData, int* nSize)
  254. {
  255.         ReleaseMemoryBuffer();
  256.         *pData = 0;
  257.  
  258.         if (m_chunks.empty())
  259.         {
  260.                 m_LastError.Format("Writing *empty* chunk files is not supported");
  261.                 return false;
  262.         }
  263.  
  264.         // Do writing in *two* stages:
  265.         //  1) computing required size (see sizeWriter below)
  266.         //  2) allocating and writing data (see memoryWriter below)
  267.  
  268.         ChunkFile::SizeWriter sizeWriter;
  269.         ChunkFile::MemoryWriter memoryWriter;
  270.  
  271.         for (int stage = 0; stage < 2; ++stage)
  272.         {
  273.                 ChunkFile::IWriter* pWriter;
  274.                 if (stage == 0)
  275.                 {
  276.                         sizeWriter.Start();
  277.                         pWriter = &sizeWriter;
  278.                 }
  279.                 else
  280.                 {
  281.                         assert(m_pInternalData == 0);
  282.                         *nSize = sizeWriter.GetPos();
  283.                         assert(*nSize > 0);
  284.  
  285.                         m_pInternalData = (char*)malloc(*nSize);
  286.                         if (m_pInternalData == 0)
  287.                         {
  288.                                 m_LastError.Format("Failed to allocate %u bytes", uint(*nSize));
  289.                                 return false;
  290.                         }
  291.  
  292.                         if (!memoryWriter.Start(m_pInternalData, *nSize))
  293.                         {
  294.                                 assert(0);
  295.                                 m_LastError.Format("Internal error");
  296.                                 ReleaseMemoryBuffer();
  297.                                 return false;
  298.                         }
  299.                         pWriter = &memoryWriter;
  300.                 }
  301.  
  302.                 ChunkFile::MemorylessChunkFileWriter wr(ChunkFile::MemorylessChunkFileWriter::eChunkFileFormat_0x746, pWriter);
  303.                 wr.SetAlignment(4);
  304.  
  305.                 while (wr.StartPass())
  306.                 {
  307.                         for (size_t i = 0; i < m_chunks.size(); ++i)
  308.                         {
  309.                                 const ChunkDesc& cd = *m_chunks[i];
  310.                                 wr.StartChunk((cd.bSwapEndian ? eEndianness_NonNative : eEndianness_Native), cd.chunkType, cd.chunkVersion, cd.chunkId);
  311.                                 wr.AddChunkData(cd.data, cd.size);
  312.                         }
  313.                 }
  314.  
  315.                 if (!wr.HasWrittenSuccessfully())
  316.                 {
  317.                         m_LastError.Format("Failed to write");
  318.                         ReleaseMemoryBuffer();
  319.                         return false;
  320.                 }
  321.  
  322.                 assert(stage != 2 || memoryWriter.GetPos() == *nSize);
  323.         }
  324.  
  325.         *pData = m_pInternalData;
  326.  
  327.         return true;
  328. }
  329.  
  330. //////////////////////////////////////////////////////////////////////////
  331. void CChunkFile::ReleaseMemoryBuffer()
  332. {
  333.         if (m_pInternalData)
  334.         {
  335.                 free(m_pInternalData);
  336.                 m_pInternalData = 0;
  337.         }
  338. }
  339.  
  340. //////////////////////////////////////////////////////////////////////////
  341. bool CChunkFile::Read(const char* filename)
  342. {
  343.         LOADING_TIME_PROFILE_SECTION;
  344.  
  345.         ReleaseChunks();
  346.  
  347.         // Loading chunks
  348.         {
  349.                 ChunkFile::CryFileReader f;
  350.  
  351.                 if (!f.Open(filename))
  352.                 {
  353.                         m_LastError.Format("File %s failed to open for reading", filename);
  354.                         return false;
  355.                 }
  356.  
  357.                 {
  358.                         const char* err = 0;
  359.  
  360.                         err = ChunkFile::GetChunkTableEntries_0x746(&f, m_chunks);
  361.                         if (err)
  362.                         {
  363.                                 err = ChunkFile::GetChunkTableEntries_0x744_0x745(&f, m_chunks);
  364.                                 if (!err)
  365.                                 {
  366.                                         err = ChunkFile::StripChunkHeaders_0x744_0x745(&f, m_chunks);
  367.                                 }
  368.                         }
  369.  
  370.                         if (err)
  371.                         {
  372.                                 m_LastError = err;
  373.                                 return false;
  374.                         }
  375.                 }
  376.  
  377.                 for (size_t i = 0; i < m_chunks.size(); ++i)
  378.                 {
  379.                         ChunkDesc& cd = *m_chunks[i];
  380.  
  381.                         assert(cd.data == 0);
  382.  
  383.                         cd.data = new char[cd.size];
  384.  
  385.                         if (!f.SetPos(cd.fileOffset) ||
  386.                             !f.Read(cd.data, cd.size))
  387.                         {
  388.                                 m_LastError.Format(
  389.                                   "Failed to read chunk data (offset:%u, size:%u) from file %s",
  390.                                   cd.fileOffset, cd.size, filename);
  391.                                 return false;
  392.                         }
  393.                 }
  394.         }
  395.  
  396.         m_nLastChunkId = 0;
  397.  
  398.         for (size_t i = 0; i < m_chunks.size(); ++i)
  399.         {
  400.                 // Add chunk to chunk map.
  401.                 m_chunkIdMap[m_chunks[i]->chunkId] = m_chunks[i];
  402.  
  403.                 // Update last chunk ID.
  404.                 if (m_chunks[i]->chunkId > m_nLastChunkId)
  405.                 {
  406.                         m_nLastChunkId = m_chunks[i]->chunkId;
  407.                 }
  408.         }
  409.  
  410.         if (m_chunks.size() != m_chunkIdMap.size())
  411.         {
  412.                 const int duplicateCount = (int)(m_chunks.size() - m_chunkIdMap.size());
  413.                 m_LastError.Format(
  414.                   "%d duplicate chunk ID%s found in file %s",
  415.                   duplicateCount, ((duplicateCount > 1) ? "s" : ""), filename);
  416.                 return false;
  417.         }
  418.  
  419.         m_bLoaded = true;
  420.  
  421.         return true;
  422. }
  423.  
downloadChunkFile.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