diff --git a/LibCmo/LibCmo.vcxproj b/LibCmo/LibCmo.vcxproj index a3cec72..35fff1b 100644 --- a/LibCmo/LibCmo.vcxproj +++ b/LibCmo/LibCmo.vcxproj @@ -100,7 +100,7 @@ true LIBCMO_EXPORTING;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(BOOST_MMAP_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) + $(BOOST_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) stdcpp20 @@ -118,7 +118,7 @@ true LIBCMO_EXPORTING;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(BOOST_MMAP_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) + $(BOOST_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) stdcpp20 @@ -136,7 +136,7 @@ true LIBCMO_EXPORTING;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(BOOST_MMAP_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) + $(BOOST_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) stdcpp20 @@ -154,7 +154,7 @@ true LIBCMO_EXPORTING;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(BOOST_MMAP_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) + $(BOOST_INCLUDE_PATH);$(ZLIB_PATH);%(AdditionalIncludeDirectories) stdcpp20 @@ -168,9 +168,11 @@ + + diff --git a/LibCmo/LibCmo.vcxproj.filters b/LibCmo/LibCmo.vcxproj.filters index c2526e8..e63257d 100644 --- a/LibCmo/LibCmo.vcxproj.filters +++ b/LibCmo/LibCmo.vcxproj.filters @@ -18,6 +18,9 @@ Sources + + Sources + @@ -32,5 +35,8 @@ Headers + + Headers + \ No newline at end of file diff --git a/LibCmo/VTConstants.hpp b/LibCmo/VTConstants.hpp index 8bf8842..e9a3e09 100644 --- a/LibCmo/VTConstants.hpp +++ b/LibCmo/VTConstants.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include namespace LibCmo { @@ -25,6 +27,16 @@ namespace LibCmo { } using CK_ID = uint32_t; + using CKDWORD = uint32_t; + using CKBOOL = int32_t; + + using XString = std::string; + using XBitArray = std::vector; + template + using XArray = std::vector; + using XIntArray = std::vector; + template + using XClassArray = std::vector; enum class CK_CLASSID : uint32_t { CKCID_OBJECT = 1, diff --git a/LibCmo/VTEncoding.hpp b/LibCmo/VTEncoding.hpp new file mode 100644 index 0000000..b22f372 --- /dev/null +++ b/LibCmo/VTEncoding.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include + +#if defined(_WIN32) +#define LIBCMO_OS_WIN32 +#endif + +#if defined(LIBCMO_OS_WIN32) +#include +#else +#include +#endif + +namespace LibCmo { + namespace Encoding { + +#pragma region assist functions + +#if defined(LIBCMO_OS_WIN32) + +#define LIBCMO_STR_EQUAL(a, b) strcmp(reinterpret_cast(a), reinterpret_cast(b)) == 0 + bool GetWindowsCodePage(const char* u8_encoding_spec, UINT* result) { + if (LIBCMO_STR_EQUAL(u8_encoding_spec, u8"CP_ACP")) *result = CP_ACP; + else if (LIBCMO_STR_EQUAL(u8_encoding_spec, u8"CP_MACCP")) *result = CP_MACCP; + else if (LIBCMO_STR_EQUAL(u8_encoding_spec, u8"CP_OEMCP")) *result = CP_OEMCP; + else if (LIBCMO_STR_EQUAL(u8_encoding_spec, u8"CP_THREAD_ACPP")) *result = CP_THREAD_ACP; + else if (LIBCMO_STR_EQUAL(u8_encoding_spec, u8"CP_UTF8")) *result = CP_UTF8; + else { + char* pend = nullptr; + errno = 0; + uint64_t v = std::strtoull(u8_encoding_spec, &pend, 10); + + if (pend == u8_encoding_spec || errno == ERANGE) return false; + *result = static_cast(v); + } + return true; + } +#undef LIBCMO_STR_EQUAL + + bool WcharToChar(const wchar_t* src, std::string& dest, UINT codepage) { + int count, write_result; + + //converter to CHAR + count = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL); + if (count <= 0) return false; + + dest.resize(count); + write_result = WideCharToMultiByte(CP_UTF8, 0, src, -1, dest.data(), count, NULL, NULL); + if (write_result <= 0) return false; + + return true; + } + bool WcharToChar(std::wstring& src, std::string& dest, UINT codepage) { + return WcharToChar(src.c_str(), dest, codepage); + } + + bool CharToWchar(const char* src, std::wstring& dest, UINT codepage) { + int wcount, write_result; + + // convert to WCHAR + wcount = MultiByteToWideChar(codepage, 0, src, -1, NULL, 0); + if (wcount <= 0) return false; + + dest.resize(wcount); + write_result = MultiByteToWideChar(CP_UTF8, 0, src, -1, dest.data(), wcount); + if (write_result <= 0) return false; + + return true; + } + bool CharToWchar(std::string& src, std::wstring& dest, UINT codepage) { + return CharToWchar(src.c_str(), dest, codepage); + } + +#else + + //todo: linux implementation + +#endif + +#pragma endregion + +#pragma region core functions + +#if defined(LIBCMO_OS_WIN32) + + void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, const char* u8_encoding_spec) { + // switch encoding spec + UINT codepage = CP_ACP; + if (!GetWindowsCodePage(u8_encoding_spec, &codepage)) { + u8_name = native_name.c_str(); + return; + } + + // do convert + std::wstring intermediary; + if (!CharToWchar(native_name, intermediary, codepage)) { + u8_name = native_name.c_str(); + return; + } + if (!WcharToChar(intermediary, u8_name, CP_UTF8)) { + u8_name = native_name.c_str(); + return; + } + + return; + } + +#else + //todo: linux implementation +#error NO IMPLEMENTATION FOR LINUX ENCODING! + +#endif + +#pragma endregion + + } +} diff --git a/LibCmo/VTStruct.cpp b/LibCmo/VTStruct.cpp new file mode 100644 index 0000000..abf6204 --- /dev/null +++ b/LibCmo/VTStruct.cpp @@ -0,0 +1,56 @@ +#include "VTStruct.hpp" + +namespace LibCmo { + + VxMemoryMappedFile::VxMemoryMappedFile(const char* u8_filepath) : + m_szFilePath(), + m_hFile(nullptr), m_hFileMapping(nullptr), + m_bIsValid(false) { + + // save file path and set region option + boost::interprocess::map_options_t region_option; +#if defined(LIBCMO_OS_WIN32) + Encoding::CharToWchar(u8_filepath, this->m_szFilePath, CP_UTF8); + region_option = FILE_MAP_READ; +#else + this->m_szFilePath = u8_filepath; + region_option = boost::interprocess::default_map_options; +#endif + + // open file + this->m_hFile = new boost::interprocess::file_mapping( + this->m_szFilePath.c_str(), boost::interprocess::read_only + ); + + // open region + this->m_hFileMapping = new boost::interprocess::mapped_region( + this->m_hFile, boost::interprocess::read_only, + 0, 0, nullptr, + region_option + ); + + // set valid + this->m_bIsValid = true; + + } + + VxMemoryMappedFile::~VxMemoryMappedFile(void) { + this->m_bIsValid = false; + + delete this->m_hFileMapping; + boost::interprocess::file_mapping::remove(this->m_szFilePath.c_str()); + delete this->m_hFile; + } + + void* VxMemoryMappedFile::GetBase(void) { return this->m_hFileMapping->get_address(); } + size_t VxMemoryMappedFile::GetFileSize(void) { return this->m_hFileMapping->get_size(); } + bool VxMemoryMappedFile::IsValid(void) { return this->m_bIsValid; } + + + CKFile::CKFile() { + } + + CKFile::~CKFile() { + } + +} diff --git a/LibCmo/VTStruct.hpp b/LibCmo/VTStruct.hpp index 6f70f09..2fc05fe 100644 --- a/LibCmo/VTStruct.hpp +++ b/LibCmo/VTStruct.hpp @@ -1 +1,142 @@ #pragma once + +#include "VTConstants.hpp" +#include "VTEncoding.hpp" +#include + +// only expose boost in libcom self. do not let it be seen by any program using libcmo. +#if defined(LIBCMO_EXPORTING) +#include +#include +#endif + +namespace LibCmo { + + struct CKGUID { + union { + struct { + CKDWORD d1, d2; + }; + CKDWORD d[2]; + }; + CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) { d[0] = gd1; d[1] = gd2; } + }; + + // define some mapped file to make boost is invisible for + // any program using this library +#if defined(LIBCMO_EXPORTING) + using P_FILE_MAPPING = boost::interprocess::file_mapping*; + using P_MAPPED_REGION = boost::interprocess::mapped_region*; +#else + using P_FILE_MAPPING = void*; + using P_MAPPED_REGION = void*; +#endif + + class VxMemoryMappedFile { + public: + VxMemoryMappedFile(const char* u8_filepath); + ~VxMemoryMappedFile(void); + + void* GetBase(void); + size_t GetFileSize(void); + bool IsValid(void); + + private: + +#if defined(LIBCMO_OS_WIN32) + std::wstring m_szFilePath; +#else + std::string m_szFilePath; +#endif + + P_FILE_MAPPING m_hFile; + P_MAPPED_REGION m_hFileMapping; + bool m_bIsValid; + }; + + class CKBufferParser { + private: + char* m_ReaderBegin; + size_t m_ReaderPos; + bool m_NeedManualFree; + size_t m_ReaderSize; + + public: + CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) : + m_ReaderBegin(static_cast(ptr)), + m_ReaderPos(0u), m_ReaderSize(rsize), + m_NeedManualFree(need_manual_free) { + ; + } + ~CKBufferParser() { + if (this->m_NeedManualFree) free(this->m_ReaderBegin); + } + + inline void* GetPtr(void) { return (this->m_ReaderBegin + m_ReaderPos); } + inline size_t GetSize(void) { return this->m_ReaderSize; } + inline void MoveCursor(size_t off) { this->m_ReaderPos += off; } + inline void SetCursor(size_t off) { this->m_ReaderPos = off; } + }; + + struct CKFileInfo { + CKDWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) + CKDWORD ProductBuild; // Virtools Build Number. + CK_FILE_WRITEMODE FileWriteMode; // Options used to save this file. (CK_FILE_WRITEMODE) + CKDWORD FileVersion; // Version of file format when file was saved. + CKDWORD CKVersion; // Version of CK when file was saved. + CKDWORD FileSize; // Size of file in bytes. + CKDWORD ObjectCount; // Number of objects stored in the file. + CKDWORD ManagerCount; // Number of managers which saved data in the file. + CKDWORD MaxIDSaved; // Maximum Object identifier saved + CKDWORD Crc; // Crc of data + CKDWORD Hdr1PackSize; // Reserved + CKDWORD Hdr1UnPackSize; // Reserved + CKDWORD DataPackSize; // Reserved + CKDWORD DataUnPackSize; // Reserved + }; + + struct CKFileObject { + CK_ID Object; + CK_ID CreatedObject; + CK_CLASSID ObjectCid; + void* ObjPtr; + std::string Name; + void* Data; + CKDWORD PostPackSize; + CKDWORD PrePackSize; + CK_FO_OPTIONS Options; + CKDWORD FileIndex; + CK_FILE_WRITEMODE SaveFlags; + }; + + struct CKFilePluginDependencies { + CKDWORD m_PluginCategory; + XArray m_Guids; + XBitArray ValidGuids; + }; + + class CKFile { + public: + CKFile(); + ~CKFile(); + + + int32_t m_SaveIDMax; + XArray m_FileObject; + //XArray m_ManagersData; + XClassArray m_PluginDep; + //XClassArray m_IndexByClassId; + //XClassArray m_IncludedFiles; + + CKFileInfo m_FileInfo; + + CK_LOAD_FLAGS m_Flags; + std::string m_FileName; + CKBufferParser* m_Parser; + VxMemoryMappedFile* m_MappedFile; + + bool m_ReadFileDataDone; + + }; + +} diff --git a/LibRef.props b/LibRef.props index ef3cd11..47c1132 100644 --- a/LibRef.props +++ b/LibRef.props @@ -2,7 +2,7 @@ - D:\CppLib\interprocess-boost-1.81.0\include + D:\CppLib\boost_1_81_0 D:\CppLib\SQLite\sqlite-amalgamation-3400100 D:\CppLib\SQLite\sqlite-dll-win32-x86-3400100 @@ -13,8 +13,8 @@ - - $(BOOST_MMAP_INCLUDE_PATH) + + $(BOOST_INCLUDE_PATH) diff --git a/Unvirt/Unvirt.cpp b/Unvirt/Unvirt.cpp index 25f4db6..25308c4 100644 --- a/Unvirt/Unvirt.cpp +++ b/Unvirt/Unvirt.cpp @@ -10,7 +10,7 @@ int main(int argc, char* argv[]) { Unvirt::AccessibleValue::GetEnumName(Unvirt::AccessibleValue::EnumDesc::CK_FO_OPTIONS, test, LibCmo::CK_FO_OPTIONS::CK_FO_RENAMEOBJECT); printf("%s\n", test.c_str()); - + Unvirt::AccessibleValue::GetFlagEnumName(Unvirt::AccessibleValue::EnumDesc::CK_LOAD_FLAGS, test, LibCmo::CK_LOAD_FLAGS::CK_LOAD_DEFAULT); printf("%s\n", test.c_str()); auto v = LibCmo::EnumHelper::FlagEnumAdd(LibCmo::CK_LOAD_FLAGS::CK_LOAD_ANIMATION, LibCmo::CK_LOAD_FLAGS::CK_LOAD_ASCHARACTER);