Fix script leaks + increase memory
This commit is contained in:
parent
62d9bd6e92
commit
935d44d4a3
@ -106,11 +106,6 @@ namespace gsc
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scr_emit_function_hook.create(SELECT_VALUE(0x3BD680_b, 0x504660_b), &scr_emit_function_stub);
|
||||
|
||||
utils::hook::call(SELECT_VALUE(0x3BD626_b, 0x504606_b), unknown_function_stub); // CompileError (LinkFile)
|
||||
|
@ -348,11 +348,6 @@ namespace gsc
|
||||
utils::hook::inject(SELECT_VALUE(0x3BDC36_b, 0x504C66_b) + 3, &meth_table);
|
||||
utils::hook::set<uint32_t>(SELECT_VALUE(0x3BDC3F_b, 0x504C6F_b), sizeof(meth_table));
|
||||
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
developer_script = dvars::register_bool("developer_script", false, 0, "Enable developer script comments");
|
||||
|
||||
utils::hook::nop(SELECT_VALUE(0x3CB723_b, 0x512783_b), 8);
|
||||
@ -466,36 +461,39 @@ namespace gsc
|
||||
return scripting::script_value{};
|
||||
});
|
||||
|
||||
function::add("say", [](const function_args& args)
|
||||
{
|
||||
const auto message = args[0].as<std::string>();
|
||||
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||
|
||||
return scripting::script_value{};
|
||||
});
|
||||
|
||||
function::add("typeof", typeof);
|
||||
function::add("type", typeof);
|
||||
|
||||
method::add("tell", [](const game::scr_entref_t ent, const function_args& args)
|
||||
if (!game::environment::is_sp())
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
function::add("say", [](const function_args& args)
|
||||
{
|
||||
throw std::runtime_error("Invalid entity");
|
||||
}
|
||||
const auto message = args[0].as<std::string>();
|
||||
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||
|
||||
const auto client = ent.entnum;
|
||||
return scripting::script_value{};
|
||||
});
|
||||
|
||||
if (game::mp::g_entities[client].client == nullptr)
|
||||
method::add("tell", [](const game::scr_entref_t ent, const function_args& args)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
throw std::runtime_error("Invalid entity");
|
||||
}
|
||||
|
||||
const auto message = args[0].as<std::string>();
|
||||
game::SV_GameSendServerCommand(client, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||
const auto client = ent.entnum;
|
||||
|
||||
return scripting::script_value{};
|
||||
});
|
||||
if (game::mp::g_entities[client].client == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
|
||||
const auto message = args[0].as<std::string>();
|
||||
game::SV_GameSendServerCommand(client, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||
|
||||
return scripting::script_value{};
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -39,13 +39,48 @@ namespace gsc
|
||||
std::unordered_map<std::string, std::uint32_t> main_handles;
|
||||
std::unordered_map<std::string, std::uint32_t> init_handles;
|
||||
|
||||
utils::memory::allocator scriptfile_allocator;
|
||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||
|
||||
struct
|
||||
{
|
||||
char* buf = nullptr;
|
||||
char* pos = nullptr;
|
||||
unsigned int size = 0x1000000;
|
||||
} script_memory;
|
||||
|
||||
char* allocate_buffer(size_t size)
|
||||
{
|
||||
if (script_memory.buf == nullptr)
|
||||
{
|
||||
script_memory.buf = game::PMem_AllocFromSource_NoDebug(script_memory.size, 4, 1, game::PMEM_SOURCE_SCRIPT);
|
||||
script_memory.pos = script_memory.buf;
|
||||
}
|
||||
|
||||
if (script_memory.pos + size > script_memory.buf + script_memory.size)
|
||||
{
|
||||
game::Com_Error(game::ERR_FATAL, "Out of custom script memory");
|
||||
}
|
||||
|
||||
const auto pos = script_memory.pos;
|
||||
script_memory.pos += size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void free_script_memory()
|
||||
{
|
||||
game::PMem_PopFromSource_NoDebug(script_memory.buf, script_memory.size, 4, 1, game::PMEM_SOURCE_SCRIPT);
|
||||
script_memory.buf = nullptr;
|
||||
script_memory.pos = nullptr;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
main_handles.clear();
|
||||
init_handles.clear();
|
||||
loaded_scripts.clear();
|
||||
scriptfile_allocator.clear();
|
||||
free_script_memory();
|
||||
}
|
||||
|
||||
bool read_script_file(const std::string& name, std::string* data)
|
||||
@ -75,14 +110,13 @@ namespace gsc
|
||||
return false;
|
||||
}
|
||||
|
||||
char* allocate_buffer(size_t size)
|
||||
{
|
||||
// PMem_AllocFromSource_NoDebug
|
||||
return utils::hook::invoke<char*>(SELECT_VALUE(0x41FB50_b, 0x5A4DC0_b), size, 4, 1, 5);
|
||||
}
|
||||
|
||||
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
||||
{
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (const auto itr = loaded_scripts.find(real_name); itr != loaded_scripts.end())
|
||||
{
|
||||
return itr->second;
|
||||
@ -134,7 +168,7 @@ namespace gsc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto script_file_ptr = reinterpret_cast<game::ScriptFile*>(allocate_buffer(sizeof(game::ScriptFile)));
|
||||
const auto script_file_ptr = scriptfile_allocator.allocate<game::ScriptFile>();
|
||||
script_file_ptr->name = file_name;
|
||||
|
||||
const auto stack = assembler->output_stack();
|
||||
@ -143,15 +177,12 @@ namespace gsc
|
||||
const auto script = assembler->output_script();
|
||||
script_file_ptr->bytecodeLen = static_cast<int>(script.size());
|
||||
|
||||
const auto script_size = script.size();
|
||||
const auto buffer_size = script_size + stack.size() + 2;
|
||||
script_file_ptr->buffer = game::Hunk_AllocateTempMemoryHigh(stack.size() + 1);
|
||||
std::memcpy(script_file_ptr->buffer, stack.data(), stack.size());
|
||||
|
||||
const auto buffer = allocate_buffer(buffer_size);
|
||||
std::memcpy(buffer, script.data(), script_size);
|
||||
std::memcpy(&buffer[script_size], stack.data(), stack.size());
|
||||
script_file_ptr->bytecode = allocate_buffer(script.size() + 1);
|
||||
std::memcpy(script_file_ptr->bytecode, script.data(), script.size());
|
||||
|
||||
script_file_ptr->bytecode = &buffer[0];
|
||||
script_file_ptr->buffer = reinterpret_cast<char*>(&buffer[script.size()]);
|
||||
script_file_ptr->compressedLen = 0;
|
||||
|
||||
loaded_scripts[real_name] = script_file_ptr;
|
||||
@ -254,8 +285,6 @@ namespace gsc
|
||||
{
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x2B9DA0_b, 0x18BC00_b), a1, a2);
|
||||
|
||||
clear();
|
||||
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return;
|
||||
@ -286,6 +315,27 @@ namespace gsc
|
||||
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x1F1E00_b, 0x396080_b), rawfile, buf, size);
|
||||
}
|
||||
|
||||
void pmem_init_stub()
|
||||
{
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x420260_b, 0x5A5590_b));
|
||||
|
||||
const auto type_0 = &game::g_scriptmem[0];
|
||||
const auto type_1 = &game::g_scriptmem[1];
|
||||
|
||||
const auto size_0 = 0x100000; // default size
|
||||
const auto size_1 = 0x100000 + script_memory.size;
|
||||
|
||||
const auto block = reinterpret_cast<char*>(VirtualAlloc(NULL, size_0 + size_1, MEM_RESERVE, PAGE_READWRITE));
|
||||
|
||||
type_0->buf = block;
|
||||
type_0->size = size_0;
|
||||
|
||||
type_1->buf = block + size_0;
|
||||
type_1->size = size_1;
|
||||
|
||||
utils::hook::set<uint32_t>(SELECT_VALUE(0x420252_b, 0x5A5582_b), size_0 + size_1);
|
||||
}
|
||||
}
|
||||
|
||||
void load_main_handles()
|
||||
@ -329,11 +379,6 @@ namespace gsc
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// allow custom scripts to include other custom scripts
|
||||
xsk::gsc::h1::resolver::init([](const auto& include_name)
|
||||
{
|
||||
@ -369,6 +414,9 @@ namespace gsc
|
||||
// loads scripts with an uncompressed stack
|
||||
utils::hook::call(SELECT_VALUE(0x3C7280_b, 0x50E3C0_b), db_get_raw_buffer_stub);
|
||||
|
||||
// Increase script memory
|
||||
utils::hook::call(SELECT_VALUE(0x38639C_b, 0x15C4D6_b), pmem_init_stub);
|
||||
|
||||
scripting::on_shutdown([](int free_scripts)
|
||||
{
|
||||
if (free_scripts)
|
||||
|
@ -343,8 +343,6 @@ namespace party
|
||||
const auto path = get_usermap_file_path(mapname, ext);
|
||||
const auto hash = get_file_hash(path);
|
||||
|
||||
console::debug("%s %s %s != %s\n", ext.data(), key.data(), hash.data(), source_hash.data());
|
||||
|
||||
if ((!source_hash.empty() && hash != source_hash) || (source_hash.empty() && !opt))
|
||||
{
|
||||
command::execute("disconnect");
|
||||
@ -423,8 +421,6 @@ namespace party
|
||||
}
|
||||
}
|
||||
|
||||
console::debug("%i %s\n", is_usermap, buffer.data());
|
||||
|
||||
net_out_of_band_print_hook.invoke<void>(sock, addr, buffer.data());
|
||||
}
|
||||
}
|
||||
|
@ -1599,6 +1599,28 @@ namespace game
|
||||
int ingame_cursor_visible;
|
||||
};
|
||||
|
||||
enum PMem_Source
|
||||
{
|
||||
PMEM_SOURCE_EXTERNAL = 0x0,
|
||||
PMEM_SOURCE_DATABASE = 0x1,
|
||||
PMEM_SOURCE_DEFAULT_LOW = 0x2,
|
||||
PMEM_SOURCE_DEFAULT_HIGH = 0x3,
|
||||
PMEM_SOURCE_MOVIE = 0x4,
|
||||
PMEM_SOURCE_SCRIPT = 0x5,
|
||||
};
|
||||
|
||||
struct physical_memory
|
||||
{
|
||||
char __pad0[0x10];
|
||||
char* buf;
|
||||
char __pad1[0x8];
|
||||
int unk1;
|
||||
size_t size;
|
||||
char __pad2[0x500];
|
||||
};
|
||||
|
||||
static_assert(sizeof(physical_memory) == 0x530);
|
||||
|
||||
namespace mp
|
||||
{
|
||||
struct cachedSnapshot_t
|
||||
|
@ -117,6 +117,8 @@ namespace game
|
||||
|
||||
WEAK symbol<int(const char* buf, int max, char** infos)> GameInfo_ParseArenas{0x0, 0x4DE0B0};
|
||||
|
||||
WEAK symbol<char*(const size_t size)> Hunk_AllocateTempMemoryHigh{0x415DB0, 0x59DEC0};
|
||||
|
||||
WEAK symbol<char*(char* string)> I_CleanStr{0x4293E0, 0x5AF2E0};
|
||||
|
||||
WEAK symbol<const char*(int, int, int)> Key_KeynumToString{0x1AC410, 0x199990};
|
||||
@ -155,6 +157,11 @@ namespace game
|
||||
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{0x560740, 0x683890};
|
||||
|
||||
WEAK symbol<char*(const size_t size, unsigned int alignment,
|
||||
unsigned int type, PMem_Source source)> PMem_AllocFromSource_NoDebug{0x41FB50, 0x5A4DC0};
|
||||
WEAK symbol<void(char* buf, const size_t size, unsigned int alignment,
|
||||
unsigned int type, PMem_Source source)> PMem_PopFromSource_NoDebug{0x4203D0, 0x5A5700};
|
||||
|
||||
WEAK symbol<unsigned int(unsigned int localId, const char* pos,
|
||||
unsigned int paramcount)> VM_Execute{0x3C9E50, 0x510EB0};
|
||||
|
||||
@ -299,6 +306,8 @@ namespace game
|
||||
WEAK symbol<scrVmPub_t> scr_VmPub{0xC3F4E20, 0xB7AE3C0};
|
||||
WEAK symbol<function_stack_t> scr_function_stack{0xC4015C0, 0xB7B8940};
|
||||
|
||||
WEAK symbol<physical_memory> g_scriptmem{0xD5F3140, 0xC92EC40};
|
||||
|
||||
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0xF7530B0, 0xE9213F0};
|
||||
|
||||
WEAK symbol<int> dvarCount{0xC90E550, 0x2999C34};
|
||||
|
Loading…
Reference in New Issue
Block a user