From 45f84745dcdc8630e86687a3fd3c965c7718a30f Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 4 Feb 2023 18:08:00 +0000 Subject: [PATCH 1/2] Revert "feature: new gsc compiler (#603)" This reverts commit 95185e52f3bd6a7f78f0e489dafd5af736d44a74. --- .gitmodules | 5 +- deps/extra/gsc-tool/gsc_interface.cpp | 6 - deps/extra/gsc-tool/gsc_interface.hpp | 15 -- deps/extra/gsc-tool/interface.cpp | 28 +++ deps/extra/gsc-tool/interface.hpp | 9 + deps/fmt | 1 - deps/gsc-tool | 2 +- deps/premake/fmt.lua | 34 ---- deps/premake/gsc-tool.lua | 29 ++- src/client/component/gsc/script_extension.cpp | 14 +- src/client/component/gsc/script_loading.cpp | 170 +++++++++--------- src/client/game/scripting/functions.cpp | 31 ++-- src/client/game/scripting/lua/context.cpp | 7 +- 13 files changed, 159 insertions(+), 192 deletions(-) delete mode 100644 deps/extra/gsc-tool/gsc_interface.cpp delete mode 100644 deps/extra/gsc-tool/gsc_interface.hpp create mode 100644 deps/extra/gsc-tool/interface.cpp create mode 100644 deps/extra/gsc-tool/interface.hpp delete mode 160000 deps/fmt delete mode 100644 deps/premake/fmt.lua diff --git a/.gitmodules b/.gitmodules index 03c64ab..1e8e1fd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -47,7 +47,4 @@ [submodule "deps/gsc-tool"] path = deps/gsc-tool url = https://github.com/xensik/gsc-tool.git - branch = dev -[submodule "deps/fmt"] - path = deps/fmt - url = https://github.com/fmtlib/fmt.git + branch = xlabs diff --git a/deps/extra/gsc-tool/gsc_interface.cpp b/deps/extra/gsc-tool/gsc_interface.cpp deleted file mode 100644 index b4115f9..0000000 --- a/deps/extra/gsc-tool/gsc_interface.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "gsc_interface.hpp" - -namespace gsc -{ - const std::unique_ptr cxt = std::make_unique(); -} diff --git a/deps/extra/gsc-tool/gsc_interface.hpp b/deps/extra/gsc-tool/gsc_interface.hpp deleted file mode 100644 index dbd9d30..0000000 --- a/deps/extra/gsc-tool/gsc_interface.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#undef ERROR -#undef IN -#undef TRUE -#undef FALSE - -#undef far - -#include -#include - -namespace gsc -{ - extern const std::unique_ptr cxt; -} diff --git a/deps/extra/gsc-tool/interface.cpp b/deps/extra/gsc-tool/interface.cpp new file mode 100644 index 0000000..4e224a6 --- /dev/null +++ b/deps/extra/gsc-tool/interface.cpp @@ -0,0 +1,28 @@ +#include +#include +#include "interface.hpp" + +namespace gsc +{ + std::unique_ptr compiler() + { + auto compiler = std::make_unique(); + compiler->mode(xsk::gsc::build::prod); + return compiler; + } + + std::unique_ptr decompiler() + { + return std::make_unique(); + } + + std::unique_ptr assembler() + { + return std::make_unique(); + } + + std::unique_ptr disassembler() + { + return std::make_unique(); + } +} diff --git a/deps/extra/gsc-tool/interface.hpp b/deps/extra/gsc-tool/interface.hpp new file mode 100644 index 0000000..133e6ae --- /dev/null +++ b/deps/extra/gsc-tool/interface.hpp @@ -0,0 +1,9 @@ +#pragma once + +namespace gsc +{ + std::unique_ptr compiler(); + std::unique_ptr decompiler(); + std::unique_ptr assembler(); + std::unique_ptr disassembler(); +} diff --git a/deps/fmt b/deps/fmt deleted file mode 160000 index 05e3a92..0000000 --- a/deps/fmt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 05e3a9233ac1dd0c2d9643e046dbb5f788c39f61 diff --git a/deps/gsc-tool b/deps/gsc-tool index 66ecf90..7d37402 160000 --- a/deps/gsc-tool +++ b/deps/gsc-tool @@ -1 +1 @@ -Subproject commit 66ecf90171a6dda4de515423379d30c13df0f1ef +Subproject commit 7d374025b7675bada64c247ebe9378dd335a33da diff --git a/deps/premake/fmt.lua b/deps/premake/fmt.lua deleted file mode 100644 index 905bbf7..0000000 --- a/deps/premake/fmt.lua +++ /dev/null @@ -1,34 +0,0 @@ -fmt = { - source = path.join(dependencies.basePath, "fmt"), -} - -function fmt.import() - links { "fmt" } - - fmt.includes() -end - -function fmt.includes() - includedirs { - path.join(fmt.source, "include"), - } -end - -function fmt.project() - project "fmt" - kind "StaticLib" - language "C++" - - fmt.includes() - - files { - path.join(fmt.source, "include/fmt/*.h"), - path.join(fmt.source, "src/*.cc") - } - - removefiles { - path.join(fmt.source, "src/fmt.cc") - } -end - -table.insert(dependencies, fmt) diff --git a/deps/premake/gsc-tool.lua b/deps/premake/gsc-tool.lua index 50530e2..325a64d 100644 --- a/deps/premake/gsc-tool.lua +++ b/deps/premake/gsc-tool.lua @@ -11,9 +11,6 @@ function gsc_tool.includes() includedirs { path.join(gsc_tool.source, "s1"), path.join(gsc_tool.source, "utils"), - path.join(gsc_tool.source, "gsc"), - gsc_tool.source, - path.join(dependencies.basePath, "extra/gsc-tool"), } end @@ -23,6 +20,9 @@ function gsc_tool.project() kind "StaticLib" language "C++" + pchheader "stdafx.hpp" + pchsource (path.join(gsc_tool.source, "utils/stdafx.cpp")) + files { path.join(gsc_tool.source, "utils/**.hpp"), path.join(gsc_tool.source, "utils/**.cpp"), @@ -34,30 +34,23 @@ function gsc_tool.project() } zlib.includes() - fmt.includes() project "xsk-gsc-s1" kind "StaticLib" language "C++" filter "action:vs*" + buildoptions "/bigobj" buildoptions "/Zc:__cplusplus" filter {} + pchheader "stdafx.hpp" + pchsource (path.join(gsc_tool.source, "s1/stdafx.cpp")) + files { - path.join(gsc_tool.source, "s1/s1_pc.hpp"), - path.join(gsc_tool.source, "s1/s1_pc.cpp"), - path.join(gsc_tool.source, "s1/s1_pc_code.cpp"), - path.join(gsc_tool.source, "s1/s1_pc_func.cpp"), - path.join(gsc_tool.source, "s1/s1_pc_meth.cpp"), - path.join(gsc_tool.source, "s1/s1_pc_token.cpp"), - - path.join(gsc_tool.source, "gsc/misc/*.hpp"), - path.join(gsc_tool.source, "gsc/misc/*.cpp"), - path.join(gsc_tool.source, "gsc/*.hpp"), - path.join(gsc_tool.source, "gsc/*.cpp"), - - path.join(dependencies.basePath, "extra/gsc-tool/gsc_interface.cpp"), + path.join(gsc_tool.source, "s1/**.hpp"), + path.join(gsc_tool.source, "s1/**.cpp"), + path.join(dependencies.basePath, "extra/gsc-tool/interface.cpp"), } includedirs { @@ -65,8 +58,6 @@ function gsc_tool.project() gsc_tool.source, path.join(dependencies.basePath, "extra/gsc-tool"), } - - fmt.includes() end table.insert(dependencies, gsc_tool) diff --git a/src/client/component/gsc/script_extension.cpp b/src/client/component/gsc/script_extension.cpp index 0ddcbd2..0a85134 100644 --- a/src/client/component/gsc/script_extension.cpp +++ b/src/client/component/gsc/script_extension.cpp @@ -13,7 +13,8 @@ #include -#include +#include +#include namespace gsc { @@ -95,11 +96,11 @@ namespace gsc if (function_id > 0x1000) { - console::warn("in call to builtin method \"%s\"%s", gsc::cxt->meth_name(function_id).data(), error.data()); + console::warn("in call to builtin method \"%s\"%s", xsk::gsc::s1::resolver::method_name(function_id).data(), error.data()); } else { - console::warn("in call to builtin function \"%s\"%s", gsc::cxt->func_name(function_id).data(), error.data()); + console::warn("in call to builtin function \"%s\"%s", xsk::gsc::s1::resolver::function_name(function_id).data(), error.data()); } } @@ -107,8 +108,7 @@ namespace gsc { try { - auto index = gsc::cxt->opcode_enum(opcode); - return {xsk::gsc::opcode_name(index)}; + return {xsk::gsc::s1::resolver::opcode_name(opcode)}; } catch (...) { @@ -232,7 +232,7 @@ namespace gsc void override_function(const std::string& name, game::BuiltinFunction func) { - const auto id = gsc::cxt->func_id(name); + const auto id = xsk::gsc::s1::resolver::function_id(name); builtin_funcs_overrides.emplace(id, func); } @@ -240,7 +240,7 @@ namespace gsc { ++function_id_start; functions[function_id_start] = function; - gsc::cxt->func_add(name, function_id_start); + xsk::gsc::s1::resolver::add_function(name, function_id_start); } class extension final : public component_interface diff --git a/src/client/component/gsc/script_loading.cpp b/src/client/component/gsc/script_loading.cpp index dcc8341..1b958f1 100644 --- a/src/client/component/gsc/script_loading.cpp +++ b/src/client/component/gsc/script_loading.cpp @@ -4,7 +4,6 @@ #include #include -#include #include "component/filesystem.hpp" #include "component/console.hpp" @@ -13,29 +12,37 @@ #include "script_loading.hpp" -#include +#include +#include +#include +#include +#include +#include +#include +#include namespace gsc { namespace { + auto compiler = ::gsc::compiler(); + auto decompiler = ::gsc::decompiler(); + auto assembler = ::gsc::assembler(); + auto disassembler = ::gsc::disassembler(); + std::unordered_map main_handles; std::unordered_map init_handles; std::unordered_map loaded_scripts; - std::unordered_map script_stack_buffers; - - const game::dvar_t* developer_script; void clear() { main_handles.clear(); init_handles.clear(); loaded_scripts.clear(); - script_stack_buffers.clear(); } - bool read_raw_script_file(const std::string& name, std::string* data) + bool read_script_file(const std::string& name, std::string* data) { if (filesystem::read_file(name, data)) { @@ -80,7 +87,7 @@ namespace gsc } std::string source_buffer{}; - if (!read_raw_script_file(real_name + ".gsc", &source_buffer)) + if (!read_script_file(real_name + ".gsc", &source_buffer)) { return nullptr; } @@ -88,14 +95,9 @@ namespace gsc std::vector data; data.assign(source_buffer.begin(), source_buffer.end()); - auto& compiler = gsc::cxt->compiler(); - auto& assembler = gsc::cxt->assembler(); - - xsk::gsc::assembly::ptr assembly_ptr; - try { - assembly_ptr = compiler.compile(real_name, data); + compiler->compile(real_name, data); } catch (const std::exception& ex) { @@ -105,32 +107,11 @@ namespace gsc return nullptr; } + auto assembly = compiler->output(); + try { - // second shoulde be stacc and first byte cum - const auto output_script = assembler.assemble(*assembly_ptr); - - const auto script_file_ptr = static_cast(game::Hunk_AllocateTempMemoryHighInternal(sizeof(game::ScriptFile))); - script_file_ptr->name = file_name; - - script_file_ptr->len = static_cast(output_script.second.size); - - script_file_ptr->bytecodeLen = static_cast(output_script.first.size); - - const auto stack_size = static_cast(output_script.second.size + 1); - const auto byte_code_size = static_cast(output_script.first.size + 1); - - script_file_ptr->buffer = static_cast(game::Hunk_AllocateTempMemoryHighInternal(stack_size)); - std::memcpy(const_cast(script_file_ptr->buffer), output_script.second.data, output_script.second.size); - - script_file_ptr->bytecode = static_cast(game::PMem_AllocFromSource_NoDebug(byte_code_size, 4, 1, 5)); - std::memcpy(script_file_ptr->bytecode, output_script.first.data, output_script.first.size); - - script_file_ptr->compressedLen = 0; - - loaded_scripts[real_name] = script_file_ptr; - - return script_file_ptr; + assembler->assemble(real_name, assembly); } catch (const std::exception& ex) { @@ -139,11 +120,35 @@ namespace gsc console::error("**********************************************\n"); return nullptr; } + + const auto script_file_ptr = static_cast(game::Hunk_AllocateTempMemoryHighInternal(sizeof(game::ScriptFile))); + script_file_ptr->name = file_name; + + const auto stack = assembler->output_stack(); + script_file_ptr->len = static_cast(stack.size()); + + const auto script = assembler->output_script(); + script_file_ptr->bytecodeLen = static_cast(script.size()); + + const auto stack_size = static_cast(stack.size() + 1); + const auto byte_code_size = static_cast(script.size() + 1); + + script_file_ptr->buffer = static_cast(game::Hunk_AllocateTempMemoryHighInternal(stack_size)); + std::memcpy(const_cast(script_file_ptr->buffer), stack.data(), stack.size()); + + script_file_ptr->bytecode = static_cast(game::PMem_AllocFromSource_NoDebug(byte_code_size, 4, 1, 5)); + std::memcpy(script_file_ptr->bytecode, script.data(), script.size()); + + script_file_ptr->compressedLen = 0; + + loaded_scripts[real_name] = script_file_ptr; + + return script_file_ptr; } std::string get_script_file_name(const std::string& name) { - const auto id = gsc::cxt->token_id(name); + const auto id = xsk::gsc::s1::resolver::token_id(name); if (!id) { return name; @@ -152,7 +157,7 @@ namespace gsc return std::to_string(id); } - std::pair read_compiled_script_file(const std::string& name, const std::string& real_name) + std::vector decompile_script_file(const std::string& name, const std::string& real_name) { const auto* script_file = game::DB_FindXAssetHeader(game::ASSET_TYPE_SCRIPTFILE, name.data(), false).scriptfile; if (!script_file) @@ -162,15 +167,17 @@ namespace gsc console::info("Decompiling scriptfile '%s'\n", real_name.data()); - const std::string stack{script_file->buffer, static_cast(script_file->len)}; + std::vector stack{script_file->buffer, script_file->buffer + script_file->len}; + std::vector bytecode{script_file->bytecode, script_file->bytecode + script_file->bytecodeLen}; - const auto decompressed_stack = utils::compression::zlib::decompress(stack); + auto decompressed_stack = xsk::utils::zlib::decompress(stack, static_cast(stack.size())); - // Store buffer - script_stack_buffers[real_name] = decompressed_stack; - const auto itr = script_stack_buffers.find(real_name); + disassembler->disassemble(name, bytecode, decompressed_stack); + auto output = disassembler->output(); - return {{script_file->bytecode, static_cast(script_file->bytecodeLen)}, {reinterpret_cast(itr->second.data()), itr->second.size()}}; + decompiler->decompile(name, output); + + return decompiler->output(); } void load_script(const std::string& name) @@ -180,8 +187,8 @@ namespace gsc return; } - const auto main_handle = game::Scr_GetFunctionHandle(name.data(), gsc::cxt->token_id("main")); - const auto init_handle = game::Scr_GetFunctionHandle(name.data(), gsc::cxt->token_id("init")); + const auto main_handle = game::Scr_GetFunctionHandle(name.data(), xsk::gsc::s1::resolver::token_id("main")); + const auto init_handle = game::Scr_GetFunctionHandle(name.data(), xsk::gsc::s1::resolver::token_id("init")); if (main_handle) { @@ -302,42 +309,6 @@ namespace gsc game::RemoveRefToObject(thread); } } - - void scr_begin_load_scripts_stub() - { - const auto comp_mode = developer_script->current.enabled ? - xsk::gsc::build::dev : - xsk::gsc::build::prod; - - gsc::cxt->init(comp_mode, [](const std::string& include_name) -> std::pair - { - const auto real_name = include_name + ".gsc"; - - std::string file_buffer; - if (!read_raw_script_file(real_name, &file_buffer) || file_buffer.empty()) - { - const auto name = get_script_file_name(include_name); - if (game::DB_XAssetExists(game::ASSET_TYPE_SCRIPTFILE, name.data())) - { - return read_compiled_script_file(name, real_name); - } - - throw std::runtime_error(std::format("Could not load gsc file '{}'", real_name)); - } - - return {xsk::gsc::buffer(reinterpret_cast(file_buffer.data()), file_buffer.size()), {}}; - }); - - utils::hook::invoke(SELECT_VALUE(0x1403118E0, 0x1403EDE60)); - } - - void scr_end_load_scripts_stub() - { - // Cleanup the compiler - gsc::cxt->cleanup(); - - utils::hook::invoke(SELECT_VALUE(0x140243780, 0x1403EDF90)); - } } game::ScriptFile* find_script(game::XAssetType type, const char* name, int allow_create_default) @@ -346,7 +317,7 @@ namespace gsc const auto id = static_cast(std::atoi(name)); if (id) { - real_name = gsc::cxt->token_name(id); + real_name = xsk::gsc::s1::resolver::token_name(id); } auto* script = load_custom_script(name, real_name); @@ -366,16 +337,34 @@ namespace gsc // Load our scripts with an uncompressed stack utils::hook::call(SELECT_VALUE(0x14031ABB0, 0x1403F7380), db_get_raw_buffer_stub); - utils::hook::call(SELECT_VALUE(0x1403309E9, 0x1403309E9), scr_begin_load_scripts_stub); // GScr_LoadScripts - utils::hook::call(SELECT_VALUE(0x14023DA84, 0x140330B9C), scr_end_load_scripts_stub); // GScr_LoadScripts - - developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments"); - if (game::environment::is_sp()) { return; } + // Allow custom scripts to include other custom scripts + xsk::gsc::s1::resolver::init([](const auto& include_name) -> std::vector + { + const auto real_name = include_name + ".gsc"; + + std::string file_buffer; + if (!read_script_file(real_name, &file_buffer) || file_buffer.empty()) + { + const auto name = get_script_file_name(include_name); + if (game::DB_XAssetExists(game::ASSET_TYPE_SCRIPTFILE, name.data())) + { + return decompile_script_file(name, real_name); + } + + throw std::runtime_error(std::format("Could not load gsc file '{}'", real_name)); + } + + std::vector result; + result.assign(file_buffer.begin(), file_buffer.end()); + + return result; + }); + // ProcessScript utils::hook::call(0x1403F7317, find_script); utils::hook::call(0x1403F7327, db_is_x_asset_default); @@ -391,6 +380,7 @@ namespace gsc { if (free_scripts) { + xsk::gsc::s1::resolver::cleanup(); clear(); } }); diff --git a/src/client/game/scripting/functions.cpp b/src/client/game/scripting/functions.cpp index 1dd958f..d7e8965 100644 --- a/src/client/game/scripting/functions.cpp +++ b/src/client/game/scripting/functions.cpp @@ -5,26 +5,33 @@ #include "component/gsc/script_extension.hpp" -#include +#include +#include namespace scripting { namespace { - int find_function_index(const std::string& name, [[maybe_unused]] const bool prefer_global) + int find_function_index(const std::string& name, const bool prefer_global) { const auto target = utils::string::to_lower(name); - auto const& first = gsc::cxt->func_map(); - auto const& second = gsc::cxt->meth_map(); - - if (const auto itr = first.find(name); itr != first.end()) + auto first = xsk::gsc::s1::resolver::function_id; + auto second = xsk::gsc::s1::resolver::method_id; + if (!prefer_global) { - return static_cast(itr->second); + std::swap(first, second); } - if (const auto itr = second.find(name); itr != second.end()) + const auto first_res = first(target); + if (first_res) { - return static_cast(itr->second); + return first_res; + } + + const auto second_res = second(target); + if (second_res) + { + return second_res; } return -1; @@ -43,17 +50,17 @@ namespace scripting std::string find_token(std::uint32_t id) { - return gsc::cxt->token_name(id); + return xsk::gsc::s1::resolver::token_name(static_cast(id)); } std::string find_token_single(std::uint32_t id) { - return gsc::cxt->token_name(id); + return xsk::gsc::s1::resolver::token_name(static_cast(id)); } unsigned int find_token_id(const std::string& name) { - const auto id = gsc::cxt->token_id(name); + const auto id = xsk::gsc::s1::resolver::token_id(name); if (id) { return id; diff --git a/src/client/game/scripting/lua/context.cpp b/src/client/game/scripting/lua/context.cpp index e1135e6..5c0ef0f 100644 --- a/src/client/game/scripting/lua/context.cpp +++ b/src/client/game/scripting/lua/context.cpp @@ -11,7 +11,8 @@ #include -#include +#include +#include namespace scripting::lua { @@ -245,7 +246,7 @@ namespace scripting::lua auto entity_type = state.new_usertype("entity"); - for (auto const& func : gsc::cxt->meth_map()) + for (const auto& func : xsk::gsc::s1::resolver::get_methods()) { const auto name = std::string(func.first); entity_type[name] = [name](const entity& entity, const sol::this_state s, sol::variadic_args va) @@ -377,7 +378,7 @@ namespace scripting::lua auto game_type = state.new_usertype("game_"); state["game"] = game(); - for (auto const& func : gsc::cxt->func_map()) + for (const auto& func : xsk::gsc::s1::resolver::get_functions()) { const auto name = std::string(func.first); game_type[name] = [name](const game&, const sol::this_state s, sol::variadic_args va) From a67ad1410a48f997ccd8acff67152a4fd7574d8e Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 4 Feb 2023 18:11:54 +0000 Subject: [PATCH 2/2] fix scripts --- data/maps/mp/gametypes/_damage.gsc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/maps/mp/gametypes/_damage.gsc b/data/maps/mp/gametypes/_damage.gsc index 3696197..486c953 100644 --- a/data/maps/mp/gametypes/_damage.gsc +++ b/data/maps/mp/gametypes/_damage.gsc @@ -104,7 +104,7 @@ handlesuicidedeath( var_0, var_1 ) [[ level.onsuicidedeath ]]( self ); if ( isdefined( self.friendlydamage ) ) - self iprintlnbold( &"MP_FRIENDLY_FIRE_WILL_NOT" ); + self _meth_826E( &"MP_FRIENDLY_FIRE_WILL_NOT" ); self.pers["suicideSpawnDelay"] = maps\mp\gametypes\_tweakables::gettweakablevalue( "game", "suicidespawndelay" ); } @@ -326,7 +326,7 @@ callback_playergrenadesuicide( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_8 = 1; if ( var_8 ) - var_0 laststanddie(); + var_0 _meth_82C8(); [[ level.callbackplayerlaststand ]]( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, 0 ); } @@ -3240,17 +3240,17 @@ _obituary( var_0, var_1, var_2, var_3 ) if ( var_7 == "spectator" ) { - var_6 iprintlnbold( &"MP_OBITUARY_NEUTRAL", var_1.name, var_0.name ); + var_6 _meth_826E( &"MP_OBITUARY_NEUTRAL", var_1.name, var_0.name ); continue; } if ( var_7 == var_4 ) { - var_6 iprintlnbold( &"MP_OBITUARY_ENEMY", var_1.name, var_0.name ); + var_6 _meth_826E( &"MP_OBITUARY_ENEMY", var_1.name, var_0.name ); continue; } - var_6 iprintlnbold( &"MP_OBITUARY_FRIENDLY", var_1.name, var_0.name ); + var_6 _meth_826E( &"MP_OBITUARY_FRIENDLY", var_1.name, var_0.name ); } }