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.