fix scripting_extension somehow?
This commit is contained in:
parent
dda06366e3
commit
38a0003ac7
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
namespace gsc
|
namespace gsc
|
||||||
{
|
{
|
||||||
std::uint16_t function_id_start = 0x326;
|
std::uint16_t function_id_start = 806;
|
||||||
std::uint16_t method_id_start = 0x85DB;
|
std::uint16_t method_id_start = 1483 + 0x8000;
|
||||||
|
|
||||||
constexpr size_t func_table_count = 0x1000;
|
constexpr size_t func_table_count = 0x1000;
|
||||||
constexpr size_t meth_table_count = 0x1000;
|
constexpr size_t meth_table_count = 0x1000;
|
||||||
@ -68,6 +68,9 @@ namespace gsc
|
|||||||
reinterpret_cast<size_t>(pos - 2));
|
reinterpret_cast<size_t>(pos - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nullstub_func() {}
|
||||||
|
void nullstub_meth(game::scr_entref_t) {}
|
||||||
|
|
||||||
void execute_custom_function(const std::uint16_t id)
|
void execute_custom_function(const std::uint16_t id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -87,8 +90,9 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_call_builtin_function_internal(int function_id)
|
void vm_call_builtin_function_internal()
|
||||||
{
|
{
|
||||||
|
const std::uint16_t function_id = get_function_id();
|
||||||
const auto custom_function_id = static_cast<std::uint16_t>(function_id); // cast for gsc-tool & our custom func map
|
const auto custom_function_id = static_cast<std::uint16_t>(function_id); // cast for gsc-tool & our custom func map
|
||||||
const auto custom = functions.contains(custom_function_id);
|
const auto custom = functions.contains(custom_function_id);
|
||||||
if (custom)
|
if (custom)
|
||||||
@ -100,25 +104,13 @@ namespace gsc
|
|||||||
builtin_function func = func_table[function_id - 1]; // game does this for the stock func table
|
builtin_function func = func_table[function_id - 1]; // game does this for the stock func table
|
||||||
if (func == nullptr)
|
if (func == nullptr)
|
||||||
{
|
{
|
||||||
scr_error(utils::string::va("builtin function \"%s\" doesn't exist", gsc_ctx->func_name(custom_function_id).data()), true);
|
scr_error(utils::string::va("builtin function \"%s\" doesn't exist", gsc_ctx->func_name(function_id).data()), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_call_builtin_function_stub(utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.pushad64();
|
|
||||||
a.push(rcx);
|
|
||||||
a.mov(rcx, rcx); // function id is already in rcx
|
|
||||||
a.call_aligned(vm_call_builtin_function_internal);
|
|
||||||
a.pop(rcx);
|
|
||||||
a.popad64();
|
|
||||||
|
|
||||||
a.jmp(0xC0E8F9_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_custom_method(const std::uint16_t id, game::scr_entref_t ent_ref)
|
void execute_custom_method(const std::uint16_t id, game::scr_entref_t ent_ref)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -138,46 +130,11 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_call_builtin_method_internal(game::scr_entref_t ent_ref, int function_id)
|
|
||||||
{
|
|
||||||
const auto custom_function_id = static_cast<std::uint16_t>(function_id); // cast for gsc-tool & our custom method map
|
|
||||||
const auto custom = methods.contains(custom_function_id);
|
|
||||||
if (custom)
|
|
||||||
{
|
|
||||||
execute_custom_method(custom_function_id, ent_ref);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
builtin_method meth = meth_table[function_id - 0x8000];
|
|
||||||
if (meth == nullptr)
|
|
||||||
{
|
|
||||||
scr_error(utils::string::va("builtin method \"%s\" doesn't exist", gsc_ctx->meth_name(custom_function_id).data()), true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
meth(ent_ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vm_call_builtin_method_stub(utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.pushad64();
|
|
||||||
a.push(rdx);
|
|
||||||
a.push(ecx);
|
|
||||||
a.mov(rdx, rdi); // function id is stored in rdi
|
|
||||||
a.mov(ecx, ebx); // ent ref is stored in ebx
|
|
||||||
a.call_aligned(vm_call_builtin_method_internal);
|
|
||||||
a.pop(rdx);
|
|
||||||
a.pop(ecx);
|
|
||||||
a.popad64();
|
|
||||||
|
|
||||||
a.jmp(0xC0E8F9_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void builtin_call_error(const std::string& error)
|
void builtin_call_error(const std::string& error)
|
||||||
{
|
{
|
||||||
const auto function_id = get_function_id();
|
const auto function_id = get_function_id();
|
||||||
|
|
||||||
if (function_id > 0x1000)
|
if (function_id > func_table_count)
|
||||||
{
|
{
|
||||||
console::warn("in call to builtin method \"%s\"%s", gsc_ctx->meth_name(function_id).data(), error.data());
|
console::warn("in call to builtin method \"%s\"%s", gsc_ctx->meth_name(function_id).data(), error.data());
|
||||||
}
|
}
|
||||||
@ -218,13 +175,12 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_error_stub(int mark_pos)
|
void vm_error_internal()
|
||||||
{
|
{
|
||||||
const bool dev_script = developer_script ? developer_script->current.enabled : false;
|
const bool dev_script = developer_script ? developer_script->current.enabled : false;
|
||||||
|
|
||||||
if (!dev_script && !force_error_print)
|
if (!dev_script && !force_error_print)
|
||||||
{
|
{
|
||||||
utils::hook::invoke<void>(0x510C80_b, mark_pos);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +214,17 @@ namespace gsc
|
|||||||
|
|
||||||
print_callstack();
|
print_callstack();
|
||||||
console::warn("**********************************************\n");
|
console::warn("**********************************************\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_error_stub(__int64 mark_pos)
|
||||||
|
{
|
||||||
|
vm_error_internal();
|
||||||
|
|
||||||
|
if (!game::CL_IsGameClientActive(0))
|
||||||
|
{
|
||||||
|
//return game::Com_Error(game::errorParm::ERR_SCRIPT_DROP, gsc_error_msg.has_value() ? gsc_error_msg.value().data() : "Fatal script error");
|
||||||
|
}
|
||||||
|
|
||||||
utils::hook::invoke<void>(0x510C80_b, mark_pos);
|
utils::hook::invoke<void>(0x510C80_b, mark_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,11 +294,7 @@ namespace gsc
|
|||||||
force_error_print = force_print;
|
force_error_print = force_print;
|
||||||
gsc_error_msg = error;
|
gsc_error_msg = error;
|
||||||
|
|
||||||
// TODO: check why Scr_ErrorInternal crashes the game
|
game::Scr_ErrorInternal();
|
||||||
// is the longjmp actually happening? we're crashing at 0x140C0AC76 at a random 0xCC???
|
|
||||||
//game::Scr_ErrorInternal();
|
|
||||||
|
|
||||||
console::error("%s\n", error); // remove once we can actually get errors working
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace function
|
namespace function
|
||||||
@ -395,6 +358,41 @@ namespace gsc
|
|||||||
return {this->values_[index], index};
|
return {this->values_[index], index};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_call_builtin_method_internal(game::scr_entref_t ent_ref, int function_id)
|
||||||
|
{
|
||||||
|
const auto custom_function_id = static_cast<std::uint16_t>(function_id); // cast for gsc-tool & our custom method map
|
||||||
|
const auto custom = methods.contains(custom_function_id);
|
||||||
|
if (custom)
|
||||||
|
{
|
||||||
|
execute_custom_method(custom_function_id, ent_ref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builtin_method meth = meth_table[function_id - 0x8000];
|
||||||
|
if (meth == nullptr)
|
||||||
|
{
|
||||||
|
scr_error(utils::string::va("builtin method \"%s\" doesn't exist", gsc_ctx->meth_name(custom_function_id).data()), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meth(ent_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_call_builtin_method_stub(utils::hook::assembler& a)
|
||||||
|
{
|
||||||
|
a.pushad64();
|
||||||
|
a.push(rdx);
|
||||||
|
a.push(ecx);
|
||||||
|
a.mov(rdx, rdi); // function id is stored in rdi
|
||||||
|
a.mov(ecx, ebx); // ent ref is stored in ebx
|
||||||
|
a.call_aligned(vm_call_builtin_method_internal);
|
||||||
|
a.pop(rdx);
|
||||||
|
a.pop(ecx);
|
||||||
|
a.popad64();
|
||||||
|
|
||||||
|
a.jmp(0xC0E8F9_b);
|
||||||
|
}
|
||||||
|
|
||||||
class extension final : public component_interface
|
class extension final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -403,18 +401,17 @@ namespace gsc
|
|||||||
developer_script = game::Dvar_RegisterBool("developer_script", true, 0, "Enable developer script comments"); // enable by default for now
|
developer_script = game::Dvar_RegisterBool("developer_script", true, 0, "Enable developer script comments"); // enable by default for now
|
||||||
|
|
||||||
utils::hook::set<uint32_t>(0xBFD16B_b + 1, func_table_count); // change builtin func count
|
utils::hook::set<uint32_t>(0xBFD16B_b + 1, func_table_count); // change builtin func count
|
||||||
|
|
||||||
utils::hook::set<uint32_t>(0xBFD172_b + 4, static_cast<uint32_t>(reverse_b((&func_table))));
|
utils::hook::set<uint32_t>(0xBFD172_b + 4, static_cast<uint32_t>(reverse_b((&func_table))));
|
||||||
utils::hook::nop(0xC0E5CE_b, 12); // nop the call & jmp at the end of call_builtin
|
|
||||||
utils::hook::jump(0xC0E5CE_b, utils::hook::assemble(vm_call_builtin_function_stub), true);
|
|
||||||
utils::hook::inject(0xBFD5A1_b + 3, &func_table);
|
utils::hook::inject(0xBFD5A1_b + 3, &func_table);
|
||||||
utils::hook::set<uint32_t>(0xBFD595_b + 2, sizeof(func_table));
|
utils::hook::set<uint32_t>(0xBFD595_b + 2, sizeof(func_table));
|
||||||
|
utils::hook::nop(0xC0E5CE_b, 7);
|
||||||
|
utils::hook::call(0xC0E5CE_b, vm_call_builtin_function_internal);
|
||||||
|
|
||||||
utils::hook::set<uint32_t>(0xBFD182_b + 4, static_cast<uint32_t>(reverse_b((&meth_table))));
|
utils::hook::set<uint32_t>(0xBFD182_b + 4, static_cast<uint32_t>(reverse_b((&meth_table))));
|
||||||
utils::hook::nop(0xC0E8EB_b, 14); // nop the lea & call at the end of call_builtin_method
|
|
||||||
utils::hook::jump(0xC0E8EB_b, utils::hook::assemble(vm_call_builtin_method_stub), true);
|
|
||||||
utils::hook::inject(0xBFD5AF_b + 3, &meth_table);
|
utils::hook::inject(0xBFD5AF_b + 3, &meth_table);
|
||||||
utils::hook::set<uint32_t>(0xBFD5B6_b + 2, sizeof(meth_table));
|
utils::hook::set<uint32_t>(0xBFD5B6_b + 2, sizeof(meth_table));
|
||||||
|
utils::hook::nop(0xC0E8EB_b, 14); // nop the lea & call at the end of call_builtin_method
|
||||||
|
utils::hook::jump(0xC0E8EB_b, utils::hook::assemble(vm_call_builtin_method_stub), true);
|
||||||
|
|
||||||
utils::hook::call(0xC0F8C1_b, vm_error_stub); // LargeLocalResetToMark
|
utils::hook::call(0xC0F8C1_b, vm_error_stub); // LargeLocalResetToMark
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils::hook::detour g_load_structs_hook;
|
utils::hook::detour g_load_structs_hook;
|
||||||
void g_load_structs_stub()
|
void g_load_structs_stub(float a1)
|
||||||
{
|
{
|
||||||
for (auto& function_handle : main_handles)
|
for (auto& function_handle : main_handles)
|
||||||
{
|
{
|
||||||
@ -345,7 +345,7 @@ namespace gsc
|
|||||||
game::RemoveRefToObject(game::Scr_ExecThread(function_handle.second, 0));
|
game::RemoveRefToObject(game::Scr_ExecThread(function_handle.second, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_load_structs_hook.invoke<void>();
|
g_load_structs_hook.invoke<void>(a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::hook::detour scr_load_level_hook;
|
utils::hook::detour scr_load_level_hook;
|
||||||
|
Loading…
Reference in New Issue
Block a user