Skip to content

Commit

Permalink
Merge pull request #118 from psiberx/master
Browse files Browse the repository at this point in the history
Decoded more buffers and mesh related types
  • Loading branch information
wopss authored May 2, 2024
2 parents 5ea7a1e + 3edad22 commit e498564
Show file tree
Hide file tree
Showing 24 changed files with 370 additions and 151 deletions.
81 changes: 81 additions & 0 deletions include/RED4ext/Buffer-inl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#pragma once

#ifdef RED4EXT_STATIC_LIB
#include <RED4ext/Buffer.hpp>
#endif

RED4EXT_INLINE RED4ext::RawBuffer::RawBuffer()
: data(nullptr)
, size(0)
, alignment(8)
, allocator{0}
{
}

RED4EXT_INLINE RED4ext::RawBuffer::RawBuffer(void* aData, uint32_t aSize, uint32_t aAlignment)
: data(aData)
, size(aSize)
, alignment(aAlignment)
, allocator{0}
{
}

RED4EXT_INLINE RED4ext::RawBuffer::~RawBuffer()
{
if (data && allocator[0])
{
reinterpret_cast<RawBufferAllocator*>(&allocator)->Free(data);
}
}

RED4EXT_INLINE RED4ext::SharedPtr<RED4ext::DeferredDataBufferToken> RED4ext::DeferredDataBuffer::LoadAsync()
{
using LoadBufferAsync_t = JobHandle* (*)(DeferredDataBuffer*, JobHandle*, int64_t);
static UniversalRelocFunc<LoadBufferAsync_t> func(Detail::AddressHashes::DeferredDataBuffer_LoadAsync);

JobHandle loadingJob;
func(this, &loadingJob, 0);

return MakeShared<DeferredDataBufferToken>(*this, loadingJob);
}

RED4EXT_INLINE RED4ext::SharedPtr<RED4ext::DeferredDataBufferCopyToken> RED4ext::DeferredDataBuffer::LoadCopyAsync()
{
using LoadBufferRefAsync_t = void* (*)(DeferredDataBuffer*, SharedPtr<DeferredDataBufferCopyToken>*, int8_t);
static UniversalRelocFunc<LoadBufferRefAsync_t> func(Detail::AddressHashes::DeferredDataBuffer_LoadRefAsync);

SharedPtr<DeferredDataBufferCopyToken> token;
func(this, &token, 0);

return token;
}

RED4EXT_INLINE RED4ext::DeferredDataBufferToken::DeferredDataBufferToken(DeferredDataBuffer& aBuffer,
JobHandle& aJob) noexcept
: buffer(aBuffer)
, job(aJob)
{
}

RED4EXT_INLINE void RED4ext::DeferredDataBufferToken::OnLoaded(LoadedCallback&& aCallback)
{
JobQueue jobQueue;
jobQueue.Wait(job);
jobQueue.Dispatch([self = MakeShared<DeferredDataBufferToken>(*this), callback = std::move(aCallback)]()
{ callback(self->buffer); });
}

RED4EXT_INLINE RED4ext::DeferredDataBufferCopyToken::~DeferredDataBufferCopyToken()
{
using DestructUnk28_t = void (*)(void**);
static UniversalRelocFunc<DestructUnk28_t> DestructUnk28(Detail::AddressHashes::ResourceToken_DestructUnk38);
DestructUnk28(&unk28);
}

RED4EXT_INLINE void RED4ext::DeferredDataBufferCopyToken::OnLoaded(LoadedCallback&& aCallback) const
{
JobQueue jobQueue;
jobQueue.Wait(job);
jobQueue.Dispatch([self = self.Lock(), callback = std::move(aCallback)]()
{ callback(self); });
}
121 changes: 121 additions & 0 deletions include/RED4ext/Buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#pragma once

#include <cstdint>

#include <RED4ext/Callback.hpp>
#include <RED4ext/JobQueue.hpp>
#include <RED4ext/Memory/Allocators.hpp>
#include <RED4ext/Memory/SharedPtr.hpp>

