mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2026-10-10 03:43:07 +08:00
fix call_hook crash with FSL and script function hook improvements (#223)
This commit is contained in:
@@ -2,7 +2,21 @@
|
|||||||
|
|
||||||
Class for wrapping arguments and return values of GTA script functions, used by add_script_function_hook.
|
Class for wrapping arguments and return values of GTA script functions, used by add_script_function_hook.
|
||||||
|
|
||||||
## Functions (6)
|
## Functions (10)
|
||||||
|
|
||||||
|
### `get_count()`
|
||||||
|
|
||||||
|
Get the total number of elements in the wrapper.
|
||||||
|
|
||||||
|
- **Returns:**
|
||||||
|
- `int`: The number of elements in the wrapper.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
count = scr_value_wrapper:get_count()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `get_int()`
|
### `get_int()`
|
||||||
|
|
||||||
@@ -36,6 +50,38 @@ scr_value_wrapper:set_int(0, 42)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `get_uns()`
|
||||||
|
|
||||||
|
Get the unsigned int value currently contained by the wrapper.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `index` (int): The index to access.
|
||||||
|
|
||||||
|
- **Returns:**
|
||||||
|
- `int`: The current unsigned value.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
value = scr_value_wrapper:get_uns(0)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `set_uns()`
|
||||||
|
|
||||||
|
Set the unsigned int value contained by the wrapper.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `index` (int): The index to access.
|
||||||
|
- `value` (int): The new unsigned value.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
scr_value_wrapper:set_uns(0, 42)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `get_float()`
|
### `get_float()`
|
||||||
|
|
||||||
Get the float value currently contained by the wrapper.
|
Get the float value currently contained by the wrapper.
|
||||||
@@ -97,3 +143,20 @@ Set the string value contained by the wrapper.
|
|||||||
```lua
|
```lua
|
||||||
scr_value_wrapper:set_string(0, "hello")
|
scr_value_wrapper:set_string(0, "hello")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `get_reference()`
|
||||||
|
|
||||||
|
Get the reference value currently contained by the wrapper.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `index` (int): The index to access.
|
||||||
|
|
||||||
|
- **Returns:**
|
||||||
|
- `class`: The current value.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
value = scr_value_wrapper:get_reference(0)
|
||||||
|
```
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Table for calling and hooking GTA script functions. Calls must be made in the fiber pool.
|
Table for calling and hooking GTA script functions. Calls must be made in the fiber pool.
|
||||||
|
|
||||||
## Functions (4)
|
## Functions (5)
|
||||||
|
|
||||||
### `call_script_function(script_name, function_name, pattern, return_type_string, args_)`
|
### `call_script_function(script_name, function_name, pattern, return_type_string, args_)`
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ Hooks a script function. If the callback returns `false`, the original function
|
|||||||
- `script_name` (string): Name of the script.
|
- `script_name` (string): Name of the script.
|
||||||
- `hook_name` (string): Name of the hook. This parameter needs to be unique.
|
- `hook_name` (string): Name of the hook. This parameter needs to be unique.
|
||||||
- `pattern` (string): Pattern to scan for within the script.
|
- `pattern` (string): Pattern to scan for within the script.
|
||||||
- `hook_func` (string): The callback function. It receives args and rets, which can be read or set via `get/set_int/float/string` methods. Return value determines whether to skip or execute the original function.
|
- `hook_func` (string): The callback function. It receives args and rets, which can be read or set via `get/set_int/uns/float/string/reference` methods. Return value determines whether to skip or execute the original function.
|
||||||
|
|
||||||
**Example Usage:**
|
**Example Usage:**
|
||||||
```lua
|
```lua
|
||||||
@@ -71,6 +71,28 @@ scr_function.add_script_function_hook("some_script", "my_hook", "2D 00 ? ? 00 61
|
|||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `add_script_function_hook(script_name, hook_name, instruction_pointer, hook_func)`
|
||||||
|
|
||||||
|
Hooks a script function directly using the function position. If the callback returns `false`, the original function is skipped, and values in `rets` are pushed to the stack. If `true`, the original function executes normally.
|
||||||
|
|
||||||
|
- **Parameters:**
|
||||||
|
- `script_name` (string): Name of the script.
|
||||||
|
- `hook_name` (string): Name of the hook. This parameter needs to be unique.
|
||||||
|
- `instruction_pointer` (int): Position of the function within the script.
|
||||||
|
- `hook_func` (string): The callback function. It receives args and rets, which can be read or set via `get/set_int/uns/float/string/reference` methods. Return value determines whether to skip or execute the original function.
|
||||||
|
|
||||||
|
**Example Usage:**
|
||||||
|
```lua
|
||||||
|
scr_function.add_script_function_hook("some_script", "my_hook", 0x10BE, function(args, rets)
|
||||||
|
local val = args:get_int(0)
|
||||||
|
if val == 1 then
|
||||||
|
rets:set_int(0, 100)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
### `remove_script_function_hook(script_name, hook_name)`
|
### `remove_script_function_hook(script_name, hook_name)`
|
||||||
|
|
||||||
Removes an existing script function hook.
|
Removes an existing script function hook.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace big
|
|||||||
{
|
{
|
||||||
call_hook_memory::call_hook_memory()
|
call_hook_memory::call_hook_memory()
|
||||||
{
|
{
|
||||||
m_memory = VirtualAlloc((void*)((uintptr_t)GetModuleHandle(0) + 0x20000000), 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
m_memory = VirtualAlloc((void*)((uintptr_t)GetModuleHandle(0) + 0x40000000), 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace lua::scr_function
|
|||||||
|
|
||||||
// Lua API: Table
|
// Lua API: Table
|
||||||
// Name: scr_function
|
// Name: scr_function
|
||||||
// Table for calling GTA script functions. Needs to be called in the fiber pool. Only call the function when necessary.
|
// Table for calling and hooking GTA script functions. Calls must be made in the fiber pool.
|
||||||
|
|
||||||
// Lua API: function
|
// Lua API: function
|
||||||
// Table: scr_function
|
// Table: scr_function
|
||||||
@@ -358,22 +358,34 @@ namespace lua::scr_function
|
|||||||
class scr_value_wrapper_t
|
class scr_value_wrapper_t
|
||||||
{
|
{
|
||||||
rage::scrValue* m_data;
|
rage::scrValue* m_data;
|
||||||
|
std::uint32_t m_count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
scr_value_wrapper_t(rage::scrValue* data) :
|
scr_value_wrapper_t(rage::scrValue* data, std::uint32_t count) :
|
||||||
m_data(data)
|
m_data(data),
|
||||||
|
m_count(count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lua API: Function
|
||||||
|
// Class: scr_value_wrapper
|
||||||
|
// Name: get_count
|
||||||
|
// Returns: int: The number of elements in the wrapper.
|
||||||
|
// Get the total number of elements in the wrapper.
|
||||||
|
std::uint32_t get_count()
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
// Lua API: Function
|
// Lua API: Function
|
||||||
// Class: scr_value_wrapper
|
// Class: scr_value_wrapper
|
||||||
// Name: get_int
|
// Name: get_int
|
||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Returns: int: The current value.
|
// Returns: int: The current value.
|
||||||
// Get the int value currently contained by the wrapper.
|
// Get the int value currently contained by the wrapper.
|
||||||
int get_int(int index)
|
std::int32_t get_int(std::uint32_t index)
|
||||||
{
|
{
|
||||||
return m_data[index].Int;
|
return index < m_count ? m_data[index].Int : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua API: Function
|
// Lua API: Function
|
||||||
@@ -382,20 +394,44 @@ namespace lua::scr_function
|
|||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Param: value: int: The new value.
|
// Param: value: int: The new value.
|
||||||
// Set the int value contained by the wrapper.
|
// Set the int value contained by the wrapper.
|
||||||
void set_int(int index, int value)
|
void set_int(std::uint32_t index, std::int32_t value)
|
||||||
{
|
{
|
||||||
|
if (index < m_count)
|
||||||
m_data[index].Int = value;
|
m_data[index].Int = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lua API: Function
|
||||||
|
// Class: scr_value_wrapper
|
||||||
|
// Name: get_uns
|
||||||
|
// Param: index: int: The index to access.
|
||||||
|
// Returns: int: The current unsigned value.
|
||||||
|
// Get the unsigned int value currently contained by the wrapper.
|
||||||
|
std::uint32_t get_uns(std::uint32_t index)
|
||||||
|
{
|
||||||
|
return index < m_count ? m_data[index].Uns : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lua API: Function
|
||||||
|
// Class: scr_value_wrapper
|
||||||
|
// Name: set_uns
|
||||||
|
// Param: index: int: The index to access.
|
||||||
|
// Param: value: int: The new unsigned value.
|
||||||
|
// Set the unsigned int value contained by the wrapper.
|
||||||
|
void set_uns(std::uint32_t index, std::uint32_t value)
|
||||||
|
{
|
||||||
|
if (index < m_count)
|
||||||
|
m_data[index].Uns = value;
|
||||||
|
}
|
||||||
|
|
||||||
// Lua API: Function
|
// Lua API: Function
|
||||||
// Class: scr_value_wrapper
|
// Class: scr_value_wrapper
|
||||||
// Name: get_float
|
// Name: get_float
|
||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Returns: float: The current value.
|
// Returns: float: The current value.
|
||||||
// Get the float value currently contained by the wrapper.
|
// Get the float value currently contained by the wrapper.
|
||||||
float get_float(int index)
|
float get_float(std::uint32_t index)
|
||||||
{
|
{
|
||||||
return m_data[index].Float;
|
return index < m_count ? m_data[index].Float : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua API: Function
|
// Lua API: Function
|
||||||
@@ -404,8 +440,9 @@ namespace lua::scr_function
|
|||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Param: value: float: The new value.
|
// Param: value: float: The new value.
|
||||||
// Set the float value contained by the wrapper.
|
// Set the float value contained by the wrapper.
|
||||||
void set_float(int index, float value)
|
void set_float(std::uint32_t index, float value)
|
||||||
{
|
{
|
||||||
|
if (index < m_count)
|
||||||
m_data[index].Float = value;
|
m_data[index].Float = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,9 +452,9 @@ namespace lua::scr_function
|
|||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Returns: string: The current value.
|
// Returns: string: The current value.
|
||||||
// Get the string value currently contained by the wrapper.
|
// Get the string value currently contained by the wrapper.
|
||||||
const char* get_string(int index)
|
const char* get_string(std::uint32_t index)
|
||||||
{
|
{
|
||||||
return m_data[index].String;
|
return index < m_count ? m_data[index].String : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua API: Function
|
// Lua API: Function
|
||||||
@@ -426,10 +463,22 @@ namespace lua::scr_function
|
|||||||
// Param: index: int: The index to access.
|
// Param: index: int: The index to access.
|
||||||
// Param: value: string: The new value.
|
// Param: value: string: The new value.
|
||||||
// Set the string value contained by the wrapper.
|
// Set the string value contained by the wrapper.
|
||||||
void set_string(int index, const char* value)
|
void set_string(std::uint32_t index, const char* value)
|
||||||
{
|
{
|
||||||
|
if (index < m_count)
|
||||||
m_data[index].String = value;
|
m_data[index].String = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lua API: Function
|
||||||
|
// Class: scr_value_wrapper
|
||||||
|
// Name: get_reference
|
||||||
|
// Param: index: int: The index to access.
|
||||||
|
// Returns: class: The current value.
|
||||||
|
// Get the reference value currently contained by the wrapper.
|
||||||
|
scr_value_wrapper_t get_reference(std::uint32_t index)
|
||||||
|
{
|
||||||
|
return index < m_count ? scr_value_wrapper_t(m_data[index].Reference, m_count) : scr_value_wrapper_t(nullptr, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lua API: function
|
// Lua API: function
|
||||||
@@ -451,11 +500,44 @@ namespace lua::scr_function
|
|||||||
// return true
|
// return true
|
||||||
// end)
|
// end)
|
||||||
// ```
|
// ```
|
||||||
static void add_script_function_hook(const std::string& script_name, const std::string& hook_name, const std::string& pattern, sol::protected_function hook_func)
|
static void add_script_function_hook_by_signature(const std::string& script_name, const std::string& hook_name, const std::string& pattern, sol::protected_function hook_func)
|
||||||
{
|
{
|
||||||
big::g_script_function_hook_service->add_hook(rage::joaat(script_name), hook_name, pattern, [hook_func](rage::scrValue* args, rage::scrValue* rets) -> bool {
|
big::g_script_function_hook_service->add_hook(rage::joaat(script_name), hook_name, pattern, [hook_func](rage::scrValue* args, const std::uint32_t argCount, rage::scrValue* rets, const std::uint32_t retCount) -> bool {
|
||||||
scr_value_wrapper_t lua_args(args);
|
scr_value_wrapper_t lua_args(args, argCount);
|
||||||
scr_value_wrapper_t lua_rets(rets);
|
scr_value_wrapper_t lua_rets(rets, retCount);
|
||||||
|
|
||||||
|
auto result = hook_func(lua_args, lua_rets);
|
||||||
|
if (!result.valid())
|
||||||
|
return true; // don't skip the original if lua fails
|
||||||
|
|
||||||
|
return result.get<bool>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lua API: function
|
||||||
|
// Table: scr_function
|
||||||
|
// Name: add_script_function_hook
|
||||||
|
// Param: script_name: string: Name of the script.
|
||||||
|
// Param: hook_name: string: Name of the hook. This parameter needs to be unique.
|
||||||
|
// Param: instruction_pointer: integer: Position of the function within the script.
|
||||||
|
// Param: hook_func: function: The callback function. It receives args and rets, which can be read or set via `get/set_int/float/string` methods. Return value determines whether to skip or execute the original function.
|
||||||
|
// Hooks a script function directly using the function position. If the callback returns `false`, the original function is skipped, and values in `rets` are pushed to the stack. If `true`, the original function executes normally.
|
||||||
|
// **Example Usage:**
|
||||||
|
// ```lua
|
||||||
|
// scr_function.add_script_function_hook("some_script", "my_hook", 0x10BE, function(args, rets)
|
||||||
|
// local val = args:get_int(0)
|
||||||
|
// if val == 1 then
|
||||||
|
// rets:set_int(0, 100)
|
||||||
|
// return false
|
||||||
|
// end
|
||||||
|
// return true
|
||||||
|
// end)
|
||||||
|
// ```
|
||||||
|
static void add_script_function_hook_by_instruction_pointer(const std::string& script_name, const std::string& hook_name, const std::uint32_t instruction_pointer, sol::protected_function hook_func)
|
||||||
|
{
|
||||||
|
big::g_script_function_hook_service->add_hook(rage::joaat(script_name), hook_name, instruction_pointer, [hook_func](rage::scrValue* args, const std::uint32_t argCount, rage::scrValue* rets, const std::uint32_t retCount) -> bool {
|
||||||
|
scr_value_wrapper_t lua_args(args, argCount);
|
||||||
|
scr_value_wrapper_t lua_rets(rets, retCount);
|
||||||
|
|
||||||
auto result = hook_func(lua_args, lua_rets);
|
auto result = hook_func(lua_args, lua_rets);
|
||||||
if (!result.valid())
|
if (!result.valid())
|
||||||
@@ -484,17 +566,21 @@ namespace lua::scr_function
|
|||||||
{
|
{
|
||||||
auto ut = state.new_usertype<scr_value_wrapper_t>("scr_value_wrapper");
|
auto ut = state.new_usertype<scr_value_wrapper_t>("scr_value_wrapper");
|
||||||
|
|
||||||
|
ut["get_count"] = &scr_value_wrapper_t::get_count;
|
||||||
ut["get_int"] = &scr_value_wrapper_t::get_int;
|
ut["get_int"] = &scr_value_wrapper_t::get_int;
|
||||||
ut["set_int"] = &scr_value_wrapper_t::set_int;
|
ut["set_int"] = &scr_value_wrapper_t::set_int;
|
||||||
|
ut["get_uns"] = &scr_value_wrapper_t::get_uns;
|
||||||
|
ut["set_uns"] = &scr_value_wrapper_t::set_uns;
|
||||||
ut["get_float"] = &scr_value_wrapper_t::get_float;
|
ut["get_float"] = &scr_value_wrapper_t::get_float;
|
||||||
ut["set_float"] = &scr_value_wrapper_t::set_float;
|
ut["set_float"] = &scr_value_wrapper_t::set_float;
|
||||||
ut["get_string"] = &scr_value_wrapper_t::get_string;
|
ut["get_string"] = &scr_value_wrapper_t::get_string;
|
||||||
ut["set_string"] = &scr_value_wrapper_t::set_string;
|
ut["set_string"] = &scr_value_wrapper_t::set_string;
|
||||||
|
ut["get_reference"] = &scr_value_wrapper_t::get_reference;
|
||||||
|
|
||||||
auto ns = state["scr_function"].get_or_create<sol::table>();
|
auto ns = state["scr_function"].get_or_create<sol::table>();
|
||||||
|
|
||||||
ns["call_script_function"] = sol::overload(call_script_function_by_signature, call_script_function_by_instruction_pointer);
|
ns["call_script_function"] = sol::overload(call_script_function_by_signature, call_script_function_by_instruction_pointer);
|
||||||
ns["add_script_function_hook"] = add_script_function_hook;
|
ns["add_script_function_hook"] = sol::overload(add_script_function_hook_by_signature, add_script_function_hook_by_instruction_pointer);
|
||||||
ns["remove_script_function_hook"] = remove_script_function_hook;
|
ns["remove_script_function_hook"] = remove_script_function_hook;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,6 @@ script_vm_on_enter_end_handler PROC
|
|||||||
mov [rsp + 20h], r15 ; ctx
|
mov [rsp + 20h], r15 ; ctx
|
||||||
mov [rsp + 28h], r13 ; code
|
mov [rsp + 28h], r13 ; code
|
||||||
call process_script_function_hooks
|
call process_script_function_hooks
|
||||||
|
|
||||||
add rsp, 30h
|
add rsp, 30h
|
||||||
|
|
||||||
; restore stuff
|
; restore stuff
|
||||||
|
|||||||
@@ -38,10 +38,13 @@ namespace big
|
|||||||
g_script_function_hook_service = nullptr;
|
g_script_function_hook_service = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function_hook_service::process_hook(const function_hook& hook, std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, std::uint8_t** code)
|
void script_function_hook_service::process_hook(function_hook& hook, std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, std::uint8_t** code)
|
||||||
{
|
{
|
||||||
|
// prevent reentrancy in case the hook calls the original function via the script_function class
|
||||||
|
hook.m_active = true;
|
||||||
|
|
||||||
rage::scrValue ret_val[256]{};
|
rage::scrValue ret_val[256]{};
|
||||||
if (!hook.m_hook_func(fp, ret_val))
|
if (!hook.m_hook_func(fp, hook.m_arg_count, ret_val, hook.m_ret_count))
|
||||||
{
|
{
|
||||||
// push return value onto stack
|
// push return value onto stack
|
||||||
for (std::uint32_t i = 0; i < hook.m_ret_count; i++)
|
for (std::uint32_t i = 0; i < hook.m_ret_count; i++)
|
||||||
@@ -52,9 +55,14 @@ namespace big
|
|||||||
ip = &code[offset >> 14][offset & 0x3FFF] - 1;
|
ip = &code[offset >> 14][offset & 0x3FFF] - 1;
|
||||||
base = &ip[-offset];
|
base = &ip[-offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook.m_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_function_hook_service::resolve_hook(function_hook& hook, rage::scrProgram* program)
|
void script_function_hook_service::resolve_hook(function_hook& hook, rage::scrProgram* program)
|
||||||
|
{
|
||||||
|
std::uint32_t entry_ip = hook.m_start_ip;
|
||||||
|
if (entry_ip == 0)
|
||||||
{
|
{
|
||||||
auto location = scripts::get_code_location_by_pattern(program, memory::pattern(hook.m_pattern));
|
auto location = scripts::get_code_location_by_pattern(program, memory::pattern(hook.m_pattern));
|
||||||
if (!location)
|
if (!location)
|
||||||
@@ -64,8 +72,10 @@ namespace big
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG(VERBOSE) << "Found pattern " << hook.m_name << " at " << HEX_TO_UPPER(*location) << " in script " << program->m_name;
|
LOG(VERBOSE) << "Found pattern " << hook.m_name << " at " << HEX_TO_UPPER(*location) << " in script " << program->m_name;
|
||||||
|
entry_ip = *location;
|
||||||
|
}
|
||||||
|
|
||||||
std::uint32_t post_enter = *location + scripts::get_insn_size(program, *location);
|
std::uint32_t post_enter = entry_ip + scripts::get_insn_size(program, entry_ip);
|
||||||
std::uint32_t pos = post_enter;
|
std::uint32_t pos = post_enter;
|
||||||
|
|
||||||
while (pos < program->m_code_size)
|
while (pos < program->m_code_size)
|
||||||
@@ -83,6 +93,7 @@ namespace big
|
|||||||
{
|
{
|
||||||
hook.m_start_ip = post_enter;
|
hook.m_start_ip = post_enter;
|
||||||
hook.m_end_ip = pos;
|
hook.m_end_ip = pos;
|
||||||
|
hook.m_arg_count = op[1];
|
||||||
hook.m_ret_count = op[2];
|
hook.m_ret_count = op[2];
|
||||||
hook.m_resolved = true;
|
hook.m_resolved = true;
|
||||||
break;
|
break;
|
||||||
@@ -95,9 +106,9 @@ namespace big
|
|||||||
|
|
||||||
void script_function_hook_service::process_hooks(std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, rage::scrThreadContext* ctx, std::uint8_t** code)
|
void script_function_hook_service::process_hooks(std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, rage::scrThreadContext* ctx, std::uint8_t** code)
|
||||||
{
|
{
|
||||||
for (const auto& hook : m_hooks)
|
for (auto& hook : m_hooks)
|
||||||
{
|
{
|
||||||
if (!hook.m_resolved || hook.m_script != ctx->m_script_hash || hook.m_start_ip != static_cast<std::uint32_t>(ip - base))
|
if (!hook.m_resolved || hook.m_active || hook.m_script != ctx->m_script_hash || hook.m_start_ip != static_cast<std::uint32_t>(ip - base))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
process_hook(hook, ip, base, sp, fp, code);
|
process_hook(hook, ip, base, sp, fp, code);
|
||||||
@@ -137,6 +148,28 @@ namespace big
|
|||||||
m_hooks.push_back(hook);
|
m_hooks.push_back(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void script_function_hook_service::add_hook(rage::joaat_t script, const std::string& name, std::uint32_t ip, const hook_func& hook_func)
|
||||||
|
{
|
||||||
|
// prevent duplicates
|
||||||
|
for (const auto& hook : m_hooks)
|
||||||
|
{
|
||||||
|
if (hook.m_script == script && hook.m_name == name)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function_hook hook{};
|
||||||
|
hook.m_script = script;
|
||||||
|
hook.m_name = name;
|
||||||
|
hook.m_start_ip = ip; // init with entry IP now, we will update it to point to post-enter in resolve_hook
|
||||||
|
hook.m_hook_func = hook_func;
|
||||||
|
|
||||||
|
// if the program is already available, set the data now, otherwise we will try in init_native_tables
|
||||||
|
if (auto program = gta_util::find_script_program(script))
|
||||||
|
resolve_hook(hook, program);
|
||||||
|
|
||||||
|
m_hooks.push_back(hook);
|
||||||
|
}
|
||||||
|
|
||||||
void script_function_hook_service::remove_hook(rage::joaat_t script, const std::string& name)
|
void script_function_hook_service::remove_hook(rage::joaat_t script, const std::string& name)
|
||||||
{
|
{
|
||||||
m_hooks.erase(std::remove_if(m_hooks.begin(), m_hooks.end(), [&](const function_hook& hook) {
|
m_hooks.erase(std::remove_if(m_hooks.begin(), m_hooks.end(), [&](const function_hook& hook) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace big
|
|||||||
class script_function_hook_service
|
class script_function_hook_service
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using hook_func = std::function<bool(rage::scrValue*, rage::scrValue*)>;
|
using hook_func = std::function<bool(rage::scrValue* args, const std::uint32_t argCount, rage::scrValue* rets, const std::uint32_t retCount)>;
|
||||||
|
|
||||||
script_function_hook_service();
|
script_function_hook_service();
|
||||||
~script_function_hook_service();
|
~script_function_hook_service();
|
||||||
@@ -20,6 +20,7 @@ namespace big
|
|||||||
void process_hooks(std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, rage::scrThreadContext* ctx, std::uint8_t** code);
|
void process_hooks(std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, rage::scrThreadContext* ctx, std::uint8_t** code);
|
||||||
void resolve_hooks(rage::scrProgram* program);
|
void resolve_hooks(rage::scrProgram* program);
|
||||||
void add_hook(rage::joaat_t script, const std::string& name, const std::string& pattern, const hook_func& hook_func);
|
void add_hook(rage::joaat_t script, const std::string& name, const std::string& pattern, const hook_func& hook_func);
|
||||||
|
void add_hook(rage::joaat_t script, const std::string& name, std::uint32_t ip, const hook_func& hook_func);
|
||||||
void remove_hook(rage::joaat_t script, const std::string& name);
|
void remove_hook(rage::joaat_t script, const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -30,12 +31,14 @@ namespace big
|
|||||||
std::string m_pattern;
|
std::string m_pattern;
|
||||||
std::uint32_t m_start_ip;
|
std::uint32_t m_start_ip;
|
||||||
std::uint32_t m_end_ip;
|
std::uint32_t m_end_ip;
|
||||||
|
std::uint32_t m_arg_count;
|
||||||
std::uint32_t m_ret_count;
|
std::uint32_t m_ret_count;
|
||||||
hook_func m_hook_func;
|
hook_func m_hook_func;
|
||||||
bool m_resolved;
|
bool m_resolved;
|
||||||
|
bool m_active;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void process_hook(const function_hook& hook, std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, std::uint8_t** code);
|
static void process_hook(function_hook& hook, std::uint8_t*& ip, std::uint8_t*& base, rage::scrValue*& sp, rage::scrValue* fp, std::uint8_t** code);
|
||||||
static void resolve_hook(function_hook& hook, rage::scrProgram* program);
|
static void resolve_hook(function_hook& hook, rage::scrProgram* program);
|
||||||
|
|
||||||
std::vector<function_hook> m_hooks;
|
std::vector<function_hook> m_hooks;
|
||||||
|
|||||||
Reference in New Issue
Block a user