Add broken argument handling

This commit is contained in:
momo5502 2019-01-17 23:09:50 +01:00
parent e51f7afa3d
commit fa81d5e5e0
6 changed files with 136 additions and 18 deletions

View File

@ -17,6 +17,8 @@ namespace game
RemoveRefToValue_t RemoveRefToValue;
SL_GetStringOfSize_t SL_GetStringOfSize;
Sys_ShowConsole_t Sys_ShowConsole;
VM_Notify_t VM_Notify;
@ -29,7 +31,9 @@ namespace game
char** scrMemTreePub;
unsigned int* scr_numParam;
unsigned int* scr_numArgs;
VariableValue** scr_stackPtr;
VariableValue** scr_stackEndPtr;
scr_call_t* scr_instanceFunctions;
scr_call_t* scr_globalFunctions;
@ -97,13 +101,18 @@ namespace game
}
}
const char* SL_ConvertToString(unsigned int stringValue)
const char* SL_ConvertToString(const unsigned int stringValue)
{
if (!stringValue) return nullptr;
static const auto size = is_sp() ? 16 : 12;
return *scrMemTreePub + size * stringValue + 4;
}
unsigned int SL_GetString(const char *str, const unsigned int user)
{
return SL_GetStringOfSize(str, user, strlen(str), 7);
}
}
launcher::mode mode = launcher::mode::none;
@ -139,6 +148,8 @@ namespace game
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490));
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
@ -151,7 +162,9 @@ namespace game
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
native::scr_numParam = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2598, 0x20B4A98, 0x1F5B098));
native::scr_numArgs = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2594, 0x20B4A94, 0x1F5B094));
native::scr_stackPtr = reinterpret_cast<native::VariableValue**>(SELECT_VALUE(0x1BF2590, 0x20B4A90, 0x1F5B090));
native::scr_stackEndPtr = reinterpret_cast<native::VariableValue**>(SELECT_VALUE(0x1BF2584, 0x20B4A84, 0x1F5B084));
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258, 0x1BF59C8));
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x186C68C, 0x1D6EB34, 0x1C152A4));

View File

@ -27,6 +27,9 @@ namespace game
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
extern RemoveRefToValue_t RemoveRefToValue;
typedef unsigned int (*SL_GetStringOfSize_t)(const char *str, unsigned int user, unsigned int len, int type);
extern SL_GetStringOfSize_t SL_GetStringOfSize;
typedef void (*Sys_ShowConsole_t)();
extern Sys_ShowConsole_t Sys_ShowConsole;
@ -41,7 +44,9 @@ namespace game
extern char** scrMemTreePub;
extern unsigned int* scr_numParam;
extern unsigned int* scr_numArgs;
extern VariableValue** scr_stackPtr;
extern VariableValue** scr_stackEndPtr;
extern scr_call_t* scr_instanceFunctions;
extern scr_call_t* scr_globalFunctions;
@ -58,6 +63,7 @@ namespace game
scr_call_t Scr_GetFunc(unsigned int index);
const char* SL_ConvertToString(unsigned int stringValue);
unsigned int SL_GetString(const char *str, unsigned int user);
}
bool is_mp();

View File

