diff --git a/LibCmo/CKFile.cpp b/LibCmo/CKFile.cpp index 4e652a5..562b945 100644 --- a/LibCmo/CKFile.cpp +++ b/LibCmo/CKFile.cpp @@ -37,17 +37,19 @@ namespace LibCmo::CK2 { } CKFileObject::~CKFileObject() { - ; + if (Data != nullptr) delete Data; } #pragma endregion #pragma region CKFileManagerData - CKFileManagerData::CKFileManagerData() { + CKFileManagerData::CKFileManagerData() : + Data(nullptr) { } CKFileManagerData::~CKFileManagerData() { + if (Data != nullptr) delete Data; } #pragma endregion @@ -67,7 +69,7 @@ namespace LibCmo::CK2 { #pragma region ShallowDocument ShallowDocument::ShallowDocument() { - this->m_IndexByClassId.resize(static_cast(CK_CLASSID::CKCID_MAXCLASSID)); + /*this->m_IndexByClassId.resize(static_cast(CK_CLASSID::CKCID_MAXCLASSID));*/ } ShallowDocument::~ShallowDocument() { @@ -79,7 +81,7 @@ namespace LibCmo::CK2 { #pragma region DeepDocument DeepDocument::DeepDocument() { - this->m_IndexByClassId.resize(static_cast(CK_CLASSID::CKCID_MAXCLASSID)); + /*this->m_IndexByClassId.resize(static_cast(CK_CLASSID::CKCID_MAXCLASSID));*/ } DeepDocument::~DeepDocument() { diff --git a/LibCmo/CKFile.hpp b/LibCmo/CKFile.hpp index b30cbe0..1aca6a7 100644 --- a/LibCmo/CKFile.hpp +++ b/LibCmo/CKFile.hpp @@ -137,7 +137,7 @@ namespace LibCmo::CK2 { XArray m_FileObjects; XArray m_FileManagersData; XClassArray m_PluginDep; - XClassArray m_IndexByClassId; + /*XClassArray m_IndexByClassId;*/ XClassArray m_IncludedFiles; private: @@ -155,7 +155,7 @@ namespace LibCmo::CK2 { CKFileInfo m_FileInfo; XArray m_Objects; - XClassArray m_IndexByClassId; + /*XClassArray m_IndexByClassId;*/ XClassArray m_IncludedFiles; private: diff --git a/LibCmo/CKFileReader.cpp b/LibCmo/CKFileReader.cpp index fd7b0e3..f8b5f82 100644 --- a/LibCmo/CKFileReader.cpp +++ b/LibCmo/CKFileReader.cpp @@ -1,6 +1,7 @@ #include "CKFile.hpp" #include "CKGlobals.hpp" #include "CKStateChunk.hpp" +#include "CKObjects.hpp" #include "VxMemoryMappedFile.hpp" #include "CKMinContext.hpp" #include @@ -351,6 +352,65 @@ namespace LibCmo::CK2 { } CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileData::DeepDocument** out_doc) { + // ========== prepare work ========== + // preset value + *out_doc = nullptr; + + // get shallow document first + CKFileData::ShallowDocument* rawShallowDoc = nullptr; + CKERROR err = this->ShallowLoad(u8_filename, &rawShallowDoc); + if (rawShallowDoc == nullptr) return err; + std::unique_ptr shallowDoc(rawShallowDoc); + if (err != CKERROR::CKERR_OK) return err; + + // create deep document + std::unique_ptr deepDoc(new(std::nothrow) CKFileData::DeepDocument()); + if (deepDoc == nullptr) return CKERROR::CKERR_OUTOFMEMORY; + + // ========== create object first ========== + size_t index = 0u; + std::vector createdObjs(shallowDoc->m_FileObjects.size(), nullptr); + for (index = 0u; index < shallowDoc->m_FileObjects.size(); ++index) { + // todo: skip CK_LEVEL + // todo: resolve references + const auto& obj = shallowDoc->m_FileObjects[index]; + if (obj.Data == nullptr) continue; + + createdObjs[index] = m_MinCtx->CreateCKObject(obj.ObjectId, obj.ObjectCid, obj.Name.c_str()); + } + + // ========== CKStateChunk remap ========== + // todo: remap + // todo: CK_LEVEL special proc + + // ========== consume Managers ========== + // todo... + + // ========== analyze objects CKStateChunk ========== + for (index = 0u; index < shallowDoc->m_FileObjects.size(); ++index) { + const auto& obj = shallowDoc->m_FileObjects[index]; + if (obj.Data == nullptr || createdObjs[index] == nullptr) continue; + + // todo: special treat for CK_LEVEL + // try parsing data + CKERROR err = createdObjs[index]->Load(obj.Data, shallowDoc.get()); + if (err != CKERROR::CKERR_OK) { + delete (createdObjs[index]); + createdObjs[index] = nullptr; + } else { + // add into result + deepDoc->m_Objects.push_back(createdObjs[index]); + } + + } + + // ========== finalize work ========== + // copy misc structure + deepDoc->m_IncludedFiles = shallowDoc->m_IncludedFiles; + deepDoc->m_SaveIDMax = shallowDoc->m_SaveIDMax; + deepDoc->m_FileInfo = shallowDoc->m_FileInfo; + // detach and return + *out_doc = deepDoc.release(); return CKERROR::CKERR_OK; } diff --git a/LibCmo/CKMinContext.cpp b/LibCmo/CKMinContext.cpp index 52f7db9..b5ac17a 100644 --- a/LibCmo/CKMinContext.cpp +++ b/LibCmo/CKMinContext.cpp @@ -11,11 +11,13 @@ namespace LibCmo::CK2 { static char g_UniqueFolder[] = "LibCmo"; #endif +#pragma region Ctor Dtor CKMinContext::CKMinContext() : m_NameEncoding(), m_NameEncodingToken(EncodingHelper::ENCODING_TOKEN_DEFAULT), m_TempFolder(), m_PrintCallback(nullptr), + m_CKObjectMaxID(0u), // register CKObjects m_ObjectsCreationMap{ {CK_CLASSID::CKCID_OBJECT, ([](CKMinContext* ctx, CK_ID id, CKSTRING name) ->CKObjectImplements::CKObject* { return new(std::nothrow) CKObjectImplements::CKObject(ctx, id, name); })}, @@ -43,6 +45,10 @@ namespace LibCmo::CK2 { } +#pragma endregion + +#pragma region Print + void CKMinContext::Printf(CKSTRING fmt, ...) { if (m_PrintCallback == nullptr) return; @@ -65,6 +71,52 @@ namespace LibCmo::CK2 { m_PrintCallback = cb; } +#pragma endregion + +#pragma region Objects + + CKObjectImplements::CKObject* CKMinContext::CreateCKObject(CK_ID id, CK_CLASSID cls, CKSTRING name) { + // pick creation function + const auto& creation = m_ObjectsCreationMap.find(cls); + if (creation == m_ObjectsCreationMap.end()) return nullptr; + + // check ckid + if (m_ObjectsList.contains(id)) return nullptr; + + // create it + return creation->second(this, id, name); + } + + CKObjectImplements::CKObject* CKMinContext::GetCKObject(CK_ID id) { + const auto& probe = m_ObjectsList.find(id); + if (probe == m_ObjectsList.end()) return nullptr; + else return probe->second; + } + + void CKMinContext::DestroyCKObject(CK_ID id) { + const auto& probe = m_ObjectsList.find(id); + if (probe != m_ObjectsList.end()) { + delete (probe->second); + m_ObjectsList.erase(probe); + } + } + + CK_ID CKMinContext::GetObjectMaxID(void) { + return this->m_CKObjectMaxID; + } + + void CKMinContext::SetObjectMaxID(CK_ID id) { + this->m_CKObjectMaxID = id; + } + +#pragma endregion + +#pragma region Managers + +#pragma endregion + +#pragma region Misc Funcs + void CKMinContext::GetUtf8String(std::string& native_name, std::string& u8_name) { EncodingHelper::GetUtf8VirtoolsName(native_name, u8_name, this->m_NameEncodingToken); } @@ -95,4 +147,6 @@ namespace LibCmo::CK2 { this->m_NameEncodingToken = EncodingHelper::CreateEncodingToken(this->m_NameEncoding); } +#pragma endregion + } \ No newline at end of file diff --git a/LibCmo/CKMinContext.hpp b/LibCmo/CKMinContext.hpp index 087a593..69c8a18 100644 --- a/LibCmo/CKMinContext.hpp +++ b/LibCmo/CKMinContext.hpp @@ -22,11 +22,14 @@ namespace LibCmo::CK2 { CKObjectImplements::CKObject* CreateCKObject(CK_ID id, CK_CLASSID cls, CKSTRING name); CKObjectImplements::CKObject* GetCKObject(CK_ID id); - void DestroyCKObject(CKObjectImplements::CKObject* obj); + void DestroyCKObject(CK_ID id); - CKManagerImplements::CKBaseManager* CreateCKManager(CKGUID guid); - CKManagerImplements::CKBaseManager* GetCKManager(CK_ID guid); - void DestroyCKManager(CKManagerImplements::CKBaseManager* mgr); + //CKManagerImplements::CKBaseManager* CreateCKManager(CKGUID guid); + //CKManagerImplements::CKBaseManager* GetCKManager(CK_ID guid); + //void DestroyCKManager(CKManagerImplements::CKBaseManager* mgr); + + CK_ID GetObjectMaxID(void); + void SetObjectMaxID(CK_ID id); void GetUtf8String(std::string& native_name, std::string& u8_name); void GetNativeString(std::string& u8_name, std::string& native_name); @@ -45,6 +48,8 @@ namespace LibCmo::CK2 { std::map> m_ObjectsCreationMap; std::map> m_ManagersCreationMap; + CK_ID m_CKObjectMaxID; + std::string m_NameEncoding; EncodingHelper::ENCODING_TOKEN m_NameEncodingToken; std::filesystem::path m_TempFolder; diff --git a/LibCmo/CKObjectImplements/CKObject.cpp b/LibCmo/CKObjectImplements/CKObject.cpp index 4b0f474..302f385 100644 --- a/LibCmo/CKObjectImplements/CKObject.cpp +++ b/LibCmo/CKObjectImplements/CKObject.cpp @@ -4,7 +4,7 @@ namespace LibCmo::CK2::CKObjectImplements { CKObject::CKObject(CKMinContext* ctx, CK_ID ckid, CKSTRING name) : m_ID(ckid), m_Context(ctx), - m_Name(name == nullptr ? "" : name), m_HasName(name != nullptr), + m_Name(name == nullptr ? "" : name), m_ObjectFlags(CK_OBJECT_FLAGS::CK_PARAMETERIN_DISABLED) { ; } @@ -13,6 +13,13 @@ namespace LibCmo::CK2::CKObjectImplements { } + CKERROR CKObject::Load(CKStateChunk* chunk, const CKFileData::ShallowDocument* doc) { + return CKERROR::CKERR_OK; + } + CKStateChunk* CKObject::Save(CKFileData::ShallowDocument* doc) { + return nullptr; + } + CKSceneObject::CKSceneObject(CKMinContext* ctx, CK_ID ckid, CKSTRING name) : CKObject(ctx, ckid, name) { } CKSceneObject::~CKSceneObject() { @@ -35,6 +42,11 @@ namespace LibCmo::CK2::CKObjectImplements { CKTexture::CKTexture(CKMinContext* ctx, CK_ID ckid, CKSTRING name) : CKBeObject(ctx, ckid, name) { } + CKTexture::~CKTexture() { + } + + CKMaterial::CKMaterial(CKMinContext* ctx, CK_ID ckid, CKSTRING name) : CKBeObject(ctx, ckid, name) { + } CKMaterial::~CKMaterial() { } diff --git a/LibCmo/CKObjects.hpp b/LibCmo/CKObjects.hpp index 5550194..2d31279 100644 --- a/LibCmo/CKObjects.hpp +++ b/LibCmo/CKObjects.hpp @@ -13,22 +13,17 @@ namespace LibCmo::CK2::CKObjectImplements { virtual ~CKObject(); CK_ID GetID(void) { return this->m_ID; } - CKSTRING GetName(void) { return m_HasName ? this->m_Name.c_str() : nullptr; } - void SetName(CKSTRING u8_name) { - this->m_HasName = u8_name != nullptr; - if (this->m_HasName) this->m_Name = u8_name; - else this->m_Name.clear(); - } + CKSTRING GetName(void) { (this->m_Name.empty()) ? (nullptr) : (this->m_Name.c_str()); } + void SetName(CKSTRING u8_name) { this->m_Name = (u8_name == nullptr ? "" : u8_name); } CK_OBJECT_FLAGS GetObjectFlags(void) { return this->m_ObjectFlags; } void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; } virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; } - virtual CKERROR Load(CKStateChunk* chunk, CKFileData::ShallowDocument* doc); + virtual CKERROR Load(CKStateChunk* chunk, const CKFileData::ShallowDocument* doc); virtual CKStateChunk* Save(CKFileData::ShallowDocument* doc); protected: CK_ID m_ID; std::string m_Name; - bool m_HasName; CK_OBJECT_FLAGS m_ObjectFlags; CKMinContext* m_Context; }; diff --git a/Unvirt/Unvirt.cpp b/Unvirt/Unvirt.cpp index 0e98e3a..b34830b 100644 --- a/Unvirt/Unvirt.cpp +++ b/Unvirt/Unvirt.cpp @@ -17,8 +17,8 @@ int main(int argc, char* argv[]) { vtctx.SetEncoding("850"); LibCmo::CK2::CKFile vtfile(&vtctx); - LibCmo::CK2::CKFileData::ShallowDocument* doc; - LibCmo::CK2::CKERROR err = vtfile.ShallowLoad("Language.old.nmo", &doc); + LibCmo::CK2::CKFileData::DeepDocument* doc; + LibCmo::CK2::CKERROR err = vtfile.DeepLoad("Language.old.nmo", &doc); if (doc) Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);