update gsc
yoink some from h2-mod
This commit is contained in:
parent
e4eecf66c5
commit
483aad7425
@ -56,7 +56,7 @@ namespace gsc
|
||||
{
|
||||
const auto& pos = function.value();
|
||||
unknown_function_error = std::format(
|
||||
"while processing function '{}' in script '{}':\nunknown script '{}'", pos.first, pos.second, scripting::current_file
|
||||
"while processing function '{}' in script '{}':\nunknown script '{}'", pos.function, pos.file, scripting::current_file
|
||||
);
|
||||
}
|
||||
else
|
||||
@ -289,26 +289,29 @@ namespace gsc
|
||||
}
|
||||
}
|
||||
|
||||
void print_callstack(uint8_t opcode_id)
|
||||
void print_callstack()
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
for (auto frame = game::scr_VmPub->function_frame; frame != game::scr_VmPub->function_frame_start; --frame)
|
||||
{
|
||||
const auto function_stack = game::scr_function_stack;
|
||||
const auto pos = frame == game::scr_VmPub->function_frame ? function_stack->pos : frame->fs.pos;
|
||||
const auto function = find_function(pos);
|
||||
const auto pos = frame == game::scr_VmPub->function_frame ? game::scr_function_stack->pos : frame->fs.pos;
|
||||
const auto script_info = find_function(pos);
|
||||
|
||||
if (function.has_value())
|
||||
if (!script_info.has_value())
|
||||
{
|
||||
auto& file_name = function.value().second;
|
||||
console::warn("\tat unknown location %p\n", pos);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gsc::source_pos_map.contains(file_name))
|
||||
const auto& function = script_info->function;
|
||||
const auto& file = script_info->file;
|
||||
const auto* loaded_script = gsc::get_loaded_script(file);
|
||||
|
||||
if (loaded_script)
|
||||
{
|
||||
const auto script = gsc::loaded_scripts[file_name];
|
||||
const auto script = loaded_script->ptr;
|
||||
assert(script);
|
||||
|
||||
const auto& pos_map = gsc::source_pos_map[file_name];
|
||||
const auto& pos_map = loaded_script->devmap;
|
||||
|
||||
auto position = static_cast<std::uint32_t>(pos - script->bytecode);
|
||||
for (auto i = 0; i < 8; ++i)
|
||||
@ -326,7 +329,7 @@ namespace gsc
|
||||
const auto& info = pos_map.at(position);
|
||||
|
||||
console::warn("\tat function \"%s\" in file \"%s.gsc\" (line %d, col %d)\n",
|
||||
function.value().first.data(), file_name.data(), info.line, info.column);
|
||||
function.data(), file.data(), info.line, info.column);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -336,16 +339,9 @@ namespace gsc
|
||||
else
|
||||
{
|
||||
NO_DEVMAP:
|
||||
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.value().first.data(), file_name.data());
|
||||
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.data(), file.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console::warn("\tat unknown location %p\n", pos);
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
void vm_error_internal()
|
||||
@ -360,9 +356,8 @@ namespace gsc
|
||||
console::warn("*********** script runtime error *************\n");
|
||||
|
||||
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(0x146B22940);
|
||||
const std::string error_str = gsc_error_msg.has_value()
|
||||
? utils::string::va(": %s", gsc_error_msg.value().data())
|
||||
: "";
|
||||
|
||||
const std::string error_str = gsc_error_msg.has_value() ? std::format(": {}", gsc_error_msg.value()) : std::string();
|
||||
|
||||
if ((opcode_id >= gsc_ctx->opcode_id(xsk::gsc::opcode::OP_CallBuiltin0) && opcode_id <= gsc_ctx->opcode_id(xsk::gsc::opcode::OP_CallBuiltin))
|
||||
|| (opcode_id >= gsc_ctx->opcode_id(xsk::gsc::opcode::OP_CallBuiltinMethod0) && opcode_id <= gsc_ctx->opcode_id(xsk::gsc::opcode::OP_CallBuiltinMethod)))
|
||||
@ -385,7 +380,7 @@ namespace gsc
|
||||
force_error_print = false;
|
||||
gsc_error_msg = {};
|
||||
|
||||
print_callstack(opcode_id);
|
||||
print_callstack();
|
||||
console::warn("**********************************************\n");
|
||||
}
|
||||
|
||||
@ -428,16 +423,21 @@ namespace gsc
|
||||
game::Scr_ErrorInternal();
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos)
|
||||
std::optional<script_info_t> find_function(const char* pos)
|
||||
{
|
||||
for (const auto& file : scripting::script_function_table_sort)
|
||||
{
|
||||
const auto first_function = file.second.begin();
|
||||
for (auto i = file.second.begin(); i != file.second.end() && std::next(i) != file.second.end(); ++i)
|
||||
{
|
||||
const auto next = std::next(i);
|
||||
if (pos >= i->second && pos < next->second)
|
||||
{
|
||||
return {std::make_pair(i->first, file.first)};
|
||||
script_info_t info{};
|
||||
info.function = i->first;
|
||||
info.file = file.first;
|
||||
info.script_start = first_function->second;
|
||||
return { info };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,13 @@
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
void scr_error(const char* error, const bool force_print = false);
|
||||
struct script_info_t
|
||||
{
|
||||
const char* script_start;
|
||||
std::string file;
|
||||
std::string function;
|
||||
};
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos);
|
||||
void scr_error(const char* error, const bool force_print = false);
|
||||
std::optional<script_info_t> find_function(const char* pos);
|
||||
}
|
@ -311,17 +311,6 @@ namespace gsc
|
||||
|
||||
utils::hook::jump(0x140C0D0A4, utils::hook::assemble(vm_execute_stub), true);
|
||||
|
||||
/*
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
function::add("isusingmatchrulesdata", [](const function_args& args)
|
||||
{
|
||||
// return 0 so the game doesn't override the cfg
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
function::add("print", [](const function_args& args)
|
||||
{
|
||||
print(args);
|
||||
@ -375,9 +364,14 @@ namespace gsc
|
||||
const auto what = args[0].get_raw();
|
||||
const auto with = args[1].get_raw();
|
||||
|
||||
if (what.type != game::VAR_FUNCTION || with.type != game::VAR_FUNCTION)
|
||||
if (what.type != game::VAR_FUNCTION)
|
||||
{
|
||||
throw std::runtime_error("replacefunc: parameter 1 must be a function");
|
||||
throw std::runtime_error("parameter 1 must be a function");
|
||||
}
|
||||
|
||||
if (with.type != game::VAR_FUNCTION)
|
||||
{
|
||||
throw std::runtime_error("parameter 2 must be a function");
|
||||
}
|
||||
|
||||
vm_execute_hooks[what.u.codePosValue] = with.u.codePosValue;
|
||||
|
@ -20,8 +20,7 @@
|
||||
namespace gsc
|
||||
{
|
||||
std::unique_ptr<xsk::gsc::iw7::context> gsc_ctx = std::make_unique<xsk::gsc::iw7::context>();
|
||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||
std::unordered_map<std::string, code_pos_map> source_pos_map;
|
||||
std::unordered_map<std::string, loaded_script_t> loaded_scripts;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -106,40 +105,44 @@ namespace gsc
|
||||
return false;
|
||||
}
|
||||
|
||||
void parse_gsc_map(const std::string& name, const xsk::gsc::buffer& devmap)
|
||||
std::map<std::uint32_t, col_line_t> parse_devmap(const xsk::gsc::buffer& devmap)
|
||||
{
|
||||
auto data = devmap.data;
|
||||
auto offset = 0;
|
||||
|
||||
auto count = *reinterpret_cast<const int*>(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
console::debug("parsing gscmap for \"%s\" (%d)\n", name.data(), count);
|
||||
|
||||
code_pos_map pos_map{};
|
||||
|
||||
for (auto i = 0; i < count; ++i)
|
||||
const auto read_32 = [&]()
|
||||
{
|
||||
auto pos = *reinterpret_cast<const uint32_t*>(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
const auto val = *reinterpret_cast<const std::uint32_t*>(data);
|
||||
data += sizeof(std::uint32_t);
|
||||
return val;
|
||||
};
|
||||
|
||||
auto line = *reinterpret_cast<const uint16_t*>(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
const auto read_16 = [&]()
|
||||
{
|
||||
const auto val = *reinterpret_cast<const std::uint16_t*>(data);
|
||||
data += sizeof(std::uint16_t);
|
||||
return val;
|
||||
};
|
||||
|
||||
auto column = *reinterpret_cast<const uint16_t*>(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
std::map<std::uint32_t, col_line_t> pos_map;
|
||||
|
||||
pos_map[pos] = { line, column };
|
||||
const auto devmap_count = read_32();
|
||||
for (auto i = 0u; i < devmap_count; i++)
|
||||
{
|
||||
const auto script_pos = read_32();
|
||||
const auto line = read_16();
|
||||
const auto col = read_16();
|
||||
|
||||
pos_map[script_pos] = { line, col };
|
||||
}
|
||||
|
||||
source_pos_map[name] = pos_map;
|
||||
return pos_map;
|
||||
}
|
||||
|
||||
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
||||
{
|
||||
if (const auto itr = loaded_scripts.find(file_name); itr != loaded_scripts.end())
|
||||
{
|
||||
return itr->second;
|
||||
return itr->second.ptr;
|
||||
}
|
||||
|
||||
if (game::Com_FrontEnd_IsInFrontEnd())
|
||||
@ -177,13 +180,7 @@ namespace gsc
|
||||
data.assign(source_buffer.begin(), source_buffer.end());
|
||||
|
||||
const auto assembly_ptr = compiler.compile(real_name, data);
|
||||
const auto output_script = assembler.assemble(*assembly_ptr);
|
||||
|
||||
const auto bytecode = std::get<0>(output_script);
|
||||
const auto stack = std::get<1>(output_script);
|
||||
const auto devmap = std::get<2>(output_script);
|
||||
|
||||
parse_gsc_map(real_name, devmap);
|
||||
const auto& [bytecode, stack, devmap] = assembler.assemble(*assembly_ptr);
|
||||
|
||||
const auto script_file_ptr = static_cast<game::ScriptFile*>(scriptfile_allocator.allocate(sizeof(game::ScriptFile)));
|
||||
script_file_ptr->name = file_name;
|
||||
@ -202,7 +199,10 @@ namespace gsc
|
||||
|
||||
script_file_ptr->compressedLen = 0;
|
||||
|
||||
loaded_scripts[file_name] = script_file_ptr;
|
||||
loaded_script_t loaded_script{};
|
||||
loaded_script.ptr = script_file_ptr;
|
||||
loaded_script.devmap = parse_devmap(devmap);
|
||||
loaded_scripts.insert(std::make_pair(file_name, loaded_script));
|
||||
|
||||
console::debug("Loaded custom gsc '%s.gsc'", real_name.data());
|
||||
|
||||
@ -459,6 +459,15 @@ namespace gsc
|
||||
return game::DB_FindXAssetHeader(type, name, allow_create_default).scriptfile;
|
||||
}
|
||||
|
||||
loaded_script_t* get_loaded_script(const std::string& name)
|
||||
{
|
||||
if (loaded_scripts.contains(name))
|
||||
{
|
||||
return &loaded_scripts[name];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class loading final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -3,16 +3,20 @@
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
extern std::unique_ptr<xsk::gsc::iw7::context> gsc_ctx;
|
||||
extern std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||
|
||||
struct source_pos_info
|
||||
struct col_line_t
|
||||
{
|
||||
xsk::u16 line;
|
||||
xsk::u16 column;
|
||||
std::uint16_t line;
|
||||
std::uint16_t column;
|
||||
};
|
||||
using code_pos_map = std::map<uint32_t, source_pos_info>;
|
||||
extern std::unordered_map<std::string, code_pos_map> source_pos_map;
|
||||
|
||||
struct loaded_script_t
|
||||
{
|
||||
game::ScriptFile* ptr;
|
||||
std::map<std::uint32_t, col_line_t> devmap;
|
||||
};
|
||||
|
||||
extern std::unique_ptr<xsk::gsc::iw7::context> gsc_ctx;
|
||||
|
||||
game::ScriptFile* find_script(game::XAssetType type, const char* name, int allow_create_default);
|
||||
loaded_script_t* get_loaded_script(const std::string& name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user