This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
YimMenu/BigBaseV2/src/script_hook.cpp

108 lines
2.5 KiB
C++
Raw Normal View History

2019-03-21 20:18:31 +01:00
#include "common.hpp"
#include "crossmap.hpp"
#include "gta/script_program.hpp"
#include "logger.hpp"
#include "pointers.hpp"
#include "script_hook.hpp"
namespace big
{
inline std::unordered_map<rage::scrProgram*, script_hook*> script_hook::s_map;
static bool map_native(rage::scrNativeHash* hash)
2019-03-21 20:18:31 +01:00
{
for (auto const& mapping : g_crossmap)
2019-03-21 20:18:31 +01:00
{
if (mapping.first == *hash)
{
*hash = mapping.second;
return true;
}
}
return false;
}
script_hook::script_hook(rage::joaat_t script_hash, std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements) :
m_script_hash(script_hash),
m_native_replacements(std::move(native_replacements))
{
ensure();
}
script_hook::~script_hook()
{
if (m_program)
{
for (auto [hash, handler_ptr] : m_native_handler_ptrs)
2019-03-21 20:18:31 +01:00
{
auto og_handler = g_pointers->m_get_native_handler(g_pointers->m_native_registration_table, hash);
*handler_ptr = og_handler;
}
}
if (m_vmt_hook)
{
m_vmt_hook->disable();
s_map.erase(m_program);
}
}
void script_hook::ensure()
{
if (m_vmt_hook)
return;
if (auto program = g_pointers->m_script_program_table->find_script(m_script_hash))
{
if (program->is_valid())
{
hook_instance(program);
LOG(INFO) << "Hooked " << program->m_name << " script (" << HEX_TO_UPPER(static_cast<void*>(program)) << ")";
2019-03-21 20:18:31 +01:00
}
}
}
void script_hook::hook_instance(rage::scrProgram* program)
2019-03-21 20:18:31 +01:00
{
m_program = program;
s_map.emplace(m_program, this);
m_vmt_hook = std::make_unique<vmt_hook>(m_program, 3);
m_vmt_hook->hook(0, &scrprogram_dtor);
for (auto [replacement_hash, replacement_handler] : m_native_replacements)
{
auto hash = replacement_hash;
map_native(&hash);
auto og_handler = g_pointers->m_get_native_handler(g_pointers->m_native_registration_table, hash);
if (!og_handler)
continue;
auto handler_ptr = m_program->get_address_of_native_entrypoint(og_handler);
if (!handler_ptr)
continue;
m_native_handler_ptrs.emplace(hash, reinterpret_cast<rage::scrNativeHandler*>(handler_ptr));
*handler_ptr = replacement_handler;
}
}
void script_hook::scrprogram_dtor(rage::scrProgram* this_, bool free_memory)
2019-03-21 20:18:31 +01:00
{
if (auto it = s_map.find(this_); it != s_map.end())
{
auto hook = it->second;
hook->m_program = nullptr;
s_map.erase(it);
auto og_func = hook->m_vmt_hook->get_original<decltype(&scrprogram_dtor)>(0);
hook->m_vmt_hook->disable();
hook->m_vmt_hook.reset();
og_func(this_, free_memory);
}
}
}