Skip to content

Commit

Permalink
Merge pull request #137 from iw4x/louve/menus_rewrite
Browse files Browse the repository at this point in the history
Rewrite menu code to track memory usage, prevent crashes and fix leaks
  • Loading branch information
Rackover authored Sep 19, 2024
2 parents c8474f5 + 102d059 commit 541c671
Show file tree
Hide file tree
Showing 19 changed files with 1,181 additions and 477 deletions.
4 changes: 2 additions & 2 deletions src/Components/Modules/AssetInterfaces/IMenuList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Assets
Utils::Memory::Allocator* allocator = builder->getAllocator();

// actually gets the whole list
auto menus = Components::Menus::LoadMenu(name);
auto menus = Components::Menus::LoadMenuByName_Recursive(name);
if (menus.empty()) return;

// Allocate new menu list
Expand All @@ -28,7 +28,7 @@ namespace Assets
// Copy new menus
for (unsigned int i = 0; i < menus.size(); ++i)
{
newList->menus[i] = menus[i].second;
newList->menus[i] = menus[i];
}

header->menuList = newList;
Expand Down
4 changes: 2 additions & 2 deletions src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace Assets
void ImenuDef_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
{
// load from disk
auto menus = Components::Menus::LoadMenu(std::format("ui_mp/{}.menu", name));
auto menus = Components::Menus::LoadMenuByName_Recursive(std::format("ui_mp/{}.menu", name));

if (menus.empty()) return;
if (menus.size() > 1) Components::Logger::Print("Menu '{}' on disk has more than one menudef in it. Only saving the first one\n", name);

header->menu = menus[0].second;
header->menu = menus[0];
}


Expand Down
4 changes: 2 additions & 2 deletions src/Components/Modules/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ namespace Components

bool Console::isCommand;

const char** Console::GetAutoCompleteFileList(const char* path, const char* extension, Game::FsListBehavior_e behavior, int* numfiles, int allocTrackType)
const char** Console::GetAutoCompleteFileList(const char* path, const char* extension, Game::FsListBehavior_e behavior, int* numfiles, [[maybe_unused]] int allocTrackType)
{
if (path == reinterpret_cast<char*>(0xBAADF00D) || path == reinterpret_cast<char*>(0xCDCDCDCD) || ::Utils::Memory::IsBadReadPtr(path)) return nullptr;
return Game::FS_ListFiles(path, extension, behavior, numfiles, allocTrackType);
return Game::FS_ListFiles(path, extension, behavior, numfiles);
}

void Console::RefreshStatus()
Expand Down
48 changes: 48 additions & 0 deletions src/Components/Modules/Events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Components
Utils::Concurrency::Container<Events::Callback> Events::ServerInitTasks_;
Utils::Concurrency::Container<Events::Callback> Events::DvarInitTasks_;
Utils::Concurrency::Container<Events::Callback> Events::NetworkInitTasks_;
Utils::Concurrency::Container<Events::Callback> Events::CGameInitTasks_;
Utils::Concurrency::Container<Events::Callback> Events::UIInitTasks_;

Events::ClientCmdCallback Events::ClientCmdButtonsTasks_;
Events::ClientCmdCallback Events::ClientKeyMoveTasks_;
Expand Down Expand Up @@ -55,6 +57,14 @@ namespace Components
});
}

void Events::AfterUIInit(const std::function<void()>& callback)
{
UIInitTasks_.access([&callback](Callback& tasks)
{
tasks.emplace_back(callback);
});
}

void Events::OnClientCmdButtons(const std::function<void(Game::usercmd_s*)>& callback)
{
ClientCmdButtonsTasks_.emplace_back(callback);
Expand Down Expand Up @@ -89,6 +99,14 @@ namespace Components
});
}

void Events::OnCGameInit(const std::function<void()>& callback)
{
CGameInitTasks_.access([&callback](Callback& tasks)
{
tasks.emplace_back(callback);
});
}

