diff --git a/src/gsc/assembler.cpp b/src/gsc/assembler.cpp index f24f7ac6..6fbf0d0d 100644 --- a/src/gsc/assembler.cpp +++ b/src/gsc/assembler.cpp @@ -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)); } } diff --git a/src/gsc/context.cpp b/src/gsc/context.cpp index 0015ce45..55cd931b 100644 --- a/src/gsc/context.cpp +++ b/src/gsc/context.cpp @@ -9,30 +9,57 @@ namespace xsk::gsc { -read_cb_type read_callback = nullptr; -std::unordered_map header_files; -std::set includes; -std::unordered_map> include_cache; -std::set new_func_map; -std::set new_meth_map; +extern std::array, 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>(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 +auto context::load_header(std::string const& name) -> std::tuple { - 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(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{}; @@ -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, 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 diff --git a/src/gsc/context.hpp b/src/gsc/context.hpp index 6511f63e..38c86a3d 100644 --- a/src/gsc/context.hpp +++ b/src/gsc/context.hpp @@ -18,6 +18,8 @@ namespace xsk::gsc class context { public: + using fs_callback = std::function>(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 const& { return func_map_rev_; } auto meth_map() const -> std::unordered_map 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; - - auto fs_to_game_path(std::filesystem::path const& file) const -> std::filesystem::path; + auto load_header(std::string const& name) -> std::tuple; 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_map_; + std::unordered_map opcode_map_rev_; std::unordered_map code_map_; std::unordered_map code_map_rev_; std::unordered_map func_map_; @@ -117,6 +126,11 @@ protected: std::unordered_map token_map_rev_; std::unordered_map path_map_; std::unordered_map hash_map_; + std::unordered_map header_files_; + std::unordered_set includes_; + std::unordered_map> include_cache_; + std::unordered_set new_func_map_; + std::unordered_set new_meth_map_; }; } // namespace xsk::gsc diff --git a/src/gsc/decompiler.cpp b/src/gsc/decompiler.cpp index 5ce0db0f..6783b747 100644 --- a/src/gsc/decompiler.cpp +++ b/src/gsc/decompiler.cpp @@ -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))); } } diff --git a/src/gsc/disassembler.cpp b/src/gsc/disassembler.cpp index fce36b6e..2a740a7b 100644 --- a/src/gsc/disassembler.cpp +++ b/src/gsc/disassembler.cpp @@ -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)); } } diff --git a/src/gsc/misc/assembly.cpp b/src/gsc/misc/assembly.cpp deleted file mode 100644 index 5ea7d2bc..00000000 --- a/src/gsc/misc/assembly.cpp +++ /dev/null @@ -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, 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_map; -std::unordered_map 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>(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 diff --git a/src/gsc/misc/assembly.hpp b/src/gsc/misc/assembly.hpp index 6e1d8a2b..34f6ba41 100644 --- a/src/gsc/misc/assembly.hpp +++ b/src/gsc/misc/assembly.hpp @@ -264,7 +264,4 @@ inline auto make_assembly() -> std::unique_ptr return std::unique_ptr(new assembly); } -auto opcode_name(opcode op) -> std::string; -auto opcode_enum(std::string const& name) -> opcode; - } // namespace xsk::gsc diff --git a/src/gsc/misc/buffer.hpp b/src/gsc/misc/buffer.hpp new file mode 100644 index 00000000..b8660556 --- /dev/null +++ b/src/gsc/misc/buffer.hpp @@ -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 diff --git a/src/gsc/misc/types.cpp b/src/gsc/misc/types.cpp deleted file mode 100644 index 36ec45c9..00000000 --- a/src/gsc/misc/types.cpp +++ /dev/null @@ -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 diff --git a/src/gsc/misc/types.hpp b/src/gsc/misc/types.hpp index 89c29422..296f0b7a 100644 --- a/src/gsc/misc/types.hpp +++ b/src/gsc/misc/types.hpp @@ -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::string const&)>; - -auto engine_name(engine engine) -> std::string_view; - // fordward decl for modules ref class context; diff --git a/src/gsc/preprocessor.cpp b/src/gsc/preprocessor.cpp index 6e9dc0bb..33270332 100644 --- a/src/gsc/preprocessor.cpp +++ b/src/gsc/preprocessor.cpp @@ -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) }); diff --git a/src/gsc/preprocessor.hpp b/src/gsc/preprocessor.hpp index e637f113..3db34f50 100644 --- a/src/gsc/preprocessor.hpp +++ b/src/gsc/preprocessor.hpp @@ -13,7 +13,7 @@ namespace xsk::gsc class preprocessor { - context const* ctx_; + context* ctx_; std::stack lexer_; std::stack indents_; std::vector 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; diff --git a/src/gsc/source.cpp b/src/gsc/source.cpp index 2fc7f9db..d0f33aed 100644 --- a/src/gsc/source.cpp +++ b/src/gsc/source.cpp @@ -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 buf_ = std::vector{}; 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 buf_ = std::vector{}; 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) { diff --git a/src/gsc/source.hpp b/src/gsc/source.hpp index 25982de6..c398edc3 100644 --- a/src/gsc/source.hpp +++ b/src/gsc/source.hpp @@ -12,12 +12,12 @@ namespace xsk::gsc class source { - context const* ctx_; + context* ctx_; std::vector buf_; u32 indent_; public: - source(context const* ctx); + source(context* ctx); auto parse_assembly(buffer const& data) -> assembly::ptr; auto parse_assembly(std::vector const& data) -> assembly::ptr; auto parse_assembly(u8 const* data, usize size) -> assembly::ptr; diff --git a/src/stdinc.hpp b/src/stdinc.hpp index bb487a92..0591269b 100644 --- a/src/stdinc.hpp +++ b/src/stdinc.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include using namespace std::literals; diff --git a/src/tool/main.cpp b/src/tool/main.cpp index 541922d6..f8b9bf9c 100644 --- a/src/tool/main.cpp +++ b/src/tool/main.cpp @@ -439,7 +439,7 @@ auto rename_file(game game, fs::path file, fs::path rel) -> void std::unordered_map> files; -auto read_file_cb(std::string const& name) -> std::pair +auto fs_callback(std::string const& name) -> std::pair> { auto data = utils::file::read(fs::path{ name }); @@ -448,12 +448,11 @@ auto read_file_cb(std::string const& name) -> std::pair 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - contexts[game::h2]->init(build::prod, read_file_cb); + contexts[game::h2]->init(build::prod, fs_callback); } }