h2-mod/src/client/component/fastfiles.cpp

590 lines
20 KiB
C++
Raw Normal View History

2021-09-06 18:40:37 -04:00
#include <std_include.hpp>
2021-04-29 17:47:05 -04:00
#include "loader/component_loader.hpp"
#include "fastfiles.hpp"
#include "command.hpp"
2022-06-17 14:22:12 -04:00
#include "console.hpp"
2022-05-04 18:48:19 -04:00
#include "localized_strings.hpp"
2021-04-29 17:47:05 -04:00
#include <utils/hook.hpp>
#include <utils/concurrency.hpp>
2022-05-04 18:48:19 -04:00
#include <utils/string.hpp>
2021-04-29 17:47:05 -04:00
namespace fastfiles
{
static utils::concurrency::container<std::string> current_fastfile;
namespace
{
2022-10-07 14:49:53 -04:00
template <size_t Bits>
struct bit_array
{
char data[Bits / 8]{};
};
2021-04-29 17:47:05 -04:00
utils::hook::detour db_try_load_x_file_internal_hook;
2022-05-04 18:48:19 -04:00
utils::hook::detour db_find_xasset_header;
2021-04-29 17:47:05 -04:00
void db_try_load_x_file_internal(const char* zone_name, const int flags)
{
2022-06-17 14:22:12 -04:00
console::info("Loading fastfile %s\n", zone_name);
2021-04-29 17:47:05 -04:00
current_fastfile.access([&](std::string& fastfile)
{
fastfile = zone_name;
});
return db_try_load_x_file_internal_hook.invoke<void>(zone_name, flags);
}
2022-05-04 18:48:19 -04:00
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
{
const auto start = game::Sys_Milliseconds();
const auto result = db_find_xasset_header.invoke<game::XAssetHeader>(type, name, allow_create_default);
const auto diff = game::Sys_Milliseconds() - start;
if (diff > 100)
{
2022-06-17 14:22:12 -04:00
console::print(
2022-05-04 18:48:19 -04:00
result.data == nullptr
2022-06-17 14:22:12 -04:00
? console::con_type_error
: console::con_type_warning,
2022-05-04 18:48:19 -04:00
"Waited %i msec for %sasset \"%s\", of type \"%s\"\n",
diff,
result.data == nullptr
? "missing "
: "",
name,
game::g_assetNames[type]
);
}
return result;
}
void add_missing_localized_strings()
{
for (auto map = &game::maps[0]; map->unk; ++map)
{
const auto str = utils::string::va("LUA_MENU_SP_LOCATION_%s",
utils::string::to_upper(map->name).data());
localized_strings::override(str, str);
}
}
2022-08-16 21:05:45 -04:00
utils::hook::detour db_read_stream_file_hook;
void db_read_stream_file_stub(int a1, int a2)
{
// always use lz4 compressor type when reading stream files
*game::g_compressor = 4;
return db_read_stream_file_hook.invoke<void>(a1, a2);
}
void skip_extra_zones_stub(utils::hook::assembler& a)
{
const auto skip = a.newLabel();
const auto original = a.newLabel();
a.pushad64();
a.test(r15d, game::DB_ZONE_CUSTOM); // allocFlags
a.jnz(skip);
a.bind(original);
a.popad64();
a.mov(r8d, 9);
a.mov(rdx, 0x140933528);
a.jmp(0x140415E09);
a.bind(skip);
a.popad64();
a.mov(r14d, game::DB_ZONE_CUSTOM);
a.not_(r14d);
a.and_(r15d, r14d);
a.jmp(0x140415E29);
}
2022-08-21 19:42:13 -04:00
bool try_load_zone(std::string name, bool localized, bool game = false)
{
if (localized)
{
const auto language = game::SEH_GetCurrentLanguageCode();
2022-10-06 13:21:44 -04:00
try_load_zone(language + "_"s + name, false);
2022-08-21 19:42:13 -04:00
}
if (!fastfiles::exists(name))
{
return false;
}
game::XZoneInfo info{};
info.name = name.data();
info.allocFlags = (game ? game::DB_ZONE_GAME : game::DB_ZONE_COMMON) | game::DB_ZONE_CUSTOM;
info.freeFlags = 0;
game::DB_LoadXAssets(&info, 1u, game::DBSyncMode::DB_LOAD_ASYNC);
return true;
}
void load_post_gfx_and_ui_and_common_zones(game::XZoneInfo* zoneInfo,
unsigned int zoneCount, game::DBSyncMode syncMode)
{
// code_post_gfx_mp
// ui_mp
// common_mp
try_load_zone("h2_mod_ui", true);
try_load_zone("h2_mod_common", true);
game::DB_LoadXAssets(zoneInfo, zoneCount, syncMode);
try_load_zone("mod", true);
}
constexpr unsigned int get_asset_type_size(const game::XAssetType type)
{
constexpr int asset_type_sizes[] =
{
96, 88, 128, 56, 40, 216, 56, 696,
624, 32, 32, 32, 32, 32, 2112, 2032,
104, 32, 24, 1520, 152, 152, 16, 64,
640, 40, 16, 136, 24, 296, 176, 2896,
48, 0, 24, 200, 88, 16, 144, 3848,
56, 72, 16, 16, 0, 0, 0, 0, 24,
40, 24, 48, 40, 24, 16, 80, 128,
2280, 136, 32, 72, 24, 64, 88, 48,
32, 96, 120, 64, 32, 32
};
return asset_type_sizes[type];
}
constexpr unsigned int get_pool_type_size(const game::XAssetType type)
{
constexpr int asset_pool_sizes[] =
{
2022-08-22 20:49:56 -04:00
150, 1024, 16, 1, 128, 7000, 5248, 2560,
10624, 256, 49152, 12288, 12288, 72864,
512, 3072, 12000, 16000, 256, 64, 64,
64, 64, 10000, 1, 1, 1, 1, 1, 2, 1,
1, 32, 0, 128, 400, 0, 11500, 128,
360, 1, 2048, 4, 6, 0, 0, 0, 0, 1024,
768, 400, 128, 128, 24, 24, 24, 32,
128, 2, 0, 64, 384, 128, 1, 128, 64,
32, 32, 16, 32, 16
2022-08-21 19:42:13 -04:00
};
return asset_pool_sizes[type];
}
template <game::XAssetType Type, size_t Size>
char* reallocate_asset_pool()
{
constexpr auto element_size = get_asset_type_size(Type);
static char new_pool[element_size * Size] = {0};
static_assert(element_size != 0);
assert(element_size == game::DB_GetXAssetTypeSize(Type));
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;
return new_pool;
}
template <game::XAssetType Type, size_t Multiplier>
char* reallocate_asset_pool_multiplier()
{
constexpr auto pool_size = get_pool_type_size(Type);
return reallocate_asset_pool<Type, pool_size * Multiplier>();
}
2022-08-23 13:07:24 -04:00
#define RVA(ptr) static_cast<uint32_t>(reinterpret_cast<size_t>(ptr) - 0x140000000)
void reallocate_xmodel_pool()
{
// array used for DB_GetAllXAssetOfType, not big enough if many assets are added
2022-10-07 14:49:53 -04:00
static game::XAssetHeader assets[0x10000]{};
2022-08-23 13:07:24 -04:00
utils::hook::inject(0x1403E2AB7, &assets);
utils::hook::inject(0x1403E2AC3, &assets);
utils::hook::inject(0x1403E2ACF, &assets);
constexpr auto xmodel_pool_size = get_pool_type_size(game::ASSET_TYPE_XMODEL) * 2;
const auto xmodel_pool = reallocate_asset_pool<game::ASSET_TYPE_XMODEL, xmodel_pool_size>();
utils::hook::inject(0x140413D93, xmodel_pool + 8);
2022-10-07 14:49:53 -04:00
utils::hook::set(0x1403E30E0 + 3, xmodel_pool_size);
// not the actual struct
static struct
{
int array_1[xmodel_pool_size];
int array_2[xmodel_pool_size];
int array_3[xmodel_pool_size];
int array_4[xmodel_pool_size];
int array_5[xmodel_pool_size];
bit_array<xmodel_pool_size> bit_array_1;
bit_array<xmodel_pool_size> bit_array_2;
bit_array<xmodel_pool_size> bit_array_3;
int unk_array[xmodel_pool_size * 6];
} xmodel_data{};
// array 1
utils::hook::set<uint32_t>(0x14041E0C2 + 4, RVA(&xmodel_data.array_1));
utils::hook::inject(0x14041E7F6 + 3, &xmodel_data.array_1);
utils::hook::set<uint32_t>(0x140420797 + 4, RVA(&xmodel_data.array_1));
utils::hook::inject(0x1404228F6 + 3, &xmodel_data.array_1);
utils::hook::inject(0x14042290E + 3, &xmodel_data.array_1);
utils::hook::set<uint32_t>(0x140710280 + 4, RVA(&xmodel_data.array_1));
2022-08-23 13:07:24 -04:00
2022-10-07 14:49:53 -04:00
// array 2
utils::hook::set<uint32_t>(0x14041E2FA + 4, RVA(&xmodel_data.array_2));
utils::hook::set<uint32_t>(0x1404207BC + 4, RVA(&xmodel_data.array_2));
utils::hook::inject(0x140422AE1 + 3, &xmodel_data.array_2);
utils::hook::set<uint32_t>(0x140422B20 + 4, RVA(&xmodel_data.array_2));
utils::hook::inject(0x140422B8D + 3, &xmodel_data.array_2);
utils::hook::set<uint32_t>(0x140422BC7 + 4, RVA(&xmodel_data.array_2));
utils::hook::inject(0x140422C41 + 3, &xmodel_data.array_2);
utils::hook::set<uint32_t>(0x140422CE0 + 4, RVA(&xmodel_data.array_2));
utils::hook::set<uint32_t>(0x140422D16 + 4, RVA(&xmodel_data.array_2));
utils::hook::set<uint32_t>(0x140723BAE + 6, RVA(&xmodel_data.array_2));
utils::hook::set<uint32_t>(0x140723BCC + 6, RVA(&xmodel_data.array_2));
utils::hook::inject(0x140728332 + 3, &xmodel_data.array_2);
// array 3
utils::hook::set<uint32_t>(0x1404207D4 + 4, RVA(&xmodel_data.array_3));
utils::hook::set<uint32_t>(0x140724BA3 + 5, RVA(&xmodel_data.array_3));
utils::hook::set<uint32_t>(0x140724BC1 + 5, RVA(&xmodel_data.array_3));
// array 4
utils::hook::set<uint32_t>(0x1404207C8 + 4, RVA(&xmodel_data.array_4));
utils::hook::inject(0x140422888 + 3, &xmodel_data.array_4);
utils::hook::inject(0x14041EAC0 + 3, reinterpret_cast<void*>(reinterpret_cast<size_t>(&xmodel_data.array_4) + 0x10));
// array 5
utils::hook::set<uint32_t>(0x1404205BC + 4, RVA(&xmodel_data.array_5));
utils::hook::set<uint32_t>(0x14042062D + 4, RVA(&xmodel_data.array_5));
utils::hook::inject(0x140420A35 + 3, &xmodel_data.array_5);
// bit array 1
utils::hook::set<uint32_t>(0x1404207AA + 4, RVA(&xmodel_data.bit_array_1));
utils::hook::inject(0x1404208DE + 3, &xmodel_data.bit_array_1);
utils::hook::inject(0x140422535 + 2, &xmodel_data.bit_array_1);
// bit array 2
utils::hook::inject(0x1403E2A8E + 3, &xmodel_data.bit_array_2);
utils::hook::inject(0x1403E2FD9 + 3, &xmodel_data.bit_array_2);
utils::hook::inject(0x1403E37C5 + 3, &xmodel_data.bit_array_2);
// bit array 3
utils::hook::set<uint32_t>(0x1404207B4 + 4, RVA(&xmodel_data.bit_array_3));
utils::hook::inject(0x140422AD7 + 3, &xmodel_data.bit_array_3);
utils::hook::set<uint32_t>(0x140422B18 + 4, RVA(&xmodel_data.bit_array_3));
utils::hook::inject(0x140422B83 + 3, &xmodel_data.bit_array_3);
utils::hook::set<uint32_t>(0x140422BBF + 4, RVA(&xmodel_data.bit_array_3));
utils::hook::inject(0x140422C37 + 3, &xmodel_data.bit_array_3);
utils::hook::inject(0x140422C97 + 3, &xmodel_data.bit_array_3);
utils::hook::set<uint32_t>(0x140422CD8 + 4, RVA(&xmodel_data.bit_array_3));
utils::hook::set<uint32_t>(0x140422D0E + 4, RVA(&xmodel_data.bit_array_3));
// unk arrays
utils::hook::set<uint32_t>(0x1404205AF + 3, RVA(&xmodel_data.unk_array));
utils::hook::set<uint32_t>(0x140420752 + 4, RVA(&xmodel_data.unk_array));
utils::hook::set<uint32_t>(0x1404205A7 + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x14042065B + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x14042068D + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x1404206AF + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x1404206F0 + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x140420720 + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x14042075F + 4, RVA(&xmodel_data.unk_array) + 8);
utils::hook::set<uint32_t>(0x14041EE9B + 4, RVA(&xmodel_data.unk_array) + 0x10);
utils::hook::set<uint32_t>(0x1404205A0 + 3, RVA(&xmodel_data.unk_array) + 0x10);
utils::hook::set<uint32_t>(0x14042060D + 5, RVA(&xmodel_data.unk_array) + 0x10);
utils::hook::set<uint32_t>(0x140420618 + 3, RVA(&xmodel_data.unk_array) + 0x10);
// replace indirect refs
const auto xmodel_unk_ptr = 0x14417B980;
const auto replace_offset = [](const size_t ptr, const void* arr, const int64_t off = 0)
{
const auto offset = reinterpret_cast<int64_t>(arr) - xmodel_unk_ptr + off;
utils::hook::set<int32_t>(ptr, static_cast<int32_t>(offset));
};
// array 1 -> no refs
// 0xAEB80 -> array 2
replace_offset(0x14041E530 + 6, &xmodel_data.array_2);
replace_offset(0x14041E50D + 6, &xmodel_data.array_2);
replace_offset(0x140422F15 + 4, &xmodel_data.array_2);
replace_offset(0x1404CBE64 + 6, &xmodel_data.array_2);
replace_offset(0x1404CBE7B + 6, &xmodel_data.array_2);
replace_offset(0x140723075 + 5, &xmodel_data.array_2);
replace_offset(0x140723062 + 5, &xmodel_data.array_2);
replace_offset(0x1404225E2 + 6, &xmodel_data.array_2);
replace_offset(0x140422607 + 4, &xmodel_data.array_2);
// 0xA8380 -> array 3
replace_offset(0x1404225EC + 6, &xmodel_data.array_3);
replace_offset(0x140422613 + 4, &xmodel_data.array_3);
// array 4 -> no refs
// 0xA5B80 -> array 5
replace_offset(0x140420351 + 4, &xmodel_data.array_5);
replace_offset(0x140420359 + 6, &xmodel_data.array_5);
replace_offset(0x140420363 + 4, &xmodel_data.array_5);
replace_offset(0x14042036E + 6, &xmodel_data.array_5);
replace_offset(0x1404203F7 + 4, &xmodel_data.array_5);
replace_offset(0x1404203FF + 4, &xmodel_data.array_5);
// 0xA5A00 -> bit array 1
replace_offset(0x1404203A7 + 4, &xmodel_data.bit_array_2);
replace_offset(0x1404203BC + 4, &xmodel_data.bit_array_2);
replace_offset(0x140420880 + 3, &xmodel_data.bit_array_2);
replace_offset(0x14042258D + 4, &xmodel_data.bit_array_2);
// bit array 2 -> no refs
// 0xE1800 -> bit array 3
replace_offset(0x140422F0B + 4, &xmodel_data.bit_array_3);
replace_offset(0x140422659 + 4, &xmodel_data.bit_array_3);
replace_offset(0x140422669 + 4, &xmodel_data.bit_array_3);
// 0x96A00 -> unk_array + 0
replace_offset(0x140420301 + 5, &xmodel_data.unk_array);
replace_offset(0x14042030E + 5, &xmodel_data.unk_array);
replace_offset(0x140420321 + 5, &xmodel_data.unk_array);
replace_offset(0x14042033E + 5, &xmodel_data.unk_array);
replace_offset(0x1404203D1 + 5, &xmodel_data.unk_array);
replace_offset(0x1404203DA + 5, &xmodel_data.unk_array);
replace_offset(0x14042089C + 3, &xmodel_data.unk_array);
replace_offset(0x1404225C8 + 4, &xmodel_data.unk_array);
replace_offset(0x1403E309A + 4, &xmodel_data.unk_array);
// 0x96A08 -> unk_array + 8
replace_offset(0x1404208A3 + 4, &xmodel_data.unk_array, 8);
replace_offset(0x1403E30A6 + 4, &xmodel_data.unk_array, 8);
replace_offset(0x1404225D5 + 4, &xmodel_data.unk_array, 8);
// 0x96A10 -> unk_array + 0x10
replace_offset(0x140420317 + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x14042032A + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x140420334 + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x140420347 + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x1404203E3 + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x1404203ED + 6, &xmodel_data.unk_array, 0x10);
replace_offset(0x14042261F + 4, &xmodel_data.unk_array, 0x10);
replace_offset(0x140422649 + 6, &xmodel_data.unk_array, 0x10);
2022-08-23 13:07:24 -04:00
}
2022-08-21 19:42:13 -04:00
void reallocate_asset_pools()
{
2022-10-07 14:49:53 -04:00
reallocate_xmodel_pool();
reallocate_asset_pool_multiplier<game::ASSET_TYPE_XMODELSURFS, 2>();
2022-08-21 19:42:13 -04:00
reallocate_asset_pool_multiplier<game::ASSET_TYPE_WEAPON, 2>();
reallocate_asset_pool_multiplier<game::ASSET_TYPE_SOUND, 2>();
reallocate_asset_pool_multiplier<game::ASSET_TYPE_LOADED_SOUND, 2>();
2022-08-21 20:04:21 -04:00
reallocate_asset_pool_multiplier<game::ASSET_TYPE_XANIM, 2>();
2022-08-31 22:13:23 -04:00
reallocate_asset_pool_multiplier<game::ASSET_TYPE_LOCALIZE, 2>();
2022-08-21 19:42:13 -04:00
}
2022-10-06 13:21:44 -04:00
void add_custom_level_load_zone(game::LevelLoad* load, const char* name, const size_t size_est)
2022-08-21 19:42:13 -04:00
{
2022-10-06 13:21:44 -04:00
const auto language = game::SEH_GetCurrentLanguageCode();
const auto lang_name = language + "_"s + name;
2022-08-21 19:42:13 -04:00
2022-10-06 13:21:44 -04:00
if (fastfiles::exists(lang_name))
{
game::DB_LevelLoadAddZone(load, lang_name.data(), game::DB_ZONE_GAME | game::DB_ZONE_CUSTOM, size_est);
2022-08-21 19:42:13 -04:00
}
game::DB_LevelLoadAddZone(load, name, game::DB_ZONE_GAME | game::DB_ZONE_CUSTOM, size_est);
}
2022-10-06 13:21:44 -04:00
void db_load_level_add_custom_zone_stub(game::LevelLoad* load, const char* name, const unsigned int alloc_flags,
2022-08-21 19:42:13 -04:00
const size_t size_est)
{
2022-10-06 13:21:44 -04:00
add_custom_level_load_zone(load, name, size_est);
2022-08-21 19:42:13 -04:00
}
2022-10-06 13:21:44 -04:00
void db_load_level_add_map_zone_stub(game::LevelLoad* load, const char* name, const unsigned int alloc_flags,
2022-08-21 19:42:13 -04:00
const size_t size_est)
{
auto is_builtin_map = false;
for (auto map = &game::maps[0]; map->unk; ++map)
{
if (!std::strcmp(map->name, name))
{
is_builtin_map = true;
break;
}
}
if (is_builtin_map)
{
2022-08-22 10:50:22 -04:00
const auto name_ = "h2_mod_patch_"s + name;
if (fastfiles::exists(name_))
{
2022-10-06 13:21:44 -04:00
add_custom_level_load_zone(load, name_.data(), size_est);
2022-08-22 10:50:22 -04:00
}
2022-08-21 19:42:13 -04:00
game::DB_LevelLoadAddZone(load, name, alloc_flags, size_est);
}
else
{
2022-10-06 13:21:44 -04:00
add_custom_level_load_zone(load, name, size_est);
2022-08-21 19:42:13 -04:00
}
}
2022-10-06 13:21:44 -04:00
void db_load_xassets_stub(game::XZoneInfo* info, unsigned int zone_count, game::DBSyncMode sync_mode)
{
game::DB_LoadXAssets(info, zone_count, game::DB_LOAD_ASYNC);
}
2021-04-29 17:47:05 -04:00
}
2022-08-21 19:42:13 -04:00
bool exists(const std::string& zone)
{
const auto is_localized = game::DB_IsLocalized(zone.data());
const auto db_fs = game::DB_FSInitialize();
auto handle = db_fs->vftbl->OpenFile(db_fs,
(is_localized ? game::SF_ZONE_LOC : game::SF_ZONE), utils::string::va("%s.ff", zone.data()));
const auto _0 = gsl::finally([&]
{
if (handle != nullptr)
{
db_fs->vftbl->Close(db_fs, handle);
}
});
return handle != nullptr;
}
2022-08-21 20:04:21 -04:00
2022-01-02 17:51:38 -05:00
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool includeOverride)
{
game::DB_EnumXAssets_Internal(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
{
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
cb(header);
}), &callback, includeOverride);
}
2021-04-29 17:47:05 -04:00
std::string get_current_fastfile()
{
std::string fastfile_copy;
2022-05-04 18:48:19 -04:00
return current_fastfile.access<std::string>([&](std::string& fastfile)
2021-04-29 17:47:05 -04:00
{
2022-05-04 18:48:19 -04:00
return fastfile;
2021-04-29 17:47:05 -04:00
});
}
class component final : public component_interface
{
public:
void post_unpack() override
{
2022-05-04 18:48:19 -04:00
db_try_load_x_file_internal_hook.create(0x1404173B0, db_try_load_x_file_internal);
db_find_xasset_header.create(game::DB_FindXAssetHeader, db_find_xasset_header_stub);
add_missing_localized_strings();
2021-04-29 17:47:05 -04:00
2022-08-16 21:05:45 -04:00
// Allow loading of mixed compressor types
utils::hook::nop(0x1403E66A7, 2);
// Fix compressor type on streamed file load
db_read_stream_file_hook.create(0x14041D710, db_read_stream_file_stub);
// Don't load extra zones with loadzone
utils::hook::nop(0x140415DFC, 13);
utils::hook::jump(0x140415DFC, utils::hook::assemble(skip_extra_zones_stub), true);
2022-08-21 19:42:13 -04:00
// load our custom ui and common zones
utils::hook::call(0x14074E22A, load_post_gfx_and_ui_and_common_zones);
reallocate_asset_pools();
// only load extra zones with addon maps & common_specialops & common_survival & custom maps if the exist
utils::hook::call(0x1404128B0, db_load_level_add_map_zone_stub);
utils::hook::call(0x140412854, db_load_level_add_custom_zone_stub);
utils::hook::call(0x14041282D, db_load_level_add_custom_zone_stub);
utils::hook::call(0x14041287C, db_load_level_add_custom_zone_stub);
2022-10-06 13:21:44 -04:00
// Load assets from 2nd phase (common_specialops, addon map) with DB_LOAD_SYNC
utils::hook::call(0x140414EA1, db_load_xassets_stub);
2021-04-29 17:47:05 -04:00
command::add("loadzone", [](const command::params& params)
{
if (params.size() < 2)
{
2022-06-17 14:22:12 -04:00
console::info("usage: loadzone <zone>\n");
2021-04-29 17:47:05 -04:00
return;
}
2022-08-16 21:05:45 -04:00
const auto name = params.get(1);
2022-08-21 19:42:13 -04:00
if (!try_load_zone(name, false))
2022-08-16 21:05:45 -04:00
{
console::warn("loadzone: zone \"%s\" could not be found!\n", name);
}
2021-04-29 17:47:05 -04:00
});
command::add("g_poolSizes", []()
{
for (auto i = 0; i < game::ASSET_TYPE_COUNT; i++)
{
2022-06-17 14:29:53 -04:00
console::info("g_poolSize[%i]: %i // %s\n", i, game::g_poolSize[i], game::g_assetNames[i]);
2021-04-29 17:47:05 -04:00
}
});
2022-08-21 20:16:57 -04:00
command::add("poolUsages", []()
{
for (auto i = 0; i < game::ASSET_TYPE_COUNT; i++)
{
auto count = 0;
enum_assets(static_cast<game::XAssetType>(i), [&](game::XAssetHeader header)
{
count++;
}, true);
console::info("%i %s: %i / %i\n", i, game::g_assetNames[i], count, game::g_poolSize[i]);
}
});
command::add("poolUsage", [](const command::params& params)
{
if (params.size() < 2)
{
console::info("Usage: poolUsage <type>\n");
return;
}
const auto type = static_cast<game::XAssetType>(std::atoi(params.get(1)));
auto count = 0;
enum_assets(type, [&](game::XAssetHeader header)
{
count++;
}, true);
console::info("%i %s: %i / %i\n", type, game::g_assetNames[type], count, game::g_poolSize[type]);
});
2022-08-22 20:49:56 -04:00
command::add("assetCount", [](const command::params& params)
{
auto count = 0;
for (auto i = 0; i < game::ASSET_TYPE_COUNT; i++)
{
enum_assets(static_cast<game::XAssetType>(i), [&](game::XAssetHeader header)
{
count++;
}, true);
}
console::info("assets: %i / %i\n", count, 155000);
});
2021-04-29 17:47:05 -04:00
}
};
}
REGISTER_COMPONENT(fastfiles::component)