Disables script patches from the Lua layer on eject. (#3628)

This commit is contained in:
gir489 2024-08-28 17:38:13 -04:00 committed by GitHub
parent 6af80e936d
commit 1f985a5a21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 164 additions and 135 deletions

View File

@ -25,6 +25,12 @@ namespace lua::scr_patch
module->m_registered_script_patches.push_back(std::make_unique<scr_patch>(*this)); module->m_registered_script_patches.push_back(std::make_unique<scr_patch>(*this));
} }
scr_patch::~scr_patch()
{
disable();
big::g_script_patcher_service->remove_patch(m_patch_name);
}
void scr_patch::enable() void scr_patch::enable()
{ {
if (!m_enable) if (!m_enable)

View File

@ -2,7 +2,7 @@
namespace lua::scr_patch namespace lua::scr_patch
{ {
struct scr_patch class scr_patch
{ {
rage::joaat_t m_script; rage::joaat_t m_script;
std::string m_patch_name; std::string m_patch_name;
@ -21,6 +21,7 @@ namespace lua::scr_patch
// Param: patch_: table: The bytes to be written into the script's bytecode. // Param: patch_: table: The bytes to be written into the script's bytecode.
// Adds a patch for the specified script. // Adds a patch for the specified script.
explicit scr_patch(const std::string& script_name, const std::string& patch_name, const std::string& pattern, const int offset, sol::table patch_, sol::this_state state); explicit scr_patch(const std::string& script_name, const std::string& patch_name, const std::string& pattern, const int offset, sol::table patch_, sol::this_state state);
~scr_patch();
// Lua API: Function // Lua API: Function
// Class: scr_patch // Class: scr_patch

View File

@ -126,6 +126,7 @@ namespace big
{ {
std::lock_guard guard(m_registered_scripts_mutex); std::lock_guard guard(m_registered_scripts_mutex);
m_registered_scripts.clear(); m_registered_scripts.clear();
m_registered_script_patches.clear();
} }
for (const auto owned_tab : m_owned_tabs) for (const auto owned_tab : m_owned_tabs)

View File

@ -1,34 +1,39 @@
#pragma once #pragma once
#include "memory/pattern.hpp" #include "memory/pattern.hpp"
namespace big namespace big
{ {
struct script_data; struct script_data;
class script_patch class script_patch
{ {
rage::joaat_t m_script; rage::joaat_t m_script;
const memory::pattern m_pattern; const memory::pattern m_pattern;
std::string m_name; std::string m_name;
int32_t m_offset; int32_t m_offset;
std::vector<uint8_t> m_patch; std::vector<uint8_t> m_patch;
std::vector<uint8_t> m_original; std::vector<uint8_t> m_original;
bool* m_bool; bool* m_bool;
int32_t m_ip; int32_t m_ip;
static uint8_t* get_code_address(script_data* data, uint32_t index); static uint8_t* get_code_address(script_data* data, uint32_t index);
static const std::optional<uint32_t> get_code_location_by_pattern(script_data* data, const memory::pattern& pattern); static const std::optional<uint32_t> get_code_location_by_pattern(script_data* data, const memory::pattern& pattern);
public: public:
void enable(script_data* data); void enable(script_data* data);
void disable(script_data* data); void disable(script_data* data);
inline rage::joaat_t get_script() inline rage::joaat_t get_script()
{ {
return m_script; return m_script;
} }
script_patch(rage::joaat_t script, std::string name, const memory::pattern pattern, int32_t offset, std::vector<uint8_t> patch, bool* enable_bool); inline std::string get_name()
void update(script_data* data); {
}; return m_name;
}
script_patch(rage::joaat_t script, std::string name, const memory::pattern pattern, int32_t offset, std::vector<uint8_t> patch, bool* enable_bool);
void update(script_data* data);
};
} }

View File

@ -1,101 +1,116 @@
#include "script_patcher_service.hpp" #include "script_patcher_service.hpp"
#include "script_data.hpp" #include "script_data.hpp"
#include "script_patch.hpp" #include "script_patch.hpp"
#include <script/scrProgram.hpp> #include <script/scrProgram.hpp>
namespace big namespace big
{ {
script_patcher_service::script_patcher_service() script_patcher_service::script_patcher_service()
{ {
g_script_patcher_service = this; g_script_patcher_service = this;
} }
script_patcher_service::~script_patcher_service() script_patcher_service::~script_patcher_service()
{ {
m_script_data.clear(); m_script_data.clear();
m_script_patches.clear(); m_script_patches.clear();
g_script_patcher_service = nullptr; g_script_patcher_service = nullptr;
} }
script_data* script_patcher_service::get_data_for_script(rage::joaat_t script) script_data* script_patcher_service::get_data_for_script(rage::joaat_t script)
{ {
for (auto& p : m_script_data) for (auto& p : m_script_data)
{ {
if (p.first == script) if (p.first == script)
{ {
return p.second.get(); return p.second.get();
} }
} }
return nullptr; return nullptr;
} }
bool script_patcher_service::does_script_have_patches(rage::joaat_t script) bool script_patcher_service::does_script_have_patches(rage::joaat_t script)
{ {
for (auto& p : m_script_patches) for (auto& p : m_script_patches)
{ {
if (p.get_script() == script) if (p.get_script() == script)
return true; return true;
} }
return false; return false;
} }
void script_patcher_service::create_data_for_script(rage::scrProgram* program) void script_patcher_service::create_data_for_script(rage::scrProgram* program)
{ {
auto pages = new uint8_t*[program->get_num_code_pages()]; auto pages = new uint8_t*[program->get_num_code_pages()];
for (auto i = 0u; i < program->get_num_code_pages(); i++) for (auto i = 0u; i < program->get_num_code_pages(); i++)
{ {
pages[i] = new uint8_t[program->get_code_page_size(i)]; pages[i] = new uint8_t[program->get_code_page_size(i)];
std::memcpy(pages[i], program->get_code_page(i), program->get_code_page_size(i)); std::memcpy(pages[i], program->get_code_page(i), program->get_code_page_size(i));
} }
m_script_data.emplace(program->m_name_hash, std::make_unique<script_data>(program->m_code_size, pages, program->get_num_code_pages())); m_script_data.emplace(program->m_name_hash, std::make_unique<script_data>(program->m_code_size, pages, program->get_num_code_pages()));
} }
void script_patcher_service::update_all_patches_for_script(rage::joaat_t script) void script_patcher_service::update_all_patches_for_script(rage::joaat_t script)
{ {
auto data = get_data_for_script(script); auto data = get_data_for_script(script);
for (auto& p : m_script_patches) for (auto& p : m_script_patches)
if (p.get_script() == script) if (p.get_script() == script)
p.update(data); p.update(data);
} }
void script_patcher_service::add_patch(script_patch&& patch) void script_patcher_service::add_patch(script_patch&& patch)
{ {
m_script_patches.push_back(std::move(patch)); m_script_patches.push_back(std::move(patch));
} }
void script_patcher_service::on_script_load(rage::scrProgram* program) void script_patcher_service::remove_patch(std::string_view patch_name)
{ {
if (get_data_for_script(program->m_name_hash) == nullptr && does_script_have_patches(program->m_name_hash)) for (auto it = m_script_patches.begin(); it != m_script_patches.end();)
{ {
create_data_for_script(program); if (it->get_name() == patch_name)
update_all_patches_for_script(program->m_name_hash); {
} it = m_script_patches.erase(it);
} }
else
uint8_t** script_patcher_service::get_script_bytecode(rage::joaat_t script) {
{ ++it;
if (auto data = get_data_for_script(script)) }
return data->m_bytecode; }
}
return nullptr;
} void script_patcher_service::on_script_load(rage::scrProgram* program)
{
void script_patcher_service::update() if (get_data_for_script(program->m_name_hash) == nullptr && does_script_have_patches(program->m_name_hash))
{ {
for (auto& p : m_script_patches) create_data_for_script(program);
{ update_all_patches_for_script(program->m_name_hash);
auto data = get_data_for_script(p.get_script()); }
if (data) }
{
p.update(data); uint8_t** script_patcher_service::get_script_bytecode(rage::joaat_t script)
} {
} if (auto data = get_data_for_script(script))
} return data->m_bytecode;
return nullptr;
}
void script_patcher_service::update()
{
for (auto& p : m_script_patches)
{
auto data = get_data_for_script(p.get_script());
if (data)
{
p.update(data);
}
}
}
} }

View File

@ -9,7 +9,7 @@ namespace big
{ {
class script_patcher_service class script_patcher_service
{ {
std::vector<script_patch> m_script_patches; std::list<script_patch> m_script_patches;
std::unordered_map<rage::joaat_t, std::unique_ptr<script_data>> m_script_data; std::unordered_map<rage::joaat_t, std::unique_ptr<script_data>> m_script_data;
script_data* get_data_for_script(rage::joaat_t script); script_data* get_data_for_script(rage::joaat_t script);
bool does_script_have_patches(rage::joaat_t script); bool does_script_have_patches(rage::joaat_t script);
@ -20,6 +20,7 @@ namespace big
~script_patcher_service(); ~script_patcher_service();
void add_patch(script_patch&& patch); void add_patch(script_patch&& patch);
void remove_patch(std::string_view patch_name);
void on_script_load(rage::scrProgram* program); void on_script_load(rage::scrProgram* program);
uint8_t** get_script_bytecode(rage::joaat_t script); uint8_t** get_script_bytecode(rage::joaat_t script);
void update_all_patches_for_script(rage::joaat_t script); void update_all_patches_for_script(rage::joaat_t script);