diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp index 42c061ff..b7651765 100644 --- a/src/client/component/fastfiles.cpp +++ b/src/client/component/fastfiles.cpp @@ -526,6 +526,8 @@ namespace fastfiles namespace mp { + char* new_pools[game::XAssetType::ASSET_TYPE_COUNT]{nullptr}; + constexpr unsigned int get_asset_type_size(const game::XAssetType type) { constexpr int asset_type_sizes[] = @@ -571,15 +573,24 @@ namespace fastfiles char* reallocate_asset_pool() { constexpr auto element_size = get_asset_type_size(Type); - static char new_pool[element_size * Size] = {0}; + constexpr auto new_pool_size = element_size * Size; + char* new_pool = reinterpret_cast(utils::hook::allocate_somewhere_near( + reinterpret_cast(game::base_address), new_pool_size)); + + assert(new_pool != nullptr); + assert(utils::hook::is_relatively_far(game::g_assetPool[Type], new_pool) == false); + static_assert(element_size != 0); assert(element_size == game::DB_GetXAssetTypeSize(Type)); + std::memset(new_pool, 0, new_pool_size); std::memmove(new_pool, game::g_assetPool[Type], game::g_poolSize[Type] * element_size); game::g_assetPool[Type] = new_pool; game::g_poolSize[Type] = Size; + new_pools[Type] = new_pool; + return new_pool; } @@ -1050,6 +1061,18 @@ namespace fastfiles reallocate_asset_pool_multiplier(); reallocate_asset_pool_multiplier(); } + + void free_reallocated_asset_pools() + { + for (auto* pool : new_pools) + { + if (pool) + { + VirtualFree(pool, 0, MEM_RELEASE); + pool = nullptr; + } + } + } } void reallocate_asset_pools() @@ -1060,6 +1083,14 @@ namespace fastfiles } } + void free_reallocated_asset_pools() + { + if (!game::environment::is_sp()) + { + mp::free_reallocated_asset_pools(); + } + } + utils::hook::detour db_link_x_asset_entry_hook; game::XAssetEntry* db_link_x_asset_entry_stub(game::XAssetType type, game::XAssetHeader* header) { @@ -1317,6 +1348,11 @@ namespace fastfiles console::info("assets: %i / %i\n", count, 155000); }); } + + void pre_destroy() override + { + free_reallocated_asset_pools(); + } }; } diff --git a/src/common/utils/hook.cpp b/src/common/utils/hook.cpp index be05cb96..3c6c9df3 100644 --- a/src/common/utils/hook.cpp +++ b/src/common/utils/hook.cpp @@ -307,4 +307,31 @@ namespace utils::hook return extract(data + 1); } + + uint8_t* allocate_somewhere_near(const void* base_address, const size_t size) + { + size_t offset = 0; + while (true) + { + offset += size; + auto* target_address = static_cast(base_address) - offset; + if (utils::hook::is_relatively_far(base_address, target_address)) + { + return nullptr; + } + + const auto res = VirtualAlloc(const_cast(target_address), size, MEM_RESERVE | MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (res) + { + if (utils::hook::is_relatively_far(base_address, target_address)) + { + VirtualFree(res, 0, MEM_RELEASE); + return nullptr; + } + + return static_cast(res); + } + } + } } diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp index bb24f8ce..e7899d73 100644 --- a/src/common/utils/hook.hpp +++ b/src/common/utils/hook.hpp @@ -202,4 +202,6 @@ namespace utils::hook { return static_cast(func)(args...); } + + uint8_t* allocate_somewhere_near(const void* base_address, const size_t size); }