diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index 27b15e5..ddf10a2 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -172,7 +172,7 @@ namespace LibCmo::CK2 { CKFileVisitor& operator=(const CKFileVisitor&); CKFileVisitor& operator=(CKFileVisitor&&); - const CKFileObject* GetFileObjectByIndex(size_t index); + const CKFileObject* GetFileObjectByIndex(CKDWORD index); CKDWORD GetIndexByObjectID(CK_ID objid); protected: bool m_IsReader; diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp index 4385d8d..18a03cc 100644 --- a/LibCmo/CK2/CKFileOthers.cpp +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -284,12 +284,12 @@ namespace LibCmo::CK2 { CKFileVisitor::CKFileVisitor(CKFileReader* reader) : m_IsReader(true), m_Reader(reader), m_Writer(nullptr), m_Ctx(reader->m_Ctx) { - if (reader == nullptr) LIBPANIC("Reader is nullptr."); + if (reader == nullptr) LIBCMO_PANIC("Reader is nullptr."); } CKFileVisitor::CKFileVisitor(CKFileWriter* writer) : m_IsReader(false), m_Reader(nullptr), m_Writer(writer), m_Ctx(writer->m_Ctx) { - if (writer == nullptr) LIBPANIC("Writer is nullptr."); + if (writer == nullptr) LIBCMO_PANIC("Writer is nullptr."); } CKFileVisitor::CKFileVisitor(const CKFileVisitor& rhs) : @@ -316,7 +316,7 @@ namespace LibCmo::CK2 { return *this; } - const CKFileObject* CKFileVisitor::GetFileObjectByIndex(size_t index) { + const CKFileObject* CKFileVisitor::GetFileObjectByIndex(CKDWORD index) { if (m_IsReader) { return &m_Reader->m_FileObjects[index]; } else { diff --git a/LibCmo/CK2/CKGlobals.cpp b/LibCmo/CK2/CKGlobals.cpp index 49da212..10f63cf 100644 --- a/LibCmo/CK2/CKGlobals.cpp +++ b/LibCmo/CK2/CKGlobals.cpp @@ -267,7 +267,7 @@ namespace LibCmo::CK2 { // find direct parent CKClassDesc& parent = g_CKClassInfo[static_cast(desc.Parent)]; - if (!parent.IsValid) LIBPANIC("No such CK_CLASSID."); + if (!parent.IsValid) LIBCMO_PANIC("No such CK_CLASSID."); // if it is not self inheritance, call recursively if (desc.Self != desc.Parent) { @@ -291,7 +291,7 @@ namespace LibCmo::CK2 { // find direct parent CKClassDesc& parent = g_CKClassInfo[static_cast(desc.Parent)]; - if (!parent.IsValid) LIBPANIC("No such CK_CLASSID."); + if (!parent.IsValid) LIBCMO_PANIC("No such CK_CLASSID."); // if it is not self inheritance, call recursively if (desc.Self != desc.Parent) { diff --git a/LibCmo/CK2/CKStateChunkReader.cpp b/LibCmo/CK2/CKStateChunkReader.cpp index b1d69a4..22fdf72 100644 --- a/LibCmo/CK2/CKStateChunkReader.cpp +++ b/LibCmo/CK2/CKStateChunkReader.cpp @@ -149,7 +149,7 @@ namespace LibCmo::CK2 { if (id == nullptr) return false; // get basic value - CKINT gotten_id = 0; + CKDWORD gotten_id = 0; if (!this->ReadStruct(gotten_id)) return false; // different strategy according to chunk ver @@ -162,7 +162,7 @@ namespace LibCmo::CK2 { return true; } // if it is positive, return corresponding value - if (gotten_id >= 0) { + if ((gotten_id & 0x80000000) == 0) { *id = this->m_BindFile->GetFileObjectByIndex(gotten_id)->CreatedObjectId; return true; } diff --git a/LibCmo/CK2/CKStateChunkWriter.cpp b/LibCmo/CK2/CKStateChunkWriter.cpp index a2d85ec..b7e1a13 100644 --- a/LibCmo/CK2/CKStateChunkWriter.cpp +++ b/LibCmo/CK2/CKStateChunkWriter.cpp @@ -3,22 +3,6 @@ #include "CKContext.hpp" #include "ObjImpls/CKObject.hpp" -/* -Memorandum: - -No need to write any data in m_ObjectList when writing Object ID. -Because m_ObjectList only need to be written in when no bind CKFile -according to IDA reversed code. -However we assuem all CKStateChunk have bind file so no need to treat it. - -However, m_ManagerList should be filled when writing Manager Int. -This is also instructed by IDA revsersed code. - -For m_ChunkList, it is same as m_ManagerList. We need write it. - -*/ - - namespace LibCmo::CK2 { void CKStateChunk::StartWrite() { @@ -166,9 +150,21 @@ namespace LibCmo::CK2 { } bool CKStateChunk::WriteObjectID(const CK_ID* id) { - // MARK: if BindFile is not nullptr, no need to push this obj into obj list according to IDA code. - // but we assume BindFile always it not nullptr, so I remove that pushing code. - return this->WriteStruct(m_BindFile->GetIndexByObjectID(*id)); + // if BindFile is not nullptr, + // no need to push this obj into obj list according to IDA code. + + if (m_BindFile != nullptr) { + this->WriteStruct(m_BindFile->GetIndexByObjectID(id != nullptr ? (*id) : 0)); + } else { + if (id != nullptr) { + AddEntry(m_ObjectList, m_Parser.m_CurrentPos); + this->WriteStruct(id); + } else { + this->WriteStruct(static_cast(0)); + } + } + + return true; } bool CKStateChunk::WriteObjectPointer(ObjImpls::CKObject* obj) { @@ -223,19 +219,25 @@ namespace LibCmo::CK2 { bool CKStateChunk::WriteObjectIDSequence(const XContainer::XObjectArray* ls) { if (ls == nullptr) return false; - // MARK: there is a recording oper for object list when no bind file. - // but we always have bind file, so ignore it + // add current pos into manager list if no bind file + if (ls->size() != 0 && m_BindFile == nullptr) { + AddEntries(m_ObjectList, m_Parser.m_CurrentPos); + } // write size first CKDWORD objidsize = static_cast(ls->size()); if (!this->WriteStruct(objidsize)) return false; - // write each data + // write each item for (auto objid : *ls) { - // MARK: originally we should not call WriteObjectID like ReadObjectIDSequence. - // because we do not write position data in obj list for each item. - // even if bind file always is not nullptr. - if (!this->WriteStruct(m_BindFile->GetIndexByObjectID(objid))) return false; + // because we do not want write position data in obj list for each item. + // so we do not call WriteObjectID here. + if (m_BindFile != nullptr) { + if (!this->WriteStruct(m_BindFile->GetIndexByObjectID(objid))) return false; + } else { + if (!this->WriteStruct(static_cast(objid))) return false; + } + } return true; @@ -271,6 +273,7 @@ namespace LibCmo::CK2 { bool CKStateChunk::WriteXObjectPointerArray(const XContainer::XObjectPointerArray* ls) { if (ls == nullptr) return false; + // convert to id list and pass to id writer. XContainer::XObjectArray conv; for (auto obj : *ls) { if (obj == nullptr) conv.emplace_back(0); diff --git a/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp index 0ca0eeb..ca8f222 100644 --- a/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp +++ b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp @@ -1,4 +1,6 @@ #include "CKBitmapHandler.hpp" +#include "stb_image.h" +#include "stb_image_write.h" namespace LibCmo::CK2::DataHandlers { diff --git a/LibCmo/CK2/MgrImpls/CKPathManager.cpp b/LibCmo/CK2/MgrImpls/CKPathManager.cpp index bef6e4a..5779c02 100644 --- a/LibCmo/CK2/MgrImpls/CKPathManager.cpp +++ b/LibCmo/CK2/MgrImpls/CKPathManager.cpp @@ -99,6 +99,14 @@ namespace LibCmo::CK2::MgrImpls { return false; } + void CKPathManager::GetFileName(XContainer::XString& u8path) { + std::filesystem::path filepath; + EncodingHelper::U8PathToStdPath(filepath, u8path.c_str()); + + auto result = filepath.filename(); + EncodingHelper::StdPathToU8Path(u8path, result); + } + void CKPathManager::GetExtension(XContainer::XString& u8path) { std::filesystem::path filepath; EncodingHelper::U8PathToStdPath(filepath, u8path.c_str()); diff --git a/LibCmo/CK2/MgrImpls/CKPathManager.hpp b/LibCmo/CK2/MgrImpls/CKPathManager.hpp index 91e68a3..0d43857 100644 --- a/LibCmo/CK2/MgrImpls/CKPathManager.hpp +++ b/LibCmo/CK2/MgrImpls/CKPathManager.hpp @@ -53,9 +53,15 @@ namespace LibCmo::CK2::MgrImpls { */ bool ResolveFileName(XContainer::XString& u8_filename); + /** + * @brief Get file name part of given path. + * @param u8path[inout] The given path. overwritten by the gotten file name. + */ + void GetFileName(XContainer::XString& u8path); + /** * @brief Returns the file extension including period (.) - * @param u8path[inout] The given path. overwritten by the gotten extension. set to blank when failed. + * @param u8path[inout] The given path. overwritten by the gotten extension. */ void GetExtension(XContainer::XString& u8path); diff --git a/LibCmo/LibCmo.vcxproj b/LibCmo/LibCmo.vcxproj index e0e8885..39810e2 100644 --- a/LibCmo/LibCmo.vcxproj +++ b/LibCmo/LibCmo.vcxproj @@ -228,7 +228,6 @@ - diff --git a/LibCmo/LibCmo.vcxproj.filters b/LibCmo/LibCmo.vcxproj.filters index bafe075..ab9c854 100644 --- a/LibCmo/LibCmo.vcxproj.filters +++ b/LibCmo/LibCmo.vcxproj.filters @@ -224,9 +224,6 @@ Headers\CK2\ObjImpls - - Headers - Headers diff --git a/LibCmo/VTAll.hpp b/LibCmo/VTAll.hpp index e90f346..cb5214a 100644 --- a/LibCmo/VTAll.hpp +++ b/LibCmo/VTAll.hpp @@ -38,10 +38,6 @@ Use native Win32 function in Windows. And use iconv under other OS. */ #include "VTEncoding.hpp" -/* -System independent image loader / saver -*/ -#include "VTImage.hpp" // Define the basic type of CK2. #include "CK2/CKTypes.hpp" diff --git a/LibCmo/VTImage.hpp b/LibCmo/VTImage.hpp deleted file mode 100644 index 087e442..0000000 --- a/LibCmo/VTImage.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -// Bad wrapper for stb image library. - -#include "stb_image.h" -#include "stb_image_write.h" -#include "stb_image_resize.h" diff --git a/LibCmo/VTUtils.cpp b/LibCmo/VTUtils.cpp index ef69089..a979b6f 100644 --- a/LibCmo/VTUtils.cpp +++ b/LibCmo/VTUtils.cpp @@ -1,5 +1,16 @@ #include "VTUtils.hpp" +#if defined(LIBCMO_OS_WIN32) +#include +// disable annoy macro at the same time +#undef GetObject +#undef GetClassName +#undef LoadImage +#undef GetTempPath +#else +#include +#endif + namespace LibCmo { void LibPanic(int line, const char* file, const char* errmsg) { @@ -8,4 +19,18 @@ namespace LibCmo { std::abort(); } + void LibOrderDebugger() { +#if defined(LIBCMO_BUILD_DEBUG) + +#if defined(LIBCMO_OS_WIN32) + // win32 debug break + __debugbreak(); +#else + // generic debug break + raise(SIGTRAP); +#endif + +#endif + } + } diff --git a/LibCmo/VTUtils.hpp b/LibCmo/VTUtils.hpp index 29526ba..1a34c02 100644 --- a/LibCmo/VTUtils.hpp +++ b/LibCmo/VTUtils.hpp @@ -77,7 +77,21 @@ namespace LibCmo { [[noreturn]] void LibPanic(int line, const char* file, const char* errmsg); -#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg); +#define LIBCMO_PANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg); + + void LibOrderDebugger(); +#if defined(LIBCMO_BUILD_DEBUG) + /** + This macro only available in Debug mode. + It will order debugger stop. + This macro frequently used when program entering some rarely area. + For example, in CKStateChunk::ReadObjectID, if code run into the calling of Skip, it mean that this file is pretty old and debugger should notice it. + */ +#define LIBCMO_ORDER_DEBUGGER LibOrderDebugger(); +#else + // define a blank one +#define LIBCMO_ORDER_DEBUGGER +#endif namespace EnumsHelper { diff --git a/LibCmo/VxMath/VxMath.cpp b/LibCmo/VxMath/VxMath.cpp index f1b45aa..d60f59f 100644 --- a/LibCmo/VxMath/VxMath.cpp +++ b/LibCmo/VxMath/VxMath.cpp @@ -1,5 +1,6 @@ -#include "../VTImage.hpp" #include "VxMath.hpp" +#include "stb_image_resize.h" + namespace LibCmo::VxMath {