Skip to content

Commit

Permalink
Cleanup pak page creation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Mauler125 committed Dec 16, 2024
1 parent b8a2a1f commit 6e15f32
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 47 deletions.
53 changes: 23 additions & 30 deletions src/logic/pakfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<int>(m_vPages.size()-1); // note: (index-1) because we just emplace'd this instance.
page.flags = flags;
Expand All @@ -513,56 +514,48 @@ 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<uint8_t>(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<uint32_t>(chunkAlignment)) - this->dataSize;
const uint32_t alignAmount = IALIGN(page.dataSize, static_cast<uint32_t>(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;
chunk.size = alignAmount;
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<int>(size);
chunk.alignment = static_cast<uint8_t>(alignment);
chunk.released = false;

CPakDataChunk chunk{ size, static_cast<uint8_t>(alignment), buf };
page.AddDataChunk(chunk);
page.dataSize += static_cast<int>(size);
m_vVirtualSegments[page.segmentIndex].AddToDataSize(size);

return chunk;
}
Expand Down
32 changes: 15 additions & 17 deletions src/logic/pakfile.h
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand All @@ -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<int>(pageOffset + offset) }; };
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 6e15f32

Please sign in to comment.