namespace RED4ext
{
struct RawBufferAllocator
{
virtual void sub_00() = 0; // 08
virtual void Free(void* aData) = 0; // 08
virtual Memory::IAllocator GetAllocator() = 0; // 10

void* unk08;
};
RED4EXT_ASSERT_SIZE(RawBufferAllocator, 0x10);

struct RawBuffer
{
using AllocatorType = Memory::EngineAllocator;

RawBuffer();
RawBuffer(void* aData, uint32_t aSize, uint32_t aAlignment = 8);
RawBuffer(const RawBuffer&) = delete;
RawBuffer(RawBuffer&&) = default;
~RawBuffer();

void* data; // 00
uint32_t size; // 08
uint32_t alignment; // 0C
uint64_t allocator[2]; // 10
};
RED4EXT_ASSERT_SIZE(RawBuffer, 0x20);

struct DataBuffer
{
RawBuffer buffer; // 00
uint64_t unk20; // 20 - Pointer to something
};
RED4EXT_ASSERT_SIZE(DataBuffer, 0x28);

struct SharedDataBuffer
{
int64_t unk00; // 00
};
RED4EXT_ASSERT_SIZE(SharedDataBuffer, 0x8);

struct DeferredDataBufferToken;
struct DeferredDataBufferCopyToken;

enum class DeferredDataBufferState : uint8_t
{
Unloaded = 0,
Loading = 1,
Loaded = 2,
};

struct DeferredDataBuffer
{
SharedPtr<DeferredDataBufferToken> LoadAsync();
SharedPtr<DeferredDataBufferCopyToken> LoadCopyAsync();

RawBuffer temp; // 00 - Can be used during loading
SharedPtr<RawBuffer> raw; // 20 - Loaded data
void* unk30; // 30
uint8_t unk38; // 38
uint64_t unk40; // 40
uint64_t unk48; // 48
uint32_t unk50; // 50
DeferredDataBufferState state; // 54
SharedMutex lock; // 55
uint16_t unk56; // 56
};
RED4EXT_ASSERT_SIZE(DeferredDataBuffer, 0x58);
RED4EXT_ASSERT_OFFSET(DeferredDataBuffer, raw, 0x20);
RED4EXT_ASSERT_OFFSET(DeferredDataBuffer, state, 0x54);
RED4EXT_ASSERT_OFFSET(DeferredDataBuffer, lock, 0x55);

struct DeferredDataBufferToken
{
using AllocatorType = Memory::EngineAllocator;
using LoadedCallback = Callback<void (*)(DeferredDataBuffer&)>;

DeferredDataBufferToken(DeferredDataBuffer& aBuffer, JobHandle& aJob) noexcept;
DeferredDataBufferToken(const DeferredDataBufferToken&) = default;
DeferredDataBufferToken(DeferredDataBufferToken&&) = default;

void OnLoaded(LoadedCallback&& aCallback);

DeferredDataBuffer& buffer;
JobHandle job;
};

struct DeferredDataBufferCopyToken
{
using AllocatorType = Memory::EngineAllocator;
using LoadedCallback = Callback<void (*)(const SharedPtr<DeferredDataBufferCopyToken>&)>;

~DeferredDataBufferCopyToken();

void OnLoaded(LoadedCallback&& aCallback) const;

WeakPtr<DeferredDataBufferCopyToken> self; // 00
JobHandle job; // 10
SharedPtr<RawBuffer> raw; // 18
void* unk28; // 28 - SharedPtr.instance
void* unk30; // 30 - SharedPtr.refCount
};
RED4EXT_ASSERT_SIZE(DeferredDataBufferCopyToken, 0x38);
RED4EXT_ASSERT_OFFSET(DeferredDataBufferCopyToken, job, 0x10);
RED4EXT_ASSERT_OFFSET(DeferredDataBufferCopyToken, raw, 0x18);
RED4EXT_ASSERT_OFFSET(DeferredDataBufferCopyToken, unk28, 0x28);
} // namespace RED4ext

#ifdef RED4EXT_HEADER_ONLY
#include <RED4ext/Buffer-inl.hpp>
#endif
20 changes: 17 additions & 3 deletions include/RED4ext/Callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ class Callback<R (*)(Args...), InlineSize>

static_assert(InlineSize >= sizeof(void*), "Buffer size can't be less than pointer size");

Callback()
: buffer()
, handler(nullptr)
{
}

Callback(R (*aFunc)(Args...)) noexcept
{
using TargetType = Detail::UnboundFunctionTarget<R, Args...>;
Expand Down Expand Up @@ -220,6 +226,14 @@ class FlexCallback<R (*)(Args...), InlineSize>

static_assert(InlineSize >= sizeof(void*), "Buffer size can't be less than pointer size");

FlexCallback()
: buffer()
, handler(nullptr)
, allocator(0)
, extendedSize(0)
{
}

FlexCallback(R (*aFunc)(Args...))
: allocator(0)
, extendedSize(0)
Expand Down Expand Up @@ -397,14 +411,14 @@ class FlexCallback<R (*)(Args...), InlineSize>
return InlineSize;
}

[[nodiscard]] void* GetBuffer() noexcept
[[nodiscard]] void* GetBuffer() const noexcept
{
if (IsExtendedMode())
{
return *reinterpret_cast<void**>(buffer);
return *reinterpret_cast<void**>(const_cast<uint8_t*>(buffer));
}

return buffer;
return const_cast<uint8_t*>(buffer);
}

