From fe50596ba148760198fd6227146caed0e818d2f6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:00:01 +0100 Subject: [PATCH 1/3] Fix incorrect slab padding caused by interleafing pages Page buffer isn't sorted per slab, but in the order they are created (they must retain like this as well for pointer conversions done in the runtime). However, we never accounted for this when padding out slabs and pages causing them to be padded out incorrectly as the prior page could belong to a different slab. Code now tracks to which slab the page belongs and independently handles the alignment thereof. Paks generated by RePak are now identical to retail. --- src/logic/pakpage.cpp | 28 ++++++++++++++++++---------- src/logic/pakpage.h | 8 ++++++-- src/pch.h | 1 + 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/logic/pakpage.cpp b/src/logic/pakpage.cpp index 5e9eab8f..9d34385d 100644 --- a/src/logic/pakpage.cpp +++ b/src/logic/pakpage.cpp @@ -41,6 +41,7 @@ // Constructors/Destructors //----------------------------------------------------------------------------- CPakPageBuilder::CPakPageBuilder() + : m_slabCount(0) { } CPakPageBuilder::~CPakPageBuilder() @@ -66,7 +67,7 @@ PakSlab_s& CPakPageBuilder::FindOrCreateSlab(const int flags, const int align) // Try and find a slab that has the same flags, and the closest alignment // of request. - for (size_t i = 0; i < m_slabs.size(); i++) + for (uint16_t i = 0; i < m_slabCount; i++) { PakSlab_s& slab = m_slabs[i]; PakSlabHdr_s& header = slab.header; @@ -106,9 +107,9 @@ PakSlab_s& CPakPageBuilder::FindOrCreateSlab(const int flags, const int align) } // If we didn't have a close match, create a new slab. - PakSlab_s& newSlab = m_slabs.emplace_back(); + PakSlab_s& newSlab = m_slabs[m_slabCount]; - newSlab.index = static_cast(m_slabs.size() - 1); + newSlab.index = m_slabCount++; newSlab.header.flags = flags; newSlab.header.alignment = align; newSlab.header.dataSize = 0; @@ -286,22 +287,28 @@ const PakPageLump_s CPakPageBuilder::CreatePageLump(const int size, const int fl //----------------------------------------------------------------------------- void CPakPageBuilder::PadSlabsAndPages() { - int lastPageSizeAligned = 0; - int lastPageAlign = 0; + struct PageAlignmentTracker_s + { + int lastPageSizeAligned = 0; + int lastPageAlign = 0; + }; + + PageAlignmentTracker_s alignTrack[PAK_MAX_SLAB_COUNT]; for (PakPage_s& page : m_pages) { PakPageHdr_s& pageHdr = page.header; PakSlab_s& slab = m_slabs[pageHdr.slabIndex]; PakSlabHdr_s& slabHdr = slab.header; + PageAlignmentTracker_s& track = alignTrack[pageHdr.slabIndex]; const int pageSize = pageHdr.dataSize; const int pageAlign = pageHdr.alignment; // The runtime pads the previous page to align our current page, we have // to add this extra size to the slab to accommodate for this. - if (lastPageSizeAligned > 0 && pageAlign > lastPageAlign) - slabHdr.dataSize += IALIGN(lastPageSizeAligned, pageAlign) - lastPageSizeAligned; + if (track.lastPageSizeAligned > 0 && pageAlign > track.lastPageAlign) + slabHdr.dataSize += IALIGN(track.lastPageSizeAligned, pageAlign) - track.lastPageSizeAligned; const int pagePadAmount = IALIGN(pageSize, pageAlign) - pageSize; @@ -312,8 +319,8 @@ void CPakPageBuilder::PadSlabsAndPages() if (pagePadAmount > 0) slabHdr.dataSize += pagePadAmount; - lastPageSizeAligned = pageSize + pagePadAmount; - lastPageAlign = pageAlign; + track.lastPageSizeAligned = pageSize + pagePadAmount; + track.lastPageAlign = pageAlign; } } @@ -322,8 +329,9 @@ void CPakPageBuilder::PadSlabsAndPages() //----------------------------------------------------------------------------- void CPakPageBuilder::WriteSlabHeaders(BinaryIO& out) const { - for (const PakSlab_s& slab : m_slabs) + for (uint16_t i = 0; i < m_slabCount; i++) { + const PakSlab_s& slab = m_slabs[i]; out.Write(slab.header); } } diff --git a/src/logic/pakpage.h b/src/logic/pakpage.h index ca6d61cd..7e161ebc 100644 --- a/src/logic/pakpage.h +++ b/src/logic/pakpage.h @@ -1,6 +1,8 @@ #pragma once #include "public/rpak.h" +#define PAK_MAX_SLAB_COUNT 20 + // Pages can only be merged with other pages with equal flags and an alignment // equal or higher than its own if the combined size aligned to the page's // new alignment is below this value. @@ -62,7 +64,7 @@ class CPakPageBuilder CPakPageBuilder(); ~CPakPageBuilder(); - inline uint16_t GetSlabCount() const { return static_cast(m_slabs.size()); } + inline uint16_t GetSlabCount() const { return m_slabCount; } inline uint16_t GetPageCount() const { return static_cast(m_pages.size()); } const PakPageLump_s CreatePageLump(const int size, const int flags, const int align, void* const buf = nullptr); @@ -78,6 +80,8 @@ class CPakPageBuilder PakPage_s& FindOrCreatePage(const int flags, const int align, const int size); private: - std::vector m_slabs; + std::array m_slabs; + uint16_t m_slabCount; + std::vector m_pages; }; diff --git a/src/pch.h b/src/pch.h index 46b274ad..40fd697b 100644 --- a/src/pch.h +++ b/src/pch.h @@ -10,6 +10,7 @@ #include //#include #include +#include #include #include #include From b2bfd4853e24c01ab844f276e7985a00e073b6ed Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:00:57 +0100 Subject: [PATCH 2/3] Add guard for max slabs Make sure we never allocate more than 20 slabs, as this is the limit of what the runtime can have. --- src/logic/pakpage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/logic/pakpage.cpp b/src/logic/pakpage.cpp index 9d34385d..d805a741 100644 --- a/src/logic/pakpage.cpp +++ b/src/logic/pakpage.cpp @@ -106,6 +106,9 @@ PakSlab_s& CPakPageBuilder::FindOrCreateSlab(const int flags, const int align) return *toReturn; } + if (m_slabCount + 1 > PAK_MAX_SLAB_COUNT) + Error("Out of room while adding new slab; runtime has a limit of %hu.\n", PAK_MAX_SLAB_COUNT); + // If we didn't have a close match, create a new slab. PakSlab_s& newSlab = m_slabs[m_slabCount]; From 0c9712dfc8e0826bd3fc29475502f1cf6ac8378a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:06:20 +0100 Subject: [PATCH 3/3] Add comment to newly added define --- src/logic/pakpage.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logic/pakpage.h b/src/logic/pakpage.h index 7e161ebc..ea1387ee 100644 --- a/src/logic/pakpage.h +++ b/src/logic/pakpage.h @@ -1,6 +1,7 @@ #pragma once #include "public/rpak.h" +// Maximum number of slabs that can be allocated into the runtime collection. #define PAK_MAX_SLAB_COUNT 20 // Pages can only be merged with other pages with equal flags and an alignment