1.04 -> 1.15

This commit is contained in:
Skull Merlin 2022-05-17 17:56:26 +03:00
parent 8f02b94b03
commit 31d18eb618
61 changed files with 516 additions and 293 deletions

View File

@ -303,7 +303,7 @@ targetname "h1-mod"
pchheader "std_include.hpp" pchheader "std_include.hpp"
pchsource "src/client/std_include.cpp" pchsource "src/client/std_include.cpp"
linkoptions {"/IGNORE:4254", "/DYNAMICBASE:NO", "/SAFESEH:NO", "/LARGEADDRESSAWARE", "/LAST:.main", "/PDBCompress"} linkoptions {"/IGNORE:4254", "/SAFESEH:NO", "/LARGEADDRESSAWARE", "/PDBCompress"}
files {"./src/client/**.rc", "./src/client/**.hpp", "./src/client/**.cpp", "./src/client/resources/**.*"} files {"./src/client/**.rc", "./src/client/**.hpp", "./src/client/**.cpp", "./src/client/resources/**.*"}

View File

@ -0,0 +1,163 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include <utils/hook.hpp>
namespace arxan
{
namespace
{
DWORD get_steam_pid()
{
static DWORD pid = 0; //234567;//GetCurrentProcessId();
if (pid) return pid;
HKEY hRegKey;
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_QUERY_VALUE,
&hRegKey) != ERROR_SUCCESS)
return pid;
DWORD dwLength = sizeof(pid);
RegQueryValueExA(hRegKey, "pid", nullptr, nullptr, reinterpret_cast<BYTE*>(&pid), &dwLength);
RegCloseKey(hRegKey);
return pid;
}
utils::hook::detour nt_close_hook;
utils::hook::detour nt_query_information_process_hook;
NTSTATUS WINAPI nt_query_information_process_stub(const HANDLE handle, const PROCESSINFOCLASS info_class,
const PVOID info,
const ULONG info_length, const PULONG ret_length)
{
auto* orig = static_cast<decltype(NtQueryInformationProcess)*>(nt_query_information_process_hook.
get_original());
const auto status = orig(handle, info_class, info, info_length, ret_length);
if (NT_SUCCESS(status))
{
if (info_class == ProcessBasicInformation)
{
static DWORD explorer_pid = 0;
if (!explorer_pid)
{
auto* const shell_window = GetShellWindow();
GetWindowThreadProcessId(shell_window, &explorer_pid);
}
static_cast<PPROCESS_BASIC_INFORMATION>(info)->Reserved3 = PVOID(DWORD64(get_steam_pid()));
}
else if (info_class == 30) // ProcessDebugObjectHandle
{
*static_cast<HANDLE*>(info) = nullptr;
return 0xC0000353;
}
else if (info_class == 7) // ProcessDebugPort
{
*static_cast<HANDLE*>(info) = nullptr;
}
else if (info_class == 31)
{
*static_cast<ULONG*>(info) = 1;
}
//https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
}
return status;
}
NTSTATUS NTAPI nt_close_stub(const HANDLE handle)
{
char info[16];
if (NtQueryObject(handle, OBJECT_INFORMATION_CLASS(4), &info, 2, nullptr) >= 0 && size_t(handle) != 0x12345)
{
auto* orig = static_cast<decltype(NtClose)*>(nt_close_hook.get_original());
return orig(handle);
}
return STATUS_INVALID_HANDLE;
}
LONG WINAPI exception_filter(const LPEXCEPTION_POINTERS info)
{
if (info->ExceptionRecord->ExceptionCode == STATUS_INVALID_HANDLE)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void hide_being_debugged()
{
auto* const peb = PPEB(__readgsqword(0x60));
peb->BeingDebugged = false;
*reinterpret_cast<PDWORD>(LPSTR(peb) + 0xBC) &= ~0x70;
}
void remove_hardware_breakpoints()
{
CONTEXT context;
ZeroMemory(&context, sizeof(context));
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
auto* const thread = GetCurrentThread();
GetThreadContext(thread, &context);
context.Dr0 = 0;
context.Dr1 = 0;
context.Dr2 = 0;
context.Dr3 = 0;
context.Dr6 = 0;
context.Dr7 = 0;
SetThreadContext(thread, &context);
}
BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context)
{
return SetThreadContext(thread, context);
}
}
class component final : public component_interface
{
public:
void* load_import(const std::string& library, const std::string& function) override
{
if (function == "SetThreadContext")
{
//return set_thread_context_stub;
}
return nullptr;
}
void post_load() override
{
hide_being_debugged();
scheduler::loop(hide_being_debugged, scheduler::pipeline::async);
const utils::nt::library ntdll("ntdll.dll");
nt_close_hook.create(ntdll.get_proc<void*>("NtClose"), nt_close_stub);
nt_query_information_process_hook.create(ntdll.get_proc<void*>("NtQueryInformationProcess"),
nt_query_information_process_stub);
// https://www.geoffchappell.com/studies/windows/win32/ntdll/api/index.htm
AddVectoredExceptionHandler(1, exception_filter);
}
void post_unpack() override
{
// cba to implement sp, not sure if it's even needed
if (game::environment::is_sp()) return;
}
};
}
REGISTER_COMPONENT(arxan::component)

View File

@ -218,19 +218,19 @@ namespace auth
} }
else else
{ {
utils::hook::jump(0x140571E07, 0x140571E5A); // H1(1.4) utils::hook::jump(0x1D6193_b, 0x1D61FA_b); // 1.15
utils::hook::jump(0x14004B223, 0x14004B4F2); // H1(1.4) utils::hook::jump(0x60153_b, 0x60426_b); // 1.15
utils::hook::jump(0x14004B4AD, 0x14004B4F2); // H1(1.4) utils::hook::jump(0x603E1_b, 0x60426_b); // 1.15
utils::hook::jump(0x140572F6F, 0x140572FB0); // H1(1.4) utils::hook::jump(0x1D7542_b, 0x1D7587_b); // 1.15, MAYBE `1D7553` ON FIRST
utils::hook::jump(0x140573470, 0x1405734B6); // H1(1.4) utils::hook::jump(0x1D7A82_b, 0x1D7AC8_b); // 1.15
utils::hook::jump(0x140488BC1, get_direct_connect_stub(), true); // H1(1.4) //utils::hook::jump(0x140488BC1, get_direct_connect_stub(), true); // H1(1.4) couldn't find
utils::hook::call(0x140250ED2, send_connect_data_stub); // H1(1.4) utils::hook::call(0x12D437_b, send_connect_data_stub); // 1.15
// Skip checks for sending connect packet // Skip checks for sending connect packet
utils::hook::jump(0x1402508FC, 0x140250946); utils::hook::jump(0x12CDFC_b, 0x12CE5C_b); // 1.15
// Don't instantly timeout the connecting client ? not sure about this // Don't instantly timeout the connecting client ? not sure about this
utils::hook::set(0x14025136B, 0xC3); //utils::hook::set(0x14025136B, 0xC3); // gonna lookup for this soon
} }
command::add("guid", []() command::add("guid", []()
@ -241,4 +241,4 @@ namespace auth
}; };
} }
REGISTER_COMPONENT(auth::component) //REGISTER_COMPONENT(auth::component)

View File

@ -135,4 +135,4 @@ namespace binding
}; };
} }
REGISTER_COMPONENT(binding::component) //REGISTER_COMPONENT(binding::component)

View File

@ -106,4 +106,4 @@ namespace bots
}; };
} }
REGISTER_COMPONENT(bots::component) //REGISTER_COMPONENT(bots::component)

View File

@ -34,7 +34,6 @@ namespace branding
public: public:
void post_unpack() override void post_unpack() override
{ {
if (game::environment::is_dedi()) if (game::environment::is_dedi())
{ {
return; return;
@ -42,24 +41,26 @@ namespace branding
if (game::environment::is_mp()) if (game::environment::is_mp())
{ {
localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER\n"); //localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER\n");
localized_strings::override("MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER"); //localized_strings::override("MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER");
} }
dvars::override::set_string("version", utils::string::va("H1-Mod %s", VERSION)); //dvars::override::set_string("version", utils::string::va("H1-Mod %s", VERSION));
ui_get_formatted_build_number_hook.create( ui_get_formatted_build_number_hook.create(
SELECT_VALUE(0x1403B1C40, 0x1404E74C0), ui_get_formatted_build_number_stub); SELECT_VALUE(0x0, 0x1DF300_b), ui_get_formatted_build_number_stub);
scheduler::loop([]() scheduler::loop([]()
{ {
const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20); const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20);
if (font)
{
game::R_AddCmdDrawText("H1-Mod: " VERSION, 0x7FFFFFFF, font, 10.f, game::R_AddCmdDrawText("H1-Mod: " VERSION, 0x7FFFFFFF, font, 10.f,
5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0); 5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0);
}
}, scheduler::pipeline::renderer); }, scheduler::pipeline::renderer);
} }
}; };
} }
REGISTER_COMPONENT(branding::component) //REGISTER_COMPONENT(branding::component)

View File

@ -49,4 +49,4 @@ namespace chat
}; };
} }
REGISTER_COMPONENT(chat::component) //REGISTER_COMPONENT(chat::component)

View File

@ -179,4 +179,4 @@ namespace colors
}; };
} }
REGISTER_COMPONENT(colors::component) //REGISTER_COMPONENT(colors::component)

View File

@ -818,4 +818,4 @@ namespace command
}; };
} }
REGISTER_COMPONENT(command::component) //REGISTER_COMPONENT(command::component)

View File

@ -296,4 +296,4 @@ namespace console
} }
} }
REGISTER_COMPONENT(console::component) //REGISTER_COMPONENT(console::component)

View File

@ -330,4 +330,4 @@ namespace dedicated
}; };
} }
REGISTER_COMPONENT(dedicated::component) //REGISTER_COMPONENT(dedicated::component)

View File

@ -62,4 +62,4 @@ namespace dedicated_info
}; };
} }
REGISTER_COMPONENT(dedicated_info::component) //REGISTER_COMPONENT(dedicated_info::component)

View File

@ -596,4 +596,4 @@ namespace demonware
}; };
} }
REGISTER_COMPONENT(demonware::component) //REGISTER_COMPONENT(demonware::component)

View File

@ -285,4 +285,4 @@ namespace discord
}; };
} }
REGISTER_COMPONENT(discord::component) //REGISTER_COMPONENT(discord::component)

View File

@ -198,4 +198,4 @@ namespace dvar_cheats
}; };
} }
REGISTER_COMPONENT(dvar_cheats::component) //REGISTER_COMPONENT(dvar_cheats::component)

View File

@ -440,4 +440,4 @@ namespace dvars
}; };
} }
REGISTER_COMPONENT(dvars::component) //REGISTER_COMPONENT(dvars::component)

View File

@ -258,4 +258,4 @@ namespace exception
}; };
} }
REGISTER_COMPONENT(exception::component) //REGISTER_COMPONENT(exception::component)

View File

@ -56,4 +56,4 @@ namespace fastfiles
}; };
} }
REGISTER_COMPONENT(fastfiles::component) //REGISTER_COMPONENT(fastfiles::component)

View File

@ -130,4 +130,4 @@ namespace filesystem
}; };
} }
REGISTER_COMPONENT(filesystem::component) //REGISTER_COMPONENT(filesystem::component)

View File

@ -133,4 +133,4 @@ namespace fonts
}; };
} }
REGISTER_COMPONENT(fonts::component) //REGISTER_COMPONENT(fonts::component)

View File

@ -179,4 +179,4 @@ namespace fps
}; };
} }
REGISTER_COMPONENT(fps::component) //REGISTER_COMPONENT(fps::component)

View File

@ -797,4 +797,4 @@ namespace game_console
}; };
} }
REGISTER_COMPONENT(game_console::component) //REGISTER_COMPONENT(game_console::component)

View File

@ -3,6 +3,7 @@
#include "game_module.hpp" #include "game_module.hpp"
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <game/game.hpp>
namespace game_module namespace game_module
{ {
@ -90,7 +91,7 @@ namespace game_module
utils::nt::library get_game_module() utils::nt::library get_game_module()
{ {
static utils::nt::library game{HMODULE(0x140000000)}; static utils::nt::library game{HMODULE(game::base_address)};
return game; return game;
} }
@ -110,7 +111,11 @@ namespace game_module
void post_load() override void post_load() override
{ {
#ifdef INJECT_HOST_AS_LIB
hook_module_resolving(); hook_module_resolving();
#else
assert(get_host_module() == get_game_module());
#endif
} }
}; };
} }

View File

@ -227,4 +227,4 @@ namespace gameplay
}; };
} }
REGISTER_COMPONENT(gameplay::component) //REGISTER_COMPONENT(gameplay::component)

View File

@ -72,4 +72,4 @@ namespace input
}; };
} }
REGISTER_COMPONENT(input::component) //REGISTER_COMPONENT(input::component)

View File

@ -44,9 +44,9 @@ namespace localized_strings
void post_unpack() override void post_unpack() override
{ {
// Change some localized strings // Change some localized strings
seh_string_ed_get_string_hook.create(SELECT_VALUE(0x1403924A0, 0x1404BB2A0), &seh_string_ed_get_string); seh_string_ed_get_string_hook.create(SELECT_VALUE(0x0, 0x585DA0_b), &seh_string_ed_get_string); // 1.15
} }
}; };
} }
REGISTER_COMPONENT(localized_strings::component) //REGISTER_COMPONENT(localized_strings::component)

View File

@ -314,4 +314,4 @@ namespace logfile
}; };
} }
REGISTER_COMPONENT(logfile::component) //REGISTER_COMPONENT(logfile::component)

View File

@ -177,4 +177,4 @@ namespace logger
}; };
} }
REGISTER_COMPONENT(logger::component) //REGISTER_COMPONENT(logger::component)

View File

@ -55,4 +55,4 @@ namespace lui
}; };
} }
REGISTER_COMPONENT(lui::component) //REGISTER_COMPONENT(lui::component)

View File

@ -177,4 +177,4 @@ namespace map_rotation
}; };
} }
REGISTER_COMPONENT(map_rotation::component) //REGISTER_COMPONENT(map_rotation::component)

View File

@ -209,4 +209,4 @@ namespace materials
}; };
} }
REGISTER_COMPONENT(materials::component) //REGISTER_COMPONENT(materials::component)

View File

@ -116,4 +116,4 @@ namespace mods
}; };
} }
REGISTER_COMPONENT(mods::component) //REGISTER_COMPONENT(mods::component)

View File

@ -323,4 +323,4 @@ namespace network
}; };
} }
REGISTER_COMPONENT(network::component) //REGISTER_COMPONENT(network::component)

View File

@ -642,4 +642,4 @@ namespace party
}; };
} }
REGISTER_COMPONENT(party::component) //REGISTER_COMPONENT(party::component)

View File

@ -283,4 +283,4 @@ namespace patches
}; };
} }
REGISTER_COMPONENT(patches::component) //REGISTER_COMPONENT(patches::component)

View File

@ -44,4 +44,4 @@ namespace ranked
}; };
} }
REGISTER_COMPONENT(ranked::component) //REGISTER_COMPONENT(ranked::component)

View File

@ -80,4 +80,4 @@ namespace redirect
}; };
} }
REGISTER_COMPONENT(redirect::component) //REGISTER_COMPONENT(redirect::component)

View File

@ -82,4 +82,4 @@ namespace renderer
}; };
} }
REGISTER_COMPONENT(renderer::component) //REGISTER_COMPONENT(renderer::component)

View File

@ -75,7 +75,8 @@ namespace scheduler
{ {
new_callbacks_.access([&](task_list& new_tasks) new_callbacks_.access([&](task_list& new_tasks)
{ {
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()), std::move_iterator<task_list::iterator>(new_tasks.end())); tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()),
std::move_iterator<task_list::iterator>(new_tasks.end()));
new_tasks = {}; new_tasks = {};
}); });
}); });
@ -88,7 +89,7 @@ namespace scheduler
utils::hook::detour r_end_frame_hook; utils::hook::detour r_end_frame_hook;
utils::hook::detour g_run_frame_hook; utils::hook::detour g_run_frame_hook;
utils::hook::detour main_frame_hook; utils::hook::detour main_frame_hook;
utils::hook::detour hks_frame_hook; //utils::hook::detour hks_frame_hook; //no scripting for now
void execute(const pipeline type) void execute(const pipeline type)
{ {
@ -99,7 +100,7 @@ namespace scheduler
void r_end_frame_stub() void r_end_frame_stub()
{ {
execute(pipeline::renderer); execute(pipeline::renderer);
r_end_frame_hook.invoke<void>(); //r_end_frame_hook.invoke<void>();
} }
void server_frame_stub() void server_frame_stub()
@ -190,10 +191,23 @@ namespace scheduler
void post_unpack() override void post_unpack() override
{ {
r_end_frame_hook.create(SELECT_VALUE(0x1404F7310, 0x1405FE470), scheduler::r_end_frame_stub); utils::hook::jump(SELECT_VALUE(0, 0x6A6300_b), utils::hook::assemble([](utils::hook::assembler& a)
g_run_frame_hook.create(SELECT_VALUE(0x1402772D0, 0x14033A640), scheduler::server_frame_stub); {
main_frame_hook.create(SELECT_VALUE(0x1401CE8D0, 0x1400D8310), scheduler::main_frame_stub); a.pushad64();
hks_frame_hook.create(SELECT_VALUE(0x1400E37F0, 0x1401755B0), scheduler::hks_frame_stub); a.call_aligned(r_end_frame_stub);
a.popad64();
a.sub(rsp, 0x28);
a.call(0x6A5C20_b);
a.mov(rax, 0xEAB4308_b);
a.mov(rax, qword_ptr(rax));
a.jmp(0x6A6310_b);
}), true);
//r_end_frame_hook.create(SELECT_VALUE(0x0, 0x6A6300_b), scheduler::r_end_frame_stub);
//g_run_frame_hook.create(SELECT_VALUE(0x0, 0x417940_b), scheduler::server_frame_stub);
//main_frame_hook.create(SELECT_VALUE(0x0, 0x0), scheduler::main_frame_stub);
//hks_frame_hook.create(SELECT_VALUE(0x0, 0x0), scheduler::hks_frame_stub); // no scripting for now
} }
void pre_destroy() override void pre_destroy() override
@ -207,4 +221,4 @@ namespace scheduler
}; };
} }
REGISTER_COMPONENT(scheduler::component) //REGISTER_COMPONENT(scheduler::component)

View File

@ -216,4 +216,4 @@ namespace scripting
}; };
} }
REGISTER_COMPONENT(scripting::component) //REGISTER_COMPONENT(scripting::component)

View File

@ -423,4 +423,4 @@ namespace server_list
}; };
} }
REGISTER_COMPONENT(server_list::component) //REGISTER_COMPONENT(server_list::component)

View File

@ -48,4 +48,4 @@ namespace shaders
}; };
} }
REGISTER_COMPONENT(shaders::component) //REGISTER_COMPONENT(shaders::component)

View File

@ -50,4 +50,4 @@ namespace slowmotion
}; };
} }
REGISTER_COMPONENT(slowmotion::component) //REGISTER_COMPONENT(slowmotion::component)

View File

@ -138,4 +138,4 @@ namespace splash
}; };
} }
REGISTER_COMPONENT(splash::component) //REGISTER_COMPONENT(splash::component)

View File

@ -88,4 +88,4 @@ namespace stats
}; };
} }
REGISTER_COMPONENT(stats::component) //REGISTER_COMPONENT(stats::component)

View File

@ -185,4 +185,4 @@ namespace steam_proxy
} }
} }
REGISTER_COMPONENT(steam_proxy::component) //REGISTER_COMPONENT(steam_proxy::component)

View File

@ -51,13 +51,13 @@ namespace system_check
{ {
static std::unordered_map<std::string, std::string> mp_zone_hashes = static std::unordered_map<std::string, std::string> mp_zone_hashes =
{ {
{"patch_common_mp.ff", "3F44B0CFB0B8E0FBD9687C2942204AB7F11E66E6E15C73B8B4A5EB5920115A31"}, {"patch_common_mp.ff", "E45EF5F29D12A5A47F405F89FBBEE479C0A90D02141ABF852D481689514134A1"},
}; };
static std::unordered_map<std::string, std::string> sp_zone_hashes = static std::unordered_map<std::string, std::string> sp_zone_hashes =
{ {
// Steam doesn't necessarily deliver this file :( // Steam doesn't necessarily deliver this file :(
{"patch_common.ff", "BB0617DD94AF2F511571E7184BBEDE76E64D97E5D0DAFDB457F00717F035EBF0"}, {"patch_common.ff", "1D32A9770F90ED022AA76F4859B4AB178E194A703383E61AC2CE83B1E828B18F"},
}; };
@ -85,7 +85,7 @@ namespace system_check
public: public:
void post_load() override void post_load() override
{ {
verify_binary_version(); //verify_binary_version();
if (!is_valid()) if (!is_valid())
{ {
@ -97,4 +97,4 @@ namespace system_check
}; };
} }
REGISTER_COMPONENT(system_check::component) //REGISTER_COMPONENT(system_check::component)

View File

@ -57,4 +57,4 @@ namespace thread_names
}; };
} }
REGISTER_COMPONENT(thread_names::component) //REGISTER_COMPONENT(thread_names::component)

View File

@ -206,4 +206,4 @@ namespace ui_scripting
}; };
} }
REGISTER_COMPONENT(ui_scripting::component) //REGISTER_COMPONENT(ui_scripting::component)

View File

@ -468,4 +468,4 @@ namespace updater
}; };
} }
REGISTER_COMPONENT(updater::component) //REGISTER_COMPONENT(updater::component)

View File

@ -52,4 +52,4 @@ namespace videos
}; };
} }
REGISTER_COMPONENT(videos::component) //REGISTER_COMPONENT(videos::component)

View File

@ -61,4 +61,4 @@ namespace virtuallobby
}; };
} }
REGISTER_COMPONENT(virtuallobby::component) //REGISTER_COMPONENT(virtuallobby::component)

View File

@ -3,6 +3,14 @@
namespace game namespace game
{ {
uint64_t base_address;
void load_base_address()
{
const auto module = GetModuleHandle(NULL);
base_address = uint64_t(module);
}
int Cmd_Argc() int Cmd_Argc()
{ {
return cmd_args->argc[cmd_args->nesting]; return cmd_args->argc[cmd_args->nesting];
@ -102,3 +110,8 @@ namespace game
} }
} }
} }
uintptr_t operator"" _b(const uintptr_t ptr)
{
return game::base_address + ptr;
}

View File

@ -5,10 +5,13 @@
#define SELECT_VALUE(sp, mp) (game::environment::is_sp() ? (sp) : (mp)) #define SELECT_VALUE(sp, mp) (game::environment::is_sp() ? (sp) : (mp))
#define SERVER_CD_KEY "S1X-CD-Key" #define SERVER_CD_KEY "H1MOD-CD-Key"
namespace game namespace game
{ {
extern uint64_t base_address;
void load_base_address();
namespace environment namespace environment
{ {
launcher::mode get_mode(); launcher::mode get_mode();
@ -67,4 +70,6 @@ namespace game
bool VirtualLobby_Loaded(); bool VirtualLobby_Loaded();
} }
uintptr_t operator"" _b(const uintptr_t ptr);
#include "symbols.hpp" #include "symbols.hpp"

View File

@ -8,119 +8,119 @@ namespace game
* Functions * Functions
**************************************************************/ **************************************************************/
WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x14036E600, 0x14043C580}; WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x0, 0x0};
WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x1403700F0, 0x14043E090}; WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x0, 0x0};
WEAK symbol<void(unsigned int id)> AddRefToObject{0x14036E5F0, 0x14043C570}; WEAK symbol<void(unsigned int id)> AddRefToObject{0x0, 0x0};
WEAK symbol<void(unsigned int id)> RemoveRefToObject{0x14036FFE0, 0x14043DF80}; WEAK symbol<void(unsigned int id)> RemoveRefToObject{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x14036E960, 0x14043C8E0}; WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x0, 0x0};
WEAK symbol<ObjectVariableValue*(unsigned int* id)> AllocVariable{0x14036E9C0, 0x14043C940}; WEAK symbol<ObjectVariableValue*(unsigned int* id)> AllocVariable{0x0, 0x0};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x140342EB0, 0x1404033B0}; WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x0, 0x1CF480}; // 1.15
WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer, WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer,
void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0x140342FC0, 0x1404034C0}; void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0x0, 0x0};
WEAK symbol<void(const char* message)> Conbuf_AppendText{0x1403E3300, 0x140513FF0}; WEAK symbol<void(const char* message)> Conbuf_AppendText{0x0, 0x0};
WEAK symbol<char*(int start)> ConcatArgs{0x1402697F0, 0x140335D70}; WEAK symbol<char*(int start)> ConcatArgs{0x0, 0x0};
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x140343980, 0x140403F60}; WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x0, 0x0};
WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{0x1403433E0, 0x140403950}; WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{0x0, 0x0};
WEAK symbol<void(const char*)> Cmd_RemoveCommand{0x140343FF0, 0x1404045D0}; WEAK symbol<void(const char*)> Cmd_RemoveCommand{0x0, 0x0};
WEAK symbol<void(const char* text_in)> Cmd_TokenizeString{0x140344110, 0x1404046F0}; WEAK symbol<void(const char* text_in)> Cmd_TokenizeString{0x0, 0x0};
WEAK symbol<void()> Cmd_EndTokenizeString{0x140343630, 0x140403C20}; WEAK symbol<void()> Cmd_EndTokenizeString{0x0, 0x0};
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0, 0x14009D0F0}; WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0x0, 0x0};
WEAK symbol<void(unsigned int weapon, bool isAlternate, WEAK symbol<void(unsigned int weapon, bool isAlternate,
char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0x140430550, 0x1401F9670}; char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0x0, 0x0};
WEAK symbol<void()> Com_Frame_Try_Block_Function{0x1401CE8D0, 0x1400D8310}; WEAK symbol<void()> Com_Frame_Try_Block_Function{0x0, 0x0};
WEAK symbol<CodPlayMode()> Com_GetCurrentCoDPlayMode{0, 0x1405039A0}; WEAK symbol<CodPlayMode()> Com_GetCurrentCoDPlayMode{0x0, 0x0};
WEAK symbol<bool()> Com_InFrontend{0x1400E4B30, 0x140176A30}; WEAK symbol<bool()> Com_InFrontend{0x0, 0x0};
WEAK symbol<void(float, float, int)> Com_SetSlowMotion{0, 0x1400DB790}; WEAK symbol<void(float, float, int)> Com_SetSlowMotion{0x0, 0x0};
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{0x1403509C0, 0x1400D78A0}; WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{0x0, 0x0};
WEAK symbol<void()> Com_Quit_f{0x140352BE0, 0x1400DA830}; WEAK symbol<void()> Com_Quit_f{0x0, 0x0};
WEAK symbol<void(char const* finalMessage)> Com_Shutdown{0x140353B70, 0x1400DB8A0}; WEAK symbol<void(char const* finalMessage)> Com_Shutdown{0x0, 0x0};
WEAK symbol<void()> Quit{0x140352D90, 0x1400DA830}; WEAK symbol<void()> Quit{0x0, 0x0};
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x1401389A0, 0x140220CC0}; WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x0, 0x0};
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessageBold{0x140138750, 0x140220620}; WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessageBold{0x0, 0x0};
WEAK symbol<void(int localClientNum, /*mp::cg_s**/void* cg, WEAK symbol<void(int localClientNum, /*mp::cg_s**/void* cg,
const char* dvar, const char* value)> CG_SetClientDvarFromServer{0, 0x140236120}; const char* dvar, const char* value)> CG_SetClientDvarFromServer{0x0, 0x0};
WEAK symbol<char*(const unsigned int weapon, WEAK symbol<char*(const unsigned int weapon,
bool isAlternate, char* outputBuffer, int bufferLen)> CG_GetWeaponDisplayName{0x14016EC30, 0x1400B5840}; bool isAlternate, char* outputBuffer, int bufferLen)> CG_GetWeaponDisplayName{0x0, 0x0};
WEAK symbol<bool()> CL_IsCgameInitialized{0x14017EE30, 0x140245650}; WEAK symbol<bool()> CL_IsCgameInitialized{0x0, 0x0};
WEAK symbol<void(int a1)> CL_VirtualLobbyShutdown{0, 0x140256D40}; WEAK symbol<void(int a1)> CL_VirtualLobbyShutdown{0x0, 0x0};
WEAK symbol<void(int hash, const char* name, const char* buffer)> Dvar_SetCommand{0x1403C72B0, 0x1404FD0A0}; WEAK symbol<void(int hash, const char* name, const char* buffer)> Dvar_SetCommand{0x0, 0x0};
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x1403C5D50, 0x1404FBB00}; WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x0, 0x0};
WEAK symbol<void(const dvar_t* dvar)> Dvar_ClearModified{0x1403C5C20, 0x1404FB930}; WEAK symbol<void(const dvar_t* dvar)> Dvar_ClearModified{0x0, 0x0};
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{0x140354DF0, 0x14041D830}; WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{0x0, 0x0};
WEAK symbol<const char*(dvar_t* dvar, dvar_value value)> Dvar_ValueToString{0x1403C8560, 0x1404FE660}; WEAK symbol<const char*(dvar_t* dvar, dvar_value value)> Dvar_ValueToString{0x0, 0x0};
WEAK symbol<void(dvar_t* dvar, DvarSetSource source)> Dvar_Reset{0, 0x1404FCC40}; WEAK symbol<void(dvar_t* dvar, DvarSetSource source)> Dvar_Reset{0x0, 0x0};
WEAK symbol<void(const char*, const char*, WEAK symbol<void(const char*, const char*,
DvarSetSource)> Dvar_SetFromStringByNameFromSource{0, 0x1404FD490}; DvarSetSource)> Dvar_SetFromStringByNameFromSource{0x0, 0x0};
WEAK symbol<dvar_t*(int hash, const char* name, bool value, WEAK symbol<dvar_t*(int hash, const char* name, bool value,
unsigned int flags)> Dvar_RegisterBool{0x1403C47E0, 0x1404FA540}; unsigned int flags)> Dvar_RegisterBool{0x0, 0x0};
WEAK symbol<dvar_t*(int hash, const char* name, int value, int min, int max, WEAK symbol<dvar_t*(int hash, const char* name, int value, int min, int max,
unsigned int flags)> Dvar_RegisterInt{0x1403C4CC0, 0x1404FAA20}; unsigned int flags)> Dvar_RegisterInt{0x0, 0x0};
WEAK symbol<dvar_t*(int hash, const char* dvarName, float value, float min, WEAK symbol<dvar_t*(int hash, const char* dvarName, float value, float min,
float max, unsigned int flags)> Dvar_RegisterFloat{0x1403C4BB0, 0x1404FA910}; float max, unsigned int flags)> Dvar_RegisterFloat{0x0, 0x0};
WEAK symbol<dvar_t*(int hash, const char* dvarName, const char* value, WEAK symbol<dvar_t*(int hash, const char* dvarName, const char* value,
unsigned int flags)> Dvar_RegisterString{0x1403C4DA0, 0x1404FAB00}; unsigned int flags)> Dvar_RegisterString{0x0, 0x0};
WEAK symbol<dvar_t*(int dvarName, const char* a2, float x, float y, float z, WEAK symbol<dvar_t*(int dvarName, const char* a2, float x, float y, float z,
float w, float min, float max, unsigned int flags)> Dvar_RegisterVec4{0x1403C5220, 0x1404FAF40}; float w, float min, float max, unsigned int flags)> Dvar_RegisterVec4{0x0, 0x0};
WEAK symbol<long long(const char* qpath, char** buffer)> FS_ReadFile{0x1403B9020, 0x1404EE720}; WEAK symbol<long long(const char* qpath, char** buffer)> FS_ReadFile{0x0, 0x0};
WEAK symbol<void(void* buffer)> FS_FreeFile{0x1403B9010, 0x1404EE710}; WEAK symbol<void(void* buffer)> FS_FreeFile{0x0, 0x0};
WEAK symbol<void(const char* gameName)> FS_Startup{0x1403B85D0, 0x1404EDD30}; WEAK symbol<void(const char* gameName)> FS_Startup{0x0, 0x0};
WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x1403B6030, 0x1404EBE20}; WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x14036FDD0, 0x14043DD70}; WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewVariable{0x14036FA00, 0x14043D990}; WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewVariable{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewArrayVariable{0x14036F880, 0x14043D810}; WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewArrayVariable{0x0, 0x0};
WEAK symbol<void()> GScr_LoadConsts{0x1402D13E0, 0x140393810}; WEAK symbol<void()> GScr_LoadConsts{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x14036F4B0, 0x14043D430}; WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x0, 0x0};
WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x14036F3B0, 0x14043D330}; WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x0, 0x0};
WEAK symbol<void(unsigned int parentId, unsigned int index)> RemoveVariableValue{0x140370190, 0x14043E130}; WEAK symbol<void(unsigned int parentId, unsigned int index)> RemoveVariableValue{0x0, 0x0};
WEAK symbol<void(VariableValue* result, unsigned int classnum, WEAK symbol<void(VariableValue* result, unsigned int classnum,
int entnum, int offset)> GetEntityFieldValue{0x140373780, 0x140441780}; int entnum, int offset)> GetEntityFieldValue{0x0, 0x0};
WEAK symbol<int(const char* fname)> generateHashValue{0x1400FE8A0, 0x1401B1010}; WEAK symbol<int(const char* fname)> generateHashValue{0x0, 0x0};
WEAK symbol<void()> G_Glass_Update{0x14026C570, 0x14033A640}; WEAK symbol<void()> G_Glass_Update{0x0, 0x0};
WEAK symbol<int(int clientNum)> G_GetClientScore{0, 0x140342F90}; WEAK symbol<int(int clientNum)> G_GetClientScore{0x0, 0x0};
WEAK symbol<unsigned int(const char* name)> G_GetWeaponForName{0x1402C2A90, 0x14038C300}; WEAK symbol<unsigned int(const char* name)> G_GetWeaponForName{0x0, 0x0};
WEAK symbol<int(playerState_s* ps, unsigned int weapon, int dualWield, WEAK symbol<int(playerState_s* ps, unsigned int weapon, int dualWield,
int startInAltMode, int, int, int, char, ...)> G_GivePlayerWeapon{0x1402C2DF0, 0x14038C750}; int startInAltMode, int, int, int, char, ...)> G_GivePlayerWeapon{0x0, 0x0};
WEAK symbol<void(playerState_s* ps, unsigned int weapon, int hadWeapon)> G_InitializeAmmo{0x140270980, 0x14033EDD0}; WEAK symbol<void(playerState_s* ps, unsigned int weapon, int hadWeapon)> G_InitializeAmmo{0x0, 0x0};
WEAK symbol<void(int clientNum, unsigned int weapon)> G_SelectWeapon{0x1402C3750, 0x14038D1B0}; WEAK symbol<void(int clientNum, unsigned int weapon)> G_SelectWeapon{0x0, 0x0};
WEAK symbol<int(playerState_s* ps, unsigned int weapon)> G_TakePlayerWeapon{0x1402C3900, 0x14038D370}; WEAK symbol<int(playerState_s* ps, unsigned int weapon)> G_TakePlayerWeapon{0x0, 0x0};
WEAK symbol<char*(char* string)> I_CleanStr{0x1403CD230, 0x140503D00}; WEAK symbol<char*(char* string)> I_CleanStr{0x0, 0x0};
WEAK symbol<const char* (int, int, int)> Key_KeynumToString{0x140187CC0, 0x14024FE10}; WEAK symbol<const char* (int, int, int)> Key_KeynumToString{0x0, 0x0};
WEAK symbol<unsigned int(int)> Live_SyncOnlineDataFlags{0, 0x14059A700}; WEAK symbol<unsigned int(int)> Live_SyncOnlineDataFlags{0x0, 0x0};
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{0x1404E48B0, 0x1405EAB30}; WEAK symbol<Material* (const char* material)> Material_RegisterHandle{0x0, 0x0};
WEAK symbol<void(netadr_s*, sockaddr*)> NetadrToSockadr{0x1403C11C0, 0x1404F62F0}; WEAK symbol<void(netadr_s*, sockaddr*)> NetadrToSockadr{0x0, 0x0};
WEAK symbol<void(netsrc_t, netadr_s*, const char*)> NET_OutOfBandPrint{0x140357560, 0x1404255D0}; WEAK symbol<void(netsrc_t, netadr_s*, const char*)> NET_OutOfBandPrint{0x0, 0x0};
WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{0, 0x140425790}; WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{0x0, 0x0};
WEAK symbol<bool(const char* s, netadr_s* a)> NET_StringToAdr{0, 0x140425870}; WEAK symbol<bool(const char* s, netadr_s* a)> NET_StringToAdr{0x0, 0x0};
WEAK symbol<void(float x, float y, float width, float height, float s0, float t0, float s1, float t1, WEAK symbol<void(float x, float y, float width, float height, float s0, float t0, float s1, float t1,
float* color, Material* material)> R_AddCmdDrawStretchPic{0x14017E5C0, 0x1402443A0}; float* color, Material* material)> R_AddCmdDrawStretchPic{0x0, 0x0};
WEAK symbol<Font_s* (const char* font, int size)> R_RegisterFont{0x1404D4100, 0x1405D91E0}; WEAK symbol<Font_s* (const char* font, int size)> R_RegisterFont{0x0, 0x67F630}; // 1.15
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x1404D43B0, 0x1405D94A0}; WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x0, 0x0};
WEAK symbol<int(void* font)> R_GetFontHeight{0x1405EA360, 0x1405D92C0}; WEAK symbol<int(void* font)> R_GetFontHeight{0x0, 0x67F710}; // 1.15
WEAK symbol<void* (int a1)> R_DrawSomething{0x1404D37B0, 0x1405D8890}; WEAK symbol<void* (int a1)> R_DrawSomething{0x0, 0x67ECE0}; // 1.15
WEAK symbol<void()> R_SyncRenderThread{0x1404F8240, 0x1405FF3A0}; WEAK symbol<void()> R_SyncRenderThread{0x0, 0x0};
WEAK symbol<void* (const char* text, int maxChars, void* font, int fontHeight, float x, WEAK symbol<void* (const char* text, int maxChars, void* font, int fontHeight, float x,
float y, float xScale, float yScale, float rotation, float* color, float y, float xScale, float yScale, float rotation, float* color,
int style, int cursor_pos, char cursor_char, int style, int cursor_pos, char cursor_char,
void* style_unk)> H1_AddBaseDrawTextCmd{0x1404F3DC0, 0x1405FB1F0}; void* style_unk)> H1_AddBaseDrawTextCmd{0x0, 0x6A3080}; // 1.15
#define R_AddCmdDrawText(TXT, MC, F, X, Y, XS, YS, R, C, S) \ #define R_AddCmdDrawText(TXT, MC, F, X, Y, XS, YS, R, C, S) \
H1_AddBaseDrawTextCmd(TXT, MC, F, game::R_GetFontHeight(F), X, Y, XS, YS, R, C, S,-1, 0, game::R_DrawSomething(S)) H1_AddBaseDrawTextCmd(TXT, MC, F, game::R_GetFontHeight(F), X, Y, XS, YS, R, C, S,-1, 0, game::R_DrawSomething(S))
@ -128,157 +128,155 @@ namespace game
H1_AddBaseDrawTextCmd(TXT, MC, F, game::R_GetFontHeight(F), X, Y, XS, YS, R, C, S, CP, CC, game::R_DrawSomething(S)) H1_AddBaseDrawTextCmd(TXT, MC, F, game::R_GetFontHeight(F), X, Y, XS, YS, R, C, S, CP, CC, game::R_DrawSomething(S))
WEAK symbol<char* (GfxImage* image, uint32_t width, uint32_t height, uint32_t depth, uint32_t mipCount, WEAK symbol<char* (GfxImage* image, uint32_t width, uint32_t height, uint32_t depth, uint32_t mipCount,
uint32_t imageFlags, DXGI_FORMAT imageFormat, const char* name, const D3D11_SUBRESOURCE_DATA* initData)> Image_Setup{0x1404D7D50, 0x1405DCF90}; uint32_t imageFlags, DXGI_FORMAT imageFormat, const char* name, const D3D11_SUBRESOURCE_DATA* initData)> Image_Setup{0x0, 0x0};
WEAK symbol<unsigned int(unsigned int localId, const char* pos, WEAK symbol<unsigned int(unsigned int localId, const char* pos,
unsigned int paramcount)> VM_Execute{0x140376360, 0x140444350}; unsigned int paramcount)> VM_Execute{0x0, 0x0};
WEAK symbol<void(unsigned int id, scr_string_t stringValue, WEAK symbol<void(unsigned int id, scr_string_t stringValue,
unsigned int paramcount)> Scr_NotifyId{0x140375800, 0x1404437E0}; unsigned int paramcount)> Scr_NotifyId{0x0, 0x0};
WEAK symbol<const float*(const float* v)> Scr_AllocVector{0x140370930, 0x14043E7D0}; WEAK symbol<const float*(const float* v)> Scr_AllocVector{0x0, 0x0};
WEAK symbol<float(int index)> Scr_GetFloat{0x140374D20, 0x140442D10}; WEAK symbol<float(int index)> Scr_GetFloat{0x0, 0x0};
WEAK symbol<const char*(int index)> Scr_GetString{0x140375210, 0x140443150}; WEAK symbol<const char*(int index)> Scr_GetString{0x0, 0x0};
WEAK symbol<int()> Scr_GetNumParam{0x140374F30, 0x140442E70}; WEAK symbol<int()> Scr_GetNumParam{0x0, 0x0};
WEAK symbol<void()> Scr_ClearOutParams{0x140374460, 0x140442510}; WEAK symbol<void()> Scr_ClearOutParams{0x0, 0x0};
WEAK symbol<scr_entref_t(unsigned int entId)> Scr_GetEntityIdRef{0x140372D50, 0x140440D80}; WEAK symbol<scr_entref_t(unsigned int entId)> Scr_GetEntityIdRef{0x0, 0x0};
WEAK symbol<unsigned int(int classnum, unsigned int entnum)> Scr_GetEntityId{0x140372CA0, 0x140440CD0}; WEAK symbol<unsigned int(int classnum, unsigned int entnum)> Scr_GetEntityId{0x0, 0x0};
WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{0x1402B9F60, 0x140385330}; WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{0x0, 0x0};
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{0x1401981F0, 0x140288550}; WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{0x0, 0x0};
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)> WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)>
DB_EnumXAssets_Internal{0x1401C9C10, 0x1402BA830}; DB_EnumXAssets_Internal{0x0, 0x0};
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x14019A390, 0x14028BE50}; WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x0, 0x0};
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x14019A3B0, 0x14028BE70}; WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x0, 0x0};
WEAK symbol<XAssetHeader(XAssetType type, const char* name, WEAK symbol<XAssetHeader(XAssetType type, const char* name,
int createDefault)> DB_FindXAssetHeader{0x1401CA150, 0x1402BAC70}; int createDefault)> DB_FindXAssetHeader{0x0, 0x0};
WEAK symbol<void(int clientNum, const char* menu, WEAK symbol<void(int clientNum, const char* menu,
int a3, int a4, unsigned int a5)> LUI_OpenMenu{0x14039D5F0, 0x1404CD210}; int a3, int a4, unsigned int a5)> LUI_OpenMenu{0x0, 0x0};
WEAK symbol<bool(int clientNum, const char* name, hks::lua_State* s)> LUI_BeginEvent{0x1400D27F0, 0x140161A00}; WEAK symbol<bool(int clientNum, const char* name, hks::lua_State* s)> LUI_BeginEvent{0x0, 0x0};
WEAK symbol<void(hks::lua_State* s)> LUI_EndEvent{0x1400D3A80, 0x140162CD0}; WEAK symbol<void(hks::lua_State* s)> LUI_EndEvent{0x0, 0x0};
WEAK symbol<void()> LUI_EnterCriticalSection{0x1400D3B70, 0x140162DC0}; WEAK symbol<void()> LUI_EnterCriticalSection{0x0, 0x0};
WEAK symbol<void()> LUI_LeaveCriticalSection{0x1400D8DB0, 0x140168150}; WEAK symbol<void()> LUI_LeaveCriticalSection{0x0, 0x0};
WEAK symbol<bool(int clientNum, const char* menu)> Menu_IsMenuOpenAndVisible{0x1404709C0, 0x1404C7320}; WEAK symbol<bool(int clientNum, const char* menu)> Menu_IsMenuOpenAndVisible{0x0, 0x0};
WEAK symbol<scr_string_t(const char* str)> SL_FindString{0x14036D700, 0x14043B470}; WEAK symbol<scr_string_t(const char* str)> SL_FindString{0x0, 0x0};
WEAK symbol<scr_string_t(const char* str, unsigned int user)> SL_GetString{0x14036D9A0, 0x14043B840}; WEAK symbol<scr_string_t(const char* str, unsigned int user)> SL_GetString{0x0, 0x0};
WEAK symbol<const char*(scr_string_t stringValue)> SL_ConvertToString{0x14036D420, 0x14043B170}; WEAK symbol<const char*(scr_string_t stringValue)> SL_ConvertToString{0x0, 0x0};
WEAK symbol<unsigned int(const char* str)> SL_GetCanonicalString{0x14036A310, 0x140437EA0}; WEAK symbol<unsigned int(const char* str)> SL_GetCanonicalString{0x0, 0x0};
WEAK symbol<void(netadr_s* from)> SV_DirectConnect{0, 0x140480860}; WEAK symbol<void(netadr_s* from)> SV_DirectConnect{0x0, 0x0};
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x1403446C0, 0x140404CA0}; WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x0, 0x0};
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x140344740, 0x140404D20}; WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x0, 0x0};
WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x140344700, 0x140404CE0}; WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x0, 0x0};
WEAK symbol<mp::gentity_s*(const char* name)> SV_AddBot{0, 0x140480190}; WEAK symbol<mp::gentity_s*(const char* name)> SV_AddBot{0x0, 0x0};
WEAK symbol<bool(int clientNum)> SV_BotIsBot{0, 0x14046E6C0}; WEAK symbol<bool(int clientNum)> SV_BotIsBot{0x0, 0x0};
WEAK symbol<const char* ()> SV_BotGetRandomName{0, 0x14046DBA0}; WEAK symbol<const char* ()> SV_BotGetRandomName{0x0, 0x0};
WEAK symbol<int(mp::gentity_s* ent)> SV_SpawnTestClient{0, 0x1404832A0}; WEAK symbol<int(mp::gentity_s* ent)> SV_SpawnTestClient{0x0, 0x0};
WEAK symbol<const char* (int clientNum)> SV_GetGuid{0, 0x140484B90}; WEAK symbol<const char* (int clientNum)> SV_GetGuid{0x0, 0x0};
WEAK symbol<int(int clientNum)> SV_GetClientPing{0, 0x140484B70}; WEAK symbol<int(int clientNum)> SV_GetClientPing{0x0, 0x0};
WEAK symbol<playerState_s* (int num)> SV_GetPlayerstateForClientNum{0x1404426D0, 0x140484C10}; WEAK symbol<playerState_s* (int num)> SV_GetPlayerstateForClientNum{0x0, 0x0};
WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0, 0x140486720}; WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0x0, 0x0};
WEAK symbol<bool()> SV_Loaded{0x140442F60, 0x1404864A0}; WEAK symbol<bool()> SV_Loaded{0x0, 0x0};
WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{0, 0x14047ED00}; WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{0x0, 0x0};
WEAK symbol<bool(const char* map)> SV_MapExists{0, 0x14047ED60}; WEAK symbol<bool(const char* map)> SV_MapExists{0x0, 0x0};
WEAK symbol<void(mp::client_t*, const char*, int)> SV_ExecuteClientCommand{0, 0x140481870}; WEAK symbol<void(mp::client_t*, const char*, int)> SV_ExecuteClientCommand{0x0, 0x0};
WEAK symbol<void(int localClientNum)> SV_FastRestart{0, 0x14047E990}; WEAK symbol<void(int localClientNum)> SV_FastRestart{0x0, 0x0};
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{ WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{0x0, 0x0};
0x1403F3A70, 0x140484AD0
};
WEAK symbol<void()> Sys_ShowConsole{0x1403E3B90, 0x140514910}; WEAK symbol<void()> Sys_ShowConsole{0x0, 0x0};
WEAK symbol<void(const char* error, ...)> Sys_Error{0x1403E0C40, 0x140511520}; WEAK symbol<void(const char* error, ...)> Sys_Error{0x0, 0x0};
WEAK symbol<void(char* path, int pathSize, Sys_Folder folder, const char* filename, const char* ext)> WEAK symbol<void(char* path, int pathSize, Sys_Folder folder, const char* filename, const char* ext)>
Sys_BuildAbsPath{0x1403CFF90, 0x140507010}; Sys_BuildAbsPath{0x0, 0x0};
WEAK symbol<int()> Sys_Milliseconds{0x1403E2B10, 0x140513710}; WEAK symbol<int()> Sys_Milliseconds{0x0, 0x0};
WEAK symbol<bool()> Sys_IsDatabaseReady2{0x1403580B0, 0x14042B090}; WEAK symbol<bool()> Sys_IsDatabaseReady2{0x0, 0x0};
WEAK symbol<bool(int, void const*, const netadr_s*)> Sys_SendPacket{0x1403E2820, 0x1405133B0}; WEAK symbol<bool(int, void const*, const netadr_s*)> Sys_SendPacket{0x0, 0x0};
WEAK symbol<bool(const char* path)> Sys_FileExists{0x1403E0CE0, 0x1405115E0}; WEAK symbol<bool(const char* path)> Sys_FileExists{0x0, 0x0};
WEAK symbol<const char* (const char*)> UI_GetMapDisplayName{0, 0x140408CC0}; WEAK symbol<const char* (const char*)> UI_GetMapDisplayName{0x0, 0x0};
WEAK symbol<const char* (const char*)> UI_GetGameTypeDisplayName{0, 0x1404086A0}; WEAK symbol<const char* (const char*)> UI_GetGameTypeDisplayName{0x0, 0x0};
WEAK symbol<void(unsigned int localClientNum, const char** args)> UI_RunMenuScript{0x14039EFF0, 0x1404CFE60}; WEAK symbol<void(unsigned int localClientNum, const char** args)> UI_RunMenuScript{0x0, 0x0};
WEAK symbol<int(const char* text, int maxChars, Font_s* font, float scale)> UI_TextWidth{0x1403A0F20, 0x1404D21A0}; WEAK symbol<int(const char* text, int maxChars, Font_s* font, float scale)> UI_TextWidth{0x0, 0x0};
WEAK symbol<const char*(const char* string)> UI_SafeTranslateString{0x140350430, 0x14041C580}; WEAK symbol<const char*(const char* string)> UI_SafeTranslateString{0x0, 0x0};
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{0x140648FD4, 0x140779F64}; WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{0x0, 0x0};
WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x1406BFD30, 0x1407F5F90}; WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x0, 0x0};
/*************************************************************** /***************************************************************
* Variables * Variables
**************************************************************/ **************************************************************/
WEAK symbol<CmdArgs> sv_cmd_args{0x14AD99A10, 0x14946BA20}; WEAK symbol<CmdArgs> sv_cmd_args{0x0, 0x0};
WEAK symbol<int> g_script_error_level{0x14BCFA4A4, 0x14A33C824}; WEAK symbol<int> g_script_error_level{0x0, 0x0};
WEAK symbol<jmp_buf> g_script_error{0x14BCFA5C0, 0x14A33C940}; WEAK symbol<jmp_buf> g_script_error{0x0, 0x0};
WEAK symbol<unsigned int> levelEntityId{0x14B65E3B0, 0x149CA0730}; WEAK symbol<unsigned int> levelEntityId{0x0, 0x0};
WEAK symbol<unsigned int> gameEntityId{0x14B65E3B4, 0x149CA0734}; WEAK symbol<unsigned int> gameEntityId{0x0, 0x0};
WEAK symbol<const char*> command_whitelist{0x141079A60, 0x14120C360}; WEAK symbol<const char*> command_whitelist{0x0, 0x0};
WEAK symbol<cmd_function_s*> cmd_functions{0x14AD99AB8, 0x14946BAC8}; WEAK symbol<cmd_function_s*> cmd_functions{0x0, 0x344DF18}; // 1.15
WEAK symbol<CmdArgs> cmd_args{0x14AD99960, 0x14946B970}; WEAK symbol<CmdArgs> cmd_args{0x0, 0x0};
WEAK symbol<int> g_poolSize{0x140DE84A0, 0x140FEADF0}; WEAK symbol<int> g_poolSize{0x0, 0x0};
WEAK symbol<scr_classStruct_t> g_classMap{0x14107AAF0, 0x1412106B0}; WEAK symbol<scr_classStruct_t> g_classMap{0x0, 0x0};
WEAK symbol<scrVarGlob_t> scr_VarGlob{0x14B686480, 0x149CC8800}; WEAK symbol<scrVarGlob_t> scr_VarGlob{0x0, 0x0};
WEAK symbol<scrVmPub_t> scr_VmPub{0x14BCFC6C0, 0x14A33EA40}; WEAK symbol<scrVmPub_t> scr_VmPub{0x0, 0x0};
WEAK symbol<function_stack_t> scr_function_stack{0x14BD06C40, 0x14A348FC0}; WEAK symbol<function_stack_t> scr_function_stack{0x0, 0x0};
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x14F05CE50, 0x14FD21180}; WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x0, 0x0};
WEAK symbol<int> dvarCount{0x14C217D10, 0x14D064CF4}; WEAK symbol<int> dvarCount{0x0, 0x0};
WEAK symbol<dvar_t> dvarPool{0x14C217D20, 0x14D064D00}; WEAK symbol<dvar_t> dvarPool{0x0, 0x0};
WEAK symbol<void*> DB_XAssetPool{0x140DE8C80, 0x140FEB5D0}; WEAK symbol<void*> DB_XAssetPool{0x0, 0x0};
WEAK symbol<const char*> g_assetNames{0x1408B0870, 0x140FEA240}; WEAK symbol<const char*> g_assetNames{0x0, 0x0};
WEAK symbol<int> keyCatchers{0x14243DAF0, 0x142D0BA9C}; WEAK symbol<int> keyCatchers{0x0, 0x0};
WEAK symbol<PlayerKeyState> playerKeys{0x1422A873C, 0x142C19AFC}; WEAK symbol<PlayerKeyState> playerKeys{0x0, 0x0};
WEAK symbol<SOCKET> query_socket{0, 0x14DDFBF98}; WEAK symbol<SOCKET> query_socket{0x0, 0x0};
WEAK symbol<DWORD> threadIds{0x14B19B880, 0x149810E00}; WEAK symbol<DWORD> threadIds{0x0, 0x0};
namespace mp namespace mp
{ {
WEAK symbol<gentity_s> g_entities{0, 0x14621E530}; WEAK symbol<gentity_s> g_entities{0x0, 0x71F19E0}; // 1.15
WEAK symbol<client_t> svs_clients{0, 0x14B204A10}; WEAK symbol<client_t> svs_clients{0x0, 0x0};
WEAK symbol<int> svs_numclients{0, 0x14B204A0C}; WEAK symbol<int> svs_numclients{0x0, 0x0};
WEAK symbol<int> gameTime{0, 0x14621BDBC}; WEAK symbol<int> gameTime{0x0, 0x0};
WEAK symbol<int> ping{0, 0x142D106F0}; WEAK symbol<int> ping{0x0, 0x0};
WEAK symbol<int> sv_serverId_value{0, 0x14A3E99B8}; WEAK symbol<int> sv_serverId_value{0x0, 0x0};
WEAK symbol<bool> virtualLobby_loaded{0, 0x142D077FD}; WEAK symbol<bool> virtualLobby_loaded{0x0, 0x0};
} }
namespace sp namespace sp
{ {
WEAK symbol<gentity_s> g_entities{0x14550DD90, 0}; WEAK symbol<gentity_s> g_entities{0x0, 0x0};
} }
namespace hks namespace hks
{ {
WEAK symbol<lua_State*> lua_state{0x141E2C2F8, 0x1426D3D08}; WEAK symbol<lua_State*> lua_state{0x0, 0x0};
WEAK symbol<void(lua_State* s, const char* str, unsigned int l)> hksi_lua_pushlstring{0x14004DA90, 0x1400624F0}; WEAK symbol<void(lua_State* s, const char* str, unsigned int l)> hksi_lua_pushlstring{0x0, 0x0};
WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_getfield{0x14009C0A0, 0x14012C600}; WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_getfield{0x0, 0x0};
WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)> hks_obj_settable{0x14009D240, 0x14012D820}; WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)> hks_obj_settable{0x0, 0x0};
WEAK symbol<HksObject* (HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_gettable{0x14009C580, 0x14012CAE0}; WEAK symbol<HksObject* (HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_gettable{0x0, 0x0};
WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{0x1400C87A0, 0x140159EB0}; WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{0x0, 0x0};
WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{0x14008B3B0, 0x14011B320}; WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{0x0, 0x0};
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues, WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues,
int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0x14008B5D0, 0x14011B540}; int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0x0, 0x0};
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x1400A64D0, 0x140136D30}; WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x0, 0x0};
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x14009EF10, 0x14012F610}; WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x0, 0x0};
WEAK symbol<void(lua_State* s, HksObject* lfp)> closePendingUpvalues{0x14008EA00, 0x14011E970}; WEAK symbol<void(lua_State* s, HksObject* lfp)> closePendingUpvalues{0x0, 0x0};
} }
} }

View File

@ -31,7 +31,7 @@ FARPROC loader::load(const utils::nt::library& library, const std::string& buffe
return FARPROC(library.get_ptr() + source.get_relative_entry_point()); return FARPROC(library.get_ptr() + source.get_relative_entry_point());
} }
FARPROC loader::load_library(const std::string& filename) const FARPROC loader::load_library(const std::string& filename, uint64_t* base_address) const
{ {
const auto target = utils::nt::library::load(filename); const auto target = utils::nt::library::load(filename);
if (!target) if (!target)
@ -40,10 +40,7 @@ FARPROC loader::load_library(const std::string& filename) const
} }
const auto base = size_t(target.get_ptr()); const auto base = size_t(target.get_ptr());
if(base != 0x140000000) *base_address = base;
{
throw std::runtime_error{utils::string::va("Binary was mapped at 0x%llX (instead of 0x%llX). Something is severely broken :(", base, 0x140000000)};
}
this->load_imports(target, target); this->load_imports(target, target);
this->load_tls(target, target); this->load_tls(target, target);

View File

@ -5,7 +5,7 @@ class loader final
{ {
public: public:
FARPROC load(const utils::nt::library& library, const std::string& buffer) const; FARPROC load(const utils::nt::library& library, const std::string& buffer) const;
FARPROC load_library(const std::string& filename) const; FARPROC load_library(const std::string& filename, uint64_t* base_address) const;
void set_import_resolver(const std::function<void*(const std::string&, const std::string&)>& resolver); void set_import_resolver(const std::function<void*(const std::string&, const std::string&)>& resolver);

View File

@ -20,16 +20,6 @@ BOOL WINAPI system_parameters_info_a(const UINT uiAction, const UINT uiParam, co
return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni); return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
} }
FARPROC WINAPI get_proc_address(const HMODULE hModule, const LPCSTR lpProcName)
{
if (lpProcName == "GlobalMemoryStatusEx"s)
{
component_loader::post_unpack();
}
return GetProcAddress(hModule, lpProcName);
}
launcher::mode detect_mode_from_arguments() launcher::mode detect_mode_from_arguments()
{ {
if (utils::flags::has_flag("dedicated")) if (utils::flags::has_flag("dedicated"))
@ -50,14 +40,15 @@ launcher::mode detect_mode_from_arguments()
return launcher::mode::none; return launcher::mode::none;
} }
FARPROC load_binary(const launcher::mode mode) FARPROC load_binary(const launcher::mode mode, uint64_t* base_address)
{ {
loader loader; loader loader;
utils::nt::library self; utils::nt::library self;
loader.set_import_resolver([self](const std::string& library, const std::string& function) -> void* loader.set_import_resolver([self](const std::string& library, const std::string& function) -> void*
{ {
if (library == "steam_api64.dll") if (library == "steam_api64.dll"
&& function != "SteamAPI_GetSteamInstallPath") // Arxan requires one valid steam api import - maybe SteamAPI_Shutdown is better?
{ {
return self.get_proc<FARPROC>(function); return self.get_proc<FARPROC>(function);
} }
@ -69,10 +60,6 @@ FARPROC load_binary(const launcher::mode mode)
{ {
return system_parameters_info_a; return system_parameters_info_a;
} }
else if (function == "GetProcAddress")
{
return get_proc_address;
}
return component_loader::load_import(library, function); return component_loader::load_import(library, function);
}); });
@ -100,7 +87,12 @@ FARPROC load_binary(const launcher::mode mode)
binary.data())); binary.data()));
} }
return loader.load_library(binary); #ifdef INJECT_HOST_AS_LIB
return loader.load_library(binary, base_address);
#else
*base_address = 0x140000000;
return loader.load(self, data);
#endif
} }
void remove_crash_file() void remove_crash_file()
@ -158,6 +150,8 @@ void apply_proper_directory()
int main() int main()
{ {
ShowWindow(GetConsoleWindow(), SW_HIDE);
FARPROC entry_point; FARPROC entry_point;
enable_dpi_awareness(); enable_dpi_awareness();
@ -166,6 +160,7 @@ int main()
limit_parallel_dll_loading(); limit_parallel_dll_loading();
srand(uint32_t(time(nullptr))); srand(uint32_t(time(nullptr)));
remove_crash_file();
{ {
auto premature_shutdown = true; auto premature_shutdown = true;
@ -179,8 +174,8 @@ int main()
try try
{ {
apply_proper_directory(); //apply_proper_directory();
remove_crash_file(); //remove_crash_file();
if (!component_loader::post_start()) return 0; if (!component_loader::post_start()) return 0;
@ -194,12 +189,15 @@ int main()
game::environment::set_mode(mode); game::environment::set_mode(mode);
entry_point = load_binary(mode); uint64_t base_address{};
entry_point = load_binary(mode, &base_address);
if (!entry_point) if (!entry_point)
{ {
throw std::runtime_error("Unable to load binary into memory"); throw std::runtime_error("Unable to load binary into memory");
} }
game::base_address = base_address;
if (!component_loader::post_load()) return 0; if (!component_loader::post_load()) return 0;
premature_shutdown = false; premature_shutdown = false;

View File

@ -1,6 +1,23 @@
#include <std_include.hpp> #include <std_include.hpp>
#pragma comment(linker, "/base:0x160000000") #pragma comment(linker, "/stack:0x1000000")
#ifdef INJECT_HOST_AS_LIB
//#pragma comment(linker, "/base:0x160000000")
#else
#pragma comment(linker, "/base:0x140000000")
#pragma comment(linker, "/merge:.data=.cld")
#pragma comment(linker, "/merge:.rdata=.clr")
#pragma comment(linker, "/merge:.cl=.main")
#pragma comment(linker, "/merge:.text=.main")
#endif
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language=''\"")
#ifndef INJECT_HOST_AS_LIB
#pragma bss_seg(".payload")
char payload_data[BINARY_PAYLOAD_SIZE];
#endif
extern "C" extern "C"
{ {

View File

@ -1,6 +1,9 @@
#pragma once #pragma once
#define BINARY_PAYLOAD_SIZE 0x12000000 #define BINARY_PAYLOAD_SIZE 0x14000000
// Decide whether to load the game as lib or to inject it
#define INJECT_HOST_AS_LIB
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4100) #pragma warning(disable: 4100)

View File

@ -1,6 +1,8 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "steam.hpp" #include "steam.hpp"
#include <utils/nt.hpp>
namespace steam namespace steam
{ {
uint64_t callbacks::call_id_ = 0; uint64_t callbacks::call_id_ = 0;
@ -108,6 +110,13 @@ namespace steam
bool SteamAPI_Init() bool SteamAPI_Init()
{ {
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
if (steam_path.empty()) return true;
::utils::nt::library::load(steam_path / "tier0_s64.dll");
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
::utils::nt::library::load(steam_path / "steamclient64.dll");
return true; return true;
} }