fix(zone): align loaded block buffers (#1006)

* fix(zone): align loaded block buffers

* chore: move XBlockTests to correct dir

* chore: align XBlocks to 4096 to match the game

---------

Co-authored-by: LVEIceFire <[email protected]>
Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
LVEIceFire
2026-09-21 01:10:22 +02:00
committed by GitHub
co-authored by LVEIceFire Jan Laupetin
parent 2547516e39
commit fc1a0bbc38
3 changed files with 48 additions and 2 deletions
+15 -1
View File
@@ -1,5 +1,19 @@
#include "XBlock.h"
#include <new>
namespace
{
// This must be higher or equal to the highest alignment value in any game struct.
// The games always seem to align to 4096 up to T6 so we'll keep parity.
constexpr std::align_val_t XBLOCK_BUFFER_ALIGNMENT{4096u};
} // namespace
void XBlockBufferDeleter::operator()(std::uint8_t* buffer) const noexcept
{
::operator delete[](buffer, XBLOCK_BUFFER_ALIGNMENT);
}
XBlock::XBlock(std::string name, const unsigned index, const XBlockType type)
: m_name(std::move(name)),
m_index(index),
@@ -12,7 +26,7 @@ void XBlock::Alloc(const size_t blockSize)
{
if (blockSize > 0)
{
m_buffer = std::make_unique<uint8_t[]>(blockSize);
m_buffer.reset(static_cast<std::uint8_t*>(::operator new[](blockSize, XBLOCK_BUFFER_ALIGNMENT)));
m_buffer_size = blockSize;
}
else
+6 -1
View File
@@ -13,6 +13,11 @@ enum class XBlockType : std::uint8_t
BLOCK_TYPE_NORMAL
};
struct XBlockBufferDeleter
{
void operator()(std::uint8_t* buffer) const noexcept;
};
class XBlock
{
public:
@@ -24,6 +29,6 @@ public:
unsigned m_index;
XBlockType m_type;
std::unique_ptr<uint8_t[]> m_buffer;
std::unique_ptr<uint8_t[], XBlockBufferDeleter> m_buffer;
size_t m_buffer_size;
};
+27
View File
@@ -0,0 +1,27 @@
#include "Zone/XBlock.h"
#include <array>
#include <catch2/catch_test_macros.hpp>
#include <cstdint>
namespace
{
TEST_CASE("Zone block buffers provide the maximum asset alignment", "[zone-loading][stream]")
{
static constexpr std::uintptr_t REQUIRED_ALIGNMENT = 4096u;
XBlock block("test", 0, XBlockType::BLOCK_TYPE_NORMAL);
constexpr size_t sizes[]{1u, 7u, 16u, 4096u, 65537u};
for (const auto size : sizes)
{
block.Alloc(size);
REQUIRE(reinterpret_cast<std::uintptr_t>(block.m_buffer.get()) % REQUIRED_ALIGNMENT == 0u);
REQUIRE(block.m_buffer_size == size);
}
block.Alloc(0u);
REQUIRE(block.m_buffer.get() == nullptr);
REQUIRE(block.m_buffer_size == 0u);
}
} // namespace