Merge pull request #92 from h1-mod/develop

Release v1.0.1
This commit is contained in:
fed 2022-06-25 02:15:37 +00:00 committed by GitHub
commit 9d5c246575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 33 deletions

View File

@ -2,6 +2,10 @@ if (game:issingleplayer()) then
return
end
if (Engine.InFrontend()) then
require("shaderdialog")
end
-- defined in mp_hud/hudutils.lua
function GetGameModeName()
return Engine.Localize(Engine.TableLookup(GameTypesTable.File,

View 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

View File

@ -2,6 +2,7 @@
#include "loader/component_loader.hpp"
#include "dvars.hpp"
#include "fastfiles.hpp"
#include "version.h"
#include "command.hpp"
#include "console.hpp"
@ -155,6 +156,12 @@ namespace patches
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;
void init_network_dvars_stub(game::dvar_t* dvar)
{
@ -169,6 +176,33 @@ namespace patches
{
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
@ -201,9 +235,21 @@ namespace patches
utils::hook::nop(SELECT_VALUE(0x1AC0CE_b, 0x135EFB_b), 2);
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
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())
{
patch_mp();
@ -302,6 +348,9 @@ namespace patches
// Dont free server/client memory on asset loading (fixes crashing on map rotation)
utils::hook::nop(0x132474_b, 5);
// Fix gamepad related crash
cl_gamepad_scrolling_buttons_hook.create(0x133210_b, cl_gamepad_scrolling_buttons_stub);
}
};
}

View File

@ -16,6 +16,29 @@ namespace security
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
@ -30,6 +53,9 @@ namespace security
// Patch vulnerability in PlayerCards_SetCachedPlayerData
utils::hook::call(0xF4632_b, set_cached_playerdata_stub);
// Patch entity overflow
utils::hook::jump(0x55E4C7_b, assemble(remap_cached_entities_stub), true);
}
};
}

View File

@ -7,6 +7,19 @@ namespace game
/***************************************************************
* 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)> RemoveRefToValue{0x3C3A60, 0x50ABF0};
@ -15,16 +28,6 @@ namespace game
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x3C22B0, 0x509440};
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,
void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0x3765B0, 0x155BC0};
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*)> 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(unsigned int weapon, bool isAlternate,

View File

@ -40,12 +40,12 @@ launcher::mode detect_mode_from_arguments()
return launcher::mode::none;
}
bool apply_aslr_patch(std::string* data)
void apply_aslr_patch(std::string* data)
{
// mp binary, sp binary
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));
@ -56,22 +56,26 @@ bool apply_aslr_patch(std::string* data)
{
optional_header->DllCharacteristics &= ~(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
}
return true;
}
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) ||
(!utils::io::file_exists(patched_binary) &&
!utils::io::write_file(patched_binary, *data, false)))
try
{
throw std::runtime_error(utils::string::va(
"Could not create aslr patched binary!\n(%s)",
binary->data()
));
apply_aslr_patch(data);
if (!utils::io::file_exists(patched_binary) && !utils::io::write_file(patched_binary, *data, false))
{
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;