/*
* Should be called when a client drops from the server
* but not "between levels" (Quake-III-Arena)
Expand Down Expand Up @@ -244,6 +262,19 @@ namespace Components
Utils::Hook::Call<void()>(0x60AD10)(); // Com_InitDvars
}

int Events::CL_InitCGame_Hk()
{
CGameInitTasks_.access([](Callback& tasks)
{
for (const auto& func : tasks)
{
func();
}
});

return Game::Sys_Milliseconds();
}

void Events::NetworkStart()
{
NetworkInitTasks_.access([](Callback& tasks)
Expand All @@ -257,6 +288,19 @@ namespace Components
});
}

void Events::UI_Init_Hk(int localClientNum)
{
Utils::Hook::Call<void(int)>(0x4A57D0)(localClientNum); // CAll UI_INIT

UIInitTasks_.access([](Callback& tasks)
{
for (const auto& func : tasks)
{
func();
}
});
}

__declspec(naked) void Events::NET_OpenSocks_Hk()
{
__asm
Expand Down Expand Up @@ -284,10 +328,14 @@ namespace Components

Utils::Hook(0x5A6D8B, CL_KeyMove_Stub, HOOK_CALL).install()->quick();

Utils::Hook(0x4236A5, CL_InitCGame_Hk, HOOK_CALL).install()->quick(); // CL_InitCGame

Utils::Hook(0x60BB3A, Com_InitDvars_Hk, HOOK_CALL).install()->quick(); // Com_Init_Try_Block_Function

Utils::Hook(0x4D3665, SV_Init_Hk, HOOK_CALL).install()->quick(); // SV_Init

Utils::Hook(0x4FD4D4, NET_OpenSocks_Hk, HOOK_JUMP).install()->quick(); // NET_OpenIP

Utils::Hook(0x4B5422, UI_Init_Hk, HOOK_CALL).install()->quick();
}
}
11 changes: 10 additions & 1 deletion src/Components/Modules/Events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ namespace Components

static void OnClientInit(const std::function<void()>& callback);

static void AfterUIInit(const std::function<void()>& callback);

static void OnClientCmdButtons(const std::function<void(Game::usercmd_s*)>& callback);

static void OnClientKeyMove(const std::function<void(Game::usercmd_s*)>& callback);
Expand All @@ -37,6 +39,9 @@ namespace Components

// Client & Server (triggered once)
static void OnNetworkInit(const std::function<void()>& callback);

// Client & Server (triggered every FS/Vidrestart)
static void OnCGameInit(const std::function<void()>& callback);

private:
static Utils::Concurrency::Container<ClientCallback> ClientDisconnectTasks_;
Expand All @@ -47,6 +52,8 @@ namespace Components
static Utils::Concurrency::Container<Callback> ServerInitTasks_;
static Utils::Concurrency::Container<Callback> DvarInitTasks_;
static Utils::Concurrency::Container<Callback> NetworkInitTasks_;
static Utils::Concurrency::Container<Callback> CGameInitTasks_;
static Utils::Concurrency::Container<Callback> UIInitTasks_;

// For speed this one does not use concurrency container. Be careful
static ClientCmdCallback ClientCmdButtonsTasks_;
Expand All @@ -62,11 +69,13 @@ namespace Components
static void CL_CmdButtons_Stub();
static void CL_KeyMove(Game::usercmd_s* cmd);
static void CL_KeyMove_Stub();

static void SV_Init_Hk();
static void Com_InitDvars_Hk();

static void NetworkStart();
static void UI_Init_Hk(int localClientNum);
static void NET_OpenSocks_Hk();

static int CL_InitCGame_Hk();
};
}
33 changes: 27 additions & 6 deletions src/Components/Modules/FileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Components
{
// patch max file amount returned by Sys_ListFiles
constexpr auto FILE_COUNT_MULTIPLIER = 8;
constexpr auto NEW_MAX_FILES_LISTED = 8191 * FILE_COUNT_MULTIPLIER;

std::mutex FileSystem::Mutex;
std::recursive_mutex FileSystem::FSMutex;
Utils::Memory::Allocator FileSystem::MemAllocator;
Expand Down Expand Up @@ -156,12 +160,12 @@ namespace Components
return std::filesystem::path(path) / "iw4x";
}

std::vector<std::string> FileSystem::GetFileList(const std::string& path, const std::string& extension)
std::vector<std::string> FileSystem::GetFileList(const std::string& path, const std::string& extension, Game::FsListBehavior_e behaviour)
{
std::vector<std::string> fileList;

auto numFiles = 0;
const auto** files = Game::FS_ListFiles(path.data(), extension.data(), Game::FS_LIST_PURE_ONLY, &numFiles, 10);
const auto** files = Game::FS_ListFiles(path.data(), extension.data(), behaviour, &numFiles);

if (files)
{
Expand Down Expand Up @@ -369,6 +373,12 @@ namespace Components
return Sys_DefaultInstallPath_Hk();
}

Game::HunkUser* Hunk_UserCreate_Stub(int maxSize, const char* name, bool fixed, int type)
{
maxSize *= FILE_COUNT_MULTIPLIER;
return Utils::Hook::Call<Game::HunkUser*(int, const char*, bool, int)>(0x430E90)(maxSize, name, fixed, type);
}

FileSystem::FileSystem()
{
// Thread safe file system interaction
Expand Down Expand Up @@ -431,11 +441,22 @@ namespace Components
Utils::Hook(0x643232, Sys_HomePath_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x6431B6, Sys_Cwd_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x51C29A, Sys_Cwd_Hk, HOOK_CALL).install()->quick();

// patch max file amount returned by Sys_ListFiles
Utils::Hook::Set<std::uint32_t>(0x45A66B, (NEW_MAX_FILES_LISTED + FILE_COUNT_MULTIPLIER) * 4);
Utils::Hook::Set<std::uint32_t>(0x64AF78, NEW_MAX_FILES_LISTED);
Utils::Hook::Set<std::uint32_t>(0x64B04F, NEW_MAX_FILES_LISTED);
Utils::Hook::Set<std::uint32_t>(0x45A8CE, NEW_MAX_FILES_LISTED);

// Sys_ListFiles
Utils::Hook(0x45A806, Hunk_UserCreate_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x45A6A0, Hunk_UserCreate_Stub, HOOK_CALL).install()->quick();

// FS_ListFilteredFiles
Utils::Hook(0x4FCE82, Hunk_UserCreate_Stub, HOOK_CALL).install()->quick();
Utils::Hook::Set<std::uint32_t>(0x6427F0 + 2, NEW_MAX_FILES_LISTED);
Utils::Hook::Set<uint32_t>(0X4FCE8B + 1, (NEW_MAX_FILES_LISTED + FILE_COUNT_MULTIPLIER) * 4 + 4);

#if DEBUG
// fs_debug 1
Utils::Hook::Set<bool>(0x64315B + 1, true);
#endif
}

FileSystem::~FileSystem()
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Modules/FileSystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace Components
~FileSystem();

static std::filesystem::path GetAppdataPath();
static std::vector<std::string> GetFileList(const std::string& path, const std::string& extension);
static std::vector<std::string> GetFileList(const std::string& path, const std::string& extension, Game::FsListBehavior_e behaviour = Game::FsListBehavior_e::FS_LIST_PURE_ONLY);
static std::vector<std::string> GetSysFileList(const std::string& path, const std::string& extension, bool folders = false);
static bool _DeleteFile(const std::string& folder, const std::string& file);

Expand Down
2 changes: 1 addition & 1 deletion src/Components/Modules/GSC/Script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace Components::GSC
strncat_s(searchPath, "/", _TRUNCATE);

auto numFiles = 0;
const auto** files = Game::FS_ListFiles(searchPath, "gsc", Game::FS_LIST_ALL, &numFiles, 10);
const auto** files = Game::FS_ListFiles(searchPath, "gsc", Game::FS_LIST_ALL, &numFiles);

for (auto i = 0; i < numFiles; ++i)
{
Expand Down
Loading

0 comments on commit 541c671

Please sign in to comment.