From cefe580c0038802ed5468f6d472720a56c78f3f6 Mon Sep 17 00:00:00 2001 From: qaate47 Date: Sat, 27 Jul 2024 23:21:02 +0200 Subject: [PATCH] add refs to bo4 dll and generic config --- src/acts/main.cpp | 2 +- src/acts/tools/test.cpp | 4 +- src/bo4-ext-dll/data/bo4.hpp | 24 +++++--- src/bo4-ext-dll/data/refs.hpp | 52 ++++++++++++++++++ src/bo4-ext-dll/main.cpp | 2 +- src/bo4-ext-dll/systems/modding.cpp | 1 + src/shared/core/config.cpp | 85 +++++++++++++++-------------- src/shared/core/config.hpp | 79 ++++++++++++++++++++++----- src/shared/hook/refs.cpp | 15 +++++ src/shared/hook/refs.hpp | 22 ++++++++ 10 files changed, 221 insertions(+), 65 deletions(-) create mode 100644 src/bo4-ext-dll/data/refs.hpp create mode 100644 src/shared/hook/refs.cpp create mode 100644 src/shared/hook/refs.hpp diff --git a/src/acts/main.cpp b/src/acts/main.cpp index b3a0ece..35f08c1 100644 --- a/src/acts/main.cpp +++ b/src/acts/main.cpp @@ -212,7 +212,7 @@ int MainActs(int argc, const char* _argv[], HINSTANCE hInstance, int nShowCmd) { bool cli{ hInstance == nullptr }; auto& profiler = actscli::GetProfiler(); - core::config::SyncConfig(); + core::config::SyncConfig(true); // by default we don't display heavy logs in cli diff --git a/src/acts/tools/test.cpp b/src/acts/tools/test.cpp index 6f96706..26d89cb 100644 --- a/src/acts/tools/test.cpp +++ b/src/acts/tools/test.cpp @@ -13,7 +13,9 @@ namespace { int cfgtest(Process& proc, int argc, const char* argv[]) { using namespace core::config; - SyncConfig(); + SyncConfig(true); + + LOG_INFO("file: {}", GetMainConfig().configFile.string()); LOG_INFO("{}", GetInteger("test", 64)); LOG_INFO("{}", GetBool("test2.bool.val", true)); diff --git a/src/bo4-ext-dll/data/bo4.hpp b/src/bo4-ext-dll/data/bo4.hpp index 46d0544..c033885 100644 --- a/src/bo4-ext-dll/data/bo4.hpp +++ b/src/bo4-ext-dll/data/bo4.hpp @@ -301,6 +301,10 @@ namespace bo4 { byte requires_implements_count; }; + typedef float vec_t; + typedef vec_t vec2_t[2]; + typedef vec_t vec3_t[3]; + typedef vec_t vec4_t[4]; enum scriptInstance_t : int32_t { SCRIPTINSTANCE_SERVER = 0x0, @@ -489,18 +493,20 @@ namespace bo4 { }; struct HksGlobal {}; - struct HksCallstack - { - void* m_records; // hks::CallStack::ActivationRecord* - void* m_lastrecord; // hks::CallStack::ActivationRecord* - void* m_current; // hks::CallStack::ActivationRecord* - const void* m_current_lua_pc; // const hksInstruction* - const void* m_hook_return_addr; // const hksInstruction* - int32_t m_hook_level; - }; + struct HksCallStackActivationRecord {}; + struct hksInstruction {}; struct HksUpvalue {}; typedef void* HksErrorhandler; struct lua_State; + + struct HksCallstack { + HksCallStackActivationRecord* m_records; + HksCallStackActivationRecord* m_lastrecord; + HksCallStackActivationRecord* m_current; + const hksInstruction* m_current_lua_pc; + const hksInstruction* m_hook_return_addr; + int32_t m_hook_level; + }; struct HksObject { uint32_t t; union { diff --git a/src/bo4-ext-dll/data/refs.hpp b/src/bo4-ext-dll/data/refs.hpp new file mode 100644 index 0000000..1330d3e --- /dev/null +++ b/src/bo4-ext-dll/data/refs.hpp @@ -0,0 +1,52 @@ +#pragma once +#include +#include "bo4.hpp" + +namespace bo4 { + using namespace hook::refs; + + // gsc + S_ANY Ref ScrVm_AddBool{ 0x276E760_a }; + S_ANY Ref ScrVm_AddFloat{ 0x276E9B0_a }; + S_ANY Ref ScrVm_AddHash{ 0x276EAB0_a }; + S_ANY Ref ScrVm_AddInt{ 0x276EB80_a }; + S_ANY Ref ScrVm_AddString{ 0x276EE30_a }; + S_ANY Ref ScrVm_AddUndefined{ 0x276F3C0_a }; + S_ANY Ref ScrVm_AddConstString{ 0x276E5F0_a }; + S_ANY Ref ScrVm_GetBool{ 0x2772AB0_a }; + S_ANY Ref ScrVm_GetFloat{ 0x27733F0_a }; + S_ANY Ref ScrVm_GetHash{ 0x27738E0_a }; + S_ANY Ref ScrVm_GetInt{ 0x2773B50_a }; + S_ANY Ref ScrVm_GetString{ 0x2774840_a }; + S_ANY Ref ScrVm_GetVector{ 0x2774E40_a }; + S_ANY Ref ScrVm_GetConstString{ 0x2772E10_a }; + S_ANY Ref ScrVm_GetNumParam{ 0x2774440_a }; + S_ANY Ref ScrVm_GetPointerType{ 0x27746E0_a }; + S_ANY Ref ScrVm_GetType{ 0x2774A20_a }; + S_ANY Ref ScrVm_AddStruct{ 0x276EF00_a }; + S_ANY Ref ScrVm_SetStructField{ 0x2778450_a }; + S_ANY Ref ScrVm_AddToArray{ 0x276F1C0_a }; + S_ANY Ref ScrVm_AddToArrayStringIndexed{ 0x276F230_a }; + S_ANY Ref ScrVm_AddVector{ 0x276F490_a }; + S_ANY Ref ScrVar_PushArray{ 0x2775CF0_a }; + S_ANY Ref ScrStr_ConvertToString{ 0x2759030_a }; + S_ANY Ref ScrVar_NewVariableByIndex{ 0x2760440_a }; + S_ANY Ref ScrVar_SetValue{ 0x27616B0_a }; + + // gsc funcs + S_ANY Ref CScr_GetFunction{ 0x1F13140_a }; + S_ANY Ref Scr_GetFunction{ 0x33AF840_a }; + S_ANY Ref CScr_GetMethod{ 0x1F13650_a }; + S_ANY Ref Scr_GetMethod{ 0x33AFC20_a }; + S_ANY Ref Scr_GetGscExportInfo{ 0x2748550_a }; + S_ANY Ref ScrVm_Error{ 0x2770330_a }; + + // gsc structs + S_ANY Ref scrVarPub{ 0x8307880_a }; + S_ANY Ref scrVarGlob{ 0x8307830_a }; + S_ANY Ref scrVmPub{ 0x8307AA0_a }; + S_ANY Ref gVmOpJumpTable{ 0x4EED340_a }; + S_ANY Ref gObjFileInfoCount{ 0x82F76B0_a }; + S_ANY Ref gObjFileInfo{ 0x82EFCD0_a }; + +} \ No newline at end of file diff --git a/src/bo4-ext-dll/main.cpp b/src/bo4-ext-dll/main.cpp index 235b25b..8283fbe 100644 --- a/src/bo4-ext-dll/main.cpp +++ b/src/bo4-ext-dll/main.cpp @@ -35,7 +35,7 @@ namespace bo4 { void InitDll() { try { - core::config::SyncConfig(); + core::config::SyncConfig(true); static std::string logFile{ "acts-bo4.log" }; logFile = core::config::GetString("logger.output", logFile.c_str()); diff --git a/src/bo4-ext-dll/systems/modding.cpp b/src/bo4-ext-dll/systems/modding.cpp index 54ed626..e520e07 100644 --- a/src/bo4-ext-dll/systems/modding.cpp +++ b/src/bo4-ext-dll/systems/modding.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace { hook::library::Detour GetAssetHeaderDetour; diff --git a/src/shared/core/config.cpp b/src/shared/core/config.cpp index 1a301d1..2e24c41 100644 --- a/src/shared/core/config.cpp +++ b/src/shared/core/config.cpp @@ -7,9 +7,7 @@ namespace core::config { namespace { - rapidjson::Document main{}; - - rapidjson::GenericValue& GetVal(const char* path, size_t off = 0, rapidjson::GenericValue& loc = main) { + rapidjson::GenericValue& GetVal(const char* path, size_t off, rapidjson::GenericValue& loc) { static rapidjson::Value nullAnswer{ rapidjson::kNullType }; if (!path || !*path) { return nullAnswer; // not a valid path @@ -41,7 +39,7 @@ namespace core::config { return GetVal(path + off, idx + 1, val); } - void SetVal(const char* path, rapidjson::Value& value, size_t off = 0, rapidjson::GenericValue& loc = main) { + void SetVal(Config& cfg, const char* path, rapidjson::Value& value, size_t off, rapidjson::GenericValue& loc) { if (!path || !*path) { LOG_WARNING("Using setval with invalid path"); return; // not a valid path @@ -56,94 +54,95 @@ namespace core::config { std::string node{ path + off, sv.length() }; rapidjson::Value key{ rapidjson::kStringType }; - key.SetString(node.c_str(), main.GetAllocator()); + key.SetString(node.c_str(), cfg.main.GetAllocator()); if (loc.HasMember(key)) { loc.EraseMember(key); } - loc.AddMember(key, value, main.GetAllocator()); + loc.AddMember(key, value, cfg.main.GetAllocator()); return; } std::string node{ path + off, idx }; rapidjson::Value key{ rapidjson::kStringType }; - key.SetString(node.c_str(), main.GetAllocator()); + key.SetString(node.c_str(), cfg.main.GetAllocator()); if (!loc.HasMember(key)) { rapidjson::Value v{ rapidjson::kObjectType }; - SetVal(path + off, value, idx + 1, v); - loc.AddMember(key, v, main.GetAllocator()); + SetVal(cfg, path + off, value, idx + 1, v); + loc.AddMember(key, v, cfg.main.GetAllocator()); } else { - SetVal(path + off, value, idx + 1, loc[key]); + SetVal(cfg, path + off, value, idx + 1, loc[key]); } } } + Config::Config(const std::filesystem::path& path) : configFile(path.is_absolute() ? path : (utils::GetProgDir() / path)) {} - int64_t GetInteger(const char* path, int64_t defaultValue) { - rapidjson::Value& val = GetVal(path); + int64_t Config::GetInteger(const char* path, int64_t defaultValue) { + rapidjson::Value& val = GetVal(path, 0, main); if (val.IsNull() || !val.IsNumber()) { - SetInteger(path, defaultValue); + this->SetInteger(path, defaultValue); return defaultValue; } return val.GetInt64(); } - double GetDouble(const char* path, double defaultValue) { - rapidjson::Value& val = GetVal(path); + double Config::GetDouble(const char* path, double defaultValue) { + rapidjson::Value& val = GetVal(path, 0, main); if (val.IsNull() || !val.IsNumber()) { - SetDouble(path, defaultValue); + this->SetDouble(path, defaultValue); return defaultValue; } return val.GetDouble(); } - std::string GetString(const char* path, const char* defaultValue) { - rapidjson::Value& val = GetVal(path); + std::string Config::GetString(const char* path, const char* defaultValue) { + rapidjson::Value& val = GetVal(path, 0, main); if (val.IsNull() || !val.IsString()) { - SetString(path, defaultValue); + this->SetString(path, defaultValue); return defaultValue; } return val.GetString(); } - bool GetBool(const char* path, bool defaultValue) { - rapidjson::Value& val = GetVal(path); + bool Config::GetBool(const char* path, bool defaultValue) { + rapidjson::Value& val = GetVal(path, 0, main); if (val.IsNull() || !val.IsBool()) { - SetBool(path, defaultValue); + this->SetBool(path, defaultValue); return defaultValue; } return val.GetBool(); } - void SetInteger(const char* path, int64_t defaultValue) { + void Config::SetInteger(const char* path, int64_t defaultValue) { rapidjson::Value v{ defaultValue }; - SetVal(path, v); + SetVal(*this, path, v, 0, main); } - void SetDouble(const char* path, double defaultValue) { + void Config::SetDouble(const char* path, double defaultValue) { rapidjson::Value v{ defaultValue }; - SetVal(path, v); + SetVal(*this, path, v, 0, main); } - void SetString(const char* path, const std::string& defaultValue) { + void Config::SetString(const char* path, const std::string& defaultValue) { rapidjson::Value v{ rapidjson::kStringType }; v.SetString(defaultValue.c_str(), main.GetAllocator()); - SetVal(path, v); + SetVal(*this, path, v, 0, main); } - void SetBool(const char* path, bool defaultValue) { + void Config::SetBool(const char* path, bool defaultValue) { rapidjson::Value v{ defaultValue }; - SetVal(path, v); + SetVal(*this, path, v, 0, main); } - int64_t GetEnum(const char* path, ConfigEnumData* data, size_t dataCount, int64_t defaultEnumValue) { + int64_t Config::GetEnum(const char* path, ConfigEnumData* data, size_t dataCount, int64_t defaultEnumValue) { const char* defaultValueStr{ "" }; for (size_t i = 0; i < dataCount; i++) { if (data[i].enumValue == defaultEnumValue) { @@ -151,7 +150,7 @@ namespace core::config { break; } } - std::string val{ GetString(path, defaultValueStr) }; + std::string val{ this->GetString(path, defaultValueStr) }; if (val.empty()) { return defaultEnumValue; @@ -168,33 +167,39 @@ namespace core::config { return defaultEnumValue; } - void SetEnum(const char* path, int64_t enumValue, ConfigEnumData* data, size_t dataCount) { + void Config::SetEnum(const char* path, int64_t enumValue, ConfigEnumData* data, size_t dataCount) { for (size_t i = 0; i < dataCount; i++) { if (data[i].enumValue == enumValue) { - SetString(path, data[i].name); + this->SetString(path, data[i].name); return; } } LOG_WARNING("No enum value for path '{}': {}", path, enumValue); } - void SyncConfig() { + void Config::SyncConfig(bool save) { std::string json{}; - if (utils::ReadFile(utils::GetProgDir() / CONFIG_FILE, json)) { + if (utils::ReadFile(utils::GetProgDir() / configFile, json)) { main.Parse(json.data()); } // not reading isn't an error - - SaveConfig(); + if (save) { + this->SaveConfig(); + } } - void SaveConfig() { + void Config::SaveConfig() const { rapidjson::StringBuffer buff; rapidjson::PrettyWriter writer{ buff }; main.Accept(writer); std::string json{ buff.GetString() }; - utils::WriteFile(utils::GetProgDir() / CONFIG_FILE, json); + utils::WriteFile(utils::GetProgDir() / configFile, json); + } + + Config& GetMainConfig() { + static Config mainCfg{ MAIN_CONFIG_FILE }; + return mainCfg; } } diff --git a/src/shared/core/config.hpp b/src/shared/core/config.hpp index 801a376..d5a9f60 100644 --- a/src/shared/core/config.hpp +++ b/src/shared/core/config.hpp @@ -1,4 +1,5 @@ #pragma once +#include /* * Config utilities, search for a path inside the config file, a path is delimited by '.', @@ -7,35 +8,87 @@ * 42 is at the path "test.test2" */ namespace core::config { - constexpr const char* CONFIG_FILE = "acts.json"; + constexpr const char* MAIN_CONFIG_FILE = "acts.json"; struct ConfigEnumData { const char* name; int64_t enumValue; }; - int64_t GetInteger(const char* path, int64_t defaultValue = 0); - double GetDouble(const char* path, double defaultValue = 0); - std::string GetString(const char* path, const char* defaultValue = ""); - bool GetBool(const char* path, bool defaultValue = false); - int64_t GetEnum(const char* path, ConfigEnumData* data, size_t dataCount, int64_t defaultEnumValue = 0); + class Config { + public: + const std::filesystem::path configFile; + rapidjson::Document main{}; + Config(const std::filesystem::path& path); + + int64_t GetInteger(const char* path, int64_t defaultValue = 0); + double GetDouble(const char* path, double defaultValue = 0); + std::string GetString(const char* path, const char* defaultValue = ""); + bool GetBool(const char* path, bool defaultValue = false); + int64_t GetEnum(const char* path, ConfigEnumData* data, size_t dataCount, int64_t defaultEnumValue = 0); + template + inline T GetEnumVal(const char* path, ConfigEnumData* data, size_t dataCount, T defaultEnumValue = 0) { + return (T)GetEnum(path, data, dataCount, (int64_t)defaultEnumValue); + } + + void SetInteger(const char* path, int64_t defaultValue); + void SetDouble(const char* path, double defaultValue); + void SetString(const char* path, const std::string& defaultValue); + void SetBool(const char* path, bool defaultValue); + void SetEnum(const char* path, int64_t enumValue, ConfigEnumData* data, size_t dataCount); + + void SyncConfig(bool save); + void SaveConfig() const; + }; + + Config& GetMainConfig(); + + inline int64_t GetInteger(const char* path, int64_t defaultValue = 0) { + return GetMainConfig().GetInteger(path, defaultValue); + } + inline double GetDouble(const char* path, double defaultValue = 0) { + return GetMainConfig().GetDouble(path, defaultValue); + } + inline std::string GetString(const char* path, const char* defaultValue = "") { + return GetMainConfig().GetString(path, defaultValue); + } + inline bool GetBool(const char* path, bool defaultValue = false) { + return GetMainConfig().GetBool(path, defaultValue); + } + inline int64_t GetEnum(const char* path, ConfigEnumData* data, size_t dataCount, int64_t defaultEnumValue = 0) { + return GetMainConfig().GetEnum(path, data, dataCount, defaultEnumValue); + } template inline T GetEnumVal(const char* path, ConfigEnumData* data, size_t dataCount, T defaultEnumValue = 0) { return (T)GetEnum(path, data, dataCount, (int64_t)defaultEnumValue); } - void SetInteger(const char* path, int64_t defaultValue); - void SetDouble(const char* path, double defaultValue); - void SetString(const char* path, const std::string& defaultValue); - void SetBool(const char* path, bool defaultValue); - void SetEnum(const char* path, int64_t enumValue, ConfigEnumData* data, size_t dataCount); + inline void SetInteger(const char* path, int64_t value) { + GetMainConfig().SetInteger(path, value); + } + inline void SetDouble(const char* path, double value) { + GetMainConfig().SetDouble(path, value); + } + inline void SetString(const char* path, const std::string& value) { + GetMainConfig().SetString(path, value); + } + inline void SetBool(const char* path, bool value) { + GetMainConfig().SetBool(path, value); + } + inline void SetEnum(const char* path, int64_t enumValue, ConfigEnumData* data, size_t dataCount) { + GetMainConfig().SetEnum(path, enumValue, data, dataCount); + } /* * Load and save the config */ - void SyncConfig(); + inline void SyncConfig(bool save) { + GetMainConfig().SyncConfig(save); + } /* * Save the config */ - void SaveConfig(); + inline void SaveConfig() { + GetMainConfig().SaveConfig(); + } } \ No newline at end of file diff --git a/src/shared/hook/refs.cpp b/src/shared/hook/refs.cpp new file mode 100644 index 0000000..1a2def3 --- /dev/null +++ b/src/shared/hook/refs.cpp @@ -0,0 +1,15 @@ +#include +#include +#include "refs.hpp" + +namespace hook::refs { + +} + +byte* operator"" _g(size_t val) { + return process::Relativise(val - 0x140000000); +} + +byte* operator"" _a(size_t val) { + return process::Relativise(val); +} diff --git a/src/shared/hook/refs.hpp b/src/shared/hook/refs.hpp new file mode 100644 index 0000000..71ba69f --- /dev/null +++ b/src/shared/hook/refs.hpp @@ -0,0 +1,22 @@ +#pragma once + +#define S_ANY __declspec(selectany) +namespace hook::refs { + template + class Ref { + public: + T* ptr; + Ref(size_t loc) : ptr(reinterpret_cast(loc)) {} + Ref(void* ptr) : ptr(reinterpret_cast(ptr)) {} + + constexpr operator T* () const { + return ptr; + } + + constexpr T* operator->() const { + return ptr; + } + }; +} +byte* operator"" _g(size_t val); +byte* operator"" _a(size_t val); \ No newline at end of file