Longjmp fixes
Co-Authored-By: Edo <edoardo.sanguineti222@gmail.com>
This commit is contained in:
parent
f8247a8f3b
commit
c505c29bea
@ -41,7 +41,7 @@ namespace gsc
|
|||||||
std::unordered_map<std::string, unsigned int> main_handles;
|
std::unordered_map<std::string, unsigned int> main_handles;
|
||||||
std::unordered_map<std::string, unsigned int> init_handles;
|
std::unordered_map<std::string, unsigned int> init_handles;
|
||||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||||
std::unordered_map<unsigned int, scripting::script_function> functions;
|
std::unordered_map<scripting::script_function, unsigned int> functions;
|
||||||
std::optional<std::string> gsc_error;
|
std::optional<std::string> gsc_error;
|
||||||
|
|
||||||
char* allocate_buffer(size_t size)
|
char* allocate_buffer(size_t size)
|
||||||
@ -185,21 +185,6 @@ namespace gsc
|
|||||||
loaded_scripts.clear();
|
loaded_scripts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gscr_print_stub()
|
|
||||||
{
|
|
||||||
const auto num = game::Scr_GetNumParam();
|
|
||||||
std::string buffer{};
|
|
||||||
|
|
||||||
for (auto i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
const auto str = game::Scr_GetString(i);
|
|
||||||
buffer.append(str);
|
|
||||||
buffer.append("\t");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", buffer.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_gametype_script_stub(void* a1, void* a2)
|
void load_gametype_script_stub(void* a1, void* a2)
|
||||||
{
|
{
|
||||||
utils::hook::invoke<void>(0x1404E1400, a1, a2);
|
utils::hook::invoke<void>(0x1404E1400, a1, a2);
|
||||||
@ -318,13 +303,11 @@ namespace gsc
|
|||||||
bool force_error_print = false;
|
bool force_error_print = false;
|
||||||
void* vm_error_stub(void* a1)
|
void* vm_error_stub(void* a1)
|
||||||
{
|
{
|
||||||
if (!developer_script->current.enabled || force_error_print)
|
if (!developer_script->current.enabled && !force_error_print)
|
||||||
{
|
{
|
||||||
return utils::hook::invoke<void*>(0x140614670, a1);
|
return utils::hook::invoke<void*>(0x140614670, a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
force_error_print = false;
|
|
||||||
|
|
||||||
console::warn("*********** script runtime error *************\n");
|
console::warn("*********** script runtime error *************\n");
|
||||||
|
|
||||||
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(0x14BAA93E8);
|
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(0x14BAA93E8);
|
||||||
@ -343,6 +326,9 @@ namespace gsc
|
|||||||
opcode_id, error_str.data());
|
opcode_id, error_str.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
force_error_print = false;
|
||||||
|
gsc_error = {};
|
||||||
|
|
||||||
print_callstack();
|
print_callstack();
|
||||||
console::warn("**********************************************\n");
|
console::warn("**********************************************\n");
|
||||||
return utils::hook::invoke<void*>(0x140614670, a1);
|
return utils::hook::invoke<void*>(0x140614670, a1);
|
||||||
@ -359,7 +345,7 @@ namespace gsc
|
|||||||
utils::hook::invoke<void>(0x140509F20, a1, a2);
|
utils::hook::invoke<void>(0x140509F20, a1, a2);
|
||||||
for (const auto& func : functions)
|
for (const auto& func : functions)
|
||||||
{
|
{
|
||||||
game::Scr_RegisterFunction(func.second, 0, func.first);
|
game::Scr_RegisterFunction(func.first, 0, func.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,33 +364,54 @@ namespace gsc
|
|||||||
auto function_id_start = 0x320;
|
auto function_id_start = 0x320;
|
||||||
void add_function(const std::string& name, scripting::script_function function)
|
void add_function(const std::string& name, scripting::script_function function)
|
||||||
{
|
{
|
||||||
const auto id = ++function_id_start;
|
if (scripting::function_map.find(name) != scripting::function_map.end())
|
||||||
scripting::function_map[name] = id;
|
|
||||||
functions[id] = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_gsc_error(const std::string& error)
|
|
||||||
{
|
|
||||||
force_error_print = true;
|
|
||||||
gsc_error = error;
|
|
||||||
game::Scr_ErrorInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void assert_cmd()
|
|
||||||
{
|
|
||||||
const auto expr = get_argument(0).as<int>();
|
|
||||||
if (!expr)
|
|
||||||
{
|
{
|
||||||
set_gsc_error("assert fail");
|
const auto id = scripting::function_map[name];
|
||||||
|
functions[function] = id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto id = ++function_id_start;
|
||||||
|
scripting::function_map[name] = id;
|
||||||
|
functions[function] = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertex_cmd()
|
void execute_custom_function(scripting::script_function function)
|
||||||
{
|
{
|
||||||
const auto expr = get_argument(0).as<int>();
|
bool error = false;
|
||||||
if (!expr)
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
set_gsc_error(get_argument(1).as<std::string>());
|
function({});
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
force_error_print = true;
|
||||||
|
gsc_error = e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
game::Scr_ErrorInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_call_builtin_stub(scripting::script_function function)
|
||||||
|
{
|
||||||
|
bool custom = false;
|
||||||
|
{
|
||||||
|
custom = functions.find(function) != functions.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!custom)
|
||||||
|
{
|
||||||
|
function({});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
execute_custom_function(function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,13 +473,6 @@ namespace gsc
|
|||||||
utils::hook::call(0x1404C8F71, g_load_structs_stub);
|
utils::hook::call(0x1404C8F71, g_load_structs_stub);
|
||||||
utils::hook::call(0x1404C8F80, scr_load_level_stub);
|
utils::hook::call(0x1404C8F80, scr_load_level_stub);
|
||||||
|
|
||||||
// replace builtin print function
|
|
||||||
utils::hook::jump(0x1404EC640, gscr_print_stub);
|
|
||||||
|
|
||||||
// restore assert
|
|
||||||
utils::hook::jump(0x1404EC890, assert_cmd);
|
|
||||||
utils::hook::jump(0x1404EC920, assertex_cmd);
|
|
||||||
|
|
||||||
utils::hook::call(0x1405CB94F, vm_error_stub);
|
utils::hook::call(0x1405CB94F, vm_error_stub);
|
||||||
|
|
||||||
utils::hook::call(0x1405BC583, unknown_function_stub);
|
utils::hook::call(0x1405BC583, unknown_function_stub);
|
||||||
@ -487,31 +487,59 @@ namespace gsc
|
|||||||
utils::hook::inject(0x1405BCB78 + 3, &func_table);
|
utils::hook::inject(0x1405BCB78 + 3, &func_table);
|
||||||
utils::hook::set<uint32_t>(0x1405CA678 + 4, RVA(&func_table));
|
utils::hook::set<uint32_t>(0x1405CA678 + 4, RVA(&func_table));
|
||||||
|
|
||||||
|
utils::hook::nop(0x1405CA683, 8);
|
||||||
|
utils::hook::call(0x1405CA683, vm_call_builtin_stub);
|
||||||
|
|
||||||
|
add_function("print", [](const game::scr_entref_t ref)
|
||||||
|
{
|
||||||
|
const auto num = game::Scr_GetNumParam();
|
||||||
|
std::string buffer{};
|
||||||
|
|
||||||
|
for (auto i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
const auto str = game::Scr_GetString(i);
|
||||||
|
buffer.append(str);
|
||||||
|
buffer.append("\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n", buffer.data());
|
||||||
|
});
|
||||||
|
|
||||||
|
add_function("assert", [](const game::scr_entref_t ref)
|
||||||
|
{
|
||||||
|
const auto expr = get_argument(0).as<int>();
|
||||||
|
if (!expr)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("assert fail");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add_function("assertex", [](const game::scr_entref_t ref)
|
||||||
|
{
|
||||||
|
const auto expr = get_argument(0).as<int>();
|
||||||
|
if (!expr)
|
||||||
|
{
|
||||||
|
const auto error = get_argument(1).as<std::string>();
|
||||||
|
throw std::runtime_error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
add_function("replacefunc", [](const game::scr_entref_t ref)
|
add_function("replacefunc", [](const game::scr_entref_t ref)
|
||||||
{
|
{
|
||||||
try
|
const auto what = get_argument(0).get_raw();
|
||||||
|
const auto with = get_argument(1).get_raw();
|
||||||
|
|
||||||
|
if (what.type != game::SCRIPT_FUNCTION)
|
||||||
{
|
{
|
||||||
const auto what = get_argument(0).get_raw();
|
throw std::runtime_error("replaceFunc: parameter 1 must be a function");
|
||||||
const auto with = get_argument(1).get_raw();
|
|
||||||
|
|
||||||
if (what.type != game::SCRIPT_FUNCTION)
|
|
||||||
{
|
|
||||||
set_gsc_error("replaceFunc: parameter 0 must be a function");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (with.type != game::SCRIPT_FUNCTION)
|
|
||||||
{
|
|
||||||
set_gsc_error("replaceFunc: parameter 1 must be a function");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
notifies::set_gsc_hook(what.u.codePosValue, with.u.codePosValue);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
|
||||||
|
if (with.type != game::SCRIPT_FUNCTION)
|
||||||
{
|
{
|
||||||
set_gsc_error(utils::string::va("replaceFunc: %s", e.what()));
|
throw std::runtime_error("replaceFunc: parameter 2 must be a function");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifies::set_gsc_hook(what.u.codePosValue, with.u.codePosValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
scripting::on_shutdown([](int free_scripts)
|
scripting::on_shutdown([](int free_scripts)
|
||||||
|
@ -152,7 +152,7 @@ namespace notifies
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scr_entity_damage_stub(game::gentity_s* self, game::gentity_s* inflictor, game::gentity_s* attacker, const float* vDir, const float* vPoint,
|
void scr_entity_damage_stub(game::gentity_s* self, game::gentity_s* inflictor, game::gentity_s* attacker, const float* vDir, const float* vPoint,
|
||||||
int damage, int dflags, const unsigned int hitLoc, const unsigned int weapon, bool isAlternate, unsigned int a11, const int meansOfDeath, unsigned int a13, unsigned int a14)
|
int damage, int dflags, const unsigned int meansOfDeath, const unsigned int weapon, bool isAlternate, unsigned int a11, const int hitLoc, unsigned int a13, unsigned int a14)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string _hitLoc = reinterpret_cast<const char**>(0x140BF4AA0)[hitLoc];
|
const std::string _hitLoc = reinterpret_cast<const char**>(0x140BF4AA0)[hitLoc];
|
||||||
@ -187,7 +187,8 @@ namespace notifies
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scr_entity_damage_hook.invoke<void>(self, inflictor, attacker, vDir, vPoint, damage, dflags, hitLoc, weapon, isAlternate, a11, meansOfDeath, a13, a14);
|
scr_entity_damage_hook.invoke<void>(self,inflictor, attacker, vDir, vPoint, damage, dflags,
|
||||||
|
meansOfDeath, weapon, isAlternate, a11, hitLoc, a13, a14);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,25 +444,28 @@ namespace ui_scripting
|
|||||||
reader_data, chunk_name);
|
reader_data, chunk_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string current_error;
|
||||||
int main_handler(game::hks::lua_State* state)
|
int main_handler(game::hks::lua_State* state)
|
||||||
{
|
{
|
||||||
const auto value = state->m_apistack.base[-1];
|
bool error = false;
|
||||||
if (value.t != game::hks::TCFUNCTION)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto closure = value.v.cClosure;
|
|
||||||
if (converted_functions.find(closure) == converted_functions.end())
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& function = converted_functions[closure];
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
const auto value = state->m_apistack.base[-1];
|
||||||
|
if (value.t != game::hks::TCFUNCTION)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto closure = value.v.cClosure;
|
||||||
|
if (converted_functions.find(closure) == converted_functions.end())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& function = converted_functions[closure];
|
||||||
|
|
||||||
const auto args = get_return_values();
|
const auto args = get_return_values();
|
||||||
const auto results = function(args);
|
const auto results = function(args);
|
||||||
|
|
||||||
@ -475,7 +478,13 @@ namespace ui_scripting
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
game::hks::hksi_luaL_error(state, e.what());
|
current_error = e.what();
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
game::hks::hksi_luaL_error(state, current_error.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user