mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
make mods work without getting tuliphook link errors
This commit is contained in:
parent
53296bbb5e
commit
b9dfd1b115
8 changed files with 75 additions and 19 deletions
|
@ -123,7 +123,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
|||
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
|
||||
|
||||
# Tulip hook (hooking)
|
||||
CPMAddPackage("gh:geode-sdk/TulipHook#9980bcf")
|
||||
CPMAddPackage("gh:geode-sdk/TulipHook#b67c3d4")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources)
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
|
|||
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("function_name", begin->name),
|
||||
fmt::arg("function_convention", codegen::getModifyConvention(f)),
|
||||
fmt::arg("function_convention", codegen::getModifyConventionName(f)),
|
||||
fmt::arg("parameter_types", fmt::join(func.parameter_types, ", "))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -187,6 +187,27 @@ namespace codegen {
|
|||
else throw codegen::error("Tried to get convention of non-function");
|
||||
}
|
||||
|
||||
inline std::string getModifyConventionName(Field& f) {
|
||||
if (codegen::platform != Platform::Windows) return "Default";
|
||||
|
||||
if (auto fn = f.get_fn()) {
|
||||
auto status = getStatus(f);
|
||||
|
||||
if (fn->is_static) {
|
||||
if (status == BindStatus::Binded) return "Cdecl";
|
||||
else return "Optcall";
|
||||
}
|
||||
else if (fn->is_virtual) {
|
||||
return "Thiscall";
|
||||
}
|
||||
else {
|
||||
if (status == BindStatus::Binded) return "Thiscall";
|
||||
else return "Membercall";
|
||||
}
|
||||
}
|
||||
else throw codegen::error("Tried to get convention of non-function");
|
||||
}
|
||||
|
||||
inline std::string getUnqualifiedClassName(std::string const& s) {
|
||||
auto index = s.rfind("::");
|
||||
if (index == std::string::npos) return s;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace { namespace format_strings {
|
|||
#include <Geode/utils/addresser.hpp>
|
||||
#include <Geode/modify/Addresses.hpp>
|
||||
#include <Geode/modify/Traits.hpp>
|
||||
#include <tulip/TulipHook.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
|
||||
using namespace geode;
|
||||
using namespace geode::modifier;
|
||||
|
@ -30,7 +30,7 @@ CCDestructor::~CCDestructor() {{
|
|||
}}
|
||||
|
||||
auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadata) {
|
||||
auto wrapped = tulip::hook::createWrapper(reinterpret_cast<void*>(address), metadata);
|
||||
auto wrapped = Loader::get()->createWrapper(reinterpret_cast<void*>(address), metadata);
|
||||
if (wrapped.isErr()) {{
|
||||
throw std::runtime_error(wrapped.unwrapErr());
|
||||
}}
|
||||
|
@ -42,7 +42,7 @@ auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadat
|
|||
auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{
|
||||
using FunctionType = decltype({function_name}({arguments}))(*)({class_name}{const}*{parameter_comma}{parameter_types});
|
||||
static auto func = wrapFunction(address<{addr_index}>(), tulip::hook::WrapperMetadata{{
|
||||
.m_convention = std::make_shared<{convention}>(),
|
||||
.m_convention = Loader::get()->createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
}});
|
||||
return reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
|
||||
|
@ -54,7 +54,7 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
|
|||
auto self = addresser::thunkAdjust(Resolve<{parameter_types}>::func(&{class_name}::{function_name}), this);
|
||||
using FunctionType = decltype({function_name}({arguments}))(*)({class_name}{const}*{parameter_comma}{parameter_types});
|
||||
static auto func = wrapFunction(address<{addr_index}>(), tulip::hook::WrapperMetadata{{
|
||||
.m_convention = std::make_shared<{convention}>(),
|
||||
.m_convention = Loader::get()->createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
}});
|
||||
return reinterpret_cast<FunctionType>(func)(self{parameter_comma}{arguments});
|
||||
|
@ -65,7 +65,7 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
|
|||
auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{
|
||||
using FunctionType = decltype({function_name}({arguments}))(*)({parameter_types});
|
||||
static auto func = wrapFunction(address<{addr_index}>(), tulip::hook::WrapperMetadata{{
|
||||
.m_convention = std::make_shared<{convention}>(),
|
||||
.m_convention = Loader::get()->createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
}});
|
||||
return reinterpret_cast<FunctionType>(func)({arguments});
|
||||
|
@ -79,7 +79,7 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
|
|||
if (CCDestructor::lock(this)) return;
|
||||
using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
|
||||
static auto func = wrapFunction(address<{addr_index}>(), tulip::hook::WrapperMetadata{{
|
||||
.m_convention = std::make_shared<{convention}>(),
|
||||
.m_convention = Loader::get()->createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
}});
|
||||
reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
|
||||
|
@ -99,7 +99,7 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
|
|||
{class_name}::~{unqualified_class_name}();
|
||||
using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
|
||||
static auto func = wrapFunction(address<{addr_index}>(), tulip::hook::WrapperMetadata{{
|
||||
.m_convention = std::make_shared<{convention}>(),
|
||||
.m_convention = Loader::get()->createConvention(tulip::hook::TulipConvention::{convention}),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
|
||||
}});
|
||||
reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
|
||||
|
@ -190,7 +190,7 @@ std::string generateBindingSource(Root& root) {
|
|||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("unqualified_class_name", codegen::getUnqualifiedClassName(c.name)),
|
||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
||||
fmt::arg("convention", codegen::getModifyConvention(f)),
|
||||
fmt::arg("convention", codegen::getModifyConventionName(f)),
|
||||
fmt::arg("function_name", fn->beginning.name),
|
||||
fmt::arg("meta_index", ids.meta),
|
||||
fmt::arg("member_index", ids.member),
|
||||
|
|
|
@ -50,16 +50,17 @@ namespace geode {
|
|||
tulip::hook::HookMetadata const& hookMetadata
|
||||
);
|
||||
|
||||
template <class Convention, class DetourType>
|
||||
template <class DetourType>
|
||||
static Hook* create(
|
||||
Mod* owner,
|
||||
void* address,
|
||||
DetourType detour,
|
||||
std::string const& displayName,
|
||||
tulip::hook::TulipConvention convention,
|
||||
tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata()
|
||||
) {
|
||||
auto handlerMetadata = tulip::hook::HandlerMetadata{
|
||||
.m_convention = std::make_shared<Convention>(),
|
||||
.m_convention = Loader::get()->createConvention(convention),
|
||||
.m_abstract = tulip::hook::AbstractFunction::from(detour)
|
||||
};
|
||||
return Hook::create(
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Log.hpp"
|
||||
#include "ModInfo.hpp"
|
||||
#include "Types.hpp"
|
||||
#include <tulip/TulipHook.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
@ -79,6 +80,20 @@ namespace geode {
|
|||
|
||||
bool didLastLaunchCrash() const;
|
||||
|
||||
/**
|
||||
* Create a calling convention wrapper for a function.
|
||||
*/
|
||||
Result<void*> createWrapper(
|
||||
void* address,
|
||||
tulip::hook::WrapperMetadata const& metadata
|
||||
) noexcept;
|
||||
/**
|
||||
* Create an abstract calling convention handler for TulipHook
|
||||
*/
|
||||
std::shared_ptr<tulip::hook::CallingConvention> createConvention(
|
||||
tulip::hook::TulipConvention convention
|
||||
) noexcept;
|
||||
|
||||
friend class LoaderImpl;
|
||||
|
||||
friend Mod* takeNextLoaderMod();
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
constexpr auto b = Resolve<__VA_ARGS__>::func(&Base::FunctionName_); \
|
||||
constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::FunctionName_); \
|
||||
if constexpr (Unique::different<b, d>()) { \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
auto hook = Hook::create( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(address<AddressIndex_>()), \
|
||||
AsStaticFunction_##FunctionName_<Derived, d>::value, \
|
||||
#ClassName_ "::" #FunctionName_ \
|
||||
#ClassName_ "::" #FunctionName_, \
|
||||
tulip::hook::TulipConvention::Convention_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #FunctionName_] = hook; \
|
||||
} \
|
||||
|
@ -28,11 +29,12 @@
|
|||
do { \
|
||||
if constexpr (HasConstructor<Derived>) { \
|
||||
constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::constructor); \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
auto hook = Hook::create( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(address<AddressIndex_>()), \
|
||||
AsStaticFunction_##constructor<Derived, d>::value, \
|
||||
#ClassName_ "::" #ClassName_ \
|
||||
#ClassName_ "::" #ClassName_, \
|
||||
tulip::hook::TulipConvention::Convention_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \
|
||||
} \
|
||||
|
@ -42,11 +44,12 @@
|
|||
do { \
|
||||
if constexpr (HasDestructor<Derived>) { \
|
||||
constexpr auto d = Resolve<>::func(&Derived::destructor); \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
auto hook = Hook::create( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(address<AddressIndex_>()), \
|
||||
AsStaticFunction_##destructor<Derived, d>::value, \
|
||||
#ClassName_ "::" #ClassName_ \
|
||||
#ClassName_ "::" #ClassName_, \
|
||||
tulip::hook::TulipConvention::Convention_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \
|
||||
} \
|
||||
|
|
|
@ -121,4 +121,20 @@ bool Loader::didLastLaunchCrash() const {
|
|||
|
||||
Mod* Loader::takeNextMod() {
|
||||
return m_impl->takeNextMod();
|
||||
}
|
||||
}
|
||||
|
||||
Result<void*> Loader::createWrapper(void* address, tulip::hook::WrapperMetadata const& metadata) noexcept {
|
||||
auto res = tulip::hook::createWrapper(address, metadata);
|
||||
if (res) {
|
||||
return Ok(res.unwrap());
|
||||
}
|
||||
else {
|
||||
return Err(res.unwrapErr());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<tulip::hook::CallingConvention> Loader::createConvention(
|
||||
tulip::hook::TulipConvention convention
|
||||
) noexcept {
|
||||
return tulip::hook::createConvention(convention);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue