From 6e15f32c9a34f4fc414512601b6e12b864a68971 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:35:41 +0100 Subject: [PATCH] Cleanup pak page creation Unified 3 separate small methods into 1 which allows for making the code faster and dropping the need of a cached CPakFile pointer in the CPakPage class. The 2 separate methods could and should only be called when creating chunks so this will avoid confusion in the future as well. --- src/logic/pakfile.cpp | 53 +++++++++++++++++++------------------------ src/logic/pakfile.h | 32 ++++++++++++-------------- 2 files changed, 38 insertions(+), 47 deletions(-) diff --git a/src/logic/pakfile.cpp b/src/logic/pakfile.cpp index f6dee87..de622d2 100644 --- a/src/logic/pakfile.cpp +++ b/src/logic/pakfile.cpp @@ -100,7 +100,9 @@ void CPakFile::AddAsset(const rapidjson::Value& file) //----------------------------------------------------------------------------- void CPakFile::AddPointer(int pageIdx, int pageOffset) { - m_vPakDescriptors.push_back({ pageIdx, pageOffset }); + PakGuidRefHdr_t& refHdr = m_vPakDescriptors.emplace_back(); + refHdr.index = pageIdx; + refHdr.offset = pageOffset; } void CPakFile::AddPointer(PagePtr_t ptr) @@ -503,7 +505,6 @@ CPakPage& CPakFile::FindOrCreatePage(int flags, int alignment, size_t newDataSiz CPakVSegment& segment = FindOrCreateSegment(flags, alignment); CPakPage& page = m_vPages.emplace_back(); - page.pak = this; page.segmentIndex = segment.GetIndex(); page.pageIndex = static_cast(m_vPages.size()-1); // note: (index-1) because we just emplace'd this instance. page.flags = flags; @@ -513,35 +514,29 @@ CPakPage& CPakFile::FindOrCreatePage(int flags, int alignment, size_t newDataSiz return page; } -void CPakPage::AddDataChunk(CPakDataChunk& chunk) +CPakDataChunk CPakFile::CreateDataChunk(const size_t size, const int flags, const int alignment) { - assert(this->alignment > 0 && this->alignment < UINT8_MAX); - this->PadPageToChunkAlignment(static_cast(this->alignment)); - - chunk.pageIndex = this->GetIndex(); - chunk.pageOffset = this->GetSize(); - - this->dataSize += chunk.size; - this->pak->m_vVirtualSegments[this->segmentIndex].AddToDataSize(chunk.size); + // this assert is replicated in r5sdk + assert(alignment != 0 && alignment < UINT8_MAX); - this->chunks.emplace_back(chunk); -} + CPakPage& page = FindOrCreatePage(flags, alignment, size); + char* const buf = new char[size]; + memset(buf, 0, size); -void CPakPage::PadPageToChunkAlignment(uint8_t chunkAlignment) -{ - uint32_t alignAmount = IALIGN(this->dataSize, static_cast(chunkAlignment)) - this->dataSize; + const uint32_t alignAmount = IALIGN(page.dataSize, static_cast(alignment)) - page.dataSize; + // pad page to chunk alignment if (alignAmount > 0) { //printf("Aligning by %u bytes...\n", alignAmount); - this->dataSize += alignAmount; - this->pak->m_vVirtualSegments[this->segmentIndex].AddToDataSize(alignAmount); + page.dataSize += alignAmount; + m_vVirtualSegments[page.segmentIndex].AddToDataSize(alignAmount); // create null chunk with size of the alignment amount // these chunks are handled specially when writing to file, // writing only null bytes for the size of the chunk when no data ptr is present - CPakDataChunk& chunk = this->chunks.emplace_back(); + CPakDataChunk& chunk = page.chunks.emplace_back(); chunk.pageIndex = 0; chunk.pageOffset = 0; @@ -549,20 +544,18 @@ void CPakPage::PadPageToChunkAlignment(uint8_t chunkAlignment) chunk.alignment = 0; chunk.pData = nullptr; } -} -CPakDataChunk CPakFile::CreateDataChunk(size_t size, int flags, int alignment) -{ - // this assert is replicated in r5sdk - assert(alignment != 0 && alignment < UINT8_MAX); + CPakDataChunk& chunk = page.chunks.emplace_back(); - CPakPage& page = FindOrCreatePage(flags, alignment, size); - - char* buf = new char[size]; - memset(buf, 0, size); + chunk.pData = buf; + chunk.pageIndex = page.GetIndex(); + chunk.pageOffset = page.GetSize(); + chunk.size = static_cast(size); + chunk.alignment = static_cast(alignment); + chunk.released = false; - CPakDataChunk chunk{ size, static_cast(alignment), buf }; - page.AddDataChunk(chunk); + page.dataSize += static_cast(size); + m_vVirtualSegments[page.segmentIndex].AddToDataSize(size); return chunk; } diff --git a/src/logic/pakfile.h b/src/logic/pakfile.h index 0faeebd..9ca66ee 100644 --- a/src/logic/pakfile.h +++ b/src/logic/pakfile.h @@ -1,14 +1,16 @@ #pragma once #include "public/rpak.h" +#define MAX_PAK_PAGE_SIZE 0xffff + +class CPakFile; + struct _vseginfo_t { int index = -1; int size = 0; }; -#define MAX_PAK_PAGE_SIZE 0xffff - class CPakVSegment { friend class CPakFile; @@ -44,12 +46,10 @@ class CPakPage public: CPakPage() = default; - CPakPage(CPakFile* pak, int segIdx, int pageIdx, int flags, int align) : - pak(pak), segmentIndex(segIdx), pageIndex(pageIdx), flags(flags), alignment(align), dataSize(0) {}; + CPakPage(int segIdx, int pageIdx, int flags, int align) + : segmentIndex(segIdx), pageIndex(pageIdx), flags(flags), alignment(align), dataSize(0) {}; private: - CPakFile* pak; - int segmentIndex; // index of the virtual data segment that this page is part of int pageIndex; // index of this page in all of the pak's pages @@ -61,19 +61,17 @@ class CPakPage int dataSize; public: - inline int GetIndex() { return pageIndex; }; - inline int GetFlags() { return flags; }; - inline int GetAlignment() { return alignment; }; - - PakPageHdr_t GetHeader() { return { segmentIndex, alignment, dataSize }; }; - int GetSize() { return dataSize; }; + inline int GetIndex() const { return pageIndex; }; + inline int GetFlags() const { return flags; }; + inline int GetAlignment() const { return alignment; }; - void AddDataChunk(CPakDataChunk& chunk); - void PadPageToChunkAlignment(uint8_t alignment); + PakPageHdr_t GetHeader() const { return { segmentIndex, alignment, dataSize }; }; + int GetSize() const { return dataSize; }; }; class CPakDataChunk { + friend class CPakFile; friend class CPakPage; public: @@ -83,12 +81,12 @@ class CPakDataChunk CPakDataChunk(int pageIndex, int pageOffset, size_t size, uint8_t alignment, char* data) : pageIndex(pageIndex), pageOffset(pageOffset), size((int)size), alignment(alignment), pData(data), released(false) {}; private: + char* pData; int pageIndex; int pageOffset; int size; uint8_t alignment; bool released; - char* pData; public: inline PagePtr_t GetPointer(size_t offset=0) { return { pageIndex, static_cast(pageOffset + offset) }; }; @@ -217,9 +215,9 @@ class CPakFile void GenerateFileRelations(); void GenerateGuidData(); - CPakPage& FindOrCreatePage(int flags, int alignment, size_t newDataSize); + CPakPage& FindOrCreatePage(const int flags, const int alignment, const size_t newDataSize); - CPakDataChunk CreateDataChunk(size_t size, int flags, int alignment); + CPakDataChunk CreateDataChunk(const size_t size, const int flags, const int alignment); //_vseginfo_t CreateNewSegment(int size, uint32_t flags, uint32_t alignment, uint32_t vsegAlignment = -1); CPakVSegment& FindOrCreateSegment(int flags, int alignment);