From 376fdf16c4dbf07553847313e0f9cc5a3031a134 Mon Sep 17 00:00:00 2001 From: elasota Date: Wed, 1 Sep 2021 22:06:43 -0400 Subject: [PATCH] Add name-to-comment support to GPAs --- MergeGPF/MergeGPF.cpp | 25 +++++++++++++++++++++---- PortabilityLayer/ResourceFile.cpp | 11 +++++++++++ PortabilityLayer/ResourceFile.h | 5 +++++ gpr2gpa/gpr2gpa.cpp | 22 +++++++++++++++++++--- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/MergeGPF/MergeGPF.cpp b/MergeGPF/MergeGPF.cpp index 87511eb..e7f1dc4 100644 --- a/MergeGPF/MergeGPF.cpp +++ b/MergeGPF/MergeGPF.cpp @@ -227,6 +227,8 @@ int toolMain(int argc, const char **argv) std::vector resCentralDir; std::vector fileNameBytes; std::vector fileNameSizes; + std::vector commentBytes; + std::vector commentSizes; FILE *resF = fopen_utf8(resName.c_str(), "rb"); if (resF) @@ -266,7 +268,20 @@ int toolMain(int argc, const char **argv) } } - if (!resStream.SeekCurrent(cdirFile.m_extraFieldLength + cdirFile.m_commentLength)) + size_t commentLength = cdirFile.m_commentLength; + commentSizes.push_back(commentLength); + + if (commentLength > 0) + { + commentBytes.resize(commentBytes.size() + commentLength); + if (!resStream.Read(&commentBytes[commentBytes.size() - commentLength], commentLength)) + { + fprintf(stderr, "Error reading cdir entry"); + return -1; + } + } + + if (!resStream.SeekCurrent(cdirFile.m_extraFieldLength)) { fprintf(stderr, "Error reading cdir entry"); return -1; @@ -275,7 +290,7 @@ int toolMain(int argc, const char **argv) resCentralDir.push_back(cdirFile); numFiles++; - cdirSize += sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader) + fileNameLength; + cdirSize += sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader) + fileNameLength + commentLength; } for (size_t i = 0; i < resCentralDir.size(); i++) @@ -296,7 +311,6 @@ int toolMain(int argc, const char **argv) cdirHeader.m_localHeaderOffset = mergedStream.Tell(); cdirHeader.m_extraFieldLength = 0; - cdirHeader.m_commentLength = 0; if (!mergedStream.WriteExact(&resLH, sizeof(resLH))) { @@ -357,19 +371,22 @@ int toolMain(int argc, const char **argv) } } + size_t commentBytesOffset = 0; size_t fnameBytesOffset = 0; for (size_t i = 0; i < resCentralDir.size(); i++) { size_t fnameSize = fileNameSizes[i]; + size_t commentSize = commentSizes[i]; const PortabilityLayer::ZipCentralDirectoryFileHeader &cdir = resCentralDir[i]; - if (!mergedStream.WriteExact(&cdir, sizeof(cdir)) || (fnameSize > 0 && !mergedStream.WriteExact(&fileNameBytes[fnameBytesOffset], fnameSize))) + if (!mergedStream.WriteExact(&cdir, sizeof(cdir)) || (fnameSize > 0 && !mergedStream.WriteExact(&fileNameBytes[fnameBytesOffset], fnameSize)) || (commentSize > 0 && !mergedStream.WriteExact(&commentBytes[commentBytesOffset], commentSize))) { fprintf(stderr, "Error writing directory"); return -1; } fnameBytesOffset += fnameSize; + commentBytesOffset += commentSize; } PortabilityLayer::ZipEndOfCentralDirectoryRecord eocd; diff --git a/PortabilityLayer/ResourceFile.cpp b/PortabilityLayer/ResourceFile.cpp index 4b123a0..defb75f 100644 --- a/PortabilityLayer/ResourceFile.cpp +++ b/PortabilityLayer/ResourceFile.cpp @@ -20,6 +20,7 @@ namespace PortabilityLayer , m_numResources(0) , m_compiledTypeListBlob(nullptr) , m_numResourceTypes(0) + , m_nameListOffset(0) { } @@ -343,6 +344,16 @@ namespace PortabilityLayer outCount = m_numResourceTypes; } + const uint8_t *ResourceFile::GetResNames() const + { + return m_resNameBlob; + } + + const size_t ResourceFile::GetResNamesSize() const + { + return m_resNameBlobSize; + } + const ResourceCompiledTypeList *ResourceFile::GetResourceTypeList(const ResTypeID &resType) { const ResourceCompiledTypeList *tlStart = m_compiledTypeListBlob; diff --git a/PortabilityLayer/ResourceFile.h b/PortabilityLayer/ResourceFile.h index 6a9cc74..563be86 100644 --- a/PortabilityLayer/ResourceFile.h +++ b/PortabilityLayer/ResourceFile.h @@ -21,6 +21,9 @@ namespace PortabilityLayer void GetAllResourceTypeLists(ResourceCompiledTypeList *&outTypeLists, size_t &outCount) const; + const uint8_t *GetResNames() const; + const size_t GetResNamesSize() const; + const ResourceCompiledTypeList *GetResourceTypeList(const ResTypeID &resType); THandle LoadResource(const ResTypeID &resType, int id); @@ -43,6 +46,8 @@ namespace PortabilityLayer ResourceCompiledTypeList *m_compiledTypeListBlob; size_t m_numResourceTypes; + uint32_t m_nameListOffset; + static bool CompiledRefSortPredicate(const ResourceCompiledRef &a, const ResourceCompiledRef &b); static bool CompiledTypeListSortPredicate(const ResourceCompiledTypeList &a, const ResourceCompiledTypeList &b); diff --git a/gpr2gpa/gpr2gpa.cpp b/gpr2gpa/gpr2gpa.cpp index 93c0df4..2905158 100644 --- a/gpr2gpa/gpr2gpa.cpp +++ b/gpr2gpa/gpr2gpa.cpp @@ -52,6 +52,7 @@ struct PlannedEntry std::vector m_compressedContents; std::string m_name; + std::string m_comment; bool m_isDirectory; PlannedEntry() @@ -252,7 +253,7 @@ void ExportZipFile(const char *path, std::vector &entries, const P cdirHeader.m_uncompressedSize = static_cast(entry.m_uncompressedContents.size()); cdirHeader.m_fileNameLength = static_cast(entry.m_name.size()); cdirHeader.m_extraFieldLength = 0; - cdirHeader.m_commentLength = 0; + cdirHeader.m_commentLength = static_cast(entry.m_comment.size()); cdirHeader.m_diskNumber = 0; cdirHeader.m_internalAttributes = 0; cdirHeader.m_externalAttributes = entry.m_isDirectory ? PortabilityLayer::ZipConstants::kDirectoryAttributes : PortabilityLayer::ZipConstants::kArchivedAttributes; @@ -290,6 +291,7 @@ void ExportZipFile(const char *path, std::vector &entries, const P { fwrite(&cdirRecords[i], 1, sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader), outF); fwrite(entries[i].m_name.c_str(), 1, entries[i].m_name.size(), outF); + fwrite(entries[i].m_comment.c_str(), 1, entries[i].m_comment.size(), outF); } long cdirEndPos = ftell(outF); @@ -2363,7 +2365,6 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PortabilityLayer::ResourceFile *resFile = PortabilityLayer::ResourceFile::Create(); resFile->Load(&cfs); - cfs.Close(); PortabilityLayer::ResourceCompiledTypeList *typeLists = nullptr; size_t typeListCount = 0; @@ -2428,6 +2429,14 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes const void *resData = res.m_resData; const size_t resSize = res.GetSize(); + std::string resComment; + + if (res.m_resNameOffset >= 0) + { + const uint8_t *pstrStart = resFile->GetResNames() + res.m_resNameOffset; + resComment = std::string(reinterpret_cast(pstrStart + 1), pstrStart[0]); + } + if (typeList.m_resType == pictTypeID || typeList.m_resType == dateTypeID) { char resName[256]; @@ -2438,6 +2447,7 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PlannedEntry entry; entry.m_name = resName; + entry.m_comment = resComment; if (ImportPICT(entry.m_uncompressedContents, resData, resSize, dumpqtDir, res.m_resID)) contents.push_back(entry); @@ -2454,6 +2464,7 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PlannedEntry entry; entry.m_name = resName; + entry.m_comment = resComment; if (ImportSound(entry.m_uncompressedContents, resData, resSize, res.m_resID)) contents.push_back(entry); @@ -2470,6 +2481,7 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PlannedEntry entry; entry.m_name = resName; + entry.m_comment = resComment; if (ImportIndexedString(entry.m_uncompressedContents, resData, resSize)) contents.push_back(entry); @@ -2484,6 +2496,7 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PlannedEntry entry; entry.m_name = resName; + entry.m_comment = resComment; if (ImportDialogItemTemplate(entry.m_uncompressedContents, resData, resSize)) contents.push_back(entry); @@ -2505,8 +2518,8 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes isIcon = true; PlannedEntry entry; - entry.m_name = resName; + entry.m_comment = resComment; if (ImportIcon(entry.m_uncompressedContents, resData, resSize, iconSpec.m_width, iconSpec.m_height, iconSpec.m_bpp)) contents.push_back(entry); @@ -2527,6 +2540,7 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PlannedEntry entry; entry.m_name = resName; + entry.m_comment = resComment; entry.m_uncompressedContents.resize(res.GetSize()); memcpy(&entry.m_uncompressedContents[0], resData, resSize); @@ -2537,6 +2551,8 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes } } + cfs.Close(); + if (havePatchFile) { if (!ApplyPatch(patchFileContents, contents))