diff --git a/BMap/BMap.cpp b/BMap/BMap.cpp index 509167b..fbd74ff 100644 --- a/BMap/BMap.cpp +++ b/BMap/BMap.cpp @@ -242,8 +242,11 @@ namespace BMap { cache.emplace_back(encodings[i]); } m_Context->SetEncoding(cache); + // set default texture save mode is external m_Context->SetGlobalImagesSaveOptions(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL); + // set default file write mode is whole compressed + m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED); } BMFile::~BMFile() { @@ -257,16 +260,83 @@ namespace BMap { bool BMFile::Load(LibCmo::CKSTRING filename) { if (m_IsFreezed || !m_IsReader) return false; + // create temp ckfile and load + LibCmo::CK2::CKFileReader reader(m_Context); + LibCmo::CK2::CKERROR err = reader.DeepLoad(filename); + + // detect error + if (err != LibCmo::CK2::CKERROR::CKERR_OK) { + // failed. clear document and return false + m_Context->ClearAll(); + return false; + } + + // sync data list to our list + m_ObjGroups.clear(); + m_Obj3dObjects.clear(); + m_ObjMeshs.clear(); + m_ObjMaterials.clear(); + m_ObjTextures.clear(); + for (const auto& fileobj : reader.GetFileObjects()) { + if (fileobj.ObjPtr == nullptr) continue; + + switch (fileobj.ObjectCid) { + case LibCmo::CK2::CK_CLASSID::CKCID_GROUP: + m_ObjGroups.emplace_back(fileobj.CreatedObjectId); + break; + case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT: + m_Obj3dObjects.emplace_back(fileobj.CreatedObjectId); + break; + case LibCmo::CK2::CK_CLASSID::CKCID_MESH: + m_ObjMeshs.emplace_back(fileobj.CreatedObjectId); + break; + case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL: + m_ObjMaterials.emplace_back(fileobj.CreatedObjectId); + break; + case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE: + m_ObjTextures.emplace_back(fileobj.CreatedObjectId); + break; + } + } + return true; } bool BMFile::Save(LibCmo::CKSTRING filename, LibCmo::CKINT compress_level) { if (m_IsFreezed || m_IsReader) return false; + // create temp writer + LibCmo::CK2::CKFileWriter writer(m_Context); + + // fill object data + for (const auto& id : m_ObjGroups) { + writer.AddSavedObject(m_Context->GetObject(id)); + } + for (const auto& id : m_Obj3dObjects) { + writer.AddSavedObject(m_Context->GetObject(id)); + } + for (const auto& id : m_ObjMeshs) { + writer.AddSavedObject(m_Context->GetObject(id)); + } + for (const auto& id : m_ObjMaterials) { + writer.AddSavedObject(m_Context->GetObject(id)); + } + for (const auto& id : m_ObjTextures) { + writer.AddSavedObject(m_Context->GetObject(id)); + } + + // set compress level + m_Context->SetCompressionLevel(compress_level); + + // save to file and detect error + LibCmo::CK2::CKERROR err = writer.Save(filename); + // set freezed to stop any change again. // aka, only allow save once. m_IsFreezed = true; - return true; + + // return with error detect. + return err == LibCmo::CK2::CKERROR::CKERR_OK; } LibCmo::CK2::ObjImpls::CKObject* BMFile::GetObjectPtr(LibCmo::CK2::CK_ID objid) { diff --git a/LibCmo/VTUserAll.hpp b/LibCmo/VTUserAll.hpp index ec9a793..9f00e17 100644 --- a/LibCmo/VTUserAll.hpp +++ b/LibCmo/VTUserAll.hpp @@ -9,6 +9,7 @@ Use VTAll.hpp for project internal including. #include "VTAll.hpp" #include "CK2/CKContext.hpp" #include "CK2/CKStateChunk.hpp" +#include "CK2/CKFile.hpp" // Data handlers #include "CK2/DataHandlers/CKBitmapHandler.hpp" diff --git a/Unvirt/StructFormatter.cpp b/Unvirt/StructFormatter.cpp index 2f8a415..be023f1 100644 --- a/Unvirt/StructFormatter.cpp +++ b/Unvirt/StructFormatter.cpp @@ -122,7 +122,7 @@ namespace Unvirt::StructFormatter { LibCmo::CKDWORD count = obj->GetObjectCount(); fprintf(stdout, "Group Object Count: %" PRIuCKDWORD "\n", count); - fputs("Id\tType\tObject Pointer\tName\n", stdout); + fputs("CKID\tType\tObject\tName\n", stdout); for (LibCmo::CKDWORD i = 0; i < count; ++i) { LibCmo::CK2::ObjImpls::CKBeObject* beobj = obj->GetObject(i); diff --git a/Unvirt/UnvirtContext.cpp b/Unvirt/UnvirtContext.cpp index 3f1809c..b46f6ea 100644 --- a/Unvirt/UnvirtContext.cpp +++ b/Unvirt/UnvirtContext.cpp @@ -617,6 +617,43 @@ namespace Unvirt::Context { void Unvirt::Context::UnvirtContext::ProcTest(const CmdHelper::ArgumentsMap* amap) { #if defined(LIBCMO_BUILD_DEBUG) // MARK: Add the debug code here. + + // todo: temporaryly write Transparent Column Fixer code. + // move to independent app in future. + + // check pre-requirement + if (!HasOpenedFile()) { + PrintCommonError("No loaded file."); + return; + } + if (!m_IsShallowRead) { + PrintCommonError("Transparent Column Fixer only accept shallow loaded file."); + return; + } + + // iterate objects + LibCmo::CKDWORD expcode = static_cast(LibCmo::CK2::CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXONLY); + LibCmo::CKDWORD modcode = static_cast(LibCmo::CK2::CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_OLDTEXONLY); + for (const auto& cobj : m_FileReader->GetFileObjects()) { + if (cobj.ObjectCid == LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE && cobj.Data != nullptr) { + LibCmo::CK2::CKFileObject& obj = const_cast(cobj); + obj.Data->StartRead(); + auto chunkinfo = obj.Data->GetIdentifiersProfile(); + obj.Data->StopRead(); + + // find CK_STATESAVE_TEXONLY and change it to CK_STATESAVE_OLDTEXONLY + for (const auto& entry : chunkinfo) { + if (entry.m_Identifier == expcode) { + LibCmo::CKDWORD* p = static_cast(entry.m_DataPtr); + p -= 2; + + if (*p == expcode) { + *p = modcode; + } + } + } + } + } #else PrintCommonError("Test command only available in Debug mode."); diff --git a/Unvirt/UnvirtContext.hpp b/Unvirt/UnvirtContext.hpp index 1932e30..f7923ca 100644 --- a/Unvirt/UnvirtContext.hpp +++ b/Unvirt/UnvirtContext.hpp @@ -4,9 +4,7 @@ #include "StructFormatter.hpp" #include "CmdHelper.hpp" -#include -#include -#include +#include #include #include