refactor(gsc): remove static allocations (#63)

This commit is contained in:
Xenxo Espasandín 2023-02-12 12:56:27 +01:00 committed by GitHub
parent b3ac7d2562
commit bd05f90a34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 369 additions and 387 deletions

View File

@ -310,7 +310,7 @@ auto assembler::assemble_instruction(instruction const& inst) -> void
assemble_formal_params(inst);
break;
default:
throw asm_error(fmt::format("unhandled opcode {} at index {:04X}", opcode_name(inst.opcode), inst.index));
throw asm_error(fmt::format("unhandled opcode {} at index {:04X}", ctx_->opcode_name(inst.opcode), inst.index));
}
}

View File

@ -9,30 +9,57 @@
namespace xsk::gsc
{
read_cb_type read_callback = nullptr;
std::unordered_map<std::string, buffer> header_files;
std::set<std::string_view> includes;
std::unordered_map<std::string, std::vector<std::string>> include_cache;
std::set<std::string> new_func_map;
std::set<std::string> new_meth_map;
extern std::array<std::pair<opcode, std::string_view>, opcode_count> const opcode_list;
context::context(gsc::props props, gsc::engine engine, gsc::endian endian, gsc::system system, u32 str_count)
: props_{ props }, engine_{ engine }, endian_{ endian }, system_{ system }, str_count_{ str_count },
source_{ this }, assembler_{ this }, disassembler_{ this }, compiler_{ this }, decompiler_{ this }
{
opcode_map_.reserve(opcode_list.size());
opcode_map_rev_.reserve(opcode_list.size());
for (auto const& entry : opcode_list)
{
opcode_map_.insert({ entry.first, entry.second });
opcode_map_rev_.insert({ entry.second, entry.first });
}
}
auto context::init(gsc::build build, read_cb_type callback) -> void
auto context::init(gsc::build build, fs_callback callback) -> void
{
build_ = build;
read_callback = callback;
fs_callback_ = callback;
}
auto context::cleanup() -> void
{
header_files.clear();
include_cache.clear();
includes.clear();
source_ = gsc::source{ this };
assembler_ = gsc::assembler{ this };
disassembler_ = gsc::disassembler{ this };
compiler_ = gsc::compiler{ this };
decompiler_ = gsc::decompiler{ this };
header_files_.clear();
include_cache_.clear();
includes_.clear();
}
auto context::engine_name() const -> std::string_view
{
switch (engine_)
{
case engine::iw5: return "IW5";
case engine::iw6: return "IW6";
case engine::iw7: return "IW7";
case engine::iw8: return "IW8";
case engine::iw9: return "IW9";
case engine::s1: return "S1";
case engine::s2: return "S2";
case engine::s4: return "S4";
case engine::h1: return "H1";
case engine::h2: return "H2";
}
return "";
}
auto context::opcode_size(opcode op) const -> u32
@ -273,6 +300,30 @@ auto context::opcode_id(opcode op) const -> u8
throw error(fmt::format("couldn't resolve opcode id for '{}'", opcode_name(op)));
}
auto context::opcode_name(opcode op) const -> std::string
{
auto const itr = opcode_map_.find(op);
if (itr != opcode_map_.end())
{
return std::string{ itr->second };
}
throw std::runtime_error(fmt::format("couldn't resolve opcode string for enum '{}'", static_cast<std::underlying_type_t<opcode>>(op)));
}
auto context::opcode_enum(std::string const& name) const -> opcode
{
auto const itr = opcode_map_rev_.find(name);
if (itr != opcode_map_rev_.end())
{
return itr->second;
}
throw std::runtime_error(fmt::format("couldn't resolve opcode enum for name '{}'", name));
}
auto context::opcode_enum(u8 id) const -> opcode
{
auto const itr = code_map_.find(id);
@ -337,16 +388,16 @@ auto context::func_add(std::string const& name, u16 id) -> void
throw error(fmt::format("builtin function '{}' already defined", name));
}
auto const str = new_func_map.find(name);
auto const str = new_func_map_.find(name);
if (str != new_func_map.end())
if (str != new_func_map_.end())
{
func_map_.insert({ id, *str });
func_map_rev_.insert({ *str, id });
}
else
{
auto ins = new_func_map.insert(name);
auto ins = new_func_map_.insert(name);
if (ins.second)
{
@ -408,16 +459,16 @@ auto context::meth_add(std::string const& name, u16 id) -> void
throw error(fmt::format("builtin method '{}' already defined", name));
}
auto const str = new_meth_map.find(name);
auto const str = new_meth_map_.find(name);
if (str != new_meth_map.end())
if (str != new_meth_map_.end())
{
meth_map_.insert({ id, *str });
meth_map_rev_.insert({ *str, id });
}
else
{
auto ins = new_meth_map.insert(name);
auto ins = new_meth_map_.insert(name);
if (ins.second)
{
@ -552,20 +603,21 @@ auto context::make_token(std::string_view str) const -> std::string
return data;
}
auto context::header_file_data(std::string const& name) const -> std::tuple<std::string const*, char const*, usize>
auto context::load_header(std::string const& name) -> std::tuple<std::string const*, char const*, usize>
{
auto const itr = header_files.find(name);
// todo: remove cache to prevent use after free if files are read from fs by the game
auto const itr = header_files_.find(name);
if (itr != header_files.end())
if (itr != header_files_.end())
{
return { &itr->first, reinterpret_cast<char const*>(itr->second.data), itr->second.size };
}
auto data = read_callback(name);
auto data = fs_callback_(name);
if (data.first.data != nullptr && data.first.size != 0 && data.second.data == nullptr && data.second.size == 0)
if (data.first.data != nullptr && data.first.size != 0 && data.second.size() == 0)
{
auto const res = header_files.insert({ name, data.first });
auto const res = header_files_.insert({ name, data.first });
if (res.second)
{
@ -580,22 +632,22 @@ auto context::load_include(std::string const& name) -> bool
{
try
{
if (includes.contains(name))
if (includes_.contains(name))
{
return false;
}
includes.insert(name);
includes_.insert(name);
if (include_cache.contains(name))
if (include_cache_.contains(name))
return true;
auto file = read_callback(name);
auto file = fs_callback_(name);
if (file.first.data == nullptr && file.first.size == 0)
throw std::runtime_error("empty file");
if (file.second.data == nullptr && file.second.size == 0)
if (file.second.size() == 0)
{
// process RawFile
auto prog = source_.parse_program(name, file.first);
@ -610,12 +662,12 @@ auto context::load_include(std::string const& name) -> bool
}
}
include_cache.insert({ name, std::move(funcs) });
include_cache_.insert({ name, std::move(funcs) });
}
else
{
// process ScriptFile
auto data = disassembler_.disassemble(file.first, file.second);
auto data = disassembler_.disassemble(file.first, buffer{ file.second.data(), file.second.size() });
auto funcs = std::vector<std::string>{};
@ -624,7 +676,7 @@ auto context::load_include(std::string const& name) -> bool
funcs.push_back(fun->name);
}
include_cache.insert({ name, std::move(funcs) });
include_cache_.insert({ name, std::move(funcs) });
}
return true;
@ -637,14 +689,14 @@ auto context::load_include(std::string const& name) -> bool
auto context::init_includes() -> void
{
includes.clear();
includes_.clear();
}
auto context::is_includecall(std::string const& name, std::string& path) -> bool
{
for (auto const& inc : includes)
for (auto const& inc : includes_)
{
for (auto const& fun : include_cache.at(std::string{ inc }))
for (auto const& fun : include_cache_.at(std::string{ inc }))
{
if (name == fun)
{
@ -657,4 +709,213 @@ auto context::is_includecall(std::string const& name, std::string& path) -> bool
return false;
}
extern std::array<std::pair<opcode, std::string_view>, opcode_count> const opcode_list
{{
{ opcode::vm_invalid, "vm_invalid" },
{ opcode::OP_CastFieldObject, "OP_CastFieldObject" },
{ opcode::OP_SetLocalVariableFieldCached, "OP_SetLocalVariableFieldCached" },
{ opcode::OP_plus, "OP_plus" },
{ opcode::OP_RemoveLocalVariables, "OP_RemoveLocalVariables" },
{ opcode::OP_EvalSelfFieldVariableRef, "OP_EvalSelfFieldVariableRef" },
{ opcode::OP_ScriptFarMethodChildThreadCall, "OP_ScriptFarMethodChildThreadCall" },
{ opcode::OP_GetGameRef, "OP_GetGameRef" },
{ opcode::OP_EvalAnimFieldVariable, "OP_EvalAnimFieldVariable" },
{ opcode::OP_EvalLevelFieldVariableRef, "OP_EvalLevelFieldVariableRef" },
{ opcode::OP_GetThisthread, "OP_GetThisthread" },
{ opcode::OP_greater, "OP_greater" },
{ opcode::OP_waittillmatch, "OP_waittillmatch" },
{ opcode::OP_shift_right, "OP_shift_right" },
{ opcode::OP_dec, "OP_dec" },
{ opcode::OP_JumpOnTrue, "OP_JumpOnTrue" },
{ opcode::OP_bit_or, "OP_bit_or" },
{ opcode::OP_equality, "OP_equality" },
{ opcode::OP_ClearLocalVariableFieldCached0, "OP_ClearLocalVariableFieldCached0" },
{ opcode::OP_notify, "OP_notify" },
{ opcode::OP_GetVector, "OP_GetVector" },
{ opcode::OP_ScriptMethodChildThreadCallPointer, "OP_ScriptMethodChildThreadCallPointer" },
{ opcode::OP_PreScriptCall, "OP_PreScriptCall" },
{ opcode::OP_GetByte, "OP_GetByte" },
{ opcode::OP_ScriptFarThreadCall, "OP_ScriptFarThreadCall" },
{ opcode::OP_SetSelfFieldVariableField, "OP_SetSelfFieldVariableField" },
{ opcode::OP_JumpOnFalseExpr, "OP_JumpOnFalseExpr" },
{ opcode::OP_GetUndefined, "OP_GetUndefined" },
{ opcode::OP_jumpback, "OP_jumpback" },
{ opcode::OP_JumpOnTrueExpr, "OP_JumpOnTrueExpr" },
{ opcode::OP_CallBuiltin0, "OP_CallBuiltin0" },
{ opcode::OP_CallBuiltin1, "OP_CallBuiltin1" },
{ opcode::OP_CallBuiltin2, "OP_CallBuiltin2" },
{ opcode::OP_CallBuiltin3, "OP_CallBuiltin3" },
{ opcode::OP_CallBuiltin4, "OP_CallBuiltin4" },
{ opcode::OP_CallBuiltin5, "OP_CallBuiltin5" },
{ opcode::OP_CallBuiltin, "OP_CallBuiltin" },
{ opcode::OP_SetLocalVariableFieldCached0, "OP_SetLocalVariableFieldCached0" },
{ opcode::OP_ClearFieldVariable, "OP_ClearFieldVariable" },
{ opcode::OP_GetLevel, "OP_GetLevel" },
{ opcode::OP_size, "OP_size" },
{ opcode::OP_SafeSetWaittillVariableFieldCached, "OP_SafeSetWaittillVariableFieldCached" },
{ opcode::OP_ScriptLocalMethodThreadCall, "OP_ScriptLocalMethodThreadCall" },
{ opcode::OP_AddArray, "OP_AddArray" },
{ opcode::OP_endon, "OP_endon" },
{ opcode::OP_EvalFieldVariable, "OP_EvalFieldVariable" },
{ opcode::OP_shift_left, "OP_shift_left" },
{ opcode::OP_EvalLocalArrayRefCached0, "OP_EvalLocalArrayRefCached0" },
{ opcode::OP_Return, "OP_Return" },
{ opcode::OP_CreateLocalVariable, "OP_CreateLocalVariable" },
{ opcode::OP_SafeSetVariableFieldCached0, "OP_SafeSetVariableFieldCached0" },
{ opcode::OP_GetBuiltinFunction, "OP_GetBuiltinFunction" },
{ opcode::OP_ScriptLocalMethodCall, "OP_ScriptLocalMethodCall" },
{ opcode::OP_CallBuiltinMethodPointer, "OP_CallBuiltinMethodPointer" },
{ opcode::OP_ScriptLocalChildThreadCall, "OP_ScriptLocalChildThreadCall" },
{ opcode::OP_GetSelfObject, "OP_GetSelfObject" },
{ opcode::OP_GetGame, "OP_GetGame" },
{ opcode::OP_SetLevelFieldVariableField, "OP_SetLevelFieldVariableField" },
{ opcode::OP_EvalArray, "OP_EvalArray" },
{ opcode::OP_GetSelf, "OP_GetSelf" },
{ opcode::OP_End, "OP_End" },
{ opcode::OP_EvalSelfFieldVariable, "OP_EvalSelfFieldVariable" },
{ opcode::OP_less_equal, "OP_less_equal" },
{ opcode::OP_EvalLocalVariableCached0, "OP_EvalLocalVariableCached0" },
{ opcode::OP_EvalLocalVariableCached1, "OP_EvalLocalVariableCached1" },
{ opcode::OP_EvalLocalVariableCached2, "OP_EvalLocalVariableCached2" },
{ opcode::OP_EvalLocalVariableCached3, "OP_EvalLocalVariableCached3" },
{ opcode::OP_EvalLocalVariableCached4, "OP_EvalLocalVariableCached4" },
{ opcode::OP_EvalLocalVariableCached5, "OP_EvalLocalVariableCached5" },
{ opcode::OP_EvalLocalVariableCached, "OP_EvalLocalVariableCached" },
{ opcode::OP_EvalNewLocalArrayRefCached0, "OP_EvalNewLocalArrayRefCached0" },
{ opcode::OP_ScriptChildThreadCallPointer, "OP_ScriptChildThreadCallPointer" },
{ opcode::OP_EvalLocalVariableObjectCached, "OP_EvalLocalVariableObjectCached" },
{ opcode::OP_ScriptLocalThreadCall, "OP_ScriptLocalThreadCall" },
{ opcode::OP_GetInteger, "OP_GetInteger" },
{ opcode::OP_ScriptMethodCallPointer, "OP_ScriptMethodCallPointer" },
{ opcode::OP_checkclearparams, "OP_checkclearparams" },
{ opcode::OP_SetAnimFieldVariableField, "OP_SetAnimFieldVariableField" },
{ opcode::OP_waittillmatch2, "OP_waittillmatch2" },
{ opcode::OP_minus, "OP_minus" },
{ opcode::OP_ScriptLocalFunctionCall2, "OP_ScriptLocalFunctionCall2" },
{ opcode::OP_GetNegUnsignedShort, "OP_GetNegUnsignedShort" },
{ opcode::OP_GetNegByte, "OP_GetNegByte" },
{ opcode::OP_SafeCreateVariableFieldCached, "OP_SafeCreateVariableFieldCached" },
{ opcode::OP_greater_equal, "OP_greater_equal" },
{ opcode::OP_vector, "OP_vector" },
{ opcode::OP_GetBuiltinMethod, "OP_GetBuiltinMethod" },
{ opcode::OP_endswitch, "OP_endswitch" },
{ opcode::OP_ClearArray, "OP_ClearArray" },
{ opcode::OP_DecTop, "OP_DecTop" },
{ opcode::OP_CastBool, "OP_CastBool" },
{ opcode::OP_EvalArrayRef, "OP_EvalArrayRef" },
{ opcode::OP_SetNewLocalVariableFieldCached0, "OP_SetNewLocalVariableFieldCached0" },
{ opcode::OP_GetZero, "OP_GetZero" },
{ opcode::OP_wait, "OP_wait" },
{ opcode::OP_waittill, "OP_waittill" },
{ opcode::OP_GetIString, "OP_GetIString" },
{ opcode::OP_ScriptFarFunctionCall, "OP_ScriptFarFunctionCall" },
{ opcode::OP_GetAnimObject, "OP_GetAnimObject" },
{ opcode::OP_GetAnimTree, "OP_GetAnimTree" },
{ opcode::OP_EvalLocalArrayCached, "OP_EvalLocalArrayCached" },
{ opcode::OP_mod, "OP_mod" },
{ opcode::OP_ScriptFarMethodThreadCall, "OP_ScriptFarMethodThreadCall" },
{ opcode::OP_GetUnsignedShort, "OP_GetUnsignedShort" },
{ opcode::OP_clearparams, "OP_clearparams" },
{ opcode::OP_ScriptMethodThreadCallPointer, "OP_ScriptMethodThreadCallPointer" },
{ opcode::OP_ScriptFunctionCallPointer, "OP_ScriptFunctionCallPointer" },
{ opcode::OP_EmptyArray, "OP_EmptyArray" },
{ opcode::OP_SafeSetVariableFieldCached, "OP_SafeSetVariableFieldCached" },
{ opcode::OP_ClearVariableField, "OP_ClearVariableField" },
{ opcode::OP_EvalFieldVariableRef, "OP_EvalFieldVariableRef" },
{ opcode::OP_ScriptLocalMethodChildThreadCall, "OP_ScriptLocalMethodChildThreadCall" },
{ opcode::OP_EvalNewLocalVariableRefCached0, "OP_EvalNewLocalVariableRefCached0" },
{ opcode::OP_GetFloat, "OP_GetFloat" },
{ opcode::OP_EvalLocalVariableRefCached, "OP_EvalLocalVariableRefCached" },
{ opcode::OP_JumpOnFalse, "OP_JumpOnFalse" },
{ opcode::OP_BoolComplement, "OP_BoolComplement" },
{ opcode::OP_ScriptThreadCallPointer, "OP_ScriptThreadCallPointer" },
{ opcode::OP_ScriptFarFunctionCall2, "OP_ScriptFarFunctionCall2" },
{ opcode::OP_less, "OP_less" },
{ opcode::OP_BoolNot, "OP_BoolNot" },
{ opcode::OP_waittillFrameEnd, "OP_waittillFrameEnd" },
{ opcode::OP_waitframe, "OP_waitframe" },
{ opcode::OP_GetString, "OP_GetString" },
{ opcode::OP_EvalLevelFieldVariable, "OP_EvalLevelFieldVariable" },
{ opcode::OP_GetLevelObject, "OP_GetLevelObject" },
{ opcode::OP_inc, "OP_inc" },
{ opcode::OP_CallBuiltinMethod0, "OP_CallBuiltinMethod0" },
{ opcode::OP_CallBuiltinMethod1, "OP_CallBuiltinMethod1" },
{ opcode::OP_CallBuiltinMethod2, "OP_CallBuiltinMethod2" },
{ opcode::OP_CallBuiltinMethod3, "OP_CallBuiltinMethod3" },
{ opcode::OP_CallBuiltinMethod4, "OP_CallBuiltinMethod4" },
{ opcode::OP_CallBuiltinMethod5, "OP_CallBuiltinMethod5" },
{ opcode::OP_CallBuiltinMethod, "OP_CallBuiltinMethod" },
{ opcode::OP_GetAnim, "OP_GetAnim" },
{ opcode::OP_switch, "OP_switch" },
{ opcode::OP_SetVariableField, "OP_SetVariableField" },
{ opcode::OP_divide, "OP_divide" },
{ opcode::OP_GetLocalFunction, "OP_GetLocalFunction" },
{ opcode::OP_ScriptFarChildThreadCall, "OP_ScriptFarChildThreadCall" },
{ opcode::OP_multiply, "OP_multiply" },
{ opcode::OP_ClearLocalVariableFieldCached, "OP_ClearLocalVariableFieldCached" },
{ opcode::OP_EvalAnimFieldVariableRef, "OP_EvalAnimFieldVariableRef" },
{ opcode::OP_EvalLocalArrayRefCached, "OP_EvalLocalArrayRefCached" },
{ opcode::OP_EvalLocalVariableRefCached0, "OP_EvalLocalVariableRefCached0" },
{ opcode::OP_bit_and, "OP_bit_and" },
{ opcode::OP_GetAnimation, "OP_GetAnimation" },
{ opcode::OP_GetFarFunction, "OP_GetFarFunction" },
{ opcode::OP_CallBuiltinPointer, "OP_CallBuiltinPointer" },
{ opcode::OP_jump, "OP_jump" },
{ opcode::OP_voidCodepos, "OP_voidCodepos" },
{ opcode::OP_ScriptFarMethodCall, "OP_ScriptFarMethodCall" },
{ opcode::OP_inequality, "OP_inequality" },
{ opcode::OP_ScriptLocalFunctionCall, "OP_ScriptLocalFunctionCall" },
{ opcode::OP_bit_ex_or, "OP_bit_ex_or" },
{ opcode::OP_NOP, "OP_NOP" },
{ opcode::OP_abort, "OP_abort" },
{ opcode::OP_object, "OP_object" },
{ opcode::OP_thread_object, "OP_thread_object" },
{ opcode::OP_EvalLocalVariable, "OP_EvalLocalVariable" },
{ opcode::OP_EvalLocalVariableRef, "OP_EvalLocalVariableRef" },
{ opcode::OP_prof_begin, "OP_prof_begin" },
{ opcode::OP_prof_end, "OP_prof_end" },
{ opcode::OP_breakpoint, "OP_breakpoint" },
{ opcode::OP_assignmentBreakpoint, "OP_assignmentBreakpoint" },
{ opcode::OP_manualAndAssignmentBreakpoint, "OP_manualAndAssignmentBreakpoint" },
{ opcode::OP_BoolNotAfterAnd, "OP_BoolNotAfterAnd" },
{ opcode::OP_FormalParams, "OP_FormalParams" },
{ opcode::OP_IsDefined, "OP_IsDefined" },
{ opcode::OP_IsTrue, "OP_IsTrue" },
{ opcode::OP_NativeGetLocalFunction, "OP_NativeGetLocalFunction" },
{ opcode::OP_NativeLocalFunctionCall, "OP_NativeLocalFunctionCall" },
{ opcode::OP_NativeLocalFunctionCall2, "OP_NativeLocalFunctionCall2" },
{ opcode::OP_NativeLocalMethodCall, "OP_NativeLocalMethodCall" },
{ opcode::OP_NativeLocalFunctionThreadCall, "OP_NativeLocalFunctionThreadCall" },
{ opcode::OP_NativeLocalMethodThreadCall, "OP_NativeLocalMethodThreadCall" },
{ opcode::OP_NativeLocalFunctionChildThreadCall, "OP_NativeLocalFunctionChildThreadCall" },
{ opcode::OP_NativeLocalMethodChildThreadCall, "OP_NativeLocalMethodChildThreadCall" },
{ opcode::OP_NativeGetFarFunction, "OP_NativeGetFarFunction" },
{ opcode::OP_NativeFarFunctionCall, "OP_NativeFarFunctionCall" },
{ opcode::OP_NativeFarFunctionCall2, "OP_NativeFarFunctionCall2" },
{ opcode::OP_NativeFarMethodCall, "OP_NativeFarMethodCall" },
{ opcode::OP_NativeFarFunctionThreadCall, "OP_NativeFarFunctionThreadCall" },
{ opcode::OP_NativeFarMethodThreadCall, "OP_NativeFarMethodThreadCall" },
{ opcode::OP_NativeFarFunctionChildThreadCall, "OP_NativeFarFunctionChildThreadCall" },
{ opcode::OP_NativeFarMethodChildThreadCall, "OP_NativeFarMethodChildThreadCall" },
{ opcode::OP_EvalNewLocalArrayRefCached0_Precompiled, "OP_EvalNewLocalArrayRefCached0_Precompiled" },
{ opcode::OP_SetNewLocalVariableFieldCached0_Precompiled, "OP_SetNewLocalVariableFieldCached0_Precompiled" },
{ opcode::OP_CreateLocalVariable_Precompiled, "OP_CreateLocalVariable_Precompiled" },
{ opcode::OP_SafeCreateVariableFieldCached_Precompiled, "OP_SafeCreateVariableFieldCached_Precompiled" },
{ opcode::OP_FormalParams_Precompiled, "OP_FormalParams_Precompiled" },
{ opcode::OP_GetStatHash, "OP_GetStatHash" },
{ opcode::OP_GetUnkxHash, "OP_GetUnkxHash" },
{ opcode::OP_GetEnumHash, "OP_GetEnumHash" },
{ opcode::OP_GetDvarHash, "OP_GetDvarHash" },
{ opcode::OP_GetUnsignedInt, "OP_GetUnsignedInt" },
{ opcode::OP_GetNegUnsignedInt, "OP_GetNegUnsignedInt" },
{ opcode::OP_GetInteger64, "OP_GetInteger64" },
{ opcode::OP_iw9_139, "OP_iw9_139" },
{ opcode::OP_iw9_140, "OP_iw9_140" },
{ opcode::OP_iw9_141, "OP_iw9_141" },
{ opcode::OP_iw9_142, "OP_iw9_142" },
{ opcode::OP_iw9_143, "OP_iw9_143" },
{ opcode::OP_iw9_144, "OP_iw9_144" },
{ opcode::OP_iw9_166, "OP_iw9_166" },
}};
} // namespace xsk::gsc

View File

@ -18,6 +18,8 @@ namespace xsk::gsc
class context
{
public:
using fs_callback = std::function<std::pair<buffer, std::vector<u8>>(std::string const&)>;
context(props props, engine engine, endian endian, system system, u32 str_count);
auto props() const -> props { return props_; }
@ -45,14 +47,20 @@ public:
auto func_map() const -> std::unordered_map<std::string_view, u16> const& { return func_map_rev_; }
auto meth_map() const -> std::unordered_map<std::string_view, u16> const& { return meth_map_rev_; }
auto init(gsc::build build, read_cb_type callback) -> void;
auto init(gsc::build build, fs_callback callback) -> void;
auto cleanup() -> void;
auto engine_name() const -> std::string_view;
auto opcode_size(opcode op) const -> u32;
auto opcode_id(opcode op) const -> u8;
auto opcode_name(opcode op) const -> std::string;
auto opcode_enum(std::string const& name) const -> opcode;
auto opcode_enum(u8 id) const -> opcode;
auto func_id(std::string const& name) const -> u16;
@ -85,9 +93,7 @@ public:
auto make_token(std::string_view str) const -> std::string;
auto header_file_data(std::string const& name) const -> std::tuple<std::string const*, char const*, usize>;
auto fs_to_game_path(std::filesystem::path const& file) const -> std::filesystem::path;
auto load_header(std::string const& name) -> std::tuple<std::string const*, char const*, usize>;
auto load_include(std::string const& name) -> bool;
@ -107,6 +113,9 @@ protected:
gsc::disassembler disassembler_;
gsc::compiler compiler_;
gsc::decompiler decompiler_;
fs_callback fs_callback_;
std::unordered_map<opcode, std::string_view> opcode_map_;
std::unordered_map<std::string_view, opcode> opcode_map_rev_;
std::unordered_map<u8, opcode> code_map_;
std::unordered_map<opcode, u8> code_map_rev_;
std::unordered_map<u16, std::string_view> func_map_;
@ -117,6 +126,11 @@ protected:
std::unordered_map<std::string_view, u32> token_map_rev_;
std::unordered_map<u64, std::string_view> path_map_;
std::unordered_map<u64, std::string_view> hash_map_;
std::unordered_map<std::string, buffer> header_files_;
std::unordered_set<std::string_view> includes_;
std::unordered_map<std::string, std::vector<std::string>> include_cache_;
std::unordered_set<std::string> new_func_map_;
std::unordered_set<std::string> new_meth_map_;
};
} // namespace xsk::gsc

View File

@ -1505,7 +1505,7 @@ auto decompiler::decompile_instruction(instruction const& inst) -> void
case opcode::OP_CastBool:
break;
default:
throw decomp_error(fmt::format("unhandled opcode {}", opcode_name(inst.opcode)));
throw decomp_error(fmt::format("unhandled opcode {}", ctx_->opcode_name(inst.opcode)));
}
}

View File

@ -313,7 +313,7 @@ auto disassembler::dissasemble_instruction(instruction& inst) -> void
disassemble_formal_params(inst);
break;
default:
throw disasm_error(fmt::format("unhandled opcode {} at index {:04X}", opcode_name(inst.opcode), inst.index));
throw disasm_error(fmt::format("unhandled opcode {} at index {:04X}", ctx_->opcode_name(inst.opcode), inst.index));
}
}

View File

@ -1,267 +0,0 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "assembly.hpp"
namespace xsk::gsc
{
std::array<std::pair<opcode, std::string_view>, opcode_count> const opcode_list
{{
{ opcode::vm_invalid, "vm_invalid" },
{ opcode::OP_CastFieldObject, "OP_CastFieldObject" },
{ opcode::OP_SetLocalVariableFieldCached, "OP_SetLocalVariableFieldCached" },
{ opcode::OP_plus, "OP_plus" },
{ opcode::OP_RemoveLocalVariables, "OP_RemoveLocalVariables" },
{ opcode::OP_EvalSelfFieldVariableRef, "OP_EvalSelfFieldVariableRef" },
{ opcode::OP_ScriptFarMethodChildThreadCall, "OP_ScriptFarMethodChildThreadCall" },
{ opcode::OP_GetGameRef, "OP_GetGameRef" },
{ opcode::OP_EvalAnimFieldVariable, "OP_EvalAnimFieldVariable" },
{ opcode::OP_EvalLevelFieldVariableRef, "OP_EvalLevelFieldVariableRef" },
{ opcode::OP_GetThisthread, "OP_GetThisthread" },
{ opcode::OP_greater, "OP_greater" },
{ opcode::OP_waittillmatch, "OP_waittillmatch" },
{ opcode::OP_shift_right, "OP_shift_right" },
{ opcode::OP_dec, "OP_dec" },
{ opcode::OP_JumpOnTrue, "OP_JumpOnTrue" },
{ opcode::OP_bit_or, "OP_bit_or" },
{ opcode::OP_equality, "OP_equality" },
{ opcode::OP_ClearLocalVariableFieldCached0, "OP_ClearLocalVariableFieldCached0" },
{ opcode::OP_notify, "OP_notify" },
{ opcode::OP_GetVector, "OP_GetVector" },
{ opcode::OP_ScriptMethodChildThreadCallPointer, "OP_ScriptMethodChildThreadCallPointer" },
{ opcode::OP_PreScriptCall, "OP_PreScriptCall" },
{ opcode::OP_GetByte, "OP_GetByte" },
{ opcode::OP_ScriptFarThreadCall, "OP_ScriptFarThreadCall" },
{ opcode::OP_SetSelfFieldVariableField, "OP_SetSelfFieldVariableField" },
{ opcode::OP_JumpOnFalseExpr, "OP_JumpOnFalseExpr" },
{ opcode::OP_GetUndefined, "OP_GetUndefined" },
{ opcode::OP_jumpback, "OP_jumpback" },
{ opcode::OP_JumpOnTrueExpr, "OP_JumpOnTrueExpr" },
{ opcode::OP_CallBuiltin0, "OP_CallBuiltin0" },
{ opcode::OP_CallBuiltin1, "OP_CallBuiltin1" },
{ opcode::OP_CallBuiltin2, "OP_CallBuiltin2" },
{ opcode::OP_CallBuiltin3, "OP_CallBuiltin3" },
{ opcode::OP_CallBuiltin4, "OP_CallBuiltin4" },
{ opcode::OP_CallBuiltin5, "OP_CallBuiltin5" },
{ opcode::OP_CallBuiltin, "OP_CallBuiltin" },
{ opcode::OP_SetLocalVariableFieldCached0, "OP_SetLocalVariableFieldCached0" },
{ opcode::OP_ClearFieldVariable, "OP_ClearFieldVariable" },
{ opcode::OP_GetLevel, "OP_GetLevel" },
{ opcode::OP_size, "OP_size" },
{ opcode::OP_SafeSetWaittillVariableFieldCached, "OP_SafeSetWaittillVariableFieldCached" },
{ opcode::OP_ScriptLocalMethodThreadCall, "OP_ScriptLocalMethodThreadCall" },
{ opcode::OP_AddArray, "OP_AddArray" },
{ opcode::OP_endon, "OP_endon" },
{ opcode::OP_EvalFieldVariable, "OP_EvalFieldVariable" },
{ opcode::OP_shift_left, "OP_shift_left" },
{ opcode::OP_EvalLocalArrayRefCached0, "OP_EvalLocalArrayRefCached0" },
{ opcode::OP_Return, "OP_Return" },
{ opcode::OP_CreateLocalVariable, "OP_CreateLocalVariable" },
{ opcode::OP_SafeSetVariableFieldCached0, "OP_SafeSetVariableFieldCached0" },
{ opcode::OP_GetBuiltinFunction, "OP_GetBuiltinFunction" },
{ opcode::OP_ScriptLocalMethodCall, "OP_ScriptLocalMethodCall" },
{ opcode::OP_CallBuiltinMethodPointer, "OP_CallBuiltinMethodPointer" },
{ opcode::OP_ScriptLocalChildThreadCall, "OP_ScriptLocalChildThreadCall" },
{ opcode::OP_GetSelfObject, "OP_GetSelfObject" },
{ opcode::OP_GetGame, "OP_GetGame" },
{ opcode::OP_SetLevelFieldVariableField, "OP_SetLevelFieldVariableField" },
{ opcode::OP_EvalArray, "OP_EvalArray" },
{ opcode::OP_GetSelf, "OP_GetSelf" },
{ opcode::OP_End, "OP_End" },
{ opcode::OP_EvalSelfFieldVariable, "OP_EvalSelfFieldVariable" },
{ opcode::OP_less_equal, "OP_less_equal" },
{ opcode::OP_EvalLocalVariableCached0, "OP_EvalLocalVariableCached0" },
{ opcode::OP_EvalLocalVariableCached1, "OP_EvalLocalVariableCached1" },
{ opcode::OP_EvalLocalVariableCached2, "OP_EvalLocalVariableCached2" },
{ opcode::OP_EvalLocalVariableCached3, "OP_EvalLocalVariableCached3" },
{ opcode::OP_EvalLocalVariableCached4, "OP_EvalLocalVariableCached4" },
{ opcode::OP_EvalLocalVariableCached5, "OP_EvalLocalVariableCached5" },
{ opcode::OP_EvalLocalVariableCached, "OP_EvalLocalVariableCached" },
{ opcode::OP_EvalNewLocalArrayRefCached0, "OP_EvalNewLocalArrayRefCached0" },
{ opcode::OP_ScriptChildThreadCallPointer, "OP_ScriptChildThreadCallPointer" },
{ opcode::OP_EvalLocalVariableObjectCached, "OP_EvalLocalVariableObjectCached" },
{ opcode::OP_ScriptLocalThreadCall, "OP_ScriptLocalThreadCall" },
{ opcode::OP_GetInteger, "OP_GetInteger" },
{ opcode::OP_ScriptMethodCallPointer, "OP_ScriptMethodCallPointer" },
{ opcode::OP_checkclearparams, "OP_checkclearparams" },
{ opcode::OP_SetAnimFieldVariableField, "OP_SetAnimFieldVariableField" },
{ opcode::OP_waittillmatch2, "OP_waittillmatch2" },
{ opcode::OP_minus, "OP_minus" },
{ opcode::OP_ScriptLocalFunctionCall2, "OP_ScriptLocalFunctionCall2" },
{ opcode::OP_GetNegUnsignedShort, "OP_GetNegUnsignedShort" },
{ opcode::OP_GetNegByte, "OP_GetNegByte" },
{ opcode::OP_SafeCreateVariableFieldCached, "OP_SafeCreateVariableFieldCached" },
{ opcode::OP_greater_equal, "OP_greater_equal" },
{ opcode::OP_vector, "OP_vector" },
{ opcode::OP_GetBuiltinMethod, "OP_GetBuiltinMethod" },
{ opcode::OP_endswitch, "OP_endswitch" },
{ opcode::OP_ClearArray, "OP_ClearArray" },
{ opcode::OP_DecTop, "OP_DecTop" },
{ opcode::OP_CastBool, "OP_CastBool" },
{ opcode::OP_EvalArrayRef, "OP_EvalArrayRef" },
{ opcode::OP_SetNewLocalVariableFieldCached0, "OP_SetNewLocalVariableFieldCached0" },
{ opcode::OP_GetZero, "OP_GetZero" },
{ opcode::OP_wait, "OP_wait" },
{ opcode::OP_waittill, "OP_waittill" },
{ opcode::OP_GetIString, "OP_GetIString" },
{ opcode::OP_ScriptFarFunctionCall, "OP_ScriptFarFunctionCall" },
{ opcode::OP_GetAnimObject, "OP_GetAnimObject" },
{ opcode::OP_GetAnimTree, "OP_GetAnimTree" },
{ opcode::OP_EvalLocalArrayCached, "OP_EvalLocalArrayCached" },
{ opcode::OP_mod, "OP_mod" },
{ opcode::OP_ScriptFarMethodThreadCall, "OP_ScriptFarMethodThreadCall" },
{ opcode::OP_GetUnsignedShort, "OP_GetUnsignedShort" },
{ opcode::OP_clearparams, "OP_clearparams" },
{ opcode::OP_ScriptMethodThreadCallPointer, "OP_ScriptMethodThreadCallPointer" },
{ opcode::OP_ScriptFunctionCallPointer, "OP_ScriptFunctionCallPointer" },
{ opcode::OP_EmptyArray, "OP_EmptyArray" },
{ opcode::OP_SafeSetVariableFieldCached, "OP_SafeSetVariableFieldCached" },
{ opcode::OP_ClearVariableField, "OP_ClearVariableField" },
{ opcode::OP_EvalFieldVariableRef, "OP_EvalFieldVariableRef" },
{ opcode::OP_ScriptLocalMethodChildThreadCall, "OP_ScriptLocalMethodChildThreadCall" },
{ opcode::OP_EvalNewLocalVariableRefCached0, "OP_EvalNewLocalVariableRefCached0" },
{ opcode::OP_GetFloat, "OP_GetFloat" },
{ opcode::OP_EvalLocalVariableRefCached, "OP_EvalLocalVariableRefCached" },
{ opcode::OP_JumpOnFalse, "OP_JumpOnFalse" },
{ opcode::OP_BoolComplement, "OP_BoolComplement" },
{ opcode::OP_ScriptThreadCallPointer, "OP_ScriptThreadCallPointer" },
{ opcode::OP_ScriptFarFunctionCall2, "OP_ScriptFarFunctionCall2" },
{ opcode::OP_less, "OP_less" },
{ opcode::OP_BoolNot, "OP_BoolNot" },
{ opcode::OP_waittillFrameEnd, "OP_waittillFrameEnd" },
{ opcode::OP_waitframe, "OP_waitframe" },
{ opcode::OP_GetString, "OP_GetString" },
{ opcode::OP_EvalLevelFieldVariable, "OP_EvalLevelFieldVariable" },
{ opcode::OP_GetLevelObject, "OP_GetLevelObject" },
{ opcode::OP_inc, "OP_inc" },
{ opcode::OP_CallBuiltinMethod0, "OP_CallBuiltinMethod0" },
{ opcode::OP_CallBuiltinMethod1, "OP_CallBuiltinMethod1" },
{ opcode::OP_CallBuiltinMethod2, "OP_CallBuiltinMethod2" },
{ opcode::OP_CallBuiltinMethod3, "OP_CallBuiltinMethod3" },
{ opcode::OP_CallBuiltinMethod4, "OP_CallBuiltinMethod4" },
{ opcode::OP_CallBuiltinMethod5, "OP_CallBuiltinMethod5" },
{ opcode::OP_CallBuiltinMethod, "OP_CallBuiltinMethod" },
{ opcode::OP_GetAnim, "OP_GetAnim" },
{ opcode::OP_switch, "OP_switch" },
{ opcode::OP_SetVariableField, "OP_SetVariableField" },
{ opcode::OP_divide, "OP_divide" },
{ opcode::OP_GetLocalFunction, "OP_GetLocalFunction" },
{ opcode::OP_ScriptFarChildThreadCall, "OP_ScriptFarChildThreadCall" },
{ opcode::OP_multiply, "OP_multiply" },
{ opcode::OP_ClearLocalVariableFieldCached, "OP_ClearLocalVariableFieldCached" },
{ opcode::OP_EvalAnimFieldVariableRef, "OP_EvalAnimFieldVariableRef" },
{ opcode::OP_EvalLocalArrayRefCached, "OP_EvalLocalArrayRefCached" },
{ opcode::OP_EvalLocalVariableRefCached0, "OP_EvalLocalVariableRefCached0" },
{ opcode::OP_bit_and, "OP_bit_and" },
{ opcode::OP_GetAnimation, "OP_GetAnimation" },
{ opcode::OP_GetFarFunction, "OP_GetFarFunction" },
{ opcode::OP_CallBuiltinPointer, "OP_CallBuiltinPointer" },
{ opcode::OP_jump, "OP_jump" },
{ opcode::OP_voidCodepos, "OP_voidCodepos" },
{ opcode::OP_ScriptFarMethodCall, "OP_ScriptFarMethodCall" },
{ opcode::OP_inequality, "OP_inequality" },
{ opcode::OP_ScriptLocalFunctionCall, "OP_ScriptLocalFunctionCall" },
{ opcode::OP_bit_ex_or, "OP_bit_ex_or" },
{ opcode::OP_NOP, "OP_NOP" },
{ opcode::OP_abort, "OP_abort" },
{ opcode::OP_object, "OP_object" },
{ opcode::OP_thread_object, "OP_thread_object" },
{ opcode::OP_EvalLocalVariable, "OP_EvalLocalVariable" },
{ opcode::OP_EvalLocalVariableRef, "OP_EvalLocalVariableRef" },
{ opcode::OP_prof_begin, "OP_prof_begin" },
{ opcode::OP_prof_end, "OP_prof_end" },
{ opcode::OP_breakpoint, "OP_breakpoint" },
{ opcode::OP_assignmentBreakpoint, "OP_assignmentBreakpoint" },
{ opcode::OP_manualAndAssignmentBreakpoint, "OP_manualAndAssignmentBreakpoint" },
{ opcode::OP_BoolNotAfterAnd, "OP_BoolNotAfterAnd" },
{ opcode::OP_FormalParams, "OP_FormalParams" },
{ opcode::OP_IsDefined, "OP_IsDefined" },
{ opcode::OP_IsTrue, "OP_IsTrue" },
{ opcode::OP_NativeGetLocalFunction, "OP_NativeGetLocalFunction" },
{ opcode::OP_NativeLocalFunctionCall, "OP_NativeLocalFunctionCall" },
{ opcode::OP_NativeLocalFunctionCall2, "OP_NativeLocalFunctionCall2" },
{ opcode::OP_NativeLocalMethodCall, "OP_NativeLocalMethodCall" },
{ opcode::OP_NativeLocalFunctionThreadCall, "OP_NativeLocalFunctionThreadCall" },
{ opcode::OP_NativeLocalMethodThreadCall, "OP_NativeLocalMethodThreadCall" },
{ opcode::OP_NativeLocalFunctionChildThreadCall, "OP_NativeLocalFunctionChildThreadCall" },
{ opcode::OP_NativeLocalMethodChildThreadCall, "OP_NativeLocalMethodChildThreadCall" },
{ opcode::OP_NativeGetFarFunction, "OP_NativeGetFarFunction" },
{ opcode::OP_NativeFarFunctionCall, "OP_NativeFarFunctionCall" },
{ opcode::OP_NativeFarFunctionCall2, "OP_NativeFarFunctionCall2" },
{ opcode::OP_NativeFarMethodCall, "OP_NativeFarMethodCall" },
{ opcode::OP_NativeFarFunctionThreadCall, "OP_NativeFarFunctionThreadCall" },
{ opcode::OP_NativeFarMethodThreadCall, "OP_NativeFarMethodThreadCall" },
{ opcode::OP_NativeFarFunctionChildThreadCall, "OP_NativeFarFunctionChildThreadCall" },
{ opcode::OP_NativeFarMethodChildThreadCall, "OP_NativeFarMethodChildThreadCall" },
{ opcode::OP_EvalNewLocalArrayRefCached0_Precompiled, "OP_EvalNewLocalArrayRefCached0_Precompiled" },
{ opcode::OP_SetNewLocalVariableFieldCached0_Precompiled, "OP_SetNewLocalVariableFieldCached0_Precompiled" },
{ opcode::OP_CreateLocalVariable_Precompiled, "OP_CreateLocalVariable_Precompiled" },
{ opcode::OP_SafeCreateVariableFieldCached_Precompiled, "OP_SafeCreateVariableFieldCached_Precompiled" },
{ opcode::OP_FormalParams_Precompiled, "OP_FormalParams_Precompiled" },
{ opcode::OP_GetStatHash, "OP_GetStatHash" },
{ opcode::OP_GetUnkxHash, "OP_GetUnkxHash" },
{ opcode::OP_GetEnumHash, "OP_GetEnumHash" },
{ opcode::OP_GetDvarHash, "OP_GetDvarHash" },
{ opcode::OP_GetUnsignedInt, "OP_GetUnsignedInt" },
{ opcode::OP_GetNegUnsignedInt, "OP_GetNegUnsignedInt" },
{ opcode::OP_GetInteger64, "OP_GetInteger64" },
{ opcode::OP_iw9_139, "OP_iw9_139" },
{ opcode::OP_iw9_140, "OP_iw9_140" },
{ opcode::OP_iw9_141, "OP_iw9_141" },
{ opcode::OP_iw9_142, "OP_iw9_142" },
{ opcode::OP_iw9_143, "OP_iw9_143" },
{ opcode::OP_iw9_144, "OP_iw9_144" },
{ opcode::OP_iw9_166, "OP_iw9_166" },
}};
std::unordered_map<opcode, std::string_view> opcode_map;
std::unordered_map<std::string_view, opcode> opcode_map_rev;
auto opcode_name(opcode op) -> std::string
{
auto const itr = opcode_map.find(op);
if (itr != opcode_map.end())
{
return std::string{ itr->second };
}
throw std::runtime_error(fmt::format("couldn't resolve opcode string for enum '{}'", static_cast<std::underlying_type_t<opcode>>(op)));
}
auto opcode_enum(std::string const& name) -> opcode
{
auto const itr = opcode_map_rev.find(name);
if (itr != opcode_map_rev.end())
{
return itr->second;
}
throw std::runtime_error(fmt::format("couldn't resolve opcode enum for name '{}'", name));
}
struct __init__
{
__init__()
{
static bool init = false;
if (init) return;
init = true;
opcode_map.reserve(opcode_list.size());
opcode_map_rev.reserve(opcode_list.size());
for (auto const& entry : opcode_list)
{
opcode_map.insert({ entry.first, entry.second });
opcode_map_rev.insert({ entry.second, entry.first });
}
}
} _;
} // namespace xsk::gsc

View File

@ -264,7 +264,4 @@ inline auto make_assembly() -> std::unique_ptr<assembly>
return std::unique_ptr<assembly>(new assembly);
}
auto opcode_name(opcode op) -> std::string;
auto opcode_enum(std::string const& name) -> opcode;
} // namespace xsk::gsc

20
src/gsc/misc/buffer.hpp Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
} // namespace xsk::gsc

View File

@ -1,31 +0,0 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "types.hpp"
namespace xsk::gsc
{
auto engine_name(engine engine) -> std::string_view
{
switch (engine)
{
case engine::iw5: return "IW5";
case engine::iw6: return "IW6";
case engine::iw7: return "IW7";
case engine::iw8: return "IW8";
case engine::iw9: return "IW9";
case engine::s1: return "S1";
case engine::s2: return "S2";
case engine::s4: return "S4";
case engine::h1: return "H1";
case engine::h2: return "H2";
}
return "";
}
} // namespace xsk::gsc

View File

@ -7,6 +7,7 @@
#include "asset.hpp"
#include "scope.hpp"
#include "buffer.hpp"
#include "assembly.hpp"
#include "location.hpp"
#include "exception.hpp"
@ -98,19 +99,6 @@ enum class switch_type
string,
};
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
using read_cb_type = std::function<std::pair<buffer, buffer>(std::string const&)>;
auto engine_name(engine engine) -> std::string_view;
// fordward decl for modules ref
class context;

View File

@ -11,7 +11,7 @@
namespace xsk::gsc
{
preprocessor::preprocessor(context const* ctx, std::string const& name, char const* data, usize size) : ctx_{ ctx }, curr_expr_{ 0 }, expand_{ 0 }, skip_{ false }
preprocessor::preprocessor(context* ctx, std::string const& name, char const* data, usize size) : ctx_{ ctx }, curr_expr_{ 0 }, expand_{ 0 }, skip_{ false }
{
lexer_.push(lexer{ ctx, name, data, size });
defines_.reserve(4);
@ -100,7 +100,7 @@ auto preprocessor::push_header(std::string const& file) -> void
throw ppr_error(location{}, fmt::format("recursive header inclusion {} at {}", name, includes_.back()));
}
auto data = ctx_->header_file_data(name);
auto data = ctx_->load_header(name);
includes_.push_back(*std::get<0>(data));
lexer_.push(lexer{ ctx_, *std::get<0>(data), std::get<1>(data), std::get<2>(data) });

View File

@ -13,7 +13,7 @@ namespace xsk::gsc
class preprocessor
{
context const* ctx_;
context* ctx_;
std::stack<lexer> lexer_;
std::stack<directive> indents_;
std::vector<std::string> includes_;
@ -27,7 +27,7 @@ class preprocessor
u32 skip_;
public:
preprocessor(context const* ctx, std::string const& name, char const* data, usize size);
preprocessor(context* ctx, std::string const& name, char const* data, usize size);
auto process() -> token;
auto push_header(std::string const& file) -> void;
auto pop_header() -> void;

View File

@ -13,7 +13,7 @@
namespace xsk::gsc
{
source::source(context const* ctx) : ctx_{ ctx }, indent_{ 0 }
source::source(context* ctx) : ctx_{ ctx }, indent_{ 0 }
{
}
@ -86,7 +86,7 @@ auto source::parse_assembly(u8 const* data, usize size) -> assembly::ptr
{
auto inst = make_instruction();
inst->index = index;
inst->opcode = opcode_enum(opdata[0]);
inst->opcode = ctx_->opcode_enum(opdata[0]);
inst->size = ctx_->opcode_size(inst->opcode);
opdata.erase(opdata.begin());
inst->data = std::move(opdata);
@ -157,7 +157,7 @@ auto source::dump(assembly const& data) -> std::vector<u8>
buf_ = std::vector<u8>{};
buf_.reserve(0x10000);
fmt::format_to(std::back_inserter(buf_), "// {} GSC ASSEMBLY\n", engine_name(ctx_->engine()));
fmt::format_to(std::back_inserter(buf_), "// {} GSC ASSEMBLY\n", ctx_->engine_name());
fmt::format_to(std::back_inserter(buf_), "// Dumped by https://github.com/xensik/gsc-tool\n");
dump_assembly(data);
@ -170,7 +170,7 @@ auto source::dump(program const& data) -> std::vector<u8>
buf_ = std::vector<u8>{};
buf_.reserve(0x10000);
fmt::format_to(std::back_inserter(buf_), "// {} GSC SOURCE\n", engine_name(ctx_->engine()));
fmt::format_to(std::back_inserter(buf_), "// {} GSC SOURCE\n", ctx_->engine_name());
fmt::format_to(std::back_inserter(buf_), "// Dumped by https://github.com/xensik/gsc-tool\n");
dump_program(data);
@ -207,7 +207,7 @@ auto source::dump_function(function const& func) -> void
auto source::dump_instruction(instruction const& inst) -> void
{
fmt::format_to(std::back_inserter(buf_), "\t\t{}", opcode_name(inst.opcode));
fmt::format_to(std::back_inserter(buf_), "\t\t{}", ctx_->opcode_name(inst.opcode));
switch (inst.opcode)
{

View File

@ -12,12 +12,12 @@ namespace xsk::gsc
class source
{
context const* ctx_;
context* ctx_;
std::vector<u8> buf_;
u32 indent_;
public:
source(context const* ctx);
source(context* ctx);
auto parse_assembly(buffer const& data) -> assembly::ptr;
auto parse_assembly(std::vector<u8> const& data) -> assembly::ptr;
auto parse_assembly(u8 const* data, usize size) -> assembly::ptr;

View File

@ -24,6 +24,7 @@
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std::literals;

View File

@ -439,7 +439,7 @@ auto rename_file(game game, fs::path file, fs::path rel) -> void
std::unordered_map<std::string, std::vector<std::uint8_t>> files;
auto read_file_cb(std::string const& name) -> std::pair<buffer, buffer>
auto fs_callback(std::string const& name) -> std::pair<buffer, std::vector<u8>>
{
auto data = utils::file::read(fs::path{ name });
@ -448,12 +448,11 @@ auto read_file_cb(std::string const& name) -> std::pair<buffer, buffer>
asset s;
s.deserialize(data);
auto stk = utils::zlib::decompress(s.buffer, s.len);
auto res1 = files.insert({ name + "1", std::move(s.bytecode) });
auto res2 = files.insert({ name + "2", std::move(stk) });
auto res = files.insert({ name, std::move(s.bytecode) });
if(res1.second && res2.second)
if (res.second)
{
return { {res1.first->second.data(), res1.first->second.size() }, {res2.first->second.data(), res2.first->second.size() } };
return { {res.first->second.data(), res.first->second.size() }, std::move(stk) };
}
}
else
@ -474,7 +473,7 @@ auto init_iw5() -> void
if (!contexts.contains(game::iw5))
{
contexts[game::iw5] = std::make_unique<iw5_pc::context>();
contexts[game::iw5]->init(build::prod, read_file_cb);
contexts[game::iw5]->init(build::prod, fs_callback);
}
}
@ -483,7 +482,7 @@ auto init_iw5_ps() -> void
if (!contexts.contains(game::iw5ps))
{
contexts[game::iw5ps] = std::make_unique<iw5_ps::context>();
contexts[game::iw5ps]->init(build::prod, read_file_cb);
contexts[game::iw5ps]->init(build::prod, fs_callback);
}
}
@ -492,7 +491,7 @@ auto init_iw5_xb() -> void
if (!contexts.contains(game::iw5xb))
{
contexts[game::iw5xb] = std::make_unique<iw5_xb::context>();
contexts[game::iw5xb]->init(build::prod, read_file_cb);
contexts[game::iw5xb]->init(build::prod, fs_callback);
}
}
@ -501,7 +500,7 @@ auto init_iw6() -> void
if (!contexts.contains(game::iw6))
{
contexts[game::iw6] = std::make_unique<iw6_pc::context>();
contexts[game::iw6]->init(build::prod, read_file_cb);
contexts[game::iw6]->init(build::prod, fs_callback);
}
}
@ -510,7 +509,7 @@ auto init_iw6_ps() -> void
if (!contexts.contains(game::iw6ps))
{
contexts[game::iw6ps] = std::make_unique<iw6_ps::context>();
contexts[game::iw6ps]->init(build::prod, read_file_cb);
contexts[game::iw6ps]->init(build::prod, fs_callback);
}
}
@ -519,7 +518,7 @@ auto init_iw6_xb() -> void
if (!contexts.contains(game::iw6xb))
{
contexts[game::iw6xb] = std::make_unique<iw6_xb::context>();
contexts[game::iw6xb]->init(build::prod, read_file_cb);
contexts[game::iw6xb]->init(build::prod, fs_callback);
}
}
@ -528,7 +527,7 @@ auto init_iw7() -> void
if (!contexts.contains(game::iw7))
{
contexts[game::iw7] = std::make_unique<iw7::context>();
contexts[game::iw7]->init(build::prod, read_file_cb);
contexts[game::iw7]->init(build::prod, fs_callback);
}
}
@ -537,7 +536,7 @@ auto init_iw8() -> void
if (!contexts.contains(game::iw8))
{
contexts[game::iw8] = std::make_unique<iw8::context>();
contexts[game::iw8]->init(build::prod, read_file_cb);
contexts[game::iw8]->init(build::prod, fs_callback);
}
}
@ -546,7 +545,7 @@ auto init_iw9() -> void
if (!contexts.contains(game::iw9))
{
contexts[game::iw9] = std::make_unique<iw9::context>();
contexts[game::iw9]->init(build::prod, read_file_cb);
contexts[game::iw9]->init(build::prod, fs_callback);
}
}
@ -555,7 +554,7 @@ auto init_s1() -> void
if (!contexts.contains(game::s1))
{
contexts[game::s1] = std::make_unique<s1_pc::context>();
contexts[game::s1]->init(build::prod, read_file_cb);
contexts[game::s1]->init(build::prod, fs_callback);
}
}
@ -564,7 +563,7 @@ auto init_s1_ps() -> void
if (!contexts.contains(game::s1ps))
{
contexts[game::s1ps] = std::make_unique<s1_ps::context>();
contexts[game::s1ps]->init(build::prod, read_file_cb);
contexts[game::s1ps]->init(build::prod, fs_callback);
}
}
@ -573,7 +572,7 @@ auto init_s1_xb() -> void
if (!contexts.contains(game::s1xb))
{
contexts[game::s1xb] = std::make_unique<s1_xb::context>();
contexts[game::s1xb]->init(build::prod, read_file_cb);
contexts[game::s1xb]->init(build::prod, fs_callback);
}
}
@ -582,7 +581,7 @@ auto init_s2() -> void
if (!contexts.contains(game::s2))
{
contexts[game::s2] = std::make_unique<s2::context>();
contexts[game::s2]->init(build::prod, read_file_cb);
contexts[game::s2]->init(build::prod, fs_callback);
}
}
@ -591,7 +590,7 @@ auto init_s4() -> void
if (!contexts.contains(game::s4))
{
contexts[game::s4] = std::make_unique<s4::context>();
contexts[game::s4]->init(build::prod, read_file_cb);
contexts[game::s4]->init(build::prod, fs_callback);
}
}
@ -600,7 +599,7 @@ auto init_h1() -> void
if (!contexts.contains(game::h1))
{
contexts[game::h1] = std::make_unique<h1::context>();
contexts[game::h1]->init(build::prod, read_file_cb);
contexts[game::h1]->init(build::prod, fs_callback);
}
}
@ -609,7 +608,7 @@ auto init_h2() -> void
if (!contexts.contains(game::h2))
{
contexts[game::h2] = std::make_unique<h2::context>();
contexts[game::h2]->init(build::prod, read_file_cb);
contexts[game::h2]->init(build::prod, fs_callback);
}
}