diff --git a/CodeGen/src/CKMISC.txt b/CodeGen/src/CKMISC.txt index c2c1f55..03725d2 100644 --- a/CodeGen/src/CKMISC.txt +++ b/CodeGen/src/CKMISC.txt @@ -36,3 +36,35 @@ enum CK_PLUGIN_TYPE CKPLUGIN_MOVIE_READER = 6, // Movie (AVI,Mpeg) reader CKPLUGIN_EXTENSION_DLL = 7, // Generic extension (definition of new parameter types or operations for ex.) +enum CK_STATECHUNK_DATAVERSION + CHUNKDATA_OLDVERSION= 0, // Before any version was saved + CHUNKDATA_BASEVERSION= 1, // First version + CHUNK_WAVESOUND_VERSION2= 2, // Changes in wavesound format + CHUNK_WAVESOUND_VERSION3= 3, // Changes in wavesound format + CHUNK_MATERIAL_VERSION_ZTEST= 4, // Change in material save format + CHUNK_MAJORCHANGE_VERSION= 5, // Optimisations on many save functions + CHUNK_MACCHANGE_VERSION= 6, // Misc new Statechunk functions for macintosh (Big-Endian <-> Little Endian conversion ) + CHUNK_WAVESOUND_VERSION4= 7, // Changes in wavesound format (Added sound length) + CHUNK_SCENECHANGE_VERSION= 8, // Changes in sceneObjectDesc format (Remove lasttimevalue) + CHUNK_MESHCHANGE_VERSION= 9, // Changes in Mesh save format (primitives) + CHUNK_DEV_2_1= 10, // Changes in wavesound reading of inside, outside angles + + CHUNKDATA_CURRENTVERSION= CHUNK_DEV_2_1 , + +enum CK_STATECHUNK_CHUNKVERSION + CHUNK_VERSIONBASE= 0, + CHUNK_VERSION1= 4, // equal to file version : WriteObjectID => table + CHUNK_VERSION2= 5, // add Manager Data + CHUNK_VERSION3= 6, // New ConvertToBuffer / ReadFromBuffer (file system changed to reflect this ) + CHUNK_VERSION4= 7, // New WriteObjectID when saving to a file + +enum CK_STATECHUNK_CHUNKOPTIONS + CHNK_OPTION_IDS = 0x01, // IDS are stored inside chunk + CHNK_OPTION_MAN = 0x02, // Managers ints are store inside chunk + CHNK_OPTION_CHN = 0x04, // Sub chunk are stored inside chunk + CHNK_OPTION_FILE = 0x08, // Chunk was written with indices relative to a file.... + CHNK_OPTION_ALLOWDYN = 0x10, // Dynamic object can be written in the chunk + CHNK_OPTION_LISTBIG = 0x20, // List are store in big Endian ? + CHNK_DONTDELETE_PTR = 0x40, // Data buffer stored in m_Buffer is not owned by CKStateChunk , it must not be deleted... + CHNK_DONTDELETE_PARSER = 0x80, // m_Parser Ptr is not owned by CKStateChunk , it must not be deleted... + diff --git a/LibCmo/LibCmo.vcxproj b/LibCmo/LibCmo.vcxproj index 600f759..2096c66 100644 --- a/LibCmo/LibCmo.vcxproj +++ b/LibCmo/LibCmo.vcxproj @@ -173,6 +173,7 @@ + diff --git a/LibCmo/LibCmo.vcxproj.filters b/LibCmo/LibCmo.vcxproj.filters index b93dc59..fb0ce14 100644 --- a/LibCmo/LibCmo.vcxproj.filters +++ b/LibCmo/LibCmo.vcxproj.filters @@ -24,6 +24,9 @@ Sources + + Sources + diff --git a/LibCmo/VTConstants.hpp b/LibCmo/VTConstants.hpp index b89b22e..c806723 100644 --- a/LibCmo/VTConstants.hpp +++ b/LibCmo/VTConstants.hpp @@ -29,6 +29,7 @@ namespace LibCmo { using CKINT = int32_t; using CK_ID = uint32_t; using CKDWORD = uint32_t; + using CKWORD = uint16_t; using CKBOOL = int32_t; using CKMUTSTRING = char*; using CKSTRING = const char*; @@ -203,6 +204,37 @@ namespace LibCmo { CKPLUGIN_MOVIE_READER = 6, CKPLUGIN_EXTENSION_DLL = 7 }; + enum class CK_STATECHUNK_DATAVERSION : int32_t { + CHUNKDATA_OLDVERSION = 0, + CHUNKDATA_BASEVERSION = 1, + CHUNK_WAVESOUND_VERSION2 = 2, + CHUNK_WAVESOUND_VERSION3 = 3, + CHUNK_MATERIAL_VERSION_ZTEST = 4, + CHUNK_MAJORCHANGE_VERSION = 5, + CHUNK_MACCHANGE_VERSION = 6, + CHUNK_WAVESOUND_VERSION4 = 7, + CHUNK_SCENECHANGE_VERSION = 8, + CHUNK_MESHCHANGE_VERSION = 9, + CHUNK_DEV_2_1 = 10, + CHUNKDATA_CURRENTVERSION = CHUNK_DEV_2_1 + }; + enum class CK_STATECHUNK_CHUNKVERSION : int32_t { + CHUNK_VERSIONBASE = 0, + CHUNK_VERSION1 = 4, + CHUNK_VERSION2 = 5, + CHUNK_VERSION3 = 6, + CHUNK_VERSION4 = 7 + }; + enum class CK_STATECHUNK_CHUNKOPTIONS : int32_t { + CHNK_OPTION_IDS = 0x01, + CHNK_OPTION_MAN = 0x02, + CHNK_OPTION_CHN = 0x04, + CHNK_OPTION_FILE = 0x08, + CHNK_OPTION_ALLOWDYN = 0x10, + CHNK_OPTION_LISTBIG = 0x20, + CHNK_DONTDELETE_PTR = 0x40, + CHNK_DONTDELETE_PARSER = 0x80 + }; } diff --git a/LibCmo/VTStateChunk.cpp b/LibCmo/VTStateChunk.cpp new file mode 100644 index 0000000..5fa2b92 --- /dev/null +++ b/LibCmo/VTStateChunk.cpp @@ -0,0 +1,156 @@ +#include "VTStruct.hpp" + +namespace LibCmo { + + CKStateChunk::CKStateChunk() : + m_ClassId(CK_CLASSID::CKCID_OBJECT), m_DataDwSize(0u), m_pData(nullptr), + m_DataVersion(CK_STATECHUNK_DATAVERSION::CHUNKDATA_CURRENTVERSION), m_ChunkVersion(CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4), + m_Parser{ 0u, 0u, 0u }, + m_ObjectList(), m_ChunkList(), m_ManagerList() + { + ; + } + + CKStateChunk::~CKStateChunk() { + if (this->m_pData != nullptr) + delete[] this->m_pData; + } + + bool CKStateChunk::ConvertFromBuffer(const void* buf) { + if (buf == nullptr) return false; + + // read chunk ver and data ver first + // chunk ver always set in the 3rd BYTE in every format + this->m_ChunkVersion = static_cast( + reinterpret_cast(buf)[2] + ); + // data ver always set in the 1st BYTE in every format + this->m_DataVersion = static_cast( + reinterpret_cast(buf)[0] + ); + + // switch according to chunk ver + const CKDWORD* dwbuf = reinterpret_cast(buf); + size_t bufpos = 0u; + if (this->m_ChunkVersion < CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION2) { + // very old file + + this->m_ClassId = static_cast(dwbuf[1]); + this->m_DataDwSize = dwbuf[2]; + + this->m_ObjectList.resize(dwbuf[4]); + this->m_ChunkList.resize(dwbuf[5]); + bufpos = 6u; + + if (this->m_DataDwSize != 0) { + this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize]; + if (m_pData == nullptr) return false; + + memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize); + bufpos += this->m_DataDwSize; + } + if (!this->m_ObjectList.empty()) { + memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size()); + bufpos += this->m_ObjectList.size(); + } + if (!this->m_ChunkList.empty()) { + memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size()); + bufpos += this->m_ChunkList.size(); + } + + } else if (this->m_ChunkVersion == CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION2) { + // medium ver file + + this->m_ClassId = static_cast(dwbuf[1]); + this->m_DataDwSize = dwbuf[2]; + + this->m_ObjectList.resize(dwbuf[4]); + this->m_ChunkList.resize(dwbuf[5]); + this->m_ManagerList.resize(dwbuf[6]); + bufpos = 7u; + + if (this->m_DataDwSize != 0) { + this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize]; + if (m_pData == nullptr) return false; + + memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize); + bufpos += this->m_DataDwSize; + } + if (!this->m_ObjectList.empty()) { + memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size()); + bufpos += this->m_ObjectList.size(); + } + if (!this->m_ChunkList.empty()) { + memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size()); + bufpos += this->m_ChunkList.size(); + } + if (!this->m_ManagerList.empty()) { + memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size()); + bufpos += this->m_ManagerList.size(); + } + + } else if (this->m_ChunkVersion <= CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4) { + // the latest file + + // re-read some extra data + // class id located the 2nd BYTE + this->m_ClassId = static_cast( + reinterpret_cast(buf)[1] + ); + // options located the 4th BYTE + CK_STATECHUNK_CHUNKOPTIONS options = static_cast( + reinterpret_cast(buf)[3] + ); + + // read normal data + this->m_DataDwSize = dwbuf[1]; + bufpos = 2; + + if (this->m_DataDwSize != 0) { + this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize]; + if (m_pData == nullptr) return false; + + memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize); + bufpos += this->m_DataDwSize; + } + if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) { + // MARK: set ckfile = nullptr; + ; + } + if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) { + this->m_ObjectList.resize(dwbuf[bufpos]); + bufpos += 1u; + memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size()); + bufpos += this->m_ObjectList.size(); + } + if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) { + this->m_ChunkList.resize(dwbuf[bufpos]); + bufpos += 1u; + memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size()); + bufpos += this->m_ChunkList.size(); + } + if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) { + this->m_ManagerList.resize(dwbuf[bufpos]); + bufpos += 1u; + memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size()); + bufpos += this->m_ManagerList.size(); + } + + + } else { + // too new. can not read, skip + ; + } + + return true; + } + + CKDWORD CKStateChunk::ConvertToBuffer(void* buf) { + return 0u; + } + + void LibCmo::CKStateChunk::_EnsureEnoughSpace(CKDWORD size) { + ; + } + +} diff --git a/LibCmo/VTStruct.hpp b/LibCmo/VTStruct.hpp index 82befec..31a62bd 100644 --- a/LibCmo/VTStruct.hpp +++ b/LibCmo/VTStruct.hpp @@ -82,6 +82,39 @@ namespace LibCmo { inline void SetCursor(size_t off) { this->m_MemPos = off; } }; + class CKStateChunk { + public: + CKStateChunk(); + CKStateChunk(const CKStateChunk&) = delete; + CKStateChunk& operator=(const CKStateChunk&) = delete; + ~CKStateChunk(); + + bool ConvertFromBuffer(const void* buf); + CKDWORD ConvertToBuffer(void* buf); + + private: + CK_CLASSID m_ClassId; + CKDWORD m_DataDwSize; + CKDWORD* m_pData; + + CK_STATECHUNK_DATAVERSION m_DataVersion; + CK_STATECHUNK_CHUNKVERSION m_ChunkVersion; + + struct { + CKDWORD m_CurrentPos; + CKDWORD m_DataSize; + CKDWORD m_PrevIdentifierPos; + }m_Parser; + + std::vector m_ObjectList; + std::vector m_ChunkList; + std::vector m_ManagerList; + + private: + void _EnsureEnoughSpace(CKDWORD size); + + }; + struct CKFileInfo { CKDWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) CKDWORD ProductBuild; // Virtools Build Number.