void ResetBuffer()
Expand Down
1 change: 1 addition & 0 deletions include/RED4ext/Detail/AddressHashes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ constexpr std::uint32_t UpdateRegistrar_RegisterBucketUpdate = 0x192F4EA2;

#pragma region DeferredDataBuffer
constexpr std::uint32_t DeferredDataBuffer_LoadAsync = 4125893577;
constexpr std::uint32_t DeferredDataBuffer_LoadRefAsync = 1459046115;
#pragma endregion
}
// clang-format on
7 changes: 3 additions & 4 deletions include/RED4ext/Dump/Reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ using TypeChecker = std::function<bool(const RED4ext::CBaseRTTIType*)>;
using FixedTypeMapping = std::unordered_map<RED4ext::CName, std::string, RED4ext::CName>;

static constexpr const char* INVALID_CHARACTERS = R"(-|'|\(|\)|\]|\[|/|\.|\s|:)";
// small conflicts with windows macro
// Plane conflicts with itself as a type name
static constexpr const char* INVALID_KEYWORDS =
R"(\bregister\b|\bbool\b|\bint\b|\btemplate\b|\btrue\b|\bfalse\b|\bsmall\b|\bPlane\b)"; // small conflicts with
// windows macro, Plane
// conflicts with itself as
// a type name
R"(\bregister\b|\bbool\b|\bint\b|\btemplate\b|\bdefault\b|\btrue\b|\bfalse\b|\bsmall\b|\bPlane\b)";

struct ClassFileDescriptor
{
Expand Down
2 changes: 1 addition & 1 deletion include/RED4ext/JobQueue-inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ RED4EXT_INLINE RED4ext::JobQueue::~JobQueue()
func(this);
}

RED4EXT_INLINE void RED4ext::JobQueue::Wait(JobHandle& aJob)
RED4EXT_INLINE void RED4ext::JobQueue::Wait(const JobHandle& aJob)
{
unk10.Join(aJob);
}
Expand Down
4 changes: 1 addition & 3 deletions include/RED4ext/JobQueue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ RED4EXT_ASSERT_SIZE(JobParamSet, 0x3);
struct JobHandle
{
JobHandle(uintptr_t aUnk = 0);
JobHandle(const JobHandle&) = default;
JobHandle(JobHandle&&) = default;
~JobHandle();

/**
Expand Down Expand Up @@ -242,7 +240,7 @@ class JobQueue
*
* @param aJob The job to wait before continuing the queue.
*/
void Wait(JobHandle& aJob);
void Wait(const JobHandle& aJob);

/**
* @brief Finalizes the queue and returns a job handle associated with this queue.
Expand Down
50 changes: 0 additions & 50 deletions include/RED4ext/NativeTypes-inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,53 +288,3 @@ RED4EXT_INLINE bool RED4ext::Variant::CanBeInlined(const RED4ext::CBaseRTTIType*
{
return aType->GetSize() <= InlineSize && aType->GetAlignment() <= InlineAlignment;
}

RED4EXT_INLINE RED4ext::RawBuffer::RawBuffer()
: data(nullptr)
, size(0)
, alignment(8)
, allocator{0}
{
}

RED4EXT_INLINE RED4ext::RawBuffer::RawBuffer(void* aData, uint32_t aSize, uint32_t aAlignment)
: data(aData)
, size(aSize)
, alignment(aAlignment)
, allocator{0}
{
}

RED4EXT_INLINE RED4ext::RawBuffer::~RawBuffer()
{
if (data && allocator[0])
{
reinterpret_cast<RawBufferAllocator*>(&allocator)->Free(data);
}
}

RED4EXT_INLINE RED4ext::SharedPtr<RED4ext::DeferredDataBufferToken> RED4ext::DeferredDataBuffer::LoadAsync()
{
using LoadBufferAsync_t = JobHandle* (*)(DeferredDataBuffer*, JobHandle*, int64_t);
static UniversalRelocFunc<LoadBufferAsync_t> func(Detail::AddressHashes::DeferredDataBuffer_LoadAsync);

JobHandle loadingJob;
func(this, &loadingJob, 0);

return MakeShared<DeferredDataBufferToken>(*this, loadingJob);
}

RED4EXT_INLINE RED4ext::DeferredDataBufferToken::DeferredDataBufferToken(DeferredDataBuffer& aBuffer,
JobHandle& aJob) noexcept
: buffer(aBuffer)
, job(aJob)
{
}

RED4EXT_INLINE void RED4ext::DeferredDataBufferToken::OnLoaded(LoadedCallback&& aCallback)
{
JobQueue jobQueue;
jobQueue.Wait(job);
jobQueue.Dispatch([self = MakeShared<DeferredDataBufferToken>(*this), callback = std::move(aCallback)]()
{ callback(self->buffer); });
}
Loading

0 comments on commit e498564

Please sign in to comment.