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> init_handles;
|
||||
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;
|
||||
|
||||
char* allocate_buffer(size_t size)
|
||||
@ -185,21 +185,6 @@ namespace gsc
|
||||
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)
|
||||
{
|
||||
utils::hook::invoke<void>(0x1404E1400, a1, a2);
|
||||
@ -318,13 +303,11 @@ namespace gsc
|
||||
bool force_error_print = false;
|
||||
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);
|
||||
}
|
||||
|
||||
force_error_print = false;
|
||||
|
||||
console::warn("*********** script runtime error *************\n");
|
||||
|
||||
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(0x14BAA93E8);
|
||||
@ -343,6 +326,9 @@ namespace gsc
|
||||
opcode_id, error_str.data());
|
||||
}
|
||||
|
||||
force_error_print = false;
|
||||
gsc_error = {};
|
||||
|
||||
print_callstack();
|
||||
console::warn("**********************************************\n");
|
||||
return utils::hook::invoke<void*>(0x140614670, a1);
|
||||
@ -359,7 +345,7 @@ namespace gsc
|
||||
utils::hook::invoke<void>(0x140509F20, a1, a2);
|
||||
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;
|
||||
void add_function(const std::string& name, scripting::script_function function)
|
||||
{
|
||||
const auto id = ++function_id_start;
|
||||
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)
|
||||
if (scripting::function_map.find(name) != scripting::function_map.end())
|
||||
{
|
||||
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>();
|
||||
if (!expr)
|
||||
bool error = false;
|
||||
|
||||
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(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(0x1405BC583, unknown_function_stub);
|
||||
@ -487,31 +487,59 @@ namespace gsc
|
||||
utils::hook::inject(0x1405BCB78 + 3, &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)
|
||||
{
|
||||
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();
|
||||
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);
|
||||
throw std::runtime_error("replaceFunc: parameter 1 must be a function");
|
||||
}
|
||||
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)
|
||||
|
@ -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,
|
||||
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];
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string current_error;
|
||||
int main_handler(game::hks::lua_State* state)
|
||||
{
|
||||
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];
|
||||
bool error = false;
|
||||
|
||||
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 results = function(args);
|
||||
|
||||
@ -475,7 +478,13 @@ namespace ui_scripting
|
||||
}
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user