From 763c6e84f9abf6d848d0fae6d993000b9041bb8b Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 29 Aug 2023 10:42:13 +0800 Subject: [PATCH] add more info display --- LibCmo/CK2/CKFile.hpp | 2 +- LibCmo/CK2/CKFileOthers.cpp | 10 ++- LibCmo/CK2/CKStateChunk.cpp | 24 +++++- LibCmo/CK2/CKStateChunk.hpp | 4 +- LibCmo/CK2/CKTypes.hpp | 18 ++++- Unvirt/StructFormatter.cpp | 141 ++++++++++++++++++++++++------------ Unvirt/StructFormatter.hpp | 11 ++- Unvirt/UnvirtContext.cpp | 2 +- 8 files changed, 150 insertions(+), 62 deletions(-) diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index c38a032..e10fc24 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -126,7 +126,7 @@ namespace LibCmo::CK2 { //CKINT PostPackSize; /**< When compressed chunk by chunk : size of Data after compression */ //CKINT PrePackSize; /**< When compressed chunk by chunk : size of Data before compression */ CK_FO_OPTIONS Options; /**< When loading an object it may be renamed , use to replace another object */ - CKINT FileIndex; /**< Position of the object data inside uncompressed file buffer */ + CKDWORD FileIndex; /**< Position of the object data inside uncompressed file buffer */ CKDWORD SaveFlags; /**< Flags used when this object was saved. */ }; diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp index 64ad70b..7a1cabb 100644 --- a/LibCmo/CK2/CKFileOthers.cpp +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -253,25 +253,26 @@ namespace LibCmo::CK2 { #pragma region CKFileVisitor CKFileVisitor::CKFileVisitor(CKFileReader* reader) : - m_IsReader(CKTRUE), m_Reader(reader), m_Writer(nullptr) { + m_IsReader(CKTRUE), m_Reader(reader), m_Writer(nullptr), m_Ctx(reader->m_Ctx) { if (reader == nullptr) LIBPANIC("Reader is nullptr."); } CKFileVisitor::CKFileVisitor(CKFileWriter* writer) : - m_IsReader(false), m_Reader(nullptr), m_Writer(nullptr) { + m_IsReader(false), m_Reader(nullptr), m_Writer(writer), m_Ctx(writer->m_Ctx) { if (writer == nullptr) LIBPANIC("Writer is nullptr."); } CKFileVisitor::CKFileVisitor(const CKFileVisitor& rhs) : - m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {} + m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer), m_Ctx(rhs.m_Ctx) {} CKFileVisitor::CKFileVisitor(CKFileVisitor&& rhs) : - m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {} + m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer), m_Ctx(rhs.m_Ctx) {} CKFileVisitor& CKFileVisitor::operator=(const CKFileVisitor& rhs) { this->m_IsReader = rhs.m_IsReader; this->m_Reader = rhs.m_Reader; this->m_Writer = rhs.m_Writer; + this->m_Ctx = rhs.m_Ctx; return *this; } @@ -280,6 +281,7 @@ namespace LibCmo::CK2 { this->m_IsReader = rhs.m_IsReader; this->m_Reader = rhs.m_Reader; this->m_Writer = rhs.m_Writer; + this->m_Ctx = rhs.m_Ctx; return *this; } diff --git a/LibCmo/CK2/CKStateChunk.cpp b/LibCmo/CK2/CKStateChunk.cpp index 74ce088..3db559e 100644 --- a/LibCmo/CK2/CKStateChunk.cpp +++ b/LibCmo/CK2/CKStateChunk.cpp @@ -110,6 +110,26 @@ namespace LibCmo::CK2 { #pragma region Misc Funcs + const ChunkProfile CKStateChunk::GetStateChunkProfile() { + ChunkProfile profile; + + profile.m_ClassId = this->m_ClassId; + profile.m_DataDwSize = this->m_DataDwSize; + profile.m_pData = this->m_pData; + + profile.m_DataVersion = this->m_DataVersion; + profile.m_ChunkVersion = this->m_ChunkVersion; + + profile.m_ObjectListSize = this->m_ObjectList.size(); + profile.m_ChunkListSize = this->m_ChunkList.size(); + profile.m_ManagerListSize = this->m_ManagerList.size(); + + profile.m_BindFile = this->m_BindFile; + profile.m_BindContext = this->m_BindContext; + + return profile; + } + void CKStateChunk::Clear(void) { this->m_ClassId = CK_CLASSID::CKCID_OBJECT; this->m_DataVersion = CK_STATECHUNK_DATAVERSION::CHUNK_DEV_2_1; @@ -505,7 +525,7 @@ namespace LibCmo::CK2 { return true; } - XContainer::XArray CKStateChunk::GetIdentifierProfile() { + const XContainer::XArray CKStateChunk::GetIdentifierProfile() { XContainer::XArray collection; if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return collection; @@ -550,7 +570,7 @@ namespace LibCmo::CK2 { return true; } else { // failed, report to context - m_BindContext->OutputToConsoleEx("CKStateChunk read length error at %" PRIckDWORD ".", this->m_Parser.m_CurrentPos); + m_BindContext->OutputToConsoleEx("CKStateChunk read length error at %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos); return false; } } diff --git a/LibCmo/CK2/CKStateChunk.hpp b/LibCmo/CK2/CKStateChunk.hpp index 89863d5..1ff3f62 100644 --- a/LibCmo/CK2/CKStateChunk.hpp +++ b/LibCmo/CK2/CKStateChunk.hpp @@ -73,6 +73,8 @@ namespace LibCmo::CK2 { #pragma region Misc Functions public: + const ChunkProfile GetStateChunkProfile(); + //bool UnPack(CKDWORD DestSize); void Clear(void); CKDWORD GetDataSize(void); @@ -112,7 +114,7 @@ namespace LibCmo::CK2 { inline bool SeekIdentifierAndReturnSize(TEnum enum_v, CKDWORD* out_size) { return SeekIdentifierDwordAndReturnSize(static_cast(enum_v), out_size); } - XContainer::XArray GetIdentifierProfile(); + const XContainer::XArray GetIdentifierProfile(); /* ========== Basic Data Read Functions ==========*/ diff --git a/LibCmo/CK2/CKTypes.hpp b/LibCmo/CK2/CKTypes.hpp index 11b2d89..f3949e9 100644 --- a/LibCmo/CK2/CKTypes.hpp +++ b/LibCmo/CK2/CKTypes.hpp @@ -183,10 +183,20 @@ namespace LibCmo::CK2 { using CKAttributeCategory = int32_t; // type print style define -#define PRIckBYTE PRIu8 -#define PRIckDWORD PRIu32 -#define PRIckWORD PRIu16 -#define PRIckINT PRIi32 +#define PRIuCKID PRIu32 +#define PRIiCKERROR PRIi32 +#define PRIiCLASSID PRIi32 + +#define PRIuCKBYTE PRIu8 +#define PRIuCKDWORD PRIu32 +#define PRIuCKWORD PRIu16 +#define PRIxCKBYTE PRIx8 +#define PRIxCKDWORD PRIx32 +#define PRIxCKWORD PRIx16 +#define PRIXCKBYTE PRIX8 +#define PRIXCKDWORD PRIX32 +#define PRIXCKWORD PRIX16 +#define PRIiCKINT PRIi32 // ========== Class List ========== // Objects and derivated classes diff --git a/Unvirt/StructFormatter.cpp b/Unvirt/StructFormatter.cpp index f7f941d..f9463c9 100644 --- a/Unvirt/StructFormatter.cpp +++ b/Unvirt/StructFormatter.cpp @@ -8,12 +8,17 @@ namespace Unvirt::StructFormatter { #pragma region Assist Functions - static void PrintCKSTRING(const LibCmo::TypeHelper::MKString& name) { - LibCmo::CK2::CKSTRING ckname = name.c_str(); - if (ckname == nullptr) { +#define PRIuSIZET "zu" + + static void PrintCKSTRING(LibCmo::CK2::CKSTRING name) { + if (name == nullptr) { fputs(UNVIRT_TERMCOL_LIGHT_MAGENTA(("")), stdout); } else { - fputs(ckname, stdout); + if (name[0] == '\0') { + fputs(UNVIRT_TERMCOL_LIGHT_MAGENTA(("")), stdout); + } else { + fputs(name, stdout); + } } } static void PrintPointer(const void* ptr) { @@ -22,24 +27,21 @@ namespace Unvirt::StructFormatter { } else { #if UINTPTR_MAX == UINT32_MAX // 32 bit. padding 8 zero - fprintf(stdout, "<0x%08" PRIXPTR ">", reinterpret_cast(ptr)); + fprintf(stdout, "<0x%08" PRIxPTR ">", reinterpret_cast(ptr)); #else // 64 bit. padding 16 zero - fprintf(stdout, "<0x%016" PRIXPTR ">", reinterpret_cast(ptr)); + fprintf(stdout, "<0x%016" PRIxPTR ">", reinterpret_cast(ptr)); #endif } } static void PrintCKGUID(const LibCmo::CK2::CKGUID& guid) { - fprintf(stdout, "<0x%08" PRIx32 ", 0x%08" PRIx32 ">", guid.d1, guid.d2); + fprintf(stdout, "<0x%08" PRIxCKDWORD ", 0x%08" PRIxCKDWORD ">", guid.d1, guid.d2); } - static void PrintIdentifier(const LibCmo::CK2::CKDWORD val) { - fprintf(stdout, "0x%08" PRIx32, val); - } - + template static void GeneralPrintList( const std::vector<_Ty>& data, size_t page, size_t pageitems, - std::function printHdrFct, std::function printEntryFct) { + std::function printHdrFct, std::function printEntryFct) { size_t fulllen = data.size(), startpos = page * pageitems, @@ -53,7 +55,7 @@ namespace Unvirt::StructFormatter { printEntryFct(counter, data[counter]); } - fprintf(stdout, "Page %zu of %zu\n", page + 1, fullpage + 1); + fprintf(stdout, "Page %" PRIuSIZET " of %" PRIuSIZET "\n", page + 1, fullpage + 1); } #pragma endregion @@ -61,8 +63,8 @@ namespace Unvirt::StructFormatter { void PrintCKFileInfo(const LibCmo::CK2::CKFileInfo& fileinfo) { fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileInfo\n")), stdout); - fprintf(stdout, "FileVersion: %" PRIu32 "\n", fileinfo.FileVersion); - fprintf(stdout, "CKVersion: %02" PRIX32 "/%02" PRIX32 "/%04" PRIX32 "\n", + fprintf(stdout, "FileVersion: %" PRIuCKDWORD "\n", fileinfo.FileVersion); + fprintf(stdout, "CKVersion: %02" PRIxCKDWORD "/%02" PRIxCKDWORD "/%04" PRIxCKDWORD "\n", (fileinfo.CKVersion >> 24) & 0xFF, (fileinfo.CKVersion >> 16) & 0xFF, (fileinfo.CKVersion >> 0) & 0xFFFF @@ -74,59 +76,76 @@ namespace Unvirt::StructFormatter { (fileinfo.ProductBuild >> 8) & 0xFF, (fileinfo.ProductBuild >> 0) & 0xFF, }; - fprintf(stdout, "Product (Version / Build): %" PRIu32 " / %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", + fprintf(stdout, "Product (Version / Build): %" PRIuCKDWORD " / %" PRIuCKDWORD ".%" PRIuCKDWORD ".%" PRIuCKDWORD ".%" PRIuCKDWORD "\n", fileinfo.ProductVersion, product_series[0], product_series[1], product_series[2], product_series[3] ); - fprintf(stdout, "Save Flags: %s\n", Unvirt::AccessibleValue::GetFlagEnumName( - fileinfo.FileWriteMode, Unvirt::AccessibleValue::EnumDesc::CK_FILE_WRITEMODE + fprintf(stdout, "Save Flags: %s\n", AccessibleValue::GetFlagEnumName( + fileinfo.FileWriteMode, AccessibleValue::EnumDesc::CK_FILE_WRITEMODE ).c_str()); - fprintf(stdout, "File Size: %s\n", Unvirt::AccessibleValue::GetReadableFileSize(fileinfo.FileSize).c_str()); + fprintf(stdout, "File Size: %s\n", AccessibleValue::GetReadableFileSize(fileinfo.FileSize).c_str()); - fprintf(stdout, "Crc: 0x%" PRIX32 "\n", fileinfo.Crc); + fprintf(stdout, "Crc: 0x%" PRIxCKDWORD "\n", fileinfo.Crc); fputc('\n', stdout); fputs("Hdr1 (Pack / UnPack): ", stdout); - fprintf(stdout, "%s / ", Unvirt::AccessibleValue::GetReadableFileSize(fileinfo.Hdr1PackSize).c_str()); - fprintf(stdout, "%s\n", Unvirt::AccessibleValue::GetReadableFileSize(fileinfo.Hdr1UnPackSize).c_str()); + fprintf(stdout, "%s / ", AccessibleValue::GetReadableFileSize(fileinfo.Hdr1PackSize).c_str()); + fprintf(stdout, "%s\n", AccessibleValue::GetReadableFileSize(fileinfo.Hdr1UnPackSize).c_str()); fputs("Data (Pack / UnPack): ", stdout); - fprintf(stdout, "%s / ", Unvirt::AccessibleValue::GetReadableFileSize(fileinfo.DataPackSize).c_str()); - fprintf(stdout, "%s\n", Unvirt::AccessibleValue::GetReadableFileSize(fileinfo.DataUnPackSize).c_str()); + fprintf(stdout, "%s / ", AccessibleValue::GetReadableFileSize(fileinfo.DataPackSize).c_str()); + fprintf(stdout, "%s\n", AccessibleValue::GetReadableFileSize(fileinfo.DataUnPackSize).c_str()); fputc('\n', stdout); - fprintf(stdout, "Manager Count: %" PRIu32 "\nObject Count: %" PRIu32 "\nMax ID Saved: %" PRIu32 "\n", + fprintf(stdout, "Manager Count: %" PRIuCKDWORD "\nObject Count: %" PRIuCKDWORD "\nMax ID Saved: %" PRIuCKDWORD "\n", fileinfo.ManagerCount, fileinfo.ObjectCount, fileinfo.MaxIDSaved ); } - void PrintObjectList(const LibCmo::XContainer::XArray& ls, size_t page, size_t pageitems) { + void PrintObjectList( + const LibCmo::XContainer::XArray& ls, + const LibCmo::CK2::CKFileInfo& fileinfo, + size_t page, size_t pageitems) { fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileObject\n")), stdout); GeneralPrintList(ls, page, pageitems, []() -> void { - fputs("Index\tThis CK ID\tFile CK ID\tType\tCKObject\tCKStateChunk\tName\n", stdout); + fputs("SaveFlags\tOptions\tCK ID\tFile CK ID\tFile Index\tPack Size\tIndex\tType\tCKObject\tCKStateChunk\tName\n", stdout); }, - [](size_t index, const LibCmo::CK2::CKFileObject& obj) -> void { - fprintf(stdout, "#%zu\t", index); - fprintf(stdout, "%" PRIu32 "\t%" PRIu32 "\t", obj.CreatedObjectId, obj.ObjectId); - fprintf(stdout, "%s\t", Unvirt::AccessibleValue::GetClassIdName(obj.ObjectCid).c_str()); + [&fileinfo](size_t index, const LibCmo::CK2::CKFileObject& obj) -> void { + fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.SaveFlags); + fputs(AccessibleValue::GetEnumName(obj.Options, AccessibleValue::EnumDesc::CK_FO_OPTIONS).c_str(), stdout); + fputc('\t', stdout); + + fprintf(stdout, "%" PRIuCKID "\t", obj.CreatedObjectId); + fprintf(stdout, "%" PRIuCKID "\t", obj.ObjectId); + + fprintf(stdout, "0x%08" PRIxCKDWORD " (Rel: 0x%08" PRIxCKDWORD ")\t", + obj.FileIndex, + obj.FileIndex - sizeof(LibCmo::CK2::CKRawFileInfo) - fileinfo.Hdr1UnPackSize); + fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.PackSize); + + fprintf(stdout, "#%" PRIuSIZET "\t", index); + fputs(AccessibleValue::GetClassIdName(obj.ObjectCid).c_str(), stdout); + fputc('\t', stdout); PrintPointer(obj.ObjPtr); fputc('\t', stdout); PrintPointer(obj.Data); fputc('\t', stdout); - PrintCKSTRING(obj.Name); + PrintCKSTRING(obj.Name.c_str()); fputc('\n', stdout); } - ); + ); } - void PrintManagerList(const LibCmo::XContainer::XArray& ls, size_t page, size_t pageitems) { + void PrintManagerList( + const LibCmo::XContainer::XArray& ls, + size_t page, size_t pageitems) { fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileManager\n")), stdout); GeneralPrintList(ls, page, pageitems, @@ -136,13 +155,13 @@ namespace Unvirt::StructFormatter { }, [](size_t index, const LibCmo::CK2::CKFileManagerData& mgr) -> void { // print body - fprintf(stdout, "#%zu\t", index); + fprintf(stdout, "#%" PRIuSIZET "\t", index); PrintCKGUID(mgr.Manager); fputc('\t', stdout); PrintPointer(mgr.Data); fputc('\n', stdout); } - ); + ); } @@ -156,21 +175,49 @@ namespace Unvirt::StructFormatter { } void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) { fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout); - - // print header - fputs("Identifier\tData Pointer\tData Size\n", stdout); - - // print body + + // hack const state chunk LibCmo::CK2::CKStateChunk* operchunk = const_cast(chunk); + + // write profile + const auto profile = operchunk->GetStateChunkProfile(); + + fputs("Type: ", stdout); + fputs(AccessibleValue::GetClassIdName(profile.m_ClassId).c_str(), stdout); + fputc('\n', stdout); + + fprintf(stdout, "Version (Data / Chunk): %" PRIuCKDWORD " (%s) / %" PRIuCKDWORD " (%s)\n", + static_cast(profile.m_DataVersion), AccessibleValue::GetEnumName(profile.m_DataVersion, AccessibleValue::EnumDesc::CK_STATECHUNK_DATAVERSION).c_str(), + static_cast(profile.m_ChunkVersion), AccessibleValue::GetEnumName(profile.m_ChunkVersion, AccessibleValue::EnumDesc::CK_STATECHUNK_CHUNKVERSION).c_str()); + fprintf(stdout, "List (Object / Chunk / Manager): %" PRIuCKDWORD " / %" PRIuCKDWORD " / %" PRIuCKDWORD "\n", + static_cast(profile.m_ObjectListSize), + static_cast(profile.m_ChunkListSize), + static_cast(profile.m_ManagerListSize)); + + fputs("Data: ", stdout); + PrintPointer(profile.m_pData); + fprintf(stdout, " (0x%" PRIxCKDWORD " DWORD)\n", profile.m_DataDwSize); + + fputs("Bind CKFile: ", stdout); + PrintPointer(profile.m_BindFile); + fputc('\n', stdout); + + fputs("Bind CKContext: ", stdout); + PrintPointer(profile.m_BindContext); + fputc('\n', stdout); + + // write identifiers operchunk->StartRead(); - auto collection = operchunk->GetIdentifierProfile(); + const auto collection = operchunk->GetIdentifierProfile(); operchunk->StopRead(); - for (const auto& profile : collection) { - PrintIdentifier(profile.m_Identifier); + fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Identifiers\n")), stdout); + fputs("Identifier\tData Pointer\tData Size\n", stdout); + for (const auto& ident : collection) { + fprintf(stdout, "0x%08" PRIxCKDWORD "\t", ident.m_AreaSize); + PrintPointer(ident.m_DataPtr); fputc('\t', stdout); - PrintPointer(profile.m_DataPtr); - fputc('\t', stdout); - fprintf(stdout, "%" PRIckDWORD "\n", profile.m_AreaSize); + fprintf(stdout, "%" PRIuCKDWORD " (%" PRIuCKDWORD " DWORD + %" PRIuCKDWORD ")\n", + ident.m_AreaSize, ident.m_AreaSize / sizeof(LibCmo::CK2::CKDWORD), ident.m_AreaSize % sizeof(LibCmo::CK2::CKDWORD)); } } diff --git a/Unvirt/StructFormatter.hpp b/Unvirt/StructFormatter.hpp index d225016..e3dd6e9 100644 --- a/Unvirt/StructFormatter.hpp +++ b/Unvirt/StructFormatter.hpp @@ -6,8 +6,15 @@ namespace Unvirt::StructFormatter { void PrintCKFileInfo(const LibCmo::CK2::CKFileInfo& fileinfo); - void PrintObjectList(const LibCmo::XContainer::XArray& ls, size_t page, size_t pageitems); - void PrintManagerList(const LibCmo::XContainer::XArray& ls, size_t page, size_t pageitems); + + void PrintObjectList( + const LibCmo::XContainer::XArray& ls, + const LibCmo::CK2::CKFileInfo& fileinfo, + size_t page, size_t pageitems); + void PrintManagerList( + const LibCmo::XContainer::XArray& ls, + size_t page, size_t pageitems); + void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject*); void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager*); void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk*); diff --git a/Unvirt/UnvirtContext.cpp b/Unvirt/UnvirtContext.cpp index e05e611..bd4bca7 100644 --- a/Unvirt/UnvirtContext.cpp +++ b/Unvirt/UnvirtContext.cpp @@ -297,7 +297,7 @@ namespace Unvirt::Context { PrintCommonError("Page out of range."); return; } - Unvirt::StructFormatter::PrintObjectList(m_FileReader->GetFileObjects(), page, this->m_PageLen); + Unvirt::StructFormatter::PrintObjectList(m_FileReader->GetFileObjects(), m_FileReader->GetFileInfo(), page, this->m_PageLen); break; } case 1: