commit
8448eaa41f
@ -2,6 +2,10 @@ if (game:issingleplayer()) then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (Engine.InFrontend()) then
|
||||||
|
require("shaderdialog")
|
||||||
|
end
|
||||||
|
|
||||||
-- defined in mp_hud/hudutils.lua
|
-- defined in mp_hud/hudutils.lua
|
||||||
function GetGameModeName()
|
function GetGameModeName()
|
||||||
return Engine.Localize(Engine.TableLookup(GameTypesTable.File,
|
return Engine.Localize(Engine.TableLookup(GameTypesTable.File,
|
||||||
|
28
data/ui_scripts/patches/shaderdialog.lua
Normal file
28
data/ui_scripts/patches/shaderdialog.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
LUI.MenuBuilder.registerPopupType("ShaderCacheDialog_original", LUI.ShaderCacheDialog.new)
|
||||||
|
|
||||||
|
game:addlocalizedstring("PLATFORM_SHADER_PRECACHE_ASK", "Would you like to populate the shader cache? It may cause crashes with certain GPUs (e.g. RTX cards) but will improve performance if successful.")
|
||||||
|
game:addlocalizedstring("MENU_NO_DONT_ASK", "No, don't ask me again")
|
||||||
|
|
||||||
|
local function dialog(...)
|
||||||
|
if (game:sharedget("has_accepted_shader_caching") == "1") then
|
||||||
|
return LUI.ShaderCacheDialog.new(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return LUI.MenuBuilder.BuildRegisteredType("generic_yesno_popup", {
|
||||||
|
popup_title = Engine.Localize("@MENU_WARNING"),
|
||||||
|
message_text = Engine.Localize("@PLATFORM_SHADER_PRECACHE_ASK"),
|
||||||
|
yes_action = function()
|
||||||
|
game:sharedset("has_accepted_shader_caching", "1")
|
||||||
|
LUI.FlowManager.RequestAddMenu(nil, "ShaderCacheDialog_original")
|
||||||
|
end,
|
||||||
|
yes_text = Engine.Localize("@MENU_YES"),
|
||||||
|
no_text = Engine.Localize("@MENU_NO_DONT_ASK"),
|
||||||
|
no_action = function()
|
||||||
|
Engine.SetDvarInt("r_preloadShadersFrontendAllow", 0)
|
||||||
|
end,
|
||||||
|
default_focus_index = 2,
|
||||||
|
cancel_will_close = false
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
LUI.MenuBuilder.m_types_build["ShaderCacheDialog"] = dialog
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "dvars.hpp"
|
#include "dvars.hpp"
|
||||||
|
#include "fastfiles.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
@ -155,6 +156,12 @@ namespace patches
|
|||||||
game::AimAssist_AddToTargetList(aaGlob, screenTarget);
|
game::AimAssist_AddToTargetList(aaGlob, screenTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void missing_content_error_stub(int, const char*)
|
||||||
|
{
|
||||||
|
game::Com_Error(game::ERR_DROP, utils::string::va("MISSING FILE\n%s.ff",
|
||||||
|
fastfiles::get_current_fastfile().data()));
|
||||||
|
}
|
||||||
|
|
||||||
utils::hook::detour init_network_dvars_hook;
|
utils::hook::detour init_network_dvars_hook;
|
||||||
void init_network_dvars_stub(game::dvar_t* dvar)
|
void init_network_dvars_stub(game::dvar_t* dvar)
|
||||||
{
|
{
|
||||||
@ -169,6 +176,33 @@ namespace patches
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::hook::detour cl_gamepad_scrolling_buttons_hook;
|
||||||
|
void cl_gamepad_scrolling_buttons_stub(int local_client_num, int a2)
|
||||||
|
{
|
||||||
|
if (local_client_num <= 3)
|
||||||
|
{
|
||||||
|
cl_gamepad_scrolling_buttons_hook.invoke<void>(local_client_num, a2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int out_of_memory_text_stub(char* dest, int size, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
fmt = "%s (%d)\n\n"
|
||||||
|
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.\n\n"
|
||||||
|
"If this still occurs, try using the '-memoryfix' parameter to generate the 'players2' folder.";
|
||||||
|
|
||||||
|
char buffer[2048];
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return utils::hook::invoke<int>(SELECT_VALUE(0x429200_b, 0x5AF0F0_b), dest, size, "%s", buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -201,9 +235,21 @@ namespace patches
|
|||||||
utils::hook::nop(SELECT_VALUE(0x1AC0CE_b, 0x135EFB_b), 2);
|
utils::hook::nop(SELECT_VALUE(0x1AC0CE_b, 0x135EFB_b), 2);
|
||||||
utils::hook::nop(SELECT_VALUE(0x1A9DDC_b, 0x13388F_b), 6);
|
utils::hook::nop(SELECT_VALUE(0x1A9DDC_b, 0x13388F_b), 6);
|
||||||
|
|
||||||
|
// Show missing fastfiles
|
||||||
|
utils::hook::call(SELECT_VALUE(0x0_b, 0x39A78E_b), missing_content_error_stub);
|
||||||
|
|
||||||
// Allow executing custom cfg files with the "exec" command
|
// Allow executing custom cfg files with the "exec" command
|
||||||
utils::hook::call(SELECT_VALUE(0x376EB5_b, 0x156D41_b), db_read_raw_file_stub);
|
utils::hook::call(SELECT_VALUE(0x376EB5_b, 0x156D41_b), db_read_raw_file_stub);
|
||||||
|
|
||||||
|
// Remove useless information from errors + add additional help to common errors
|
||||||
|
utils::hook::set<const char*>(SELECT_VALUE(0x7E3DF0_b, 0x937B80_b),
|
||||||
|
"Create2DTexture( %s, %i, %i, %i, %i ) failed\n\n"
|
||||||
|
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.");
|
||||||
|
utils::hook::set<const char*>(SELECT_VALUE(0x800EA8_b, 0x954FF0_b),
|
||||||
|
"IDXGISwapChain::Present failed: %s\n\n"
|
||||||
|
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.");
|
||||||
|
utils::hook::call(SELECT_VALUE(0x457BC9_b, 0x1D8E09_b), out_of_memory_text_stub); // "Out of memory. You are probably low on disk space."
|
||||||
|
|
||||||
if (!game::environment::is_sp())
|
if (!game::environment::is_sp())
|
||||||
{
|
{
|
||||||
patch_mp();
|
patch_mp();
|
||||||
@ -302,6 +348,9 @@ namespace patches
|
|||||||
|
|
||||||
// Dont free server/client memory on asset loading (fixes crashing on map rotation)
|
// Dont free server/client memory on asset loading (fixes crashing on map rotation)
|
||||||
utils::hook::nop(0x132474_b, 5);
|
utils::hook::nop(0x132474_b, 5);
|
||||||
|
|
||||||
|
// Fix gamepad related crash
|
||||||
|
cl_gamepad_scrolling_buttons_hook.create(0x133210_b, cl_gamepad_scrolling_buttons_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,29 @@ namespace security
|
|||||||
utils::hook::invoke<void>(0x61A9D0_b, localclient, index1, index2);
|
utils::hook::invoke<void>(0x61A9D0_b, localclient, index1, index2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remap_cached_entities(game::mp::cachedSnapshot_t& snapshot)
|
||||||
|
{
|
||||||
|
static bool printed = false;
|
||||||
|
if (snapshot.num_clients > 1200 && !printed)
|
||||||
|
{
|
||||||
|
printed = true;
|
||||||
|
printf("Too many entities (%d)... remapping!\n", snapshot.num_clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.num_clients = std::min(snapshot.num_clients, 1200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remap_cached_entities_stub(utils::hook::assembler& a)
|
||||||
|
{
|
||||||
|
a.pushad64();
|
||||||
|
|
||||||
|
a.mov(rcx, rbx);
|
||||||
|
a.call_aligned(remap_cached_entities);
|
||||||
|
|
||||||
|
a.popad64();
|
||||||
|
a.jmp(0x55E4D8_b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -30,6 +53,9 @@ namespace security
|
|||||||
|
|
||||||
// Patch vulnerability in PlayerCards_SetCachedPlayerData
|
// Patch vulnerability in PlayerCards_SetCachedPlayerData
|
||||||
utils::hook::call(0xF4632_b, set_cached_playerdata_stub);
|
utils::hook::call(0xF4632_b, set_cached_playerdata_stub);
|
||||||
|
|
||||||
|
// Patch entity overflow
|
||||||
|
utils::hook::jump(0x55E4C7_b, assemble(remap_cached_entities_stub), true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,19 @@ namespace game
|
|||||||
/***************************************************************
|
/***************************************************************
|
||||||
* Functions
|
* Functions
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
||||||
|
namespace mp
|
||||||
|
{
|
||||||
|
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cbuf_AddText{0x0, 0x1CF480};
|
||||||
|
WEAK symbol<void(const char* text_in, int limit)> Cmd_TokenizeStringWithLimit{0x0, 0x157A40};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sp
|
||||||
|
{
|
||||||
|
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x3764A0, 0x0};
|
||||||
|
WEAK symbol<void(const char* text_in)> Cmd_TokenizeString{0x377790, 0x0};
|
||||||
|
WEAK symbol<void()> Cmd_EndTokenizeString{0x376C90, 0x0};
|
||||||
|
}
|
||||||
|
|
||||||
WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x3C1F50, 0x5090E0};
|
WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x3C1F50, 0x5090E0};
|
||||||
WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x3C3A60, 0x50ABF0};
|
WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x3C3A60, 0x50ABF0};
|
||||||
@ -15,16 +28,6 @@ namespace game
|
|||||||
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x3C22B0, 0x509440};
|
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x3C22B0, 0x509440};
|
||||||
WEAK symbol<ObjectVariableValue*(unsigned int* id)> AllocVariable{0x3C2310, 0x5094A0};
|
WEAK symbol<ObjectVariableValue*(unsigned int* id)> AllocVariable{0x3C2310, 0x5094A0};
|
||||||
|
|
||||||
namespace sp
|
|
||||||
{
|
|
||||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x3764A0, 0x0};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mp
|
|
||||||
{
|
|
||||||
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cbuf_AddText{0x0, 0x1CF480};
|
|
||||||
}
|
|
||||||
|
|
||||||
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{0x3765B0, 0x155BC0};
|
void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0x3765B0, 0x155BC0};
|
||||||
WEAK symbol<void(const char* message)> Conbuf_AppendText{0x0, 0x0};
|
WEAK symbol<void(const char* message)> Conbuf_AppendText{0x0, 0x0};
|
||||||
@ -33,17 +36,6 @@ namespace game
|
|||||||
WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{0x376A40, 0x156880};
|
WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{0x376A40, 0x156880};
|
||||||
WEAK symbol<void(const char*)> Cmd_RemoveCommand{0x377670, 0x157690};
|
WEAK symbol<void(const char*)> Cmd_RemoveCommand{0x377670, 0x157690};
|
||||||
|
|
||||||
namespace sp
|
|
||||||
{
|
|
||||||
WEAK symbol<void(const char* text_in)> Cmd_TokenizeString{0x377790, 0x0};
|
|
||||||
WEAK symbol<void()> Cmd_EndTokenizeString{0x376C90, 0x0};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mp
|
|
||||||
{
|
|
||||||
WEAK symbol<void(const char* text_in, int limit)> Cmd_TokenizeStringWithLimit{0x0, 0x157A40};
|
|
||||||
}
|
|
||||||
|
|
||||||
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0x0, 0xE66C0};
|
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0x0, 0xE66C0};
|
||||||
|
|
||||||
WEAK symbol<void(unsigned int weapon, bool isAlternate,
|
WEAK symbol<void(unsigned int weapon, bool isAlternate,
|
||||||
|
@ -40,12 +40,12 @@ launcher::mode detect_mode_from_arguments()
|
|||||||
return launcher::mode::none;
|
return launcher::mode::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool apply_aslr_patch(std::string* data)
|
void apply_aslr_patch(std::string* data)
|
||||||
{
|
{
|
||||||
// mp binary, sp binary
|
// mp binary, sp binary
|
||||||
if (data->size() != 0x1B97788 && data->size() != 0x1346D88)
|
if (data->size() != 0x1B97788 && data->size() != 0x1346D88)
|
||||||
{
|
{
|
||||||
return false;
|
throw std::runtime_error("File size mismatch, bad game files");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(&data->at(0));
|
auto* dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(&data->at(0));
|
||||||
@ -56,22 +56,26 @@ bool apply_aslr_patch(std::string* data)
|
|||||||
{
|
{
|
||||||
optional_header->DllCharacteristics &= ~(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
optional_header->DllCharacteristics &= ~(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_aslr_patched_binary(std::string* binary, std::string* data)
|
void get_aslr_patched_binary(std::string* binary, std::string* data)
|
||||||
{
|
{
|
||||||
std::string patched_binary = "h1-mod\\" + *binary;
|
const auto patched_binary = "h1-mod\\"s + *binary;
|
||||||
|
|
||||||
if (!apply_aslr_patch(data) ||
|
try
|
||||||
(!utils::io::file_exists(patched_binary) &&
|
|
||||||
!utils::io::write_file(patched_binary, *data, false)))
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error(utils::string::va(
|
apply_aslr_patch(data);
|
||||||
"Could not create aslr patched binary!\n(%s)",
|
if (!utils::io::file_exists(patched_binary) && !utils::io::write_file(patched_binary, *data, false))
|
||||||
binary->data()
|
{
|
||||||
));
|
throw std::runtime_error("Could not write file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
utils::string::va("Could not create aslr patched binary for %s! %s",
|
||||||
|
binary->data(), e.what())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
*binary = patched_binary;
|
*binary = patched_binary;
|
||||||
|
Loading…
Reference in New Issue
Block a user