mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
Initial commit
This commit is contained in:
77
arm9/source/patches/PatchCodeCollection.h
Normal file
77
arm9/source/patches/PatchCodeCollection.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include "PatchCode.h"
|
||||
#include "PatchHeap.h"
|
||||
|
||||
/// @brief Class representing a collection of patch codes.
|
||||
class PatchCodeCollection
|
||||
{
|
||||
private:
|
||||
using create_patch_code_func_t = PatchCode* (*)(PatchCodeCollection& patchCodeCollection);
|
||||
|
||||
public:
|
||||
PatchCodeCollection()
|
||||
{
|
||||
_patchCodeEntries.fill({ 0, nullptr });
|
||||
}
|
||||
|
||||
PatchCodeCollection(const PatchCodeCollection&) = delete;
|
||||
|
||||
/// @brief Adds a unique patch code to the collection. If the same patch code is added another time, it will be duplicated.
|
||||
/// @tparam T The type of patch code.
|
||||
/// @tparam ...Args The argument types for the patch code constructor.
|
||||
/// @param ...args The arguments for the patch code constructor.
|
||||
/// @return A pointer to the patch code.
|
||||
template <typename T, typename... Args> requires std::derived_from<T, PatchCode>
|
||||
const T* AddUniquePatchCode(Args&&... args)
|
||||
{
|
||||
T* patchCode = new T(std::forward<Args>(args)...);
|
||||
AddUniquePatchCode(patchCode);
|
||||
return patchCode;
|
||||
}
|
||||
|
||||
/// @brief Gets or adds a shared patch code from/to the collection.
|
||||
/// If the same patch code is requested another time, the same instance will be returned.
|
||||
/// @tparam T The type of patch code.
|
||||
/// @param factoryFunction A factory function that produces a pointer to the patch code class (T*).
|
||||
/// @return A pointer to the patch code.
|
||||
template <typename T> requires std::derived_from<std::remove_pointer_t<std::invoke_result_t<T>>, PatchCode>
|
||||
auto GetOrAddSharedPatchCode(T factoryFunction)
|
||||
// return type of the factory function converted from a pointer to a pointer to const
|
||||
-> std::add_pointer_t<std::add_const_t<std::remove_pointer_t<decltype(factoryFunction())>>>
|
||||
{
|
||||
u32 id = GetPatchCodeId<std::remove_pointer_t<decltype(factoryFunction())>>();
|
||||
auto& entry = GetOrAddSharedPatchCode(id);
|
||||
if (entry.type == 0)
|
||||
{
|
||||
entry.type = id; // claim this slot before calling the factory function
|
||||
entry.patchCode = factoryFunction();
|
||||
}
|
||||
|
||||
return static_cast<decltype(factoryFunction())>(entry.patchCode);
|
||||
}
|
||||
|
||||
/// @brief Copies all patch codes to their target location.
|
||||
void CopyAllToTarget() const;
|
||||
|
||||
private:
|
||||
struct PatchCodeEntry
|
||||
{
|
||||
u32 type;
|
||||
PatchCode* patchCode;
|
||||
};
|
||||
|
||||
std::array<PatchCodeEntry, 64> _patchCodeEntries;
|
||||
|
||||
void AddUniquePatchCode(PatchCode* patchCode);
|
||||
|
||||
PatchCodeEntry& GetOrAddSharedPatchCode(u32 id);
|
||||
|
||||
template <class T>
|
||||
static u32 GetPatchCodeId()
|
||||
{
|
||||
static const char typeId = 0;
|
||||
return (u32)&typeId;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user