@ -56,8 +56,6 @@ void notification::dispatch(event* event)
void notification::vm_notify_stub(const unsigned int notify_id, const unsigned short type,
game::native::VariableValue* stack)
{
game::native::VM_Notify(notify_id, type, stack);
try
{
event e;
@ -79,6 +77,8 @@ void notification::vm_notify_stub(const unsigned int notify_id, const unsigned s
{
scripting::propagate_error(e);
}
game::native::VM_Notify(notify_id, type, stack);
}
REGISTER_MODULE(notification)

View File

@ -12,13 +12,33 @@ std::mutex scripting::mutex_;
std::vector<std::function<void()>> scripting::start_callbacks_;
std::vector<std::function<void()>> scripting::stop_callbacks_;
scripting::entity::entity() : environment_(nullptr), entity_id_(0)
scripting::entity::entity() : entity(nullptr, 0)
{
}
scripting::entity::entity(const entity& other) : entity(other.environment_, other.entity_id_)
{
}
scripting::entity::entity(scripting* environment, const unsigned int entity_id) : environment_(environment),
entity_id_(entity_id)
{
if (this->entity_id_)
{
game::native::VariableValue value;
value.type = game::native::SCRIPT_OBJECT;
value.u.entityId = this->entity_id_;
game::native::AddRefToValue(&value);
}
}
scripting::entity::~entity()
{
if (this->entity_id_)
{
game::native::RemoveRefToValue(game::native::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)});
}
}
void scripting::entity::on_notify(const std::string& event,
@ -45,9 +65,9 @@ game::native::scr_entref_t scripting::entity::get_entity_reference() const
return game::native::Scr_GetEntityIdRef(this->get_entity_id());
}
void scripting::entity::call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments)
void scripting::entity::call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments) const
{
scripting::call(function, this->get_entity_id(), arguments);
this->environment_->call(function, this->get_entity_id(), arguments);
}
scripting::variable::variable(game::native::VariableValue value) : value_(value)
@ -264,21 +284,42 @@ void scripting::stop_execution()
}
void scripting::call(const std::string& function, const unsigned int entity_id,
const std::vector<chaiscript::Boxed_Value>& /*arguments*/)
std::vector<chaiscript::Boxed_Value> arguments) const
{
const int function_index = find_function_index(function);
const auto function_index = find_function_index(function);
if (function_index < 0)
{
throw std::runtime_error("No function found for name '" + function + "'");
}
const game::native::scr_entref_t entity = function_index > 0x1C7
? game::native::Scr_GetEntityIdRef(entity_id)
: game::native::scr_entref_t{~0u};
const auto entity = function_index > 0x1C7
? game::native::Scr_GetEntityIdRef(entity_id)
: game::native::scr_entref_t{~0u};
const auto function_ptr = game::native::Scr_GetFunc(function_index);
if(!call_safe(function_ptr, entity))
const auto old_args = *game::native::scr_numArgs;
const auto old_params = *game::native::scr_numParam;
*game::native::scr_numArgs = 0;
*game::native::scr_numParam = 0;
const auto cleanup = gsl::finally([old_args, old_params]()
{
game::native::Scr_ClearOutParams();
*game::native::scr_numArgs = old_args;
*game::native::scr_numParam = old_params;
});
std::reverse(arguments.begin(), arguments.end());
for (const auto& argument : arguments)
{
this->push_param(argument);
}
*game::native::scr_numParam = *game::native::scr_numArgs;
*game::native::scr_numArgs = 0;
if (!call_safe(function_ptr, entity))
{
throw std::runtime_error("Error executing function '" + function + "'");
}
@ -291,10 +332,10 @@ bool scripting::call_safe(const game::native::scr_call_t function, const game::n
static_assert(sizeof(jmp_buf) == 64);
*game::native::g_script_error_level += 1;
if (setjmp(game::native::g_script_error[*game::native::g_script_error_level]))
if (setjmp(game::native::g_script_error[*game::native::g_script_error_level]))
{
*game::native::g_script_error_level -= 1;
return false;
*game::native::g_script_error_level -= 1;
return false;
}
function(entref.val);
@ -321,5 +362,60 @@ int scripting::find_function_index(const std::string& function)
return -1;
}
void scripting::push_param(const chaiscript::Boxed_Value& value) const
{
if (*game::native::scr_numParam)
{
game::native::Scr_ClearOutParams();
}
if (*game::native::scr_stackPtr == *game::native::scr_stackEndPtr)
{
throw std::runtime_error("Internal script stack overflow");
}
game::native::VariableValue* value_ptr = ++*game::native::scr_stackPtr;
++*game::native::scr_numArgs;
value_ptr->type = game::native::SCRIPT_NONE;
value_ptr->u.intValue = 0;
if (value.get_type_info() == typeid(double) || value.get_type_info() == typeid(float))
{
const auto real_value = this->chai_->boxed_cast<float>(value);
value_ptr->type = game::native::SCRIPT_FLOAT;
value_ptr->u.floatValue = real_value;
}
else if (value.get_type_info() == typeid(int)
|| value.get_type_info() == typeid(unsigned int)
|| value.get_type_info() == typeid(short)
|| value.get_type_info() == typeid(unsigned short)
|| value.get_type_info() == typeid(long long)
|| value.get_type_info() == typeid(unsigned long long))
{
const auto real_value = this->chai_->boxed_cast<int>(value);
value_ptr->type = game::native::SCRIPT_INTEGER;
value_ptr->u.intValue = real_value;
}
else if (value.get_type_info() == typeid(entity))
{
const auto real_value = this->chai_->boxed_cast<entity>(value);
value_ptr->type = game::native::SCRIPT_OBJECT;
value_ptr->u.entityId = real_value.get_entity_id();
game::native::AddRefToValue(value_ptr);
}
else if (value.get_type_info() == typeid(std::string))
{
const auto real_value = this->chai_->boxed_cast<std::string>(value);
value_ptr->type = game::native::SCRIPT_STRING;
value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0);
}
else
{
throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'");
}
}
REGISTER_MODULE(scripting)

View File

@ -11,8 +11,9 @@ public:
{
public:
entity();
entity(const entity& other) = default;
entity(const entity& other);
entity(scripting* environment, unsigned int entity_id);
~entity();
void on_notify(const std::string& event,
const std::function<void(const std::vector<chaiscript::Boxed_Value>&)>& callback,
@ -21,7 +22,7 @@ public:
unsigned int get_entity_id() const;
game::native::scr_entref_t get_entity_reference() const;
void call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments);
void call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments) const;
private:
scripting* environment_;
@ -79,7 +80,8 @@ private:
static void start_execution();
static void stop_execution();
static void call(const std::string& function, unsigned int entity_id, const std::vector<chaiscript::Boxed_Value>& arguments);
void push_param(const chaiscript::Boxed_Value& value) const;
void call(const std::string& function, unsigned int entity_id, std::vector<chaiscript::Boxed_Value> arguments) const;
static bool call_safe(game::native::scr_call_t function, game::native::scr_entref_t entref);
static int find_function_index(const std::string& function);
};

View File

@ -5,6 +5,7 @@
#pragma warning(push)
#pragma warning(disable: 4458)
#pragma warning(disable: 4702)
#define WIN32_LEAN_AND_MEAN